2015-11-27 07:51 PM
First of all, forgive my poor English :)
As title indicated,I want to propose two issue I confront in my work.Before that,I would like to introduce the function I was supposed to achieve briefly. In my project, I used the example project which includes the FreeRTOS as the prototype to code my own function.The example project uses the SYSTICK register to count ticks which will stop when the MCU enters deep sleep mode(more accuratly, stop 1 mode).So I re-code the function using LPTIMER 1 instead. In fact , I don't care too much about how precisely the ticks counted in deep sleep mode is. It may drift a little along time, so the conpensation of time drift induced by stoping and re-configuring the LPTIMER is not realized.Fortunately, the code works, and the system run well....uh...seemed well.Before going into deep sleep mode, I configure the register ARR to the next wakeup time, the same as the example code did so. Step 1: get CNT value, Step 2: minuse CNT from ARR to seem how many counts remain in current tick. Step 3: calculate the ARR value for wakeup(BTW, the enable and disable of LPTIMER is under the instruction of the the Manual).the question is, the CNT is bigger than the ARR sometimes, which makes (ARR - CNT) to be a negative number,and that is a very large positive number in an uint32_t type varialble. And this makes me confused. HOW CAN CNT EXCEEDS ARR? Did I do any thing wrong with LPTIMER, or is there any thing I should pay more attention to when configure the LPTIMER registers?Another Question is :Sometimes, my code run to an infinite processing of LPTIM1's IRQ Handler, which blocks the whole FreeRTOS threads.I checked the LPTIMER's register, the configurations are all correct.It's weird, and I want to know had anyone confronted the same thing as I did? How can I make all the things right?ANSWER:The reason why CNT exceeds ARR is that ARROK bit int ISR is not set while another write to ARR occurs. Restrictly follow the instruction of configing ARR will avoid this problem. Don't forget to clear the ARROK bit.
2015-11-28 09:30 AM
If the timer is 16-bit, then you'd probably want to hold the advancing value in a uint16_t, or mask it suitably.
If it never leaves the IRQ Handler you need to look very carefully at the asserted status, and how you are clearing it. Sitting in a debugger peering at it is probably not the best way to debug it. Watch also for the NVIC tail-chaining hazard, and that you qualify the source of the interrupt and clear it early in the handler.2015-11-29 06:29 PM
Thank you very much!
Maybe my description misguided you. What I really concerned is how to always keep CNT less than or equal to ARR. The reload value is calculated in a uint32_t and if the result is greater than 0xFFFF, 0xFFFF is set to ARR. I run the program in KEIL. If I click run -> stop -> run -> stop... button when the program is well, everytime the program stops, the statement to be executed is different. But if the program is not OK, the same opt leads the program stops in the LPTIM1's IRQ Handler, no matter how many times I repeat. If the program run to an assert statement, program will stop in the assert most of the time.So I think it may be not caused by the asserted status. For the clearing and other details..., I paste part of my code here, can you help my to check this out? Thank again!void LPTIM1_IRQHandler(void)
{ if(__HAL_LPTIM_GET_FLAG(&sys_tick_timer, LPTIM_FLAG_ARRM)){ /* LPTIM in time Base mode */ //HAL_LPTIM_IRQHandler(&sys_tick_timer); LPTIM1->CNT __HAL_LPTIM_CLEAR_FLAG(&sys_tick_timer, LPTIM_FLAG_ARRM); #if configUSE_TICKLESS_IDLE == 2 if(LPTIM1->ARR != ulTimerCountsForOneTick - 1UL){ LPTIM1->ARR = ulTimerCountsForOneTick - 1UL; while(!(LPTIM1->ISR & (1<<4))); } #endif osSystickHandler(); lptick_flag ++; HAL_IncTick(); } __HAL_LPTIM_CLEAR_FLAG(&sys_tick_timer, LPTIM_FLAG_ARRM); if(__HAL_LPTIM_GET_FLAG(&sys_tick_timer, LPTIM_FLAG_CMPM)){ __HAL_LPTIM_CLEAR_FLAG(&sys_tick_timer, LPTIM_FLAG_CMPM); } if(__HAL_LPTIM_GET_FLAG(&sys_tick_timer, LPTIM_FLAG_ARROK)){ __HAL_LPTIM_CLEAR_FLAG(&sys_tick_timer, LPTIM_FLAG_ARROK); } if(__HAL_LPTIM_GET_FLAG(&sys_tick_timer, LPTIM_FLAG_CMPOK)){ __HAL_LPTIM_CLEAR_FLAG(&sys_tick_timer, LPTIM_FLAG_CMPOK); } } The other code, including LPTIMER1 init, enter SLEEP mode is in the attachment. ________________ Attachments : lptimer1.c : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0cs&d=%2Fa%2F0X0000000bcG%2F.gkQiyCrBu18KaSHqBndrkJzeV9g5qJMPh79490QBTk&asPdf=false2015-11-29 10:00 PM
Another detail for the IRQ issue is, the IRQ problem always happens after the MCU wakeup and the function __enable_irq() is called.The LPTIMER 1 was disabled before the __enable_irq() function. That means the ISR of LPTIM will never be set again.
I set a breakpoint at the first statement of the IRQ Handler.The breakpoints shows that the LPTIM interrupt is trigger while the ISR equals zero. A breakpoint after the __enable_irq() is never reached, while a run command will cause the program enter IRQ Handler again.2017-01-30 08:54 AM
I have done similar work and here are a few things I found that helped me,
My theory is that there is a problem reading/writing LPTIM registers that the HAL api doesn't completely deal with properly. However with the above workarounds I was able to get my STOP2 mode working using LPTIM1 to replace systic in a FreeRTOS environment.