• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Как загнать строки в irom.text

pvvx

Активный участник сообщества
SHERTS - какие надо давать директивы компилятору СИ и т.д, чтобы загнать строки и константы в section ".irom.text" (в кешируемую область flash)?
os_printf в SDK 0.9.5 переписали и он кладет строки в .irom.text.
Код:
#ifdef USE_OPTIMIZE_PRINTF
#define os_printf(fmt, ...) do {    \
    static const char flash_str[] ICACHE_RODATA_ATTR = fmt;    \
    os_printf_plus(flash_str, ##__VA_ARGS__);    \
    } while(0)
#else
#define os_printf    os_printf_plus
#endif
Но, при переносе туда других констант, почему-то возникает "протектед" при обращении к ним...
Я не проф.программер и не знаю что там надо приписать, чтобы загнать в область .irom.text к примеру const char *HTTPCacheControl = "Cache-Control: "; и это потом не вызывало "протектед" при обращении к строке любыми стандартными процедурами... :)
Возможно это связано со спецификой "кеширования" flash. (Типа os_printf сидит в iram, а от туда можно лезть в область "кеширования" flash, а из процедуры с атрибутом ICACHE_FLASH_ATTR нельзя?)
К С++ это тоже теперь относится, т.к. укладка переменных в область "кеширования" flash высвобождает heap и другую RAM память, и так малую. (Иначе у вас вырастет "data" и "rodata" отъев от "bss" и "heap".)
И в SDK 0.9.5 новые загрузчики flash и esp_init_data_default.bin c ещё неизвестными "котовасиями"... И в следующем SDK они опять будут новыми :) Т.е. распределение по по памяти сегментов и их загрузка с распределением не предсказуема.
 
Последнее редактирование:

CHERTS

Moderator
Команда форума
SHERTS - какие надо давать директивы компилятору СИ и т.д, чтобы загнать строки и константы в section ".irom.text" (в кешируемую область flash)?
Возможно так, но я тоже не спец по Си, это кусок из nodemcu-firmware

