mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-20 01:45:55 +08:00
添加智能灯固件代码
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
idf_component_register(SRCS "ulp_example_main.c"
|
||||
INCLUDE_DIRS ""
|
||||
REQUIRES soc nvs_flash ulp)
|
||||
#
|
||||
# ULP support additions to component CMakeLists.txt.
|
||||
#
|
||||
# 1. The ULP app name must be unique (if multiple components use ULP).
|
||||
set(ulp_app_name ulp_${COMPONENT_NAME})
|
||||
#
|
||||
# 2. Specify all assembly source files.
|
||||
# Files should be placed into a separate directory (in this case, ulp/),
|
||||
# which should not be added to COMPONENT_SRCS.
|
||||
set(ulp_s_sources "ulp/pulse_cnt.S" "ulp/wake_up.S")
|
||||
#
|
||||
# 3. List all the component source files which include automatically
|
||||
# generated ULP export file, ${ulp_app_name}.h:
|
||||
set(ulp_exp_dep_srcs "ulp_example_main.c")
|
||||
#
|
||||
# 4. Call function to build ULP binary and embed in project using the argument
|
||||
# values above.
|
||||
ulp_embed_binary(${ulp_app_name} "${ulp_s_sources}" "${ulp_exp_dep_srcs}")
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
|
||||
#
|
||||
# ULP support additions to component makefile.
|
||||
#
|
||||
# 1. ULP_APP_NAME must be unique (if multiple components use ULP)
|
||||
# Default value, override if necessary:
|
||||
ULP_APP_NAME ?= ulp_$(COMPONENT_NAME)
|
||||
#
|
||||
# 2. Specify all assembly source files here.
|
||||
# Files should be placed into a separate directory (in this case, ulp/),
|
||||
# which should not be added to COMPONENT_SRCDIRS.
|
||||
ULP_S_SOURCES = $(addprefix $(COMPONENT_PATH)/ulp/, \
|
||||
pulse_cnt.S wake_up.S\
|
||||
)
|
||||
#
|
||||
# 3. List all the component object files which include automatically
|
||||
# generated ULP export file, $(ULP_APP_NAME).h:
|
||||
ULP_EXP_DEP_OBJECTS := ulp_example_main.o
|
||||
#
|
||||
# 4. Include build rules for ULP program
|
||||
include $(IDF_PATH)/components/ulp/component_ulp_common.mk
|
||||
#
|
||||
# End of ULP support additions to component makefile.
|
||||
#
|
||||
@@ -0,0 +1,146 @@
|
||||
/* ULP Example: pulse counting
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
This file contains assembly code which runs on the ULP.
|
||||
|
||||
ULP wakes up to run this code at a certain period, determined by the values
|
||||
in SENS_ULP_CP_SLEEP_CYCx_REG registers. On each wake up, the program checks
|
||||
the input on GPIO0. If the value is different from the previous one, the
|
||||
program "debounces" the input: on the next debounce_max_count wake ups,
|
||||
it expects to see the same value of input.
|
||||
If this condition holds true, the program increments edge_count and starts
|
||||
waiting for input signal polarity to change again.
|
||||
When the edge counter reaches certain value (set by the main program),
|
||||
this program running triggers a wake up from deep sleep.
|
||||
*/
|
||||
|
||||
/* ULP assembly files are passed through C preprocessor first, so include directives
|
||||
and C macros may be used in these files
|
||||
*/
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/rtc_io_reg.h"
|
||||
#include "soc/soc_ulp.h"
|
||||
|
||||
/* Define variables, which go into .bss section (zero-initialized data) */
|
||||
.bss
|
||||
/* Next input signal edge expected: 0 (negative) or 1 (positive) */
|
||||
.global next_edge
|
||||
next_edge:
|
||||
.long 0
|
||||
|
||||
/* Counter started when signal value changes.
|
||||
Edge is "debounced" when the counter reaches zero. */
|
||||
.global debounce_counter
|
||||
debounce_counter:
|
||||
.long 0
|
||||
|
||||
/* Value to which debounce_counter gets reset.
|
||||
Set by the main program. */
|
||||
.global debounce_max_count
|
||||
debounce_max_count:
|
||||
.long 0
|
||||
|
||||
/* Total number of signal edges acquired */
|
||||
.global edge_count
|
||||
edge_count:
|
||||
.long 0
|
||||
|
||||
/* Number of edges to acquire before waking up the SoC.
|
||||
Set by the main program. */
|
||||
.global edge_count_to_wake_up
|
||||
edge_count_to_wake_up:
|
||||
.long 0
|
||||
|
||||
/* RTC IO number used to sample the input signal.
|
||||
Set by main program. */
|
||||
.global io_number
|
||||
io_number:
|
||||
.long 0
|
||||
|
||||
/* Code goes into .text section */
|
||||
.text
|
||||
.global entry
|
||||
entry:
|
||||
/* Load io_number */
|
||||
move r3, io_number
|
||||
ld r3, r3, 0
|
||||
|
||||
/* Lower 16 IOs and higher need to be handled separately,
|
||||
* because r0-r3 registers are 16 bit wide.
|
||||
* Check which IO this is.
|
||||
*/
|
||||
move r0, r3
|
||||
jumpr read_io_high, 16, ge
|
||||
|
||||
/* Read the value of lower 16 RTC IOs into R0 */
|
||||
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S, 16)
|
||||
rsh r0, r0, r3
|
||||
jump read_done
|
||||
|
||||
/* Read the value of RTC IOs 16-17, into R0 */
|
||||
read_io_high:
|
||||
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 16, 2)
|
||||
sub r3, r3, 16
|
||||
rsh r0, r0, r3
|
||||
|
||||
read_done:
|
||||
and r0, r0, 1
|
||||
/* State of input changed? */
|
||||
move r3, next_edge
|
||||
ld r3, r3, 0
|
||||
add r3, r0, r3
|
||||
and r3, r3, 1
|
||||
jump changed, eq
|
||||
/* Not changed */
|
||||
/* Reset debounce_counter to debounce_max_count */
|
||||
move r3, debounce_max_count
|
||||
move r2, debounce_counter
|
||||
ld r3, r3, 0
|
||||
st r3, r2, 0
|
||||
/* End program */
|
||||
halt
|
||||
|
||||
.global changed
|
||||
changed:
|
||||
/* Input state changed */
|
||||
/* Has debounce_counter reached zero? */
|
||||
move r3, debounce_counter
|
||||
ld r2, r3, 0
|
||||
add r2, r2, 0 /* dummy ADD to use "jump if ALU result is zero" */
|
||||
jump edge_detected, eq
|
||||
/* Not yet. Decrement debounce_counter */
|
||||
sub r2, r2, 1
|
||||
st r2, r3, 0
|
||||
/* End program */
|
||||
halt
|
||||
|
||||
.global edge_detected
|
||||
edge_detected:
|
||||
/* Reset debounce_counter to debounce_max_count */
|
||||
move r3, debounce_max_count
|
||||
move r2, debounce_counter
|
||||
ld r3, r3, 0
|
||||
st r3, r2, 0
|
||||
/* Flip next_edge */
|
||||
move r3, next_edge
|
||||
ld r2, r3, 0
|
||||
add r2, r2, 1
|
||||
and r2, r2, 1
|
||||
st r2, r3, 0
|
||||
/* Increment edge_count */
|
||||
move r3, edge_count
|
||||
ld r2, r3, 0
|
||||
add r2, r2, 1
|
||||
st r2, r3, 0
|
||||
/* Compare edge_count to edge_count_to_wake_up */
|
||||
move r3, edge_count_to_wake_up
|
||||
ld r3, r3, 0
|
||||
sub r3, r3, r2
|
||||
jump wake_up, eq
|
||||
/* Not yet. End program */
|
||||
halt
|
||||
@@ -0,0 +1,16 @@
|
||||
/* ULP assembly files are passed through C preprocessor first, so include directives
|
||||
and C macros may be used in these files
|
||||
*/
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/soc_ulp.h"
|
||||
|
||||
.global wake_up
|
||||
wake_up:
|
||||
/* Check if the system can be woken up */
|
||||
READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
|
||||
and r0, r0, 1
|
||||
jump wake_up, eq
|
||||
|
||||
/* Wake up the SoC, end program */
|
||||
wake
|
||||
halt
|
||||
@@ -0,0 +1,120 @@
|
||||
/* ULP Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "esp_sleep.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "esp32/ulp.h"
|
||||
#include "ulp_main.h"
|
||||
|
||||
extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
|
||||
extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end");
|
||||
|
||||
static void init_ulp_program(void);
|
||||
static void update_pulse_count(void);
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||
if (cause != ESP_SLEEP_WAKEUP_ULP) {
|
||||
printf("Not ULP wakeup, initializing ULP\n");
|
||||
init_ulp_program();
|
||||
} else {
|
||||
printf("ULP wakeup, saving pulse count\n");
|
||||
update_pulse_count();
|
||||
}
|
||||
|
||||
printf("Entering deep sleep\n\n");
|
||||
ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
static void init_ulp_program(void)
|
||||
{
|
||||
esp_err_t err = ulp_load_binary(0, ulp_main_bin_start,
|
||||
(ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
|
||||
ESP_ERROR_CHECK(err);
|
||||
|
||||
/* GPIO used for pulse counting. */
|
||||
gpio_num_t gpio_num = GPIO_NUM_0;
|
||||
int rtcio_num = rtc_io_number_get(gpio_num);
|
||||
assert(rtc_gpio_is_valid_gpio(gpio_num) && "GPIO used for pulse counting must be an RTC IO");
|
||||
|
||||
/* Initialize some variables used by ULP program.
|
||||
* Each 'ulp_xyz' variable corresponds to 'xyz' variable in the ULP program.
|
||||
* These variables are declared in an auto generated header file,
|
||||
* 'ulp_main.h', name of this file is defined in component.mk as ULP_APP_NAME.
|
||||
* These variables are located in RTC_SLOW_MEM and can be accessed both by the
|
||||
* ULP and the main CPUs.
|
||||
*
|
||||
* Note that the ULP reads only the lower 16 bits of these variables.
|
||||
*/
|
||||
ulp_debounce_counter = 3;
|
||||
ulp_debounce_max_count = 3;
|
||||
ulp_next_edge = 0;
|
||||
ulp_io_number = rtcio_num; /* map from GPIO# to RTC_IO# */
|
||||
ulp_edge_count_to_wake_up = 10;
|
||||
|
||||
/* Initialize selected GPIO as RTC IO, enable input, disable pullup and pulldown */
|
||||
rtc_gpio_init(gpio_num);
|
||||
rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_INPUT_ONLY);
|
||||
rtc_gpio_pulldown_dis(gpio_num);
|
||||
rtc_gpio_pullup_dis(gpio_num);
|
||||
rtc_gpio_hold_en(gpio_num);
|
||||
|
||||
/* Disconnect GPIO12 and GPIO15 to remove current drain through
|
||||
* pullup/pulldown resistors.
|
||||
* GPIO12 may be pulled high to select flash voltage.
|
||||
*/
|
||||
rtc_gpio_isolate(GPIO_NUM_12);
|
||||
rtc_gpio_isolate(GPIO_NUM_15);
|
||||
esp_deep_sleep_disable_rom_logging(); // suppress boot messages
|
||||
|
||||
/* Set ULP wake up period to T = 20ms.
|
||||
* Minimum pulse width has to be T * (ulp_debounce_counter + 1) = 80ms.
|
||||
*/
|
||||
ulp_set_wakeup_period(0, 20000);
|
||||
|
||||
/* Start the program */
|
||||
err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
|
||||
ESP_ERROR_CHECK(err);
|
||||
}
|
||||
|
||||
static void update_pulse_count(void)
|
||||
{
|
||||
const char* namespace = "plusecnt";
|
||||
const char* count_key = "count";
|
||||
|
||||
ESP_ERROR_CHECK( nvs_flash_init() );
|
||||
nvs_handle_t handle;
|
||||
ESP_ERROR_CHECK( nvs_open(namespace, NVS_READWRITE, &handle));
|
||||
uint32_t pulse_count = 0;
|
||||
esp_err_t err = nvs_get_u32(handle, count_key, &pulse_count);
|
||||
assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND);
|
||||
printf("Read pulse count from NVS: %5d\n", pulse_count);
|
||||
|
||||
/* ULP program counts signal edges, convert that to the number of pulses */
|
||||
uint32_t pulse_count_from_ulp = (ulp_edge_count & UINT16_MAX) / 2;
|
||||
/* In case of an odd number of edges, keep one until next time */
|
||||
ulp_edge_count = ulp_edge_count % 2;
|
||||
printf("Pulse count from ULP: %5d\n", pulse_count_from_ulp);
|
||||
|
||||
/* Save the new pulse count to NVS */
|
||||
pulse_count += pulse_count_from_ulp;
|
||||
ESP_ERROR_CHECK(nvs_set_u32(handle, count_key, pulse_count));
|
||||
ESP_ERROR_CHECK(nvs_commit(handle));
|
||||
nvs_close(handle);
|
||||
printf("Wrote updated pulse count to NVS: %5d\n", pulse_count);
|
||||
}
|
||||
Reference in New Issue
Block a user