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