ESP32-S3のULP-RISC-VでLチカしてみた

2022.07.13

こんにちは、CX事業本部 Delivery部のakkyです。

今回は、ULP(サブプロセッサ)にRISC-Vを搭載したESP32-S3を試してみましたので、ご紹介します。

ESP32-S3

Espressif ESP32-S3はメインCPUにXtensa LX7デュアルコアを採用し、Wi-FiとBluetooth5に対応したSoCです。無印のESP32と比較して、CPUコアがLX6→LX7となっており、性能が向上しています(参考資料の2を参照)。USBの搭載や、単体デバッグの対応も大きな変更です。

ソフトウェアはESP-IDFが使用でき、ハードウェアも順当に性能向上を果たしたESP32-S3ですが、個人的に面白いと思った新機能としては、ULPにRISC-Vコアが追加されたことです。ULPはメインCPUがスリープモードになっている際に使用できる省電力のコアで、今までのESP32にはFSMと呼ばれるEspressif独自コアのCPUが搭載されていました。ESP32-S3では、従来のFSMに加えてRISC-Vコアが追加され、C言語でプログラミングできるようになりました。

なお、ESP32-C3という、メインCPUにRISC-Vを搭載した別製品もありますが、こちらとは違います。

ULP-RISC-Vは非常に便利に使えそうなのですが、ESP-IDFでもまだdevelopブランチ版でしか使用できず、まだサンプルも充実していません。I2CやADCも使用できるはずなのですが、サンプルはなく…ひとまずLED点滅(Lチカ)が実行できることを確かめてみることにしました。

ハードウェア

ULPからアクセスできるのはRTC-GPIOペリフェラルで、IO 0~21が使用できます。無印ESP32とは異なり、メインのGPIOと同じ番号にマッピングされるようになりました。

今回はIO21にLEDを接続しました。

ソフトウェア

ULP-RISC-VはESP-IDF v5.0から対応するようで、現在のリリースであるv4.4.1では対応していません(ESP32-S3用にビルドするとエラーになります)。そのため、Online Installerを使用し、masterブランチから開発版をダウンロードしてください。

ソースコード

examples\system\ulp_riscv\gpioを改変して使用します。

ulp_riscv_example_main.c

//* ULP riscv DS18B20 1wire temperature sensor 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 "ulp_riscv.h"
#include "ulp_main.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.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);

void app_main(void)
{
    esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
    /* not a wakeup from ULP, load the firmware */
    if (cause != ESP_SLEEP_WAKEUP_ULP) {
        printf("Not a ULP-RISC-V wakeup, initializing it! \n");
        init_ulp_program();
    }

    /* ULP Risc-V read and detected a change in GPIO_0, prints */
    if (cause == ESP_SLEEP_WAKEUP_ULP) {
        printf("ULP-RISC-V woke up the main CPU! \n");
    }

    /* Go back to sleep, only the ULP Risc-V will run */
    printf("Entering in deep sleep\n\n");

    /* Small delay to ensure the messages are printed */
    vTaskDelay(100);

    ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup());
    esp_deep_sleep_start();
}

static void init_ulp_program(void)
{
    esp_err_t err = ulp_riscv_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start));
    ESP_ERROR_CHECK(err);
    
    /* Start the program */
    err = ulp_riscv_run();
    ESP_ERROR_CHECK(err);
}

ulp/main.c

/* ULP-RISC-V 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.

   This code runs on ULP-RISC-V  coprocessor
*/

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "ulp_riscv.h"
#include "ulp_riscv_utils.h"
#include "ulp_riscv_gpio.h"
#include "soc/rtc_cntl_reg.h"

#define GPIO_LED GPIO_NUM_21

int main (void)
{
    ulp_riscv_gpio_init(GPIO_LED);
    ulp_riscv_gpio_output_enable(GPIO_LED);
    ulp_riscv_gpio_set_output_mode(GPIO_LED, RTCIO_MODE_OUTPUT);

    while(1) {
        ulp_riscv_gpio_output_level(GPIO_LED, 1);
        ulp_riscv_delay_cycles(ULP_RISCV_CYCLES_PER_MS * 1000); // wait 1000 ms
        ulp_riscv_gpio_output_level(GPIO_LED, 0);
        ulp_riscv_delay_cycles(ULP_RISCV_CYCLES_PER_MS * 1000);
    }
    
    return 0;
}

ビルド

set-targetでビルドターゲットをesp32s3に変更し、buildしてください。

idf.py set-target esp32s3
idf.py build
idf.py -p <シリアルポート> flash

転送すると、IO21に接続したLEDが点滅することが確認できました。

おわりに

ESP32-S3でRISC-VのULPを使用することができました。まだライブラリはあまり整備されていないのですが、今後、I2CやADCが使用できるようになると、デバイスの省電力化ができるようになり、電池での使用期間の延長などのメリットが得られるはずです。 ESP-IDFの最新版をキャッチアップしていきたいと思います。

参考資料

  1. Espressif ESP32-S3
  2. Lang-Ship ESP32シリーズ(無印, S2, S3, C3, …)比較 2022年1月