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