ME507 Utility Library  0.2.1
Mechatronics Course Support Software for ARM/Arduino/FreeRTOS
ME507 Utility Library Documentation

Introduction

This library supports the programming of microcontrollers for the ME507 mechatronics course at California Polytechnic State University, San Luis Obispo. It contains some C++ "wrapper" classes which facilitate the use of FreeRTOS for efficient multitasking on microcontrollers.

Tasks

The ME507 library uses FreeRTOS tasks with essentially no modifications. Using the library requires the following #include lines:

#include <Arduino.h>
#if defined (STM32L4xx || defined STM32F4xx)
#include <STM32FreeRTOS.h>
#endif
#include <PrintStream.h>
#include "taskshare.h"
#include "taskqueue.h"

The #if defined directive is used to include a library only when an STM32 processor is being used. If your project will never use an STM32 processor, those three lines may be left out, and it it will only ever run on an STM32, the #include <STM32FreeRTOS.h> may be used without the #if directive around it.

Each task is implemented by writing a task function; all task functions have the following form:

/** @brief Task function which measures the heart rate of a loon.
* @details The details aren't important; this is just an example.
* @param p_params A pointer to function parameters which we don't use.
*/
void task_loony_heart (void* p_params)
{
// Setup code: Create variable(s) and initialize hardware
int16_t birdy_rate;
avian_HRM.init (-32.2);
for (;;)
{
// Measure and save heart rate
birdy_rate = avian_HRM.measure ();
my_SD_card.store (birdy_rate);
// Run the loop code every ~2.5 seconds
vTaskDelay (2500);
}
}

A task function such as the one above is run by the FreeRTOS scheduler after the scheduler has been started. The task must be registered with the scheduler through the use of the xTaskCreate() function:

// Create a task which measures shorebird pulmonary function
xTaskCreate (task_loony_heart, // Task function
"Send", // Name shown on printouts
256, // Stack size
NULL, // Parameters for task function
3, // Priority
NULL); // Place to save task handle, if used

The FreeRTOS scheduler may or may not need to be started, depending on the processor being used. See the platform-specific notes below for details.

Shares

The term "shared variables" is used herein to mean variables which carry information from one task to another. Shares are used to communicate data whose current value is important but whose history is not; previous values of a shared variable are assumed to be unimportant, as they are overwritten whenever a new value is put into the share. The shared variables used here are different from ordinary global variables in that these shares employ protection mechanisms to ensure that data transmitted from one task to another is not corrupted due to the RTOS switching between tasks using an interrupt based mechanism. Ordinary global variables are not thread-safe and must not be used to exchange data between tasks.

See the documentation for class Share for information on how to use these shared variable objects. Expand the Classes category in the navigation bar to find this documentation.

Queues

Queues are used to communicate data between tasks in such a way that older data is not lost when new data is placed into a queue. This is done through the use of a buffer in each queue; it's a bit like polite people standing in line. The receiving task removes (gets) data from the queue in the order in which data was put into the queue by the sending task.

See the documentation for class Queue for information on how to use this wrapper class to implement inter-task queues. Expand the Classes category in the navigation bar to find this documentation.

There is also a queue for text, class TextQueue. A queue made from this class can only hold characters of type char, but it can be written using the stream insertion operator <<. This is convenient when one task wants to write quick bursts of data to a slow receiving device such as a serial terminal or SD card.

Platform-Specific Notes

The ESP32 port of the Arduino environment has FreeRTOS support build in, and FreeRTOS tasks can be used without any special effort. When setup() is running, tasks can be created using xTaskCreate() and will begin to run as soon as they have been created. The Arduino header must be included, and we like to use the Arduino-PrintStream library as well. See below for the necessary #include lines.

The STM32 port of Arduino requires some extra effort. The STM32FreeRTOS software must be attached. In addition, the scheduler must be explicitly started; this is not the case for many other FreeRTOS Arduino ports. To start the FreeRTOS scheduled for STM32's, place the following lines as the last lines in function setup():

#if defined (STM32L4xx || defined STM32F4xx)
vTaskStartScheduler ();
#endif

If your code will only ever run on an STM32, you may omit the preprocessor directives and always call vTaskStartScheduler().

Hardware

This software is designed to run on most microcontroller platforms using ARM Cortex™ processors. Boards which are specifically supported for the ME507 course are STM32 Nucleo-64™ boards with the STM32L476RG and the KeeYees™ board with an ESP-WROOM-32 module. Many other boards should work fine as long as they are supported by the Arduino environment.

taskshare.h
Data which can be shared between tasks in a thread-safe manner.
taskqueue.h