Как сделать свой bootloader. Изучаем работу SPIFI

cryptozoy

Member
C:
//врубаем QPI-режим
HAL_SPIFI_SendCommand(&spifi, &spifi_enable_qpi, 0, 0, 0, 0, HAL_SPIFI_TIMEOUT);

Вы изменили функцию HAL_SPIFI_SendCommand? Откуда у неё появилось ещё два параметра? Она же в оригинале такая:

C:
HAL_SPIFI_SendCommand(&spifi, &spifi_enable_qpi, 0, 0, 0);

void HAL_SPIFI_SendCommand(
    SPIFI_HandleTypeDef *spifi,
    SPIFI_CommandTypeDef *cmd,
    uint32_t address,
    uint16_t dataLength,
    uint8_t *dataBytes)
{
 

ejsanyo

Active member
Вы изменили функцию HAL_SPIFI_SendCommand? Откуда у неё появилось ещё два параметра? Она же в оригинале такая:
Это я слил более свежий (наверно) HAL отсюда. Вроде каких-то фундаментальных отличий в нём не появилось: ну разделили буферы, да ввели таймаут...или всё же не всё так просто?
PS Попробовал откатиться на "старый" HAL. К сожалению ничего не изменилось.
 
Последнее редактирование:

mscs

Member
Может, при подаче питания он вначале сидит во втором режиме, а чтобы его перевести в командный, нужно что-то специфическое станцевать ещё?
У меня в загрузчике контроллер SPIFI перед началом выдачи команд чтения из SPI Flash сбрасывается (SPIFI_STA = 0x30) и настраивается (SPIFI_CTRL = 0xD081FFFF).
 

ejsanyo

Active member
У меня в загрузчике контроллер SPIFI перед началом выдачи команд чтения из SPI Flash сбрасывается (SPIFI_STA = 0x30) и настраивается (SPIFI_CTRL = 0xD081FFFF).
Ну вот SPIFI_STA = 0x30 это по сути эквивалентно SPIFI_CONFIG->STAT |= SPIFI_CONFIG_STAT_INTRQ_M | SPIFI_CONFIG_STAT_RESET_M; А вот значения SPIFI_CTRL у вас явно настроены под DMA-обмен, и, конечно, просто так оно не работает...

...а проблема была на самом деле в другом! 😁 Держите код:
C:
#include "mik32_hal.h"
#include "mik32_hal_spifi.h"

void SPIFI_Config();

void main()
{
    // Конфигурация кэш памяти
    // SPIFI переключаем в полный QPI режим
    SPIFI_Config();

    /* Загрузка из внешней flash по SPIFI */
    asm volatile( "la ra, 0x80000000\n\t"
                    "jalr ra"
                );

    while (1)
    {
    }
}

void SPIFI_Config()
{
    uint8_t tmp;

    SPIFI_HandleTypeDef spifi;
    SPIFI_CommandTypeDef spifi_enable_qpi;
    SPIFI_MemoryCommandTypeDef spifi_qpi_memory_read;
    SPIFI_MemoryModeConfig_HandleTypeDef spifi_mem_config;

    spifi.Instance = SPIFI_CONFIG;
    HAL_SPIFI_MspInit(&spifi); //делает ноги флешечным интерфейсом!

    //сброс контроллера и его прерываний
    SPIFI_CONFIG->STAT |= SPIFI_CONFIG_STAT_INTRQ_M | SPIFI_CONFIG_STAT_RESET_M;

    //сбрасывает регистры на дефолтное значение
    SPIFI_CONFIG->ADDR = 0x00;
    SPIFI_CONFIG->IDATA = 0x00;
    SPIFI_CONFIG->CLIMIT = 0x00000000;

    spifi_enable_qpi.Direction = SPIFI_DIRECTION_INPUT;
    spifi_enable_qpi.InterimLength = 0;
    spifi_enable_qpi.FieldForm = SPIFI_FIELDFORM_ALL_SERIAL;
    spifi_enable_qpi.FrameForm = SPIFI_FRAMEFORM_OPCODE;
    spifi_enable_qpi.InterimData = 0;
    spifi_enable_qpi.OpCode = 0x38; //команда "Enable QPI"

    //врубаем QPI-режим
    HAL_SPIFI_SendCommand(&spifi, &spifi_enable_qpi, 0, 0, &tmp);

    //заполняем шаблон команды
    spifi_qpi_memory_read.InterimLength = 3;
    spifi_qpi_memory_read.FieldForm = SPIFI_FIELDFORM_ALL_PARALLEL;
    spifi_qpi_memory_read.FrameForm = SPIFI_FRAMEFORM_OPCODE_3ADDR;
    spifi_qpi_memory_read.InterimData = 0;
    spifi_qpi_memory_read.OpCode = 0xEB; //команда "Quad I/O Fast Read" Полноценный QPI режим

    spifi_mem_config.CacheEnable = SPIFI_CACHE_ENABLE;
    spifi_mem_config.CacheLimit = 0x90000000; //не кэшировать всё, чей адрес выше 2,5 гигов?
    spifi_mem_config.Instance = SPIFI_CONFIG;
    spifi_mem_config.Command = spifi_qpi_memory_read;
    HAL_SPIFI_MemoryMode_Init(&spifi_mem_config); //забиваем настройки кэша и команду, которая будет делать чтение из флэхи
}
И сразу обращаем внимание на HAL_SPIFI_MspInit(&spifi); В котором, как несложно заметить, заложено переназначение ног.
Так что получается, что при подаче питания...просто не все флешечные ноги сразу переключались под SPIFI, а часть оставалось банальными GPIO!
 
Последнее редактирование:

mscs

Member
При запуске МК из SPI Flash выводы P2.0...5 автоматически переводятся в режим 1 (PAD2_CFG имеет начальное значение 0x555). При запуске из EEPROM или из ОЗУ режим указанных выводов по умолчанию 0 (GPIO), требуется перенастройка.
 

ejsanyo

Active member
При запуске МК из SPI Flash выводы P2.0...5 автоматически переводятся в режим 1 (PAD2_CFG имеет начальное значение 0x555). При запуске из EEPROM или из ОЗУ режим указанных выводов по умолчанию 0 (GPIO), требуется перенастройка.
И, кстати, особо жёсткий прикол в том, что когда мы, несмотря ни на что, переходим в режим работы эмулятором памяти, контроллер похоже сам собой переназначает нужные ему ноги.
 

mscs

Member
Переназначает при каждом аппаратном сбросе. Если отладочная приставка использует сигнал nRESET для сброса МК, например.
 

cryptozoy

Member
И сразу обращаем внимание на HAL_SPIFI_MspInit(&spifi); В котором, как несложно заметить, заложено переназначение ног.
Так что получается, что при подаче питания...просто не все флешечные ноги сразу переключались под SPIFI, а часть оставалось банальными GPIO!
Пардон, это я невнимательно ваш код смотрел. Ну значит теперь режим QPI работает без проблем?
 

ejsanyo

Active member
Пардон, это я невнимательно ваш код смотрел. Ну значит теперь режим QPI работает без проблем?
Да, наконец-то заработало. Но важнее даже то, что сама отправка команд заработала! Ведь, понятное дело, пишущий во флешку бутлодырь без этого был бы нереализуем.
 

cryptozoy

Member
И да, не забудьте обновить «mik32-uploader», который сбрасывает режим QPI последовательностью из команд «0x66» и «0x99» для возможности дальнейшей прошивки флешки в стандартном режиме SPI. Иначе перед прошивкой придётся не давать вашему загрузчику запускаться. Об этом я уже писал ранее.
 
Последнее редактирование:

cryptozoy

Member
Я уже пробовал прошивать внешнюю флеш-память в режиме QSPI. Никакого выигрыша в скорости не получил. А всё потому, что отладочный интерфейс MIK32 ограничен частотой 4 МГц и последовательным режимом работы. SPIFI также работает в последовательном режиме, но частота 16 МГц. Ясное дело, что ускорять её переключением в четырёхбитный режим смысла не имеет, потому что она и так 3/4 времени простаивает без дела, а в QSPI режиме будет простаивать ещё в 4 раза больше. При загрузке прошивки через UART скорость будет ещё ниже, ибо его максимальный битрейт 2 Мбит/сек.
 
Последнее редактирование:

cryptozoy

Member
Uploader написан на Python и он точно так же управляет интерфейсом SPIFI, только через отладочный интерфейс посредством утилиты OpenOCD. Там всё просто и понятно. Разберётся практически любой, кто плотно занимается программированием МК.
 

mscs

Member
отладочный интерфейс MIK32 ограничен частотой 4 МГц
Ограничен частотой fCPU / 12, т.е. 2,7 МГц максимум при тактировании МК от встроенного генератора с частотой 32,5 МГц (максимальное значение согласно ТУ) - ограничение ядра Syntacore SCR1.
 

cryptozoy

Member
Ограничен частотой fCPU / 12, т.е. 2,7 МГц максимум при тактировании МК от встроенного генератора с частотой 32,5 МГц (максимальное значение согласно ТУ) - ограничение ядра Syntacore SCR1

Цитаты из «SCR1 External Architecture Specification, Version 1.2.9 - 20220113»:

На странице 44
8.2. TAP Controller
8.2.1. JTAG frequency requirement
IMPORTANT
The following ratio between System Clock (clk) and JTAG Clock (tck)
frequencies must be met: ClkFreq / TckFreq >= 12.
На странице 105
The TAP Controller works on tck, but the Debug Module, which is integrated into the core, and
which interfaces with the TAP Controller, is timed by the core clock. The signals between the TAP
Controller and the Debug Module are going through the synchronization logic. For its proper
functioning JTAG clock frequency has to fulfill the following relation: ClkFreq/TckFreq >= 12.

То есть должен быть ниже рабочей частоты ядра процессора в 12 или более раз. Как же он тогда без ошибок работает на 4 МГц? Должно, но не обязано? :)
 
