I'm planning to use my STM32 board to send CAN frames. I implemented a simple scheduler that contains 10 tasks;one task will be responsible to send frames.
To do the job I declared a structure for the CAN frame:
typedef struct
{
unsigned int id;
unsigned char data[];
unsigned char dlc;
unsigned int timeOfSend //This is the time in ms in which a frame should be sent
}tFrame;
And then I declared a table of the frames to be sent
aubFrames[MAX_FRAMES] = {
{0x12, 0xAABBCC, 4, 100},
{0x12, 0xAABBCC, 4, 1000},
{0x12, 0xAABBCC, 4, 2000},
{0x12, 0xAABBCC, 4, 2010}
};
This tell the board to send the first frame after 100 ms, the second after 1000 ms, etc.
What I actually do:
I added a new task in the scheduler with a period of 10 ms. This task will check the aubFrames table and if it's time to send a frame it sends the concerned frame, else nothing is to be done. The problem with this solution is that there is a big loss of time. For example, to send the first frame the scheduler access to this task nine times, but with nothing to do.
Is there another solution so that the scheduling will be more effective?
I thought to use a timer interrupt, but I don't think that's the good solution since there are only four timers on the board and the number of frames is more than four, so in my opinion configuring the timers to generate interrupts for different period of time won't work.
Most RTOSes have a couple of features that seem like they could be appropriate.
One method is for the task to suspend itself for the appropriate amount of time (rather than waking periodically to poll whether it's time). For example, FreeRTOS has the vTaskDelay
function, which blocks the task for a specified amount of time. Your task knows that it doesn't have to do anything for 100 or 1000 ms so it should delay itself for that amount of time.
Another method is to use a software timer rather than a hardware timer. The RTOS is apparently already getting a periodic tick because it knows to wake your task every 10 ms. It probably also has a software timer service like this one from FreeRTOS. The software timer service is driven by the hardware timer that the RTOS scheduler uses. And it allows you to set up a variety of periodic and single-shot software timers without the need for another hardware timer. Your task could read the aubFrames
array and setup a one-shot timer for each frame, which expire at the appropriate times. If you don't like the idea of all those software timers running at once then set up the next timer with the previous timer expires.