/*********************************************************************
 * @fn      OADTarget_writeFlash
 *
 * @brief   Write data to flash.
 *
 * @param   page   - page to write to in flash
 * @param   offset - offset into flash page to begin writing
 * @param   pBuf   - pointer to buffer of data to write
 * @param   len    - length of data to write in bytes
 *
 * @return  None.
 */
void OADTarget_writeFlash(uint8_t page, uint32_t offset, uint8_t *pBuf, 
                          uint16_t len)
{
  OADTarget_disableCache();
  
  ROM_FlashProgram( pBuf, (uint32_t)FLASH_ADDRESS(page, offset), len );
  
  OADTarget_enableCache();
}
예제 #2
0
//*****************************************************************************
//
// Read the application image from the file system and program it into flash.
//
// This function will attempt to open and read the firmware image file from
// the mass storage device.  If the file is found it will be programmed into
// flash.  The name of the file to be read is configured by the macro
// \b USB_UPDATE_FILENAME.  It will be programmed into flash starting at the
// address specified by APP_START_ADDRESS.
//
// \return Zero if successful or non-zero if the file cannot be read or
// programmed.
//
//*****************************************************************************
uint32_t
ReadAppAndProgram(void)
{
    uint_fast32_t ui32FlashEnd;
    uint_fast32_t ui32FileSize;
    uint_fast32_t ui32DataSize;
    uint_fast32_t ui32Remaining;
    uint_fast32_t ui32ProgAddr;
    uint_fast32_t ui32SavedRegs[2];
    volatile uint_fast32_t ui32Idx;
    uint_fast32_t ui32DriveTimeout;

    //
    // Initialize the drive timeout.
    //
    ui32DriveTimeout = USBMSC_DRIVE_RETRY;

    //
    // Check to see if the mass storage device is ready.  Some large drives
    // take a while to be ready, so retry until they are ready.
    //
    while(USBHMSCDriveReady(g_psMSCInstance))
    {
        //
        // Wait about 500ms before attempting to check if the
        // device is ready again.
        //
        SysCtlDelay(SysCtlClockGet()/(3*2));

        //
        // Decrement the retry count.
        //
        ui32DriveTimeout--;

        //
        // If the timeout is hit then return with a failure.
        //
        if(ui32DriveTimeout == 0)
        {
            return(1);
        }
    }

    //
    // Initialize the file system and return if error.
    //
    if(SimpleFsInit(g_ui8SectorBuf))
    {
        return(1);
    }

    //
    // Attempt to open the firmware file, retrieving the file/image size.
    // A file size of error means the file was not there, or there was an
    // error.
    //
    ui32FileSize = SimpleFsOpen(USB_UPDATE_FILENAME);
    if(ui32FileSize == 0)
    {
        return(1);
    }

    //
    // Get the size of flash.  This is the ending address of the flash.
    // If reserved space is configured, then the ending address is reduced
    // by the amount of the reserved block.
    //
    ui32FlashEnd = FLASH_SIZE;
#ifdef FLASH_RSVD_SPACE
    ui32FlashEnd -= FLASH_RSVD_SPACE;
#endif

    //
    // If flash code protection is not used, then change the ending address
    // to be the ending of the application image.  This will be the highest
    // flash page that will be erased and so only the necessary pages will
    // be erased.  If flash code protection is enabled, then all of the
    // application area pages will be erased.
    //
#ifndef FLASH_CODE_PROTECTION
    ui32FlashEnd = ui32FileSize + APP_START_ADDRESS;
#endif

    //
    // Check to make sure the file size is not too large to fit in the flash.
    // If it is too large, then return an error.
    //
    if((ui32FileSize + APP_START_ADDRESS) > ui32FlashEnd)
    {
        return(1);
    }

    //
    // Enter a loop to erase all the requested flash pages beginning at the
    // application start address (above the USB stick updater).
    //
    for(ui32Idx = APP_START_ADDRESS; ui32Idx < ui32FlashEnd; ui32Idx += 1024)
    {
        ROM_FlashErase(ui32Idx);
    }

    //
    // Enter a loop to read sectors from the application image file and
    // program into flash.  Start at the user app start address (above the USB
    // stick updater).
    //
    ui32ProgAddr = APP_START_ADDRESS;
    ui32Remaining = ui32FileSize;
    while(SimpleFsReadFileSector())
    {
        //
        // Compute how much data was read from this sector and adjust the
        // remaining amount.
        //
        ui32DataSize = ui32Remaining >= 512 ? 512 : ui32Remaining;
        ui32Remaining -= ui32DataSize;

        //
        // Special handling for the first block of the application.
        // This block contains as the first two location the application's
        // initial stack pointer and instruction pointer.  The USB updater
        // relied on the values in these locations to determine if a valid
        // application is present.  When there is a valid application the
        // updater runs the user application.  Otherwise the updater attempts
        // to load a new application.
        // In order to prevent a partially programmed imaged (due to some
        // error occurring while programming), the first two locations are
        // not programmed until all of the rest of the image has been
        // successfully loaded into the flash.  This way if there is some error,
        // the updater will detect that a user application is not present and
        // will not attempt to run it.
        //
        // For the first block, do not program the first two word locations
        // (8 bytes).  These two words will be programmed later, after
        // everything else.
        //
        if(ui32ProgAddr == APP_START_ADDRESS)
        {
            uint32_t *pui32Temp;

            pui32Temp = (uint32_t *)g_ui8SectorBuf;
            ui32SavedRegs[0] = pui32Temp[0];
            ui32SavedRegs[1] = pui32Temp[1];

            //
            // Call the function to program a block of flash.  Skip the first
            // two words (8 bytes) since these contain the initial SP and PC.
            //
            ROM_FlashProgram((uint32_t *)&g_ui8SectorBuf[8],
                             ui32ProgAddr + 8,
                             ((ui32DataSize - 8) + 3) & ~3);
        }

        //
        // All other blocks except the first block
        //
        else
        {
            //
            // Call the function to program a block of flash.  The length of the
            // block passed to the flash function must be divisible by 4.
            //
            ROM_FlashProgram((uint32_t *)g_ui8SectorBuf, ui32ProgAddr,
                             (ui32DataSize + 3) & ~3);
        }

        //
        // If there is more image to program, then update the programming
        // address.  Progress will continue to the next iteration of
        // the while loop.
        //
        if(ui32Remaining)
        {
            ui32ProgAddr += ui32DataSize;
        }

        //
        // Otherwise we are done programming so perform final steps.
        // Program the first two words of the image that were saved earlier,
        // and return a success indication.
        //
        else
        {
            ROM_FlashProgram((uint32_t *)ui32SavedRegs, APP_START_ADDRESS,
                              8);

            return(0);
        }
    }

    //
    // If we make it here, that means that an attempt to read a sector of
    // data from the device was not successful.  That means that the complete
    // user app has not been programmed into flash, so just return an error
    // indication.
    //
    return(1);
}