Merge pull request #494 from ADVANSEE/cc2538-lpm-fixes
cc2538: lpm: Fix several issues
This commit is contained in:
commit
79e6514c80
@ -83,10 +83,10 @@ notify(uint8_t mask, uint8_t port)
|
||||
void
|
||||
gpio_port_a_isr()
|
||||
{
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
lpm_exit();
|
||||
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
notify(REG(GPIO_A_BASE | GPIO_MIS), GPIO_A_NUM);
|
||||
|
||||
GPIO_CLEAR_INTERRUPT(GPIO_A_BASE, 0xFF);
|
||||
@ -99,10 +99,10 @@ gpio_port_a_isr()
|
||||
void
|
||||
gpio_port_b_isr()
|
||||
{
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
lpm_exit();
|
||||
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
notify(REG(GPIO_B_BASE | GPIO_MIS), GPIO_B_NUM);
|
||||
|
||||
GPIO_CLEAR_INTERRUPT(GPIO_B_BASE, 0xFF);
|
||||
@ -115,10 +115,10 @@ gpio_port_b_isr()
|
||||
void
|
||||
gpio_port_c_isr()
|
||||
{
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
lpm_exit();
|
||||
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
notify(REG(GPIO_C_BASE | GPIO_MIS), GPIO_C_NUM);
|
||||
|
||||
GPIO_CLEAR_INTERRUPT(GPIO_C_BASE, 0xFF);
|
||||
@ -131,10 +131,10 @@ gpio_port_c_isr()
|
||||
void
|
||||
gpio_port_d_isr()
|
||||
{
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
lpm_exit();
|
||||
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
notify(REG(GPIO_D_BASE | GPIO_MIS), GPIO_D_NUM);
|
||||
|
||||
GPIO_CLEAR_INTERRUPT(GPIO_D_BASE, 0xFF);
|
||||
|
@ -158,16 +158,28 @@ enter_pm0(void)
|
||||
static void
|
||||
select_32_mhz_xosc(void)
|
||||
{
|
||||
/*First, make sure there is no ongoing clock source change */
|
||||
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SOURCE_CHANGE) != 0);
|
||||
|
||||
/* Turn on the 32 MHz XOSC and source the system clock on it. */
|
||||
REG(SYS_CTRL_CLOCK_CTRL) &= ~SYS_CTRL_CLOCK_CTRL_OSC;
|
||||
|
||||
/* Wait for the switch to take place */
|
||||
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_OSC) != 0);
|
||||
|
||||
/* Power down the unused oscillator. */
|
||||
REG(SYS_CTRL_CLOCK_CTRL) |= SYS_CTRL_CLOCK_CTRL_OSC_PD;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
select_16_mhz_rcosc(void)
|
||||
{
|
||||
/*
|
||||
* Power up both oscillators in order to speed up the transition to the 32-MHz
|
||||
* XOSC after wake up.
|
||||
*/
|
||||
REG(SYS_CTRL_CLOCK_CTRL) &= ~SYS_CTRL_CLOCK_CTRL_OSC_PD;
|
||||
|
||||
/*First, make sure there is no ongoing clock source change */
|
||||
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SOURCE_CHANGE) != 0);
|
||||
|
||||
@ -187,6 +199,16 @@ lpm_exit()
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* When returning from PM1/2, the sleep timer value (used by RTIMER_NOW()) is
|
||||
* not up-to-date until a positive edge on the 32-kHz clock has been detected
|
||||
* after the system clock restarted. To ensure an updated value is read, wait
|
||||
* for a positive transition on the 32-kHz clock by polling the
|
||||
* SYS_CTRL_CLOCK_STA.SYNC_32K bit, before reading the sleep timer value.
|
||||
*/
|
||||
while(REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SYNC_32K);
|
||||
while(!(REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SYNC_32K));
|
||||
|
||||
LPM_STATS_ADD(REG(SYS_CTRL_PMCTL) & SYS_CTRL_PMCTL_PM3,
|
||||
RTIMER_NOW() - sleep_enter_time);
|
||||
|
||||
@ -301,6 +323,11 @@ lpm_enter()
|
||||
select_32_mhz_xosc();
|
||||
|
||||
REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM0;
|
||||
|
||||
/* Remember IRQ energest for next pass */
|
||||
ENERGEST_IRQ_SAVE(irq_energest);
|
||||
ENERGEST_ON(ENERGEST_TYPE_CPU);
|
||||
ENERGEST_OFF(ENERGEST_TYPE_LPM);
|
||||
} else {
|
||||
/* All clear. Assert WFI and drop to PM1/2. This is now un-interruptible */
|
||||
assert_wfi();
|
||||
|
@ -150,6 +150,12 @@ void lpm_enter(void);
|
||||
* interrupt. This may lead to other parts of the code trying to use the RF,
|
||||
* so we need to switch the clock source \e before said code gets executed.
|
||||
*
|
||||
* This function also makes sure that the sleep timer value is up-to-date
|
||||
* following wake-up from PM1/2 so that RTIMER_NOW() works.
|
||||
*
|
||||
* \note This function should be called at the very beginning of ISRs waking up
|
||||
* the SoC in order to restore all clocks and timers.
|
||||
*
|
||||
* \sa lpm_enter(), rtimer_isr()
|
||||
*/
|
||||
void lpm_exit(void);
|
||||
|
@ -136,13 +136,6 @@ rtimer_arch_now()
|
||||
void
|
||||
rtimer_isr()
|
||||
{
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
next_trigger = 0;
|
||||
|
||||
nvic_interrupt_unpend(NVIC_INT_SM_TIMER);
|
||||
nvic_interrupt_disable(NVIC_INT_SM_TIMER);
|
||||
|
||||
/*
|
||||
* If we were in PM1+, call the wake-up sequence first. This will make sure
|
||||
* that the 32MHz OSC is selected as the clock source. We need to do this
|
||||
@ -150,6 +143,13 @@ rtimer_isr()
|
||||
*/
|
||||
lpm_exit();
|
||||
|
||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||
|
||||
next_trigger = 0;
|
||||
|
||||
nvic_interrupt_unpend(NVIC_INT_SM_TIMER);
|
||||
nvic_interrupt_disable(NVIC_INT_SM_TIMER);
|
||||
|
||||
rtimer_run_next();
|
||||
|
||||
ENERGEST_OFF(ENERGEST_TYPE_IRQ);
|
||||
|
Loading…
Reference in New Issue
Block a user