[SOLVED] FreeRTOS BluePill strange behaviour

Working libraries, libraries being ported and related hardware
Post Reply
User avatar
jfitter
Posts: 10
Joined: Tue Feb 13, 2018 2:41 pm
Location: Sunshine Coast, Australia

[SOLVED] FreeRTOS BluePill strange behaviour

Post by jfitter » Sun Aug 19, 2018 5:00 am

Using Visual Studio and Visual Micro plugin. Selected device is Maple Serial (Generic STM32F103C series) with Roger's bootloader. Using FreeRTOS v9 as bundled with Roger's core.

I create a mutex to manage access to the Bluetooth serial port. If I create it in setup() the program works. If I create it in SetupComms() the program doesn't just fail, but crashes catastrophically. The device is no longer recognizable by Windows. Even plugging it in to another computer it is not recognized.

If I then put the mutex creation back into setup(), recompile, and upload with a manual reset of the board, everything works again. the board is recognized, a comm port assigned, and the program runs. Bizzare....

Does anyone have any clues about this behaviour???
Here is the code;

Code: Select all

void setup() {
    SetupComms();                                   // Initialize communications.
    InitFilteredData();                             // Initialize the filtered accelerometer data.
    SetupIO();                                      // Initialize chip i/o.
//    InitAccels();                                   // Start and calibrate accelerometers.
//    SetLiveMode(PMODE_SIM);                         // Start in test mode.
//    SetupRotorSpooler();                            // Initialize rotor spooler timer.
    SetupHeartBeatLed();                            // Initialize the heartbeat led blink timer.
//    SetupIndex();                                   // Initialize index led flash timer & sensor.
//    SetupCommandHandler();                          // Initialize the command handler task.
    SetupMainTask();                                // Initialize the main processing task.
    if((xBTSerialSemaphore = xSemaphoreCreateMutex()) != NULL)
        xSemaphoreGive(xBTSerialSemaphore);
    vTaskStartScheduler();                          // Set everything in motion.
    INFO("Insufficient RAM");                       // If execution gets to here program has failed.
    while(true);
}
void SetupComms() {
    // Start serial bt comms, set the baud rate, and create a mutex for task access to the port.
    BTSerial.begin(BTSERIALBAUD);
    while(!BTSerial);
//    if((xBTSerialSemaphore = xSemaphoreCreateMutex()) != NULL)
//        xSemaphoreGive(xBTSerialSemaphore);
//    cmdMsg.attach(CmdReady);                        // Attach command handler callback.
    SETUPDBGSERIAL();
    INFO("Bluetooth comms connected at %lu baud", BTSERIALBAUD);
    INFO("Bluetooth mutex created");
//    INFO("Command handler attached");
}
Some time later...

I just tried putting the mutex creation at the end of the SetupComms() function and the program worked.
It is looking like this problem is related to serial port management of the BluePill when FreeRTOS is being used. My previous post also documents some strange behaviour of the serial ports when using FreeRTOS.
I don't really understand what is going on here. Any clues???
Thanks.

Hours and hours later, and lots of reading....

It seems that prior to starting the scheduler, any call to a FreeRTOS API function will cause interrupts to be disabled. This is documented on the FreeRTOS site. Creating tasks and timers fits this definition and this is what we do in setup(). It would appear that the effect of this is to stop the USB UART from sending any characters. worse, the program hangs and the board needs a reset to upload any more code.

Adding taskENTER_CRITICAL macros does not fix the problem.

If I am careful then I can print as much as I like from setup() provided it happens before any API calls, and to be sure I flush the serial buffer. As soon as I call an API function subsequent serial printing fails. I suspect interrupts are needed to send serial data, so the program never gets to start the scheduler.

In addition to this since delay() uses systick, it stops working too, and I can't use vtaskDelay because the scheduler is not started yet. After Serial.begin() I need 2000ms delay before any characters will emerge (why, I don't know) so I am reduced to using a timing loop, which is very bad form.

