v0.2.0
- добавлен сброс бита CMP в статус-регистре 2 flash-памяти перед переходом в основную программу - добавлена проверка успешности записи страницы во flash-память - добавлена команда на получение версии начального загрузчика Co-authored-by: KLASSENTS <klassen@elron.tech> Co-committed-by: KLASSENTS <klassen@elron.tech>
This commit is contained in:
parent
85b74eb004
commit
5012c9a0f0
@ -11,6 +11,11 @@
|
||||
|
||||
#include "string.h"
|
||||
|
||||
// версия начального загрузчика
|
||||
#define MAJOR_VER 0
|
||||
#define MINOR_VER 2
|
||||
#define BUGFIX_VER 0
|
||||
|
||||
#define JALR_TO_SPIFI() \
|
||||
asm volatile( "la ra, 0x80000000\n\t" \
|
||||
"jalr ra" \
|
||||
@ -29,6 +34,7 @@ typedef enum
|
||||
{
|
||||
PACKAGE_SIZE = 0x30, /* Команда размера пакета */
|
||||
SEND_PACKAGE = 0x60, /* Команда отправить пакет */
|
||||
VERSION = 0x90, /* Команда получения версии начального загрузчика */
|
||||
FULL_ERASE = 0xBADC0FEE /* Команда стирания spifi */
|
||||
} BotloaderComand;
|
||||
|
||||
@ -42,7 +48,7 @@ typedef enum
|
||||
{
|
||||
ERROR_NONE = 0,
|
||||
ERROR_TIMEOUT = 1, // Время ожидания истекло
|
||||
ERROR_CRC
|
||||
ERROR_CRC, // Ошибка при получении строки hex от ПК или при записи страницы данных на flash
|
||||
} Bootloader_error;
|
||||
|
||||
typedef struct
|
||||
@ -192,6 +198,22 @@ uint32_t rel_addr = 0; // адрес от начала области spifi, п
|
||||
#define TAIL_SIZE 15 // если попадутся строки хекса, в которых не 16 байт, то мы рискуем записать данные уарта мимо буфера package_data. а если больше 16 байт, то это проблема завтрашнего дня
|
||||
uint8_t page_data[MAX_PACKAGE_SIZE + TAIL_SIZE] = {0}; // сюда собираем распарсенные данные из хекса
|
||||
uint16_t page_fill_size = 0; // счетчик, сколько заполнно в page_data. когда page_data заполнена до конца - будем записывать в spifi
|
||||
uint8_t read_data[MAX_PACKAGE_SIZE] = {0};
|
||||
|
||||
bool page_data_is_written(void)
|
||||
{
|
||||
// читаем ту же страницу в другой буфер
|
||||
memset(read_data, 0xFF, MAX_PACKAGE_SIZE);
|
||||
HAL_SPIFI_W25_ReadData(&spifi, (uint32_t)hBootloader.address, MAX_PACKAGE_SIZE, read_data);
|
||||
// побайтово сравниваем содержимое двух буферов
|
||||
for (uint16_t i = 0; i < MAX_PACKAGE_SIZE; i++)
|
||||
{
|
||||
if (read_data[i] != page_data[i])
|
||||
// если не сходится хоть один байт, прерываем проверку
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void mem_write()
|
||||
{
|
||||
@ -202,18 +224,27 @@ void mem_write()
|
||||
|
||||
// записываем страницу в 256 байт в spifi
|
||||
HAL_SPIFI_W25_PageProgram(&spifi, (uint32_t)hBootloader.address, MAX_PACKAGE_SIZE, page_data);
|
||||
|
||||
// проверить, записалось ли действительно содержимое буфера
|
||||
if (!page_data_is_written())
|
||||
{
|
||||
// если не записалось, выставим ошибку по crc и выходим
|
||||
hBootloader.error = ERROR_CRC;
|
||||
return;
|
||||
}
|
||||
|
||||
// увеличиваем адреса, по которым писать и стирать
|
||||
hBootloader.address += MAX_PACKAGE_SIZE;
|
||||
// обнуляем часть буфера, которая была записана в память и уменьшаем счетчик заполнения буфера на столько, сколько было записано
|
||||
// очищаем часть буфера, которая была записана в память и уменьшаем счетчик заполнения буфера на столько, сколько было записано
|
||||
if (page_fill_size <= MAX_PACKAGE_SIZE)
|
||||
page_fill_size = 0;
|
||||
else
|
||||
page_fill_size -= MAX_PACKAGE_SIZE;
|
||||
memset(&page_data[0], 0, MAX_PACKAGE_SIZE);
|
||||
memset(&page_data[0], 0xFF, MAX_PACKAGE_SIZE);
|
||||
// хвост копируем в начало буфера, чтобы записать его в следующий раз
|
||||
memcpy(&page_data[0], &page_data[MAX_PACKAGE_SIZE], TAIL_SIZE);
|
||||
// а сам хвост обнуляем
|
||||
memset(&page_data[MAX_PACKAGE_SIZE], 0, TAIL_SIZE);
|
||||
// а сам хвост очищаем
|
||||
memset(&page_data[MAX_PACKAGE_SIZE], 0xFF, TAIL_SIZE);
|
||||
}
|
||||
void Bootloader_parseHexAndLoadInMemory(uint8_t rx_data[])
|
||||
{
|
||||
@ -235,7 +266,7 @@ void Bootloader_parseHexAndLoadInMemory(uint8_t rx_data[])
|
||||
memcpy(&page_data[page_fill_size], &rx_data[DATA_POS], rx_data[BYTE_COUNT_POS]);
|
||||
// указываем, на сколько заполнился буфер
|
||||
page_fill_size += rx_data[BYTE_COUNT_POS];
|
||||
// если пора записывать целую страницу - пишемм
|
||||
// если пора записывать целую страницу - пишем
|
||||
if (page_fill_size >= 256)
|
||||
mem_write();
|
||||
break;
|
||||
@ -244,7 +275,12 @@ void Bootloader_parseHexAndLoadInMemory(uint8_t rx_data[])
|
||||
Bootloader_UART_WriteByte(ACK);
|
||||
// если есть недозаполненная страница, записываем ее как есть
|
||||
if (page_fill_size != 0)
|
||||
{
|
||||
mem_write();
|
||||
// если при записи остатков возникли ошибки, здесь в основную программу не будем переходить
|
||||
if (hBootloader.error)
|
||||
return;
|
||||
}
|
||||
// и идем в записанную программу
|
||||
go_to_spifi();
|
||||
break;
|
||||
@ -305,6 +341,15 @@ void Bootloader_Commands()
|
||||
{
|
||||
switch (hBootloader.command)
|
||||
{
|
||||
case VERSION:
|
||||
validCommandsTimeout = 0; // Сброс таймаута валидных команд
|
||||
eraseChipBufferIndex = 0;
|
||||
Bootloader_UART_WriteByte(ACK); // Подтвердить команду
|
||||
// отправить все составляющие версии загрузчика
|
||||
Bootloader_UART_WriteByte((uint16_t)MAJOR_VER);
|
||||
Bootloader_UART_WriteByte((uint16_t)MINOR_VER);
|
||||
Bootloader_UART_WriteByte((uint16_t)BUGFIX_VER);
|
||||
break;
|
||||
case PACKAGE_SIZE:
|
||||
validCommandsTimeout = 0; // Сброс таймаута валидных команд
|
||||
eraseChipBufferIndex = 0;
|
||||
@ -426,6 +471,7 @@ void SPIFI_Init()
|
||||
if (sreg1 > 0x03) sreg1 = 0; // снятие защиты от записи (protection bits)
|
||||
uint8_t sreg2 = HAL_SPIFI_W25_ReadSREG(&spifi, W25_SREG2);
|
||||
if (!(sreg2 & 0x02)) sreg2 |= 0x02; // установка бита QE (quad enable)
|
||||
if (sreg2 & 0x40) sreg2 &= ~0x40; // сброс бита CMP. Если вдруг он выставился по какой-то причине, часть или вся память можеть быть заблокирована для записи
|
||||
HAL_SPIFI_W25_WriteSREG(&spifi, sreg1, sreg2);
|
||||
|
||||
#if CHIP_MODE == 1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user