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 */