Hello,
I need an immediate advice for booting DSP from SPI flash.
I have made a custom board with TMS320C6652 which boots from SPI flash connected to SPISCS0, but the booting process is always suspended after the initial 4 bytes are read by DSP.
Somehow DSP resumes the rest of the booting process either when DSP's DVDD15 power is temporarily turned off for more than 3ms (this violates the power/reset sequence, though) or when DSP is extremely cooled down by a cold spray.
I guessed the RBL of DSP is probably trapped in an infinite loop after reading the first 4 bytes from SPI flash and resetting DVDD15 or putting DSP in low temperature brings DSP out of that loop to continue reading the following data from SPI flash.
I looked over the source code of RBL and narrowed down on the most suspicious loop probably responsible of suspending the boot process.
Line 140 - 144 of spi.c :
/* Clear out any pending read data */
do {
v = DEVICE_REG32_R (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIBUF);
v = DEVICE_REG32_R (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIFLG);
} while (SPI_REG_SPIFLG_RX_DATA(v));
Does anybody have an idea what can make this loop infinite!?
This loop is within hw_spi_xfer(), which is called by hwSpiRead(), which is called by boot_spi_read_blocked_block() of spimain.c.
I paste a part of spimain.c codes below. I am pretty sure the booting process is suspended between the two hwSpiRead() function calls.
Line 161 - 189 of spimain.c :
void *boot_spi_read_blocked_block (UINT32 *addr, UINT32 *sizeBytes, spiConfig_t *spiCfg)
{
UINT16 *data = spi_boot_tbl_buf;
UINT16 checksum;
/* Read the header */
if (hwSpiRead (*addr, BOOT_SPI_SECTION_HEADER_SIZE_BYTES, data, spiCfg) != 0) { ←the first hwSpiRead() to read the first 4 bytes
bootLogEntry ((char *)fname, __LINE__, BOOT_SPI_LOG_READ_FAIL);
*sizeBytes = 0;
return (NULL);
}
*sizeBytes = data[BOOT_SPI_HEADER_OFFSET_LENGTH_UINT16];
/* Validate the block size */
if ( (*sizeBytes > BOOT_SPI_SECTION_HEADER_SIZE_BYTES) &&
(*sizeBytes <= BOOT_SPI_MAX_SECTION_SIZE_BYTES) &&
((*sizeBytes & 1) == 0) ) {
if (hwSpiRead (*addr + BOOT_SPI_SECTION_HEADER_SIZE_BYTES,
*sizeBytes - BOOT_SPI_SECTION_HEADER_SIZE_BYTES,
&data[BOOT_SPI_SECTION_HEADER_SIZE_BYTES >> 1], spiCfg) != 0) { ←the second hwSpiRead() that can be reached only by resetting DVDD15 or low temperature
bootLogEntry ((char *)fname, __LINE__, BOOT_SPI_LOG_READ_FAIL);
*sizeBytes = 0;
return (NULL);
}