ULP RISC-V calling assembly from C not working

bitmandu
Posts: 6
Joined: Fri Apr 23, 2021 2:37 pm

ULP RISC-V calling assembly from C not working

Postby bitmandu » Mon May 03, 2021 10:10 pm

According to the manual, the ULP-RISC-V co-processor on the esp32-s2 can be programmed with both C and assembly. I'm having trouble getting a trivial example using both C and assembly to work.

My code (on GitHub) builds and runs, but doesn't return the correct result from a function implemented in assembly.

This is the code running on the ULP-RISC-V:

Code: Select all

#include "ulp_riscv/ulp_riscv.h"
#include "ulp_riscv/ulp_riscv_utils.h"

extern int add(int x, int y);

volatile int result_s;
volatile int result_c;

int main(void)
{
    result_s = add(1, 2);
    result_c = 1 + 2;
}
My main application prints out both ulp_result_s and ulp_result_c. Instead of 3, both are 0.

If I comment out the call to the external assembly function add()

Code: Select all

    //result_s = add(1, 2);
    result_c = 1 + 2;
the C-only part works and ulp_result_c is correct (3).

The add function is implemented as add.S:

Code: Select all

.section .text

.global add
.type add, @function

add:
	add a0, a0, a1
	ret
I don't think it can get any simpler, but I am by no means an expert in assembly.

Everything builds and flashes to the chip fine. Any help getting this to work is appreciated!

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: ULP RISC-V calling assembly from C not working

Postby ESP_Angus » Wed May 05, 2021 7:39 am

Hi bitmandu,

Thanks for the very clear test case! After scratching my head about this for a bit, I can confirm this is a bug in the ESP-IDF linker script that we will fix ASAP. In the meantime you can make your program work by changing the name of the assembly section that holds the add function, like this:

Code: Select all

.section .text.add

.global add
.type add, @function

add:
	add a0, a0, a1
	ret
(The section names for assembly files can be ".text.anything", anything but ".text")

Why does this fix the problem? Address 0x0 in the ULP binary has to be the ULP CPU's reset vector that starts program execution. This currently happens in most cases only because the reset vector is the only function in the ".text" section and this section is placed first by the linker script (any C files are compiled with -ffunction-sections so they all have section names like .text.something).

Because "add.S" was sorted first in the linker order, the add() function was placed at address 0x0 in the ULP binary and executed first as if it was the reset vector. Causing the whole program not to run!

Thanks again for helping us find and fix this. Sorry for the time it's probably cost you.

bitmandu
Posts: 6
Joined: Fri Apr 23, 2021 2:37 pm

Re: ULP RISC-V calling assembly from C not working

Postby bitmandu » Thu May 06, 2021 1:12 am

Thanks for the help ESP_Angus! Your explanation (and solution) really made things clear.

Who is online

Users browsing this forum: No registered users and 298 guests