//***************************************************************************** // //! 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; }
//***************************************************************************** // //! 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; }