I often meet a problem of “_abort_stack_end”.
Do you know what causes this problem and how to overcome it?
I am grateful for any help!
I often meet a problem of “_abort_stack_end”.
Do you know what causes this problem and how to overcome it?
I am grateful for any help!
I’m afraid you are going to have to provide a lot more information before anybody can begin to offer suggestions. For example, which FreeRTOS and compiler port are you using as _abort_stack_end sounds like a linker variable (i.e. not necessarily anything to do with FreeRTOS). Under what circumstances does this happen (when you first turn it on, after a few months, after a particular event, etc.).
@rtel : I apologize for an unclear question.
I am running FreeRTOS on two Cortex A9 cores of Zynq 7000.
When I start software in a debug mode, I see one core doesn’t work as expected. I wonder why _abort_stack_end() happens as the following screenshot.
Thanks. If I understand correctly then, you get a Data Abort exception when running in debug mode.
Have you tried debugging the data abort to find where in the code it is caused?
Does this also happen in Release mode?
Does it work ok when you run the code ‘standalone’ rather than through the debugger (because the startup requirements on the Zynq are different when running in the debugger Vs standalone).
Does this happen immediately, or occasionally?
Have you seen the instructions regarding careful use of standard library functions that might unknowingly use floating point instructions?
@rtel: Thanks for your hints!
Yes, I have.
The program fails to create a task, then jumps to _abort_stack_end and Data Abort Exception.
The following screenshot shows information of pxIndex when a task cannot be created.
This screenshot shows information of pxIndex when a task is successfully created.
It happens similarly in Release Mode.
I don’t get what “standalone” means. Can you clarify it?
Both cores run FreeRTOS. This problem happens immediately on Core 0 when the software creates a task. However, Core 1 doesn’t experience this issue.
Floating point is not used.
Can you elaborate on ‘fails to create a task’? The image shows 0xa5a5a5a5 being dereferenced (which is the value used to fill the stack), which will be the cause of the data abort, but something went wrong before then. Does ‘failed to create a task’ mean it could not allocate the memory for the task? If so, how did it then get into vListInsertEnd() within vTaskCreate() without having first allocated the required memory?
Thanks for your guidance!
—> a task cannot be created.
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
{
...
prvAddNewTaskToReadyList( pxNewTCB );
...
}
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
{
...
prvAddTaskToReadyList( pxNewTCB );
...
}
#define prvAddTaskToReadyList( pxTCB ) \
traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
...
}
Exception: Cannot read target memory. Memory read error at 0xA5A5A5A5. PL AXI slave ports access is not allowed. This address has not been added to the memory map
This is value of pxList that is passed to the function vListInsertEnd()
I wonder why 0xa5a5a5a5 is dereferenced.
As per my last post - something went wrong before then. We need to find out why the task cannot be created. It looks like the task create function runs, errs, doesn’t notice it has erred, then tried to continue anyway with bad values that then lead to the abort - so the question is where did the bad value come from?
Sorry for the delay in replying!
When the program creates its first task.
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
{
/* Ensure interrupts don't access the task lists while the lists are being
updated. */
taskENTER_CRITICAL();
{
uxCurrentNumberOfTasks++;
if( pxCurrentTCB == NULL )
{
/* There are no other tasks, or all the other tasks are in
the suspended state - make this the current task. */
pxCurrentTCB = pxNewTCB;
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
{
/* This is the first task to be created so do the preliminary
initialisation required. We will not recover if this call
fails, but we will report the failure. */
prvInitialiseTaskLists();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* If the scheduler is not already running, make this task the
current task if it is the highest priority task to be created
so far. */
if( xSchedulerRunning == pdFALSE )
{
if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
{
pxCurrentTCB = pxNewTCB;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
uxTaskNumber++;
#if ( configUSE_TRACE_FACILITY == 1 )
{
/* Add a counter into the TCB for tracing only. */
pxNewTCB->uxTCBNumber = uxTaskNumber;
}
#endif /* configUSE_TRACE_FACILITY */
traceTASK_CREATE( pxNewTCB );
prvAddTaskToReadyList( pxNewTCB );
portSETUP_TCB( pxNewTCB );
}
taskEXIT_CRITICAL();
if( xSchedulerRunning != pdFALSE )
{
/* If the created task is of a higher priority than the current task
then it should run now. */
if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
{
taskYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
uxCurrentNumberOfTasks has value of 0xa5a5a5a5.
However, it should be 0 because the first task is being created and its initial value is 0.
PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
Values of pxCurrentTCB
Similarly, pxCurrentTCB should be NULL.
PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
/*
* Place the task represented by pxTCB into the appropriate ready list for
* the task. It is inserted at the end of the list.
*/
#define prvAddTaskToReadyList( pxTCB ) \
traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
pxReadyTasksLists has values
I haven’t found the reason why the bad value appears yet.
Hi XuanTran,
I’m afraid there is not a big value in posting screen shots of FreeRTOS code. Can you show us the code YOU wrote, in particular the sequence up to your first invocation of xTaskCreate()? Can you show us the contents of your interrupt vector table and your linker command file? It almost looks as if your startup stack gets corrupted.
The source code is as follows.
//disable caching on shared memory
Xil_SetTlbAttributes( 0x00000000 ,0x14DE2);
Xil_SetTlbAttributes(OCM_SHMEM_LO_ADDR,0x14DE2);
shared_data_ptr->shm_valid=0;
// SHM core2core constructs.
// XScuGic IntcInstance; // scope: portZynq7000.c:xInterruptController
extern XScuGic xInterruptController;
static int InterruptCounter = 0;
//Setup semaphore on shared memory and initialize it
StaticSemaphore_t * xSemaphoreBuffer = (StaticSemaphore_t *)SHMEM_SEMPHR_ADDR;
xSemaphore = xSemaphoreCreateBinaryStatic(xSemaphoreBuffer);
xSemaphoreGive(xSemaphore);
//Setup function call queue
StaticQueue_t * rpcCallQueue = (StaticQueue_t *)SHMEM_FNCTN_QUEUE_ADDR;
uint8_t * queueStorageArea = (uint8_t *)SHMEM_FNCTN_QUEUE_STORAGE_ADDR;
xFnctnQueue = xQueueGenericCreateStatic(FNCTN_QUEUE_LENGTH,FNCTN_STRUCT_SIZE,queueStorageArea,rpcCallQueue,0);
//Setup function return queue
StaticQueue_t * rpcReturnQueue = (StaticQueue_t *)SHMEM_RETURN_QUEUE_ADDR;
uint8_t * retQueueStorageArea = (uint8_t *)SHMEM_RETURN_QUEUE_STORAGE_ADDR;
xReturnQueue = xQueueGenericCreateStatic(RETURN_QUEUE_LENGTH,RETURN_VALUE_SIZE,retQueueStorageArea,rpcReturnQueue,0);
// init the UARTs before waking up CPU1
u32 * uartAvailable = &shared_data_ptr->uart_available;
(*uartAvailable) = 0;
dmb();
if ( lld_uart_init() == 0 ) {
(*uartAvailable) = 2; // send ownership to core 0
};
sleep(1);
xil_printf("CPU0: writing startaddress for cpu1 and reset.\n\r");
{
/*
* Reset and start CPU1
* - Application for cpu1 exists at APP_CPU1_ADDR per cpu1 linkerscript
*
*/
#include "xil_misc_psreset_api.h"
#include "xil_io.h"
#define A9_CPU_RST_CTRL (XSLCR_BASEADDR + 0x244)
#define A9_RST1_MASK 0x00000002
#define A9_CLKSTOP1_MASK 0x00000020
#define CPU1_CATCH 0x00000024
#define XSLCR_LOCK_ADDR (XSLCR_BASEADDR + 0x4)
#define XSLCR_LOCK_CODE 0x0000767B
u32 RegVal;
/*
* Setup cpu1 catch address with starting address of app_cpu1. The FSBL initialized the vector table at 0x00000000
* using a boot.S that checks for cpu number and jumps to the address stored at the
* end of the vector table in cpu0_catch and cpu1_catch entries.
* Note: Cache has been disabled at the beginning of main(). Otherwise
* a cache flush would have to be issued after this write
*/
Xil_Out32(CPU1_CATCH, APP_CPU1_ADDR);
/* Unlock the slcr register access lock */
Xil_Out32(XSLCR_UNLOCK_ADDR, XSLCR_UNLOCK_CODE);
// the user must stop the associated clock, de-assert the reset, and then restart the clock. During a
// system or POR reset, hardware automatically takes care of this. Therefore, a CPU cannot run the code
// that applies the software reset to itself. This reset needs to be applied by the other CPU or through
// JTAG or PL. Assuming the user wants to reset CPU1, the user must to set the following fields in the
// slcr.A9_CPU_RST_CTRL (address 0xF8000244) register in the order listed:
// 1. A9_RST1 = 1 to assert reset to CPU0
// 2. A9_CLKSTOP1 = 1 to stop clock to CPU0
// 3. A9_RST1 = 0 to release reset to CPU0
// 4. A9_CLKSTOP1 = 0 to restart clock to CPU0
/* Assert and deassert cpu1 reset and clkstop using above sequence*/
RegVal = Xil_In32(A9_CPU_RST_CTRL);
RegVal |= A9_RST1_MASK;
Xil_Out32(A9_CPU_RST_CTRL, RegVal);
RegVal |= A9_CLKSTOP1_MASK;
Xil_Out32(A9_CPU_RST_CTRL, RegVal);
RegVal &= ~A9_RST1_MASK;
Xil_Out32(A9_CPU_RST_CTRL, RegVal);
RegVal &= ~A9_CLKSTOP1_MASK;
Xil_Out32(A9_CPU_RST_CTRL, RegVal);
/* lock the slcr register access */
Xil_Out32(XSLCR_LOCK_ADDR, XSLCR_LOCK_CODE);
}
while(! (shared_data_ptr->uart_available == 1)){
// wait for core 1 to hand back UART handle (simple "alive" detection)
}
u32 reg_val;
//ensure OCM is mapped low
reg_val = Xil_In32(XPS_SYS_CTRL_BASEADDR + 0x910);
if((reg_val & 0x000F) != 0) {
Xil_Out32((XPS_SYS_CTRL_BASEADDR + 0x8),0xDF0D );
Xil_Out32((XPS_SYS_CTRL_BASEADDR + 0x910),(reg_val & 0xFFF0));
Xil_Out32((XPS_SYS_CTRL_BASEADDR + 0x4),0x767B );
}
TaskHandle_t xadcTask;
/* Start the two tasks */
xTaskCreate( ccLld_powerController, ( const char * ) "PWRCTL",
configMINIMAL_STACK_SIZE, NULL,
POWER_CONTROLLER_TASK_PRIORITY, &pctrlTask );
xTaskCreate( ccLld_i2cHandler, ( const char * ) "I2C",
configMINIMAL_STACK_SIZE, NULL,
I2C_HANDLER_TASK_PRIORITY, &i2cHandlerTaskHandle);
xTaskCreate( ccLld_pmbusHandler, ( const char *) "PMBUS",
configMINIMAL_STACK_SIZE, NULL,
PMBUS_HANDLER_TASK_PRIORITY , &pmbusHandlerTaskHandle);
xTaskCreate( ccLld_xadcLoop, ( const char * ) "XADC",
configMINIMAL_STACK_SIZE, NULL,
XADC_TASK_PRIORITY, &xadcTask );
xTaskCreate(ccLld_qziHandler, (const char *) "QZI",
configMINIMAL_STACK_SIZE, NULL,
QZI_HANDLER_TASK_PRIORITY, &qziHandlerTaskHandle);
/* Start the tasks and timer running. */
vTaskStartScheduler();
/* If all is well, the scheduler will now be running, and the following line
will never be reached. If the following line does execute, then there was
insufficient FreeRTOS heap memory available for the idle and/or timer tasks
to be created. See the memory management section on the FreeRTOS web site
for more details. */
for( ;; );
lscript.ld
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x40000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x20000;
_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024;
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;
/* Define Memories in the system */
MEMORY
{
ps7_ddr_0_S_AXI_BASEADDR : ORIGIN = 0x01000000, LENGTH = 0x01000000
ps7_qspi_linear_0_S_AXI_BASEADDR : ORIGIN = 0xFC000000, LENGTH = 0x1000000
ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x0, LENGTH = 0x30000
ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00
}
/* Specify the default entry point to the program */
ENTRY(_vector_table)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.text : {
KEEP (*(.vectors))
*(.boot)
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.plt)
*(.gnu_warning)
*(.gcc_execpt_table)
*(.glue_7)
*(.glue_7t)
*(.vfp11_veneer)
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
} > ps7_ddr_0_S_AXI_BASEADDR
.init : {
KEEP (*(.init))
} > ps7_ddr_0_S_AXI_BASEADDR
.fini : {
KEEP (*(.fini))
} > ps7_ddr_0_S_AXI_BASEADDR
.rodata : {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.rodata1 : {
__rodata1_start = .;
*(.rodata1)
*(.rodata1.*)
__rodata1_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sdata2 : {
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
__sdata2_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sbss2 : {
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.data : {
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.jcr)
*(.got)
*(.got.plt)
__data_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.data1 : {
__data1_start = .;
*(.data1)
*(.data1.*)
__data1_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.got : {
*(.got)
} > ps7_ddr_0_S_AXI_BASEADDR
.ctors : {
__CTOR_LIST__ = .;
___CTORS_LIST___ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
___CTORS_END___ = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.dtors : {
__DTOR_LIST__ = .;
___DTORS_LIST___ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
___DTORS_END___ = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.fixup : {
__fixup_start = .;
*(.fixup)
__fixup_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.eh_frame : {
*(.eh_frame)
} > ps7_ddr_0_S_AXI_BASEADDR
.eh_framehdr : {
__eh_framehdr_start = .;
*(.eh_framehdr)
__eh_framehdr_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.gcc_except_table : {
*(.gcc_except_table)
} > ps7_ddr_0_S_AXI_BASEADDR
.mmu_tbl (ALIGN(16384)) : {
__mmu_tbl_start = .;
*(.mmu_tbl)
__mmu_tbl_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
*(.gnu.linkonce.armexidix.*.*)
__exidx_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.preinit_array : {
__preinit_array_start = .;
KEEP (*(SORT(.preinit_array.*)))
KEEP (*(.preinit_array))
__preinit_array_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.init_array : {
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.fini_array : {
__fini_array_start = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
__fini_array_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.ARM.attributes : {
__ARM.attributes_start = .;
*(.ARM.attributes)
__ARM.attributes_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sdata : {
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sbss (NOLOAD) : {
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
__sbss_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.tdata : {
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.tbss : {
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.bss (NOLOAD) : {
__bss_start = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
__bss_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
/* Generate Stack and Heap definitions */
.heap (NOLOAD) : {
. = ALIGN(16);
_heap = .;
HeapBase = .;
_heap_start = .;
. += _HEAP_SIZE;
_heap_end = .;
HeapLimit = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.stack (NOLOAD) : {
. = ALIGN(16);
_stack_end = .;
. += _STACK_SIZE;
. = ALIGN(16);
_stack = .;
__stack = _stack;
. = ALIGN(16);
_irq_stack_end = .;
. += _IRQ_STACK_SIZE;
. = ALIGN(16);
__irq_stack = .;
_supervisor_stack_end = .;
. += _SUPERVISOR_STACK_SIZE;
. = ALIGN(16);
__supervisor_stack = .;
_abort_stack_end = .;
. += _ABORT_STACK_SIZE;
. = ALIGN(16);
__abort_stack = .;
_fiq_stack_end = .;
. += _FIQ_STACK_SIZE;
. = ALIGN(16);
__fiq_stack = .;
_undef_stack_end = .;
. += _UNDEF_STACK_SIZE;
. = ALIGN(16);
__undef_stack = .;
} > ps7_ddr_0_S_AXI_BASEADDR
_end = .;
}
Did you make sure that your task priorities fall into the valid range defined by your configMAX_PRIORITIES constant?
Also, what are the CONTENTS of your interrupt vector table, in particular, where does your initial SP (offset 0) point to, and is there enough untouched RAM before it to cleanly run all of your xTaskCreate() calls?
You should also make it a habit to monitor the return values of ALL FreeRTOS calls, ie don’t just expect your xTaskCreate() calls to succeed. Also, in what context are the first lines of code (ie from ```
//disable caching on shared memory
called?
Also are you sure about using configMINIMAL_STACK_SIZE
(what’s the value ?) for all your tasks ? That’s often not sufficient b/c it’s just the bare minimum.
I’d recommend to define configASSERT and also enable stack overflow checking for development/debugging in case you didn’t already.
Thanks so much for your swift reply!
#define configMAX_PRIORITIES (8)
/* Priorities at which the tasks are created. */
#define POWER_CONTROLLER_TASK_PRIORITY 6 // This is the highest priority task
#define I2C_HANDLER_TASK_PRIORITY ( PMBUS_HANDLER_TASK_PRIORITY + 1 )
#define PMBUS_HANDLER_TASK_PRIORITY ( XADC_TASK_PRIORITY + 1 )
#define XADC_TASK_PRIORITY ( QZI_HANDLER_TASK_PRIORITY + 1 )
#define QZI_HANDLER_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
Do you know where I can find information of interrupt vector table?
Thanks for your tips! Honestly, I didn’t write this code. I am curious about the issue and eager to learn new things.
int main( void )
{
uint32_t status = XST_FAILURE;
// Initialization of pheripherals
ccLld_LedIoInit();
ccLld_GpioInit();
ccLld_drPllIoInit();
ccLld_CBPosIoInit();
ccLld_XcvuConfIoInit();
ccLld_LldAnlgIoInit();
ccLld_MJtagIoInit();
ccLld_sysCtrlIoInit();
ccLld_uWireIoInit();
ccLld_xadc_init();
ccLld_i2cInit();
logInforInit();
shared_data_ptr->swVersion = SDK_REV_CODE;
ccLld_qziBoardInfor ();
pmbusInit (&pmbusInstance);
status = pmbusConfigureAllDevices (&pmbusInstance, pmbusDeviceTable, NUM_DCDC);
if (XST_FAILURE == status)
{
xil_printf("Configure DCDCs via PMMUS failed.\r\n");
}
//disable caching on shared memory
Xil_SetTlbAttributes( 0x00000000 ,0x14DE2);
Xil_SetTlbAttributes(OCM_SHMEM_LO_ADDR,0x14DE2);
...
...
}
Search for
.vectors
in your code base. Normally it’s in your startup file. Then look for the identifier stored there in offset 0, and find that one in your code base. That is the initial stack pointer loaded into your MCU at reset time. There must be enough RAM UP TO that address to run your startup code (and later on all of your maximum nested interrupts) correctly. Remember that the stack moves from higher to lower addresses (on most including your platforms).
uxCurrentNumberOfTasks has value of 0xa5a5a5a5.
Put a break point on the first line of main() and inspect the value of uxCurrentNumberOfTasks there. It should be 0 - if not your C startup code is not clearing the .bss section as it is supposed to.
Next inspect uxCriticalNesting - it should be 0xff. If it is not then the C startup code is not initialising the .data section correctly.
@hs2
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 8192)
use_freertos_asserts is set.
check_for_stack_overflow is set to 2.
@RAc : Is that .vector section that you mentioned?
.section .vectors
_vector_table:
B _boot
B Undefined
B SVCHandler
B PrefetchAbortHandler
B DataAbortHandler
NOP /* Placeholder for address exception vector*/
B IRQHandler
B FIQHandler
Next inspect uxCriticalNesting - it should be 0xff. If it is not then the C startup code is not initialising the .data section correctly.
The code that you pointed to is for MicroBlazeV9.
I am using CortexA9.
Do you know what causes the problems of .bss and .data sections?
.section .vectors _vector_table: B _boot B Undefined B SVCHandler B PrefetchAbortHandler B DataAbortHandler NOP /* Placeholder for address exception vector*/ B IRQHandler B FIQHandler
Hmmm, where is the initial stack pointer?
Can you dump the memory beginning from start address 0 (that should be the location of the vector table)?
Edit: Oh I see, the A9 has a different layout… I’m not familiar with the core, and it seems not to be too easy to determine where in the boot sequence the initial stack pointer comes from. I still believe there is something wrong with your startup stack, maybe someone with more knowledge about that core can jump in?..
Is that what you meant?
/*****************************************************************************/
/**
* @file asm_vectors.s
*
* This file contains the initial vector table for the Cortex A9 processor
******************************************************************************/
#include "xil_errata.h"
#include "xparameters.h"
.org 0
.text
.arm
.global _boot
.global _freertos_vector_table
.global _vector_table
.globl _cpu0_catch
.globl _cpu1_catch
.globl OKToRun
.globl EndlessLoop0
.global FIQInterrupt
.global DataAbortInterrupt
.global PrefetchAbortInterrupt
.global vPortInstallFreeRTOSVectorTable
.extern FreeRTOS_IRQ_Handler
.extern FreeRTOS_SWI_Handler
.section .vectors
_vector_table:
_freertos_vector_table:
B _boot
B FreeRTOS_Undefined
ldr pc, _swi
B FreeRTOS_PrefetchAbortHandler
B FreeRTOS_DataAbortHandler
NOP /* Placeholder for address exception vector*/
LDR PC, _irq
B FreeRTOS_FIQHandler
_irq: .word FreeRTOS_IRQ_Handler
_swi: .word FreeRTOS_SWI_Handler
#if XPAR_CPU_ID==0
_cpu0_catch:
.word OKToRun /* fixed addr for caught cpu- */
_cpu1_catch:
.word EndlessLoop0 /* fixed addr for caught cpu- */
#elif XPAR_CPU_ID==1
_cpu0_catch:
.word EndlessLoop0
_cpu1_catch:
.word OKToRun
#endif
.align 4
FreeRTOS_FIQHandler: /* FIQ vector handler */
stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */
FIQLoop:
blx FIQInterrupt /* FIQ vector */
ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */
subs pc, lr, #4 /* adjust return */
.align 4
FreeRTOS_Undefined: /* Undefined handler */
b .
.align 4
FreeRTOS_DataAbortHandler: /* Data Abort handler */
#ifdef CONFIG_ARM_ERRATA_775420
dsb
#endif
stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */
blx DataAbortInterrupt /*DataAbortInterrupt :call C function here */
ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */
subs pc, lr, #4 /* adjust return */
.align 4
FreeRTOS_PrefetchAbortHandler: /* Prefetch Abort handler */
#ifdef CONFIG_ARM_ERRATA_775420
dsb
#endif
stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */
blx PrefetchAbortInterrupt /* PrefetchAbortInterrupt: call C function here */
ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */
subs pc, lr, #4 /* adjust return */
.align 4
.type vPortInstallFreeRTOSVectorTable, %function
vPortInstallFreeRTOSVectorTable:
/* Set VBAR to the vector table that contains the FreeRTOS handlers. */
ldr r0, =_freertos_vector_table
mcr p15, 0, r0, c12, c0, 0
dsb
isb
bx lr
.end
Disassembly content:
00000000: b +300 ; addr=0x00000134
00000004: b +156 ; addr=0x000000a8
00000008: b +180 ; addr=0x000000c4
0000000c: b +244 ; addr=0x00000108
00000010: b +208 ; addr=0x000000e8
00000014: nop
00000018: b +8 ; addr=0x00000028
0000001c: b +68 ; addr=0x00000068
00000020: andeq r0, r0, r12, ror #2
00000024: andeq r0, r0, r12, asr r1
00000028: push {r0,r1,r2,r3,r12,lr}
0000002c: vpush {d0-d7}
00000030: vpush {d16-d31}
00000034: vmrs r1, fpscr
00000038: push {r1}
0000003c: vmrs r1, fpexc
00000040: push {r1}
00000044: bl +27236 ; addr=0x00006ab0
00000048: pop {r1}
0000004c: vmsr fpexc, r1
00000050: pop {r1}
00000054: vmsr fpscr, r1
00000058: vpop {d16-d31}
0000005c: vpop {d0-d7}
00000060: pop {r0,r1,r2,r3,r12,lr}
00000064: subs pc, lr, #4
00000068: push {r0,r1,r2,r3,r12,lr}
0000006c: vpush {d0-d7}
00000070: vpush {d16-d31}
00000074: vmrs r1, fpscr
00000078: push {r1}
0000007c: vmrs r1, fpexc
00000080: push {r1}
00000084: bl +27152 ; addr=0x00006a9c
00000088: pop {r1}
0000008c: vmsr fpexc, r1
00000090: pop {r1}
00000094: vmsr fpscr, r1
00000098: vpop {d16-d31}
0000009c: vpop {d0-d7}
000000a0: pop {r0,r1,r2,r3,r12,lr}
000000a4: subs pc, lr, #4
000000a8: push {r0,r1,r2,r3,r12,lr}
000000ac: ldr r0, [pc, #+116]
000000b0: sub r1, lr, #4
000000b4: str r1, [r0]
......... ...
_boot
No. What happens in _boot? It looks as if the A9 requires the programmer to set up the stack pointer in the _boot routine.