1515#include "stm32f4xx.h"
1616#include "device/usbd.h"
1717
18+ #define EXTI_USBWakeUp_Line EXTI_IMR_IM18
19+
20+
1821extern uint32_t SystemCoreClock ;
1922void SystemCoreClockUpdate (void );
2023
@@ -59,7 +62,7 @@ const rcc_clock_setup_t clock_setup_hse_value_out_84mhz_3v3 = {
5962 .hpre = RCC_CFGR_HPRE_DIV1 ,
6063 .ppre1 = RCC_CFGR_PPRE1_DIV2 ,
6164 .ppre2 = RCC_CFGR_PPRE2_DIV1 ,
62- .voltage_scale = PWR_CR_VOS_SCALE1 ,
65+ .voltage_scale = PWR_CR_VOS_SCALE2 ,
6366 .flash_config = FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_LATENCY_2WS
6467};
6568
@@ -85,6 +88,11 @@ const rcc_clock_setup_t clock_setup_hse_value_out_84mhz_3v3 = {
8588#define GPIO_OSPEED_HIGH 3
8689
8790
91+ // --- additional USB register
92+ #define PCGCCTL ((volatile uint32_t *)((uint32_t)USB_OTG_FS + USB_OTG_PCGCCTL_BASE))
93+
94+
95+
8896static inline void rcc_wait_for_osc_ready (uint32_t rcc_cr_clk_rdy ) {
8997 while (get_reg (& RCC -> CR , rcc_cr_clk_rdy ) == 0 )
9098 ;
@@ -254,6 +262,13 @@ void board_init(void) {
254262 gpio_mode_setup (GPIOC , 13 , GPIO_MODE_OUTPUT , GPIO_PUPD_NO_PULL );
255263
256264 usb_init_serial_num ();
265+
266+ // enable USB wakeup interrupt
267+ EXTI -> PR = EXTI_USBWakeUp_Line ;
268+ EXTI -> RTSR |= EXTI_USBWakeUp_Line ;
269+ EXTI -> IMR |= EXTI_USBWakeUp_Line ;
270+ NVIC_SetPriority (OTG_FS_WKUP_IRQn , 0 );
271+ NVIC_EnableIRQ (OTG_FS_WKUP_IRQn );
257272}
258273
259274uint32_t board_millis (void ) {
@@ -262,9 +277,44 @@ uint32_t board_millis(void) {
262277
263278void board_led_write (bool on ) {
264279 if (on )
265- gpio_set (GPIOC , 13 );
266- else
267280 gpio_clear (GPIOC , 13 );
281+ else
282+ gpio_set (GPIOC , 13 );
283+ }
284+
285+ void board_sleep (void ) {
286+
287+ // turn off LED
288+ board_led_write (false);
289+
290+ // stop PCLK to USB
291+ set_reg (PCGCCTL , USB_OTG_PCGCCTL_STOPCLK , USB_OTG_PCGCCTL_STOPCLK_Msk );
292+
293+ // pause systick interrupts
294+ set_reg (& SysTick -> CTRL , 0 , SysTick_CTRL_TICKINT_Msk );
295+
296+ // enter stop mode when the CPU enters deep sleep
297+ set_reg (& PWR -> CR , 0 , PWR_CR_PDDS_Msk | PWR_CR_LPDS_Msk );
298+
299+ // use deep sleep mode
300+ set_reg (& SCB -> SCR , SCB_SCR_SLEEPDEEP_Msk , SCB_SCR_SLEEPDEEP_Msk );
301+
302+ __WFI ();
303+
304+ // reset to regular sleep mode
305+ set_reg (& SCB -> SCR , 0 , SCB_SCR_SLEEPDEEP_Msk );
306+
307+ // after wakeup, re-enable PLL as clock source
308+ rcc_clock_setup_pll (& clock_setup_hse_value_out_84mhz_3v3 );
309+
310+ // resume systick interrupts
311+ set_reg (& SysTick -> CTRL , SysTick_CTRL_TICKINT_Msk , SysTick_CTRL_TICKINT_Msk );
312+
313+ // restart PCLK to USB
314+ set_reg (PCGCCTL , 0 , USB_OTG_PCGCCTL_STOPCLK_Msk );
315+
316+ // turn on LED
317+ board_led_write (true);
268318}
269319
270320
@@ -278,4 +328,9 @@ void OTG_FS_IRQHandler(void) {
278328 tud_int_handler (0 );
279329}
280330
331+ void OTG_FS_WKUP_IRQHandler (void ) {
332+ // clear interrupt
333+ EXTI -> PR = EXTI_USBWakeUp_Line ;
334+ }
335+
281336#endif
0 commit comments