Skip to content

Commit 67b556b

Browse files
committed
[MAX32620HSP] Added Deep Sleep support with USB.
1 parent 59f04b4 commit 67b556b

File tree

2 files changed

+82
-13
lines changed

2 files changed

+82
-13
lines changed

hal/targets/hal/TARGET_Maxim/TARGET_MAX32620/sleep.c

Lines changed: 78 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,23 @@
3838
#include "clkman_regs.h"
3939
#include "ioman_regs.h"
4040
#include "rtc_regs.h"
41+
#include "usb_regs.h"
4142
#include "wait_api.h"
4243

4344
#define REVISION_A3 2
4445
#define REVISION_A4 3
4546

47+
// USB state to be restored upon wakeup
48+
typedef struct {
49+
uint32_t dev_cn;
50+
uint32_t dev_inten;
51+
uint32_t ep_base;
52+
uint32_t ep[MXC_USB_NUM_EP];
53+
} usb_state_t;
54+
4655
static mxc_uart_regs_t *stdio_uart = (mxc_uart_regs_t*)STDIO_UART;
56+
static int restore_usb;
57+
static usb_state_t usb_state;
4758

4859
void sleep(void)
4960
{
@@ -54,28 +65,79 @@ void sleep(void)
5465
__WFI();
5566
}
5667

68+
static void usb_sleep(void)
69+
{
70+
int i;
71+
72+
if (MXC_USB->cn & MXC_F_USB_CN_USB_EN) {
73+
// The USB module will not survive Deep Sleep.
74+
75+
// Save the USB state to restore it upon wakeup
76+
usb_state.dev_cn = MXC_USB->dev_cn;
77+
usb_state.dev_inten = MXC_USB->dev_inten;
78+
usb_state.ep_base = MXC_USB->ep_base;
79+
for (i = 0; i < MXC_USB_NUM_EP; i++) {
80+
usb_state.ep[i] = MXC_USB->ep[i] & (MXC_F_USB_EP_DIR | MXC_F_USB_EP_BUF2 | MXC_F_USB_EP_INT_EN | MXC_F_USB_EP_NAK_EN);
81+
}
82+
restore_usb = 1;
83+
84+
// Shut down the USB module.
85+
MXC_USB->dev_inten = 0;
86+
MXC_USB->dev_cn = 0;
87+
MXC_USB->cn = 0;
88+
restore_usb = 1; // USB should be restored upon wakeup
89+
}
90+
else {
91+
restore_usb = 0;
92+
}
93+
}
94+
95+
// Restore the USB module state.
96+
static void usb_wakeup(void)
97+
{
98+
int i;
99+
100+
if (restore_usb) {
101+
MXC_USB->cn = MXC_F_USB_CN_USB_EN;
102+
MXC_USB->dev_cn = MXC_F_USB_DEV_CN_URST;
103+
MXC_USB->dev_cn = 0;
104+
for (i = 0; i < MXC_USB_NUM_EP; i++) {
105+
MXC_USB->ep[i] = usb_state.ep[i];
106+
}
107+
MXC_USB->ep_base = usb_state.ep_base;
108+
MXC_USB->dev_cn = usb_state.dev_cn;
109+
MXC_USB->dev_inten = usb_state.dev_inten;
110+
restore_usb = 0;
111+
}
112+
}
113+
57114
// Low-power stop mode
58115
void deepsleep(void)
59116
{
60-
/* Deep Sleep is not yet supported. */
61-
sleep();
62-
63-
#if 0
64117
unsigned int part_rev = MXC_PWRMAN->mask_id0 & MXC_F_PWRMAN_MASK_ID0_REVISION_ID;
65118

66-
// Deep sleep is not working properly on Revisions A3 and earlier
119+
// Deep Sleep is not working properly on Revisions A3 and earlier
67120
if (part_rev <= REVISION_A3) {
68121
sleep();
69122
return;
70123
}
71124

72125
// Wait for all STDIO characters to be sent. The UART clock will stop.
73-
while ( (((stdio_uart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY)
74-
>> MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY_POS) > 0) ||
75-
(!(stdio_uart->intfl & MXC_F_UART_INTFL_TX_DONE)) );
126+
while ((stdio_uart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY) ||
127+
!(stdio_uart->intfl & MXC_F_UART_INTFL_TX_DONE));
76128

77129
__disable_irq();
78130

131+
// Do not enter Deep Sleep if connected to VBUS
132+
if (MXC_USB->dev_intfl & MXC_F_USB_DEV_INTFL_VBUS_ST) {
133+
__enable_irq();
134+
sleep();
135+
return;
136+
}
137+
138+
// The USB module will not survive Deep Sleep. Shut it down.
139+
usb_sleep();
140+
79141
// Make sure RTC is not pending before sleeping, if its still synchronizing
80142
// we might not wake up.
81143
while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING);
@@ -104,17 +166,20 @@ void deepsleep(void)
104166
MXC_PWRSEQ->msk_flags |= MXC_F_PWRSEQ_MSK_FLAGS_PWR_TVDD12_RST_BAD;
105167
MXC_PWRSEQ->reg0 &= ~(MXC_F_PWRSEQ_REG0_PWR_SVMTVDD12EN_RUN);
106168
MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_SVMTVDD12EN_RUN;
107-
MXC_PWRSEQ->msk_flags &= ~(MXC_F_PWRSEQ_MSK_FLAGS_PWR_TVDD12_RST_BAD);
169+
MXC_PWRSEQ->msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_PWR_TVDD12_RST_BAD;
108170
}
109171

