Updater: Use -O0 and write flash writer and fix hex parser

This commit is contained in:
Mario Hüttel 2021-04-07 23:14:45 +02:00
parent bfdc3d3246
commit d962110823
6 changed files with 398 additions and 55 deletions

View File

@ -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")

View 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;
}

View 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_ */

View File

@ -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)

View File

@ -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);

View File

@ -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);
}