1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-03-16 luobeihai first version
9 */
10
11 #include "board.h"
12
13 #ifdef BSP_USING_ON_CHIP_FLASH
14 #include "drv_flash.h"
15
16 #if defined(RT_USING_FAL)
17 #include "fal.h"
18 #endif
19
20 #define DRV_DEBUG
21 #define LOG_TAG "drv.flash"
22 #include <drv_log.h>
23
24 /* Base address of the Flash sectors */
25 #define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
26 #define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */
27 #define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */
28 #define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */
29 #define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */
30 #define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */
31 #define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */
32 #define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */
33 #define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */
34 #define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */
35 #define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
36 #define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */
37
38 /**
39 * @brief Gets the sector of a given address
40 * @param None
41 * @retval The sector of a given address
42 */
GetSector(rt_uint32_t Address)43 static rt_uint32_t GetSector(rt_uint32_t Address)
44 {
45 rt_uint32_t sector = 0;
46
47 if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
48 {
49 sector = FMC_SECTOR_0;
50 }
51 else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
52 {
53 sector = FMC_SECTOR_1;
54 }
55 else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
56 {
57 sector = FMC_SECTOR_2;
58 }
59 else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
60 {
61 sector = FMC_SECTOR_3;
62 }
63 else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
64 {
65 sector = FMC_SECTOR_4;
66 }
67 else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
68 {
69 sector = FMC_SECTOR_5;
70 }
71 else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
72 {
73 sector = FMC_SECTOR_6;
74 }
75 else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
76 {
77 sector = FMC_SECTOR_7;
78 }
79 else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
80 {
81 sector = FMC_SECTOR_8;
82 }
83 else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
84 {
85 sector = FMC_SECTOR_9;
86 }
87 else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
88 {
89 sector = FMC_SECTOR_10;
90 }
91 else if((Address < APM32_FLASH_END_ADDRESS) && (Address >= ADDR_FLASH_SECTOR_11))
92 {
93 sector = FMC_SECTOR_11;
94 }
95
96 return sector;
97 }
98
99 /**
100 * Read data from flash.
101 * @note This operation's units is word.
102 *
103 * @param addr flash address
104 * @param buf buffer to store read data
105 * @param size read bytes size
106 *
107 * @return result
108 */
apm32_flash_read(rt_uint32_t addr,rt_uint8_t * buf,size_t size)109 int apm32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size)
110 {
111 size_t i;
112
113 if ((addr + size) > APM32_FLASH_END_ADDRESS)
114 {
115 LOG_E("read outrange flash size! addr is (0x%p)", (void*)(addr + size));
116 return -1;
117 }
118
119 for (i = 0; i < size; i++, buf++, addr++)
120 {
121 *buf = *(rt_uint8_t *) addr;
122 }
123
124 return size;
125 }
126
127 /**
128 * Write data to flash.
129 * @note This operation's units is word.
130 * @note This operation must after erase. @see flash_erase.
131 *
132 * @param addr flash address
133 * @param buf the write data buffer
134 * @param size write bytes size
135 *
136 * @return result
137 */
apm32_flash_write(rt_uint32_t addr,const rt_uint8_t * buf,size_t size)138 int apm32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size)
139 {
140 rt_err_t result = RT_EOK;
141 rt_uint32_t end_addr = addr + size;
142 rt_uint32_t written_size = 0;
143 rt_uint32_t write_size = 0;
144
145 if ((end_addr) > APM32_FLASH_END_ADDRESS)
146 {
147 LOG_E("write outrange flash size! addr is (0x%p)", (void*)(addr + size));
148 return -RT_EINVAL;
149 }
150
151 if (size < 1)
152 {
153 return -RT_EINVAL;
154 }
155
156 FMC_Unlock();
157
158 FMC_ClearStatusFlag(FMC_FLAG_ENDOP | FMC_FLAG_ERROP | FMC_FLAG_ERRWRP | FMC_FLAG_ERRPGA | FMC_FLAG_ERRPGP | FMC_FLAG_ERRPGS);
159
160 while (written_size < size)
161 {
162 if (((addr + written_size) % 4 == 0) && (size - written_size >= 4))
163 {
164 if (FMC_ProgramWord(addr + written_size, *((rt_uint32_t *)(buf + written_size))) == FMC_COMPLETE)
165 {
166 if (*(rt_uint32_t *)(addr + written_size) != *(rt_uint32_t *)(buf + written_size))
167 {
168 result = -RT_ERROR;
169 break;
170 }
171 }
172 else
173 {
174 result = -RT_ERROR;
175 break;
176 }
177 write_size = 4;
178 }
179 else if (((addr + written_size) % 2 == 0) && (size - written_size >= 2))
180 {
181 if (FMC_ProgramHalfWord(addr + written_size, *((rt_uint16_t *)(buf + written_size))) == FMC_COMPLETE)
182 {
183 if (*(rt_uint16_t *)(addr + written_size) != *(rt_uint16_t *)(buf + written_size))
184 {
185 result = -RT_ERROR;
186 break;
187 }
188 }
189 else
190 {
191 result = -RT_ERROR;
192 break;
193 }
194 write_size = 2;
195 }
196 else
197 {
198 if (FMC_ProgramByte(addr + written_size, *((rt_uint8_t *)(buf + written_size))) == FMC_COMPLETE)
199 {
200 if (*(rt_uint8_t *)(addr + written_size) != *(rt_uint8_t *)(buf + written_size))
201 {
202 result = -RT_ERROR;
203 break;
204 }
205 }
206 else
207 {
208 result = -RT_ERROR;
209 break;
210 }
211 write_size = 1;
212 }
213
214 written_size += write_size;
215 }
216
217 FMC_Lock();
218
219 if (result != RT_EOK)
220 {
221 return result;
222 }
223
224 return size;
225 }
226
227 /**
228 * Erase data on flash.
229 * @note This operation is irreversible.
230 * @note This operation's units is different which on many chips.
231 *
232 * @param addr flash address
233 * @param size erase bytes size
234 *
235 * @return result
236 */
apm32_flash_erase(rt_uint32_t addr,size_t size)237 int apm32_flash_erase(rt_uint32_t addr, size_t size)
238 {
239 rt_err_t result = RT_EOK;
240 rt_uint32_t FirstSector = 0, NbOfSectors = 0;
241 rt_uint32_t index = 0;
242
243 if ((addr + size) > APM32_FLASH_END_ADDRESS)
244 {
245 LOG_E("ERROR: erase outrange flash size! addr is (0x%p)\n", (void*)(addr + size));
246 return -RT_EINVAL;
247 }
248
249 if (size < 1)
250 {
251 return -RT_EINVAL;
252 }
253
254 /* Unlock the Flash to enable the flash control register access */
255 FMC_Unlock();
256
257 FMC_ClearStatusFlag(FMC_FLAG_ENDOP | FMC_FLAG_ERROP | FMC_FLAG_ERRWRP | FMC_FLAG_ERRPGA | FMC_FLAG_ERRPGP | FMC_FLAG_ERRPGS);
258
259 /* Get the 1st sector to erase */
260 FirstSector = GetSector(addr) >> 3;
261
262 /* Get the number of sector to erase from 1st sector */
263 NbOfSectors = (GetSector(addr + size - 1) >> 3) - FirstSector + 1;
264
265 /* Erase by sector by sector to be done */
266 for (index = FirstSector; index < (FirstSector + NbOfSectors); index++)
267 {
268 if (FMC_EraseSector((FMC_SECTOR_T)(index << 3), FMC_VOLTAGE_3) != FMC_COMPLETE)
269 {
270 result = -RT_ERROR;
271 goto __exit;
272 }
273 }
274
275 __exit:
276 FMC_Lock();
277
278 if (result != RT_EOK)
279 {
280 return result;
281 }
282
283 LOG_D("erase done: addr (0x%p), size %d", (void*)addr, size);
284 return size;
285 }
286
287 #if defined(RT_USING_FAL)
288
289 static int fal_flash_read_16k(long offset, rt_uint8_t *buf, size_t size);
290 static int fal_flash_read_64k(long offset, rt_uint8_t *buf, size_t size);
291 static int fal_flash_read_128k(long offset, rt_uint8_t *buf, size_t size);
292
293 static int fal_flash_write_16k(long offset, const rt_uint8_t *buf, size_t size);
294 static int fal_flash_write_64k(long offset, const rt_uint8_t *buf, size_t size);
295 static int fal_flash_write_128k(long offset, const rt_uint8_t *buf, size_t size);
296
297 static int fal_flash_erase_16k(long offset, size_t size);
298 static int fal_flash_erase_64k(long offset, size_t size);
299 static int fal_flash_erase_128k(long offset, size_t size);
300
301 const struct fal_flash_dev apm32_onchip_flash_16k =
302 {
303 "onchip_flash_16k",
304 APM32_FLASH_START_ADRESS_16K,
305 FLASH_SIZE_GRANULARITY_16K,
306 (16 * 1024),
307 {
308 NULL,
309 fal_flash_read_16k,
310 fal_flash_write_16k,
311 fal_flash_erase_16k,
312 },
313 8,
314 };
315 const struct fal_flash_dev apm32_onchip_flash_64k =
316 {
317 "onchip_flash_64k",
318 APM32_FLASH_START_ADRESS_64K,
319 FLASH_SIZE_GRANULARITY_64K,
320 (64 * 1024),
321 {
322 NULL,
323 fal_flash_read_64k,
324 fal_flash_write_64k,
325 fal_flash_erase_64k,
326 },
327 8,
328 };
329 const struct fal_flash_dev apm32_onchip_flash_128k =
330 {
331 "onchip_flash_128k",
332 APM32_FLASH_START_ADRESS_128K,
333 FLASH_SIZE_GRANULARITY_128K,
334 (128 * 1024),
335 {
336 NULL,
337 fal_flash_read_128k,
338 fal_flash_write_128k,
339 fal_flash_erase_128k,
340 },
341 8,
342 };
343
fal_flash_read_16k(long offset,rt_uint8_t * buf,size_t size)344 static int fal_flash_read_16k(long offset, rt_uint8_t *buf, size_t size)
345 {
346 return apm32_flash_read(apm32_onchip_flash_16k.addr + offset, buf, size);
347 }
fal_flash_read_64k(long offset,rt_uint8_t * buf,size_t size)348 static int fal_flash_read_64k(long offset, rt_uint8_t *buf, size_t size)
349 {
350 return apm32_flash_read(apm32_onchip_flash_64k.addr + offset, buf, size);
351 }
fal_flash_read_128k(long offset,rt_uint8_t * buf,size_t size)352 static int fal_flash_read_128k(long offset, rt_uint8_t *buf, size_t size)
353 {
354 return apm32_flash_read(apm32_onchip_flash_128k.addr + offset, buf, size);
355 }
356
fal_flash_write_16k(long offset,const rt_uint8_t * buf,size_t size)357 static int fal_flash_write_16k(long offset, const rt_uint8_t *buf, size_t size)
358 {
359 return apm32_flash_write(apm32_onchip_flash_16k.addr + offset, buf, size);
360 }
fal_flash_write_64k(long offset,const rt_uint8_t * buf,size_t size)361 static int fal_flash_write_64k(long offset, const rt_uint8_t *buf, size_t size)
362 {
363 return apm32_flash_write(apm32_onchip_flash_64k.addr + offset, buf, size);
364 }
fal_flash_write_128k(long offset,const rt_uint8_t * buf,size_t size)365 static int fal_flash_write_128k(long offset, const rt_uint8_t *buf, size_t size)
366 {
367 return apm32_flash_write(apm32_onchip_flash_128k.addr + offset, buf, size);
368 }
369
fal_flash_erase_16k(long offset,size_t size)370 static int fal_flash_erase_16k(long offset, size_t size)
371 {
372 return apm32_flash_erase(apm32_onchip_flash_16k.addr + offset, size);
373 }
fal_flash_erase_64k(long offset,size_t size)374 static int fal_flash_erase_64k(long offset, size_t size)
375 {
376 return apm32_flash_erase(apm32_onchip_flash_64k.addr + offset, size);
377 }
fal_flash_erase_128k(long offset,size_t size)378 static int fal_flash_erase_128k(long offset, size_t size)
379 {
380 return apm32_flash_erase(apm32_onchip_flash_128k.addr + offset, size);
381 }
382
383 #endif
384 #endif /* BSP_USING_ON_CHIP_FLASH */
385