stm32软件开发调试完成之后,需要发布产品进行批量生产。每一个产品应该有一个唯一的设备编号,我们可以把设备编号与软件程序一起,写入stm32的flash中进行保存,在软件中读取到设备编号使用。这时候我们就需要使用到J-Flash的Serial number(序列号,简称SN)功能。
综述
打开J-Flash,Help->J-Flash User Guide,打开J-Flash用户手册,搜索“serial number”,可以找到对应介绍章节(不同版本章节可能不同)。
1. 编程连续的序列号。
Address:编程序列号的flash地址,十六进制格式;
Len:序列号的长度,十进制,支持1-4字节;
Next SN:下一个序列号,十进制,区分正负;
Increment:增量,每次写入之后SN增加的大小,十进制,可正可负;
开始测试: 先向flash中写入SN,之后读出flash,查看SN(J-Flash下载程序请参照SEGGER J-Flash 烧写stm32程序)。
test0:在0x08050000写入序列号123456,递增1;
结果:写入正确,Next SN增加Increment变为123457
test1:写入在0x08050000写入序列号2147483647(0x7FFFFFFF),递增1;
结果:2147483647写入成功,Next SN加1后变为了-2147483648???
其实,在有符号四字节的数据里,0x7FFFFFFF再增1就会符号溢出,0x80000000表示有符号的-2147483648。然而Next SN输入框里面,最多输入10位数字,包括正负号,所以我们最大可填入的SN号为7FFFFFFF。当然我们程序里面解析的时候,可以将4字节当做无符号整型,可以获得最大2^32的SN号值。实际使用,也可以填入负数的SN号,比如-1,其写入flash的值为0xFFFFFFFF。
Next SN输入框中,可填入负数最小为-999999999(0xC4653601),可填入正数最大9999999999,但是写入的会是2147483647(0x7FFFFFFF)。
test2:修改文件写入序列号
事实上,J-Flash写入的SN号保存在一个文本文件里,我们可以通过直接修改这个文件对要写入的SN号进行修改,在写入非连续的SN号时,该方式比较方便。SN号保存文件路径与工程文件路径相同,使用 Flie->Open project… 打开的一般就是当前打开的工程的路径,在资源管理器中找到该路径即可看到与工程名同名的序列号文件。
文本输入长度没有限制,十进制格式,可以输入负数,比如-2147483648,写入结果应该是0x80000000。
注意:修改文本文件之后,记得Ctrl+S保存一下,否则不生效。如果文本内容格式错误的话,将会写入0x00000000;正数溢出写入0x7FFFFFFF;负数溢出写入0x80000000。
2. 从序列号列表文件中编程序列号
test2中使用文本文件写入序列号,保存序列号的文本文件名称为 < JFlashProjectName >_Serial.txt,而需要使用列表写入的话,则需要在工程文件目录下创建一个名称为 < JFlashProjectName >_SNList.txt的文件,在其中填入要写入的序列号。每行为一个序列号,每个序列号为4字节十六进制数(不带0x),文件的排列的字节序就是写入flash的字节序。
在工程文件目录下有SNList文件时,优先使用SNList文件,忽略Serial文件。该方式需要配合Program serial number中的参数使用。
Address:编程序列号的flash地址,十六进制格式;
Len:序列号的长度,十进制,支持1-4字节;
Next SN:列表行号,十进制非负数,从0开始,0代表列表第一行;
Increment:增量,每次写入之后列表行号增加的大小,十进制,可正可负;
test3:使用序列号列表文件写入序列号
列表写入模式与直接写入区别不大,如果不满4字节,在后面自动补0,超出则自动截断,格式错误则写入0x00000000,行数超出则不写入。
3. 读取flash函数
#define SN_ADDR (uint32_t)0x08050000
/**
* @brief 读取指定地址的字(32位数据)
* @param addr 读地址
* @return uint32_t 读取的数据
*/
uint32_t StmFlashReadWord(uint32_t addr)
{
return *(uint32_t *)addr;
}
/**
* @brief 从指定地址开始读出指定长度的数据,每次读出一个字(32位)
* @param readAddr 起始地址
* @param pbuf 数据指针
* @param readNum 读出字(32位)数
* @return void
*/
void StmFlashRead(uint32_t readAddr, uint32_t *pbuf, uint32_t readNum)
{
uint32_t i;
for (i = 0; i < readNum; i++) {
pbuf[i] = StmFlashReadWord(readAddr);
readAddr += 4;
}
}