打印
[STM8]

STM8L IAP 使用说明

[复制链接]
792|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
前言
本篇主要介绍 STM8Lxxxx 如何实现在应用程序中编程(In-application programming)。

使用特权

评论回复
沙发
菜鸟的第一步|  楼主 | 2021-11-14 21:49 | 只看该作者
1. IAP user Flash 分配框图及中断向量表重定向

使用特权

评论回复
板凳
菜鸟的第一步|  楼主 | 2021-11-14 21:50 | 只看该作者
注意:
1 和 2 为 IAP 代码空间。为客户自己的 bootloader 代码,应用程序中更新 Flash 的代码。
3 和 4 为客户应用程序代码,实现产品具体操作功能。
中断向量表 1 中除了 Reset,其他存放的是指向中断向量表 2 的地址;中断向量表 2 中放的是具体的 APP 中断处理程序入口
地址。发生中断后 PC 指针先指向中断向量表 1,然后再指向中断向量表 2,最后到具体的中断处理函数处。
客户应用程序起始位置(上图是 0x9000)可以根据客户需要设置,比如可以改 0x9000 为 0xA000(如果客户的
bootloader 程序超过 0x9000 但没有超过 0xA000 可以这样设置)。

使用特权

评论回复
地板
菜鸟的第一步|  楼主 | 2021-11-14 21:51 | 只看该作者
2. IAP 对中断向量表重定向的说明
STM8 的中断向量位置是固定的,大部分是 0x8000 开始处。IAP 程序中需要手工处理中断向量表。并且 boot 程序不
能使用任何中断(IAP 程序中的中断跳转(中断向量表 1)会使 PC 指到 0x900x 处,如果此时 APP 没有程序,程序就会出
错。),程序中的所有中断(向量表 1)的处理最终都要跳转到用户程序的中断向量表 2 处。
IAP bootloader 参考程序为 STSW-STM8006。可以在 www.st.com 或是 www.stmcu.com.cn 上下载。
下面以 STVD 工程 Cosmic 为例进行说明。
…\STSW-STM8006\AN2659-IAP_using_user-bootloader\Project\STM8L_User-Bootloader_example\STVD\Cosmic
Stm8_interrupt_vector.c: 下面的中断向量表 1 位于 0x8000 到 0x8080 地址空间。
假设发生了 0x8001 中断,指针经硬件定向到了 0x8001,在 0x8001 里存储的是跳转到 0x9001 代码,然后程序跳转
到 0x9001 位置去执行,而 0x9001 中的代码是跳转到具体的中断函数处。(具体代码中使用函数指针来实现)
0x82 为操作码,意思是跳转到后面的地址去执行。如下例:

//*********IAP bootloader 程序中的 中断向量表 1 ************************** 
extern void _stext(); /* startup routine */
struct interrupt_vector const UserISR_IRQ[32] [url=home.php?mod=space&uid=72445]@[/url] MAIN_USER_RESET_ADDR;
//redirected interrupt table
struct interrupt_vector const _vectab[] = {
{0x82, (interrupt_handler_t)_stext}, /* reset */ //note:向量表代码开始位置为
0x8000,0x82 后面的 24bits 存放 0x9000
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 1)}, /* trap */ //note:代码位于
0x8001,0x82 后面的 24bits 存放 0x9001
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 2)}, /* irq0 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 3)}, /* irq1 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 4)}, /* irq2 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 5)}, /* irq3 */
Step1 发生中断
Step2 跳转到向量表 2
Step3 跳转到具体的处理函数
Step4 APP 软件发生中断
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 6)}, /* irq4 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 7)}, /* irq5 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 8)}, /* irq6 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 9)}, /* irq7 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+10)}, /* irq8 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+11)}, /* irq9 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+12)}, /* irq10 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+13)}, /* irq11 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+14)}, /* irq12 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+15)}, /* irq13 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+16)}, /* irq14 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+17)}, /* irq15 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+18)}, /* irq16 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+19)}, /* irq17 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+20)}, /* irq18 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+21)}, /* irq19 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+22)}, /* irq20 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+23)}, /* irq21 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+24)}, /* irq22 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+25)}, /* irq23 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+26)}, /* irq24 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+27)}, /* irq25 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+28)}, /* irq26 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+29)}, /* irq27 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+30)}, /* irq28 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+31)}, /* irq29 */
};
//*********************************************************************************

使用特权

评论回复
5
菜鸟的第一步|  楼主 | 2021-11-14 21:52 | 只看该作者
对 0x82 的描述在文件 PM0044 有如下描述: 0x82 为内部指令:
在 main.h 里有下面的代码: MAIN_USER_RESET_ADDR 的地址为 0x9000。所以 APP 代码开始的位置在 0x9000,开始存
放第二个中断向量表(中断向量表 2),此处为中断处理函数入口地址的重定向表。
//*********************************************************************************
//user application start (user interrupt table address)
#define MAIN_USER_RESET_ADDR 0x9000ul
//*********************************************************************************

