Overriding linker location for a single IDF routine?

go4retro
Posts: 18
Joined: Thu Jan 10, 2019 5:36 am

Re: Overriding linker location for a single IDF routine?

Postby go4retro » Mon Jan 21, 2019 4:54 am

esp-idf 3.3 (dloaded a few weeks ago)

esp32 devkit 1 (https://docs.zerynth.com/latest/officia ... index.html)

Jim

Ritesh
Posts: 1383
Joined: Tue Sep 06, 2016 9:37 am
Location: India
Contact:

Re: Overriding linker location for a single IDF routine?

Postby Ritesh » Wed Jan 23, 2019 4:32 pm

go4retro wrote:
Mon Jan 21, 2019 4:54 am
esp-idf 3.3 (dloaded a few weeks ago)

esp32 devkit 1 (https://docs.zerynth.com/latest/officia ... index.html)

Jim
Hi,

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

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

Re: Overriding linker location for a single IDF routine?

Postby ESP_Angus » Thu Jan 24, 2019 2:01 am

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

go4retro
Posts: 18
Joined: Thu Jan 10, 2019 5:36 am

Re: Overriding linker location for a single IDF routine?

Postby go4retro » Thu Jan 24, 2019 4:48 am

Ritesh wrote:
Wed Jan 23, 2019 4:32 pm
go4retro wrote:
Mon Jan 21, 2019 4:54 am
esp-idf 3.3 (dloaded a few weeks ago)

esp32 devkit 1 (https://docs.zerynth.com/latest/officia ... index.html)

Jim
Hi,

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 was indeed using v3.3, but I repeated the test with v3.1.2, dloaded tonight from here: https://github.com/espressif/esp-idf/releases

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.*)
I then performed a 'make clean' and then 'make flash'.

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

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

Re: Overriding linker location for a single IDF routine?

Postby ESP_Angus » Thu Jan 24, 2019 6:45 am

go4retro wrote:
Thu Jan 24, 2019 4:48 am
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.
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?)

ESP_igrr
Posts: 2072
Joined: Tue Dec 01, 2015 8:37 am

Re: Overriding linker location for a single IDF routine?

Postby ESP_igrr » Thu Jan 24, 2019 10:39 am

Also it's probably gpio.o rather than gpio_set_level.o

go4retro
Posts: 18
Joined: Thu Jan 10, 2019 5:36 am

Re: Overriding linker location for a single IDF routine?

Postby go4retro » Thu Jan 24, 2019 7:42 pm

ESP_igrr wrote:
Thu Jan 24, 2019 10:39 am
Also it's probably gpio.o rather than gpio_set_level.o
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
But, when I compile, the map file doesn't *seem* to show it in iram:

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 
 
I used the standard blink example as my base, have made no other changes to the Makefile.

Jim

go4retro
Posts: 18
Joined: Thu Jan 10, 2019 5:36 am

Re: Overriding linker location for a single IDF routine?

Postby go4retro » Thu Jan 24, 2019 7:57 pm

ESP_Angus wrote:
Thu Jan 24, 2019 6:45 am

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.
Looks like not:

Code: Select all

$ nm blink.elf | grep gpio_set_level
400e6a38 T gpio_set_level

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?)
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)

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
It's the clock pin that is causing the issue. The specification shows that the master (not my unit) will bring the clock low to signify to the device that it should read the data on the 4 data lines. THen, it will raise the clock line and look to see if the clock line is now high. If the device is faster than the master, there are no worries, but if the device needs more time to read or handle the data, it can bring the clock line low to signal more time is needed. The master will then wait until the clock line returns high.

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

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

Re: Overriding linker location for a single IDF routine?

Postby ESP_Angus » Fri Jan 25, 2019 2:47 am

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.)

go4retro
Posts: 18
Joined: Thu Jan 10, 2019 5:36 am

Re: Overriding linker location for a single IDF routine?

Postby go4retro » Fri Jan 25, 2019 4:15 am

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

Who is online

Users browsing this forum: Gaston1980 and 175 guests