1 ////////////////////////////////////////////////////////////////////////////////
2 /// @file     hal_flash.c
3 /// @author   AE TEAM
4 /// @brief    THIS FILE PROVIDES ALL THE FLASH FIRMWARE FUNCTIONS.
5 ////////////////////////////////////////////////////////////////////////////////
6 /// @attention
7 ///
8 /// THE EXISTING FIRMWARE IS ONLY FOR REFERENCE, WHICH IS DESIGNED TO PROVIDE
9 /// CUSTOMERS WITH CODING INFORMATION ABOUT THEIR PRODUCTS SO THEY CAN SAVE
10 /// TIME. THEREFORE, MINDMOTION SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT OR
11 /// CONSEQUENTIAL DAMAGES ABOUT ANY CLAIMS ARISING OUT OF THE CONTENT OF SUCH
12 /// HARDWARE AND/OR THE USE OF THE CODING INFORMATION CONTAINED HEREIN IN
13 /// CONNECTION WITH PRODUCTS MADE BY CUSTOMERS.
14 ///
15 /// <H2><CENTER>&COPY; COPYRIGHT MINDMOTION </CENTER></H2>
16 ////////////////////////////////////////////////////////////////////////////////
17 
18 // Define to prevent recursive inclusion
19 #define _HAL_FLASH_C_
20 
21 // Files includes
22 #include "hal_flash.h"
23 
24 ////////////////////////////////////////////////////////////////////////////////
25 /// @addtogroup MM32_Hardware_Abstract_Layer
26 /// @{
27 
28 ////////////////////////////////////////////////////////////////////////////////
29 /// @addtogroup FLASH_HAL
30 /// @{
31 
32 ////////////////////////////////////////////////////////////////////////////////
33 /// @addtogroup FLASH_Exported_Functions
34 /// @{
35 
36 ////////////////////////////////////////////////////////////////////////////////
37 /// @brief  Sets the code latency value.
38 /// @note   This function can be used for all MM32 devices.
39 /// @param  latency: specifies the FLASH Latency value.
40 ///         This parameter can be one of the following values:
41 /// @arg    FLASH_Latency_0: FLASH Zero Latency cycle
42 /// @arg    FLASH_Latency_1: FLASH One Latency cycle
43 /// @arg    FLASH_Latency_2: FLASH Two Latency cycles
44 /// @arg    FLASH_Latency_3: FLASH Three Latency cycles
45 /// @retval None.
46 ////////////////////////////////////////////////////////////////////////////////
FLASH_SetLatency(FLASH_Latency_TypeDef latency)47 void FLASH_SetLatency(FLASH_Latency_TypeDef latency)
48 {
49     FLASH->ACR = (FLASH->ACR & (~FLASH_ACR_LATENCY)) | latency;
50 }
51 
52 ////////////////////////////////////////////////////////////////////////////////
53 /// @brief  Enables or disables the Half cycle flash access.
54 /// @note   This function can be used for all MM32 devices.
55 /// @param  half_cycle_access: specifies the FLASH Half cycle Access mode.
56 ///         This parameter can be one of the following values:
57 /// @arg    FLASH_HalfCycleAccess_Enable: FLASH Half Cycle Enable
58 /// @arg    FLASH_HalfCycleAccess_Disable: FLASH Half Cycle Disable
59 /// @retval None.
60 ////////////////////////////////////////////////////////////////////////////////
FLASH_HalfCycleAccessCmd(FLASH_HalfCycleAccess_TypeDef half_cycle_access)61 void FLASH_HalfCycleAccessCmd(FLASH_HalfCycleAccess_TypeDef half_cycle_access)
62 {
63     FLASH->ACR &= ~FLASH_ACR_HLFCYA;
64     FLASH->ACR |= half_cycle_access;
65 }
66 
67 ////////////////////////////////////////////////////////////////////////////////
68 /// @brief  Enables or disables the Prefetch Buffer.
69 /// @note   This function can be used for all MM32 devices.
70 /// @param  prefetch_buffer: specifies the Prefetch buffer status.
71 ///         This parameter can be one of the following values:
72 /// @arg    FLASH_PrefetchBuffer_Enable: FLASH Prefetch Buffer Enable
73 /// @arg    FLASH_PrefetchBuffer_Disable: FLASH Prefetch Buffer Disable
74 /// @retval None.
75 ////////////////////////////////////////////////////////////////////////////////
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_TypeDef prefetch_buffer)76 void FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_TypeDef prefetch_buffer)
77 {
78     FLASH->ACR &= ~FLASH_ACR_PRFTBE;
79     FLASH->ACR |= prefetch_buffer;
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// @brief  Locks the FLASH Program Erase Controller.
84 /// @note   This function can be used for all MM32 devices.
85 /// @param  None.
86 /// @retval None.
87 ////////////////////////////////////////////////////////////////////////////////
FLASH_Lock(void)88 void FLASH_Lock(void)
89 {
90     FLASH->CR |= FLASH_CR_LOCK;
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 /// @brief  Unlocks the FLASH Program Erase Controller.
95 /// @note   This function can be used for all MM32 devices.
96 /// @param  None.
97 /// @retval None.
98 ////////////////////////////////////////////////////////////////////////////////
FLASH_Unlock()99 void FLASH_Unlock()
100 {
101     FLASH->KEYR = FLASH_KEY1;
102     FLASH->KEYR = FLASH_KEY2;
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 /// @brief  Enable to program the FLASH Option Byte.
107 /// @note   This function can be used for all MM32 devices.
108 /// @param  None.
109 /// @retval None.
110 ////////////////////////////////////////////////////////////////////////////////
FLASH_OPTB_Enable(void)111 void FLASH_OPTB_Enable(void)
112 {
113     FLASH->OPTKEYR = FLASH_KEY1;
114     FLASH->OPTKEYR = FLASH_KEY2;
115 }
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 /// @brief  Erases a specified FLASH page.
119 /// @note   This function can be used for all MM32 devices.
120 /// @param  page_address: The page address to be erased.
121 /// @retval FLASH Status: The returned value can be: FLASH_BUSY,
122 ///         FLASH_ERROR_PG, FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
123 ////////////////////////////////////////////////////////////////////////////////
FLASH_ErasePage(u32 page_address)124 FLASH_Status FLASH_ErasePage(u32 page_address)
125 {
126     FLASH->CR |= FLASH_CR_PER;
127     FLASH->AR = page_address;
128     FLASH->CR |= FLASH_CR_STRT;
129     return FLASH_WaitForLastOperation(EraseTimeout);
130 }
131 
132 ////////////////////////////////////////////////////////////////////////////////
133 /// @brief  Erases all FLASH pages.
134 /// @note   This function can be used for all MM32 devices.
135 /// @param  None.
136 /// @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
137 ///         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
138 ////////////////////////////////////////////////////////////////////////////////
FLASH_EraseAllPages()139 FLASH_Status FLASH_EraseAllPages()
140 {
141     FLASH->AR = FLASH_BASE;
142     FLASH->CR |= (FLASH_CR_MER | FLASH_CR_STRT);
143     return FLASH_WaitForLastOperation(EraseTimeout);
144 }
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 /// @brief  Erases the FLASH option bytes.
148 /// @note   This function can be used for all MM32 devices.
149 /// @param  None.
150 /// @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
151 ///         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
152 ////////////////////////////////////////////////////////////////////////////////
FLASH_EraseOptionBytes()153 FLASH_Status FLASH_EraseOptionBytes()
154 {
155     FLASH_OPTB_Enable();
156     FLASH->AR = OB_BASE;
157     FLASH->CR |= (FLASH_CR_OPTER | FLASH_CR_STRT);
158     return FLASH_WaitForLastOperation(EraseTimeout);
159 }
160 ////////////////////////////////////////////////////////////////////////////////
161 /// @brief  Programs a half word at a specified address.
162 /// @note   This function can be used for all MM32 devices.
163 /// @param  address: specifies the address to be programmed.
164 /// @param  data: specifies the data to be programmed.
165 /// @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
166 ///         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
167 ////////////////////////////////////////////////////////////////////////////////
FLASH_ProgramHalfWord(u32 address,u16 data)168 FLASH_Status FLASH_ProgramHalfWord(u32 address, u16 data)
169 {
170     FLASH->CR |= FLASH_CR_PG;
171 
172     *(vu16*)address = data;
173 
174 
175     return FLASH_WaitForLastOperation(ProgramTimeout);
176 }
177 
178 ////////////////////////////////////////////////////////////////////////////////
179 /// @brief  Programs a word at a specified address.
180 /// @note   This function can be used for all MM32 devices.
181 /// @param  address: specifies the address to be programmed.
182 /// @param  data: specifies the data to be programmed.
183 /// @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
184 ///         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
185 ////////////////////////////////////////////////////////////////////////////////
FLASH_ProgramWord(u32 address,u32 data)186 FLASH_Status FLASH_ProgramWord(u32 address, u32 data)
187 {
188     FLASH_Status ret = FLASH_ProgramHalfWord(address, data);
189     if (ret == FLASH_COMPLETE) {
190         ret = FLASH_ProgramHalfWord(address + 2, data >> 16);
191     }
192     return ret;
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// @brief  Programs a byte at a specified Option Byte Data address.
197 /// @note   This function can be used for all MM32 devices.
198 /// @param  address: specifies the address to be programmed.
199 ///         This parameter can be 0x1FFFF804 or 0x1FFFF806.
200 /// @param  data: specifies the data to be programmed.
201 /// @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
202 ///         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
203 ////////////////////////////////////////////////////////////////////////////////
FLASH_ProgramOptionByteData(u32 address,u8 data)204 FLASH_Status FLASH_ProgramOptionByteData(u32 address, u8 data)
205 {
206     FLASH_Status ret;
207     __IO u16 temp;
208     FLASH_OPTB_Enable();
209     FLASH->CR |= FLASH_CR_OPTPG;
210     temp = (u16)(~data);
211     temp = (temp << 8) & 0xFF00;
212     temp = temp | (u16)data;
213     address = address & (~0x1);
214     *(vu16*)address = temp;
215     ret = FLASH_WaitForLastOperation(ProgramTimeout);
216 
217     return ret;
218 }
219 
220 ////////////////////////////////////////////////////////////////////////////////
221 /// @brief  Programs a half word at a specified Option Byte Data address.
222 /// @note   This function can be used for all MM32 devices.
223 /// @param  address: specifies the address to be programmed.
224 ///         This parameter can be 0x1FFFF804 or 0x1FFFF806.
225 /// @param  data: specifies the data to be programmed.
226 /// @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
227 ///         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
228 ////////////////////////////////////////////////////////////////////////////////
FLASH_ProgramOptionHalfWord(u32 address,u16 data)229 FLASH_Status FLASH_ProgramOptionHalfWord(u32 address, u16 data)
230 {
231     FLASH_Status ret;
232     FLASH_OPTB_Enable();
233     FLASH->CR |= FLASH_CR_OPTPG;
234     *(vu16*)address = data;
235     ret = FLASH_WaitForLastOperation(ProgramTimeout);
236 
237     return ret;
238 }
239 
240 ////////////////////////////////////////////////////////////////////////////////
241 /// @brief  Read protection for the specified address
242 /// @note   This function can be used for all MM32 devices.
243 /// @retval None.
244 ////////////////////////////////////////////////////////////////////////////////
FLASH_ProgramProtect(u32 address,u16 data)245 FLASH_Status FLASH_ProgramProtect(u32 address, u16 data)
246 {
247     return FLASH_ProgramOptionHalfWord(address, data);
248 
249 //    FLASH_Status ret;
250 //  ret = FLASH_ProgramOptionHalfWord(address, 0x7F80);
251 //
252 //  if (ret == FLASH_COMPLETE) {
253 //      ret = FLASH_ProgramOptionHalfWord(address + 2, 0xFF00);
254 //    }
255 //    return ret;
256 }
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 /// @brief  Write protection for the specified address
260 /// @note   This function can be used for all MM32 devices.
261 /// @param  page: specifies the address of the pages to be write
262 ///         protected.
263 ///         This parameter is (0x01 << ((Absolute address - 0x08000000)/0x1000))
264 /// @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
265 ///         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
266 ////////////////////////////////////////////////////////////////////////////////
FLASH_EnableWriteProtection(u32 page)267 FLASH_Status FLASH_EnableWriteProtection(u32 page)
268 {
269     FLASH_Status ret;
270     u8           i;
271     for (i = 0; i < 4; i++) {
272         ret = FLASH_ProgramOptionHalfWord((OB_BASE + 8 + i * 2), ~(page >> (i * 8)));
273         if (ret != FLASH_COMPLETE) {
274             break;
275         }
276     }
277     return ret;
278 }
279 
280 ////////////////////////////////////////////////////////////////////////////////
281 /// @brief  Programs the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY.
282 /// @note   This function can be used for all MM32 devices.
283 /// @param  ob_iwdg: Selects the IWDG mode
284 /// @param  ob_stop: Reset event when entering STOP mode.
285 /// @param  standby: Reset event when entering Standby mode.
286 /// @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
287 ///         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
288 ////////////////////////////////////////////////////////////////////////////////
FLASH_UserOptionByteConfig(OB_IWDG_TypeDef ob_iwdg,OB_STOP_TypeDef ob_stop,OB_STDBY_TypeDef standby)289 FLASH_Status FLASH_UserOptionByteConfig(OB_IWDG_TypeDef ob_iwdg, OB_STOP_TypeDef ob_stop, OB_STDBY_TypeDef standby)
290 {
291     FLASH_OPTB_Enable();
292     FLASH->CR |= FLASH_CR_OPTPG;
293     OB->USER = ob_iwdg;
294     OB->USER |= ob_stop;
295     OB->USER |= standby;
296     OB->USER |= 0xF8;
297     //    OB->USER = iwdg | stop | stdby | 0xF8;
298     return FLASH_WaitForLastOperation(ProgramTimeout);
299 }
300 
301 ////////////////////////////////////////////////////////////////////////////////
302 /// @brief  Returns the FLASH User Option Bytes values.
303 /// @note   This function can be used for all MM32 devices.
304 /// @param  None.
305 /// @retval The FLASH User Option Bytes values:IWDG_SW(Bit0), RST_STOP(Bit1)
306 ///         and RST_STDBY(Bit2).
307 ////////////////////////////////////////////////////////////////////////////////
FLASH_GetUserOptionByte()308 u32 FLASH_GetUserOptionByte()
309 {
310     return (FLASH->OBR >> 2);
311 }
312 
313 ////////////////////////////////////////////////////////////////////////////////
314 /// @brief  Returns the FLASH Write Protection Option Bytes Register value.
315 /// @note   This function can be used for all MM32 devices.
316 /// @param  None.
317 /// @retval The FLASH Write Protection  Option Bytes Register value.
318 ////////////////////////////////////////////////////////////////////////////////
FLASH_GetWriteProtectionOptionByte()319 u32 FLASH_GetWriteProtectionOptionByte()
320 {
321     return (FLASH->WRPR);
322 }
323 ////////////////////////////////////////////////////////////////////////////////
324 /// @brief  Checks whether the FLASH Prefetch Buffer status is set or not.
325 /// @note   This function can be used for all MM32 devices.
326 /// @param  None.
327 /// @retval FLASH Prefetch Buffer Status (SET or RESET).
328 ////////////////////////////////////////////////////////////////////////////////
FLASH_GetPrefetchBufferStatus(void)329 FlagStatus FLASH_GetPrefetchBufferStatus(void)
330 {
331     return (FLASH->ACR & FLASH_ACR_PRFTBS) ? SET : RESET;
332 }
333 ////////////////////////////////////////////////////////////////////////////////
334 /// @brief  Enables or disables the specified FLASH interrupts.
335 /// @note   This function can be used for all MM32 devices.
336 /// @param  interrupt: specifies the FLASH interrupt sources to be enabled or
337 ///         disabled.
338 /// @param  state: new state of the specified Flash interrupts.
339 ///         This parameter can be: ENABLE or DISABLE.
340 /// @retval None.
341 ////////////////////////////////////////////////////////////////////////////////
FLASH_ITConfig(FLASH_IT_TypeDef interrupt,FunctionalState state)342 void FLASH_ITConfig(FLASH_IT_TypeDef interrupt, FunctionalState state)
343 {
344     (state) ? (FLASH->CR |= interrupt) : (FLASH->CR &= ~interrupt);
345 }
346 
347 ////////////////////////////////////////////////////////////////////////////////
348 /// @brief  Checks whether the specified FLASH flag is set or not.
349 /// @note   This function can be used for all MM32 devices.
350 /// @param  flag: specifies the FLASH flags to clear.
351 ///         This parameter can be one of the following values:
352 /// @arg    FLASH_FLAG_BSY: FLASH Busy flag
353 /// @arg    FLASH_FLAG_PGERR: FLASH Program error flag
354 /// @arg    FLASH_FLAG_WRPRTERR: FLASH Write protected error flag
355 /// @arg    FLASH_FLAG_EOP: FLASH End of Operation flag
356 /// @arg    FLASH_FLAG_OPTERR:  FLASH Option Byte error flag
357 /// @retval The new state of FLASH_FLAG (SET or RESET).
358 ////////////////////////////////////////////////////////////////////////////////
FLASH_GetFlagStatus(u16 flag)359 FlagStatus FLASH_GetFlagStatus(u16 flag)
360 {
361     return ((flag == FLASH_FLAG_OPTERR) ? (FLASH->OBR & FLASH_FLAG_OPTERR) : (FLASH->SR & flag)) ? SET : RESET;
362 }
363 
364 ////////////////////////////////////////////////////////////////////////////////
365 /// @brief  Clears the FLASH's pending flags.
366 /// @note   This function can be used for all MM32 devices.
367 /// @param  flag: specifies the FLASH flags to clear.
368 ///         This parameter can be any combination of the following values:
369 /// @arg    FLASH_FLAG_PGERR: FLASH Program error flag
370 /// @arg    FLASH_FLAG_WRPRTERR: FLASH Write protected error flag
371 /// @arg    FLASH_FLAG_EOP: FLASH End of Operation flag
372 /// @retval None.
373 ////////////////////////////////////////////////////////////////////////////////
FLASH_ClearFlag(u16 flag)374 void FLASH_ClearFlag(u16 flag)
375 {
376     FLASH->SR = flag;
377 }
378 
379 ////////////////////////////////////////////////////////////////////////////////
380 /// @brief  Returns the FLASH Status.
381 /// @note   This function can be used for all MM32 devices.
382 /// @param  None.
383 /// @retval FLASH Status: The returned value can be: FLASH_BUSY,
384 ///         FLASH_ERROR_PG, FLASH_ERROR_WRP or FLASH_COMPLETE.
385 ////////////////////////////////////////////////////////////////////////////////
FLASH_GetStatus()386 FLASH_Status FLASH_GetStatus()
387 {
388     return (FLASH_Status)((FLASH->SR & FLASH_FLAG_BSY))
389            ? FLASH_BUSY
390            : ((FLASH->SR & FLASH_FLAG_PGERR) ? FLASH_ERROR_PG
391               : ((FLASH->SR & FLASH_FLAG_WRPRTERR) ? FLASH_ERROR_WRP : FLASH_COMPLETE));
392 }
393 
394 ////////////////////////////////////////////////////////////////////////////////
395 /// @brief  Waits for a Flash operation to complete or a TIMEOUT to occur.
396 /// @note   This function can be used for all MM32 devices
397 /// @param  time_out: FLASH programming time_out
398 /// @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
399 ///         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
400 ////////////////////////////////////////////////////////////////////////////////
FLASH_WaitForLastOperation(u32 time_out)401 FLASH_Status FLASH_WaitForLastOperation(u32 time_out)
402 {
403     u32          i;
404     FLASH_Status ret;
405     do {
406         ret = FLASH_GetStatus();
407         time_out--;
408         for (i = 0xFF; i != 0; i--)
409             ;
410     } while ((ret == FLASH_BUSY) && (time_out != 0x00));
411 
412     FLASH->CR = 0;
413     FLASH->SR = FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR;
414     return (FLASH_Status)((time_out == 0x00) ? FLASH_TIMEOUT : ret);
415 }
416 
417 ////////////////////////////////////////////////////////////////////////////////
418 /// @brief  Erases a specified FLASH page.
419 /// @note   This function can be used for all MM32 devices.
420 /// @param  Page_Address: The page address to be erased.
421 /// @retval None.
422 ////////////////////////////////////////////////////////////////////////////////
exFLASH_EraseEE(u32 page_address)423 void exFLASH_EraseEE(u32 page_address)
424 {
425     FLASH_Unlock();
426     FLASH_ErasePage(page_address);
427     FLASH_Lock();
428 }
429 
430 ////////////////////////////////////////////////////////////////////////////////
431 /// @brief  Programs a buffer at a specified address.
432 /// @note   This function can be used for all MM32 devices.
433 /// @param *buf: the pointer of the buffer to be programmed.
434 /// @param  addr: specifies the address to be programmed.
435 /// @param  len: the number of bytes in the buffer.
436 ///         This parameter can only be even.
437 /// @retval None.
438 ////////////////////////////////////////////////////////////////////////////////
exFLASH_ProgramEE(u16 * buf,u32 addr,u16 len)439 void exFLASH_ProgramEE(u16* buf, u32 addr, u16 len)
440 {
441     u16 i;
442     FLASH_Unlock();
443     for (i = 0; i < len / 2; i++) {
444         FLASH_ProgramHalfWord(addr, *buf);
445         addr += 2;
446         buf++;
447     }
448     FLASH_Lock();
449 }
450 
451 ////////////////////////////////////////////////////////////////////////////////
452 /// @brief  Determine if the data that at the ptr address with the length is len
453 ///         is empty.
454 /// @note   This function can be used for all MM32 devices.
455 /// @param *ptr: the pointer of the starting address.
456 /// @param  len: the number of bytes.
457 ///         This parameter can only be even.
458 /// @retval 1 presents the data is empty,
459 ///         0 presents the data has been written.
460 ////////////////////////////////////////////////////////////////////////////////
exFLASH_FindEmpty(u16 * ptr,u16 len)461 u8 exFLASH_FindEmpty(u16* ptr, u16 len)
462 {
463     u16 i;
464     for (i = 0; i < (len / 2); i++) {
465         if (*(ptr + i) != 0xffff)
466             return 0;
467     }
468     return 1;
469 }
470 
471 ////////////////////////////////////////////////////////////////////////////////
472 /// @brief  Locate the writable area on the specified address.
473 /// @note   This function can be used for all MM32 devices.
474 /// @param  page_address: specifies the beginning of the EEprom.
475 ///         The EEprom can be some continuously pages in the flash.
476 /// @param  len: the number of bytes to be written.
477 ///         This parameter can only be even.
478 /// @retval the pointer of the starting address.
479 ////////////////////////////////////////////////////////////////////////////////
exFLASH_Locate(u32 page_address,u16 len)480 void* exFLASH_Locate(u32 page_address, u16 len)
481 {
482     u16 i;
483     u16* ptr = (u16*)page_address;
484     for (i = 0; i < (0x0800 / len); i++) {
485         if (exFLASH_FindEmpty(ptr, len)) {
486             if (i == 0)
487                 return 0;
488             break;
489         }
490         ptr += len / 2;
491     }
492     return ptr;
493 }
494 
495 ////////////////////////////////////////////////////////////////////////////////
496 /// @brief  Programs a buffer at a specified address.
497 /// @note   This function can be used for all MM32 devices.
498 /// @param *buf: the pointer of the buffer to be programmed.
499 /// @param  page_address: specifies the beginning of the EEprom.
500 ///         The EEprom can be some continuously pages in the flash.
501 /// @param  len: the number of bytes in the buffer.
502 ///         This parameter can only be even.
503 /// @retval None.
504 ////////////////////////////////////////////////////////////////////////////////
exFLASH_WriteEE(u16 * buf,u32 page_address,u16 len)505 void exFLASH_WriteEE(u16* buf, u32 page_address, u16 len)
506 {
507     u16* ptr = exFLASH_Locate(page_address, len);
508     if (ptr == 0) {
509         exFLASH_EraseEE(page_address + 0x000);
510         exFLASH_EraseEE(page_address + 0x400);
511         exFLASH_ProgramEE(buf, page_address, len);
512     }
513     else {
514         if (ptr == (u16*)(page_address + ((0x0400 / len) - 1) * len)) {
515             exFLASH_EraseEE(page_address + 0x400);
516             exFLASH_ProgramEE(buf, (u32)ptr, len);
517         }
518         else if (ptr == (u16*)(page_address + 0x0800)) {
519             exFLASH_EraseEE(page_address + 0x000);
520             exFLASH_ProgramEE(buf, (u32)page_address, len);
521         }
522         else {
523             exFLASH_ProgramEE(buf, (u32)ptr, len);
524         }
525     }
526 }
527 
528 ////////////////////////////////////////////////////////////////////////////////
529 /// @brief  Read the beginning address of the last written data.
530 /// @note   This function can be used for all MM32 devices.
531 /// @param  page_address: specifies the beginning of the EEprom.
532 ///         The EEprom can be some continuously pages in the flash.
533 /// @param  len: the number of bytes have been written.
534 ///         This parameter can only be even.
535 /// @retval the beginning address of the last written data.
536 ///         0 presents that this is the first time to use this as EEprom.
537 ////////////////////////////////////////////////////////////////////////////////
exFLASH_ReadEE(u32 page_address,u16 len)538 void* exFLASH_ReadEE(u32 page_address, u16 len)
539 {
540     u16* ptr = exFLASH_Locate(page_address, len);
541     return (ptr == 0) ? 0 : (ptr - len / 2);
542 }
543 
544 /// @}
545 
546 /// @}
547 
548 /// @}
549