Последнее редактирование:

mscs

Member
С отладочной приставкой J-Link V11 на частоте 4 МГц не работает. Максимум - 2 МГц.
В одной из плат к МК подключен кварцевый резонатор 8 МГц, с этой платой - максимум 600 кГц.
 
Последнее редактирование:

ejsanyo

Active member
И да, не забудьте обновить «mik32-uploader», который сбрасывает режим QPI командой «0xFF» для дальнейшей прошивки флешки в стандартном режиме SPI. Иначе перед прошивкой придётся не давать вашему загрузчику запускаться. Об этом я уже писал ранее.
и...эта версия мне пишет в консоль, мол "Error loading Python DLL 'R:\Temp\_MEI34162\python312.dll'." R: это кстати мой RAM-диск...на компе с Windows 7. Да, я знаю, что разрабы Петюни вроде как забили на поддержку семёрки, но есть неофициальные сборки. Я конечно поставил последнюю, 3.12.4, и вроде бы со всем прочим софтом она работает нормально. Пробовал я кстати и сделать папку, про которую оно пишет, и скинуть туда dll, но при этом ничего не меняется. Наверно под десяткой таких проблем нет?
 

cryptozoy

Member
...эта версия мне пишет в консоль, мол "Error loading Python DLL 'R:\Temp\_MEI34162\python312.dll'." Наверно под десяткой таких проблем нет?
Соберите исполняемый EXE-файл из программ на Python у себя. Для этого после установки Python установите библиотеку PyInstaller командой «pip install pyinstaller». Для удобства пересборки я создал пакетный файл «mik32_upload_build.bat» с командой «pyinstaller mik32_upload.spec». Среда разработки VSCode с расширением PlatformIO запускает Python-скрипты напрямую. Исполняемый файл требуется для Mikron IDE на базе Eclipse.
 
Последнее редактирование:

ejsanyo

Active member
Соберите исполняемый EXE-файл из программ на Python у себя. Для этого после установки Python установите библиотеку PyInstaller. Пакетный файл «mik32_upload_build.bat» с командой «pyinstaller mik32_upload.spec» я сделал себе для удобства. Среда разработки VSCode с расширением PlatformIO запускает Python-скрипты напрямую. Исполняемый файл требуется для Mikron IDE на базе Eclipse.
Действительно, станцевал всё это - появился новый exe-шник. И вот он работает нормально, в т.ч. когда залит загрузчик с QPI-режимом! Попутно заметил, что на время его работы в моём Temp-е появляется та самая папка _MEI40762, потом самоудаляется. :unsure:
 

ejsanyo

Active member
Кстати, стащил полученный EXE-шник на другой пека, но тоже под Win7. И там он заработал нормально.
Вывод могу сделать такой: при компиляции в недра EXE-файла вшиваются библиотеки из того питуна, который установлен в данный момент в системе. А потом если полученный EXE-шник запускать - они из него распаковываются во временную папку и каким-то образом используются. В моём случае это были библиотеки, совместимые с семёркой, вот в всё и заработало, а в вашем - библиотеки из десятки (?), вот они на семёрке и не пошли.o_O
 
Сверху