stm32逐步开发
使用cubemx生成初始化工程
选择MCU型号
打开 STM32CubeMX 后,依次点击工具栏中的 “File” -> “New Project …” 或通过快捷键 Ctrl + N 来新建一个 STM32CubeMX 工程,软件会打开一个选择 MCU 型号的界面
在界面左侧添加 你所需要的开发板芯片型号 的信息,然后在界面右侧找到并选中 该型号,然后点击右上角的 Start Project
配置工程信息
进入配置界面后,打开 Project Manager 配置工程的基础信息
Project Structure:选择需要的工程结构,这里仅勾选 Appli
Project Structure介绍
FSBL:FSBL(First Stage Boot Loader)工程主要用于开发 FSBL,FSBL 是 STM32N6 结束硬件复位后自动从外部 Flash 加载到内部 SRAM 并运行的第一段用户程序,主要完成相应的初始化工作,并启动 Appli 程序。
Appli:Appli 工程主要用于开发用户的应用程序,应用程序主要用于实现用户功能。
ExtMemLoader:ExtMemLoader 工程主要用于开发 External loader,External loader 主要用于 STM32CubeProgrammer、STM32CubeIDE 等工具访问、操作 MCU 外部 Flash
Toolchain / IDE:选择所使用的工具链或 IDE,这里选择 STM32CubeIDE,并取消勾选Generate Under Root,因为后续需要使用 STM32CubeIDE 打开工程。
MCU引脚和外设配置
接下来打开Pinout&Configuration配置MCU引脚和外设
Cache 管理
概述
STM32N6 使用 Cortex-M55。
这类内核为了提高性能,会使用数据缓存 D-Cache。
CPU 访问内存时,并不总是直接去 SRAM 取数据,很多时候先访问 Cache。
这本身是性能优化,但只要系统里用了 DMA,就会带来一个非常典型的问题:
CPU 看到的数据,不一定和 DMA 刚写入的数据一致
这引入了Cache管理的需求
原因在于 CPU 和 DMA 访问内存的路径不一样。
- CPU 常常先走 Cache
- DMA 直接访问物理 SRAM
这很可能导致数据处理和发送时都使用了旧数据
在实时的检测时会存在延时和数据不更新的问题
解决
DMA 接收完成后,CPU 读取前要失效,对应 Cache
也就是常说的 Invalidate。
意思是告诉 CPU缓存内容不可信,下次重新从 SRAM 读取
invalidate是在DMA接收完成后CPU读取前,典型位置在ADC/SPI的DMA回调里面
1 | |
适用场景:
- ADC DMA 接收完成
- SPI DMA 接收完成
- 某块接收缓冲区即将交给 DSP 处理
CPU 修改完待发送数据后,DMA 启动前要回写 Cache
也就是常说的 Clean。
意思是把 Cache 里的最新数据强制同步回 SRAM,CPU 改完发送缓冲后,先 Clean,再启动 DMA 发送
1 | |
适用场景:
- CPU 算完一帧特征后要发出去
- CPU 组织好一段 SPI 发送缓冲后交给 DMA
给 DMA 缓冲区单独留非缓存区
如果项目里 DMA 缓冲区固定,而且你不想每次都手工刷 Cache,可以考虑 MPU 方案:
- 划一块 SRAM
- 配成
Non-Cacheable - 把所有 DMA 交互缓冲区都放进去
这样做的好处是逻辑更稳定:
- DMA 写进去,CPU 读到的就是实际内存
- CPU 写进去,DMA 读到的也是实际内存
代价是:
- 这块区域访问性能会差一些
- 内存规划要提前做
32b对齐
CPU 读写 Cache 时,并不像很多人想象的那样“一次只搬 1 个字节”或“一次只搬 1 个 int”,这太慢了。
Cache 的管理是按块(Block)进行的,这个块就是 Cache Line。
Cache line,Cache的最小单位,有32字节,当 CPU 想读取地址 0x00 处的一个字节时,硬件实际上会把从 0x00 ~ 0x1F全部从 SRAM 一口气打包拉进 Cache 里
因此刷新invalidate的时候会刷新32字节的区域,所以DMA buffer最好和32b对齐
如果不对齐,可能造成数据存储的挤压和混乱,导致清除缓存的时候把某个文件的头和尾也清洗掉了
1 | |
算法buffer要尽量连续,这样cache命中率高
由于 Cache 的工作原理是“要一个字,给你32字节”。
如果光谱特征数组像链表、散列或者是东挑一块西找一块的数据。CPU 每次去 SRAM 抓 32 字节上来,结果你只用 1 个,下次又要去另一个远处的地址抓新 Cache,这叫**“Cache 命中率低”**,反复读 SRAM 极大拖慢性能。
如果你的滤波数组是一大块连续的浮点或定点大容量数组(数组天然是内存连续的),CPU 读第一个数时,后边的几个数也顺带被打包拉进了超快的 Cache 里。后面的读取瞬间变成内部光速响应,这就是“命中率高”,也是 CMSIS 算法能跑飞快的原因。
CPU 为什么会优先读 Cache
DMA 为什么绕过 Cache 直接访问 SRAM
在 CORTEX_M55_S 配置页中,将 CPU ICache 和 CPU DCache 都配置为 Enable
(此处留白)
使用cubeide进行开发
打开main.c编辑main函数
1 | |
上述代码中,实现了跑马灯效果的功能
对于 STM32CubeMX 生成的代码,强烈建议仅在 xxx CODE BEGIN xxx 和 xxx CODE END xxx 之间添加或修改代码,否则在后续使用 STM32CubeMX 重新生成代码时,添加或修改的代码会被覆盖。