Updater: Use -O0 and write flash writer and fix hex parser
This commit is contained in:
		@@ -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,5 +1,6 @@
 | 
			
		||||
#include "hex-parser.h"
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
static int convert_hex_char_to_value(char c, uint32_t *out)
 | 
			
		||||
{
 | 
			
		||||
@@ -64,6 +65,7 @@ static int convert_big_endian_hex_string_to_val(const char *string, size_t len,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*out = converted_value;
 | 
			
		||||
	ret_val = 0;
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
	return ret_val;
 | 
			
		||||
@@ -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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user