DIY编程器网

标题: C8051F340 Bootloader 代码 [打印本页]

作者: liyf    时间: 2011-8-16 05:23
标题: 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_START  0x0000    // APP区起始地址
#define D_APP_LIMIT  0xEE00    // APP区结束地址
#define D_RUN_ADDRESS 0xEE00    // APP运行地址(只使用3Byte)
#define D_BOOT_ADDR  0xF000    // Boot程序存储地址
#define D_BOOT_LIMIT 0xF800    // Boot区结束地址
#define D_FLASH_LIMIT 0xFA00    // FLASH可操作区结束地址

/** 本地变量*/
uint8 rst_addr[3];      // 用以保存启动向量
uint8 xdata *pwrite;     // 指向代码区的指针
uint8 code *pread;      // 指向代码区的指针
uint8 dat;
/** @func RTload
* @brief 载入函数
*/
static void
RTload(void)
{
uint8 dat, tmp[4];
uint16 i, size, dnCS, CheckSum;
Uart_Print(">Start erasing flash...\n");
/** 1. 保存boot入口地址, 最后回写 */
pread = 0;
rst_addr[0] = *pread++;
rst_addr[1] = *pread++;
rst_addr[2] = *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[0]);
flash_write(pwrite++, rst_addr[1]);
flash_write(pwrite++, rst_addr[2]);
/** 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[1]<<8)+tmp[0]) - 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[1]<<8) + tmp[0];
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
学习了。
作者: liyf    时间: 2011-8-16 11:21

作者: liyf    时间: 2011-8-24 06:21
大家一起收获
作者: sxccxz    时间: 2013-11-13 22:56
拿到手了 谢谢啊
作者: lusonlin    时间: 2021-2-13 12:19
多谢楼主分享




欢迎光临 DIY编程器网 (http://diybcq.com/) Powered by Discuz! X3.2