1 /*
2  * Copyright (c) 2006-2024 RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-07-26     Rbb666       first version
9  */
10 
11 #include <rtthread.h>
12 #include "drv_common.h"
13 
14 #ifdef BSP_USING_ON_CHIP_FLASH
15 #include "drv_flash.h"
16 
17 #if defined(RT_USING_FAL)
18     #include "fal.h"
19 #endif
20 
21 #define DRV_DEBUG
22 #define LOG_TAG                "drv.flash"
23 #include <drv_log.h>
24 
25 static cyhal_flash_t flash_obj;
26 static cyhal_flash_block_info_t block_info;
27 static cyhal_flash_info_t flash_info;
28 
_flash_init(void)29 int _flash_init(void)
30 {
31     cy_rslt_t err = CY_RSLT_SUCCESS;
32     /* Init Flash */
33     err = cyhal_flash_init(&flash_obj);
34 
35     /* Handle Error */
36     if (CY_RSLT_SUCCESS != err)
37     {
38         LOG_E("\r\n Flash Init failed");
39     }
40 
41     cyhal_flash_get_info(&flash_obj, &flash_info);
42 
43     block_info = flash_info.blocks[flash_info.block_count - 1u];
44 
45     return 0;
46 }
47 
get_page_32k(uint32_t addr)48 static rt_uint32_t get_page_32k(uint32_t addr)
49 {
50     rt_uint32_t page = 0;
51 
52     page = RT_ALIGN_DOWN(addr, IFX_EFLASH_PAGE_SIZE);
53 
54     return page;
55 }
56 
57 /**
58   * @brief  gets the page of a given address
59   * @param  addr: address of the flash memory
60   * @retval the page of a given address
61   */
get_page_256k(uint32_t addr)62 static rt_uint32_t get_page_256k(uint32_t addr)
63 {
64     rt_uint32_t page = 0;
65 
66     page = RT_ALIGN_DOWN(addr, IFX_FLASH_PAGE_SIZE);
67 
68     return page;
69 }
70 
ifx_flash_read_32k(rt_uint32_t addr,rt_uint8_t * buf,rt_uint32_t size)71 int ifx_flash_read_32k(rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t size)
72 {
73     rt_uint32_t i;
74 
75     if ((addr + size) > IFX_EFLASH_END_ADDRESS)
76     {
77         LOG_E("read outrange flash size! addr is (0x%p)", (void *)(addr + size));
78         return -RT_EINVAL;
79     }
80 
81     for (i = 0; i < size; i++, buf++, addr++)
82     {
83         *buf = *(rt_uint8_t *) addr;
84     }
85 
86     return size;
87 }
88 
89 /**
90  * @brief read data from flash.
91  * @note this operation's units is word.
92  *
93  * @param addr flash address
94  * @param buf buffer to store read data
95  * @param size read bytes size
96  *
97  * @return result
98  */
ifx_flash_read_256k(rt_uint32_t addr,rt_uint8_t * buf,rt_uint32_t size)99 int ifx_flash_read_256k(rt_uint32_t addr, rt_uint8_t *buf, rt_uint32_t size)
100 {
101     rt_uint32_t i;
102 
103     if ((addr + size) > IFX_FLASH_END_ADDRESS)
104     {
105         LOG_E("read outrange flash size! addr is (0x%p)", (void *)(addr + size));
106         return -RT_EINVAL;
107     }
108 
109     for (i = 0; i < size; i++, buf++, addr++)
110     {
111         *buf = *(rt_uint8_t *) addr;
112     }
113 
114     return size;
115 }
116 
117 /**
118  * @brief write data to flash.
119  * @note this operation's units is word.
120  * @note this operation must after erase. @see flash_erase.
121  *
122  * @param addr flash address
123  * @param buf the write data buffer
124  * @param size write bytes size
125  *
126  * @return result
127  */
ifx_flash_write(rt_uint32_t addr,const rt_uint8_t * buf,rt_uint32_t size)128 int ifx_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, rt_uint32_t size)
129 {
130     rt_err_t result = RT_EOK;
131     rt_base_t level;
132     cy_rslt_t err = CY_RSLT_SUCCESS;
133     size_t written_size = 0;
134 
135 #define BSP_FEATURE_FLASH_WRITE_SIZE 512U
136 
137     if (size % BSP_FEATURE_FLASH_WRITE_SIZE)
138     {
139         LOG_E("Flash Write size must be an integer multiple of %d", BSP_FEATURE_FLASH_WRITE_SIZE);
140         return -RT_EINVAL;
141     }
142 
143     while (written_size < size)
144     {
145         level = rt_hw_interrupt_disable();
146         /* Write code flash data*/
147         err = cyhal_flash_write(&flash_obj, addr + written_size, (rt_uint32_t *)(buf + written_size));
148         rt_hw_interrupt_enable(level);
149 
150         /* Error Handle */
151         if (CY_RSLT_SUCCESS != err)
152         {
153             LOG_E("Write API failed");
154             return -RT_EIO;
155         }
156 
157         written_size += BSP_FEATURE_FLASH_WRITE_SIZE;
158     }
159 
160     if (result != RT_EOK)
161     {
162         return result;
163     }
164 
165     return size;
166 }
167 
ifx_flash_erase_32k(rt_uint32_t addr,rt_uint32_t size)168 int ifx_flash_erase_32k(rt_uint32_t addr, rt_uint32_t size)
169 {
170     rt_err_t result = RT_EOK;
171     rt_uint32_t end_addr = addr + size;
172     rt_uint32_t page_addr = 0;
173     rt_base_t level;
174 
175     level = rt_hw_interrupt_disable();
176 
177     if ((end_addr) > IFX_EFLASH_END_ADDRESS)
178     {
179         LOG_E("erase outrange flash size! addr is (0x%p)", (void *)(addr + size));
180         return -RT_EINVAL;
181     }
182 
183     while (addr < end_addr)
184     {
185         page_addr = get_page_32k(addr);
186 
187         if (cyhal_flash_erase(&flash_obj, page_addr) != CY_RSLT_SUCCESS)
188         {
189             result = -RT_ERROR;
190             goto __exit;
191         }
192 
193         addr += IFX_FLASH_PAGE_SIZE;
194     }
195 
196     rt_hw_interrupt_enable(level);
197 
198 __exit:
199 
200     if (result != RT_EOK)
201     {
202         return result;
203     }
204 
205     return size;
206 }
207 
208 /**
209  * @brief erase data on flash .
210  * @note this operation is irreversible.
211  * @note this operation's units is different which on many chips.
212  *
213  * @param addr flash address
214  * @param size erase bytes size
215  *
216  * @return result
217  */
ifx_flash_erase_256k(rt_uint32_t addr,rt_uint32_t size)218 int ifx_flash_erase_256k(rt_uint32_t addr, rt_uint32_t size)
219 {
220     rt_err_t result = RT_EOK;
221     rt_uint32_t end_addr = addr + size;
222     rt_uint32_t page_addr = 0;
223     rt_base_t level;
224 
225     level = rt_hw_interrupt_disable();
226 
227     if ((end_addr) > IFX_FLASH_END_ADDRESS)
228     {
229         LOG_E("erase outrange flash size! addr is (0x%p)", (void *)(addr + size));
230         return -RT_EINVAL;
231     }
232 
233     while (addr < end_addr)
234     {
235         page_addr = get_page_256k(addr);
236 
237         if (cyhal_flash_erase(&flash_obj, page_addr) != CY_RSLT_SUCCESS)
238         {
239             result = -RT_ERROR;
240             goto __exit;
241         }
242 
243         addr += IFX_FLASH_PAGE_SIZE;
244     }
245 
246     rt_hw_interrupt_enable(level);
247 
248 __exit:
249 
250     if (result != RT_EOK)
251     {
252         return result;
253     }
254 
255     return size;
256 }
257 
258 #if defined(RT_USING_FAL)
259 static int fal_flash_read_32k(long offset, rt_uint8_t *buf, size_t size);
260 static int fal_flash_read_256k(long offset, rt_uint8_t *buf, size_t size);
261 
262 static int fal_flash_write_32k(long offset, const rt_uint8_t *buf, size_t size);
263 static int fal_flash_write_256k(long offset, const rt_uint8_t *buf, size_t size);
264 
265 static int fal_flash_erase_32k(long offset, size_t size);
266 static int fal_flash_erase_256k(long offset, size_t size);
267 
268 const struct fal_flash_dev ifx_onchip_flash_32k =
269 {
270     "onchip_flash_32k",
271     IFX_EFLASH_START_ADRESS,
272     IFX_EFLASH_SIZE,
273     IFX_EFLASH_PAGE_SIZE,
274     {
275         NULL,
276         fal_flash_read_32k,
277         fal_flash_write_32k,
278         fal_flash_erase_32k
279     }
280 };
281 
282 const struct fal_flash_dev ifx_onchip_flash_256k =
283 {
284     "onchip_flash_256k",
285     IFX_FLASH_START_ADRESS,
286     IFX_FLASH_SIZE,
287     IFX_FLASH_PAGE_SIZE,
288     {
289         _flash_init,
290         fal_flash_read_256k,
291         fal_flash_write_256k,
292         fal_flash_erase_256k
293     }
294 };
295 
fal_flash_read_32k(long offset,rt_uint8_t * buf,size_t size)296 static int fal_flash_read_32k(long offset, rt_uint8_t *buf, size_t size)
297 {
298     return ifx_flash_read_32k(ifx_onchip_flash_32k.addr + offset, buf, size);
299 }
300 
fal_flash_read_256k(long offset,rt_uint8_t * buf,size_t size)301 static int fal_flash_read_256k(long offset, rt_uint8_t *buf, size_t size)
302 {
303     return ifx_flash_read_256k(ifx_onchip_flash_256k.addr + offset, buf, size);
304 }
305 
fal_flash_write_32k(long offset,const rt_uint8_t * buf,size_t size)306 static int fal_flash_write_32k(long offset, const rt_uint8_t *buf, size_t size)
307 {
308     return ifx_flash_write(ifx_onchip_flash_32k.addr + offset, buf, size);
309 }
310 
fal_flash_write_256k(long offset,const rt_uint8_t * buf,size_t size)311 static int fal_flash_write_256k(long offset, const rt_uint8_t *buf, size_t size)
312 {
313     return ifx_flash_write(ifx_onchip_flash_256k.addr + offset, buf, size);
314 }
315 
fal_flash_erase_32k(long offset,size_t size)316 static int fal_flash_erase_32k(long offset, size_t size)
317 {
318     return ifx_flash_erase_32k(ifx_onchip_flash_32k.addr + offset, size);
319 }
320 
fal_flash_erase_256k(long offset,size_t size)321 static int fal_flash_erase_256k(long offset, size_t size)
322 {
323     return ifx_flash_erase_256k(ifx_onchip_flash_256k.addr + offset, size);
324 }
325 
326 #if defined(BSP_USING_ON_CHIP_FLASH)
rt_hw_on_chip_flash_init(void)327 static int rt_hw_on_chip_flash_init(void)
328 {
329     fal_init();
330     return RT_EOK;
331 }
332 INIT_ENV_EXPORT(rt_hw_on_chip_flash_init);
333 
flash64k_test(void)334 int flash64k_test(void)
335 {
336 #define TEST_OFF (ifx_onchip_flash_256k.len - 0x40000)
337     const struct fal_partition *param;
338     uint8_t write_buffer[512U] = {0};
339     uint8_t read_buffer[512U] = {0};
340 
341     /* Set write buffer, clear read buffer */
342     for (uint16_t index = 0; index < 512U; index++)
343     {
344         write_buffer[index] = index;
345         read_buffer[index] = 0;
346     }
347 
348     param = fal_partition_find("app");
349 
350     if (param == RT_NULL)
351     {
352         LOG_E("not find partition app!");
353         return -1;
354     }
355 
356     LOG_I("Erase Start...");
357     fal_partition_erase(param, TEST_OFF, 0x40000);
358     LOG_I("Erase succeeded!");
359     LOG_I("Write Start...");
360     fal_partition_write(param, TEST_OFF, write_buffer, sizeof(write_buffer));
361     LOG_I("Write succeeded!");
362     LOG_I("Read Start...");
363     fal_partition_read(param, TEST_OFF, read_buffer, 128U);
364     LOG_I("Read succeeded!");
365 
366     for (int i = 0; i < 128U; i++)
367     {
368         if (read_buffer[i] != write_buffer[i])
369         {
370             LOG_E("Data verification failed!");
371             return -1;
372         }
373     }
374 
375     LOG_I("Data verification succeeded!");
376     return 0;
377 }
378 MSH_CMD_EXPORT(flash64k_test, "drv flash64k test.");
379 
flash32k_test(void)380 int flash32k_test(void)
381 {
382 #define TEST32_OFF (ifx_onchip_flash_32k.len - 0x8000)
383     const struct fal_partition *param;
384     uint8_t write_buffer[512U] = {0};
385     uint8_t read_buffer[512U] = {0};
386 
387     /* Set write buffer, clear read buffer */
388     for (uint16_t index = 0; index < 512U; index++)
389     {
390         write_buffer[index] = index;
391         read_buffer[index] = 0;
392     }
393 
394     param = fal_partition_find("param");
395 
396     if (param == RT_NULL)
397     {
398         LOG_E("not find partition param!");
399         return -1;
400     }
401 
402     LOG_I("Erase Start...");
403     fal_partition_erase(param, TEST32_OFF, 0x8000);
404     LOG_I("Erase succeeded!");
405     LOG_I("Write Start...");
406     fal_partition_write(param, TEST32_OFF, write_buffer, sizeof(write_buffer));
407     LOG_I("Write succeeded!");
408     LOG_I("Read Start...");
409     fal_partition_read(param, TEST32_OFF, read_buffer, 128U);
410     LOG_I("Read succeeded!");
411 
412     for (int i = 0; i < 128U; i++)
413     {
414         if (read_buffer[i] != write_buffer[i])
415         {
416             LOG_E("Data verification failed!");
417             return -1;
418         }
419     }
420 
421     LOG_I("Data verification succeeded!");
422     return 0;
423 }
424 MSH_CMD_EXPORT(flash32k_test, "drv flash32k test.");
425 #endif
426 #endif
427 #endif /* BSP_USING_ON_CHIP_FLASH */
428