Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 9, 2016

Processor: STM32F373VC IDE: Ac6 System Workbench The job was created by STM32CubeMX with the FREERTOS option enabled.

Am I correct in my understanding that pvPortMalloc() will allocate from the FREERTOS Heap, the size of which is specified by configTOTALHEAPSIZE? And that malloc(), which is not thread safe, will allocate outside the FREERTOS Heap in the C/C++ Heap?

If I set configTOTALHEAPSIZE to the processor's total amount of RAM, which is 32000, and if I subtract from this amount the the Linker's overflow error message to use for the next value of configTOTALHEAPSIZE I will have compiled using the maximum value configTOTALHEAPSIZE can be. But will the result be reliable? Will it ever be the case that while the firmware is running there will be a need for a larger C/C++ heap?

What is the C/C++ Heap used for? Is any of it dynamically allocated beyond the Linker's awareness?

The default value of configTOTALHEAPSIZE was 10000. I find that if I go over this I get a HardFault() call when osKernelStart() is called.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by edwards3 on March 10, 2016

Am I correct in my understanding that pvPortMalloc() will allocate from the FREERTOS Heap, the size of which is specified by configTOTALHEAPSIZE? And that malloc(), which is not thread safe, will allocate outside the FREERTOS Heap in the C/C++ Heap?

Yes.http://www.freertos.org/a00111.html

If I set configTOTALHEAPSIZE to the processor's total amount of RAM, which is 32000, and if I subtract from this amount the the Linker's overflow error message to use for the next value of configTOTALHEAPSIZE I will have compiled using the maximum value configTOTALHEAPSIZE can be. But will the result be reliable? Will it ever be the case that while the firmware is running there will be a need for a larger C/C++ heap?

? only the firmware writer knows that. In any bare metal or RTOS system if the amount of RAM you try allocating with malloc is more than the RAM available the allocation will fail or corrupt something.

What is osKernelStart?


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 10, 2016

In the frimware I wrote all RAM allocations I do are done with pvPortMalloc(), which is necessary for thread safety when using FREERTOS. These allocations come from the FREETOS heap which is sized by configTOTALHEAPSIZE.

There is a lot of other software in the drivers that STM32CubeMX included in the project. A search for malloc and realloc in them did not get any hits.

osKernelStart() appears in the STM32CubeMX created file main.c where it is inside main(). It is this call that starts up and runs FREERTOS. After this call the firmware runs in threads (tasks in FREERTOS parlance). If osKernelStart() works right it never returns. It runs until processor reset, or power down.

When I set configTOTALHEAPSIZE to 32000 I get this compile time error:

region 'RAM' overflowed by 7416 bytes TEC Driver SW4STM32 Configuration

The amount of RAM in hardware minus the overflow minus the configTOTALHEAPSIZE value is 32000 - 7416 - 10000 = 24584. That is 24584 bytes of RAM I cannot account for, and need to use if it isn't in use elsewhere. If I try to use it by increasing the size of configTOTALHEAPSIZE by any significant amount over 10000 I get a call to HardFault().


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by rtel on March 10, 2016

There is a lot of other software in the drivers that STM32CubeMX included in the project. A search for malloc and realloc in them did not get any hits.

A simple way to see if malloc() is being called anywhere is to define your own implementation, then set a break point in the implementation, or otherwise do something like put an infinite loop in the implementation to see if it ever gets called.

If it does get called then you can re-direct it to pvPortMalloc(), or simply call pvPortMalloc() from your own implementation:

void* malloc( size_t size )
{
     /* If this function gets called it will get stuck here. */
     for(;;);
}

If malloc() is never called then there is no point allocating any RAM to the heap that is set up by your linker.

When I set configTOTALHEAPSIZE to 32000 I get this compile time error:

region 'RAM' overflowed by 7416 bytes TEC Driver SW4STM32 Configuration

Which would be expected if you set the FreeRTOS heap fill all the available RAM - it is just a statically allocated array and you must allow some RAM for use by other variables in the system, the stack used by main(), etc.

So when the amount of RAM in hardware minus the overflow minus the configTOTALHEAPSIZE value is 32000 - 7416 - 10000 = 24584. That is 24584 bytes of RAM I cannot account for, and need to use if it isn't in use elsewhere. If I try to use it by increasing the size of configTOTALHEAPSIZE by any significant amount over 10000 I get a call to HardFault().

