#技术资源# #申请原创#
前言
本文测试了AC7802X的EFLASH功能,实现了向DFLASH的page0,1,2,3写入数据和读取数据,并且擦除page0的数据。
1 EFLASH介绍
查看官方提供的用户手册《ATC_AC7802x_ReferenceManual_CH.pdf》19 片内Flash(Embedded Flash)。
下图为EFLASH的介绍,说明了EFLASH包含了两部分:
- PFLASH:用来保存用户程序
- DFLASH:用来保存不需要经常更新的标定数据
PFLASH一般只用来保存用户程序,因为一般情况下,擦除次数小于DFLASH,所以不要对PFLASH进行频繁擦写操作,也为了防止对PFLASH的操作损坏用户代码,所以一般数据的写入都放在DFLASH中,而DFLASH一般也只用来保存不会频繁擦写的数据,因为其寿命远小于EEPROM。
从下面的介绍还可以知道DFLASH一页为8Bytes,大小为2KBytes,一个块为16Bytes。
2 DFLASH地址划分
因为本文主要测试对DFLASH的擦写,所以需要先了解DFLASH的地址划分,如下:
- 起始地址: 0x08020000,即page0
- page1:0x08020008
- page2:0x08020010
- page3:0x08020018
3 代码实现
知道了DFLASH的地址划分以及原理之后,我们可以开始实现代码编写,如下:
- eflash_DataInit(): 初始化要写入到DFLASH的数据
- eflash_DFlashAllErase(): 擦除整个DFLASH区域的功能,如果是第一次使用,可以调用该函数擦除整个DFLASH区域
- eflash_DFlashPageErase(): 擦除指定页,即8Bytes区域
- eflash_DFlashPageWrite(): 向指定page地址写入数据,最小写入单位为4Bytes。
- eflash_DemoRuning(): 测试演示,在主函数while(1)之前调用,用于验证DFLASH擦写是否成功。该函数主要实现向DFLASH的page0和page2写入16Bytes的数据,然后在擦除page0的数据。
下面说一下注意事项:
- g_WriteBuff为要写入的数组变量,这个变量不能直接赋初值,直接赋初值会导致写入不成功,我也不清楚为什么
- 需要先调用eflash_DataInit初始化要写入的数据(原因见上一条)
- 不能使用函数EFLASH_PageEraseVerify来验证DFLASH是否擦除成功,因为该函数只支持PFLASH,不支持DFLASH。
/*
@hehung
2023-6-15
email: 1398660197@qq.com
wechat: hehung95
reproduced and please indicate the source @hehung
*/
#include "ac780x_eflash.h"
#include "stdbool.h"
#include "app_eflash.h"
#include <stdio.h>
#define WRITE_LENGTH 16U /*! 写入数据长度,最小写入长度为4字节, 所以WRITE_LENGTH 需要大于等于4 */
#define DFLASH_PAGE0_ADRESS 0x08020000U /*! Dflash Page0 0x0802_0000 ~ 0x0802_000F size 16B - 2pages */
#define DFLASH_PAGE2_ADRESS 0x08020010U /*! Dflash Page0 0x0802_0010 ~ 0x0802_001F size 16B - 2pages*/
#define DFLASH_PAGE255_ADRESS 0x080207F8U /*! Dflash Page0 0x0802_07F8 ~ 0x0802_07FF size 8B */
uint8_t g_WriteBuff[WRITE_LENGTH] = {0}; /*! 写入数据BUFF */
uint8_t g_ReadBuff[WRITE_LENGTH] = {0}; /*! 读取数据BUFF */
static void eflash_DataInit(void)
{
uint16_t i = 0;
for (i = 0; i < WRITE_LENGTH; i++)
{
g_WriteBuff[i] = i;
}
}
static void eflash_DFlashAllErase(void)
{
EFLASH_UnlockCtrl(); /*! Flash 写入/擦除前需要先解锁 */
EFLASH_DFMassErase(); /*! D-flash 全片擦除,因为Code 存放在P-flash中, 不建议对P-flash进行全片擦除 */
if (EFLASH_STATUS_SUCCESS != EFLASH_DFMassEraseVerify()) /*! 验证相应位置是否擦除成功 */
{
printf("[LINE %d] ERROR :Erase Dflash failue.\r\n", __LINE__); /*! 若擦除失败,则打印相应错误警告 */
}
EFLASH_LockCtrl(); /*! 完成flash操作后重新上锁, 上锁与解锁要配套使用 */
}
static void eflash_DFlashPageErase(uint32_t page)
{
EFLASH_UnlockCtrl(); /*! Flash 写入/擦除前需要先解锁 */
EFLASH_PageErase(page); /*! 擦除D-flash page0 */
// if (EFLASH_STATUS_SUCCESS != EFLASH_PageEraseVerify(page, WRITE_LENGTH / 4U)) /*! 验证相应位置是否擦除成功 */
// {
// printf("[LINE %d] ERROR :Erase [0x%08X] failue.\r\n", __LINE__, page); /*! 若擦除失败,则打印相应错误警告 */
// }
EFLASH_LockCtrl(); /*! 完成flash操作后重新上锁, 上锁与解锁要配套使用 */
}
static void eflash_DFlashPageWrite(uint32_t page)
{
uint16_t i = 0;
EFLASH_UnlockCtrl(); /*! Flash 写入/擦除前需要先解锁 */
EFLASH_PageProgram(page, (uint32_t*)g_WriteBuff, WRITE_LENGTH / 4); /*! 将数据写入D-Flash, 最小写入单位为4字节 */
printf("\r\nWrite g_WriteBuff[WRITE_LENGTH] to D-Flash ...\r\n");
EFLASH_Read(page, (uint32_t*)g_ReadBuff, WRITE_LENGTH / 4); /*! 读取D-Flash数据 */
printf("Read D-Flash [0x%X] : ", page); /*! 打印相关信息 */
for (i = 0; i < WRITE_LENGTH; i++)
{
printf("%02X ", g_ReadBuff[i]);
}
printf("\r\n");
EFLASH_LockCtrl(); /*! 完成flash操作后重新上锁, 上锁与解锁要配套使用 */
}
void eflash_DemoRuning(void)
{
eflash_DataInit();
// 等待输入要写入到DFLASH的数据
// 擦除全部DFLASH
eflash_DFlashAllErase();
printf ("Erase DFlash finished\r\n");
//写入数据到DFLASH的page0和page1
eflash_DFlashPageWrite(DFLASH_PAGE0_ADRESS);
printf ("Write page0 of DFlash finished\r\n");
eflash_DFlashPageWrite(DFLASH_PAGE2_ADRESS);
printf ("Write page2 of DFlash finished\r\n");
// 擦除page0,保留page1
eflash_DFlashPageErase(DFLASH_PAGE0_ADRESS);
printf ("Erase page0 of DFlash finished\r\n");
}
4 试验结果
试验结果如下:
1. 进入Debug界面
2. 在两个page写入结束处打上断点,用于观察数据是否写入成功,见下图,可以数据写入成功。
3. 在函数结尾处打一个断点,观察page0是否擦除成功,见下图,page0被擦除,只剩下page1~page3的数据。
4. 下面是串口打印的结果
|