Skip to content

Commit 4302078

Browse files
committed
MCU8MASS-856 Fix a bug where power down would reset the board and reduce power consumption even more
1 parent 25101d1 commit 4302078

File tree

1 file changed

+127
-57
lines changed

1 file changed

+127
-57
lines changed

src/low_power.cpp

Lines changed: 127 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,17 @@
5252
#define TIMER_LENGTH 11
5353
#define TIMER_SLEEP_INDEX 8
5454

55-
#define RING_PORT VPORTC
56-
5755
#ifdef __AVR_AVR128DB48__ // MINI
5856

57+
#define RING_PORT VPORTC
5958
#define RING_PIN_bm PIN6_bm
6059

6160
#define LOWQ_PIN PIN_PB4
6261
#define VOLTAGE_MEASURE_EN_PIN PIN_PB3
6362
#define VOLTAGE_MEASURE_PIN PIN_PE0
6463

64+
#define EEPROM_CS_PIN PIN_PE3
65+
6566
#define DEBUGGER_TX_PIN PIN_PB0
6667
#define DEBUGGER_RX_PIN PIN_PB1
6768
#define DEBUGGER_LED_PIN PIN_PB2
@@ -73,16 +74,26 @@
7374
#define I2C1_SDA_PIN PIN_PF2
7475
#define I2C1_SCL_PIN PIN_PF3
7576

77+
#define SPI_CS PIN_PB5
78+
#define SPI_MOSI PIN_PA4
79+
#define SPI_MISO PIN_PA5
80+
#define SPI_SCK PIN_PA6
81+
82+
#define SW0_PORT PORTD
83+
7684
#else
7785

7886
#ifdef __AVR_AVR128DB64__ // Non-Mini
7987

88+
#define RING_PORT VPORTC
8089
#define RING_PIN_bm PIN4_bm
8190

8291
#define LOWQ_PIN PIN_PB4
8392
#define VOLTAGE_MEASURE_EN_PIN PIN_PB3
8493
#define VOLTAGE_MEASURE_PIN PIN_PE0
8594

95+
#define EEPROM_CS_PIN PIN_PE3
96+
8697
#define DEBUGGER_TX_PIN PIN_PB0
8798
#define DEBUGGER_RX_PIN PIN_PB1
8899
#define DEBUGGER_LED_PIN PIN_PB2
@@ -94,6 +105,13 @@
94105
#define I2C1_SDA_PIN PIN_PF2
95106
#define I2C1_SCL_PIN PIN_PF3
96107

108+
#define SPI_CS PIN_PB5
109+
#define SPI_MOSI PIN_PA4
110+
#define SPI_MISO PIN_PA5
111+
#define SPI_SCK PIN_PA6
112+
113+
#define SW0_PORT PORTD
114+
97115
#else
98116
#error "INCOMPATIBLE_DEVICE_SELECTED"
99117
#endif
@@ -331,70 +349,119 @@ static void disablePIT(void) {
331349
RTC.PITCTRLA &= ~RTC_PITEN_bm;
332350
}
333351

