升级说明
①升级程序结构:
bootloader |
应用程序区 |
程序备份区 |
0x8000~0x81FF
0x8200~0xC100
0xC100~0xFFFF
②stm8s005芯片中断向量表:
IRQ no | Source block | Vector address |
| RESET | 0x8000 |
| TRAP | 0x8004 |
0 | TLI | 0x8008 |
1 | AWU | 0x800c |
2 | CLK | 0x8010 |
3 | EXTI0 | 0x8014 |
4 | EXTI1 | 0x8018 |
5 | EXTI2 | 0x801C |
6 | EXTI3 | 0x8020 |
7 | EXTI4 | 0x8024 |
8 | Reserved | 0x8028 |
9 | Reserved | 0x802C |
10 | SPI | 0x8030 |
11 | TIM1 | 0x8034 |
12 | TIM1 | 0x8038 |
13 | TIM | 0x803C |
14 | TIM | 0x8040 |
15 | TIM3 | 0x8044 |
16 | TIM3 | 0x8048 |
17 | Reserved | 0x804C |
18 | Reserved | 0x8050 |
19 | I2C | 0x8054 |
20 | UART2 | 0x8058 |
21 | UART2 | 0x805C |
22 | ADC1 | 0x8060 |
23 | TIM | 0x8064 |
24 | Flash | 0x8068 |
Reserved | 0x806C | |
0x807C |
③bootloader功能:芯片程序从0x8000地址启动,bootloader程序运行流程图如下:
bootloader与应用程序公共数据存放到中断向量表reserved区域,这样公共数据不再占用其他空间(ram或flash),也可以通过下载程序的方法直接写到相应位置。流程中操作flash数据是先把flash数据读取到内存中,在把内存数据写到flash,这样做的原因是按块操作flash必须是在内存中操作。(按字节对比flash数据)
bootloader的lkf文件:
#<BEGIN SEGMENT_CONF># Segment Code,Constants: +seg .const -b 0x8000 -m 0x200 -n .const -it +seg .text -a .const -n .text# Segment Eeprom:+seg .eeprom -b 0x4000 -m 0x140 -n .eeprom# Segment Zero Page:+seg .bsct -b 0x0 -m 0x30 -n .bsct+seg .ubsct -a .bsct -n .ubsct+seg .bit -a .ubsct -n .bit -id+seg .share -a .bit -n .share -is# Segment Ram:+seg .data -b 0x30 -m 0x300 -n .data+seg .bss -a .data -n .bss#<END SEGMENT_CONF>
#Debug\loader.o +seg .xtext -b 0x4140 -m 0x140 -n .xtext# Object files list - section reserved for STVD#<BEGIN OBJECT_FILES> Debug\loader.o Debug\myboot.o
# Interrupt vectors file - section reserved for STVD#<BEGIN VECTOR_FILE> +seg .const -b 0x8000 -k Debug\myboot.o#<END VECTOR_FILE>
从lkf文件中可以看出bootloader程序分成了两个部分:loader和myboot。 Myboot完成两个事1、中断向量表的中断函数地址从0x8000跳转到0x8200的相对位置;2、把loader程序拷贝到以0x200起始的内存中并执行;loader只是把备份区的程序拷贝到运行程序空间,完成后擦除备份区的更新标志;loader程序编译完成后是写在eeprom的 +seg .xtext -b 0x4140 -m 0x140 -n .xtext的位置,stm8s005芯片内部eeprom有1Kbytes空间。(放在程序空间0x8080~0x81FF)
Bootloader需要使用的数据:
new_program_mark: 0xC170 更新程序标志(1byte)
new_prg_sz: 0xC16E 程序文件大小(2bytes)
升级文件中包含的数据:
file_ver: 0xC16C 程序版本(2bytes)
new_prg_sz: 0xC16E 程序文件大小(2bytes)
device_type: 0xC172 设备类型(8bytes)
升级相关工具:
stm8up.exe:上位机软件,通过抄控器与待升级设备通信。
cal_file_crc.exe:修改程序文件:计算文件大小写到0x826E位置;计算文件CRC写到0x826C位置;设备类型写到0x8272位置。
s19_2_bin_tool.exe:编译完成的程序文件是S19格式,转换成bin格式给cal_file_crc.exe软件使用。
④应用程序升级流程:
应用程序结构图:
系统时钟初始化 |
看门狗初始化 |
串口初始化 |
升级程序 |
其他硬件初始化 |
数据初始化 |
程序主循环while(1) |
⑤升级协议:
FBD数据格式:
cmd(1) | seq(2) | ack(1) | crc(2) | length(1) | data(n) |
cmd:表示升级命令0x05。
seq:0表示启动升级;
1~0xFFFE表示升级块数;
0xFFFF表示升级完成。
设备类型:按照设备类型格式定义(厂商号(2)+设备种类(2)+设备型号(2)+附加信息(2))。
crc:升级文件crc16(设备响应同一升级版本命令,并需要保存成功升级版本号)。实际使用程序文件的crc16校验(crc16校验)。
ack:0表示上位机不需要设备应答;1表示上位机要求设备应答;
length:data长度。
data:数据包传输帧:程序分块数据。
启动帧数据格式:程序文件大小(4)+程序文件crc(2)+数据包大小(1)+设备类型<厂商号(2)+设备种类(2)+设备型号(2)+附加信息(2)>。
升级流程:
注:1、启动帧命令中数据改变说明需要重新开始升级。升级过程中数据包大小改变需重新开始升级。
2、设备收到上位机发送的启动升级命令。通过程序文件大小、数据包大小可以计算出程序升级包块数。升级完成后,发送升级完成帧命令,
并自动重启。
3、上位机发送升级命令时,如果使用的是无应答方式,上位机软件发送报文间隔时间要大于2s。因为载波芯片在接收到非广播数据时会有2s时间的超时等待设备mcu应答。
1、启动帧格式:
cmd | seq_0 | seq_1 | ack | crc_0 | crc_1 | length | file size(4) | file crc(2) | block size(1) | 设备类型(8) |
05 00 00 01 xx xx 0f xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
正常应答帧格式:
cmd | seq_0 | seq_1 | ack | crc_0 | crc_1 | length |
05 xx xx 00 xx xx 00
否认应答帧格式(程序文件大小、版本和设备类型有一个不同,返回当前程序信息):
cmd | seq_0 | seq_1 | ack | crc_0 | crc_1 | length | file size(4) | file crc(2) | block size(1) | 设备类型(8) |
05 00 00 00 xx xx 0f xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
2、传输数据帧格式:
cmd | seq_0 | seq_1 | ack | crc_0 | crc_1 | length(n) | data(n) |
05 xx xx 00/01 xx xx n xx...(n)
应答帧格式(下行报文ack为1时):
cmd | seq_0 | seq_1 | ack | crc_0 | crc_1 | length |
05 xx xx 00 xx xx 00
升级完成帧格式:(seq = 0xFFFF)
cmd | seq_0 | seq_1 | ack | crc_0 | crc_1 | length |
05 xx xx 00 xx xx 00
否认应答帧格式(程序文件大小、版本和设备类型有一个不同,返回当前程序信息):
cmd | seq_0 | seq_1 | ack | crc_0 | crc_1 | length | file size(4) | file crc(2) | block size(1) | 设备类型(8) |
抄控器地址设置:
上位机设置地址00000001:[发送]7E 00 00 00 00 00 00 00 00 00 05 01 01 00 00 00 85
抄控器应答:[接收]7E 00 00 00 00 00 00 00 00 00 01 00 7F
上位机设置地址00000001:[发送]7E 00 00 00 00 00 00 00 00 00 05 01 01 00 00 00 85
抄控器地址被重复设置应答:[接收]7E 00 00 00 00 00 00 00 00 00 01 FF 7E
报文举例:
1、启动升级:
->7E 02 00 00 00 CF 2C 00 66 01 17 05 00 00 01 E2 1D 0E 00 00 00 80 01 02 80 FF FF 18 00 01 00 01 00 cs
<-7E CF 2C 00 66 02 00 00 00 81 07 05 00 01 00 00 00 00 cs
2、升级报文1:(上位机下发升级数据)
->7E 02 00 00 00 CF 2C 00 66 01 0E 05 00 01 00 E2 1D 40 data(64bytes) cs
<-无应答
3、升级报文2:(上位机查询需要升级块号)
->7E 02 00 00 00 CF 2C 00 66 01 0E 05 00 00 01 E2 1D 07 00 00 00 80 01 02 80 cs
<-7E CF 2C 00 66 02 00 00 00 81 07 05 XX XX(2bytes 设备需要升级的块号) 00 00 00 00 cs
<-升级完成报文:7E CF 2C 00 66 02 00 00 00 81 07 05 FF FF 00 00 00 00 cs
crc16计算附录:
unsigned short sp_crc16_with_init(unsigned short crc, const unsigned char *buf, int size)
{
unsigned char i;
while(size--!=0)
{
for(i=0x80; i!=0; i/=2)
{
if((crc&0x8000)!=0)
{
crc*=2;
crc^=0x1021;
} /* 余式CRC乘以2再求CRC */
else
{
crc*=2;
}
if((*buf&i)!=0)
{
crc^=0x1021; /* 再加上本位的CRC */
}
}
buf++;
}
return(crc);
}
unsigned short sp_crc16(const unsigned char *buf, int size)
{
return(sp_crc16_with_init(0x00,buf,size));
}