]> granicus.if.org Git - esp-idf/blob - examples/system/ulp/main/ulp_example_main.c
esp32: Allow SPIRAM_MALLOC_RESERVE_INTERNAL to span multiple regions of memory
[esp-idf] / examples / system / ulp / main / ulp_example_main.c
1 /* ULP Example
2
3    This example code is in the Public Domain (or CC0 licensed, at your option.)
4
5    Unless required by applicable law or agreed to in writing, this
6    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7    CONDITIONS OF ANY KIND, either express or implied.
8 */
9
10 #include <stdio.h>
11 #include "esp_sleep.h"
12 #include "nvs.h"
13 #include "nvs_flash.h"
14 #include "soc/rtc_cntl_reg.h"
15 #include "soc/sens_reg.h"
16 #include "soc/rtc_periph.h"
17 #include "driver/gpio.h"
18 #include "driver/rtc_io.h"
19 #include "esp32/ulp.h"
20 #include "ulp_main.h"
21
22 extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
23 extern const uint8_t ulp_main_bin_end[]   asm("_binary_ulp_main_bin_end");
24
25 static void init_ulp_program();
26 static void update_pulse_count();
27
28 void app_main()
29 {
30     esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
31     if (cause != ESP_SLEEP_WAKEUP_ULP) {
32         printf("Not ULP wakeup, initializing ULP\n");
33         init_ulp_program();
34     } else {
35         printf("ULP wakeup, saving pulse count\n");
36         update_pulse_count();
37     }
38
39     printf("Entering deep sleep\n\n");
40     ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
41     esp_deep_sleep_start();
42 }
43
44 static void init_ulp_program()
45 {
46     esp_err_t err = ulp_load_binary(0, ulp_main_bin_start,
47             (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
48     ESP_ERROR_CHECK(err);
49
50     /* GPIO used for pulse counting. */
51     gpio_num_t gpio_num = GPIO_NUM_0;
52     assert(rtc_gpio_desc[gpio_num].reg && "GPIO used for pulse counting must be an RTC IO");
53
54     /* Initialize some variables used by ULP program.
55      * Each 'ulp_xyz' variable corresponds to 'xyz' variable in the ULP program.
56      * These variables are declared in an auto generated header file,
57      * 'ulp_main.h', name of this file is defined in component.mk as ULP_APP_NAME.
58      * These variables are located in RTC_SLOW_MEM and can be accessed both by the
59      * ULP and the main CPUs.
60      *
61      * Note that the ULP reads only the lower 16 bits of these variables.
62      */
63     ulp_debounce_counter = 3;
64     ulp_debounce_max_count = 3;
65     ulp_next_edge = 0;
66     ulp_io_number = rtc_gpio_desc[gpio_num].rtc_num; /* map from GPIO# to RTC_IO# */
67     ulp_edge_count_to_wake_up = 10;
68
69     /* Initialize selected GPIO as RTC IO, enable input, disable pullup and pulldown */
70     rtc_gpio_init(gpio_num);
71     rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_INPUT_ONLY);
72     rtc_gpio_pulldown_dis(gpio_num);
73     rtc_gpio_pullup_dis(gpio_num);
74     rtc_gpio_hold_en(gpio_num);
75
76     /* Disconnect GPIO12 and GPIO15 to remove current drain through
77      * pullup/pulldown resistors.
78      * GPIO15 may be connected to ground to suppress boot messages.
79      * GPIO12 may be pulled high to select flash voltage.
80      */
81     rtc_gpio_isolate(GPIO_NUM_12);
82     rtc_gpio_isolate(GPIO_NUM_15);
83
84     /* Set ULP wake up period to T = 20ms.
85      * Minimum pulse width has to be T * (ulp_debounce_counter + 1) = 80ms.
86      */
87     ulp_set_wakeup_period(0, 20000);
88
89     /* Start the program */
90     err = ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t));
91     ESP_ERROR_CHECK(err);
92 }
93
94 static void update_pulse_count()
95 {
96     const char* namespace = "plusecnt";
97     const char* count_key = "count";
98
99     ESP_ERROR_CHECK( nvs_flash_init() );
100     nvs_handle handle;
101     ESP_ERROR_CHECK( nvs_open(namespace, NVS_READWRITE, &handle));
102     uint32_t pulse_count = 0;
103     esp_err_t err = nvs_get_u32(handle, count_key, &pulse_count);
104     assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND);
105     printf("Read pulse count from NVS: %5d\n", pulse_count);
106
107     /* ULP program counts signal edges, convert that to the number of pulses */
108     uint32_t pulse_count_from_ulp = (ulp_edge_count & UINT16_MAX) / 2;
109     /* In case of an odd number of edges, keep one until next time */
110     ulp_edge_count = ulp_edge_count % 2;
111     printf("Pulse count from ULP: %5d\n", pulse_count_from_ulp);
112
113     /* Save the new pulse count to NVS */
114     pulse_count += pulse_count_from_ulp;
115     ESP_ERROR_CHECK(nvs_set_u32(handle, count_key, pulse_count));
116     ESP_ERROR_CHECK(nvs_commit(handle));
117     nvs_close(handle);
118     printf("Wrote updated pulse count to NVS: %5d\n", pulse_count);
119 }