Implementing the Flash Memory Erase Functions (Windows Embedded CE 6.0)

1/5/2010

The flash memory erase functions enable flash memory erase operations to occur before, during, and after the run-time image download operation. The BLCOMMON library calls these functions.

Note

If you want your boot loader to be more secure and validate the downloaded run-time image before altering flash memory, you should keep the stubbed versions of the flash memory erase functions and implement the erase and write operations in OEMWriteFlash.

The flash memory erase functions can be implemented in many different ways and the implementation is mostly dependent on the flash memory technology being used in your hardware platform.

For example, some flash memory technologies allow for N blocks to be marked for erasure in parallel, while in many cases, the flash memory is erased in sequential block order.

The following table shows the flash memory erase functions that you need to implement.

Function Description

OEMStartEraseFlash

Called when the download process begins, and provides the overall run-time image start address and total run-time image length.

The run-time image start address and total run-time image length specify the overall flash memory address range to be erased for the new run-time image.

OEMContinueEraseFlash

Called on every run-time image .bin record download to allow the boot loader to continue the flash memory erase operation.

OEMFinishEraseFlash

Called after the run-time image is completely downloaded and allows the boot loader to finish all flash memory erase operations.

To implement flash memory erase functions

  • Edit the file Flash.c by adding the code necessary to fully implement the flash memory erase functions.

    The following code example shows the implementation of the flash memory erase functions for the hardware platform used in this boot loader example.

    BOOL OEMStartEraseFlash (DWORD dwStartAddr, DWORD dwLength)
    {
        ULONG i = 0;
        ULONG nNumBlocks = 0;
    
        //
        // Be sure the start and end addresses are in flash.
        //
        if (!OEMIsFlashAddr(dwStartAddr) || !OEMIsFlashAddr(dwStartAddr + dwLength - 1))
        {
            EdbgOutputDebugString("ERROR: OEMStartEraseFlash - not a flash address (0x%x or 0x%x).\r\n", dwStartAddr, (dwStartAddr + dwLength - 1));
            return(FALSE);
        }
    
        // 
        // Be sure start address is block-aligned.
        //
        if (dwStartAddr % FLASH_BLOCK_SIZE)
        {
            EdbgOutputDebugString("ERROR: OEMStartEraseFlash - start address isn't block aligned (0x%x).\r\n", dwStartAddr);
            return(FALSE);
        }
        if (dwLength & 0x03)
        {
            EdbgOutputDebugString("ERROR: OEMStartEraseFlash - length isn't an integral number of longwords (0x%x).\r\n", dwLength);
            return(FALSE);
        }
    
        //
        // Clear the flash cache, where the image will be stored during download.
        //
        //memset((void *)FCACHE, 0, dwLength);
    
        //
        // Determine affected flash blocks.
        //
        gnStartBlock = (dwStartAddr - FLASH_BASE) / FLASH_BLOCK_SIZE;
        gnEndBlock   = ((dwStartAddr + dwLength + (FLASH_BLOCK_SIZE - 1) - FLASH_BASE) / FLASH_BLOCK_SIZE);
        gnBlocks     = (int)(gnEndBlock - gnStartBlock);
        gnBlockCount = gnStartBlock;
    
        EdbgOutputDebugString("Erasing flash blocks: start block = %d  end block = %d\r\n", gnStartBlock, gnEndBlock);
    
        return(TRUE);
    }
    
    void OEMContinueEraseFlash(void)
    {
        UCHAR nEraseCount = BLOCK_ERASE_STEP;   // Number of blocks to erase...
    
        // 
        // Verify that all the blocks have been erased.
        //
        if (!gnBlocks || (gnBlockCount == gnEndBlock))
            return;
    
        //
        // Erase a few blocks.
        //
        while ((gnBlockCount < gnEndBlock) && nEraseCount)
        {
            if (CFI_Erase_Block((unsigned32*)BLOCK_ADDR(gnBlockCount), 0, NULL) != PASS)
            {
                EdbgOutputDebugString("ERROR: OEMContinueEraseFlash - flash erase error (block number %d).\r\n", gnBlockCount);
                return;
            }
    
            ++gnBlockCount;
            --nEraseCount;
        }
    
        return;
    }
    
    BOOL OEMFinishEraseFlash(void)
    {
    
        EdbgOutputDebugString("INFO: Finishing flash erase...\r\n");
    
        while(gnBlocks && (gnBlockCount != gnEndBlock))
        {
            OEMContinueEraseFlash();
        }
    
        return(TRUE);
    }
    
    void OEMContinueEraseFlash(void)
    {
        UCHAR nEraseCount = BLOCK_ERASE_STEP;   // Number of blocks to erase...
    
        // 
        // Verify that all the blocks have been erased.
        //
        if (!gnBlocks || (gnBlockCount == gnEndBlock))
            return;
    
        //
        // Erase a few blocks...
        //
        while ((gnBlockCount < gnEndBlock) && nEraseCount)
        {
            if (CFI_Erase_Block((unsigned32*)BLOCK_ADDR(gnBlockCount), 0, NULL) != PASS)
            {
                EdbgOutputDebugString("ERROR: OEMContinueEraseFlash - flash erase error (block number %d).\r\n", gnBlockCount);
                return;
            }
    
            ++gnBlockCount;
            --nEraseCount;
        }
    
        return;
    }
    

See Also

Tasks

How to Develop a Boot Loader