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

RTL8710AF - загрузчик в ROM-BIOS

pvvx

Активный участник сообщества
Загрузчик в ROM-BIOS:
Анализ показывает, что чип стартует с процедуры HalResetVsr() (в ROM0x3c4).
1) очищает rom_bss
2) исполняет HalRomInfo(); и включает блок отладчика (v400001F8 = v400001F8 & 0xFFFFFF00 | 2; )
3) устанавливает регистры тактирования блока Jtag:
*((volatile u32 *)(40000230)) |= 0x40;
*((volatile u32 *)(40000230)) |= 0x80;
4) разрешает JTAG: HalPinCtrlRtl8195A(JTAG, 0, 1);
5) устанавливает GPIO_GPE0_PULL_CTRL v40000338 = v40000338 & 0xFFFFFFFC | 2;
6) в зависимости от значений в регистре по адресу 0x40000210 (используется в режиме Debug RAM*) вызывает процедуры Debug_addr1 или Debug_addr2 или Debug_addr3 или Standart_addr_run. Debug_addr4 вызывается после инициализации console - см п.п.18. Таблица, кусок с адреса 0x20, должна быть размещена в памяти по адресу 0x10000bc8. В таблице описаны условия вызова.
7) устанавливает частоту 41666666 Hz: CPU HalCpuClkConfig(2);
8) устанавливает переменную ConfigDebugErr = -1;
9) инициализирует VectorTableInitRtl8195A(0x1FFFFFFC);
10) включает ноги LOG_UART: HalPinCtrlRtl8195A(LOG_UART, 0, 1);
11) назначает:
UartAdapter.BaudRate = UART_BAUD_RATE_38400;
UartAdapter.DataLength = UART_DATA_LEN_8BIT;
UartAdapter.FIFOControl = 0xC1;
UartAdapter.IntEnReg = 0x00;
UartAdapter.Parity = UART_PARITY_DISABLE;
UartAdapter.Stop = UART_STOP_1BIT;
и инициализирует: HalLogUartInit(UartAdapter);
12) инициализирует VectorIrqRegisterRtl8195A(UartLogIrqHandle);
13) назначает: UartAdapter.IntEnReg = 0x5;
и инициализирует: HalLogUartInit(UartAdapter);
14) инициализирует console: RtlConsolInit(0, 6, UartLogRomCmdTable);
15) инициализирует регистры :
*((volatile u32 *)(0x40000270)) |= 1u; // OSC32K_CTRL
*((volatile u32 *)(0x40000210)) |= 0x10000u; // SOC_GTIMER_EN
*((volatile u32 *)(0x40000230)) |= 0x4000u; // SOC_ACTCK_TIMER_EN
*((volatile u32 *)(0x40000230)) |= 0x8000u; // SOC_SLPCK_TIMER_EN
*((volatile u32 *)(0x40000204)) &= 0xFFFFFFEF; // ISO_OSC32K_EN
16) инициализирует таймер: HalTimerOpInit(HalTimerOp); HalTimerOp->HalTimerEn(0);
17) Через DiagPrintf() выводит надпись ROM Version: ....
18) в зависимости от значений в регистре по адресу 0x40000210 (используется в режиме Debug RAM) вызывает процедуры Debug_addr4. Таблица, кусок с адреса 0x20, должна быть размещена в памяти по адресу 0x10000bc8.
19) инициализирует spic (HalPinCtrlRtl8195A(), SpicInitRtl8195A())
20) считывает из Flash size [0x9800 0010] и addr [0x9800 0014], сравнивает “подпись” (dw [0x9800 0034], [0x9800 0038]) c ROM_IMG1_VALID_PATTEN (ROM: 0x00030c80: 23 79 16 88 FF 00 00 00), загружает из Flash код в RAM, отключает JTAG(!) ( HalPinCtrlRtl8195A(JTAG, 0, 0)) и запускает: Standart_addr_run().

RTL8710AF_Flash_record:
Flash_header.gif

