/************************************************************************************ * loadCode.c * * synopsis: During its boot procedure (mode 01101b) the master DSP reads the IPRAM * code sections from the boot ROM and loads them into the IPRAM. loadCode * reads non-IPRAM code and initialized data sections, i.e. those targeted * for IDRAM and SDRAM, from the boot ROM and writes them to the targeted * locations. loadCode is executed just after initEmif (the function which * initializes the EMIF). * * Damon Fasching, UW Madison fasching@wisconsin.cern.ch * Douglas Ferguson, UW Madison (510) 486-5230 dpferguson@lbl.gov * * modifications/bugs * - need to look for '0xc0ffee' and leave that section alone.The DSP-BIOS * fills the stack with 0xc0ffee at link time (gives an easy test of its * max size during execution); this causes the flash-rom creation program * coffconv to add another initialized section for loadCode to copy-- * only this one is disastrous to copy! Temporary until coffconv is * modified. 01.03.02 dpsf ************************************************************************************/ #include "processor.h" #include "fxnProto.h" #include "memoryPartitions.h" #include "errorCodes.h" #pragma CODE_SECTION(loadCode, "icode"); #if (defined(TI_EVM) || defined(SIM)) INT32 loadCode(void) { return SUCCESS; } #else INT32 loadCode(void) { UINT32 numSections, sectionLength, sectionNumber; UINT32 *sourceAddress, *destAddress, *sourceAddressSave, *destAddressSave, *baseAddress; UINT32 checksum, dataWord; UINT32 verifyError, errorCounter, addressErrors = 0; INT32 checksumWC; /* Calculate checksum contribution from IPRAM and IDRAM sections of boot ROM. */ baseAddress = (UINT32 *)(BOOT_ROM_BASE); checksumWC = (INT32)(((IPRAM_SZ) + (IDRAM_SZ)) >> 2); checksum = calculateChecksum(baseAddress, checksumWC); /* set source address to start of external code section of boot ROM & read header */ sourceAddress = (UINT32 *)((BOOT_ROM_BASE) + (IPRAM_SZ) + (IDRAM_SZ)); numSections = *sourceAddress; checksum ^= numSections; ++sourceAddress; /* loop over the various destinations */ for (sectionNumber = 0; sectionNumber < numSections; ++sectionNumber) { /* read the section header */ sectionLength = *sourceAddress; checksum ^= sectionLength; ++sourceAddress; destAddress = (UINT32 *)*sourceAddress; checksum ^= (UINT32)destAddress; ++sourceAddress; /* check size and match of header and trailer length parameter */ if ( (sourceAddress +sectionLength +4) > (UINT32 *)((BOOT_ROM_BASE) + (BOOT_ROM_SZ)) ) { return -(CODE_EXCEEDS_ROM); } if (*(sourceAddress + sectionLength) != sectionLength) { return -(CODE_LENGTH_MISMATCH); } /* check for 0xc0ffee in src (stack), do not load if so. 1st 3 words are checked. This needs doing only for BIOS, but is harmless too. */ if ( (*sourceAddress==0xc0ffee) && (*(sourceAddress+4)==0xc0ffee) && (*(sourceAddress+8)==0xc0ffee) ) { for (dataWord = 0; dataWord < sectionLength; ++dataWord) { checksum ^= *sourceAddress; ++sourceAddress; } } else { /* load the code */ destAddressSave = destAddress; sourceAddressSave = sourceAddress; for (dataWord = 0; dataWord < sectionLength; ++dataWord) { *destAddress = *sourceAddress; checksum ^= *sourceAddress; ++sourceAddress; ++destAddress; } /* verify data: If a word is wrong, attempt to copy it again, up to * 5 times before error exit. */ destAddress = destAddressSave; sourceAddress = sourceAddressSave; for (dataWord = 0; dataWord < sectionLength; ++dataWord) { errorCounter = 0; verifyError = 1; while (errorCounter < 5 && verifyError) { if (*destAddress == *sourceAddress) { verifyError = 0; } else { *destAddress = *sourceAddress; ++errorCounter; if (errorCounter == 1) ++addressErrors; } } if (verifyError) return -(CODE_LOAD_ERROR); ++sourceAddress; ++destAddress; } } /* end of code loading */ /* Skip over trailing copy of sectionLength. */ checksum ^= *sourceAddress; ++sourceAddress; } /* end of copy section loop */ if (checksum != *sourceAddress) { return -(CHECKSUM_ERROR); } return SUCCESS; } #endif