RAM 缓冲区

← 返回 OTA | ← 主页

1. OTA 中的缓冲区职责

OTA 通常采用“接收一小块、校验一小块、写入存储”的流式处理方式,不会把整个固件一次性放进 RAM。

概念位置作用
RAM 双缓冲MCU 内部 RAM在串口接收和 Flash 写任务之间传递数据
Flash A/B 区外部或内部 Flash保存升级包、备份镜像和回滚数据

RAM 双缓冲不是 Flash 的 A/B 升级分区:前者解决任务间的数据暂存和吞吐,后者解决掉电保护、版本切换和回滚。

2. 当前工程的数据链路

串口 / Ymodem
      ↓
  1030 字节接收缓冲区
      ↓ memcpy
  双缓冲槽 s_slots[2]
      ↓ 队列传递槽指针
  Flash 写任务
      ↓
  4 KB 缓冲区
      ↓
  写入外部 W25Q64 的 A 区

这里还有一个ymodem实在是程序设计问题了,到时候如果是OTA应该不要这个ymodem的缓存,而是直接写到flash的双缓存里去

4. 小型工程:固定块内存池

下面的思路来自OTA 内存池复盘中的面试复盘对话。

门锁、门禁等小型工程可以用一个大数组划分固定大小的块,再用简单的单向空闲链表管理这些块:

大数组(静态分配)
  ├─ 128B 块 0
  ├─ 128B 块 1
  ├─ 128B 块 2
  └─ ...
 
空闲链表:
  [块 0 | next] → [块 1 | next] → [块 2 | next] → ...

如果数组是静态定义并初始化为 0,例如:

static uint8_t g_pool[POOL_BLOCK_COUNT][POOL_BLOCK_SIZE] = {0};

它通常进入 .bss 段(具体仍以编译器、链接脚本和初始化方式为准)。数组本身保存实际存储空间,空闲链表只保存每个块的首地址和 next 关系:

static uint8_t g_pool[16][128] = {0};

因为每个元素较小,需要多个元素才能组成一个OTA的缓冲区,但是内存池是供给所有任务的,他肯定会不连续,所以需要用链表的方式,找到下一个内存块的位置,这里链表可以直接用freertos的list.h,也可自己写,这样可以省一些空间,因为只需要单向的链表就好了