使用特权

评论回复
6
菜鸟的第一步|  楼主 | 2021-11-14 21:53 | 只看该作者
3. STVD 软件中,下图 Project/Settings 中对中断向量表位置的处理可以看到。 中断向量表 1 是从 0x8000 开始存放(Vector file name and Vector addr.)。

对“Vector file name”的定义为“stm8_interrupt_vector.c”;“Vector address”定义为“0x8000”地址。如下图。

使用特权

评论回复
7
菜鸟的第一步|  楼主 | 2021-11-14 21:55 | 只看该作者
…\STSW-STM8006\AN2659-IAP_using_user-bootloader\Project\STM8L_User-Bootloader_example\STVD\Cosmic\Debug
有文件“userbootloader.lkf”,有代码如下:(当这个文件中的设置同 STVD Project/Settings/Linker 对画框中的设置不一样时,
优先使用对话框中的设置)
//**********************************************************************************
# Segment configuration - section reserved for STVD
#<BEGIN SEGMENT_CONF>
# Segment Code,Constants:
+seg .const -b 0x8080 -m 0x7f80 -n .const -it
+seg .text -a .const -n .text
# Segment Eeprom:
+seg .eeprom -b 0x1000 -m 0x400 -n .eeprom
# Segment Zero Page:
+seg .bsct -b 0x0 -m 0x100 -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 0x100 -m 0x4ff -n .data
+seg .bss -a .data -n .bss
+seg .FLASH_CODE -a .bss -n .FLASH_CODE -ic
#<END SEGMENT_CONF

# Interrupt vectors file - section reserved for STVD
#<BEGIN VECTOR_FILE>
+seg .const -b 0x8000 -k 
Debug\stm8_interrupt_vector.o
#<END VECTOR_FILE>
//*******************************************************************************



使用特权

评论回复
8
菜鸟的第一步|  楼主 | 2021-11-14 21:56 | 只看该作者
4. User Flash 空间烧写方式
Bootloader 程序可以烧写内部 Flash、EEPROM、RAM。适用于产品软件的更新。

使用特权

评论回复
9
菜鸟的第一步|  楼主 | 2021-11-14 21:57 | 只看该作者
5.对 _fctcpy 的说明,对 Flash 的大块区域编程的代码在 RAM 中运行的问题解
决。
对 Flash 进行大块区域的编程的代码需要在 RAM 中运行,为了实现这个,需要一个自定义代码段,并将这个代码段放在
RAM 中。在例程中定义了一个“.FLASH_CODE”段。 请查看下面代码红色区域。
 //*********************IAP 的 bootloader 程序********************************* 
