1 /******************************************************************************
2 *Copyright(C)2018, Huada Semiconductor Co.,Ltd All rights reserved.
3 *
4 * This software is owned and published by:
5 * Huada Semiconductor Co.,Ltd("HDSC").
6 *
7 * BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
8 * BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
9 *
10 * This software contains source code for use with HDSC
11 * components. This software is licensed by HDSC to be adapted only
12 * for use in systems utilizing HDSC components. HDSC shall not be
13 * responsible for misuse or illegal use of this software for devices not
14 * supported herein. HDSC is providing this software "AS IS" and will
15 * not be responsible for issues arising from incorrect user implementation
16 * of the software.
17 *
18 * Disclaimer:
19 * HDSC MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
20 * REGARDING THE SOFTWARE (INCLUDING ANY ACOOMPANYING WRITTEN MATERIALS),
21 * ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING,
22 * WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED
23 * WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED
24 * WARRANTY OF NONINFRINGEMENT.
25 * HDSC SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT,
26 * NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT
27 * LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
28 * LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR
29 * INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA,
31 * SAVINGS OR PROFITS,
32 * EVEN IF Disclaimer HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33 * YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
34 * INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED
35 * FROM, THE SOFTWARE.
36 *
37 * This software may be replicated in part or whole for the licensed use,
38 * with the restriction that this Disclaimer and Copyright notice must be
39 * included with each copy of this software, whether used in part or whole,
40 * at all times.
41 */
42
43 /** \file flash.c
44 **
45 ** Common API of flash.
46 ** @link flashGroup Some description @endlink
47 **
48 ** - 2018-05-08
49 **
50 ******************************************************************************/
51
52 /*******************************************************************************
53 * Include files
54 ******************************************************************************/
55 #include "hc32l196_flash.h"
56 /**
57 *******************************************************************************
58 ** \addtogroup FlashGroup
59 ******************************************************************************/
60 //@{
61
62 /*******************************************************************************
63 * Local pre-processor symbols/macros ('#define')
64 ******************************************************************************/
65 #define FLASH_END_ADDR (0x0003FFFFu)
66 #define FLASH_BYPASS() M0P_FLASH->BYPASS = 0x5A5A;\
67 M0P_FLASH->BYPASS = 0xA5A5;
68 #define FLASH_IE_TRUE (0x03)
69 #define FLASH_IE_FALSE (0x00)
70
71 #define FLASH_TIMEOUT_INIT (0xFFFFFFu)
72 #define FLASH_TIMEOUT_PGM (0xFFFFFFu)
73 #define FLASH_TIMEOUT_ERASE (0xFFFFFFu)
74
75 #define FLASH_LOCK_ALL (0u)
76 #define FLASH_UNLOCK_ALL (0xFFFFFFFFu)
77 /*******************************************************************************
78 * Global variable definitions (declared in header file with 'extern')
79 ******************************************************************************/
80
81 /*******************************************************************************
82 * Local type definitions ('typedef')
83 ******************************************************************************/
84 /**
85 ******************************************************************************
86 ** \brief FLASH OP
87 **
88 ** Flash 操作控制数据类型重定义
89 ******************************************************************************/
90 typedef enum en_flash_op
91 {
92 Read = 0u, ///<读配置值
93 Program = 1u, ///<编程配置值
94 SectorErase = 2u, ///<扇区擦除配置值
95 ChipErase = 3u, ///<全片擦除配置值
96 } en_flash_op_t;
97
98 /**
99 ******************************************************************************
100 ** \brief FLASH 编程时间参数配置
101 **
102 ** FLASH编程时间参数配置数组定义 (4MHz)
103 ******************************************************************************/
104 const uint32_t pu32PcgTimer4M[] = {
105 0x20u, //Tnvs
106 0x17u, //Tpgs
107 0x1Bu, //Tprog
108 0x4650u, //Tserase
109 0x222E0u, //Tmerase
110 0x18u, //Tprcv
111 0xF0u, //Tsrcv
112 0x3E8u //Tmrcv
113 };
114 /*******************************************************************************
115 * Local variable definitions ('static')
116 ******************************************************************************/
117
118 /*******************************************************************************
119 * Local function prototypes ('static')
120 ******************************************************************************/
121
122 /*******************************************************************************
123 * Function implementation - global ('extern') and local ('static')
124 ******************************************************************************/
125
126 /**
127 *****************************************************************************
128 ** \brief Flash中断标志获取
129 **
130 **
131 ** \param [in] enFlashIntType Flash中断类型
132 **
133 ** \retval TRUE or FALSE
134 *****************************************************************************/
Flash_GetIntFlag(en_flash_int_type_t enFlashIntType)135 boolean_t Flash_GetIntFlag(en_flash_int_type_t enFlashIntType)
136 {
137 boolean_t bRetVal = FALSE;
138
139 if(M0P_FLASH->IFR & enFlashIntType)
140 {
141 bRetVal = TRUE;
142 }
143
144 return bRetVal;
145 }
146
147 /**
148 *****************************************************************************
149 ** \brief Flash中断标志清除
150 **
151 **
152 ** \param [in] enFlashIntType Flash中断类型
153 **
154 ** \retval Ok or Error
155 *****************************************************************************/
Flash_ClearIntFlag(en_flash_int_type_t enFlashIntType)156 en_result_t Flash_ClearIntFlag(en_flash_int_type_t enFlashIntType)
157 {
158 en_result_t enResult = Error;
159
160 M0P_FLASH->ICLR &= ~(uint32_t)enFlashIntType;
161 enResult = Ok;
162
163 return enResult;
164 }
165
166 /**
167 *****************************************************************************
168 ** \brief Flash中断使能
169 **
170 **
171 ** \param [in] enFlashIntType Flash中断类型
172 **
173 ** \retval Ok or Error
174 *****************************************************************************/
Flash_EnableIrq(en_flash_int_type_t enFlashIntType)175 en_result_t Flash_EnableIrq (en_flash_int_type_t enFlashIntType)
176 {
177 en_result_t enResult = Error;
178
179 FLASH_BYPASS();
180 M0P_FLASH->CR_f.IE |= enFlashIntType;
181
182 enResult = Ok;
183
184 return enResult;
185 }
186
187 /**
188 *****************************************************************************
189 ** \brief Flash中断禁止
190 **
191 **
192 ** \param [in] enFlashIntType Flash中断类型
193 **
194 ** \retval Ok or Error
195 *****************************************************************************/
Flash_DisableIrq(en_flash_int_type_t enFlashIntType)196 en_result_t Flash_DisableIrq(en_flash_int_type_t enFlashIntType)
197 {
198 en_result_t enResult = Error;
199
200 FLASH_BYPASS();
201 M0P_FLASH->CR_f.IE &= ~(uint32_t)enFlashIntType;
202
203 enResult = Ok;
204
205 return enResult;
206 }
207
208 /**
209 *****************************************************************************
210 ** \brief FLASH 初始化函数——中断服务程序、编程时间配置及低功耗模式
211 **
212 ** 该函数用于配置中断服务函数、低功耗模式、根据系统时钟配置FLASH编程时间相关寄存器.
213 **
214 ** \param [in] u8FreqCfg FLASH编程时钟频率配置(根据HCLK的频率选择配置值):
215 ** 1 - 4MHz;
216 ** 2 - 8MHz;
217 ** 4 - 16MHz;
218 ** 6 - 24MHz;
219 ** 8 - 32MHz;
220 ** 12 - 48MHz;
221 ** other - 无效值
222 ** \param [in] bDpstbEn TRUE - 当系统进入DeepSleep模式,FLASH进入低功耗模式;
223 ** FALSE - 当系统进入DeepSleep模式,FLASH不进入低功耗模式;
224 **
225 ** \retval Ok 操作成功.
226 ** \retval ErrorInvalidParameter 参数无效.
227 ** \retval ErrorUninitialized 初始化失败。
228 *****************************************************************************/
Flash_Init(uint8_t u8FreqCfg,boolean_t bDpstbEn)229 en_result_t Flash_Init(uint8_t u8FreqCfg, boolean_t bDpstbEn)
230 {
231 uint32_t u32Index = 0;
232 volatile uint32_t u32TimeOut = FLASH_TIMEOUT_INIT;
233 en_result_t enResult = Ok;
234 uint32_t u32PrgTimer[8] = {0};
235 volatile uint32_t *pu32PrgTimerReg = (volatile uint32_t*)M0P_FLASH;
236
237 if ((1 != u8FreqCfg) && (2 != u8FreqCfg) &&
238 (4 != u8FreqCfg) && (6 != u8FreqCfg) &&
239 (8 != u8FreqCfg) && (12 != u8FreqCfg))
240 {
241 enResult = ErrorInvalidParameter;
242 return (enResult);
243 }
244
245 M0P_FLASH->CR_f.DPSTB_EN = bDpstbEn;
246
247 //flash时间参数配置值计算
248 for(u32Index=0; u32Index<8; u32Index++)
249 {
250 u32PrgTimer[u32Index] = u8FreqCfg * pu32PcgTimer4M[u32Index];
251 }
252
253 //flash时间参数寄存器配置
254 for(u32Index=0; u32Index<8; u32Index++)
255 {
256 u32TimeOut = FLASH_TIMEOUT_INIT;
257 while(pu32PrgTimerReg[u32Index] != u32PrgTimer[u32Index])
258 {
259 if(u32TimeOut--)
260 {
261 FLASH_BYPASS();
262 pu32PrgTimerReg[u32Index] = u32PrgTimer[u32Index];
263 }
264 else
265 {
266 return ErrorUninitialized;
267 }
268 }
269 }
270
271 return (enResult);
272 }
273
274 /**
275 *****************************************************************************
276 ** \brief FLASH 字节写
277 **
278 ** 用于向FLASH写入1字节数据.
279 **
280 ** \param [in] u32Addr Flash地址
281 ** \param [in] u8Data 1字节数据
282 **
283 ** \retval Ok 写入成功.
284 ** \retval ErrorInvalidParameter FLASH地址无效
285 ** \retval ErrorTimeout 操作超时
286 *****************************************************************************/
Flash_WriteByte(uint32_t u32Addr,uint8_t u8Data)287 en_result_t Flash_WriteByte(uint32_t u32Addr, uint8_t u8Data)
288 {
289 en_result_t enResult = Ok;
290 volatile uint32_t u32TimeOut = FLASH_TIMEOUT_PGM;
291
292 if (FLASH_END_ADDR < u32Addr)
293 {
294 enResult = ErrorInvalidParameter;
295 return (enResult);
296 }
297
298 //busy?
299 u32TimeOut = FLASH_TIMEOUT_PGM;
300 while (TRUE == M0P_FLASH->CR_f.BUSY)
301 {
302 if(0 == u32TimeOut--)
303 {
304 return ErrorTimeout;
305 }
306 }
307
308 //set OP
309 u32TimeOut = FLASH_TIMEOUT_PGM;
310 while(Program != M0P_FLASH->CR_f.OP)
311 {
312 if(u32TimeOut--)
313 {
314 FLASH_BYPASS();
315 M0P_FLASH->CR_f.OP = Program;
316 }
317 else
318 {
319 return ErrorTimeout;
320 }
321 }
322
323 //Flash 解锁
324 Flash_UnlockAll();
325
326 //write data
327 *((volatile uint8_t*)u32Addr) = u8Data;
328
329 //busy?
330 u32TimeOut = FLASH_TIMEOUT_PGM;
331 while (TRUE == M0P_FLASH->CR_f.BUSY)
332 {
333 if(0 == u32TimeOut--)
334 {
335 return ErrorTimeout;
336 }
337 }
338
339 //Flash 加锁
340 Flash_LockAll();
341
342 return (enResult);
343 }
344
345 /**
346 *****************************************************************************
347 ** \brief FLASH 半字写
348 **
349 ** 用于向FLASH写入半字(2字节)数据.
350 **
351 ** \param [in] u32Addr Flash地址
352 ** \param [in] u16Data 半字(2字节)数据
353 **
354 ** \retval Ok 写入成功.
355 ** \retval ErrorInvalidParameter FLASH地址无效
356 ** \retval ErrorTimeout 操作超时
357 *****************************************************************************/
Flash_WriteHalfWord(uint32_t u32Addr,uint16_t u16Data)358 en_result_t Flash_WriteHalfWord(uint32_t u32Addr, uint16_t u16Data)
359 {
360 en_result_t enResult = Ok;
361 volatile uint32_t u32TimeOut = FLASH_TIMEOUT_PGM;
362
363 if (FLASH_END_ADDR < u32Addr)
364 {
365 enResult = ErrorInvalidParameter;
366 return (enResult);
367 }
368
369 //busy?
370 u32TimeOut = FLASH_TIMEOUT_PGM;
371 while (TRUE == M0P_FLASH->CR_f.BUSY)
372 {
373 if(0 == u32TimeOut--)
374 {
375 return ErrorTimeout;
376 }
377 }
378
379 //set OP
380 u32TimeOut = FLASH_TIMEOUT_PGM;
381 while(Program != M0P_FLASH->CR_f.OP)
382 {
383 if(u32TimeOut--)
384 {
385 FLASH_BYPASS();
386 M0P_FLASH->CR_f.OP = Program;
387 }
388 else
389 {
390 return ErrorTimeout;
391 }
392 }
393
394 //Flash 解锁
395 Flash_UnlockAll();
396
397 //write data
398 *((volatile uint16_t*)u32Addr) = u16Data;
399
400 //busy?
401 u32TimeOut = FLASH_TIMEOUT_PGM;
402 while (TRUE == M0P_FLASH->CR_f.BUSY)
403 {
404 if(0 == u32TimeOut--)
405 {
406 return ErrorTimeout;
407 }
408 }
409
410 //Flash 加锁
411 Flash_LockAll();
412
413 return (enResult);
414 }
415
416 /**
417 *****************************************************************************
418 ** \brief FLASH 字写
419 **
420 ** 用于向FLASH写入1个字的数据.
421 **
422 ** \param [in] u32Addr Flash地址
423 ** \param [in] u32Data 1个字数据
424 **
425 ** \retval Ok 写入成功.
426 ** \retval ErrorInvalidParameter FLASH地址无效
427 ** \retval ErrorTimeout 操作超时
428 *****************************************************************************/
Flash_WriteWord(uint32_t u32Addr,uint32_t u32Data)429 en_result_t Flash_WriteWord(uint32_t u32Addr, uint32_t u32Data)
430 {
431 en_result_t enResult = Ok;
432 volatile uint32_t u32TimeOut = FLASH_TIMEOUT_PGM;
433
434 if (FLASH_END_ADDR < u32Addr)
435 {
436 enResult = ErrorInvalidParameter;
437 return (enResult);
438 }
439
440 //busy?
441 u32TimeOut = FLASH_TIMEOUT_PGM;
442 while (TRUE == M0P_FLASH->CR_f.BUSY)
443 {
444 if(0 == u32TimeOut--)
445 {
446 return ErrorTimeout;
447 }
448 }
449
450 //Flash 解锁
451 Flash_UnlockAll();
452
453 //set OP
454 u32TimeOut = FLASH_TIMEOUT_PGM;
455 while(Program != M0P_FLASH->CR_f.OP)
456 {
457 if(u32TimeOut--)
458 {
459 FLASH_BYPASS();
460 M0P_FLASH->CR_f.OP = Program;
461 }
462 else
463 {
464 return ErrorTimeout;
465 }
466 }
467
468 //write data
469 *((volatile uint32_t*)u32Addr) = u32Data;
470
471 //busy?
472 u32TimeOut = FLASH_TIMEOUT_PGM;
473 while (TRUE == M0P_FLASH->CR_f.BUSY)
474 {
475 if(0 == u32TimeOut--)
476 {
477 return ErrorTimeout;
478 }
479 }
480
481 //Flash 加锁
482 Flash_LockAll();
483
484 return (enResult);
485 }
486
487 /**
488 *****************************************************************************
489 ** \brief FLASH 扇区擦除
490 **
491 ** FLASH 扇区擦除.
492 **
493 ** \param [in] u32SectorAddr 所擦除扇区内的地址
494 **
495 ** \retval Ok 擦除成功.
496 ** \retval ErrorInvalidParameter FLASH地址无效
497 ** \retval ErrorTimeout 操作超时
498 *****************************************************************************/
Flash_SectorErase(uint32_t u32SectorAddr)499 en_result_t Flash_SectorErase(uint32_t u32SectorAddr)
500 {
501 en_result_t enResult = Ok;
502 volatile uint32_t u32TimeOut = FLASH_TIMEOUT_ERASE;
503
504 if (FLASH_END_ADDR < u32SectorAddr)
505 {
506 enResult = ErrorInvalidParameter;
507 return (enResult);
508 }
509
510 //busy?
511 u32TimeOut = FLASH_TIMEOUT_ERASE;
512 while (TRUE == M0P_FLASH->CR_f.BUSY)
513 {
514 if(0 == u32TimeOut--)
515 {
516 return ErrorTimeout;
517 }
518 }
519
520 //Flash 解锁
521 Flash_UnlockAll();
522
523 //set OP
524 u32TimeOut = FLASH_TIMEOUT_ERASE;
525 while(SectorErase != M0P_FLASH->CR_f.OP)
526 {
527 if(u32TimeOut--)
528 {
529 FLASH_BYPASS();
530 M0P_FLASH->CR_f.OP = SectorErase;
531 }
532 else
533 {
534 return ErrorTimeout;
535 }
536 }
537
538 //write data
539 *((volatile uint8_t*)u32SectorAddr) = 0;
540
541 //busy?
542 u32TimeOut = FLASH_TIMEOUT_ERASE;
543 while (TRUE == M0P_FLASH->CR_f.BUSY)
544 {
545 if(0 == u32TimeOut--)
546 {
547 return ErrorTimeout;
548 }
549 }
550
551 //Flash 加锁
552 Flash_LockAll();
553
554 return (enResult);
555 }
556
557 /**
558 *****************************************************************************
559 ** \brief FLASH 全片擦除(该函数仅限RAM中运行!!!)
560 **
561 ** FLASH 全片擦除.
562 **
563 **
564 ** \retval Ok 擦除成功.
565 ** \retval ErrorTimeout 操作超时
566 **
567 *****************************************************************************/
Flash_ChipErase(void)568 en_result_t Flash_ChipErase(void)
569 {
570 en_result_t enResult = Ok;
571 volatile uint32_t u32TimeOut = FLASH_TIMEOUT_ERASE;
572
573 //busy?
574 u32TimeOut = FLASH_TIMEOUT_ERASE;
575 while (TRUE == M0P_FLASH->CR_f.BUSY)
576 {
577 if(0 == u32TimeOut--)
578 {
579 return ErrorTimeout;
580 }
581 }
582
583 //set OP
584 u32TimeOut = FLASH_TIMEOUT_ERASE;
585 while(ChipErase != M0P_FLASH->CR_f.OP)
586 {
587 if(u32TimeOut--)
588 {
589 FLASH_BYPASS();
590 M0P_FLASH->CR_f.OP = ChipErase;
591 }
592 else
593 {
594 return ErrorTimeout;
595 }
596 }
597
598 //Flash 解锁
599 Flash_UnlockAll();
600
601 //write data
602 *((volatile uint8_t*)0) = 0;
603
604 //busy?
605 u32TimeOut = FLASH_TIMEOUT_ERASE;
606 while (TRUE == M0P_FLASH->CR_f.BUSY)
607 {
608 if(0 == u32TimeOut--)
609 {
610 return ErrorTimeout;
611 }
612 }
613
614 //Flash 加锁
615 Flash_LockAll();
616
617 return (enResult);
618 }
619
620 /**
621 *****************************************************************************
622 ** \brief FLASH 编程保护加锁
623 **
624 **
625 ** \retval Null
626 *****************************************************************************/
Flash_LockAll(void)627 void Flash_LockAll(void)
628 {
629 FLASH_BYPASS();
630 M0P_FLASH->SLOCK0 = FLASH_LOCK_ALL;
631 FLASH_BYPASS();
632 M0P_FLASH->SLOCK1 = FLASH_LOCK_ALL;
633 FLASH_BYPASS();
634 M0P_FLASH->SLOCK2 = FLASH_LOCK_ALL;
635 FLASH_BYPASS();
636 M0P_FLASH->SLOCK3 = FLASH_LOCK_ALL;
637
638 }
639
640 /**
641 *****************************************************************************
642 ** \brief FLASH 编程保护解锁
643 **
644 **
645 ** \retval Null
646 *****************************************************************************/
Flash_UnlockAll(void)647 void Flash_UnlockAll(void)
648 {
649
650 FLASH_BYPASS();
651 M0P_FLASH->SLOCK0 = FLASH_UNLOCK_ALL;
652 FLASH_BYPASS();
653 M0P_FLASH->SLOCK1 = FLASH_UNLOCK_ALL;
654 FLASH_BYPASS();
655 M0P_FLASH->SLOCK2 = FLASH_UNLOCK_ALL;
656 FLASH_BYPASS();
657 M0P_FLASH->SLOCK3 = FLASH_UNLOCK_ALL;
658
659 }
660
661 /**
662 *****************************************************************************
663 ** \brief FLASH 读等待周期设置
664 **
665 ** \param [in] enWaitCycle 插入FLASH读等待周期数枚举类型
666 **
667 ** \retval Ok 解锁成功
668 ** \retval ErrorInvalidParameter 参数错误
669 *****************************************************************************/
Flash_WaitCycle(en_flash_waitcycle_t enWaitCycle)670 en_result_t Flash_WaitCycle(en_flash_waitcycle_t enWaitCycle)
671 {
672 en_result_t enResult = Ok;
673
674 FLASH_BYPASS();
675 M0P_FLASH->CR_f.WAIT = enWaitCycle;
676
677 return enResult;
678 }
679
680 /**
681 *****************************************************************************
682 ** \brief FLASH LOCK 设置
683 **
684 ** \param [in] enLock @ref en_flash_lock_t
685 ** \param [in] u32LockValue 32bits,对应bit=0:加锁,对应Sector不允许擦写;对应bit=1:解锁。
686 ** \note 加解锁范围Sector:[enLock*128 + i*4, enLock*128 + i*4+3]
687 ** (i表示u32LockValue的bit位置,0~31)
688 ** 例如:enLock = FlashLock1, u32LockValue = 0x00000002,
689 ** 则加解锁范围为:[Sector128,Sector131]
690 ** \retval Ok 解锁成功
691 ** \retval ErrorInvalidParameter 参数错误
692 *****************************************************************************/
Flash_LockSet(en_flash_lock_t enLock,uint32_t u32LockValue)693 en_result_t Flash_LockSet(en_flash_lock_t enLock, uint32_t u32LockValue)
694 {
695 FLASH_BYPASS();
696 *((&M0P_FLASH->SLOCK0) + enLock) = u32LockValue;
697
698 return Ok;
699 }
700 //@} // FlashGroup
701
702 /*******************************************************************************
703 * EOF (not truncated)
704 ******************************************************************************/
705