1 /*
2 * Copyright (c) 2006-2025, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-11-30 flybreak first version
9 */
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14
15 #include "board.h"
16 #include "hal_data.h"
17
18 #include "drv_common.h"
19
20 #if defined(RT_USING_FAL)
21 #include "fal.h"
22 #endif
23
24 //#define DRV_DEBUG
25 #define LOG_TAG "drv.flash"
26 #ifdef DRV_DEBUG
27 #define DBG_LVL DBG_LOG
28 #else
29 #define DBG_LVL DBG_INFO
30 #endif /* DRV_DEBUG */
31 #include <rtdbg.h>
32
33 #if BSP_FEATURE_FLASH_HP_VERSION
34 /* FLASH API */
35 #define R_FLASH_Open R_FLASH_HP_Open
36 #define R_FLASH_Reset R_FLASH_HP_Reset
37 #define R_FLASH_Write R_FLASH_HP_Write
38 #define R_FLASH_Erase R_FLASH_HP_Erase
39 #define R_FLASH_StartUpAreaSelect R_FLASH_HP_StartUpAreaSelect
40 /* BSP_FEATURE_FLASH */
41 #define FLASH_CF_WRITE_SIZE BSP_FEATURE_FLASH_HP_CF_WRITE_SIZE
42
43 #else /* FLASH LP */
44 /* FLASH API */
45 #define R_FLASH_Open R_FLASH_LP_Open
46 #define R_FLASH_Reset R_FLASH_LP_Reset
47 #define R_FLASH_Write R_FLASH_LP_Write
48 #define R_FLASH_Erase R_FLASH_LP_Erase
49 #define R_FLASH_StartUpAreaSelect R_FLASH_LP_StartUpAreaSelect
50 /* BSP_FEATURE_FLASH */
51 #define FLASH_CF_WRITE_SIZE BSP_FEATURE_FLASH_LP_CF_WRITE_SIZE
52
53 #endif
54
_flash_init(void)55 int _flash_init(void)
56 {
57 fsp_err_t err = FSP_SUCCESS;
58 /* Open Flash_HP */
59 err = R_FLASH_Open(&g_flash_ctrl, &g_flash_cfg);
60 /* Handle Error */
61 if (FSP_SUCCESS != err)
62 {
63 LOG_E("\r\n Flah_HP_Open API failed");
64 }
65 /* Setup Default Block 0 as Startup Setup Block */
66 err = R_FLASH_StartUpAreaSelect(&g_flash_ctrl, FLASH_STARTUP_AREA_BLOCK0, true);
67 if (err != FSP_SUCCESS)
68 {
69 LOG_E("\r\n Flah_HP_StartUpAreaSelect API failed");
70 }
71 return 0;
72 }
73
74 /**
75 * Read data from flash.
76 * @note This operation's units is word.
77 *
78 * @param addr flash address
79 * @param buf buffer to store read data
80 * @param size read bytes size
81 *
82 * @return result
83 */
_flash_read(rt_uint32_t addr,rt_uint8_t * buf,size_t size)84 int _flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size)
85 {
86 size_t i;
87
88 for (i = 0; i < size; i++, buf++, addr++)
89 {
90 *buf = *(rt_uint8_t *) addr;
91 }
92
93 return size;
94 }
95
96 /**
97 * Write data to flash.
98 * @note This operation's units is word.
99 * @note This operation must after erase. @see flash_erase.
100 *
101 * @param addr flash address
102 * @param buf the write data buffer
103 * @param size write bytes size
104 *
105 * @return result
106 */
_flash_write(rt_uint32_t addr,const rt_uint8_t * buf,size_t size)107 int _flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size)
108 {
109 rt_err_t result = RT_EOK;
110 rt_base_t level;
111 fsp_err_t err = FSP_SUCCESS;
112 size_t written_size = 0;
113
114 if (size % FLASH_CF_WRITE_SIZE)
115 {
116 LOG_E("Flash Write size must be an integer multiple of %d", FLASH_CF_WRITE_SIZE);
117 }
118
119 while (written_size < size)
120 {
121 level = rt_hw_interrupt_disable();
122 R_FLASH_Reset(&g_flash_ctrl);
123 /* Write code flash data*/
124 err = R_FLASH_Write(&g_flash_ctrl, (uint32_t)(buf + written_size), addr + written_size, FLASH_CF_WRITE_SIZE);
125 rt_hw_interrupt_enable(level);
126
127 /* Error Handle */
128 if (FSP_SUCCESS != err)
129 {
130 LOG_E("Write API failed");
131 return -RT_EIO;
132 }
133
134 written_size += FLASH_CF_WRITE_SIZE;
135 }
136
137 if (result != RT_EOK)
138 {
139 return result;
140 }
141
142 return size;
143 }
144
145 typedef bool (*block_func)(int no, size_t addr, size_t size, void *parm1, void *parm2, void *parm3);
fal_block_iter(const struct fal_flash_dev * flash,block_func func,void * parm1,void * parm2,void * parm3)146 void fal_block_iter(const struct fal_flash_dev *flash, block_func func, void *parm1, void *parm2, void *parm3)
147 {
148 int no = 0;
149 size_t addr = flash->addr;
150 for (int i = 0; i < FAL_DEV_BLK_MAX; i++)
151 {
152 /* blocks[i] */
153 const struct flash_blk *cur_blk = &flash->blocks[i];
154 if (cur_blk->size == 0 || cur_blk->count == 0)
155 {
156 break;
157 }
158 int j = cur_blk->count;
159 while (j--)
160 {
161 /* block_no */
162 if (func(no, addr, cur_blk->size, parm1, parm2, parm3) == true)
163 {
164 return;
165 }
166 addr += cur_blk->size;
167 no ++;
168 }
169 }
170 }
171
calculate_block_num(int no,size_t addr,size_t size,void * erase_addr,void * erase_size,void * number)172 bool calculate_block_num(int no, size_t addr, size_t size, void *erase_addr, void *erase_size, void *number)
173 {
174 rt_uint32_t e_addr = (rt_uint32_t)erase_addr;
175 size_t e_size = (size_t)erase_size;
176 int *i = (int *)number;
177
178 LOG_D("block_num: no: %d, addr is (0x%p), size: %d\n, i:%d", no, addr, size, *i);
179 LOG_D("erase_addr: (0x%p), erase_size: %d\n", e_addr, e_size);
180 if (e_addr >= addr && e_addr < addr + size)
181 {
182 (*i) ++;
183 return false;
184 }
185 else if (addr > e_addr && addr < e_addr + e_size)
186 {
187 (*i) ++;
188 return false;
189 }
190 else if (addr >= e_addr + e_size)
191 {
192 return true;
193 }
194 return false;
195 }
196
197 /**
198 * Erase data on flash.
199 * @note This operation is irreversible.
200 * @note This operation's units is different which on many chips.
201 *
202 * @param addr flash address
203 * @param size erase bytes size
204 *
205 * @return result
206 */
207 #if BSP_FEATURE_FLASH_HP_VERSION
_flash_hp0_erase(rt_uint32_t addr,size_t size)208 int _flash_hp0_erase(rt_uint32_t addr, size_t size)
209 #else
210 int _flash_lp_erase(rt_uint32_t addr, size_t size)
211 #endif
212 {
213 fsp_err_t err = FSP_SUCCESS;
214 rt_base_t level;
215 int block_num = 0;
216
217 if ((addr + size) > BSP_FEATURE_FLASH_CODE_FLASH_START + BSP_ROM_SIZE_BYTES)
218 {
219 LOG_E("ERROR: erase outrange flash size! addr is (0x%p)\n", (void *)(addr + size));
220 return -RT_EINVAL;
221 }
222
223 if (size < 1)
224 {
225 return -RT_EINVAL;
226 }
227
228 level = rt_hw_interrupt_disable();
229 R_FLASH_Reset(&g_flash_ctrl);
230
231 fal_block_iter(&_onchip_flash_hp0, &calculate_block_num, (void *)addr, (void *)size, &block_num);
232
233 /* Erase Block */
234 #if BSP_FEATURE_FLASH_HP_VERSION
235 err = R_FLASH_Erase(&g_flash_ctrl,
236 RT_ALIGN_DOWN(addr, BSP_FEATURE_FLASH_HP_CF_REGION0_BLOCK_SIZE),
237 block_num);
238 #else
239 err = R_FLASH_Erase(&g_flash_ctrl,
240 RT_ALIGN_DOWN(addr, BSP_FEATURE_FLASH_LP_CF_BLOCK_SIZE),
241 ((size - 1) / BSP_FEATURE_FLASH_LP_CF_BLOCK_SIZE + 1));
242 #endif
243 rt_hw_interrupt_enable(level);
244
245 if (err != FSP_SUCCESS)
246 {
247 LOG_E("Erase failed:addr (0x%p), size %d", (void *)addr, size);
248 return -RT_EIO;
249 }
250
251 LOG_D("erase done: addr (0x%p), size %d", (void *)addr, size);
252 return size;
253 }
254
255 #if defined(RT_USING_FAL)
256
257 #if BSP_FEATURE_FLASH_HP_VERSION
258
259 static int fal_flash_hp0_read(long offset, rt_uint8_t *buf, size_t size);
260 static int fal_flash_hp0_write(long offset, const rt_uint8_t *buf, size_t size);
261 static int fal_flash_hp0_erase(long offset, size_t size);
262
263 const struct fal_flash_dev _onchip_flash_hp0 =
264 {
265 "onchip_flash_hp0",
266 BSP_FEATURE_FLASH_CODE_FLASH_START,
267 BSP_ROM_SIZE_BYTES,
268 BSP_FEATURE_FLASH_HP_CF_REGION0_BLOCK_SIZE,
269 {
270 _flash_init,
271 fal_flash_hp0_read,
272 fal_flash_hp0_write,
273 fal_flash_hp0_erase
274 },
275 (BSP_FEATURE_FLASH_HP_CF_WRITE_SIZE * 8)
276 , {
277 {
278 .size = BSP_FEATURE_FLASH_HP_CF_REGION0_BLOCK_SIZE,
279 .count = BSP_FEATURE_FLASH_HP_CF_REGION0_SIZE / BSP_FEATURE_FLASH_HP_CF_REGION0_BLOCK_SIZE
280 },
281 {
282 .size = BSP_FEATURE_FLASH_HP_CF_REGION1_BLOCK_SIZE,
283 .count = (BSP_ROM_SIZE_BYTES - BSP_FEATURE_FLASH_HP_CF_REGION0_SIZE) / BSP_FEATURE_FLASH_HP_CF_REGION1_BLOCK_SIZE
284 },
285 }
286 };
287
288 /* code flash region0 */
fal_flash_hp0_read(long offset,rt_uint8_t * buf,size_t size)289 static int fal_flash_hp0_read(long offset, rt_uint8_t *buf, size_t size)
290 {
291 return _flash_read(_onchip_flash_hp0.addr + offset, buf, size);
292 }
293
fal_flash_hp0_write(long offset,const rt_uint8_t * buf,size_t size)294 static int fal_flash_hp0_write(long offset, const rt_uint8_t *buf, size_t size)
295 {
296 return _flash_write(_onchip_flash_hp0.addr + offset, buf, size);
297 }
298
fal_flash_hp0_erase(long offset,size_t size)299 static int fal_flash_hp0_erase(long offset, size_t size)
300 {
301 return _flash_hp0_erase(_onchip_flash_hp0.addr + offset, size);
302 }
303
304 #else /* flash lp code flash */
305
306 static int fal_flash_lp_read(long offset, rt_uint8_t *buf, size_t size);
307 static int fal_flash_lp_write(long offset, const rt_uint8_t *buf, size_t size);
308 static int fal_flash_lp_erase(long offset, size_t size);
309
310 const struct fal_flash_dev _onchip_flash_lp =
311 {
312 "onchip_flash_lp",
313 FLASH_START_ADDRESS,
314 BSP_ROM_SIZE_BYTES,
315 BSP_FEATURE_FLASH_LP_CF_BLOCK_SIZE,
316 {
317 _flash_init,
318 fal_flash_lp_read,
319 fal_flash_lp_write,
320 fal_flash_lp_erase
321 },
322 (BSP_FEATURE_FLASH_LP_CF_WRITE_SIZE * 8)
323 };
324
fal_flash_lp_read(long offset,rt_uint8_t * buf,size_t size)325 static int fal_flash_lp_read(long offset, rt_uint8_t *buf, size_t size)
326 {
327 return _flash_read(_onchip_flash_lp.addr + offset, buf, size);
328 }
329
fal_flash_lp_write(long offset,const rt_uint8_t * buf,size_t size)330 static int fal_flash_lp_write(long offset, const rt_uint8_t *buf, size_t size)
331 {
332 return _flash_write(_onchip_flash_lp.addr + offset, buf, size);
333 }
334
fal_flash_lp_erase(long offset,size_t size)335 static int fal_flash_lp_erase(long offset, size_t size)
336 {
337 return _flash_lp_erase(_onchip_flash_lp.addr + offset, size);
338 }
339
340 #endif
341
342 #endif
343