Have you tried stepping through the code to see where the hard fault is generated, or otherwise debugging the hard fault?


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 10, 2016

Yes, I did. The result did not make sense to me.

The call to osKernelStart () leads to the Supervisor Call Handler listed below:

                          SVC_Handler:

08005f4c: SVCHandler+0 ldr r3, [pc, #24] ; (0x8005f68 <SVCHandler+28>) 08005f4e: SVCHandler+2 ldr r1, [r3, #0] 08005f50: SVCHandler+4 ldr r0, [r1, #0] 08005f52: SVCHandler+6 ldmia.w r0!, {r4, r5, r6, r7, r8, r9, r10, r11, lr} 08005f56: SVCHandler+10 msr PSP, r0 08005f5a: SVCHandler+14 isb sy 08005f5e: SVCHandler+18 mov.w r0, #0 08005f62: SVCHandler+22 msr BASEPRI, r0 08005f66: SVCHandler+26 bx lr 08005f68: SVCHandler+28 adds r2, #64 ; 0x40 08005f6a: SVCHandler+30 movs r0, #0 399 configASSERT( uxCriticalNesting == 1000UL );

After the instruction at SVC_Handler+4 is executed the value stored in r0 is 0x20002744.

When the instruction at SVCHandler+6 is executed, the program counter increments to SVCHandler+10, and then the disassembly tab changes from displaying the SVCHandler code above, to the displaying the SVCHandler code below:

                           SVC_Handler:

08005f4c: SVCHandler+0 movs r4, r4 08005f4e: SVCHandler+2 movs r0, r0 08005f50: SVCHandler+4 movs r4, r4 08005f52: SVCHandler+6 movs r0, r0 08005f54: SVCHandler+8 movs r4, r4 08005f56: SVCHandler+10 movs r0, r0 08005f58: SVCHandler+12 movs r4, r4 08005f5a: SVCHandler+14 movs r0, r0 08005f5c: SVCHandler+16 movs r4, r4 08005f5e: SVCHandler+18 movs r0, r0 08005f60: SVCHandler+20 movs r4, r4 08005f62: SVCHandler+22 movs r0, r0 08005f64: SVCHandler+24 movs r4, r4 08005f66: SVCHandler+26 movs r0, r0 08005f68: SVCHandler+28 movs r4, r4 08005f6a: SVCHandler+30 movs r0, r0

The value of r0 changes to 0x20002768. The call to HardFault happens right after this.

If the disassembly window is to be believed it appears that something is happening to change the instructions in flash. What else could it be?


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by rtel on March 11, 2016

Something goes wrong when the instructions you are viewing change. The addresses are the same, but the instructions decoded are different. That could be because the debugger has let go and is no longer able to query the target correctly, or because the memory map is remapped (because a system register was written to), or no doubt other reasons too.

I suspect that, if you are setting the FreeRTOS heap to the absolutely maximum that the linker will allow, then the heap is overlapping the stacks (which the linker may not know about), resulting in the stack becoming corrupted.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 11, 2016

In the above debug session description where the assembly code changed configTOTALHEAPSIZE was set to 10500. The maximum setting the linker will allow is 24584.

This problem does not happen when configTOTALHEAPSIZE is set to 10000.

The value of r0 during the execution of the instruction at SVC_Handler+6 changes from 0x20002744 to 0x20002768. This is a RAM address range. It is the location range in RAM that contains the data loaded into the registers r4, r5, r6, r7, r8, r9, r10, r11, lr. No memory mapped system registers are being written to. I do not understand how that could change a memory map.

After stepping up to and including the instruction at SVC_Handler+6 this message appears in the Console tab: Info : halted: PC: 0x08005f4e Info : halted: PC: 0x08005f50 Info : halted: PC: 0x08005f52 Info : halted: PC: 0x08005f56 Warn : WARNING! The target is already running. All changes GDB did to registers will be discarded! Waiting for target to halt.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by edwards3 on March 12, 2016

The warning is telling you the debugger has lost contact with the target, so what you see in the debugger and reported in your post is junk probably random data.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 13, 2016

The instruction at SVC_Handler+6 is a psuedo code. Which means there is more going on there than a single opcode.

I have noticed that when the breakpoint at SVCHandler+0 is hit, and I do not go into Instruction Stepping Mode there as I had in the above code, and do a Step Over (F5), it advances to StartThreadUARTRx+0, where there is a call to HardFault().

The relevant part of the C source code for StartThreadUARTRx is pasted below: ~~~~ void StartThreadUARTRx(void const * argument) { uint8t rxchar BaseTypet xQueueReceiveResult;

for(;;) { xQueueReceiveResult = xQueueReceive( QueueUARTRxHandle, (void *)&rxchar, portMAXDELAY ); ..... } } ~~~~ The statements that creates the thread and the queue elsewhere in the firmware are: ~~~~ osThreadDef( ThreadUARTRx, StartThreadUARTRx, osPriorityNormal, 0, 512); ThreadUARTRxHandle = osThreadCreate(osThread(ThreadUARTRx), NULL);

/* definition and creation of QueueUARTRx */ osMessageQDef(QueueUARTRx, 10, uint8t ); QueueUARTRxHandle = osMessageCreate(osMessageQ(QueueUARTRx), NULL); ~~~~ When stepping through C source code the HardFault() is called in the statement where xQueueReceive() is called. When stepping through the assembly code pasted below the call to HardFault() is called when the instruction at StartThreadUARTRx+14 is executed. ~~~~ StartThreadUARTRx: 08001ea4: StartThreadUARTRx+0 push {r4, lr} 08001ea6: StartThreadUARTRx+2 sub sp, #8 08001ea8: StartThreadUARTRx+4 sub.w r3, sp, #12224 ; 0x2fc0 08001eac: StartThreadUARTRx+8 movs r2, #0 08001eae: ...tThreadUARTRx+10 str.w r2, [r3, #-60] 159 { xQueueReceiveResult = xQueueReceive( QueueUARTRxHandle, (void *)&rxchar, portMAXDELAY ); 08001eb2: ...tThreadUARTRx+14 ldr r4, [pc, #128] ; (0x8001f34 <StartThreadUARTRx+144>) 08001eb4: ...tThreadUARTRx+16 movs r3, #0 08001eb6: ...tThreadUARTRx+18 mov.w r2, #4294967295 08001eba: ...tThreadUARTRx+22 add.w r1, sp, #7 08001ebe: ...tThreadUARTRx+26 ldr r0, [r4, #0] 08001ec0: ...tThreadUARTRx+28 bl 0x80068d4 ~~~~ The value at StartThreadUARTRx+144 is: ~~~~ 08001f34: ...ThreadUARTRx+144 ; instruction: 0x47ec ~~~~ When the call to HardFault() happens this message appears in the console: ~~~~ Info : halted: PC: 0x08001eac Info : halted: PC: 0x08001eae Info : halted: PC: 0x08001eb2 Info : halted: PC: 0x08000280 Error: jtag status contains invalid mode value - communication failure Polling target stm32f3x.cpu failed, GDB will be halted. Polling again in 100ms Info : Previous state query failed, trying to reconnect Polling target stm32f3x.cpu succeeded again, trying to reexamine Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints ~~~~ All this is doing is loading the value 0x47ec into r4 and that causes a call to HardFault(). The ST-Link V2 gets disconnected, but it seems it automaically reconnects. How could the instruction at StartThreadUARTRx+14 create a Hard Fault?


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 13, 2016

I have looked up where the pc registers points when HardFault() is called. This is the first instruction in MXUSBDEVICEInit() which is called in StartDefaultTask(). I commented out the MXUSBDEVICEInit() call and found that HardFault() happened on the next function call after the commented out MXUSBDEVICE_Init(). It is begining to look like HardFault() is called upon the first function call in any thread.

I have set configCHECKFORSTACK_OVERFLOW to a value of 2 and implemented vApplicationStackOverflowHook(). It is not called.

I have also set configUSEMALLOCFAILED_HOOK to a value of 1 snd implemented vApplicationMallocFailedHook(). It also is not called.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by rtel on March 13, 2016

If everything works fine until the array size is increased I would still first suspect that the larger array is overlapping RAM used for something else (like the stack used by an ISR for example), or is pushing other variables up the memory space so they are overlapping with RAM used by something else.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 13, 2016

The FREERTOS heap is declared as a static array in line 102 heap_4.c.

static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];

