1 /**
2 ****************************************************************************************************
3 * @file fm33lc0xx_fl_flash.c
4 * @author FMSH Application Team
5 * @brief Src file of FLASH FL Module
6 ****************************************************************************************************
7 * @attention
8 *
9 * Copyright (c) [2021] [Fudan Microelectronics]
10 * THIS SOFTWARE is licensed under Mulan PSL v2.
11 * You can use this software according to the terms and conditions of the Mulan PSL v2.
12 * You may obtain a copy of Mulan PSL v2 at:
13 * http://license.coscl.org.cn/MulanPSL2
14 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
15 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
16 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
17 * See the Mulan PSL v2 for more details.
18 *
19 ****************************************************************************************************
20 */
21
22
23 /* Includes ------------------------------------------------------------------*/
24 #include "fm33lc0xx_fl.h"
25
26 /** @addtogroup FM33LC0XX_FL_Driver
27 * @{
28 */
29
30 /** @addtogroup FLASH
31 * @{
32 */
33
34 #ifdef FL_FLASH_DRIVER_ENABLED
35
36 /* Private macros ------------------------------------------------------------*/
37 /** @addtogroup FLASH_FL_Private_Macros
38 * @{
39 */
40
41 #define IS_FLASH_ALL_INSTANCE(INTENCE) (((INTENCE) == FLASH))
42
43 #define IS_FL_FLASH_PAGE_NUM(__VALUE__) ((((uint32_t)0x00000000U) < (__VALUE__)) &&\
44 ((__VALUE__) <= (FL_FLASH_MAX_PAGE_NUM)))
45
46 #define IS_FL_FLASH_SECTOR_NUM(__VALUE__) ((((uint32_t)0x00000000U) < (__VALUE__)) &&\
47 ((__VALUE__) <= (FL_FLASH_MAX_SECTOR_NUM)))
48
49 #define IS_FL_FLASH_MAX_ADDR(__VALUE__) ((((uint32_t)0x00000000U) < (__VALUE__)) &&\
50 ((__VALUE__) <= (FL_FLASH_ADDR_MAXPROGRAM)))
51
52 #define IS_FL_FLASH_MAX_PAGE(__VALUE__) ((((uint32_t)0x00000000U) < (__VALUE__)) &&\
53 ((__VALUE__) <= (FL_FLASH_MAX_PAGE_NUM)))
54
55 #define IS_FL_FLASH_MAX_SECTOR(__VALUE__) ((((uint32_t)0x00000000U) < (__VALUE__)) &&\
56 ((__VALUE__) <= (FL_FLASH_MAX_SECTOR_NUM)))
57 /**
58 * @}
59 */
60
61 /** @addtogroup FLASH_FL_EF_Init
62 * @{
63 */
64
65 /**
66 *@}
67 */
68
69 /** @addtogroup FLASH_FL_EF_Operation
70 * @{
71 */
72
73 /**
74 * @brief Flash 页擦除函数,一个页为512byte.
75 * @param FLASHx 外设入口地址
76 * @param address 为需要擦除的页内任意地址,推荐使用页开始的首地址(字对齐)
77 * .
78 * @retval 错误状态,可能值:
79 * -FL_FAIL 擦写发生错误
80 * -FL_PASS 擦写成功
81 */
FL_FLASH_PageErase(FLASH_Type * FLASHx,uint32_t address)82 FL_ErrorStatus FL_FLASH_PageErase(FLASH_Type *FLASHx, uint32_t address)
83 {
84 uint32_t timeout = 0;
85 uint32_t primask;
86 FL_ErrorStatus ret = FL_PASS;
87 /* 入口参数检查 */
88 assert_param(IS_FLASH_ALL_INSTANCE(FLASHx));
89 assert_param(IS_FL_FLASH_MAX_ADDR((uint32_t)address));
90 /*时钟使能*/
91 FL_RCC_EnableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
92 if(address & (FL_FLASH_ADDRS_ALIGN - 1))
93 {
94 /*地址未对齐*/
95 return FL_FAIL;
96 }
97 if(FL_FLASH_GetFlashLockStatus(FLASHx) == FL_FLASH_KEY_STATUS_ERROR)
98 {
99 /*Flash 已经锁定,复位前无法操作*/
100 return FL_FAIL;
101 }
102 FL_RCC_EnableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
103 /*配置擦写类型*/
104 FL_FLASH_SetFlashEraseType(FLASHx, FL_FLASH_ERASE_TYPE_PAGE);
105 /* 开始擦除页*/
106 FL_FLASH_EnableErase(FLASHx);
107 /* Key 序列*/
108 primask = __get_PRIMASK();
109 __disable_irq();
110 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_ERASE_KEY);
111 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_PAGE_ERASE_KEY);
112 __set_PRIMASK(primask);
113 FL_FLASH_ClearFlag_EraseComplete(FLASHx);
114 /* 擦请求 */
115 *((uint32_t *)address) = FL_FLASH_ERASE_REQUEST;
116 while(1)
117 {
118 timeout++;
119 if((timeout > FL_FLASH_ERASE_TIMEOUT)\
120 || (FL_FLASH_IsActiveFlag_ClockError(FLASHx))\
121 || (FL_FLASH_IsActiveFlag_KeyError(FLASHx))\
122 || (FL_FLASH_IsActiveFlag_AuthenticationError(FLASHx)))
123 {
124 /* 超时或出现错误 */
125 ret = FL_FAIL;
126 break;
127 }
128 else
129 if(FL_FLASH_IsActiveFlag_EraseComplete(FLASHx))
130 {
131 /*编程成功*/
132 FL_FLASH_ClearFlag_EraseComplete(FLASHx);
133 ret = FL_PASS;
134 break;
135 }
136 }
137 FL_FLASH_LockFlash(FLASHx);
138 FL_RCC_DisableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
139 FL_RCC_DisableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
140 return ret;
141 }
142
143 /**
144 * @brief Flash 扇区擦除函数,一个扇区为2k byte.
145 * @param FLASHx 外设入口地址
146 * @param address 为需要擦除的扇区内任意地址,推荐使用扇区开始的首地址(字对齐)
147 * .
148 * @retval 错误状态,可能值:
149 * -FL_FAIL 擦写发生错误
150 * -FL_PASS 擦写成功
151 */
FL_FLASH_SectorErase(FLASH_Type * FLASHx,uint32_t address)152 FL_ErrorStatus FL_FLASH_SectorErase(FLASH_Type *FLASHx, uint32_t address)
153 {
154 uint32_t timeout = 0;
155 uint32_t primask;
156 FL_ErrorStatus ret = FL_PASS;
157 /* 入口参数检查 */
158 assert_param(IS_FLASH_ALL_INSTANCE(FLASHx));
159 assert_param(IS_FL_FLASH_MAX_ADDR((uint32_t)address));
160 /*时钟使能*/
161 FL_RCC_EnableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
162 if(address & (FL_FLASH_ADDRS_ALIGN - 1))
163 {
164 /*地址未对齐*/
165 return FL_FAIL;
166 }
167 if(FL_FLASH_GetFlashLockStatus(FLASHx) == FL_FLASH_KEY_STATUS_ERROR)
168 {
169 /*Flash 已经锁定,复位前无法操作*/
170 return FL_FAIL;
171 }
172 FL_RCC_EnableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
173 /*配置擦写类型*/
174 FL_FLASH_SetFlashEraseType(FLASHx, FL_FLASH_ERASE_TYPE_SECTOR);
175 /* 开始擦除扇区*/
176 FL_FLASH_EnableErase(FLASHx);
177 /* Key 序列*/
178 primask = __get_PRIMASK();
179 __disable_irq();
180 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_ERASE_KEY);
181 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_SECTOR_ERASE_KEY);
182 __set_PRIMASK(primask);
183 FL_FLASH_ClearFlag_EraseComplete(FLASHx);
184 /* 擦请求 */
185 *((uint32_t *)address) = FL_FLASH_ERASE_REQUEST;
186 while(1)
187 {
188 timeout++;
189 if((timeout > FL_FLASH_ERASE_TIMEOUT)\
190 || (FL_FLASH_IsActiveFlag_ClockError(FLASHx))\
191 || (FL_FLASH_IsActiveFlag_KeyError(FLASHx))\
192 || (FL_FLASH_IsActiveFlag_AuthenticationError(FLASHx)))
193 {
194 /* 超时或出现错误 */
195 ret = FL_FAIL;
196 break;
197 }
198 else
199 if(FL_FLASH_IsActiveFlag_EraseComplete(FLASHx))
200 {
201 /*编程成功*/
202 FL_FLASH_ClearFlag_EraseComplete(FLASHx);
203 ret = FL_PASS;
204 break;
205 }
206 }
207 FL_FLASH_LockFlash(FLASHx);
208 FL_RCC_DisableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
209 FL_RCC_DisableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
210 return ret;
211 }
212
213 /**
214 * @brief 单次编程函数,编程地址必须对齐到字边界.
215 * @param FLASHx 外设入口地址
216 * @param address 为需要编程的已经擦除过的扇区内任意地址,非对齐地址编程将触发fault。
217 * @param data 待写入数据
218 * @retval 错误状态,可能值:
219 * -FL_FAIL 编程发生错误
220 * -FL_PASS 编程成功
221 */
FL_FLASH_Program_Word(FLASH_Type * FLASHx,uint32_t address,uint32_t data)222 FL_ErrorStatus FL_FLASH_Program_Word(FLASH_Type *FLASHx, uint32_t address, uint32_t data)
223 {
224 uint32_t timeout = 0;
225 uint32_t primask;
226 FL_ErrorStatus ret = FL_PASS;
227 /* 入口参数检查 */
228 assert_param(IS_FLASH_ALL_INSTANCE(FLASHx));
229 assert_param(IS_FL_FLASH_MAX_ADDR((uint32_t)address));
230 /*时钟使能*/
231 FL_RCC_EnableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
232 if(address & (FL_FLASH_ADDRS_ALIGN - 1))
233 {
234 /*地址未对齐*/
235 return FL_FAIL;
236 }
237 if(FL_FLASH_GetFlashLockStatus(FLASHx) == FL_FLASH_KEY_STATUS_ERROR)
238 {
239 /*Flash 已经锁定,复位前无法操作*/
240 return FL_FAIL;
241 }
242 FL_RCC_EnableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
243 /* 开始编程*/
244 FL_FLASH_EnableProgram(FLASHx);
245 /* Key 序列*/
246 primask = __get_PRIMASK();
247 __disable_irq();
248 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_PROGRAM_KEY1);
249 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_PROGRAM_KEY2);
250 __set_PRIMASK(primask);
251 *((uint32_t *)address) = data;
252 while(1)
253 {
254 timeout++;
255 if((timeout > FL_FLASH_ERASE_TIMEOUT)\
256 || (FL_FLASH_IsActiveFlag_ClockError(FLASHx))\
257 || (FL_FLASH_IsActiveFlag_KeyError(FLASHx))\
258 || (FL_FLASH_IsActiveFlag_AuthenticationError(FLASHx)))
259 {
260 /* 超时或出现错误 */
261 ret = FL_FAIL;
262 break;
263 }
264 else
265 if(FL_FLASH_IsActiveFlag_ProgramComplete(FLASHx))
266 {
267 /*编程成功*/
268 FL_FLASH_ClearFlag_ProgramComplete(FLASHx);
269 ret = FL_PASS;
270 break;
271 }
272 }
273 FL_FLASH_LockFlash(FLASHx);
274 FL_RCC_DisableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
275 FL_RCC_DisableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
276 return ret;
277 }
278
279 /**
280 * @brief 页编程函数,编程地址必须对齐到字边界.
281 * @param FLASHx 外设入口地址
282 * @param PageNum 为需要编程的已经擦除过的扇区号,FM33LC04最大为256,非对齐地址编程将触发fault。
283 * @param *data 待写入页数据
284 * @retval 错误状态,可能值:
285 * -FL_FAIL 编程发生错误
286 * -FL_PASS 编程成功
287 */
FL_FLASH_Program_Page(FLASH_Type * FLASHx,uint32_t pageNum,uint32_t * data)288 FL_ErrorStatus FL_FLASH_Program_Page(FLASH_Type *FLASHx, uint32_t pageNum, uint32_t *data)
289 {
290 uint32_t count;
291 uint32_t primask;
292 uint32_t address;
293 uint32_t timeout;
294 FL_ErrorStatus ret;
295 /* 入口参数检查 */
296 assert_param(IS_FLASH_ALL_INSTANCE(FLASHx));
297 assert_param(IS_FL_FLASH_MAX_PAGE((uint32_t)pageNum));
298 address = pageNum * FL_FLASH_PAGE_SIZE_BYTE;
299 /* 页对齐*/
300 if(address & (FL_FLASH_PAGE_SIZE_BYTE - 1))
301 {
302 /*地址未对齐*/
303 return FL_FAIL;
304 }
305 FL_RCC_EnableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
306 FL_RCC_EnableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
307 FL_FLASH_EnableProgram(FLASHx);
308 /* Key 序列*/
309 primask = __get_PRIMASK();
310 __disable_irq();
311 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_PROGRAM_KEY1);
312 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_PROGRAM_KEY2);
313 __set_PRIMASK(primask);
314 for(count = 0; count < FL_FLASH_PAGE_SIZE_BYTE; count += 4)
315 {
316 timeout = 0;
317 FL_FLASH_EnableProgram(FLASHx);
318 *((uint32_t *)address) = *data;
319 address += 4;
320 data++;
321 while(1)
322 {
323 timeout++;
324 if((timeout > FL_FLASH_ERASE_TIMEOUT)\
325 || (FL_FLASH_IsActiveFlag_ClockError(FLASHx))\
326 || (FL_FLASH_IsActiveFlag_KeyError(FLASHx))\
327 || (FL_FLASH_IsActiveFlag_AuthenticationError(FLASHx)))
328 {
329 /* 超时或出现错误 */
330 ret = FL_FAIL;
331 break;
332 }
333 if(FL_FLASH_IsActiveFlag_ProgramComplete(FLASHx))
334 {
335 /*编程成功*/
336 FL_FLASH_ClearFlag_ProgramComplete(FLASHx);
337 ret = FL_PASS;
338 break;
339 }
340 }
341 if(ret == FL_FAIL)
342 {
343 break;
344 }
345 }
346 FL_FLASH_LockFlash(FLASHx);
347 FL_RCC_DisableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
348 FL_RCC_DisableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
349 return ret;
350 }
351
352 /**
353 * @brief 扇区编程函数,编程地址必须对齐到字边界.
354 * @param FLASHx 外设入口地址
355 * @param sectorNum 为需要编程的已经擦除过的扇区号,最大为128,非对齐地址编程将触发fault。
356 * @param *data 待写入扇区数据
357 * @retval 错误状态,可能值:
358 * -FL_FAIL 编程发生错误
359 * -PASS编程成功
360 */
FL_FLASH_Program_Sector(FLASH_Type * FLASHx,uint32_t sectorNum,uint32_t * data)361 FL_ErrorStatus FL_FLASH_Program_Sector(FLASH_Type *FLASHx, uint32_t sectorNum, uint32_t *data)
362 {
363 uint32_t count;
364 uint32_t primask;
365 uint32_t address;
366 uint32_t timeout;
367 FL_ErrorStatus ret;
368 /* 入口参数检查 */
369 assert_param(IS_FLASH_ALL_INSTANCE(FLASHx));
370 assert_param(IS_FL_FLASH_MAX_SECTOR((uint32_t)sectorNum));
371 address = sectorNum * FL_FLASH_SECTOR_SIZE_BYTE;
372 /* 页对齐*/
373 if(address & (FL_FLASH_SECTOR_SIZE_BYTE - 1))
374 {
375 /*地址未对齐*/
376 return FL_FAIL;
377 }
378 FL_RCC_EnableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
379 FL_RCC_EnableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
380 FL_FLASH_EnableProgram(FLASHx);
381 /* Key 序列*/
382 primask = __get_PRIMASK();
383 __disable_irq();
384 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_PROGRAM_KEY1);
385 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_PROGRAM_KEY2);
386 __set_PRIMASK(primask);
387 for(count = 0; count < FL_FLASH_SECTOR_SIZE_BYTE; count += 4)
388 {
389 timeout = 0;
390 FL_FLASH_EnableProgram(FLASHx);
391 *((uint32_t *)address) = *data;
392 address += 4;
393 data++;
394 while(1)
395 {
396 timeout++;
397 if((timeout > FL_FLASH_ERASE_TIMEOUT)\
398 || (FL_FLASH_IsActiveFlag_ClockError(FLASHx))\
399 || (FL_FLASH_IsActiveFlag_KeyError(FLASHx))\
400 || (FL_FLASH_IsActiveFlag_AuthenticationError(FLASHx)))
401 {
402 /* 超时或出现错误 */
403 ret = FL_FAIL;
404 break;
405 }
406 if(FL_FLASH_IsActiveFlag_ProgramComplete(FLASHx))
407 {
408 /*编程成功*/
409 FL_FLASH_ClearFlag_ProgramComplete(FLASHx);
410 ret = FL_PASS;
411 break;
412 }
413 }
414 if(ret == FL_FAIL)
415 {
416 break;
417 }
418 }
419 FL_FLASH_LockFlash(FLASHx);
420 FL_RCC_DisableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
421 FL_RCC_DisableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
422 return ret;
423 }
424
425 /**
426 * @brief DMA编程函数,编程地址必须对齐到halt-page,长度固定为64字.
427 * @param FLASHx 外设入口地址
428 * @param address 待编程Flash地址
429 * @param *data 待写入Flash数据
430 *
431 * @retval 错误状态,可能值:
432 * -FL_FAIL 编程发生错误
433 * -FL_PASS 编程成功
434 */
FL_FLASH_Write_Dma(FLASH_Type * FLASHx,uint32_t address,uint32_t * data)435 FL_ErrorStatus FL_FLASH_Write_Dma(FLASH_Type *FLASHx, uint32_t address, uint32_t *data)
436 {
437 FL_ErrorStatus ret;
438 uint32_t primask;
439 uint32_t timeout;
440 FL_DMA_InitTypeDef initStruct = {0};
441 /* 入口参数检查 */
442 assert_param(IS_FLASH_ALL_INSTANCE(FLASHx));
443 assert_param(IS_FL_FLASH_MAX_ADDR(address));
444 /* 半页对齐*/
445 if(address & (FL_FLASH_PAGE_SIZE_BYTE / 2 - 1))
446 {
447 /*地址未对齐*/
448 return FL_FAIL;
449 }
450 FL_RCC_EnableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_DMA);
451 FL_DMA_Disable(DMA);
452 FL_RCC_EnableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
453 FL_RCC_EnableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
454 FL_FLASH_EnableProgram(FLASHx);
455 /* Key 序列*/
456 primask = __get_PRIMASK();
457 __disable_irq();
458 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_PROGRAM_KEY1);
459 FL_FLASH_UnlockFlash(FLASHx, FL_FLASH_PROGRAM_KEY2);
460 __set_PRIMASK(primask);
461 FL_FLASH_EnableProgram(FLASHx);
462 initStruct.circMode = FL_DISABLE;
463 initStruct.direction = FL_DMA_DIR_RAM_TO_FLASH;
464 initStruct.memoryAddressIncMode = FL_DMA_CH7_MEMORY_INC_MODE_INCREASE;
465 initStruct.flashAddressIncMode = FL_DMA_CH7_FLASH_INC_MODE_INCREASE;
466 initStruct.priority = FL_DMA_PRIORITY_HIGH;
467 FL_DMA_Init(DMA, &initStruct, FL_DMA_CHANNEL_7);
468 FL_DMA_WriteFlashAddress(DMA, address >> 2);
469 FL_DMA_WriteMemoryAddress(DMA, (uint32_t)data >> 2, FL_DMA_CHANNEL_7);
470 FL_DMA_WriteTransmissionSize(DMA, 64 - 1, FL_DMA_CHANNEL_7);
471 FL_DMA_ClearFlag_TransferComplete(DMA, FL_DMA_CHANNEL_7);
472 FL_DMA_EnableChannel(DMA, FL_DMA_CHANNEL_7);
473 FL_DMA_Enable(DMA);
474 timeout = 0;
475 while(1)
476 {
477 timeout++;
478 if(timeout > FL_FLASH_ERASE_TIMEOUT)
479 {
480 ret = FL_FAIL;
481 break;
482 }
483 if(FL_DMA_IsActiveFlag_TransferComplete(DMA, FL_DMA_CHANNEL_7) == FL_SET)
484 {
485 ret = FL_PASS;
486 break;
487 }
488 }
489 FL_DMA_Disable(DMA);
490 FL_FLASH_LockFlash(FLASHx);
491 FL_RCC_DisableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
492 FL_RCC_DisableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
493 return ret;
494 }
495
496 /**
497 * @brief DMA读取函数,编程地址必须对齐到halt-page.
498 * @param FLASHx 外设入口地址
499 * @param address 读取数据Flash地址
500 * @param *data 读出数据存储区
501 * @param length 读出数据的字长度
502 *
503 * @retval 错误状态,可能值:
504 * -FL_FAIL 读取发生错误
505 * -FL_PASS 读取成功
506 */
FL_FLASH_Read_Dma(FLASH_Type * FLASHx,uint32_t address,uint32_t * data,uint16_t length)507 FL_ErrorStatus FL_FLASH_Read_Dma(FLASH_Type *FLASHx, uint32_t address, uint32_t *data, uint16_t length)
508 {
509 FL_ErrorStatus ret;
510 uint32_t Timeout;
511 FL_DMA_InitTypeDef initStruct = {0};
512 /* 入口参数检查 */
513 assert_param(IS_FLASH_ALL_INSTANCE(FLASHx));
514 assert_param(IS_FL_FLASH_MAX_ADDR(address));
515 /* 半页对齐*/
516 if(address & (FL_FLASH_PAGE_SIZE_BYTE / 2 - 1))
517 {
518 /*地址未对齐*/
519 return FL_FAIL;
520 }
521 initStruct.circMode = FL_DISABLE;
522 initStruct.direction = FL_DMA_DIR_FLASH_TO_RAM;
523 initStruct.memoryAddressIncMode = FL_DMA_CH7_MEMORY_INC_MODE_INCREASE;
524 initStruct.flashAddressIncMode = FL_DMA_CH7_FLASH_INC_MODE_INCREASE;
525 initStruct.priority = FL_DMA_PRIORITY_HIGH;
526 FL_DMA_Init(DMA, &initStruct, FL_DMA_CHANNEL_7);
527 FL_DMA_WriteFlashAddress(DMA, address >> 2);
528 FL_DMA_WriteMemoryAddress(DMA, (uint32_t)data >> 2, FL_DMA_CHANNEL_7);
529 FL_DMA_WriteTransmissionSize(DMA, length - 1, FL_DMA_CHANNEL_7);
530 FL_DMA_ClearFlag_TransferComplete(DMA, FL_DMA_CHANNEL_7);
531 FL_DMA_EnableChannel(DMA, FL_DMA_CHANNEL_7);
532 FL_DMA_Enable(DMA);
533 Timeout = 0;
534 while(1)
535 {
536 Timeout++;
537 if(Timeout > FL_FLASH_ERASE_TIMEOUT)
538 {
539 ret = FL_FAIL;
540 break;
541 }
542 if(FL_DMA_IsActiveFlag_TransferComplete(DMA, FL_DMA_CHANNEL_7) == FL_SET)
543 {
544 ret = FL_PASS;
545 break;
546 }
547 }
548 return ret;
549 }
550
551 /**
552 * @}
553 */
554
555 #endif /* FL_FLASH_DRIVER_ENABLED */
556
557 /**
558 * @}
559 */
560
561 /**
562 * @}
563 */
564
565 /********************** (C) COPYRIGHT Fudan Microelectronics **** END OF FILE ***********************/
566