This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM5726: Regarding DSP boot delay time

Part Number: AM5726
Other Parts Discussed in Thread: SYSBIOS

Hi experts,

My customer has a question about boot delays for DSP1 and DSP2.

When customers boot in the order ARM → DSP1 → DSP2, they boot successfully if they insert a delay of 10000 CPU CYCLE before booting DSP2.
However, when booting in the order ARM → DSP2 → DSP1, if they insert a delay of 10000 CPU CYCLE before booting DSP1, they will not boot normally. Setting this delay to 100000 CPU CYCLE will boot normally.
Do you know why they have to insert a lot of delay when booting in the order ARM → DSP2 → DSP1?
The customer code is below. The delay time is set by #define BOOT_LOOP.

====================================================

#include <xdc/std.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/timers/dmtimer/Timer.h>
#include <ti/sysbios/hal/Cache.h>
#include <xdc/runtime/Diags.h>
#include <xdc/runtime/Log.h>

/* includes from demo */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ti/sysbios/family/arm/gic/Hwi.h>

#include <ti/csl/soc.h>
#include <ti/csl/cslr_device.h>

#include <ti/board/board.h>

/* TI-RTOS Header files */
#include <ti/drv/i2c/I2C.h>
#include <ti/drv/i2c/soc/I2C_v1.h>
#include "js_io.h"
#include "ipc_share.h"


/*==============================================================================*/
/* Debug trace declaration (with trace output when enabled) */
/*==============================================================================*/
#define DBG_ERR() osw_printf("ERR:%s(line %u)\n",__FUNCTION__,__LINE__)
#define DBG_TRACE1(...) osw_printf(__VA_ARGS__)
#define DBG_TRACE2(...) osw_printf(__VA_ARGS__)

//#define SMC_BRD


extern const unsigned char dsp1_data[];
extern const unsigned int dsp1_size;

extern const unsigned char io_delay_data[];
extern const unsigned int io_delay_size;

extern const unsigned char dsp2_data[];
extern const unsigned int dsp2_size;

/*******************************************#define*************************************/
/** \brief Puts string to the UART and replace "\n" to "\n\r"
*
* \return N/A
*/
static int UARTPutStringWithCR(char* pStr, int maxLength)
{
int symCount = 0;
char* pCurrent = pStr;

while (*pCurrent != 0)
{
Char curChar = *pCurrent;
if ( '\n' == curChar )
{
UART_putc('\n');
UART_putc('\r');
}
else
UART_putc(curChar);

symCount++;

pCurrent++;
}

return symCount;
}

/* ========================================================================== */
/* Macros */
/* ========================================================================== */


void InitAuxClockTimer( void );
extern int Core0_start( void );
extern const I2C_Config I2C_config[];

/* ========================================================================== */
/* Function Definitions */
/* ========================================================================== */

#define CM_DSP1_CLKSTCTRL 0x4A005400
#define CM_DSP1_DSP_CLKCTRL 0x4A005420
#define RM_DSP1_RSTCTRL 0x4AE06410
#define RM_DSP1_RSTST 0x4AE06414
#define CTRL_CORE_CONTROL_DSP1_RST_VECT 0x4A00255C

#define CM_DSP2_CLKSTCTRL 0x4A005600
#define CM_DSP2_DSP_CLKCTRL 0x4A005620
#define RM_DSP2_RSTCTRL 0x4AE07B10
#define RM_DSP2_RSTST 0x4AE07B14
#define CTRL_CORE_CONTROL_DSP2_RST_VECT 0x4A002560

//#define DSP2_1ST
#ifdef DSP2_1ST
#define BOOT_LOOP 10000
#else
#define BOOT_LOOP 100000
#endif

