Skip to content

Commit

Permalink
Test device: suspend and resume
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelbl committed Mar 11, 2024
1 parent 6b57956 commit 84f84b7
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 16 deletions.
5 changes: 4 additions & 1 deletion test-devices/loopback-stm32/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"usbd.h": "c",
"usbd_pvt.h": "c",
"dwc2_stm32.h": "c",
"stm32f7xx.h": "c"
"stm32f7xx.h": "c",
"stm32f4xx.h": "c",
"stm32f401xc.h": "c",
"stm32f401xe.h": "c"
}
}
Binary file modified test-devices/loopback-stm32/bin/blackpill-f401cc.bin
Binary file not shown.
Binary file modified test-devices/loopback-stm32/bin/blackpill-f411ce.bin
Binary file not shown.
Binary file modified test-devices/loopback-stm32/bin/bluepill-f103c8.bin
Binary file not shown.
Binary file modified test-devices/loopback-stm32/bin/disco_f723ie.bin
Binary file not shown.
3 changes: 3 additions & 0 deletions test-devices/loopback-stm32/src/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ void board_led_write(bool on);
// Return the number of milliseconds since a time in the past
uint32_t board_millis(void);

// Enter sleep or stop mode and wake up on USB resume
void board_sleep(void);

// USB serial number
extern char board_serial_num[13];

Expand Down
44 changes: 41 additions & 3 deletions test-devices/loopback-stm32/src/board_f1.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "stm32f1xx.h"
#include "device/usbd.h"

#define EXTI_USBWakeUp_Line EXTI_IMR_IM18


extern uint32_t SystemCoreClock;
void SystemCoreClockUpdate(void);
Expand Down Expand Up @@ -180,6 +182,12 @@ void board_init(void) {
gpio_set_mode(GPIOB, 12, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSH_PULL);

usb_init_serial_num();

// Wake up event is only available as interrupt, not as an event.
// See product errata sheet
set_reg(&EXTI->RTSR, EXTI_USBWakeUp_Line, EXTI_USBWakeUp_Line);
set_reg(&EXTI->IMR, EXTI_USBWakeUp_Line, EXTI_USBWakeUp_Line);
NVIC_EnableIRQ(USBWakeUp_IRQn);
}