*Запуск процедур по флагам в регистре с адресом 0x40000210 требуется для обхода отладчиком загрузки с flash. Отладчик инициализирует CPU через JTAG и прописывает флаги в регистр с адресом 0x40000210 и загружает коды в RAM. После старта, если установлены флаги, CPU переходит в процедуры Debug_addr1, или Debug_addr2, или Debug_addr3, или Debug_addr4 до загрузки RAM из Flash. Этим и осуществляется отладка кода, заранее загруженного отладчиком в RAM.
Для отладки с GDB в Eclipse надо добавить команду:
GDB_J-link.gif
Или вписать в скрипт:
Код:
#############
# Boot_Flash
define SetBootFlash
printf "SetBoot = Flash:\n"
monitor long 0x40000210 = 0x211157
end
# Boot RAM start_addr0() Run if ( v400001F4 & 0x8000000 ) && ( v40000210 & 0x80000000 )
define SetBootCall0
printf "SetBoot = Call0:\n"
monitor long 0x40000210 = 0x80011117
end
# Boot RAM start_addr1() Run if ( v40000210 & 0x20000000 )
define SetBootCall1
printf "SetBoot = Call1:\n"
monitor long 0x40000210 = 0x20011117
end
# Boot RAM start_addr2() Run if ( v40000210 & 0x10000000 )
define SetBootCall2
printf "SetBoot = Call2:\n"
monitor long 0x40000210 = 0x10011117
end
# Boot RAM start_addr3() Run if ( v400001F4 & 0x8000000 ) && ( v40000210 & 0x8000000 )
define SetBootCall3
printf "SetBoot = Call3:\n"
monitor long 0x40000210 = 0x8011117
end
# Boot RAM start_addr4() Init console, Run if ( v40000210 & 0x4000000 )
define SetBootCall4
printf "SetBoot = Call4:\n"
monitor long 0x40000210 = 0x4011117
end
 
Последнее редактирование:

pvvx

Активный участник сообщества
Тест скорости чтения Flash:
Код:
=========================================================

ROM Version: 0.3

Build ToolChain Version: gcc version 4.8.3 (Realtek ASDK-4.8.3p1 Build 2003)

=========================================================
Flash[0]: 0x96969999
CPU CLK : 166 666 666 Hz
t0 = 1
read(): tFlash = 4718597, clk/byte = 72
memcpy(): tFlash = 9396289, clk/byte = 143
read(): tRAM = 147459, clk/byte = 2
read(): tTCM = 136536, clk/byte = 2
read(): tFlash/tTCM = 34, tFlash/tRAM = 31
memcpy(): tFlash/tTCM = 68, tFlash/tRAM = 63
Flash[0]: 0x96969999
End
memcpy() из Flash в RAM выходит 143 такта на байт.
Простое чтение Flash в 31 раз медленнее TCM памяти...
Код теста RTL00_HelloWorld/main_frd.c at master · pvvx/RTL00_HelloWorld · GitHub
 

pvvx

Активный участник сообщества
Частота контроллера 8710 таки 166 МГц? Вроде же где-то писали что 83, а 166 это начиная с 8711... Или я невнимательно читал?
ROM-BIOS cтартует на 83. Это прописано в REG_SYS_EFUSE_SYSCFG6 -> BIT_SHIFT_SYS_CPU_CLK_SEL ...
А "Вроде же где-то писали что 83" - это тут http://files.pine64.org/doc/PADI/documentation/padi-iot-stamp-datasheet.pdf
83 - чтобы кушал меньше, чем конкурент в виде ESP8266...

Есть переключение HalCpuClkConfig(0); // 0 - 166666666 Hz, 1 - 83333333 Hz, 2 - 41666666 Hz, 3 - 20833333 Hz, 4 - 10416666 Hz, 5 - 4000000 Hz

Не понятно, почему SpicInitRtl8195AV02(2, SpicQuadBitMode);// SpicDualBitMode); При InitBaudRate = 1 [void SpicInitRtl8195AV02(u8 InitBaudRate, u8 SpicBitMode)] - Flash почему-то читается с ошибками, даже при 4 MHz CLK CPU.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Всё - описание загрузка в ROM-BIOS закончено. Описал до каждого битика :) Вопросы есть?
 

pvvx

Активный участник сообщества
Типа демо проект, для начала создания своего загрузчика.
GitHub - pvvx/RTL00ConsoleROM: Test RTL Console ROM
Запускает RTL Console встроенную в ROM.
Код:
Start Init code: 4
EFUSE  0..3: 0x16c28195 0x004959d5 0x4a814000 0x0000e404
EFUSE  4..7: 0x00000001 0x00000000 0x02000000 0x00000000
SYSCFG 0..2: 0x41000220 0x00010301 0x00000003
SOC_FUNC_EN: 0x04011117

