Skip to content

Commit 7475f55

Browse files
fal: add new example for norflash
1 parent 59a690a commit 7475f55

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
#include <fal.h>
2+
#include "fal_def.h"
3+
4+
#define FLASH_SECTOR_SIZE ( 4 * 1024 )
5+
#define FLASH_START_ADDR 0U
6+
#define FLASH_END_ADDR 0x01000000U // 16*1024*1024
7+
8+
#define FLASH_PROGRAM_MIN_SIZE 256 // 256 bytes
9+
//每次对falsh写入时 底层可以写入的最大字节数为 FALSH_PAGE_SIZE
10+
#define FALSH_PAGE_SIZE FLASH_PROGRAM_MIN_SIZE // 256 bytes
11+
12+
/**
13+
* @brief 需要实现以下函数
14+
*/
15+
extern int norflash_init( void );
16+
extern void norflash_read( uint8_t* pbuf, uint32_t addr, uint16_t datalen );
17+
extern void norflash_write_page( uint8_t* pbuf, uint32_t addr, uint16_t datalen );
18+
extern void norflash_erase_sector( uint32_t saddr );
19+
20+
static int init( void );
21+
static int read( long offset, uint8_t* buf, size_t size );
22+
static int write( long offset, const uint8_t* buf, size_t size );
23+
static int erase( long offset, size_t size );
24+
25+
#define FAL_ALIGN_UP( size, align ) \
26+
( ( ( size ) + ( align ) - 1 ) - ( ( ( size ) + ( align ) - 1 ) % ( align ) ) )
27+
#define FAL_ALIGN_DOWN( size, align ) ( ( ( size ) / ( align ) ) * ( align ) )
28+
29+
static int32_t get_sector( uint32_t address )
30+
{
31+
uint32_t sector = 0;
32+
if ( address < FLASH_END_ADDR && address >= FLASH_START_ADDR ) {
33+
address -= FLASH_START_ADDR;
34+
sector = address / FLASH_SECTOR_SIZE;
35+
return sector;
36+
}
37+
return -1;
38+
}
39+
40+
static int init( void )
41+
{
42+
norflash_init();
43+
return 0;
44+
}
45+
46+
47+
static int read( long offset, uint8_t* buf, size_t size )
48+
{
49+
norflash_read( buf, offset + FLASH_START_ADDR, size );
50+
return size;
51+
}
52+
53+
static uint32_t judge_whether_erase( uint8_t* sector_buf, uint16_t len )
54+
{
55+
uint8_t* p = sector_buf;
56+
for ( size_t i = 0; i < len; i++ ) {
57+
if ( p[ i ] != 0xFF ) {
58+
return 1;
59+
}
60+
}
61+
return 0;
62+
}
63+
/**
64+
* @brief
65+
*
66+
* @param offset 绝对地址
67+
* @param buf 读出来的扇区数据缓存
68+
* @param size 从扇区开始要写的长度 小于扇区大小
69+
* @return int
70+
*/
71+
static int write_sector( long offset, const uint8_t* buf, size_t size )
72+
{
73+
uint32_t addr = FLASH_START_ADDR + offset;
74+
uint32_t addr_up = FAL_ALIGN_UP( addr, FALSH_PAGE_SIZE );
75+
uint32_t addr_down = FAL_ALIGN_DOWN( addr, FALSH_PAGE_SIZE );
76+
77+
uint32_t addr_end = addr + size;
78+
uint32_t addr_end_up = FAL_ALIGN_UP( addr_end, FALSH_PAGE_SIZE );
79+
uint32_t addr_end_down = FAL_ALIGN_DOWN( addr_end, FALSH_PAGE_SIZE );
80+
81+
uint32_t cur_addr = addr_down;
82+
uint32_t max_write_len = 0;
83+
uint32_t write_len = 0;
84+
while ( cur_addr < addr_end_up ) {
85+
if ( cur_addr < addr ) {
86+
max_write_len = ( addr_up - addr );
87+
write_len = size >= max_write_len ? max_write_len : size;
88+
norflash_write_page( buf, addr, write_len );
89+
buf += write_len;
90+
}
91+
else if ( cur_addr == addr_end_down ) {
92+
max_write_len = FALSH_PAGE_SIZE;
93+
write_len = addr_end - cur_addr;
94+
write_len = write_len >= max_write_len ? max_write_len : write_len;
95+
norflash_write_page( buf, cur_addr, write_len );
96+
}
97+
else {
98+
norflash_write_page( buf, cur_addr, FALSH_PAGE_SIZE );
99+
buf += FALSH_PAGE_SIZE;
100+
}
101+
102+
cur_addr += FALSH_PAGE_SIZE;
103+
}
104+
return size;
105+
}
106+
static int write( long offset, const uint8_t* buf, size_t size )
107+
{
108+
uint32_t addr = FLASH_START_ADDR + offset;
109+
uint32_t addr_up = FAL_ALIGN_UP( addr, FLASH_SECTOR_SIZE );
110+
uint32_t addr_down = FAL_ALIGN_DOWN( addr, FLASH_SECTOR_SIZE );
111+
112+
uint32_t addr_end = addr + size;
113+
uint32_t addr_end_up = FAL_ALIGN_UP( addr_end, FLASH_SECTOR_SIZE );
114+
uint32_t addr_end_down = FAL_ALIGN_DOWN( addr_end, FLASH_SECTOR_SIZE );
115+
uint32_t cur_addr = addr_down;
116+
117+
uint32_t max_write_len = 0;
118+
uint32_t write_len = 0;
119+
120+
if ( addr_end_up > FLASH_END_ADDR || ( int )addr_end_down < FLASH_START_ADDR ) return -1;
121+
//如果不使用内存分配可以定义一个static FLASH_SECTOR_SIZE 长度的buf
122+
uint8_t* read_sector_buf = FAL_MALLOC( FLASH_SECTOR_SIZE );
123+
if ( read_sector_buf == RT_NULL ) {
124+
return -2;
125+
}
126+
while ( cur_addr < addr_end_up ) {
127+
// 首次扇区写
128+
if ( cur_addr < addr ) {
129+
read( cur_addr - FLASH_START_ADDR, read_sector_buf, FLASH_SECTOR_SIZE );
130+
max_write_len = ( addr_up - addr );
131+
write_len = size >= max_write_len ? max_write_len : size;
132+
if ( judge_whether_erase( read_sector_buf + addr - cur_addr, write_len ) ){
133+
norflash_erase_sector( get_sector( cur_addr ) );
134+
FAL_MEMCPY( read_sector_buf + ( addr - cur_addr ), buf, write_len );
135+
write_sector( cur_addr, read_sector_buf, FLASH_SECTOR_SIZE );
136+
}
137+
else {
138+
write_sector( addr, buf, write_len );
139+
}
140+
buf += write_len;
141+
}
142+
//最后一次扇区写
143+
else if ( cur_addr == addr_end_down ) {
144+
read( cur_addr - FLASH_START_ADDR, read_sector_buf, FLASH_SECTOR_SIZE );
145+
max_write_len = FLASH_SECTOR_SIZE;
146+
write_len = addr_end - cur_addr;
147+
write_len = write_len >= max_write_len ? max_write_len : write_len;
148+
if ( judge_whether_erase( read_sector_buf, write_len ) ) {
149+
FAL_MEMCPY( read_sector_buf, buf, write_len );
150+
norflash_erase_sector( get_sector( cur_addr ) );
151+
write_sector( cur_addr, read_sector_buf, FLASH_SECTOR_SIZE );
152+
}
153+
else {
154+
write_sector( cur_addr, buf, write_len );
155+
}
156+
}
157+
//中间扇区写 直接擦除
158+
else {
159+
norflash_erase_sector( get_sector( cur_addr ) );
160+
write_sector( cur_addr, buf, FLASH_SECTOR_SIZE );
161+
buf += FLASH_SECTOR_SIZE;
162+
}
163+
cur_addr += FLASH_SECTOR_SIZE;
164+
}
165+
FAL_FREE( read_sector_buf );
166+
return size;
167+
}
168+
169+
static int erase( long offset, size_t size )
170+
{
171+
int32_t cur_erase_sector;
172+
uint32_t addr = FLASH_START_ADDR + offset;
173+
uint32_t addr_down = FAL_ALIGN_DOWN( addr, FLASH_SECTOR_SIZE );
174+
175+
uint32_t addr_end = addr + size;
176+
uint32_t addr_end_up = FAL_ALIGN_UP( addr_end, FLASH_SECTOR_SIZE );
177+
uint32_t cur_addr = addr_down;
178+
179+
while ( cur_addr < addr_end_up ) {
180+
cur_erase_sector = get_sector( cur_addr );
181+
if ( cur_erase_sector == -1 ) {
182+
return cur_addr - addr;
183+
}
184+
norflash_erase_sector( cur_erase_sector );
185+
cur_addr += FLASH_SECTOR_SIZE;
186+
}
187+
return size;
188+
}
189+
const struct fal_flash_dev norflash0 = {
190+
.name = "norflash0",
191+
.addr = FLASH_START_ADDR,
192+
.len = FLASH_END_ADDR - FLASH_START_ADDR,
193+
.blk_size = FLASH_SECTOR_SIZE,
194+
.ops = { init, read, write, erase },
195+
.write_gran = 1,
196+
};

0 commit comments

Comments
 (0)