352+
static void setPinLowPowerMode(const uint8_t pin, const bool pull_up = true) {
353+
354+
if (pull_up) {
355+
pinConfigure(pin,
356+
PIN_DIR_INPUT | PIN_ISC_DISABLE | PIN_PULLUP_ON |
357+
PIN_INPUT_DISABLE);
358+
} else {
359+
pinConfigure(pin, PIN_DIR_INPUT | PIN_ISC_DISABLE | PIN_INPUT_DISABLE);
360+
}
361+
}
362+
363+
static void setPinNormalInputMode(const uint8_t pin) {
364+
pinConfigure(pin, PIN_DIR_INPUT | PIN_PULLUP_OFF | PIN_INPUT_ENABLE);
365+
}
366+
367+
static void setPinNormalOutputMode(const uint8_t pin) {
368+
pinConfigure(pin, PIN_DIR_OUTPUT | PIN_PULLUP_OFF | PIN_INPUT_ENABLE);
369+
}
370+
334371
static void powerDownPeripherals(void) {
335-
// LEDs
336-
pinConfigure(LedCtrl.getLedPin(Led::CELL),
337-
PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
338-
pinConfigure(LedCtrl.getLedPin(Led::CON),
339-
PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
340-
pinConfigure(LedCtrl.getLedPin(Led::DATA),
341-
PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
342-
pinConfigure(LedCtrl.getLedPin(Led::ERROR),
343-
PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
344-
pinConfigure(LedCtrl.getLedPin(Led::USER),
345-
PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
346-
347-
// Make sure that I2C pins are pulled up and there won't be a voltage drop
348-
// over them over the external pull up resistors
349-
pinConfigure(I2C0_SDA_PIN, PIN_DIR_OUTPUT | PIN_PULLUP_ON);
350-
pinConfigure(I2C0_SCL_PIN, PIN_DIR_OUTPUT | PIN_PULLUP_ON);
351-
pinConfigure(I2C1_SDA_PIN, PIN_DIR_OUTPUT | PIN_PULLUP_ON);
352-
pinConfigure(I2C1_SCL_PIN, PIN_DIR_OUTPUT | PIN_PULLUP_ON);
353372

354-
// Voltage measure
355-
digitalWrite(VOLTAGE_MEASURE_EN_PIN, LOW);
373+
// EEPROM - Set in standby mode
374+
setPinLowPowerMode(EEPROM_CS_PIN);
375+
376+
// I2C
377+
//
378+
// We don't pull up the I2C lines as they have external pull-ups
379+
Wire.end();
380+
Wire1.end();
381+
setPinLowPowerMode(I2C0_SDA_PIN, false);
382+
setPinLowPowerMode(I2C0_SCL_PIN, false);
383+
setPinLowPowerMode(I2C1_SDA_PIN, false);
384+
setPinLowPowerMode(I2C1_SCL_PIN, false);
385+
386+
// SPI
387+
setPinLowPowerMode(SPI_CS);
388+
setPinLowPowerMode(SPI_MOSI);
389+
setPinLowPowerMode(SPI_MOSI);
390+
setPinLowPowerMode(SPI_SCK);
391+
392+
// Debugger, add pull-ups on pins for USART TX & RX, as well as LED pin
356393

357-
// Debugger
358394
DEBUGGER_USART.CTRLB &= ~(USART_RXEN_bm | USART_TXEN_bm);
359-
pinConfigure(DEBUGGER_TX_PIN,
360-
PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
361-
pinConfigure(DEBUGGER_RX_PIN,
362-
PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
363-
pinConfigure(DEBUGGER_LED_PIN,
364-
PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
365-
pinConfigure(DEBUGGER_SW0_PIN,
366-
PIN_DIR_INPUT | PIN_PULLUP_ON | PIN_INPUT_DISABLE);
395+
setPinLowPowerMode(DEBUGGER_TX_PIN);
396+
setPinLowPowerMode(DEBUGGER_RX_PIN);
397+
setPinLowPowerMode(DEBUGGER_LED_PIN);
398+
399+
// Only enable pull-up for SW0 to not have current over it, but keep active
400+
// for waking the device up by the button
401+
SW0_PORT.PIN2CTRL |= PORT_PULLUPEN_bm;
402+
403+
// LEDs
404+
setPinLowPowerMode(LedCtrl.getLedPin(Led::CELL));
405+
setPinLowPowerMode(LedCtrl.getLedPin(Led::CON));
406+
setPinLowPowerMode(LedCtrl.getLedPin(Led::DATA));
407+
setPinLowPowerMode(LedCtrl.getLedPin(Led::ERROR));
408+
setPinLowPowerMode(LedCtrl.getLedPin(Led::USER));
409+
410+
// Disable ADC0, used for analogRead
411+
ADC0.CTRLA &= ~ADC_ENABLE_bm;
412+
413+
// Voltage measure enable and voltage measure pins have external pull-up
414+
setPinLowPowerMode(VOLTAGE_MEASURE_EN_PIN, false);
415+
setPinLowPowerMode(VOLTAGE_MEASURE_PIN, false);
416+
417+
// Disable millis() timer
418+
stop_millis();
367419
}
368420

369421
static void powerUpPeripherals() {
370422

371-
pinConfigure(LedCtrl.getLedPin(Led::CELL),
372-
PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
373-
pinConfigure(LedCtrl.getLedPin(Led::CON),
374-
PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
375-
pinConfigure(LedCtrl.getLedPin(Led::DATA),
376-
PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
377-
pinConfigure(LedCtrl.getLedPin(Led::ERROR),
378-
PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
379-
pinConfigure(LedCtrl.getLedPin(Led::USER),
380-
PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
381-
382-
// Make sure that I2C pins are pulled up and there won't be a voltage drop
383-
// over them
384-
pinConfigure(I2C0_SDA_PIN, PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
385-
pinConfigure(I2C0_SCL_PIN, PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
386-
pinConfigure(I2C1_SDA_PIN, PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
387-
pinConfigure(I2C1_SCL_PIN, PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
423+
// Enable millis() timer
424+
restart_millis();
388425

389426
// Voltage measure
390-
digitalWrite(VOLTAGE_MEASURE_PIN, HIGH);
427+
setPinNormalInputMode(VOLTAGE_MEASURE_PIN);
428+
setPinNormalOutputMode(VOLTAGE_MEASURE_EN_PIN);
429+
430+
// ADC for analogRead
431+
init_ADC0();
432+
433+
// LEDs
434+
setPinNormalOutputMode(LedCtrl.getLedPin(Led::CELL));
435+
setPinNormalOutputMode(LedCtrl.getLedPin(Led::CON));
436+
setPinNormalOutputMode(LedCtrl.getLedPin(Led::DATA));
437+
setPinNormalOutputMode(LedCtrl.getLedPin(Led::ERROR));
438+
setPinNormalOutputMode(LedCtrl.getLedPin(Led::USER));
391439

392440
// Debugger
393-
DEBUGGER_USART.CTRLB |= (USART_RXEN_bm | USART_TXEN_bm);
394-
pinConfigure(DEBUGGER_TX_PIN, PIN_DIR_OUTPUT);
395-
pinConfigure(DEBUGGER_RX_PIN, PIN_DIR_INPUT | PIN_INPUT_ENABLE);
396-
pinConfigure(DEBUGGER_LED_PIN, PIN_DIR_OUTPUT);
397-
pinConfigure(DEBUGGER_SW0_PIN, PIN_DIR_OUTPUT | PIN_INPUT_ENABLE);
441+
setPinNormalOutputMode(DEBUGGER_TX_PIN);
442+
setPinNormalInputMode(DEBUGGER_RX_PIN);
443+
setPinNormalOutputMode(DEBUGGER_LED_PIN);
444+
445+
SW0_PORT.PIN2CTRL &= ~PORT_PULLUPEN_bm;
446+
447+
DEBUGGER_USART.CTRLB |= USART_TXEN_bm | USART_RXEN_bm;
448+
449+
// I2C
450+
setPinNormalOutputMode(I2C0_SDA_PIN);
451+
setPinNormalOutputMode(I2C0_SCL_PIN);
452+
setPinNormalOutputMode(I2C1_SDA_PIN);
453+
setPinNormalOutputMode(I2C1_SCL_PIN);
454+
Wire.begin();
455+
Wire1.begin();
456+
457+
// SPI
458+
setPinNormalOutputMode(SPI_CS);
459+
setPinNormalOutputMode(SPI_MOSI);
460+
setPinNormalInputMode(SPI_MISO);
461+
setPinNormalOutputMode(SPI_SCK);
462+
463+
// EEPROM
464+
setPinNormalOutputMode(EEPROM_CS_PIN);
398465
}
399466

400467
static void enableLDO(void) {
@@ -403,15 +470,15 @@ static void enableLDO(void) {
403470
digitalWrite(LOWQ_PIN, HIGH);
404471

405472
// Wait a little to let LDO mode settle
406-
delay(10);
473+
delay(100);
407474
}
408475

409476
static void disableLDO(void) {
410477
pinConfigure(LOWQ_PIN, PIN_DIR_OUTPUT);
411478
digitalWrite(LOWQ_PIN, LOW);
412479

413480
// Wait a little to let PWM mode settle
414-
delay(10);
481+
delay(100);
415482
}
416483

417484
void LowPowerClass::configurePowerDown(void) {
@@ -553,7 +620,6 @@ void LowPowerClass::powerDown(const uint32_t power_down_time_seconds) {
553620

554621
const unsigned long start_time_ms = millis();
555622

556-
powerDownPeripherals();
557623
SLPCTRL.CTRLA |= SLPCTRL_SMODE_PDOWN_gc | SLPCTRL_SEN_bm;
558624

559625
Lte.end();
@@ -564,6 +630,10 @@ void LowPowerClass::powerDown(const uint32_t power_down_time_seconds) {
564630
power_down_time_seconds -
565631
(uint32_t)(((millis() - start_time_ms) / 1000.0f));
566632

633+
// Need to power down the peripherals here as we want to grab the time
634+
// (millis()) from the timer before disabling it
635+
powerDownPeripherals();
636+
567637
while (remaining_time_seconds > 0) {
568638

569639
sleep_cpu();

0 commit comments

Comments
 (0)