This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/TMS320C5515: NOR Flash issue

Part Number: TMS320C5515


Tool/software: Code Composer Studio

Hi,

I have developed a custom board using the C5515 processor with a NOR flash (SST39VF3201C) wired very similarly to the C5515ezDSP board. The first prototype was working great. NOR flash was reading and writing as expected. I started copying the first version of the code to a dozen boards and ran into problems where I couldn't read the NOR flash. I programmed the boards using the "programmer" project I found referred to on one of the TI wiki sites. Some boards worked, but some only read 0s. The strange thing is, the code must be there and readable because the boards will boot from the NOR flash and the code will start running normally (other than reading the flash). If the boot code can read it and the "programmer" code can write it, the address and control lines must be fine. I do have the EMIF clock divider in play so the clock is considerably slower for the EMIF.  Anyone have some suggestions what to check? 

Thanks,

Cam

  • Hi Cam,

    Sorry about the trouble. To make sure I understand... All of the boards are able to boot from NOR flash, but during the application execution some of the boards cannot read from NOR flash? Is that right, or do some of the board fail to boot from NOR flash sometimes too?

    Do you have JTAG access on these boards?

    This issue could be caused by many things: bootloader compatibility with the flash, copying code into SARAM31 that is used by the bootloader, device initializtion after boot (during application execution).

    One data point to check is the Program Counter after the bootloader has completed. Make sure not to use a GEL file when connecting to the device after the bootloader executes. The GEL file will wipe the state of the device after the bootload.

    You should be able to read back the contents of the NOR flash with the programmer after programming the NOR. You should also be able to see the contents of the flash through the mem window in CCS. Look for the valid boot signature of 0x09AA in the first two bytes to verify the boot image was copied correctly (at least the first two bytes).

    Refer to the bootloader and programmer resources.

    - http://processors.wiki.ti.com/index.php/C5515_Boot-Image_Programmer#How_to_program_a_boot_image_onto_C5515_EVM

    - Refer to C5515 Schematic checklist - Section 3.20 Bootloader "NOR Boot: NOR Flash must support the Flash reset command (0x00F0 on data) and return to the read array mode afterwards, NOR Flash should support the common flash memory interface (CFI) (not applicable to C5532/33/34/35 or C5545)"

      We ran into this issue with the Intel P30 NOR flash. It does not support the software reset command, and would repeatedly read the status register instead of reading data from the array.

    I checked the SST39VF3201C datasheet and it does not appear to support the reset command. You might just try issueing this command with a test project from CCS to see how the flash responds to the unhandled command.

    See the below code excerpt from the bootloader - the reset command is issued at least three times.

    Have you checked that your application code can run by itself, without any initializtion performed by the GEL file?

    The program should be able to reset all peripherals and initialize the pin mux (EBSR), PLL, EMIF, and any peripheral it needs by itself. Load the program without first running a GEL file from CCS.

    Confirm PLL and EMIF are set as they are in the CSL examples.

    For the programmer - get it from the latest CSL http://www.ti.com/tool/sprc133 

    <INSTALL_PATH>\c55_csl_3.08\utilities\Programmer\c5515

    <INSTALL_PATH>\c55_csl_3.08\ccs_v6.x_examples\programmer

    Lets get this thing debugged.

    Regards,

    Mark

    =-=-=-=-

    // flash "Reset" command
    #define FLASH_RESET_CMD1  0x00F0
    // flash "Autoselect" command
    #define FLASH_AUTOSELECT_CMD1  0x00AA
    #define FLASH_AUTOSELECT_CMD2  0x0055
    #define FLASH_AUTOSELECT_CMD3  0x0090
    //flash program command
    #define FLASH_PROGRAM_CMD1  0x00AA
    #define FLASH_PROGRAM_CMD2  0x0055
    #define FLASH_PROGRAM_CMD3  0x00A0
    
    int flashGetDeviceData(FlashDeviceData_t *Data)
    
    {
    
      Uint16 Tmp1, Tmp2, Tmp3;
    
      Uint16 NumEraseBlockRegions;
    
      Uint16 ReadIndex;
    
      Uint16 Region;
    
      int FlashDeviceIndex;
    
      // flash "Reset" command
    
      ((volatile unsigned short*)NorFlashBaseAddr)[0] = FLASH_RESET_CMD1;
    
      // flash "Autoselect" command
    
      ((volatile unsigned short*)NorFlashBaseAddr)[0x555] = FLASH_AUTOSELECT_CMD1;
    
      ((volatile unsigned short*)NorFlashBaseAddr)[0x2AA] = FLASH_AUTOSELECT_CMD2;
    
      ((volatile unsigned short*)NorFlashBaseAddr)[0x555] = FLASH_AUTOSELECT_CMD3;
    
      // get the manufacturer-id and device-id
    
      Data->MfrId = *(volatile unsigned short *)NorFlashBaseAddr;
    
      Data->DevId[0] = *((volatile unsigned short *)NorFlashBaseAddr + 0x1);
    
      Data->DevId[1] = *((volatile unsigned short *)NorFlashBaseAddr + 0xe);
    
      Data->DevId[2] = *((volatile unsigned short *)NorFlashBaseAddr + 0xf);
    
      // flash "Reset" command
    
      ((volatile unsigned short*)NorFlashBaseAddr)[0] = FLASH_RESET_CMD1;
    
      // flash "CFI Query" command
    
      ((volatile unsigned short*)NorFlashBaseAddr)[0x55] = 0x98;
    
      // verify "QRY"
    
      Tmp1 = ((volatile unsigned short*)NorFlashBaseAddr)[0x10];
    
      Tmp2 = ((volatile unsigned short*)NorFlashBaseAddr)[0x11];
    
      Tmp3 = ((volatile unsigned short*)NorFlashBaseAddr)[0x12];
    
      if ((Tmp1 == 'Q') && (Tmp2 == 'R') && (Tmp3 == 'Y'))
    
      {
    
         // read the number of erase-block regions
    
         NumEraseBlockRegions = ((volatile unsigned short*)NorFlashBaseAddr)[0x2C];
    
         if (NumEraseBlockRegions > FLASH_NUM_SECTOR_MAP_ENTRIES)
    
         {
    
            ((volatile unsigned short*)NorFlashBaseAddr)[0] = FLASH_RESET_CMD1;
    
            return FLASH_STATUS_ERROR;
    
         }
    
         ReadIndex = 0x2D;
    
         for (Region=0; Region<NumEraseBlockRegions; Region++)
    
         {
    
            // read the number of sectors in the region
    
            Tmp1 = ((volatile unsigned short*)NorFlashBaseAddr)[ReadIndex+0];
    
            Tmp2 = ((volatile unsigned short*)NorFlashBaseAddr)[ReadIndex+1];
    
            Data->SectorMap[Region].NumSectors = (Tmp2 << 8) + (Tmp1 & 0xFF) + 1;
    
            // read the size of the sectors in the region (words)
    
            Tmp1 = ((volatile unsigned short*)NorFlashBaseAddr)[ReadIndex+2];
    
            Tmp2 = ((volatile unsigned short*)NorFlashBaseAddr)[ReadIndex+3];
    
            Data->SectorMap[Region].SectorSize = ((Tmp2 << 8) + (Tmp1 & 0xFF)) << 7;
    
            ReadIndex += 4;
    
         }
    
         for (; Region<FLASH_NUM_SECTOR_MAP_ENTRIES; Region++)
    
         {
    
            Data->SectorMap[Region].NumSectors = 0;
    
            Data->SectorMap[Region].SectorSize = 0;
    
         }
    
         // check device-id to find match in table (needed for some top-boot devices)
    
         FlashDeviceIndex = flashGetDeviceIndex(Data); // -1 means not found
    
         if (FlashDeviceIndex >= 0) // if not found, just use data from device
    
         {
    
            // Copy the sector-map data (override needed for some top-boot devices).
    
            // The sector map data is reversed, as read from some top-boot devices.
    
            for (Region=0; Region<FLASH_NUM_SECTOR_MAP_ENTRIES; Region++)
    
            {
    
               Data->SectorMap[Region].NumSectors = FlashDeviceTable[FlashDeviceIndex].SectorMap[Region].NumSectors;
    
               Data->SectorMap[Region].SectorSize = FlashDeviceTable[FlashDeviceIndex].SectorMap[Region].SectorSize;
    
            }
    
         }
    
      }
    
      else
    
      {
    
         // try to find the device in the flash-device-table
    
         Data->SectorMap[0].NumSectors = 0; // set to 0 to indicate no erase-block data
    
         FlashDeviceIndex = flashGetDeviceIndex(Data); // -1 means not found
    
         if (FlashDeviceIndex < 0)
    
         {
    
            ((volatile unsigned short*)NorFlashBaseAddr)[0] = FLASH_RESET_CMD1;
    
            return FLASH_STATUS_ERROR;
    
         }
    
         // copy the sector-map data
    
         for (Region=0; Region<FLASH_NUM_SECTOR_MAP_ENTRIES; Region++)
    
         {
    
            Data->SectorMap[Region].NumSectors = FlashDeviceTable[FlashDeviceIndex].SectorMap[Region].NumSectors;
    
            Data->SectorMap[Region].SectorSize = FlashDeviceTable[FlashDeviceIndex].SectorMap[Region].SectorSize;
    
         }
    
      }
    
      // flash "Reset" command
    
      ((volatile unsigned short*)NorFlashBaseAddr)[0] = FLASH_RESET_CMD1;
    
      return FLASH_STATUS_OK;
    
    }

  • Hi Mark,

    Thanks for the quick reply and I'll go over your info in more detail to see what might be a clue. First, to answer a few of your questions.

    All the boards took the programming via JTAG and CCSv7 using programmer_C5515_eZdsp.out. All boards boot up ok and run the application. Most don't read the NOR properly. I have been using CCS to see what is happening and notice the are reading 0s. I did use the memory browser to take a look at address 0x400000 to see the boot code (starting with 09AA) and on a good board I can see the code. On the bad one, the memory browser only shows 0s all the way to the top of memory from what I quickly scrolled through.

    I was wondering if my EMIF parameters were incorrect, but it looks like they ok looking at the timing diagrams. Any idea what the parameters for the boot code are?

    I'll take a detailed look at your answer and try some more experimentation, but if you have any other thoughts, please fire them my way.

    Cheers.
  • Here is an extra bit if information.

    I have a firmware update option in my code that will read from the SD and writes to the lower part of NOR. It works fine running independently without CCS both before and after the update. Obviously the code is successfully writing to NOR but when it gets to other parts of the code where it is suppose to read, it doesn't. Hmmm.

    Oh, and I did check and the NOR is CFI compliant and has a 0x0F reset. They just call it a CFI Exit but the text says it does a reset as well. 

  • Well it sounds like you are close to having the flash working.

    I stand corrected about the Microchip NOR flash not supporting the "0xF0" reset command. They just call it the "Software ID Exis/CFI Exit/Sec ID Exit" command.

    See Table 7 Software Command Sequence of the datasheet.

    Maybe try giving one of those commands to the flash to kick it back into read data mode.

    Can you probe the signals? Make sure the right CS is going low for boot, SD reprogram, and read. Compare reading during boot with reading during your application.

    The bootloader uses the below EMIF reg settings.

    =-=-

    /********************************************************************* 
    * EMIF Registers (0x1000 - 0x10DD)
    **********************************************************************/
    #define IOPORT_REG_EMIF_ASYNC_WAIT_0         (IOPORT_REGISTER(0x1004))
    #define IOPORT_REG_EMIF_ASYNC_WAIT_1         (IOPORT_REGISTER(0x1005))
    #define IOPORT_REG_EMIF_ASYNC1_CONFIG_0      (IOPORT_REGISTER(0x1010))
    #define IOPORT_REG_EMIF_ASYNC1_CONFIG_1      (IOPORT_REGISTER(0x1011))
    #define IOPORT_REG_EMIF_ASYNC2_CONFIG_0      (IOPORT_REGISTER(0x1014))
    #define IOPORT_REG_EMIF_ASYNC2_CONFIG_1      (IOPORT_REGISTER(0x1015))
    #define IOPORT_REG_EMIF_ASYNC3_CONFIG_0      (IOPORT_REGISTER(0x1018))
    #define IOPORT_REG_EMIF_ASYNC3_CONFIG_1      (IOPORT_REGISTER(0x1019))
    #define IOPORT_REG_EMIF_ASYNC4_CONFIG_0      (IOPORT_REGISTER(0x101C))
    #define IOPORT_REG_EMIF_ASYNC4_CONFIG_1      (IOPORT_REGISTER(0x101D))
    #define IOPORT_REG_EMIF_NAND_CTRL            (IOPORT_REGISTER(0x1060))
    #define IOPORT_REG_EMIF_NAND_STATUS          (IOPORT_REGISTER(0x1064))
    
    
    int nor_flash_init(Uint16 ChipSelect)
    {
       /* Access EMIF registers as 16-bit registers */
       IOPORT_REG_EMIF_CNTL = 0x0000;
    
    	/* Configure ASYNC Wait config Registers */
       IOPORT_REG_EMIF_ASYNC_WAIT_0 = 0x0080; // max_ext_wait = 0x80
       IOPORT_REG_EMIF_ASYNC_WAIT_1 = 0x00E4; // wp(all) = 0
    
       /* Not using NAND here */
       IOPORT_REG_EMIF_NAND_CTRL = 0x0000;
    
    	/* Configure as 16-bit data bus */
       IOPORT_REG_EMIF_ASYNC1_CONFIG_0 = 0xFFFD;
       IOPORT_REG_EMIF_ASYNC1_CONFIG_1 = 0x3FFF;
       IOPORT_REG_EMIF_ASYNC2_CONFIG_0 = 0xFFFD;
       IOPORT_REG_EMIF_ASYNC2_CONFIG_1 = 0x3FFF;
       IOPORT_REG_EMIF_ASYNC3_CONFIG_0 = 0xFFFD;
       IOPORT_REG_EMIF_ASYNC3_CONFIG_1 = 0x3FFF;
       IOPORT_REG_EMIF_ASYNC4_CONFIG_0 = 0xFFFD;
       IOPORT_REG_EMIF_ASYNC4_CONFIG_1 = 0x3FFF;
       if (ChipSelect > NOR_FLASH_CS5)
          return 1;
       NorFlashBaseAddr = NorFlashBaseAddrTable[ChipSelect];
    
       flashReset();
    	return 0;
    }
    

    Regards,
    Mark

  • Ok, some progress. I haven't probed the CS yet (all the other lines are buried) but I did find only one difference in the EMIF settings that did make a difference. All the suggested settings are at the max and mine were originally copied from some demo code, so they were all the at the max too. The only difference was the ewMode which I had at 1 and the bootloader has at 0. After changing this, I could read the memory in the emulator. I think I may now have a slight issue with writing because I followed a write to the NOR and every other word is missing. This may be because there is not extended wait delay and I may need to improve my busy monitoring. So, it would be nice to have extended wait working, but I guess there are ways around it. Any idea what the problem might be?

    Thanks Mark. At least at this point I feel a little better :)
  • Found my answer in the NOR datasheet. It requires a pull up on the Ready/Busy# line.

    I guess we may be good to go. Hopefully no more surprises. Thanks Mark, you really helped getting me looking in the right spot.
  • Cam,

    That's great to hear. Thanks for sharing your solution on the E2E.

    Regards,
    Mark