Program hangs with libopencm3 on STM32F103C8T6 (Blue-Pill)

Hello, I’m trying to learn / use FreeRTOS with libopencm3 on a STM32 thanks to Warren Gay’s book the code examples used in his book are available here I have already asked this question on StackOverflow and on ve3wwg/stm32f103c8t6 but I did not get an answer that solved my problem.

Hardware

  • MCU: STM32F103C8T6 (also known as Blue Pill)
  • FT232RL breakout board
  • ST-Link V2

Software

  • Kubuntu 18.04
  • arm-none-eabi-gcc (15:6.3.1+svn253039-1build1) 6.3.1 20170620
  • gdb-multiarch – GNU gdb (Ubuntu 8.2-0ubuntu1~18.04) 8.2)
  • FreeRTOS 10.2.0
  • libopencm3 latest commit 0fd4f74ee301af5de4e9b036f391bf17c5a52f02
The following program creates two tasks and a queue. The queue is filled by the task “SEND” and the task “RECEIVE” receives from the same queue, the Blue Pill LED (GPIOC, GPIO13) is turned on by the “SEND” task every 1100 ms and the “RECEIVE” tasks turns it off when it receives a message (100 ms after it has been turned on). ~~~

include <FreeRTOS.h>

include <libopencm3/stm32/gpio.h>

include <libopencm3/stm32/rcc.h>

include <queue.h>

include <task.h>

