44 Commits

Author SHA1 Message Date
fe0bde5c32 Fix wrong string constant 2021-05-20 23:54:42 +02:00
2beaccbe32 Fix typo in comment 2021-05-20 23:54:21 +02:00
b6760ff426 Merge branch 'issue/24-update-could-fail' of mhu/reflow-oven-control-sw into dev 2021-05-16 20:41:56 +02:00
1b2dac21f2 Merge branch 'issue/25-add-update-to-gui' of mhu/reflow-oven-control-sw into dev 2021-05-16 20:40:39 +02:00
97f154d3b9 Add working reflow profile so it isn't lost by accident 2021-05-16 20:38:17 +02:00
ee5dda4a33 Issue #25: Add update menu to GUI 2021-05-16 20:34:09 +02:00
afb8e93b13 Rework function for finding temperature profiles to be able to search for any pattern 2021-05-16 19:57:08 +02:00
9bd0dd194b Issue #24: Fix bug in update code 2021-05-16 19:53:46 +02:00
6322c3728b Use singly linked list to store profile commands. 2021-05-15 21:58:00 +02:00
174bf4220e Remove unused function 2021-05-15 21:57:23 +02:00
566436201e Increase heap size 2021-05-15 21:56:33 +02:00
61e3b58992 Use singly linked list dfor temperature profile file list 2021-05-07 22:09:55 +02:00
01b445a0fb Update linked list library and include it into build 2021-04-10 22:35:30 +02:00
5437a323c3 Add linklist submodule 2021-04-10 22:29:18 +02:00
28e42d3306 Shell: Update: Print error if no update file name is specified 2021-04-10 22:28:30 +02:00
08606689b4 Update fatfs in main application 2021-04-10 20:35:33 +02:00
5776feee85 Merge branch 'dev' of git.shimatta.de:mhu/reflow-oven-control-sw into dev 2021-04-10 20:13:29 +02:00
6273c68821 Shell update command: Take file name as argument 2021-04-10 20:09:52 +02:00
3381840bba Modify git version generation in cmake 2021-04-10 20:09:15 +02:00
cf35ba735f Modify git version generation in cmake 2021-04-10 19:40:49 +02:00
3f31acfada Updater: Fix missing line break in uart output 2021-04-10 15:42:19 +02:00
77251cc1bc increase stack and heap sizes 2021-04-10 14:44:27 +02:00
f2972903d5 Use safer string copying in gui for file list 2021-04-10 14:37:51 +02:00
31b17dfd8d Updater: Clear shell at startup and print size of update 2021-04-10 14:37:05 +02:00
9f1a791be2 Remove custom option checker and use the one of the shellmatta instead 2021-04-10 14:10:17 +02:00
54416a6350 Edit Cmake file to use ENV variable to device if Uart is on debug header or not 2021-04-10 13:45:00 +02:00
9c94428144 Bugfix: button ready state not correctly detected when menu drops back 2021-04-10 13:24:15 +02:00
81155887de Bug: Fix missing variable in printf varargs for gui 2021-04-10 13:11:35 +02:00
8309cef5ec Updater: Fix updating code 2021-04-08 22:03:38 +02:00
1a76a69b6d Switch updater to -Os compilation 2021-04-08 21:50:42 +02:00
e50e3f0ace Add verify step to updater 2021-04-08 21:49:53 +02:00
5fb1612773 make updater reboot after successful update 2021-04-08 21:37:49 +02:00
72735915ee Clear code updated status flag upon startup 2021-04-08 21:35:19 +02:00
08ec458e8f Add update code to updater and use uart for status updates 2021-04-08 21:23:25 +02:00
d962110823 Updater: Use -O0 and write flash writer and fix hex parser 2021-04-07 23:14:45 +02:00
bfdc3d3246 Updater: Store update file name in safety memory before executing updater. Currently name is hardcoded. 2021-04-07 13:26:39 +02:00
dca839ce2e Merge branch 'dev' into updater 2021-04-07 13:19:53 +02:00
eea0826c7b updater: Add function to safety memory for storing the update file name 2021-04-07 13:19:16 +02:00
6e5627fde2 Updater: Add safety memory to updater 2021-04-06 20:55:41 +02:00
0f239dc39d Fix warning in temp profile parser 2021-04-06 20:53:18 +02:00
08eee66d30 Issue #28: Change GUI of profile executer 2021-04-06 19:46:31 +02:00
7c9d296e34 Merge branch 'dev' into feature/28-profile-parser 2021-04-06 19:45:37 +02:00
533656ca28 Add Cmake variable for Uart on debug header in release and use -Og for debugbuild instead of -O0 2021-04-06 19:25:25 +02:00
d146b10569 Issue #28: Inmprove GUI of profile executer 2021-04-06 19:23:45 +02:00
33 changed files with 1380 additions and 337 deletions

3
.gitmodules vendored
View File

@@ -10,3 +10,6 @@
path = stm-firmware/base64-lib
url = https://git.shimatta.de/mhu/base64-lib.git
branch = master
[submodule "stm-firmware/linklist-lib"]
path = stm-firmware/linklist-lib
url = https://git.shimatta.de/mhu/linklist-lib.git

View File

@@ -0,0 +1,15 @@
# This is a comment
pid_conf 10 0.3 5 60 2.5 0.5
temp_set 50
wait_temp 45
temp_set 45
temp_ramp 150 120
temp_ramp 190 90
pid_conf 9 0.5 6 60 2.5 0.5
temp_set 250
wait_temp 245
temp_off
beep 1
wait_time 1
beep 0

View File

