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 *
***********************************************************/