零基础开发小安派-Eyes-S1【外设篇】——FLASH

描述

AiPi-Eyes-S1是安信可开源团队专门为Ai-M61-32S设计的一款开发板,支持WiFi6、BLE5.3。所搭载的Ai-M61-32S 模组具有丰富的外设接口,具体包括 DVP、MJPEG、Dispaly、AudioCodec、USB2.0、SDU、以太网 (EMAC)、SD/MMC(SDH)、SPI、UART、I2C、I2S、PWM、GPDAC、GPADC、ACOMP 和 GPIO 等。

AiPi-Eyes-S1集成了SPI屏幕接口,DVP摄像头接口,外置ES8388音频编解码芯片以及预留TF卡座,并且引出USB接口,可接入USB摄像头。

从零开始学习小安派:

1、零基础开发小安派-Eyes-S1【入门篇】——初识小安派-Eyes-S1

2、零基础开发小安派-Eyes-S1【入门篇】——安装VMware与Ubuntu

3、入门篇:零基础开发小安派-Eyes-S1——新建工程并烧录调试

4、零基础开发小安派-Eyes-S1入门篇——Win下SSH连接Linux

5、零基础开发小安派-Eyes-S1【入门篇】——Samba共享文件夹

6、零基础开发小安派-Eyes-S1【入门篇】——工程文件架构

7、零基础开发小安派-Eyes-S1【外设篇】——GPIO 输入输出

8、零基础开发小安派-Eyes-S1【外设篇】——GPIO中断编程

9、零基础开发小安派-Eyes-S1【外设篇】——PWM

10、零基础开发小安派-Eyes-S1【外设篇】——UART

11、零基础开发小安派-Eyes-S1【外设篇】——I2C

12、零基础开发小安派-Eyes-S1【外设篇】——ADC

Flash 简称闪存,它的特点是擦除和编程速度快,单片机的程序一般都是存储在一定空间内中进行运行。在 C 语言中,程序分为代码段、常量区、静态数据区(BSS 段,数据段)、栈、堆五个部分组成。内部空间就分为 ROM 和 RAM,都是可以用来存储内容,区别在于:

ROM 的存储特性比较稳定,很久以前它不可擦除,所以只可读不可写,FLASH 就是一种特殊的 ROM,可擦除可读可写,在掉电后不丢失。RAM 的存储特性较不稳定,但读写速度快,掉电后丢失。

它们的差异如下:

FlaSh

总结:FLASH 也就是 ROM,掉电后不丢失,读写速度较慢,空间大,可以理解未电脑上的硬盘。RAM 速度快,掉电后丢失,可以理解未电脑上的内存。

一、了解小安派-Eyes-S1 的存储

618FLASH 物理上的地址起始地址是 0XA0000000。M61-32S 的 FLASH 大小是 8M。在数据手册中可以看到所有的模块地址映射,包括外设的地址。

在这之前需要了解分区表的概念,分区表就是划分 FLASH 的清单,将 FLASH 划分为多个不同功能区域用于其它功能。在操作 FLASH 时得看一下分区表,查看哪些地址可以使用。在 SDK 中有 4M 的分区表,里面规划了一些分区的命名,起始地址和大小,这个目录下找到。

AiPi-Open-Kits/aithinker_Ai-M6X_SDK/bsp/board/bl616dk/config/partition_cfg_4M.toml,在参与编译时会在工程文件夹下的 build/build_out 中生成 partition.bin。我们在 flash_prog_cfg.ini 中可以看到,常见的有 BOOT2 固件,filedir:固件路径,address:地址,boot2 必须使用 0 地址。而 partition 表示分区表固件,address 是根据 partition_cfg_4M.toml 指定。而 FW 则表示需要烧录的应用固件,FW 可以在 partition_cfg_4M.toml 中看到。

FlaSh

我们可以添加一样的“分区”,创建属于自己的名字,也可以在分区表中查看已有的分区使用。当然,建议还是使用原厂分配的分区表。

1.bflb_flash_init

说明: flash 初始化,自动识别支持的 flash 并重新配置 flash 的参数。如果返回错误,必须停止运行代码。

int bflb_flash_init(void);

FlaSh

2.bflb_flash_get_jedec_id

说明: 获取 flash jedec id。

uint32_t bflb_flash_get_jedec_id(void);

FlaSh

3.bflb_flash_get_cfg

说明: 获取 flash 配置。

void bflb_flash_get_cfg(uint8_t **cfg_addr, uint32_t *len);

FlaSh

4.bflb_flash_set_iomode

说明: 设置 flash IO 工作模式。

void bflb_flash_set_iomode(uint8_t iomode);

FlaSh

可填入以下几种模式:

#define FLASH_IOMODE_NIO 0
#define FLASH_IOMODE_DO 1
#define FLASH_IOMODE_QO 2
#define FLASH_IOMODE_DIO 3
#define FLASH_IOMODE_QIO 4

5.bflb_flash_get_image_offset

说明: 获取代码 xip 虚拟地址实际所在的 flash 物理地址。

uint32_tbflb_flash_get_image_offset(void);

FlaSh

6.bflb_flash_erase

说明: flash 扇区擦除。len 为擦除的长度,需要为 4096 倍数,假设 addr 为 0 , len 为 4096,则擦除范围为 0 ~ 4095。

