1 /*
2  * SPDX-FileCopyrightText: 2016 STMicroelectronics
3  * SPDX-FileCopyrightText: 2019-2025 SiFli Technologies(Nanjing) Co., Ltd
4  *
5  * SPDX-License-Identifier: BSD-3-Clause AND Apache-2.0
6  */
7 
8 #include "bf0_hal.h"
9 #include "bf0_hal_pinmux.h"
10 /** @addtogroup BF0_HAL_Driver
11   * @{
12   */
13 
14 /** @defgroup HAL_COMMON Hal Common functions
15   * @brief HAL module driver
16   * @{
17   */
18 
19 #if defined(HAL_MODULE_ENABLED)||defined(_SIFLI_DOXYGEN_)
20 
21 /* Private typedef -----------------------------------------------------------*/
22 /* Private define ------------------------------------------------------------*/
23 
24 #if defined(VREFBUF)
25     #define VREFBUF_TIMEOUT_VALUE     10U   /* 10 ms (to be confirmed) */
26 #endif /* VREFBUF */
27 
28 /* ------------ SYSCFG registers bit address in the alias region ------------ */
29 #define SYSCFG_OFFSET             (SYSCFG_BASE - PERIPH_BASE)
30 /* ---  MEMRMP Register ---*/
31 /* Alias word address of FB_MODE bit */
32 #define MEMRMP_OFFSET             SYSCFG_OFFSET
33 #define FB_MODE_BitNumber         8U
34 #define FB_MODE_BB                (PERIPH_BB_BASE + (MEMRMP_OFFSET * 32U) + (FB_MODE_BitNumber * 4U))
35 
36 /* --- SCSR Register ---*/
37 /* Alias word address of SRAM2ER bit */
38 #define SCSR_OFFSET               (SYSCFG_OFFSET + 0x18U)
39 #define BRER_BitNumber            0U
40 #define SCSR_SRAM2ER_BB           (PERIPH_BB_BASE + (SCSR_OFFSET * 32U) + (BRER_BitNumber * 4U))
41 
42 /* Private macro -------------------------------------------------------------*/
43 /* Private variables ---------------------------------------------------------*/
44 /* Private function prototypes -----------------------------------------------*/
45 
46 /* Exported variables --------------------------------------------------------*/
47 
48 #if defined(__CC_ARM) || defined(__CLANG_ARM)
49 #elif defined(__GNUC__)
50     /* workaround large bin size produced by arm-none-eabi-gcc xpack version
51     * see https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/discussions/23
52     */
__aeabi_unwind_cpp_pr0(void)53     __WEAK int __aeabi_unwind_cpp_pr0(void) { return 0; }
__aeabi_unwind_cpp_pr1(void)54     __WEAK int __aeabi_unwind_cpp_pr1(void) { return 0; }
__aeabi_unwind_cpp_pr2(void)55     __WEAK int __aeabi_unwind_cpp_pr2(void) { return 0; }
56 #endif
57 
58 /** @defgroup HAL_Exported_Variables HAL Exported Variables
59   * @{
60   */
61 __IO uint32_t uwTick;
62 /**
63   * @} HAL_Exported_Variables
64   */
65 
66 /* Exported functions --------------------------------------------------------*/
67 
68 /** @defgroup HAL_Exported_Functions HAL Exported Functions
69   * @{
70   */
71 
72 /** @defgroup HAL_Exported_Functions_Group1 Initialization and de-initialization Functions
73  *  @brief    Initialization and de-initialization functions
74  *
75 @verbatim
76  ===============================================================================
77               ##### Initialization and de-initialization functions #####
78  ===============================================================================
79     [..]  This section provides functions allowing to:
80       (+) Initialize the Flash interface the NVIC allocation and initial time base
81           clock configuration.
82       (+) De-initialize common part of the HAL.
83       (+) Configure the time base source to have 1ms time base with a dedicated
84           Tick interrupt priority.
85         (++) SysTick timer is used by default as source of time base, but user
86              can eventually implement his proper time base source (a general purpose
87              timer for example or other time source), keeping in mind that Time base
88              duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
89              handled in milliseconds basis.
90         (++) Time base configuration function (HAL_InitTick ()) is called automatically
91              at the beginning of the program after reset by HAL_Init() or at any time
92              when clock is configured, by HAL_RCC_ClockConfig().
93         (++) Source of time base is configured  to generate interrupts at regular
94              time intervals. Care must be taken if HAL_Delay() is called from a
95              peripheral ISR process, the Tick interrupt line must have higher priority
96             (numerically lower) than the peripheral interrupt. Otherwise the caller
97             ISR process will be blocked.
98        (++) functions affecting time base configurations are declared as __weak
99              to make  override possible  in case of other  implementations in user file.
100 @endverbatim
101   * @{
102   */
103 
104 /**
105   * @brief  Configure the Flash prefetch, the Instruction and Data caches,
106   *         the time base source, NVIC and any required global low level hardware
107   *         by calling the HAL_PreInit() weak function to be optionally defined in user file
108   *
109   * @note   HAL_Init() function is called at the beginning of program after reset and before
110   *         the clock configuration.
111   *
112   * @note   In the default implementation the System Timer (Systick) is used as source of time base.
113   *         The Systick configuration is based on MSI clock, as MSI is the clock
114   *         used after a system Reset and the NVIC configuration is set to Priority group 4.
115   *         Once done, time base tick starts incrementing: the tick variable counter is incremented
116   *         each 1ms in the SysTick_Handler() interrupt handler.
117   *
118   * @retval HAL status
119   */
HAL_Init(void)120 HAL_StatusTypeDef HAL_Init(void)
121 {
122     HAL_StatusTypeDef  status = HAL_OK;
123 
124     /* Configure Flash prefetch, Instruction cache, Data cache */
125     /* Default configuration at reset is:                      */
126     /* - Prefetch disabled                                     */
127     /* - Instruction cache enabled                             */
128     /* - Data cache enabled                                    */
129 #if (INSTRUCTION_CACHE_ENABLE == 0)
130 //   __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
131 #endif /* INSTRUCTION_CACHE_ENABLE */
132 
133 #if (DATA_CACHE_ENABLE == 0)
134 //   __HAL_FLASH_DATA_CACHE_DISABLE();
135 #endif /* DATA_CACHE_ENABLE */
136 
137 #if (PREFETCH_ENABLE != 0)
138     __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
139 #endif /* PREFETCH_ENABLE */
140 
141 #if defined(HAL_V2D_GPU_MODULE_ENABLED)
142     HAL_RCC_ResetModule(RCC_MOD_GPU);
143 #endif
144 
145     HAL_PreInit();
146 
147 #ifdef SOC_BF0_HCPU
148     if (PM_STANDBY_BOOT != SystemPowerOnModeGet())
149     {
150 //TODO: 52x also needs RC48
151 //#ifndef SF32LB52X
152         // Except Standby mode, all other boot mode need to re-calibrate RC48
153         status = HAL_RCC_CalibrateRC48();
154 #ifndef TARMAC
155         HAL_ASSERT(HAL_OK == status);
156 #endif
157 //#endif /* SF32LB52X */
158     }
159 #endif /* SOC_BF0_HCPU */
160 
161     HAL_PostMspInit();
162     HAL_RCC_Init();
163 
164 #ifdef SOC_BF0_HCPU
165     if (PM_STANDBY_BOOT != SystemPowerOnModeGet())
166     {
167         HAL_PMU_Init();
168     }
169 #endif /* SOC_BF0_HCPU */
170 
171 #ifdef HAL_ADC_MODULE_ENABLED
172     HAL_ADC_HwInit(PM_STANDBY_BOOT != SystemPowerOnModeGet());
173 #endif /* HAL_ADC_MODULE_ENABLED */
174 
175     /* Set Interrupt Group Priority */
176     HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
177 
178 #ifndef NONE_HAL_TICK_INIT
179     /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
180     if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
181     {
182         status = HAL_ERROR;
183     }
184     else
185 #endif
186     {
187 #ifdef SOC_BF0_HCPU
188         /* init AES_ACC as normal mode */
189         __HAL_SYSCFG_CLEAR_SECURITY();
190         HAL_EFUSE_Init();
191 #endif
192     }
193 
194     /* Return function status */
195     return status;
196 }
197 
198 /**
199   * @brief De-initialize common part of the HAL and stop the source of time base.
200   * @note This function is optional.
201   * @retval HAL status
202   */
HAL_DeInit(void)203 HAL_StatusTypeDef HAL_DeInit(void)
204 {
205 
206 #if 0
207     /* Reset of all peripherals */
208     __HAL_RCC_APB1_FORCE_RESET();
209     __HAL_RCC_APB1_RELEASE_RESET();
210 
211     __HAL_RCC_APB2_FORCE_RESET();
212     __HAL_RCC_APB2_RELEASE_RESET();
213 
214     __HAL_RCC_AHB1_FORCE_RESET();
215     __HAL_RCC_AHB1_RELEASE_RESET();
216 
217     __HAL_RCC_AHB2_FORCE_RESET();
218     __HAL_RCC_AHB2_RELEASE_RESET();
219 
220     __HAL_RCC_AHB3_FORCE_RESET();
221     __HAL_RCC_AHB3_RELEASE_RESET();
222 #endif
223     /* De-Init the low level hardware */
224     HAL_MspDeInit();
225 
226     /* Return function status */
227     return HAL_OK;
228 }
229 
230 /**
231   * @brief  Before HAL_Init is called, board specific initialization.
232   * @retval None
233   */
HAL_PreInit(void)234 __weak void HAL_PreInit(void)
235 {
236     /* NOTE : This function should not be modified, when the callback is needed,
237               the HAL_PreInit could be implemented in the board specific file
238      */
239 }
240 
241 /**
242   * @brief  It's called after HAL_PreInit.
243   * @retval None
244   */
245 
HAL_PostMspInit(void)246 __weak void HAL_PostMspInit(void)
247 {
248 
249 }
250 
251 
252 /**
253   * @brief  DeInitialize the MSP.
254   * @retval None
255   */
HAL_MspDeInit(void)256 __weak void HAL_MspDeInit(void)
257 {
258     /* NOTE : This function should not be modified, when the callback is needed,
259               the HAL_MspDeInit could be implemented in the user file
260      */
261 }
262 
263 /**
264   * @brief This function configures the source of the time base:
265   *        The time source is configured to have 1ms time base with a dedicated
266   *        Tick interrupt priority.
267   * @note This function is called  automatically at the beginning of program after
268   *       reset by HAL_Init() or at any time when clock is reconfigured  by HAL_RCC_ClockConfig().
269   * @note In the default implementation, SysTick timer is the source of time base.
270   *       It is used to generate interrupts at regular time intervals.
271   *       Care must be taken if HAL_Delay() is called from a peripheral ISR process,
272   *       The SysTick interrupt must have higher priority (numerically lower)
273   *       than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
274   *       The function is declared as __weak  to be overwritten  in case of other
275   *       implementation  in user file.
276   * @param TickPriority  Tick interrupt priority.
277   * @retval HAL status
278   */
HAL_InitTick(uint32_t TickPriority)279 __weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
280 {
281     HAL_StatusTypeDef  status = HAL_OK;
282 
283     /*Configure the SysTick to have interrupt in 1ms time basis*/
284     if (HAL_SYSTICK_Config(SystemCoreClock / 1000UL) != 0U)
285     {
286         status = HAL_ERROR;
287     }
288     else
289     {
290         /*Configure the SysTick IRQ priority */
291         HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0);
292     }
293 
294     /* Return function status */
295     return status;
296 }
297 
298 /**
299   * @} HAL_Exported_Functions_Group1
300   */
301 
302 /** @defgroup HAL_Exported_Functions_Group2 HAL Control functions
303  *  @brief    HAL Control functions
304  *
305 @verbatim
306  ===============================================================================
307                       ##### HAL Control functions #####
308  ===============================================================================
309     [..]  This section provides functions allowing to:
310       (+) Provide a tick value in millisecond
311       (+) Provide a blocking delay in millisecond
312       (+) Suspend the time base source interrupt
313       (+) Resume the time base source interrupt
314       (+) Get the HAL API driver version
315       (+) Get the device identifier
316       (+) Get the device revision identifier
317 
318 @endverbatim
319   * @{
320   */
321 
322 
323 /**
324   * @brief This function is called to increment a global variable "uwTick"
325   *        used as application time base.
326   * @note In the default implementation, this variable is incremented each 1ms
327   *       in SysTick ISR.
328  * @note This function is declared as __weak to be overwritten in case of other
329   *      implementations in user file.
330   * @retval None
331   */
HAL_IncTick(void)332 __weak void HAL_IncTick(void)
333 {
334     uwTick++;
335 }
336 
337 /**
338   * @brief Provide a tick value in millisecond.
339   * @note This function is declared as __weak to be overwritten in case of other
340   *       implementations in user file.
341   * @retval tick value
342   */
HAL_GetTick(void)343 __weak uint32_t HAL_GetTick(void)
344 {
345     return uwTick;
346 }
347 
348 // For CM33, need 5 instructions(12 cycles), Please note that XIP might take more time in flash read.
349 
350 /*
351     LDR     r0,[sp,#0]  3 cycles
352     SUBS    r1,r0,#1    1
353     CMP     r0,#0       1
354     STR     R1,[SP,0]       1
355     BNE     6 cycles
356 */
357 #define WAIT_US_LOOP_CYCLE 12
HAL_Delay_us_(__IO uint32_t us)358 __weak void HAL_Delay_us_(__IO uint32_t us)
359 {
360     //TODO: replaced by SystemCoreClock?
361     static uint32_t sysclk_m;
362 
363     if (us == 0 || sysclk_m == 0)
364     {
365         sysclk_m = HAL_RCC_GetHCLKFreq(CORE_ID_DEFAULT) / 1000000;
366         if (us == 0)
367             return;
368     }
369 
370     if (us > (1 << 24)) // MAX 16s to avoid cnt over range --- suppose clk max to 256M
371         HAL_ASSERT(0);
372 
373     //if (sysclk_m > 48)   // DLL has extra cost, Reason to be determined.
374     //    us -= 1;
375     if (us > 0)          // Extra 1 us for cost of function
376     {
377 #ifdef DWT
378 
379         if (0 == HAL_DBG_DWT_IsInit())
380         {
381             HAL_DBG_DWT_Init();
382         }
383         uint32_t cnt = sysclk_m * us;
384         uint32_t start = HAL_DBG_DWT_GetCycles();
385         while ((HAL_DBG_DWT_GetCycles() - start) < cnt)
386         {
387         }
388 
389 #else
390         volatile uint32_t i = sysclk_m * (us - 1) / WAIT_US_LOOP_CYCLE;
391         while (i-- > 0); //need 5 instructions at ARMCC
392 #endif
393     }
394 }
395 
396 // Use systick to get more accurate us level delay.
HAL_Delay_us2_(__IO uint32_t us)397 __weak void HAL_Delay_us2_(__IO uint32_t us)
398 {
399     uint32_t reload = SysTick->LOAD;
400     uint32_t told, tnow, tcnt = 0;
401     us = us * reload / (1000000 / HAL_TICK_PER_SECOND);
402     told = SysTick->VAL;
403     while (1)
404     {
405         tnow = SysTick->VAL;
406         if (tnow != told)
407         {
408             if (tnow < told)
409             {
410                 tcnt += told - tnow;
411             }
412             else
413             {
414                 tcnt += reload - tnow + told;
415             }
416             told = tnow;
417             if (tcnt >= us)
418             {
419                 break;
420             }
421         }
422     }
423 
424 }
425 
426 #define MAX_US_DELAY    10000
HAL_Delay_us(uint32_t us)427 __weak void HAL_Delay_us(uint32_t us)
428 {
429     uint32_t ticks;
430 
431     if (0 == us)
432     {
433         /* sysclk_m needs to be initialized as it's a random value in keil driver */
434         HAL_Delay_us_(0);
435     }
436 
437     while (us > 0)
438     {
439         if (us > MAX_US_DELAY)
440         {
441             ticks = MAX_US_DELAY;
442             us -= MAX_US_DELAY;
443         }
444         else
445         {
446             ticks = us;
447             us = 0;
448         }
449         if ((SysTick->CTRL & SysTick_CTRL_ENABLE_Msk) == 0) // Systick not enabled yet, use loop
450             HAL_Delay_us_(ticks);
451         else
452             HAL_Delay_us2_(ticks);
453     }
454 }
455 
456 
457 /**
458   * @brief This function provides minimum delay (in milliseconds) based
459   *        on variable incremented.
460   * @note In the default implementation , SysTick timer is the source of time base.
461   *       It is used to generate interrupts at regular time intervals where uwTick
462   *       is incremented.
463   * @note This function is declared as __weak to be overwritten in case of other
464   *       implementations in user file.
465   * @param Delay  specifies the delay time length, in milliseconds.
466   * @retval None
467   */
HAL_Delay(__IO uint32_t Delay)468 __weak void HAL_Delay(__IO uint32_t Delay)
469 {
470 #if 1
471     while (Delay > 0)
472     {
473         HAL_Delay_us(1000);
474         Delay--;
475     }
476 #else
477     uint32_t tickstart = HAL_GetTick();
478     uint32_t wait = Delay;
479 
480     /* Add a period to guaranty minimum wait */
481     if (wait < HAL_MAX_DELAY)
482     {
483         wait++;
484     }
485 
486     while ((HAL_GetTick() - tickstart) < wait)
487     {
488     }
489 #endif
490 }
491 
492 /**
493   * @brief Suspend Tick increment.
494   * @note In the default implementation , SysTick timer is the source of time base. It is
495   *       used to generate interrupts at regular time intervals. Once HAL_SuspendTick()
496   *       is called, the SysTick interrupt will be disabled and so Tick increment
497   *       is suspended.
498   * @note This function is declared as __weak to be overwritten in case of other
499   *       implementations in user file.
500   * @retval None
501   */
HAL_SuspendTick(void)502 __weak void HAL_SuspendTick(void)
503 {
504     /* Disable SysTick Interrupt */
505     SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
506 }
507 
508 /**
509   * @brief Resume Tick increment.
510   * @note In the default implementation , SysTick timer is the source of time base. It is
511   *       used to generate interrupts at regular time intervals. Once HAL_ResumeTick()
512   *       is called, the SysTick interrupt will be enabled and so Tick increment
513   *       is resumed.
514   * @note This function is declared as __weak to be overwritten in case of other
515   *       implementations in user file.
516   * @retval None
517   */
HAL_ResumeTick(void)518 __weak void HAL_ResumeTick(void)
519 {
520     /* Enable SysTick Interrupt */
521     SysTick->CTRL  |= SysTick_CTRL_TICKINT_Msk;
522 }
523 
HAL_AssertFailed(char * file,uint32_t line)524 __weak void HAL_AssertFailed(char *file, uint32_t line)
525 {
526     volatile uint32_t dummy = 0;
527     while (0 == dummy);
528 }
529 
530 #ifndef SF32LB55X
531 #ifdef HAL_WDT_MODULE_ENABLED
WDT_IRQHandler(void)532 __weak void WDT_IRQHandler(void)
533 {
534 
535 }
536 #endif
537 
DBG_Trigger_IRQHandler(void)538 __weak void DBG_Trigger_IRQHandler(void)
539 {
540 
541 }
542 
543 //SF32LB52X in security mode used
544 #if defined(SF32LB52X) && defined(SOC_BF0_HCPU)
PendSv_DBG_Trigger(void)545 void PendSv_DBG_Trigger(void)
546 {
547     DBG_Trigger_IRQHandler();
548 }
549 #endif /* SF32LB52X && SOC_BF0_HCPU */
550 
551 #ifdef HAL_NMI_HANLDER_OVERRIDED
NMI_Handler(void)552     __weak void NMI_Handler(void)
553 #else
554     void NMI_Handler(void)
555 #endif /* HAL_NMI_HANLDER_OVERRIDED */
556 {
557     if (__HAL_SYSCFG_Get_Trigger_Assert_Flag())
558         DBG_Trigger_IRQHandler();
559 #ifdef HAL_WDT_MODULE_ENABLED
560     else
561         WDT_IRQHandler();
562 #endif
563 }
564 
565 #if defined(SF32LB52X) && defined(SOC_BF0_LCPU)
HAL_GetLXTEnabled(void)566 __HAL_ROM_USED uint32_t HAL_GetLXTEnabled(void)
567 {
568     uint8_t is_lxt_enabled;
569     uint16_t len = 1;
570     HAL_StatusTypeDef ret = HAL_LCPU_CONFIG_get(HAL_LCPU_CONFIG_XTAL_ENABLED, &is_lxt_enabled, &len);
571 
572     //default is 32K
573     if (ret != HAL_OK)
574         is_lxt_enabled = 1;
575 
576     return (uint32_t)is_lxt_enabled;
577 }
578 #endif
579 
580 
581 #endif // SF32LB55X
582 
583 /**
584  * @} HAL_Exported_Functions_Group2
585  */
586 
587 /**
588  * @} HAL_Exported_Functions
589  */
590 
591 #endif /* HAL_MODULE_ENABLED */
592 
593 /**
594  * @} HAL_COMMON
595  */
596 
597 /**
598  * @} BF0_HAL_Driver
599  */