Wouldn't the linker avoid assigning any variable storage that overlaps with storage allocated to ucHeap[]?

If there was not enough RAM to assign to all the other arrays and variables wouldn't the linker fail?

A workspace wide search for the function malloc did not get any hits other than where the function itself is defined in stdlib.h. All dynamic allocations are being made with pvPortMalloc(). If there was not enough RAM to dynamically allocate storage wouldn't vApplicationMallocFailedHook() be called?

If a stack overflowed wouldn't vApplicationStackOverflowHook() be called?


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 14, 2016

I have discovered I have not had any information about the cause of the Hard Fault becuse in SCB->SHCSR the USGFAULTENA, BUSFAULTENA, and MEMFAULTENA bits were not set. So as one of the top lines of code in main() I put this statement:

SCB->SHCSR |= (1<<16) | (1<<17) | (1<<18);

The result is in SCB->SHCSR the BUSFAULTACT bit (bit 1) is set and in SCB->CFSR the IMPRECISERR bit (bit 10) is set.

I do not now know what to do about this fault.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by rtel on March 14, 2016

Wouldn't the linker avoid assigning any variable storage that overlaps with storage allocated to ucHeap[]?

If there was not enough RAM to assign to all the other arrays and variables wouldn't the linker fail?

Assuming you have the linker script configured correctly for your target; the linker will not itself allocate two variables so that they would overlap, but it is possible there are other memory regions in use that are not directly allocated by the linker. For example, space left in the memory map for use by the stack.