intbflb_flash_erase(uint32_t addr,uint32_t len);

FlaSh

7.bflb_flash_write

说明:获取代码 xip 虚拟地址实际所在的 flash 物理地址。

intbflb_flash_write(uint32_t addr, uint8_t *data,uint32_t len);

FlaSh

8.bflb_flash_read

说明: 获取代码 xip 虚拟地址实际所在的 flash 物理地址。

intbflb_flash_read(uint32_t addr,uint8_t *data,uint32_t len);

FlaSh

9.bflb_flash_aes_init

说明: 配置某一段 flash 区域进行硬件 aes 解密,能够通过 xip 直接读取解密后的内容。

voidbflb_flash_aes_init(struct bflb_flash_aes_config_s *config);

FlaSh

10.bflb_flash_aes_enable

说明: 使能 flash aes 解密。

voidbflb_flash_aes_enable(void);

11.bflb_flash_aes_disable

说明: 关闭 flash aes 解密。

voidbflb_flash_aes_disable(void);

二、简单示例——上电后读取 flash 内的值并打印

1.首次写入

#include "bflb_flash.h"
#include "board.h"
#include "string.h"
//头文件
#define FLASH_RW_START_ADDR 0x3F3000
//宏定义读写起始地址,查看分区表可以看出这是“DATA”所在分区
static uint8_t write_buf[16];
static uint8_t read_buf[16];
//定义读写缓存数组
int main(void)
{
uint32_t i;
board_init();
//板子初始化,包括了bflb_flash_init
memset(write_buf, 0, sizeof(write_buf));
memset(read_buf, 0, sizeof(read_buf));
//清空缓存数组
strcpy(write_buf,"HelloWorld!");
//填写write数组内容
/* erase flash */
bflb_flash_erase(FLASH_RW_START_ADDR,sizeof(write_buf));
//擦除缓存数组大小,从起始地址开始
/* read flash data */
bflb_flash_read(FLASH_RW_START_ADDR, read_buf, sizeof(read_buf));
//读取flash内的内容缓存到read数组里
for (i = 0; i < sizeof(read_buf); i++) {
if (read_buf[i] != write_buf[i]) {
printf("rnflash read fail at %d, expect:%d but get %d", i, write_buf[i], read_buf[i]);
}
}
//for循环校验,当write和read内容不一致时会打印
/* write flash data */
bflb_flash_write(FLASH_RW_START_ADDR, write_buf, sizeof(write_buf));
//将write内容写入flash中
memset(read_buf, 0, sizeof(read_buf));
/* read flash data */
bflb_flash_read(FLASH_RW_START_ADDR, read_buf, sizeof(read_buf));

printf("rn%s",read_buf);
while (1) {
}
}

第一次运行程序效果:在擦除了后读出来的 ASCII 码为 255

FlaSh

2.二次读取,查看上电打印信息

#include "bflb_flash.h"
#include "board.h"
#include "string.h"
#define FLASH_RW_START_ADDR 0x3F3000
static uint8_t write_buf[16];
static uint8_t read_buf[16];
int main(void)
{
uint32_t i;
board_init();
memset(write_buf, 0, sizeof(write_buf));
memset(read_buf, 0, sizeof(read_buf));
strcpy(write_buf,"HelloWorld!");
/* read flash data */
bflb_flash_read(FLASH_RW_START_ADDR, read_buf, sizeof(read_buf));
for (i = 0; i < sizeof(read_buf); i++) {
if (read_buf[i] != write_buf[i]) {
printf("rnflash read fail at %d, expect:%d but get %d", i, write_buf[i], read_buf[i]);
}
}
printf("rn%s",read_buf);
while (1) {
}
}

二次读取后的运行效果:校验成功,只读取出 hellowold

FlaSh

三、使用 easyflash 库,匹配字段

在 AiPi-SCP_SmartCtrl 工程中的 components 下,有 easy_flash 库,使用 easy_flash 更加方便快捷,只需要定义字段,第一个参数填入字段,第二个参数填入值,即可通过匹配字段的方式将值与字段匹配上。添加库的方式如下:

1.将 easy_flash 的文件夹复制下来,放到模板工程中,这里使用 Project_basic 的模板工程,记得修改工程名。

FlaSh

2.在 CMakeLists.txt 下的添加 easyflash 的库文件。

FlaSh

3.在 proj.conf 下打开 easyflash 控件。

FlaSh

4.使用方法,只需要在调用 flash_erase_set 时填入两个参数,第一个参数为匹配的字段,一般由宏定义的字符串常量。第二个参数为值,也就是需要存储的值。这样在 flash 中就是由常驻的字段 + 值组成,在获取值时可以通过“字段‘来寻找相应的值。通过 flash_get_data 的方式,传入查找的字段和长度,得到存储的值。

FlaSh

FlaSh

FlaSh

5.easyflash 使用的“PSM”分区,大小是 32K,起始地址是 0X3E9000。在这里面我们可以存放一些标志位,或者是类似 wifi 名称密码、AP 名称密码等关键信息,使用起来也方便,通过匹配字段的方式将关键信息填入所需任务。如在 AT 指令中将 SSID 和 PASS 通过第三个参数 0 或 1 选择是否存入 flash 中。方便实现开机自动连接 wifi 且可通过指令修改 wifi 等操作。

FlaSh



审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分