fal: add new example for norflash

This commit is contained in:
ricky 2025-03-28 08:08:16 +08:00 committed by GitHub
parent 59a690addc
commit 7475f5549d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 196 additions and 0 deletions

View File

@ -0,0 +1,196 @@
#include <fal.h>
#include "fal_def.h"
#define FLASH_SECTOR_SIZE ( 4 * 1024 )
#define FLASH_START_ADDR 0U
#define FLASH_END_ADDR 0x01000000U // 16*1024*1024
#define FLASH_PROGRAM_MIN_SIZE 256 // 256 bytes
//每次对falsh写入时 底层可以写入的最大字节数为 FALSH_PAGE_SIZE
#define FALSH_PAGE_SIZE FLASH_PROGRAM_MIN_SIZE // 256 bytes
/**
* @brief
*/
extern int norflash_init( void );
extern void norflash_read( uint8_t* pbuf, uint32_t addr, uint16_t datalen );
extern void norflash_write_page( uint8_t* pbuf, uint32_t addr, uint16_t datalen );
extern void norflash_erase_sector( uint32_t saddr );
static int init( void );
static int read( long offset, uint8_t* buf, size_t size );
static int write( long offset, const uint8_t* buf, size_t size );
static int erase( long offset, size_t size );
#define FAL_ALIGN_UP( size, align ) \
( ( ( size ) + ( align ) - 1 ) - ( ( ( size ) + ( align ) - 1 ) % ( align ) ) )
#define FAL_ALIGN_DOWN( size, align ) ( ( ( size ) / ( align ) ) * ( align ) )
static int32_t get_sector( uint32_t address )
{
uint32_t sector = 0;
if ( address < FLASH_END_ADDR && address >= FLASH_START_ADDR ) {
address -= FLASH_START_ADDR;
sector = address / FLASH_SECTOR_SIZE;
return sector;
}
return -1;
}
static int init( void )
{
norflash_init();
return 0;
}
static int read( long offset, uint8_t* buf, size_t size )
{
norflash_read( buf, offset + FLASH_START_ADDR, size );
return size;
}
static uint32_t judge_whether_erase( uint8_t* sector_buf, uint16_t len )
{
uint8_t* p = sector_buf;
for ( size_t i = 0; i < len; i++ ) {
if ( p[ i ] != 0xFF ) {
return 1;
}
}
return 0;
}
/**
* @brief
*
* @param offset
* @param buf
* @param size
* @return int
*/
static int write_sector( long offset, const uint8_t* buf, size_t size )
{
uint32_t addr = FLASH_START_ADDR + offset;
uint32_t addr_up = FAL_ALIGN_UP( addr, FALSH_PAGE_SIZE );
uint32_t addr_down = FAL_ALIGN_DOWN( addr, FALSH_PAGE_SIZE );
uint32_t addr_end = addr + size;
uint32_t addr_end_up = FAL_ALIGN_UP( addr_end, FALSH_PAGE_SIZE );
uint32_t addr_end_down = FAL_ALIGN_DOWN( addr_end, FALSH_PAGE_SIZE );
uint32_t cur_addr = addr_down;
uint32_t max_write_len = 0;
uint32_t write_len = 0;
while ( cur_addr < addr_end_up ) {
if ( cur_addr < addr ) {
max_write_len = ( addr_up - addr );
write_len = size >= max_write_len ? max_write_len : size;
norflash_write_page( buf, addr, write_len );
buf += write_len;
}
else if ( cur_addr == addr_end_down ) {
max_write_len = FALSH_PAGE_SIZE;
write_len = addr_end - cur_addr;
write_len = write_len >= max_write_len ? max_write_len : write_len;
norflash_write_page( buf, cur_addr, write_len );
}
else {
norflash_write_page( buf, cur_addr, FALSH_PAGE_SIZE );
buf += FALSH_PAGE_SIZE;
}
cur_addr += FALSH_PAGE_SIZE;
}
return size;
}
static int write( long offset, const uint8_t* buf, size_t size )
{
uint32_t addr = FLASH_START_ADDR + offset;
uint32_t addr_up = FAL_ALIGN_UP( addr, FLASH_SECTOR_SIZE );
uint32_t addr_down = FAL_ALIGN_DOWN( addr, FLASH_SECTOR_SIZE );
uint32_t addr_end = addr + size;
uint32_t addr_end_up = FAL_ALIGN_UP( addr_end, FLASH_SECTOR_SIZE );
uint32_t addr_end_down = FAL_ALIGN_DOWN( addr_end, FLASH_SECTOR_SIZE );
uint32_t cur_addr = addr_down;
uint32_t max_write_len = 0;
uint32_t write_len = 0;
if ( addr_end_up > FLASH_END_ADDR || ( int )addr_end_down < FLASH_START_ADDR ) return -1;
//如果不使用内存分配可以定义一个static FLASH_SECTOR_SIZE 长度的buf
uint8_t* read_sector_buf = FAL_MALLOC( FLASH_SECTOR_SIZE );
if ( read_sector_buf == RT_NULL ) {
return -2;
}
while ( cur_addr < addr_end_up ) {
// 首次扇区写
if ( cur_addr < addr ) {
read( cur_addr - FLASH_START_ADDR, read_sector_buf, FLASH_SECTOR_SIZE );
max_write_len = ( addr_up - addr );
write_len = size >= max_write_len ? max_write_len : size;
if ( judge_whether_erase( read_sector_buf + addr - cur_addr, write_len ) ){
norflash_erase_sector( get_sector( cur_addr ) );
FAL_MEMCPY( read_sector_buf + ( addr - cur_addr ), buf, write_len );
write_sector( cur_addr, read_sector_buf, FLASH_SECTOR_SIZE );
}
else {
write_sector( addr, buf, write_len );
}
buf += write_len;
}
//最后一次扇区写
else if ( cur_addr == addr_end_down ) {
read( cur_addr - FLASH_START_ADDR, read_sector_buf, FLASH_SECTOR_SIZE );
max_write_len = FLASH_SECTOR_SIZE;
write_len = addr_end - cur_addr;
write_len = write_len >= max_write_len ? max_write_len : write_len;
if ( judge_whether_erase( read_sector_buf, write_len ) ) {
FAL_MEMCPY( read_sector_buf, buf, write_len );
norflash_erase_sector( get_sector( cur_addr ) );
write_sector( cur_addr, read_sector_buf, FLASH_SECTOR_SIZE );
}
else {
write_sector( cur_addr, buf, write_len );
}
}
//中间扇区写 直接擦除
else {
norflash_erase_sector( get_sector( cur_addr ) );
write_sector( cur_addr, buf, FLASH_SECTOR_SIZE );
buf += FLASH_SECTOR_SIZE;
}
cur_addr += FLASH_SECTOR_SIZE;
}
FAL_FREE( read_sector_buf );
return size;
}
static int erase( long offset, size_t size )
{
int32_t cur_erase_sector;
uint32_t addr = FLASH_START_ADDR + offset;
uint32_t addr_down = FAL_ALIGN_DOWN( addr, FLASH_SECTOR_SIZE );
uint32_t addr_end = addr + size;
uint32_t addr_end_up = FAL_ALIGN_UP( addr_end, FLASH_SECTOR_SIZE );
uint32_t cur_addr = addr_down;
while ( cur_addr < addr_end_up ) {
cur_erase_sector = get_sector( cur_addr );
if ( cur_erase_sector == -1 ) {
return cur_addr - addr;
}
norflash_erase_sector( cur_erase_sector );
cur_addr += FLASH_SECTOR_SIZE;
}
return size;
}
const struct fal_flash_dev norflash0 = {
.name = "norflash0",
.addr = FLASH_START_ADDR,
.len = FLASH_END_ADDR - FLASH_START_ADDR,
.blk_size = FLASH_SECTOR_SIZE,
.ops = { init, read, write, erase },
.write_gran = 1,
};