Files
templates/c/set-protocol/ports/stm32g474-usb-boot/boot_writer.h

49 lines
2.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Накопление неполного 64-битного слова Flash STM32G474 между пакетами. ECC требует
* программировать слово один раз; только последний хвост дополняется 0xFF, а длина исходного
* образа остаётся неизменной.
*/
#ifndef G474_BOOT_WRITER_H
#define G474_BOOT_WRITER_H
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
/* ECC Flash must be programmed once per 64-bit word. Keep partial words in RAM
* across SET packets; pad only the final word, without changing the image CRC. */
typedef bool (*g474_program_word)(void *user, uint32_t offset, uint64_t word);
typedef struct {
uint32_t size, received;
uint8_t pending[8];
uint8_t used;
bool failed;
} g474_writer;
static inline void g474_writer_init(g474_writer *w, uint32_t size)
{
memset(w, 0, sizeof(*w)); w->size = size;
memset(w->pending, 0xff, sizeof(w->pending));
}
/* offset и length описывают байты исходного образа. Хвост пакета остаётся
* в pending до следующего вызова; повтор или перестановка пакетов запрещены.
* После отказа program контекст помечается failed до новой инициализации. */
static inline bool g474_writer_write(g474_writer *w, uint32_t offset,
const uint8_t *data, uint16_t length, g474_program_word program, void *user)
{
if (w->failed || !length || offset != w->received ||
offset > w->size || length > w->size - offset) return false;
while (length--) {
w->pending[w->used++] = *data++; ++w->received;
if (w->used == 8 || w->received == w->size) {
uint64_t word;
/* Адрес берётся от начала накопленного слова, а не от границы
* текущего пакета, которая может проходить внутри этого слова. */
uint32_t start = w->received - w->used;
memcpy(&word, w->pending, sizeof(word));
if (!program(user, start, word)) { w->failed = true; return false; }
w->used = 0; memset(w->pending, 0xff, sizeof(w->pending));
}
}
return true;
}
#endif