I'm hoping to setup more than one timers in the system we're developing such that one will be 1 seconds tick while others or in milliseconds tick, etc.
I've imported the lptmr SDK project, which uses LPTMR0 & manipulated it a little bit to do what I need for use in 4 factors, some in seconds, and counting to minutes, with lowest time in seconds.
Since MKL28Z claims to have both LPTMR0 and LPTMR1, I tried swapping everything in this imported simple lptmr project from lptmr0 to lptmr1 values, e.g. based register address, interrupt #, interrupt handler pointer.
I know I replaced all in the definitions but the rest of the function calls and configuration settings I kept AS IT IS for lptmr0 also in lptmr1.
PROBLEM: In using lptmr1, it hangs... it does not behave or do anything as how it did when using lptmr0.
Are these 2 interchangeable?
I noticed this though on MKL28Z7.h which I'm not sure effects the problem:
<partial quote of device interrupts>
LPTMR0_IRQn = 26, /**< LPTMR0 interrupt */
RTC_Seconds_IRQn = 27, /**< RTC seconds */
INTMUX0_0_IRQn = 28, /**< INTMUX0 channel 0 interrupt */
INTMUX0_1_IRQn = 29, /**< INTMUX0 channel 1 interrupt */
INTMUX0_2_IRQn = 30, /**< INTMUX0 channel 2 interrupt */
INTMUX0_3_IRQn = 31, /**< INTMUX0 channel 3 interrupt */
LPTMR1_IRQn = 32, /**< LPTMR1 interrupt (INTMUX source IRQ0) */
Notice LPTMR0_IRQn = 26, solely for lptmr0 interrupt. However, LPTMR1_IRQn = 32 is "shared" with INTMUX source IRQ0.
I'm not sure which in this project triggers IRQ0 & if so could that be what's causing lptmr1 not to work?
Worst comes to worst, and I'm just stuck with LPTMR0, since I can declare a config structure, e.g.
Can I declare several such lptmr_config data structures and just vary each by the prescaler value for each structure so some ticks in seconds while others are faster in milliseconds or such? E.g.
config->prescalerClockSource = kLPTMR_PrescalerClock_1; // or _0 thru _3
>>> Addition: Also if I only use LPTMR0 with several data configured timer structures, how do I know which triggered the LPTMR0_IRQHandler()? inside the interrupt handler? The problem I have with MKL28Z is I don't see any "timer handle" or "timer label" to know which triggered what, like we do it in other MCU's.
Or maybe someone knows how that is done in MKL28Z? because I don't.
>>> More addition: In further studing the lptmr SDK project example, I see that it setup the time period (called LPTMR_SetTimerPeriod()) once for a single lptmr data config structure. Does that mean I can only also setup for ONE (1) timer data structure & run one lptmr0 timer in the system only at a time? And in order to refine to ticks in milliseconds I should use other PrescalerClock that's not 1 second but use the faster milliseconds divider & just do "counters" to "simulate" which completed 100 millisecond vs. 1 second vs. 10 minutes, etc?
Thanks for the help.
I tried out use of LpoClk reference for BOTH lptmr0 and lptmr1 and all worked fine. You just have to adapt calculation of time period's with right USEC definitions to what timer tick you need for each of lptmr0 and lptmr1, accordingly, to use in this function, e.g.:
LPTMR_SetTimerPeriod(LPTMR0_ADDR, USEC_TO_COUNT(LPTMR0_USEC_COUNT, LPTMR_SOURCE_CLOCK));
NOTE: Remember to use LpoClk in the 2nd argument of USEC_TO_COUNT, macro, LPTMR_SOURCE_CLOCK.
You are welcome, Kerry.
It is really quite simple. Honestly, I patterned the method as how the Touch Sensor Interface (TSI0) module was setup with INTMUX0. TSI0 required more setup configuration than LPTMR module. At first my lptmr1 interrupt handler was not triggering but after a few more tweaks and tries, BOTH lptmr0 and lptmr1 function handlers were finally triggering. I did this in MCUXpresso by simply putting breakpoints within each interrupt handler.
Another thing I did was to assign each a DIFFERENT PRESCALER reference clock. One with LPOCLK (01) 1 KHz & the other OSC32KCLK (10) 32KHz. And also use a different USEC definition for each to compute each of their time period. I did that when it was not yet working just to see if it is because of "overlapping" of clocks that one is winning over the other. (Although I know the MCU does timeslicing for each process anyway, even though I'm not running RTOS in the system yet, at least not for this prototype development.)
So, I still have to try assign only LPOCLK to BOTH lptmr0 and lptmr1 but for sure, I'll keep the USEC for computing time periods different for each.
Just FYI to those interested:
I was able to setup both lptmr0 and lptmr1 in the same system to run separately, as well as I was able to setup the system to run only with lptmr1.
After more study and tries, I figured out how to enable lptmr1 interrupt & make its timer run independently with and without lptmr0.
The keys to setup and use lptmr1 as another system timer are:
1. Need to initialize and enable INTMUX0 interrupt
2. Need to use NVIC_EnableIRQ() to enable lptmr1, instead of going through LPTMR_EnableInterrupts() where the >= 32 interrupt vector limit roadblock will make it fail and not enable lptmr1.
3. start lptmr1 just as how lptmr0 timer is started.
I'm happy because this gives me relief to leave TSI0 to use lptmr0 because lptmr0 is the "HW timer driver" of TSI0, while I can use lptmr1 for use as different timer ticks in other operations in the system.
Comments or questions are welcome.
Just a note (see also the explanation video in the thread) as to the way that the INTMUX details are automated in the uTasker project to avoid the user needing to do any extra configuration (for LPTMR1 or other such interrupt sources):
1. fnEnterInterrupt(), which is used to configure an NVIC interrupt, set its priority and enter its interrupt vector, detects when an extended interrupt is being entered and automatically powers up the INTMUX and installs a dispatcher.
[The FSL method simply ignores such attemps and results in potential loss of time working out why and how to do it with other techniques]
2. The user can connect extended interrupts to any of the 4 INTMUX channels by setting a define (default is):
#define INTMUX_LPTMR1 INPUT_TO_INTMUX0_CHANNEL_0 // the LPTMR1 extended interrupt is connected to INTMUX0 channel 0 (inherits INTMUX0 channel 0's priority)
where the channel's interrupt priority is chosen by
#define PRIORITY_INTMUX0_0_INT 0 // priority of extended interrupts using INTMUX0 chnnel 0
INPUT_TO_INTMUX0_CHANNEL_1, INPUT_TO_INTMUX0_CHANNEL_2 and INPUT_TO_INTMUX0_CHANNEL_3 can be set as alternatives to the default to select different channels.
3. The LPTMR1 and its interrupt via the INTMUX are simulated in Visual Studio so that the complete code and application operation can be tested and verified without need for the HW target. It also allows simple study of the INTMUX operation for educational purposes.
4. Even if not used as main development tool the uTasker open source project can be used to quickly identify reasons for such problems (through simulation and immediate/automatic solution) in order to aid in correcting them in the FSL environment.
If only I have extra time to spend to delve deeper in my original question but I am pressed with 2.5 weeks to finish a prototype for demo-ing to a possible client.
Yes, I asked can lptmr0 be interchangeable with lptmr1. Then I found that lptmr1 is multiplexed with level 1 interrupt at # 32 with INTMUX. Yes, I'm bowing out of this complication mainly because I do not have time to spare. If I had leisure time I would play but not at this time. There are much more complicated things to tackle than this in 2 weeks, I don't want to add anymore if I want this prototype to be close to perfect because integrating all the modules is at hand and FULL system needs to be tested so we don't fail & get this client.
I see the question was asked in 2016 but nobody really delved deeper into doing it.
Again, I would but I don't have time to spare right now.
Believe me, I'm not trying to avoid it. I'm trying to be practical. I'd like to keep the TSI0 for 3 touch buttons as sole interrupt multiplex with INTMUX. People here like to make me do almost impossible things with self-capacitive touch mode on supposedly touch buttons to behave like mutual-capacitive touch like multi-finger/touch happening at the same time. Don't know if you remember now how I managed to deal with "scanning" 3 separately touched touch buttons in self-cap mode, that post before, after realizing the TSI0 module can only scan 1 touch CHANNEL out of 16 at a time because it is 4-multiplexed-to-1 interrupt trigger & you have to set electrode one at a time 1-2-3-1-2-3-1-2-3...
And right now lptmr0 with the plan I'm doing, will provide me more than enough timers for what I need.
So as an engineer, I'd like to be practical as I'm reserving other complications for the TSI0 module's "multi-touch" combination trigger.
Thanks for the comments.
The INTMUX supports 4 independent interrupts so a second will not effect TSI operation.
How you solve your product design is your engineering decision. The thread is however about the LPTMR1 not being as straightforward as LPTMR0 due to the interrupt vector difference and that is why I am concentrating on that, since other viewers may need to use it and will then be able to solve their issue. There is also another thread about the LPTMR1 on KL28 and KL82 where the same problem was initially encountered so it probably crops up now and again: https://community.nxp.com/thread/435382
LPTMR1 clock is definitely getting enabled.
It is failing on this line of code in EnableIRQ(), because the LEVEL1_INT_VECTOR is "32" & the if statement checks for FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS >= 32... return kStatus Fail, as:
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
if (interrupt >= FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
So after all the preparation, setup configuration, the LPTMR1 interrupt fails to get "enabled".
What I thought is "hanging" (e.g. I put breakpoint inside interrupt handler function) is the interrupt is not triggering at all, but the system continues to run.
I've worked with INTMUX in the Touch Sensing Interrupt enable of TSI0 module; they are multiplexed.
I don't think I need that extra complication of using LPTMR1, INTMUX, especially there will definitely be TSI0 with INTMUX already in the system I'm developing.
Besides those I'll be using PWM/TPM as well when I'm measuring pulses from flow meter input.
Like I said, so many I/O's & timers & pulse counters to take care of so I don't need any more complications.
Right now, I'm settling with just using LPTMR0, given prescaler at 1 KHz LpoClk source, I'll use smaller value for "LPTMR_USEC_COUNT" fed to this set timer period function call.
LPTMR_SetTimerPeriod(LPTMR_BASE1, USEC_TO_COUNT(LPTMR_USEC_COUNT, LPTMR_SOURCE_CLOCK));
Instead of LPTMR_USEC_COUNT = 1M, which results to only minimum of 1 second ticks, I'll reduce that definition to small value so I can refine ticks to 100 msecs. Then "distribute" such ticks to different timers that don't go below 100 msec ticks. I think that is simple enough to me to get different timers to check in one & only one interrupt handler function.
Comments are welcome.
Thanks for the help.
If you have already configured interrupt for touch via the INTMUX you can do the same for the LPTMR1. It would be a shame to have to avoid using HW resources due to the library being too complicated to set them up.
Of course there are many ways to reach a solution and so you can also avoid it if it is easier to do like that.
The LPTMR0 and 1 are equivalent apart from the fact that you need to route LPTMR1's interrupt through the INTMUX,
as you have already seen.
Also don't forget to enable the LPTMR1 clock gate when using it.
See the following video if you don't yet have experience with the INTMUX operation: https://www.youtube.com/watch?v=zKa5BoOhBrg&list=PLWKlVb_MqDQFZAulrUywU30v869JBYi9Q&index=15
I also attached the uTasker LPTMR driver as reference which has complete support for such things and automates the details, which may help understand what needs to be done to extend the FSL library examples.
Complete Kinetis solutions for professional needs, training and support: http://www.utasker.com/kinetis.html
Kinetis KL25, KL26, KL27, KL28, KL43, KL46, KL82
uTasker: supporting >1'000 registered Kinetis users get products faster and cheaper to market
Request Free emergency remote desk-top consulting at http://www.utasker.com/services.html
Open Source version at https://github.com/uTasker/uTasker-Kinetis