int main()
{
UINT32 addr1, addr2, i;

/* Call board init functions */
Board_IDInfo info;
Board_initCfg boardCfg;

Log_print0(Diags_ENTRY, "--> main:");

boardCfg = BOARD_INIT_UNLOCK_MMR | BOARD_INIT_PINMUX_CONFIG | BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO;
Board_init(boardCfg);

memset(&info, 0,sizeof(Board_IDInfo));

InitAuxClockTimer();

DBG_TRACE1("console_start().\n");
DBG_TRACE1("Core0_start().\n");
if( Core0_start() == 0 ){
DBG_ERR();
while( 1 );
}

#ifdef DSP2_1ST
/* ========== DSP2 reset release ========== */
addr2 = ENTRY_ADDRESS_DSP2;
IOREG32(CTRL_CORE_CONTROL_DSP2_RST_VECT,0) = 0x02000000 | (addr2 >> 10);
IOREG32(RM_DSP2_RSTCTRL,0) = 0x3;
IOREG32(CM_DSP2_CLKSTCTRL,0) = 0x2;
IOREG32(CM_DSP2_DSP_CLKCTRL,0) = 0x1;
while( (IOREG32(CM_DSP2_CLKSTCTRL,0) & 0x100) != 0x100 );
IOREG32(RM_DSP2_RSTCTRL,0) = 0x1;
while( (IOREG32(RM_DSP2_RSTST,0) & 0x2) != 0x2 );
memcpy( (void *)(addr2), (void *)dsp2_data, dsp2_size );
Cache_wbInv((void *)(addr2), dsp2_size, Cache_Type_ALL, TRUE);
IOREG32(RM_DSP2_RSTCTRL,0) = 0x0;
while( (IOREG32(RM_DSP2_RSTST,0) & 0x3) != 0x3 );
while( (IOREG32(CM_DSP2_DSP_CLKCTRL,0) & 0x30000) != 0x0 );
/* ========== DSP1 reset release ========== */
for (i = 0; i < BOOT_LOOP; i++) {
addr1 = ENTRY_ADDRESS_DSP1;
IOREG32(CTRL_CORE_CONTROL_DSP1_RST_VECT,0) = 0x02000000 | (addr1 >> 10);
}
addr1 = ENTRY_ADDRESS_DSP1;
IOREG32(CTRL_CORE_CONTROL_DSP1_RST_VECT,0) = 0x02000000 | (addr1 >> 10);
IOREG32(RM_DSP1_RSTCTRL,0) = 0x3;
IOREG32(CM_DSP1_CLKSTCTRL,0) = 0x2;
IOREG32(CM_DSP1_DSP_CLKCTRL,0) = 0x1;
while( (IOREG32(CM_DSP1_CLKSTCTRL,0) & 0x100) != 0x100 );
IOREG32(RM_DSP1_RSTCTRL,0) = 0x1;
while( (IOREG32(RM_DSP1_RSTST,0) & 0x2) != 0x2 );
memcpy( (void *)(addr1), (void *)dsp1_data, dsp1_size );
memcpy( (void *)(ADDRESS_DSP1_IODELAY), (void *)io_delay_data, io_delay_size );
Cache_wbInv((void *)(addr1), dsp1_size, Cache_Type_ALL, TRUE);
IOREG32(RM_DSP1_RSTCTRL,0) = 0x0;
while( (IOREG32(RM_DSP1_RSTST,0) & 0x3) != 0x3 );
while( (IOREG32(CM_DSP1_DSP_CLKCTRL,0) & 0x30000) != 0x0 );
#else
/* ==========DSP1 reset release ========== */
addr1 = ENTRY_ADDRESS_DSP1;
IOREG32(CTRL_CORE_CONTROL_DSP1_RST_VECT,0) = 0x02000000 | (addr1 >> 10);
IOREG32(RM_DSP1_RSTCTRL,0) = 0x3;
IOREG32(CM_DSP1_CLKSTCTRL,0) = 0x2;
IOREG32(CM_DSP1_DSP_CLKCTRL,0) = 0x1;
while( (IOREG32(CM_DSP1_CLKSTCTRL,0) & 0x100) != 0x100 );
IOREG32(RM_DSP1_RSTCTRL,0) = 0x1;
while( (IOREG32(RM_DSP1_RSTST,0) & 0x2) != 0x2 );
memcpy( (void *)(addr1), (void *)dsp1_data, dsp1_size );
memcpy( (void *)(ADDRESS_DSP1_IODELAY), (void *)io_delay_data, io_delay_size );
Cache_wbInv((void *)(addr1), dsp1_size, Cache_Type_ALL, TRUE);
IOREG32(RM_DSP1_RSTCTRL,0) = 0x0;
while( (IOREG32(RM_DSP1_RSTST,0) & 0x3) != 0x3 );
while( (IOREG32(CM_DSP1_DSP_CLKCTRL,0) & 0x30000) != 0x0 );
for (i = 0; i < BOOT_LOOP; i++) {
addr2 = ENTRY_ADDRESS_DSP2;
IOREG32(CTRL_CORE_CONTROL_DSP2_RST_VECT,0) = 0x02000000 | (addr2 >> 10);
}
/* ========== DSP2 reset release ========== */
IOREG32(RM_DSP2_RSTCTRL,0) = 0x3;
IOREG32(CM_DSP2_CLKSTCTRL,0) = 0x2;
IOREG32(CM_DSP2_DSP_CLKCTRL,0) = 0x1;
while( (IOREG32(CM_DSP2_CLKSTCTRL,0) & 0x100) != 0x100 );
IOREG32(RM_DSP2_RSTCTRL,0) = 0x1;
while( (IOREG32(RM_DSP2_RSTST,0) & 0x2) != 0x2 );
memcpy( (void *)(addr2), (void *)dsp2_data, dsp2_size );
Cache_wbInv((void *)(addr2), dsp2_size, Cache_Type_ALL, TRUE);
IOREG32(RM_DSP2_RSTCTRL,0) = 0x0;
while( (IOREG32(RM_DSP2_RSTST,0) & 0x3) != 0x3 );
while( (IOREG32(CM_DSP2_DSP_CLKCTRL,0) & 0x30000) != 0x0 );
#endif

BIOS_start();

return(0);
}

