Page 1 of 3

esp32 ulp programming

Posted: Sun Mar 04, 2018 2:23 am
by duffster
edit: Goto to see how to use the Arduino IDE to compile ulp assembly files.
Has anyone been able to program the ulp co-processor using the Arduino ide? I have not found anything about this. Arduino can compile .S assembly files but the esp32 core gives errors that it can't recognize symbols.

Re: esp32 ulp programming

Posted: Tue Mar 06, 2018 4:31 am
by duffster
Well, looks like I can use the ulp assembly MACROS to program ulp coprocessor. Here is a little test sketch I put together that just blinks my esp32's on board led. Not sure all esp32 led's are on the same pin but you can change that in the sketch. I'm still trying to work through the docs about the esp32 so at this time i'm not sure what the registers def all mean I just got lucky by coping pasting from an example to get the led configured.

Code: Select all

 * ESP32 Sketch shows that you can program the ulp co-processor using
 * Arduino using the ulp assembly MACRO's. This sketch just blinks the
 * on board LED on for x microseconds and OFF x microseconds using the ulp. 
 * This sketch was inspired from 
#include "esp32/ulp.h"
#include "driver/rtc_io.h"

void ULP_BLINK_RUN(uint32_t us);

void setup() {
  // microseconds to delay between halt and wake states

void loop() {
  // put your main code here, to run repeatedly:

// ------------------------------------------------------------------------
void ULP_BLINK_RUN(uint32_t us) {
  RTC_SLOW_MEM[12] = 0;
  ulp_set_wakeup_period(0, us);
  const ulp_insn_t  ulp_blink[] = {
    I_MOVI(R3, 12),                         // #12 -> R3
    I_LD(R0, R3, 0),                        // R0 = RTC_SLOW_MEM[R3(#12)] 
    M_BL(1, 1),                             // GOTO M_LABEL(1) IF R0 < 1
    I_WR_REG(RTC_GPIO_OUT_REG, 26, 27, 1),  // RTC_GPIO12 = 1
    I_SUBI(R0, R0, 1),                      // R0 = R0 - 1, R0 = 1, R0 = 0
    I_ST(R0, R3, 0),                        // RTC_SLOW_MEM[R3(#12)] = R0
    M_BX(2),                                // GOTO M_LABEL(2)
    M_LABEL(1),                             // M_LABEL(1)
      I_WR_REG(RTC_GPIO_OUT_REG, 26, 27, 0),// RTC_GPIO12 = 0
      I_ADDI(R0, R0, 1),                    // R0 = R0 + 1, R0 = 0, R0 = 1
      I_ST(R0, R3, 0),                      // RTC_SLOW_MEM[R3(#12)] = R0
    M_LABEL(2),                             // M_LABEL(2)
    I_HALT()                                // HALT COPROCESSOR
  const gpio_num_t led_gpios[] = {
  for (size_t i = 0; i < sizeof(led_gpios) / sizeof(led_gpios[0]); ++i) {
    rtc_gpio_set_direction(led_gpios[i], RTC_GPIO_MODE_OUTPUT_ONLY);
    rtc_gpio_set_level(led_gpios[i], 0);
  size_t size = sizeof(ulp_blink) / sizeof(ulp_insn_t);
  ulp_process_macros_and_load(0, ulp_blink, &size);

Re: esp32 ulp programming

Posted: Tue Mar 06, 2018 7:38 am
by juan3211
Me too. I think ULP programming in arduino ide is a key to finally promote and improve the ESP32 development over arduino's makers.

Please, could someone help us ?


Re: esp32 ulp programming

Posted: Wed Mar 07, 2018 6:42 pm
by duffster
I've been looking at how to program the ulp in non Arduino environment and I'm going to try to set that up to see if I can glean any info into integrating it into the Arduino IDE. Looks like the ulp needs its own tool chain and esp32ulp-binutils to compile .S assembly files. I know the Arduino IDE can in other toolchains compile these assembly files.

Re: esp32 ulp programming

Posted: Thu Mar 08, 2018 8:10 pm
by duffster
I took a deep dive into this problem and found that the .S assembly files do work with Arduino, the instructions refer to the main cores not the ulp! This was evident from the platform.txt ... rm.txt#L33 file so looks like the only way currently to access the ulp is through those MACROS I posted an example about.

I downloaded the esp-idf and setup my build environment successfully and compiled and uploaded a few programs, this led me to the wiki about installing the ulp toolchain which I did successfully and was able to use menu config to activate the ulp. Then I took an example from the esp-idf for the ulp and compiled and uploaded it successfully (non Arduino). That was good start but I want to use .S files for programming the ulp in Arduino. When diving into the Arduino-esp32 core files I found that it DOES NOT have the ulp toolchain required to compile .S assembly files for the ulp nor could it because the .S files are for the main processors not the ulp.

I'm thinking that we could add the ulp toolchain (binutils) to the Arduino IDE and make the platform.txt use .s files for programing in assembly the ulp. Thats a lower case "s". This is just thought now haven't tried it so there are probably much more details that I do not know about to get it to work?

Re: esp32 ulp programming

Posted: Fri Mar 09, 2018 3:24 pm
by tele_player
That sounds correct.

Another possibility- develop and debug your ULP code using IDF, then convert the result into hex text, and embed it in your Arduino code.

Re: esp32 ulp programming

Posted: Mon Mar 12, 2018 6:27 pm
by duffster
tele_player wrote:That sounds correct.

Another possibility- develop and debug your ULP code using IDF, then convert the result into hex text, and embed it in your Arduino code.
What I did is to use Arduino as a component in the esp-idf build environment as a way to see how to build and link in the ulp code but the makefiles span many different directories and are kind of cryptic to my eyes so far. On this front I also tried to limit the components that get compiled because they all do even if you don't use them, they just don't get linked in from what I can tell. I ended up having to build them all because they all need something from one another!

What I want to figure out now is how to just build ulp code by itself and then how it links into the main esp-idf code. Then I can go to Arduino and make some changes to platform.txt recipe to use binutils for compiling ulp code. That being said I'm not very good at setting up toolchains with all the intricacies that are needed to combine these two toolchains into one usable hex file to upload. But I'm still trying:)

Re: esp32 ulp programming

Posted: Wed Mar 14, 2018 8:05 pm
by duffster
So I have learned a lot since my last post, this problem is on four fronts:
  • [1] First was getting the correct OS compiled binutils ulp toolchain into Arduino.
    [2] Second was figuring out how to build and link the ulp to the main code using esp32-idf with command line.
    [3] Third was figuring out how to build with Arduino.
    [4] Fourth replicating how to build and link the ulp in Arduino using the esp-idf build process as template.
I also found a lot documentation on the build process.

Armed with this I am almost able to get the ulp assembly code to compile in Arduino but I'm missing an important part still, Step 6 from "Build the application as usual (e.g. `make app`)" in the ulp.rst file:
  • Inside, the build system will take the following steps to build ULP program:

    1. **Run each assembly file (foo.S) through C preprocessor.** This step generates the preprocessed assembly files (foo.ulp.pS) in the
    component build directory. This step also generates dependency files (foo.ulp.d).

    2. **Run preprocessed assembly sources through assembler.** This produces objects (foo.ulp.o) and listing (foo.ulp.lst) files. Listing file
    are generated for debugging purposes and are not used at later stages of build process.

    3. **Run linker script template through C preprocessor.** The template is located in components/ulp/ld directory.

    4. **Link object files into an output ELF file** (ulp_app_name.elf). Map file ( generated at this stage may be useful
    for debugging purposes.

    5. **Dump contents of the ELF file into binary** (ulp_app_name.bin) for embedding into the application.

    6. **Generate list of global symbols** (ulp_app_name.sym) in the ELF file using esp32ulp-elf-nm.

    7. **Create LD export script and header file** (ulp_app_name.ld and ulp_app_name.h) containing the symbols from ulp_app_name.sym.
    This is done using utility.

    8. **Add the generated binary to the list of binary files** to be embedded into the application.
I can do step 6 without Arduino using just the command line but Arduino balks with an error saying ".../bin/esp32ulp-elf-nm: '>': No such file". Here is my recipe:
  • recipe.hooks.libraries.prebuild.04.pattern="{compiler.ulp.path}{compiler.nm.cmd}" {compiler.nm.flags} {build.path}/sketch/ulp_main.elf > {build.path}/sketch/ulp_main.sym
So basically I can't get Arduino platform.txt recipe's can't do a unix pipe commands like ">". I'm almost there but yet so far away:(

Re: esp32 ulp programming

Posted: Thu Mar 15, 2018 12:05 am
by tele_player
If you’re on a linux or other Unix-like system, you can write a shell script to wrap bin/esp32ulp-elf-nm and handle the redirection into a file.

Re: esp32 ulp programming

Posted: Thu Mar 15, 2018 6:17 am
by ESP_igrr
Since Arduino for esp32 already depends on Python, this might be an option for you:
(still WIP but simple programs can already be compiled).