Updater: Use -O0 and write flash writer and fix hex parser
This commit is contained in:
parent
bfdc3d3246
commit
d962110823
@ -20,7 +20,7 @@ add_executable(${ELFFILE} ${SRCS} ${FATFS_SRCS} ${SDIO_SRCS} ${STM_PERIPH_SRCS}
|
||||
|
||||
target_include_directories(${ELFFILE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ../../include)
|
||||
target_compile_options(${ELFFILE} PRIVATE -Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter)
|
||||
target_compile_options(${ELFFILE} PRIVATE -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles -Wimplicit-fallthrough=3 -Wsign-compare -Os -g3)
|
||||
target_compile_options(${ELFFILE} PRIVATE -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles -Wimplicit-fallthrough=3 -Wsign-compare -O0 -g3)
|
||||
target_compile_definitions(${ELFFILE} PRIVATE -DGIT_VER=${GIT_DESCRIBE} -DHSE_VALUE=8000000UL -DSTM32F407xx -DSTM32F4XX -DARM_MATH_CM4 -DSAFETY_MEMORY_STRIPOUT_DUMP)
|
||||
target_link_options(${ELFFILE} PRIVATE -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 --disable-newlib-supplied-syscalls -nostartfiles -T${LINKER_SCRIPT} -Wl,--print-memory-usage)
|
||||
set(GEN_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/include/generated")
|
||||
|
108
stm-firmware/updater/ram-code/flash-writer.c
Normal file
108
stm-firmware/updater/ram-code/flash-writer.c
Normal file
@ -0,0 +1,108 @@
|
||||
#include "flash-writer.h"
|
||||
#include <stm32/stm32f4xx.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static bool flash_op_busy(void)
|
||||
{
|
||||
return !!(FLASH->SR & FLASH_SR_BSY);
|
||||
}
|
||||
|
||||
static void lock_flash_cr(void)
|
||||
{
|
||||
FLASH->CR |= FLASH_CR_LOCK;
|
||||
}
|
||||
|
||||
void flash_writer_enable_access(void)
|
||||
{
|
||||
const uint32_t key1 = 0x45670123UL;
|
||||
const uint32_t key2 = 0xCDEF89ABUL;
|
||||
|
||||
FLASH->KEYR = key1;
|
||||
FLASH->KEYR = key2;
|
||||
}
|
||||
|
||||
void flash_writer_perform_mass_erase(void)
|
||||
{
|
||||
flash_writer_enable_access();
|
||||
while (flash_op_busy());
|
||||
|
||||
FLASH->CR = DMA_SxCR_PSIZE_1;
|
||||
FLASH->CR |= FLASH_CR_MER;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
|
||||
while(flash_op_busy());
|
||||
lock_flash_cr();
|
||||
}
|
||||
|
||||
uint32_t flash_writer_get_flash_size(void)
|
||||
{
|
||||
uint32_t flash_size;
|
||||
const uint32_t *flash_size_ptr = (const uint32_t *)0x1FFF7A22UL;
|
||||
|
||||
flash_size = *flash_size_ptr;
|
||||
flash_size *= 1024;
|
||||
|
||||
return flash_size;
|
||||
}
|
||||
|
||||
int flash_writer_write_to_memory(void *dest, void *src, uint32_t size)
|
||||
{
|
||||
uint32_t full_word_cnt;
|
||||
uint32_t byte_cnt;
|
||||
uint32_t idx;
|
||||
uint32_t *word_src_ptr;
|
||||
uint32_t *word_dest_ptr;
|
||||
char *char_src_ptr;
|
||||
char *char_dest_ptr;
|
||||
|
||||
flash_writer_enable_access();
|
||||
while (flash_op_busy());
|
||||
|
||||
/* Do the full words */
|
||||
full_word_cnt = size / 4u;
|
||||
byte_cnt = size % 4;
|
||||
|
||||
word_dest_ptr = dest;
|
||||
word_src_ptr = src;
|
||||
|
||||
if (full_word_cnt) {
|
||||
FLASH->CR = FLASH_CR_PSIZE_1;
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
|
||||
for (idx = 0; idx < full_word_cnt; idx++) {
|
||||
*word_dest_ptr = *word_src_ptr;
|
||||
word_dest_ptr++;
|
||||
word_src_ptr++;
|
||||
}
|
||||
|
||||
while (flash_op_busy());
|
||||
FLASH->CR = 0;
|
||||
}
|
||||
|
||||
/* write remaining bytes */
|
||||
if (byte_cnt) {
|
||||
char_src_ptr = (char *)word_src_ptr;
|
||||
char_dest_ptr = (char *)word_dest_ptr;
|
||||
|
||||
FLASH->CR = 0;
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
|
||||
for (idx = 0; idx < byte_cnt; idx++) {
|
||||
*char_dest_ptr = *char_src_ptr;
|
||||
char_dest_ptr++;
|
||||
char_src_ptr++;
|
||||
}
|
||||
|
||||
while (flash_op_busy());
|
||||
FLASH->CR = 0;
|
||||
}
|
||||
|
||||
lock_flash_cr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t flash_writer_get_base_address(void)
|
||||
{
|
||||
return FLASH_BASE;
|
||||
}
|
16
stm-firmware/updater/ram-code/flash-writer.h
Normal file
16
stm-firmware/updater/ram-code/flash-writer.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef _FLASH_WRITER_H_
|
||||
#define _FLASH_WRITER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void flash_writer_enable_access(void);
|
||||
|
||||
void flash_writer_perform_mass_erase(void);
|
||||
|
||||
uint32_t flash_writer_get_flash_size(void);
|
||||
|
||||
uint32_t flash_writer_get_base_address(void);
|
||||
|
||||
int flash_writer_write_to_memory(void *dest, void *src, uint32_t size);
|
||||
|
||||
#endif /* _FLASH_WRITER_H_ */
|
@ -1,72 +1,74 @@
|
||||
#include "hex-parser.h"
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
static int convert_hex_char_to_value(char c, uint32_t *out)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t value = 0;
|
||||
int ret = 0;
|
||||
uint32_t value = 0;
|
||||
|
||||
if (!out)
|
||||
return -1002;
|
||||
if (!out)
|
||||
return -1002;
|
||||
|
||||
switch (c) {
|
||||
case '0' ... '9':
|
||||
value = (uint32_t)c - (uint32_t)'0';
|
||||
break;
|
||||
case 'a' ... 'f':
|
||||
/* Convert to upper */
|
||||
c -= 0x20;
|
||||
/* FALLTHRU */
|
||||
case 'A' ... 'F':
|
||||
value = (uint32_t)c - (uint32_t)'A' + 10UL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
switch (c) {
|
||||
case '0' ... '9':
|
||||
value = (uint32_t)c - (uint32_t)'0';
|
||||
break;
|
||||
case 'a' ... 'f':
|
||||
/* Convert to upper */
|
||||
c -= 0x20;
|
||||
/* FALLTHRU */
|
||||
case 'A' ... 'F':
|
||||
value = (uint32_t)c - (uint32_t)'A' + 10UL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
*out = value;
|
||||
if (ret == 0)
|
||||
*out = value;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int convert_big_endian_hex_string_to_val(const char *string, size_t len, uint32_t *out)
|
||||
{
|
||||
int ret_val = -1;
|
||||
uint32_t converted_value = 0UL;
|
||||
uint32_t digit;
|
||||
int res;
|
||||
unsigned int i;
|
||||
int ret_val = -1;
|
||||
uint32_t converted_value = 0UL;
|
||||
uint32_t digit;
|
||||
int res;
|
||||
unsigned int i;
|
||||
|
||||
/* Return error in case of an input error */
|
||||
if (!string || !len)
|
||||
goto exit;
|
||||
/* Return error in case of an input error */
|
||||
if (!string || !len)
|
||||
goto exit;
|
||||
|
||||
if (!out)
|
||||
return -1003;
|
||||
if (!out)
|
||||
return -1003;
|
||||
|
||||
/* we don't support strings larger than 8 chars */
|
||||
if (len > 8)
|
||||
goto exit;
|
||||
/* we don't support strings larger than 8 chars */
|
||||
if (len > 8)
|
||||
goto exit;
|
||||
|
||||
|
||||
for (i = 0; i < len && string[i] != '\0'; i++) {
|
||||
/* Convert current character to number */
|
||||
res = convert_hex_char_to_value(string[i], &digit);
|
||||
if (res) {
|
||||
/* Not a hex number */
|
||||
ret_val = -2;
|
||||
goto exit;
|
||||
}
|
||||
for (i = 0; i < len && string[i] != '\0'; i++) {
|
||||
/* Convert current character to number */
|
||||
res = convert_hex_char_to_value(string[i], &digit);
|
||||
if (res) {
|
||||
/* Not a hex number */
|
||||
ret_val = -2;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
converted_value *= 0x10;
|
||||
converted_value += digit;
|
||||
}
|
||||
converted_value *= 0x10;
|
||||
converted_value += digit;
|
||||
}
|
||||
|
||||
*out = converted_value;
|
||||
*out = converted_value;
|
||||
ret_val = 0;
|
||||
|
||||
exit:
|
||||
return ret_val;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
enum hex_parser_ret hex_parser_open(struct hex_parser *parser, const char *file_name)
|
||||
@ -85,7 +87,179 @@ enum hex_parser_ret hex_parser_open(struct hex_parser *parser, const char *file_
|
||||
return HEX_PARSER_OK;
|
||||
}
|
||||
|
||||
enum hex_parser_ret hex_parser_parse(struct hex_parser *parser, uint32_t *address, char *data, size_t data_len);
|
||||
static int read_line_from_file(FIL *file, char *data, int size)
|
||||
{
|
||||
char *ret_ptr;
|
||||
int length;
|
||||
|
||||
ret_ptr = f_gets(data, size, file);
|
||||
if (!ret_ptr)
|
||||
return -1;
|
||||
|
||||
/* To be sure */
|
||||
data[size - 1] = 0;
|
||||
length = strlen(ret_ptr);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static int hex_record_check_checksum(const char *buff, int hex_byte_count)
|
||||
{
|
||||
int i;
|
||||
int res;
|
||||
uint32_t checksum = 0;
|
||||
uint32_t tmp;
|
||||
|
||||
if (!buff || !hex_byte_count)
|
||||
return -1000;
|
||||
|
||||
for (i = 0; i < hex_byte_count; i++) {
|
||||
res = convert_big_endian_hex_string_to_val(&buff[2 * i], 2, &tmp);
|
||||
if (res)
|
||||
return -1;
|
||||
checksum += tmp;
|
||||
}
|
||||
|
||||
if (checksum & 0xFF) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum hex_parser_ret hex_parser_parse(struct hex_parser *parser, uint32_t *address, char *data, size_t data_len,
|
||||
size_t *lenout)
|
||||
{
|
||||
static char workbuff[512];
|
||||
int count;
|
||||
int i;
|
||||
enum hex_parser_ret retval = HEX_PARSER_DATA_OK;
|
||||
uint32_t hex_addr;
|
||||
uint32_t byte_count;
|
||||
uint32_t record_type;
|
||||
uint32_t tmp;
|
||||
|
||||
if (!parser || !lenout || !data_len || !data || !address)
|
||||
return HEX_PARSER_ERROR;
|
||||
|
||||
/* Read a line from the file */
|
||||
count = read_line_from_file(&parser->file, workbuff, sizeof(workbuff));
|
||||
if (!count) {
|
||||
/* Check for error in case nothing is read */
|
||||
if (f_error(&parser->file)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
} else if (f_eof(&parser->file)) {
|
||||
retval = HEX_PARSER_FILE_END;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Strip out invalid characters at the end */
|
||||
for (i = count - 1; i >= 0; i--) {
|
||||
if (workbuff[i] == '\r' || workbuff[i] == '\n' ||
|
||||
workbuff[i] == '\t' || workbuff[i] == ' ')
|
||||
{
|
||||
workbuff[i] = 0;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
/* We read a valid line, check for valid marker */
|
||||
if (workbuff[0] != ':') {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Line has to be longer than 11 chars in total */
|
||||
if (count < 11) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Read in the data count */
|
||||
if (convert_big_endian_hex_string_to_val(&workbuff[1], 2, &byte_count)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Read in the address */
|
||||
if (convert_big_endian_hex_string_to_val(&workbuff[3], 4, &hex_addr)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Read in the record type */
|
||||
if (convert_big_endian_hex_string_to_val(&workbuff[7], 2, &record_type)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (byte_count * 2 + 9 + 2 != (unsigned int)count) {
|
||||
/* Line not the expected length */
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Check the checksum. We have bytecount + 5 bytes in a record */
|
||||
if (hex_record_check_checksum(&workbuff[1], byte_count + 5)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Check record type */
|
||||
switch (record_type) {
|
||||
case 0x00: /* Data */
|
||||
if (byte_count > data_len) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
*lenout = 0;
|
||||
*address = hex_addr + parser->current_address_offset;
|
||||
|
||||
for (i = 0; i < (int)byte_count; i++) {
|
||||
if (convert_big_endian_hex_string_to_val(&workbuff[9 + 2*i], 2, &tmp)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
*data = (char)(tmp & 0xFF);
|
||||
data++;
|
||||
(*lenout)++;
|
||||
}
|
||||
retval = HEX_PARSER_DATA_OK;
|
||||
break;
|
||||
case 0x01: /* End of file */
|
||||
retval = HEX_PARSER_EOF_RECORD;
|
||||
break;
|
||||
case 0x04: /* extended linear address */
|
||||
if (byte_count != 2) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Parse the upper 16 bit of the address */
|
||||
if (convert_big_endian_hex_string_to_val(&workbuff[9], 4, &tmp)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
parser->current_address_offset = tmp << 16;
|
||||
retval = HEX_PARSER_OK;
|
||||
break;
|
||||
case 0x05:
|
||||
retval = HEX_PARSER_OK;
|
||||
break;
|
||||
default:
|
||||
retval = HEX_PARSER_ERROR;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
enum hex_parser_ret hex_parser_close(struct hex_parser *parser) {
|
||||
if (!parser)
|
||||
|
@ -6,10 +6,11 @@
|
||||
#include <stddef.h>
|
||||
|
||||
enum hex_parser_ret {
|
||||
HEX_PARSER_OK,
|
||||
HEX_PARSER_OK = 0,
|
||||
HEX_PARSER_DATA_OK,
|
||||
HEX_PARSER_ERROR,
|
||||
HEX_PARSER_FILE_END,
|
||||
HEX_PARSER_EOF_RECORD,
|
||||
};
|
||||
|
||||
struct hex_parser {
|
||||
@ -19,7 +20,8 @@ struct hex_parser {
|
||||
|
||||
enum hex_parser_ret hex_parser_open(struct hex_parser *parser, const char *file_name);
|
||||
|
||||
enum hex_parser_ret hex_parser_parse(struct hex_parser *parser, uint32_t *address, char *data, size_t data_len);
|
||||
enum hex_parser_ret hex_parser_parse(struct hex_parser *parser, uint32_t *address, char *data, size_t data_len,
|
||||
size_t *len_out);
|
||||
|
||||
enum hex_parser_ret hex_parser_close(struct hex_parser *parser);
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <stm-periph/stm32-gpio-macros.h>
|
||||
|
||||
#include <reflow-controller/safety/safety-memory.h>
|
||||
#include "flash-writer.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@ -49,13 +50,52 @@ static void __attribute__((noreturn)) ram_code_exit(bool updated)
|
||||
while(1);
|
||||
}
|
||||
|
||||
static int check_hex_file(const char *fname)
|
||||
{
|
||||
enum hex_parser_ret hex_ret;
|
||||
struct hex_parser parser;
|
||||
uint32_t addr;
|
||||
char data[128];
|
||||
size_t dlen;
|
||||
int retval = -1;
|
||||
uint32_t flash_base;
|
||||
uint32_t flash_top;
|
||||
|
||||
flash_base = flash_writer_get_base_address();
|
||||
flash_top = flash_base + flash_writer_get_flash_size();
|
||||
|
||||
hex_ret = hex_parser_open(&parser, fname);
|
||||
if (hex_ret != HEX_PARSER_OK) {
|
||||
retval = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
do {
|
||||
hex_ret = hex_parser_parse(&parser, &addr, data, sizeof(data), &dlen);
|
||||
if (hex_ret == HEX_PARSER_DATA_OK) {
|
||||
if (addr < flash_base || addr+dlen >= flash_top) {
|
||||
retval = -2;
|
||||
goto ret_close_parser;
|
||||
}
|
||||
}
|
||||
} while (hex_ret == HEX_PARSER_DATA_OK || hex_ret == HEX_PARSER_OK);
|
||||
|
||||
if (hex_ret == HEX_PARSER_EOF_RECORD) {
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
ret_close_parser:
|
||||
hex_parser_close(&parser);
|
||||
exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
int ram_code_main(void)
|
||||
{
|
||||
FRESULT fres;
|
||||
int res;
|
||||
enum safety_memory_state safety_mem_state;
|
||||
enum hex_parser_ret hex_ret;
|
||||
struct hex_parser parser;
|
||||
static char filename[256];
|
||||
|
||||
SysTick_Config(168000UL);
|
||||
external_watchdog_disable();
|
||||
@ -71,8 +111,11 @@ int ram_code_main(void)
|
||||
ram_code_exit(false);
|
||||
}
|
||||
|
||||
hex_ret = hex_parser_open(&parser, "update.hex");
|
||||
if (hex_ret != HEX_PARSER_OK) {
|
||||
res = safety_memory_get_update_filename(filename, NULL);
|
||||
if (res)
|
||||
ram_code_exit(false);
|
||||
|
||||
if (check_hex_file(filename)) {
|
||||
ram_code_exit(false);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user