lwtimer

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
3,363 Views
Nouchi
Senior Contributor II

Hello,

 

I need some explanation on how lwtimer works. I don't find examples in MQX directories about this, MQXRM and MQXUG are pretty poor too.

 

Emmanuel

1 Solution
1,634 Views
DavidS
NXP Employee
NXP Employee

Hi Emmanuel,

Example below:

 

#include <mqx.h>
#include <bsp.h>
#include <fio.h>
#include <lwtimer.h>


#if ! BSPCFG_ENABLE_IO_SUBSYSTEM
#error This application requires BSPCFG_ENABLE_IO_SUBSYSTEM defined non-zero in user_config.h. Please recompile BSP with this option.
#endif


#ifndef BSP_DEFAULT_IO_CHANNEL_DEFINED
#error This application requires BSP_DEFAULT_IO_CHANNEL to be not NULL. Please set corresponding BSPCFG_ENABLE_TTYx to non-zero in user_config.h and recompile BSP with this option.
#endif


/*  This example calls _timer_create_component before it activates the
**  timers so that the application can specify the timer task stack size.
**  The stack size may need to be larger than the TIMER_DEFAULT_STACK_SIZE
**  that is defined in timer.h, since the application's handler function uses
**  this stack. In this example, the handlers are LED_on and LED_off,
**  which have large stack requirements. You may need to increase the stack size
**  for your target hardware.
*/
#define LWTIMER_TASK_PRIORITY  2
#define LWTIMER_STACK_SIZE     2000

#define MAIN_TASK      10

extern void main_task(uint_32);
extern void LED_on(void);
extern void LED_off(void);
volatile _mqx_uint LED_on_counter=0;
volatile _mqx_uint LED_off_counter=0;


const TASK_TEMPLATE_STRUCT  MQX_template_list[] =
{
   /* Task Index, Function,   Stack, Priority,  Name,     Attributes,          Param, Time Slice */
    { MAIN_TASK,  main_task,  2000,     8,      "Main",   MQX_AUTO_START_TASK, 0,     0 },
    { 0 }
};

/*FUNCTION*------------------------------------------------------
*
* Function Name  : LED_on
* Returned Value : none
* Comments       :
*     This timer function prints out "ON"
*END*-----------------------------------------------------------*/
static void LED_on
   (
   )
{
   LED_on_counter++;
}

/*FUNCTION*------------------------------------------------------
*
* Function Name  : LED_off
* Returned Value : none
* Comments       :
*     This timer function prints out "OFF"
*END*-----------------------------------------------------------*/
static void LED_off
   (
   )
{
   LED_off_counter++;
}

/*TASK*----------------------------------------------------------
*
* Task Name : main_task
* Comments  :
*     This task creates two timers, each of a period of 2 seconds,
*     the second timer offset by 1 second from the first.
*END*-----------------------------------------------------------*/

void main_task
   (
      uint_32 initial_data
   )
{
   LWTIMER_PERIOD_STRUCT ps;
   LWTIMER_STRUCT lst_on, lst_off;
   _mqx_uint time=20;
     
   _mqx_uint period=6;
   _mqx_uint wait_ticks=0;
   _mqx_uint delay_on=3;
   _mqx_uint delay_off=3;

   printf("\n\nTwo lwtimers are created, each of a period of %d ticks,\nthe second lwtimer offset by %d ticks from the first.\n", period, delay_off);
   printf("Task runs for %d seconds,\nthen lwtimers are closed and task finishes.\n\n", time);          

   /*
   ** Create the lwtimer component with more stack than the default
   ** in order to handle printf() requirements:
   */
   _lwtimer_create_periodic_queue(&ps, period, wait_ticks);

   _lwtimer_add_timer_to_queue(&ps, &lst_on, delay_on, LED_on, 0);

   _lwtimer_add_timer_to_queue(&ps, &lst_off, delay_off, LED_off, 0);


   _time_delay(time * 1000); // wait 6 seconds
   printf("\nThe task is finished!");
   printf("\nLED_on_counter = %d LED_off_counter = %d", LED_on_counter, LED_off_counter);

   _lwtimer_cancel_period(&ps);

   _mqx_exit(0);

}

/* EOF */

 

Regards,

David

View solution in original post

0 Kudos
15 Replies
1,634 Views
DavidS
NXP Employee
NXP Employee

Hi Lucas,

I have not tried this with KSDK_1.3.

Documentation: C:\Freescale\KSDK_1.3.0\doc\rtos\mqx\MQX RTOS Reference Manual.pdf

You can tryC:\Freescale\KSDK_1.3.0\rtos\mqx\mqx\examples\timer\build\kds\timer_twrk24f120m .

Assuming this works fine I would then modify it for the lwtimer capability.

Regards,

David

1,634 Views
lucasdias
Contributor II

