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

Где взять описание отсутствующих в офф.доках функций?

JustACat

Moderator
Команда форума
Пришло время и мне задать нубский вопрос, и пусть те, кто уже прошел по граблям, похахают надо мной, но все же, желательно, помогут.

Итак, пытаюсь въехать в код. Если конкретно, то код из Sming. Хотя вроде это не имеет значения. SDK v 1.0.0
Ковыряю функцию:
Код:
Serial.systemDebugOutput();
Пытаюсь найти ее вызов, мне eclipse вроде бы показывает: class HardwareSerial который тут:
C:\Sming\Sming\SmingCore\HardwareSerial.h
(чтобы скопировать путь, пришлось открыть его в Notepad++ там так удобно, правой кнопкой по закладке и там все есть, в эклипсе такое не нашел)
Ок, значит реализация там же рядом в HardwareSerial.cpp Хорошо, нашли:
Код:
void HardwareSerial::systemDebugOutput(bool enabled)
{
    if (uart == UART_ID_0)
        os_install_putc1(enabled ? (void *)uart_tx_one_char : NULL);
    //else
    //    os_install_putc1(enabled ? (void *)uart1_tx_one_char : NULL); //TODO: Debug serial
}
Но дальше-то затык... Что такое os_install_putc1?
Эклипс мне уже не смог ответить на этот вопрос (может я не так чего нажимаю?)...
Хорошо, воспользуемся поиском по файлам в Notepad++.
Ага, нашли единственное место:
C:\Espressif\ESP8266_SDK\include\osapi.h
Код:
#define os_install_putc1 ets_install_putc1
Круто... Теперь ищем ets_install_putc1 и находим его вот тут:
C:\Sming\Sming\system\include\esp_systemapi.h
Код:
extern void ets_install_putc1(void *routine);
И еще вот тут:
C:\Espressif\ESP8266_SDK\ld\eagle.rom.addr.v6.ld
Код:
PROVIDE ( ets_install_putc1 = 0x4000242c );
Могу ошибаться, но из этого я делаю вывод, что это некая функция, которая скрывается где-то в закомпиленных уже либах и исходников к ней нет.

Чтож, но вопрос не в этом, вопрос в том: как понять дальше, что эта хреновина делает?

Попытки найти в pdf'ках от Espressif описание этих функций - ничего не дают.
Не, я понимаю, что дальше умные люди вооружаются дизассемблерами, либо еще чем-то и...
Но мой вопрос стоит именно так: простые смертные могут где-то найти информацию, хотя бы общую, что делает и/или как работает та или иная функция, которая не описана в доках от Espressif?
То есть может где-то собран этот кладезь знаний уже? Может я не туда куда-то смотрю?

Пните меня в нужном направлении, и я как ежик, с удовольствием туда полечу! Спасибо! :)

PS: и да, мне не нужно объяснять конкретно эту вот строчку:
os_install_putc1(enabled ? (void *)uart_tx_one_char : NULL);
Я логикой ее понимаю, что-то вроде: прописываем куда-то в системе указатель на колбек-функцию, которую система будет вызывать каждый раз, когда захочет вывести 1 символ дебажной информации, а в этой функции мы уже этот символ выводим туда, куда нам надо, например, в UART0. Либо прописываем NULL, и тогда система не вызывает никокой функции и дебаг не выводится.
Но мне, например, не понятно, почему эта функция называется os_install_putc1/ets_install_putc1, то есть не может ли быть так, что она не только дебажную информацию выводит, но и что-то еще?
Почему не os_install_debug_putc какой-нибудь?// В общем, беда-беда, огорчение :)

Сейчас подумалось еще, что эта функция выставляет коллбек для другой функции, типа ets_putc.
Которая в свою очередь и вызывается для вывода каждого символа. Но как это все именно с дебагом связано, то есть именно с отладочной информацией?
 

pvvx

