| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- #include "system.h"
- #include "uart.h"
- #include "flash.h"
- SYS_ClocksTypeDef SYS_Clocks = {
- .HSI_FREQUENCY = BOARD_HSI_FREQUENCY,
- .HSE_FREQUENCY = BOARD_HSE_FREQUENCY,
- .PLL_FREQUENCY = BOARD_PLL_FREQUENCY,
- .EXT_FREQUENCY = BOARD_EXT_FREQUENCY,
- };
- uint32_t SYS_GetSysClkFreq(void)
- {
- switch (SYS->CLK_CNTL & SYS_CLK_SOURCE_MASK) {
- case SYS_CLK_SOURCE_HSI:
- return SYS_Clocks.HSI_FREQUENCY;
- case SYS_CLK_SOURCE_HSE:
- return SYS_Clocks.HSE_FREQUENCY;
- case SYS_CLK_SOURCE_PLL:
- return SYS_Clocks.PLL_FREQUENCY;
- default:
- return SYS_Clocks.EXT_FREQUENCY;
- }
- }
- uint32_t SYS_GetPclkFreq(void)
- {
- return SYS_GetSysClkFreq() / (SYS->PBUS_DIVIDER + 1);
- }
- void SYS_SwitchHSIClock(void)
- {
- SYS->CLK_CNTL &= ~SYS_CLK_SOURCE_MASK;
- SYS->CLK_CNTL &= ~(SYS_CLK_PLL_ON | SYS_CLK_HSE_ON); // Turn off HSE and PLL, must be done after clock source switched to HSI
- }
- void SYS_SwitchHSEClock(SYS_HSE_BypassTypeDef hse_bypass)
- {
- SYS_SwitchHSIClock();
- uint32_t clk_control = SYS->CLK_CNTL;
- // Turn on HSE clock
- clk_control |= SYS_CLK_HSE_ON;
- if (hse_bypass == SYS_HSE_BYPASS_ON) {
- clk_control |= SYS_CLK_HSE_BYP;
- } else {
- clk_control &= ~SYS_CLK_HSE_BYP;
- }
- SYS->CLK_CNTL = clk_control;
- // Wait for HSE ready and switch
- while (!SYS_IsHseReady());
- clk_control |= SYS_CLK_SOURCE_HSE;
- SYS->CLK_CNTL = clk_control;
- }
- void SYS_SwitchPLLClock(SYS_HSE_BypassTypeDef hse_bypass)
- {
- SYS_SwitchHSIClock();
- SYS_SetSclkAuto(SYS_GetPLLFreq()); // Since PLL frequency may exceed FLASH_MAX_FREQ
- uint32_t clk_control = SYS->CLK_CNTL;
- // Turn on PLL clock
- clk_control &= ~SYS_CLK_HSE_BYP;
- switch (hse_bypass) {
- case SYS_HSE_BYPASS_ON:
- clk_control |= SYS_CLK_HSE_BYP;
- // Fall through
- case SYS_HSE_BYPASS_OFF:
- clk_control |= SYS_CLK_HSE_ON;
- // Fall through
- default:
- clk_control |= SYS_CLK_PLL_ON;
- break;
- }
- SYS->CLK_CNTL = clk_control;
- if (clk_control & SYS_CLK_HSE_ON) {
- while (!SYS_IsHseReady());
- }
- uint32_t counter = 0;
- // Wait for PLL ready and switch
- while (!SYS_IsPllReady()) {
- if (++counter > 5000) {
- counter = 0;
- SYS->CLK_CNTL = clk_control & ~SYS_CLK_PLL_ON;
- SYS->CLK_CNTL = clk_control;
- }
- }
- clk_control |= SYS_CLK_SOURCE_PLL;
- SYS->CLK_CNTL = clk_control;
- }
- void SYS_SetSclkDivider(uint8_t divider)
- {
- MODIFY_BIT(SYS->CLK_CNTL, SYS_SCLK_DIV_HIGH_MASK | SYS_SCLK_DIV_LOW_MASK, SYS_SCLK_DIV_HIGH(divider) | SYS_SCLK_DIV_LOW(divider));
- }
- uint8_t SYS_SetSclkAuto(uint32_t freq)
- {
- uint8_t divider = (freq - 1) / FLASH_MAX_FREQ;
- SYS_SetSclkDivider(divider);
- return divider;
- }
- void SYS_EnterSleepMode(void)
- {
- MODIFY_BIT(SYS->PWR_CNTL, SYS_LOWPOWER_MODE_MASK, SYS_SLEEP_MODE);
- asm("fence"); // Make sure SYS->PWR_CNTL is effective
- SYS_EnterLowPower();
- }
- void SYS_EnterStopMode(void)
- {
- MODIFY_BIT(SYS->PWR_CNTL, SYS_LOWPOWER_MODE_MASK, SYS_STOP_MODE);
- asm("fence"); // Make sure SYS->PWR_CNTL is effective
- SYS_SwitchHSIClock();
- SYS_EnterLowPower();
- }
- void SYS_EnterStandbyMode(void)
- {
- MODIFY_BIT(SYS->PWR_CNTL, SYS_LOWPOWER_MODE_MASK, SYS_STANDBY_MODE);
- asm("fence"); // Make sure SYS->PWR_CNTL is effective
- SYS_SwitchHSIClock();
- SYS_EnterLowPower();
- }
|