Implementing the Flash Memory Erase Functions

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

Note   If you want your boot loader to be more secure and validate the downloaded 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 image start address and total image length. The image start address and total image length specify the overall flash memory address range to be erased for the new image.
OEMContinueEraseFlash Called on every image .bin record download to allow the boot loader to continue the flash memory erase operation.
OEMFinishEraseFlash Called after the 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

How to Develop a Boot Loader

Last updated on Wednesday, April 13, 2005

© 2005 Microsoft Corporation. All rights reserved.