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/TMS320C6678: Nand boot problem at the IBL with nand device change

Part Number: TMS320C6678

Tool/software: Code Composer Studio

Hi.

We develop and use boards with TMS320C6678.
However, there was a problem with board modification due to discontinuation of NAND flash.

Previous NAND flash used NAND512R3A2SZA6E and now used MT29F1G08ABCHC on the board.

The development environment is as follows.
MCSDK 2.1.2.6
PDK 1.1.2.6
CCS 8.3

NAND flash device was changed, NANDWriter and platform_lib were modified, write and read was successful.

However, it does not become a NAND boot using the IBL that was previously used.
If the NAND flash device is changed, is there anything to be modified in the IBL?
Give me some advice.

  • ForLee,

    This device as you have implemented support NAND boot only by using a user defined intermediate bootloader (IBL). When you modified platform library and NAND Writer to support the NAND geometry for the new flash you have used, did you also make or rebuild the IBL for the device? The changes made to the platform library will not be picked up by the IBL without rebuilding the IBL and reflashing it to the custom board. Can you please indicate the changes that you have made to the platform library. At the minimum, you need to update evmc66x_nand.h to reflect the NAND geometry and check the instruction set matches. 

    Also, when the NAND boot is failing, are you able to connect to the DSP and check where the Program counter(PC) is executing. By correlating the PC with IBL map file, you can see where the IBL hangs.  The NAND geometry in the new Micron flash seems very different from previous Numonyx NAND so the changes need to be incorporated in the IBL. The other thing to check would be the ECC requirements and the read instruction for the NAND and to check if it matches with the IBL implementation.

    Regards,

    Rahul

  • Thank you for your answer.

    As a result of testing after changing NAND flash, the NAND-Flash related file was modified on platform_lib because it did not run on the NAND writer.

    The modified file is as follows.
    The evmc66x_nand.h and evm66x_nand.c, platform.c files were modified.
    After modification, the platform_lib was built and the NAND writer was built. (Modify start_adrs = 131072)
    The file concerned is as shown in the attachment.

    5672.evmc66x_nand.h

    /******************************************************************************
     * Copyright (c) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
     * 
     *  Redistribution and use in source and binary forms, with or without 
     *  modification, are permitted provided that the following conditions 
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright 
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the 
     *    documentation and/or other materials provided with the   
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     *****************************************************************************/
    
    /******************************************************************************
     *
     * File	Name:       evm66x_nand.c
     *
     * Description: This contains   TMS320C6678 specific nand functions.
     * 
     * 
     ******************************************************************************/
    #include "platform_internal.h"
    
    #if (PLATFORM_NAND_IN)
    
    /************************
     * Include Files
     ************************/
    
    /************************
     * Globals
     ************************/
    
    /************************
     * Defines and Macros
     ************************/
    
    #pragma DATA_SECTION(nandPageBuf,"platform_lib");
    static uint8_t nandPageBuf[BYTES_PER_PAGE + SPARE_BYTES_PER_PAGE];
    
     /************************
      * Globals
      ************************/
    
    /******************************************************************************
     *
     * Function:    NandCmdSet
     *
     * Description: This function is used to indicates command cycle occurring,
     *              and to send command to NAND device
     *
     * Parameters:  uint32_t cmd - Command to NAND
     *
     * Return Value: None
     *
     *****************************************************************************/
    static void NandCmdSet(uint32_t cmd)
    {
        /* 8-bit NAND */
        uint8_t *cle_addr  = (uint8_t *) NAND_CMD_ADDR;
    
        *cle_addr = cmd;
    }
    
    /******************************************************************************
     *
     * Function:    NandAleSet
     *
     * Description: This function is used to indicates Address cycle occurring,
     *              and to send address value to NAND device
     *
     * Parameters:  uint32_t addr - Address to NAND
     *
     * Return Value: None
     *
     *****************************************************************************/
    static void NandAleSet(uint32_t addr)
    {
          /* 8-bit NAND */
          uint8_t *ale_addr  = (uint8_t *) NAND_ALE_ADDR;
    
          *ale_addr = addr;
    
          return;
    }
    
    
    /******************************************************************************
      *
      * Function:    NandWaitRdy
      *
      * Description: This function waits for the NAND status to be ready
      *
      * Parameters:  uint32_t in_timeout - time out value in micro seconds
      *
      * Return Value: Failure if Ready Pin is not high for prescribed time
      *
      *****************************************************************************/
     static uint32_t NandWaitRdy(uint32_t in_timeout)
     {
         uint32_t count = 0;
    
         do {
            platform_delay(1);
    
            if ((CSL_FEXT(hEmif16Cfg->NANDFSR, EMIF16_NANDFSR_WAITSTAT) & 1) == 1) {
                break;
            }
            count ++;        
         } while (count < in_timeout);
    
         if (count >= in_timeout) 
            return FAIL;
         else
            return SUCCESS;
     }
     
    
    
    #if (PLATFORM_NAND_READ_IN | PLATFORM_NAND_WRITE_IN)
    
    /* Read raw ECC code after writing to NAND. */
    static void
    NandRead4bitECC
    (
        uint32_t    *code
    )
    {
        uint32_t    mask = 0x03ff03ff;
    
        code[0] = hEmif16Cfg->NANDF4BECC1R & mask;
        code[1] = hEmif16Cfg->NANDF4BECC2R & mask;
        code[2] = hEmif16Cfg->NANDF4BECC3R & mask;
        code[3] = hEmif16Cfg->NANDF4BECC4R & mask;
    }
    
    
    static void
    NandCalculate4bitECC
    (
        uint32_t    read,
        uint8_t     *ecc_code
    )
    {
        uint32_t i, raw_ecc[4], *p;
    
       /* After a read, terminate ECC calculation by a dummy read
        * of some 4-bit ECC register.  ECC covers everything that
        * was read; correct() just uses the hardware state, so
        * ecc_code is not needed.
        */
        if (read)
        {
            i = hEmif16Cfg->NANDF4BECC1R;
            return;
        }
    
       /* Pack eight raw 10-bit ecc values into ten bytes, making
        * two passes which each convert four values (in upper and
        * lower halves of two 32-bit words) into five bytes.  The
        * ROM boot loader uses this same packing scheme.
        */
        NandRead4bitECC(raw_ecc);
        for (i = 0, p = raw_ecc; i < 2; i++, p += 2) {
            *ecc_code++ =   p[0]        & 0xff;
            *ecc_code++ = ((p[0] >>  8) & 0x03) | ((p[0] >> 14) & 0xfc);
            *ecc_code++ = ((p[0] >> 22) & 0x0f) | ((p[1] <<  4) & 0xf0);
            *ecc_code++ = ((p[1] >>  4) & 0x3f) | ((p[1] >> 10) & 0xc0);
            *ecc_code++ =  (p[1] >> 18) & 0xff;
        }
    
         return;
    }
    
    /* Correct up to 4 bits in data we just read, using state left in the
    * hardware plus the ecc_code computed when it was first written.
    */
    static int32_t
    NandCorrect4bitECC
    (
        uint8_t     *data,
        uint8_t     *ecc_code
    )
    {
        int32_t     i;
        uint16_t    ecc10[8];
        uint16_t    *ecc16;
        uint32_t    syndrome[4];
        uint32_t    num_errors, corrected;
    
        /* All bytes 0xff?  It's an erased page; ignore its ECC. */
        for (i = 0; i < 10; i++) {
            if (ecc_code[i] != 0xff)
                goto compare;
        }
        return 0;
    
    compare:
    /* Unpack ten bytes into eight 10 bit values.  We know we're
    * little-endian, and use type punning for less shifting/masking.
        */
        ecc16 = (uint16_t *)ecc_code;
    
        ecc10[0] =  (ecc16[0] >>  0) & 0x3ff;
        ecc10[1] = ((ecc16[0] >> 10) & 0x3f) | ((ecc16[1] << 6) & 0x3c0);
        ecc10[2] =  (ecc16[1] >>  4) & 0x3ff;
        ecc10[3] = ((ecc16[1] >> 14) & 0x3)  | ((ecc16[2] << 2) & 0x3fc);
        ecc10[4] =  (ecc16[2] >>  8)         | ((ecc16[3] << 8) & 0x300);
        ecc10[5] =  (ecc16[3] >>  2) & 0x3ff;
        ecc10[6] = ((ecc16[3] >> 12) & 0xf)  | ((ecc16[4] << 4) & 0x3f0);
        ecc10[7] =  (ecc16[4] >>  6) & 0x3ff;
    
        /* Tell ECC controller about the expected ECC codes. */
        for (i = 7; i >= 0; i--)
        {
            hEmif16Cfg->NANDF4BECCLR = ecc10[i];
        }
    
            /* Allow time for syndrome calculation ... then read it.
            * A syndrome of all zeroes 0 means no detected errors.
        */
        i = hEmif16Cfg->NANDFSR;
        NandRead4bitECC(syndrome);
        if (!(syndrome[0] | syndrome[1] | syndrome[2] | syndrome[3]))
            return 0;
    
            /*
            * Clear any previous address calculation by doing a dummy read of an
            * error address register.
        */
        i = hEmif16Cfg->NANDFEA1R;
    
        /* Start address calculation, and wait for it to complete.
        * We _could_ start reading more data while this is working,
        * to speed up the overall page read.
        */
        CSL_FINS(hEmif16Cfg->NANDFCTL, EMIF16_NANDFCTL_ADDR_CALC_ST, 1);
        for (;;) {
            uint32_t    fsr = hEmif16Cfg->NANDFSR;
    
            switch ((fsr >> 8) & 0x0f) {
            case 0:     /* no error, should not happen */
                i = hEmif16Cfg->NANDFEV1R;
                return 0;
            case 1:     /* five or more errors detected */
                i = hEmif16Cfg->NANDFEV1R;
                return -1;
            case 2:     /* error addresses computed */
            case 3:
                num_errors = 1 + ((fsr >> 16) & 0x03);
                goto correct;
            default:    /* still working on it */
                platform_delay(5);
                continue;
            }
        }
    
    correct:
        /* correct each error */
        for (i = 0, corrected = 0; i < num_errors; i++) {
            int error_address, error_value;
    
            if (i > 1) {
                error_address = hEmif16Cfg->NANDFEA2R;
                error_value = hEmif16Cfg->NANDFEV2R;;
            } else {
                error_address = hEmif16Cfg->NANDFEA1R;
                error_value = hEmif16Cfg->NANDFEV1R;
            }
    
            if (i & 1) {
                error_address >>= 16;
                error_value >>= 16;
            }
            error_address &= 0x3ff;
            error_address = (512 + 7) - error_address;
    
            if (error_address < 512) {
                data[error_address] ^= error_value;
                corrected++;
            }
        }
    
        return corrected;
    }
    
     /******************************************************************************
      *
      * Function:    NandReadDataByte
      *
      * Description: This function is used to read Nand data byte
      *
      * Parameters:  uint8_t* puchValue - Pointer to data buffer
      *
      * Return Value: None
      *
      *****************************************************************************/
    static void NandReadDataByte(uint8_t* puchValue)
     {
        /*8-bit NAND*/
        uint8_t *data_addr  = (uint8_t *) NAND_DATA_ADDR;
    
        *puchValue = *data_addr;
     }
    
     /******************************************************************************
      * 
      * Function:    NandReadDataBytes
      *
      * Description: This function is used to read data bytes from the NAND device
      *
      * Parameters:  uiNumBytes - Number of bytes to be read
      *              pBuffer - Data buffer
      *
      * Return Value: Error/Success codes
      *
      *****************************************************************************/
     static uint32_t NandReadDataBytes(uint32_t uiNumBytes, uint8_t *pBuffer)
     {
         uint32_t i;
    
         /* 8-bit NAND */
         for (i = 0; i < uiNumBytes; i++)
         {
             /* NANDRead done directly without checking for nand width */
             NandReadDataByte((uint8_t *)pBuffer);
             pBuffer++;
         }
         return SUCCESS;
     }
    
     /******************************************************************************
      * 
      * Function:    NandReadSpareArea
      *
      * Description: Function to read Nand spare area
      *
      * Parameters:  uiBlkAddr - Block Address
      *              uiPage - Page Number
      *              pBuffer - Data Buffer
      *
      * Return Value: Error/Success codes
      *
      *****************************************************************************/
     uint32_t NandReadSpareArea(PLATFORM_DEVICE_info *p_device, uint32_t uiBlkAddr, uint32_t uiPage, uint8_t *pBuffer)
     {
         uint32_t uiAddr, ret_val = SUCCESS;
         uint32_t uiColumn;
         uint8_t status;
    
    
         /* Read the data to the destination buffer and detect error */
         //uiColumn = p_device->column;
         uiColumn = 2048;
         /* Send 0x50h command to read the spare area */
         NandCmdSet(NAND_PAGE_READ); // First cycle send 0
         platform_delay(10);
    
         /*
          * Send address of the block + page to be read
          * Address cycles = 4, Block shift = 22, Page Shift = 16, Bigblock = 0
          */
         uiAddr = PACK_ADDR(uiColumn, uiPage, uiBlkAddr);
         NandAleSet((uiAddr >>  0u) & 0xFF);   // CA0-CA7  1st Cycle;  column addr
         NandAleSet((uiAddr >>  8u) & 0x0F);   // CA8-CA11and Upper Nibble Low 2nd Cycle;  colum  addr
         NandAleSet((uiAddr >> 16u) & 0xFF);   // // PA0-PA5 and BA9 -BA8 3rd Cycle;Page addr & Block addr
         NandAleSet((uiAddr >> 24u) & 0xFF);    // BA0 to BA7  4th Cycle;  Plane addr
    
         NandCmdSet(0x30); // Last  cycle send 30h command
         platform_delay(EMIF16_WAIT_PIN_POLL_ST_DLY);
    
         // Wait for Ready Busy Pin to go HIGH
         ret_val = NandWaitRdy(EMIF16_NAND_PROG_TIMEOUT);
    
         if (ret_val != SUCCESS) {
        	platform_errno = PLATFORM_ERRNO_DEV_BUSY;
     		IFPRINT(platform_write("NandReadSpareArea: Device timeout.\n"));
            return FAIL;
         }
    
         /* Read the data to the destination buffer and detect error */
         NandReadDataBytes(p_device->spare_size, pBuffer);
    
    
         NandCmdSet(NAND_STATUS);
         platform_delay(10);
         NandReadDataByte(&status);
    
         if ((status & 0x01) == 1) {
            /* if SR0 bit is set to 1, there is Error - operation failed */
         	platform_errno = PLATFORM_ERRNO_DEV_FAIL;
    		IFPRINT(platform_write("NandReadSpareArea: Status (0x%x) has error bit set.\n", status));
            return FAIL;
         }
    
         return SUCCESS;
     }
    #endif
    
    
     /******************************************************************************
      *
      * Function:    readNandPage
      *
      * Description: This function reads a page from NAND flash and detects and
      *              corrects the bit errors if ECC is enabled
      *
      * Parameters:  NAND_ADDR address - Block Address/Page address of NAND flash
      *              uint8_t* puchBuffer - Pointer to buffer
      *
      * Return Value: status
      *
      * Assumptions: puchBuffer points to a 2KB buffer
      *
      ******************************************************************************/
    #if (PLATFORM_NAND_READ_IN)
     uint32_t readNandPage(PLATFORM_DEVICE_info *p_device, NAND_ADDR address, uint8_t* puchBuffer)
     {
         int32_t i = 0;
         uint8_t *puchSpareAreaBuf;
         uint8_t *pBuffer_loc;
         uint32_t uiAddr;
         uint32_t ret_val = SUCCESS;
    //     uint8_t  status;
         int32_t iIteration;
         int32_t byte_count = 0;
         /* ECC locations for the micron nand device */
         uint8_t   eccLoc[4*NAND_MAX_NUM_ECC_BYTES] = { 7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
         	 	 	 	 	 	 	 	 	 	 	 	17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
         	 	 	 	 	 	 	 	 	 	 	 	27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
         	 	 	 	 	 	 	 	 	 	 	 	37, 38, 39, 40, 41, 42, 43, 44, 45, 46
         	 	 	 	 	 	 	 	 	 	 	   };
         uint8_t   eccCalc[4*NAND_MAX_NUM_ECC_BYTES];
         uint8_t   eccCode[4*NAND_MAX_NUM_ECC_BYTES];
         if(puchBuffer == NULL)
             return NULL_POINTER_ERROR;
    
         pBuffer_loc = nandPageBuf;
         puchSpareAreaBuf = nandPageBuf + BYTES_PER_PAGE;
         if (NandReadSpareArea(p_device, address.uiBlockAddr, address.uiPageAddr, puchSpareAreaBuf) != SUCCESS)
        	 return FAIL;
          platform_delay(10);
    
          /*
           * Send address of the block + page to be read
           * Address cycles = 4, Block shift = 14, Page Shift = 9, Bigblock = 0
           */
         for (iIteration = 0; iIteration < 4; iIteration++) {
    
          uiAddr = PACK_ADDR(byte_count, address.uiPageAddr, address.uiBlockAddr);
    
     /***********************READ A Command***************************************/
          NandCmdSet(NAND_PAGE_READ); // First cycle send 0
          platform_delay(10);
    
          NandAleSet((uiAddr >>  0u) & 0xFF);   // CA0-CA7  1st Cycle;  column addr
          NandAleSet((uiAddr >>  8u) & 0x0F);   // CA8-CA11 and Upper Nibble Low 2nd Cycle;  colum  addr
          NandAleSet((uiAddr >> 16u) & 0xFF);   // PA0-PA5 and BA9 -BA8 3rd Cycle;Page addr & Block addr
          NandAleSet((uiAddr >> 24u) & 0xFF);    // BA7 to BA0  4th Cycle;  Block addr
    
          NandCmdSet(0x30); // Last cycle send 30h command
    	  platform_delay(EMIF16_WAIT_PIN_POLL_ST_DLY);
    
          /* Wait for Ready Busy Pin to go HIGH  */
          ret_val = NandWaitRdy(EMIF16_NAND_PROG_TIMEOUT);
    
          if (ret_val != SUCCESS) {
        	  platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
        	  return FAIL;
          }
    
         /* Start 4-bit ECC HW calculation for read */
         CSL_FINS(hEmif16Cfg->NANDFCTL, EMIF16_NANDFCTL_4BIT_ECC_ST , 1);
    
          /* Read the data to the destination buffer and detect error */
          NandReadDataBytes(512, pBuffer_loc);
          platform_delay(10);
    
         /* Calculate the 4-bit ECC bytes for read */
         NandCalculate4bitECC(TRUE, &eccCalc[iIteration*10]);
    
         CSL_FINS(hEmif16Cfg->NANDFCTL, EMIF16_NANDFCTL_4BIT_ECC_ST , 0);
    
    	for (i = 0; i < NAND_MAX_NUM_ECC_BYTES; i++)
    	 {
    		  eccCode[(iIteration * 10) + i] = puchSpareAreaBuf[eccLoc[(iIteration * 10) + i]];
    	 }
    
         if (NandCorrect4bitECC(pBuffer_loc, &eccCode[iIteration * 10]) < 0)
    	 {
    		return FAIL;
    	 }
         pBuffer_loc += 512;
         byte_count += 512;
    
         }
        memcpy(puchBuffer, nandPageBuf, gDeviceNand.page_size);
    
        return SUCCESS;
    }
    #endif
    
     /******************************************************************************
      *
      * Function:    NandWriteDataBytes
      *
      * Description: This function is used to write data bytes to the NAND device
      *
      * Parameters:  uiNumBytes - Number of bytes to be written
      *              pBuffer - Data buffer
      *
      * Return Value: Error/Success codes
      *
      *****************************************************************************/
    
    #if (PLATFORM_NAND_WRITE_IN)
     static void NandWriteDataByte(uint8_t uchData)
     {
         volatile uint8_t* dest;
    
         /* Data is written to the data register on the rising edge of WE# when
              � CE#, CLE, and ALE are LOW, and
              � the device is not busy. */
         dest = (volatile uint8_t *)(NAND_DATA_ADDR);
         *dest = uchData;
     }
    
    uint32_t NandWriteDataBytes(PLATFORM_DEVICE_info *p_device, uint32_t uiNumBytes, uint8_t *pBuffer)
     {
         uint32_t i;
    
         /* Starting the ECC in the NANDFCR register for CS2(bit no.8)
            Read ECC to Clear Before Starting */
         if (p_device->width == 8)
         {
             /* 8-bit NAND */
             for (i = 0; i < uiNumBytes; i++)
             {
                 /* NAND Write done directly without checking for nand width */
                 NandWriteDataByte( (uint8_t) *pBuffer );
                 pBuffer++;
             }
         }
         return SUCCESS;
     }
    #endif
    
     /******************************************************************************
      *
      * Function:    writeNandPage
      *
      * Description: This function a page to NAND flash. It computes ECC and
      *              and writes it to spare area if ECC is enabled
      *
      * Parameters:  NAND_ADDR address - Block Address/Page address of NAND flash
      *              uint8_t* puchBuffer - Pointer to buffer
      *
      * Return Value: status
      *
      * Assumptions: puchBuffer points to a 2KB buffer
      *
      ******************************************************************************/
    #if (PLATFORM_NAND_WRITE_IN)
     uint32_t  writeNandPage(PLATFORM_DEVICE_info *p_device, NAND_ADDR address, uint8_t* puchBuffer)
     {
         int32_t iErrors = SUCCESS;
         int32_t i = 0;
         int32_t iIteration;
         uint8_t puchSpareAreaBuf[SPARE_BYTES_PER_PAGE];
         uint8_t *pBuffer_loc;
         uint32_t addr;
         uint32_t ret_val = SUCCESS;
         uint8_t  status;
         int32_t byte_count = 0;
    
         /* ECC locations for the Numonyx nand device */
         uint8_t   eccLoc[4*NAND_MAX_NUM_ECC_BYTES] = { 7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
         	 	 	 	 	 	 	 	 	 	 	 	17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
         	 	 	 	 	 	 	 	 	 	 	 	27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
         	 	 	 	 	 	 	 	 	 	 	 	37, 38, 39, 40, 41, 42, 43, 44, 45, 46
         	 	 	 	 	 	 	 	 	 	 	   };
         uint8_t   eccCalc[4*NAND_MAX_NUM_ECC_BYTES];
    
         /* Init the buffer by reading the existing values in the spare area */
        iErrors = NandReadSpareArea(p_device, address.uiBlockAddr, address.uiPageAddr, puchSpareAreaBuf);
        if(iErrors != SUCCESS)
        {
            return iErrors;
        }
    
         for (iIteration = 0; iIteration < 4; iIteration++) {
    
         NandCmdSet(NAND_PROG_PAGE);
         platform_delay(10);
    
        	 /*
    		  * Send address of the block + page to be read
    		  * Address cycles = 4, Block shift = 22, Page Shift = 16, Bigblock = 0
    		  */
    		 addr = PACK_ADDR(byte_count, address.uiPageAddr, address.uiBlockAddr);
    
    		 NandAleSet((addr >>  0u) & 0xFF);   // CA0-CA7  1st Cycle;  column addr
    		 NandAleSet((addr >>  8u) & 0x0F);   // CA8-CA11and Upper Nibble Low 2nd Cycle;  colum  addr
    		 NandAleSet((addr >> 16u) & 0xFF);   // PA0-PA5 and BA9 -BA8 3rd Cycle;Page addr & Block addr
    		 NandAleSet((addr >> 24u) & 0xFF);    // BA-7 to BA0  4th Cycle;  Plane addr
    
         platform_delay (EMIF16_WAIT_PIN_POLL_ST_DLY);
    
         /* Start 4-bit ECC HW calculation for write */
         CSL_FINS(hEmif16Cfg->NANDFCTL, EMIF16_NANDFCTL_4BIT_ECC_ST , 1);
         platform_delay (10);
    
    		 /* Write the data */
    		 pBuffer_loc = puchBuffer;
    		 NandWriteDataBytes(p_device, 512, pBuffer_loc);
    
         platform_delay (10);
    
    		 /* Calculate the 4-bit ECC bytes for write */
    		 NandCalculate4bitECC(FALSE, &eccCalc[iIteration * 10]);
    
    		/* Update the calculated ECC bytes to spare area data */
    		for (i = 0; i < NAND_MAX_NUM_ECC_BYTES; i++)
    		{
    			puchSpareAreaBuf[eccLoc[(iIteration*10) + i]] = eccCalc[(iIteration * 10) + i];
    		}
    
    		byte_count += 512;
    		puchBuffer += 512;
    
         /* Wait for Ready Busy Pin to go HIGH  */
         NandCmdSet(NAND_CMD_10H);
    
         platform_delay(EMIF16_WAIT_PIN_POLL_ST_DLY);
    
         ret_val = NandWaitRdy(EMIF16_NAND_PROG_TIMEOUT*50);
    
         if (ret_val != SUCCESS) {
        	 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
        	 return FAIL;
         }
    
         NandCmdSet(NAND_STATUS);
         platform_delay(10);
    
         NandReadDataByte(&status);
    
    		 if ((status & 0x01) == 1) {
    			 /* if SR0 bit is set to 1, there is Error - operation failed */
    			 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
    			 return FAIL;
    		 }
         }
    
    	if (NandWriteSpareArea (p_device, address.uiBlockAddr, address.uiPageAddr, puchSpareAreaBuf) != SUCCESS)
    		return FAIL;
    
        return SUCCESS;
     }
    #endif
     
     /******************************************************************************
      * 
     * Function:    NandWriteSpareArea
     *
     * Description: Function to write a spare area of the NAND
     *
     * Parameters:  uiBlkAddr - Block Address
     *              uiPage - Page Number
     *              pBuffer - Data Buffer
     *
     * Return Value: Error/Success codes
     *
     *****************************************************************************/
    #if (PLATFORM_NAND_WRITE_IN)
    uint32_t NandWriteSpareArea (PLATFORM_DEVICE_info *p_device, uint32_t uiBlkAddr, uint32_t uiPage, uint8_t *pBuffer)
    {
        uint32_t addr;
        uint32_t ret_val = SUCCESS;
        uint8_t  status;
        uint8_t *pBuffer_loc;
        uint32_t uiColumn;
     
        /* Read the data to the destination buffer and detect error */
        uiColumn = p_device->column;
     
        /* Spare Area*/
        /*NandCmdSet(NAND_PAGE_READ);
        platform_delay(20);*/
        NandCmdSet(NAND_PROG_PAGE);
        platform_delay(10);
     
        /*
         * Send address of the block + page to be read
         * Address cycles = 4, Block shift = 22, Page Shift = 16, Bigblock = 0
         */
        addr = PACK_ADDR(uiColumn, uiPage, uiBlkAddr);
    
        NandAleSet((addr >>  0u) & 0xFF);   // CA0-CA7  1st Cycle;  column addr
        NandAleSet((addr >>  8u) & 0x0F);   // CA8-CA11and Upper Nibble Low 2nd Cycle;  colum  addr
        NandAleSet((addr >> 16u) & 0xFF);   // PA0-PA5 and BA9 -BA8 3rd Cycle;Page addr & Block addr
        NandAleSet((addr >> 24u) & 0xFF);    // BA-7 to BA0  4th Cycle;  Plane addr
    
        platform_delay (EMIF16_WAIT_PIN_POLL_ST_DLY);
     
        /* Write the data */
        pBuffer_loc = pBuffer;
        NandWriteDataBytes(p_device, p_device->spare_size, (uint8_t *)pBuffer_loc);
     
        /* Wait for Ready Busy Pin to go HIGH  */
        NandCmdSet(NAND_CMD_10H);
     
        platform_delay(EMIF16_WAIT_PIN_POLL_ST_DLY);
     
        ret_val = NandWaitRdy(EMIF16_NAND_PROG_TIMEOUT*50);
     
        if (ret_val != SUCCESS) {
        	platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
        	return FAIL;
        }
     
        NandCmdSet(NAND_STATUS);
        platform_delay(10);
     
        NandReadDataByte(&status);
     
        if ((status & 0x01) == 1) {
        	/* if SR0 bit is set to 1, there is Error - operation failed */
         	platform_errno = PLATFORM_ERRNO_DEV_FAIL;
        	return FAIL;
        }
    
        return SUCCESS;
    }
    #endif
     
     /******************************************************************************
      * 
      * Function:    nandFlashBlockErase  
      *
      * Description: This function erases the specified block of NAND flash 
      *
      * Parameters:  NAND_ADDR address - Block Address of NAND flash
      * 
      * Return Value: status
      * 
      *****************************************************************************/ 
    #if (PLATFORM_NAND_WRITE_IN)
     uint32_t nandFlashBlockErase(PLATFORM_DEVICE_info *p_device, uint32_t uiBlockNumber)
     {
         uint32_t addr = 0, ret_val = SUCCESS;
         uint8_t  status;
    
         NandCmdSet(NAND_BLOCK_ERASE); // Block erase command
         platform_delay(25);
    
         /*
          * Send address of the block + page to be read
          * Address cycles = 2, Block shift = 22, Page shiht = 16
          */
         addr = PACK_ADDR(0x0, 0x0, uiBlockNumber);
    
         /* Properly adjust the shifts to match to the data sheet */
    
         NandAleSet((addr >> 16u) & 0xC0);   // A17-A24 3rd Cycle; Block addr
         platform_delay(25);
         NandAleSet((addr >> 24u) & 0xFF);    // A25-A26  4th Cycle;  Plane addr
         platform_delay(1000);
    
         NandCmdSet(NAND_ERASE_CONFIRM); // Erase confirm
         platform_delay(EMIF16_WAIT_PIN_POLL_ST_DLY);
    
         /* Wait for erase operation to finish: 2msec  */
         ret_val = NandWaitRdy(EMIF16_NAND_BLOCK_ERASE_TIMEOUT);
    
         if (ret_val != SUCCESS) {
            platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
             return FAIL;
         }
    
         NandCmdSet(NAND_STATUS);
         platform_delay(10);
    
         NandReadDataByte(&status);
         
         if ((status & 0x01) == 1) {
        	 /* if SR0 bit is set to 1, there is Error - operation failed */
        	 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
        	 return FAIL;
         }
         
         return SUCCESS;
    
     }
    #endif
    
     /******************************************************************************
      * 
      * Function:    NandConfig  
      *
      * Description: This function is used to congigure the NAND Device  
      *
      * Parameters:  None
      * 
      * Return Value: Err Status
      * 
      *****************************************************************************/
    static uint32_t NandConfig (void)
     {
    
          /* Config nand FCR reg. 8 bit NAND, 4-bit HW ECC */
         hEmif16Cfg->A0CR = (0                                         \
             | (0 << 31)     /* selectStrobe */ \
             | (0 << 30)     /* extWait (never with NAND) */ \
             | (0xf << 26)   /* writeSetup  10 ns */ \
             | (0x3f << 20)  /* writeStrobe 40 ns */ \
             | (7 << 17)     /* writeHold   10 ns */ \
             | (0xf << 13)   /* readSetup   10 ns */ \
             | (0x3f << 7)   /* readStrobe  60 ns */ \
             | (7 << 4)      /* readHold    10 ns */ \
             | (3 << 2)      /* turnAround  40 ns */ \
             | (0 << 0));   /* asyncSize   8-bit bus */ \
    
    
    
         CSL_FINS(hEmif16Cfg->NANDFCTL, EMIF16_NANDFCTL_CE0NAND , CSL_EMIF16_NANDFCTL_CE0NAND_ENABLE);
         CSL_FINS(hEmif16Cfg->NANDFCTL, EMIF16_NANDFCTL_4BIT_ECC_SEL , CSL_EMIF16_NANDFCTL_4BIT_ECC_SEL_RESETVAL);
    
         /* Set the wait polarity */
         hEmif16Cfg->AWCCR = (0x80            /* max extended wait cycle */ \
             | (0 << 16)     /* CS2 uses WAIT0 */    \
             | (0 << 28));  /* WAIT0 polarity low */ \
    
         /*
         Wait Rise.
         Set to 1 by hardware to indicate rising edge on the
         corresponding WAIT pin has been detected.
         The WP0-3 bits in the Async Wait Cycle Config register have
         no effect on these bits.
         */
    
         /*
         Asynchronous Timeout.
         Set to 1 by hardware to indicate that during an extended
         asynchronous memory access cycle, the WAIT signal did not
         go inactive within the number of cycles defined by the
         MAX_EXT_WAIT field in Async Wait Cycle Config register.
         */
    
         hEmif16Cfg->IRR = (1                      /* clear async timeout */ \
             | (1 << 2));   /* clear wait rise */ \
    
         return SUCCESS;
     }
     
     /******************************************************************************
      * 
      * Function:    NandOpenDevice  
      *
      * Description: This function is used to open the NAND device and configure it  
      *
      * Parameters:  None
      * 
      * Return Value: Error/Success codes
      * 
      *****************************************************************************/      
     static uint32_t NandOpenDevice(void)
     {
         uint8_t  status;
    
         /* Initialize NAND interface */
         if (NandConfig() != SUCCESS) {
        	IFPRINT(platform_write("NandOpenDevice ... could not initialize the Nand Interface. \n"));
         	return FAIL;
         }
    
         /* Send reset command to NAND */
         NandCmdSet(NAND_RST);
         platform_delay (EMIF16_WAIT_PIN_POLL_ST_DLY);
             
         if (NandWaitRdy(EMIF16_NAND_RESET_TIMEOUT) != SUCCESS) {
         	platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
        	IFPRINT(platform_write("NandOpenDevice ... Nand wait ready failed. \n"));
            return FAIL;
         }     
    
         NandCmdSet(NAND_STATUS);
         platform_delay(10);
    
         NandReadDataByte(&status);
    
         if ((status & 0x01) == 1) {
            /* if SR0 bit is set to 1, there is Error - operation failed */
         	platform_errno =  PLATFORM_ERRNO_DEV_FAIL;
        	IFPRINT(platform_write("NandOpenDevice ... Nand status error bit was set. \n"));
             return FAIL;
         }
         
         return SUCCESS;
     }    
    
    
     /******************************************************************************
      * 
      * Function:    NandGetDetails  
      *
      * Description: Get details of the NAND flash used from the id and the 
      *              table of NAND   
      *
      * Parameters:  pNandInfo - Pointer to Nand Info structure
      * 
      * Return Value: Error/Success codes
      * 
      *****************************************************************************/
     uint32_t NandGetDetails(PLATFORM_DEVICE_info *pNandInfo)
     {   
    	 uint32_t	i;
    	 uint32_t 	uiStatus;
         NAND_ADDR  address;
    
         /* Clear the Information */
         pNandInfo->device_id = pNandInfo->manufacturer_id = 0x0;
     
         /* Read manufacturer ID and device ID */
         NandCmdSet(NAND_RDID);
         platform_delay(10); 
         NandAleSet(NAND_ADD_00H); 
         platform_delay(10); 
    
         /* Always reading the ID alone in 8 bit mode */
         NandReadDataByte((uint8_t *)&pNandInfo->manufacturer_id);
         NandReadDataByte((uint8_t *)&pNandInfo->device_id);
         
         /* Get the bad block table */
         address.uiPageAddr 	= 0;
         address.uiColumnAddr 	= 0;
    
         for (i=0; i < BLOCKS_PER_DEVICE; i++) {
             address.uiBlockAddr     = i;
    
             /* Clear the Spare Area */
             memset(nandPageBuf, 0, SPARE_BYTES_PER_PAGE);
    
             // Read the spare area in to buffer
             uiStatus = NandReadSpareArea(pNandInfo, address.uiBlockAddr,
                                             address.uiPageAddr, nandPageBuf);
             if(uiStatus != SUCCESS) {
                return PLATFORM_ERRNO_NANDBBT;
             }
             else { // Success in reading the NAND spare area
                 if (nandPageBuf[pNandInfo->bboffset] == 0xFF) {
                	 pNandInfo->bblist[i]  = 0xFF;
                 } else {
                	 pNandInfo->bblist[i]  = 0x00;
                 }
             }
         }
         return SUCCESS;
     }
    
     /******************************************************************************
      * 
      * Function:    nandInit
      *
      * Description: This function configures the GPIO pins for communication
      *              between DSP and FPGA NAND flash controller.
      *
      * Parameters:  None
      *
      * Return Value: status
      * 
      ******************************************************************************/
     uint32_t nandInit(void)
     {
       /* Open the NAND Device */
       return NandOpenDevice();
     }
     
    #endif /*(PLATFORM_NAND_IN)*/
     
    
    
    /****************************************************************************
     * Copyright (c) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
     * 
     *  Redistribution and use in source and binary forms, with or without 
     *  modification, are permitted provided that the following conditions 
     *  are met:
     *    Redistributions of source code must retain the above copyright 
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the 
     *    documentation and/or other materials provided with the   
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     *****************************************************************************/
    #include "platform_internal.h"
    
    /* Errno value */
    uint32_t platform_errno = 0;
    uint32_t platform_init_return_code = 0;
    
    
    /* Platform Library Version*/
    #if (PLATFORM_VERSTRING_IN)
    #pragma DATA_SECTION(platform_library_version,"platform_lib");
    static char platform_library_version[16] = PLATFORM_LIB_VERSION;
    #endif
    
    /* Information we need to keep around for access */
    #pragma DATA_SECTION(platform_mcb,"platform_lib");
    static struct platform_mcb_t {
        uint32_t	frequency;
        int32_t  	board_version;
        int32_t		mastercore;
    } platform_mcb = {0, 0, 0};
    
    #if (PLATFORM_WRITE_IN)
    #pragma DATA_SECTION(write_type,"platform_lib");
    static WRITE_info	write_type;
    #pragma DATA_SECTION(write_buffer,"platform_lib");
    static char			write_buffer[MAX_WRITE_LEN];
    #endif
    
    
    /* This structure holds information about the devices on the platform */
    #if (PLATFORM_NAND_IN)
    #pragma DATA_SECTION(gDeviceNandBBlist,"platform_lib");
    uint8_t gDeviceNandBBlist[BLOCKS_PER_DEVICE];
    
    #pragma DATA_SECTION(gDeviceNand,"platform_lib");
    //PLATFORM_DEVICE_info gDeviceNand = {0x20,	0x36,PLATFORM_DEVICE_NAND, 8, BLOCKS_PER_DEVICE, PAGES_PER_BLOCK, BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE, PLATFORM_DEVID_NAND512R3A2D, 5, 0x200, 0, NULL, NULL};
    PLATFORM_DEVICE_info gDeviceNand = {0x2C, 0xA1, PLATFORM_DEVICE_NAND, 8, BLOCKS_PER_DEVICE, PAGES_PER_BLOCK, BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE, PLATFORM_DEVID_NAND512R3A2D, 5, 0x800, 0, NULL, NULL};
    #endif
    
    #if (PLATFORM_NOR_IN)
    #pragma DATA_SECTION(gDeviceNor,"platform_lib");
    PLATFORM_DEVICE_info gDeviceNor  = {0, 0, PLATFORM_DEVICE_NOR, 8, SPI_NOR_SECTOR_COUNT, (SPI_NOR_PAGE_COUNT / SPI_NOR_SECTOR_COUNT), SPI_NOR_PAGE_SIZE, 0, PLATFORM_DEVID_NORN25Q128, 0, 0, 0, NULL, NULL};
    #endif
    
    #if (PLATFORM_EEPROM_IN)
    #pragma DATA_SECTION(gDeviceEeprom0,"platform_lib");
    PLATFORM_DEVICE_info gDeviceEeprom0 = {PLATFORM_EEPROM_MANUFACTURER_ID,PLATFORM_EEPROM_DEVICE_ID_1,PLATFORM_DEVICE_EEPROM,	8, 1, 1, 65536, 0, PLATFORM_DEVID_EEPROM50, 0, 0, 0, NULL, NULL};
    #pragma DATA_SECTION(gDeviceEeprom1,"platform_lib");
    PLATFORM_DEVICE_info gDeviceEeprom1 = {PLATFORM_EEPROM_MANUFACTURER_ID,PLATFORM_EEPROM_DEVICE_ID_2,PLATFORM_DEVICE_EEPROM,	8, 1, 1, 65536, 0, PLATFORM_DEVID_EEPROM51, 0, 0, 0, NULL, NULL};
    #endif
    
    /* This structure holds information about the EMAC port on the platform */
    #pragma DATA_SECTION(emac_port_mode,"platform_lib");
    PLATFORM_EMAC_PORT_MODE emac_port_mode[PLATFORM_MAX_EMAC_PORT_NUM] =
    {
        //PLATFORM_EMAC_PORT_MODE_AMC
        PLATFORM_EMAC_PORT_MODE_PHY,
        PLATFORM_EMAC_PORT_MODE_PHY
    };
    
    #if (PLATFORM_EXTMEMTEST_IN || PLATFORM_INTMEMTEST_IN)
    static inline int32_t platform_memory_test (uint32_t start_address, uint32_t end_address);
    #endif
    
    /******************************************************************************
     * platform_get_frequency
     *
     * Internal function to read frequency from PLL.
     *
     ******************************************************************************/
    static inline uint32_t platform_get_frequency(void)
    {
        CSL_Status      status;
        PllcHwSetup     hwSetupRead;
        uint32_t        dsp_freq;
        
        status = CorePllcGetHwSetup (&hwSetupRead);
    
        if (status != CSL_SOK) {
            IFPRINT(platform_write("platform_get_info: Hardware setup parameters reading... Failed.\n"));
            IFPRINT(platform_write("\tReason: Error setting in hardware validation."\
                    " [status = 0x%x].\n", status));
            platform_errno = PLATFORM_ERRNO_GENERIC;
            return (uint32_t)-1;
        } else {
            /* Compute the real dsp freq (*100) */
            dsp_freq = (hwSetupRead.pllM + 1)>> 1;
            dsp_freq = (dsp_freq * PLATFORM_BASE_CLK_RATE_MHZ)/(hwSetupRead.preDiv + 1);        
        }
    
        return (dsp_freq);
        
    }
    
    Bool
    serial_num_isvalid
    (
        char    c
    )
    {
        if (
            ((c >= '0') && (c <= '9'))    ||
            ((c >= 'a') && (c <= 'z'))    ||
            ((c >= 'A') && (c <= 'Z'))
           )
        {
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }
    
    #define MAX_SN_SIZE             10      /* Maximum number of the chars of Serial Number for the EVM */
    #define MAX_SN_STORE_SIZE       128     /* Maximum size in bytes to store the serial number info */   
    static void
    getSerialNumber(char *buf)
    {
    #if (PLATFORM_EEPROM_IN)
    	PLATFORM_DEVICE_info    *p_device;
        uint32_t                i;
    
        buf[0] = 0;
    
        p_device = platform_device_open(PLATFORM_DEVID_EEPROM50, 0);
        if (p_device != NULL) 
        {
            /* Serial number stored in the last 128 bytes of the EEPROM 0x50 */
            if (platform_device_read(p_device->handle, gDeviceEeprom0.page_size-MAX_SN_STORE_SIZE, (uint8_t *)buf, 16) == Platform_EOK)
            {
                for (i = 0; i < MAX_SN_SIZE; i++)
                {
                    if(!serial_num_isvalid(buf[i]))
                    {
                        break;
                    }
                }
                buf[i] = 0;
            }
            else
            {
                IFPRINT(platform_write("Unable to read board serial number."));
            }
        }
    
        platform_device_close(p_device->handle);
    #endif
    
        return;
    }
    
    /******************************************************************************
     * platform_get_info
     ******************************************************************************/
    #if (PLATFORM_GETINFO_IN)
    void platform_get_info(platform_info * p_info)
    {
        uint32_t 			csr 		= CSL_chipReadCSR();
        volatile uint32_t 	*megm_rev   = (uint32_t *) (MEGM_REV_ID_REGISTER);
        uint32_t 			i;
        
        if (p_info == 0) {
            IFPRINT(platform_write("p_info argument is NULL\n"));
            platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
            return;
        }
    
        memset(p_info, 0, sizeof(platform_info));
    
        strncpy(p_info->version, platform_library_version, 16);
    
        p_info->cpu.core_count 	= PLATFORM_CORE_COUNT;
        p_info->cpu.id 			= (Uint16) CSL_FEXT(csr, CHIP_CSR_CPU_ID);
        p_info->cpu.revision_id = (Uint16) CSL_FEXT(csr, CHIP_CSR_REV_ID);
        strncpy(p_info->cpu.name, PLATFORM_INFO_CPU_NAME, 32);
        
        p_info->cpu.megamodule_revision_major = 
            (uint16_t)(((*megm_rev) & MEGM_REV_ID_MAJ_MASK) >> MEGM_REV_ID_MAJ_SHIFT);
        p_info->cpu.megamodule_revision_minor = 
            (uint16_t)(((*megm_rev) & MEGM_REV_ID_MIN_MASK) >> MEGM_REV_ID_MIN_SHIFT);
    
        strncpy(p_info->board_name, PLATFORM_INFO_BOARD_NAME, 32);
    
    
        if ( TRUE == CSL_BootCfgIsLittleEndian() ) {
            p_info->cpu.endian = PLATFORM_LE;
        } 
        else {
            p_info->cpu.endian = PLATFORM_BE;
        }
    
        p_info->emac.port_count = PLATFORM_MAX_EMAC_PORT_NUM;
    
        p_info->frequency 			= platform_get_frequency();
        platform_mcb.frequency 		= p_info->frequency;
        p_info->board_rev 			= getBoardVersion();  
        platform_mcb.board_version 	= p_info->board_rev;
        getSerialNumber(p_info->serial_nbr);
    
        platform_get_macaddr(PLATFORM_MAC_TYPE_EFUSE, &(p_info->emac.efuse_mac_address[0]));
        platform_get_macaddr(PLATFORM_MAC_TYPE_EEPROM, &(p_info->emac.eeprom_mac_address[0]));
    
        for (i = PLATFORM_USER_LED_CLASS; i < PLATFORM_END_LED_CLASS; i++ ) {        
            switch (i) {
                case PLATFORM_USER_LED_CLASS:
                    p_info->led[i].count     = PLATFORM_FPGA_LED_COUNT;
                    break;
                case PLATFORM_SYSTEM_LED_CLASS:
                    p_info->led[i].count     = PLATFORM_I2C_LED_COUNT;
                    break;
                default:
                    IFPRINT(platform_write("Can't read LED Class information\n"));
                    platform_errno = PLATFORM_ERRNO_LED;
                    break;
            }        
        }
    }
    #endif
    
    /******************************************************************************
     * platform_init
     ******************************************************************************/
    #if (PLATFORM_INIT_IN)
    
    /* Registers to enable or disable memory ECC for L1, L2 and MSMC memories */
    #define L1PEDSTAT	0x01846404
    #define L1PEDCMD	0x01846408
    #define L1PEDADDR	0x0184640C
    #define L2EDSTAT	0x01846004
    #define L2EDCMD		0x01846008
    #define L2EDADDR	0x0184600C
    #define L2EDCPEC	0x01846018
    #define L2EDCNEC	0x0184601C
    #define L2EDCEN		0x01846030
    #define SMCERRAR	0x0BC00008
    #define	SMCERRXR	0x0BC0000C
    #define SMEDCC		0x0BC00010
    #define SMCEA		0x0BC00014
    #define SMSECC		0x0BC00018
    
    /*Enable EDC on MSMC*/
    /* Note: Once MSMC EDC is enabled, error correction stays enabled until
     * the MSMC is reset
     */
    
    static int MSMC_enableEDC ()
    {
    	unsigned int status = 0;
    
    	*(unsigned int *)(SMEDCC) &= 0x7FFFFFFF;	//Clear SEN(bit31)=0
    	*(unsigned int *)(SMEDCC) |= 0x40000000;	//Set ECM(bit30)=1
    
    	/* Check the status */
    	status = *(unsigned int *)(SMEDCC);
    
    
    	if ((status>>30)==0x1)
    		/* Enabled */
    		return 1;
    
    	/* Failed */
    	return 0;
    }
    
    
    /*Enable EDC on L1P*/
    static int enableL1PEDC ()
    {
    	unsigned int status = 0;
    
    	*(unsigned int *)(L1PEDCMD) = 0x1;	//Set EN(bit0)=1
    
    	/* Check the status */
    	status = *(unsigned int *)(L1PEDSTAT);
    
    	if ((status<<28) == 0x10000000)
    		/* Enabled */
    		return 1;
    
    	/* Failed */
    	return 0;
    }
    
    
    /*Enable EDC on L2*/
    static int enableL2EDC ()
    {
    	unsigned int status = 0;
    
    	*(unsigned int *)(L2EDCMD) = 0x1;
    
    	/* Check the status */
    	status = *(unsigned int *)(L2EDSTAT);
    
    	if ((status<<28) == 0x10000000)
    		/* Enabled */
    		return 1;
    
    	/* Failed */
    	return 0;
    }
    
    /*Enable all bits in L2EDCEN*/
    static int enableEDCL2EDCEN ()
    {
    	/* Set DL2CEN(bit0),PL2CEN(bit1),DL2SEN(bit2),PL2SEN(bit3),SDMAEN(bit4)=1 */
    	*(unsigned int *)(L2EDCEN) |= 0x1F;
    	return 1;
    }
    
    Platform_STATUS platform_init(platform_init_flags  * p_flags,
            					  platform_init_config * p_config)
    {
        CSL_Status              status;
        PllcHwSetup             pllc_hwSetup;
        PllcHwSetup             pllc_hwSetupRead;
    
    #ifdef PLATFORM_PLL_REINIT
        int loop_count;
    #endif
    
        /*************************************************************************
         * This routine may be called before BIOS or the application has loaded.
         * Do not try and write debug statements from here.
         ***********************************************************************/
    
        if ((p_flags == 0) || (p_config == 0)){
            platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
            return ( (Platform_STATUS) Platform_EFAIL);
        }
    
        /* Start TCSL so its free running */
        CSL_chipWriteTSCL(0);
    
    #ifdef PLATFORM_PLL_REINIT
        for (loop_count = 0; loop_count < 10; loop_count++) {
            platform_errno = 0;
    #endif
    
            /* PLLC module handle structure */
            if (p_flags->pll) {
    
                /* Set the Core PLL */
                /* Clear local data structures */
                memset(&pllc_hwSetup, 0, sizeof(PllcHwSetup));
    
                /* Setup PLLC hardware parameters */
                pllc_hwSetup.divEnable  = (CSL_BitMask32) (PLLC_DIVEN_PLLDIV2 |
                                                           PLLC_DIVEN_PLLDIV5 |
                                                           PLLC_DIVEN_PLLDIV8) ;
    
                /* Setup PLLC hardware parameters */        
                pllc_hwSetup.pllM       = 
                        (((p_config->pllm) ? p_config->pllm : PLATFORM_PLL1_PLLM_val) - 1);
                pllc_hwSetup.preDiv   = PLATFORM_PLL_PREDIV_val - 1;
                pllc_hwSetup.pllDiv2  = PLATFORM_PLLDIV2_val - 1;
                pllc_hwSetup.pllDiv5  = PLATFORM_PLLDIV5_val - 1;
                pllc_hwSetup.pllDiv8  = PLATFORM_PLLDIV8_val - 1;
                pllc_hwSetup.postDiv  = PLATFORM_PLL_POSTDIV_val -1;
    
                /* set Pll */
                status = CorePllcHwSetup (&pllc_hwSetup);
    
                if (status != CSL_SOK) {
                     platform_errno = PLATFORM_ERRNO_PLL_SETUP;
                    return ( (Platform_STATUS) Platform_EFAIL);
                }
    
                /* Read back */
                status = CorePllcGetHwSetup (&pllc_hwSetupRead);
    
                if (status != CSL_SOK) {
                    platform_errno = PLATFORM_ERRNO_PLL_SETUP;
                    return ( (Platform_STATUS) Platform_EFAIL);
                }
    
                /* Set the PA_SS PLL */
                status = SetPaPllConfig();
                if (status != CSL_SOK) {
                    platform_errno = PLATFORM_ERRNO_PLL_SETUP;
                    return ( (Platform_STATUS) Platform_EFAIL);
                }
    
    			/* Set the DDR3 PLL if DDR flag is set */
                if (p_flags->ddr) {
                    status = SetDDR3PllConfig();
                    if (status != CSL_SOK) {
                        platform_errno = PLATFORM_ERRNO_PLL_SETUP;
                        return ( (Platform_STATUS) Platform_EFAIL);
                    }
                }
            }
    		
            /* Initialize DDR3 */
            if (p_flags->ddr) {
                xmc_setup();
    
                status = DDR3Init();
    
                if (status != CSL_SOK) {
                    platform_errno = PLATFORM_ERRNO_GENERIC;
                    return ( (Platform_STATUS) Platform_EFAIL);
                }
            }
    
    #ifdef PLATFORM_PLL_REINIT
            if (!p_flags->pll || !p_flags->ddr) {
                break;
            }
    
            /* Run DDR3 test */
            if (platform_memory_test(PLL_REINIT_DDR3_TEST_START_ADDR, 
                    PLL_REINIT_DDR3_TEST_END_ADDR) == Platform_EOK) {
                break;
            }
        }
        platform_init_return_code = loop_count;
    
        if (loop_count == 10) {
            platform_errno = PLATFORM_ERRNO_GENERIC;
            return ( (Platform_STATUS) Platform_EFAIL);
        }
    #endif
    
        /* Save frequency, its needed by  platform_delay */
        if(!platform_mcb.frequency) {
          platform_mcb.frequency = platform_get_frequency();
        }
        PowerUpDomains();
    
        /* Enable Error Correction for memory */
        if (p_flags->ecc) {
        	   enableL1PEDC();
        	   enableEDCL2EDCEN();
        	   enableL2EDC();
        	   MSMC_enableEDC();
        }
    
        if (p_flags->phy) {
            configSerdes();
            Init_SGMII(0);
            // Init_SGMII(1);
        }
    
    
        return Platform_EOK;
    }
    #endif
    
    /******************************************************************************
     * platform_get_coreid
     ******************************************************************************/
    #if (PLATFORM_GETCOREID_IN)
    uint32_t platform_get_coreid(void)
    {
        return (CSL_chipReadDNUM());
    }
    #endif
    
    /******************************************************************************
     * platform_getmacaddr
     ******************************************************************************/
    #if (PLATFORM_GETMACADDR_IN)
    Platform_STATUS platform_get_emac_info(uint32_t port_num, PLATFORM_EMAC_EXT_info * emac_info)
    {
        uint32_t mac_addr2, mac_addr1;
    
    	IFPRINT(platform_write("platform_get_emac_info called \n"));
    
        emac_info->port_num       = port_num;
        emac_info->mode           = emac_port_mode[port_num];
    
        CSL_BootCfgGetMacIdentifier(&mac_addr1, &mac_addr2);
        emac_info->mac_address[0] = ((mac_addr2 & 0x0000ff00) >> 8);
        emac_info->mac_address[1] =  (mac_addr2 & 0x000000ff);
    
        emac_info->mac_address[2] = ((mac_addr1 & 0xff000000) >> 24);
        emac_info->mac_address[3] = ((mac_addr1 & 0x00ff0000) >> 16);
        emac_info->mac_address[4] = ((mac_addr1 & 0x0000ff00) >> 8);
        emac_info->mac_address[5] =  (mac_addr1 & 0x000000ff);
    
        return Platform_EOK;
    }
    
    /*
     * August 15, 2011 - platform_get_macaddr() is deprecated, application needs to call
     * the new API platform_get_emac_info() to get the MAC address of the port
     */
    Platform_STATUS platform_get_macaddr(PLATFORM_MAC_TYPE type, uint8_t * p_mac_address)
    {
    	IFPRINT(platform_write("platform_get_macaddr called \n"));
    
        switch (type) {
    
            case PLATFORM_MAC_TYPE_EFUSE:
            {
                uint32_t mac_addr2, mac_addr1;
    
                CSL_BootCfgGetMacIdentifier(&mac_addr1, &mac_addr2);
                p_mac_address[0] = ((mac_addr2 & 0x0000ff00) >> 8);
                p_mac_address[1] =  (mac_addr2 & 0x000000ff);
    
                p_mac_address[2] = ((mac_addr1 & 0xff000000) >> 24);
                p_mac_address[3] = ((mac_addr1 & 0x00ff0000) >> 16);
                p_mac_address[4] = ((mac_addr1 & 0x0000ff00) >> 8);
                p_mac_address[5] =  (mac_addr1 & 0x000000ff);
    
                return Platform_EOK;
            }
            
            default:
            case PLATFORM_MAC_TYPE_EEPROM:
            {
                memset(p_mac_address, 0, 6);
                return ((Platform_STATUS) Platform_EUNSUPPORTED);
            }
        }
    }
    #endif
    
    /******************************************************************************
     * platform_get_phy_addr
     ******************************************************************************/
    #if (PLATFORM_GETPHYADDR_IN)
    int32_t platform_get_phy_addr(uint32_t port_num)
    {
    	IFPRINT(platform_write("platform_get_phy_addr called \n"));
    
    	return port_num;
    }
    #endif
    
    /******************************************************************************
     * platform_phy_link_status
     ******************************************************************************/
    #if (PLATFORM_PHYLINKSTATUS_IN)
    Platform_STATUS platform_phy_link_status(uint32_t port_num)
    {
        uint32_t phy_addr;
        CSL_MDIO_USERACCESS    user_access_reg;
    
    	IFPRINT(platform_write("platform_get_phy_link_status (portnum = %d) called \n", port_num));
    
        phy_addr = platform_get_phy_addr( port_num);
    
        CSL_MDIO_getUserAccessRegister(port_num, &user_access_reg);
    
        user_access_reg.phyAddr = phy_addr;
        user_access_reg.regAddr = 24;      //The LED Control Reg address 
        user_access_reg.data    &= 0xFFBE; // Need to check this in ?
        user_access_reg.data    |= 1;
    
        CSL_MDIO_setUserAccessRegister(port_num, &user_access_reg);
    
        return Platform_EOK;
    }
    #endif
    
    /******************************************************************************
     * platform_get_switch_state
     ******************************************************************************/
    #if (PLATFORM_GETSWITCHSTATE_IN)
    uint32_t platform_get_switch_state(uint32_t id)
    {
    	IFPRINT(platform_write("platform_get_switch_state(id=%d) called \n", id));
    
       return (fpgaGetUserSwitch(id));
    }
    #endif
    
    
    /******************************************************************************
     * platform_uart_read
     ******************************************************************************/
    #if (PLATFORM_UART_IN)
    Platform_STATUS platform_uart_read(uint8_t *buf, uint32_t delay)
    {
        uint32_t delayCount = delay;
    
        if (buf == NULL){
            return ((Platform_STATUS) Platform_EINVALID);
        }
    
        while( (UartIsDataReady()) != 1)
        {
            if (delayCount--)
            {
                platform_delay(1);
            }
            else
            {
                IFPRINT(platform_write("platform_uart_read: Read timeout\n"));
                platform_errno = PLATFORM_ERRNO_READTO;
                *buf = UartReadData();
                return ( (Platform_STATUS) Platform_EFAIL);
            }
        }
    
        *buf = UartReadData ();
    
        return Platform_EOK;
    }
    
    /******************************************************************************
     * platform_uart_write
     ******************************************************************************/
    Platform_STATUS platform_uart_write(uint8_t buf)
    {
        UartWriteData(buf);
    
        return Platform_EOK;
    }
    
    /******************************************************************************
     * platform_uart_set_baudrate
     ******************************************************************************/
    Platform_STATUS platform_uart_set_baudrate(uint32_t baudrate) {
    
    	uint16_t brate;
    
    	IFPRINT(platform_write("platform_uart_set_baudrate(baudrate=%d) called \n", baudrate));
    
        brate = ((Uint16) (PLATFORM_UART_INPUT_CLOCK_RATE/(baudrate * 16)));
    
    	UartSetBaudRate(brate);
    
        return Platform_EOK;
    }
    
    /******************************************************************************
     * platform_uart_init
     ******************************************************************************/
    Platform_STATUS platform_uart_init(void) {
    
    	IFPRINT(platform_write("platform_uart_init called \n"));
    
    	UartInit();
    
    	platform_uart_set_baudrate(115200);
    
        return Platform_EOK;
    }
    
    #endif
    
    
    /******************************************************************************
     * platform_led
     ******************************************************************************/
    #if (PLATFORM_LED_IN)
    Platform_STATUS platform_led(uint32_t led_id, PLATFORM_LED_OP operation, LED_CLASS_E led_class)
    {
    
    
    	IFPRINT(platform_write("platform_led(ledid=%d,operation=%d,class=%d) called \n", led_id, operation, led_class));
    
        switch (led_class) {
            case PLATFORM_USER_LED_CLASS:
                fpgaControlUserLEDs((FPGA_UserLed)(led_id),(FPGA_LedStatus) operation);
                break;
            case PLATFORM_SYSTEM_LED_CLASS:
            	return ( (Platform_STATUS) Platform_EUNSUPPORTED);
            default:
                IFPRINT(platform_write("platform_led: Invalid led_id %d\n", led_id));
                platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
                return ( (Platform_STATUS) Platform_EUNSUPPORTED);
        }
        return Platform_EOK;
    }
    #endif
    
    /******************************************************************************
     * platform_delay
     ******************************************************************************/
    #if (PLATFORM_DELAY_IN)
    Platform_STATUS platform_delay(uint32_t usecs)
    {
        int32_t delayCount = (int32_t) usecs * platform_mcb.frequency;
        int32_t start_val  = (int32_t) CSL_chipReadTSCL();
    
        while (((int32_t)CSL_chipReadTSCL() - start_val) < delayCount);
    
        return Platform_EOK;
    }
    
    void platform_delaycycles(uint32_t cycles)
    {
    	uint32_t start_val  = CSL_chipReadTSCL();
    
    	while ((CSL_chipReadTSCL() - start_val) < cycles);
    
        return;
    }
    #endif
    
    /******************************************************************************
     * platform_memory_test
     ******************************************************************************/
    #if (PLATFORM_EXTMEMTEST_IN || PLATFORM_INTMEMTEST_IN)
    static inline int32_t platform_memory_test (uint32_t start_address, uint32_t end_address)
    {
        uint32_t index, value;
    
        /* Write a pattern */
        for (index = start_address; index < end_address; index += 4) {
            *(volatile uint32_t *) index = (uint32_t)index;
        }
    
        /* Read and check the pattern */
        for (index = start_address; index < end_address; index += 4) {
            	
        	value = *(uint32_t *) index;
        	
            if (value  != index) {
                IFPRINT(platform_write("platform_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
                    index, value, *(volatile uint32_t *) index));
                platform_errno = index;
                return (Platform_EFAIL);
            }
        }
    
        /* Write a pattern for complementary values */
        for (index = start_address; index < end_address; index += 4) {
            *(volatile uint32_t *) index = (uint32_t)~index;
        }
    
        /* Read and check the pattern */
        for (index = start_address; index < end_address; index += 4) {
    
        	value = *(uint32_t *) index;
    
            if (value  != ~index) {
                IFPRINT(platform_write("platform_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
                    index, value, *(volatile uint32_t *) index));
                platform_errno = index;
                return (Platform_EFAIL);
            }
        }
    
        return Platform_EOK;
    }
    #endif
    
    /******************************************************************************
     * platform_external_memory_test
     ******************************************************************************/
    #if (PLATFORM_EXTMEMTEST_IN)
    Platform_STATUS platform_external_memory_test(uint32_t start_address, uint32_t end_address)
    {
    	IFPRINT(platform_write("platform_external_memory_test(start=0x%x,end=0x%x) called \n", start_address, end_address));
    
        if((start_address == 0) && (end_address == 0)) {
            start_address = PLATFORM_DDR3_SDRAM_START;
            end_address   = PLATFORM_DDR3_SDRAM_END - 1;
        }
    
        if ((start_address < PLATFORM_DDR3_SDRAM_START) ||
            (end_address >  PLATFORM_DDR3_SDRAM_END) ||
            (start_address >= end_address)){
            IFPRINT(platform_write("platform_external_memory_test: Start address (0x%08x) or end address (0x%08x)\n",
                start_address, end_address));
            platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
            return ((Platform_STATUS) Platform_EINVALID);
        }
    
        return platform_memory_test(start_address, end_address);
    }
    #endif
    
    /******************************************************************************
     * platform_internal_memory_test
     ******************************************************************************/
    #if (PLATFORM_INTMEMTEST_IN)
    Platform_STATUS platform_internal_memory_test(uint32_t id)
    {
        uint32_t start_address, end_address;
        CSL_PSC_MODSTATE state_prev, state_val;
        CSL_PSC_MDLRST   loc_rst_prev, loc_rst_val;
        uint32_t rstiso_prev_flag;    
        uint32_t module_number = 15;
        int32_t status = Platform_EOK;
    
    	IFPRINT(platform_write("platform_internal_memory_test(core=%d) called \n", id));
    
        if (platform_get_coreid() == id) {
            IFPRINT(platform_write("platform_internal_memory_test: Can't run the test own core(%d)\n",
                id));
            platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
            return ((Platform_STATUS) Platform_EUNSUPPORTED);
        }
    
        if (id >= PLATFORM_CORE_COUNT) {
            IFPRINT(platform_write("platform_internal_memory_test: core id should be in range [0..%d]\n",
                PLATFORM_CORE_COUNT - 1));
            platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
            return ((Platform_STATUS) Platform_EINVALID);
        }
    
        /* For the 6678L */
        switch (id) {
            case 0:
                module_number = 15; //(C66x Core 0 and Timer 0)
                break;
            case 1:
                module_number = 16; //(C66x Core 1 and Timer 1)
                break;
            case 2:
                module_number = 17; //(C66x Core 2 and Timer 2)
                break;
            case 3:
                module_number = 18; //(C66x Core 3 and Timer 3)
                break;
            case 4:
                module_number = 19; //(C66x Core 4 and Timer 4)
                break;
            case 5:
                module_number = 20; //(C66x Core 5 and Timer 5)
                break;
            case 6:
                module_number = 21; //(C66x Core 6 and Timer 6)
                break;
            case 7:
                module_number = 22; //(C66x Core 7 and Timer 7)
                break;
        }
        
        /* Preserve the state, local reset and resetiso values */
        state_prev          = CSL_PSC_getModuleNextState(module_number);
        loc_rst_prev        = CSL_PSC_getModuleLocalReset(module_number);
        rstiso_prev_flag    = CSL_PSC_isModuleResetIsolationEnabled(module_number);
    
        /* Clear the state, local reset and resetiso values */
        state_val           = PSC_MODSTATE_SWRSTDISABLE;
        loc_rst_val         = PSC_MDLRST_ASSERTED;
    
        CSL_PSC_setModuleNextState(module_number, state_val);
        CSL_PSC_setModuleLocalReset(module_number, loc_rst_val);
        CSL_PSC_disableModuleResetIsolation(module_number);
    
        /* Test L1P memory region*/
        start_address = PLATFORM_L1P_BASE_ADDRESS | (id << 24);
        end_address   = start_address + PLATFORM_L1P_SIZE;
        if (platform_memory_test(start_address, end_address) != Platform_EOK) {
            status = Platform_EFAIL;
        }
    
        /* Test L1D memory region*/
        start_address = PLATFORM_L1D_BASE_ADDRESS | (id << 24);
        end_address   = start_address + PLATFORM_L1D_SIZE;
        if (platform_memory_test(start_address, end_address) != Platform_EOK) {
            status = Platform_EFAIL;
        }
    
        /* Restore the previous state, local reset and resetiso values */
        CSL_PSC_setModuleNextState(module_number, state_prev);
        CSL_PSC_setModuleLocalReset(module_number, loc_rst_prev);
        if (rstiso_prev_flag) {
             CSL_PSC_enableModuleResetIsolation(module_number);
        } else {
             CSL_PSC_disableModuleResetIsolation(module_number);
        }
        
        return status;
    }
    #endif
    
    /******************************************************************************
     * platform_write  - Printf or echo to UART or both
     ******************************************************************************/
    #if (PLATFORM_WRITE_IN)
    WRITE_info platform_write_configure (WRITE_info	wtype) {
    	WRITE_info original;
    	IFPRINT(platform_write("platform_write_configure(write_type=%d) called \n", wtype));
    	original = write_type;
    	write_type = wtype;
    	return original;
    }
    
    void platform_write(const char *fmt, ... )
    {
        va_list 	arg_ptr;
    	uint32_t	i, length;
    	
        /* Initial platform_write to temporary buffer.. at least try some sort of sanity check so we don't write all over
         * memory if the print is too large.
         */
        if (strlen(fmt) > MAX_WRITE_LEN) {platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT; return;}
     
        va_start( arg_ptr, fmt );
        length = vsprintf( (char *)write_buffer, fmt, arg_ptr );
        va_end( arg_ptr );
    
    	if ((write_type == PLATFORM_WRITE_PRINTF) || (write_type == PLATFORM_WRITE_ALL)) {
    		printf( "%s", write_buffer );
    	}
    
    	if ((write_type == PLATFORM_WRITE_UART) || (write_type == PLATFORM_WRITE_ALL)) {
    		/* Log to console port (routine only sends a byte at a time) */
    		for (i=0; i < length; i++) {
    			if (write_buffer[i] == '\n') {
    				(void) platform_uart_write((uint8_t)0x0D);
    				(void) platform_uart_write((uint8_t)0x0A);
    			}
    			else {
    				(void) platform_uart_write((uint8_t)write_buffer[i]);
    			}
    		}
    	}
    
    	return;
    }
    #endif
    
    
    /******************************************************************************
     * platform_flash_open
     ******************************************************************************/
    #if (PLATFORM_NAND_IN) || (PLATFORM_NOR_IN)  || (PLATFORM_EEPROM_IN)
    PLATFORM_DEVICE_info *platform_device_open(uint32_t deviceid, uint32_t flags ) {
     
    	PLATFORM_DEVICE_info *p_info;
    
    	IFPRINT(platform_write("platform_device_open(deviceid=0x%x,flags=0x%x) called \n", deviceid, flags));
    
    #if (PLATFORM_NAND_IN)
    
    	if (deviceid == PLATFORM_DEVID_NAND512R3A2D) {
    		/* Disable Write protect in NAND */
            if (nandInit() != SUCCESS) {
                IFPRINT(platform_write("platform_dveice_open: Initialization failed.\n"));
                return NULL;
            }
    
            /* Store the open flags */
            gDeviceNand.flags	= flags;
    
            /* Set the device to point to its bad block list */
            gDeviceNand.bblist = (uint8_t *)&gDeviceNandBBlist;
    
            p_info = &gDeviceNand;
    
       		 if (NandGetDetails(p_info) != SUCCESS) {
       		    IFPRINT(platform_write("platform_device_open: Unable to read device information.\n"));
                platform_errno = PLATFORM_ERRNO_BADFLASHDEV;
       		    return NULL;
       		 }
    
    		p_info->handle	= deviceid;
    
           return p_info;
    	}
    
    #endif
    
    #if (PLATFORM_NOR_IN)
    	    
    	NOR_STATUS      nor_status;
        
    	if (deviceid == PLATFORM_DEVID_NORN25Q128) {
    
    		/* Disable Write protect in NOR */
           //fpgaDisableNorWriteProtect();
           nor_status = nor_init();
           if (nor_status != NOR_EOK) {
                IFPRINT(platform_write("platform_device_open: Initialization failed.\n"));
                return NULL;
            } 
    
           /* Store the open flags */
           gDeviceNor.flags	= flags;
    
           p_info = &gDeviceNor;
    
    	    if (nor_get_details(p_info) != SUCCESS) {
                IFPRINT(platform_write("platform_device_open: Unable to read device information.\n"));
                platform_errno = PLATFORM_ERRNO_BADFLASHDEV;
                return NULL;
    	    }
     
       		p_info->handle	= deviceid;
          
        	return p_info;
    	}
    #endif
    
    #if (PLATFORM_EEPROM_IN)
    
    	if (deviceid == PLATFORM_DEVID_EEPROM50) {
    	    /* Store the open flags */
    	    gDeviceEeprom0.flags	= flags;
            evmI2CInit();
    		p_info = &gDeviceEeprom0;
       		p_info->handle	= deviceid;
        	return p_info;
    	}
    
    	if (deviceid == PLATFORM_DEVID_EEPROM51) {
    	    /* Store the open flags */
    	    gDeviceEeprom1.flags	= flags;
            evmI2CInit();
    		p_info = &gDeviceEeprom1;
       		p_info->handle	= deviceid;
        	return p_info;
    	}
    
    #endif
    
    	platform_errno = PLATFORM_ERRNO_UNSUPPORTED;
    
    	return NULL;
    }
    #endif
    
    /******************************************************************************
     * platform_flash_close
     ******************************************************************************/
    #if (PLATFORM_NAND_IN) || (PLATFORM_NOR_IN)  || (PLATFORM_EEPROM_IN)
    Platform_STATUS platform_device_close(PLATFORM_DEVHANDLE deviceid) {
     
    	IFPRINT(platform_write("platform_device_close(handle=0x%x) called \n", deviceid));
    
    #if (PLATFORM_NAND_IN)
    	if (deviceid == PLATFORM_DEVID_NAND512R3A2D) {
    		gDeviceNand.handle = 0;
    		return Platform_EOK;
    	}
    #endif
    
    #if (PLATFORM_NOR_IN)
    	if (deviceid == PLATFORM_DEVID_NORN25Q128) {
    		gDeviceNor.handle = 0;
         	return Platform_EOK;   
    	}
    #endif
    
    #if (PLATFORM_EEPROM_IN)
    
    	if (deviceid == PLATFORM_DEVID_EEPROM50) {
    		gDeviceEeprom0.handle = 0;
    		return Platform_EOK;
    	}
    
    	if (deviceid == PLATFORM_DEVID_EEPROM51) {
    		gDeviceEeprom1.handle = 0;
    		return Platform_EOK;
    	}
    
    #endif
    
    	return Platform_EUNSUPPORTED;
    }
    #endif
    
    /******************************************************************************
     * platform_flash_read_spare_data
     ******************************************************************************/
    #if (PLATFORM_NAND_IN) || (PLATFORM_NOR_IN) || (PLATFORM_EEPROM_IN)
    Platform_STATUS platform_device_read_spare_data(PLATFORM_DEVHANDLE deviceid,
    												uint32_t block_number,
    												uint32_t page_number,
    												uint8_t *buf) {
    
    	IFPRINT(platform_write("platform_device_read_spare_data(handle=0x%x, block=%d, page=%d,buf=0x%x) called \n",
    			deviceid, block_number, page_number, buf));
    
    	if (buf == NULL) {
    		platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
    		return Platform_EINVALID;
    	}
    
    #if (PLATFORM_NAND_IN)
    	if (deviceid == PLATFORM_DEVID_NAND512R3A2D) {
    		if ((block_number >= gDeviceNand.block_count) || (page_number >= gDeviceNand.page_count))
            {
    			platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
    			return Platform_EINVALID;
    		}
    
    	    if (NandReadSpareArea (&gDeviceNand, block_number, page_number, buf) != SUCCESS) {
    	        return ( (Platform_STATUS) Platform_EFAIL);
    	    }
           return Platform_EOK;
    	}
    #endif
    
    	return Platform_EUNSUPPORTED;
    													
    }
    #endif
    
    /******************************************************************************
     * platform_device_mark_block_bad
     ******************************************************************************/
    #if PLATFORM_NAND_WRITE_IN
    Platform_STATUS platform_device_mark_block_bad(PLATFORM_DEVHANDLE deviceid,
    												uint32_t block_number) {
    
        uint8_t *buf = NULL;
        PLATFORM_DEVICE_info *p_device;
    
        if (deviceid == PLATFORM_DEVID_NAND512R3A2D) {
    		p_device = &gDeviceNand;
        }
    	else {
    		p_device = NULL;
    	}
    
    	if (p_device == NULL) {
    		platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
    		return Platform_EINVALID;
    	}
        
        buf =  (uint8_t *) Osal_platformMalloc(platform_roundup(p_device->spare_size, PLATFORM_CACHE_LINE_SIZE),
        										PLATFORM_CACHE_LINE_SIZE);
    
        platform_device_read_spare_data(deviceid, block_number, 0, buf);
    
        buf[p_device->bboffset] = 0xA5; /* BI indicator byte*/
        
    	if ( block_number >= gDeviceNand.block_count ) {
    		platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
    		Osal_platformFree(buf, platform_roundup(p_device->spare_size, PLATFORM_CACHE_LINE_SIZE));
    		return Platform_EINVALID;
    	}
    
    	if (NandWriteSpareArea (p_device, block_number, 0, buf) != SUCCESS) {
    		Osal_platformFree(buf, platform_roundup(p_device->spare_size, PLATFORM_CACHE_LINE_SIZE));
    	    return ( (Platform_STATUS) Platform_EFAIL);
    	 }
    
    	Osal_platformFree(buf, platform_roundup(p_device->spare_size, PLATFORM_CACHE_LINE_SIZE));
    
        return Platform_EOK;
    
    }
    #endif
    
    /******************************************************************************
     * platform_flash_write_spare_data
     ******************************************************************************/
    #if (PLATFORM_NAND_IN) || (PLATFORM_NOR_IN) || (PLATFORM_EEPROM_IN)
    Platform_STATUS platform_device_write_spare_data(PLATFORM_DEVHANDLE deviceid,
    												uint32_t block_number,
    												uint32_t page_number,
    												uint8_t *buf) {
    
    	IFPRINT(platform_write("platform_device_write_spare_data(handle=0x%x, block=%d, page=%d,buf=0x%x) called \n",
    			deviceid, block_number, page_number, buf));
    
    	if (buf == NULL) {
    		platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
    		return Platform_EINVALID;
    	}
    
    #if (PLATFORM_NAND_WRITE_IN)
    	if (deviceid == PLATFORM_DEVID_NAND512R3A2D) {
    		if ((block_number >= gDeviceNand.block_count) || (page_number >= gDeviceNand.page_count))
            {
    			platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
    			return Platform_EINVALID;
    		}
    
    	    if (NandWriteSpareArea (&gDeviceNand, block_number, page_number, buf) != SUCCESS) {
    	        return ( (Platform_STATUS) Platform_EFAIL);
    	    }
           return Platform_EOK;
    	}
    #endif
    
    	return Platform_EUNSUPPORTED;
    													
    }
    #endif
    
    /******************************************************************************
     * platform_flash_read
     ******************************************************************************/
    #if (PLATFORM_NAND_IN) || (PLATFORM_NOR_IN) || (PLATFORM_EEPROM_IN)
    Platform_STATUS platform_device_read(PLATFORM_DEVHANDLE 	deviceid,
    									 uint32_t 	offset,
                                         uint8_t 	*buf,
                                         uint32_t	len) {
    
    	IFPRINT(platform_write("platform_device_read(handle=0x%x, offset=%d, len=%d, buf=0x%x) called \n",
    			deviceid, offset, len, buf));
    
    	if (buf == NULL || len == 0) {
    		platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
    		return Platform_EINVALID;
    	}
    
    #if (PLATFORM_NAND_IN)
    	if (deviceid == PLATFORM_DEVID_NAND512R3A2D) {
        	NAND_ADDR addr;
            uint32_t  read_len = 0;
    
    	    addr.uiColumnAddr= 0;
    
            for (read_len = 0; read_len < len; read_len += gDeviceNand.page_size)
            {
                if (platform_offset_to_blocknpage(deviceid, offset+read_len, &addr.uiBlockAddr, &addr.uiPageAddr) != Platform_EOK) {
                    return Platform_EUNSUPPORTED;
                }
    
                if (readNandPage (&gDeviceNand, addr, &buf[read_len]) != SUCCESS) {
                    return ( (Platform_STATUS) Platform_EFAIL);
                }
            }
    		    
           	return Platform_EOK;
    	}
    #endif
    
    #if (PLATFORM_NOR_IN)
    	if (deviceid == PLATFORM_DEVID_NORN25Q128) {
    	    if (nor_read (&gDeviceNor, offset, len, buf) != SUCCESS) {
    	        return ( (Platform_STATUS) Platform_EFAIL);
    	    }
         	return Platform_EOK;   
    	}
    #endif
    
    #if (PLATFORM_EEPROM_IN)
    
    	if (deviceid == PLATFORM_DEVID_EEPROM50) {
    	    if (i2cEepromRead (offset, len, buf, 0x50) != I2C_RET_OK) {
    	        IFPRINT(platform_write("platform_eeprom_read: EEPROM read failed\n"));
    	        return ( (Platform_STATUS) Platform_EFAIL);
    	    }
        	return Platform_EOK;
    	}
    
    	if (deviceid == PLATFORM_DEVID_EEPROM51) {
    	    if (i2cEepromRead (offset, len, buf, 0x51) != I2C_RET_OK) {
    	        IFPRINT(platform_write("platform_eeprom_read: EEPROM read failed\n"));
    	        return ( (Platform_STATUS) Platform_EFAIL);
    	    }
        	return Platform_EOK;
    	}
    
    #endif
    
    	return Platform_EUNSUPPORTED;
    
    }
    #endif
    
    /******************************************************************************
     * Computes a block and page based on an offset
     ******************************************************************************/
    #if (PLATFORM_NAND_IN) || (PLATFORM_NOR_IN)
    
    Platform_STATUS platform_offset_to_blocknpage(PLATFORM_DEVHANDLE 	deviceid,
    									 uint32_t 	offset,
                                         uint32_t 	*block,
                                         uint32_t	*page) {
    	uint32_t	leftover;
    	uint32_t	block_size;
    	uint32_t	block_count, page_size, page_count;
    
    	IFPRINT(platform_write("platform_offset_to_blocknpage(handle=0x%x, offset=%d) called \n",
    			deviceid, offset));
    
    	if (deviceid == PLATFORM_DEVID_NAND512R3A2D) {
    		block_count = gDeviceNand.block_count;
    		page_size	= gDeviceNand.page_size;
    		page_count 	= gDeviceNand.page_count;
    	}
    	else if (deviceid == PLATFORM_DEVID_NORN25Q128) {
    		block_count = gDeviceNor.block_count;
    		page_size	= gDeviceNor.page_size;
    		page_count 	= gDeviceNor.page_count;
    	}
    	else {
    		return Platform_EUNSUPPORTED;
    	}
    
    	block_size = (page_count * page_size);
    
    	*block 	  = offset / block_size;
    	leftover  = offset % block_size;
    	*page 	  = leftover / page_size;
    	if (leftover % page_size) {
    		/* All writes must be page aligned for now */
    		return Platform_EUNSUPPORTED;
    	}
    	if (*block > block_count) {
    		return Platform_EINVALID;
    	}
    	if (*page > page_count) {
    		return Platform_EINVALID;
    	}
    
    	IFPRINT(platform_write("platform_offset_to_blocknpage: offset = %d block = %d page = %d \n", offset, *block, *page));
    
    	return Platform_EOK;
    
    }
    
    #endif
    
    /******************************************************************************
     * Computes a block and page based on an offset
     ******************************************************************************/
    #if (PLATFORM_NAND_IN) || (PLATFORM_NOR_IN)
    
    Platform_STATUS platform_blocknpage_to_offset(PLATFORM_DEVHANDLE 	deviceid,
    									 uint32_t 	*offset,
                                         uint32_t 	block,
                                         uint32_t	page) {
    
    	uint32_t	block_count, page_size, page_count;
    
    	IFPRINT(platform_write("platform_blocknpage_to_offset(handle=0x%x, block=%d, page=%d) called \n",
    			deviceid, block, page));
    
    	if (deviceid == PLATFORM_DEVID_NAND512R3A2D) {
    		block_count = gDeviceNand.block_count;
    		page_size	= gDeviceNand.page_size;
    		page_count 	= gDeviceNand.page_count;
    	}
    	else if (deviceid == PLATFORM_DEVID_NORN25Q128) {
    		block_count = gDeviceNor.block_count;
    		page_size	= gDeviceNor.page_size;
    		page_count 	= gDeviceNor.page_count;
    	}
    	else {
    		return Platform_EUNSUPPORTED;
    	}
    
    	if (block >block_count || page > page_count) {
    			return Platform_EINVALID;
    	}
    
    	*offset = 	(block * (page_count * page_size)) + (page * page_size);
    
    	IFPRINT(platform_write("platform_blocknpage_to_offset: offset = %d block = %d page = %d \n", *offset, block, page));
    
    	return Platform_EOK;
    }
    
    #endif
    
    /******************************************************************************
     * platform_flash_write
     ******************************************************************************/
    
    #if (PLATFORM_NAND_IN) || (PLATFORM_NOR_IN) || (PLATFORM_EEPROM_IN)
    
    Platform_STATUS platform_device_write(PLATFORM_DEVHANDLE 	deviceid,
    									 uint32_t 	offset,
                                         uint8_t 	*buf,
                                         uint32_t	len) {
    
    	IFPRINT(platform_write("platform_device_write(handle=0x%x, offset=%d, len=%d, buf=0x%x) called \n",
    			deviceid, offset, len, buf));
    
    	/* Check general args */
    	if (buf == NULL || len == 0) {
    		platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
    		return Platform_EINVALID;
    	}
    
    #if (PLATFORM_NAND_WRITE_IN || PLATFORM_NOR_WRITE_IN)
    	if ((deviceid == PLATFORM_DEVID_NAND512R3A2D) || (deviceid == PLATFORM_DEVID_NORN25Q128))
    	{
    	    NAND_ADDR 			 addr;
    	    NAND_ADDR 			 StartAddress;
    	    Platform_STATUS		 retval = Platform_EOK;
    	    PLATFORM_DEVICE_info *p_device;
    		int32_t				block, page;
    		int32_t				bufindex;
    		int32_t				index;
    		int32_t				useable_page_size;
    		int32_t				block_size;
    		uint32_t			noraddress;
    		uint8_t				*pBlock	= NULL;
    		uint8_t				*pPage	= NULL;
    
    		if (deviceid == PLATFORM_DEVID_NAND512R3A2D) {
    			p_device = &gDeviceNand;
    		}
    		else {
    			p_device = &gDeviceNor;
    		}
    
    		/* Calculate the usable page area.. Its the size of the page  */
    		useable_page_size = p_device->page_size;
    
    		/* allocate a buffer big enough to hold one block (must include spare area) */
    		block_size = p_device->page_size * p_device->page_count;
    
    		pBlock = Osal_platformMalloc(platform_roundup(block_size, PLATFORM_CACHE_LINE_SIZE),
    									 PLATFORM_CACHE_LINE_SIZE);
    
    		if ( !pBlock ){
    			platform_errno = PLATFORM_ERRNO_OOM;
    			retval = Platform_EFAIL;
    			goto FLASHWRITE_ERROR;
    		}
    
    		/* allocate a buffer big enough to hold one page of the flash */
    		pPage =  Osal_platformMalloc(platform_roundup(p_device->page_size, PLATFORM_CACHE_LINE_SIZE),
    				 	 	 	 	 	 PLATFORM_CACHE_LINE_SIZE);
    
    		if ( !pPage ){
    			platform_errno = PLATFORM_ERRNO_OOM;
    			retval = Platform_EFAIL;
    			goto FLASHWRITE_ERROR;
    		}
    
    		/* Get starting address */
    		addr.uiColumnAddr= 0;
    		if (platform_offset_to_blocknpage(deviceid, offset, &addr.uiBlockAddr, &addr.uiPageAddr) != Platform_EOK) {
    			retval = Platform_EUNSUPPORTED;
    			goto FLASHWRITE_ERROR;
    		}
    
    		/*
    		 * We can now write the file to flash. The basic algorithm is this:
    		 *  Read the bad block table
    		 *  While we have data to write do
    		 *     skip block if bad
    		 *     read the block   (page level)
    		 *     erase the block  (block level)
    		 *     write the block	(page level)
    		 */
    
    		/* set index to start of the data to write */
    		bufindex = 0;
    
    		/* Initialize the starting block we will be using */
    		block 	= addr.uiBlockAddr;
    		StartAddress.uiBlockAddr  = addr.uiBlockAddr;
    		StartAddress.uiPageAddr	  = addr.uiPageAddr;
    		StartAddress.uiColumnAddr = 0;
    
    		while (len) {
    
    			/* Skip bad blocks */
    			if (p_device->bblist) {
    				if (p_device->bblist[block] == 0x00) {
    					/* Block is bad, skip to next good one */
    					IFPRINT(platform_write( "platform_device_write: Skipping bad block %d. \n", block));
    					block++;
    					while (p_device->bblist[block] == 0x00) {
    						block++;
    					}
    				}
    			}
    
    			/* Make sure we didn't exceed number of blocks  */
    			if (block > p_device->block_count) {
    				IFPRINT(platform_write( "Due to bad blocks, you have run out of room in the Flash for this image. \n"));
    				platform_errno = PLATFORM_ERRNO_NOFREEBLOCKS;
    				retval = Platform_EFAIL;
    				goto FLASHWRITE_ERROR;
    			}
    
    			IFPRINT(platform_write( "platform_device_write: Writing block %d \n", block));
    
    			/*
    			 * Read the block..
    			 *    may need to preserve what we don't actually write out.
    			 */
    			for (page=0, index = 0; page < p_device->page_count;
    				 page ++, index +=p_device->page_size) {
    				addr.uiBlockAddr = block;
    				addr.uiPageAddr	 = page;
    				addr.uiColumnAddr= 0;
    				if (p_device->handle == PLATFORM_DEVID_NAND512R3A2D) {
    #if (PLATFORM_NAND_WRITE_IN)
    
    					if (readNandPage (&gDeviceNand, addr, (uint8_t *)(pBlock + index)) != SUCCESS) {
    						retval = Platform_EFAIL;
    						IFPRINT(platform_write( "platform_device_write: Error reading block %d page %d. \n", block, page));
    						goto FLASHWRITE_ERROR;
    					}
    #endif
    				}
    			    else {
    #if (PLATFORM_NOR_WRITE_IN)
    			    	(void) platform_blocknpage_to_offset(p_device->handle, &noraddress, addr.uiBlockAddr, addr.uiPageAddr);
    			    	 if (nor_read (&gDeviceNor, noraddress, p_device->page_size, (uint8_t *)(pBlock + index)) != SUCCESS) {
    						 retval = Platform_EFAIL;
    						 platform_write( "platform_device_write: Error reading block %d page %d. \n", block, page);
    						 goto FLASHWRITE_ERROR;
    			    	}
    #endif
    			    }
    			}
    
    			/* erase the block */
    			if (p_device->handle == PLATFORM_DEVID_NAND512R3A2D) {
    #if (PLATFORM_NAND_WRITE_IN)
    				if (nandFlashBlockErase (&gDeviceNand, block) != SUCCESS) {
    					IFPRINT(platform_write( "platform_device_write: Could not erase block %d. \n", block));
    					retval = Platform_EFAIL;
    					goto FLASHWRITE_ERROR;
    				}
    #endif
    			}
    			else {
    #if (PLATFORM_NOR_WRITE_IN)
    			    if (nor_erase (&gDeviceNor, block) != SUCCESS) {
    					IFPRINT(platform_write( "platform_device_write: Could not erase block %d. \n", block));
    					retval = Platform_EFAIL;
    					goto FLASHWRITE_ERROR;
    			    }
    #endif
    			}
    
    			/*
    			 * Write the block...
    			 * 	 - Get one page of data and write out or
    			 *   - if we run out of data re-write what we previously read.
    			 */
    			for (page = 0, index = 0; page < p_device->page_count;
    				 page ++, index +=p_device->page_size) {
    
    				IFPRINT(platform_write( "platform_device_write: Writing to block %d page %d \n", block, page));
    
    				if (block == StartAddress.uiBlockAddr && page < StartAddress.uiPageAddr) {
    				   /* if we are within the first block we are writing, then we may have a start
    					* page other than page 0, so re-write what was there.
    					*/
    					memcpy(pPage, (pBlock+bufindex), useable_page_size);
    				}
    				else
    				if (len == 0) {
    					/* we wrote all the data, so write back any pages we pre-read that are left */
    					memcpy(pPage, (pBlock+bufindex), useable_page_size);
    				}
    				else
    				if (len < useable_page_size) {
    					/* we have less than a full page of data */
    					memset(pPage, 0xFF, p_device->page_size);
    					memcpy(pPage, (buf+bufindex), len);
    					len = 0;
    				}
    				else {
    					/* get a full page of data */
    					memcpy(pPage, (buf+bufindex), useable_page_size);
    					len -= useable_page_size;
    					bufindex += useable_page_size;
    				}
    				/* write the page */
    				addr.uiBlockAddr = block;
    				addr.uiPageAddr	 = page;
    				addr.uiColumnAddr= 0;
    				if (p_device->handle == PLATFORM_DEVID_NAND512R3A2D) {
    #if (PLATFORM_NAND_WRITE_IN)
    					if (writeNandPage (&gDeviceNand, addr, pPage) != SUCCESS) {
    						IFPRINT(platform_write( "platform_device_write: Error writing block %d page %d. \n", block, page));
    						retval = Platform_EFAIL;
    						goto FLASHWRITE_ERROR;
    					}
    #endif
    				}
    				else {
    #if (PLATFORM_NOR_WRITE_IN)
    			    	(void) platform_blocknpage_to_offset(p_device->handle, &noraddress, addr.uiBlockAddr, addr.uiPageAddr);
    					if (nor_write(&gDeviceNor, noraddress,  p_device->page_size, pPage) != SUCCESS) {
    						IFPRINT(platform_write( "platform_device_write: Error writing block %d page %d. \n", block, page));
    						retval = Platform_EFAIL;
    						goto FLASHWRITE_ERROR;
    					}
    #endif
    				}
    			}
    
    			/* increment to the next block */
    			block++;
    		}
    	
    FLASHWRITE_ERROR:
    
    		if (pBlock) {
    			Osal_platformFree( pBlock, platform_roundup(block_size, PLATFORM_CACHE_LINE_SIZE) );
    		}
    
    		if (pPage) {
    			Osal_platformFree( pPage, platform_roundup(p_device->page_size, PLATFORM_CACHE_LINE_SIZE));
    		}
    
    		return retval;
    	}
    #endif
    
    #if (PLATFORM_EEPROM_IN) && (PLATFORM_EEPROM_WRITE_IN)
    
    	if (deviceid == PLATFORM_DEVID_EEPROM50) {
    	   if (i2cEepromWriteByteAddr(offset, 0x50, buf, len, I2C_RELEASE_BUS) != I2C_RET_OK) {
    	       IFPRINT(platform_write("platform_device_write: EEPROM write for address 0x%x failed\n", 0x50));
    	       platform_errno = PLATFORM_ERRNO_EEPROM;
    	       return ( (Platform_STATUS) Platform_EFAIL);
    	    }
        	return Platform_EOK;
    	}
    
    	if (deviceid == PLATFORM_DEVID_EEPROM51) {
    	   if (i2cEepromWriteByteAddr(offset, 0x51, buf, len, I2C_RELEASE_BUS) != I2C_RET_OK) {
    	       IFPRINT(platform_write("platform_device_write: EEPROM write for address 0x%x failed\n", 0x51));
    	       platform_errno = PLATFORM_ERRNO_EEPROM;
    	       return ( (Platform_STATUS) Platform_EFAIL);
    	    }
        	return Platform_EOK;
    	}
    
    #endif
    
    	return Platform_EUNSUPPORTED;
    
    }
    #endif
    									
    /******************************************************************************
     * platform_flash_erase_block
     ******************************************************************************/
    #if (PLATFORM_NAND_IN) || (PLATFORM_NOR_IN) || (PLATFORM_EEPROM_IN)
    Platform_STATUS platform_device_erase_block(PLATFORM_DEVHANDLE	deviceid,
                                               uint32_t block_number) {
    
    	IFPRINT(platform_write("platform_device_erase_block(handle=0x%x, blockt=%d) called \n",
    			deviceid, block_number));
    
    #if (PLATFORM_NAND_IN) && (PLATFORM_NAND_WRITE_IN)
    	if (deviceid == PLATFORM_DEVID_NAND512R3A2D) {
    		if (block_number >= gDeviceNand.block_count) {
    			platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
    			return Platform_EINVALID;
    		}
    	    if (nandFlashBlockErase (&gDeviceNand, block_number) != SUCCESS) {
    	        return ( (Platform_STATUS) Platform_EFAIL);
    	    }		    
           	return Platform_EOK;
    	}
    #endif
    
    #if (PLATFORM_NOR_IN) && (PLATFORM_NOR_WRITE_IN)
    	if (deviceid == PLATFORM_DEVID_NORN25Q128) {
    		if (block_number > gDeviceNor.block_count) {
    			platform_errno = PLATFORM_ERRNO_INVALID_ARGUMENT;
    			return Platform_EINVALID;
    		}
    	    if (nor_erase (&gDeviceNor, block_number) != SUCCESS) {
    	        return ( (Platform_STATUS) Platform_EFAIL);
    	    }
         	return Platform_EOK;   
    	}
    #endif
    
    	return Platform_EUNSUPPORTED;
    }
    #endif
    																
    
    #if PLATFORM_CACHE_IN
    uint32_t Convert_CoreLocal2GlobalAddr (uint32_t  addr)
    {
        uint32_t coreNum;
    
        /* Get the core number. */
    #ifdef SIMULATOR_SUPPORT
        coreNum = CSL_chipReadDNUM();
    #else
        coreNum = platform_get_coreid();
    #endif
        /* Check if the address is a valid Local L2 address to convert */
        if ( (addr >= (uint32_t) 0x800000) &&
             (addr <  (uint32_t) 0x880000) ) {
             /* Compute the global address. */
             return ((1 << 28) | (coreNum << 24) | (addr & 0x00ffffff));
        }
        else {
            return (addr);
        }
    }
    #endif
    
    

    and modify in the i2cConfig.gel file


        ibl.bootModes[1].u.nandBoot.bootFormat        = ibl_BOOT_FORMAT_BBLOB; /* ibl_BOOT_FORMAT_BBLOB ibl_BOOT_FORMAT_ELF; */
        ibl.bootModes[1].u.nandBoot.bootAddress[0][0]   = 0x20000;         /* Image 0 NAND offset address (block 1) in LE mode */
        ibl.bootModes[1].u.nandBoot.bootAddress[0][1]   = 0x4000000;      /* Image 1 NAND offset address (block 512) in LE mode */
        ibl.bootModes[1].u.nandBoot.bootAddress[1][0]   = 0x4000;     /* Image 0 NAND offset address (block 1) in BE mode */
        ibl.bootModes[1].u.nandBoot.bootAddress[1][1]   = 0x2000000;      /* Image 1 NAND offset address (block 2048) in BE mode */
        ibl.bootModes[1].u.nandBoot.interface         = ibl_PMEM_IF_CHIPSEL_2;


        ibl.bootModes[1].u.nandBoot.nandInfo.busWidthBits  = 8;
        ibl.bootModes[1].u.nandBoot.nandInfo.pageSizeBytes = 2048;
        ibl.bootModes[1].u.nandBoot.nandInfo.pageEccBytes  = 64;
        ibl.bootModes[1].u.nandBoot.nandInfo.pagesPerBlock = 64;
        ibl.bootModes[1].u.nandBoot.nandInfo.totalBlocks   = 1024;

        ibl.bootModes[1].u.nandBoot.nandInfo.addressBytes  = 4;
        ibl.bootModes[1].u.nandBoot.nandInfo.lsbFirst      = TRUE;
        ibl.bootModes[1].u.nandBoot.nandInfo.blockOffset   = 22;
        ibl.bootModes[1].u.nandBoot.nandInfo.pageOffset    = 16;
        ibl.bootModes[1].u.nandBoot.nandInfo.columnOffset  = 0;

    And add a define target.h that "#define NAND_TYPE_LARGE" in the target.h( C:\ti\mcsdk_2_01_02_06\tools\boot_loader\ibl\src\device\c66x )

    modify  a    #define PACK_ADDR(col, page, block) \
                      ((col & 0x00000fff) | ((page & 0x0000003f)<<16) | ((block & 0x000003ff) << 22 ))

    After modify that the NAND writer is running, the existing IBL was rebuilt and used.

    Please review it.

  • Hi.

    We are in the middle of a NAND boot problem. ( NAND device change )
    I've posted the progress data, so please advise me.

    Thank you.!~

  • 1. IBL is a software that runs post ROM boot. When the boot fails are you able to connect JTAG And see if the ROM is still hung in L2ROM or has it loaded the IBL from I2C EEPROM into MSMC ? If it is executing from MSMC, you should be able to load symbols and see what function it is hung in.

    http://software-dl.ti.com/processor-sdk-rtos/esd/docs/latest/rtos/index_Foundational_Components.html#software-debug-steps

    2. Please note that it is important for NAND devices that the NAND is erased prior to programming the block and page data. When you are confirming the programming, can you also confirm that the page data looks correct. Also, pay close attention to whether ECC data is generated correctly on the correct EMIF CE and also that the ECC data is stored in the right format in the NAND.  There are some additional tips for NAND boot on C6678 provided here:

    NAND Boot FAQ

    Regards,

    Rahul

  • Thanks.

    We used a board with 6678 devices for three years.
    They are asking questions due to changes in NAND flash chips.

    <JTAG connect status>  in boot fail status

    <consol view>

    It seems to be comprehensive information.

    I want to know about changes in source code and configuration etc.in IBL or nand writer (only change nand flash)

    .

  • Hi.

    Is there other contents???

    ......

  • ForLee,

    Sorry for the delay in getting back to you on this issue.  It appears that you are able to get the IBL booting from I2C but then you are not able to connect to the core to debug the setup further. I would recommend either adding a while loop on a spinlock at the start of main. So it allows you to connect and step through the IBL and see what causes the DSP hang.

    The other thing that may help is to see if the EMIF pins are toggling after the chnages that you have made. At the bare-minimum, you need the IBL code to read the NAND ID and geometry and find if the ONFI NAND is supported. Does the NAND you are using have a WAITENABLE pin.

    If the platform lib is updated and the nand writer is working with the change the same platform_lib gets used in IBL so no reason for this to not work. Looking at the EMIF/NAND flash pins may provide more insight but also try to add the while loop as described here:

    http://software-dl.ti.com/processor-sdk-rtos/esd/docs/latest/rtos/index_Foundational_Components.html#software-debug-steps (Adding spinlock)

    If you are able to connect before the DSP is hung, you can monitor the NAND strctures to see if correct geometry is detected.

    Regards,

    Rahul

  • Thank you for reply.

    I waited your reply for long time.


    I solved through C6657 SDK

    Have a good day.