📄 flashutils.c
字号:
}
STATIC uint32 CRC32Value(uint16 inCRC)
{
int16 j;
uint32 ulCRC = inCRC;
// for this byte (inCRC)...
for (j=8; j; j--) {
// lsb on? yes -- shift right and XOR with poly. else just shift
if (ulCRC & 1) {
ulCRC = (ulCRC >> 1) ^ CRC32_POLYNOMIAL;
}
else {
ulCRC >>= 1;
}
}
return ulCRC;
}
/************************************************************************************
* uint8 GetPreamble
* Purpose: get image preamble
*
* This routine is avaliable to application code. It is re-entrant but not
* thread-safe.
*
* Arguments:
* input:
* baseAddr: base address of image
* output:
* info: void pointer to destination memory
* Returns:
* 0: OK
* 1: error
*
* NOTE: this works only because the preamble is always on the first flash page.
* This is important given that the downloaded image can wrap. It won't wrap
* within a page.
************************************************************************************/
STATIC uint8 GetPreamble(image_t itype, uint32 baseAddr, preamble_t *info)
{
uint8 preOffset;
if (IMAGE_DL == itype) {
mbox.AccessZLOADStatus(ACTION_GET, SFIELD_PREAMBLE_OFFSET, &preOffset);
baseAddr += preOffset;
rw_Xmem(XMEM_READ, baseAddr, (uint8 *)info, sizeof(preamble_t));
}
else if (IMAGE_ACTIVE == itype) {
uint8 i;
baseAddr += PREAMBLE_BASE;
// need > 16-bit pointer arithmetic
for (i=0; i<sizeof(preamble_t); ++i, ++baseAddr) {
*((uint8 *)info+i) = GetCodeByte(baseAddr);
}
}
else {
return 1;
}
return 0;
}
/************************************************************************************
* uint8 AccessStatus
* Purpose: get and set fields in OAD persistent memory
*
* This routine is avaliable to application code. It neither re-entrant nor
* thread-safe.
*
* Arguments:
* input:
* action: get or set
* sfield: which field to operate on
* output:
* info: void pointer to source (set) or destination (get) memory
* Returns:
* 0: OK
* 1: bad action or field
************************************************************************************/
STATIC uint8 AccessStatus(action_t action, sfield_t sfield, void *info)
{
uint8 bcnt, os, rc = 0;
// all results for this function (except the boot sector size) are byte copies
// the offset and byte counts are set based on boot code knowledge of how the
// persistent memory is arranged. the offsets and sizes are set here. they are
// defined in a header. they could be calculated but it takes a lot more code.
switch (sfield) {
#if 0 // base and first page always the same for the 8051 with external memory
case SFIELD_DLFIRSTPAGE_ADDR:
bcnt = sizeof(uint32);
os = OADPM_OS_FIRSTPAGE_ADDR;
break;
#else
case SFIELD_DLFIRSTPAGE_ADDR:
#endif
case SFIELD_DLBASE:
bcnt = sizeof(uint32);
os = OADPM_OS_BADDR;
break;
case SFIELD_PREAMBLE_OFFSET:
bcnt = sizeof(uint8);
os = OADPM_OS_PREAMBLE_OFFSET;
break;
// we don't need to support the next few accesses now. they were intended
// to support the case where the entire image could not be downloaded and
// we needed to have server context in case of failure. they have been
// tested but are removed for now.
#if 0
case SFIELD_SERVER_IEEE_ADDR:
bcnt = SIZEOF_IEEE_ADDRESS;
os = OADPM_OS_IEEE_ADDR;
break;
case SFIELD_SERVER_NWK_ADDR:
bcnt = sizeof(uint16);
os = OADPM_OS_NWK_ADDR;
break;
case SFIELD_SERVER_ENDPOINT:
bcnt = sizeof(uint8);
os = OADPM_OS_ENDPT;
break;
case SFIELD_IMAGE_ID:
bcnt = SIZEOF_DLIMAGE_INFO;
os = OADPM_OS_DLIMG_INFO;
break;
#endif
case SFIELD_STATUS:
bcnt = sizeof(uint16);
os = OADPM_OS_STATUS;
break;
#if 0 // not used for CC2430
case SFIELD_BOOTSIZE:
// doesn't really belong here because it isn't kept in PM but
// it is conventient to support it with this API
if (action == ACTION_SET) {
// not legal
return 1;
}
*(uint16 *)info = bootSize;
return 0;
#endif
case SFIELD_EXTERNAL_MEM_OS:
// doesn't really belong here because it isn't kept in PM but
// it is conventient to support it with this API
if (action == ACTION_SET) {
// not legal
return 1;
}
*(uint16 *)info = DL_BASE_ADDRESS;
return 0;
default:
rc = 1;
break;
}
if (!rc) {
if (action == ACTION_SET) {
rw_Xmem(XMEM_WRITE, SYSNV_BASE_ADDRESS + os, info, bcnt);
}
else if (action == ACTION_GET) {
rw_Xmem(XMEM_READ, SYSNV_BASE_ADDRESS + os, info, bcnt);
}
else {
rc = 1;
}
}
return rc;
}
STATIC uint8 ReadFlash(image_t itype, uint32 address, uint8 __xdata *buf, uint16 len)
{
uint8 rc = 0;
if (IMAGE_ACTIVE == itype) {
uint16 i = len;
while (i--) {
*buf++ = GetCodeByte(address++);
}
}
else if (IMAGE_DL == itype) {
rw_Xmem(XMEM_READ, address, buf, len);
}
else {
rc = 1;
}
return rc;
}
STATIC uint8 WriteFlash(image_t itype, uint32 address, uint8 __xdata *buf, uint16 len)
{
uint8 rc = 1; // 1 == write was OK.
if (IMAGE_ACTIVE == itype) {
uint16 fbase, i;
uint8 page = address >> CHIP_SHIFTCOUNT;
// if we're on a page boundary for the target (chip) flash, erase the page
// this implies that we either write a page sequentially or minimally
// write the first address on the first call so the page gets eraseed.
if (!(address & 0x000007FF)) {
FLASH_ERASE_PAGE(page);
}
// OK. do the rest. use DMA Channel 0
// Set up Flash DMA
FlashDMA.DST_HI = 0xdf;
FlashDMA.DST_LO = 0xaf;
FlashDMA.VLEN = 0x00;
FlashDMA.LEN = 0x04;
FlashDMA.TRIG = 0x12;
FlashDMA.INCMODE = 0x42;
DMA0CFGH = (uint16)&FlashDMA >> 8;
DMA0CFGL = (uint16)&FlashDMA;
fbase = (page << 9) + ((address & 0x000007FF)>>2);
// 'len' must be 0 (mod 4)
for (i=0; i<(len/4); ++i) {
// set buffer pointer in DMA config info
FlashDMA.SRC_HI = (uint16)buf >> 8;
FlashDMA.SRC_LO = (uint16)buf;
// Set Flash write address based on fbase
FADDRH = fbase >> 8;
FADDRL = fbase;
DMAARM = 0x01;
halFlashDmaTrigger();
while (!(DMAIRQ & 0x01)); // wait for DMA transfer
while ( FCTL & FWBUSY ); // wait until Flash controller not busy
DMAIRQ &= ~0x01;
fbase++;
buf += 4;
}
}
else if (IMAGE_DL == itype) {
rw_Xmem(XMEM_WRITE, address, buf, len);
}
else {
rc = 0;
}
return rc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -