Skip to main content
欢迎来到PAWPAW技术文档网站了解更多信息

读写Flash数据分区

使用基于XTC-Tool的quadflash.hquadflashlib.h对Flash进行读写,本笔记提供了其代码示例:

  1. 初始化存储设备

    • 使用 fl_connectToDevice 函数连接到特定的闪存设备。
    • 设置引导分区大小。
    • 获取每页的字节数和每块的页数。
  2. 写入操作 (massStorageWrite):

    • 将数据写入到闪存的特定块中。
    • 每次写入前,数据被复制到 pageBuffer_g,然后使用 fl_writeDataPage 函数写入。
  3. 读取操作 (massStorageRead):

    • 从闪存的特定块中读取数据。
    • 使用 fl_readDataPage 函数读取数据到 pageBuffer_g,然后复制到输出缓冲区。
  4. 计算存储大小 (massStorageSize):

    • 计算总共可用于数据存储的块数。
  5. 主函数 (main):

    • 执行初始化。
    • 创建测试数据并填充到写缓冲区。
    • 写入数据到闪存并计算写入速度。
    • 读取数据并计算读取速度。
    • 验证读取的数据是否与写入的数据相同。
    • 输出测试结果。

get_time() 函数是一个包装函数,它调用 get_reference_time() 来获取当前时间。

由于 get_reference_time() 只能在 C 文件中使用,而不能在 XC 文件中使用,所以 get_time() 提供了一个兼容的接口,使得可以在 XC 文件中间接使用 get_reference_time()。在 C 文件中定义 get_time() 函数时,需要包含 <xcore/hwtimer.h> 头文件。

#include <stdio.h>
#include <xcore/hwtimer.h>

uint32_t get_time()
{
return get_reference_time();
}

点击下载 Flash数据分区的读写示例代码

Flash数据分区的读写示例代码
#include <xs1.h>
#include <platform.h>
#include <xclib.h>
#include <string.h>
#include <stdio.h>
#include "stdint.h"
#include "print.h"

//Flash_Functions_start
#include <quadflash.h>
#include <quadflashlib.h>

extern uint32_t get_time();

#define FL_QUADDEVICE_UC25HQ40 \
{ \
0, /* UC25HQ16B_QSPI - Just specify 0 as flash_id */\
256, /* page size */\
2048, /* num pages */\
3, /* address size */\
3, /* log2 clock divider */\
0x9F, /* QSPI_RDID */\
0, /* id dummy bytes */\
3, /* id size in bytes */\
0xB36013, /* device id */\
0x20, /* QSPI_SE */\
4096, /* Sector erase is always 4KB */\
0x06, /* QSPI_WREN */\
0x04, /* QSPI_WRDI */\
PROT_TYPE_NONE, /* Protection via SR */\
{{0,0},{0x00,0x00}}, /* QSPI_SP, QSPI_SU */\
0x02, /* QSPI_PP */\
0xEB, /* QSPI_READ_FAST */\
1, /* 1 read dummy byte */\
SECTOR_LAYOUT_REGULAR, /* mad sectors */\
{4096,{0,{0}}}, /* regular sector sizes */\
0x05, /* QSPI_RDSR */\
0x01, /* QSPI_WRSR */\
0x01, /* QSPI_WIP_BIT_MASK */\
}

on tile[0]: fl_QSPIPorts QspiPort =
{
XS1_PORT_1B, /* PORT_SQI_CS */
XS1_PORT_1C, /* PORT_SQI_SCLK */
XS1_PORT_4B, /* PORT_SQI_SIO */
XS1_CLKBLK_1
};

#define MASS_STORAGE_BLOCKLENGTH 256
#define FLASH_PARTITION_SIZE (65536/* page size: 256 */ * 4) // Boot Partition size

fl_QuadDeviceSpec flashSpec[1] = {FL_QUADDEVICE_UC25HQ40};


int pagesPerBlock_g = 0;
int bytesPerPage_g = 0;
unsigned char pageBuffer_g[MASS_STORAGE_BLOCKLENGTH];

void massStorageInit() {
fl_connectToDevice(QspiPort, flashSpec, 1);
fl_setBootPartitionSize(FLASH_PARTITION_SIZE);
bytesPerPage_g = fl_getPageSize();
pagesPerBlock_g = (MASS_STORAGE_BLOCKLENGTH / bytesPerPage_g);
}

int massStorageWrite(unsigned int blockNr, unsigned char buffer[]) {
for(int i = 0; i < pagesPerBlock_g; i++) {
for(int j = 0; j < bytesPerPage_g; j++) {
pageBuffer_g[j] = buffer[i * bytesPerPage_g + j];
}
fl_writeDataPage(blockNr * pagesPerBlock_g + i, buffer);
}
return 0;
}

int massStorageRead(unsigned int blockNr, unsigned char buffer[]) {
for(int i = 0; i < pagesPerBlock_g; i++) {
fl_readDataPage(blockNr * pagesPerBlock_g + i, pageBuffer_g);
for(int j = 0; j < bytesPerPage_g; j++) {
buffer[i * bytesPerPage_g + j] = pageBuffer_g[j];
}
}
return 0;
}

int massStorageSize() {
int x = fl_getNumDataPages();
return x / pagesPerBlock_g;
}

void print_data(const char* label, const unsigned char* data, size_t size) {
printf("%s: ", label);
for (size_t i = 0; i < size; ++i) {
printf("%02X ", data[i]);
}
printf("\n");
}

int main()
{
printf("The Flash data partition read and write test starts\n\n");

// 初始化存储设备
massStorageInit();

int numDataPages = fl_getNumDataPages();
int numBlocks = massStorageSize();

printf("Total number of data pages: %d\n", numDataPages);
printf("Size of each block: %d pages\n", pagesPerBlock_g);

// 创建测试缓冲区并填充数据
unsigned char testWriteBuffer[MASS_STORAGE_BLOCKLENGTH];
for (int i = 0; i < MASS_STORAGE_BLOCKLENGTH; ++i) {
testWriteBuffer[i] = i % 256; // 填充测试数据
}

// 打印写入的数据
print_data("Write Data", testWriteBuffer, MASS_STORAGE_BLOCKLENGTH/16);

// 写入数据到指定块
unsigned int testBlockNr = 0; // 测试块号
uint32_t writeStart = get_time();
massStorageWrite(testBlockNr, testWriteBuffer);
uint32_t writeEnd = get_time();
double writeSpeedBytesPerSec = MASS_STORAGE_BLOCKLENGTH / ((writeEnd - writeStart) / 1e9);

// 打印写入数据的块号、大小和速度(MB/s)
printf("Written block number: %u\n", testBlockNr);
printf("Written block size: %u bytes\n", MASS_STORAGE_BLOCKLENGTH);
printf("Write speed: %.2f MB/s\n", writeSpeedBytesPerSec / 1e6);
printf("Bytes that can be written in 1 second: %.0f bytes\n", writeSpeedBytesPerSec);

// 清除测试缓冲区
unsigned char testReadBuffer[MASS_STORAGE_BLOCKLENGTH] = {0};

// 读取数据
uint32_t readStart = get_time();
massStorageRead(testBlockNr, testReadBuffer);
uint32_t readEnd = get_time();
double readSpeedBytesPerSec = MASS_STORAGE_BLOCKLENGTH / ((readEnd - readStart) / 1e9);

// 打印读取的数据
print_data("Read Data", testReadBuffer, MASS_STORAGE_BLOCKLENGTH/16);

// 打印读取数据的块号、大小和速度(MB/s)
printf("Read block number: %u\n", testBlockNr);
printf("Read block size: %u bytes\n", MASS_STORAGE_BLOCKLENGTH);
printf("Read speed: %.2f MB/s\n", readSpeedBytesPerSec / 1e6);
printf("Bytes that can be read in 1 second: %.0f bytes\n", readSpeedBytesPerSec);

// 验证数据
int isDataValid = (memcmp(testReadBuffer, testWriteBuffer, MASS_STORAGE_BLOCKLENGTH) == 0);

// 输出测试结果
if (isDataValid) {
printf("Mass storage read/write test passed.\n");
} else {
printf("Mass storage read/write test failed.\n");
}

}