Активный участник сообщества
Не, я понимаю, что дальше умные люди вооружаются дизассемблерами, либо еще чем-то и...
Но мой вопрос стоит именно так: простые смертные могут где-то найти информацию, хотя бы общую, что делает и/или как работает та или иная функция, которая не описана в доках от Espressif?
Найдете только в своем компе, если сами положили её туда :)
То есть может где-то собран этот кладезь знаний уже? Может я не туда куда-то смотрю?
Частично собран, но находится на тысячах носителей, которые не желают объединяться.

os_install_putc1(enabled ? (void *)uart_tx_one_char : NULL); - это если enabled != 0, то будет включена функция вывода для printf и т.д. uart_tx_one_char(). А если enabled == 0, то вывода у системных функций типа printf не будет. Всё это обращается к кодам в BIOS-ROM и её системе ввода-вывода и т.д.
Код:
ROM:40001CB0 off_40001CB0    .int dword_3FFFDD3C     ; DATA XREF: ROM:eprintf_init_bufr
ROM:40001CB0                                         ; ROM:40001CDFr ...
....
ROM:4000242C ets_install_putc1:                      ; CODE XREF: ROM:40002441j
ROM:4000242C                                         ; DATA XREF: default_exception_handler:a_ets_install_putc1o
ROM:4000242C                 l32r            a3, off_40001CB0
ROM:4000242F                 s32i.n          a2, a3, 0xC
ROM:40002431                 ret.n
ROM:40002431 ; ---------------------------------------------------------------------------
ROM:40002433                 .byte 0
ROM:40002434 a_putc1         .int uart1_write_char   ; DATA XREF: ROM:ets_install_uart_printfr
ROM:40002434                                         ; ROM:40002566r
ROM:40002438 ; ---------------------------------------------------------------------------
ROM:40002438
ROM:40002438 ets_install_uart_printf:                ; CODE XREF: ROM:40000FFEj
ROM:40002438                 l32r            a2, a_putc1
ROM:4000243B                 addi            a1, a1, 0xF0
ROM:4000243E                 s32i            a0, a1, 0
ROM:40002441                 call0           ets_install_putc1
ROM:40002444                 l32i.n          a0, a1, 0
ROM:40002446                 addi            a1, a1, 0x10
ROM:40002449                 ret.n
ROM:40002449 ; ---------------------------------------------------------------------------
 
Последнее редактирование:

JustACat

Moderator
Команда форума
Всё это обращается к кодам в BIOS-ROM и её системе ввода-вывода и т.д.
Вот я и говорю, что по логике-то я это понимаю. Но хотелось бы некое подтверждение иметь.

Мне вот, например, непонятно, почему я вызываю один раз эту штуку - разрешаю этот самый отладочный вывод, и он остается включенным, даже если вызов этой строчки уберу из прошивки.
Опять же по логике получается, что оно где-то в системе прописывается и сохраняется во флеш, так?
Но если это так, то не получится ли так, что, если, допустим, я в своей программе поставлю в начале строчку, отключающую этот самый вывод, то она каждый раз при старте программы будет это куда-то во флеш записывать и протрет там дырку?..
 

JustACat

Moderator
Команда форума
А нет, наврал, не сохраняется... По умолчанию дебаг включен, и если не вызвать Serial.systemDebugOutput(false); (которая в Sming и вызывает дальше отключение), то отладка появляется в терминале...
Значит тогда получается, что я так и не могу толком разобраться со всеми этими Target'ами в этом eclipse... Да еще и в купе с запутанной памятью в ESP.
Чего и как компилить и шить правильно, чтобы программа работала так, как написано?
Конечно можно каждый раз делать clean - all - flash , но это долго, особенно в Sming там билдится куча библиотек каждый раз...
А если только all - flash , не всегда оно корректно и происходит...

pvvx, за дамп из рома спасибо конечно, но, боюсь, вы меня переоцениваете. Нет, я ассемблер знаю немного конечно, но не на столько, чтобы глядя в эту штуку все сразу прояснилось :)
 

d946

New member
Что такое os_install_putc1
типичная реализация связки printf и putchar (в нашем случае os_install_putc1)

Код:
void * func_putchar = NULL;

void os_install_putc1( (void *)putchar_cb){
     func_putchar= putchar_cb;
}

void os_printf(void *str, ...){
  char buf[1024];
  os_sprintf((char *)buf, str, ...);
  if (func_putchar!=NULL){
    while(*buf){
       func_putchar(*buf);
       buf++;
    }
  }
Дополнительная информация http://we.easyelectronics.ru/Soft/formatnyy-vyvod-na-si-dlya-mikrokontrollerov.html
 

JustACat

Moderator
Команда форума
d946, спасибо за инфу, но как я уже и говорил, меня интересует не конкретно данная строчка, а вообще принцип добывания информации по функциям SDK.
То есть, если мне, к примеру, нужно понять, что за функция и как работает на php, я знаю, что надо идти на php.net, там просто ввести эту функцию в строку поиска и получить по ней зачастую исчерпывающие данные... Вот то же самое меня интересует и тут. А os_install_putc1 я привел лишь как частный пример такого поиска...
Но вам в любом случае спасибо!
 

pvvx

Активный участник сообщества
То есть, если мне, к примеру, нужно понять, что за функция и как работает
Этот вопрос может разрешить только Espressif, путем создания полного SDK, а не огрызка.
А пока на их форуме присутствует единственная правильная рекомендация - использовать реверс :), т.е. дизасм.
Часть, того, что я смотрел по своим нуждам и было время и возможность как-то перевести дизасм на язык СИ вложено в исходники к моей веб свалке в папке "Хлам" :) Это всего малая часть кусков из общего бардака по дизасму, которые не совсем страшные ...
 
Последнее редактирование:

Victor

Administrator
Команда форума
единственная правильная рекомендация - использовать реверс
Здравствуйте, pvvx!
Раз уж вы не спите, не подскажете можно ли реверснуть бут и пропатчить NOP там, где вывод мусора в UART0. Или переключить его на UART1, или еще какие варианты есть.
 

pvvx

Активный участник сообщества
Здравствуйте, pvvx!
Раз уж вы не спите, не подскажете можно ли реверснуть бут и пропатчить NOP там, где вывод мусора в UART0. Или переключить его на UART1, или еще какие варианты есть.
Не выйдет - основные сообщения при старте в оба UART дает ROM-BIOS и от этого не избавится. Надо новую ревизию чипа.
Или речь о сообщениях при старте boot_vX.X.bin от Espressif?
 
Последнее редактирование:

pvvx

Активный участник сообщества
Код:
void call_user_start(void)
{
    init_sflash_start();
    ets_run();
}
Так стартует SDK в app_main.c.
А далее в SDK 1.0.0 приписали ненужную и глючную разборку по заголовку в flash и всякие выводы времени компиляции и т.д.
В библиотеке libmain.a они спецом смешали всю ненужную белиберду в один модуль app_main.o, чтобы это простой перепаковкой либы и заменой малого obj было не решить.
 

pvvx

Активный участник сообщества
ну мы ведь и не ждали от них ничего лучшего. а жаль.
Там главное, что при старте у них везде опять стоит:
Код:
    while(READ_PERI_REG(UART_STATUS(0))  & (UART_TXFIFO_CNT<<UART_TXFIFO_CNT_S));
    while(READ_PERI_REG(UART_STATUS(1))  & (UART_TXFIFO_CNT<<UART_TXFIFO_CNT_S));
и тем самым увеличивает время до старта рабочих процедур и не позволяет уменьшить потребление чипа при просыпаниях в deep_sleep c отключенным WiFi для опроса датчиков...
Но их не интересует ничего кроме Iot SDK для работы со своим сайтом. AT прошивка - это второстепенное и случайное образование :)
 

pvvx

Активный участник сообщества
Ещё по поводу старта:
Если при настройке параметров WiFi (конкретнее при сохранении параметров в flash) выключить или пропадет питание модуля, то при следующем старте вполне получите дамп памяти:
Код:
struct ets_FlashHeader { // заголовок flash (использует загрузчик BIOS)
    uint8 id; // = 0xE9
    uint8 number_segs; // Number of segments
    uint8 spi_interface; // SPI Flash Interface (0 = QIO, 1 = QOUT, 2 = DIO, 0x3 = DOUT)
    struct esp_flash_hsz hsz; // options
}  __attribute__((packed));

struct ets_store_wifi_hdr { // 0x4027F000 (пишется в последний сектор)
    uint8 bank;     // +00 = 0, 1 // используется первый или второй сектор настроек WiFi
    uint32 flag;    // +04 = 0x55AA55AA
    uint32 x;         // +08 = 0x00000119
    uint32 xx[2];    // +12 = 28, 28
    uint32 chk[2];    // +20 = 0x91, 0x91
};
void hex_damp_sec_blk_flash(uint32 fsec, uint32 len)
{
    uint8* buf = pvPortMalloc(len+3);
    if(spi_flash_read(fsec << 12, (uint32_t *)buf, len & 0xfffc) == SPI_FLASH_RESULT_OK) {
        uint8* ptr = buf;
        uint32 i = 0;
        while(len--) {
            os_printf_plus("%08x ", *ptr++);
            if((++i & 0x1F) == 0) os_printf_plus("\n");
        }
    }
    os_printf_plus("\n");
    vPortFree(buf);
}
void system_param_error(uint32 fsec)
{
    os_printf_plus("system param error\n");
    hex_damp_sec_blk_flash(fsec + 1, 0x370 ); // первый сектор сохранения параметров WiFi и размер структуры
    hex_damp_sec_blk_flash(fsec + 2, 0x370 ); // второй сектор сохранения параметров WiFi и размер структуры
    hex_damp_sec_blk_flash(fsec + 3, 28 ); // третий сектор заголовка сохранения параметров WiFi и размер это структуры
}

static void init_sflash_start(void)
{
    struct ets_FlashHeader fhead;
    uint8 wifi_cfg[0x370];
    struct ets_store_wifi_hdr buf;
    uint8 macaddr[6];

    read_macaddr_from_otp(&macaddr);

    SET_PERI_REG_MASK(SPI_USER(0), SPI_CS_SETUP); // +1 такт перед CS
    SPIRead(0, (uint32_t *)fhead, sizeof(fhead));

    uint8_t speed = fhead.hsz.spi_freg;
    if (speed >= 3) {
        speed = (speed == 0x15) ? 1 : 2; 
    } else {
        speed += 2;
    }

    uint32 fsize = 0x80000;
    switch(fhead.hsz.flash_size)
    {
        case 1:
            fsize = 0x40000;
            break;
        case 2:
            fsize = 0x100000;
            break;
        case 3:
            fsize = 0x200000;
            break;
        case 4:
            fsize = 0x400000;
            break;
    }
    flashchip->chip_size = fsize;
    sflash_something(speed);

    uint32 fsector = flashchip->chip_size >> 12;
    fsector -= 4;

    SPIRead(flashchip->chip_size - 0x1000,(uint32_t *)buf, sizeof(buf));

    uint32 store_cfg_addr = flashchip->chip_size - 0x3000 + ((buf.bank)? 0x1000 : 0);

    SPIRead(store_cfg_addr, &wifi_cfg, sizeof(wifi_cfg));

    Cache_Read_Enable(0,0,1);
    mem_clr_bss();
    ets_install_putc1(uart1_write_char_ram);
    if(buf.flag != 0x55AA55AA){
        if(buf.flag != 0xFFFFFFFF) {
            system_param_error(fsector);
        }
    }
    if(buf.chk[(buf.bank)? 1 : 0] != system_get_checksum((uint8 *)&wifi_cfg, sizeof(wifi_cfg)){
        system_param_error(fsector);
    }
....
}
Аналогично и при нестандартных размерах flash :) Но об этом уже писал и давал что выводится в UART этот дамп с "system param error\n"...
 
Сверху Снизу