place in FarFuncCode { ro section .far.rodata,
ro section .far_func.text };
place in HugeFuncCode { ro section .huge.rodata,
ro section .huge_func.text };
place in Eeprom { section .eeprom.noinit };
place in Eeprom { section .eeprom.data };
place in Eeprom { section .eeprom.rodata };
/////////////////////////////////////////////////////////////////
2、APP程序
(1)主函数
#include \
void Clk_Init(void) {
CLK_SWR = 0x01; //HSI selected as system clock source CLK_CKDIVR = 0x00; //System clock source/1 }
void Jump_To_App(void) {
asm(\ SP \ asm(\ A, $FF\ asm(\ XL, A \ asm(\, X \
asm(\ //9000是要跳转到偏移地址 }
void main(void) {
Clk_Init();
PC_DDR |= 0x80; //PC7输出口 PC_CR1 |= 0x80; //PC7推挽输出 PC_CR2 |= 0x80; //PC7输出速度最大为10MHZ PC_ODR &= ~0x80;//PC7输出低
Timer2_Init(200);
rim();
while(1) {
}
}
(2)定时器函数
TIM TimerCount; //定时器计数器
void Speak(void) { u8 i = 255; while(i > 0) { Buzzer_On(); Delayus(185); Buzeer_Off(); Delayus(185); i--; } }
void Buzzer(u8 speakcnt) //算了,把Buzzer函数也贴出来吧 { while(speakcnt > 0) { Speak(); Delayms(30); Delayms(30); Delayms(30); speakcnt--; } }
/*********************************************** * 文件名 :Timer2_Init
* 描述 :定时器4初始化 1ms定时周期 * 创建时间 :2017-05-17
************************************************/ void Timer2_Init(u8 ms) {
if(ms>254) ms = 254;
CLK_PCKENR1 |= 0x01; //Enable TIM2 clock TIM2_PSCR = 0x06; //prescaler:(2^6) = /64 TIM2_ARRH = ms; TIM2_ARRL = 250; //SYS_CLK_HSI_DIV1 Auto-Reload value: 16M / 64 = 1/4M, 1/4M / 1k = 250 TIM2_CNTRH = 0; TIM2_CNTRL = 0; //Counter value: 0, to compensate the initialization of TIMER TIM2_IER |= 0X01; //TIM2 Update interrupt enabled TIM2_SR1 &= ~0x01; //clear update flag TIM2_CR1 |= 0x01; //Enable Counter }
/*********************************************** * 文件名 :Timer2
* 描述 :定时器2中断入口函数 * 创建时间 :2017-05-17
************************************************/ #pragma vector = 0x15
__interrupt void Timer2_IRQhandle(void) {
TimerCount.T2++;
if(TimerCount.T2 == 5) {
TimerCount.T2 = 0; Buzzer(1); //Buzzer是蜂鸣器函数,大家板子上没有的可以随便写一个验证函数, //比如LED什么的,主要是为了验证升级成功了 }
TIM2_SR1 &= ~0x01; //clear }
(3)lnkstm8l052r8_App.icf
///////////////////////////////////////////////////////////////// // Example ILINK command file for
// STM8 IAR C/C++ Compiler and Assembler. //
// Copyright 2014 IAR Systems AB. //
/////////////////////////////////////////////////////////////////
define memory with size = 16M;
define region TinyData = [from 0x00 to 0xFF];
define region NearData = [from 0x0000 to 0x0FFF];
define region Eeprom = [from 0x1000 to 0x10FF];
define region BootROM = [from 0x6000 to 0x67FF];
define region NearFuncCode = [from 0xB800 to 0xDFFF];
define region FarFuncCode = [from 0xB800 to 0xDFFF];
define region HugeFuncCode = [from 0xB800 to 0xDFFF]; /*
define region NearFuncCode = [from 0x8000 to 0xFFFF];
define region FarFuncCode = [from 0x8000 to 0xFFFF]
| [from 0x10000 to 0x17FFF];
define region HugeFuncCode = [from 0x8000 to 0x17FFF]; */
/////////////////////////////////////////////////////////////////
define block CSTACK with size = _CSTACK_SIZE {};
define block HEAP with size = _HEAP_SIZE {};
define block INTVEC with size = 0x80 { ro section .intvec };
// Initialization
initialize by copy { rw section .far.bss,
rw section .far.data,
rw section .far_func.textrw, rw section .huge.bss, rw section .huge.data,
rw section .huge_func.textrw,
rw section .iar.dynexit, rw section .near.bss, rw section .near.data,
rw section .near_func.textrw, rw section .tiny.bss, rw section .tiny.data, ro section .tiny.rodata };
initialize by copy with packing = none {section __DLIB_PERTHREAD };
do not initialize { rw section .eeprom.noinit, rw section .far.noinit, rw section .huge.noinit, rw section .near.noinit, rw section .tiny.noinit, rw section .vregs };
// Placement
place at start of TinyData { rw section .vregs }; place in TinyData { rw section .tiny.bss,
rw section .tiny.data, rw section .tiny.noinit, rw section .tiny.rodata };
place at end of NearData { block CSTACK }; place in NearData { block HEAP,
rw section __DLIB_PERTHREAD, rw section .far.bss, rw section .far.data, rw section .far.noinit,
rw section .far_func.textrw, rw section .huge.bss, rw section .huge.data, rw section .huge.noinit,
rw section .huge_func.textrw, rw section .iar.dynexit, rw section .near.bss, rw section .near.data, rw section .near.noinit,
rw section .near_func.textrw };
place at start of NearFuncCode { block INTVEC };
place in NearFuncCode { ro section __DLIB_PERTHREAD_init, ro section .far.data_init,
ro section .far_func.textrw_init, ro section .huge.data_init,
ro section .huge_func.textrw_init, ro section .iar.init_table, ro section .init_array,
ro section .near.data_init, ro section .near.rodata, ro section .near_func.text, ro section .near_func.textrw_init,
ro section .tiny.data_init, ro section .tiny.rodata_init };
place in FarFuncCode { ro section .far.rodata,
ro section .far_func.text };
place in HugeFuncCode { ro section .huge.rodata,
ro section .huge_func.text };
place in Eeprom { section .eeprom.noinit };
place in Eeprom { section .eeprom.data };
place in Eeprom { section .eeprom.rodata };
/////////////////////////////////////////////////////////////////
二、STM8L052R8在线升级步骤
1、在bootloader程序中重新映射中断向量表(直接放在bootloader程序就行),其中0x8200B804中的B800是重新映射的起始地址, //中断向量重映射
__root const long reintvec[]@\{
0x82008080,0x8200B804,0x8200B808,0x8200B80c, 0x8200B810,0x8200B814,0x8200B818,0x8200B81c, 0x8200B820,0x8200B824,0x8200B828,0x8200B82c, 0x8200B830,0x8200B834,0x8200B838,0x8200B83c, 0x8200B840,0x8200B844,0x8200B848,0x8200B84c, 0x8200B850,0x8200B854,0x8200B858,0x8200B85c, 0x8200B860,0x8200B864,0x8200B868,0x8200B86c,
0x8200B870,0x8200B874,0x8200B878,0x8200B87c, };
2、重新分配bootloader工程的lnkstm8l052r8_boot.icf文件中定义的地址起始,定义bootloader文件占用空间的大小,例如:
更改后的地址分配 0x8000--0xD7FF bootloader工程被分配占用22K空间 define region NearFuncCode = [from 0x8000 to 0xD7FF]; define region FarFuncCode = [from 0x8000 to 0xD7FF]; define region HugeFuncCode = [from 0x8000 to 0xD7FF]; /*
原文件的空间分配
define region NearFuncCode = [from 0x8000 to 0xFFFF]; define region FarFuncCode = [from 0x8000 to 0xFFFF]
| [from 0x10000 to 0x17FFF]; define region HugeFuncCode = [from 0x8000 to 0x17FFF]; */
3、重新分配App工程的lnkstm8l052r8_App.icf文件中定义的地址起始,定义App文件占用空间的大小,例如:重新分配APP的起始地址, 0xB800 -- 0xDFFF App工程被分配占用10K空间
define region NearFuncCode = [from 0xB800 to 0xDFFF]; define region FarFuncCode = [from 0xB800 to 0xDFFF]; define region HugeFuncCode = [from 0xB800 to 0xDFFF]; /*
原文件的空间分配
define region NearFuncCode = [from 0x8000 to 0xFFFF]; define region FarFuncCode = [from 0x8000 to 0xFFFF]
| [from 0x10000 to 0x17FFF]; define region HugeFuncCode = [from 0x8000 to 0x17FFF];
*/ 4、将lnkstm8l052r8_boot.icf和lnkstm8l052r8_App.icf,放置在安装目录下的config文件夹下面,(“C:\\Program Files\\IAR Systems\\Embedded Workbench 7.0\\stm8\\config”),否则有些功能可能不能实现。
5、需要在Opition中的LINK选项下链接“$TOOLKIT_DIR$\\config\\lnkstm8l052r8_boot.icf”“$TOOLKIT_DIR$\\config\\lnkstm8l052r8_App.icf”,否则不能实现在线升级。不能运行App程序。 6、bootloader工程接收并向Flash中写完App工程的数据后,会向APP_Valid_address地址写入temp_Valid_flag数组的数据,然后软件复位,重新开始运行bootloader程序,检测到APP_Valid_address地址的数据有效后,就跳向App起始地址开始运行App程序。
7、 用串口助手(sscom3)发送升级命令7E 01 00 02 02 56 17 5B E7,其中02 56是要升级的总字节数(要根据自己的文件大小更改),17 58是16位的CRC校验(命令不同校验码不同),7E、E7分别是包头和包尾,01是命令,发送完升级命令后,bootloader程序会发送0x55到串口助手,然后再发送你要升级的文件(升级文件用的.bin格式),发送完成后蜂鸣器每隔一秒响一次。
8、因为百度文库不能上传压缩包,只能上传文档,所以大部分的程序只能都贴到word里了,看着有些费劲,但是大部分的程序都贴出来了,想学习在线升级的朋友就不要嫌麻烦,自己建立工程整理代码吧!