本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
本文发布单片机flash通用读写库TZFlash,有两个优点:
// 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
// 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 flash\n");
TZFlashLoad(PAGE_SIZE, erase, write, read);
testCase0();
testCase1();
testCase2();
printf("-------------------->test end\n");
}
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("-------------------->testCase0\n");
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", "123456789\n");
writeNum += TZFlashWrite(fd, "abcde", strlen("abcde"));
printf("write:%s", "abcde\n");
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:%s\n", writeNum, readNum, buf);
}
static void testCase1(void) {
printf("-------------------->testCase1\n");
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:%d\n", 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:%d\n", readNum);
for (int i = 0; i < 10; i++) {
printf("%d ", buf1[i]);
}
printf("\n");
}
TZFlashClose(fd);
}
static void testCase2(void) {
printf("-------------------->testCase2\n");
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:%d\n", i, buf[0]);
}
}
printf("write num:%d\n", 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) {
printf("read:%d:%d\n", i, buf[0]);
}
}
printf("read num:%d\n", readNum);
TZFlashClose(fd);
}
测试输出:
-------------------->test tz flash
-------------------->testCase0
write:i am jdh!
write:123456789
write:abcde
write num:22 read num:22 read text:i am jdh123456789abcde
-------------------->testCase1
write num:2340
read num:10
0 1 2 3 4 5 6 7 8 9
read num:10
10 11 12 13 14 15 16 17 18 19
read num:10
20 21 22 23 24 25 26 27 28 29
read num:10
30 31 32 33 34 35 36 37 38 39
read num:10
40 41 42 43 44 45 46 47 48 49
-------------------->testCase2
write:0:0
write:1:1
write:2:2
write:3:3
write:4:4
write:1021:253
write:1022:254
write:1023:255
write num:1024
read:0:0
read:1:1
read:2:2
read:3:3
read:4:4
read:1021:253
read:1022:254
read:1023:255
read num:1024
-------------------->test end