FLASH 开发指导_Rev1.3

English

修订记录

版本

日期

作者

修订内容

Rev1.0

23-09-11

TL

创建文档

Rev1.1

24-03-25

sxx

更改文档名称

Rev1.2

24-05-07

YMX

优化文档结构,调整部分文字描述

Rev1.3

25-04-18

ZH

增加系列常见问题

1 引言

本文档介绍 LTE-EC71X FLASH 接口 API 情况, API 接口位于 components/kernel/lierda_api/liot_flash/liot_flash.h 文件声明中。

新增

如下图为flash区域分区参考图,不同版本SDK FLASH分区会有所不同:

/*
flash layout, toatl 4MB
flash raw address: 0x00000000---0x00400000
flash xip address(from both ap/cp view): 0x00800000---0x00c00000

0x00000000          |---------------------------------|
                    |      header1 4KB                |
0x00001000          |---------------------------------|
                    |      header2 4KB                |
0x00002000          |---------------------------------|
                    |      fuse mirror 4KB            |
0x00003000          |---------------------------------|
                    |      bl 72KB                    |
0x00015000          |---------------------------------|
                    |      rel data(factory)20KB      |
0x0001a000          |---------------------------------|
                    |      cp img 400KB               |
0x0007e000          |---------------------------------|
                    |      app img 3116KB             |
0x00389000          |---------------------------------|
                    |      hib backup 96KB            |
0x003a1000          |---------------------------------|
                    |      lfs  48KB                  |
0x003ad000          |---------------------------------|
                    |      fota 272KB                 |
0x003f1000          |---------------------------------|
                    |      rel data 52KB              |
0x003fe000          |---------------------------------|
                    |      plat config 8KB            |
0x00400000          |---------------------------------|

*/

#define FLASH_RESERVE_USER_REGION_START           (0x3ad000)
#define FLASH_RESERVE_USER_REGION_END             (0x3ac000)
#define FLASH_RESERVE_USER_REGION_SIZE            (FLASH_RESERVE_USER_REGION_END-FLASH_RESERVE_USER_REGION_START) // 4KB

上述分区图

2 API 函数概览

函数

说明

liot_flash_erase()

擦除 flash 中的数据。

liot_flash_read()

从 flash 中读取数据。

liot_flash_write()

向 flash 中写入数据。

3 API 函数详解

API 仅限对预留的 4KB 区域(0x3ad000~0x3ac000)进行操作,API频繁调用减少falsh寿命(10W次),建议频繁操作时使用文件系统相关API。

3.1 liot_flash_erase

该函数用于擦除 flash 中的数据。

  1. 声明

uint32_t liot_flash_erase(uint32_t SectorAddress, uint32_t size);
  1. 参数

  • SectorAddress:[In] 清除区域起始地址。它必须是 0x1000 的倍数,并且位于用户 FLASH 中。

  • size:[In] 要擦除的长度。

  1. 返回值

  • 0:成功。

  • other: 失败。

3.2 liot_flash_read

该函数用于从 flash 中读取数据。

  1. 声明

uint32_t liot_flash_read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size);
  1. 参数

  • pData:[Out] 存储从 flash 中读取数据的地址。

  • ReadAddr:[In] 读取数据的起始地址。

  • Size:[In] 要读取的长度。

  1. 返回值

  • 0:成功。

  • other: 失败。

3.3 liot_flash_write

该函数用于向 flash 中写入数据。

  1. 声明

uint32_t liot_flash_write(uint8_t *pData, uint32_t WriteAddr, uint32_t Size);
  1. 参数

  • pData:[In] 存储向 flash 中写入数据的地址。。

  • WriteAddr:[In] 写入数据的起始地址。

  • Size:[In] 要写入数据的长度。

  1. 返回值

  • 0:成功。

  • other: 失败。

4 代码示例

  1. 示例代码参考  examples/demo/src/demo_flash.c 文件。

#include "lierda_app_main.h"
#include "liot_flash.h"
#include "liot_os.h"
#include "liot_type.h"
#include "mem_map.h"

/*
    This project demonstrates the use of user area flash.
    In this case, we will erase a user area, write data to it, and then read the written data for printing.
    Non-user areas, such as the LIOT_BEFORE_APP_ADDR and LIOT_AFTER_APP_ADDR areas, cannot be erased, written, or read.
 */
#define FLASH_RESERVE_USER_REGION_START           (0x3e4000)
#define FLASH_RESERVE_USER_REGION_END             (0x3e5000)
#define FLASH_RESERVE_USER_REGION_SIZE            (FLASH_RESERVE_USER_REGION_END-FLASH_RESERVE_USER_REGION_START) // 4KB
void liot_flash_demo_task(void *argv)
{
    char app_data[] = "BBBBBBBBBB";

    char app_buff[11] = {0};

    liot_rtos_task_sleep_ms(2000);
    liot_trace("========== flash demo start ==========");
    liot_trace("=== Print erase flash address ====", LIOT_APP_ADDR_START, LIOT_APP_ADDR_END);
    liot_trace("=== erase before app address, ret(%d) ====", liot_flash_erase(LIOT_APP_ADDR_START, LIOT_APP_ADDR_SIZE));

    liot_rtos_task_sleep_ms(100);

    liot_trace("=== Write data to flash ====");
    liot_trace("=== write data on before app address, ret(%d) ====",
               liot_flash_write((uint8_t *)app_data, LIOT_APP_ADDR_START, 10));

    liot_rtos_task_sleep_ms(100);

    liot_trace("=== Read data from flash ====");
    liot_trace("=== read data on app address, ret(%d) ====",
               liot_flash_read((uint8_t *)(&app_buff\[0\]), LIOT_APP_ADDR_START, 10));

    liot_rtos_task_sleep_ms(100);

    liot_trace("=== Print the read data ===");
    liot_trace("=== app_buff(%s) ===", app_buff);

    liot_trace("========== flash demo end ==========");

    liot_rtos_task_delete(NULL); // kill itself
}
  • 运行结果:

_images/flash-guide/image_1.png

如上图所示,对比读写前后的两组数据,liot_flash_write()写入成功,liot_flash_read()读取到数据 BBBBBBBBBB,与写入数据一致,表明 flash 读写成功。

5 常见问题

5.1 如何确认FLASH的地址范围

示例代码中的地址范围如下:

#define FLASH_RESERVE_USER_REGION_START           (0x3e4000)
#define FLASH_RESERVE_USER_REGION_END             (0x3e5000)
#define FLASH_RESERVE_USER_REGION_SIZE            (FLASH_RESERVE_USER_REGION_END-FLASH_RESERVE_USER_REGION_START) // 4KB

不同模组的地址范围不同,具体查看"mem_map_71x.h"中的宏定义,如716s中地址定义如下:

_images/flash-guide/image_2.png

5.2 Flash写入之前需要先擦除吗

建议擦除。

如果不擦除,比如Flash中已经写入"hello world",再次写入"12345",则读出的数据为"12345 world"

5.3 Flash擦写次数是多少

10W次。

5.4 重新烧录固件后写入的Flash是否会被擦除

会被擦除。

5.5 EC718 是否支持外挂 flash?

可以,通过普通的 4 线 SPI 接口就可以实现外挂 flash,注意外挂 flash 只能存放一些数据,片外 flash 不支持代码执行。