ejsanyo
Active member
По случаю, попробовал прикрутить флеху MX25L3233F от Macronix ёмкостью аж в 4 мегабайта! Зачем? Ну, в целом просто для разнообразия (чтоб не Winbond-ом единым
). И это оказалась одна из тех флэх, у которых с завода всякие "четверные" режимы доступа отключены, и чтобы они всё же заработали, придётся кое-что станцевать дополнительно. Что-ж, немного модифицируем бутлодырь из шапки темы чтобы заставить её работать по максимуму:
Как видно, мы проверяем и, если надо, выставляем бит QE в "регистре статуса" флеш-чипа. Поскольку команда записи, согласно даташиту, записывает два регистра сразу, приходится в довесок вычитывать ещё один лишний.
C:
/*
* Простой bootloader, изначально под флэху MX25L3233F
* E.J.SanYo 2024
*
*/
#include "mik32_hal.h"
#include "mik32_hal_spifi.h"
void SPIFI_Config();
void main()
{
// Конфигурация кэш памяти
// SPIFI переключаем в 4 битный режим
SPIFI_Config();
/* Загрузка из внешней flash по SPIFI */
asm volatile( "la ra, 0x80000000\n\t"
"jalr ra"
);
while (1)
{
}
}
void SPIFI_Config()
{
SPIFI_HandleTypeDef spifi;
SPIFI_CommandTypeDef spifi_rdsr, spifi_rdcr, spifi_write_enable, spifi_wrsr;
SPIFI_MemoryCommandTypeDef spifi_quad_addr_memory_read;
SPIFI_MemoryModeConfig_HandleTypeDef spifi_mem_config;
uint8_t Sregs[2]; //хранить результат чтения регистров
spifi.Instance = SPIFI_CONFIG;
HAL_SPIFI_MspInit(); //делает ноги флешечным интерфейсом
//сброс контроллера и его прерываний
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_rdsr.Direction = SPIFI_DIRECTION_INPUT;
spifi_rdsr.InterimLength = 0;
spifi_rdsr.FieldForm = SPIFI_FIELDFORM_ALL_SERIAL;
spifi_rdsr.FrameForm = SPIFI_FRAMEFORM_OPCODE;
spifi_rdsr.InterimData = 0;
spifi_rdsr.OpCode = 0x05; //команда "Read Status Register"
spifi_rdcr.Direction = SPIFI_DIRECTION_INPUT;
spifi_rdcr.InterimLength = 0;
spifi_rdcr.FieldForm = SPIFI_FIELDFORM_ALL_SERIAL;
spifi_rdcr.FrameForm = SPIFI_FRAMEFORM_OPCODE;
spifi_rdcr.InterimData = 0;
spifi_rdcr.OpCode = 0x15; //команда "Read Configuration Register"
spifi_write_enable.Direction = SPIFI_DIRECTION_INPUT;
spifi_write_enable.InterimLength = 0;
spifi_write_enable.FieldForm = SPIFI_FIELDFORM_ALL_SERIAL;
spifi_write_enable.FrameForm = SPIFI_FRAMEFORM_OPCODE;
spifi_write_enable.OpCode = 0x06; //команда "Write Enable"
spifi_wrsr.Direction = SPIFI_DIRECTION_OUTPUT;
spifi_wrsr.InterimLength = 0;
spifi_wrsr.FieldForm = SPIFI_FIELDFORM_ALL_SERIAL;
spifi_wrsr.FrameForm = SPIFI_FRAMEFORM_OPCODE;
spifi_wrsr.InterimData = 0;
spifi_wrsr.OpCode = 0x01; //команда "Write Status Register"
spifi_quad_addr_memory_read.InterimLength = 3;
spifi_quad_addr_memory_read.FieldForm = SPIFI_FIELDFORM_OPCODE_SERIAL;
spifi_quad_addr_memory_read.FrameForm = SPIFI_FRAMEFORM_OPCODE_3ADDR;
spifi_quad_addr_memory_read.InterimData = 0;
spifi_quad_addr_memory_read.OpCode = 0xEB; //команда "Quad I/O Fast Read"
HAL_SPIFI_SendCommand(&spifi, &spifi_rdsr, 0, 1, &Sregs[0], 0, HAL_SPIFI_TIMEOUT); //читаем регистр флэхи
if ((Sregs[0] & 0x40) == 0) //проверяем бит QE
{
HAL_SPIFI_SendCommand(&spifi, &spifi_rdcr, 0, 1, &Sregs[1], 0, HAL_SPIFI_TIMEOUT); //дополнительно читаем другой регистр
Sregs[0] |= 0x40; //выставляем бит QE
HAL_SPIFI_SendCommand(&spifi, &spifi_write_enable, 0, 0, 0, 0, HAL_SPIFI_TIMEOUT); //открываем запись
HAL_SPIFI_SendCommand(&spifi, &spifi_wrsr, 0, 2, 0, Sregs, HAL_SPIFI_TIMEOUT); //перезаписываем регистры
do
{
HAL_SPIFI_SendCommand(&spifi, &spifi_rdsr, 0, 1, &Sregs[0], 0, HAL_SPIFI_TIMEOUT);
}
while (Sregs[0] & 0x01); //топчемся на месте пока не сбросится бит WIP
}
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_quad_addr_memory_read;
HAL_SPIFI_MemoryMode_Init(&spifi_mem_config); //забиваем настройки кэша и команду, которая будет делать чтение из флэхи
}