单片机flash通用读写库:TZFlash

单片机flash通用读写库:TZFlash

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

说明

本文发布单片机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 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
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值