【IAR工程】STM8S208RB基于ST标准库内部EEPROM使用
【IAR工程】STM8S208RB基于ST标准库内部EEPROM使用
- 📍相关篇《【IAR工程】STM8S208RB基于ST标准库软硬件I2C方式实现读写AT24Cxx》
- 🔖基于ST STM8S/A标准外设库:STSW-STM8069,版本号:
2.3.1
- 📌STSW-STM8069官方资源下载地址:
https://www.st.com/zh/embedded-software/stsw-stm8069.html
- 🔧IAR编译器版本:
IAR Assembler for STMicroelectronics STM8 3.11.1
- 📌STM8S207/208RBT6最小系统板:
https://oshwhub.com/perseverance51/stm8s207rbt6-kai-fa-ban
- 🔖以下为在官方手册上有关对于内部EEPROM(DATA) 描述内容。
📑数据EEPROM(DATA)
数据EEPROM(DATA)区域可用于存储用户具体项目所需的数据。默认情况下,DATA区域是写保护的,这样可以在主程序工作在IAP模式时防止DATA区域被无意地修改。只有使用特定的MASS密钥才能对DATA区域的写保护解锁.
📓存储器组织结构
STM8S的EEPROM以32位字长(每字4字节)为基础组织起来。根据不同的器件,存储器组织机构有所不同:
● 小容量STM8S器件(EEPROM的起始地址为0x004000
,结束地址为0x00427F
)
─ 8K FLASH程序存储器,每页64字节,共128页
─ 640字节数据EEPROM,每页64字节,共10页。数据EEPROM包括一页的选项字节
(64字节)。
● 中容量STM8S器件(EEPROM的起始地址为0x004000
,结束地址为0x0043FF
)
─ 从16K到32K FLASH程序存储器,每页512字节,最多64页
─ 1K字节数据EEPROM,每页512字节,共2页。数据EEPROM包括一页的选项字节(512字节)。
● 大容量STM8S器件(EEPROM的起始地址为0x004000
,结束地址为0x00487F
)
─ 从64K到128K FLASH程序存储器,每页512字节,最多256页
─ 从1K到2K字节数据EEPROM,每页512字节,共4页。数据EEPROM包括一页的选项字节(512字节)。
- 🌿小容量STM8S的FLASH存储器和数据EEPROM组织机构
- 🌿中容量STM8S的FLASH存储器和数据EEPROM组织机构
- 🌿大容量STM8S的FLASH存储器和数据EEPROM组织机构
📗用户启动区域(UBC)
用户启动区域(UBC)包含有复位和中断向量表,它可用于存储IAP及通讯程序。UBC有一个两级保护结构可保护用户代码及数据在IAP编程中免于无意的擦除或修改。这意味着该区域总是写保护的,而且写保护不能通过使用MASS密钥来解锁。
- 📜在ICP模式下(使用SWIM接口)可以通过修改选项字节来配置UBC的大小。UBC选项字节指定了分配在UBC中的页的数量。UBC区域的起始地址是0x00 8000。可以通过读取UBC选项字节来获得UBC区域的大小。
- 🎋小容量STM8S的UBC区域大小
- 🎋中容量STM8S的UBC区域大小
- 🎋大容量STM8S的UBC区域大小
✅存储器保护
📖读保护
当选项字节中的ROP字节被编程为’0xAA
’时,读保护就生效了。这种情况下,无论写保护是否
生效,在ICP模式中(使用SWIM接口)读取或修改FLASH程序存储器和DATA区域都是被禁止
的。即使认为没有什么保护是完全不可破解的,对于一个通用微处理器来说,STM8的读保护的
特性也提供了一个非常高水平的保护级别。
- 🔧可以在ICP模式中通过对选项字节中的
ROP
字节重新编程来解除程序存储器、UBC和DATA区域
的读保护。在这种情况下,程序存储器、UBC、DATA区域以及选项字节都被自动擦除,器件也
可以被重新编程了.
📓存储器存取安全系统(MASS)
在复位以后,主程序和DATA区域都被自动保护以防止无意的写操作。在试图修改其内容前必须
对其解锁,而解锁的机制由存储器存取安全系统(MASS)来管理。
UBC区域的特性指明了在UBC中的内容一直是写保护的.
- 🔖一旦存储器内容被修改完毕,推荐将写保护使能以防止数据被破坏.
- 📝对主程序存储器的写操作:
在器件复位后,可以通过向FLASH_PUKR寄存器连续写入两个被叫作MASS密钥的值来解除主程序存储器的写保护(请参考4.9.6 FLASH程序存储器解保入FLASH_PUKR的值)会和以下两个硬件密钥值相比较:
- ● 第一个硬件密钥:0b0101 0110 (0x56)
● 第二个硬件密钥:0b1010 1110 (0xAE)
- 需要通过如下步骤来解除主程序存储器区域的写保护:
- 向FLASH_PUKR写入第一个8位密钥。在系统复位后,当这个寄存器被首次写入值时,数总线上的值没有被直接锁存到这个寄存器中,而是和第一个硬件密钥值(0x56)相比较。
- 如果密钥输入错误,FLASH_PUKR寄存器在下一次系统复位之复位前,再向该寄存器进行的任何写操作都会被系统忽略掉。
- 如果第一个硬件密钥正确,当这个寄存器被第二次写入值时,数存到这个寄存器中,而是和第二个硬件密钥值(0xAE)相比较。
- 如果密钥输入错误,FLASH_PUKR寄存器在下一次系统复位之复位前,再向该寄存器进行的任何写操作都会被系统忽略掉。
- 如果第二个硬件密钥正确,主程序存储器写保护被解除,同时FLASH_IAPSR中的PUL位为1.
在开始编程之前,应用程序可以校验PUL位是否被有效地置1。应用程序可以在任意时刻通过清
PUL位来重新禁止对FLASH程序区域的写操作.
- 对DATA区域的写操作:
在器件复位后,可以通过向FLASH DUKR寄存器连续写入两个被叫作MASS密钥的值来解除DATA区域的写保护,这两个写入FLASHLDUKR的值会和以下两个硬件密钥值相比较:
● 第一个硬件密钥:0b0101 0110 (0x56)
● 第二个硬件密钥:0b1010 1110 (0xAE)
需要通过如下步骤来解除数据区域的写保护:
- 向FLASH DUKR写入第一个8位察钥。在系练复位后,当这个寄存器被首次写入信时,数据总线上的值没有被直接锁存到这个寄存器中,而是和第一个硬件密钥值(Ox56)相比较。
- 如果密钥输入错误,应用程序可以尝试重新输入这两个MASS密钥来对DATA区域进行解
- 如果第一个硬件密钥正确,当这个寄存器被第二次写入值时,数据总线上的值没有被直接锁存到这个寄存器中,而是和第二个硬件密钥值(OxAE)相比较
- 如果密钥输入错误,DATA EEPROM区域在下一次系统复位之前将一直保持写保护状态。在下一次复位前,再向该寄存器进行的任何写操作都会被系统忽略掉
- 如果第二个硬件密钥正确,DATA区域的写保护被解除,同时FLASHIAPSR中的DUL位为1
对选项字节的写操作
对选项字节的写操作的步骤和对DATA EEPROM的操作大致相同。但是要注意到FLASHCR2中的OPT位要为1以及FLASH_NCR中的NOPT位要为0,这样才可以对选项字节进行写操作。
存储器编程
在尝试执行任何编程操作之前,必须对主程序存储器和DATA区域解锁.
读同时写 (RWW)
RWW特性允许用户在执行程序和读程序存储器时对DATA EEPROM区域进行写操作,因此执行的时间优化了。相反的操作是不允许的,即你不可以在写程序存储器时对DATA EEPROM进行读操作。
RWW特性是一直有效的而且可以在任意时刻使用。
- 注意:并不是所方STM8都拥有RWW特性。
字节编程
可以对主程序存储器和DATA区域逐字节地编程。要对一个字节编程,应用程序可直接向目标地
扑写入数据。
- 在主程序存储器中当字节编程操作执行时,应用程序停止运行。
- 在DATA区域中
-
- 有RWW功能的器件:在IAP模式下,应用程序不停止运行,字节编程利用RWW功能
进行操作。
- 有RWW功能的器件:在IAP模式下,应用程序不停止运行,字节编程利用RWW功能
-
- 无RWW功能的器件:当字节编程操作执行时,应用程序停止运行
要擦除一个字节,向对应的字节简单写入‘0x00
’即可。
应用程序可以通过读FLASH IAPSR寄存器来校验编程或擦除操作是否已被正确执行:
- 无RWW功能的器件:当字节编程操作执行时,应用程序停止运行
- 在一次成功的编程操作后EOP位被置1。
- 当软件试图对一个被保护的页进行写操作时WP_PG_DIS位被置1。在这种情况下,写操作不会被执行
如果FLASH_CR1中的IE位已经被预先使能,则只要这些标志位(EOP/WP_PG_DIS)中有一个被
置位就会产生一个中断。
自动快速字节编程
根据目标地址的初始化内容的不同,编程持续时间可能也有所不同。如果字(4个字节)中包含不为空的字节,在编程前整个字会被自动擦除。相反,如果字为空,由于不会执行擦除操作从而编程时间变短(请参考taog参数,在数据手册的"Flash progrem memory
"表中)。然而,可以通过对FLASH_CR1中的FIX位置1来强迫执行系统擦除操作而不管其内容是否为空,从而使编程时间固定(请参考FLASH控制寄存器)。编程总时间随之被规定为擦除时间和写操作时间的和(请参考tprog参数,在数据手册的”Flash program memory
"表中)。
- 注意:为了快速写一个字节(没有擦除操作),将要被写入的数据整个字4个字节必须被预先擦除。因此不可能对同一个字节做连续两次快速写操作(在第二次写之前,没有擦除操作):第一次写字节操作将是快速操作但针对另外一个字节的第二次写操作将需要一个擦除操作。
块编程
🔖此部分详情请内容看手册。
选项字节(Option byte)编程
对选项字节编程和对DATAEEPROM区域编程非常相似。
应用程序可直接向目标地址进行写操作。利用STM8的RWW功能,在对洗项字节写操作的同时程序不必停下来。
ICP和IAP
在线编程(ICP)用于更新整个存储器的内容。ICP使用SWIM接口把用户的程序装载到微控制器中,同时提供迅速而有效的设计迭代并且去除了不必要的封装处理和器件插槽。SWM接口(单线接口模块)使用SWIM引脚和编程工具相连接。
- 相对于ICP方式,在应用编程(IAP)可使用STM8支持的任意通讯接口I/O、I2C、SPI、UART…来下载要编入存储器中的数据。IAP允许在应用程序运行中对FLASH程序存储器的内容重新编程。然而要想使用IAP,必须通过ICP对FLASH程序存储器预先编程。
- 请参考STM8 Flash 编程手册(PM0051)和STM8SWIM通信协议和调试模块用户手册 (UM04701)
来了解关于编程步骤的更多细节. - 不同编程模式下的存储器存取
- R/W/E = 读;写和运行;
R/E = 读和运行(写操作被禁止);
R = 读(写操作和运行被禁止);
P = 该区域不可存取(读;写和运行被禁止);
P/WROP= 被保护。除ROP选项字节外,写操作被禁止。 - 在向FLASH_PUKR写入正确的MASS密钥之前,Flash程序存储器是写保护的(锁住)。可以
通过清PUL位来重新锁住该区域,但在两次复位之间仅可解锁一次。 - 在向FLASH_DUKR写入正确的MASS密钥之前,DATA存储器是写保护的(锁住)。可以通过
清DUL位来重新锁住该区域。 - 如果想对UBC区域编程,首先要清除UBC对应的选项字节位。
- 在向FLASH_DUKR写入正确的MASS密钥(同时OPT位要置1)之前,选项字节是写保护的(锁
住)。可以通过清DUL位来重新锁住该区域。 - 当ROP位被清除,整个存储器(包括选项字节)被自动擦除。
内部EEPROM驱动示例代码
- 📌eeprom驱动采用的是《STM8内部EEPROM的使用详解》驱动源文件。
- 通过串口打印写入的数据信息:
- 📝主程序代码
/**************************************************************************************
实验现象: LED1指示灯闪烁,打开串口助手,操作K1键打印读取的数据,在串口助手上显示。
接线说明: 1,STM8S单片机-->LED1
PC7-->LED1
PC7-->LED2
2,STM8S单片机-->独立按键模块
PG0-->K1
PG1-->K2
注意事项: 1,程序下载完成后再次按下STM8S单片机上的复位按钮RST即可运行程序。
-------------------------------------------------
***************************************************************************************/
#include "stm8s.h" /* 添加库函数头文件 */
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "eeprom_inner.h"
u8 Buffer[] = "Hi!STM8S208RB 9527 Perseverance";
//#define BASE_ADDRESS ((u16)0x0000)
#define countof(a) (sizeof(a) / sizeof(*(a)))
#define BufferSize1 (countof(Buffer)-1)
u8 Read_Buffer[BufferSize1];
/* 主函数 */
int main( void )
{
u8 i = 0;
u8 k = 0;
disableInterrupts(); //关闭系统中断
//内部时钟为1分频 = 16Mhz
CLK_SYSCLKConfig( CLK_PRESCALER_HSIDIV1 );
USART1_Init( 9600 ); //初始化USART1 , 并设置波特率为9600
printf("STM8S208RB \r\n");
eeprom_init();
LED_Init();
enableInterrupts(); //使能系统中断
KEY_Init();
//EEPROM写操作
for(i=0;i<BufferSize1;i++)
{
eeprom_write_byte( (FLASH_DATA_START_PHYSICAL_ADDRESS + (uint16_t)i),Buffer[i]);
}
delay_ms(2000);
//EEPROM读操作
for(i=0;i<BufferSize1;i++)
{
Read_Buffer[i] = eeprom_read_byte( FLASH_DATA_START_PHYSICAL_ADDRESS + (uint16_t)i);
}
while( 1 )
{
if( KEY1 == 0 )
{
delay_ms( 20 );
if( KEY1 == 0 )
{
k++;
if( k > 254 )
{
k = 254;
}
printf( "EEPROM Read:%s \r\n", Read_Buffer);
}
while( KEY1 == 0 );
}
// if( KEY2 == 0 )
// {
// delay_ms( 20 );
// if( KEY2 == 0 )
// {
// k = 0 ;
// printf( "读取的数据是:%d\r\n", k );
// }
// while( KEY2 == 0 );
// }
i++;
if( i % 20 == 0 )
{
LED1_TOGGLE;
}
delay_ms( 10 );
}
}
//是一个宏定义;在固件库中,它的作用就是检测传递给函数的参数是否是有效的参数
void assert_failed( u8* file, u32 line )
{
while ( 1 )
{
}
}
📚程序源码
- 🔖IAR对中文路径不友好,不要将工程解压在带有中文字符路径的文件夹内直接打开工程编译,这样会导致IAR内部检索文件路径将消耗大量CPU资源。
链接: https://pan.baidu.com/s/1xnZey5A_3BBwGxHs-tyq-A
提取码: 6ect