Tool/software:
Hi,
I am trying to boot my c6657 DSP from NOR flash that has been written by a program I have created on my SOC that can reach the NOR flash device over the SPI interface. I modified the NORWRITER.c program provided by TI to work with my custom spi interface on my SOC to ensure my programming was done in the same way that running the NORWRITER.c program through code composer works.
I am currently struggling to get the c6657 DSP to boot from the NOR after I wrote it. Its able to read the addresses for a while, but once it gets to address 04F900 it starts to fail to read and then boot.
In my debugging its also been difficult to get output from the NORWRITER.c file to compare the actual writing that works, vs my own writing that is failing to work.
Below is the function call that actually programs the NOR from my SOC application. The file pointer is to the app.dat file. Also included is the spi write function
int flash_nor() {
uint32_t cur_block, cur_sector, cur_page; // For iterating over the device
uint32_t curHex; // Stores the current line read
FILE *fp; // Pointer to file containing write data
int curLine, block_cnt = 0, cur_data_block = 0; // Current line, data block
int write_size_bytes = 256; // Size that youre trying to write
uint16_t data_block[write_size_bytes]; // Array to store data to currently write
uint8_t mini_data_block[4];
// Check to see if the current sector has been erased
int cur_sector_erase = 0;
// Allocate memory for line reader
char* lineRead = malloc(sizeof(char)*15);
if (!lineRead) {
printf("Failed to allocate memory for lineRead\n");
return -1;
}
// Open the file for reading
fp = fopen(norWriterInfo.file_name, "r");
if (!fp) {
printf("Failed to open app.dat\n");
return -1;
}
// Clear out the start of the file
fgets(lineRead, 15, fp);
fgets(lineRead, 15, fp);
/* The folowing code programs the entire nor device according
* to how the platform.c file and norwriter.c works. There
* are some comments to explain the process below
*
* Notes:
* - block is 64kb
* - sector is 4kb
* - page is 256 bytes
*
* norwriter process: (Sector and block are the same thing, p2 vs p3)
* - read the block (page level)
* - erase the block (block level)
* - write the block (page level)
*/
/* Iterate over all the blocks in memory
Starting block is norWriterInfo.startAddr (usually 0), last block starts at 7F0000
Iterate at 01xxxx at a time */
for (cur_block = norWriterInfo.startAddr; cur_block <= 0x7F0000; cur_block += 0x010000) {
printf ("Flashing block/sector %d (%d bytes of %d)\n", block_cnt, cur_block, norWriterInfo.writeBytes);
/* Iterate over each sector in the current block
Max sector size is xxFxxx, so iterate at xx1xxx at a time */
for (cur_sector = cur_block; cur_sector <= cur_block + 0x00F000; cur_sector += 0x001000) {
// Read all pages in current sector
/* Iterate over each page in the current sector
Max page is xxxFFF, so itereate 256 bytes at a time (xxx100)
cur_sector includes the cur_block, no need to add it again */
for (cur_page = cur_sector; cur_page <= cur_sector + 0x000FFF; cur_page += write_size_bytes) {
#if VDEBUG
printf("Current block: 0x%04x, Cur sector: 0x%04x, Cur page: 0x%04x\n", cur_block, cur_sector, cur_page);
#endif
uint16_t *readData = malloc(sizeof(uint16_t)*write_size_bytes);
// read block at page level (not neccessary?)
if (spi_read(readData, cur_page, write_size_bytes) != 1) {
printf("Failed to read from 0x%08x! Exiting\n", cur_page);
free(readData);
return -1;
}
//todo save this data
free(readData);
}
// End reading all pages in current sector
// Erase the current sector
#if DEBUG
printf("Erasing sector 0x%08x\n", cur_sector);
#endif
if (spi_sector_erase(cur_sector) != 1) {
printf("Failed to erase sector 0x%04x! Exiting\n", cur_sector);
return -1;
}
cur_sector_erase = 1;
// End erase current sector
// Write all pages in current sector
/* Iterate over each page in the current sector
Max page is xxxFFF, so itereate 256 bytes at a time (xxx100)
cur_sector includes the cur_block, no need to add it again */
for (cur_page = cur_sector; cur_page <= cur_sector + 0x000FFF; cur_page += write_size_bytes) {
/* Get the data to write
Loop over block num size (defined above)
Set to 0 since fgets always gets the next line even in new loop
Count up to write_size_bytes/2 since each line is 32 bit, and
array is expected 16 bit, so each line is 2 data block worth */
for (curLine = 0; curLine < write_size_bytes/2; ++curLine) {
/* Get the current line
The pointer does not reset, so it will continue from last time
which is why there curLine is always 0 */
fgets(lineRead, 15, fp);
// Read from the current line and place into the hex var
sscanf(lineRead, "%x", &curHex);
#if VDEBUG
printf("Current line: 0x%08x\n", curHex);
#endif
// Split the 32bit hex into two 16bit hex and reorder the data for writing
// Grab the bottom 16 and split
mini_data_block[0] = curHex & 0x000000FF;
mini_data_block[1] = (curHex & 0x0000FF00) >> 8;
// Grab the top 16 and split
mini_data_block[2] = (curHex & 0x00FF0000) >> 16;
mini_data_block[3] = (curHex & 0xFF000000) >> 24;
// Combine the mini data
data_block[cur_data_block] = (mini_data_block[0] << 8) | mini_data_block[1];
data_block[cur_data_block + 1] = (mini_data_block[2] << 8) | mini_data_block[3];
#if VDEBUG
printf("Current data block(s): 0x%04x 0x%04x\n", data_block[cur_data_block], data_block[cur_data_block + 1]);
#endif
// Iterate the current block in the array by 2 (places 32bit worth data)
cur_data_block += 2;
}
// Reset pointer for data_block array
cur_data_block = 0;
#if VDEBUG
// Print out the data put into data_block array for debug
printf("Data read from file: \n");
print_data(data_block, write_size_bytes/2);
#endif
// write the block at the page level (after erase)
// Write and verify the page
if (spi_write_verify(data_block, cur_page, write_size_bytes) == -1) {
printf("Writing page 0x%08x failed!\n", cur_page);
return -1;
}
// Reset the current sector erased var
cur_sector_erase += 0;
}
// End write all pages in current sector
}
// If all the data has been printed, exit
if (cur_block >= norWriterInfo.writeBytes - 65536) {
printf("Finished flashing\n");
break;
}
// Increment the number of blocks written so far
++block_cnt;
}
fclose(fp);
return 1;
}
int spi_write(uint16_t writeData[], uint32_t address, int num_write_bytes) {
int status;
static uint16_t writeCmd = 0x0200;
int num_write_words = num_write_bytes/2; // Every 2 bytes is one word
// Writing strings - 0x0000 is max
// Determine length of command
int length = num_write_bytes + 4; // 4 is size of command and address
// Check to ensure length is within one page
if (num_write_bytes > 256) {
printf("Data too large, max write is 256 words\n");
return -1;
}
// Get size for tx_write array (write command and data)
// Format: command, next are 4 page, last 2 address starting point, data...
// Each uint16 is 2 bytes
uint16_t tx_write[num_write_words + 2];
// Check for valid address
if (address > 0x7fffff) {
printf("Invalid address, exiting read\n");
return -1;
}
// Set slave select to NOR flash
WriteReg(SPI_MASTER_SLAVESEL, 0x1);
tx_write[0] = ((uint16_t)(address >> 16)) | writeCmd;
tx_write[1] = (uint16_t)address;
#if DEBUG
printf("Write address and command: 0x%04x 0x%04x\n", tx_write[0], tx_write[1]);
#endif
// Copy from the 3rd element onwards to keep command and address
memcpy(&tx_write[2], writeData, sizeof(uint16_t) * num_write_words);
#if VDEBUG
printf("Data to write:\n");
print_data(tx_write, num_write_words + 2);
#endif
// Send command and data
// SPI Struct for write operations
struct spi_ioc_transfer SPIWrite = {
.tx_buf = (unsigned long)tx_write, // Set correct buffers for tx rx
.len = length, // Length of command and data in bytes
.speed_hz = 10000000, // Speed of spi (not sure, but works for now)
.bits_per_word = 16, // Sets interfaces data frame length
.cs_change = 0, // Set to 0 to not enable device select between transfers
};
// Enable write
status = write(spiDevice, tx_wrEn, sizeof(tx_wrEn));
if (status < 0) {
printf("Write enable failed\n");
close(spiDevice);
return -1;
}
// Send the writing command and data
status = ioctl(spiDevice, SPI_IOC_MESSAGE(1), &SPIWrite);
if (status < 1) {
printf("Cant write to SPI\n");
close(spiDevice);
return -1;
}
// Poll status reg to wait for complete transfer
nor_busy_wait(spiDevice);
//if (writeFinished == 1) {
// // Enable disable
// status = write(spiDevice, tx_wrDis, sizeof(tx_wrDis));
// if (status < 0) {
// printf("Write disable failed\n");
// close(spiDevice);
// return -1;
// }
//}
WriteReg(SPI_MASTER_SLAVESEL, 0x0);
return 1;
}


