From a72731ad2b8ae518918b445d0c9be04b06e05652 Mon Sep 17 00:00:00 2001 From: KLASSENTS Date: Wed, 23 Jul 2025 15:13:50 +0700 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0?= =?UTF-8?q?=20-=20=D0=B4=D0=B5=D0=B9=D1=81=D1=82=D0=B2=D0=B8=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D0=BE=20=D0=BB=D0=B8=20=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=86=D0=B0=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=B2=D0=BE=20flash=20=D0=BF=D0=B0=D0=BC=D1=8F=D1=82=D1=8C.=20?= =?UTF-8?q?=D0=95=D1=81=D0=BB=D0=B8=20=D0=BD=D0=B5=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BD=D0=B0,=20=D0=B7=D0=B0=D0=B3=D1=80?= =?UTF-8?q?=D1=83=D0=B7=D1=87=D0=B8=D0=BA=D1=83=20=D0=BE=D1=82=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D1=8F=D0=B5=D1=82=D1=81=D1=8F=20NACK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bootloader.c | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/bootloader.c b/src/bootloader.c index d0d9359..c6c10fe 100644 --- a/src/bootloader.c +++ b/src/bootloader.c @@ -41,8 +41,8 @@ typedef enum typedef enum { ERROR_NONE = 0, - ERROR_TIMEOUT = 1, // Время ожидания истекло - ERROR_CRC + ERROR_TIMEOUT = 1, // Время ожидания истекло + ERROR_CRC, // Ошибка при получении строки hex от ПК или при записи страницы данных на flash } Bootloader_error; typedef struct @@ -192,6 +192,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 +218,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 +260,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 +269,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;