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; }