65 lines
2.2 KiB
C
65 lines
2.2 KiB
C
/**
|
|
* @file fwu.c
|
|
* @brief Implementation of the Firmware Update (FWU) library.
|
|
*
|
|
* This file implements the logic for receiving a new firmware image in chunks
|
|
* over Modbus. It maintains a buffer for the incoming data, calculates the CRC
|
|
* of the received chunk, and handles commands to verify the chunk and finalize
|
|
* the update process. The actual writing to flash is simulated.
|
|
*/
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/logging/log.h>
|
|
#include <zephyr/sys/byteorder.h>
|
|
#include <zephyr/sys/crc.h>
|
|
#include <lib/fwu.h>
|
|
|
|
LOG_MODULE_REGISTER(fwu, LOG_LEVEL_INF);
|
|
|
|
#define FWU_BUFFER_SIZE 256
|
|
static uint8_t fwu_buffer[FWU_BUFFER_SIZE]; // Buffer to store incoming
|
|
// firmware data chunks
|
|
static uint32_t fwu_chunk_offset = 0; // Offset for the current firmware chunk in the overall image
|
|
static uint16_t fwu_chunk_size = 0; // Size of the current firmware chunk
|
|
static uint16_t fwu_last_chunk_crc = 0; // CRC16 of the last received firmware chunk
|
|
|
|
void fwu_init(void)
|
|
{
|
|
}
|
|
|
|
void fwu_handler(uint16_t addr, uint16_t reg)
|
|
{
|
|
// This is a simplified handler. In a real scenario, you would have a proper
|
|
// mapping between register addresses and actions.
|
|
if (addr == 0x0100) { // FWU_COMMAND
|
|
if (reg == 1) {
|
|
LOG_INF("FWU: Chunk at offset %u (size %u) verified.",
|
|
fwu_chunk_offset,
|
|
fwu_chunk_size);
|
|
} else if (reg == 2) {
|
|
LOG_INF("FWU: Finalize command received. Rebooting (simulated).");
|
|
}
|
|
} else if (addr == 0x0101) { // FWU_CHUNK_OFFSET_LOW
|
|
fwu_chunk_offset = (fwu_chunk_offset & 0xFFFF0000) | reg;
|
|
} else if (addr == 0x0102) { // FWU_CHUNK_OFFSET_HIGH
|
|
fwu_chunk_offset = (fwu_chunk_offset & 0x0000FFFF) | ((uint32_t)reg << 16);
|
|
} else if (addr == 0x0103) { // FWU_CHUNK_SIZE
|
|
fwu_chunk_size = (reg > FWU_BUFFER_SIZE) ? FWU_BUFFER_SIZE : reg;
|
|
} else if (addr >= 0x0180 && addr < (0x0180 + (FWU_BUFFER_SIZE / 2))) {
|
|
uint16_t index = (addr - 0x0180) * 2;
|
|
if (index < sizeof(fwu_buffer)) {
|
|
sys_put_be16(reg, &fwu_buffer[index]);
|
|
if (index + 2 >= fwu_chunk_size) {
|
|
fwu_last_chunk_crc =
|
|
crc16_ccitt(0xffff, fwu_buffer, fwu_chunk_size);
|
|
LOG_INF("FWU: Chunk received, CRC is 0x%04X", fwu_last_chunk_crc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
uint16_t fwu_get_last_chunk_crc(void)
|
|
{
|
|
return fwu_last_chunk_crc;
|
|
}
|