
1. 引言在许多基于 BlueNRG-1/2 系列芯片的低功耗蓝牙的设计项目时,客户通常会在 Flash的特定区域存储定制的数据。然而需要特别注意的是,在 BlueNRG-1/2 方案中,用户对Flash 的读写操作必须在射频空闲的情况下进行,两者是互斥的关系。5 {. k$ ~- h. j M( j/ n: c 6 w* f$ j) |4 u 2. 问题描述9 P+ ]7 p4 Y% F! Z% F 客户经常反馈类似问题,诸如:当用户程序尝试将用户定制数据写入 Flash 中特定区域时,发现 BLE 射频部分停止工作,或芯片直接死机了。9 E. m& d1 x) M z : W# n( [$ I p& v9 V7 {" ~ / s! ?! t! u! b) h 2.1. 原因分析 2.1.1. BlueNRG-1/2 的 Flash 存储应用数据时可能遇到这个问题。因为在擦除一页的过程中,中断会被关掉大概 20 多 ms, 在此期间,radio 中断是被关掉了的,会导致整个radio 的状态被延时或者整个 radio 部分的状态被破坏。, W* H1 w8 F4 O' v# _. O+ ] 2 E, H' @2 m4 b+ J' Z. R/ [2 c 5 r4 |3 K3 ?5 F: W! I+ l9 N3 S 2.1.2. ST 的 SDK 虽然提供了访问 Flash 的示例代码,但是当 Flash 操作比较多时,与蓝牙事件的互斥就比较难处理了;特别是对于一些多连接应用或者同时用了主从、多种蓝牙事件的场景,互斥就显得更麻烦了。1 ?" }* @1 X' E 6 R0 X/ A9 h& T, b7 U' g+ S 3. 解决办法+ T2 ]& C% H7 j 使用一个双向链表来管理 Flash 操作(Flash 擦除或者是 Flash 写,Flash 读无需和BLE 相关事件互斥),并使用一个双向链表来管理空余时间状态。在空余的时间执行Flash 操作。从芯片手册可以知道,操作 Flash,特别是擦除时,会占用比较多的时间。为了避免操作 Flash 占用过多的时间片,把每次写或者擦除 Flash,用一个列表来管理,每次写或者擦除操作,插入 Flash 操作链表的最后。 在主循环中检测是否有足够的时间写,如果当前空闲的时间足够,取出 Flash 操作链表中最前的一个节点,执行 Flash 操作,然后将节点移除。对于如何检测空闲时刻,也用一个链表来管理空闲时刻。9 U7 R. b1 y9 U 具体思路如下:3 _% v o$ ?5 |- @* S. q 第一步:初始化时需要设置 radio active 事件抛到应用。 aci_hal_set_radio_activity_mask(0x0001|0x0002|0x0004|0x0008|0x0010|0x0020); - q$ O( G0 f0 L0 m: E5 Y ![]() 第二步:设置之后,重写函数 aci_hal_end_of_radio_activity_event,当有事件触发时,就会进入这个函数。图2.重写函数 aci_hal_end_of_radio_activity_event 5 u4 T$ W: t1 c& l1 D 8 C6 X7 g+ y# ~ _' I9 t- g ( [) f2 c2 y e ![]() ( `% M! S" N+ f2 t, I; o 第三步:构造一个 Flash 操作调度函数,每次进入这个函数,生成一个空闲时刻的节点插入到链表中。主循环中有个 Flash 操作的调度函数,不停的调度是否有数据需要写入。在 Flash操作的调度函数中,主要做两件事情,一个是把空闲时间计算出来给到底层的 Flash 操作链表调度中。另一个是移除过期的节点 完整版请查看:附件 ![]() |
新版STM32Cube for Visual Studio Code开发体验
【STM32N6570-DK评测】3.CubeMX关于DCMIPP和CSI的BUG整理及摄像头使用
经验分享常被误解的开、关总中断
【STM32C0测评】Nucleo-C092开发板功耗测试
【STM32C0测评】Nucleo-C092开发板IIC通信测试(硬件IIC)
【STM32C0测评】Nucleo-C092开发板IIC通信测试(软件IIC)
【STM32C0测评】Nucleo-C092开发板IIC通信测试(硬件软件IIC一网打尽)
【STM32C0测评】Nucleo-C092开发板USART串口测试
【STM32C0测评】Nucleo-C092开发板使用PWM控制板载LED呼吸灯
【STM32C0测评】Nucleo-C092板卡外部中断控制板载LED灯