RTL Console ROM: Start - press key 'Up', Help '?'
<RTL[871AF>
<RTL8710AF>?
----------------- COMMAND MODE HELP ------------------
        HELP (?)   : Print this help messag

        DB <Address, Hex> <Len, Dec>:
                                 Dump memory byte or Read Hw byte register
        DHW <Address, Hex> <Len, Dec>:
                                 Dump memory helf-word or Read Hw helf-word register
        DW <Address, Hex> <Len, Dec>:
                                 Dump memory word or Read Hw word register
        EW <Address, Hex> <Value, Hex>:
                                 Write memory word or Write Hw word register
                                 Can write more word at the same time
                                 Ex: EW Address Value0 Value1
        SPICTOOL <Mode, Dec> <BitMode, Dec>:
                                 Mode = 1: Init SPIC;  BitMode: 0(One)/1(Dual)/2(Quad)
                                 Mode = 2: Erase Chip

----------------- COMMAND MODE END  ------------------
<RTL8710AF>
Код загружается с помощью JLink.exe -> JLink-RTL00ConsoleROM.bat
В main.c указанна минимальная инициализация в зависимости от веток загрузки...
 
Последнее редактирование:

pvvx

Активный участник сообщества
Частота контроллера 8710 таки 166 МГц? Вроде же где-то писали что 83, а 166 это начиная с 8711... Или я невнимательно читал?
Уточнение в связи с учетом ROM V01
ROM-BIOS запускает RTL8710AF на 41.7 MHz.
Другие на 83.3 MHz. Это завязано со SPIC (контроллер Flash) и ROM не имеет правильной инициализации SPIC на других вариантах SLK CPU.
Понижение наверно сделано для надежности старта (вдруг питание мало), а для RTL8710AF - чисто в коммерческих целях, т.к. данный чип позиционируется для устройств с совсем пониженным потреблением и ему не следует превышать потребление выше некоторых норм при старте, а далее пользователь решает сам на сколько он может увеличить потребление в своем исполнении, поставив требуемые частоты работы CPU.
Иначе возникает ужас, как в ESP-32S - при старте требуется питание более полу-Ампера! :eek: И исправить это вы уже не можете (т.е. чип ESP-32S не вписывается в спецификацию BLE!).
Для данного SoC процедуры ROM-BIOS поддерживают работу на базовых CLK PLL в 200 MHz (они всегда такие), без исключения RTL8710AF.
Все внутренности RTL8710AF работают и на 200 MHz, при этом за рамки норм ничего не выходит. 200 MHz могут быть критичны только в случае RTL8195A - там значительно больше периферии (+USB и SDRAM) и общее потребление и тепловое рассеивание кристалла может выйти за рамки норм в верхнем диапазоне гарантированных производителем рабочих температур чипа.
Тактирование периферии CPU при переключении делителя c 1:5/6 (166 MHz) на 1:1 (200 MHz) повышается в 1.2 раза.
Т.е. выходит возможность более точного подбора частных делителей для необходимого ряда, к примеру для UART и других встроенных контроллеров.

Поддерживаемые CLK CPU в ROM-BIOS для данного SoC:
  • 200, 000 000 МГц
  • 166, 666 666 666 667 МГц
  • 100, 000 000 МГц
  • 83, 333 333 333 333 МГц
  • 50, 000 000 МГц
  • 41, 666 666 666 667 МГц
  • 25, 000 000 МГц
  • 20, 833 333 333 333 МГц
  • 12, 500 000 МГц
  • 10, 416 666 666 667 МГц
  • 4, 000 000 МГц
 
Последнее редактирование:

Creep

Member
перечитывал старое и возник вопрос:
  • read(): tFlash = 4718597, clk/byte = 72
  • memcpy(): tFlash = 9396289, clk/byte = 143
чтение из флеш выглядит так:
Код:
    volatile u32 * ptr = (volatile u32 *)SPI_FLASH_BASE+0x4000;
    for(i=0; i < 16384; i++) *ptr++;
а memcpy() выглядит так:
Код:
    memcpy((u8 *)0x10010000,(u8 *) SPI_FLASH_BASE+0x10000, 65536);
    for(i=0; i < 16384; i++) *ptr++;
собственно, вопрос: зачем после копирования куска памяти выполнять дополнительное чтение?
ну и получается неудивительный результат:
memcpy() из Flash в RAM выходит 143 такта на байт.
 

pvvx

Активный участник сообщества
перечитывал старое и возник вопрос
Ну наверно опечатка, т.к. проверка делалась кое-как и искал разные варианты - исполнение кода из ROM идет без задержек, а из SRAM - с задержками, из TCM - без, из SDRAM с большими задержками. Тем более смутил код от Ameba, где старательно вписано выравнивание на dword (align(4) + uint32).
Но самое интересное - это то, что всего спустя почти год кто-то заметил и начал обсуждать данную тему, а уже были созданы другие темы и где всё уточнено, что чтение байтами или dword дают идентичные временные характеристики и с моим новым boot у SPIC вообще другие скорости:
https://esp8266.ru/forum/threads/rtl871x-flash-memory-map.2117/#post-32878
 

Creep

Member
Но самое интересное - это то, что всего спустя почти год
представляете, каждый год появляются те, кто не читал Пушкина! А этот "кладезь" (форум) читать не в пример труднее, не говоря, что сразу весь объем осилить просто невозможно.
Так что простите за некропостинг и незнание содержания всех остальных топиков.

добавлено: почитал про калибровку SPIC - пока не все понял => надо почитать про сам контроллер.
за наводку спасибо.
 
Последнее редактирование:

pvvx

Активный участник сообщества
представляете, каждый год появляются те, кто не читал Пушкина! А этот "кладезь" (форум) читать не в пример труднее, не говоря, что сразу весь объем осилить просто невозможно.
Так что простите за некропостинг и незнание содержания всех остальных топиков.
А я не придираюсь - предложение в ответе имеет минимум два разно-весовых смысла (так и задумано, чтобы вы выбрали предпочитаемый вами), а там был комплимент, несущий смысл: "Почти целый год никто, кроме вас не заметил" :)
добавлено: почитал про калибровку SPIC - пока не все понял => надо почитать про сам контроллер.
за наводку спасибо.
Краткий смысл - не все параметры задержек работают. Существуют кратности. RTL8710AF стартуете на 41 MHz в ROM, а Ameba писала на RT8195Ax, стартующий на 83МГц. В инициализации SDK используются процедуры обращения к Flash через SPIC, но инициализации нет, а переключение CLK CPU стоит. 8710 при этом переключают на 83МГц, а 8195 на 166. Возникает путаница и зависон при обращении к SPIC... Это один и самый частый вариант. Второй связан с уже прописанными установками в flash от старта на модуле boot от SDK 3.4 из 2015 года. Там выходят другие константы, т.к. частоты ставятся другие и с такими установками код от Ameba Arduino виснет там-же - на обращении к области отображения Flash, т.к. не пересчитывает, а считает что записанные константы в Flash верны... Т.е. после OTA модуль благополучно накрывается и лечиться только переписыванием boot через Jtag.
"надо почитать про сам контроллер" - его описания не найдено - подписывайте NDA и тогда мы вас теряем :) Есть только путь изучения дизасмом исходников и метод "тыка". Итого приведено в boot -> RTL00MP3/rtl_boot.c at master · pvvx/RTL00MP3 · GitHub
 
Последнее редактирование:

Creep

Member
я правильно понимаю, что к внутренней флеш ядро ходит через тот же SPIC (или такой же) что и "на улицу"?
косяк c константами понятен: "не царское это дело" перенастраивать оборудование когда переключаешь "передачи" :)
я пока не понял смысл калибровочных констант - надо почитать про сам "автомат" SPIС
только закончил читать про I2C-контроллер.
 

Creep

Member
его описания не найдено - подписывайте NDA и тогда мы вас теряем :) Есть только путь изучения дизасмом исходников и метод "тыка".
не думаю что спик от реалтека принципиально отличается от какого-то другого спика например стма, то бишь сначала бы разобраться в его функционировании, ну а потом буде такая нужда реверсить нюансы конкретной реализации.

с уже прописанными установками в flash от старта на модуле boot от SDK 3.4 из 2015 года. Там выходят другие константы,
а это вообще красота :)
 

pvvx

Активный участник сообщества
не думаю что спик от реалтека принципиально отличается от какого-то другого спика например стма, то бишь сначала бы разобраться в его функционировании, ну а потом буде такая нужда реверсить нюансы конкретной реализации.
На RTL стоят полные и самодостаточные контроллеры, а на STM - обрезки, требующие обращение к регистрам во время работы. На полных контроллерах сложная инициализация (на много букав) , а дальнейший полет - прост и контроллер его обслуживает сам. STM = гонка за дешевизной и простой... В итоге совпадение по периферии с STM не более 10%.
 

