📄 flash_pb.c
字号:
//*****************************************************************************
//
// flash_pb.c - Flash parameter block functions.
//
// Copyright (c) 2007-2008 Luminary Micro, Inc. All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 716 of the BLDC motor application.
//
//*****************************************************************************
#include "../../DriverLib/hw_types.h"
#include "../../DriverLib/src/flash.h"
#include "../../DriverLib/src/sysctl.h"
#include "flash_pb.h"
//*****************************************************************************
//
//! \page flash_pb_intro Introduction
//!
//! This module provides a fault-tolerant, persistent storage mechanism for the
//! parameter block of the motor drive. The last several pages of flash are
//! used for the storage; more than one page is required in order to be
//! fault-tolerant.
//!
//! Parameter blocks are an array of bytes that contain the persistent
//! parameters of the motor drive. The only special requirement for the
//! parameter block is that the first byte is a sequence number (explained
//! later) 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.
//! Each region is scanned at startup; 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.
//! The contents of this region of flash are loaded into SRAM as the current
//! parameters for the motor drive.
//!
//! Saving new parameter blocks involves three steps:
//!
//! - Setting the sequence number such that it is one greater than the sequence
//! number of the latest parameter block in flash.
//! - Computing the checksum of the parameter block.
//! - Writing the parameter block into the storage immediately following the
//! latest parameter block in flash; if that storage is at the start of an
//! erase block, that block is erased first.
//!
//! By this process, there is always a valid parameter block in flash. If
//! power is lost while writing a new parameter block, the checksum will not
//! match and the partially written parameter block will be ignored. This is
//! what makes this fault-tolerant.
//!
//! Another benefit of this scheme is that it provides wear leveling on the
//! flash. Since multiple parameter blocks fit into each erase block of flash,
//! and multiple erase blocks are used for parameter block storage, it takes
//! quite a few parameter block saves before flash is re-written.
//!
//! In order to make this efficient and effective, two conditions must be met.
//! The first is that at least two erase blocks of flash must be dedicated to
//! parameter block storage. If not, fault tolerance can not be guaranteed
//! since an erase of the single block will leave a window where there are no
//! valid parameter blocks in flash. The second condition is that the size 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.
//!
//! When the microcontroller is initially programmed, the flash blocks used for
//! parameter block storage are left in an erased state. The default settings
//! in the motor drive application are therefore used initially.
//!
//! The code for handling the flash parameter blocks is contained in
//! <tt>flash_pb.c</tt>, with <tt>flash_pb.h</tt> containing the definitions
//! for the functions exported to the remainder of the application.
//
//*****************************************************************************
//*****************************************************************************
//
//! \defgroup flash_pb_api Definitions
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
//! The address of the beginning of the flash used for storing parameter
//! blocks; this must be the start of an erase block in the flash.
//
//*****************************************************************************
static unsigned char *g_pucFlashPBStart;
//*****************************************************************************
//
//! The address of the end of the flash used for storing parameter blocks; this
//! must be the start of an erase block in the flash, or the first location
//! after the end of the flash array if the last erase block is used for
//! storing parameters.
//
//*****************************************************************************
static unsigned char *g_pucFlashPBEnd;
//*****************************************************************************
//
//! The size of the parameter block when stored in flash; this must be a power
//! of two less than or equal to 1024.
//
//*****************************************************************************
static unsigned long g_ulFlashPBSize;
//*****************************************************************************
//
//! The address of the most recent parameter block in flash.
//
//*****************************************************************************
static unsigned char *g_pucFlashPBCurrent;
//*****************************************************************************
//
//! Determines if the parameter block at the given address is valid.
//!
//! \param pucOffset is the address of the parameter block to check.
//!
//! This function will compute the checksum of a parameter block in flash to
//! determine if it is valid.
//!
//! \return Returns one if the parameter block is valid and zero if it is not.
//
//*****************************************************************************
static unsigned long
FlashPBIsValid(unsigned char *pucOffset)
{
unsigned long ulIdx, ulSum;
//
// Loop through the bytes in the block, computing the checksum.
//
for(ulIdx = 0, ulSum = 0; ulIdx < g_ulFlashPBSize; ulIdx++)
{
ulSum += pucOffset[ulIdx];
}
//
// The checksum should be zero, so return a failure if it is not.
//
if((ulSum & 255) != 0)
{
return(0);
}
//
// This is a valid parameter block.
//
return(1);
}
//*****************************************************************************
//
//! Gets the address of the most recent parameter block.
//!
//! This function returns the address of the most recent parameter block that
//! is stored in flash.
//!
//! \return Returns the address of the most recent parameter block, or NULL if
//! there are no valid parameter blocks in flash.
//
//*****************************************************************************
unsigned char *
FlashPBGet(void)
{
//
// See if there is a valid parameter block.
//
if(g_pucFlashPBCurrent)
{
//
// Return the address of the most recent parameter block.
//
return(g_pucFlashPBCurrent);
}
//
// There are no valid parameter blocks in flash, so return NULL.
//
return(0);
}
//*****************************************************************************
//
//! Writes a new parameter block to flash.
//!
//! \param pucBuffer is the address of the parameter block to be written to
//! flash.
//!
//! This function will write a parameter block to flash. The parameter block
//! is written to the next available portion of the parameter block space in
//! flash, being careful to keep the previous parameter block intact in case
//! there is a power loss or fault mid-way through the save process.
//!
//! \return None.
//
//*****************************************************************************
void
FlashPBSave(unsigned char *pucBuffer)
{
unsigned char *pucNew;
unsigned long ulIdx, ulSum;
//
// See if there is a valid parameter block in flash.
//
if(g_pucFlashPBCurrent)
{
//
// Set the sequence number to one greater than the most recent
// parameter block.
//
pucBuffer[0] = g_pucFlashPBCurrent[0] + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -