Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Low Power Proof of Concept #35

Open
richarthurs opened this issue Jan 30, 2018 · 4 comments
Open

Low Power Proof of Concept #35

richarthurs opened this issue Jan 30, 2018 · 4 comments
Assignees
Labels

Comments

@richarthurs
Copy link
Contributor

Using tickless idle, implement a proof of concept of low power entry.

@liquiddandruff
Copy link
Member

Related #22 + note that this would mean moving to cooperative scheduling from preemptive (big change).

@richarthurs
Copy link
Contributor Author

Is that still the case? I didn't see a reference to cooperative here: https://www.freertos.org/low-power-tickless-rtos.html

@liquiddandruff
Copy link
Member

Ah, tickless idle. Nevermind you're right, the stuff about the scheduler won't be relevant here: we do want the option for the idle task to run without tick interrupts, and doing so won't involve any change to the current scheduler.

I misread and thought we want to change the whole RTOS to be tickless :)

liquiddandruff added a commit that referenced this issue Jun 10, 2018
Setup:
- OBC/RF board set 1 compiled with STX strobe in rfTxTestSequence().
- OBC/RF board set 2 compiled with SRX strobe in rfTxTestSequence().
- In UART prompt, enter on both sets: > task resume 10
- Set 1 sample output:
...
radio task (0x0)
S 0x3d
 < 0x0f
tx_underflowed:no tx_numbytes:0
S 0x3d
 < 0x0f
TX FIFO_BYTES_AVAILABLE: 0xf
S 0xbd
 < 0x00
RX FIFO_BYTES_AVAILABLE: 0x0
S 0x3d
 < 0x0f
62 Bytes Radio TX FIFO written
AFTER: tx_underflowed:no tx_numbytes:62
S 0x35
 < 0x02
STX strobed...
S 0x3d
 < 0x24
StatusByte: 0x24
radio task (0x0)
S 0x3d
 < 0x0f
tx_underflowed:no tx_numbytes:0
S 0x3d
 < 0x0f
TX FIFO_BYTES_AVAILABLE: 0xf
S 0xbd
 < 0x00
RX FIFO_BYTES_AVAILABLE: 0x0
S 0x3d
 < 0x0f
62 Bytes Radio TX FIFO written
AFTER: tx_underflowed:no tx_numbytes:62
S 0x35
 < 0x02
STX strobed...
S 0x3d
 < 0x24
StatusByte: 0x24
radio task (0x0)
S 0x3d
 < 0x0f
tx_underflowed:no tx_numbytes:0
S 0x3d
 < 0x0f
TX FIFO_BYTES_AVAILABLE: 0xf
S 0xbd
 < 0x00
RX FIFO_BYTES_AVAILABLE: 0x0
S 0x3d
 < 0x0f
62 Bytes Radio TX FIFO written
AFTER: tx_underflowed:no tx_numbytes:62
S 0x35
 < 0x02
STX strobed...
S 0x3d
 < 0x24
StatusByte: 0x24

- Set 2 sample output:
...
radio task (0x0)
S 0x3d
< 0x02
tx_underflowed:no tx_numbytes:62
S 0x3d
< 0x02
TX FIFO_BYTES_AVAILABLE: 0x2
S 0xbd
< 0x0f
RX FIFO_BYTES_AVAILABLE: 0xf
S 0x3d
< 0x02
Radio did not write
AFTER: tx_underflowed:no tx_numbytes:62
S 0x34
< 0x02
STX strobed...
S 0x3d
< 0x12
StatusByte: 0x12
RX Byte #0: 3e
RX Byte #1: 10
RX Byte #2: 02
RX Byte #3: 03
RX Byte #4: 04
RX Byte #5: 05
RX Byte #6: 06
RX Byte #7: 07
RX Byte #8: 08
RX Byte #9: 09
RX Byte #10: 0a
RX Byte #11: 0b
RX Byte #12: 0c
RX Byte #13: 0d
RX Byte #14: 0e
RX Byte #15: 0f
RX Byte #16: 10
RX Byte #17: 11
RX Byte #18: 12
RX Byte #19: 13
RX Byte #20: 14
RX Byte #21: 15
RX Byte #22: 16
RX Byte #23: 17
RX Byte #24: 18
RX Byte #25: 19
RX Byte #26: 1a
RX Byte #27: 1b
RX Byte #28: 1c
RX Byte #29: 1d
RX Byte #30: 1e
RX Byte #31: 1f
RX Byte #32: 20
RX Byte #33: 21
RX Byte #34: 22
RX Byte #35: 23
RX Byte #36: 24
RX Byte #37: 25
RX Byte #38: 26
RX Byte #39: 27
RX Byte #40: 28
RX Byte #41: 29
RX Byte #42: 2a
RX Byte #43: 2b
RX Byte #44: 2c
RX Byte #45: 2d
RX Byte #46: 2e
RX Byte #47: 2f
RX Byte #48: 30
RX Byte #49: 31
RX Byte #50: 32
RX Byte #51: 33
RX Byte #52: 34
RX Byte #53: 35
RX Byte #54: 36
RX Byte #55: 37
RX Byte #56: 38
RX Byte #57: 39
RX Byte #58: 3a
RX Byte #59: 3b
RX Byte #60: 3c
RX Byte #61: 3d
RX Byte #62: e8
RX Byte #63: ba

