I’m new to FreeRTOS and studying the book from FreeRTOS. I’m trying to test Idle hook function, so I need to edit parameter of FreeRTOSConfig.h (configUSE_IDLE_HOOK -> 1).
My hardware is STM32F103C8T6 blue pill from ebay and my code is as follow:
#include <MapleFreeRTOS821.h>
/* The task function. */
void vTaskFunction( void *pvParameters );
/* A variable that is incremented by the idle task hook function. */
static unsigned long ulIdleCycleCount = 0UL;
/* Define the strings that will be passed in as the task parameters. These are
defined const and off the stack to ensure they remain valid when the tasks are
executing. */
const char *pcTextForTask1 = "Task 1 is running\r\n";
const char *pcTextForTask2 = "Task 2 is running\t\n";
/*-----------------------------------------------------------*/
void setup()
{
/* Create the first task at priority 1... */
xTaskCreate( vTaskFunction, "Task 1", 1000, (void*)pcTextForTask1, 1, NULL );
/* ... and the second task at priority 2. The priority is the second to
last parameter. */
xTaskCreate( vTaskFunction, "Task 2", 1000, (void*)pcTextForTask2, 2, NULL );
/* Start the scheduler so our tasks start executing. */
vTaskStartScheduler();
for( ;; );
}
void loop() {}
void vTaskFunction( void *pvParameters )
{
char *pcTaskName;
/* The string to print out is passed in via the parameter. Cast this to a
character pointer. */
pcTaskName = ( char * ) pvParameters;
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task AND the number of times ulIdleCycleCount
has been incremented. */
Serial.println(pcTaskName);
Serial.println(ulIdleCycleCount);
/* Delay for a period. This time we use a call to vTaskDelay() which
puts the task into the Blocked state until the delay period has expired.
The delay period is specified in 'ticks'. */
vTaskDelay( 250 / portTICK_RATE_MS );
}
}
/*-----------------------------------------------------------*/
/* Idle hook functions MUST be called vApplicationIdleHook(), take no parameters,
and return void. */
void vApplicationIdleHook( void )
{
/* This hook function does nothing but increment a counter. */
ulIdleCycleCount++;
}
extern "C" void vApplicationIdleHook( void )
{
/* This hook function does nothing but increment a counter. */
ulIdleCycleCount++;
}
It’s working now, so extern “C” is used for calling a C function from C++.
So questions:
- when did you last get the Libmaple core code?
- what OS are you using?
- which version of Arduino GUI and GCC compiler are you using?
- which board and board options are you using?
Thanks in advance and best, E.
Thanks for your help.
when did you last get the Libmaple core code? -> Recent one https://github.com/rogerclarkmelbourne/Arduino_STM32
what OS are you using? -> Win 10
which version of Arduino GUI and GCC compiler are you using? -> Arduino IDE v 1.6.9 and follow instruction from https://github.com/rogerclarkmelbourne/Arduino_STM32
which board and board options are you using? -> STM32F103C8T6 blue pill from ebay
Here is my another working code:
#include <MapleFreeRTOS821.h>
#define pinLED PC13 //For STM32F103C8T6
/* The task function. */
void vTaskFunction( void *pvParameters );
/* A variable that is incremented by the idle task hook function. */
static uint32_t ulIdleCycleCount = 0UL;
const char *pcTextForTask1 = "\n\rTask 1 is running, ulIdleCycleCount = ";
const char *pcTextForTask2 = "\n\rTask 2 is running, ulIdleCycleCount = ";
extern "C" void vApplicationIdleHook( void )
{
/* This hook function does nothing but increment a counter. */
ulIdleCycleCount++;
}
void vTaskFunction( void *pvParameters )
{
char *pcTaskName;
const TickType_t xDelay250ms = pdMS_TO_TICKS( 1UL );
/* The string to print out is passed in via the parameter. Cast this to a
character pointer. */
pcTaskName = ( char * ) pvParameters;
/* As per most tasks, this task is implemented in an infinite loop. */
for( ;; )
{
/* Print out the name of this task AND the number of times ulIdleCycleCount
has been incremented. */
Serial.print(pcTaskName);
Serial.print(ulIdleCycleCount);
/* Delay for a period of 250 milliseconds. */
digitalWrite(pinLED, HIGH);
vTaskDelay( xDelay250ms );
digitalWrite(pinLED, LOW);
vTaskDelay( xDelay250ms );
}
}
void setup()
{
// initialize the digital pin as an output:
pinMode(pinLED, OUTPUT);
Serial.begin(921600); //For Olimex Maple
// Now set up two tasks to run independently.
xTaskCreate(
vTaskFunction /* Pointer to the function that implements the task. */
, (const portCHAR *) "Task 1" /* Text name for the task. This is to facilitate debugging only. */
, configMINIMAL_STACK_SIZE /* Stack depth - most small microcontrollers will use much less stack than this. */
, (void*)pcTextForTask1 /* Pass the text to be printed into the task using the task parameter. */
, tskIDLE_PRIORITY + 1 /* Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.*/
, NULL );/* We are not using the task handle. */
xTaskCreate(
vTaskFunction /* Pointer to the function that implements the task. */
, (const portCHAR *) "Task 2" /* Text name for the task. This is to facilitate debugging only. */
, configMINIMAL_STACK_SIZE /* Stack depth - most small microcontrollers will use much less stack than this. */
, (void*)pcTextForTask2 /* Pass the text to be printed into the task using the task parameter. */
, tskIDLE_PRIORITY + 1 /* Change priority looks at what happens*/
, NULL );/* We are not using the task handle. */
// Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
vTaskStartScheduler();
/* If all is well we will never reach here as the scheduler will now be
running. If we do reach here then it is likely that there was insufficient
heap available for the idle task to be created. */
for( ;; );
}
void loop()
{
// Insert background code here
}
If I set:
xTaskCreate( vTaskFunction, "Task 1", 1000, (void*)pcTextForTask1, 1, NULL );
xTaskCreate( vTaskFunction, "Task 2", 1000, (void*)pcTextForTask2, 2, NULL );
The defult config is kind of limited in the number of tasks, number of priorities, minimum stack size, etc. Have a look at the config file to see if there some config value that may be affecting you.
Maybe Pak changed something more (i.e. some config parameter or choose an upload method that for example does not drive the Maple VCP) and I was trying to find what..
If I set:
Code: Select all
xTaskCreate( vTaskFunction, “Task 1”, 1000, (void*)pcTextForTask1, 1, NULL );
xTaskCreate( vTaskFunction, “Task 2”, 1000, (void*)pcTextForTask2, 2, NULL );
the code breaks and Windows can’t even recognize the Maple Serial USB.
If instead I set:
Code: Select all
xTaskCreate( vTaskFunction, “Task 1”, 100, (void*)pcTextForTask1, 1, NULL );
xTaskCreate( vTaskFunction, “Task 2”, 100, (void*)pcTextForTask2, 2, NULL );
the code is working fine.
So it seems a memory allocation conflict issue..
Just wondering why this does not happen also to you as we are using almost the same mcu (I’m using a Maple mini in truth).
Another question: which upload method are you using?
I’m using the maple bootloader 2.0
Hello edogaldo,
Actually, I messed up the code with example from the book, I’m really sorry about that.
I’ve tried to test your code
xTaskCreate( vTaskFunction, "Task 1", 1000, (void*)pcTextForTask1, 1, NULL );
xTaskCreate( vTaskFunction, "Task 2", 1000, (void*)pcTextForTask2, 2, NULL );
The task’s stacks come to the Heap, you will not see its size there in the message (those 11kB are global vars only).
Double-check what your freertos Heap size is like:
configTOTAL_HEAP_SIZEhttp://www.freertos.org/uxTaskGetStackH … rMark.html
I have used in the past to confirm if I had stack overflow in a task that was failing, ended up being something else, but thanks to this code I adjusted the stack of each task according to actual usage rather than estimates.
Note that the highwater mark is not how much stack is used, but how much is unused.
I had 1 task running every N ms sending the highwtermark for each of the other tasks in the serial/usb port.
Also on v9 you can use statics for pretty much everything. You can allocate your tasks stack as static variables, that way you get it reported during compilation:
http://www.freertos.org/xTaskCreateStatic.html
There are several more settings related to stack, there is config to enable stack overflow detection, and I believe that one also fills up the stack with control charaters before it start running tasks.
Adding to Pito’s post, the FreeRTOS heap is used for all FreeRTOS objects, like semaphores, mutex, stacks… so those 8KB may run low quick depending what you do.
Thanks for suggestion.
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 120 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8 * 1024 ) )Your SRAM (BPill=20kB) includes several segments, like
. initialised global vars (.data)
. uninitialised global vars (.bss)
. Heap
. stack (of the OS itself)..
So it has to fit…

