Using multiple ULP program in a larger project fails silently at runtime (IDFGH-14143) #14945
Open
3 tasks done
Labels
Status: Opened
Issue is new
Answers checklist.
General issue report
It's a bit similar to #14921 in the concept. I have multiple different program for the ULP's LP core on ESP32 C6 CPU. I've declared them like this in the
main
's CMakelists.txt:The first issue happens if you have the same variable name in both file. In that case it's not possible, in C to include the automatically generated header in your main function, since both refer to the same variable, but variables are located at different address. So if I have, let's say a variable called
uint32_t state
in both file, the generated headerulp_main.h
andulp_ds_cal.h
both have anextern uint32_t ulp_state;
. Yet, the first ULP program will have this linker script:PROVIDE ( ulp_state = 0x50000ab8 );
and the second will havePROVIDE ( ulp_state = 0x50000640 );
.Yet, it'll link fine but obviously fails at runtime, since the variable will just refer to a random memory location when using the second program.
So, since it's clear that both variables can't be referred with a single name, I've used C++ like this to move each declaration in its own namespace:
This strangely links fine (I would have expected that the linker choked on an undefined reference on
extern uint32_t ULPDSCal::ulp_state
but it's perfectly happy with that), but obviously it doesn't work at runtime. If I print the address of theULPDSCal::ulp_state
variable in HP core, I get 0x50000ab8, which is the address of the first program, not the second one.I think this is a bug in the linker script that's not using the expected mangled name for linking (it should have failed to link a symbol with a different name, the mangled name for the
ULPDSCal::ulp_state
variable is notulp_state
).It can only be solved by either changing the symbol processing script to allow changing the prefix for the variable (so the first script could use
ulp_
and the second would use, for example,ulp_2_
) or, better, to allow using a C++ namespace instead (so instead ofulp_VARIABLE
, simply have aNAMESPACE::VARIABLE
declaration).Another option would be to have a macro for variable declaration allowing to position the variable at a specific address. Notice that using
uint32_t variable = *(volatile uint32_t*)0x50000210;
is not possible since the linker can place whatever it wants at this address later on. On ARM, there's the attribute__attribute(at(address))__
that can be used for this exact feature.There also the hacky:
that seems to work but this become completely invisible to the linker's script and variable renaming so it's also very fragile since the linker doesn't not know that a variable exists at 0x50000210 and can put whatever it wants here, breaking the code.
The text was updated successfully, but these errors were encountered: