Chat freely about anything...

User avatar
By attil
#23330 Hello,
I have a problem with a project big enough not to fit in iROM.
I've compiled all the files using xtensa's gcc/g++ to objects, then tried linked them. I am using these memory map options:
Code: Select allMEMORY
{
  dport0_0_seg :                        org = 0x3FF00000, len = 0x10
  dram0_0_seg :                         org = 0x3FFE8000, len = 0x14000
  iram1_0_seg :                         org = 0x40100000, len = 0x8000
  irom0_0_seg :                         org = 0x40201010, len = 0x69ff0
}

It didn't work sadly, as .text section was too big to fit in irom, as ld told me. To remedy that, I have found on the google I should move .text section and .literal to irom, which according to the above memory map is much, much bigger. I did so by moving
Code: Select all    *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)

line in linker script from .text to .irom0.text.
Everything compiled nice this time and I've got an elf file. I converted everything to .bin files, using esptool.py and got two bin files: one starting at 0x00000 and one starting at 0x01010. While uploading the first one worked fine, second one couldn't be uploaded (exception: failed to enter flash download mode) which indicated bad starting address. I have changed memory map in linker script to:
Code: Select allMEMORY
{
  dport0_0_seg :                        org = 0x3FF00000, len = 0x10
  dram0_0_seg :                         org = 0x3FFE8000, len = 0x14000
  iram1_0_seg :                         org = 0x40100000, len = 0x8000
  irom0_0_seg :                         org = 0x40240000, len = 0x69ff0
}

Everything compiled fine once again, i elf2bin'd elf file again, this time, as expected, I've got 0x00000 and 0x40000 addresses, which I could upload this time. Everything seemed fine expect...
It doesn't work
I've reduced the setup function to setting up Serial at 9600 and loop to writing something at it, so it should be extremely easy to see it works, but it doesn't nothing shows up on serial monitor.
To me it seems like the program is not even starting, as I dont think I have notified ESP where the program starts or something like that. But I am quite new to this, so I may be missing or forgetting something.
In short, what I've done:

1. Compile files to .a
2. Link them together with libraries
3. esptool.py elf2bin
4. esptool.py write_flash

Any help would be appreciated!

Edit: If it may help, I am using ESP8266 Arduino libraries, but I'm not using its IDE. This is important, because I am porting an already-existing Arduino project to ESP8266.

Analyzing eagle.rom.addr.v6.ld, it looks like there are defined some addresses of functions, like the one named __start looks like beginning of the program. Maybe these only apply to the provided sdk library and not to mine? (Im guessing, because I have no idea what I am doing). Is this correlated to this issue?

Alternatively, how to run a program bigger than 64kB (I think that is the size of IRAM?) without moving everything to irom? Is it even possible?
User avatar
By attil
#23395 Hello,
Sorry for double post, but I've managed to resolve this problem and decided to post the way to do it here, for people who might have similar problems in future.

What has worked is instead of placing entire thing in irom, I've placed only my custom functions.
That is done by placing
Code: Select all*(.literal.* .text.*)

in irom section and removing that part from iram.
Now, we only have to place our functions etc in .literal.* and .text.* sections, while the sdk etc. stays in .text and .literal. How to do it?
For example, use these flags as a parameter for gcc:
Code: Select all-ffunction-sections
-fdata-sections


After uploading it, everything worked fine!
User avatar
By eriksl
#23490 I have the impression you do not understand what you're doing.

First of all the terminology.

iram (or iram0) is a piece of 32 k (available) RAM memory. Every piece of code that doesn't have the ugly ICACHE_FLASH_ATTR in front of it, will end up in the .text section and .text section will end up in this piece of RAM (copied from SPI flash at start). And that is only 32 kbyte large. A lot of functions from various libraries are (also) not prefixed with ICACHE_FLASH_ATTR, so they also end up in the iram. That's why there is only a few kbyte left for your code.

irom is just the plain SPI flash memory. Your program can be as big as the flash memory is (divided by 2 for OTA updates and minus library code and minus the 32 k of the iram code). That will still get you about 100 kbytes of storage, which I think is plenty (otherwise buy a version with large SPI flash modules, they exist).

So. The chance that you run out of irom space is really small. You're probably running out of iram space. Mostly you can prevent that by carefully prefix each function that doesn't need to run at full speed with ICACHE_FLASH_ATTR.

Code running in irom runs at 1/4 of the speed, the SPI flash is "serial" (four data lines) and is not nearly as fast as the internal static ram.

Code that really must be run from iram is interrupt handlers and code that writes to flash. Other code can easily run from irom, albeit a bit slower, is my experience.

Don't go tinkering with loader scripts if you don't know what you're doing.
User avatar
By dkinzer
#23984
eriksl wrote:Every piece of code that doesn't have the ugly ICACHE_FLASH_ATTR in front of it, will end up in the .text section [...]
That is true but, as the OP suggested, it is a simple matter to use objcopy to rename the sections so that they end up in irom0. The objcopy parameters needed are:
Code: Select all--rename-section .text=.irom0.text --rename-section .literal=.irom0.literal

This is much easier than going through the source code adding the ICACHE_FLASH_ATTR attribute to every function and, as a bonus, it works even if you don't have access to the source code.