Skip to content

Commit 6b21a18

Browse files
authored
Merge pull request #1 from fpistm/FreeRTOS-9.0.0
First version based on FreeRTOS 9.0.0
2 parents 7f312cb + 0072887 commit 6b21a18

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+36756
-0
lines changed

README.md

+46
Original file line numberDiff line numberDiff line change
@@ -1 +1,47 @@
11
# STM32 FreeRTOS Library for Arduino
2+
3+
This is a port of FreeRTOS for STM32 as Arduino libraries.
4+
5+
For more information about FreeRTOS, visit the [FreeRTOS Web Site](http://www.freertos.org/ "FreeRTOS").
6+
Also, See the very useful [Getting Started](http://www.freertos.org/FreeRTOS-quick-start-guide.html "Quick Start Guide") page.
7+
8+
Current FreeRTOS version used for this library is [9.0.0](http://www.freertos.org/FreeRTOS-V9.html) and has been modified by ST (See st_readme.txt in FreeRTOS Source).
9+
10+
This is the current one provided with the [STM32Cube MCU Packages](http://www.st.com/en/embedded-software/stm32cube-mcu-packages.html)
11+
12+
## Configuration
13+
14+
FreeRTOS has several configuration options, which can be specified from within the FreeRTOSConfig.h file.
15+
16+
This library provides a default FreeRTOS configuration file named `FreeRTOSConfig_Default.h`.
17+
18+
User can provide his own FreeRTOS configuration file at sketch level by adding his configuration in a file named `STM32FreeRTOSConfig.h`.
19+
20+
Heap allocation schemes are provided by FreeRTOS, see [Memory allocation implementations included in the RTOS source](https://www.freertos.org/a00111.html).
21+
By default, the `heap_3.c` is used. It can be changed thanks a define in the configuration file:
22+
```
23+
/* Default (3) Memory allocation implementations (heap_[1-5].c) */
24+
/*#define configMEMMANG_HEAP_NB 3*/
25+
```
26+
27+
## Limitations
28+
29+
* MPU: not supported.
30+
31+
## Files & Configuration
32+
33+
* STM32FreeRTOS.h : Must always be #include first. It references required include files.
34+
* STM32FreeRTOSConfig.h : If exist at sketch level, it contains the FreeRTOS configurations.
35+
* FreeRTOSConfig_Default.h : Contains the default FreeRTOS configurations for this STM32 port if `STM32FreeRTOSConfig.h` doesn't exist.
36+
37+
## Test results (using [Arduino_Core_STM32](https://github.com/stm32duino/Arduino_Core_STM32))
38+
| Board | AnalogRead_DigitalRead | Blink_AnalogRead | frBlink | frBlinkPrint | frJitter | frLiuLayland |
39+
| --- | :---: | :---: | :---: | :---: | :---: | :---: |
40+
| [Nucleo F091RC](http://www.st.com/en/evaluation-tools/nucleo-f091rc.html) | PASSED | PASSED | PASSED | PASSED | PASSED | FAILED |
41+
| [Nucleo F103RB](http://www.st.com/en/evaluation-tools/nucleo-f103rb.html) | PASSED | PASSED | PASSED | PASSED | PASSED | PASSED |
42+
| [Nucleo F303RE](http://www.st.com/en/evaluation-tools/nucleo-f303re.html) | PASSED | PASSED | PASSED | PASSED | PASSED | PASSED |
43+
| [Nucleo F429ZI](http://www.st.com/en/evaluation-tools/nucleo-f429zi.html) | PASSED | PASSED | PASSED | PASSED | PASSED | PASSED |
44+
| [STM32F746G-DISCOVERY](http://www.st.com/en/evaluation-tools/32f746gdiscovery.html) | PASSED | PASSED | PASSED | PASSED | PASSED | PASSED |
45+
| [Nucleo L053R8](http://www.st.com/en/evaluation-tools/nucleo-l053r8.html) | PASSED | PASSED | PASSED | PASSED | PASSED | FAILED |
46+
| [Nucleo L152RE](http://www.st.com/en/evaluation-tools/nucleo-l152re.html) | PASSED | PASSED | PASSED | PASSED | PASSED | PASSED |
47+
| [B-L475E-IOT01A](http://www.st.com/en/evaluation-tools/b-l475e-iot01a.html) | PASSED | PASSED | PASSED | PASSED | PASSED | PASSED |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Based on AnalogRead_DigitalRead example from: https://github.com/feilipu/Arduino_FreeRTOS_Library
3+
* Modified by: Frederic Pillon <frederic.pillon (at) st.com>
4+
*/
5+
#include <STM32FreeRTOS.h>
6+
7+
// If no default pin for user button (USER_BTN) is defined, define it
8+
#ifndef USER_BTN
9+
#define USER_BTN 2
10+
#endif
11+
12+
// Declare a mutex Semaphore Handle which we will use to manage the Serial Port.
13+
// It will be used to ensure only only one Task is accessing this resource at any time.
14+
SemaphoreHandle_t xSerialSemaphore;
15+
16+
// define two Tasks for DigitalRead & AnalogRead
17+
void TaskDigitalRead( void *pvParameters );
18+
void TaskAnalogRead( void *pvParameters );
19+
20+
// the setup function runs once when you press reset or power the board
21+
void setup() {
22+
23+
// initialize serial communication at 9600 bits per second:
24+
Serial.begin(9600);
25+
26+
while (!Serial) {
27+
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.
28+
}
29+
30+
// Semaphores are useful to stop a Task proceeding, where it should be paused to wait,
31+
// because it is sharing a resource, such as the Serial port.
32+
// Semaphores should only be used whilst the scheduler is running, but we can set it up here.
33+
if ( xSerialSemaphore == NULL ) // Check to confirm that the Serial Semaphore has not already been created.
34+
{
35+
xSerialSemaphore = xSemaphoreCreateMutex(); // Create a mutex semaphore we will use to manage the Serial Port
36+
if ( ( xSerialSemaphore ) != NULL )
37+
xSemaphoreGive( ( xSerialSemaphore ) ); // Make the Serial Port available for use, by "Giving" the Semaphore.
38+
}
39+
40+
// Now set up two Tasks to run independently.
41+
xTaskCreate(
42+
TaskDigitalRead
43+
, (const portCHAR *)"DigitalRead" // A name just for humans
44+
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater
45+
, NULL
46+
, 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
47+
, NULL );
48+
49+
xTaskCreate(
50+
TaskAnalogRead
51+
, (const portCHAR *) "AnalogRead"
52+
, 128 // Stack size
53+
, NULL
54+
, 1 // Priority
55+
, NULL );
56+
57+
// start scheduler
58+
vTaskStartScheduler();
59+
Serial.println("Insufficient RAM");
60+
while(1);
61+
}
62+
63+
void loop()
64+
{
65+
// Empty. Things are done in Tasks.
66+
}
67+
68+
/*--------------------------------------------------*/
69+
/*---------------------- Tasks ---------------------*/
70+
/*--------------------------------------------------*/
71+
72+
void TaskDigitalRead( void *pvParameters __attribute__((unused)) ) // This is a Task.
73+
{
74+
/*
75+
DigitalReadSerial
76+
Reads a digital input on pin defined with USER_BTN, prints the result to the serial monitor
77+
78+
This example code is in the public domain.
79+
*/
80+
81+
// defined USER_BTN digital pin has a pushbutton attached to it. Give it a name:
82+
uint8_t pushButton = USER_BTN;
83+
84+
// make the pushbutton's pin an input:
85+
pinMode(pushButton, INPUT);
86+
87+
for (;;) // A Task shall never return or exit.
88+
{
89+
// read the input pin:
90+
int buttonState = digitalRead(pushButton);
91+
92+
// See if we can obtain or "Take" the Serial Semaphore.
93+
// If the semaphore is not available, wait 5 ticks of the Scheduler to see if it becomes free.
94+
if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
95+
{
96+
// We were able to obtain or "Take" the semaphore and can now access the shared resource.
97+
// We want to have the Serial Port for us alone, as it takes some time to print,
98+
// so we don't want it getting stolen during the middle of a conversion.
99+
// print out the state of the button:
100+
Serial.print("Button state: ");
101+
Serial.println(buttonState);
102+
103+
xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others.
104+
}
105+
106+
vTaskDelay(1); // one tick delay (15ms) in between reads for stability
107+
}
108+
}
109+
110+
void TaskAnalogRead( void *pvParameters __attribute__((unused)) ) // This is a Task.
111+
{
112+
113+
for (;;)
114+
{
115+
// read the input on analog pin 0:
116+
int sensorValue = analogRead(A0);
117+
118+
// See if we can obtain or "Take" the Serial Semaphore.
119+
// If the semaphore is not available, wait 5 ticks of the Scheduler to see if it becomes free.
120+
if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
121+
{
122+
// We were able to obtain or "Take" the semaphore and can now access the shared resource.
123+
// We want to have the Serial Port for us alone, as it takes some time to print,
124+
// so we don't want it getting stolen during the middle of a conversion.
125+
// print out the value you read:
126+
Serial.println(sensorValue);
127+
128+
xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others.
129+
}
130+
131+
vTaskDelay(1); // one tick delay (15ms) in between reads for stability
132+
}
133+
}
134+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Based on Blink_AnalogRead example from: https://github.com/feilipu/Arduino_FreeRTOS_Library
3+
* Modified by: Frederic Pillon <frederic.pillon (at) st.com>
4+
*/
5+
#include <STM32FreeRTOS.h>
6+
7+
// define two tasks for Blink & AnalogRead
8+
void TaskBlink( void *pvParameters );
9+
void TaskAnalogRead( void *pvParameters );
10+
11+
// the setup function runs once when you press reset or power the board
12+
void setup() {
13+
14+
// initialize serial communication at 9600 bits per second:
15+
Serial.begin(9600);
16+
17+
while (!Serial) {
18+
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.
19+
}
20+
21+
// Now set up two tasks to run independently.
22+
xTaskCreate(
23+
TaskBlink
24+
, (const portCHAR *)"Blink" // A name just for humans
25+
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater
26+
, NULL
27+
, 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
28+
, NULL );
29+
30+
xTaskCreate(
31+
TaskAnalogRead
32+
, (const portCHAR *) "AnalogRead"
33+
, 128 // Stack size
34+
, NULL
35+
, 1 // Priority
36+
, NULL );
37+
38+
// start scheduler
39+
vTaskStartScheduler();
40+
Serial.println("Insufficient RAM");
41+
while(1);
42+
}
43+
44+
void loop()
45+
{
46+
// Empty. Things are done in Tasks.
47+
}
48+
49+
/*--------------------------------------------------*/
50+
/*---------------------- Tasks ---------------------*/
51+
/*--------------------------------------------------*/
52+
53+
void TaskBlink(void *pvParameters) // This is a task.
54+
{
55+
(void) pvParameters;
56+
57+
/*
58+
Blink
59+
Turns on an LED on for one second, then off for one second, repeatedly.
60+
61+
Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO
62+
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care
63+
of use the correct LED pin whatever is the board used.
64+
65+
The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute
66+
the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.
67+
e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.
68+
69+
If you want to know what pin the on-board LED is connected to on your Arduino model, check
70+
the Technical Specs of your board at https://www.arduino.cc/en/Main/Products
71+
72+
This example code is in the public domain.
73+
74+
modified 8 May 2014
75+
by Scott Fitzgerald
76+
77+
modified 2 Sep 2016
78+
by Arturo Guadalupi
79+
*/
80+
81+
// initialize digital LED_BUILTIN on pin 13 as an output.
82+
pinMode(LED_BUILTIN, OUTPUT);
83+
84+
for (;;) // A Task shall never return or exit.
85+
{
86+
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
87+
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
88+
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
89+
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
90+
}
91+
}
92+
93+
void TaskAnalogRead(void *pvParameters) // This is a task.
94+
{
95+
(void) pvParameters;
96+
97+
/*
98+
AnalogReadSerial
99+
Reads an analog input on pin 0, prints the result to the serial monitor.
100+
Graphical representation is available using serial plotter (Tools > Serial Plotter menu)
101+
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
102+
103+
This example code is in the public domain.
104+
*/
105+
106+
for (;;)
107+
{
108+
// read the input on analog pin 0:
109+
int sensorValue = analogRead(A0);
110+
// print out the value you read:
111+
Serial.println(sensorValue);
112+
vTaskDelay(1); // one tick delay (15ms) in between reads for stability
113+
}
114+
}
115+

examples/frBlink/frBlink.ino

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Example to demonstrate thread definition, semaphores, and thread sleep.
3+
*/
4+
#include <STM32FreeRTOS.h>
5+
6+
// Define the LED pin is attached
7+
const uint8_t LED_PIN = LED_BUILTIN;
8+
9+
// Declare a semaphore handle.
10+
SemaphoreHandle_t sem;
11+
//------------------------------------------------------------------------------
12+
/*
13+
* Thread 1, turn the LED off when signalled by thread 2.
14+
*/
15+
// Declare the thread function for thread 1.
16+
static void Thread1(void* arg) {
17+
UNUSED(arg);
18+
while (1) {
19+
20+
// Wait for signal from thread 2.
21+
xSemaphoreTake(sem, portMAX_DELAY);
22+
23+
// Turn LED off.
24+
digitalWrite(LED_PIN, LOW);
25+
}
26+
}
27+
//------------------------------------------------------------------------------
28+
/*
29+
* Thread 2, turn the LED on and signal thread 1 to turn the LED off.
30+
*/
31+
// Declare the thread function for thread 2.
32+
static void Thread2(void* arg) {
33+
UNUSED(arg);
34+
pinMode(LED_PIN, OUTPUT);
35+
36+
while (1) {
37+
// Turn LED on.
38+
digitalWrite(LED_PIN, HIGH);
39+
40+
// Sleep for 200 milliseconds.
41+
vTaskDelay((200L * configTICK_RATE_HZ) / 1000L);
42+
43+
// Signal thread 1 to turn LED off.
44+
xSemaphoreGive(sem);
45+
46+
// Sleep for 200 milliseconds.
47+
vTaskDelay((200L * configTICK_RATE_HZ) / 1000L);
48+
}
49+
}
50+
//------------------------------------------------------------------------------
51+
void setup() {
52+
portBASE_TYPE s1, s2;
53+
54+
Serial.begin(9600);
55+
56+
// initialize semaphore
57+
sem = xSemaphoreCreateCounting(1, 0);
58+
59+
// create task at priority two
60+
s1 = xTaskCreate(Thread1, NULL, configMINIMAL_STACK_SIZE, NULL, 2, NULL);
61+
62+
// create task at priority one
63+
s2 = xTaskCreate(Thread2, NULL, configMINIMAL_STACK_SIZE, NULL, 1, NULL);
64+
65+
// check for creation errors
66+
if (sem== NULL || s1 != pdPASS || s2 != pdPASS ) {
67+
Serial.println(F("Creation problem"));
68+
while(1);
69+
}
70+
71+
// start scheduler
72+
vTaskStartScheduler();
73+
Serial.println("Insufficient RAM");
74+
while(1);
75+
}
76+
77+
//------------------------------------------------------------------------------
78+
// WARNING idle loop has a very small stack (configMINIMAL_STACK_SIZE)
79+
// loop must never block
80+
void loop() {
81+
// Not used.
82+
}

0 commit comments

Comments
 (0)