查看完整版本: C8051F340 Bootloader 代码

liyf 发表于 2011-8-16 05:23:49

C8051F340 Bootloader 代码

鉴于大家学习方便,现给出C8051F340 Bootloader的代码架构,由于涉及商业信息,所以不能给出整个工程,请谅解!
相关文档信息,请参看blog: http://blog.ednchina.com/zhurunping/239751/message.aspx#

// 项目名称: C8051F340 BootLoader
// 版本介绍:
// 1.4.2 该程序仅作学习测试使用, 请勿用作其他.
//   介意使用内部晶振.
/** 擦除一个分区 */
#define flash_erase(addr)D_MACRO_BEGIN \
         FLKEY = 0xA5; \
         FLKEY = 0xF1; \
         PSCTL= 0x03; \
         *addr = 0x00; \
         PSCTL = 0x00; \
      D_MACRO_END
/** 写入Flash一个字节*/
#define flash_write(addr, x) D_MACRO_BEGIN \
         FLKEY = 0xA5; \
         FLKEY = 0xF1; \
         *(addr) = x; \
      D_MACRO_END
/** 串口查询方式发送一字节数据*/
#define Uart_PutCh(dat)   D_MACRO_BEGIN \
         SBUF1 = dat; \
         while ((SCON1&0x02) == 0); \
         SCON1 &= 0xFD; \
      D_MACRO_END
#define D_APP_START0x0000    // APP区起始地址
#define D_APP_LIMIT0xEE00    // APP区结束地址
#define D_RUN_ADDRESS 0xEE00    // APP运行地址(只使用3Byte)
#define D_BOOT_ADDR0xF000    // Boot程序存储地址
#define D_BOOT_LIMIT 0xF800    // Boot区结束地址
#define D_FLASH_LIMIT 0xFA00    // FLASH可操作区结束地址

/** 本地变量*/
uint8 rst_addr;      // 用以保存启动向量
uint8 xdata *pwrite;   // 指向代码区的指针
uint8 code *pread;      // 指向代码区的指针
uint8 dat;
/** @func RTload
* @brief 载入函数
*/
static void
RTload(void)
{
uint8 dat, tmp;
uint16 i, size, dnCS, CheckSum;
Uart_Print(">Start erasing flash...\n");
/** 1. 保存boot入口地址, 最后回写 */
pread = 0;
rst_addr = *pread++;
rst_addr = *pread++;
rst_addr = *pread++;
/** 2. 准备扇区 */
for (pwrite=0; pwrite<D_APP_LIMIT; pwrite+=0x200) { // APP区
flash_erase(pwrite);
}
pwrite = D_RUN_ADDRESS;    // 启动参数区
flash_erase(pwrite);
Uart_Print(">Erasing complete.\n");
/** 3. 回写boot入口地址 */
PSCTL = 0x01;
pwrite = 0;
flash_write(pwrite++, rst_addr);
flash_write(pwrite++, rst_addr);
flash_write(pwrite++, rst_addr);
/** 4. 通知主机发送代码 */
SCON1 |= B_REN1;
Uart_Print(">Please transmit bin file...\n");
/** 5. 读接收数据长度 */
for (i=0; i<4; i++) {
while ((SCON1&0x01) == 0);
SCON1 &= 0xFE;
tmp = SBUF1;
}
size = ((tmp<<8)+tmp) - 4 - 2;
if (size > D_APP_LIMIT) {
PSCTL = 0x00;
Uart_Print(">Error: no enough space for your app!\n");
return;
}
/** 6. 开始接收数据, 同时写入Flash APP区*/
CheckSum= 0;
pwrite = D_RUN_ADDRESS;    // 启动地址(3Byte)
for (i=0; i<3; i++) {
while ((SCON1&0x01) == 0);
SCON1 &= 0xFE;
dat = SBUF1;
CheckSum += dat;
flash_write(pwrite++, dat);
}
pwrite = 3;       // 程序区
for (i=3; i<size; i++) {
while ((SCON1&0x01) == 0);
SCON1 &= 0xFE;
dat = SBUF1;
CheckSum += dat;
flash_write(pwrite++, dat);
}
PSCTL = 0x00;       // 禁止Flash操作
/** 7. 读校验和 */
for (i=0; i<2; i++) {
while ((SCON1&0x01) == 0);
SCON1 &= 0xFE;
tmp = SBUF1;
}
dnCS = (tmp<<8) + tmp;
Uart_Print(">Transmit complete.\n");
/** 8. 校验数据*/
if (dnCS != CheckSum) {
Uart_Print(">CheckSum error!\n");
} else {
Uart_Print(">Programming Complete.\n");
Uart_Print(">You have to restart the device to use the new firmware.\n");
}
}
void
main(void)
{
uint8 dat;
uint16 timeout;
void (*boot)( void);
Init_Device();       // 初始化设备
FLSCL = ((FLSCL&0xF0) | 0x09);// 设置FLASH预分频器
PFE0CN = PFE0CN & 0xFE;    // FLASH按字节写入
// 此处读取Loader使能按键
// ...
if (1) { // 用户设置为下载模式
/** 创建握手过程*/
Uart_Print("\n");
Uart_Print("****************ZBoot v1.4.2*****************\n");
Uart_Print(">Please press 's' to start programming.\n");
while (1) {
   //此处判断读入's'
   // ...
   if ("键入正确") {
    RTload();   // Download
   } else if ("超时") {
    goto boot_out;
   }
}
}
boot_out:
pread = D_RUN_ADDRESS;
if (*pread != 0x02) {
Uart_Print(">Error: no app program for run!\n");
while (1);
}
boot = D_RUN_ADDRESS;
(*boot)();
}

hdzl 发表于 2011-8-16 11:16:39

学习了。

liyf 发表于 2011-8-16 11:21:55

:lol

liyf 发表于 2011-8-24 06:21:47

大家一起收获

sxccxz 发表于 2013-11-13 22:56:23

拿到手了 谢谢啊

lusonlin 发表于 2021-2-13 12:19:57

多谢楼主分享
页: [1]
查看完整版本: C8051F340 Bootloader 代码