uint32_t board_millis(void) {
Expand All @@ -188,9 +196,38 @@ uint32_t board_millis(void) {

void board_led_write(bool on) {
if (on)
gpio_set(GPIOB, 12);
else
gpio_clear(GPIOB, 12);
else
gpio_set(GPIOB, 12);
}

void board_sleep(void) {

// turn off LED
board_led_write(false);

// pause systick interrupts
set_reg(&SysTick->CTRL, 0, SysTick_CTRL_TICKINT_Msk);

// enter Stop mode when the CPU enters deep sleep
set_reg(&PWR->CR, 0, PWR_CR_PDDS_Msk | PWR_CR_LPDS_Msk);

set_reg(&SCB->SCR, SCB_SCR_SLEEPDEEP_Msk, SCB_SCR_SLEEPDEEP_Msk);

// sleep until an interrupt occurs
__WFI();

// reset SLEEPDEEP bit
set_reg(&SCB->SCR, 0, SCB_SCR_SLEEPDEEP_Msk);

// after wakeup, re-enable PLL as clock source
rcc_clock_setup_in_hse_8mhz_out_72mhz();

// resume systick interrupts
set_reg(&SysTick->CTRL, SysTick_CTRL_TICKINT_Msk, SysTick_CTRL_TICKINT_Msk);

// turn on LED
board_led_write(true);
}


Expand All @@ -201,7 +238,8 @@ void SysTick_Handler (void) {
}

void USBWakeUp_IRQHandler(void) {
tud_int_handler(0);
// clear interrupt
EXTI->PR = EXTI_USBWakeUp_Line;
}

void USB_HP_IRQHandler(void) {
Expand Down
61 changes: 58 additions & 3 deletions test-devices/loopback-stm32/src/board_f4.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
#include "stm32f4xx.h"
#include "device/usbd.h"

#define EXTI_USBWakeUp_Line EXTI_IMR_IM18


extern uint32_t SystemCoreClock;
void SystemCoreClockUpdate(void);

Expand Down Expand Up @@ -59,7 +62,7 @@ const rcc_clock_setup_t clock_setup_hse_value_out_84mhz_3v3 = {
.hpre = RCC_CFGR_HPRE_DIV1,
.ppre1 = RCC_CFGR_PPRE1_DIV2,
.ppre2 = RCC_CFGR_PPRE2_DIV1,
.voltage_scale = PWR_CR_VOS_SCALE1,
.voltage_scale = PWR_CR_VOS_SCALE2,
.flash_config = FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_LATENCY_2WS
};

Expand All @@ -85,6 +88,11 @@ const rcc_clock_setup_t clock_setup_hse_value_out_84mhz_3v3 = {
#define GPIO_OSPEED_HIGH 3


// --- additional USB register
#define PCGCCTL ((volatile uint32_t *)((uint32_t)USB_OTG_FS + USB_OTG_PCGCCTL_BASE))



static inline void rcc_wait_for_osc_ready(uint32_t rcc_cr_clk_rdy) {
while (get_reg(&RCC->CR, rcc_cr_clk_rdy) == 0)
;
Expand Down Expand Up @@ -254,6 +262,13 @@ void board_init(void) {
gpio_mode_setup(GPIOC, 13, GPIO_MODE_OUTPUT, GPIO_PUPD_NO_PULL);

usb_init_serial_num();

// enable USB wakeup interrupt
EXTI->PR = EXTI_USBWakeUp_Line;
EXTI->RTSR |= EXTI_USBWakeUp_Line;
EXTI->IMR |= EXTI_USBWakeUp_Line;
NVIC_SetPriority(OTG_FS_WKUP_IRQn, 0);
NVIC_EnableIRQ(OTG_FS_WKUP_IRQn);
}

uint32_t board_millis(void) {
Expand All @@ -262,9 +277,44 @@ uint32_t board_millis(void) {

void board_led_write(bool on) {
if (on)
gpio_set(GPIOC, 13);
else
gpio_clear(GPIOC, 13);
else
gpio_set(GPIOC, 13);
}

void board_sleep(void) {

// turn off LED
board_led_write(false);

// stop PCLK to USB
set_reg(PCGCCTL, USB_OTG_PCGCCTL_STOPCLK, USB_OTG_PCGCCTL_STOPCLK_Msk);

// pause systick interrupts
set_reg(&SysTick->CTRL, 0, SysTick_CTRL_TICKINT_Msk);

// enter stop mode when the CPU enters deep sleep
set_reg(&PWR->CR, 0, PWR_CR_PDDS_Msk | PWR_CR_LPDS_Msk);

// use deep sleep mode
set_reg(&SCB->SCR, SCB_SCR_SLEEPDEEP_Msk, SCB_SCR_SLEEPDEEP_Msk);

__WFI();

// reset to regular sleep mode
set_reg(&SCB->SCR, 0, SCB_SCR_SLEEPDEEP_Msk);

// after wakeup, re-enable PLL as clock source
rcc_clock_setup_pll(&clock_setup_hse_value_out_84mhz_3v3);

// resume systick interrupts
set_reg(&SysTick->CTRL, SysTick_CTRL_TICKINT_Msk, SysTick_CTRL_TICKINT_Msk);

// restart PCLK to USB
set_reg(PCGCCTL, 0, USB_OTG_PCGCCTL_STOPCLK_Msk);

// turn on LED
board_led_write(true);
}


Expand All @@ -278,4 +328,9 @@ void OTG_FS_IRQHandler(void) {
tud_int_handler(0);
}

void OTG_FS_WKUP_IRQHandler(void) {
// clear interrupt
EXTI->PR = EXTI_USBWakeUp_Line;
}

#endif
4 changes: 4 additions & 0 deletions test-devices/loopback-stm32/src/board_f7.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ void board_init(void) {
usb_init_serial_num();
}

void board_sleep(void) {
// not implemented yet
}

uint32_t board_millis(void) {
return millis_count;
}
Expand Down
10 changes: 2 additions & 8 deletions test-devices/loopback-stm32/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ int num_echos;
enum {
BLINK_NOT_MOUNTED = 250,
BLINK_MOUNTED = 1000,
BLINK_SUSPENDED = 2500,
};

static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
Expand Down Expand Up @@ -288,12 +287,7 @@ void tud_umount_cb(void) {
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
void tud_suspend_cb(bool remote_wakeup_en) {
(void) remote_wakeup_en;
blink_interval_ms = BLINK_SUSPENDED;
}

// Invoked when usb bus is resumed
void tud_resume_cb(void) {
blink_interval_ms = BLINK_MOUNTED;
board_sleep();
}


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

// Blink every interval ms
if ( board_millis() - start_ms < blink_interval_ms)
return; // not enough time
return; // interval not elapsed yet
start_ms += blink_interval_ms;

board_led_write(led_state);
Expand Down
2 changes: 1 addition & 1 deletion test-devices/loopback-stm32/src/usb_descriptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ enum {

uint8_t const desc_fs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, INTF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 500),
TUD_CONFIG_DESCRIPTOR(1, INTF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x80, 500),
// Loopback interface (alternate 0)
CUSTOM_VENDOR_INTERFACE(0, 4),
// Loopback endpoint OUT
Expand Down

0 comments on commit 84f84b7

Please sign in to comment.