#ifdef _COSMIC_
#pragma section (FLASH_CODE) //定义 FLASH_CODE 代码段
#endif /* _COSMIC */
#ifdef _IAR_
#pragma location = "FLASH_CODE"
#endif /* _IAR_ */
#ifdef _RAISONANCE_
void Mem_ProgramBlock(u16 BlockNum, FLASH_MemType_TypeDef MemType, u8 *Buffer) inram
#else
void Mem_ProgramBlock(u16 BlockNum, FLASH_MemType_TypeDef MemType, u8 *Buffer)
#endif /*_RAISONANCE_*/
Byte/Work 编程 (1~4bytes) 块编程 (由具 体 STM8 IC 确 定 优点:小区域编程,code 可以在 Flash 里执行。 适合几个 bytes 的编程,或是可以接受很慢的编程速度 缺点:烧写 Flash 时,code 的执行停止(几个 ms); 速度慢。 优点:大块区域编程,速度快。 缺点:code 必须在 RAM 里执行,需要拷贝代码到 RAM 里。 拷贝可执行代码到 RAM 里/保存 RAM 代码/允许代码在 RAM 空间/编译代码使其能在 RAM 里运行。 客户程序空间烧写 User Flash programming
{
u16 Count = 0;
u32 StartAddress = 0;
u16 timeout = (u16)0x6000;

/* Set Start address wich refers to mem_type */
if (MemType == FLASH_MEMTYPE_PROG)
{
StartAddress = FLASH_START;
}
else
{
StartAddress = EEPROM_START;
}
/* Point to the first block address */
StartAddress = StartAddress + ((u32)BlockNum * BLOCK_SIZE);
/* Standard programming mode */
FLASH->CR2 |= (u8)0x01;

/* Copy data bytes from RAM to FLASH memory */
for (Count = 0; Count < BLOCK_SIZE; Count++)
{
*((PointerAttr u8*)StartAddress + Count) = ((u8)(Buffer[Count]));
}
#if defined (STM8S208) || defined(STM8S207) || defined(STM8S105)
if (MemType == FLASH_MEMTYPE_DATA)
{
/* Waiting until High voltage flag is cleared*/
while ((FLASH->IAPSR & 0x40) != 0x00 || (timeout == 0x00))
{
timeout--;
}
}
#endif /* STM8S208, STM8S207, STM8S105 */
}
#ifdef _COSMIC_
#pragma section () //普通默认代码段
#endif /* __COSMIC__ */
//*******************************************************************************



使用特权

评论回复
10
菜鸟的第一步|  楼主 | 2021-11-14 21:59 | 只看该作者
_fctcpy 功能:
COSMIC 中的函数_fctcpy 是将 Flash 中的代码拷贝到 RAM 中并运行。_fctcpy 寻找 linker 定义的描述符(此描述符是在 RAM
中定义段的第一个字符),在 STSW-STM8006 中定义了一个段 FLASH_CODE (#pragma section (FLASH_CODE))。因
此第一个字符是‘F’.
在 mian 函数中调用_fctcpy('F')的作用是把 FLASH_CODE 段拷贝到 RAM 中并运行。
FLASH_CODE 是一个可以移动的段,需要在 IAP “boot 程序链接配置”的 RAM 区添加。
在 RAM 中创建一个“.FLASH_CODE”段,并在 Option 中输入“-ic”;“.FLASH_CODE”表示在 RAM 中定义一个
FLASH_CODE 的段,程序可以从此地址运行。“-ic”表示标记这个段为可移动的段,可将 Flash 中的代码移植到此。

void main(void) 
{

_fctcpy('F'); //把 FLASH_CODE 代码拷贝到 RAM 中并运行

}



使用特权

评论回复
11
菜鸟的第一步|  楼主 | 2021-11-14 22:01 | 只看该作者
可以在生成的*.map 文件中检查生成的段是否正确,示例代码中有如下的 map 文件
//******************************************************************************* 
--------
Segments
--------
start 00008080 end 000080a2 length 34 segment .const
start 00008104 end 00008be0 length 2780 segment .text
start 00001000 end 00001000 length 0 segment .eeprom
start 00000000 end 00000001 length 1 segment .bsct, initialized
start 000080af end 000080b0 length 1 segment .bsct, from
start 00000001 end 00000091 length 144 segment .ubsct
start 00000091 end 00000091 length 0 segment .bit
start 00000091 end 00000091 length 0 segment .share
start 00000100 end 00000100 length 0 segment .data
start 00000100 end 00000100 length 0 segment .bss
start 00000100 end 00000154 length 84 segment .FLASH_CODE, initialized
start 000080b0 end 00008104 length 84 segment .FLASH_CODE, from
start 00000000 end 000004de length 1246 segment .info.
start 00000000 end 00000e70 length 3696 segment .debug
start 00008000 end 00008080 length 128 segment .const
start 000080a2 end 000080af length 13 segment .init
//*******************************************************************************
“from”为存放代码的部分。“initialized”为执行代码的部分。
IAP 的 bootloader 和 APP 分开为两个独立的工程文件。上面的内容是针对 IAP 的 bootloader 的程序工程的处理说明(属于
图 1 中的“1.中断变量表 1,复位后硬件 PC 指针从这里开始”和“2.客户程序中的 bootloader 代码” 段),下面来说说
APP 工程段(图 1 中的 3 和 4 代码段)。


使用特权

评论回复
12
菜鸟的第一步|  楼主 | 2021-11-14 22:02 | 只看该作者
6. APP 工程说明。
在 APP 工程里,设置中断向量地址为 0x9000(上面以 0x9000 为例。如果从 0xA000 开始,就设置为 0xA000)。代码段的
起始地址为 0x9080. 编译后生成的二进制文件就是需要通过 bootloader 烧写到 Flash 0x9000 之后地址的 APP 程序。


使用特权

评论回复
13
drer| | 2021-12-9 12:02 | 只看该作者
层次非常的清晰

使用特权

评论回复
14
zljiu| | 2021-12-9 12:03 | 只看该作者
需要什么操作平台呢

使用特权

评论回复
15
coshi| | 2021-12-9 12:04 | 只看该作者
这个系列和其他的是通用的吧

使用特权

评论回复
16
aoyi| | 2021-12-9 12:06 | 只看该作者
需要详细了解寄存器地址啥的吧

使用特权

评论回复
17
gwsan| | 2021-12-9 12:09 | 只看该作者
它有什么优势吗

使用特权

评论回复
18
duo点| | 2021-12-9 16:04 | 只看该作者
它有什么特别的地方吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

57

主题

436

帖子

1

粉丝