Overriding linker location for a single IDF routine?
Re: Overriding linker location for a single IDF routine?
esp-idf 3.3 (dloaded a few weeks ago)
esp32 devkit 1 (https://docs.zerynth.com/latest/officia ... index.html)
Jim
esp32 devkit 1 (https://docs.zerynth.com/latest/officia ... index.html)
Jim
Re: Overriding linker location for a single IDF routine?
Hi,go4retro wrote: ↑Mon Jan 21, 2019 4:54 amesp-idf 3.3 (dloaded a few weeks ago)
esp32 devkit 1 (https://docs.zerynth.com/latest/officia ... index.html)
Jim
Are you sure IDF version 3.3 you have taken as last stable release is 3.1 branch?
Please confirm with that as well.
Regards,
Ritesh Prajapati
Ritesh Prajapati
Re: Overriding linker location for a single IDF routine?
Hi go4retro,
There is a bug/limitation in the linker script generator feature where each library (ie libdriver in this case) can only be mentioned in one linker script fragment per project.
Originally the use cases for linker script fragments didn't seem to require the same library to be mentioned in multiple fragments, but we've discovered that this is not the case (and so have you!)
Support for this is being worked on now and will probably be released in IDF v3.3.
In the meantime, the best workaround is to tweak IDF: edit the esp32.common.ld linker script (as Ritesh suggests), or to delete the conflicting components/app_trace/linker.lf fragment if you're not using the app_trace feature. Or it's possible to set the COMPONENTS variable in the project to not include the app_trace component in the project build at all.
Angus
There is a bug/limitation in the linker script generator feature where each library (ie libdriver in this case) can only be mentioned in one linker script fragment per project.
Originally the use cases for linker script fragments didn't seem to require the same library to be mentioned in multiple fragments, but we've discovered that this is not the case (and so have you!)
Support for this is being worked on now and will probably be released in IDF v3.3.
In the meantime, the best workaround is to tweak IDF: edit the esp32.common.ld linker script (as Ritesh suggests), or to delete the conflicting components/app_trace/linker.lf fragment if you're not using the app_trace feature. Or it's possible to set the COMPONENTS variable in the project to not include the app_trace component in the project build at all.
Angus
Re: Overriding linker location for a single IDF routine?
I was indeed using v3.3, but I repeated the test with v3.1.2, dloaded tonight from here: https://github.com/espressif/esp-idf/releasesRitesh wrote: ↑Wed Jan 23, 2019 4:32 pmHi,go4retro wrote: ↑Mon Jan 21, 2019 4:54 amesp-idf 3.3 (dloaded a few weeks ago)
esp32 devkit 1 (https://docs.zerynth.com/latest/officia ... index.html)
Jim
Are you sure IDF version 3.3 you have taken as last stable release is 3.1 branch?
Please confirm with that as well.
I compiled and ran with no changes to common.ld first, and the problem exists still. So, I went into common.ld and added line 113 and 114:
Code: Select all
/*jlb*/
*libdriver.a:gpio_set_level.o(.literal .text .literal.* .text.*)
The problem persists. The gpio_set_level() takes far too long to react to the event (the event lasts 9.5uS, and the gpio level does not change for 29uS.
Jim
Re: Overriding linker location for a single IDF routine?
You can verify that gpio_set_level ended up in IRAM by looking at the .map file output in the build directory, or running "nm PROJECT.elf" and looking for gpio_set_level address.
Can you explain exactly what you're looking to do? It sounds like you need to do more than just set the level (ie monitor for some input and react to it?)
Re: Overriding linker location for a single IDF routine?
Also it's probably gpio.o rather than gpio_set_level.o
Re: Overriding linker location for a single IDF routine?
Thanks. I changed it to gpio.o
Code: Select all
.iram0.text :
{
/* Code marked as runnning out of IRAM */
_iram_text_start = ABSOLUTE(.);
*(.iram1 .iram1.*)
*libfreertos.a:(.literal .text .literal.* .text.*)
*libheap.a:multi_heap.*(.literal .text .literal.* .text.*)
*libheap.a:multi_heap_poisoning.*(.literal .text .literal.* .text.*)
*libesp32.a:panic.*(.literal .text .literal.* .text.*)
*libesp32.a:core_dump.*(.literal .text .literal.* .text.*)
*libapp_trace.a:(.literal .text .literal.* .text.*)
*libxtensa-debug-module.a:eri.*(.literal .text .literal.* .text.*)
*librtc.a:(.literal .text .literal.* .text.*)
*libsoc.a:(.literal .text .literal.* .text.*)
*libhal.a:(.literal .text .literal.* .text.*)
*libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*)
*libspi_flash.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*)
*libgcov.a:(.literal .text .literal.* .text.*)
/*jlb*/
*libdriver.a:gpio.o(.literal .text .literal.* .text.*)
INCLUDE esp32.spiram.rom-functions-iram.ld
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg
app.map relevant entries:
Code: Select all
.literal.gpio_set_level
0x400d0be4 0x4 C:/Users/brain/projects/HEXTIr/build/driver\libdriver.a(gpio.o)
0x20 (size before relaxing)
...
.text.gpio_set_level
0x400e6a38 0xbd C:/Users/brain/projects/HEXTIr/build/driver\libdriver.a(gpio.o)
0xc1 (size before relaxing)
0x400e6a38 gpio_set_level
*fill* 0x400e6af5 0x3
Jim
Re: Overriding linker location for a single IDF routine?
Looks like not:
Code: Select all
$ nm blink.elf | grep gpio_set_level
400e6a38 T gpio_set_level
Sure, and let me state that I realize I may be asking too much of the esp32. I can head down another path if necessary, but I'd hate to add more HW to the effort only to find out it was just a compilation issue (which it looks like it might be)
Can you explain exactly what you're looking to do? It sounds like you need to do more than just set the level (ie monitor for some input and react to it?)
I am trying to provide a Wifi interface to a system with a non standard bus. The bus contains the following interesting aspects:
- It's a 4 bit bus, but is bidirectional like I2C using open collector outputs
- It has a "Bus Available" line which is also open collector and bi directional
- Finally, it has a clock pin that is bidirectional and is also used as an bus acknowledge function
For performance, I've placed the clock pin on an interrupt, and the first thing I do in the ISR is bring the clock line low, to signify I need more time to handle things. I then raise the clock line at the end of the ISR.
BUt, what I see on the trace is the master bringing the clock line low, waiting for 10uS, bringing the line high, and then 19uS after the line goes high, the ISR brings it low again, and then high again after the ISR over.
Once the ISR is called once, subsequent calls show no latency. SO, it does seem obvious it's a caching issue.
Jim
Re: Overriding linker location for a single IDF routine?
It does sound like moving this function to IRAM will help.
If you search the map file for the exact line you added to esp32.common.ld (*libdriver.a:gpio.o(.literal .text .literal.* .text.*)), do you find it? One part of the map file should have each line of the linker script which was processed, followed by the symbols linked by this line.
If it's not there at all, it's possible you found a bug in the build system where modifying esp32.common.ld didn't cause a re-link? Deleting the ELF file should force the re-link, if that's the case (shouldn't be necessary, though.)
If you search the map file for the exact line you added to esp32.common.ld (*libdriver.a:gpio.o(.literal .text .literal.* .text.*)), do you find it? One part of the map file should have each line of the linker script which was processed, followed by the symbols linked by this line.
If it's not there at all, it's possible you found a bug in the build system where modifying esp32.common.ld didn't cause a re-link? Deleting the ELF file should force the re-link, if that's the case (shouldn't be necessary, though.)
Re: Overriding linker location for a single IDF routine?
Initially, the map file did *NOT* have the libdriver.a:gpio.o line. I checked all over my esp-idf dirs looking for a miss, to find none. But, then I found that the build dir in my project had an build/esp32/esp32.common.ld file with the wrong syntax (libdriver.a:gpio_set_level.o). I changed it there.
I had done a make clean every time I changed the esp-idf/components/esp32/common.ld file, but it appears the files in the build dir don't all get refreshed during a make clean, make all sequence.
With that fixed, the code is now working, though it is still tight. The ISR does not seem to respond and drive the GPIO for 9uS after the event, and I am concerned about that margin (8uS is the minimum specified time as per protocol, and 9.5uS was empirically seen).
I also tested it under v3.3 beta, and the same response time was seen.
Still, thanks for getting me past this hurdle. Now, I need to either find a way to shave a few more uS off to get some margin, or I might have to still consider using HW to address the issue...
Jim
I had done a make clean every time I changed the esp-idf/components/esp32/common.ld file, but it appears the files in the build dir don't all get refreshed during a make clean, make all sequence.
With that fixed, the code is now working, though it is still tight. The ISR does not seem to respond and drive the GPIO for 9uS after the event, and I am concerned about that margin (8uS is the minimum specified time as per protocol, and 9.5uS was empirically seen).
I also tested it under v3.3 beta, and the same response time was seen.
Still, thanks for getting me past this hurdle. Now, I need to either find a way to shave a few more uS off to get some margin, or I might have to still consider using HW to address the issue...
Jim
Who is online
Users browsing this forum: Gaston1980 and 175 guests