Add 'Wake CPU' functionality #24
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Following on from the discussion here and here, This PR adds an optional argument to the
#[interrupt]
proc-macro that returns the CPU to Active Mode after the interrupt completes.This behaviour is usually controlled by the status register, which can be freely written to outside of an interrupt. However, if the CPU is turned off then the only time the CPU wakes up again is during an interrupt. Unfortunately the status register can't be naively written to during an interrupt, as the previous state of the status register is pushed onto the stack before an interrupt begins and this value is restored after the interrupt returns, making any changes to the status register itself during an interrupt temporary.
To make permanent changes to the system state we must modify the copy of the status register that was pushed to the stack. In msp430-gcc this is handled by a compiler intrinsic, which isn't available to us here. Instead, we can use a naked function to ensure that nothing is pushed to the stack before our code runs (proof of concept), modify the item most recently pushed to the stack (the copy of the status register), then run the user interrupt handler.
This is implemented as an optional argument to the
#[interrupt]
proc-macro. The behaviour of#[interrupt]
is untouched, and the new functionality is enabled when#[interrupt(wake_cpu)]
is used.As a refresher, consider the existing interrupt handler macro:
This expands to the following:
With the new
wake_cpu
option:expands to:
All the bits related to low power modes are cleared, as only clearing CPU_OFF may put the MSP430 into one of the undocumented power modes.
This isn't an ideal solution, as we still can't conditionally write to the copy of the status register on the stack like you could with the compiler intrinsics (e.g. GCC has
__bic_sr_register_on_exit()
which can be called anywhere within an interrupt handler)A full working example can be seen here, which runs on an MSP-EXP430FR2355 dev board (build with
cargo run --example lpm0
).Any comments or modifications welcome.