Skip to content

Commit 84f84b7

Browse files
committed
Test device: suspend and resume
1 parent 6b57956 commit 84f84b7

11 files changed

Lines changed: 113 additions & 16 deletions

File tree

test-devices/loopback-stm32/.vscode/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"usbd.h": "c",
44
"usbd_pvt.h": "c",
55
"dwc2_stm32.h": "c",
6-
"stm32f7xx.h": "c"
6+
"stm32f7xx.h": "c",
7+
"stm32f4xx.h": "c",
8+
"stm32f401xc.h": "c",
9+
"stm32f401xe.h": "c"
710
}
811
}
160 Bytes
Binary file not shown.
160 Bytes
Binary file not shown.
132 Bytes
Binary file not shown.
-24 Bytes
Binary file not shown.

test-devices/loopback-stm32/src/board.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ void board_led_write(bool on);
2828
// Return the number of milliseconds since a time in the past
2929
uint32_t board_millis(void);
3030

31+
// Enter sleep or stop mode and wake up on USB resume
32+
void board_sleep(void);
33+
3134
// USB serial number
3235
extern char board_serial_num[13];
3336

test-devices/loopback-stm32/src/board_f1.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "stm32f1xx.h"
1616
#include "device/usbd.h"
1717

18+
#define EXTI_USBWakeUp_Line EXTI_IMR_IM18
19+
1820

1921
extern uint32_t SystemCoreClock;
2022
void SystemCoreClockUpdate(void);
@@ -180,6 +182,12 @@ void board_init(void) {
180182
gpio_set_mode(GPIOB, 12, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSH_PULL);
181183

182184
usb_init_serial_num();
185+
186+
// Wake up event is only available as interrupt, not as an event.
187+
// See product errata sheet
188+
set_reg(&EXTI->RTSR, EXTI_USBWakeUp_Line, EXTI_USBWakeUp_Line);
189+
set_reg(&EXTI->IMR, EXTI_USBWakeUp_Line, EXTI_USBWakeUp_Line);
190+
NVIC_EnableIRQ(USBWakeUp_IRQn);
183191
}
184192

185193
uint32_t board_millis(void) {
@@ -188,9 +196,38 @@ uint32_t board_millis(void) {
188196

189197
void board_led_write(bool on) {
190198
if (on)
191-
gpio_set(GPIOB, 12);
192-
else
193199
gpio_clear(GPIOB, 12);
200+
else
201+
gpio_set(GPIOB, 12);
202+
}
203+
204+
void board_sleep(void) {
205+
206+
// turn off LED
207+
board_led_write(false);
208+
209+
// pause systick interrupts
210+
set_reg(&SysTick->CTRL, 0, SysTick_CTRL_TICKINT_Msk);
211+
212+
// enter Stop mode when the CPU enters deep sleep
213+
set_reg(&PWR->CR, 0, PWR_CR_PDDS_Msk | PWR_CR_LPDS_Msk);
214+
215+
set_reg(&SCB->SCR, SCB_SCR_SLEEPDEEP_Msk, SCB_SCR_SLEEPDEEP_Msk);
216+
217+
// sleep until an interrupt occurs
218+
__WFI();
219+
220+
// reset SLEEPDEEP bit
221+
set_reg(&SCB->SCR, 0, SCB_SCR_SLEEPDEEP_Msk);
222+
223+
// after wakeup, re-enable PLL as clock source
224+
rcc_clock_setup_in_hse_8mhz_out_72mhz();
225+
226+
// resume systick interrupts
227+
set_reg(&SysTick->CTRL, SysTick_CTRL_TICKINT_Msk, SysTick_CTRL_TICKINT_Msk);
228+
229+
// turn on LED
230+
board_led_write(true);
194231
}
195232

196233

@@ -201,7 +238,8 @@ void SysTick_Handler (void) {
201238
}
202239

203240
void USBWakeUp_IRQHandler(void) {
204-
tud_int_handler(0);
241+
// clear interrupt
242+
EXTI->PR = EXTI_USBWakeUp_Line;
205243
}
206244

207245
void USB_HP_IRQHandler(void) {

test-devices/loopback-stm32/src/board_f4.c

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#include "stm32f4xx.h"
1616
#include "device/usbd.h"
1717

18+
#define EXTI_USBWakeUp_Line EXTI_IMR_IM18
19+
20+
1821
extern uint32_t SystemCoreClock;
1922
void 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+
8896
static 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

259274
uint32_t board_millis(void) {
@@ -262,9 +277,44 @@ uint32_t board_millis(void) {
262277

263278
void 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

test-devices/loopback-stm32/src/board_f7.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ void board_init(void) {
284284
usb_init_serial_num();
285285
}
286286

287+
void board_sleep(void) {
288+
// not implemented yet
289+
}
290+
287291
uint32_t board_millis(void) {
288292
return millis_count;
289293
}

test-devices/loopback-stm32/src/main.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ int num_echos;
4242
enum {
4343
BLINK_NOT_MOUNTED = 250,
4444
BLINK_MOUNTED = 1000,
45-
BLINK_SUSPENDED = 2500,
4645
};
4746

4847
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
@@ -288,12 +287,7 @@ void tud_umount_cb(void) {
288287
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
289288
void tud_suspend_cb(bool remote_wakeup_en) {
290289
(void) remote_wakeup_en;
291-
blink_interval_ms = BLINK_SUSPENDED;
292-
}
293-
294-
// Invoked when usb bus is resumed
295-
void tud_resume_cb(void) {
296-
blink_interval_ms = BLINK_MOUNTED;
290+
board_sleep();
297291
}
298292

299293

@@ -305,7 +299,7 @@ void led_blinking_task(void) {
305299

306300
// Blink every interval ms
307301
if ( board_millis() - start_ms < blink_interval_ms)
308-
return; // not enough time
302+
return; // interval not elapsed yet
309303
start_ms += blink_interval_ms;
310304

311305
board_led_write(led_state);

0 commit comments

Comments
 (0)