Ok David !
Thanks for the feedback! I will check these documents.

Regards,

Lucas Dias

0 Kudos
1,634 Views
lucasdias
Contributor II

Hi David!
I don't know if this topic is right , but I can not find much information about the lwtimer communities , etc.
I'm using a MK24FN1M0VLQ12 Kinetis , and the KDS KSDK 1.3 development platform.

Do the procedure , you quoted above ( had done in Code Warrior and worked perfectly ), but the KDS does not work , the system hangs .
Do you have any tips or information to help me ?

Thank you very much in advance!
Hug!

Att .
Lucas Dias

0 Kudos
1,635 Views
DavidS
NXP Employee
NXP Employee

Hi Emmanuel,

Example below:

 

#include <mqx.h>
#include <bsp.h>
#include <fio.h>
#include <lwtimer.h>


#if ! BSPCFG_ENABLE_IO_SUBSYSTEM
#error This application requires BSPCFG_ENABLE_IO_SUBSYSTEM defined non-zero in user_config.h. Please recompile BSP with this option.
#endif


#ifndef BSP_DEFAULT_IO_CHANNEL_DEFINED
#error This application requires BSP_DEFAULT_IO_CHANNEL to be not NULL. Please set corresponding BSPCFG_ENABLE_TTYx to non-zero in user_config.h and recompile BSP with this option.
#endif


/*  This example calls _timer_create_component before it activates the
**  timers so that the application can specify the timer task stack size.
**  The stack size may need to be larger than the TIMER_DEFAULT_STACK_SIZE
**  that is defined in timer.h, since the application's handler function uses
**  this stack. In this example, the handlers are LED_on and LED_off,
**  which have large stack requirements. You may need to increase the stack size
**  for your target hardware.
*/
#define LWTIMER_TASK_PRIORITY  2
#define LWTIMER_STACK_SIZE     2000

#define MAIN_TASK      10

extern void main_task(uint_32);
extern void LED_on(void);
extern void LED_off(void);
volatile _mqx_uint LED_on_counter=0;
volatile _mqx_uint LED_off_counter=0;


const TASK_TEMPLATE_STRUCT  MQX_template_list[] =
{
   /* Task Index, Function,   Stack, Priority,  Name,     Attributes,          Param, Time Slice */
    { MAIN_TASK,  main_task,  2000,     8,      "Main",   MQX_AUTO_START_TASK, 0,     0 },
    { 0 }
};

/*FUNCTION*------------------------------------------------------
*
* Function Name  : LED_on
* Returned Value : none
* Comments       :
*     This timer function prints out "ON"
*END*-----------------------------------------------------------*/
static void LED_on
   (
   )
{
   LED_on_counter++;
}

/*FUNCTION*------------------------------------------------------
*
* Function Name  : LED_off
* Returned Value : none
* Comments       :
*     This timer function prints out "OFF"
*END*-----------------------------------------------------------*/
static void LED_off
   (
   )
{
   LED_off_counter++;
}

/*TASK*----------------------------------------------------------
*
* Task Name : main_task
* Comments  :
*     This task creates two timers, each of a period of 2 seconds,
*     the second timer offset by 1 second from the first.
*END*-----------------------------------------------------------*/

void main_task
   (
      uint_32 initial_data
   )
{
   LWTIMER_PERIOD_STRUCT ps;
   LWTIMER_STRUCT lst_on, lst_off;
   _mqx_uint time=20;
     
   _mqx_uint period=6;
   _mqx_uint wait_ticks=0;
   _mqx_uint delay_on=3;
   _mqx_uint delay_off=3;

   printf("\n\nTwo lwtimers are created, each of a period of %d ticks,\nthe second lwtimer offset by %d ticks from the first.\n", period, delay_off);
   printf("Task runs for %d seconds,\nthen lwtimers are closed and task finishes.\n\n", time);          

   /*
   ** Create the lwtimer component with more stack than the default
   ** in order to handle printf() requirements:
   */
   _lwtimer_create_periodic_queue(&ps, period, wait_ticks);

   _lwtimer_add_timer_to_queue(&ps, &lst_on, delay_on, LED_on, 0);

   _lwtimer_add_timer_to_queue(&ps, &lst_off, delay_off, LED_off, 0);


   _time_delay(time * 1000); // wait 6 seconds
   printf("\nThe task is finished!");
   printf("\nLED_on_counter = %d LED_off_counter = %d", LED_on_counter, LED_off_counter);

   _lwtimer_cancel_period(&ps);

   _mqx_exit(0);

}

/* EOF */

 

Regards,

David

0 Kudos
1,634 Views
kaustubhkagalka
Contributor II

Hi David,

Is it practical to do a constant loop with this function ? i.e. doing a constant LED_off and LED_on using this lwtimer function?