Misc:
- Fix calculation of fifo bytes in writeToTxFIFO.
- TODO: readFromRxFIFO changed to always queuering FIFO_RX; change to check only when needed.
- Create IS_STATE macro to check state easily.
@richarthurs
Copy link
Contributor Author

richarthurs commented Jul 7, 2018

Background reading:

When searching for forum posts, try things like "hercules low power", "TMS570 sleep"

Power Saving Methods

Idle Task Low Power

The idle task is run by the RTOS at the lowest priority, and is used for freeing up memory and things like that. Using the idle task hook, which is just a function that the idle task will call, we can enter into a low power mode. When this is done, it means we are very frequently entering a low power mode for the duration of an RTOS tick (1 ms), and then exiting to check if other tasks need to be executed. Despite the frequent switching, it can still result in power savings.

To use this, we must place the processor into a sleep mode that is able to be woken up by the RTI (timer) interrupt, which is the RTOS tick.

This post has mention of keeping the RTI going while in low power mode: https://e2e.ti.com/support/microcontrollers/hercules/f/312/t/640585?CCS-Wakeup-hercules-from-Snooze-mode

This post has details about how interrupts are used to wake up from sleep, and a really simple sample application:
https://e2e.ti.com/support/microcontrollers/hercules/f/312/p/640687/2363875#2363875

We can essentially take the sleep() function from the post above and use that as our idle task hook, as long as everything is set up to wake up on RTI interrupt.

Tickless Idle

Tickless idle seems to be what we think about as “low power state” - it is controlled by the application and won’t happen automatically. https://www.freertos.org/low-power-tickless-rtos.html

Tickless idle will keep the system tick from interrupting the idle task constantly. To do this, it will do the following, when we ask to enter tickless idle:

  • Double check that it’s ok to stop running the RTOS (no tasks need to be executed)
  • Start another tick that is operable in a low power mode. This will time how long we’re in the low power mode. Call this the low power tick.
  • Enter low power mode
  • Exit from the low power mode is from some sort of interrupt - either a low power timer, an external event (such as RTC alarm or communication over radio)
  • When it exits, using the low power tick, it will determine how long it was sleeping for. The system tick will be adjusted accordingly. Tasks will restart.

This is the second thing we'll do. Low power state will place the satellite into low power mode for an extended period of time (multiple seconds), and will be woken up by some external source, such as an alarm from the RTC, or an incoming radio message. To get this working, we will need to set up the low power timer, and change some application logic to suspend everything before entry into this mode. It will be entirely controlled by us.

Experiment 1

Using a launchpad and by adapting the code from here: https://e2e.ti.com/support/microcontrollers/hercules/f/312/p/640687/2363875#2363875

  • create a new CCS and halcogen project for this
  • Do not call sleep() at the top of main. You MUST have a long busy-wait loop (multiple seconds) at the top of main. Once the wait is done, you can sleep. There have been forum posts about people bricking their chips by having them sleep as soon as they get power, which makes them impossible to program.
  • Figure out what registers are being written to during the sleep function
  • Figure out if any wake up source is enabled with the code
  • Create a demo that allows us to enter and exit sleep mode with a GPIO

Experiment 2

Implement idle task hook sleep mode. The wake up sources will need to be changed for this, but if experiment 1 is successful, experiment 2 should be straightforward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants