1 #include <twr_system.h>
2 #include <twr_scheduler.h>
7 #include <stm32l0xx_hal_conf.h>
11 #define _TWR_SYSTEM_DEBUG_ENABLE 0
13 static const uint32_t twr_system_clock_table[3] =
20 static int _twr_system_hsi16_enable_semaphore;
22 static int _twr_system_pll_enable_semaphore;
24 static int _twr_system_deep_sleep_disable_semaphore;
26 static void _twr_system_init_flash(
void);
28 static void _twr_system_init_debug(
void);
30 static void _twr_system_init_clock(
void);
32 static void _twr_system_init_power(
void);
34 static void _twr_system_init_gpio(
void);
36 static void _twr_system_init_rtc(
void);
38 static void _twr_system_init_shutdown_i2c_sensors(
void);
40 static void _twr_system_switch_clock(twr_system_clock_t clock);
42 void twr_system_init(
void)
44 _twr_system_init_flash();
46 _twr_system_init_debug();
48 _twr_system_init_clock();
50 _twr_system_init_power();
52 _twr_system_init_gpio();
54 _twr_system_init_rtc();
56 _twr_system_init_shutdown_i2c_sensors();
59 static void _twr_system_init_flash(
void)
62 FLASH->ACR |= FLASH_ACR_PRFTEN;
65 FLASH->ACR |= FLASH_ACR_LATENCY;
68 static void _twr_system_init_debug(
void)
70 #if _TWR_SYSTEM_DEBUG_ENABLE == 1
73 RCC->APB2ENR |= RCC_APB2ENR_DBGMCUEN;
79 DBGMCU->CR |= DBGMCU_CR_DBG_STANDBY;
82 DBGMCU->CR |= DBGMCU_CR_DBG_STOP;
85 DBGMCU->CR |= DBGMCU_CR_DBG_SLEEP;
88 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_LPTIMER_STOP;
91 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_I2C3_STOP;
94 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_I2C1_STOP;
97 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_IWDG_STOP;
100 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_WWDG_STOP;
103 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_RTC_STOP;
106 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM7_STOP;
109 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM6_STOP;
112 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM3_STOP;
115 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM2_STOP;
118 DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM22_STOP;
121 DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP;
126 static void _twr_system_init_clock(
void)
130 SystemCoreClock = 2097000;
132 RCC->APB1ENR |= RCC_APB1ENR_PWREN;
135 PWR->CR |= PWR_CR_VOS;
138 RCC->CFGR = RCC_CFGR_PLLDIV2 | RCC_CFGR_PLLMUL4;
141 SysTick->LOAD = 2097 - 1;
147 SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
150 SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
153 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
156 static void _twr_system_init_power(
void)
159 RCC->APB1ENR |= RCC_APB1ENR_PWREN;
165 PWR->CR |= PWR_CR_DBP;
168 PWR->CR |= PWR_CR_FWU;
171 PWR->CR |= PWR_CR_ULP;
174 PWR->CR |= PWR_CR_LPSDSR;
177 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
180 static void _twr_system_init_gpio(
void)
183 RCC->IOPENR = RCC_IOPENR_GPIOAEN;
189 GPIOA->MODER |= GPIO_MODER_MODE4_1 | GPIO_MODER_MODE4_0;
192 static void _twr_system_init_rtc(
void)
196 RCC->CSR |= RCC_CSR_LSEDRV_1;
199 RCC->CSR |= RCC_CSR_LSEON;
202 while ((RCC->CSR & RCC_CSR_LSERDY) == 0)
208 RCC->CSR |= RCC_CSR_RTCSEL_LSE;
211 RCC->CSR |= RCC_CSR_RTCEN;
216 twr_rtc_enable_write();
219 if ((RTC->ISR & RTC_ISR_INITS) == 0)
224 RTC->PRER = TWR_RTC_PREDIV_S - 1;
225 RTC->PRER |= (TWR_RTC_PREDIV_A - 1) << 16;
228 RTC->CR &= ~RTC_CR_FMT;
234 RTC->CR &= ~RTC_CR_WUTE;
237 while ((RTC->ISR & RTC_ISR_WUTWF) == 0)
243 RTC->WUTR = LSE_VALUE / 16 * TWR_SCHEDULER_INTERVAL_MS / 1000;
246 RTC->ISR &= ~RTC_ISR_WUTF;
249 RTC->CR |= RTC_CR_WUTIE;
252 RTC->CR |= RTC_CR_WUTE;
254 twr_rtc_disable_write();
257 EXTI->IMR |= EXTI_IMR_IM20;
260 EXTI->RTSR |= EXTI_IMR_IM20;
263 NVIC_EnableIRQ(RTC_IRQn);
266 static void _twr_system_init_shutdown_i2c_sensors(
void)
278 void twr_system_deep_sleep_enable(
void)
280 _twr_system_deep_sleep_disable_semaphore--;
282 if (_twr_system_deep_sleep_disable_semaphore == 0)
284 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
288 void twr_system_deep_sleep_disable(
void)
290 if (_twr_system_deep_sleep_disable_semaphore == 0)
292 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
295 _twr_system_deep_sleep_disable_semaphore++;
298 void twr_system_enter_standby_mode(
void)
300 _twr_system_init_shutdown_i2c_sensors();
304 GPIOA->MODER = 0xFFFFFFFF;
305 GPIOB->MODER = 0xFFFFFFFF;
306 GPIOC->MODER = 0xFFFFFFFF;
307 GPIOH->MODER = 0xFFFFFFFF;
310 RCC->CSR &= ~(RCC_CSR_RTCEN | RCC_CSR_LSEON | RCC_CSR_RTCSEL_LSE);
315 RCC->CSR &= ~RCC_CSR_LSEDRV_Msk;
317 PWR->CR &= ~PWR_CR_LPSDSR;
319 PWR->CR |= PWR_CR_PDDS;
321 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
323 PWR->CR |= PWR_CR_CWUF;
328 twr_system_clock_t twr_system_clock_get(
void)
330 if (_twr_system_pll_enable_semaphore != 0)
332 return TWR_SYSTEM_CLOCK_PLL;
334 else if (_twr_system_hsi16_enable_semaphore != 0)
336 return TWR_SYSTEM_CLOCK_HSI;
340 return TWR_SYSTEM_CLOCK_MSI;
344 void twr_system_hsi16_enable(
void)
346 if (++_twr_system_hsi16_enable_semaphore == 1)
349 PWR->CR |= PWR_CR_VOS_0;
350 PWR->CR &= ~PWR_CR_VOS_1;
353 FLASH->ACR |= FLASH_ACR_LATENCY | FLASH_ACR_PRE_READ;
356 RCC->CR |= RCC_CR_HSION;
358 while ((RCC->CR & RCC_CR_HSIRDY) == 0)
363 _twr_system_switch_clock(TWR_SYSTEM_CLOCK_HSI);
366 SysTick->LOAD = 16000 - 1;
369 SystemCoreClock = 16000000;
375 void twr_system_hsi16_disable(
void)
377 if (--_twr_system_hsi16_enable_semaphore == 0)
379 _twr_system_switch_clock(TWR_SYSTEM_CLOCK_MSI);
382 RCC->CR &= ~RCC_CR_HSION;
384 while ((RCC->CR & RCC_CR_HSIRDY) != 0)
390 SysTick->LOAD = 2097 - 1;
393 SystemCoreClock = 2097000;
396 FLASH->ACR &= ~(FLASH_ACR_LATENCY | FLASH_ACR_PRE_READ);
399 PWR->CR |= PWR_CR_VOS;
405 void twr_system_pll_enable(
void)
407 if (++_twr_system_pll_enable_semaphore == 1)
409 twr_system_hsi16_enable();
412 RCC->CR |= RCC_CR_PLLON;
414 while ((RCC->CR & RCC_CR_PLLRDY) == 0)
419 _twr_system_switch_clock(TWR_SYSTEM_CLOCK_PLL);
422 SysTick->LOAD = 32000 - 1;
425 SystemCoreClock = 32000000;
429 void twr_system_pll_disable(
void)
431 if (--_twr_system_pll_enable_semaphore == 0)
433 _twr_system_switch_clock(TWR_SYSTEM_CLOCK_HSI);
436 RCC->CR &= ~RCC_CR_PLLON;
438 while ((RCC->CR & RCC_CR_PLLRDY) != 0)
443 twr_system_hsi16_disable();
447 uint32_t twr_system_get_clock(
void)
449 return SystemCoreClock;
452 void twr_system_reset(
void)
457 bool twr_system_get_vbus_sense(
void)
459 static bool init =
false;
466 RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
472 GPIOA->PUPDR |= GPIO_PUPDR_PUPD12_1;
475 GPIOA->MODER &= ~GPIO_MODER_MODE12_Msk;
483 return (GPIOA->IDR & GPIO_IDR_ID12) != 0;
486 __attribute__((weak))
void twr_system_error(
void)
495 void HardFault_Handler(
void)
500 void RTC_IRQHandler(
void)
503 if (RTC->ISR & RTC_ISR_WUTF)
506 RTC->ISR &= ~RTC_ISR_WUTF;
508 twr_tick_increment_irq(TWR_SCHEDULER_INTERVAL_MS);
512 EXTI->PR = EXTI_IMR_IM20;
516 static void _twr_system_switch_clock(twr_system_clock_t clock)
518 uint32_t clock_mask = twr_system_clock_table[clock];
522 uint32_t rcc_cfgr = RCC->CFGR;
523 rcc_cfgr &= ~RCC_CFGR_SW_Msk;
524 rcc_cfgr |= clock_mask;
525 RCC->CFGR = rcc_cfgr;
void twr_i2c_deinit(twr_i2c_channel_t channel)
Deitialize I2C channel.
void twr_i2c_init(twr_i2c_channel_t channel, twr_i2c_speed_t speed)
Initialize I2C channel.
bool twr_i2c_memory_write_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t data)
Memory write 1 byte to I2C channel.
bool twr_i2c_memory_write_16b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t data)
Memory write 2 bytes to I2C channel.
@ TWR_I2C_SPEED_100_KHZ
I2C communication speed is 100 kHz.
@ TWR_I2C_I2C0
I2C channel I2C0.
void twr_irq_disable(void)
Disable interrupt requests globally (call can be nested)
void twr_irq_enable(void)
Enable interrupt requests globally (call can be nested)
void twr_rtc_set_init(bool state)
Enable or disable RTC initialization mode.
void twr_timer_init(void)
Initialize timer.
void twr_timer_delay(uint16_t microseconds)
Relative delay.
void twr_timer_stop(void)
Stop timer.
void twr_timer_start(void)
Start timer.