Beispiel #1
0
//*****************************************************************************
//
//! Initializes the flash parameter block.
//!
//! \param ulStart is the address of the flash memory to be used for storing
//! flash parameter blocks; this must be the start of an erase block in the
//! flash.
//! \param ulEnd is the address of the end of flash memory to be used for
//! storing flash parameter blocks; this must be the start of an erase block in
//! the flash (the first block that is NOT part of the flash memory to be
//! used), or the address of the first word after the flash array if the last
//! block of flash is to be used.
//! \param ulSize is the size of the parameter block when stored in flash;
//! this must be a power of two less than or equal to the flash erase block
//! size (typically 1024).
//!
//! This function initializes a fault-tolerant, persistent storage mechanism
//! for a parameter block for an application.  The last several erase blocks
//! of flash (as specified by \e ulStart and \e ulEnd are used for the
//! storage; more than one erase block is required in order to be
//! fault-tolerant.
//!
//! A parameter block is an array of bytes that contain the persistent
//! parameters for the application.  The only special requirement for the
//! parameter block is that the first byte is a sequence number (explained
//! in FlashPBSave()) and the second byte is a checksum used to validate the
//! correctness of the data (the checksum byte is the byte such that the sum of
//! all bytes in the parameter block is zero).
//!
//! The portion of flash for parameter block storage is split into N
//! equal-sized regions, where each region is the size of a parameter block
//! (\e ulSize).  Each region is scanned to find the most recent valid
//! parameter block.  The region that has a valid checksum and has the highest
//! sequence number (with special consideration given to wrapping back to zero)
//! is considered to be the current parameter block.
//!
//! In order to make this efficient and effective, three conditions must be
//! met.  The first is \e ulStart and \e ulEnd must be specified such that at
//! least two erase blocks of flash are dedicated to parameter block storage.
//! If not, fault tolerance can not be guaranteed since an erase of a single
//! block will leave a window where there are no valid parameter blocks in
//! flash.  The second condition is that the size (\e ulSize) of the parameter
//! block must be an integral divisor of the size of an erase block of flash.
//! If not, a parameter block will end up spanning between two erase blocks of
//! flash, making it more difficult to manage.  The final condition is that the
//! size of the flash dedicated to parameter blocks (\e ulEnd - \e ulStart)
//! divided by the parameter block size (\e ulSize) must be less than or equal
//! to 128.  If not, it will not be possible in all cases to determine which
//! parameter block is the most recent (specifically when dealing with the
//! sequence number wrapping back to zero).
//!
//! When the microcontroller is initially programmed, the flash blocks used for
//! parameter block storage are left in an erased state.
//!
//! This function must be called before any other flash parameter block
//! functions are called.
//!
//! \return None.
//
//*****************************************************************************
void
FlashPBInit(unsigned long ulStart, unsigned long ulEnd, unsigned long ulSize)
{
    unsigned char *pucOffset, *pucCurrent;
    unsigned char ucOne, ucTwo;

    //
    // Check the arguments.
    //
    ASSERT((ulStart % FLASH_ERASE_SIZE) == 0);
    ASSERT((ulEnd % FLASH_ERASE_SIZE) == 0);
    ASSERT((FLASH_ERASE_SIZE % ulSize) == 0);

    //
    // Set the number of clocks per microsecond to enable the flash controller
    // to properly program the flash.
    //
    FlashUsecSet(SysCtlClockGet() / 1000000);

    //
    // Save the characteristics of the flash memory to be used for storing
    // parameter blocks.
    //
    g_pucFlashPBStart = (unsigned char *)ulStart;
    g_pucFlashPBEnd = (unsigned char *)ulEnd;
    g_ulFlashPBSize = ulSize;

    //
    // Loop through the portion of flash memory used for storing parameter
    // blocks.
    //
    for(pucOffset = g_pucFlashPBStart, pucCurrent = 0;
        pucOffset < g_pucFlashPBEnd; pucOffset += g_ulFlashPBSize)
    {
        //
        // See if this is a valid parameter block (i.e. the checksum is
        // correct).
        //
        if(FlashPBIsValid(pucOffset))
        {
            //
            // See if a valid parameter block has been previously found.
            //
            if(pucCurrent != 0)
            {
                //
                // Get the sequence numbers for the current and new parameter
                // blocks.
                //
                ucOne = pucCurrent[0];
                ucTwo = pucOffset[0];

                //
                // See if the sequence number for the new parameter block is
                // greater than the current block.  The comparison isn't
                // straightforward since the one byte sequence number will wrap
                // after 256 parameter blocks.
                //
                if(((ucOne > ucTwo) && ((ucOne - ucTwo) < 128)) ||
                   ((ucTwo > ucOne) && ((ucTwo - ucOne) > 128)))
                {
                    //
                    // The new parameter block is older than the current
                    // parameter block, so skip the new parameter block and
                    // keep searching.
                    //
                    continue;
                }
            }

            //
            // The new parameter block is more recent than the current one, so
            // make it the new current parameter block.
            //
            pucCurrent = pucOffset;
        }
    }

    //
    // Save the address of the most recent parameter block found.  If no valid
    // parameter blocks were found, this will be a NULL pointer.
    //
    g_pucFlashPBCurrent = pucCurrent;
}
Beispiel #2
0
//*****************************************************************************
//
//! Initializes the flash parameter block.
//!
//! \param ui32Start is the address of the flash memory to be used for storing
//! flash parameter blocks; this must be the start of an erase block in the
//! flash.
//! \param ui32End is the address of the end of flash memory to be used for
//! storing flash parameter blocks; this must be the start of an erase block in
//! the flash (the first block that is NOT part of the flash memory to be
//! used), or the address of the first word after the flash array if the last
//! block of flash is to be used.
//! \param ui32Size is the size of the parameter block when stored in flash;
//! this must be a power of two less than or equal to the flash erase block
//! size (typically 1024).
//!
//! This function initializes a fault-tolerant, persistent storage mechanism
//! for a parameter block for an application.  The last several erase blocks
//! of flash (as specified by \e ui32Start and \e ui32End are used for the
//! storage; more than one erase block is required in order to be
//! fault-tolerant.
//!
//! A parameter block is an array of bytes that contain the persistent
//! parameters for the application.  The only special requirement for the
//! parameter block is that the first byte is a sequence number (explained
//! in FlashPBSave()) and the second byte is a checksum used to validate the
//! correctness of the data (the checksum byte is the byte such that the sum of
//! all bytes in the parameter block is zero).
//!
//! The portion of flash for parameter block storage is split into N
//! equal-sized regions, where each region is the size of a parameter block
//! (\e ui32Size).  Each region is scanned to find the most recent valid
//! parameter block.  The region that has a valid checksum and has the highest
//! sequence number (with special consideration given to wrapping back to zero)
//! is considered to be the current parameter block.
//!
//! In order to make this efficient and effective, three conditions must be
//! met.  The first is \e ui32Start and \e ui32End must be specified such that
//! at least two erase blocks of flash are dedicated to parameter block
//! storage.  If not, fault tolerance can not be guaranteed since an erase of a
//! single block will leave a window where there are no valid parameter blocks
//! in flash.  The second condition is that the size (\e ui32Size) of the
//! parameter block must be an integral divisor of the size of an erase block
//! of flash.  If not, a parameter block will end up spanning between two erase
//! blocks of flash, making it more difficult to manage.  The final condition
//! is that the size of the flash dedicated to parameter blocks (\e ui32End -
//! \e ui32Start) divided by the parameter block size (\e ui32Size) must be
//! less than or equal to 128.  If not, it will not be possible in all cases to
//! determine which parameter block is the most recent (specifically when
//! dealing with the sequence number wrapping back to zero).
//!
//! When the microcontroller is initially programmed, the flash blocks used for
//! parameter block storage are left in an erased state.
//!
//! This function must be called before any other flash parameter block
//! functions are called.
//!
//! \return None.
//
//*****************************************************************************
void
FlashPBInit(uint32_t ui32Start, uint32_t ui32End, uint32_t ui32Size)
{
    uint8_t *pui8Offset, *pui8Current;
    uint8_t ui8One, ui8Two;

    //
    // Check the arguments.
    //
    ASSERT((ui32Start % FLASH_SECTOR_SIZE) == 0);
    ASSERT((ui32End % FLASH_SECTOR_SIZE) == 0);
    ASSERT((FLASH_SECTOR_SIZE % ui32Size) == 0);

    //
    // Save the characteristics of the flash memory to be used for storing
    // parameter blocks.
    //
    g_pui8FlashPBStart = (uint8_t *)ui32Start;
    g_pui8FlashPBEnd = (uint8_t *)ui32End;
    g_ui32FlashPBSize = ui32Size;

    //
    // Loop through the portion of flash memory used for storing parameter
    // blocks.
    //
    for(pui8Offset = g_pui8FlashPBStart, pui8Current = 0;
        pui8Offset < g_pui8FlashPBEnd; pui8Offset += g_ui32FlashPBSize)
    {
        //
        // See if this is a valid parameter block (in other words, the checksum
        // is correct).
        //
        if(FlashPBIsValid(pui8Offset))
        {
            //
            // See if a valid parameter block has been previously found.
            //
            if(pui8Current != 0)
            {
                //
                // Get the sequence numbers for the current and new parameter
                // blocks.
                //
                ui8One = pui8Current[0];
                ui8Two = pui8Offset[0];

                //
                // See if the sequence number for the new parameter block is
                // greater than the current block.  The comparison isn't
                // straightforward since the one byte sequence number will wrap
                // after 256 parameter blocks.
                //
                if(((ui8One > ui8Two) && ((ui8One - ui8Two) < 128)) ||
                   ((ui8Two > ui8One) && ((ui8Two - ui8One) > 128)))
                {
                    //
                    // The new parameter block is older than the current
                    // parameter block, so skip the new parameter block and
                    // keep searching.
                    //
                    continue;
                }
            }

            //
            // The new parameter block is more recent than the current one, so
            // make it the new current parameter block.
            //
            pui8Current = pui8Offset;
        }
    }

    //
    // Save the address of the most recent parameter block found.  If no valid
    // parameter blocks were found, this will be a NULL pointer.
    //
    g_pui8FlashPBCurrent = pui8Current;
}