心血来潮想整理一下这里的知识点。
STM32F4的自举模式烧写固件
一、知识点
1.相关手册
2.硬件电路
- STM32的启动模式
启动模式选择引脚 | 启动模式 | 说明 | |
---|---|---|---|
BOOT1 | BOOT0 | ||
X | 0 | 主闪存存储器 | 主闪存存储器被选为启动区域 |
0 | 1 | 系统存储器 | 系统存储器被选为启动区域 |
1 | 1 | 内置SRAM | 内置SRAM被选为启动区域 |
- STM32的启动模式设计自启动电路
3.启动模式
- 自举程序激活模式
芯片对应的激活模式请自行查看手册。
STM32F40xxx/41xxx
自举程序通过Pattern1
激活。
自举程序激活模式 | |
---|---|
模式 | 条件 |
Pattern1 | Boot0(pin) = 1 和 Boot1(pin) = 0 |
Pattern2 | Boot0(pin) = 1 和 nBoot1(bit) = 1 |
Pattern3 | Boot0(pin) = 1, Boot1(pin) = 0 和 BFB2(bit) = 1 |
Boot0(pin) = 0, BFB2(bit) = 0 且两个存储区均不包含有效代码 | |
Boot0(pin) = 1, Boot1(pin) = 0, BFB2(bit) = 0 两个存储区均不包含有效代码 | |
Pattern4 | Boot0(pin) = 1, Boot1(pin) = 0 和 BFB2(bit) = 1 |
Boot0(pin) = 0, BFB2(bit) = 0 且两个存储区均不包含有效代码 | |
Boot0(pin) = 1, Boot1(pin) = 0 和 BFB2(bit) = 0 | |
Pattern5 | Boot0(pin) = 1, Boot1(pin) = 0 和 BFB2(bit) = 0 |
Boot0(pin) = 0, BFB2(bit) = 1 且两个存储区均不包含有效代码 | |
Boot0(pin) = 1, Boot1(pin) = 0 和 BFB2 (bit) = 1 | |
Pattern6 | Boot0(pin) = 1, nBoot1(bit) = 1 和 nBoot0_SW(bit) = 1 |
nBoot0(bit) = 0, nBoot1(bit) = 1 和 nBoot0_SW(bit) = 0 | |
Boot0(pin) = 0, nBoot0_SW (bit) = 1 且主 Flash 为空 | |
Pattern7 | Boot0(pin) = 1, nBoot1(bit) = 1 和 BFB2(bit) = 0 |
Boot0(pin) = 0, BFB2(bit) = 1 且两个存储区均不包含有效代码 | |
Boot0(pin) = 1, nBoot1(bit) = 1 和 BFB2(bit) = 1 | |
Pattern8 | Boot(pin) = 0 和 BOOT_ADD0(optionbyte) = 0x0040 |
Boot(pin) = 1 和 BOOT_ADD1(optionbyte) = 0x0040 |
- 禁用所有外设时钟
- 禁用所用的 PLL
- 禁用中断
- 清空挂起的中断
通过离开自举程序激活条件并生成硬件复位,或使用Go
命令来执行用户代码,可退出系统存储器自举模式。
注: 如果选择执行Go
命令,则在跳转到用户应用程序之前,自举程序使用的外设寄存器不会初始化为默认复位值。如果要使用这些寄存器,应在用户应用程序中对其重新配置。因此,如果应用程序正在使用IWDG,则必须调整 IWDG 预分频器值来满足应用程序的要求 (因为已将预分频器设置为最大值)。
4.器件的配置
自举程序存储在 STM32 器件的内部自举 ROM 存储器 (系统存储器)中。在芯片生产期间由 ST 编程。其主要任务是通过一种可用的串行外设(USART、CAN、USB、I2C 等)将应用程序下载到内部 Flash 中。对应的串行模式支持与引脚请自行查阅Datasheet。此处以我使用的芯片STM32F4
为例,且使用的为USART
。
自举程序 | 功能 / 外设 | 状态 | 备注 |
---|---|---|---|
USART1 自举程序 | USART1 | 启用 | 初始化后, USART1 的配置为:8 位,偶校 验位和 1 个停止位。 |
USART1_RX 引脚 | 输入 | PA10 引脚:USART1 处于接收模式 | |
USART1_TX 引脚 | 输出 | PA9 引脚:USART1 处于发送模式 |
二、启动流程
1.自举程序流程图
2.USART 自举程序命令
命令 (1) | 命令代码 | 命令说明 |
---|---|---|
Get (2) | 0x00 | 获取当前自举程序版本及允许使用的命令 |
Get Version & Read Protection Status (2) | 0x01 | 获取自举程序版本及 Flash 的读保护状态 |
Get ID (2) | 0x02 | 获取芯片 ID |
Read Memory | 0x11 | 从应用程序指定的地址开始读取最多 256 个字节的存储器空间 |
Go | 0x21 | 跳转到内部 Flash 或 SRAM 内的应用程序代码 |
Write Memory | 0x31 | 从应用程序指定的地址开始将最多 256 个字节的数据写入RAM 或 Flash |
Erase(3) | 0x43 | 擦除一个到全部 Flash 页面 |
Extended Erase(3) | 0x44 | 使用双字节寻址模式擦除一个到全部 Flash 页面(仅用于 v3.0 usart 自举程序版本及以上版本)。 |
Write Protect(4) | 0x63 | 使能某些扇区的写保护 |
Write Unprotect(4) | 0x73 | 禁止所有 Flash 扇区的写保护 |
Readout Protect | 0x82 | 使能读保护 |
Readout Unprotect(2) | 0x92 | 禁止读保护 |
- 如果接收到拒绝命令或在执行命令期间出现错误,自举程序则会发送 NACK 字节并返回检查命令状态。
- 读保护 - 激活 RDP(读保护)选项后,只能使用这一有限的命令子集。其它命令都会收到 NACK 应答,并且不会对器件起作用。取消 RDP 即可激活其它命令。
- Erase (x043) 和 Extended Erase (0x44) 均为独占命令。一个器件可支持 Erase 命令或 Extended Erase 命令,但不能同时支持这两个命令。
- 请参见
AN3155应用笔记
第 3.1 节:器件相关的自举程序参数。
3.上位机程序参考
编程工具 (PC) 到器件的所有通信均通过如下方式验证:
- 校验和:接收到的数据字节块进行异或运算。每个通信结尾增加一个字节(校验和字节),包含前面所有字节异或运算的结果。异或运算所有接收到的字节,即数据包加上校验和字节,结果必须为0x00
- 针对每条命令,主机都会发送一个字节及其补码(异或结果 = 0x00)
- UART:激活奇偶校验(偶校验)
每个数据包或者被接受(ACK 应答)或者被丢弃(NACK 应答):
- ACK = 0x79
- NACK = 0x1F
上位机结合硬件电路,通过操作USART
的DTR
和RTS
实现复位
与进入Pattern1模式
。
//配置DTR#输出高电平 MCU复位
mSerialPort.DtrEnable = false;
Debug.WriteLine("DTR#输出高电平 MCU复位 延时100ms");
Thread.Sleep(100);
//配置RTS#输出低电平 使BOOT0引脚为高电平
mSerialPort.RtsEnable = true;
Debug.WriteLine("RTS#输出低电平 BOOT0拉高 延时100ms");
Thread.Sleep(100);
//配置DTR#输出低电平 释放MCU复位
mSerialPort.DtrEnable = true;
Debug.WriteLine("DTR#输出低电平 释放复位 延时100ms");
Thread.Sleep(100);
- 发送
0x7F
等待应答。
byte[] Sendbuf = new byte[] { 0X7F };
byte[] Recbuf = new byte[1];
//发送0x7F前清空串口缓存
while (mSerialPort.BytesToRead != 0){
mSerialPort.DiscardInBuffer();
}
Thread.Sleep(100);
if (Usart_SendCmmRec(Sendbuf, ref Recbuf, 1, 1000)){
//有应答,进入成功
if ((Recbuf[0] == MCU_ACK)){
return "进入成功/r/n";
}
else{
return "进入失败/r/n";
}
}
else{
return "超时无应答/r/n";
}
三、Erase Memory命令
1.擦除命令说明
Erase (x043)
和Extended Erase (0x44)
均为独占命令。一个器件可支持Erase
命令或Extended Erase
命令,但不能同时支持这两个命令。- 这里只把Erase命令单独做讲解,其他的命令不做单独说明。因为Erase命令的讲述在手册中存在错误。
Erase (x043)
命令也不做过多讲解,主要讲Extended Erase (0x44)
。
2.Erase Memory命令说明
主机可通过 Erase Memory 命令擦除 Flash 页面。自举程序接收到 Erase Memory 命令后, 会将 ACK 字节发送到主机。发送 ACK 字节后,自举程序将接收一个字节(待擦除的页面 数)、Flash 页面代码以及一个校验和字节; 如果校验和正确,则自举程序将擦除该存储器 并向主机发送一个 ACK 字节,否则将向主机发送一个 NACK 字节并中止此命令。
Erase Memory 命令规范:
- 自举程序接收一个包含 N(要擦除的页数 - 1)的字节。
保留 N = 255 用于全局擦除请求。0 ≤ N ≤ 254 时,擦除 N + 1 页。 - 自举程序接收到 (N + 1) 个字节,每个字节都包含一个页数
注: 在具有写保护的扇区中执行擦除操作时不会返回错误信息。
2.Erase Memory流程图
3.全片擦除
byte[] Sendbuff = new byte[] { 0X43, 0XBC };
byte[] Receivebuff = new byte[1];
if (Usart_SendCmmRec(Sendbuff, ref Receivebuff, 1)){
if (Receivebuff[0] == MCU_ACK){
Sendbuff[0] = 0XFF;
Sendbuff[1] = 0x00;
if (Usart_SendCmmRec(Sendbuff, ref Receivebuff, 1)){
if (Receivebuff[0] == MCU_ACK)
return true;
}
}
else{
return false;
}
}