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 and
8
+ turning off the SWD pins.
9
+
10
+ SparkFun labored with love to create this code. Feel like supporting open source hardware?
11
+ Buy a board from SparkFun! https://www.sparkfun.com/products/15376
12
+
13
+ How close can we get to 2.7uA in deep sleep?
14
+ This example shows how decrease the Artemis current consumption to ~2.4uA in deep sleep
15
+ with a wake up every 5 seconds to blink the LED. The RTC is used to trigger an interrupt
16
+ every second.
17
+
18
+ Note that Artemis modules with revision A1 silicon will use ~30uA. Please see the
19
+ Ambiq errata for more information: https://www.ambiqmicro.com/static/mcu/files/Apollo3_Blue_Errata_List_v1_0_external_release.pdf
20
+
21
+ To monitor the current to the Edge cut the MEAS jumper, solder in headers, and attach
22
+ a DMM via IC hooks (https://www.sparkfun.com/products/506).
23
+
24
+ The USB to serial bridge draws some current:
25
+ Serial Basic C - ~1.2uA (https://www.sparkfun.com/products/15096)
26
+ FTDI Basic - ~5.5uA (https://www.sparkfun.com/products/9873)
27
+
28
+ */
29
+
30
+ static uint32_t g_RTCseconds = 0 ;
31
+
32
+ void setup ()
33
+ {
34
+ Serial.begin (115200 );
35
+ Serial.println (" Low power sleep example" );
36
+
37
+ pinMode (LED_BUILTIN, OUTPUT);
38
+
39
+ // Turn off ADC
40
+ power_adc_disable ();
41
+
42
+ // Set the clock frequency.
43
+ am_hal_clkgen_control (AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0 );
44
+
45
+ // Set the default cache configuration
46
+ am_hal_cachectrl_config (&am_hal_cachectrl_defaults);
47
+ am_hal_cachectrl_enable ();
48
+
49
+ // Initialize for low power in the power control block
50
+ am_hal_pwrctrl_low_power_init ();
51
+
52
+ // Disabling the debugger GPIOs saves about 1.2 uA total:
53
+ am_hal_gpio_pinconfig (20 /* SWDCLK */ , g_AM_HAL_GPIO_DISABLE);
54
+ am_hal_gpio_pinconfig (21 /* SWDIO */ , g_AM_HAL_GPIO_DISABLE);
55
+
56
+ // These two GPIOs are critical: the TX/RX connections between the Artemis module and the CH340S on the Blackboard
57
+ // are prone to backfeeding each other. To stop this from happening, we must reconfigure those pins as GPIOs
58
+ // and then disable them completely:
59
+ am_hal_gpio_pinconfig (48 /* TXO-0 */ , g_AM_HAL_GPIO_DISABLE);
60
+ am_hal_gpio_pinconfig (49 /* RXI-0 */ , g_AM_HAL_GPIO_DISABLE);
61
+
62
+ // The default Arduino environment runs the System Timer (STIMER) off the 48 MHZ HFRC clock source.
63
+ // The HFRC appears to take over 60 uA when it is running, so this is a big source of extra
64
+ // current consumption in deep sleep.
65
+ // For systems that might want to use the STIMER to generate a periodic wakeup, it needs to be left running.
66
+ // However, it does not have to run at 48 MHz. If we reconfigure STIMER (system timer) to use the 32768 Hz
67
+ // XTAL clock source instead the measured deepsleep power drops by about 64 uA.
68
+ am_hal_stimer_config (AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);
69
+
70
+ // This option selects 32768 Hz via crystal osc. This appears to cost about 0.1 uA versus selecting "no clock"
71
+ am_hal_stimer_config (AM_HAL_STIMER_XTAL_32KHZ);
72
+
73
+ // This option would be available to systems that don't care about passing time, but might be set
74
+ // to wake up on a GPIO transition interrupt.
75
+ // am_hal_stimer_config(AM_HAL_STIMER_NO_CLK);
76
+
77
+ // Turn OFF Flash1
78
+ if (am_hal_pwrctrl_memory_enable (AM_HAL_PWRCTRL_MEM_FLASH_512K))
79
+ {
80
+ while (1 )
81
+ ;
82
+ }
83
+
84
+ // Power down SRAM
85
+ PWRCTRL->MEMPWDINSLEEP_b .SRAMPWDSLP = PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER32K;
86
+
87
+ setupRTC ();
88
+
89
+ Serial.println (" Going to sleep..." );
90
+ delay (100 ); // Wait for print to complete
91
+ Serial.end (); // Disable Serial
92
+
93
+ // Enable interrupts to the core.
94
+ am_hal_interrupt_master_enable ();
95
+ }
96
+
97
+ void loop ()
98
+ {
99
+ // Go to Deep Sleep.
100
+ am_hal_sysctrl_sleep (AM_HAL_SYSCTRL_SLEEP_DEEP);
101
+ }
102
+
103
+ void setupRTC ()
104
+ {
105
+ // Enable the XT for the RTC.
106
+ am_hal_clkgen_control (AM_HAL_CLKGEN_CONTROL_XTAL_START, 0 );
107
+
108
+ // Select XT for RTC clock source
109
+ am_hal_rtc_osc_select (AM_HAL_RTC_OSC_XT);
110
+
111
+ // Enable the RTC.
112
+ am_hal_rtc_osc_enable ();
113
+
114
+ // Set the alarm repeat interval to be every second.
115
+ am_hal_rtc_alarm_interval_set (AM_HAL_RTC_ALM_RPT_SEC);
116
+
117
+ // Clear the RTC alarm interrupt.
118
+ am_hal_rtc_int_clear (AM_HAL_RTC_INT_ALM);
119
+
120
+ // Enable the RTC alarm interrupt.
121
+ am_hal_rtc_int_enable (AM_HAL_RTC_INT_ALM);
122
+
123
+ // Enable RTC interrupts to the NVIC.
124
+ NVIC_EnableIRQ (RTC_IRQn);
125
+ }
126
+
127
+ extern " C" void am_rtc_isr (void )
128
+ {
129
+ // Clear the RTC alarm interrupt.
130
+ am_hal_rtc_int_clear (AM_HAL_RTC_INT_ALM);
131
+
132
+ // Check the desired number of seconds until LED is toggled.
133
+ if (++g_RTCseconds >= 5 )
134
+ {
135
+ // Reset the seconds counter.
136
+ g_RTCseconds = 0 ;
137
+
138
+ // Toggle LED
139
+ digitalWrite (LED_BUILTIN, HIGH);
140
+ delay (100 );
141
+ digitalWrite (LED_BUILTIN, LOW);
142
+ }
143
+ }
0 commit comments