<div dir="ltr"><div>I'm busy adding EEPROM access to the code generator for AVR. Although the general code required is relatively straight forward, the problem I ran into is that the EEPROM access registers are not at the same addresses for the different controllers. The register names and addresses are included in the respective controller units, so the addresses are available in the automatically loaded controller unit at compile time.</div><div><br></div><div>For example I do not know how to generate the equivalent to the following user assembler code:</div><div> lds r0, EECR</div><div>where EECR is defined as follows in a different unit:</div><div>var EECR: byte absolute $1F;</div><div><br></div><div>The following line illustrates what I'm attempting to do:</div><div></div><div> list.concat(taicpu.op_reg_ref(A_LDS,tmpreg,tmpref));</div><div>where tempref should reference the EECR symbol in another unit.</div><div><br></div><div>How do I build such a reference in the code generator so that the reference can resolve to the appropriate address?</div><div><br></div><div>Regards,</div><div>Christo<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Oct 4, 2020 at 1:49 PM Christo Crause <<a href="mailto:christo.crause@gmail.com" target="_blank">christo.crause@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">The AVR architecture uses different address spaces with potentially different access methods [1]. Currently constant data (messages, bitmaps etc.) are stored in flash and copied to RAM by the start-up code. Data access makes use of the LD* instructions (and ST* if the data is writeable). Accessing e.g. read-only data directly from flash saves RAM space - this can be done byt informing the linker to locate the data in the progmem section. While one can use the section modifier to inform the linker to place data in specific address spaces it still require user supplied access code. This leads to code and maintenance duplication for the user to cater for different memory spaces, with associated code bloat.<br><br>The xtensa architecture has several address reagions that can be used for different purposes [2]. One example would be to place time critical interrupt code in the IRAM address space. The DRAM space can also be used to store constant data which can be accessed from an interrupt routine. Several other address spaces are available for specific use cases [3].<br><br>FPC can use the section modifier to specify which address space should be used for data. It is however very limited in that the code generator is not aware of the potentially different address spaces that can be specified, hence it is up to the user to provide the correct access code (for AVR). The section modifier also takes a user supplied string, which currently isn't checked for sensible or allowed values. I want to propose a unified mechanism for specifying both data and instruction address spaces using the same syntax for functions/procedures and variables, together with implementing the necessary access functionality as required (mainly AVR) for the compiler to generate the appropriate code without further user involvement.<br><br>The first proposal is to extend the section modifier to accept predefined (target specific) keywords (flash, eeprom, iram, dram, rtc_noinit and others), e.g.:<br>// AVR const data in flash<br>const<br> smileyGlyph: array[0..6] of byte = (19, 35, 64, 92, 64, 35, 19); section flash; // keep data in flash, read using spm (or LD* for newer AVRs)<br><br>// AVR Read/write access to data stored in EEPROM<br>var<br> restartCount: byte; section eeprom; // If one needs a fixed location, perhaps use in combination with absolute? <br><br>// Xtensa interrupt handler user code<br>procedure encoderPulse; section iram;<br><br>// Xtensa code that executes after wakeup from deep sleep<br>procedure afterDeepSleep; section rtc_iram;<br><br>// Xtensa variable that retains value after deep sleep:<br>var<br> oldState: uint32; section rtc_slow_data;<br><br>The alternative is to skip the section modifier and simply use the various keywords (flash, iram etc.) as modifiers. Not sure if there is any advantage of this compared to the first proposal.<br><br>Critique, improvements and other use cases to consider would be appreciated.<br><br>[1] <a href="https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html#AVR-Named-Address-Spaces" target="_blank">https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html#AVR-Named-Address-Spaces</a><br>[2] <a href="https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/general-notes.html#memory-layout" target="_blank">https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/general-notes.html#memory-layout</a><br>[3] <a href="https://github.com/espressif/esp-idf/blob/7b7c641076ef4c5dff7b994170d445bbb46f81ab/components/xtensa/include/esp_attr.h#L21" target="_blank">https://github.com/espressif/esp-idf/blob/7b7c641076ef4c5dff7b994170d445bbb46f81ab/components/xtensa/include/esp_attr.h#L21</a><br></div>
</blockquote></div></div>