📄 flashutils.c
字号:
#define ENABLE_BIT_DEFINITIONS 1
#include "zcomdef.h"
#include "FlashUtils.h"
#include <ioCC2430.h>
#include "OADSupport.h"
#include "OSAL_Memory.h"
#ifdef NV_IS_I2C
#include "i2cSupport.h"
#endif
#ifdef NV_IS_SPI
#include "serialize.h"
#endif
#define STATIC static
#define FERASE 0x01 // Page erase: erase=1
#define FWRITE 0x02 // Page write: write=1
#define FCONRD 0x10 // Continuous read: enable=1
#define FSWBSY 0x40 // Single write: busy=1
#define FBUSY 0x80 // Write/erase: busy=1
#define FWBUSY 0xC0 // Flash write: busy=1
/******************************************************************************
** ANY VARIABLES DECLARED 'STATIC' MUST BE USED _ONLY_ IN BOOT STARTUP CODE
** memory addresses assigned to static variables will not be valid when
** application code is running. they are valid only when the boot startup
** code is running.
*******************************************************************************/
/*********************************************************************
* MACROS
*/
//Macro for erasing a given flash page
#define ERASE 0x01
#define FLASH_ERASE_PAGE(page) \
do{ \
FADDRH = (page) << 1; \
FCTL = ERASE; \
asm("NOP"); \
while(FCTL == 0x80); \
}while (0)
// DMA Sturcture
typedef struct
{
uint8 SRC_HI;
uint8 SRC_LO;
uint8 DST_HI;
uint8 DST_LO;
uint8 VLEN;
uint8 LEN;
uint8 TRIG;
uint8 INCMODE;
} DMA_t;
static DMA_t __xdata FlashDMA;
extern __near_func uint8 GetCodeByte(uint32 address);
// set up the mailbox in RAM
extern mbox_t mbox;
// LOCAL FUNCTIONS
STATIC uint8 CheckCode(image_t, uint32, uint32);
STATIC uint8 GetPreamble(image_t, uint32, preamble_t *);
STATIC uint32 CRC32Value(uint16);
STATIC uint8 imageCRC(image_t, uint32, uint32, preamble_t *);
STATIC uint8 AccessStatus(action_t, sfield_t, void *);
STATIC uint8 ReadFlash(image_t, uint32 page, uint8 __xdata *buf, uint16 len);
STATIC uint8 WriteFlash(image_t, uint32 page, uint8 __xdata *buf, uint16 len);
__near_func void flashErasePage(uint8, uint8 __xdata *);
// EXTERNAL FUNCTIONS
__near_func void halFlashDmaTrigger(void);
static int8 (*rw_Xmem)(uint8, uint32, uint8 *, uint16);
void FlashInit()
{
#ifdef NV_IS_SPI
// initialize SPI-dataflash interface
DF_spiInit(&rw_Xmem);
#endif
#ifdef NV_IS_I2C
// initialize I2C-dataflash interface
DF_i2cInit(&rw_Xmem);
#endif
// populate mailbox function pointers
mbox.ReadFlash = ReadFlash;
mbox.WriteFlash = WriteFlash;
mbox.CheckCodeSanity = CheckCode;
mbox.GetPreamble = GetPreamble;
mbox.AccessZLOADStatus = AccessStatus;
return;
}
void GetFlashRWFunc(int8 (**func)(uint8, uint32, uint8 *, uint16))
{
#ifdef NV_IS_SPI
// initialize SPI-dataflash interface
DF_spiInit(&rw_Xmem);
#endif
#ifdef NV_IS_I2C
// initialize I2C-dataflash interface
DF_i2cInit(&rw_Xmem);
#endif
*func = rw_Xmem;
}
/************************************************************************************
* uint8 CheckCode
* Purpose: Do all code sanity checks. Currently, this is to check the magic
* and check the FCS.
*
* This routine is avaliable to application code. It is re-entrant but not
* thread-safe.
*
* Arguments:
* input:
* baseAddr: base address of image
* firstPageAddr: address of first page
* output:
* none.
* Returns:
* 0: Code at spefied address is sane
* 1: Code at spefied address is NOT sane
************************************************************************************/
STATIC uint8 CheckCode(image_t itype, uint32 baseAddr, uint32 firstPageAddress)
{
uint8 rc;
preamble_t preamble;
// get preamble
mbox.GetPreamble(itype, firstPageAddress, &preamble);
// check for magic
if ((preamble.pre_Magic[0] != PREAMBLE_MAGIC1) || (preamble.pre_Magic[1] != PREAMBLE_MAGIC2)) {
return 1;
}
// only thing left to check for is CRC
rc = imageCRC(itype, baseAddr, firstPageAddress, &preamble);
return rc;
}
/************************************************************************************
* uint8 imageCRC
* Purpose: compute image CRC. Taken as an amalgam from various sources. There
* are a number of slightly varying implementations. It was hard to find test
* data for this specific implementation. The test used is the very weak test
* in which the ASCII string "123456789" is checked.
*
* In this space it is calculating the CRC on downloaded image only. The
* application will never request the CRC calculated on the active image.
*
* Note: the routine that follows this one also supports the CRC calculation.
*
* Arguments:
* input:
* baseAddr: base address of image
* firstPageOffset: offset from baseAddr of actual first page of image
* premable: pointer to preamble info
* output:
* none
* Returns:
* 0: CRC calculation matches the CRC in image
* 1: CRC calculation does NOT match the CRC in image
************************************************************************************/
#define DFBUFSIZE 32
STATIC uint8 imageCRC(image_t itype, uint32 baseAddr, uint32 firstPageAddress, preamble_t *preamble)
{
uint8 ch, scnt, dfIdx, dfSize;
uint32 imgCRC, imglen, ulCRC, ulTemp1, ulTemp2, lastAddress, baseOrig;
#ifdef CC2430_BOOT_CODE
uint8 cptr[DFBUFSIZE];
#else
uint8 *cptr;
#endif
imglen = preamble->pre_Length;
// figure out wrap address in case image wraps within download area
// the number is too big if the image doesn't wrap but that won't
// matter becuase the loop(s) below will terminate since the image
// length count is reached. this value matters only if the image
// stored actually wraps.
lastAddress = (baseAddr + imglen - 1) | ((itype == IMAGE_DL) ? (DF_PAGESIZE-1) : (CHIP_PAGESIZE-1));
baseOrig = baseAddr;
baseAddr = firstPageAddress;
// start with all bits on. common practice to guard against initial sequence of
// 0's (even though we don't have this case)
ulCRC = 0xFFFFFFFF;
imgCRC = 0;
scnt = 0;
dfIdx = 0;
if (IMAGE_DL == itype) {
dfIdx = dfSize = DFBUFSIZE;
#ifndef CC2430_BOOT_CODE
if (!(cptr = osal_mem_alloc(DFBUFSIZE))) {
// Plan B if the malloc fails...
dfIdx = dfSize = 1;
cptr = &ch;
}
#endif
}
// the same logic is used to both calculate the checksum and to retrieve stored
// CRC. this is because the method below already deals with wrapping so we
// might as well use the same logic to get the CRC. Otherwise the wrapping
// logic has to be repeated: though unlikely, the CRC _could_ span the wrap.
do {
for (; baseAddr <= lastAddress && imglen; baseAddr++, imglen--) {
// next byte...
if (IMAGE_ACTIVE == itype) {
ch = GetCodeByte(baseAddr);
}
else {
if (dfIdx >= dfSize) {
rw_Xmem(XMEM_READ, baseAddr, cptr, dfSize);
dfIdx = 0;
}
ch = cptr[dfIdx++];
}
if (imglen > FCS_LENGTH) {
ulTemp1 = (ulCRC >> 8) & 0x00FFFFFFL;
ulTemp2 = CRC32Value(((uint16)ulCRC ^ ch) & 0xFF);
ulCRC = ulTemp1 ^ ulTemp2;
}
else {
// we've reached the stored CRC. create the actual
// value by shifting in the bytes.
imgCRC = imgCRC | (uint32)ch<<scnt;
scnt += 8;
}
}
baseAddr = baseOrig;
} while (imglen);
#ifndef CC2430_BOOT_CODE
if (dfSize > 1) {
osal_mem_free(cptr);
}
#endif
// XOR with all bits on. this is a common practice
ulCRC ^= 0xFFFFFFFF;
// match?
if (ulCRC != imgCRC) {
// "Close, but no match and the board goes back" (remember that?)
return 1;
}
return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -