|
2楼
楼主 |
发表于 2008-9-1 17:09:10
|
只看该作者
/***********************************************************
* 函数库说明:Bootloader底层操作函数库 *
* 版本: v1.00beta *
* 作者: 王卓然 *
* 创建日期: 2008年8月31日 *
* -------------------------------------------------------- *
* [支 持 库] *
* 支持库名称: *
* 需要版本: *
* 声明库说明: *
* -------------------------------------------------------- *
* [版本更新] *
* 修改: *
* 修改日期: *
* 版本: *
* -------------------------------------------------------- *
* [版本历史] *
* -------------------------------------------------------- *
* [使用说明] *
***********************************************************/
/********************
* 头 文 件 配 置 区 *
********************/
# include "RD_MacroAndConst.h"
# include "BL_Config.h"
# include "PF_Config.h"
/********************
* 系 统 宏 定 义 *
********************/
/*------------------*
* 常 数 宏 定 义 *
*------------------*/
# define SPM_ENBALE_RWW (BIT(RWWSRE)|BIT(SPMEN))
# define SPM_PAGE_WRITE (BIT(PGWRT)|BIT(SPMEN))
# define SPM_PAGE_ERASE (BIT(PGERS)|BIT(SPMEN))
# define SPM_WRITE_BUFFER BIT(SPMEN)
#ifndef FLASH_PAGE_SIZE
# define FLASH_PAGE_SIZE 64
#endif
#ifdef BOOTLOADER_USE_CRC16
# define CRC_INIT 0xFFFF
# define CRC(__CRCVAL,__NEWCHAR) CRC16_Check(&(__CRCVAL),(__NEWCHAR));
#endif
/*------------------*
* 动 作 宏 定 义 *
*------------------*/
/********************
* 模块结构体定义区 *
********************/
/********************
* 函 数 声 明 区 *
********************/
BOOL Bootloader_Flash_Page_Verify
(
BYTE *pchDataBuffer,
UINT16 wAddress
);
#ifdef BL_USE_LOAD_PAGE
#if defined(BOOTLOADER_USE_CRC16)
UINT16 Bootloader_Load_Page_Buffer
#elif defined(BOOTLOADER_USE_XOR)
UINT8 Bootloader_Load_Page_Buffer
#else
void Bootloader_Load_Page_Buffer
#endif
(
BYTE chDataBuffer[FLASH_PAGE_SIZE],
UINT16 wAddress
);
#endif
BOOL Bootloader_Write_Page
(
void *pData,
uint16 wLength,
UINT16 wAddress
);
void Bootloader_Put_INT_Vector_Into_APPS(void);
void Bootloader_Put_INT_Vector_Into_BLS(void);
/********************
* 模块函数声明区 *
********************/
static void Do_Boot_Loader_Action(UINT8 chFunction);
static UINT16 CRC16_Check(UINT16 *pwCRCValue,BYTE chData);
static BOOL Fill_Page_Buffer
(
BYTE chDataBuffer[FLASH_PAGE_SIZE],
UINT16 wAddress
);
/********************
* 模块变量声明区 *
********************/
/********************
* 全局变量声明区 *
********************/
#ifdef BOOTLOADER_USE_CRC16
/***********************************************************
* 函数说明: CRC16单数据处理函数 *
* 输入: 保存CRC校验值的地址,新的数据 *
* 输出: CRC交验 *
* 调用函数: 无 *
***********************************************************/
static UINT16 CRC16_Check(UINT16 *pwCRCValue,BYTE chData)
{
UINT16 wCRC = (*pwCRCValue);
chData ^= (UINT8)((UINT16)wCRC & 0x00FF);
chData ^= chData << 4;
(*pwCRCValue) = ((((uint16)chData << 8) | (wCRC >> 8)) ^ (uint8)(chData >> 4)
^ ((uint16)chData << 3));
return (*pwCRCValue);
}
#endif
/***********************************************************
* 函数说明: 等待SPM指令执行结束函数 *
* 输入: 需要执行的功能 *
* 输出: 无 *
* 调用函数: 无 *
***********************************************************/
static void Do_Boot_Loader_Action(UINT8 chFunction)
{
/* 等待上次操作结束 */
while(SPMCSR & BIT(SPMEN));
SAFE_CODE_PERFORMANCE
(
while(EECR & BIT(EEWE));
SPMCSR = chFunction;
asm("spm");
)
}
#ifdef BL_USE_LOAD_PAGE
/***********************************************************
* 函数说明: 读取指定的页面到指定的缓冲区 *
* 输入: 缓冲区地址,页面地址 *
* 输出: 无/CRC校验/XOR校验 *
* 调用函数: 无 *
* -------------------------------------------------------- *
* [ 说 明 ] *
* 如果输入的缓冲区指针为空,则只进行校验操作 *
***********************************************************/
#if defined(BOOTLOADER_USE_CRC16)
UINT16 Bootloader_Load_Page_Buffer
#elif defined(BOOTLOADER_USE_XOR)
UINT8 Bootloader_Load_Page_Buffer
#else
void Bootloader_Load_Page_Buffer
#endif
(
BYTE chDataBuffer[FLASH_PAGE_SIZE],
UINT16 wAddress
)
{
UINT16 wCounter = FLASH_PAGE_SIZE;
#if defined(BOOTLOADER_USE_CRC16)
UINT16 wTempCRC = CRC_INIT;
UINT8 chData = 0;
#elif defined(BOOTLOADER_USE_XOR)
UINT8 chXOR = 0;
#endif
#if !defined(BOOTLOADER_USE_CRC16) && !defined(BOOTLOADER_USE_XOR)
if (chDataBuffer == NULL)
{
/* 在无校验的情况下,给与空指针传递,无意义 */
return ;
}
#endif
/* 开启RWW区的读取功能 */
while(SPMCSR & BIT(RWWSB))
{
Do_Boot_Loader_Action(SPM_ENBALE_RWW);
}
/* 将地址保存到Z寄存器 */
asm("movw r30,r18");
/* 将地址保存到X寄存器 */
asm("movw r26,r16");
if (chDataBuffer != NULL)
{
/* 将地址保存到Z寄存器 */
//asm("movw r30,r18");
/* 遍历整个Flash 页面 */
while(wCounter--)
{
/* 读取数据并复制到SRAM中 */
asm("lpm r0,z+");
asm("st x+,r0");
/* 进行校验 */
#if defined(BOOTLOADER_USE_CRC16)
asm("mov %chData,r0");
CRC(wTempCRC,chData);
#elif defined (BOOTLOADER_USE_XOR)
asm("mov r1,%chXOR");
asm("eor r1,r0");
asm("mov %chXOR,r1");
#endif
}
}
else
{
/* 将地址保存到Z寄存器 */
//asm("movw r30,r18");
/* 仅仅进行校验 */
#if defined(BOOTLOADER_USE_CRC16)
/* 遍历整个Flash 页面 */
while(wCounter--)
{
asm("lpm r0,z+");
asm("mov %chData,r0");
CRC(wTempCRC,chData);
}
#elif defined (BOOTLOADER_USE_XOR)
/* 遍历整个Flash 页面 */
while(wCounter--)
{
asm("lpm r0,z+");
asm("mov r1,%chXOR");
asm("eor r1,r0");
asm("mov %chXOR,r1");
}
#endif
}
#if defined(BOOTLOADER_USE_CRC16)
return wTempCRC;
#elif defined(BOOTLOADER_USE_XOR)
return chXOR;
#endif
}
#endif
/***********************************************************
* 函数说明: 向页缓冲区写入数据函数 *
* 输入: 缓冲区指针,要写入的地址 *
* 输出: 写入是否成功 *
* 调用函数: 无 *
***********************************************************/
static BOOL Fill_Page_Buffer
(
BYTE chDataBuffer[FLASH_PAGE_SIZE],
UINT16 wAddress
)
{
UINT8 chCounter = (FLASH_PAGE_SIZE>>1);
if (chDataBuffer == NULL)
{
return FALSE;
}
/* 给Z寄存器写入地址 */
asm("ldi r30,0");
//asm("ldi r31,0");
asm("movw r26,r16");
/* 循环将数据写入页缓冲区 */
while(chCounter--)
{
asm("ld r0,x+");
asm("ld r1,x+");
Do_Boot_Loader_Action(SPM_WRITE_BUFFER);
asm("adiw r30,2");
}
/* 将地址保存到Z寄存器 */
asm("movw r30,r18");
return TRUE;
}
/***********************************************************
* 函数说明: 页面校验函数 *
* 输入: 源页面缓冲区,目标地址 *
* 输出: 校验是否成功 *
* 调用函数: 无 *
***********************************************************/
BOOL Bootloader_Flash_Page_Verify
(
BYTE *pchDataBuffer,
UINT16 wAddress
)
{
UINT16 wCounter = FLASH_PAGE_SIZE;
UINT8 chDataA = 0;
UINT8 chDataB = 0;
if (pchDataBuffer == NULL)
{
return FALSE;
}
/* 将地址保存到Z寄存器 */
asm("movw r30,r18");
asm("movw r26,r16");
while(wCounter--)
{
asm("lpm r0,z+");
asm("mov %chDataA,r0");
asm("ld r0,x+");
asm("mov %chDataB,r0");
if (chDataA != chDataB)
{
return FALSE;
}
}
return TRUE;
}
/***********************************************************
* 函数说明: 写入页面函数 *
* 输入: 缓冲区地址,目标地址 *
* 输出: 操作是否成功 *
* 调用函数: *
***********************************************************/
BOOL Bootloader_Write_Page
(
void *pData,
uint16 wLength,
UINT16 wAddress
)
{
BYTE *pchData = pData;
BYTE *pchBuffer = NULL;
if (pData == NULL)
{
return FALSE;
}
/* 写多页 */
while(wLength > FLASH_PAGE_SIZE)
{
/* Bootloader 写入时序 */
Fill_Page_Buffer(pchData,wAddress);
Do_Boot_Loader_Action(SPM_PAGE_ERASE);
Do_Boot_Loader_Action(SPM_PAGE_WRITE);
Do_Boot_Loader_Action(SPM_ENBALE_RWW);
/* 进行校验 */
if (
!Bootloader_Flash_Page_Verify
(
pchData,
wAddress
)
)
{
/* 校验失败 */
return FALSE;
}
pchData += FLASH_PAGE_SIZE;
wAddress += FLASH_PAGE_SIZE;
wLength -= FLASH_PAGE_SIZE;
}
if (wLength < FLASH_PAGE_SIZE)
{
/* 需要读取页面缓冲 */
BYTE chBuffer[FLASH_PAGE_SIZE] = {0};
pchBuffer = chBuffer;
#ifdef BL_USE_LOAD_PAGE
Bootloader_Load_Page_Buffer
(
chBuffer,
wAddress
);
#endif
/* 进行数据复制 */
while(wLength--)
{
*pchBuffer++ = *pchData++;
}
pchBuffer = chBuffer;
}
else
{
pchBuffer = pchData;
}
/* Bootloader 写入时序 */
Fill_Page_Buffer(pchBuffer,wAddress);
Do_Boot_Loader_Action(SPM_PAGE_ERASE);
Do_Boot_Loader_Action(SPM_PAGE_WRITE);
Do_Boot_Loader_Action(SPM_ENBALE_RWW);
/* 进行校验 */
if (
!Bootloader_Flash_Page_Verify
(
pchBuffer,
wAddress
)
)
{
/* 校验失败 */
return FALSE;
}
return TRUE;
}
/***********************************************************
* 函数说明: 将中断向量表放置到Bootloader Section *
* 输入: 无 *
* 输出: 无 *
* 调用函数: 无 *
***********************************************************/
void Bootloader_Put_INT_Vector_Into_BLS(void)
{
MCUCR |= BIT(IVCE);
MCUCR |= BIT(IVSEL);
}
/***********************************************************
* 函数说明: 将中断向量表放置到Application Section *
* 输入: 无 *
* 输出: 无 *
* 调用函数: 无 *
***********************************************************/
void Bootloader_Put_INT_Vector_Into_APPS(void)
{
MCUCR |= BIT(IVCE);
MCUCR &= ~BIT(IVSEL);
} |
|