• Система автоматизации с открытым исходным кодом на базе 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 загрузка работала.
 
Сверху Снизу