diff --git a/cores/arduino/am_sdk_ap3/mcu/apollo3/hal/am_hal_pin.h b/cores/arduino/am_sdk_ap3/mcu/apollo3/hal/am_hal_pin.h index 2339969a..0577824b 100644 --- a/cores/arduino/am_sdk_ap3/mcu/apollo3/hal/am_hal_pin.h +++ b/cores/arduino/am_sdk_ap3/mcu/apollo3/hal/am_hal_pin.h @@ -70,6 +70,7 @@ #define AM_HAL_PIN_1_MSPI5 (5) #define AM_HAL_PIN_1_NCE1 (7) +#define AM_HAL_PIN_2_UART1RX (0) #define AM_HAL_PIN_2_SLMISO (1) #define AM_HAL_PIN_2_UART0RX (2) #define AM_HAL_PIN_2_GPIO (3) @@ -89,7 +90,7 @@ #define AM_HAL_PIN_4_SLINT (1) #define AM_HAL_PIN_4_NCE4 (2) #define AM_HAL_PIN_4_GPIO (3) -#define AM_HAL_PIN_4_UART0RX (5) +#define AM_HAL_PIN_4_UART1RX (5) #define AM_HAL_PIN_4_CTIM17 (6) #define AM_HAL_PIN_4_MSPI2 (7) @@ -129,6 +130,7 @@ #define AM_HAL_PIN_9_SCCIO (4) #define AM_HAL_PIN_9_UART1RX (6) +#define AM_HAL_PIN_10_UART1TX (0) #define AM_HAL_PIN_10_M1MOSI (1) #define AM_HAL_PIN_10_NCE10 (2) #define AM_HAL_PIN_10_GPIO (3) @@ -437,7 +439,7 @@ #define AM_HAL_PIN_44_CTIM20 (2) #define AM_HAL_PIN_44_GPIO (3) #define AM_HAL_PIN_44_M4MOSI (5) -#define AM_HAL_PIN_44_M5nCE6 (6) +#define AM_HAL_PIN_44_UART0TX (6) #if defined (AM_PACKAGE_BGA) #define AM_HAL_PIN_45_UART1CTS (0) diff --git a/cores/arduino/ard_sup/ap3_uart_types.h b/cores/arduino/ard_sup/ap3_uart_types.h index 7c66aca2..c74ab2e4 100644 --- a/cores/arduino/ard_sup/ap3_uart_types.h +++ b/cores/arduino/ard_sup/ap3_uart_types.h @@ -25,13 +25,13 @@ SOFTWARE. #define AP3_UART_PIN_UNUSED 0xFF -#define AP3_UART0_NUM_TX_PADS 11 -#define AP3_UART0_NUM_RX_PADS 13 +#define AP3_UART0_NUM_TX_PADS 12 +#define AP3_UART0_NUM_RX_PADS 12 #define AP3_UART0_NUM_RTS_PADS 8 #define AP3_UART0_NUM_CTS_PADS 8 -#define AP3_UART1_NUM_TX_PADS 11 -#define AP3_UART1_NUM_RX_PADS 11 +#define AP3_UART1_NUM_TX_PADS 12 +#define AP3_UART1_NUM_RX_PADS 13 #define AP3_UART1_NUM_RTS_PADS 8 #define AP3_UART1_NUM_CTS_PADS 8 diff --git a/cores/arduino/ard_sup/uart/ap3_uart_structures.c b/cores/arduino/ard_sup/uart/ap3_uart_structures.c index dbab963a..eb3cec34 100644 --- a/cores/arduino/ard_sup/uart/ap3_uart_structures.c +++ b/cores/arduino/ard_sup/uart/ap3_uart_structures.c @@ -35,12 +35,12 @@ const ap3_uart_pad_map_elem_t ap3_uart0_tx_map[AP3_UART0_NUM_TX_PADS] = { {.pad = 30, .funcsel = AM_HAL_PIN_30_UART0TX}, {.pad = 39, .funcsel = AM_HAL_PIN_39_UART0TX}, {.pad = 41, .funcsel = AM_HAL_PIN_41_UART0TX}, + {.pad = 44, .funcsel = AM_HAL_PIN_44_UART0TX}, {.pad = 48, .funcsel = AM_HAL_PIN_48_UART0TX}, }; const ap3_uart_pad_map_elem_t ap3_uart0_rx_map[AP3_UART0_NUM_RX_PADS] = { {.pad = 2, .funcsel = AM_HAL_PIN_2_UART0RX}, - {.pad = 4, .funcsel = AM_HAL_PIN_4_UART0RX}, {.pad = 11, .funcsel = AM_HAL_PIN_11_UART0RX}, {.pad = 17, .funcsel = AM_HAL_PIN_17_UART0RX}, {.pad = 21, .funcsel = AM_HAL_PIN_21_UART0RX}, @@ -72,12 +72,13 @@ const ap3_uart_pad_map_elem_t ap3_uart0_cts_map[AP3_UART0_NUM_CTS_PADS] = { {.pad = 24, .funcsel = AM_HAL_PIN_24_UART0CTS}, {.pad = 29, .funcsel = AM_HAL_PIN_29_UART0CTS}, {.pad = 33, .funcsel = AM_HAL_PIN_33_UART0CTS}, - {.pad = 26, .funcsel = AM_HAL_PIN_36_UART0CTS}, + {.pad = 36, .funcsel = AM_HAL_PIN_36_UART0CTS}, {.pad = 38, .funcsel = AM_HAL_PIN_38_UART0CTS}, }; const ap3_uart_pad_map_elem_t ap3_uart1_tx_map[AP3_UART1_NUM_TX_PADS] = { {.pad = 8, .funcsel = AM_HAL_PIN_8_UART1TX}, + {.pad = 10, .funcsel = AM_HAL_PIN_10_UART1TX}, {.pad = 12, .funcsel = AM_HAL_PIN_12_UART1TX}, {.pad = 14, .funcsel = AM_HAL_PIN_14_UART1TX}, {.pad = 18, .funcsel = AM_HAL_PIN_18_UART1TX}, @@ -91,7 +92,9 @@ const ap3_uart_pad_map_elem_t ap3_uart1_tx_map[AP3_UART1_NUM_TX_PADS] = { }; const ap3_uart_pad_map_elem_t ap3_uart1_rx_map[AP3_UART1_NUM_RX_PADS] = { - {.pad = 9, .funcsel = AM_HAL_PIN_9_UART1RX}, + {.pad = 2, .funcsel = AM_HAL_PIN_2_UART1RX}, + {.pad = 4, .funcsel = AM_HAL_PIN_4_UART1RX}, + {.pad = 9, .funcsel = AM_HAL_PIN_9_UART1RX}, {.pad = 13, .funcsel = AM_HAL_PIN_13_UART1RX}, {.pad = 15, .funcsel = AM_HAL_PIN_15_UART1RX}, {.pad = 19, .funcsel = AM_HAL_PIN_19_UART1RX}, diff --git a/docs/ACKNOWLEDGEMENTS.md b/docs/ACKNOWLEDGEMENTS.md index c48b2c42..f122b855 100644 --- a/docs/ACKNOWLEDGEMENTS.md +++ b/docs/ACKNOWLEDGEMENTS.md @@ -8,8 +8,9 @@ Thank you to everyone who has contributed! Contributors ============ -* Jim Lindblom +* Stephen Fordyce * Kenny Hora +* Jim Lindblom * Owen Lyke * Aaron Micyus -* Nathan Seidle +* Nathan Seidle \ No newline at end of file diff --git a/libraries/Examples/examples/Advanced/LowPower_WithWorkAndGPIOInterrupt/LowPower_WithWorkAndGPIOInterrupt.ino b/libraries/Examples/examples/Advanced/LowPower_WithWorkAndGPIOInterrupt/LowPower_WithWorkAndGPIOInterrupt.ino new file mode 100644 index 00000000..744b08da --- /dev/null +++ b/libraries/Examples/examples/Advanced/LowPower_WithWorkAndGPIOInterrupt/LowPower_WithWorkAndGPIOInterrupt.ino @@ -0,0 +1,160 @@ +/* + LowPower_WithWorkAndGPIOInterrupt + Adapted by Stephen Fordyce 2020-03-23 from: + Artemis Low Power: How low can we go? + By: Nathan Seidle + SparkFun Electronics + Date: February 26th, 2020 + License: This code is public domain. +*/ + +uint32_t msToSleep = 5000; //This is the user editable number of ms to sleep between RTC checks +#define TIMER_FREQ 32768L //Counter/Timer 6 will use the 32kHz clock +uint32_t sysTicksToSleep = msToSleep * TIMER_FREQ / 1000; + +const byte STATUS_LED = 14;//13 for Redboard onboard LED, 19 for Nano onboard LED +const byte INPUT_BUTTON = 19;//You'll have to add one, it needs to connect to GND for active + +bool awakeFlag = true; //Stops wakeFromSleep() being run if the system is already awake + + +// GPIO Interrupt Service Routine +void myGPIO_ISR(void) +{ + detachInterrupt(digitalPinToInterrupt(INPUT_BUTTON)); //Stop interrupt from being triggered again + wakeFromSleep(); //Without waking the processor properly, nothing more will happen. This means wakeFromSleep() is called twice though. +// am_hal_stimer_compare_delta_set(6, 0); //Or, force the timer to run out, and resume from where you left off. +} + + +void setup(void) { + Serial.begin(115200); + Serial.println("Artemis Low Power (with timer & GPIO wakeup) Example"); + pinMode(STATUS_LED, OUTPUT); + pinMode(INPUT_BUTTON, INPUT_PULLUP); + //Initialise stuff like I2C/Wire/SPI here +} + + +void loop(void) { + Serial.println("Starting loop, and flashing LED"); + digitalWrite(STATUS_LED, HIGH); + delay(200); + digitalWrite(STATUS_LED, LOW); + Serial.println("Phew, that was hard work, sleep for 4 seconds"); + msToSleep = 4000; + sysTicksToSleep = msToSleep * TIMER_FREQ / 1000; + goToSleep(); +} + + +//Power everything down and wait for interrupt wakeup +void goToSleep() +{ + attachInterrupt(digitalPinToInterrupt(INPUT_BUTTON), myGPIO_ISR, FALLING); + + //End stuff like I2C/Wire/SPI here + + power_adc_disable(); //Power down ADC. It it started by default before setup(). + + Serial.println("Going to sleep"); + delay(50); //Wait for serial to finish + Serial.end(); //Power down UART(s) + awakeFlag = false; + + //Disable all pads except the interrupt button + for (int x = 0 ; x < 50 ; x++) + { + if(x != INPUT_BUTTON) + am_hal_gpio_pinconfig(x , g_AM_HAL_GPIO_DISABLE); + } + + //We use counter/timer 6 to cause us to wake up from sleep but 0 to 7 are available + //CT 7 is used for Software Serial. All CTs are used for Servo. + am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREG); //Clear CT6 + am_hal_stimer_int_enable(AM_HAL_STIMER_INT_COMPAREG); //Enable C/T G=6 + + //Use the lower power 32kHz clock. Use it to run CT6 as well. + am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE); + am_hal_stimer_config(AM_HAL_STIMER_XTAL_32KHZ | AM_HAL_STIMER_CFG_COMPARE_G_ENABLE); + + //Setup interrupt to trigger when the number of ms have elapsed + am_hal_stimer_compare_delta_set(6, sysTicksToSleep); + + //Power down Flash, SRAM, cache + am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_CACHE); //Turn off CACHE + am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_FLASH_512K); //Turn off everything but lower 512k + am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_SRAM_64K_DTCM); //Turn off everything but lower 64k + //am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_ALL); //Turn off all memory (doesn't recover) + + // Enable interrupts to the core. + am_hal_interrupt_master_enable(); + + //Enable the timer interrupt in the NVIC. + NVIC_EnableIRQ(STIMER_CMPR6_IRQn); + + //Go to Deep Sleep. + am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); + + ///////////////////////////////////////////////////////////////////// + // (and/or while interrupt routines run)// + ///////////////////////////////////////////////////////////////////// + + //Turn off timer interrupt + NVIC_DisableIRQ(STIMER_CMPR6_IRQn); + + //Turn off GPIO interrupt + detachInterrupt(digitalPinToInterrupt(INPUT_BUTTON)); + + //We're BACK! + wakeFromSleep(); + Serial.println("End of goToSleep()"); + Serial.println(); +} + + +//Power everything up gracefully +void wakeFromSleep() +{ + if(awakeFlag) //Already awake + return; + + //Power up SRAM, turn on entire Flash + am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_MAX); + + //Go back to using the main clock + am_hal_stimer_int_enable(AM_HAL_STIMER_INT_OVERFLOW); + NVIC_EnableIRQ(STIMER_IRQn); + am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE); + am_hal_stimer_config(AM_HAL_STIMER_HFRC_3MHZ); + + //Turn on ADC + ap3_adc_setup(); + + //Set any pinModes + pinMode(STATUS_LED, OUTPUT); + pinMode(INPUT_BUTTON, INPUT_PULLUP); + + //Optional - start again (will never reach the end of goToSleep() or wakeFromSleep() though) + //Note - global variables will be preserved if you don't power down SRAM (comment out the line) +//setup(); + + //Restart Serial + Serial.begin(115200); + delay(10); + Serial.println("Back on"); + awakeFlag = true; + + //Initialise stuff like I2C/Wire/SPI here +} + + +//Called once number of milliseconds has passed +extern "C" void am_stimer_cmpr6_isr(void) +{ + uint32_t ui32Status = am_hal_stimer_int_status_get(false); + if (ui32Status & AM_HAL_STIMER_INT_COMPAREG) + { + am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREG); + } +}