TMS320C6657: Trying to boot from NOR flash, written by SOC through SPI on system

Part Number: TMS320C6657

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

  • ,

    By any chance, you have TI's C6657 EVM?

    If yes, the NOR booting steps given in the below FAQ will work straight away on the board. Follow from Step 4 in the below link... 

    [FAQ] TMS320C6657: How to flash the IBL ( Intermediate Boot loader ) into EEPROM and how to flash the application binary into NOR? How to boot the IBL + Application binary? - Processors forum - Processors - TI E2E support forums

    So that you can compare it with your custom board.

    ---

    Some General questions to you.

    1. Do you use the same NOR flash memory in your custom board as that of C6657 TI EVM? I mean the part number of NOR is same?

        -----> Because, if it different, you may have to modify the code to work for the new NOR flash.

    2. In the FAQ above, could you point out in which step you are failing?

    --

    The step 4 is given as a video material in this FAQ:- (+) [FAQ] TMS320C6678: How to flash the IBL ( Intermediate Boot loader ) into EEPROM and how to flash the application binary into NOR? How to boot the IBL + Application binary? - Processors forum - Processors - TI E2E support forums

    Please note that this step is created for C6678 DSP but it is the same step for C6657 device too.

    Regards

    Shankari G 

  • Hi Shankari,

    Yes we do have a EVM board, which we based our custom board on so the nor flash chip is the same (micron N25Q064A). We have no problem using the TI norwriter and CCS to flash the nor flash device. What I am struggling with is I need to be able to flash and update this nor device with updated code through our SOC which has access to the nor flash device as well. The problem im running into is that Im unsure how the norwriter works completely, as through my investigation I have noticed that the norwriter code keeps writing more data after it finishes writing the app.dat file. I have ensured that all the related conversion needed is done (ill provide the script we built to convert the .out to a .dat) before writing the code so thats why I am at a bit of a loss on what to do

    #!/bin/sh
    ./hex6x.exe project.rmd
    ./b2i2c.exe project.btbl project.btbl.i2c
    ./b2ccs.exe project.btbl.i2c project.i2c.ccs
    ./romparse.exe nysh.spi.map > /dev/null
    sed -i '9 s/51/00/' i2crom.ccs
    cp i2crom.ccs projectRom_le.dat
    ./byteswapccs.exe i2crom.ccs app.dat

    I can ensure you that the dip switches are set correctly. Its hard to give a specific part of your FAQ that is failing, since the way its getting flashed is completely different.

    If you could provide any insights to what I may be missing in my attempts to flash this nor device so the DSP can boot, that would be great.

    Thanks,

    Camden

  • Camden,

    You have come this far, it is little bit few more steps....That's it.

    Please do have hope!.

    --

    First, have your TI EVM board and follow the steps completely from start to finish by following this FAQ.

    [FAQ] TMS320C6657: How to flash the IBL ( Intermediate Boot loader ) into EEPROM and how to flash the application binary into NOR? How to boot the IBL + Application binary? - Processors forum - Processors - TI E2E support forums

    Let me know whether you succeeded in TI EVM?

    We have to go step by step...

    Regards

    Shankari G

  • Shankari,

    I think you have missed part of my post. I am able to flash the nor flash device through code composer using the ti provided norwriter code both on the EVM board and our custom board, that is not the problem. The problem i am facing is that I need to adapt this code to work without using code composer, and instead be able to run standalone on our system on a SOC chip that has access to the nor device. Because of that, I cant really give you a specific step that I am failing on since what you linked does not relate to what we are trying to accomplish.

    I also forgot to include that we are not using a IBL for this application, so that part can be ignored. Apologies for that.

    We are struggling to find differences between what our custom norwriter code writes to the flash, and the TI norwriter writes to the flash when flashing from code composer. After we have flashed the nor device with our custom code the DSP c6657 seems to get stuck reading at a certain address, and reading all zeros which i presume is the line thats located at the end of app.dat. When i load into code composer and connect to the DSP at this point I can see the registers and it looks like the program seems to be getting lost per this post. Additionally I was able to find this post which also seems to be a similar problem, but no solution is provided.

    Iv also ensured the boot mode is correct since the bootmode pins are all tied to pullup's/pull downs via resistors and are not driven by any other signal, so it would be impossible for them to go wrong.

    I have also included a screen clip of the registers while its trying to boot.

    Thanks,

    Camden

  • Camden,

    Few stuffs here are beyond the scope of Forum support.....

    For example,

    --------------

    Case 1:-

    -------------

    that I need to adapt this code to work without using code composer, and instead be able to run standalone on our system on a SOC chip that has access to the nor device

    If you don't use code composer, may I ask you which tool you use and how..?

    ---------------

    Case 2:-

    ---------------

    I also forgot to include that we are not using a IBL for this application, so that part can be ignored. Apologies for that.

    IBL is essential for initalizing all the peripherals to operate in optimal speed. This includes SPI interface too through which the NOR-flash is written.

    If you don't use IBL, what is the method adpated to by-pass without loosing its significance?

    ----------------

    Case 3:-

    -----------------

    I have ensured that all the related conversion needed is done (ill provide the script we built to convert the .out to a .dat) before writing the code so thats why I am at a bit of a loss on what to do

    May I know why there is a conversion from .out to .dat ?

    Because in the processor SDK 6.3, the conversion of .out to .bin is just the extension-name replacement.

    For example, 

    1. Copy the UART-app binary ( .out)  you want to flash to "C:\ti\pdk_c665x_2_0_16\packages\ti\boot\writer\nor\evmc6657l\bin" directory.
    2. Rename the binary you copied in the previous step to “app.bin”.

    We are struggling to find differences between what our custom norwriter code writes to the flash, and the TI norwriter writes to the flash when flashing from code composer. After we have flashed the nor device with our custom code the DSP c6657 seems to get stuck reading at a certain address, and reading all zeros which i presume is the line thats located at the end of app.dat.

    The script that you use to convert the binary seems to be a customized one. 

    Instead of using the script use the commands one by one and check whether there is any difference in the output behavioral pattern...

    When you say, it stuck at certain address, are you sure that it is a valid accessible address? Have you check with a simple read and write to this particular address?

    --

    Just try with the " app.bin "  instead of   " app.dat"    ---------- > ( The data formats are treated differently in CCS as we know but...... As you are not, using CCS, you, the author, must be knowing why this data format is choosen to be .dat and how it is to be read back etc....... right?  

    Regards

    Shankari G

  • 1. 
    We have an Arria 10 chip that has access to the same NOR device that the DSP has access to. The goal of this activity is to be able to successfully and easily provide production releases after this product's release. Programming through CCS is not feasible for those purposes. The end goal is a USB is inserted to our unit and our SoC (Arria 10) application will program the NOR flash to update the DSP code. 
    2. 
    Apologies this was a misunderstanding on our part. You are correct
    3.
    This is not a custom script. This is done exactly as how those links you have sent have specified.

    This may be outside the scope of what TI can help us with, but the only reason we are asking is because we are looking to replicate the "norwriter.c" functionality for this purpose. We can and have programmed our NOR flash with this "norwriter" through CCS with no difficulty. We have tried to replicate this functionality on our SoC, but given its complex and obfuscated nature we have reason to believe we are not writing to the NOR flash in the same way as the norwriter.c despite our intent. The behavior we see is we package our data in the same way as the NOR writer and send it to be written yet the data is getting corrupted. For example many lines that should be "0x00000000" are essentially random bytes. Given this we have been investigating the "norwriter.c" and its function calls extensively, yet we still have a limited understanding. Any and all information about how the physical write to the NOR flash is performed would be of great use

  • Camden,

    Thanks.

    Please answer the third question too related to the data format -----> i.e., ".bin" and ".dat" ?

    Regards

    Shankari G

  • Hi,

    The reason that it is formated in the .dat instead of .bin is in relation to this post you made link. The provided link is the original guide we followed to first flash the nor flash on our system and the EVM board.

    Thanks,
    Camden

  • Camden,

    Ohh, OK.

    You are doing a direct SPI-boot without IBL. 

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

    Few suggestions/trials to narrow down this issue.

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

    1. Focus on spiboot.bat file.

    1.1    Instead of using the script ( spiboot.bat), use the commands manually one by one.

    1.2    Check the file size of each output one by one. compare it when you generated using the script.

    2. Focus on the Norwriter.out

    2.1 Check whether the NORwriter.out enclosed in the Direct_ROM boot folder is same as that of the "norwriter.out" enclosed in the processor SDK 6.3

    2.2 In your customized NOrwriter-code, first "WRITE, READ and VERIFY" with a simple data to all the addresses in the NOR flash and "read-back" and make sure, NOR flash memory works fine with all the addresses.

    2.3   When you say, "For example many lines that should be "0x00000000" are essentially random bytes" -----> would you please write and read back a simple data. "This data neednot to be the bootloader " --------->

    This step will make sure your norwriter is working fine with the NORflash memory irrespective of the bootloader getting involved.

    Basically we are eradicating the possibility of the data format here....... Are you with me? I mean forget the binary format/data getting appended in ".dat" etc..etc..

    "Create a simple known data-----> Write it using your customized NOR writer into NOR flash------> Read back and check whether it is the same data.

    3. In the  link., I hope you have not missed this step, right?

    Important Note: Open the spirom_le_swap.dat in CCS and change the value at 0x1F offset as "00" if it has value " 0x51"

    4. Tools to debug:-

     4.1 If it is CCS, after the norwriter.out writes the data into the NOR memory, we will pop out the debug messages to ensure that the flashing is completed successfully.

     4.2 In your customized method, WITHOUT CCS, how do you ensure that it completes the flashing?

    4.3 In the  link. how do you ensure the below step in your setup, without CCS ? What is the debugging techniques you used?

         

    Regards

    Shankari G

  • The issue has been resolved. For anyone who is trying to do the same, the top 128 bytes of the nor flash seem to be protected, so you need to write the bottom 128 bytes at a time.