A workspace wide search for the function malloc did not get any hits other than where the function itself is defined in stdlib.h.

I think my first reply suggested a way of verifying this was actually the case, did you try the suggestion?

All dynamic allocations are being made with pvPortMalloc(). If there was not enough RAM to dynamically allocate storage wouldn't vApplicationMallocFailedHook() be called?

Yes, but that won't tell you if the memory is overlapping with something else, such as a stack.

If a stack overflowed wouldn't vApplicationStackOverflowHook() be called?

Only if the stack of a task was corrupted, not if the stack used by interrupts was corrupted - but it doesn't sound like you are getting that far anyway.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 15, 2016

To change the imprecise error to a precise one, at the cost of some processor performance, I added this line of code to one of the first lines of code in main():

SCnSCB->ACTLR |= SCnSCB_ACTLR_DISDEFWBUF_Msk;

I now have identified what is causing this Bus Fault in the assembly code. I still do not know how to fix this in C source code. When source code is stepped the fault happens on the line where xQueueReceive() is called in the below code snippet: ~~~~ void StartThreadUARTRx(void const * argument) { uint8t rxchar; static pMsgt pmsg; pMsgt pEchoMsg; portBASETYPE TxQueueResult; HALStatusTypeDef HALUARTDMAResumeStat; UBaseTypet N; BaseTypet xQueueReceiveResult;

for(;;) { xQueueReceiveResult = xQueueReceive( QueueUARTRxHandle, (void *)&rxchar, portMAXDELAY ); ... } ~~~~ The corresponding compiler produced assembly code is: ~~~~ 150 { uint8t rxchar; StartThreadUARTRx: 0800285c: StartThreadUARTRx+0 push {r4, r7, lr} 0800285e: StartThreadUARTRx+2 sub sp, #36 ; 0x24 08002860: StartThreadUARTRx+4 add r7, sp, #0 08002862: StartThreadUARTRx+6 str r0, [r7, #4] 08002864: StartThreadUARTRx+8 sub.w r3, sp, #12224 ; 0x2fc0 08002868: ...tThreadUARTRx+12 subs r3, #60 ; 0x3c 0800286a: ...tThreadUARTRx+14 movs r2, #0 0800286c: ...tThreadUARTRx+16 str r2, [r3, #0] ; Call to BusFaultHandler() on this line 159 { xQueueReceiveResult = xQueueReceive( QueueUARTRxHandle, (void *)&rxchar, portMAXDELAY ); 0800286e: ...tThreadUARTRx+18 ldr r3, [pc, #172] ; (0x800291c ) 08002870: ...tThreadUARTRx+20 ldr r0, [r3, #0] 08002872: ...tThreadUARTRx+22 add.w r1, r7, #15 08002876: ...tThreadUARTRx+26 movs r3, #0 08002878: ...tThreadUARTRx+28 mov.w r2, #4294967295 0800287c: ...tThreadUART_Rx+32 bl 0x8009860 ~~~~

Pasted below is what I see happening when the assembly code is instruction stepped. The given values of sp and r3 are as the are after the instruction for the described line is executed:

~~~~ Starting value sp = 0x20002b78 4:24 PM 3/14/2016 ...Rx+0 Push r4, r7, and lr onto the process stack. (sp = 0x20002b6c ) ...Rx+2 Subtract from the stack pointer a value of 36 (sp = 0x20002b48) ...Rx+8 Subtract a value of 12224 from the stack pointer and put the result in r3 (r3 = 0x1ffffb88 ) ...Rx+12 Subtract a value of 60 from r3 ( r3 = 0x1ffffb4c ) ...Rx+14 Set r2 to a value of zero. ...Rx+16 Store a value of zero (r2) into the location pointed to by r3. ~~~~

The fault is happening because at ...Rx+16 a value is attempted to be written to address 0x1ffffb4c, which is not a valid RAM address. Everything at and below 0x1ffffffff is reserved for flash memory.

My question now is what in the C source code can cause instructions to be wrtten that cause this BusFault_Handler() call?

The subtraction by 12224 is suspiciously large. What is this doing?


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by rtel on March 15, 2016

This is excellent information - now we can see the route cause of the problem, and it probably also shows why the size of the array is effecting the symptom - if the array is smaller then maybe the memory access would have stayed in the RAM region?

You say you are using Ac6 System Workbench - am I right in thinking that means you are using GCC? Can you post the GCC command line that is being generated by the tool for both the compilation and linking phase (just post the command generated to compile one C file, not every C file, and the final linking phase). It will be interesting to see the optimisation level, and where the linker script is coming from.

Are you 100% sure the linker script is correctly describing the memory layout of the device?

sub.w r3, sp, #12224

This does look like a bizarre line of assembly code to me (by the way, this issue does not look to be related to FreeRTOS directly). Stack pointer relative addressing outside of the current stack frame is not normally seen. Prior to this line of code the asm seems to be setting up the stack frame (I'm guessing that in total the variables declared on the stack consume 36 bytes) and frame pointer.

How big is the pMsg_t type?

pmsg is static, so not on the stack, can you look in the map file to see where it is allocated (what is its address).


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 15, 2016

If the array were smaller maybe it would, but the assembly instructions that cause the Bus Fault are suspicous to me now. I will need to know more about this before I have confidence a smaller ucHeap array would cause memory corruption instead of a Bus Fault. I could live with smaller memory, but it would mean eliminating a thread or two.

The processor is an STM32F373VCT6.

The IDE is Ac6 System Workbench using GCC.

The MCU GCC Compiler command line arguments:

-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -D__weak="__attribute__((weak))" -D__packed="__attribute__((__packed__))" -DUSE_HAL_DRIVER -DSTM32F373xC -I../../../Inc -I"C:\Projects\TEC Driver SW4STM32\TEC\Inc" -I"C:\Projects\TEC Driver SW4STM32\Inc" -I../../../Drivers/STM32F3xx_HAL_Driver/Inc -I../../../Drivers/STM32F3xx_HAL_Driver/Inc/Legacy -I../../../Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F -I../../../Middlewares/ST/STM32_USB_Device_Library/Core/Inc -I../../../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc -I../../../Middlewares/Third_Party/FreeRTOS/Source/include -I../../../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS -I../../../Drivers/CMSIS/Include -I../../../Drivers/CMSIS/Device/ST/STM32F3xx/Include -O0 -g3 -Wall -fmessage-length=0 -fstack-usage -fstack-check -c -fmessage-length=0

The MCU GCC Linker command line arguments:

-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -specs=nosys.specs -specs=nano.specs -T"../STM32F373VCTx_FLASH.ld" -Wl,-Map=output.map -Wl,--gc-sections -lm

pMsg_t is a pointer to a small structure:

~~~~ typedef struct { MsgItrt itr; int32t strln; char *pstr; } Msgt; typedef Msgt* pMsgt; ~~~~

In the Expressoins tab the expression &pmsg evaluates to 0x200007cc


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by rtel on March 15, 2016

First, if you have not done so already, its worth checking the STM32F373VCTx_FLASH.ld file to be sure it is correct - you would imagine it is, but something is wrong somewhere.

Even if the linker script were wrong I would still be at a loss to understand the stack pointer relative addressing going so far outside of the current stack frame.

The command line does not specify an optimisation level - I don't know what the default is but would guess it to be either -O0 or -O1 - try compiling with both of those optimisation levels set explicitly in turn to see how the asm code changes.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 15, 2016

Pasted below is what was copied from the first lines of the STM32F373VCTx_FLASH.ld currently in effect:

~~~~ /* Entry Point */ ENTRY(Reset_Handler)

/* Highest address of the user mode stack / _estack = 0x20008000; / end of RAM / / Generate a link error if heap and stack don't fit into RAM / MinHeap_Size = 0x200; / required amount of heap / MinStack_Size = 0x400; / required amount of stack */

/* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K } ~~~~

The optimizaton level in effect for the instruction stepping result above was -O0. Earlier I also had tried -Og which got the same result regarding the Bus Fault.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by rtel on March 15, 2016

It is likely, given that linker script, that the linker is not taking the space used by the stack into account, but that would not explain the straing asm instructions.

Did you try -O1 to see what asm is generated then?


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 15, 2016

The -O1 optimization produces this assembly code:

~~~~ StartThreadUARTRx: 08002098: StartThreadUARTRx+0 push {r4, r5, r6, lr} 0800209a: StartThreadUARTRx+2 sub sp, #16 0800209c: StartThreadUARTRx+4 sub.w r3, sp, #12224 ; 0x2fc0 080020a0: StartThreadUARTRx+8 movs r2, #0 080020a2: ...tThreadUARTRx+10 str.w r2, [r3, #-60] 159 { xQueueReceiveResult = xQueueReceive( QueueUARTRxHandle, (void *)&rxchar, portMAXDELAY ); 080020a6: ...tThreadUARTRx+14 ldr r5, [pc, #128] ; (0x8002128 <StartThreadUARTRx+144>) 161 HALUARTDMAResumeStat = HALUARTDMAResume( &huart2 ); 080020a8: ...tThreadUARTRx+16 ldr r6, [pc, #128] ; (0x800212c <StartThreadUARTRx+148>) 159 { xQueueReceiveResult = xQueueReceive( QueueUARTRxHandle, (void *)&rxchar, portMAXDELAY ); 080020aa: ...tThreadUARTRx+18 movs r3, #0 080020ac: ...tThreadUARTRx+20 mov.w r2, #4294967295 080020b0: ...tThreadUARTRx+24 add.w r1, sp, #15 080020b4: ...tThreadUARTRx+28 ldr r0, [r5, #0] 080020b6: ...tThreadUART_Rx+30 bl 0x8006984 ~~~~

The Bus Fault happens just as before at ...Rx+10.

Is it possible this is a GCC bug?


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 15, 2016

I commented out code in void StartThreadUARTRx() so that this was all that was left in effect: ~~~~ void StartThreadUARTRx(void const * argument) { for(;;){} } ~~~~ The instructions that caused the Bus Fault were not produced, and the thread ran normally.

I then brought back only the call to xQueueReceive() such that the code in effect was: ~~~~ void StartThreadUARTRx(void const * argument) { uint8t rxchar; BaseTypet xQueueReceiveResult; for(;;) { xQueueReceiveResult = xQueueReceive( QueueUARTRxHandle, (void *)&rxchar, 10000 ), portMAX_DELAY ); } } ~~~~ The assembly code that caused the Bus Fault returned.

Next I tried: ~~~~ void StartThreadUARTRx(void const * argument) { sizet len for(;;) { len = strlen("test"); } } ~~~~ The assembly code that caused the Bus Fault was not present. This ran normally.

Next I tried: ~~~~ void StartThreadUARTRx(void const * argument) { HALStatusTypeDef HALUARTDMAResumeStat; for(;;) { HALUARTDMAResumeStat = HALUARTDMAResume( &huart2 ); } } ~~~~ The Bus Fault causing assembly code returned.

There are certain function calls the cause the Bus Fault assembly code to be created.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by rtel on March 16, 2016

0800209c: StartThreadUART_Rx+4 sub.w r3, sp, #12224 ;

So this line is still weird. Then there are these lines:

080020a0: StartThreadUARTRx+8 movs r2, #0 080020a2: ...tThreadUARTRx+10 str.w r2, [r3, #-60]

So it looks like it is loading a base address from into r3, maybe the base of a structure or array, but using an address which is off memory. Then it is indexing into an offset from that base address.

I commented out code in void StartThreadUART_Rx() so that this was all that was left in effect:

void StartThreadUART_Rx(void const * argument) { for(;;){} }

The instructions that caused the Bus Fault were not produced, and the thread ran normally.

I then brought back only the call to xQueueReceive() such that the code in effect was:

void StartThreadUARTRx(void const * argument) { uint8t rxchar; BaseTypet xQueueReceiveResult; for(;;) { xQueueReceiveResult = xQueueReceive( QueueUARTRxHandle, (void *)&rxchar, 10000 ), portMAX_DELAY ); } }

The assembly code that caused the Bus Fault returned.

Even if QueueUART_RxHandle was not a valid handle it would not explain the asm code.

I think you have one too many ')' brackets in your line to xQueueReceive, but assume that is a typeo in adding the code to the forum post.

Next I tried:

void StartThreadUARTRx(void const * argument) { sizet len for(;;) { len = strlen("test"); } }

The assembly code that caused the Bus Fault was not present. This ran normally.

Ok.

Next I tried:

void StartThreadUARTRx(void const * argument) { HALStatusTypeDef HALUARTDMAResumeStat; for(;;) { HALUARTDMAResumeStat = HALUARTDMAResume( &huart2 ); } }

The Bus Fault causing assembly code returned.

There are certain function calls the cause the Bus Fault assembly code to be created.

So this shows it is not related to the xQueueReceive() function, or how it is used. Very very strange!


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 16, 2016

This appears to me to be a compiler bug. As a work around I am going to try to do the function calls in assembly code. I am studying this document: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf to learn how to do this. If you can recommend any other I would appreciate your doing so.

The above xQueueReceive() call arguments were in error. It was a remnant of an experiment to find out if less than the maximum delay would make a difference here. It should have been: xQueueReceive( QueueUART_RxHandle, (void *)&rxchar, portMAX_DELAY );


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 17, 2016

An examination of the disassembly code showed that strlen() is not actually called. It was instead placed inline. And the compiler was smart enough to count the number of characters in the string, so not even counting characters is done in the instructions it produced. Instead it simply set len to 4.

So I tried the function malloc() in its place, and the instructions that produce the Bus Fault appeared. It appears that any function call in the body of StartThreadUART_Rx() causes those Bus Fault instructions to be created, not just FREERTOS ones.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by spflanze on March 17, 2016

This problem is solved. It became apparant this is a compiler issue and not a FREERTOS issue. So I created this thread at GCC where I got the answer: http://gcc.1065356.n5.nabble.com/Bus-Fault-td1246632.html#a1246958

The problem was the -fstack-check compiler option. When this was removed the code that caused the Bus Fault was no longer created.

I thank you for your help :)


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by rtel on March 18, 2016

I thank you for your help :)

...and thanks for taking the time to report back.


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by fedeandrades on May 30, 2016

where the option to disable the "-fstack-check" in the STM32 workbenck of AC6, I have the same problem and if this solves it would be wonderful to know how.

regreted, written in English by web translator

thanks.

edit: MCF GCC Compiler All options: -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Dweak="attribute((weak))" -Dpacked="attribute((packed))" -DUSEHALDRIVER -DSTM32F429xx -I../Inc -I"L:DESIGNCPUARMWORKSPACE.SOFTRTOS2016V1Srcminini12b" -I../Drivers/STM32F4xxHALDriver/Inc -I../Drivers/STM32F4xxHALDriver/Inc/Legacy -I../Middlewares/ThirdParty/FreeRTOS/Source/portable/GCC/ARMCM4F -I../Middlewares/ST/STM32USBDeviceLibrary/Core/Inc -I../Middlewares/ST/STM32USBDeviceLibrary/Class/MSC/Inc -I../Middlewares/ThirdParty/FatFs/src -I../Middlewares/ThirdParty/FreeRTOS/Source/include -I../Middlewares/ThirdParty/FreeRTOS/Source/CMSISRTOS -I../Drivers/CMSIS/Include -I../Drivers/CMSIS/Device/ST/STM32F4xx/Include -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -fmessage-length=0

i not have -fstack-check !!!! but the problem still occurs


Finding configTOTAL_HEAP_SIZE Maximum Value

Posted by heinbali01 on May 31, 2016

Frederico,

Lo siento, aunque el Español es mucho mas bonito que el Ingles :-), tu tendrás que aprender mucho Ingles si tu quieres volverte en un buen programador de embedded software. No es suficiente utilizar el Google Translate.

Porque piensas que tu tienes el mismo problema que la persona "Artist"? Qué estas observando? Que hace tu programa?

I'm sorry, although Spanish is much more beautiful than English :-), you will have to master English if you want to become a good embedded software programmer. It is not enough to use Google Translate.

Why do you think that you have a similar problem as the poster "Artist", here above? What do you observe? What does the program do?


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS