• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Размер IRAM

Garmin

Member
Столкнулся тут с нехваткой памяти кэша программ. Подключение библиотеки libat в SDK 2.0 тянет за собой ещё три библиотеки, и требуемая память программ становится больше 32к. Начал гуглить вопрос 48k iram и нашёл регистр с адресом 0x3FF00024 , в котором биты 3 и 4 отвечают за маппинг памяти iram 40108000h - 4010C000h.
Вот чего я не знаю - этот регистр только для чтения, и размер памяти программ задаётся заводом, или его можно включать самому?
 

pvvx

Активный участник сообщества
Столкнулся тут с нехваткой памяти кэша программ.
Что за проект, которому необходимо помещение такого кол-ва процедур в IRAM? :eek:
Подключение библиотеки libat в SDK 2.0 тянет за собой ещё три библиотеки, и требуемая память программ становится больше 32к.
В связи с чем их нельзя разместить в область кеша Flash?
Эти библиотеки исполняются в аппаратных прерываниях в момент недоступности Flash (в момент записи или стирания flash)? :eek:
Единственно понятное увеличение размера IRAM до 48 кило за счет отключения части 'кеша' Flash - для увеличения размера RAM и использования дополнительной части для буферов данных или загрузки программных оверлеев из области flash недосягаемой 'кешем' или из внешних интерфесов...
 

Garmin

Member
Проект небольшой, и при использовании SDK 1.5.0 требовалось 31k iram.
Исходным был демо проект lwip_open_demo_app. В него я добавил библиотеку AT команд (прописал в makefile -lat).
Я столкнулся с проблемой IP адресов и решил проверить свой проект в версии SDK 2.0.
Библиотека libat.a в этой версии потребовала ещё libwps.a, liblwip.a, libairkiss.a
В результате памяти требуется 33к :(
Я с библиотеками ничего поделать не могу, только использовать старый вариант libat.
 

pvvx

Активный участник сообщества
Опишите распределение библиотек в область 'кеша' Flash, в ld файле. Во время записи/стирания flash в SDK прерывания запрещены и процедуры из 'кеша' Flash не вызываются. В остальное время область 'кеша' Flash для процессора всегда доступна.
В IRAM помещаются процедуры исполняемые до включения и инициализации 'кеша' Flash и критические обработчики аппаратных прерываний. А в аппаратных прерываниях не используют громоздкие внешние библиотеки...
Другой вариант - используйте укороченную версию libmgcc.a, из которой убраны дубли процедур находящиеся в BIOS-ROM.
Китайский SDK и его загрузчики не поддерживают 48к IRAM - требуется масса патчей и свои загрузчики с инициализацией. Иначе область выше 32k будет всегда затираться.
Если критические процедуры не лезут в 32к (!) IRAM - значит не тот проц выбрали для проекта или неверно составлен сам проект.
 
Последнее редактирование:

Garmin

Member
Посмотрю, как устроен ld файл...
Скорее всего, мне не будет нужна новая библиотека. Посмотрю, что получится.
А насчёт самого вопроса:
регистр с адресом 0x3FF00024 доступен только для чтения, или можно вручную его переписать, и размер iram изменится? Безотносительно поддержки в программах.
 

pvvx

Активный участник сообщества
Посмотрю, как устроен ld файл...
Скорее всего, мне не будет нужна новая библиотека. Посмотрю, что получится.
А насчёт самого вопроса:
регистр с адресом 0x3FF00024 доступен только для чтения, или можно вручную его переписать, и размер iram изменится? Безотносительно поддержки в программах.
В этом регистре включаются/выключаются используемые под 'кеш' Flash две страницы по 16 кило, следующие за областью 32к IRAM.
IRAM имеет 64 килобайта. Простое переключение на ходу из области кешируемого кода без команды реинициализации 'кеша' может привести к печальным последствиям :). Данное отключение части 'кеша' надо производить из первой части (32k) IRAM...
Примеры, спец.загрузчик, код и прочее для реализации опции 48к IRAM даны в Web-свалке...
 

Garmin

Member
Простое чтение команд линковщика не дало понимания.
Вот мой ld файл:
Код:
/* This linker script generated from xt-genldscripts.tpp for LSP . */
/* Linker Script for ld -N */
MEMORY
{
  dport0_0_seg :                        org = 0x3FF00000, len = 0x100
  dram0_0_seg :                         org = 0x3FFE8000, len = 0x14000
  iram1_0_seg :                         org = 0x40100000, len = 0xC000
  irom0_0_seg :                         org = 0x40210000, len = 0xBC000
}

PHDRS
{
  dport0_0_phdr PT_LOAD;
  dram0_0_phdr PT_LOAD;
  dram0_0_bss_phdr PT_LOAD;
  iram1_0_phdr PT_LOAD;
  irom0_0_phdr PT_LOAD;
}


/*  Default entry point:  */
ENTRY(call_user_start)
EXTERN(_DebugExceptionVector)
EXTERN(_DoubleExceptionVector)
EXTERN(_KernelExceptionVector)
EXTERN(_NMIExceptionVector)
EXTERN(_UserExceptionVector)
PROVIDE(_memmap_vecbase_reset = 0x40000000);
/* Various memory-map dependent cache attribute settings: */
_memmap_cacheattr_wb_base = 0x00000110;
_memmap_cacheattr_wt_base = 0x00000110;
_memmap_cacheattr_bp_base = 0x00000220;
_memmap_cacheattr_unused_mask = 0xFFFFF00F;
_memmap_cacheattr_wb_trapnull = 0x2222211F;
_memmap_cacheattr_wba_trapnull = 0x2222211F;
_memmap_cacheattr_wbna_trapnull = 0x2222211F;
_memmap_cacheattr_wt_trapnull = 0x2222211F;
_memmap_cacheattr_bp_trapnull = 0x2222222F;
_memmap_cacheattr_wb_strict = 0xFFFFF11F;
_memmap_cacheattr_wt_strict = 0xFFFFF11F;
_memmap_cacheattr_bp_strict = 0xFFFFF22F;
_memmap_cacheattr_wb_allvalid = 0x22222112;
_memmap_cacheattr_wt_allvalid = 0x22222112;
_memmap_cacheattr_bp_allvalid = 0x22222222;
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);

SECTIONS
{

  .dport0.rodata : ALIGN(4)
  {
    _dport0_rodata_start = ABSOLUTE(.);
    *(.dport0.rodata)
    *(.dport.rodata)
    _dport0_rodata_end = ABSOLUTE(.);
  } >dport0_0_seg :dport0_0_phdr

  .dport0.literal : ALIGN(4)
  {
    _dport0_literal_start = ABSOLUTE(.);
    *(.dport0.literal)
    *(.dport.literal)
    _dport0_literal_end = ABSOLUTE(.);
  } >dport0_0_seg :dport0_0_phdr

  .dport0.data : ALIGN(4)
  {
    _dport0_data_start = ABSOLUTE(.);
    *(.dport0.data)
    *(.dport.data)
    _dport0_data_end = ABSOLUTE(.);
  } >dport0_0_seg :dport0_0_phdr

  .data : ALIGN(4)
  {
    _data_start = ABSOLUTE(.);
    *(.data)
    *(.data.*)
    *(.gnu.linkonce.d.*)
    *(.data1)
    *(.sdata)
    *(.sdata.*)
    *(.gnu.linkonce.s.*)
    *(.sdata2)
    *(.sdata2.*)
    *(.gnu.linkonce.s2.*)
    *(.jcr)
    _data_end = ABSOLUTE(.);
  } >dram0_0_seg :dram0_0_phdr

  .rodata : ALIGN(4)
  {
    _rodata_start = ABSOLUTE(.);
    *(.sdk.version)
    *(.rodata)
    *(.rodata.*)
    *(.gnu.linkonce.r.*)
    *(.rodata1)
    __XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
    *(.xt_except_table)
    *(.gcc_except_table)
    *(.gnu.linkonce.e.*)
    *(.gnu.version_r)
    *(.eh_frame)
    /*  C++ constructor and destructor tables, properly ordered:  */
    KEEP (*crtbegin.o(.ctors))
    KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
    KEEP (*crtbegin.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
    /*  C++ exception handlers table:  */
    __XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
    *(.xt_except_desc)
    *(.gnu.linkonce.h.*)
    __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
    *(.xt_except_desc_end)
    *(.dynamic)
    *(.gnu.version_d)
    . = ALIGN(4);        /* this table MUST be 4-byte aligned */
    _bss_table_start = ABSOLUTE(.);
    LONG(_bss_start)
    LONG(_bss_end)
    _bss_table_end = ABSOLUTE(.);
    _rodata_end = ABSOLUTE(.);
  } >dram0_0_seg :dram0_0_phdr

  .bss ALIGN(8) (NOLOAD) : ALIGN(4)
  {
    . = ALIGN (8);
    _bss_start = ABSOLUTE(.);
    *(.dynsbss)
    *(.sbss)
    *(.sbss.*)
    *(.gnu.linkonce.sb.*)
    *(.scommon)
    *(.sbss2)
    *(.sbss2.*)
    *(.gnu.linkonce.sb2.*)
    *(.dynbss)
    *(.bss)
    *(.bss.*)
    *(.gnu.linkonce.b.*)
    *(COMMON)
    . = ALIGN (8);
    _bss_end = ABSOLUTE(.);
    _heap_start = ABSOLUTE(.);
/*    _stack_sentry = ALIGN(0x8); */
  } >dram0_0_seg :dram0_0_bss_phdr
/* __stack = 0x3ffc8000; */

  .text : ALIGN(4)
  {
    _stext = .;
    _text_start = ABSOLUTE(.);
    *(.UserEnter.text)
    . = ALIGN(16);
    *(.DebugExceptionVector.text)
    . = ALIGN(16);
    *(.NMIExceptionVector.text)
    . = ALIGN(16);
    *(.KernelExceptionVector.text)
    LONG(0)
    LONG(0)
    LONG(0)
    LONG(0)
    . = ALIGN(16);
    *(.UserExceptionVector.text)
    LONG(0)
    LONG(0)
    LONG(0)
    LONG(0)
    . = ALIGN(16);
    *(.DoubleExceptionVector.text)
    LONG(0)
    LONG(0)
    LONG(0)
    LONG(0)
    . = ALIGN (16);
    *(.entry.text)
    *(.init.literal)
    *(.init)
    *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
    *(.fini.literal)
    *(.fini)
    *(.gnu.version)
    _text_end = ABSOLUTE(.);
    _etext = .;
  } >iram1_0_seg :iram1_0_phdr

  .lit4 : ALIGN(4)
  {
    _lit4_start = ABSOLUTE(.);
    *(*.lit4)
    *(.lit4.*)
    *(.gnu.linkonce.lit4.*)
    _lit4_end = ABSOLUTE(.);
  } >iram1_0_seg :iram1_0_phdr

  .irom0.text : ALIGN(4)
  {
    _irom0_text_start = ABSOLUTE(.);
    *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
    libwps.a
    liblwip.a
    libat.a
    libairkiss.a
    _irom0_text_end = ABSOLUTE(.);
  } >irom0_0_seg :irom0_0_phdr
}

/* get ROM code address */
INCLUDE "../ld/eagle.rom.addr.v6.ld"
Для пробы я добавил имена новых библиотек в секцию irom0.text
Размер iram не изменился. Значит эти библиотеки уже размещены.
Но я не знаю, какие из секций можно переместить в кешируемуюпамять.
Вот список, подскажите:
*(.entry.text)
*(.init.literal)
*(.init)
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
 

pvvx

Активный участник сообщества
Для пробы я добавил имена новых библиотек в секцию irom0.text
Размер iram не изменился. Значит эти библиотеки уже размещены.
Но я не знаю, какие из секций можно переместить в кешируемуюпамять.
Вот список, подскажите:
*(.entry.text)
*(.init.literal)
*(.init)
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
А это не простая задача. Необходимо переделывать/переписывать и все исходники (включая китайские :)), назначая свои секции. Стандартные либы обычно размещаются в секции с 'text'...
По переносу секций и всяких добавок типа каждой процедуре своя секция смотрите пример в NodeMCU...
Вы взялись за то, что ещё не полностью осознали из-за пары лишних не лезущих кило. Вам уже дал одно из простых решений:
Другой вариант - используйте укороченную версию libmgcc.a, из которой убраны дубли процедур находящиеся в BIOS-ROM.
В libgcc.a находится куча процедур, которые уже есть в ROM-BIOS. Вам обязательно нужны дубли их в IRAM, чтобы ваши либы не лезли? :confused:
 

