这是一个利用ULP来实现的指示灯闪烁。代码主体是网上的,但是通过官方编译是自己动的手。
ulp/bink.S
实现了亮100ms,熄500ms
#include "soc/soc_ulp.h" // for WRITE_RTC_REG
#include "soc/rtc_io_reg.h" // for RTC_GPIO_*
.global entry // 定义全局入口地址
.set gpio_2, 12 // 定义一个端口
.text // 正文开始
entry:
// use digital function, not rtc function
// WRITE_RTC_REG(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_S, 1, 1)
// 写RTC寄存器,定义GPIO2为输出
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + gpio_2, 1, 1)
on:
// GPIO输出电平点亮
WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS_S + gpio_2, 1, 1)
// 循环
move r1, 100 // wait in ms
move r2, off // return address
jump delay // call subroutine
off:
// 输出电平熄灭
WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC_S + gpio_2, 1, 1)
move r1, 500 // wait in ms
move r2, on // return address
jump delay // call subroutine
delay:
wait 8000 // wait 8000 clock ticks at 8MHz -> 1ms
sub r1, r1, 1 // decrement ms count
jump r2, eq // if ms count is zero then return to caller
jump delay // else continue to wait
main.c
#include <stdio.h> // printf(), fflush()
#include "esp_sleep.h" // esp_sleep_enable_ulp_wakeup(), esp_deep_sleep_start()
#include "ulp-util.h" // my ulp_init(), ulp_start()
#include "esp32/ulp.h"
void app_main()
{
printf("Hello Blink ULP!\n");
ulp_init();
ulp_start();
printf("Started ULP, going to sleep now.\n");
fflush(stdout);
ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() ); //允许ulp唤醒esp
esp_deep_sleep_start(); //esp开始偷懒(睡)
}
//这里原本是ulp-util.c的内容,不过都是通用的东西。
extern const uint8_t _ulp_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t _ulp_end[] asm("_binary_ulp_main_bin_end");
void ulp_init() {
ESP_ERROR_CHECK( ulp_load_binary(0, _ulp_start, (_ulp_end-_ulp_start)/sizeof(ulp_entry)) );
}
void ulp_start() {
ESP_ERROR_CHECK( ulp_run(&ulp_entry-RTC_SLOW_MEM) );
}
ulp-util.h
#pragma once
#include <stdint.h>
extern uint32_t ulp_entry; //一个入口必须说明
void ulp_init();
void ulp_start();
原本还有ulp-util.c,但可能是配置文件没整对,导致不能通过,就将代码一并交到main.c中了。
原来的ulp-util.c
#include "ulp-util.h"
#include "esp32/ulp.h"
extern const uint8_t _ulp_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t _ulp_end[] asm("_binary_ulp_main_bin_end");
void ulp_init() {
ESP_ERROR_CHECK( ulp_load_binary(0, _ulp_start, (_ulp_end-_ulp_start)/sizeof(ulp_entry)) );
}
void ulp_start() {
ESP_ERROR_CHECK( ulp_run(&ulp_entry-RTC_SLOW_MEM) );
}
CMakeLists.txt
# 后来发现,在此行main.c后面添加 ulp-util.c 即可包含另一个源代码文件
idf_component_register(SRCS "main.c"
INCLUDE_DIRS ""
REQUIRES soc nvs_flash ulp driver)
set(ulp_app_name ulp_${COMPONENT_NAME})
set(ulp_s_sources "ulp/blink.S")
set(ulp_exp_dep_srcs "main.c")
ulp_embed_binary(${ulp_app_name} "${ulp_s_sources}" "${ulp_exp_dep_srcs}")
这个示例中,关于写RTC寄存器,为什么要写这些地址,没太明白。
还有另一种闪灯的方式:
主程序中定闹钟(定时唤醒) ulp_set_wakeup_period(0, 500 * 1000);
ulp负责亮-延时-灭-睡
顺便看看多任务的blink
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#define BLINK_GPIO 2
void blink_task(void *pvParameter) {
gpio_pad_select_gpio(BLINK_GPIO);
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
while(1){
gpio_set_level(BLINK_GPIO,0);
vTaskDelay(1000/portTICK_PERIOD_MS);
gpio_set_level(BLINK_GPIO,1);
vTaskDelay(1000/portTICK_PERIOD_MS);
}
}
void app_main(){
xTaskCreate(&blink_task,"blink",configMINIMAL_STACK_SIZE,NULL,5,NULL);
}