KMS_TICK->CYCCNT Not Counting when Debugger Not Connected

cancel
Showing results for 
Search instead for 
Did you mean: 

KMS_TICK->CYCCNT Not Counting when Debugger Not Connected

284 Views
Senior Contributor I

Hello, 

I am having a strange problem that I am curious if you have seen or not, and if you know what may be causing it. In my Sensorless Velocity Project, when the debugger is not connected, GetProfilerCycles() returns zero. This works fine when the debugger is connected, and in my sensored project. I was just wondering if maybe something keeps resetting this. Have you seen this before?

Thanks for the help, 

Derek

Labels (1)
0 Kudos
5 Replies

15 Views
Senior Contributor I

Derek,

I can't say that I've seen this before. We leverage the DWT for this functionality. So I'm not sure what is going on there. 

Take a look at the MCU documentation and ARM documentation (ARM Information Center )

0 Kudos

15 Views
Senior Contributor I

Hey Adam, 

Thanks for the reply. I seem to have fixed the issue by moving StartProfiler() under EnableGlobalIRQ(). I am a little uncomfortable about this because I am unsure as to why moving the Profiler under the IRQ enable would resolve this issue, as you do not run this sequence of events in your KMS project. 

This is the sequence of events in which the profiler was hanging each time without the debugger connected: 

/* Init Platform Independent Motor Commander Core */
DRV_init(&flashSysParams);

/* Enable the Profile to be free running */
StartProfiler();

/* Enable UART ISRs */
NVIC_EnableIRQ(UART1_RX_TX_IRQn);
NVIC_SetPriority(UART1_RX_TX_IRQn, 14);
NVIC_EnableIRQ(UART1_ERR_IRQn);
NVIC_SetPriority(UART1_ERR_IRQn, 14);

focPwmDecimation = flashSysParamsHeader.FocPwmDecimation; /*!< PWM to Fast ISR Decimation */
fastTicksPerSlowTick = flashSysParamsHeader.fastTicksPerSlowTick; /*!< Fast to Slow ISR Decimation */

/* Enable Global interrupts */
EnableGlobalIRQ(ui32PrimaskReg);

/* Install handler for ADC1 (conversion complete) interrupt */
NVIC_EnableIRQ(ADC1_IRQn); /* enable ADC1 interrupt */
NVIC_SetPriority(ADC1_IRQn, 12);

/* Enable PDB0 ISR */
NVIC_EnableIRQ(PDB0_IRQn);
NVIC_SetPriority(PDB0_IRQn, 13);

/* Use the SWI IRQ to trigger the slow tick routine */
NVIC_EnableIRQ(SWI_IRQn);
NVIC_SetPriority(SWI_IRQn, 15);

I changed this to the following, and not the profiler starts every time without a problem: 

/* Init Platform Independent Motor Commander Core */
DRV_init(&flashSysParams);

/* Enable UART ISRs */
NVIC_EnableIRQ(UART1_RX_TX_IRQn);
NVIC_SetPriority(UART1_RX_TX_IRQn, 14);
NVIC_EnableIRQ(UART1_ERR_IRQn);
NVIC_SetPriority(UART1_ERR_IRQn, 14);

focPwmDecimation = flashSysParamsHeader.FocPwmDecimation; /*!< PWM to Fast ISR Decimation */
fastTicksPerSlowTick = flashSysParamsHeader.fastTicksPerSlowTick; /*!< Fast to Slow ISR Decimation */

/* Enable Global interrupts */
EnableGlobalIRQ(ui32PrimaskReg);

/* Enable the Profile to be free running */
StartProfiler();

/* Install handler for ADC1 (conversion complete) interrupt */
NVIC_EnableIRQ(ADC1_IRQn); /* enable ADC1 interrupt */
NVIC_SetPriority(ADC1_IRQn, 12);

/* Enable PDB0 ISR */
NVIC_EnableIRQ(PDB0_IRQn);
NVIC_SetPriority(PDB0_IRQn, 13);

/* Use the SWI IRQ to trigger the slow tick routine */
NVIC_EnableIRQ(SWI_IRQn);
NVIC_SetPriority(SWI_IRQn, 15);

0 Kudos

15 Views
Senior Contributor I

You can take a peak at the StartProfiler function call. It merely configures the DWT hardware on the MCU. So moving it shouldn't have any impact. It is possible we did something wrong in the reference project with respect to the correct location.

0 Kudos

15 Views
Senior Contributor I

Moving the StartProfiler() around does not make sense to me. I'm not sure why it would start any better after the EnableGlobalIRQ(). I'm afraid the issue may still be present, just not as prevalent as it was. I have not seen the issue since Friday, however.

I compared the StartProfiler() function to another post online, and it seems to match pretty well as to what the other person was doing: Cycle Counting on ARM Cortex-M with DWT | MCU on Eclipse 

In the StartProfiler() it looks like the correct register is being written to enable the DEMCR (Debug Exception and Monitor Control Register).

The Control Register is being written to 1 to enable the cycle counter, and you're resetting the Cycle Counter. 

I did notice the KMS order of events was different than this online post however. I wonder if resetting the cycle counter after enabling it could maybe cause some inconsistency? I also noticed that when setting the control bit a '=' is used instead of '|='. I'm not sure if this would cause a problem either. 

Currently StartProfiler() looks like this: 

static inline void StartProfiler(void)
{
CLOCK_ENABLE_KMS_TICK;

KMS_TICK->CTRL = DWT_CTRL_CYCCNTENA_Msk; 

KMS_TICK->CYCCNT = 0;
}

The example online did this: 

KIN1_InitCycleCounter(); /* enable DWT hardware */
KIN1_ResetCycleCounter(); /* reset cycle counter */
KIN1_EnableCycleCounter(); /* start counting */
foo(); /* call function and count cycles */
cycles = KIN1_GetCycleCounter(); /* get cycle counter */
KIN1_DisableCycleCounter(); /* disable counting if not used any more */
 

I wonder if start profiler should look like this - I'm just not sure if resetting the CYCCNT after enabling could cause the CYCCNT to get stuck at 0?

static inline void StartProfiler(void)
{
CLOCK_ENABLE_KMS_TICK;

KMS_TICK->CYCCNT = 0;

KMS_TICK->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}

0 Kudos

15 Views
Senior Contributor I

You could switch out the code and see if that resolves the issue. On the reference hardware the debugger isn't being used, and the mcu boots from flash. So I'm not sure why it works there but not on your board.

0 Kudos