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