Timer_Handle g_auxClocksTimerHandle = 0;
void InitAuxClockTimer()
{
const UInt auxClockTimerInstance = 1; // instance number defined in EcMaster.cfg
g_auxClocksTimerHandle = Timer_getHandle(auxClockTimerInstance);
}
void TimerEmptyISR()
{
}

====================================================

Best regards,
Sasaki

  • Hi Sasaki-san,

    for (i = 0; i < BOOT_LOOP; i++) {
    addr1 = ENTRY_ADDRESS_DSP1;
    IOREG32(CTRL_CORE_CONTROL_DSP1_RST_VECT,0) = 0x02000000 | (addr1 >> 10);
    }

    Is there a specific reason for writing this register again and again or this is just for delay purpose? 

    Also, you can directly use SBL_DSP1_BringUp and SBL_DSP2_BringUp from <pdkInstallPath>\packages\ti\boot\sbl\soc\am57xx\sbl_slave_core_boot.c to boot DSPs. There should not be any delay requirement for them. Please make sure, you enable clocks for the DSPs using DSP1_ClkEnable and DSP2_ClkEnable before using these APIs

    Regards,
    Parth

  • Hi Parth-san,

    Thank you for the information.

    Is there a specific reason for writing this register again and again or this is just for delay purpose? 

    This is just delay purpose, and there is no specific reason.

    Also, you can directly use SBL_DSP1_BringUp and SBL_DSP2_BringUp from <pdkInstallPath>\packages\ti\boot\sbl\soc\am57xx\sbl_slave_core_boot.c to boot DSPs. There should not be any delay requirement for them. Please make sure, you enable clocks for the DSPs using DSP1_ClkEnable and DSP2_ClkEnable before using these APIs

    We will contact the customer with this information and wait for customer feedback.

    Best regards,
    Sasaki

  • Hi Sasaki-san,

    This is just delay purpose, and there is no specific reason.

    This is not a good way to introduce delay in code. You should suggest them to use Board_delay or Osal_delay for delay purposes.

    We will contact the customer with this information and wait for customer feedback.

    Sure, do let us know the feedback on this. I am hoping, there should not be any delay requirements when using these APIs.

    Regards,
    Parth