Garmin

Member
Я вам благодарен за помощь и консультации.
Я поступил вначале так:
Заменил библиотеку libat.o на вариант от версии 1.5.0 и убрал из команды линкера две ненужные библиотеки libwps.a и libairkiss.a
Проект влез в 32к. Объём iram = 31428 байт
Потом заменил библиотеку libgcc на libmgss и прописал её вместо первой в makefile.
Скомпилированный заново проект имеет iram = 31073 байт. Этого больше, чем достаточно.
pvvx, вы даёте правильные советы, мне совсем не нужны эти дебри. Я просто хочу получить блок, работающий так, как мне нужно.
 

pvvx

Активный участник сообщества
Проект небольшой, и при использовании SDK 1.5.0 требовалось 31k iram.
Исходным был демо проект lwip_open_demo_app. В него я добавил библиотеку AT команд (прописал в makefile -lat).
Я столкнулся с проблемой IP адресов и решил проверить свой проект в версии SDK 2.0.
Библиотека libat.a в этой версии потребовала ещё libwps.a, liblwip.a, libairkiss.a
В результате памяти требуется 33к :(
Я с библиотеками ничего поделать не могу, только использовать старый вариант libat.
Итоги сборки AT2.0.0 для варианта 512к flash, в котрую входят все указанные вами либы + 'обрезанная' libgcc:
Код:
   Section|                   Description| Start (hex)|   End (hex)|Used space
------------------------------------------------------------------------------
      data|        Initialized Data (RAM)|    3FFE8000|    3FFE8864|    2148
    rodata|           ReadOnly Data (RAM)|    3FFE8870|    3FFEA690|    7712
       bss|      Uninitialized Data (RAM)|    3FFEA690|    3FFF2088|   31224
      text|          Uncached Code (IRAM)|    40100000|    401077DF|   30687
irom0_text|             Cached Code (SPI)|    40220000|    4027A8FD|  370941
------------------------------------------------------------------------------
Entry Point : 40100004 call_user_start()
Total Used RAM : 41084
Free RAM : 40836
Free IRam : 2081
 
Сверху Снизу