Creep

Member
Вас не затруднит подсказать источник по спику для чайника - алгоритм работы, управляющие регистры и тому подобное, если это окажется на понятном русском вообще великолепно. Просто нужен "вход в тему". Каюсь, сам пока источник не искал.
 

Neov

Member
Кстати, насчет кода бутлодера.
В функции [inline]IsForceLoadDefaultImg2[/inline] в строке [inline]for (int i = 1; i; i--) {[/inline] нужно наверное указать i=2 ?
Далее, бутлодер в нормальном режиме должен загружать дефолтовую OTA, а у вас грузит 1 или 2 (в зависимости от значения пина) начиная с 0xB000. Дефолтовая загрузится, если мы запросим некорректную прошивку через пины
 

pvvx

Активный участник сообщества
Кстати, насчет кода бутлодера.
В функции [inline]IsForceLoadDefaultImg2[/inline] в строке [inline]for (int i = 1; i; i--) {[/inline] нужно наверное указать i=2 ?
Далее, бутлодер в нормальном режиме должен загружать дефолтовую OTA, а у вас грузит 1 или 2 (в зависимости от значения пина) начиная с 0xB000. Дефолтовая загрузится, если мы запросим некорректную прошивку через пины
Это оставлено на усмотрение пользователя. Пример: в проекте RTLHTTPD, sharikov сделал другой вариант. Он вложен в дубль RTLHTTPD/rtl_boot_s.c at master · pvvx/RTLHTTPD · GitHub
Я пока не выбрал никакого варианта, а по умолчанию с стоит тот, что образовался при написании кода. Т.е. стихийно и без анализа алгоритма. Об этом уж было написано не раз.
Исходник предоставляет полный выбор алго, который зависит от итогового проекта и компоновки images пользователем. Возникает множество вариантов. Текущий - стихийный, он как-то работает и c Arduino Ameba и cо сборкой SDK, если указан пин переключения основная или OTA прошивка...
У меня, например, boot не должен грузить OTA, т.к. он не знает - последний ли это OTA или есть уже другой. Аналогично и при специальной "дефолтной" прошивке - когда она вызывается не определено. Т.е. в алго не учитывается и не дописан в boot вариант назначения загружаемой images по умолчанию с установкой по WiFi (удаленно), т.к. тут всё зависит от самого проекта, целей устройства и компоновке images при удаленной прошивке (как и куда пишутся). Единого решения при таком выборе нет.

Если вы пропишите оф. версию boot и прошивку AT от Ameba, то пару "AT" команд приводят к полному краху - ничего не будет грузиться или выберется битая прошивка... Аналогично с прошивкой boot в модулях от PINE, приводящий к краху с патовой ситуацией описан у них на сайте форума. Тоже-самое и с Arduino Ameba... А с текущим boot, при указанном пине переключения этого не возникает. Но не распределен вариант "дефолтной" прошивки, загружаемый по указателю, а не по разметке записанных images...

В итого, в совокупность алго boot повязаны: стиль укладки images в flash, описанные пины переключения и указатель на "дефолтную" прошивку. Т.е. алго больше зависит от внешних факторов и предпочтений проектировщика системы и должен правиться им.
 
Последнее редактирование:

Neov

Member
У меня, например, boot не должен грузить OTA, т.к. он не знает - последний ли это OTA или есть уже другой.
Как по мне, так дефолтовой прошивкой должна быть та, которую проще всего обновить - OTA. Как говорится загрузи и посмотри какая версия, если что обнови.
Множество основных прошивок - баловство. Достаточно иметь одну и стабильную, лишь бы OTA загрузка работала.
 
Сверху Снизу