说明
本文发布单片机flash通用读写库TZFlash,有两个优点:
TZFlash将flash的读写抽象成文件读写,更易于使用。
flash写入需要4字节对齐,TZFlash增加cache机制,可以将任意长度的写入flash。
源码
tzflash.h
// Copyright 2019-2019 The TZIOT Authors. All rights reserved.
// flash管理模块头文件
#ifndef TZFLASH_H
#define TZFLASH_H
#include "tzbasedef.h"
// TZFlashEraseFunc 函数类型:擦除flash
// addr:起始地址.size:擦除字节数
// 成功返回true,失败返回false
typedef bool (*TZFlashEraseFunc)(int addr, int size);
// TZFlashWriteFunc 函数类型:写入flash
// addr:起始地址.bytes:待写入的字节流.size:写入字节数
// 成功返回true,失败返回false
typedef bool (*TZFlashWriteFunc)(int addr, uint8_t* bytes, int size);
// TZFlashReadFunc 函数类型:读取flash
// addr:起始地址.bytes:读取的字节流存放的缓存.size:读取的字节数
// 成功返回true,失败返回false
typedef bool (*TZFlashReadFunc)(int addr, uint8_t* bytes, int size);
// TZFlashOpenMode 打开模式
typedef enum {
TZFLASH_READ_ONLY = 0,
TZFLASH_WRITE_ONLY
} TZFlashOpenMode;
// TZFlashLoad 模块载入
void TZFlashLoad(int pageSize, TZFlashEraseFunc eraseFunc, TZFlashWriteFunc writeFunc, TZFlashReadFunc readFunc);
// TZFlashOpen 打开flash文件.
// 注意:打开时会擦除flash.要保证打开的flash大小是页的整数倍,否则会打开失败
// 返回值为0表示打开失败
intptr_t TZFlashOpen(int addrStart, int size, TZFlashOpenMode mode);
// TZFlashWrite 向flash写入数据
// 成功返回写入的字节数,失败返回-1
int TZFlashWrite(intptr_t fd, uint8_t* bytes, int size);
// TZFlashRead 从flash中读取数据
// 成功返回读取的字节数,失败返回-1
int TZFlashRead(intptr_t fd, uint8_t* bytes, int size);
// TZFlashClose 关闭
void TZFlashClose(intptr_t fd);
#endif
tzflash.c
// Copyright 2019 The TZIOT Authors. All rights reserved.
// flash管理模块主文件
#include "tzflash.h"
#define CACHE_SIZE 64
#pragma pack(1)
// tFlashInterface flash管理接口
typedef struct {
int pageSize;
TZFlashEraseFunc erase;
TZFlashWriteFunc write;
TZFlashReadFunc read;
} tFlashInterface;
// tFlashFile flash文件类型
typedef struct {
int addrStart;
int addrStop;
int offset;
TZFlashOpenMode mode;
uint8_t cache[CACHE_SIZE];
int cacheLen;
} tFlashFile;
#pragma pack()
static tFlashInterface gInterface;
// TZFlashLoad 模块载入
void TZFlashLoad(int pageSize, TZFlashEraseFunc eraseFunc, TZFlashWriteFunc writeFunc, TZFlashReadFunc readFunc) {
gInterface.pageSize = pageSize;
gInterface.erase = eraseFunc;
gInterface.write = writeFunc;
gInterface.read = readFunc;
}
// TZFlashOpen 打开flash文件.
// 注意:只写模式打开时会擦除flash.要保证打开的flash大小是页的整数倍,否则会打开失败
// 返回值为0表示打开失败
intptr_t TZFlashOpen(int addrStart, int size, TZFlashOpenMode mode) {
if (mode == TZFLASH_WRITE_ONLY) {
if (size % gInterface.pageSize != 0) {
return 0;
}
if (gInterface.erase(addrStart, size) == false) {
return 0;
}
}
tFlashFile* file = malloc(sizeof(tFlashFile));
if (file == NULL) {
return 0;
}
file->addrStart = addrStart;
file->addrStop = addrStart + size - 1;
file->mode = mode;
file->offset = file->addrStart;
file->cacheLen = 0;
return (intptr_t)file;
}
// TZFlashWrite 向flash写入数据
// 成功返回写入的字节数,失败返回-1
int TZFlashWrite(intptr_t fd, uint8_t* bytes, int size) {
tFlashFile* file = (tFlashFile*)fd;
if (file->mode == TZFLASH_READ_ONLY) {
return -1;
}
if (file->offset + file->cacheLen + size > file->addrStop) {
return -1;
}
int delta = 0;
int writeNum = 0;
for (;;) {
delta = CACHE_SIZE - file->cacheLen;
// 比cache可写入空间小则直接写入
if (size < delta) {
memcpy(file->cache + file->cacheLen, bytes, (size_t)size);
file->cacheLen += size;
writeNum += size;
break;
}
// 写满cache,再全部写入flash
memcpy(file->cache + file->cacheLen, bytes, (size_t)delta);
file->cacheLen += delta;
gInterface.write(file->offset, file->cache, file->cacheLen);
file->offset += file->cacheLen;
file->cacheLen = 0;
size -= delta;
writeNum += delta;
}
return writeNum;
}
// TZFlashRead 从flash中读取数据
// 成功返回读取的字节数,失败返回-1
int TZFlashRead(intptr_t fd, uint8_t* bytes, int size) {
tFlashFile* file = (tFlashFile*)fd;
if (file->mode == TZFLASH_WRITE_ONLY) {
return -1;
}
if (file->offset > file->addrStop) {
return 0;
}
int delta = file->addrStop - file->offset + 1;
int readSize = delta > size ? size : delta;
gInterface.read(file->offset, bytes, readSize);
file->offset += readSize;
return readSize;
}
// TZFlashClose 关闭
void TZFlashClose(intptr_t fd) {
tFlashFile* file = (tFlashFile*)fd;
gInterface.write(file->offset, file->cache, file->cacheLen);
free(file);
}
测试
#include "test_tzflash.h"
#include "tzflash.h"
#define PAGE_SIZE 1024
#define FLASH_SIZE 10240
static uint8_t gFlash[FLASH_SIZE] = {0};
static bool erase(int addr, int size);
static bool write(int addr, uint8_t* bytes, int size);
static bool read(int addr, uint8_t* bytes, int size);
static void testCase0(void);
static void testCase1(void);
static void testCase2(void);
void TestTZFlashRun(void) {
printf("-------------------->test tz flashn");
TZFlashLoad(PAGE_SIZE, erase, write, read);
testCase0();
testCase1();
testCase2();
printf("-------------------->test endn");
}
static bool erase(int addr, int size) {
if (size % PAGE_SIZE != 0) {
return false;
}
memset(gFlash + addr, 0, (size_t)size);
return true;
}
static bool write(int addr, uint8_t* bytes, int size) {
if (addr + size > FLASH_SIZE) {
return false;
}
memcpy(gFlash + addr, bytes, (size_t)size);
return true;
}
static bool read(int addr, uint8_t* bytes, int size) {
if (size > FLASH_SIZE - addr) {
return false;
}
memcpy(bytes, gFlash + addr, (size_t)size);
return true;
}
static void testCase0(void) {
printf("-------------------->testCase0n");
intptr_t fd = TZFlashOpen(0, PAGE_SIZE, TZFLASH_WRITE_ONLY);
int writeNum = 0;
writeNum = TZFlashWrite(fd, "i am jdh!", strlen("i am jdh"));
printf("write:%s", "i am jdh!n");
writeNum += TZFlashWrite(fd, "123456789", strlen("123456789"));
printf("write:%s", "123456789n");
writeNum += TZFlashWrite(fd, "abcde", strlen("abcde"));
printf("write:%s", "abcden");
TZFlashClose(fd);
fd = TZFlashOpen(0, PAGE_SIZE, TZFLASH_READ_ONLY);
char buf[100] = {0};
int readNum = TZFlashRead(fd, buf, writeNum);
TZFlashClose(fd);
printf("write num:%d read num:%d read text:%sn", writeNum, readNum, buf);
}
static void testCase1(void) {
printf("-------------------->testCase1n");
intptr_t fd = TZFlashOpen(1024, PAGE_SIZE * 4, TZFLASH_WRITE_ONLY);
uint8_t buf[255] = {0};
for (int i = 0; i < 234; i++) {
buf[i] = i;
}
int writeNum = 0;
for (int i = 0; i < 10; i++) {
writeNum += TZFlashWrite(fd, buf, 234);
}
printf("write num:%dn", writeNum);
TZFlashClose(fd);
fd = TZFlashOpen(1024, PAGE_SIZE, TZFLASH_READ_ONLY);
uint8_t buf1[255] = {0};
int readNum = 0;
for (int i = 0; i < 5; i++) {
readNum = TZFlashRead(fd, buf1, 10);
printf("read num:%dn", readNum);
for (int i = 0; i < 10; i++) {
printf("%d ", buf1[i]);
}
printf("n");
}
TZFlashClose(fd);
}
static void testCase2(void) {
printf("-------------------->testCase2n");
intptr_t fd = TZFlashOpen(2048, PAGE_SIZE * 4, TZFLASH_WRITE_ONLY);
uint8_t buf[1] = {0};
int writeNum = 0;
for (int i = 0; i < 1024; i++) {
buf[0] = i;
writeNum += TZFlashWrite(fd, buf, 1);
if (i < 5 || i > 1020) {
printf("write:%d:%dn", i, buf[0]);
}
}
printf("write num:%dn", writeNum);
TZFlashClose(fd);
fd = TZFlashOpen(2048, PAGE_SIZE, TZFLASH_READ_ONLY);
int readNum = 0;
for (int i = 0; i < 1024; i++) {
readNum += TZFlashRead(fd, buf, 1);
if (i < 5 || i > 1020) {
上一篇:STM32待机模式测试
下一篇:驱动字库芯片GT23L24M0140
推荐阅读
史海拾趣
为了进一步拓展业务,ABI Electronics公司开始积极寻求全球市场的布局。通过与各地的电子分销商、代理商建立合作关系,ABI的产品逐渐进入了全球各地的市场。同时,ABI还积极参加各类国际电子展会,展示其最新技术和产品,与全球同行建立了广泛的联系和合作。
随着产品线的不断丰富和市场需求的持续增长,Cotco公司开始加大市场拓展力度。公司积极参加国内外各类电子行业展览和交流活动,与潜在客户和合作伙伴建立了广泛的联系。同时,Cotco也注重品牌建设,通过赞助行业活动、开展公益事业等方式提升品牌知名度和美誉度。经过几年的努力,Cotco已经成为电子行业内一个响当当的名字。
DIALIGHT公司一直专注于工业LED照明领域的发展。他们深入了解工业空间照明的需求和挑战,设计了一系列专为工业应用而定制的LED照明产品。这些产品不仅易于安装和维护,而且能在恶劣的环境下持续使用。此外,DIALIGHT还提供集成系统解决方案,帮助客户降低能源成本、维护成本和碳足迹,同时提高设施的安全性和生产力。通过不断创新和优质服务,DIALIGHT在工业LED照明领域赢得了广泛的认可和信赖。
为了确保产品质量和客户满意度,杰力建立了一套完善的质量管理体系。公司从原材料采购、生产制造到产品检测等各个环节都实行严格的质量控制和管理。同时,杰力还引进了先进的检测设备和技术手段,对产品质量进行全面检测和评估。这些措施使得杰力的产品在质量上得到了有效保障,并赢得了客户的信赖和好评。
随着技术的不断成熟和产品的广泛应用,BTCPower开始寻求更广阔的市场空间。公司积极与国际知名电子品牌进行合作,将其产品推向全球市场。通过与这些品牌的合作,BTCPower不仅提升了自身的品牌知名度,还获得了更多的商业机会和市场份额。
在稳固了国内市场后,Elpress AB开始积极拓展国际市场。公司设立了多个海外子公司和物流中心,如丹麦的锡尔克堡、德国的Viersen以及中国的北京等地。这些海外机构的建立为Elpress AB的产品提供了更广阔的销售渠道和更便捷的服务支持。同时,Elpress AB还与国际知名电子企业开展合作,共同研发新产品、开拓新市场,进一步提升了公司的国际影响力。
电路如下,测得TXD和TXA的波形如图中所示,TXD接单片机TXD,TXA为光耦输出波形,TXD波形还算理想,但TXA波形上升沿上升缓慢,请问各位大虾如何改善TXA波形? … 查看全部问答∨ |
|
我在一个窗口中添加一个button, 在WM_COMMAND中, 点击这个button, button处于按下的状态, 松开鼠标的时候, 弹出一个窗口, 关闭这个弹出的窗口之后, button才被弹起来, 我想要的是松开鼠标的同时, button进入弹起的状态, 也就是说, 这个弹出窗口被关 ...… 查看全部问答∨ |
|
Window ce.net 4.0 如何开发屏幕保护程序,并指定快捷键Ctrl+Alt+Q Window ce.net 4.0 如何开发屏幕保护程序,并指定快捷键Ctrl+Alt+Q 是一台设备上的系统,我想按下快捷键显示屏幕保护程序,并在中间显示几行字 知道的请帮助我一下… 查看全部问答∨ |
请教一个问题: 在WinCE环境下,使用eVC编程 定义了2个字节的数据 TCHAR buf1[3]=_T("7A"); SetDlgItemText(IDC_EDIT3,buf1); 显示的ASCII 现在我想用十进制显示出来,怎么转换呢?… 查看全部问答∨ |
用RS232串口实现最简单,但是速度慢; 用EPP/ECP并口传输数据和用USB总线传输数据两种方案从开发难易程度、通信速度方面各有哪些优势呢? 开发难易程度需要考虑FPGA端的开发以及PC端软件的开发两方面; 谢谢各位,目前正在方案选择中,希望大家 ...… 查看全部问答∨ |
设计资源 培训 开发板 精华推荐
- 【贝能好礼相送】我们拼啦 寻觅Infineon 调光恒流LED驱动器 ICL5102写真
- 2022 Digi-Key KOL 视频系列:你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍
- 【报名赢小米手环、膳魔师保温杯等好礼】罗德与施瓦茨HDMI 1.4b/2.1 接口测试
- STM32 线上技术日开播【40块新品开发板等你抽】|解读多款新品技术及应用
- 解锁【W5500-EVB-Pico】,探秘以太网底层,得捷Follow me第4期来袭!
- 是德科技服务日研讨会|武汉站——邀请函
- 2020年全球工程师调查
- 【双11特别推荐】新产品,新方案,#TI“芯”世界#之电机驱动器
- 村田感恩季:这份电子元器件使用攻略已备好,速来闯关!
- 早睡早起,为自己的健康打个卡