Код:
#include "c_types.h"
#define ICACHE_STORE_ATTR __attribute__((aligned(4)))
static volatile const uint8_t flash_init_data[128] ICACHE_STORE_ATTR ICACHE_RODATA_ATTR =
{
  0x05, 0x00, 0x04, 0x02, 0x05, 0x05, 0x05, 0x02, 0x05, 0x00, 0x04, 0x05, 0x05, 0x04, 0x05, 0x05,
  0x04, 0xFE, 0xFD, 0xFF, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xE1, 0x0A, 0xFF, 0xFF, 0xF8, 0x00,
  0xF8, 0xF8, 0x52, 0x4E, 0x4A, 0x44, 0x40, 0x38, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05,
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xE1, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x93, 0x43, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
рабоатет с SDK 0.9.5, с SDK 0.9.4 и ниже нужно определить

Код:
#define ICACHE_RODATA_ATTR __attribute__((section(".irom.text")))
 
Последнее редактирование:

pvvx

Активный участник сообщества
Не помогает :( "exception (3)"
exception (3):
epc1=0x4000df2f, epc2=0x00000000, epc3=0x00000000, excvaddr=0x40268e94, depc=0x00000000
static const char HTTPsfupload[] ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = "<html><body style='margin:100px'><form method='post' action='/fsupload' enctype='multipart/form-data'><b>File Upload</b><p><input type='file' name='file' size=40> <input type='submit' value='Upload'></form></body></html>";
0x4000df2f - это в теле memcmp() ROM
0x40268e94 - это в области к`эша Flash:
Код:
40268e90 3e 00 00 00 3c 68 74 6d 6c 3e 3c 62 6f 64 79 20 >...<html><body
40268ea0 73 74 79 6c 65 3d 27 6d 61 72 67 69 6e 3a 31 30 style='margin:10
40268eb0 30 70 78 27 3e 3c 66 6f 72 6d 20 6d 65 74 68 6f 0px'><form metho
40268ec0 64 3d 27 70 6f 73 74 27 20 61 63 74 69 6f 6e 3d d='post' action=
40268ed0 27 2f 66 73 75 70 6c 6f 61 64 27 20 65 6e 63 74 '/fsupload' enct
40268ee0 79 70 65 3d 27 6d 75 6c 74 69 70 61 72 74 2f 66 ype='multipart/f
40268ef0 6f 72 6d 2d 64 61 74 61 27 3e 3c 62 3e 46 69 6c orm-data'><b>Fil
40268f00 65 20 55 70 6c 6f 61 64 3c 2f 62 3e 3c 70 3e 3c e Upload</b><p><
40268f10 69 6e 70 75 74 20 74 79 70 65 3d 27 66 69 6c 65 input type='file
40268f20 27 20 6e 61 6d 65 3d 27 66 69 6c 65 27 20 73 69 ' name='file' si
40268f30 7a 65 3d 34 30 3e 20 3c 69 6e 70 75 74 20 74 79 ze=40> <input ty
40268f40 70 65 3d 27 73 75 62 6d 69 74 27 20 76 61 6c 75 pe='submit' valu
40268f50 65 3d 27 55 70 6c 6f 61 64 27 3e 3c 2f 66 6f 72 e='Upload'></for
40268f60 6d 3e 3c 2f 62 6f 64 79 3e 3c 2f 68 74 6d 6c 3e m></body></html>
40268f70 00 00 00 00
Строка напрямую отдается LwIP-у на передачу.
Без ICACHE_STORE_ATTR ICACHE_RODATA_ATTR работает, но строка помещена в rodata: 0x3ffe8aa0 ~ 0x3ffe9bb8, len: 4376. И выходит на неё меньше heap.
И aligned не требуется - используется указатель на байты.

При:
const char *xxxx ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = "....";
Ругается на ошибку уже компилятор.
Непонятно в каком месте приписывать атрибуты. В разных СИ, особенно для MCU это всё по разному :(
 
Последнее редактирование:

CHERTS

Moderator
Команда форума
Не помогает :( "exception (3)"
При:
const char *xxxx ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = "....";
Ругается на ошибку уже компилятор.
у меня все нормально:

в user_main.c

Код:
#include <c_types.h>
#include "user_config.h"
const char *HTTPCacheControl ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = "HelloWorld";
в user_config_h

Код:
#ifndef __USER_CONFIG_H__
#define __USER_CONFIG_H__

#define ICACHE_STORE_ATTR __attribute__((aligned(4)))

#endif
 

pvvx

Активный участник сообщества
у меня все нормально:
в user_main.c
Но там используется адаптированная os_printf.
Пустое объявление строки никуда нигде не использующееся? :)
И такое странслирует, без обращения к строке:
static const char * hello __attribute__((aligned(4))) __attribute__((section("xaxa"))) = "\nHello World!\n";
 
Последнее редактирование:

pvvx

Активный участник сообщества
CHERTS - перетусовка указателя через (void *) с копированием в os_memcpy() строки из "кэшируемой" области flash в память спасает дело. Похоже что не всегда отрабатывает кеш, при обращениях к section(".irom.text") из кода в section(".irom0.text").
Что-то похожее уже наблюдал - нельзя обращаться к области кэш за раз с длиной более килобайта с чем-то. Типа os_memcpy(ram, cache_flash, 2048) - вызовет "протектед" (есть ещё зависимость от положения копируемого буфера в секторе flash).
По тому давно уже написал при чтении памяти памяти в WEB переход к ограничению размеров блоков, когда попадаем в зону кеширования flash, что снижает скорость передачи по TCP (мельче блоки - меньше скорость).
if((web_conn->udata_start >= 0x40000000)&&(web_conn->udata_start < 0x50000000)&&(len > 1024)) len = 1024;
 
Последнее редактирование:

Andrey

New member
#define ICACHE_STORE_ATTR __attribute__((aligned(4)))
Ничего не понял. Эта запись означает что код будет располагаться с адреса кратного 4. Это выравнивание по 32 битам. И никакого отношения к секциям и кешированию не имеет. Это они так поменяли макрос? Раньше этот макрос располагал код в .irom0.text
Я просто 0.9.5 не ставил ещё.
 

pvvx

Активный участник сообщества
Ничего не понял. Эта запись означает что код будет располагаться с адреса кратного 4. Это выравнивание по 32 битам. И никакого отношения к секциям и кешированию не имеет. Это они так поменяли макрос? Раньше этот макрос располагал код в .irom0.text
Я просто 0.9.5 не ставил ещё.
Это так написано у любителей Lua, а define на .irom0.text другой. Без aligned(4) больше проблем, если читать из flash стандартной процедурой spi_flash_read() - будет "exception".
 

avn

New member
Неглубоко копаете :)

Во-первых, ICACHE_RODATA_ATTR определяется в файле c_types.h только в случае, если при компиляции задан ключ -DICACHE_FLASH
Во-вторых, если вы определяете указатель char *, а не массив char [], то в секцию rodata попадет только сам указатель - 32-битное целое число, а строка останется в секции data и будет загружена в оперативную память, которой очень мало.
В-третьих, функция os_printf_plus только первый аргумент может читать из rodata, а остальные из data, поэтому написать что-то типа console_printf( "XXX: %s\n", xxx ) не получится. Нужно писать аж три оператора:

C:
console_printf( "XXX: " ); os_printf_plus( xxx ); console_printf( "\n" );

Поэтому, описывать строки, которые вы хотите поместить в rodata нужно по образцу:
C:
const char xxx[] ICACHE_RODATA_ATTR STORE_ATTR = "xxx";

И проверьте, правильно ли у вас определена console_printf (в некоторых заголовочных файлах я встречал ошибки):

C:
#define USE_OPTIMIZE_PRINTF // можно вынести в ключ компиляции -DUSE_OPTIMIZE_PRINTF
#ifdef USE_OPTIMIZE_PRINTF
#ifdef console_printf
#undef console_printf
#endif
int os_printf_plus(const char *format, ...)  __attribute__ ((format (printf, 1, 2)));
#define console_printf(fmt, ...) do {   \
   static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = fmt; \
   os_printf_plus(flash_str, ##__VA_ARGS__); \
   } while(0)
#endif

А вот проблема, которую мне так и не удалось решить - это как запихнуть в rodata массив указателей и сами строки char *xxx[] . Указатели-то попадают куда надо, а вот строки остаются в оперативной памяти.

Т.е. писать приходится как-то так:

C:
const char FlashSizeMap[][32] ICACHE_RODATA_ATTR STORE_ATTR =
{
        "512 KB (256 KB + 256 KB)",   // 0x00
       "256 KB",           // 0x01
       "1024 KB (512 KB + 512 KB)",    // 0x02
       "2048 KB (512 KB + 512 KB)",   // 0x03
       "4096 KB (512 KB + 512 KB)",   // 0x04
       "2048 KB (1024 KB + 1024 KB)",   // 0x05
       "4096 KB (1024 KB + 1024 KB)"   // 0x06
};

Для вышепреведенного примера это небольшая проблема, но если строки существенно отличаются по длине, то память расходуется неэффективно.
 

pvvx

Активный участник сообщества
Неглубоко копаете :)
Всё уже перекопано и вывернуто через .. . :)

функция os_printf_plus только первый аргумент может читать из rodata, а остальные из data, поэтому написать что-то типа console_printf( "XXX: %s\n", xxx ) не получится. Нужно писать аж три оператора:
[inline]console_printf( "XXX: " ); os_printf_plus( xxx ); console_printf( "\n" );[/inline]
:) Это кому как -> esp8266web/os_printf.c at master · pvvx/esp8266web · GitHub

А вот проблема, которую мне так и не удалось решить - это как запихнуть в rodata массив указателей и сами строки char *xxx[] .
Ручками. Описываете каждую строчку отдельно, а указатели на них в другой массив... Примерно так esp8266web/web_srv.c at master · pvvx/esp8266web · GitHub
Или создаете отдельный файл и в obj производите замену секций...
PS: что вы ожидаете от недоделанного компилятора на экзотический процессор? :)
 
Последнее редактирование:

avn

New member
Всё уже перекопано и вывернуто через .. . :)
Уверен, но здесь это не получило отражения.

:) Это кому как -> esp8266web/os_printf.c at master · pvvx/esp8266web · GitHub

Это альтернативная реализация, я написал про стандартный SDK

Ручками. Описываете каждую строчку отдельно, а указатели на них в другой массив... Примерно так esp8266web/web_srv.c at master · pvvx/esp8266web · GitHub
Или создаете отдельный файл и в obj производите замену секций...

Понятно, что извратиться можно всегда, непонятно, почему штатно код генерится неверно.

PS: что вы ожидаете от недоделанного компилятора на экзотический процессор? :)
Ничего не ожидаю, просто описываю глюки.
 
Сверху Снизу