Merge pull request #494 from ADVANSEE/cc2538-lpm-fixes
cc2538: lpm: Fix several issues
This commit is contained in:
commit
79e6514c80
4 changed files with 48 additions and 15 deletions
|
@ -83,10 +83,10 @@ notify(uint8_t mask, uint8_t port)
|
||||||
void
|
void
|
||||||
gpio_port_a_isr()
|
gpio_port_a_isr()
|
||||||
{
|
{
|
||||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
|
||||||
|
|
||||||
lpm_exit();
|
lpm_exit();
|
||||||
|
|
||||||
|
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||||
|
|
||||||
notify(REG(GPIO_A_BASE | GPIO_MIS), GPIO_A_NUM);
|
notify(REG(GPIO_A_BASE | GPIO_MIS), GPIO_A_NUM);
|
||||||
|
|
||||||
GPIO_CLEAR_INTERRUPT(GPIO_A_BASE, 0xFF);
|
GPIO_CLEAR_INTERRUPT(GPIO_A_BASE, 0xFF);
|
||||||
|
@ -99,10 +99,10 @@ gpio_port_a_isr()
|
||||||
void
|
void
|
||||||
gpio_port_b_isr()
|
gpio_port_b_isr()
|
||||||
{
|
{
|
||||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
|
||||||
|
|
||||||
lpm_exit();
|
lpm_exit();
|
||||||
|
|
||||||
|
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||||
|
|
||||||
notify(REG(GPIO_B_BASE | GPIO_MIS), GPIO_B_NUM);
|
notify(REG(GPIO_B_BASE | GPIO_MIS), GPIO_B_NUM);
|
||||||
|
|
||||||
GPIO_CLEAR_INTERRUPT(GPIO_B_BASE, 0xFF);
|
GPIO_CLEAR_INTERRUPT(GPIO_B_BASE, 0xFF);
|
||||||
|
@ -115,10 +115,10 @@ gpio_port_b_isr()
|
||||||
void
|
void
|
||||||
gpio_port_c_isr()
|
gpio_port_c_isr()
|
||||||
{
|
{
|
||||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
|
||||||
|
|
||||||
lpm_exit();
|
lpm_exit();
|
||||||
|
|
||||||
|
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||||
|
|
||||||
notify(REG(GPIO_C_BASE | GPIO_MIS), GPIO_C_NUM);
|
notify(REG(GPIO_C_BASE | GPIO_MIS), GPIO_C_NUM);
|
||||||
|
|
||||||
GPIO_CLEAR_INTERRUPT(GPIO_C_BASE, 0xFF);
|
GPIO_CLEAR_INTERRUPT(GPIO_C_BASE, 0xFF);
|
||||||
|
@ -131,10 +131,10 @@ gpio_port_c_isr()
|
||||||
void
|
void
|
||||||
gpio_port_d_isr()
|
gpio_port_d_isr()
|
||||||
{
|
{
|
||||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
|
||||||
|
|
||||||
lpm_exit();
|
lpm_exit();
|
||||||
|
|
||||||
|
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
||||||
|
|
||||||
notify(REG(GPIO_D_BASE | GPIO_MIS), GPIO_D_NUM);
|
notify(REG(GPIO_D_BASE | GPIO_MIS), GPIO_D_NUM);
|
||||||
|
|
||||||
GPIO_CLEAR_INTERRUPT(GPIO_D_BASE, 0xFF);
|
GPIO_CLEAR_INTERRUPT(GPIO_D_BASE, 0xFF);
|
||||||
|
|
|
@ -158,16 +158,28 @@ enter_pm0(void)
|
||||||
static void
|
static void
|
||||||
select_32_mhz_xosc(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. */
|
/* Turn on the 32 MHz XOSC and source the system clock on it. */
|
||||||
REG(SYS_CTRL_CLOCK_CTRL) &= ~SYS_CTRL_CLOCK_CTRL_OSC;
|
REG(SYS_CTRL_CLOCK_CTRL) &= ~SYS_CTRL_CLOCK_CTRL_OSC;
|
||||||
|
|
||||||
/* Wait for the switch to take place */
|
/* Wait for the switch to take place */
|
||||||
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_OSC) != 0);
|
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
|
static void
|
||||||
select_16_mhz_rcosc(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 */
|
/*First, make sure there is no ongoing clock source change */
|
||||||
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SOURCE_CHANGE) != 0);
|
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SOURCE_CHANGE) != 0);
|
||||||
|
|
||||||
|
@ -187,6 +199,16 @@ lpm_exit()
|
||||||
return;
|
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,
|
LPM_STATS_ADD(REG(SYS_CTRL_PMCTL) & SYS_CTRL_PMCTL_PM3,
|
||||||
RTIMER_NOW() - sleep_enter_time);
|
RTIMER_NOW() - sleep_enter_time);
|
||||||
|
|
||||||
|
@ -301,6 +323,11 @@ lpm_enter()
|
||||||
select_32_mhz_xosc();
|
select_32_mhz_xosc();
|
||||||
|
|
||||||
REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM0;
|
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 {
|
} else {
|
||||||
/* All clear. Assert WFI and drop to PM1/2. This is now un-interruptible */
|
/* All clear. Assert WFI and drop to PM1/2. This is now un-interruptible */
|
||||||
assert_wfi();
|
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,
|
* 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.
|
* 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()
|
* \sa lpm_enter(), rtimer_isr()
|
||||||
*/
|
*/
|
||||||
void lpm_exit(void);
|
void lpm_exit(void);
|
||||||
|
|
|
@ -136,13 +136,6 @@ rtimer_arch_now()
|
||||||
void
|
void
|
||||||
rtimer_isr()
|
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
|
* 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
|
* that the 32MHz OSC is selected as the clock source. We need to do this
|
||||||
|
@ -150,6 +143,13 @@ rtimer_isr()
|
||||||
*/
|
*/
|
||||||
lpm_exit();
|
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();
|
rtimer_run_next();
|
||||||
|
|
||||||
ENERGEST_OFF(ENERGEST_TYPE_IRQ);
|
ENERGEST_OFF(ENERGEST_TYPE_IRQ);
|
||||||
|
|
Loading…
Reference in a new issue