Quality RTOS & Embedded Software

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




Loading

BusFault after multiple pvPortMalloc calls

Posted by Andreas D on September 4, 2013
Hello,

I'm currently developing an application on an Cortex-M3 (STM32F103ZG) using FreeRTOS 7.5.0 (non-MPU). The memory allocation implementation used was heap2, switched to heap4 now, but the following error still occurs.

The IDE used is Keil ┬ÁVision with MDK-ARM toolchain 4.21 (C compiler 4.1.0.713)
The application consists of about 20 tasks.

Under certain circumstances, a task does some extensive data operations. This includes allocating (quite big) memory blocks (one is 8K), reading in a file from SD card and freeing the block again after processing. According to xPortGetFreeHeapSize, after freeing, the memory is available again (but what about fragmentation?). This task *always* does the memory allocating and freeing. But the file reading is only done under the circumstances.
After these operations, uxTaskGetStackHighWaterMark reports 100 byte (words?) minimal stack remaining for this task.

After the task has finished the operations, a context switch to another task occurs, which also tries to allocate some memory for a buffer. This is when the BusFault occurs. The bus fault does not occur there when the previous task doesn't do these extensive operations.

In the BusFault_Handler, Keil reports the following (Fault reports window):

BUS_FAULT_ADDR: 0x00312800 (What does that tell me anyway?)
BUS_FAULT_STAT: 0x82
Flags set: PRECISERR, BFARVALID

LR in exception handler: 0xfffffffd (bit 2 = 1, Process stack? According to ARM appnote 209)
PSP: 0x20009318

Memory window:

(R0) 0x20009318: 0x00312800
(R1) 0x2000931C: 0x20009A78
(R2) 0x20009320: 0x00000000
(R3) 0x20009324: 0x00312800
(R12) 0x20009328: 0x00000000
(LR) 0x2000932C: 0x0802F619 (unaligned address? now that's interesting)
(PC) 0x20009330: 0x0802F25A
(PSR) 0x20009334: 0x81000000


The PC address is inside heap_4.c:

343: for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
344: {
345: /* Nothing to do here, just iterate to the right position. */
346: }
347:
348: /* Do the block being inserted, and the block it is being inserted after
349: make a contiguous block of memory? */
0x0802F254 4816 LDR r0,[pc,#88] ; @0x0802F2B0
0x0802F256 E000 B 0x0802F25A
0x0802F258 6800 LDR r0,[r0,#0x00]
0x0802F25A 6803 LDR r3,[r0,#0x00]
0x0802F25C 428B CMP r3,r1
0x0802F25E D3FB BCC 0x0802F258
350: puc = ( unsigned char * ) pxIterator;


LR address is also inside heap_4.c:

223: xFreeBytesRemaining -= pxBlock->xBlockSize;
224:
225: /* The block is being returned - it is allocated and owned
226: by the application and has no "next" block. */
0x0802F618 490C LDR r1,[pc,#48] ; @0x0802F64C
0x0802F61A 6860 LDR r0,[r4,#0x04]
0x0802F61C 6809 LDR r1,[r1,#0x00]
0x0802F61E EBA10000 SUB r0,r1,r0
0x0802F622 490A LDR r1,[pc,#40] ; @0x0802F64C
0x0802F624 6008 STR r0,[r1,#0x00]
227: pxBlock->xBlockSize |= xBlockAllocatedBit;


Can somebody give me advice what to do about this? The unaligned address in the saved LR makes me very suspicious, but where does it come from?

Thanks in advance!
Andreas

FreeRTOSConfig.h:

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#define configUSE_TICKLESS_IDLE 0
#define configCPU_CLOCK_HZ 72000000UL
#define configTICK_RATE_HZ 100
#define configMAX_PRIORITIES 5
#define configMINIMAL_STACK_SIZE 128
#define configTOTAL_HEAP_SIZE ( 45 * 1024 )
#define configMAX_TASK_NAME_LEN 6
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 0
#define configUSE_RECURSIVE_MUTEXES 0
#define configUSE_COUNTING_SEMAPHORES 0
// don't use this feature
#define configQUEUE_REGISTRY_SIZE 0
#define configUSE_QUEUE_SETS 0

/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 2
// If used, must be void vApplicationMallocFailedHook( void );
#define configUSE_MALLOC_FAILED_HOOK 0

#ifdef MYDEBUG
#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
#define configUSE_TRACE_FACILITY 1
//#include "trcKernelPort.h"
extern unsigned long uiOverflowCounter;
void App_Trace_vActivateTimer(void);
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() {App_Trace_vActivateTimer();}
#define portGET_RUN_TIME_COUNTER_VALUE() uiOverflowCounter
#endif

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2

/* Software timer related definitions. */
// do not use freertos software timers
#define configUSE_TIMERS 0

/* Interrupt nesting behaviour configuration. */
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY 255
// Syscall priority - all INTs with higher prio (==lower number) can NOT use FreeRTOS API!
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (8<<4) //only 4 bits //NEVER! 0 /* No IRQs will interrupt the criticals anymore*/
/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15. This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting. Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15
// Same name
#define configMAX_API_CALL_INTERRUPT_PRIORITY 15

/* Define to trap errors during development. */
//#define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet 0
#define INCLUDE_uxTaskPriorityGet 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xResumeFromISR 0
#define INCLUDE_vTaskDelayUntil 0
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xTaskGetCurrentTaskHandle 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
#define INCLUDE_pcTaskGetTaskName 0
#define INCLUDE_eTaskGetState 0

#define INCLUDE_uxTaskGetStackHighWaterMark 1
#ifdef STACK_CHECK
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#endif

#endif /* FREERTOS_CONFIG_H */

RE: BusFault after multiple pvPortMalloc calls

Posted by Richard on September 4, 2013
Why do you have configASSERT() commented out - it is there to help you catch problems in your code.

Are you using the STM32 peripheral library from ST? If so, then before spending time looking into this, I recommend upgrading to FreeRTOS V7.5.2, uncommenting configASSERT() and then running the same application. V7.5.2 contains code specifically for users of the ST peripheral libraries, which have some special Cortex-M3 configuration requirements (unlike any other dirvers we have encountered, they require you to change the Cortex-M3 configuration from its power up default). See http://www.freertos.org/History.txt

Try that then get back to us to let us know if it caught a (Cortex-M3) configuration issue. If not, we can try to diagnose your problem.

Regards.

RE: BusFault after multiple pvPortMalloc calls

Posted by Andreas D on September 4, 2013
Hello Richard,

thanks for your reply.
I upgraded to FreeRTOS 7.5.2 and uncommented configASSERT, creating a function so I can inspect the file and line number.

Upgrading fixed the assert in PortValidateInterruptPriority (line 650) I got in v7.5.0. And yes, I'm using the STM32PeriphLib (and thus calling NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); before scheduler starts)

Now I don't get configASSERTs anymore.

Indeed, the problem occurs when actually reading the file into the buffer. If I don't write anything into the buffer, everything works fine.
The buffer I'm allocating memory for is a struct (well, an array of them) consisting of multiple char-arrays, each struct is 36 byte in size. I'm using configASSERT now to check if I write out of the buffer and/or the character arrays, but that doesn't happen.

...
Actually, the sizes of the character array were kind of "uneven" (10, 5, 3, 4, 6, 3, 5 Bytes). I just changed it to (10, 6, 4, 4, 6, 4, 6), resulting in a total of 40 bytes per struct. And now it works fine, the error is gone.
Looks like it was an alignment problem?

Regards,

Andreas


[ 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