Skip to content

Commit

Permalink
Merge pull request #2214 from rousselk/msp430-fix-intr
Browse files Browse the repository at this point in the history
Msp430 misc interrupt-related fixes
  • Loading branch information
OlegHahm committed Dec 19, 2014
2 parents 6a35845 + 892268d commit db58a8b
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 25 deletions.
20 changes: 14 additions & 6 deletions cpu/msp430-common/include/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ extern "C" {
extern volatile int __inISR;
extern char __isr_stack[MSP430_ISR_STACK_SIZE];

//#define eINT() eint()
//#define dINT() dint()
/*#define eINT() eint() */
/*#define dINT() dint() */

inline void __save_context_isr(void)
{
Expand Down Expand Up @@ -125,14 +125,22 @@ inline void __restore_context(unsigned int irqen)

inline void eINT(void)
{
// puts("+");
eint();
/* puts("+"); */
/* eint(); // problem with MSPGCC intrinsics? */
__asm__ __volatile__("bis %0, r2" : : "i"(GIE));
__asm__ __volatile__("nop");
/* this NOP is needed to handle a "delay slot" that all MSP430 MCUs
impose silently after messing with the GIE bit, DO NOT REMOVE IT! */
}

inline void dINT(void)
{
// puts("-");
dint();
/* puts("-"); */
/* dint(); // problem with MSPGCC intrinsics? */
__asm__ __volatile__("bic %0, r2" : : "i"(GIE));
__asm__ __volatile__("nop");
/* this NOP is needed to handle a "delay slot" that all MSP430 MCUs
impose silently after messing with the GIE bit, DO NOT REMOVE IT! */
}

int inISR(void);
Expand Down
49 changes: 30 additions & 19 deletions cpu/msp430-common/lpm_cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@
/* Initialise the MSP430 power-saving mechanisms. */
void lpm_init(void)
{
// nothing to initialize on MSP430s: everything is done by fiddling
// with 4 bits of the status register (SR).
/* nothing to initialize on MSP430s: everything is done by fiddling
with 4 bits of the status register (SR). */

// just ensure MCU is fully up and running at start
/* just ensure MCU is fully up and running at start */
lpm_awake();
}

Expand All @@ -45,33 +45,44 @@ enum lpm_mode lpm_set(enum lpm_mode target)
{
enum lpm_mode last_mode = lpm_get();

/* ensure that interrupts are enabled before going to sleep,
or we're bound to hang our MCU! */
if (target != LPM_ON) {
if ((__read_status_register() & GIE) == 0) {
printf("WARNING: entering low-power mode with interrupts disabled!\n");
printf(" Forcing GIE bit to 1!\n\n");
__bis_status_register(GIE);
}
}

switch (target)
{
case LPM_ON:
// fully running MCU
/* fully running MCU */
__bic_status_register(CPUOFF | OSCOFF | SCG0 | SCG1);
break;
case LPM_IDLE:
// lightest mode => LPM0 mode of MSP430
/* lightest mode => LPM0 mode of MSP430 */
__bic_status_register(OSCOFF | SCG0 | SCG1);
// only stops CPU block
/* only stops CPU block */
__bis_status_register(CPUOFF);
break;
case LPM_SLEEP:
// mid-level mode => LPM1 mode of MSP430
/* mid-level mode => LPM1 mode of MSP430 */
__bic_status_register(OSCOFF | SCG1);
// stops CPU and master clock blocks
/* stops CPU and master clock blocks */
__bis_status_register(CPUOFF | SCG0);
break;
case LPM_POWERDOWN:
// deep-level mode => LPM3 mode of MSP430
/* deep-level mode => LPM3 mode of MSP430 */
__bic_status_register(OSCOFF);
// stops all blocks except auxiliary clock (timers)
/* stops all blocks except auxiliary clock (timers) */
__bis_status_register(CPUOFF | SCG0 | SCG1);
break;
case LPM_OFF:
// MCU totally down (LPM4), only RESET or NMI can resume execution
__bis_status_register(CPUOFF | OSCOFF | SCG0 | SCG1); // all blocks off
/* MCU totally down (LPM4), only RESET or NMI can resume execution */
__bis_status_register(CPUOFF | OSCOFF | SCG0 | SCG1);
/* all blocks off */
break;
default:
printf("ERROR: trying to set an invalid low-power mode!\n");
Expand All @@ -90,20 +101,20 @@ enum lpm_mode lpm_get(void)

unsigned int current_sr = __read_status_register();
switch (current_sr & LPM_MASK_SR) {
case CPUOFF + OSCOFF + SCG0 + SCG1: // MSP430's LPM4
case CPUOFF + OSCOFF + SCG0 + SCG1: /* MSP430's LPM4 */
current_mode = LPM_OFF;
break;
case CPUOFF + SCG0 + SCG1: // MSP430's LPM3
case CPUOFF + SCG1: // MSP430's LPM2
case CPUOFF + SCG0 + SCG1: /* MSP430's LPM3 */
case CPUOFF + SCG1: /* MSP430's LPM2 */
current_mode = LPM_POWERDOWN;
break;
case CPUOFF + SCG0: // MSP430's LPM1
case CPUOFF + SCG0: /* MSP430's LPM1 */
current_mode = LPM_SLEEP;
break;
case CPUOFF: // MSP430's LPM1
case CPUOFF: /* MSP430's LPM1 */
current_mode = LPM_IDLE;
break;
case 0: // MSP430 active
case 0: /* MSP430 active */
current_mode = LPM_ON;
break;
}
Expand All @@ -114,7 +125,7 @@ enum lpm_mode lpm_get(void)
/* resume the MSP430 MCU */
inline void lpm_awake(void)
{
// disable all power savings mechanisms
/* disable all power savings mechanisms */
__bic_status_register(CPUOFF | OSCOFF | SCG0 | SCG1);
}

Expand Down
3 changes: 3 additions & 0 deletions cpu/msp430-common/msp430-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ splhigh_(void)
int sr;
asmv("mov r2, %0" : "=r"(sr));
asmv("bic %0, r2" : : "i"(GIE));
asmv("nop");
return sr & GIE; /* Ignore other sr bits. */
}
/*---------------------------------------------------------------------------*/
Expand All @@ -169,8 +170,10 @@ splhigh_(void)
void
splx_(int sr)
{
sr &= GIE;
/* If GIE was set, restore it. */
asmv("bis %0, r2" : : "r"(sr));
asmv("nop");
}
/*---------------------------------------------------------------------------*/

Expand Down

0 comments on commit db58a8b

Please sign in to comment.