static QueueHandle_t queue; static void taskreceive(void *args attribute((unused))) { bool nothing; while (1) { if (xQueueReceive(queue, &nothing, 10) == pdPASS) gpioset(GPIOC, GPIO13); // Turn off } } static void tasksend(void *args attribute((unused))) { bool nothing = false; while (1) { gpioclear(GPIOC, GPIO13); // Turn on vTaskDelay(pdMSTOTICKS(100)); xQueueSendToBack(queue, &nothing, portMAXDELAY); vTaskDelay(pdMSTO_TICKS(1000)); } } int main(void) { rccclocksetupinhse8mhzout_72mhz(); // Blue-Pill led rccperiphclockenable(RCCGPIOC); gpiosetmode( GPIOC, GPIOMODEOUTPUT2MHZ, GPIOCNFOUTPUTPUSHPULL, GPIO13); gpioset(GPIOC, GPIO13); // Turn off (polarity of the led is inversed!) queue = xQueueCreate(32, sizeof(bool)); if (queue == 0) { while (1) { gpiotoggle(GPIOC, GPIO13); for (uint32t i = 0; i < 80000; ++i) asm(“nop”); }; } xTaskCreate(taskreceive, “RECEIVE”, 200, NULL, configMAXPRIORITIES-1, NULL); xTaskCreate(tasksend, “SEND”, 200, NULL, configMAXPRIORITIES-2, NULL); vTaskStartScheduler(); while(1); return 0; } ~~~ This program does not work when I flash it on a Blue Pill, the led stays on and never turns off, I think the execution is blocking at the xQueueSendToBack call (it never exits). I am using the configuration files from the rtos/uart2 example of the book. I have tried debugging this with the ST-Link V2, here is the output of my debug session: (note: the program is named uart.elf because I’m using the rtos/uart2 example files, I replaced the code with the one above) ~~~ gdb-multiarch layout split file uart.elf target extended-remote :4242 load uart.elf b main ~~~ At that point the everything looks fine from my point of view: gdb session Then I set a breakpoint to the xQueueSendToBack call and continue: ~~~ (gdb) b uart.c:30 Breakpoint 2 at 0x8000156: file uart.c, line 30. (gdb) c Continuing. ~~~ If I let the code continue and halt it afterwards I get this: ~~~ (gdb) c Continuing. Program received signal SIGTRAP, Trace/breakpoint trap. 0x08000e9c in prvIdleTask (pvParameters=) at rtos/tasks.c:3166 (gdb) bt

0 0x08000e9c in prvIdleTask (pvParameters=) at rtos/tasks.c:3166

1 0x08000462 in uxListRemove (pxItemToRemove=) at rtos/list.c:238

Backtrace stopped: previous frame identical to this frame (corrupt stack?) ~~~ There seems to be something wrong here, however I don’t know how to interpret this corrupt stack error. Why is this example not working on my Blue-Pill? There must be something wrong in my setup but I can’t find what. If there is any information missing please ask as I’m willing to provide as much as you need to help me fix this problem. I’m a little desperate here 🙂 Bye

Program hangs with libopencm3 on STM32F103C8T6 (Blue-Pill)

It is hard to see the context using the command line debugger, but it is quite normal to be in the idle task when you stop the debugger, especially in your application with only two asks that are blocked most of the time. The fact that you are in the idle task would seem to indicate that the scheduler has started. The fact that GDB doesn’t know how to decode the stack can just be because there is no real end to the stack as far as GDB knows because the task stacks from from the heap (unless you are using xTaskCreateStatic() to create the tasks). Using configuration options it is possible to try an alleviate the debuggers interpretation of the stack by ending it with a NULL value. First thing then, are you sure the LED is working as you expect? If you were to ignore FreeRTOS for a moment and just try turning the LED on and off from main() before the scheduler is started, does it turn on and off as expected? Next thing to do would be to check the tick interrupt is executing. When you are stopped on the debugger try viewing the xTickCount variable. If it is not incrementing then time is standing still as far as the scheduler is concerned so the blocked tasks will never time out.

Program hangs with libopencm3 on STM32F103C8T6 (Blue-Pill)

I forgot to mention that FreeRTOS tasks without queues work fine and so does libopencm3 at toggling the LED: ~~~

include <FreeRTOS.h>

include <libopencm3/stm32/gpio.h>

include <libopencm3/stm32/rcc.h>

include <task.h>

static void taskoff(void *args attribute((unused))) { while (1) { vTaskDelay(pdMSTOTICKS(300)); gpioset(GPIOC, GPIO13); // Turn off } } static void taskon(void *args attribute((unused))) { while (1) { vTaskDelay(pdMSTOTICKS(1000)); gpioclear(GPIOC, GPIO13); // Turn on } } int main(void) { rccclocksetupinhse8mhzout_72mhz(); // Blue-Pill led rccperiphclockenable(RCCGPIOC); gpiosetmode( GPIOC, GPIOMODEOUTPUT2MHZ, GPIOCNFOUTPUTPUSHPULL, GPIO13); gpioset(GPIOC, GPIO13); // Turn off (polarity of the led is inversed!) xTaskCreate(taskon, “ON”, 200, NULL, configMAXPRIORITIES-1, NULL); xTaskCreate(taskoff, “OFF”, 200, NULL, configMAXPRIORITIES-1, NULL); vTaskStartScheduler(); while(1); return 0; } ~~~ This code works fine and the LED blinks (with a hard to predict scheme, but that’s not the point). Things stop working when I push a value into a queue.
For the first program (the one with the queue), just before the call to xQueueSendToBack the tick count (xTickCount) is 0, after that it is equal to 100 and never changes after that, I have continued/halted the program several times. This time it looks like the program was stuck in the blocking_handler(void) function of vector.c in libopencm3: https://github.com/libopencm3/libopencm3/blob/master/lib/cm3/vector.c#L102

Program hangs with libopencm3 on STM32F103C8T6 (Blue-Pill)

I have investigated further. The problem I experience lays in the prvCopyDataToQueue function of the queue.c file, I’m now pretty sure that the memcpy call at line 2098 (of queue.c) seems to be the root cause of my problem. This is a portion of the surrounding code (line 2096 of queue.c): ~~~ else if( xPosition == queueSENDTOBACK ) { ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ pxQueue->pcWriteTo += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ { pxQueue->pcWriteTo = pxQueue->pcHead; } ~~~ I’m using rtos/uart2 example . At the beginning of the prvCopyDataToQueue function everything looks fine: ~~~ Breakpoint 2, prvCopyDataToQueue (pxQueue=pxQueue@entry=0x20000020 <ucHeap+8>, pvItemToQueue=pvItemToQueue@entry=0x8001698, xPosition=xPosition@entry=0) at rtos/queue.c:1698 1: pxQueue->pcWriteTo = (int8t *) 0x20000068 <ucHeap+80> “” 2: pxQueue->pcTail = (int8t *) 0x20000168 <ucHeap+336> “” 3: pxQueue->uxItemSize = 1 ~~~ The queue is empty and the queue size in this example is 256, we have ucHeap+336ucHeap+80 = 256, all good! Next breakpoint is at the memcpy call, after the memcpy call this is what I get: ~~~ 1: pxQueue->pcWriteTo = (int8t *) 0x8001603 “G” 2: pxQueue->pcTail = (int8t *) 0x8001605 “”826530I31L31HS30203B”, 3: pxQueue->uxItemSize = 134223361 ~~~ The item size becomes gigantic and the memcpy did nasty things to the queue, the adresses are completely wrong. Any idea why?

Program hangs with libopencm3 on STM32F103C8T6 (Blue-Pill)

I solved the issue by updating the compiler to the latest version found on https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads: Version 8-2018-q4-major Linux 64-bit After this update and recompiling the example code everything executes as expected! So I recommend not to use the arm-none-eabi compiler shipped with Kubuntu 18.04: arm-none-eabi-gcc (15:6.3.1+svn253039-1build1) 6.3.1 20170620. It seems to contain a bug in memcpy for cortex M3 targets. Thanks for you support.

Program hangs with libopencm3 on STM32F103C8T6 (Blue-Pill)

Thanks for taking the time to report back.