(原) ESP32 ULP 示例 blink

原创文章,请后转载,并注明出处。

这是一个利用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);
}

相关文章