@@ -27,11 +27,24 @@ if(NOT WIN32)
set(BoldWhite "${Esc}[1;37m")
endif()
execute_process(COMMAND bash -c "echo -n $(git describe --always --tags --dirty)"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_DESCRIBE)
find_package(Git)
if (GIT_FOUND)
message("Git found")
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --always --tags --dirty
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_DESCRIBE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message("${BoldGreen}Git based version number: ${GIT_DESCRIBE}${ColorReset}")
else (GIT_FOUND)
set(GIT_DESCRIBE "v0.0.0-unknown")
message("${BoldRed}No git installation found. It is highly recommended using git to generate the version number")
message("Version is set to: ${GIT_DESCRIBE}${ColorReset}")
endif (GIT_FOUND)
set(ELFFILE ${PROJECT_NAME}.elf)
set(HEXFILE ${PROJECT_NAME}.hex)
set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/stm32f407vet6_flash.ld)
add_compile_options(-Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter)
@@ -45,19 +58,23 @@ add_subdirectory(updater/ram-code)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
message("${BoldGreen}Version: ${GIT_DESCRIBE}${ColorReset}")
IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DDEBUGBUILD)
add_compile_options(-O0 -g)
add_definitions(-DDEBUGBUILD)
add_compile_options(-Og -g)
ELSE()
add_definitions(-DDEBUGBUILD)
add_compile_options(-O3 -g)
add_link_options(-Wl,--gc-sections)
add_compile_options(-O3 -g)
add_link_options(-Wl,--gc-sections)
ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_subdirectory(base64-lib)
if (UART_ON_DEBUG_HEADER)
add_definitions(-DUART_ON_DEBUG_HEADER)
message("${BoldRed}UART forced to debug header${ColorReset}")
endif (UART_ON_DEBUG_HEADER)
add_subdirectory(base64-lib)
add_subdirectory(linklist-lib)
aux_source_directory("." MAIN_SOURCES)
aux_source_directory("config-parser" CFG_PARSER_SRCS)
@@ -81,6 +98,12 @@ add_dependencies(${ELFFILE} updater-ram-code-header-blob)
target_include_directories(${ELFFILE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/shellmatta/api ${CMAKE_CURRENT_SOURCE_DIR}/config-parser/include)
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)
target_link_libraries(${ELFFILE} base64-lib)
target_link_libraries(${ELFFILE} base64-lib linklist-lib)
target_include_directories(${ELFFILE} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/updater/ram-code/include/")
set(HEX_PATH "${CMAKE_CURRENT_BINARY_DIR}/${HEXFILE}")
add_custom_target(update-image ALL DEPENDS ${HEX_PATH})
add_custom_command(
DEPENDS ${ELFFILE}
OUTPUT ${HEX_PATH}
COMMAND ${CMAKE_OBJCOPY} -O ihex ${ELFFILE} ${HEX_PATH})

View File

@@ -23,6 +23,7 @@
#include <string.h>
#include <stdlib.h>
#include <fatfs/ff.h>
#include <linklist-lib/singly-linked-list.h>
struct pl_command_list_map {
enum pl_command_type command;
@@ -106,7 +107,7 @@ static int parse_line(char *line, struct pl_command *cmd)
uint8_t token_idx = 0;
char *token;
const char * const delim = " \t";
const struct pl_command_list_map *map;
const struct pl_command_list_map *map = NULL;
char *endptr;
struct pl_command c;
@@ -146,7 +147,7 @@ static int parse_line(char *line, struct pl_command *cmd)
token_idx++;
}
if (token_idx - 1 < map->expected_param_count) {
if (!map || (token_idx - 1 < map->expected_param_count)) {
return -3;
}
@@ -155,9 +156,20 @@ static int parse_line(char *line, struct pl_command *cmd)
return 0;
}
static SlList *copy_and_append_command_to_list(SlList *list, const struct pl_command *cmd)
{
struct pl_command *alloced_cmd;
alloced_cmd = (struct pl_command *)malloc(sizeof(struct pl_command));
memcpy(alloced_cmd, cmd, sizeof(struct pl_command));
list = sl_list_append(list, alloced_cmd);
return list;
}
enum pl_ret_val temp_profile_parse_from_file(const char *filename,
struct pl_command *cmd_list,
uint32_t cmd_list_length,
SlList **command_list,
uint32_t max_len,
uint32_t *cmds_parsed)
{
FIL script_file;
@@ -165,9 +177,10 @@ enum pl_ret_val temp_profile_parse_from_file(const char *filename,
int res;
enum pl_ret_val ret = PL_RET_SUCCESS;
char workbuff[256];
struct pl_command temp_command;
uint32_t cmd_idx;
if (!filename || !cmd_list || !cmd_list_length || !cmds_parsed)
if (!filename || !command_list || !max_len || !cmds_parsed)
return PL_RET_PARAM_ERR;
@@ -189,19 +202,22 @@ enum pl_ret_val temp_profile_parse_from_file(const char *filename,
}
/* Check if list already full */
if (cmd_idx >= cmd_list_length) {
if (cmd_idx >= max_len) {
ret = PL_RET_LIST_FULL;
goto exit_close;
}
/* Parse the line */
res = parse_line(workbuff, &cmd_list[cmd_idx]);
res = parse_line(workbuff, &temp_command);
if (res < 0) {
ret = PL_RET_SCRIPT_ERR;
goto exit_close;
} else if (res == 0) {
cmd_idx++;
*cmds_parsed= cmd_idx;
*cmds_parsed = cmd_idx;
/* Append the temp_command to the list */
*command_list = copy_and_append_command_to_list(*command_list, &temp_command);
}
@@ -212,3 +228,15 @@ exit_close:
exit:
return ret;
}
static void delete_pl_command(void *cmd)
{
if (cmd)
free(cmd);
}
void temp_profile_free_command_list(SlList **list)
{
sl_list_free_full(*list, delete_pl_command);
*list = NULL;
}

View File

@@ -1,5 +1,5 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2019 */
/* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2019 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
@@ -12,14 +12,8 @@
#include "shimatta_sdio_driver/shimatta_sdio.h"
/* Definitions of physical drive number for each drive */
#define DEV_SD 0 /* Example: Map MMC/SD card to physical drive 0*/
/*
DSTATUS SDIO_status();
DSTATUS SDIO_initialize();
DRESULT SDIO_disk_read(BYTE *buff, DWORD sector, UINT count);
DRESULT SDIO_disk_write(const BYTE *buff, DWORD sector, UINT count);
DRESULT SDIO_disk_ioctl(BYTE cmd, void* buff);
*/
#define DEV_SD 0
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
@@ -116,4 +110,3 @@ DRESULT disk_ioctl (
return RES_PARERR;
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem Module R0.14 /
/ FatFs - Generic FAT Filesystem Module R0.14a /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2019, ChaN, all right reserved.
/ Copyright (C) 2020, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
@@ -29,7 +29,7 @@
---------------------------------------------------------------------------*/
#if FF_DEFINED != 86606 /* Revision ID */
#if FF_DEFINED != 80196 /* Revision ID */
#error Wrong include file (ff.h).
#endif
@@ -1134,13 +1134,12 @@ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */
/* Create FSInfo structure */
mem_set(fs->win, 0, sizeof fs->win);
st_word(fs->win + BS_55AA, 0xAA55);
st_dword(fs->win + FSI_LeadSig, 0x41615252);
st_dword(fs->win + FSI_StrucSig, 0x61417272);
st_dword(fs->win + FSI_Free_Count, fs->free_clst);
st_dword(fs->win + FSI_Nxt_Free, fs->last_clst);
/* Write it into the FSInfo sector */
fs->winsect = fs->volbase + 1;
st_word(fs->win + BS_55AA, 0xAA55); /* Boot signature */
st_dword(fs->win + FSI_LeadSig, 0x41615252); /* Leading signature */
st_dword(fs->win + FSI_StrucSig, 0x61417272); /* Structure signature */
st_dword(fs->win + FSI_Free_Count, fs->free_clst); /* Number of free clusters */
st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); /* Last allocated culuster */
fs->winsect = fs->volbase + 1; /* Write it into the FSInfo sector (Next to VBR) */
disk_write(fs->pdrv, fs->win, fs->winsect, 1);
fs->fsi_flag = 0;
}
@@ -1235,7 +1234,8 @@ static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFF
break;
}
}
/* go to default */
val = 1; /* Internal error */
break;
#endif
default:
val = 1; /* Internal error */
@@ -1266,7 +1266,7 @@ static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */
if (clst >= 2 && clst < fs->n_fatent) { /* Check if in valid range */
switch (fs->fs_type) {
case FS_FAT12 :
case FS_FAT12:
bc = (UINT)clst; bc += bc / 2; /* bc: byte offset of the entry */
res = move_window(fs, fs->fatbase + (bc / SS(fs)));
if (res != FR_OK) break;
@@ -1280,16 +1280,16 @@ static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */
fs->wflag = 1;
break;
case FS_FAT16 :
case FS_FAT16:
res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
if (res != FR_OK) break;
st_word(fs->win + clst * 2 % SS(fs), (WORD)val); /* Simple WORD array */
fs->wflag = 1;
break;
case FS_FAT32 :
case FS_FAT32:
#if FF_FS_EXFAT
case FS_EXFAT :
case FS_EXFAT:
#endif
res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
if (res != FR_OK) break;
@@ -1821,7 +1821,7 @@ static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DEN
static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */
DIR* dp, /* Pointer to the directory object */
UINT nent /* Number of contiguous entries to allocate */
UINT n_ent /* Number of contiguous entries to allocate */
)
{
FRESULT res;
@@ -1836,16 +1836,16 @@ static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */
res = move_window(fs, dp->sect);
if (res != FR_OK) break;
#if FF_FS_EXFAT
if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) {
if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) { /* Is the entry free? */
#else
if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) {
if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) { /* Is the entry free? */
#endif
if (++n == nent) break; /* A block of contiguous free entries is found */
if (++n == n_ent) break; /* Is a block of contiguous free entries found? */
} else {
n = 0; /* Not a blank entry. Restart to search */
n = 0; /* Not a free entry, restart to search */
}
res = dir_next(dp, 1);
} while (res == FR_OK); /* Next entry with table stretch enabled */
res = dir_next(dp, 1); /* Next entry with table stretch enabled */
} while (res == FR_OK);
}
if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */
@@ -2527,19 +2527,19 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
FRESULT res;
FATFS *fs = dp->obj.fs;
#if FF_USE_LFN /* LFN configuration */
UINT n, nlen, nent;
UINT n, len, n_ent;
BYTE sn[12], sum;
if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */
for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */
for (len = 0; fs->lfnbuf[len]; len++) ; /* Get lfn length */
#if FF_FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
res = dir_alloc(dp, nent); /* Allocate directory entries */
n_ent = (len + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
res = dir_alloc(dp, n_ent); /* Allocate directory entries */
if (res != FR_OK) return res;
dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */
dp->blk_ofs = dp->dptr - SZDIRE * (n_ent - 1); /* Set the allocated entry block offset */
if (dp->obj.stat & 4) { /* Has the directory been stretched by new allocation? */
dp->obj.stat &= ~4;
@@ -2580,19 +2580,19 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
}
/* Create an SFN with/without LFNs. */
nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1; /* Number of entries to allocate */
res = dir_alloc(dp, nent); /* Allocate entries */
if (res == FR_OK && --nent) { /* Set LFN entry if needed */
res = dir_sdi(dp, dp->dptr - nent * SZDIRE);
n_ent = (sn[NSFLAG] & NS_LFN) ? (len + 12) / 13 + 1 : 1; /* Number of entries to allocate */
res = dir_alloc(dp, n_ent); /* Allocate entries */
if (res == FR_OK && --n_ent) { /* Set LFN entry if needed */
res = dir_sdi(dp, dp->dptr - n_ent * SZDIRE);
if (res == FR_OK) {
sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */
do { /* Store LFN entries in bottom first */
res = move_window(fs, dp->sect);
if (res != FR_OK) break;
put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum);
put_lfn(fs->lfnbuf, dp->dir, (BYTE)n_ent, sum);
fs->wflag = 1;
res = dir_next(dp, 0); /* Next entry */
} while (res == FR_OK && --nent);
} while (res == FR_OK && --n_ent);
}
}
@@ -2778,7 +2778,10 @@ static void get_fileinfo (
/* Pattern matching */
/*-----------------------------------------------------------------------*/
static DWORD get_achar ( /* Get a character and advances ptr */
#define FIND_RECURS 4 /* Maximum number of wildcard terms in the pattern to limit recursion */
static DWORD get_achar ( /* Get a character and advance ptr */
const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */
)
{
@@ -2809,41 +2812,43 @@ static DWORD get_achar ( /* Get a character and advances ptr */
}
static int pattern_matching ( /* 0:not matched, 1:matched */
static int pattern_match ( /* 0:mismatched, 1:matched */
const TCHAR* pat, /* Matching pattern */
const TCHAR* nam, /* String to be tested */
int skip, /* Number of pre-skip chars (number of ?s) */
int inf /* Infinite search (* specified) */
UINT skip, /* Number of pre-skip chars (number of ?s, b8:infinite (* specified)) */
UINT recur /* Recursion count */
)
{
const TCHAR *pp, *np;
DWORD pc, nc;
int nm, nx;
const TCHAR *pptr, *nptr;
DWORD pchr, nchr;
UINT sk;
while (skip--) { /* Pre-skip name chars */
while ((skip & 0xFF) != 0) { /* Pre-skip name chars */
if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */
skip--;
}
if (*pat == 0 && inf) return 1; /* (short circuit) */
if (*pat == 0 && skip) return 1; /* Matched? (short circuit) */
do {
pp = pat; np = nam; /* Top of pattern and name to match */
pptr = pat; nptr = nam; /* Top of pattern and name to match */
for (;;) {
if (*pp == '?' || *pp == '*') { /* Wildcard? */
nm = nx = 0;
do { /* Analyze the wildcard block */
if (*pp++ == '?') nm++; else nx = 1;
} while (*pp == '?' || *pp == '*');
if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */
nc = *np; break; /* Branch mismatched */
if (*pptr == '?' || *pptr == '*') { /* Wildcard term? */
if (recur == 0) return 0; /* Too many wildcard terms? */
sk = 0;
do { /* Analyze the wildcard term */
if (*pptr++ == '?') sk++; else sk |= 0x100;
} while (*pptr == '?' || *pptr == '*');
if (pattern_match(pptr, nptr, sk, recur - 1)) return 1; /* Test new branch (recursive call) */
nchr = *nptr; break; /* Branch mismatched */
}
pc = get_achar(&pp); /* Get a pattern char */
nc = get_achar(&np); /* Get a name char */
if (pc != nc) break; /* Branch mismatched? */
if (pc == 0) return 1; /* Branch matched? (matched at end of both strings) */
pchr = get_achar(&pptr); /* Get a pattern char */
nchr = get_achar(&nptr); /* Get a name char */
if (pchr != nchr) break; /* Branch mismatched? */
if (pchr == 0) return 1; /* Branch matched? (matched at end of both strings) */
}
get_achar(&nam); /* nam++ */
} while (inf && nc); /* Retry until end of name if infinite search is specified */
} while (skip && nchr); /* Retry until end of name if infinite search is specified */
return 0;
}
@@ -3290,23 +3295,37 @@ static DWORD make_rand (
/* Check what the sector is */
static UINT check_fs ( /* 0:FAT VBR, 1:exFAT VBR, 2:Valid BS but not FAT, 3:Invalid BS, 4:Disk error */
static UINT check_fs ( /* 0:FAT VBR, 1:exFAT VBR, 2:Not FAT and valid BS, 3:Not FAT and invalid BS, 4:Disk error */
FATFS* fs, /* Filesystem object */
LBA_t sect /* Sector to load and check if it is an FAT-VBR or not */
)
{
WORD w, sign;
BYTE b;
fs->wflag = 0; fs->winsect = (LBA_t)0 - 1; /* Invaidate window */
if (move_window(fs, sect) != FR_OK) return 4; /* Load the boot sector */
if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot signature (always here regardless of the sector size) */
if (FF_FS_EXFAT && !mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* Check if exFAT VBR */
if (fs->win[BS_JmpBoot] == 0xE9 || fs->win[BS_JmpBoot] == 0xEB || fs->win[BS_JmpBoot] == 0xE8) { /* Valid JumpBoot code? */
if (!mem_cmp(fs->win + BS_FilSysType, "FAT", 3)) return 0; /* Is it an FAT VBR? */
if (!mem_cmp(fs->win + BS_FilSysType32, "FAT32", 5)) return 0; /* Is it an FAT32 VBR? */
sign = ld_word(fs->win + BS_55AA);
#if FF_FS_EXFAT
if (sign == 0xAA55 && !mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* It is an exFAT VBR */
#endif
b = fs->win[BS_JmpBoot];
if (b == 0xEB || b == 0xE9 || b == 0xE8) { /* Valid JumpBoot code? (short jump, near jump or near call) */
if (sign == 0xAA55 && !mem_cmp(fs->win + BS_FilSysType32, "FAT32 ", 8)) return 0; /* It is an FAT32 VBR */
/* FAT volumes formatted with early MS-DOS lack boot signature and FAT string, so that we need to identify the FAT VBR without them. */
w = ld_word(fs->win + BPB_BytsPerSec);
if ((w & (w - 1)) == 0 && w >= FF_MIN_SS && w <= FF_MAX_SS) { /* Properness of sector size */
b = fs->win[BPB_SecPerClus];
if (b != 0 && (b & (b - 1)) == 0 /* Properness of cluster size */
&& (fs->win[BPB_NumFATs] == 1 || fs->win[BPB_NumFATs] == 2) /* Properness of number of FATs */
&& ld_word(fs->win + BPB_RootEntCnt) != 0 /* Properness of root entry count */
&& ld_word(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size */
return 0; /* Sector can be presumed an FAT VBR */
}
}
}
return 2; /* Valid BS but not FAT */
return sign == 0xAA55 ? 2 : 3; /* Not an FAT VBR (valid or invalid BS) */
}
@@ -3698,7 +3717,7 @@ FRESULT f_open (
DIR dj;
FATFS *fs;
#if !FF_FS_READONLY
DWORD cl, bcs, clst;
DWORD cl, bcs, clst, tm;
LBA_t sc;
FSIZE_t ofs;
#endif
@@ -3765,8 +3784,10 @@ FRESULT f_open (
#endif
{
/* Set directory entry initial state */
tm = GET_FATTIME(); /* Set created time */
st_dword(dj.dir + DIR_CrtTime, tm);
st_dword(dj.dir + DIR_ModTime, tm);
cl = ld_clust(fs, dj.dir); /* Get current cluster chain */
st_dword(dj.dir + DIR_CrtTime, GET_FATTIME()); /* Set created time */
dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */
st_clust(fs, dj.dir, 0); /* Reset file allocation info */
st_dword(dj.dir + DIR_FileSize, 0);
@@ -4705,9 +4726,9 @@ FRESULT f_findnext (
for (;;) {
res = f_readdir(dp, fno); /* Get a directory item */
if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */
if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for the file name */
if (pattern_match(dp->pat, fno->fname, 0, FIND_RECURS)) break; /* Test for the file name */
#if FF_USE_LFN && FF_USE_FIND == 2
if (pattern_matching(dp->pat, fno->altname, 0, 0)) break; /* Test for alternative name if exist */
if (pattern_match(dp->pat, fno->altname, 0, FIND_RECURS)) break; /* Test for alternative name if exist */
#endif
}
return res;
@@ -5376,10 +5397,12 @@ FRESULT f_getlabel (
if (res == FR_OK) {
switch (fs->fs_type) {
case FS_EXFAT:
di = BPB_VolIDEx; break;
di = BPB_VolIDEx;
break;
case FS_FAT32:
di = BS_VolID32; break;
di = BS_VolID32;
break;
default:
di = BS_VolID;
@@ -5677,7 +5700,7 @@ FRESULT f_forward (
#if !FF_FS_READONLY && FF_USE_MKFS
/*-----------------------------------------------------------------------*/
/* Create an FAT/exFAT volume */
/* Create FAT/exFAT volume */
/*-----------------------------------------------------------------------*/
#define N_SEC_TRACK 63 /* Sectors per track for determination of drive CHS */
@@ -5685,12 +5708,12 @@ FRESULT f_forward (
#define GPT_ITEMS 128 /* Number of GPT table size (>=128, sector aligned) */
/* Create partitions on the physical drive */
/* Create partitions on the physical drive in format of MBR or GPT */
static FRESULT create_partition (
BYTE drv, /* Physical drive number */
const LBA_t plst[], /* Partition list */
UINT sys, /* System ID (for only MBR, temp setting) and bit8:GPT */
BYTE sys, /* System ID (for only MBR, temp setting) */
BYTE* buf /* Working buffer for a sector */
)
{
@@ -5801,7 +5824,7 @@ static FRESULT create_partition (
st_dword(pte + PTE_StLba, s_lba32); /* Start LBA */
st_dword(pte + PTE_SizLba, n_lba32); /* Number of sectors */
pte[PTE_System] = (BYTE)sys; /* System type */
pte[PTE_System] = sys; /* System type */
cy = (UINT)(s_lba32 / n_sc / n_hd); /* Start cylinder */
hd = (BYTE)(s_lba32 / n_sc % n_hd); /* Start head */
@@ -5966,10 +5989,9 @@ FRESULT f_mkfs (
#if FF_FS_EXFAT
if (fsty == FS_EXFAT) { /* Create an exFAT volume */
DWORD szb_bit, szb_case, sum, nb, cl, tbl[3];
DWORD szb_bit, szb_case, sum, nbit, clu, clen[3];
WCHAR ch, si;
UINT j, st;
BYTE b;
if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume for exFAT? */
#if FF_USE_TRIM
@@ -5990,12 +6012,12 @@ FRESULT f_mkfs (
if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */
if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */
szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */
tbl[0] = (szb_bit + sz_au * ss - 1) / (sz_au * ss); /* Number of allocation bitmap clusters */
szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */
clen[0] = (szb_bit + sz_au * ss - 1) / (sz_au * ss); /* Number of allocation bitmap clusters */
/* Create a compressed up-case table */
sect = b_data + sz_au * tbl[0]; /* Table start sector */
sum = 0; /* Table checksum to be stored in the 82 entry */
sect = b_data + sz_au * clen[0]; /* Table start sector */
sum = 0; /* Table checksum to be stored in the 82 entry */
st = 0; si = 0; i = 0; j = 0; szb_case = 0;
do {
switch (st) {
@@ -6006,10 +6028,10 @@ FRESULT f_mkfs (
}
for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */
if (j >= 128) {
ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 */
ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 chars */
}
st = 1; /* Do not compress short run */
/* go to next case */
/* FALLTHROUGH */
case 1:
ch = si++; /* Fill the short run */
if (--j == 0) st = 0;
@@ -6028,16 +6050,15 @@ FRESULT f_mkfs (
sect += n; i = 0;
}
} while (si);
tbl[1] = (szb_case + sz_au * ss - 1) / (sz_au * ss); /* Number of up-case table clusters */
tbl[2] = 1; /* Number of root dir clusters */
clen[1] = (szb_case + sz_au * ss - 1) / (sz_au * ss); /* Number of up-case table clusters */
clen[2] = 1; /* Number of root dir clusters */
/* Initialize the allocation bitmap */
sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of sectors */
nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */
sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of bitmap sectors */
nbit = clen[0] + clen[1] + clen[2]; /* Number of clusters in-use by system (bitmap, up-case and root-dir) */
do {
mem_set(buf, 0, sz_buf * ss);
for (i = 0; nb >= 8 && i < sz_buf * ss; buf[i++] = 0xFF, nb -= 8) ;
for (b = 1; nb != 0 && i < sz_buf * ss; buf[i] |= b, b <<= 1, nb--) ;
mem_set(buf, 0, sz_buf * ss); /* Initialize bitmap buffer */
for (i = 0; nbit != 0 && i / 8 < sz_buf * ss; buf[i / 8] |= 1 << (i % 8), i++, nbit--) ; /* Mark used clusters */
n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */
if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
sect += n; nsect -= n;
@@ -6045,20 +6066,20 @@ FRESULT f_mkfs (
/* Initialize the FAT */
sect = b_fat; nsect = sz_fat; /* Start of FAT and number of FAT sectors */
j = nb = cl = 0;
j = nbit = clu = 0;
do {
mem_set(buf, 0, sz_buf * ss); i = 0; /* Clear work area and reset write index */
if (cl == 0) { /* Set FAT [0] and FAT[1] */
st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++;
st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++;
mem_set(buf, 0, sz_buf * ss); i = 0; /* Clear work area and reset write offset */
if (clu == 0) { /* Initialize FAT [0] and FAT[1] */
st_dword(buf + i, 0xFFFFFFF8); i += 4; clu++;
st_dword(buf + i, 0xFFFFFFFF); i += 4; clu++;
}
do { /* Create chains of bitmap, up-case and root dir */
while (nb != 0 && i < sz_buf * ss) { /* Create a chain */
st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF);
i += 4; cl++; nb--;
while (nbit != 0 && i < sz_buf * ss) { /* Create a chain */
st_dword(buf + i, (nbit > 1) ? clu + 1 : 0xFFFFFFFF);
i += 4; clu++; nbit--;
}
if (nb == 0 && j < 3) nb = tbl[j++]; /* Next chain */
} while (nb != 0 && i < sz_buf * ss);
if (nbit == 0 && j < 3) nbit = clen[j++]; /* Get next chain length */
} while (nbit != 0 && i < sz_buf * ss);
n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */
if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
sect += n; nsect -= n;
@@ -6072,13 +6093,13 @@ FRESULT f_mkfs (
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */
st_dword(buf + SZDIRE * 2 + 20, 2 + clen[0]); /* cluster */
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
sect = b_data + sz_au * (tbl[0] + tbl[1]); nsect = sz_au; /* Start of the root directory and number of sectors */
sect = b_data + sz_au * (clen[0] + clen[1]); nsect = sz_au; /* Start of the root directory and number of sectors */
do { /* Fill root directory sectors */
n = (nsect > sz_buf) ? sz_buf : nsect;
if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
mem_set(buf, 0, ss);
mem_set(buf, 0, ss); /* Rest of entries are filled with zero */
sect += n; nsect -= n;
} while (nsect);
@@ -6094,7 +6115,7 @@ FRESULT f_mkfs (
st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */
st_dword(buf + BPB_DataOfsEx, (DWORD)(b_data - b_vol)); /* Data offset [sector] */
st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */
st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */
st_dword(buf + BPB_RootClusEx, 2 + clen[0] + clen[1]); /* Root dir cluster # */
st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */
st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */
for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */
@@ -6520,7 +6541,7 @@ static void putc_bfd (putbuff* pb, TCHAR c)
WCHAR hs, wc;
#if FF_LFN_UNICODE == 2
DWORD dc;
TCHAR *tp;
const TCHAR *tp;
#endif
#endif
@@ -6562,7 +6583,7 @@ static void putc_bfd (putbuff* pb, TCHAR c)
return;
}
}
tp = (TCHAR*)pb->bs;
tp = (const TCHAR*)pb->bs;
dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */
if (dc == 0xFFFFFFFF) return; /* Wrong code? */
wc = (WCHAR)dc;
@@ -6650,7 +6671,7 @@ static int putc_flush (putbuff* pb)
if ( pb->idx >= 0 /* Flush buffered characters to the file */
&& f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK
&& (UINT)pb->idx == nw) return pb->nchr;
return EOF;
return -1;
}
@@ -6754,7 +6775,7 @@ int f_printf (
d = c;
if (IsLower(d)) d -= 0x20;
switch (d) { /* Atgument type is... */
case 'S' : /* String */
case 'S': /* String */
p = va_arg(arp, TCHAR*);
for (j = 0; p[j]; j++) ;
if (!(f & 2)) { /* Right padded */
@@ -6764,21 +6785,26 @@ int f_printf (
while (j++ < w) putc_bfd(&pb, ' ') ; /* Left padded */
continue;
case 'C' : /* Character */
putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue;
case 'C': /* Character */
putc_bfd(&pb, (TCHAR)va_arg(arp, int));
continue;
case 'B' : /* Unsigned binary */
r = 2; break;
case 'B': /* Unsigned binary */
r = 2;
break;
case 'O' : /* Unsigned octal */
r = 8; break;
case 'O': /* Unsigned octal */
r = 8;
break;
case 'D' : /* Signed decimal */
case 'U' : /* Unsigned decimal */
r = 10; break;
case 'D': /* Signed decimal */
case 'U': /* Unsigned decimal */
r = 10;
break;
case 'X' : /* Unsigned hexdecimal */
r = 16; break;
case 'X': /* Unsigned hexdecimal */
r = 16;
break;
default: /* Unknown type (pass-through) */
putc_bfd(&pb, c); continue;

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.14 /
/ FatFs - Generic FAT Filesystem module R0.14a /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2019, ChaN, all right reserved.
/ Copyright (C) 2020, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
@@ -20,7 +20,7 @@
#ifndef FF_DEFINED
#define FF_DEFINED 86606 /* Revision ID */
#define FF_DEFINED 80196 /* Revision ID */
#ifdef __cplusplus
extern "C" {
@@ -345,10 +345,6 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
#endif

View File

@@ -2,7 +2,7 @@
/ FatFs Functional Configurations
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 86606 /* Revision ID */
#define FFCONF_DEF 80196 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
@@ -205,8 +205,8 @@
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
#define FF_MIN_GPT 0x100000000
/* Minimum number of sectors to switch GPT format to create partition in f_mkfs and
#define FF_MIN_GPT 0x10000000
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
@@ -237,7 +237,7 @@
#define FF_FS_NORTC 0
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2019
#define FF_NORTC_YEAR 2020
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp

View File

@@ -22,6 +22,7 @@
#define __CONFIG_PARSER_TEMP_PROFILE_PARSER_H__
#include <stdint.h>
#include <linklist-lib/singly-linked-list.h>
enum pl_command_type {
PL_PID_CONF = 0,
@@ -49,9 +50,33 @@ struct pl_command {
float params[PROFILE_LANG_MAX_NUM_ARGS];
};
/**
* @brief Parse a temperature profile from file and generate the command list
*
* Commands are parsed into the list given by \p command_list. If \p max_len is reached,
* the function returns with @ref PL_RET_LIST_FULL
*
* In any case, the command list not cleared afterwards. The user has to clear the command list manually
* using @ref temp_profile_free_command_list.
*
* @param filename File to parse
* @param[in, out] command_list Command list to output @ref pl_command elements in.
* @param max_len maximum number of commands.
* @param cmds_parsed Number of parsed commands
* @return
*/
enum pl_ret_val temp_profile_parse_from_file(const char *filename,
struct pl_command *cmd_list,
uint32_t cmd_list_length,
SlList **command_list,
uint32_t max_len,
uint32_t *cmds_parsed);
/**
* @brief Fully free a comamnd list including hte sotred command structures.
*
* \p list's destination is set to NULL to indicate the empty list.
*
* @param[in, out] list Pointer to list.
*/
void temp_profile_free_command_list(SlList **list);
#endif /* __CONFIG_PARSER_TEMP_PROFILE_PARSER_H__ */

View File

@@ -47,6 +47,8 @@
#define SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT 32UL
#define SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE 256U
/**
* @brief Safety memory header
*/
@@ -55,6 +57,7 @@ struct safety_memory_header {
uint32_t boot_status_offset; /**< @brief Offset of the safety_memory_boot_status struct (in 32 bit words)*/
uint32_t config_overrides_offset; /**< @brief Offset address of override entries */
uint32_t config_overrides_len; /**< @brief Length of override entries in words */
uint32_t firmware_update_filename; /**< @brief Filename of the firmware update. This string is at maximum 256 bytes long including the 0 terminator */
uint32_t err_memory_offset; /**< @brief Offset of the error memory */
uint32_t err_memory_end; /**< @brief End of the error memory. This points to the word after the error memory, containing the CRC of the whole backup RAM. */
uint32_t crc; /**< @brief CRC of the header */
@@ -240,13 +243,35 @@ int safety_memory_insert_config_override(struct config_override *config_override
int safety_memory_get_config_override_count(uint32_t *count);
/**
* @brief Get a config ovveide entry
* @brief Get a config entry
* @param idx Index of the requested entry
* @param[out] config_override READ override
* @return 0 if successful
*/
int safety_memory_get_config_override(uint32_t idx, struct config_override *config_override);
/**
* @brief Read the set update filename from the safety backup memory
*
* \p filename has to be large enough to hold the filename (255 chars) plus the '\0'-terminator.
*
* @param[out] filename Array to fill in file name. May be NULL to only read the length.
* @param[out] outlen String length of the filename. May be NULL to only read the file name.
* @note \p filename may be NULL. In this case this function can be used to read the currently set filename's length.
* @warning Function will fail if both parameters are NULL
* @return 0 if successful
*/
int safety_memory_get_update_filename(char *filename, size_t *outlen);
/**
* @brief Set the filename of the update file
* @param[in] filename Filename to set. Must be 255 chars at max (256 including null terminator)
* @return 0 if successful
*/
int safety_memory_set_update_filename(const char *filename);
#ifndef SAFETY_MEMORY_STRIPOUT_DUMP
/**
* @brief Get a base64 dump of the whole safety memory.
* @param[out] buffer Buffer to write the base 64 dump into.
@@ -256,6 +281,8 @@ int safety_memory_get_config_override(uint32_t idx, struct config_override *conf
*/
int safety_memory_dump_base64(char *buffer, size_t buffsize, size_t *used_size);
#endif /* SAFETY_MEMORY_STRIPOUT_DUMP */
#endif /* __SAFETY_MEMORY_H__ */
/** @} */

View File

@@ -24,7 +24,7 @@
#include <stdint.h>
#include <reflow-controller/config-parser/temp-profile-parser.h>
#define MAX_PROFILE_LENGTH 50
#define MAX_PROFILE_LENGTH 64
enum tpe_status {
TPE_OFF,

View File

@@ -25,7 +25,14 @@
/**
* @brief Start the RAM Code of the updater. This function will never return!
*
* This function is called at startup when the controller detects, that an update should
* be performed.
*
* @note You prabably want to call @ref start_updater function to update.
*/
void __attribute__((noreturn)) start_updater(void);
void __attribute__((noreturn)) start_updater_ram_code(void);
void __attribute__((noreturn)) updater_update_from_file(const char *filename);
#endif /* __UPDATER_UPDATER_H__ */

View File

@@ -37,7 +37,7 @@
#include <stm-periph/stm32-gpio-macros.h>
#include <stm-periph/rcc-manager.h>
#include <stm-periph/uart.h>
#include <reflow-controller/shell-uart-config.h>
#include <reflow-controller/periph-config/shell-uart-config.h>
#include <reflow-controller/oven-driver.h>
#include <fatfs/ff.h>
#include <reflow-controller/ui/gui.h>
@@ -162,7 +162,12 @@ static inline void handle_boot_status(void)
led_set(0, 1);
led_set(1, 1);
start_updater();
start_updater_ram_code();
}
if (status.code_updated) {
status.code_updated = 0x0UL;
safety_memory_set_boot_status(&status);
}
}

View File

@@ -22,7 +22,11 @@
#include <helper-macros/helper-macros.h>
#include <stm-periph/crc-unit.h>
#include <stm-periph/backup-ram.h>
#include <string.h>
#ifndef SAFETY_MEMORY_STRIPOUT_DUMP
#include <base64-lib/base64-lib.h>
#endif /* SAFETY_MEMORY_STRIPOUT_DUMP */
static int word_to_error_memory_entry(uint32_t entry_data, struct error_memory_entry *out)
{
@@ -99,7 +103,9 @@ static enum safety_memory_state safety_memory_get_header(struct safety_memory_he
res++;
if (header->config_overrides_len > SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT)
res++;
if (header->err_memory_offset < header->config_overrides_offset + header->config_overrides_len)
if (header->firmware_update_filename < header->config_overrides_offset + header->config_overrides_len)
res++;
if (header->err_memory_offset < header->firmware_update_filename + (SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE / 4))
res++;
if (header->err_memory_end >= backup_ram_get_size_in_words() || header->err_memory_end < header->err_memory_offset)
res++;
@@ -133,7 +139,8 @@ static void safety_memory_write_new_header(void)
header.boot_status_offset = wordsize_of(struct safety_memory_header);
header.config_overrides_len = SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT;
header.config_overrides_offset = header.boot_status_offset + wordsize_of(struct safety_memory_boot_status);
header.err_memory_offset = header.config_overrides_offset + SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT;
header.firmware_update_filename = header.config_overrides_offset + SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT;
header.err_memory_offset = header.firmware_update_filename + (SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE / 4);
header.err_memory_end = header.err_memory_offset;
header.magic = SAFETY_MEMORY_MAGIC;
@@ -608,6 +615,8 @@ int safety_memory_get_config_override(uint32_t idx, struct config_override *conf
return 0;
}
#ifndef SAFETY_MEMORY_STRIPOUT_DUMP
int safety_memory_dump_base64(char *buffer, size_t buffsize, size_t *used_size)
{
uint32_t safety_mem_size;
@@ -633,3 +642,66 @@ int safety_memory_dump_base64(char *buffer, size_t buffsize, size_t *used_size)
*used_size = output_size + 1u;
return 0;
}
#endif /* SAFETY_MEMORY_STRIPOUT_DUMP */
int safety_memory_get_update_filename(char *filename, size_t *outlen)
{
struct safety_memory_header header;
unsigned int i;
volatile char *ptr;
size_t len = 0u;
/* If filename and outlen are both NULL, we don't do anything */
if (!filename && !outlen)
return -1;
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
return -2000;
/* Get the filename */
ptr = (volatile char *)backup_ram_get_base_ptr();
ptr += (unsigned int)(header.firmware_update_filename * 4);
for (i = 0; i < SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE; i++) {
if (filename)
filename[i] = *ptr;
if (*ptr)
len++;
else
break;
ptr++;
}
if (outlen)
*outlen = len;
return 0;
}
int safety_memory_set_update_filename(const char *filename)
{
int ret = 0;
size_t len;
unsigned int i;
struct safety_memory_header header;
volatile char *ram_ptr;
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
return -2000;
if (!filename)
return -1001;
len = strnlen(filename, SAFETY_MEMORY_UPDATE_FILENAME_MAXSIZE - 1);
ram_ptr = backup_ram_get_base_ptr();
ram_ptr += header.firmware_update_filename * 4;
for (i = 0u; i < len; i++) {
ram_ptr[i] = filename[i];
}
ram_ptr[i] = 0;
ret = safety_memory_gen_crc();
return ret;
}

View File

@@ -42,6 +42,7 @@
#include <reflow-controller/safety/safety-memory.h>
#include <reflow-controller/hw-version-detect.h>
#include <reflow-controller/temp-profile-executer.h>
#include <reflow-controller/updater/updater.h>
#ifndef GIT_VER
#define GIT_VER "VERSION NOT SET"
@@ -52,28 +53,6 @@ static shellmatta_instance_t shell;
static char shell_buffer[512];
static char IN_SECTION(.ccm.bss) history_buffer[512];
static bool check_opt(const char *args, uint32_t len, const char *opt_to_check)
{
(void)len;
char str[128];
const char *ptr;
static const char * const tokens = "\t ";
strncpy(str, args, sizeof(str));
str[sizeof(str) - 1] = 0;
/* Tokenize the string */
ptr = strtok(str, tokens);
while (ptr) {
if (strcmp(ptr, opt_to_check) == 0)
return true;
ptr = strtok(NULL, tokens);
}
return false;
}
static shellmatta_retCode_t shell_cmd_ver(const shellmatta_handle_t handle,
const char *arguments,
uint32_t length)
@@ -182,7 +161,7 @@ static shellmatta_retCode_t shell_cmd_pt1000_res(const shellmatta_handle_t han
pt1000_status = adc_pt1000_get_current_resistance(&resistance);
if (pt1000_status == 2) {
strcat(display_status, " UNSTABLE ");
strcat(display_status, "UNSTABLE");
} else if (pt1000_status) {
strcpy(display_status, "ERROR");
} else {
@@ -344,14 +323,36 @@ static shellmatta_retCode_t shell_cmd_read_flags(const shellmatta_handle_t handl
uint32_t i;
char name[64];
bool flag;
bool tryack;
bool tryack = false;
int status;
enum safety_flag flag_enum;
struct analog_monitor_info amon_info;
struct timing_monitor_info timing_info;
char *argument;
uint32_t len;
char option;
shellmatta_retCode_t opt_ret;
static const shellmatta_opt_long_t options[] = {
{"ack", 'a', SHELLMATTA_OPT_ARG_NONE},
{NULL, '\0', SHELLMATTA_OPT_ARG_NONE}
};
do {
opt_ret = shellmatta_opt_long(handle, options, &option, &argument, &len);
if (opt_ret != SHELLMATTA_OK) {
break;
}
switch (option) {
case 'a':
tryack = true;
break;
default:
break;
}
} while(1);
/* Check for the --ack option */
tryack = check_opt(arguments, length, "--ack");
shellmatta_printf(handle, "Error Flags\r\n"
"-----------\r\n");
@@ -631,13 +632,35 @@ shellmatta_retCode_t shell_cmd_update(const shellmatta_handle_t handle, const ch
(void)handle;
(void)arguments;
(void)length;
struct safety_memory_boot_status status;
shellmatta_retCode_t opt_stat;
char option;
char *argument;
uint32_t arg_len;
const char *update_file = NULL;
safety_memory_get_boot_status(&status);
status.reboot_to_bootloader = 0xFFFFFFFFUL;
safety_memory_set_boot_status(&status);
const shellmatta_opt_long_t options[] = {
{NULL, '\0', SHELLMATTA_OPT_ARG_NONE},
};
NVIC_SystemReset();
while (1) {
opt_stat = shellmatta_opt_long(handle, options, &option, &argument, &arg_len);
if (opt_stat != SHELLMATTA_OK)
break;
switch (option) {
case '\0':
update_file = argument;
break;
default:
break;
}
}
if (!update_file || !strlen(update_file)) {
shellmatta_printf(handle, "Please specify a valid update file!\r\n");
return SHELLMATTA_ERROR;
}
updater_update_from_file(update_file);
return SHELLMATTA_OK;
}
@@ -876,7 +899,7 @@ static shellmatta_cmd_t cmd[21] = {
{
.cmd = "save-calibration",
.cmdAlias = "save-cal",
.helpText = "",
.helpText = "Permanently save the calibration to EEPROM",
.usageText = "",
.cmdFct = shell_cmd_save_cal,
.next = &cmd[13],
@@ -924,8 +947,8 @@ static shellmatta_cmd_t cmd[21] = {
{
.cmd = "update",
.cmdAlias = NULL,
.helpText = "Update Firmware",
.usageText = "",
.helpText = "Update Firmware from HEX file",
.usageText = "update </path/to/update.hex>",
.cmdFct = shell_cmd_update,
.next = &cmd[19],

View File

@@ -18,13 +18,13 @@
* --------------------------------------------------------------------
* FLASH: 512K
* RAM: 128K
* CCM RAM: 64L
* CCM RAM: 64K
* FPU: fpv4-sp-d16
*/
/* USER PARAMETERS */
__ld_stack_size = 0x3000;
__ld_heap_size = 0x4200;
__ld_stack_size = 0x3500;
__ld_heap_size = 0x5000;
__stack_corruption_area_size = 128;
/* END OF USER PARAMETERS */

View File

@@ -34,7 +34,7 @@ static bool IN_SECTION(.ccm.bss) pid_should_run;
struct pid_controller IN_SECTION(.ccm.bss) pid;
bool IN_SECTION(.ccm.bss) cmd_continue;
static struct pl_command IN_SECTION(.ccm.bss) cmd_list[MAX_PROFILE_LENGTH];
static SlList *command_list = NULL;
static void tpe_abort(void)
{
@@ -59,11 +59,19 @@ enum pl_ret_val temp_profile_executer_start(const char *filename)
state.profile_steps = 0;
cmd_continue = false;
res = temp_profile_parse_from_file(filename, cmd_list, MAX_PROFILE_LENGTH, &parsed_count);
/* This should never happen... But who knows */
if (command_list) {
temp_profile_free_command_list(&command_list);
}
res = temp_profile_parse_from_file(filename, &command_list, MAX_PROFILE_LENGTH, &parsed_count);
if (res == PL_RET_SUCCESS) {
state.profile_steps = parsed_count;
state.status = TPE_RUNNING;
state.start_timestamp = systick_get_global_tick();
} else {
if (command_list)
temp_profile_free_command_list(&command_list);
}
return res;
@@ -177,7 +185,7 @@ int temp_profile_executer_handle(void)
if (!systick_ticks_have_passed(last_tick, 100))
return 0;
current_cmd = &cmd_list[state.step];
current_cmd = (struct pl_command *)sl_list_nth(command_list, state.step)->data;
next_step = state.step;
switch (current_cmd->cmd) {
@@ -250,6 +258,10 @@ int temp_profile_executer_stop(void)
oven_pid_stop();
}
/* Free the command list */
if (command_list)
temp_profile_free_command_list(&command_list);
loudspeaker_set(0);
return 0;

View File

@@ -28,6 +28,7 @@
#include <reflow-controller/safety/safety-controller.h>
#include <reflow-controller/settings/settings.h>
#include <reflow-controller/temp-converter.h>
#include <reflow-controller/updater/updater.h>
#include <helper-macros/helper-macros.h>
#include <stm-periph/unique-id.h>
#include <stddef.h>
@@ -38,6 +39,8 @@
#include <reflow-controller/oven-driver.h>
#include <fatfs/ff.h>
#include <reflow-controller/temp-profile-executer.h>
#include <linklist-lib/singly-linked-list.h>
#include <stdlib.h>
static char IN_SECTION(.ccm.bss) display_buffer[4][21] = {0};
static struct lcd_menu IN_SECTION(.ccm.bss) reflow_menu;
@@ -374,43 +377,38 @@ static void gui_menu_constant_temperature_driver(struct lcd_menu *menu, enum men
}
/**
* @brief load_temperature_file_list_from_sdcard
* @return -1 File error, 0 successful
*/
static int load_temperature_file_list_from_sdcard(char (*list)[17], uint32_t len)
static void delete_file_list_entry(void *obj)
{
if (obj)
free(obj);
}
static SlList *load_file_list_from_sdcard(int *error, const char *file_pattern)
{
uint32_t i, j;
DIR directory;
FILINFO finfo;
FRESULT fres;
if (!list)
return -1001;
/* Zero out the list */
for (i = 0; i < len; i++) {
for (j = 0; j < sizeof(*list); j++) {
list[i][j] = 0;
}
}
SlList *list = NULL;
char *name;
/* find the frist file */
fres = f_findfirst(&directory, &finfo, "/", "*.tpr");
i = 0;
fres = f_findfirst(&directory, &finfo, "/", file_pattern);
while (fres == FR_OK && finfo.fname[0]) {
strncpy(list[i], finfo.fname, sizeof(*list));
name = malloc(strlen(finfo.fname) + 1);
strcpy(name, finfo.fname);
list = sl_list_append(list, name);
fres = f_findnext(&directory, &finfo);
i++;
if (i >= len)
break;
}
if (fres != FR_OK) {
return -1;
sl_list_free_full(list, delete_file_list_entry);
list = NULL;
if (error)
*error = -1;
}
return (int)i;
return list;
}
static void gui_menu_temp_profile_execute(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void* parent)
@@ -428,23 +426,32 @@ static void gui_menu_temp_profile_execute(struct lcd_menu *menu, enum menu_entry
last_tick = 0ULL;
}
if (systick_ticks_have_passed(last_tick, 300)) {
if (systick_ticks_have_passed(last_tick, 250)) {
state = temp_profile_executer_status();
if (state->status == TPE_RUNNING)
menu_lcd_outputf(menu, 0, "Profile running");
else if (state->status == TPE_OFF) {
menu_lcd_outputf(menu, 0, "Profile finished");
if (state->status == TPE_RUNNING) {
menu_lcd_outputf(menu, 0, "Executing...");
menu_lcd_outputf(menu, 1, "Step %u/%u", state->step, state->profile_steps);
(void)adc_pt1000_get_current_resistance(&resistance);
res = temp_converter_convert_resistance_to_temp(resistance, &temperature);
menu_lcd_outputf(menu, 2, "Temp: %s%.1f " LCD_DEGREE_SYMBOL_STRING "C",
(res < 0 ? "<" : (res > 0 ? ">" : "")), temperature);
if (oven_pid_get_status() == OVEN_PID_RUNNING) {
menu_lcd_outputf(menu, 3, "Target: %.0f " LCD_DEGREE_SYMBOL_STRING "C", state->setpoint);
} else {
menu_lcd_outputf(menu, 3, "Temp Off");
}
} else if (state->status == TPE_OFF) {
menu_lcd_outputf(menu, 0, "Finished!");
menu_lcd_outputf(menu, 1, "Press button");
menu_lcd_outputf(menu, 2, "to return.");
(void)adc_pt1000_get_current_resistance(&resistance);
res = temp_converter_convert_resistance_to_temp(resistance, &temperature);
menu_lcd_outputf(menu, 3, "Temp: %.1f ", LCD_DEGREE_SYMBOL_STRING "C", temperature);
} else {
menu_lcd_outputf(menu, 0, "Profile aborted!");
}
menu_lcd_outputf(menu, 1, "Step %u/%u", state->step, state->profile_steps);
(void)adc_pt1000_get_current_resistance(&resistance);
res = temp_converter_convert_resistance_to_temp(resistance, &temperature);
menu_lcd_outputf(menu, 2, "Temp: %s%.0f", (res < 0 ? "<" : (res > 0 ? ">" : "")), temperature);
if (oven_pid_get_status() == OVEN_PID_RUNNING) {
menu_lcd_outputf(menu, 3, "Target: %.0f", state->setpoint);
} else {
menu_lcd_outputf(menu, 3, "Temp Off");
menu_lcd_outputf(menu, 1, "Check flags!");
menu_lcd_outputf(menu, 2, "");
menu_lcd_outputf(menu, 3, "Press button");
}
last_tick = systick_get_global_tick();
@@ -461,29 +468,29 @@ static void gui_menu_temp_profile_execute(struct lcd_menu *menu, enum menu_entry
static void gui_menu_temp_profile_select(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
{
static void *my_parent;
static char profile_list[10][17];
static bool file_error = false;
static SlList *file_list = NULL;
static int file_error = 0;
static enum pl_ret_val profile_ret_val = PL_RET_SUCCESS;
static uint8_t currently_selected = 0U;
static uint8_t loaded;
int16_t delta;
enum button_state button;
int res;
if (entry_type == MENU_ENTRY_FIRST_ENTER) {
menu_display_clear(menu);
my_parent = parent;
res = load_temperature_file_list_from_sdcard(profile_list, 10);
file_error = false;
file_error = 0;
loaded = 0;
if (res < 0) {
file_error = true;
if (file_list) {
sl_list_free_full(file_list, delete_file_list_entry);
}
file_list = load_file_list_from_sdcard(&file_error, "*.tpr");
currently_selected = 0u;
profile_ret_val = PL_RET_SUCCESS;
loaded = (uint32_t)res;
loaded = sl_list_length(file_list);
menu_lcd_outputf(menu, 0, "Select:");
} else if (entry_type == MENU_ENTRY_DROPBACK) {
menu_entry_dropback(menu, my_parent);
@@ -501,14 +508,20 @@ static void gui_menu_temp_profile_select(struct lcd_menu *menu, enum menu_entry_
if (file_error) {
menu_lcd_outputf(menu, 0, "Disk Error");
menu_lcd_outputf(menu, 1, "SD inserted?");
if (button == BUTTON_SHORT_RELEASED)
if (button == BUTTON_SHORT_RELEASED) {
sl_list_free_full(file_list, delete_file_list_entry);
file_list = NULL;
menu_entry_dropback(menu, my_parent);
}
return;
} else if (loaded == 0) {
menu_lcd_outputf(menu, 0, "No profiles");
menu_lcd_outputf(menu, 1, "found");
if (button == BUTTON_SHORT_RELEASED)
if (button == BUTTON_SHORT_RELEASED) {
sl_list_free_full(file_list, delete_file_list_entry);
file_list = NULL;
menu_entry_dropback(menu, my_parent);
}
return;
} else if (profile_ret_val != PL_RET_SUCCESS) {
menu_lcd_outputf(menu, 0, "ERROR");
@@ -528,17 +541,22 @@ static void gui_menu_temp_profile_select(struct lcd_menu *menu, enum menu_entry_
break;
}
if (button == BUTTON_SHORT_RELEASED)
if (button == BUTTON_SHORT_RELEASED) {
sl_list_free_full(file_list, delete_file_list_entry);
file_list = NULL;
menu_entry_dropback(menu, my_parent);
}
return;
} else if (currently_selected < loaded) {
/* Show currently selected profile */
menu_lcd_outputf(menu, 1, "%s", &profile_list[currently_selected][0]);
menu_lcd_outputf(menu, 1, "%s", sl_list_nth(file_list, currently_selected)->data);
if (button == BUTTON_SHORT_RELEASED) {
/* Execute selected profile */
profile_ret_val = temp_profile_executer_start(&profile_list[currently_selected][0]);
profile_ret_val = temp_profile_executer_start(sl_list_nth(file_list, currently_selected)->data);
if (profile_ret_val == PL_RET_SUCCESS) {
sl_list_free_full(file_list, delete_file_list_entry);
file_list = NULL;
menu_entry_enter(menu, gui_menu_temp_profile_execute, true);
return;
}
@@ -590,6 +608,84 @@ static void gui_menu_constant_temperature_driver_setup(struct lcd_menu *menu, en
}
}
static void gui_update_firmware(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
{
static void *my_parent;
static SlList *file_list = NULL;
static int error;
enum button_state button;
static uint32_t currently_selected_file;
uint32_t previously_selected_file;
static uint32_t list_length;
const char *fname;
int16_t rotary;
if (entry_type == MENU_ENTRY_FIRST_ENTER) {
my_parent = parent;
error = 0;
list_length = 0;
if (file_list)
sl_list_free_full(file_list, delete_file_list_entry);
file_list = load_file_list_from_sdcard(&error, "*.hex");
if (error) {
if (file_list)
sl_list_free_full(file_list, delete_file_list_entry);
file_list = NULL;
} else {
list_length = sl_list_length(file_list);
}
currently_selected_file = 0;
menu_display_clear(menu);
}
if (menu_get_button_ready_state(menu)) {
button = menu_get_button_state(menu);
rotary = menu_get_rotary_delta(menu);
if (error) {
menu_lcd_output(menu, 0, "Error reading");
menu_lcd_output(menu, 1, "file list");
if (button == BUTTON_LONG || button == BUTTON_SHORT_RELEASED)
menu_entry_dropback(menu, my_parent);
} else {
previously_selected_file = currently_selected_file;
/* Display the list */
if (rotary <= -4) {
menu_ack_rotary_delta(menu);
if (currently_selected_file > 0) {
currently_selected_file--;
}
} else if (rotary >= 4) {
menu_ack_rotary_delta(menu);
if (currently_selected_file < (list_length - 1)) {
currently_selected_file++;
}
}
if (entry_type == MENU_ENTRY_FIRST_ENTER ||
previously_selected_file != currently_selected_file) {
fname = sl_list_nth(file_list, currently_selected_file)->data;
menu_lcd_output(menu, 0, "Select File:");
if (fname)
menu_lcd_output(menu, 1, fname);
}
if (button == BUTTON_SHORT_RELEASED) {
fname = sl_list_nth(file_list, currently_selected_file)->data;
menu_display_clear(menu);
sl_list_free_full(file_list, delete_file_list_entry);
file_list = NULL;
updater_update_from_file(fname);
} else if (button == BUTTON_LONG) {
sl_list_free_full(file_list, delete_file_list_entry);
file_list = NULL;
menu_entry_dropback(menu, my_parent);
}
}
}
}
static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
{
(void)parent;
@@ -601,6 +697,7 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
"Monitoring",
"Error Flags",
"About",
"Update",
NULL
};
static const menu_func_t root_entry_funcs[] = {
@@ -609,6 +706,7 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
gui_menu_monitor,
gui_menu_err_flags,
gui_menu_about,
gui_update_firmware,
};
enum button_state push_button;
int16_t rot_delta;
@@ -630,19 +728,21 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
push_button = menu_get_button_state(menu);
rot_delta = menu_get_rotary_delta(menu);
if (menu_get_button_ready_state(menu) && push_button == BUTTON_SHORT_RELEASED) {
/* Enter currently selected menu_entry */
menu_list_enter_selected_entry(&list, menu);
}
if (menu_get_button_ready_state(menu)) {
if (menu_get_button_ready_state(menu) && push_button == BUTTON_SHORT_RELEASED) {
/* Enter currently selected menu_entry */
menu_list_enter_selected_entry(&list, menu);
}
if (rot_delta >= 4) {
menu_list_scroll_down(&list);
menu_ack_rotary_delta(menu);
menu_changed = true;
} else if (rot_delta <= -4) {
menu_list_scroll_up(&list);
menu_ack_rotary_delta(menu);
menu_changed = true;
if (rot_delta >= 4) {
menu_list_scroll_down(&list);
menu_ack_rotary_delta(menu);
menu_changed = true;
} else if (rot_delta <= -4) {
menu_list_scroll_up(&list);
menu_ack_rotary_delta(menu);
menu_changed = true;
}
}
if (menu_changed)

View File

@@ -39,7 +39,8 @@ void menu_handle(struct lcd_menu *menu, int16_t rotary_encoder_delta, enum butto
tmp = menu->active_entry;
if (menu->active_entry_type == MENU_ENTRY_FIRST_ENTER && push_button != BUTTON_IDLE) {
if ((menu->active_entry_type == MENU_ENTRY_FIRST_ENTER || menu->active_entry_type == MENU_ENTRY_DROPBACK)
&& push_button != BUTTON_IDLE) {
menu->inputs.button_ready = false;
}

View File

@@ -13,13 +13,15 @@ set(ELFFILE "${PROJECT_NAME}.elf")
aux_source_directory("." SRCS)
aux_source_directory("fatfs" FATFS_SRCS)
aux_source_directory("fatfs/shimatta_sdio_driver" SDIO_SRCS)
set(STM_PERIPH_SRCS "../../stm-periph/backup-ram.c" "../../stm-periph/rcc-manager.c" "../../stm-periph/crc-unit.c")
set(SAFETY_MEMORY_SRCS "../../safety/safety-memory.c")
add_executable(${ELFFILE} ${SRCS} ${FATFS_SRCS} ${SDIO_SRCS})
add_executable(${ELFFILE} ${SRCS} ${FATFS_SRCS} ${SDIO_SRCS} ${STM_PERIPH_SRCS} ${SAFETY_MEMORY_SRCS})
target_include_directories(${ELFFILE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
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_definitions(${ELFFILE} PRIVATE -DBASE64_LOOKUP_TABLE_SECTION=\".ccm.bss\" -DSHELLMATTA_HELP_ALIAS=\"?\" -DGIT_VER=${GIT_DESCRIBE} -DHSE_VALUE=8000000UL -DSTM32F407xx -DSTM32F4XX -DARM_MATH_CM4)
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")
set(GEN_HEADER_FILE "${GEN_HEADER_PATH}/${PROJECT_NAME}.bin.h")

View File

@@ -0,0 +1,134 @@
#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 uint16_t *flash_size_ptr = (const uint16_t *)0x1FFF7A22UL;
flash_size = (uint32_t)*flash_size_ptr;
flash_size *= 1024;
return flash_size;
}
int flash_writer_write_to_memory(void *dest, const void *src, uint32_t size)
{
uint32_t full_word_cnt;
uint32_t byte_cnt;
uint32_t idx;
const uint32_t *word_src_ptr;
uint32_t *word_dest_ptr;
const char *char_src_ptr;
char *char_dest_ptr;
uint32_t pre_byte_count;
flash_writer_enable_access();
while (flash_op_busy());
/* Number of full words to program */
full_word_cnt = size / 4u;
byte_cnt = size % 4;
word_dest_ptr = dest;
word_src_ptr = src;
/* Do the first bytes, in case the destination is not word aligned */
pre_byte_count = (4 - ((uint32_t)dest % 4u)) % 4;
if (pre_byte_count) {
FLASH->CR = 0u;
FLASH->CR |= FLASH_CR_PG;
char_src_ptr = src;
char_dest_ptr = dest;
/* Write bytes to memory until we hit the next word aligned address */
for (idx = 0; idx < pre_byte_count; idx++) {
*(char_dest_ptr++) = *(char_src_ptr++);
}
/* Correct the word addresses set above */
full_word_cnt = (size - pre_byte_count) / 4u;
byte_cnt = (size - pre_byte_count) % 4;
word_dest_ptr = (uint32_t *)char_dest_ptr;
word_src_ptr = (uint32_t *)char_src_ptr;
while(flash_op_busy());
FLASH->CR = 0u;
}
/* Do the full word flash write */
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 = 0u;
}
/* write remaining bytes */
if (byte_cnt) {
char_src_ptr = (char *)word_src_ptr;
char_dest_ptr = (char *)word_dest_ptr;
FLASH->CR = 0u;
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 = 0u;
}
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, const 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

@@ -0,0 +1,53 @@
#include "itoa.h"
/*
* The heapless_itoa function is copied from the shellmatta project.
*/
/**
* @brief itoa like function to convert int to an ascii string
* @warning you have to provide a large enough buffer
* @param[in] value
* @param[in,out] buffer
* @param[in] base
* @return number of bytes in string
*/
uint32_t heapless_itoa(int32_t value, char *buffer, uint32_t base)
{
char tempBuffer[34u];
uint32_t i;
uint32_t bufferIdx = 0u;
int8_t digitValue;
/** -# check the base for plausibility */
if((base >= 2) && (base <= 16))
{
/** -# check for sign */
if(value < 0)
{
value = value * (-1);
buffer[0u] = '-';
bufferIdx += 1u;
}
/** -# loop through all digits in reverse order */
i = 0u;
do
{
digitValue = (int8_t) (value % base);
tempBuffer[i] = (digitValue < 10) ? ('0' + digitValue) : ('A' + (digitValue - 10));
value /= base;
i ++;
}while(value > 0);
/** -# store the string in the correct order onto the buffer */
while(i > 0u)
{
buffer[bufferIdx] = tempBuffer[i - 1u];
i --;
bufferIdx ++;
}
}
return bufferIdx;
}

View File

@@ -0,0 +1,8 @@
#ifndef _ITOA_H_
#define _ITOA_H_
#include <stdint.h>
uint32_t heapless_itoa(int32_t value, char *buffer, uint32_t base);
#endif /* _ITOA_H_ */

View File

@@ -3,7 +3,19 @@
#include <cmsis/core_cm4.h>
#include "hex-parser.h"
#include <fatfs/ff.h>
/* This is used to get the defines for the external watchdog */
#include <reflow-controller/safety/safety-config.h>
#include <helper-macros/helper-macros.h>
#include <stm-periph/stm32-gpio-macros.h>
#include <reflow-controller/safety/safety-memory.h>
#include "flash-writer.h"
#include <stdbool.h>
#include <string.h>
#include "uart.h"
#include "itoa.h"
static volatile unsigned int wait_tick;
@@ -12,6 +24,14 @@ static void watchdog_ack(void)
IWDG->KR = 0xAAAA;
}
static void external_watchdog_disable(void)
{
RCC->AHB1ENR |= SAFETY_EXT_WATCHDOG_RCC_MASK;
__DSB();
/* Set Pin to input. This disables the external watchdog. */
SAFETY_EXT_WATCHDOG_PORT->MODER &= MODER_DELETE(SAFETY_EXT_WATCHDOG_PIN);
}
void sdio_wait_ms(unsigned int ms)
{
wait_tick = 0;
@@ -23,24 +43,247 @@ static FATFS _fs;
static void __attribute__((noreturn)) ram_code_exit(bool updated)
{
(void)updated;
struct safety_memory_boot_status boot_status;
safety_memory_get_boot_status(&boot_status);
boot_status.code_updated = updated ? 0xFFFFFFFFUL : 0x0UL;
boot_status.reboot_to_bootloader = 0x0UL;
safety_memory_set_boot_status(&boot_status);
uart_send_string("Rebooting in 1s...\r\n");
sdio_wait_ms(1000);
NVIC_SystemReset();
while(1);
}
static int check_hex_file(const char *fname, uint32_t *update_size)
{
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;
uint32_t total_size = 0UL;
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;
}
total_size += dlen;
}
} while (hex_ret == HEX_PARSER_DATA_OK || hex_ret == HEX_PARSER_OK);
if (hex_ret == HEX_PARSER_EOF_RECORD) {
retval = 0;
if (update_size)
*update_size = total_size;
}
ret_close_parser:
hex_parser_close(&parser);
exit:
return retval;
}
int write_flash_from_buffer(const char *buffer, uint32_t len, uint32_t addr)
{
int res;
uint32_t i;
const char *verify_ptr = (const char *)addr;
res = flash_writer_write_to_memory((void *)addr, buffer, len);
if (res) {
uart_send_string("Error writing to flash!\r\n");
return -1;
}
/* Verify the write */
for (i = 0; i < len; i++, verify_ptr++) {
if (*verify_ptr != buffer[i]) {
uart_send_string("Error verifying written data!\r\n");
return -2;
}
}
return 0;
}
int update_flash_from_file(const char *fname)
{
enum hex_parser_ret hex_ret;
struct hex_parser parser;
static char write_buffer[4096];
uint32_t wbuffer_base_addr = 0;
uint32_t wbuffer_fill_level = 0;
uint32_t addr;
static char tmp_buff[256];
size_t dlen;
int retval = 0;
int res;
hex_ret = hex_parser_open(&parser, fname);
if (hex_ret != HEX_PARSER_OK) {
uart_send_string("Error reading hex file.\r\n");
return -1;
}
do {
hex_ret = hex_parser_parse(&parser, &addr, tmp_buff, sizeof(tmp_buff), &dlen);
if (hex_ret == HEX_PARSER_DATA_OK) {
/* Check if tmp would fit in wbuffer */
if (dlen + wbuffer_fill_level > sizeof(write_buffer)) {
/* Write out the buffer and clean it if it doens't fit */
res = write_flash_from_buffer(write_buffer, wbuffer_fill_level, wbuffer_base_addr);
if (res) {
retval = -4;
goto exit_parser_close;
}
wbuffer_fill_level = 0;
wbuffer_base_addr = 0;
}
/* Check if parsed data can be linearily appended to buffer */
if (wbuffer_fill_level && wbuffer_base_addr + wbuffer_fill_level != addr) {
/* Write out the buffer and clean it if it cannot be appended */
res = write_flash_from_buffer(write_buffer, wbuffer_fill_level, wbuffer_base_addr);
if (res) {
retval = -4;
goto exit_parser_close;
}
wbuffer_fill_level = 0;
wbuffer_base_addr = 0;
}
/* Fill in the data into the buffer */
if (wbuffer_fill_level == 0) {
wbuffer_base_addr = addr;
}
memcpy(&write_buffer[wbuffer_fill_level], tmp_buff, dlen);
wbuffer_fill_level += dlen;
}
} while (hex_ret == HEX_PARSER_DATA_OK || hex_ret == HEX_PARSER_OK);
if (hex_ret == HEX_PARSER_EOF_RECORD) {
if (wbuffer_fill_level > 0) {
res = write_flash_from_buffer(write_buffer, wbuffer_fill_level, wbuffer_base_addr);
if (res) {
retval = -4;
goto exit_parser_close;
}
}
retval = 0;
} else {
retval = -3;
}
exit_parser_close:
hex_parser_close(&parser);
return retval;
}
int ram_code_main(void)
{
FRESULT fres;
int res;
enum safety_memory_state safety_mem_state;
static char filename[256];
static char tmp_buff[256];
uint32_t count;
uint32_t update_size;
int retries = 3;
SysTick_Config(168000UL);
external_watchdog_disable();
__enable_irq();
fres = f_mount(fs, "0:/", 1);
if (fres != FR_OK) {
/* Init the uart module
* Pins don't need configuration. They're already setup by the main program
*/
uart_init();
/* Clear display and set cursor to home position */
uart_send_string("\e[2J\e[H");
uart_send_string("Updater started.\r\n");
res = safety_memory_init(&safety_mem_state);
if (res || safety_mem_state != SAFETY_MEMORY_INIT_VALID_MEMORY) {
ram_code_exit(false);
}
fres = f_mount(fs, "0:/", 1);
if (fres != FR_OK) {
uart_send_string("Could not mount SD card\r\n");
ram_code_exit(false);
}
res = safety_memory_get_update_filename(filename, NULL);
if (res)
ram_code_exit(false);
uart_send_string("Checking hex file ");
uart_send_string(filename);
uart_send_string("\r\n");
if (check_hex_file(filename, &update_size)) {
uart_send_string("Error in hex file\r\n");
ram_code_exit(false);
}
uart_send_string("File ");
uart_send_string(filename);
uart_send_string(" checked successfully.\r\n");
count = heapless_itoa(update_size, tmp_buff, 10);
if (count > 0) {
tmp_buff[count] = 0;
uart_send_string("Update size: ");
uart_send_string(tmp_buff);
uart_send_string(" bytes\r\n");
}
uart_send_string("Starting updater...\r\n");
/* disable the ART caches */
FLASH->ACR &= ~FLASH_ACR_DCEN;
FLASH->ACR &= ~FLASH_ACR_ICEN;
FLASH->ACR |= FLASH_ACR_DCRST | FLASH_ACR_ICRST;
do {
uart_send_string("Erasing chip...");
flash_writer_perform_mass_erase();
uart_send_string(" done\r\n");
uart_send_string("Programming flash...\r\n");
res = update_flash_from_file(filename);
if (res) {
uart_send_string("Programming NOT successful.\r\n");
if (retries > 0) {
uart_send_string("Will retry...\r\n");
}
} else {
uart_send_string("Programming completed successfully!\r\n");
ram_code_exit(true);
break;
}
} while (retries > 0);
while(1) {
__WFI();
}

View File

@@ -260,28 +260,28 @@ extern unsigned int __ld_vector_start;
extern unsigned int __ld_sbss;
extern unsigned int __ld_ebss;
#ifdef CPACR
#undef CPACR
#endif
#define CPACR (*((volatile uint32_t *)0xE000ED88))
void Reset_Handler(void)
void Reset_Handler()
{
/* The first thing we do here, is to initialize the FPU
* When this code is compiled optimized with hardfpu abi,
* GCC tends to generate FPU instructions for data copying
*/
CPACR |= (0xF << 20);
/* Reset the stack pointer to top of stack. SP is not required to be inside the clobber list! */
__asm__ __volatile__ ("mov sp, %0\n\t" :: "r"(&__ld_top_of_stack) :);
/* Fill bss with zero */
__fill_zero(&__ld_sbss, &__ld_ebss);
/* Fill Heap with zero */
/* Reset the stack pointer to top of stack. SP is not required to be inside the clobber list! */
__asm__ __volatile__ ("mov sp, %0\n\t" :: "r"(&__ld_top_of_stack) :);
ram_code_main();

View File

@@ -0,0 +1,29 @@
#include "uart.h"
#include <reflow-controller/periph-config/shell-uart-config.h>
#include <stm32/stm32f4xx.h>
#include <string.h>
void uart_init(void)
{
SHELL_UART_RCC_REG |= SHELL_UART_RCC_MASK;
SHELL_UART_PERIPH->BRR = SHELL_UART_BRR_REG_VALUE;
SHELL_UART_PERIPH->CR2 = 0;
SHELL_UART_PERIPH->CR3 = 0;
SHELL_UART_PERIPH->CR1 = USART_CR1_TE | USART_CR1_UE;
}
void uart_send_char(char c)
{
while (!(SHELL_UART_PERIPH->SR & USART_SR_TXE));
SHELL_UART_PERIPH->DR = c;
}
void uart_send_string(const char *str)
{
int len, i;
len = strlen(str);
for (i = 0; i < len; i++) {
uart_send_char(str[i]);
}
}

View File

@@ -0,0 +1,10 @@
#ifndef _UART_H_
#define _UART_H_
void uart_init(void);
void uart_send_char(char c);
void uart_send_string(const char *str);
#endif /* _UART_H_ */

View File

@@ -19,6 +19,7 @@
*/
#include <reflow-controller/updater/updater.h>
#include <reflow-controller/safety/safety-memory.h>
#include <reflow-controller/safety/watchdog.h>
#include <generated/updater-ram-code.bin.h>
#include <stm32/stm32f4xx.h>
@@ -26,7 +27,7 @@
#include <stdint.h>
#include <stddef.h>
void __attribute__((noreturn)) start_updater(void)
void __attribute__((noreturn)) start_updater_ram_code(void)
{
const char *updater_src = binary_blob;
char *dest_ptr = (char *)UPDATER_RAM_CODE_BASE_ADDRESS;
@@ -57,3 +58,17 @@ void __attribute__((noreturn)) start_updater(void)
while(1);
}
void __attribute__((noreturn)) updater_update_from_file(const char *filename)
{
struct safety_memory_boot_status status;
safety_memory_get_boot_status(&status);
status.reboot_to_bootloader = 0xFFFFFFFFUL;
safety_memory_set_boot_status(&status);
safety_memory_set_update_filename(filename);
NVIC_SystemReset();
while (1);
}