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