Our DSP application sometimes gets stuck booting after a code change. The DSP will run through c_int00, call main, and during TSK_create, a br instruction jumps to an invalid address and the DSP resets. I have noticed that in some cases adding or removing one line of code in the main application can cause or cure the issue. The line of code never has a chance to run before the error happens, but does change the link map a bit. In particular I have notice that several .cinit destination addresses change, all of which are related to DSP/BIOS.
Any ideas on what could cause this?
#include "platform.h" #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <std.h> #include <gbl.h> #include <clk.h> #include <tsk.h> #define LOAD_WINDOW_IN_MS (500) #pragma DATA_SECTION(__main_args__,".args"); uint8_t __main_args__[1024]; static uint32_t minIdleFxnTime = 0xFFFFFFFF; static uint32_t loadWindowTime = 0; static int32_t currLoad = 0; int32_t GetLoad( void ) { return currLoad; } void UpdateDspToArmTick(); unsigned int GetUsTime(); void IdleFunction( void ) { static uint32_t idleCount = 0; static uint32_t totalTime = 0; static uint32_t t0 = 0; uint32_t t1 = 0; uint32_t delta; // Keep track of times through this function GetUsTime(); UpdateDspToArmTick(); idleCount++; // Compute the time difference since the last call this function t1 = CLK_gethtime(); delta = t1 - t0; t0 = t1; // Accumulate totalIdleTime totalTime += delta; /* * 'minloop' keeps track of the shortest time thru the IDL loop. * Note that we check to make sure delta is not zero (delta * will be zero during IDL loop calibration) */ if (delta != 0 && delta < minIdleFxnTime) { minIdleFxnTime = delta; } // Compute the CPU load as 100 - "percent time idle" // "percent time idle" = 100 * (idleCount * minIdleFxnTime)/totalTime if (totalTime > loadWindowTime) { currLoad = (int32_t) (100 - ( (100 * idleCount * minIdleFxnTime) / totalTime)); idleCount = 0; totalTime = 0; } } // Replacement clock function to use in place of RTS lib version _CODE_ACCESS clock_t clock(void) { clock_t result; // Calculate absolute time in microseconds result = (clock_t) ((CLK_gethtime() * CLK_cpuCyclesPerHtime() * 1000) / GBL_getFrequency()); return result; } void Initialize( ); extern void exit(), _auto_init(); extern void IDL_loop(); extern void BIOS_start(); extern far void BCACHE_bootInit(); extern far void auto_init(const void *cinit, const unsigned int dp); /*---------------------------------------------------------------------------*/ /* ALLOCATE THE MEMORY FOR THE SYSTEM STACK. THIS SECTION WILL BE SIZED */ /* BY THE LINKER. */ /*---------------------------------------------------------------------------*/ asm(" .global __STACK_SIZE"); asm(" .global __stack"); /* * Define special symbol to guarantee that this boot file gets linked * instead of boot file from rts.lib (SDSsq24217). The GBL_config macro * will reference this symbol forcing a linker error if non-bios boot.obj * has been linked with application. */ asm(" .def GBL_boot"); asm("GBL_boot .set 1"); asm("__stack: .usect .stack, 0, 8"); /* * Put c_int00 in the .sysinit section. */ asm(" .sect \".sysinit\""); #pragma CODE_SECTION(c_int00,".sysinit") extern void interrupt c_int00() { // volatile int debugDummy = 0; // // while(debugDummy == 0); /* * Clear IER register. This is necessary to prohibit left-over * interrupts from being serviced. This is not necessary if users * reset the part before reload or restart but ... */ asm(" zero b0"); asm(" mvc b0,ier"); /*------------------------------------------------------------------------*/ /* SET UP THE STACK POINTER IN B15. */ /* THE STACK POINTER POINTS 1 WORD PAST THE TOP OF THE STACK, SO SUBTRACT */ /* 1 WORD FROM THE SIZE. */ /*------------------------------------------------------------------------*/ asm(" mvkl __stack,SP"); asm(" mvkh __stack,SP"); asm(" mvkl __STACK_SIZE - 4,B0"); asm(" mvkh __STACK_SIZE - 4,B0"); asm(" add B0,SP,SP"); /*------------------------------------------------------------------------*/ /* THE SP MUST BE ALIGNED ON AN 8-BYTE BOUNDARY. */ /*------------------------------------------------------------------------*/ asm(" and ~7,SP,SP"); /*------------------------------------------------------------------------*/ /* SET UP THE GLOBAL PAGE POINTER IN B14. */ /*------------------------------------------------------------------------*/ asm(" .global $bss"); asm(" mvkl $bss,DP"); asm(" mvkh $bss,DP"); /*------------------------------------------------------------------------*/ /* SET UP FLOATING POINT REGISTERS FOR C67 ONLY */ /*------------------------------------------------------------------------*/ #ifdef _TMS320C6700 asm(" mvk 0,B3"); /* round to nearest */ asm(" mvc B3,FADCR"); asm(" mvc B3,FMCR"); #endif /*------------------------------------------------------------------------*/ /* INITIALIZE CONTROL REGISTERS (FOR BIOS ONLY) */ /*------------------------------------------------------------------------*/ asm(" mvk 0,B3"); asm(" mvc B3,AMR"); /* addressing mode register */ asm(" mvc B3,CSR"); /* control status register */ /*------------------------------------------------------------------------*/ /* CALL BCACHE_bootInit function. This function is determined by config */ /* and bound in the generated linker command file. */ /*------------------------------------------------------------------------*/ BCACHE_bootInit(); /*------------------------------------------------------------------------*/ /* GET THE POINTER TO THE AUTOINITIALIZATION TABLES INTO THE FIRST */ /* ARGUMENT REGISTER (A4) */ /*------------------------------------------------------------------------*/ asm(" .global cinit"); asm(" mvkl cinit,A4"); asm(" mvkh cinit,A4"); /*------------------------------------------------------------------------*/ /* PASS THE CURRENT DP TO THE AUTOINITIALIZATION ROUTINE. */ /*------------------------------------------------------------------------*/ asm(" mv DP,B4"); /*------------------------------------------------------------------------*/ /* CALL THE AUTOINITIALIZATION ROUTINE. */ /*------------------------------------------------------------------------*/ asm(" .global __auto_init"); asm(" mvkl __auto_init, B0"); asm(" mvkh __auto_init, B0"); asm(" mvkl boot_ret, B3"); asm(" mvkh boot_ret, B3"); asm(" b B0"); asm(" nop 5"); asm("boot_ret:"); asm(" .global ___main_args__"); asm(" mvkl ___main_args__,A0"); asm(" mvkh ___main_args__,A0"); asm(" ldw *+A0[2],A6"); /* envp */ asm(" ldw *+A0[1],B4"); /* argv */ asm(" ldw *+A0[0],A4"); /* argc */ /*------------------------------------------------------------------------*/ /* CALL THE USER'S PROGRAM. */ /*------------------------------------------------------------------------*/ // main(); /* main(A4, B4, A6); */ asm(" .global _main"); asm(" mvkl _main, B0"); asm(" mvkh _main, B0"); asm(" b B0"); asm(" mvkl main_ret, B3"); asm(" mvkh main_ret, B3"); asm(" nop 3"); asm("main_ret:"); /*------------------------------------------------------------------------*/ /* START RUNTIME FOR BIOS. */ /* The call to BIOS_start does not return if the Task Manager is enabled */ /*------------------------------------------------------------------------*/ BIOS_start(); /*------------------------------------------------------------------------*/ /* FALL INTO THE BIOS IDLE LOOP, NEVER RETURN. */ /*------------------------------------------------------------------------*/ IDL_loop(); } TSK_Handle g_InitializeTask; void main( void ) { TSK_Attrs attrs = TSK_ATTRS; volatile int debugDummy = 0; if(g_pSharedMemory->dspInitParams.debugLevel & DSP_CODE_COMPOSER_CONNECT) while(debugDummy == 0); // Start Control task attrs.stacksize = 4 * 1024; attrs.priority = TSK_MAXPRI; attrs.name = "Initialize"; g_InitializeTask = TSK_create( (Fxn)Initialize, &attrs ); return; } /************************************************************ * Local Function Definitions * ************************************************************/ /*********************************************************** * End file * ***********************************************************/