1+ /*
2+ Artemis Low Power: How low can we go?
3+ By: Nathan Seidle
4+ SparkFun Electronics
5+ Date: October 17th, 2019
6+ License: This code is public domain. Based on deepsleep_wake.c from Ambiq SDK v2.2.0.
7+ A big thanks to robin_hodgson for pointing out the HFRC shutdown requirement.
8+
9+ SparkFun labored with love to create this code. Feel like supporting open source hardware?
10+ Buy a board from SparkFun! https://www.sparkfun.com/products/15376
11+
12+ How close can we get to 2.7uA in deep sleep?
13+ This example shows how decrease the Artemis current consumption to ~4.2uA in deep sleep
14+ with a wake up every 5 seconds to blink the LED. The RTC is used to trigger an interrupt
15+ every second.
16+
17+ To monitor the current to the Edge cut the MEAS jumper, solder in headers, and attach
18+ a DMM via IC hooks (https://www.sparkfun.com/products/506).
19+
20+ The USB to serial bridge draws some current:
21+ Serial Basic C - ~1.2uA (https://www.sparkfun.com/products/15096)
22+ FTDI Basic - ~5.5uA (https://www.sparkfun.com/products/9873)
23+
24+ */
25+
26+ static uint32_t g_RTCseconds = 0 ;
27+
28+ void setup ()
29+ {
30+ Serial.begin (115200 );
31+ Serial.println (" Low power sleep example" );
32+
33+ pinMode (LED_BUILTIN, OUTPUT);
34+
35+ // Turn off ADC
36+ power_adc_disable ();
37+
38+ // Set the clock frequency.
39+ am_hal_clkgen_control (AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0 );
40+
41+ // Set the default cache configuration
42+ am_hal_cachectrl_config (&am_hal_cachectrl_defaults);
43+ am_hal_cachectrl_enable ();
44+
45+ // Initialize for low power in the power control block
46+ am_hal_pwrctrl_low_power_init ();
47+
48+ // The default Arduino environment runs the System Timer (STIMER) off the 48 MHZ HFRC clock source.
49+ // The HFRC appears to take over 60 uA when it is running, so this is a big source of extra
50+ // current consumption in deep sleep.
51+ // For systems that might want to use the STIMER to generate a periodic wakeup, it needs to be left running.
52+ // However, it does not have to run at 48 MHz. If we reconfigure STIMER (system timer) to use the 32768 Hz
53+ // XTAL clock source instead the measured deepsleep power drops by about 64 uA.
54+ am_hal_stimer_config (AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);
55+
56+ // This option selects 32768 Hz via crystal osc. This appears to cost about 0.1 uA versus selecting "no clock"
57+ am_hal_stimer_config (AM_HAL_STIMER_XTAL_32KHZ);
58+
59+ // This option would be available to systems that don't care about passing time, but might be set
60+ // to wake up on a GPIO transition interrupt.
61+ // am_hal_stimer_config(AM_HAL_STIMER_NO_CLK);
62+
63+ // Turn OFF Flash1
64+ if (am_hal_pwrctrl_memory_enable (AM_HAL_PWRCTRL_MEM_FLASH_512K))
65+ {
66+ while (1 )
67+ ;
68+ }
69+
70+ // Power down SRAM
71+ PWRCTRL->MEMPWDINSLEEP_b .SRAMPWDSLP = PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER32K;
72+
73+ setupRTC ();
74+
75+ Serial.println (" Going to sleep..." );
76+ delay (100 ); // Wait for print to complete
77+ Serial.end (); // Disable Serial
78+
79+ // Enable interrupts to the core.
80+ am_hal_interrupt_master_enable ();
81+ }
82+
83+ void loop ()
84+ {
85+ // Go to Deep Sleep.
86+ am_hal_sysctrl_sleep (AM_HAL_SYSCTRL_SLEEP_DEEP);
87+ }
88+
89+ void setupRTC ()
90+ {
91+ // Enable the XT for the RTC.
92+ am_hal_clkgen_control (AM_HAL_CLKGEN_CONTROL_XTAL_START, 0 );
93+
94+ // Select XT for RTC clock source
95+ am_hal_rtc_osc_select (AM_HAL_RTC_OSC_XT);
96+
97+ // Enable the RTC.
98+ am_hal_rtc_osc_enable ();
99+
100+ // Set the alarm repeat interval to be every second.
101+ am_hal_rtc_alarm_interval_set (AM_HAL_RTC_ALM_RPT_SEC);
102+
103+ // Clear the RTC alarm interrupt.
104+ am_hal_rtc_int_clear (AM_HAL_RTC_INT_ALM);
105+
106+ // Enable the RTC alarm interrupt.
107+ am_hal_rtc_int_enable (AM_HAL_RTC_INT_ALM);
108+
109+ // Enable RTC interrupts to the NVIC.
110+ NVIC_EnableIRQ (RTC_IRQn);
111+ }
112+
113+ extern " C" void am_rtc_isr (void )
114+ {
115+ // Clear the RTC alarm interrupt.
116+ am_hal_rtc_int_clear (AM_HAL_RTC_INT_ALM);
117+
118+ // Check the desired number of seconds until LED is toggled.
119+ if (++g_RTCseconds >= 5 )
120+ {
121+ // Reset the seconds counter.
122+ g_RTCseconds = 0 ;
123+
124+ // Toggle LED
125+ digitalWrite (LED_BUILTIN, HIGH);
126+ delay (100 );
127+ digitalWrite (LED_BUILTIN, LOW);
128+ }
129+ }
0 commit comments