110172
// Enable Retention controller
111173
MXC_PWRSEQ->retn_ctrl0 |= MXC_F_PWRSEQ_RETN_CTRL0_RETN_CTRL_EN;
112174

175+
// Clear the firstboot bit, which is generated by a POR event and locks out LPx modes
176+
MXC_PWRSEQ->reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_FIRST_BOOT;
177+
113178
// Freeze GPIO using MBUS so that it doesn't flail while digital core is asleep
114179
MXC_PWRSEQ->reg1 |= MXC_F_PWRSEQ_REG1_PWR_MBUS_GATE;
115180

116181
// Dummy read to make sure SSB writes are complete
117-
if (MXC_PWRSEQ->reg0 & MXC_F_PWRSEQ_REG0_PWR_SYS_REBOOT) {}
182+
MXC_PWRSEQ->reg0;
118183

119184
if (part_rev == REVISION_A4) {
120185
// Note: ARM deep-sleep requires a specific sequence to clear event latches,
@@ -134,7 +199,9 @@ void deepsleep(void)
134199
// We'll wakeup here ...
135200

136201
// Unfreeze the GPIO by clearing MBUS_GATE
137-
MXC_PWRSEQ->reg1 &= ~(MXC_F_PWRSEQ_REG1_PWR_MBUS_GATE);
202+
MXC_PWRSEQ->reg1 &= ~MXC_F_PWRSEQ_REG1_PWR_MBUS_GATE;
203+
204+
usb_wakeup();
138205

139206
// Clear power sequencer event flags (write-1-to-clear)
140207
// RTC and GPIO flags are cleared in their interrupts handlers
@@ -153,5 +220,4 @@ void deepsleep(void)
153220
MXC_F_PWRSEQ_FLAGS_PWR_TVDD12_BAD);
154221

155222
__enable_irq();
156-
#endif
157223
}

libraries/USBDevice/USBDevice/USBHAL_Maxim.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ USBHAL::USBHAL(void)
9999

100100
// reset the device
101101
MXC_USB->cn = 0;
102-
MXC_USB->cn = 1;
102+
MXC_USB->cn = MXC_F_USB_CN_USB_EN;
103103
MXC_USB->dev_inten = 0;
104104
MXC_USB->dev_cn = 0;
105105
MXC_USB->dev_cn = MXC_F_USB_DEV_CN_URST;
@@ -129,6 +129,9 @@ USBHAL::USBHAL(void)
129129
// set the descriptor location
130130
MXC_USB->ep_base = (uint32_t)&ep_buffer_descriptor;
131131

132+
// enable VBUS interrupts
133+
MXC_USB->dev_inten = MXC_F_USB_DEV_INTEN_NO_VBUS | MXC_F_USB_DEV_INTEN_VBUS;
134+
132135
// attach IRQ handler and enable interrupts
133136
instance = this;
134137
NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);

0 commit comments

Comments
 (0)