mirror of https://github.com/ARMmbed/mbed-os.git
[MAX32620HSP] Added Deep Sleep support with USB.
parent
59f04b4771
commit
67b556b648
|
@ -38,12 +38,23 @@
|
|||
#include "clkman_regs.h"
|
||||
#include "ioman_regs.h"
|
||||
#include "rtc_regs.h"
|
||||
#include "usb_regs.h"
|
||||
#include "wait_api.h"
|
||||
|
||||
#define REVISION_A3 2
|
||||
#define REVISION_A4 3
|
||||
|
||||
// USB state to be restored upon wakeup
|
||||
typedef struct {
|
||||
uint32_t dev_cn;
|
||||
uint32_t dev_inten;
|
||||
uint32_t ep_base;
|
||||
uint32_t ep[MXC_USB_NUM_EP];
|
||||
} usb_state_t;
|
||||
|
||||
static mxc_uart_regs_t *stdio_uart = (mxc_uart_regs_t*)STDIO_UART;
|
||||
static int restore_usb;
|
||||
static usb_state_t usb_state;
|
||||
|
||||
void sleep(void)
|
||||
{
|
||||
|
@ -54,28 +65,79 @@ void sleep(void)
|
|||
__WFI();
|
||||
}
|
||||
|
||||
static void usb_sleep(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (MXC_USB->cn & MXC_F_USB_CN_USB_EN) {
|
||||
// The USB module will not survive Deep Sleep.
|
||||
|
||||
// Save the USB state to restore it upon wakeup
|
||||
usb_state.dev_cn = MXC_USB->dev_cn;
|
||||
usb_state.dev_inten = MXC_USB->dev_inten;
|
||||
usb_state.ep_base = MXC_USB->ep_base;
|
||||
for (i = 0; i < MXC_USB_NUM_EP; i++) {
|
||||
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);
|
||||
}
|
||||
restore_usb = 1;
|
||||
|
||||
// Shut down the USB module.
|
||||
MXC_USB->dev_inten = 0;
|
||||
MXC_USB->dev_cn = 0;
|
||||
MXC_USB->cn = 0;
|
||||
restore_usb = 1; // USB should be restored upon wakeup
|
||||
}
|
||||
else {
|
||||
restore_usb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the USB module state.
|
||||
static void usb_wakeup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (restore_usb) {
|
||||
MXC_USB->cn = MXC_F_USB_CN_USB_EN;
|
||||
MXC_USB->dev_cn = MXC_F_USB_DEV_CN_URST;
|
||||
MXC_USB->dev_cn = 0;
|
||||
for (i = 0; i < MXC_USB_NUM_EP; i++) {
|
||||
MXC_USB->ep[i] = usb_state.ep[i];
|
||||
}
|
||||
MXC_USB->ep_base = usb_state.ep_base;
|
||||
MXC_USB->dev_cn = usb_state.dev_cn;
|
||||
MXC_USB->dev_inten = usb_state.dev_inten;
|
||||
restore_usb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Low-power stop mode
|
||||
void deepsleep(void)
|
||||
{
|
||||
/* Deep Sleep is not yet supported. */
|
||||
sleep();
|
||||
|
||||
#if 0
|
||||
unsigned int part_rev = MXC_PWRMAN->mask_id0 & MXC_F_PWRMAN_MASK_ID0_REVISION_ID;
|
||||
|
||||
// Deep sleep is not working properly on Revisions A3 and earlier
|
||||
// Deep Sleep is not working properly on Revisions A3 and earlier
|
||||
if (part_rev <= REVISION_A3) {
|
||||
sleep();
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for all STDIO characters to be sent. The UART clock will stop.
|
||||
while ( (((stdio_uart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY)
|
||||
>> MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY_POS) > 0) ||
|
||||
(!(stdio_uart->intfl & MXC_F_UART_INTFL_TX_DONE)) );
|
||||
while ((stdio_uart->tx_fifo_ctrl & MXC_F_UART_TX_FIFO_CTRL_FIFO_ENTRY) ||
|
||||
!(stdio_uart->intfl & MXC_F_UART_INTFL_TX_DONE));
|
||||
|
||||
__disable_irq();
|
||||
|
||||
// Do not enter Deep Sleep if connected to VBUS
|
||||
if (MXC_USB->dev_intfl & MXC_F_USB_DEV_INTFL_VBUS_ST) {
|
||||
__enable_irq();
|
||||
sleep();
|
||||
return;
|
||||
}
|
||||
|
||||
// The USB module will not survive Deep Sleep. Shut it down.
|
||||
usb_sleep();
|
||||
|
||||
// Make sure RTC is not pending before sleeping, if its still synchronizing
|
||||
// we might not wake up.
|
||||
while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING);
|
||||
|
@ -104,17 +166,20 @@ void deepsleep(void)
|
|||
MXC_PWRSEQ->msk_flags |= MXC_F_PWRSEQ_MSK_FLAGS_PWR_TVDD12_RST_BAD;
|
||||
MXC_PWRSEQ->reg0 &= ~(MXC_F_PWRSEQ_REG0_PWR_SVMTVDD12EN_RUN);
|
||||
MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_SVMTVDD12EN_RUN;
|
||||
MXC_PWRSEQ->msk_flags &= ~(MXC_F_PWRSEQ_MSK_FLAGS_PWR_TVDD12_RST_BAD);
|
||||
MXC_PWRSEQ->msk_flags &= ~MXC_F_PWRSEQ_MSK_FLAGS_PWR_TVDD12_RST_BAD;
|
||||
}
|
||||
|
||||
// Enable Retention controller
|
||||
MXC_PWRSEQ->retn_ctrl0 |= MXC_F_PWRSEQ_RETN_CTRL0_RETN_CTRL_EN;
|
||||
|
||||
// Clear the firstboot bit, which is generated by a POR event and locks out LPx modes
|
||||
MXC_PWRSEQ->reg0 &= ~MXC_F_PWRSEQ_REG0_PWR_FIRST_BOOT;
|
||||
|
||||
// Freeze GPIO using MBUS so that it doesn't flail while digital core is asleep
|
||||
MXC_PWRSEQ->reg1 |= MXC_F_PWRSEQ_REG1_PWR_MBUS_GATE;
|
||||
|
||||
// Dummy read to make sure SSB writes are complete
|
||||
if (MXC_PWRSEQ->reg0 & MXC_F_PWRSEQ_REG0_PWR_SYS_REBOOT) {}
|
||||
MXC_PWRSEQ->reg0;
|
||||
|
||||
if (part_rev == REVISION_A4) {
|
||||
// Note: ARM deep-sleep requires a specific sequence to clear event latches,
|
||||
|
@ -134,7 +199,9 @@ void deepsleep(void)
|
|||
// We'll wakeup here ...
|
||||
|
||||
// Unfreeze the GPIO by clearing MBUS_GATE
|
||||
MXC_PWRSEQ->reg1 &= ~(MXC_F_PWRSEQ_REG1_PWR_MBUS_GATE);
|
||||
MXC_PWRSEQ->reg1 &= ~MXC_F_PWRSEQ_REG1_PWR_MBUS_GATE;
|
||||
|
||||
usb_wakeup();
|
||||
|
||||
// Clear power sequencer event flags (write-1-to-clear)
|
||||
// RTC and GPIO flags are cleared in their interrupts handlers
|
||||
|
@ -153,5 +220,4 @@ void deepsleep(void)
|
|||
MXC_F_PWRSEQ_FLAGS_PWR_TVDD12_BAD);
|
||||
|
||||
__enable_irq();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ USBHAL::USBHAL(void)
|
|||
|
||||
// reset the device
|
||||
MXC_USB->cn = 0;
|
||||
MXC_USB->cn = 1;
|
||||
MXC_USB->cn = MXC_F_USB_CN_USB_EN;
|
||||
MXC_USB->dev_inten = 0;
|
||||
MXC_USB->dev_cn = 0;
|
||||
MXC_USB->dev_cn = MXC_F_USB_DEV_CN_URST;
|
||||
|
@ -129,6 +129,9 @@ USBHAL::USBHAL(void)
|
|||
// set the descriptor location
|
||||
MXC_USB->ep_base = (uint32_t)&ep_buffer_descriptor;
|
||||
|
||||
// enable VBUS interrupts
|
||||
MXC_USB->dev_inten = MXC_F_USB_DEV_INTEN_NO_VBUS | MXC_F_USB_DEV_INTEN_VBUS;
|
||||
|
||||
// attach IRQ handler and enable interrupts
|
||||
instance = this;
|
||||
NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
|
||||
|
|
Loading…
Reference in New Issue