Currently, I am using lwevent_wait_ticks timeout for a periodic function. I am looking for a function which calls a specific function say every 10 msec.

Sorry if my question is too specific.

Thanks.

0 Kudos
1,634 Views
DavidS
NXP Employee
NXP Employee

Hi Kaustubh,

The following timer routine would work:

_timer_start_periodic_every(specific_function,NULL,TIMER_KERNEL_TIME_MODE,10);


This would setup a timer task that will execute/call the specific_function() every 10msec.

You do have to be careful that the function it is calling is short and non-blocking.

The timer task operates at a very high priority level (2 I think).  It basically is preempting the RTOS.

If the function you want to call is "big" and/or calls blocking API, then best to keep it setup that way you have implemented.


Regards,

David

1,634 Views
kaustubhkagalka
Contributor II

Hi David,

I am using this particular task to print a debug-buffer array via UART, so it is definitely not short or high priority, so I think I will stick with my current implementation. But I will definitely try this somewhere else.

Thanks a lot!

Kaustubh

0 Kudos
1,634 Views
d_
Contributor I

David,

I'm confused by your example.  First, I couldn't get it to compile unless I cast the LED functions as LWTIMER_ISR_FPTR) LED_on and LWTIMER_ISR_FPTR) LED_off.  I assume this is because of additional error checking in the compiler 3 years later.

Next, I still can't figure out the difference between the argument "period" in the create function and the arguments delay_on and delay_off in the add timer functions.  delay_on and delay_off have to be smaller than period, but how does this work?  Just what is being created when you create a queue?  What actually is happening when you add a timer?  Are these timers continuously running?  I would not think so, but then why would you be incrementing counters in the callbacks?

What I need to do is create a one-shot timer with a programmable period in msec.  The range might be 50 to 15000 msec.  What would I use for your period and delay_on or delay_off arguments?  (The tick is 1 msec I believe.)

Thanks,

Dave


0 Kudos
1,634 Views
d_
Contributor I

Setting ticks = 50 with period = 100 doesn't seem to have any affect.

I'm guessing that the ticks is a delay from the timer trigger to the callback.  So for a one-shot timer I would set ticks to zero.

Dave

0 Kudos
1,634 Views
DavidS
NXP Employee
NXP Employee

 

Hi Dave,

 

Sorry for delay.  I have returned from PTO and fought off the avalanche of emails now.

 

I'm not clear on exactly what you want your application to do.  Let me state what I interpret and please correct me.

 

You want to control a GPIO pin/signal.  Correct?

 

If yes, then you want to be able to control having it toggle at a rate of 50-15,000msec.  Correct?

 

If yes, then my question is how long to you want that toggle rate to last (i.e. when should the toggling be disabled)?

 

 

 

A different implementation that might be better for your application is to use following:

 

       _timer_start_periodic_every (LED_toggle,NULL,TIMER_KERNEL_TIME_MODE,50);   //DES timer task created and LED_toggle function called every 50msec

 

          _timer_start_oneshot_after(LED_toggle,NULL,TIMER_KERNEL_TIME_MODE,5);   //DES LED_toggle executed once each while(TRUE) loop ...need some delay 5 or greater to work.

 

 

I’m attaching my MQX4.1 “C” file that I have used to play with this and it is part of the web_hvac example.  In the code you can search for “//DES” to see where I have made modifications and added the LED_toggle callback function.

 

 

Regards,

 

David

 

0 Kudos
1,634 Views
d_
Contributor I

Hi David,

I figured out the lwtimer.  Documentation could be better.

Thanks for the tip on the periodic and one-shot timers.  I'm new to MQX and was steered away from using these for reasons I don't understand.  I tried the one-shot and it works fine.  I don't believe it can have any negative affects on the system (mostly a concern as to how it would affect PEG usage).

Thanks again.

Dave

0 Kudos
1,634 Views
DavidS
NXP Employee
NXP Employee

Hi Dave,

The oneshot basically is creating a very high priority timer task that will pre-empt the RTOS like an "interrupt" does and then return back the code base.  So the rule of thumb is to treat any code within the defined callback as interrupt code (i.e. do not call anything that could block).

Regards,

David

1,634 Views
d_
Contributor I

Yes, thanks David.

Dave

0 Kudos
1,634 Views
d_
Contributor I

Experimenting, I set the period argument in the create function to 100 and the ticks argument in the add function to 3.  I see that I get a periodic interrupt every 500 msec.  I thought the timer was based on 1 msec, but now see that it is based on a 5 msec period.  So the period of 100 gives a continuous periodic callback every 500 msec.  OK.  That makes sense.

I'm still confused by what the ticks = 3 does.  I'll keep investigating.

Dave

0 Kudos
1,634 Views
Nouchi
Senior Contributor II

Thanks David, good example........

0 Kudos