1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/ecbm-stc8-bootloader-tiny

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
main.lst 22 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
naite Отправлено 3 лет назад 8751d42
C51 COMPILER V9.59.0.0 MAIN 08/27/2022 22:38:02 PAGE 1
C51 COMPILER V9.59.0.0, COMPILATION OF MODULE MAIN
OBJECT MODULE PLACED IN .\Objects\main.obj
COMPILER INVOKED BY: C:\Keil_v5\C51\BIN\C51.EXE main.c OPTIMIZE(8,SPEED) BROWSE DEBUG OBJECTEXTEND PRINT(.\Listings\main
-.lst) OBJECT(.\Objects\main.obj)
line level source
1 /*-------------------------------------------头文件-------------------------------------------*/
2 #include <STC8.H>
3 #include "intrins.h" //单片机C语言使用汇编指令的头文件。
4 /*-------------------------------------------宏定义-------------------------------------------*/
5 typedef unsigned char u8; //无符号的 8位变量。
6 typedef unsigned int u16; //无符号的16位变量。
7 typedef unsigned long u32; //无符号的32位变量。
8 /*-----------------------------------------BOOT脚定义-----------------------------------------*/
9 #define BOOT_PIN P00 //BOOT脚设置为P0.0脚。
10 #define BOOT_RUN_APP 0 //BOOT脚为低电平的时候运行APP。
11 /*------------------------------------------功能定义------------------------------------------*/
12 sfr IAP_TPS =0xf5; //EEPROM擦除等待时间控制寄存器
13 u8 code INIT_MASK[6] ={0xff,0xff,0xff,0xff,0xff,0xff};//初始化掩码,对于FLASH而言就是0xFF。
14 void (* jmp_app)(void); //跳转函数。
15 #define BOOT_STATUS 0x4200 //4200 :BootLoader区状态
16 #define BOOT_JMP_ADDR 0x4201 //4201~4202 :BootLoader的跳转地址
17
18 #define APP_START 0x4203 //4203 :APP区起始地址
19 #define APP_MAX 5 //APP区占用空间为5字节
20 #define APP_STATUS 0x4203 //4203 :APP区状态
21 #define APP_SIZE 0x4204 //4204~4205 :APP区大小
22 #define APP_JMP_ADDR 0x4206 //4206~4207 :APP地址
23
24 #define DATA_MAX 30 //APP区的最大值,单位为扇区数。一扇区为512字节。
25 #define FLASH_SIZE (DATA_MAX*512) //APP区的最大值,单位为字节。
26
27 #define read_jmp__addr (*(unsigned int code *)(0x0001)) //读取整个程序的跳转地址。
28 #define read_jmp__addr_h (*(unsigned char code *)(0x0001))
29 #define read_jmp__addr_l (*(unsigned char code *)(0x0002))
30
31 #define read_boot_addr (*(unsigned int code *)(BOOT_JMP_ADDR))//读取Bootloader的跳转地址。
32 #define read_boot_addr_h (*(unsigned char code *)(BOOT_JMP_ADDR))
33 #define read_boot_addr_l (*(unsigned char code *)(BOOT_JMP_ADDR+1))
34
35 #define read_app__addr (*(unsigned int code *)(APP_JMP_ADDR)) //读取APP的跳转地址。
36 #define read_app__addr_h (*(unsigned char code *)(APP_JMP_ADDR))
37 #define read_app__addr_l (*(unsigned char code *)(APP_JMP_ADDR+1))
38
39 #define read_app__size (*(unsigned int code *)(APP_SIZE)) //读取APP的大小。
40 #define read_app__size_h (*(unsigned char code *)(APP_SIZE))
41 #define read_app__size_l (*(unsigned char code *)(APP_SIZE+1))
42
43 #define read_app__flag (*(unsigned char code *)(APP_STATUS)) //读取APP的状态。
44 #define read_boot_flag (*(unsigned char code *)(BOOT_STATUS)) //读取BootLoader的状态。
45 //位定义 [ D7 ][ D6 ][ D5 ][ D4 ][ D3 ][ D2 ][ D1 ][ D0 ]
46 //APP [ 使能标志位 ][ 安装 完成标志位 ][ 预留 ]
47 //BOOT [ 使能标志位 ][ 初始化完成标志位 ][ 预留 ]
48 #define BIT_ENABLE 0x80 //使能位。
49 #define SET_ENABLE (~(u8)(BIT_ENABLE)) //使能该区域。
50 #define GET_ENABLE ( (u8)(BIT_ENABLE)) //查询使能位。
51
52 #define BIT_DONE 0x40 //完成位。
53 #define SET_DONE (~(u8)(BIT_DONE)) //该区域完成了设定功能。
54 #define GET_DONE ( (u8)(BIT_DONE)) //查询完成位。
C51 COMPILER V9.59.0.0 MAIN 08/27/2022 22:38:02 PAGE 2
55
56 #define PD_APP__OK (GET_ENABLE|GET_DONE) //判断APP区是否有合法的程序。
57 #define APP__OK (0) //APP区是合法的程序。
58 /*------------------------------------------函数定义------------------------------------------*/
59 #if 1//串口部分
60 /*-------------------------------------------------------
61 函数名:hard_init
62 描 述:硬件外设初始化函数。
63 创建者:奈特
64 调用例程:无
65 创建日期:2020-11-30
66 修改记录:
67 2020-12-08:合并了串口和定时器的初始化。更名为hard_init。
68 -------------------------------------------------------*/
69 void hard_init(void){
70 1 SCON = 0x50; //8位数据,可变波特率
71 1 AUXR = 0x40; //定时器1时钟为Fosc,即1T
72 1 TMOD = 0x00; //设定定时器1为16位自动重装方式
73 1 TL0 = 0xC0; //设置定时初值
74 1 TH0 = 0x63; //20ms
75 1 TL1 = 0xCC; //设定初值
76 1 TH1 = 0xFF; //设定初值
77 1 TF0 = 0; //清除TF0标志
78 1 TF1 = 0; //清除TF1标志
79 1 TR0 = 0;
80 1 TR1 = 1; //启动定时器1
81 1 ET1 = 0; //禁止定时器1中断
82 1 }
83 /*-------------------------------------------------------
84 函数名:send_data
85 描 述:串口发送单字节函数。
86 输 入:
87 dat 要发送的字节。
88 创建者:奈特
89 调用例程:无
90 创建日期:2020-11-30
91 修改记录:
92 -------------------------------------------------------*/
93 void send_data(u8 dat){
94 1 SBUF=dat; //发送一个数据。
95 1 while(!TI); //等待数据发完。
96 1 TI=0; //清除发送标志位。
97 1 }
98 /*-------------------------------------------------------
99 函数名:send_string
100 描 述:串口发送字符串函数。
101 输 入:
102 str 要发送的字符串。
103 创建者:奈特
104 调用例程:无
105 创建日期:2020-11-30
106 修改记录:
107 2020-12-08:优化了函数的占用空间。
108 -------------------------------------------------------*/
109 void send_string(u8 code * str){
110 1 while(*str){ //判断字符串是否到头,
111 2 SBUF=*str++;//发送一个数据。
112 2 while(!TI); //等待数据发完。
113 2 TI=0; //清除发送标志位。
114 2 }
115 1 }
116 /*-------------------------------------------------------
C51 COMPILER V9.59.0.0 MAIN 08/27/2022 22:38:02 PAGE 3
117 函数名:send_num
118 描 述:串口发送16位数据函数,发送格式为%u。
119 输 入:
120 dat 要发送的数据。
121 创建者:奈特
122 调用例程:无
123 创建日期:2020-12-03
124 修改记录:
125 -------------------------------------------------------*/
126 void send_num(u16 dat){
127 1 u8 n[5],i;
128 1 for(i=0;i<5;i++){
129 2 n[i]=dat%10;
130 2 dat/=10;
131 2 }
132 1 if(n[4]){
133 2 send_data('0'+n[4]);
134 2 }
135 1 if(n[4]|n[3]){
136 2 send_data('0'+n[3]);
137 2 }
138 1 if(n[4]|n[3]|n[2]){
139 2 send_data('0'+n[2]);
140 2 }
141 1 if(n[4]|n[3]|n[2]|n[1]){
142 2 send_data('0'+n[1]);
143 2 }
144 1 send_data('0'+n[0]);
145 1 }
146 #endif
147 #if 1//FLASH操作部分
148 /*-------------------------------------------------------
149 函数名:eeprom_off
150 描 述:eeprom关闭函数。
151 创建者:奈特
152 调用例程:无
153 创建日期:2020-11-30
154 修改记录:
155 -------------------------------------------------------*/
156 void eeprom_off(void){
157 1 IAP_CONTR = 0; //关闭IAP功能
158 1 IAP_CMD = 0; //清除命令寄存器
159 1 IAP_TRIG = 0; //清除触发寄存器
160 1 IAP_ADDRH = 0xff;//将地址设置到非IAP区域
161 1 IAP_ADDRL = 0xff;//将地址设置到非IAP区域
162 1 }
163 /*-------------------------------------------------------
164 函数名:eeprom_erase
165 描 述:eeprom擦除函数,用于擦除一个扇区。
166 输 入:
167 addr 要擦除的地址。
168 创建者:奈特
169 调用例程:无
170 创建日期:2020-11-30
171 修改记录:
172 -------------------------------------------------------*/
173 void eeprom_erase(u16 addr){
174 1 IAP_CONTR = 0x81; //使能IAP
175 1 IAP_CMD = 3; //设置IAP擦除命令
176 1 IAP_ADDRL = addr; //设置IAP低地址
177 1 IAP_ADDRH = addr >> 8; //设置IAP高地址
178 1 IAP_TRIG = 0x5a; //写触发命令(0x5a)
C51 COMPILER V9.59.0.0 MAIN 08/27/2022 22:38:02 PAGE 4
179 1 IAP_TRIG = 0xa5; //写触发命令(0xa5)
180 1 _nop_(); //稍稍等待一下
181 1 eeprom_off(); //关闭IAP功能
182 1 }
183 /*-------------------------------------------------------
184 函数名:eeprom_write
185 描 述:eeprom单字节写函数,用于向指定地址写一个数据。
186 输 入:
187 addr 要写入的地址;
188 dat 要写入的数据。
189 创建者:奈特
190 调用例程:无
191 创建日期:2020-11-30
192 修改记录:
193 -------------------------------------------------------*/
194 void eeprom_write(u16 addr,u8 dat){
195 1 IAP_CONTR = 0x81; //使能IAP
196 1 IAP_CMD = 2; //设置IAP写命令
197 1 IAP_ADDRL = addr; //设置IAP低地址
198 1 IAP_ADDRH = addr >> 8; //设置IAP高地址
199 1 IAP_DATA = dat; //写IAP数据
200 1 IAP_TRIG = 0x5a; //写触发命令(0x5a)
201 1 IAP_TRIG = 0xa5; //写触发命令(0xa5)
202 1 _nop_(); //稍稍等待一下
203 1 eeprom_off(); //关闭IAP功能
204 1 }
205 /*-------------------------------------------------------
206 函数名:eeprom_write_boot_area
207 描 述:eeprom多字节写系统区函数,用于向指定区域写多个数据。
208 输 入:
209 addr 要写入的地址,必须要系统区域内;
210 buf 要写入的数据缓存;
211 len 要写入的数据数量。
212 创建者:奈特
213 调用例程:无
214 创建日期:2020-11-30
215 修改记录:
216 2020-12-03:优化了功能,现在只为固定区域服务已减小占用空间,
217 改名为eeprom_write_boot_area。
218 -------------------------------------------------------*/
219 volatile u8 xdata eeprom_buf[512];//用于整合数据的缓存
220 void eeprom_write_boot_area(u16 addr,u8 * buf,u16 len){
221 1 u16 i,ad;
222 1 for(i=0;i<512;i++){ //将系统区原本的数据读出来,放到缓存当中。
223 2 eeprom_buf[i]=(*(unsigned char code *)(BOOT_STATUS+i));
224 2 }
225 1 eeprom_erase(BOOT_STATUS); //清除系统区。
226 1 ad=addr-BOOT_STATUS; //获取地址的偏移量。
227 1 for(i=0;i<len;i++){ //将数据写入到缓存。
228 2 eeprom_buf[i+ad]=buf[i];
229 2 }
230 1 for(i=0;i<512;i++){ //将缓存写回到单片机。
231 2 eeprom_write(BOOT_STATUS+i,eeprom_buf[i]);
232 2 }
233 1 }
234 #endif
235
236 volatile u16 data_count=0,proj_count=0;//包内数据计数器和总数据计数变量。
237 /*-------------------------------------------------------
238 函数名:data_save
239 描 述:数据保存函数,用于保存从串口接收到的数据。
240 创建者:奈特
C51 COMPILER V9.59.0.0 MAIN 08/27/2022 22:38:02 PAGE 5
241 调用例程:无
242 创建日期:2020-12-24
243 修改记录:
244 -------------------------------------------------------*/
245 void data_save(void){
246 1 u16 i;
247 1 if(proj_count<=256){ //如果总计数小于256,说明是第一包数据。
248 2 eeprom_write(APP_JMP_ADDR ,eeprom_buf[1]); //第一包数据通常都包含了跳转地址,
249 2 eeprom_write(APP_JMP_ADDR+1,eeprom_buf[2]); //把跳转地址保存起来。
250 2 for(i=3;i<proj_count;i++){ //然后写入剩下的数据。
251 3 eeprom_write(i,eeprom_buf[i]);
252 3 }
253 2 }else{ //如果不是第一包数据,
254 2 for(i=0;i<data_count;i++){ //那就直接保存到flash就行了。
255 3 eeprom_write(i+(proj_count-data_count),eeprom_buf[i]);
256 3 }
257 2 }
258 1 }
259
260 void main(void){
261 1 u16 i; //16位临时变量。
262 1 u8 timeout; //时间超时计数器。
263 1 IAP_TPS=24; //STC8G和STC8H的设置,默认24MHz。
264 1 /*------------------------------------------BootLoader初始化-------------------------------*/
265 1 if(read_boot_flag&GET_ENABLE){ //判断是不是第一次运行bootload
-er,
266 2 eeprom_write(BOOT_STATUS, SET_ENABLE); //是的话就置位使能标志。
267 2 eeprom_write( APP_JMP_ADDR, (*(unsigned char code *)(0x0001))); //初始化APP的跳转地址。
268 2 eeprom_write( APP_JMP_ADDR+1, (*(unsigned char code *)(0x0002))); //
269 2 eeprom_write(BOOT_JMP_ADDR, (*(unsigned char code *)(0x0001))); //初始化BOOT的跳转地址。
270 2 eeprom_write(BOOT_JMP_ADDR+1, (*(unsigned char code *)(0x0002))); //
271 2 eeprom_write(BOOT_STATUS, SET_DONE); //置位初始化完毕标志。
272 2 } //至此BootLoader初始化完成。
273 1 /*------------------------------------------APP检测---------------------------------------*/
274 1 jmp_app=(u32)read_boot_addr; //默认把BootLoader的地址给APP地址。防止乱跳转。
275 1 if((read_app__flag&PD_APP__OK)==APP__OK){ //判断程序是否合法。
276 2 jmp_app=(u32)read_app__addr; //程序合法,则将APP跳转地址给跳转函数。
277 2 if(BOOT_PIN==BOOT_RUN_APP){jmp_app();} //BOOT脚是能跳转到APP的电平就跳转到APP。
278 2 }
279 1 /*-----------------------------------BootLoader界面--------------------------------------*/
280 1 hard_init(); //初始化串口和定时器。
281 1 send_string("[Boot](0)\r\n"); //提示进入了BOOT状态。
282 1 while(!RI); //等待接收解锁码。
283 1 RI=0; //置零接收标志位。
284 1 if(SBUF!='!'){ //如果不是解锁码,说明串口此时是乱传数据的。
285 2 send_string("[Lock](1)\r\n");//提示要锁定单片机。
286 2 while(1); //死循环,锁定单片机不能继续下载。
287 2 }
288 1 /*--------------------------------------下载界面------------------------------------------*/
289 1 send_string("[Erase](2)\r\n"); //提示开始擦除。
290 1 eeprom_erase(0x0000); //先擦第一扇区。
291 1 eeprom_write(0x0000,0x02); //立刻写入跳转指令。
292 1 eeprom_write(0x0001,(*(unsigned char code *)(BOOT_JMP_ADDR))); //取出BOOT的跳转地址高8位,写入到指定
-刂分小
293 1 eeprom_write(0x0002,(*(unsigned char code *)(BOOT_JMP_ADDR+1)));//取地址低8位,分成两个单字节写函数,
-梢约涌煸诵兴俣取
294 1 eeprom_write_boot_area(APP_START,INIT_MASK,APP_MAX); //初始化APP状态区。
295 1 eeprom_write(APP_STATUS,SET_ENABLE); //写入APP使能标志位。
296 1 for(i=512;i<FLASH_SIZE;i+=512){ //擦除后面的扇区。
297 2 eeprom_erase(i);
298 2 }
299 1 data_count=0; //清零单包数据计数器。
C51 COMPILER V9.59.0.0 MAIN 08/27/2022 22:38:02 PAGE 6
300 1 proj_count=0; //清零总体数据计数器。
301 1 send_string("[Start](3)"); //提示开始下载。
302 1 TR0=1; //打开定时器,即启用超时判断。
303 1 timeout=250; //第一次超时时间为250*20ms=5000ms=5s,上位机点击操作需要时间,第一次超时判
-断要久一些。
304 1 while(1){ //在循环里接收数据。
305 2 while(!RI){ //等待串口来数据。
306 3 if(TF0){ //每当定时器溢出时,
307 4 TF0=0; //清零标志位。
308 4 timeout--; //超时时间-1。
309 4 if(timeout==0){ //当时间减到0的时候,说明超时了。
310 5 TR0=0; //关闭定时器。
311 5 if(proj_count){ //如果期间接收了数据,
312 6 send_string("\r\n[Get "); //显示接收了多少数据。
313 6 send_num(proj_count);
314 6 send_string(" Byte](4)\r\n"); //单位是字节。
315 6 data_save(); //保存这些数据,在这里保存的通常是
-最后一包的数据。
316 6 eeprom_write(APP_SIZE, (u8)(proj_count>>8)); //读取APP的大小高8位,写入到指定地
-址中。
317 6 eeprom_write(APP_SIZE+1,(u8)(proj_count)); //读取APP的大小低8位,分成两个单字
-节写函数,可以加快运行速度。
318 6 eeprom_write(APP_STATUS,SET_DONE); //安装完成,写完成标志位。
319 6 jmp_app=(u32)read_app__addr; //将APP跳转地址给跳转函数。
320 6 }else{ //如果期间没有接收到数据,
321 6 send_string("\r\n[Time Out](5)\r\n"); //显示超时。
322 6 jmp_app=(u32)read_boot_addr; //将BOOT的跳转地址给跳转函数。
323 6 }
324 5 jmp_app(); //下载进程完毕,跳转。
325 5 }
326 4 }
327 3 }
328 2 TF0=0; //如果接收到串口数据,也要清零定时器标志位。
329 2 RI=0; //同时清零接收标志位。
330 2 eeprom_buf[data_count++]=SBUF; //将接收的数据保存下来。
331 2 proj_count++; //统计目前已接收的数据大小。
332 2 if(data_count==256){ //sscom5上位机是256字节分一包,所以每收到256字节的时候
-,
333 3 data_save(); //就要把数据保存下来。
334 3 data_count=0; //同时清零数据统计标志位。
335 3 }
336 2 if(proj_count>FLASH_SIZE){ //如果接收到的大小大于总的空间,
337 3 send_string("\r\n[Overflow](6)\r\n"); //提示容量溢出。
338 3 while(1); //死循环,锁定单片机。
339 3 }
340 2 timeout=50; //超时时间为50*20ms=1000ms=1s
341 2 }
342 1 }
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 977 ----
CONSTANT SIZE = 110 ----
XDATA SIZE = 512 ----
PDATA SIZE = ---- ----
DATA SIZE = 7 19
IDATA SIZE = ---- ----
BIT SIZE = ---- ----
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/ecbm-stc8-bootloader-tiny.git
git@gitlife.ru:oschina-mirror/ecbm-stc8-bootloader-tiny.git
oschina-mirror
ecbm-stc8-bootloader-tiny
ecbm-stc8-bootloader-tiny
master