MCU learning, Intermediate-Level, Part 3, Using STM of NXP MPC5744P to implement a software timer.
Last time we talked about the eTimer module for some application. But MPC5744P also offered a System Timer Module for some system level application.
It remind us that Particle Photon also has a function called “software timer”. How about we also create our DIY software timer? So,this article will cover how to configure STM and implement a software timer in C. Since we have ability to measure time in a releative precise way, we can also implement the function to return the time pass since device boot-up.
What do you need for this exercise?
- MPC5744P dev-board: LINK
- S32 design studio for MPC5744P: LINK
- The example that we provided: LINK
- MPC5744P User manual Rev6(2016/06)
What are we focusing on today?
- How to configure the STM on the MPC57444P?
- How to implement a software timer in the C language?
The basic idea of the configuration of software time.
The STM is relatively easy to use compared with eTimer. STM only has 1*counter register, 1*control register, 4*channel control registers, 4*channels of compare registers, and 4*channels of interrupt registers.
The flowchart of configuring STM is shown in the following picture.
The first step is to disable the STM. Then also disable the channel that you want to configure.
Follow by assigning the desired compare value that you want SMT to generate the interrupt. The STM clock speed can be as fast as 50Mhz. In this case, we configure it to 50Mhz.
Furthermore, we would like to keep the MAX clock speed, so we let the STM_CPS(Counter Prescaler Register) set to 0 which is divided by 1.
Then, to make sure the counter is 0, we also need to clear the counter. Finally, we can enable the channel and STM.
Calculate the compare register value
This calculation is based on some conditions:
a. STM Clock Speed (PBRIDGEx_CLK) is set to 50MHz via the following code:
b. STM_CPS(Counter Prescaler Register) set to 0
In void SysClk_Init(void):MC_CGM.SC_DC0.R = 0x80030000;
// PBRIDGE0/PBRIDGE1_CLK at syst clk div by 4 ... (50 MHz)
Assign the stm_isr to the interrupt vector.
By far, we had known how to configure STM Channel 0 to create an interrupt every 1ms. Then it is the same process as eTimer. Assigned the STM_O compare register interrupt vector to stm_isr();
/* Vector # 36 Platform periodic timer 0_0 (STM) STM */
Also, remember to assign priority to the interrupt service routine as well,
INTC_0.PSR.R = 0x8002; //set interrupt priority
Then, we will implement the software timer in this stm_isr();
How to implement the software timer?
Software timer event
Let’s talk about a brief idea about how to use the software timer.
The user should initialize the hardware of the System Time Module. The initialization process includes the above parameters set up. To simplify the example, stm_init() does not take any input parameters now.
Then users can register their function with the assigned period.
We should define the structure that will carry the necessary information.
The most important part of the information is the function name. Function name also refers to a memory address in the embedded system eventually. The second information is the period of this event. It will affect how long it will be executed. Then, the position of this event structure in the array. Finally is the Enable state.
2. Structure array(timer.c)
Once we have defined the structure, we will create an array for this structure. However, there is a limit on the number. It will depend on the characteristic of the timer event and CPU loading.
Similar to the interrupt ISR, it should not be blocked for a long period if you care about real-time performance. Currently, the MAX event number is 10.
3. Initialize the structure array(timer.c)
Once we had defined the structure array, we need to initialize it. In C language, it is recommended that you initialize the object that you create if possible. In this way, the content of the object won’t be unknown or undefined.
We create a virtual or useless task called “my_dummy()”. It will do nothing and we just initialize the array with “my_dummy()” with 1 second period. With this dummy timer event, every element in this array will be assigned to a “defined” event.
4. Register an event to the software timer(timer.c)
The next stage is we need to register the timer event to the software timer. This part of the code will need to check several conditions. a) Is the function’s address existed? b) Is the period greater than 0? c) Is there an empty slot for the new event?
It will be tricky if the user assigned an event which is the NULL. We do not implement a safety mechanism that could be a watchdog timer yet. We also try to limit the period.
For future development, I also reserve a variable called EventArryIndex which will record the position of this event in the array.
Once we complete it, the flag is set to TRUE and NumberOfRegisteredEven is added 1. Finally, make sure we return the status of success or not.
4. STM ISR(timer.c)
The core of this function will be the ISR itself. Generally, we will clear the interrupt flag first. STM does not reset the counter like eTimer, so we will need to clear the counter register too.
Then, we will execute each registered software timer event by the sequence of the array. In this stage, we need to check 2 conditions:
a) Is the timer event enable?
b) Is the timer event reach out the period?
Once the registered event meets these 2 conditions, it will be executed.
We also use this ISR to count the time since the device boot on and STM is initialized.
Putt all together:
You should be able to find the complete project in the link that we provide. It gives you an idea of how a software timer can be implemented.
Once you flash the code to the dev-board, you should see the LED flashing around 1Hz. We created 3 tasks for RGB led. Each task will toggle led at the assigned period. You can change the period to observe the effects.
If you have a computer science background, you may remember that in the lecture related to “Operating System” there is a topic talks about Scheduling!
Does that brings up some memories?! The software timer event here is similar to what OS did. But it is still far away to compare a complex / fully-functional OS.
OS scheduling normally provides some characteristics such as preemptive, priority, different scheduling options…etc. Here is just a FIRST-COME-FIRST-SERVE / Non-preemptive / Non-priority scheduling…hmm…maybe NOT event a task scheduling strictly speaking.
This is also mentioned in The Particle OS API statement:
To do list:
- Priority feature:
Preemptive is relatively hard to implement, but priority is something relatively easy. The STM_ISR can execute the software timer event’s sequence according to the priority. Higher Priority event will be executed first. And it will not create famous the hungry situation, since each event must be executed and it is not preemptive.
2. Watchdog timer:
ISR should not be blocked for a long time, so adding a watchdog will guarantee that the task will be ended or force to stop in an assigned period.
In some real-time applications, the feature of real-time is essential. There are many features that can increase and ensure instantaneity. The watchdog timer is an example.