1.关于BootLoader程序的设定
FLASH部分区域如下图:
如图所示可以看出来,默认情况下0X8000-0X8080时中断向量表。假如我们准备给BootLoader的程序分配4KB的空间,即从0X8000-0X9000存储BootLoader程序。那么相应的中断向量也应该映射到0X9000-0X9080区域。根据ST官方例程当用户编程区选择的起始地址为0X9000时可在main.c 文件中声明以下代码将中断向量映射到0X9000-0X9080区域。但是注意如果中断向量映射过去后,BootLoader程序将无法使用中断。
__root const long reintvec[]@".intvec"=
{ 0x82008080,0x82009004,0x82009008,0x8200900c,
0x82009010,0x82009014,0x82009018,0x8200901c,
0x82009020,0x82009024,0x82009028,0x8200902c,
0x82009030,0x82009034,0x82009038,0x8200903c,
0x82009040,0x82009044,0x82009048,0x8200904c,
0x82009050,0x82009054,0x82009058,0x8200905c,
0x82009060,0x82009064,0x82009068,0x8200906c,
0x82009070,0x82009074,0x82009078,0x8200907c,
};
关于IAR编译器的链接文件及工程设置
工程链接文件需要我们自己定义,所示我们可以从编译器默认的位置复制一份,用记事本打开并做出如图的更改。
如果BootLoader的程序不超过4Kb,只需更改
define block INTVEC with size = 0x100 { ro section .intvec };
因为这是重新映射了中断向量的定义,默认0X80,不然编译会报错。
然后重新在工程中设置使用刚才的链接文件如图:
用的是STM8L052R8T6,因此工程中还需要做如下改动,如图:
2.关于UserAPP程序的设定
UserAPP的设定相当简单,只需要更改上述的链接文件即可,如图所示:
STM8L052R8T6 是64KB的Flash,最大到0X17FFF
当然工程中勾选生成二进制bin也是必须的,后面我们会用到该文件写入Flash。如图所示:
3.BootLoader程序的跳转和数据接收
跳转到用户程序
根据官方的例程跳转到指定Flash地址在IAR编译器中推荐的汇编代码如下:
asm("LDW X, SP ");
asm("LD A, $FF");
asm("LD XL, A ");
asm("LDW SP, X ");
asm("JPF $9000");
当然在main.c中最好申明#pragma SRC
2. 数据的接收
考虑到BootLoader不能用串口中断接收数据了,那现在我们只能用循环接收的方式来接收串口发来的数据,如果超时则程序退出循环,执行其他逻辑。可参考如下代码:
while(Delay_Time<0X10)
{
Delay_Count++;
if(USART_GetFlagStatus(USART3, USART_FLAG_RXNE)==SET)
{
Uart3_ReciveData[Size] = USART_ReceiveData8(USART3);
Size++;
}
if(Delay_Count==0XFFF0)
{
Delay_Count=0;
Delay_Time++;
}
if(Size>3) break; //收到一定数据跳出 跳出后可进行数据判断
}
if(Delay_Time==0X10) //时间到
{
JumptoUserMain();
}
3.Flash相关操作
关于内存块的划分,对于STM8L052R8T6如下图:
从图中可以看出Flash program memory地址从0X8000-0X9000共64KB,共256页(Page),512块(Block),每个块128Bit。如果按图中的页地址或者块地址来划分BootLoader和UserAPP的区域的话有个很大的好处,就是可以利用库函数直接一块一块写,非常方便。如果按本例程Bootloader程序需要将UserAPP生成的.bin文件从地址0X9000开始写入Flash,利用库函数可以直接从第32个块开始写,直到写入到指定的块地址结束。
UserAPP的工程文件生成.bin文件写入Flash
为了简单的实现IAP的目的,未没加入任何协议和其他逻辑,只是为了单纯的实现这个功能。-.- 哈哈哈
①首先bin文件是个单纯的二进制文件,利用上位机获取.bin文件后发送升级指令及写入块的大小(升级MCU写入的块大小的字节长度为:
if (file.Length % 128 == 0) //刚好是128字节的整数倍
{
BlockNum = (int)file.Length / 128; //BlockNum 即为写入的块数目
}
else
{
BlockNum = (int)file.Length / 128 + 1;//加一块 后面不足位补0
}
cmdbuf[2] = (byte)(BlockNum >> 8);
cmdbuf[3]= (byte)(BlockNum&0XFF);
serialport.Write(cmdbuf, 0, 4);
),若MCU回应,则将.bin文件拆开每次按128bit的数据发送给MCU,最后一块不足128bit后位补0至128bit,因为STM8L052R8T6的Flash一块刚刚好128bit.
②当MCU每次接收到128bit的数据时,放入缓冲数组,按照上述直接从第32块开始写,写完重新接收再写,如此反复直至写入结束。库函数如下:
写入flash前:
FLASH_SetProgrammingTime(FLASH_ProgramTime_Standard);
FLASH_Unlock(FLASH_MemType_Program);
while (FLASH_GetFlagStatus(FLASH_FLAG_PUL) == RESET)
写入flash:
if(Size>=FLASH_BLOCK_SIZE)
{
Size=0;
FLASH_ProgramBlock(BLOCK_OPERATION, FLASH_MemType_Program, FLASH_ProgramMode_Standard, Uart3_ReciveData);
BLOCK_OPERATION++; //写入起始块++
/* Wait until End of high voltage flag is set*/
while (FLASH_GetFlagStatus(FLASH_FLAG_HVOFF) == RESET)
USART3_SendByte(BLOCK_OPERATION>>8);
USART3_SendByte(BLOCK_OPERATION&0XFF);
}
写入flash结束后:
FLASH_Lock(FLASH_MemType_Program);
JumptoUserMain();
注意上位机每次发送数据应间隔一段时间。
③FLASH库函数的操作要注意以下几点:根据资料:
For IAR Compiler:
1- Use the __ramfunc keyword in the function declaration to specify that it
can be executed from RAM.
This is done within the stm8l15x_flash.c file, and it’s conditioned by
RAM_EXECUTION definition.
2- Uncomment the “#define RAM_EXECUTION (1)” line in the stm8l15x.h file, or
define it in IAR compiler preprocessor to enable the access for the
__ramfunc functions.
首先Flash的块操作必须在RAM中进行,这必须需要在stm8l15x_flash.c 文件中的flash块操作函数前加入 __ramfunc 关键字。
__ramfunc IN_RAM(void FLASH_ProgramBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType, FLASH_ProgramMode_TypeDef FLASH_ProgMode, uint8_t *Buffer))
其次,stm8l15x_flash.h中添加注释#define RAM_EXECUTION (1).
5.相关测试
经测试,在UserApp工程中生成的bin文件,通过上位机发送BootLoader并且写入Flash后 定时器TIM2的中断可正常工作。
上一篇:stm8程序占用flash和ram 插件
下一篇:STM8的IAP与APP
推荐阅读最新更新时间:2024-11-11 12:31
设计资源 培训 开发板 精华推荐
- 使用 Sanken Electric Co., Ltd 的 STR2000 的参考设计
- LT1184FCS 浮动 CCFL 的典型应用电路,具有电位器控制灯电流
- IRS2548D SMPS/LED 驱动器 PFC + 半桥控制的典型应用
- LTC1628-SYNC 最大限度地减少了多输出、高电流电源中的输入电容器
- 使用 STMicroelectronics 的 RST1S31HF 的参考设计
- AT8236直流电机驱动器使用CH32F203其他C8T6通用
- 便携式电池充电器
- 使用 Analog Devices 的 LTC1669-8CMS8 的参考设计
- OP284FSZ-REEL7 具有限流功能的低压差稳压器的典型应用
- 使用 ON Semiconductor 的 KA7810E 的参考设计