All this is very awkward. In setup(), prior to starting the scheduler, I would expect to be able to use the normal core functions to setup the hardware as required and maybe produce diagnostic messages. In this implementation this is not possible. This leaves the only option to setup the hardware in the tasks after the scheduler starts, and thus I need to manage the order that the tasks start, which more or less defeats the purpose of the scheduler.

Is this the "design" behaviour or does it need fixing?

Next day....

Fixed delay problem.
delay() is defined in wirish_time.cpp and uses millis(), which uses systick, and so is unusable in setup() after any call to a FreeRTOS API function, such as creating a task or timer.
delayMicroseconds() however wraps delay_us() which is just a do-nothing loop. It does not use interrupts and is completely blocking. It can be used in setup().
Last edited by jfitter on Wed Aug 22, 2018 8:48 am, edited 1 time in total.

User avatar
jfitter
Posts: 10
Joined: Tue Feb 13, 2018 2:41 pm
Location: Sunshine Coast, Australia

Re: FreeRTOS BluePill strange behaviour

Post by jfitter » Wed Aug 22, 2018 8:13 am

OK, solved all of these problems, so just in case anyone else is struggling with this, here is how it is done - well what works for me anyway.

In FreeRTOSConfig.h you need to add this;

Code: Select all

#define configUSE_DAEMON_TASK_STARTUP_HOOK  1
In your application header you need to add this;

Code: Select all

#ifdef __cplusplus
extern "C" {
#endif
void vApplicationDaemonTaskStartupHook(void);
#ifdef __cplusplus
}
#endif
In your application source you need to do it this way (for example);

Code: Select all

void vApplicationDaemonTaskStartupHook(void) {
    SetupComms();                                   // Initialize communications.
    InitFilteredData();                             // Initialize the filtered accelerometer data.
    SetupIO();                                      // Initialize chip i/o.
    InitAccels();                                   // Start and calibrate accelerometers.
    SetupRotorSpooler();                            // Initialize rotor spooler timer.
    SetupHeartBeatLed();                            // Initialize the heartbeat led blink timer.
    SetupIndex();                                   // Initialize index led flash timer & sensor.
    SetLiveMode(PMODE_SIM);                         // Start in simulation mode.
    SetupCommandHandler();                          // Initialize the command handler task.
    SetupCmdLed();                                  // Initialize command led flash timer & led
}
void setup() {
    SetupMainTask();                                // Initialize the main processing task.
    vTaskStartScheduler();                          // Set everything in motion.
    INFO("Insufficient RAM");                       // If execution gets to here program has failed.
    while(true);
}
void loop() {;}
void SetupMainTask() {
    xTaskCreate(vMainTask, "MainTask",
                configMINIMAL_STACK_SIZE,
                NULL,
                tskIDLE_PRIORITY + 1,
                &xMainTask);
}
void vMainTask(void *pvParameters) {
    INFO("Current free heap %u", xPortGetFreeHeapSize());
    INFO("Starting main processing task");
    while(true) {
    ..........
This gives the following output in VS2015/VisualMicro;

Code: Select all

Opening port
Port open
Turbine Balancer Sensor Interface Version 3.0
Written by J. F. Fitter 
Built on Wed Aug 22 00:05:45 2018
INFO: Serial comms connected at 460800 baud 
INFO: Bluetooth comms connected at 460800 baud 
INFO: Create Bluetooth mutex: Succeeded 
INFO: Initialized 2 filter arrays of 180 samples to 0h 
INFO: Finished setting up I/O 
INFO: Calibrated 2 accelerometers with 2000 calibration samples 
INFO: Offset 0 = 7ffh 
INFO: Offset 1 = 7ffh 
INFO: Finished setting up rotor spooler 
INFO: Create rotor spooler timer: Succeeded 
INFO: Finished setting up heartbeat led 
INFO: Create heartbeat blink timer: Succeeded 
INFO: Finished setting up index led 
INFO: Create index flash timer: Succeeded 
INFO: Program mode: SIMULATION 
INFO: Create command handler task: Succeeded 
INFO: Finished setting up command mesaage led 
INFO: Create command message led flash timer: Succeeded 
INFO: Current free heap 2984 
INFO: Starting main processing task ...........................................

Post Reply