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