1 Commits

Author SHA1 Message Date
43b14bdb92 Start work on temperature profile checker 2022-06-09 17:50:33 +02:00
45 changed files with 1122 additions and 1189 deletions

View File

@@ -16,10 +16,3 @@ reflow-controller.includes
*.files
*.user.*
*.user
# VSCODE and CLANGD sepcific excludes
.vscode/
build/
.cache/
compile_commands.json

View File

@@ -1,7 +1,7 @@
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_CROSSCOMPILING 1)
cmake_minimum_required(VERSION 3.18)
cmake_minimum_required(VERSION 3.0)
set(CMAKE_TOOLCHAIN_FILE "arm-none-eabi-gcc.cmake")
@@ -43,12 +43,26 @@ else (GIT_FOUND)
message("Version is set to: ${GIT_DESCRIBE}${ColorReset}")
endif (GIT_FOUND)
find_program(PATCHELFCRC patchelfcrc)
if (PATCHELFCRC)
message("patchelfcrc found: ${PATCHELFCRC}")
else(PATCHELFCRC)
message(FATAL_ERROR "${BoldRed}Patchelfcrc not found. Cannot patch CRC checksum into ELF file: patchelfcrc: command not found! See: https://git.shimatta.de/mhu/patchelfcrc${ColorReset}")
endif (PATCHELFCRC)
find_program(VIRTUALENV virtualenv)
if (VIRTUALENV)
message("Python virtual environment found")
execute_process(
COMMAND ${VIRTUALENV} venv
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
OUTPUT_QUIET
COMMAND_ERROR_IS_FATAL ANY
)
set(VENV_BIN "${CMAKE_CURRENT_BINARY_DIR}/venv/bin")
execute_process(
COMMAND ./pip install -r "${CMAKE_CURRENT_SOURCE_DIR}/crc-patcher/requirements.txt"
WORKING_DIRECTORY ${VENV_BIN}
OUTPUT_QUIET
COMMAND_ERROR_IS_FATAL ANY
)
message("${BoldGreen}python virtual environment set up!${ColorReset}")
else(VIRTUALENV)
message(FATAL_ERROR "${BoldRed}Python virtual environment not set up: virtualenv: command not found!${ColorReset}")
endif (VIRTUALENV)
set(ELFFILE ${PROJECT_NAME}.elf)
@@ -57,7 +71,7 @@ set(MAPFILE ${PROJECT_NAME}.map)
set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/stm32f407vet6_flash.ld)
add_compile_options(-Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter)
add_compile_options(-mlittle-endian -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles -Wimplicit-fallthrough=3 -Wsign-compare)
add_compile_options(-mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles -Wimplicit-fallthrough=3 -Wsign-compare)
set(GIT_DESCRIBE "${GIT_DESCRIBE}")
@@ -110,15 +124,15 @@ add_executable(${ELFFILE} ${MAIN_SOURCES} ${CFG_PARSER_SRCS} ${UI_SRCS}
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 -mfloat-abi=hard -mfpu=fpv4-sp-d16 --disable-newlib-supplied-syscalls -nostartfiles -T${LINKER_SCRIPT} -Wl,--print-memory-usage)
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 linklist-lib)
target_include_directories(${ELFFILE} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/updater/ram-code/include/")
add_custom_command(
TARGET ${ELFFILE}
POST_BUILD
COMMAND ${PATCHELFCRC} --little-endian --verbose --granularity word --start-magic 0xa8be53f9 --end-magic 0xffa582ff -O .flashcrc -p crc-32-mpeg -S .text -S .data -S .ccmdata -S .vectors "${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ./python "${CMAKE_CURRENT_SOURCE_DIR}/crc-patcher/crc-patch-elf.py" "${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}"
WORKING_DIRECTORY ${VENV_BIN}
COMMENT "Running Flash CRC Patcher"
)

View File

@@ -28,14 +28,7 @@
#include <stdio.h>
#include <stdlib.h>
/**
* @brief Config parser magic value used to check sanity of passed structs
*/
#define CONFIG_PARSER_MAGIC 0x464a6e2bUL
/**
* @brief Config parser type casting macro
*/
#define CONFIG_PARSER(p) ((struct config_parser *)(p))
/**
@@ -44,11 +37,10 @@
* If the pointer is invalid, the function using this macro will return with
* CONFIG_PARSER_PARAM_ERR
*/
#define config_parser_check_handle(handle) do { \
if (!(handle) || \
((struct config_parser *)(handle))->magic != CONFIG_PARSER_MAGIC) \
return CONFIG_PARSER_PARAM_ERR; \
} while (0)
#define config_parser_check_handle(handle) do { if (!(handle) || \
((struct config_parser *)(handle))->magic != CONFIG_PARSER_MAGIC) \
return CONFIG_PARSER_PARAM_ERR; \
} while (0)
config_parser_handle_t config_parser_open_file(struct config_parser *config_parser, bool write, const char *file_name,
char *working_buffer, size_t buff_size)
@@ -100,17 +92,17 @@ static int parse_value(struct config_parser_entry *entry, char *value_start_toke
if (value_start_token[0] != '-') {
/* Try parsing as ul */
entry->value.uint_val = strtoul(value_start_token, &endptr, 0);
if (endptr == value_start_token)
if (endptr == value_start_token) {
return -1;
}
entry->type = CONFIG_PARSER_TYPE_UINT;
goto exit;
} else {
/* Try parsing as int */
entry->value.int_val = strtod(value_start_token, &endptr);
if (endptr == value_start_token)
if (endptr == value_start_token) {
return -1;
}
entry->type = CONFIG_PARSER_TYPE_INT;
}
@@ -118,15 +110,13 @@ exit:
return 0;
}
enum config_parser_ret config_parser_get_line(config_parser_handle_t handle, struct config_parser_entry *entry,
bool force_float)
enum config_parser_ret config_parser_get_line(config_parser_handle_t handle, struct config_parser_entry *entry, bool force_float)
{
struct config_parser *p;
char *token;
int token_round = 0;
config_parser_check_handle(handle);
p = CONFIG_PARSER(handle);
char *token;
int token_round = 0;
if (!entry)
return CONFIG_PARSER_PARAM_ERR;
@@ -141,7 +131,8 @@ enum config_parser_ret config_parser_get_line(config_parser_handle_t handle, str
if (token[0] == '#') {
if (token_round == 0)
return CONFIG_PARSER_LINE_COMMENT;
break;
else
break;
}
switch (token_round) {
@@ -149,8 +140,9 @@ enum config_parser_ret config_parser_get_line(config_parser_handle_t handle, str
entry->name = token;
break;
case 1: /* = Symbol */
if (strcmp(token, "="))
if (strcmp(token, "=")) {
return CONFIG_PARSER_LINE_MALFORM;
}
break;
case 2: /* VALUE */
if (parse_value(entry, token))
@@ -180,7 +172,6 @@ enum config_parser_ret config_parser_reset_to_start(config_parser_handle_t handl
{
FRESULT res;
struct config_parser *p;
config_parser_check_handle(handle);
p = CONFIG_PARSER(handle);
@@ -203,7 +194,6 @@ enum config_parser_ret config_parser_close_file(config_parser_handle_t handle)
{
struct config_parser *p;
FRESULT res;
config_parser_check_handle(handle);
p = CONFIG_PARSER(handle);

View File

@@ -0,0 +1,114 @@
#!/bin/python
"""
This script patches the CRC checksums into an existing ELF file.
For this, it searches the follwoing sections:
1) .text
2) .data
3) .ccmdata
4) .vectors
All sections MUST be a multiple of 4 bytes long because the CRC calculation relies on whole 32 bit words.
The sections are excrated and the CRC is calculated for each section.
In the section .flashcrc, the script expects a single struct with the prototype:
struct flash_crcs {
uint32_t start_magic;
uint32_t crc_section_text;
uint32_t crc_section_data;
uint32_t crc_section_ccm_data;
uint32_t crc_section_vectors;
uint32_t end_magic;
};
It checks, if the start magic and end magic are set to the appropriate values and then patches in the CRC values of the sections.
The magic values checked for are: 0xA8BE53F9 and 0xFFA582FF
"""
from elftools.elf.elffile import ELFFile
from elftools.elf.segments import Segment
import elftools.elf.constants as elf_const
import sys
import crcmod
import crcmod.predefined
import struct
crc_calc = crcmod.predefined.mkCrcFun('crc-32-mpeg')
if len(sys.argv) < 2:
print("Usage:", sys.argv[0], ' <elf file>')
sys.exit(-1)
filename=sys.argv[1]
def section_calculate_crc(section):
data = bytearray(section.data())
be_data = bytearray([0 for k in range(0, len(data))])
# Rearrange data, because the STM controller sees it as 32 bit little endian words
for i in range(0, int(len(data)/4)):
be_data[i*4+0] = data[i*4+3]
be_data[i*4+1] = data[i*4+2]
be_data[i*4+2] = data[i*4+1]
be_data[i*4+3] = data[i*4+0]
return crc_calc(be_data)
with open(filename, 'r+b') as f:
elf = ELFFile(f)
sections = {}
sections['.text'] = elf.get_section_by_name('.text')
sections['.data'] = elf.get_section_by_name('.data')
sections['.ccmdata'] = elf.get_section_by_name('.ccmdata')
sections['.vectors'] = elf.get_section_by_name('.vectors')
for key, sec in sections.items():
if sec is None:
print("Error! Section", key, "not found in ELF file!")
sys.exit(-1)
print('Found section', key, 'Size:',
sec.data_size, 'Type:', sec['sh_type'])
if sec['sh_type'] != 'SHT_PROGBITS':
print('Error! Section must be of type SHT_PROGBITS')
sys.exit(-1)
if (sec.data_size % 4 != 0):
print("Section", key, "has wrong size. Must be a multiple of 4 bytes!")
sys.exit(-1)
text_crc = section_calculate_crc(sections['.text'])
print('CRC of .text section:', hex(text_crc))
data_crc = section_calculate_crc(sections['.data'])
print('CRC of .data section:', hex(data_crc))
ccmdata_crc = section_calculate_crc(sections['.ccmdata'])
print('CRC of .ccmdata section:', hex(ccmdata_crc))
vextors_crc = section_calculate_crc(sections['.vectors'])
print('CRC of .vectors section:', hex(vextors_crc))
# Check the flashcrc section
flashcrc_sec = elf.get_section_by_name('.flashcrc')
if flashcrc_sec is None:
print('Section for flash CRC missing!')
sys.exit(-1)
if flashcrc_sec.data_size != 6*4:
print("Error: .flashcrc section has wrong size:",flashcrc_sec.data_size)
sys.exit(-1);
crc_sec_data = bytearray(flashcrc_sec.data())
magic1 = struct.unpack('<I'*1, bytes(crc_sec_data[0:4]))[0]
magic2 = struct.unpack('<I'*1, bytes(crc_sec_data[-4:]))[0]
print("CRC section magic values:", hex(magic1), hex(magic2))
if magic1 != 0xA8BE53F9 or magic2 != 0xFFA582FF:
print("Wrong magics in CRC section. Data misalignment?")
sys.exit(-2)
crc_sec_offset = flashcrc_sec['sh_offset']
print('CRC section ELF file offset:', hex(crc_sec_offset))
crc_sec_data[4:8] = struct.pack('<I',text_crc)
crc_sec_data[8:12] = struct.pack('<I',data_crc)
crc_sec_data[12:16] = struct.pack('<I',ccmdata_crc)
crc_sec_data[16:20] = struct.pack('<I',vextors_crc)
f.seek(crc_sec_offset)
f.write(crc_sec_data)
print('CRCs patched successfully')

View File

@@ -0,0 +1,2 @@
crcmod==1.7
pyelftools==0.27

View File

@@ -6,7 +6,7 @@ import pathlib
license_header = """/* Reflow Oven Controller
*
* Copyright (C) 2022 Mario Hüttel <mario.huettel@gmx.net>
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
@@ -37,7 +37,7 @@ cpath = os.path.join(project_dir, sys.argv[1]+'.c')
hfile = sys.argv[1]+'.h'
hpath = os.path.join(module_include_dir, hfile)
h_define = '_'+hfile.replace('.', '_').replace('-', '_').replace('/', '_').upper()+'_'
h_define = '__'+hfile.replace('.', '_').replace('-', '_').replace('/', '_').upper()+'__'
if os.path.exists(cpath) or os.path.exists(hpath):
print("File already exists! Abort!")

View File

@@ -27,15 +27,10 @@
#include <stm-periph/rcc-manager.h>
#include <stm32/stm32f4xx.h>
#if HW_REV_DETECT_PIN_LOW > HW_REV_DETECT_PIN_HIGH
#error Configuration error for Hardware derection pins. Lowest position must be less than the highest pin position.
#endif
enum hw_revision get_pcb_hardware_version(void)
{
uint8_t current_pin;
uint16_t port_bitmask = 0U; /* Use uint16_t because a port can have 16 IOs max. */
const uint16_t highest_bit_mask = (1 << (HW_REV_DETECT_PIN_HIGH - HW_REV_DETECT_PIN_LOW));
uint16_t port_bitmask = 0U;
static enum hw_revision revision = HW_REV_NOT_DETECTED;
/* If the revision has been previously detected,
@@ -58,7 +53,7 @@ enum hw_revision get_pcb_hardware_version(void)
*/
for (current_pin = HW_REV_DETECT_PIN_LOW; current_pin <= HW_REV_DETECT_PIN_HIGH; current_pin++) {
port_bitmask >>= 1;
port_bitmask |= (HW_REV_DETECT_GPIO->IDR & (1 << current_pin)) ? 0x0 : highest_bit_mask;
port_bitmask |= (HW_REV_DETECT_GPIO->IDR & (1 << current_pin)) ? 0x0 : 0x80;
}
/* Resolve the read in bitmask to a hardware version */

View File

@@ -48,6 +48,7 @@
*/
#define HW_REV_DETECT_PIN_HIGH (15U)
/**
* @brief PCB/Hardware Revision Type
*/

View File

@@ -1,37 +0,0 @@
/* Reflow Oven Controller
*
* Copyright (C) 2022 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SAFETY_FLASH_CRC_STRUCT_H_
#define _SAFETY_FLASH_CRC_STRUCT_H_
#include <stdint.h>
struct flash_crcs {
uint32_t start_magic;
uint32_t crc_section_text;
uint32_t crc_section_data;
uint32_t crc_section_ccm_data;
uint32_t crc_section_vectors;
uint32_t end_magic;
};
extern const struct flash_crcs crcs_in_flash;
#endif /* _SAFETY_FLASH_CRC_STRUCT_H_ */

View File

@@ -1,56 +0,0 @@
/* Reflow Oven Controller
*
* Copyright (C) 2022 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SAFETY_FLASH_CRC_H_
#define _SAFETY_FLASH_CRC_H_
#include <stdint.h>
enum flash_crc_section {
FLASH_CRC_VECTOR = 0,
FLASH_CRC_TEXT,
FLASH_CRC_DATA,
FLASH_CRC_CCMDATA,
N_FLASH_CRC,
};
/**
* @brief Perform a CRC check of the flash memory and set appropriate flags
* @return negative if internal error occured. Otherwise (independent from CRC check result) 0.
* @note This function requires the safety controller (and CRC unit) to be set up before calling!
*/
int flash_crc_trigger_check(void);
/**
* @brief Calculate CRC over flash section
* @param sec Section to calculate CRC over
* @param[out] crc_result Calculated CRC
* @return negative if internal error occured. Otherwise (independent from CRC check result) 0.
*/
int flash_crc_calc_section(enum flash_crc_section sec, uint32_t *crc_result);
/**
* @brief Get expected CRC value of a section
* @param sec Section
* @return Expected CRC
*/
uint32_t flash_crc_get_expected_crc(enum flash_crc_section sec);
#endif /* _SAFETY_FLASH_CRC_H_ */

View File

@@ -27,15 +27,6 @@
#ifndef __SAFETY_CONFIG_H__
#define __SAFETY_CONFIG_H__
/**
* @brief Weights of error flags.
*/
enum config_weight {
SAFETY_FLAG_CONFIG_WEIGHT_NONE = 0, /**< @brief This flag has no global error consequence, but might be respected by certain software modules. */
SAFETY_FLAG_CONFIG_WEIGHT_PID = 1, /**< @brief This flag will force a stop of the temperature PID controller */
SAFETY_FLAG_CONFIG_WEIGHT_PANIC = 2, /**< @brief This flag will trigger the panic mode */
};
/**
* @brief Enum type representing safety flags.
*
@@ -168,7 +159,7 @@ enum analog_value_monitor {
#define SAFETY_CRC_MON_SAFETY_ADC_PW 0xA8DF2368
/**
* @brief Default persistence of safety flags. These values are loaded into the safety tables on startup.
* @brief Default persistence of safety flags. These values are loaded into the safety tables on startup
*/
#define SAFETY_CONFIG_DEFAULT_PERSIST ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_MEAS_ADC_OFF, false), \
ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_MEAS_ADC_WATCHDOG, false), \
@@ -192,9 +183,9 @@ enum analog_value_monitor {
ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_FLASH_CRC_CODE, true), \
ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_FLASH_CRC_DATA, true), \
ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_CFG_CRC_MEAS_ADC, true), \
ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_CFG_CRC_SAFETY_ADC, true)
ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_CFG_CRC_SAFETY_ADC, true), \
/**
* @brief Default config weights of safety flags. These values are loaded into the safety tables on startup.
* @brief Default config weights of safety flags. These values are loaded into the safety tables on startup
*/
#define SAFETY_CONFIG_DEFAULT_WEIGHTS ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_MEAS_ADC_OFF, SAFETY_FLAG_CONFIG_WEIGHT_PID), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_MEAS_ADC_WATCHDOG, SAFETY_FLAG_CONFIG_WEIGHT_PID), \
@@ -215,9 +206,9 @@ enum analog_value_monitor {
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_SAFETY_TAB_CORRUPT, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_AMON_SUPPLY_VOLT, SAFETY_FLAG_CONFIG_WEIGHT_PID), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_OVERTEMP, SAFETY_FLAG_CONFIG_WEIGHT_PID), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_FLASH_CRC_CODE, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_FLASH_CRC_DATA, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_CFG_CRC_MEAS_ADC, SAFETY_FLAG_CONFIG_WEIGHT_PID), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_CFG_CRC_SAFETY_ADC, SAFETY_FLAG_CONFIG_WEIGHT_PANIC)
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_FLASH_CRC_CODE, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_FLASH_CRC_DATA, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_CFG_CRC_MEAS_ADC, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_CFG_CRC_SAFETY_ADC, SAFETY_FLAG_CONFIG_WEIGHT_NONE), \
#endif /* __SAFETY_CONFIG_H__ */

View File

@@ -70,14 +70,14 @@ struct timing_monitor_info {
* You have to call safety_controller_handle
* If this function fails, it will hang, because errors in the safety controller are not recoverable
*/
void safety_controller_init(void);
void safety_controller_init();
/**
* @brief Handle the safety controller.
* @note This function must be executed periodically in order to prevent the watchdog from resetting the firmware
* @returns Worst flag weigth that is currently set.
* @return 0 if successful
*/
enum config_weight safety_controller_handle(void);
int safety_controller_handle();
/**
* @brief Report one or multiple errors to the safety controller
@@ -170,13 +170,13 @@ bool safety_controller_get_flags_by_mask(enum safety_flag mask);
* @brief Get the count of error flags
* @return Error flag count
*/
uint32_t safety_controller_get_flag_count(void);
uint32_t safety_controller_get_flag_count();
/**
* @brief Get the count of analog monitors
* @return Analog monitor count
*/
uint32_t safety_controller_get_analog_monitor_count(void);
uint32_t safety_controller_get_analog_monitor_count();
/**
* @brief Get an error flag's name by its index.
@@ -267,6 +267,13 @@ int safety_controller_set_overtemp_limit(float over_temperature);
*/
float safety_controller_get_overtemp_limit(void);
/**
* @brief Perform a CRC check of the flash memory and set appropriate flags
* @return negative if internal error occured. Otherwise (independent from CRC check result) 0.
* @note This function requires the safety controller to be set up before!
*/
int safety_controller_trigger_flash_crc_check(void);
/**
* @brief Recalculate the CRC of a given CRC Monitor. This has to be done once the supervised registers update
* @param mon Monitor to recalculate

View File

@@ -24,7 +24,6 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <reflow-controller/safety/safety-config.h>
/** @addtogroup safety-memory
* @{
@@ -132,6 +131,15 @@ enum config_override_entry_type {
SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTENCE = 2,
};
/**
* @brief Weights of error flags.
*/
enum config_weight {
SAFETY_FLAG_CONFIG_WEIGHT_NONE = 0, /**< @brief This flag has no global error consequence, but might be respected by certain software modules. */
SAFETY_FLAG_CONFIG_WEIGHT_PID = 1, /**< @brief This flag will force a stop of the temperature PID controller */
SAFETY_FLAG_CONFIG_WEIGHT_PANIC = 2, /**< @brief This flag will trigger the panic mode */
};
/**
* @brief representation of a config override memory entry
*/

View File

@@ -1,42 +0,0 @@
/* Reflow Oven Controller
*
* Copyright (C) 2022 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* GDSII-Converter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SD_H_
#define _SD_H_
#include <stdbool.h>
#include <fatfs/ff.h>
/**
* @brief Mount the SD card if available and not already mounted
* @param fs Filesystem to mount to.
* @return true if mounted, false if an error occured or the SD is not inserted and cannot be mounted
*/
bool mount_sd_card_if_avail(FATFS *fs);
/**
* @brief Return whether an SD card is inserted and mounted
*
* @return true SD inserted and mounted
* @return false No SD inserted or not mounted
*/
bool sd_card_is_mounted(void);
#endif /* _SD_H_ */

View File

@@ -28,12 +28,12 @@
* @brief Initialize the SPI for the eeprom.
* @return 0 if succesful
*/
int spi_eeprom_init(void);
int spi_eeprom_init();
/**
* @brief Uninitialize the SPI EEPROM
*/
void spi_eeprom_deinit(void);
void spi_eeprom_deinit();
/**
* @brief Read from SPI EEPROM

View File

@@ -33,7 +33,7 @@ enum random_number_error {
void random_number_gen_init(bool int_enable);
void random_number_gen_deinit(void);
void random_number_gen_deinit();
void random_number_gen_reset(bool int_en);

View File

@@ -33,6 +33,4 @@ void stm_unique_id_get(uint32_t *high, uint32_t *mid, uint32_t *low);
void stm_dev_rev_id_get(uint32_t *device_id, uint32_t *revision_id);
void stm_cpuid_get(uint8_t *implementer, uint8_t *variant, uint16_t *part_no, uint8_t *rev);
#endif /* __UNIQUE_ID_H__ */

View File

@@ -32,13 +32,13 @@
#include <reflow-controller/systick.h>
#include <reflow-controller/adc-meas.h>
#include <reflow-controller/digio.h>
#include "fatfs/shimatta_sdio_driver/shimatta_sdio.h"
#include <stm-periph/stm32-gpio-macros.h>
#include <stm-periph/rcc-manager.h>
#include <stm-periph/uart.h>
#include <reflow-controller/periph-config/shell-uart-config.h>
#include <reflow-controller/oven-driver.h>
#include <fatfs/ff.h>
#include <reflow-controller/sd.h>
#include <reflow-controller/ui/gui.h>
#include <reflow-controller/ui/shell.h>
#include <reflow-controller/ui/shell-uart.h>
@@ -88,6 +88,40 @@ static inline void uart_gpio_config(void)
#endif
}
/**
* @brief Mount the SD card if available and not already mounted
* @param mounted The current mounting state of the SD card
* @return true if mounted, false if an error occured or the SD is not inserted and cannot be mounted
*/
static bool mount_sd_card_if_avail(bool mounted)
{
FRESULT res;
static uint8_t IN_SECTION(.ccm.bss) inserted_counter = 0;
if (sdio_check_inserted() && mounted) {
memset(fs_ptr, 0, sizeof(FATFS));
sdio_stop_clk();
inserted_counter = 0;
return false;
}
if (!sdio_check_inserted() && inserted_counter < 255)
inserted_counter++;
if (!sdio_check_inserted() && !mounted && inserted_counter > 4) {
inserted_counter = 0;
res = f_mount(fs_ptr, "0:/", 1);
if (res == FR_OK) {
led_set(1, 1);
return true;
} else {
return false;
}
}
return mounted;
}
/**
* @brief Process the boot status structure in the safety (backup) RAM
* Depending on the flags set there, this function will:
@@ -252,7 +286,6 @@ int main(void)
shellmatta_handle_t shell_handle;
int menu_wait_request;
uint64_t quarter_sec_timestamp = 0ULL;
enum config_weight worst_safety_flag = SAFETY_FLAG_CONFIG_WEIGHT_NONE;
/** - Setup all the peripherals and external componets like LCD, EEPROM etc. and the safety controller */
setup_system();
@@ -279,9 +312,9 @@ int main(void)
* it is tried to load it from SD card.
*/
if (systick_ticks_have_passed(quarter_sec_timestamp, 250)) {
led_set(1u, 0);
led_set(1, 0);
sd_old = sd_card_mounted;
sd_card_mounted = mount_sd_card_if_avail(fs_ptr);
sd_card_mounted = mount_sd_card_if_avail(sd_card_mounted);
if (sd_card_mounted && !sd_old) {
adc_pt1000_get_resistance_calibration(NULL, NULL, &cal_active);
@@ -292,14 +325,6 @@ int main(void)
}
}
/* Check if any flags are present, that disable the PID controller. Blink
* LED 0 in this case
*/
if (worst_safety_flag >= SAFETY_FLAG_CONFIG_WEIGHT_PID)
led_set(0u, led_get(0u) ? 0 : 1);
else
led_set(0u, 0);
quarter_sec_timestamp = systick_get_global_tick();
}
@@ -313,7 +338,7 @@ int main(void)
temp_profile_executer_handle();
/** - Handle the safety controller. This must be called! Otherwise a watchdog reset will occur */
worst_safety_flag = safety_controller_handle();
safety_controller_handle();
/** - If the Oven PID controller is running, we handle its sample function */
if (oven_pid_get_status() == OVEN_PID_RUNNING)

View File

@@ -78,6 +78,5 @@ void panic_mode(void)
}
/* Let the watchdog do the rest */
while (1)
;
while (1);
}

View File

@@ -1,31 +0,0 @@
/* Reflow Oven Controller
*
* Copyright (C) 2022 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/safety/flash-crc-struct.h>
#include <helper-macros/helper-macros.h>
const struct flash_crcs IN_SECTION(.flashcrc) crcs_in_flash = {
.start_magic = 0xA8BE53F9UL,
.crc_section_ccm_data = 0UL,
.crc_section_text = 0UL,
.crc_section_data = 0UL,
.crc_section_vectors = 0UL,
.end_magic = 0xFFA582FFUL,
};

View File

@@ -1,152 +0,0 @@
/* Reflow Oven Controller
*
* Copyright (C) 2022 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/safety/flash-crc.h>
#include <reflow-controller/safety/flash-crc-struct.h>
#include <reflow-controller/safety/safety-controller.h>
#include <stm-periph/crc-unit.h>
extern const uint32_t __ld_vectors_start;
extern const uint32_t __ld_vectors_end;
extern const uint32_t __ld_text_start;
extern const uint32_t __ld_text_end;
extern const uint32_t __ld_sdata_ccm;
extern const uint32_t __ld_edata_ccm;
extern const uint32_t __ld_load_ccm_data;
extern const uint32_t __ld_sdata;
extern const uint32_t __ld_edata;
extern const uint32_t __ld_load_data;
int flash_crc_trigger_check(void)
{
int ret = -1;
int res;
int any_err = 0;
uint32_t crc;
/* Perform CRC check over vector table */
res = flash_crc_calc_section(FLASH_CRC_VECTOR, &crc);
if (res || crc != flash_crc_get_expected_crc(FLASH_CRC_VECTOR))
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
any_err |= res;
/* Perform CRC check over text section */
res = flash_crc_calc_section(FLASH_CRC_TEXT, &crc);
if (res || crc != flash_crc_get_expected_crc(FLASH_CRC_TEXT))
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
any_err |= res;
/* Perform CRC check over data section */
res = flash_crc_calc_section(FLASH_CRC_DATA, &crc);
if (res || crc != flash_crc_get_expected_crc(FLASH_CRC_DATA))
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
any_err |= res;
/* Perform CRC check over ccm data section */
res = flash_crc_calc_section(FLASH_CRC_CCMDATA, &crc);
if (res || crc != flash_crc_get_expected_crc(FLASH_CRC_CCMDATA))
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
any_err |= res;
if (!any_err)
ret = 0;
return ret;
}
int flash_crc_calc_section(enum flash_crc_section sec, uint32_t *crc_result)
{
uint32_t len;
const uint32_t *startptr;
const uint32_t *endptr;
const uint32_t *load_addr = NULL;
if (!crc_result)
return -1002;
switch (sec) {
case FLASH_CRC_VECTOR:
startptr = &__ld_vectors_start;
endptr = &__ld_vectors_end;
break;
case FLASH_CRC_TEXT:
startptr = &__ld_text_start;
endptr = &__ld_text_end;
break;
case FLASH_CRC_DATA:
startptr = &__ld_sdata;
endptr = &__ld_edata;
load_addr = &__ld_load_data;
break;
case FLASH_CRC_CCMDATA:
startptr = &__ld_sdata_ccm;
endptr = &__ld_edata_ccm;
load_addr = &__ld_load_ccm_data;
break;
default:
return -1001;
}
len = (uint32_t)((void *)endptr - (void *)startptr);
if (!load_addr)
load_addr = startptr;
/* Not a multiple of 32bit words long. Cannot calculate CRC in this case! */
if (len % 4)
return -1;
/* Calculate word count */
len /= 4;
/* Reset CRC and calculate over data range */
crc_unit_reset();
crc_unit_input_array(load_addr, len);
*crc_result = crc_unit_get_crc();
return 0;
}
uint32_t flash_crc_get_expected_crc(enum flash_crc_section sec)
{
uint32_t crc;
switch (sec) {
case FLASH_CRC_VECTOR:
crc = crcs_in_flash.crc_section_vectors;
break;
case FLASH_CRC_TEXT:
crc = crcs_in_flash.crc_section_text;
break;
case FLASH_CRC_DATA:
crc = crcs_in_flash.crc_section_data;
break;
case FLASH_CRC_CCMDATA:
crc = crcs_in_flash.crc_section_ccm_data;
break;
default:
crc = 0xFFFFFFFFul;
break;
}
return crc;
}

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @addtogroup safety-adc
@@ -60,8 +60,7 @@ void safety_adc_init(void)
rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_DMA2EN));
if (hw_rev != HW_REV_V1_2) {
rcc_manager_enable_clock(&RCC->AHB1ENR,
BITMASK_TO_BITNO(SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PORT_RCC_MASK));
rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PORT_RCC_MASK));
SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PORT->MODER &= MODER_DELETE(SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PIN);
SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PORT->MODER |= ANALOG(SAFETY_ADC_SUPPLY_VOLTAGE_MONITOR_PIN);
}
@@ -73,7 +72,7 @@ void safety_adc_init(void)
SAFETY_ADC_ADC_PERIPHERAL->SMPR1 |= ADC_SMPR1_SMP17 | ADC_SMPR1_SMP16 | ADC_SMPR1_SMP15;
/* Standard sequence. Measure all channels in one sequence */
SAFETY_ADC_ADC_PERIPHERAL->SQR1 = (SAFETY_ADC_NUM_OF_CHANNELS - 1) << 20;
SAFETY_ADC_ADC_PERIPHERAL->SQR1 = (SAFETY_ADC_NUM_OF_CHANNELS - 1) << 20 ;
SAFETY_ADC_ADC_PERIPHERAL->SQR2 = 0UL;
SAFETY_ADC_ADC_PERIPHERAL->SQR3 = 0UL;
@@ -98,8 +97,7 @@ void safety_adc_init(void)
DMA2_Stream4->PAR = (uint32_t)&SAFETY_ADC_ADC_PERIPHERAL->DR;
DMA2_Stream4->M0AR = (uint32_t)safety_adc_conversions;
DMA2_Stream4->NDTR = SAFETY_ADC_NUM_OF_CHANNELS;
DMA2_Stream4->CR = DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_CIRC |
DMA_SxCR_TCIE | DMA_SxCR_EN;
DMA2_Stream4->CR = DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_TCIE | DMA_SxCR_EN;
NVIC_EnableIRQ(DMA2_Stream4_IRQn);
/* Enable ADC */
@@ -177,7 +175,7 @@ void safety_adc_trigger_meas(void)
safety_adc_triggered = 1;
}
void DMA2_Stream4_IRQHandler(void)
void DMA2_Stream4_IRQHandler()
{
uint32_t hisr;

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @addtogroup safety-controller
@@ -43,7 +43,6 @@
#include <stm-periph/rcc-manager.h>
#include <reflow-controller/temp-converter.h>
#include <reflow-controller/adc-meas.h>
#include <reflow-controller/safety/flash-crc.h>
#include <reflow-controller/periph-config/safety-adc-hwcfg.h>
/**
@@ -155,6 +154,15 @@ struct overtemp_config {
uint32_t crc;
};
struct flash_crcs {
uint32_t start_magic;
uint32_t crc_section_text;
uint32_t crc_section_data;
uint32_t crc_section_ccm_data;
uint32_t crc_section_vectors;
uint32_t end_magic;
};
struct crc_monitor_register {
const volatile void *reg_addr;
uint32_t mask;
@@ -207,8 +215,8 @@ static volatile struct error_flag IN_SECTION(.ccm.data) flags[] = {
};
/**
* @brief All timing monitors
*/
* @brief All timing monitors
*/
static volatile struct timing_mon IN_SECTION(.ccm.data) timings[] = {
TIM_MON_ENTRY(ERR_TIMING_PID, 2, 5000, ERR_FLAG_TIMING_PID),
TIM_MON_ENTRY(ERR_TIMING_MEAS_ADC, 0, 50, ERR_FLAG_TIMING_MEAS_ADC),
@@ -290,7 +298,7 @@ static const struct crc_monitor_register meas_adc_crc_regs[] = {
ADC_SQR2_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10 | ADC_SQR2_SQ9 |
ADC_SQR2_SQ8 | ADC_SQR2_SQ7, 4),
CRC_MON_REGISTER_ENTRY(ADC_PT1000_PERIPH->SQR3, ADC_SQR3_SQ6 | ADC_SQR3_SQ5 | ADC_SQR3_SQ4 |
ADC_SQR3_SQ3 | ADC_SQR3_SQ2 | ADC_SQR3_SQ1, 4),
ADC_SQR3_SQ3| ADC_SQR3_SQ2 | ADC_SQR3_SQ1, 4),
{NULL, 0, 0}
};
@@ -306,11 +314,12 @@ static const struct crc_monitor_register safety_adc_crc_regs[] = {
ADC_SQR2_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10 | ADC_SQR2_SQ9 |
ADC_SQR2_SQ8 | ADC_SQR2_SQ7, 4),
CRC_MON_REGISTER_ENTRY(SAFETY_ADC_ADC_PERIPHERAL->SQR3, ADC_SQR3_SQ6 | ADC_SQR3_SQ5 | ADC_SQR3_SQ4 |
ADC_SQR3_SQ3 | ADC_SQR3_SQ2 | ADC_SQR3_SQ1, 4),
ADC_SQR3_SQ3| ADC_SQR3_SQ2 | ADC_SQR3_SQ1, 4),
{NULL, 0, 0}
};
static struct crc_mon IN_SECTION(.ccm.data) crc_monitors[] = {
static struct crc_mon IN_SECTION(.ccm.data) crc_monitors[] =
{
{
.registers = meas_adc_crc_regs,
.monitor = ERR_CRC_MON_MEAS_ADC,
@@ -351,22 +360,16 @@ static void set_overtemp_config(float over_temperature)
safety_controller_overtemp_config.crc_dummy_seed = 0xA4F5C7E6UL;
safety_controller_overtemp_config.overtemp_deg_celsius = over_temperature;
safety_controller_overtemp_config.overtemp_equiv_resistance = resistance;
crc_unit_input_array((const uint32_t *)&safety_controller_overtemp_config,
wordsize_of(struct overtemp_config) - 1);
crc_unit_input_array((const uint32_t *)&safety_controller_overtemp_config, wordsize_of(struct overtemp_config) - 1);
safety_controller_overtemp_config.crc = crc_unit_get_crc();
}
/**
* @brief Check the overtemperature config structure's CRC
* @return true if check failed. false if CRC check successful
*/
static bool over_temperature_config_check(void)
{
if (safety_controller_overtemp_config.crc_dummy_seed != 0xA4F5C7E6UL)
return true;
crc_unit_reset();
crc_unit_input_array((const uint32_t *)&safety_controller_overtemp_config,
wordsize_of(struct overtemp_config) - 1);
crc_unit_input_array((const uint32_t *)&safety_controller_overtemp_config, wordsize_of(struct overtemp_config) - 1);
if (crc_unit_get_crc() != safety_controller_overtemp_config.crc)
return true;
@@ -439,7 +442,7 @@ static int flag_weight_table_crc_check(void)
static int flag_persistence_table_crc_check(void)
{
crc_unit_reset();
crc_unit_input_array((uint32_t *)flag_persistencies, wordsize_of(flag_persistencies));
crc_unit_input_array((uint32_t*)flag_persistencies, wordsize_of(flag_persistencies));
if (crc_unit_get_crc() != flag_persistencies_crc)
return -1;
@@ -516,8 +519,9 @@ static int safety_controller_check_crc_monitors(void)
if (crc_monitor_calculate_crc(mon->registers, &crc))
return -1;
if (mon->expected_crc != crc || ~mon->expected_crc_inv != crc)
if (mon->expected_crc != crc || ~mon->expected_crc_inv != crc) {
safety_controller_report_error(mon->flag_to_set);
}
mon->last_crc = crc;
}
@@ -544,7 +548,7 @@ static void init_safety_flag_weight_table_from_default(void)
}
crc_unit_reset();
crc_unit_input_array((uint32_t *)flag_weights, wordsize_of(flag_weights));
crc_unit_input_array((uint32_t*)flag_weights, wordsize_of(flag_weights));
flag_weight_crc = crc_unit_get_crc();
}
@@ -604,14 +608,16 @@ static void apply_config_overrides(void)
case SAFETY_MEMORY_CONFIG_OVERRIDE_WEIGHT:
flag_enum = flag_no_to_flag_enum(override.entry.weight_override.flag);
flag = find_error_flag(flag_enum);
if (flag && flag->weight)
if (flag && flag->weight) {
flag->weight->weight = override.entry.weight_override.weight;
}
break;
case SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTENCE:
flag_enum = flag_no_to_flag_enum(override.entry.persistence_override.flag);
flag = find_error_flag(flag_enum);
if (flag && flag->persistence)
if (flag && flag->persistence) {
flag->persistence->persistence = override.entry.persistence_override.persistence;
}
break;
default:
continue;
@@ -623,7 +629,7 @@ static void apply_config_overrides(void)
crc_unit_input_array((uint32_t *)flag_persistencies, wordsize_of(flag_persistencies));
flag_persistencies_crc = crc_unit_get_crc();
crc_unit_reset();
crc_unit_input_array((uint32_t *)flag_weights, wordsize_of(flag_weights));
crc_unit_input_array((uint32_t*)flag_weights, wordsize_of(flag_weights));
flag_weight_crc = crc_unit_get_crc();
}
@@ -641,10 +647,11 @@ static bool error_flag_get_status(const volatile struct error_flag *flag)
if (!flag)
return true;
if (flag->error_state == flag->error_state_inv)
if (flag->error_state == flag->error_state_inv) {
return true;
else
} else {
return flag->error_state;
}
}
/**
@@ -686,7 +693,7 @@ static volatile struct timing_mon *find_timing_mon(enum timing_monitor mon)
/**
* @brief Check the active timing monitors and set the appropriate flags in case of an error.
*/
static void safety_controller_process_active_timing_mons(void)
static void safety_controller_process_active_timing_mons()
{
uint32_t i;
volatile struct timing_mon *current_mon;
@@ -709,8 +716,7 @@ static void safety_controller_process_active_timing_mons(void)
* Process the analog and timing monitors and set the relevant flags in case of a monitor outside its limits.
* Furthermore, the PT1000 resistance is checked for overtemperature
*
* The checking of the analog monitors will only be armed after a startup delay of 1000 ms to
* allow the values to stabilize.
* The checking of the analog monitors will only be armed after a startup delay of 1000 ms to allow the values to stabilize.
*/
static void safety_controller_process_monitor_checks(void)
{
@@ -725,18 +731,21 @@ static void safety_controller_process_monitor_checks(void)
if (startup_completed) {
analog_mon_count = safety_controller_get_analog_monitor_count();
for (idx = 0; idx < analog_mon_count; idx++)
for (idx = 0; idx < analog_mon_count; idx++) {
if (safety_controller_get_analog_mon_by_index(idx, &amon_info)) {
panic_mode();
}
if (amon_info.status != ANALOG_MONITOR_OK)
if (amon_info.status != ANALOG_MONITOR_OK) {
safety_controller_report_error(amon_info.associated_flag);
}
}
}
adc_pt1000_get_current_resistance(&pt1000_val);
if (pt1000_val > safety_controller_overtemp_config.overtemp_equiv_resistance)
if (pt1000_val > safety_controller_overtemp_config.overtemp_equiv_resistance) {
safety_controller_report_error(ERR_FLAG_OVERTEMP);
}
(void)safety_controller_check_crc_monitors();
@@ -770,7 +779,7 @@ static int report_error(enum safety_flag flag, uint32_t key, bool prevent_error_
flags[i].error_state_inv = !flags[i].error_state;
flags[i].key = key;
if ((check_flag_persistent(&flags[i]) && !old_state && !prevent_error_mem_enty) ||
if ((check_flag_persistent(&flags[i]) && !old_state && !prevent_error_mem_enty) ||
get_flag_weight(&flags[i]) == SAFETY_FLAG_CONFIG_WEIGHT_PANIC) {
err_mem_entry.counter = 1;
err_mem_entry.flag_num = flag_enum_to_flag_no(flags[i].flag);
@@ -811,8 +820,9 @@ void safety_controller_report_timing(enum timing_monitor monitor)
tim = find_timing_mon(monitor);
if (tim) {
if (tim->enabled) {
if (!systick_ticks_have_passed(tim->last, tim->min_delta) && tim->min_delta > 0U)
if (!systick_ticks_have_passed(tim->last, tim->min_delta) && tim->min_delta > 0U) {
safety_controller_report_error(tim->associated_flag);
}
}
tim->calculated_delta = timestamp - tim->last;
@@ -860,8 +870,9 @@ static int get_safety_flags_from_error_mem(enum safety_flag *flags)
for (idx = 0; idx < count; idx++) {
res = safety_memory_get_error_entry(idx, &entry);
if (entry.type == SAFETY_MEMORY_ERR_ENTRY_FLAG)
if (entry.type == SAFETY_MEMORY_ERR_ENTRY_FLAG) {
return_flags |= flag_no_to_flag_enum(entry.flag_num);
}
}
*flags = return_flags;
@@ -873,12 +884,11 @@ static int get_safety_flags_from_error_mem(enum safety_flag *flags)
*
* The external harware watchdog has to be periodically reset or it will reset hte controller.
* Because debugging is not possible, when the watchdog is active, it is only activated, if the application is
* compiled in release mode. Any interruption of the main programm will then trigger the internal and/or
* the external watchdog.
* compiled in release mode. Any interruption of the main programm will then trigger the internal and/or the external watchdog.
*
* @note When enabled, execute the @ref external_watchdog_toggle function to reset the external watchdog.
*/
static void safety_controller_init_external_watchdog(void)
static void safety_controller_init_external_watchdog()
{
rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(SAFETY_EXT_WATCHDOG_RCC_MASK));
SAFETY_EXT_WATCHDOG_PORT->MODER &= MODER_DELETE(SAFETY_EXT_WATCHDOG_PIN);
@@ -889,7 +899,7 @@ static void safety_controller_init_external_watchdog(void)
__DSB();
}
void safety_controller_init(void)
void safety_controller_init()
{
enum safety_memory_state found_memory_state;
enum safety_flag flags_in_err_mem = ERR_FLAG_NO_FLAG;
@@ -906,7 +916,7 @@ void safety_controller_init(void)
/* This is usually done by the safety memory already. But, since this module also uses the CRC... */
crc_unit_init();
flash_crc_trigger_check();
safety_controller_trigger_flash_crc_check();
stack_check_init_corruption_detect_area();
hw_rev = get_pcb_hardware_version();
@@ -957,7 +967,7 @@ void safety_controller_init(void)
* 1) Checking the remaining free space at the moment between stack pointer and top of heap.
* 2) Checking The CRC of the corruption detect area between heap and stack
*/
static void safety_controller_check_stack(void)
static void safety_controller_check_stack()
{
int32_t free_stack;
@@ -965,17 +975,18 @@ static void safety_controller_check_stack(void)
if (free_stack < SAFETY_MIN_STACK_FREE)
safety_controller_report_error(ERR_FLAG_STACK);
if (stack_check_corruption_detect_area())
if (stack_check_corruption_detect_area()) {
safety_controller_report_error(ERR_FLAG_STACK);
}
}
/**
* @brief Handle the Safety ADC
*
* This function handles the safety ADC.
* If the safety ADC is not executing a measurment and the time since the last measurement has
* passed @ref SAFETY_CONTROLLER_ADC_DELAY_MS, the safety ADC is retriggered and will automatically perform a
* measurement on all of its channels.
* If the safety ADC ius not executing a measurment and the time since the last measurement has
* passed @ref SAFETY_CONTROLLER_ADC_DELAY_MS, the safety ADC is retriggered and will automatically perform a measurement
* on all of its channels.
* When called again, this function will retrieve the data from the safety ADC and converts it into the
* appropriate analog values for the analog value monitors.
*
@@ -984,7 +995,7 @@ static void safety_controller_check_stack(void)
*
* The channels, the ssafety ADC will convert is defined in its header file using the define @ref SAFETY_ADC_CHANNELS.
*/
static void safety_controller_handle_safety_adc(void)
static void safety_controller_handle_safety_adc()
{
static uint64_t last_result_timestamp = 0;
const uint16_t *channels;
@@ -1055,8 +1066,9 @@ static void safety_controller_handle_memory_checks(void)
/* Check the safety memory */
if (safety_memory_check()) {
(void)safety_memory_reinit(&found_state);
if (found_state != SAFETY_MEMORY_INIT_VALID_MEMORY)
if (found_state != SAFETY_MEMORY_INIT_VALID_MEMORY) {
safety_controller_report_error(ERR_FLAG_SAFETY_MEM_CORRUPT);
}
}
/* If flag weight table is broken, reinit to default and set flag */
@@ -1066,7 +1078,7 @@ static void safety_controller_handle_memory_checks(void)
}
/* If persistence table is broken, reinit to default and set flag */
if (flag_persistence_table_crc_check()) {
if(flag_persistence_table_crc_check()) {
safety_controller_report_error(ERR_FLAG_SAFETY_TAB_CORRUPT);
init_safety_flag_persistencies_from_default();
}
@@ -1085,7 +1097,7 @@ static void safety_controller_handle_memory_checks(void)
* If the systick stays constant for more than 1000 calls of this function,
* the @ref ERR_FLAG_SYSTICK flag is set.
*/
static void safety_controller_do_systick_checking(void)
static void safety_controller_do_systick_checking()
{
static uint64_t last_systick;
static uint32_t same_systick_cnt = 0UL;
@@ -1109,29 +1121,22 @@ static void safety_controller_do_systick_checking(void)
* is set, the appropriate action defined by the flag weight is executed.
* @note If no flag weigth is present for a given error flag, it is treated as the most critical category
* (@ref SAFETY_FLAG_CONFIG_WEIGHT_PANIC)
*
* @returns Worst config weight set
*/
static enum config_weight safety_controller_handle_weighted_flags(void)
static void safety_controller_handle_weighted_flags()
{
uint32_t flag_index;
volatile struct error_flag *current_flag;
enum config_weight flag_weigth;
enum config_weight worst = SAFETY_FLAG_CONFIG_WEIGHT_NONE;
for (flag_index = 0u; flag_index < COUNT_OF(flags); flag_index++) {
current_flag = &flags[flag_index];
/* Continue if this flag is not set */
if (!error_flag_get_status(current_flag))
if (!error_flag_get_status(current_flag)) {
continue;
}
flag_weigth = get_flag_weight(current_flag);
/* Override the worst flag weigt set, if it is worse than the previous ones */
if (flag_weigth > worst)
worst = flag_weigth;
switch (flag_weigth) {
case SAFETY_FLAG_CONFIG_WEIGHT_NONE:
break;
@@ -1147,20 +1152,18 @@ static enum config_weight safety_controller_handle_weighted_flags(void)
}
}
return worst;
}
#ifndef DEBUGBUILD
static void external_watchdog_toggle(void)
static void external_watchdog_toggle()
{
SAFETY_EXT_WATCHDOG_PORT->ODR ^= (1<<SAFETY_EXT_WATCHDOG_PIN);
}
#endif
enum config_weight safety_controller_handle(void)
int safety_controller_handle()
{
enum config_weight worst_weight_set;
int ret = 0;
#ifndef DEBUGBUILD
static uint32_t watchdog_counter = 0UL;
#endif
@@ -1170,10 +1173,9 @@ enum config_weight safety_controller_handle(void)
safety_controller_handle_memory_checks();
safety_controller_do_systick_checking();
safety_controller_process_monitor_checks();
worst_weight_set = safety_controller_handle_weighted_flags();
safety_controller_handle_weighted_flags();
/* Ignore error here. Will trigger restart anyway */
(void)watchdog_ack(WATCHDOG_MAGIC_KEY);
ret |= watchdog_ack(WATCHDOG_MAGIC_KEY);
#ifndef DEBUGBUILD
if (get_pcb_hardware_version() != HW_REV_V1_2) {
@@ -1184,8 +1186,7 @@ enum config_weight safety_controller_handle(void)
}
}
#endif
return worst_weight_set;
return (ret ? -1 : 0);
}
int safety_controller_enable_timing_mon(enum timing_monitor monitor, bool enable)
@@ -1272,8 +1273,9 @@ int safety_controller_ack_flag_with_key(enum safety_flag flag, uint32_t key)
int ret = -1;
volatile struct error_flag *found_flag;
if (!is_power_of_two(flag))
if (!is_power_of_two(flag)) {
return -1001;
}
found_flag = find_error_flag(flag);
if (found_flag) {
@@ -1304,17 +1306,17 @@ bool safety_controller_get_flags_by_mask(enum safety_flag mask)
return ret;
}
uint32_t safety_controller_get_flag_count(void)
uint32_t safety_controller_get_flag_count()
{
return COUNT_OF(flags);
}
uint32_t safety_controller_get_analog_monitor_count(void)
uint32_t safety_controller_get_analog_monitor_count()
{
return COUNT_OF(analog_mons);
}
uint32_t safety_controller_get_timing_monitor_count(void)
uint32_t safety_controller_get_timing_monitor_count()
{
return COUNT_OF(timings);
}
@@ -1421,8 +1423,9 @@ int safety_controller_get_timing_mon_by_index(uint32_t index, struct timing_moni
if (!info)
return -1002;
if (index >= COUNT_OF(timings))
if (index >= COUNT_OF(timings)) {
return -1001;
}
mon = &timings[index];
@@ -1446,6 +1449,99 @@ float safety_controller_get_overtemp_limit(void)
return safety_controller_overtemp_config.overtemp_deg_celsius;
}
extern const uint32_t __ld_vectors_start;
extern const uint32_t __ld_vectors_end;
extern const uint32_t __ld_text_start;
extern const uint32_t __ld_text_end;
extern const uint32_t __ld_sdata_ccm;
extern const uint32_t __ld_edata_ccm;
extern const uint32_t __ld_load_ccm_data;
extern const uint32_t __ld_sdata;
extern const uint32_t __ld_edata;
extern const uint32_t __ld_load_data;
int safety_controller_trigger_flash_crc_check()
{
/* This structs needs to be volatile!!
* This prevents the compiler form optimizing out the reads to the crcs which will be patched in later by
* a separate python script!
*/
static volatile const struct flash_crcs IN_SECTION(.flashcrc) crcs_in_flash =
{
.start_magic = 0xA8BE53F9UL,
.crc_section_ccm_data = 0UL,
.crc_section_text = 0UL,
.crc_section_data = 0UL,
.crc_section_vectors = 0UL,
.end_magic = 0xFFA582FFUL,
};
int ret = -1;
uint32_t len;
uint32_t crc;
/* Perform CRC check over vector table */
len = (uint32_t)((void *)&__ld_vectors_end - (void *)&__ld_vectors_start);
if (len % 4) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
} else {
len /= 4;
crc_unit_reset();
crc_unit_input_array(&__ld_vectors_start, len);
crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_vectors) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
}
}
/* Perform CRC check over text section */
len = (uint32_t)((void *)&__ld_text_end - (void *)&__ld_text_start);
if (len % 4) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
} else {
len /= 4;
crc_unit_reset();
crc_unit_input_array(&__ld_text_start, len);
crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_text) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
}
}
/* Perform CRC check over data section */
len = (uint32_t)((void *)&__ld_edata - (void *)&__ld_sdata);
if (len % 4) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
} else {
len /= 4;
crc_unit_reset();
crc_unit_input_array(&__ld_load_data, len);
crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_data) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
}
}
/* Perform CRC check over ccm data section */
len = (uint32_t)((void *)&__ld_edata_ccm - (void *)&__ld_sdata_ccm);
if (len % 4) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
} else {
len /= 4;
crc_unit_reset();
crc_unit_input_array(&__ld_load_ccm_data, len);
crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_ccm_data) {
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
}
}
ret = 0;
return ret;
}
int safety_controller_set_crc_monitor(enum crc_monitor mon, uint32_t password)
{
uint32_t i;

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/safety/safety-memory.h>
#include <helper-macros/helper-macros.h>
@@ -99,8 +99,7 @@ static enum safety_memory_state safety_memory_get_header(struct safety_memory_he
res = 0;
if (header->boot_status_offset < wordsize_of(struct safety_memory_header))
res++;
if (header->config_overrides_offset < header->boot_status_offset +
wordsize_of(struct safety_memory_boot_status))
if (header->config_overrides_offset < header->boot_status_offset + wordsize_of(struct safety_memory_boot_status))
res++;
if (header->config_overrides_len > SAFETY_MEMORY_CONFIG_OVERRIDE_COUNT)
res++;
@@ -108,8 +107,7 @@ static enum safety_memory_state safety_memory_get_header(struct safety_memory_he
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)
if (header->err_memory_end >= backup_ram_get_size_in_words() || header->err_memory_end < header->err_memory_offset)
res++;
if (res) {
@@ -150,7 +148,7 @@ static void safety_memory_write_new_header(void)
safety_memory_write_and_patch_header(&header);
}
static int safety_memory_check_crc(void)
static int safety_memory_check_crc()
{
struct safety_memory_header header;
enum safety_memory_state state = safety_memory_get_header(&header);
@@ -183,7 +181,7 @@ static int safety_memory_check_crc(void)
return 0;
}
static int safety_memory_gen_crc(void)
static int safety_memory_gen_crc()
{
struct safety_memory_header header;
uint32_t word_addr;
@@ -270,8 +268,9 @@ int safety_memory_get_boot_status(struct safety_memory_boot_status *status)
if (!status)
return -1001;
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) {
return -2000;
}
if (safety_memory_check_crc())
return -2001;
@@ -290,8 +289,9 @@ int safety_memory_set_boot_status(const struct safety_memory_boot_status *status
if (!status)
return -1001;
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) {
return -2000;
}
if (safety_memory_check_crc())
return -2001;
@@ -304,7 +304,7 @@ int safety_memory_set_boot_status(const struct safety_memory_boot_status *status
return 0;
}
static int safety_memory_check_error_entries(void)
static int safety_memory_check_error_entries()
{
struct safety_memory_header header;
uint32_t addr;
@@ -312,8 +312,9 @@ static int safety_memory_check_error_entries(void)
int ret = 0;
int res;
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) {
return -2000;
}
for (addr = header.err_memory_offset; addr < header.err_memory_end; addr++) {
res = backup_ram_get_data(addr, &data, 1UL);
@@ -339,8 +340,9 @@ int safety_memory_get_error_entry_count(uint32_t *count)
if (!count)
return -1001;
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) {
return -2000;
}
*count = header.err_memory_end - header.err_memory_offset;
@@ -352,8 +354,9 @@ int safety_memory_check(void)
int res;
res = safety_memory_check_crc();
if (!res)
if (!res) {
res |= safety_memory_check_error_entries();
}
return -!!res;
}
@@ -369,8 +372,9 @@ int safety_memory_get_error_entry(uint32_t idx, struct error_memory_entry *entry
if (!entry)
return -1001;
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) {
return -2000;
}
err_mem_count = header.err_memory_end - header.err_memory_offset;
if (idx < err_mem_count && err_mem_count > 0) {
@@ -406,8 +410,9 @@ int safety_memory_insert_error_entry(struct error_memory_entry *entry)
input_data = error_memory_entry_to_word(entry);
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) {
return -2000;
}
if (entry->type == SAFETY_MEMORY_ERR_ENTRY_NOP) {
/* Append to end */
@@ -505,8 +510,9 @@ int safety_memory_insert_config_override(struct config_override *config_override
int res;
int ret = -3;
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) {
return -2000;
}
if (header.config_overrides_len == 0)
return -1;
@@ -544,8 +550,9 @@ int safety_memory_get_config_override_count(uint32_t *count)
*count = 0UL;
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) {
return -2000;
}
if (header.config_overrides_len == 0)
return 0;
@@ -575,15 +582,18 @@ int safety_memory_get_config_override(uint32_t idx, struct config_override *conf
if (!config_override)
return -1002;
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY)
if (safety_memory_get_header(&header) != SAFETY_MEMORY_INIT_VALID_MEMORY) {
return -2000;
}
if (idx >= header.config_overrides_len)
if (idx >= header.config_overrides_len) {
return -1001;
}
res = backup_ram_get_data(header.config_overrides_offset + idx, &data, 1UL);
if (res)
if (res) {
return -1;
}
switch (data & 0xFF) {
case 0xA2:
@@ -639,8 +649,8 @@ int safety_memory_get_update_filename(char *filename, size_t *outlen)
{
struct safety_memory_header header;
unsigned int i;
size_t len = 0u;
volatile char *ptr;
size_t len = 0u;
/* If filename and outlen are both NULL, we don't do anything */
if (!filename && !outlen)
@@ -686,9 +696,9 @@ int safety_memory_set_update_filename(const char *filename)
ram_ptr = backup_ram_get_base_ptr();
ram_ptr += header.firmware_update_filename * 4;
for (i = 0u; i < len; i++)
for (i = 0u; i < len; i++) {
ram_ptr[i] = filename[i];
}
ram_ptr[i] = 0;
ret = safety_memory_gen_crc();

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/safety/stack-check.h>
#include <stdint.h>
@@ -26,7 +26,7 @@
extern char __ld_top_of_stack;
extern char __ld_end_stack;
int32_t stack_check_get_usage(void)
int32_t stack_check_get_usage()
{
uint32_t stack_top;
uint32_t stack_ptr;
@@ -37,7 +37,7 @@ int32_t stack_check_get_usage(void)
return stack_top - stack_ptr;
}
int32_t stack_check_get_free(void)
int32_t stack_check_get_free()
{
uint32_t upper_heap_boundary;
uint32_t stack_ptr;
@@ -102,6 +102,9 @@ int stack_check_corruption_detect_area(void)
&__ld_start_stack_corruption_detect_area;
crc_unit_reset();
crc_unit_input_array(&__ld_start_stack_corruption_detect_area, area_size_in_words);
return crc_unit_get_crc() == 0UL ? 0 : -1;
if (crc_unit_get_crc() == 0UL) {
return 0;
} else {
return -1;
}
}

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @addtogroup watchdog
@@ -50,8 +50,7 @@ int watchdog_setup(uint8_t prescaler)
RCC->CSR |= RCC_CSR_LSION;
__DSB();
/** - Wait for the oscillator to be ready */
while (!(RCC->CSR & RCC_CSR_LSIRDY))
;
while (!(RCC->CSR & RCC_CSR_LSIRDY));
if (prescaler == 4U)
prescaler_reg_val = 0UL;
@@ -69,24 +68,23 @@ int watchdog_setup(uint8_t prescaler)
prescaler_reg_val = 6UL;
/** - (De)activate the watchdog during debug access according to @ref WATCHDOG_HALT_DEBUG */
if (WATCHDOG_HALT_DEBUG)
if (WATCHDOG_HALT_DEBUG) {
DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_IWDG_STOP;
else
} else {
DBGMCU->APB1FZ &= ~DBGMCU_APB1_FZ_DBG_IWDG_STOP;
}
/** - Unlock registers */
IWDG->KR = STM32_WATCHDOG_REGISTER_ACCESS_KEY;
/** - Wait until prescaler can be written */
while (IWDG->SR & IWDG_SR_PVU)
;
while (IWDG->SR & IWDG_SR_PVU);
/** - Write prescaler value */
IWDG->PR = prescaler_reg_val;
/* - Wait until reload value can be written */
while (IWDG->SR & IWDG_SR_RVU)
;
while (IWDG->SR & IWDG_SR_RVU);
/** - Set reload value fixed to 0xFFF */
IWDG->RLR = 0xFFFU;

View File

@@ -1,65 +0,0 @@
/* Reflow Oven Controller
*
* Copyright (C) 2022 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* GDSII-Converter is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/sd.h>
#include "fatfs/ff.h"
#include "fatfs/shimatta_sdio_driver/shimatta_sdio.h"
#include <stdint.h>
#include <string.h>
#include <helper-macros/helper-macros.h>
#include <reflow-controller/digio.h>
static bool sd_card_mounted_state = false;
bool mount_sd_card_if_avail(FATFS *fs)
{
FRESULT res;
static uint8_t IN_SECTION(.ccm.bss) inserted_counter = 0;
if (sdio_check_inserted() && sd_card_mounted_state) {
memset(fs, 0, sizeof(FATFS));
sdio_stop_clk();
inserted_counter = 0;
sd_card_mounted_state = false;
goto ret;
}
if (!sdio_check_inserted() && inserted_counter < 255)
inserted_counter++;
if (!sdio_check_inserted() && !sd_card_mounted_state && inserted_counter > 4) {
inserted_counter = 0;
res = f_mount(fs, "0:/", 1);
if (res == FR_OK) {
led_set(1, 1);
sd_card_mounted_state = true;
} else {
sd_card_mounted_state = false;
}
}
ret:
return sd_card_mounted_state;
}
bool sd_card_is_mounted(void)
{
return sd_card_mounted_state;
}

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/settings/settings-eeprom.h>
#include <reflow-controller/settings/spi-eeprom.h>
@@ -37,7 +37,6 @@ struct eeprom_calibration_settings {
};
#define EEPROM_OVER_TEMP_CONFIG_BASE_ADDR (EEPROM_CALIBRATION_BASE_ADDR + sizeof(struct eeprom_calibration_settings))
struct eeprom_over_temp_config {
float over_temperature;
uint32_t over_temp_crc;
@@ -55,7 +54,7 @@ static bool check_eeprom_header(void)
return true;
}
static void settings_eeprom_zero(void)
static void settings_eeprom_zero()
{
settings_eeprom_save_calibration(0.0f, 0.0f, false);
settings_eeprom_save_overtemp_limit(0.0f, false);
@@ -63,7 +62,7 @@ static void settings_eeprom_zero(void)
bool settings_eeprom_detect_and_prepare(void)
{
bool eeprom_ready = false;
bool eeprom_ready = false;;
int res;
@@ -78,10 +77,7 @@ bool settings_eeprom_detect_and_prepare(void)
if (check_eeprom_header() == false) {
/* Try to write a new header and check it again */
spi_eeprom_write(0, expected_header, sizeof(expected_header));
while (spi_eeprom_write_in_progress())
;
while (spi_eeprom_write_in_progress());
if (check_eeprom_header() == false) {
goto ret_deinit_crc;
} else {

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/settings/settings-sd-card.h>
#include <stm-periph/unique-id.h>
@@ -72,12 +72,18 @@ static int create_controller_folder(void)
ret = 0;
} else {
filesystem_result = f_mkdir(foldername);
ret = filesystem_result == FR_OK ? 1 : -1;
if (filesystem_result == FR_OK) {
ret = 1;
} else {
ret = -1;
}
}
return ret;
}
int sd_card_settings_save_calibration(float sens_deviation, float offset, bool active)
{
char path[200];

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/settings/settings.h>
#include <reflow-controller/settings/settings-sd-card.h>
@@ -39,7 +39,7 @@ int settings_load_calibration(float *sens_dev, float *offset)
int res;
if (settings_use_eeprom) {
res = settings_eeprom_load_calibration(sens_dev, offset, &active);
res =settings_eeprom_load_calibration(sens_dev, offset, &active);
if (!res && !active)
res = -1;
} else {

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller
*
* Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
*
* Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <reflow-controller/settings/spi-eeprom.h>
#include <stm-periph/spi.h>
@@ -52,7 +52,7 @@ static void eeprom_cs_deactivate(void)
SPI_EEPROM_SPI_PORT->ODR |= (1<<SPI_EEPROM_CS_PIN);
}
int spi_eeprom_init(void)
int spi_eeprom_init()
{
static struct stm_spi_dev spi_dev;
struct stm_spi_settings settings;
@@ -61,8 +61,7 @@ int spi_eeprom_init(void)
SPI_EEPROM_SPI_PORT->MODER &= MODER_DELETE(SPI_EEPROM_CS_PIN) & MODER_DELETE(SPI_EEPROM_MISO_PIN) &
MODER_DELETE(SPI_EEPROM_MOSI_PIN) & MODER_DELETE(SPI_EEPROM_SCK_PIN);
SPI_EEPROM_SPI_PORT->MODER |= ALTFUNC(SPI_EEPROM_MISO_PIN) | ALTFUNC(SPI_EEPROM_SCK_PIN) |
ALTFUNC(SPI_EEPROM_MOSI_PIN);
SPI_EEPROM_SPI_PORT->MODER |= ALTFUNC(SPI_EEPROM_MISO_PIN) | ALTFUNC(SPI_EEPROM_SCK_PIN) | ALTFUNC(SPI_EEPROM_MOSI_PIN);
SPI_EEPROM_SPI_PORT->MODER |= OUTPUT(SPI_EEPROM_CS_PIN);
SETAF(SPI_EEPROM_SPI_PORT, SPI_EEPROM_MISO_PIN, SPI_EEPROM_SPI_ALTFUNC_NO);
@@ -86,7 +85,7 @@ int spi_eeprom_init(void)
return -1;
}
void spi_eeprom_deinit(void)
void spi_eeprom_deinit()
{
spi_deinit(eeprom_spi_handle);
@@ -167,8 +166,7 @@ static void spi_eeprom_do_write_page(uint32_t addr, const uint8_t *data, uint8_t
uint8_t cmd[2];
/* Wait for the previous write to finish */
while (spi_eeprom_write_in_progress())
;
while (spi_eeprom_write_in_progress());
/* Set the write enable latch */
spi_eeprom_set_write_enable_latch(true);

View File

@@ -46,8 +46,7 @@ void backup_ram_init(bool use_backup_regulator)
PWR->CSR |= PWR_CSR_BRE;
/* Wait until regulator is ready */
while (!(PWR->CSR & PWR_CSR_BRR))
;
while (!(PWR->CSR & PWR_CSR_BRR));
}
/* Enable clock for backup ram interface */

View File

@@ -37,10 +37,11 @@ static size_t calculate_ring_buffer_fill_level(size_t buffer_size, size_t get_id
{
size_t fill_level;
if (put_idx >= get_idx)
if (put_idx >= get_idx) {
fill_level = (put_idx - get_idx);
else
} else {
fill_level = buffer_size - get_idx + put_idx;
}
return fill_level;
}
@@ -48,7 +49,7 @@ static size_t calculate_ring_buffer_fill_level(size_t buffer_size, size_t get_id
static int dma_ring_buffer_switch_clock_enable(uint8_t base_dma, bool clk_en)
{
int ret_val;
int (*clk_func)(volatile uint32_t *reg, uint8_t bit_no);
int (*clk_func)(volatile uint32_t *, uint8_t);
if (clk_en)
clk_func = rcc_manager_enable_clock;
@@ -71,9 +72,8 @@ static int dma_ring_buffer_switch_clock_enable(uint8_t base_dma, bool clk_en)
}
int dma_ring_buffer_periph_to_mem_initialize(struct dma_ring_buffer_to_mem *dma_buffer, uint8_t base_dma_id,
DMA_Stream_TypeDef *dma_stream, size_t buffer_element_count,
size_t element_size, volatile void *data_buffer,
void *src_reg, uint8_t dma_trigger_channel)
DMA_Stream_TypeDef *dma_stream, size_t buffer_element_count, size_t element_size,
volatile void *data_buffer, void* src_reg, uint8_t dma_trigger_channel)
{
int ret_val = 0;
@@ -106,8 +106,7 @@ int dma_ring_buffer_periph_to_mem_initialize(struct dma_ring_buffer_to_mem *dma_
return 0;
}
int dma_ring_buffer_periph_to_mem_get_data(struct dma_ring_buffer_to_mem *buff, const volatile void **data_buff,
size_t *len)
int dma_ring_buffer_periph_to_mem_get_data(struct dma_ring_buffer_to_mem *buff, const volatile void **data_buff, size_t *len)
{
int ret_code = 0;
uint32_t ndtr;
@@ -168,10 +167,7 @@ int dma_ring_buffer_periph_to_mem_fill_level(struct dma_ring_buffer_to_mem *buff
return 0;
}
int dma_ring_buffer_mem_to_periph_initialize(struct dma_ring_buffer_to_periph *dma_buffer, uint8_t base_dma_id,
DMA_Stream_TypeDef *dma_stream, size_t buffer_element_count,
size_t element_size, volatile void *data_buffer,
uint8_t dma_trigger_channel, void *dest_reg)
int dma_ring_buffer_mem_to_periph_initialize(struct dma_ring_buffer_to_periph *dma_buffer, uint8_t base_dma_id, DMA_Stream_TypeDef *dma_stream, size_t buffer_element_count, size_t element_size, volatile void *data_buffer, uint8_t dma_trigger_channel, void *dest_reg)
{
if (!dma_buffer || !dma_stream || !data_buffer || !dest_reg)
return -1000;
@@ -225,8 +221,7 @@ static void queue_or_start_dma_transfer(struct dma_ring_buffer_to_periph *buff)
buff->dma->CR |= DMA_SxCR_EN;
}
int dma_ring_buffer_mem_to_periph_insert_data(struct dma_ring_buffer_to_periph *buff, const void *data_to_insert,
size_t count)
int dma_ring_buffer_mem_to_periph_insert_data(struct dma_ring_buffer_to_periph *buff, const void *data_to_insert, size_t count)
{
int ret = 0;
size_t free_item_count;
@@ -239,8 +234,7 @@ int dma_ring_buffer_mem_to_periph_insert_data(struct dma_ring_buffer_to_periph *
return -1000;
/* Check if data fits into buffer minus one element. If not: try full-1 buffer and rest
* Buffer is not allowed to be completely full, because I cannot ddifferentiate a full buffer from a
* completely empty one
* Buffer is not allowed to be completely full, because I cannot ddifferentiate a full buffer from a completely empty one
*/
if (count >= buff->buffer_count) {
ret = dma_ring_buffer_mem_to_periph_insert_data(buff, data_to_insert, buff->buffer_count - 1);
@@ -253,9 +247,7 @@ int dma_ring_buffer_mem_to_periph_insert_data(struct dma_ring_buffer_to_periph *
/* Wait for buffer to be able to handle input */
do {
free_item_count = buff->buffer_count -
calculate_ring_buffer_fill_level(buff->buffer_count, buff->dma_get_idx_current,
buff->sw_put_idx);
free_item_count = buff->buffer_count - calculate_ring_buffer_fill_level(buff->buffer_count, buff->dma_get_idx_current, buff->sw_put_idx);
} while (free_item_count < count+1);
/* Fillup buffer (max is buffer end, wrap around afterwards) */
@@ -269,7 +261,7 @@ int dma_ring_buffer_mem_to_periph_insert_data(struct dma_ring_buffer_to_periph *
buff->sw_put_idx += count;
/* If buffer is used up to last element, set put index to beginning */
if (buff->sw_put_idx >= buff->buffer_count)
if(buff->sw_put_idx >= buff->buffer_count)
buff->sw_put_idx = 0;
} else {
/* Fill up to end of buffer and fill rest after wrap around */

View File

@@ -76,14 +76,12 @@ int stm_option_bytes_program(const struct option_bytes *opts)
reg |= (opts->read_protection << 8) & FLASH_OPTCR_RDP;
reg |= (opts->wdg_sw << 5) & FLASH_OPTCR_WDG_SW;
while (FLASH->SR & FLASH_SR_BSY)
;
while (FLASH->SR & FLASH_SR_BSY);
FLASH->OPTCR = reg;
FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT;
__DSB();
while (FLASH->SR & FLASH_SR_BSY)
;
while (FLASH->SR & FLASH_SR_BSY);
FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;

View File

@@ -95,8 +95,9 @@ int rcc_manager_enable_clock(volatile uint32_t *rcc_enable_register, uint8_t bit
int ret_val = 0;
struct rcc_enable_count *entry;
if (!rcc_enable_register || bit_no > 31)
if (!rcc_enable_register || bit_no > 31) {
return -1000;
}
/* Enable the clock in any case, no matter what follows */
*rcc_enable_register |= (1U<<bit_no);
@@ -131,8 +132,9 @@ int rcc_manager_disable_clock(volatile uint32_t *rcc_enable_register, uint8_t bi
int ret_val = -1;
struct rcc_enable_count *entry;
if (!rcc_enable_register || bit_no > 31)
if (!rcc_enable_register || bit_no > 31) {
return -1000;
}
entry = search_enable_entry_in_list(rcc_enable_register, bit_no);

View File

@@ -30,7 +30,7 @@ void random_number_gen_init(bool int_enable)
random_number_gen_reset(int_enable);
}
void random_number_gen_deinit(void)
void random_number_gen_deinit()
{
RNG->CR = 0;
__DSB();
@@ -66,5 +66,5 @@ enum random_number_error random_number_gen_get_number(uint32_t *random_number, b
*random_number = RNG->DR;
/* Return from function with proper status */
return value_ready ? RNG_ERROR_OK : RNG_ERROR_NOT_READY;
return (value_ready ? RNG_ERROR_OK : RNG_ERROR_NOT_READY);
}

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller
*
* Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
*
* Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stm-periph/spi.h>
#include <helper-macros/helper-macros.h>
@@ -65,8 +65,7 @@ static struct stm_spi_dev *spi_handle_to_struct(stm_spi_handle handle)
return dev;
}
stm_spi_handle spi_init(struct stm_spi_dev *spi_dev_struct, SPI_TypeDef *spi_regs,
const struct stm_spi_settings *settings)
stm_spi_handle spi_init(struct stm_spi_dev *spi_dev_struct, SPI_TypeDef *spi_regs, const struct stm_spi_settings *settings)
{
stm_spi_handle ret_handle = NULL;
uint32_t reg_val;
@@ -132,14 +131,10 @@ void spi_deinit(stm_spi_handle handle)
static uint8_t transfer_byte(uint8_t byte, struct stm_spi_dev *dev)
{
while (dev->spi_regs->SR & SPI_SR_BSY)
;
while (dev->spi_regs->SR & SPI_SR_BSY);
dev->spi_regs->DR = (uint16_t)byte;
__DSB();
while ((dev->spi_regs->SR & SPI_SR_BSY) || !(dev->spi_regs->SR & SPI_SR_TXE))
;
while((dev->spi_regs->SR & SPI_SR_BSY) || !(dev->spi_regs->SR & SPI_SR_TXE));
return (uint8_t)dev->spi_regs->DR;
}

View File

@@ -1,227 +1,224 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stm-periph/uart.h>
#include <stm32/stm32f4xx.h>
#include <stm-periph/rcc-manager.h>
#include <stm-periph/stm32-gpio-macros.h>
#include <stm-periph/dma-ring-buffer.h>
#include <string.h>
int uart_init(struct stm_uart *uart)
{
int ret_val = 0;
uint32_t cr3 = 0;
uint32_t cr1 = 0;
if (!uart)
return -1000;
rcc_manager_enable_clock(uart->rcc_reg, uart->rcc_bit_no);
/* Reset all config regs */
uart->uart_dev->CR1 = uart->uart_dev->CR2 = uart->uart_dev->CR3 = 0UL;
/* Set baud rate */
uart->uart_dev->BRR = uart->brr_val;
/* If DMA buffers are present, configure for DMA use */
if (uart->dma_rx_buff && uart->rx) {
cr3 |= USART_CR3_DMAR;
ret_val = dma_ring_buffer_periph_to_mem_initialize(&uart->rx_ring_buff,
uart->base_dma_num,
uart->dma_rx_stream,
uart->rx_buff_count,
1U,
uart->dma_rx_buff,
(char *)&uart->uart_dev->DR,
uart->dma_rx_trigger_channel);
if (ret_val)
return ret_val;
}
if (uart->dma_tx_buff && uart->tx) {
ret_val = dma_ring_buffer_mem_to_periph_initialize(&uart->tx_ring_buff,
uart->base_dma_num,
uart->dma_tx_stream,
uart->tx_buff_count,
1U,
uart->dma_tx_buff,
uart->dma_tx_trigger_channel,
(void *)&uart->uart_dev->DR);
if (ret_val)
return ret_val;
cr3 |= USART_CR3_DMAT;
}
uart->uart_dev->CR3 = cr3;
if (uart->tx)
cr1 |= USART_CR1_TE;
if (uart->rx)
cr1 |= USART_CR1_RE;
/* Enable uart */
cr1 |= USART_CR1_UE;
uart->uart_dev->CR1 = cr1;
return 0;
}
void uart_change_brr(struct stm_uart *uart, uint32_t brr)
{
if (!uart || !uart->uart_dev)
return;
uart->brr_val = brr;
uart->uart_dev->BRR = brr;
}
uint32_t uart_get_brr(struct stm_uart *uart)
{
if (!uart || !uart->uart_dev)
return 0;
return uart->brr_val;
}
void uart_disable(struct stm_uart *uart)
{
if (!uart)
return;
uart->uart_dev->CR1 = 0;
uart->uart_dev->CR2 = 0;
uart->uart_dev->CR3 = 0;
if (uart->rx && uart->dma_rx_buff)
dma_ring_buffer_periph_to_mem_stop(&uart->rx_ring_buff);
if (uart->dma_tx_buff && uart->tx)
dma_ring_buffer_mem_to_periph_stop(&uart->tx_ring_buff);
rcc_manager_disable_clock(uart->rcc_reg, uart->rcc_bit_no);
}
void uart_send_char(struct stm_uart *uart, char c)
{
if (!uart || !uart->uart_dev)
return;
while (!(uart->uart_dev->SR & USART_SR_TXE))
;
uart->uart_dev->DR = c;
}
void uart_send_array(struct stm_uart *uart, const char *data, uint32_t len)
{
uint32_t i;
for (i = 0; i < len; i++)
uart_send_char(uart, data[i]);
}
void uart_send_string(struct stm_uart *uart, const char *string)
{
int i;
for (i = 0; string[i] != '\0'; i++)
uart_send_char(uart, string[i]);
}
void uart_send_array_with_dma(struct stm_uart *uart, const char *data, uint32_t len)
{
if (!uart || !uart->dma_tx_buff)
return;
dma_ring_buffer_mem_to_periph_insert_data(&uart->tx_ring_buff, data, len);
}
void uart_send_string_with_dma(struct stm_uart *uart, const char *string)
{
size_t len;
len = strlen(string);
uart_send_array_with_dma(uart, string, (uint32_t)len);
}
int uart_receive_data_with_dma(struct stm_uart *uart, const char **data, size_t *len)
{
if (!uart)
return -1000;
return dma_ring_buffer_periph_to_mem_get_data(&uart->rx_ring_buff, (const volatile void **)data, len);
}
char uart_get_char(struct stm_uart *uart)
{
if (!uart)
return 0;
/* Wait for data to be available */
while (!(uart->uart_dev->SR & USART_SR_RXNE))
;
return (char)uart->uart_dev->DR;
}
int uart_check_rx_avail(struct stm_uart *uart)
{
if (!uart)
return 0;
if (uart->uart_dev->SR & USART_SR_RXNE)
return 1;
else
return 0;
}
void uart_tx_dma_complete_int_callback(struct stm_uart *uart)
{
if (!uart)
return;
dma_ring_buffer_mem_to_periph_int_callback(&uart->tx_ring_buff);
}
size_t uart_dma_tx_queue_avail(struct stm_uart *uart)
{
size_t fill_level = 0UL;
if (!uart)
return 0UL;
(void)dma_ring_buffer_mem_to_periph_fill_level(&uart->tx_ring_buff, &fill_level);
return fill_level;
}
size_t uart_dma_rx_queue_avail(struct stm_uart *uart)
{
size_t fill_level = 0UL;
if (!uart)
return 0UL;
(void)dma_ring_buffer_periph_to_mem_fill_level(&uart->rx_ring_buff, &fill_level);
return fill_level;
}
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stm-periph/uart.h>
#include <stm32/stm32f4xx.h>
#include <stm-periph/rcc-manager.h>
#include <stm-periph/stm32-gpio-macros.h>
#include <stm-periph/dma-ring-buffer.h>
#include <string.h>
int uart_init(struct stm_uart *uart)
{
int ret_val = 0;
uint32_t cr3 = 0;
uint32_t cr1 = 0;
if (!uart)
return -1000;
rcc_manager_enable_clock(uart->rcc_reg, uart->rcc_bit_no);
/* Reset all config regs */
uart->uart_dev->CR1 = uart->uart_dev->CR2 = uart->uart_dev->CR3 = 0UL;
/* Set baud rate */
uart->uart_dev->BRR = uart->brr_val;
/* If DMA buffers are present, configure for DMA use */
if (uart->dma_rx_buff && uart->rx) {
cr3 |= USART_CR3_DMAR;
ret_val = dma_ring_buffer_periph_to_mem_initialize(&uart->rx_ring_buff,
uart->base_dma_num,
uart->dma_rx_stream,
uart->rx_buff_count,
1U,
uart->dma_rx_buff,
(char *)&uart->uart_dev->DR,
uart->dma_rx_trigger_channel);
if (ret_val)
return ret_val;
}
if (uart->dma_tx_buff && uart->tx) {
ret_val = dma_ring_buffer_mem_to_periph_initialize(&uart->tx_ring_buff,
uart->base_dma_num,
uart->dma_tx_stream,
uart->tx_buff_count,
1U,
uart->dma_tx_buff,
uart->dma_tx_trigger_channel,
(void *)&uart->uart_dev->DR);
if (ret_val)
return ret_val;
cr3 |= USART_CR3_DMAT;
}
uart->uart_dev->CR3 = cr3;
if (uart->tx)
cr1 |= USART_CR1_TE;
if (uart->rx)
cr1 |= USART_CR1_RE;
/* Enable uart */
cr1 |= USART_CR1_UE;
uart->uart_dev->CR1 = cr1;
return 0;
}
void uart_change_brr(struct stm_uart *uart, uint32_t brr)
{
if (!uart || !uart->uart_dev)
return;
uart->brr_val = brr;
uart->uart_dev->BRR = brr;
}
uint32_t uart_get_brr(struct stm_uart *uart)
{
if (!uart || !uart->uart_dev)
return 0;
return uart->brr_val;
}
void uart_disable(struct stm_uart *uart)
{
if (!uart)
return;
uart->uart_dev->CR1 = 0;
uart->uart_dev->CR2 = 0;
uart->uart_dev->CR3 = 0;
if (uart->rx && uart->dma_rx_buff)
dma_ring_buffer_periph_to_mem_stop(&uart->rx_ring_buff);
if (uart->dma_tx_buff && uart->tx)
dma_ring_buffer_mem_to_periph_stop(&uart->tx_ring_buff);
rcc_manager_disable_clock(uart->rcc_reg, uart->rcc_bit_no);
}
void uart_send_char(struct stm_uart *uart, char c)
{
if (!uart || !uart->uart_dev)
return;
while(!(uart->uart_dev->SR & USART_SR_TXE));
uart->uart_dev->DR = c;
}
void uart_send_array(struct stm_uart *uart, const char *data, uint32_t len)
{
uint32_t i;
for (i = 0; i < len; i++)
uart_send_char(uart, data[i]);
}
void uart_send_string(struct stm_uart *uart, const char *string)
{
int i;
for (i = 0; string[i] != '\0'; i++)
uart_send_char(uart, string[i]);
}
void uart_send_array_with_dma(struct stm_uart *uart, const char *data, uint32_t len)
{
if (!uart || !uart->dma_tx_buff)
return;
dma_ring_buffer_mem_to_periph_insert_data(&uart->tx_ring_buff, data, len);
}
void uart_send_string_with_dma(struct stm_uart *uart, const char *string)
{
size_t len;
len = strlen(string);
uart_send_array_with_dma(uart, string, (uint32_t)len);
}
int uart_receive_data_with_dma(struct stm_uart *uart, const char **data, size_t *len)
{
if (!uart)
return -1000;
return dma_ring_buffer_periph_to_mem_get_data(&uart->rx_ring_buff, (const volatile void **)data, len);
}
char uart_get_char(struct stm_uart *uart)
{
if (!uart)
return 0;
/* Wait for data to be available */
while (!(uart->uart_dev->SR & USART_SR_RXNE));
return (char)uart->uart_dev->DR;
}
int uart_check_rx_avail(struct stm_uart *uart)
{
if (!uart)
return 0;
if (uart->uart_dev->SR & USART_SR_RXNE)
return 1;
else
return 0;
}
void uart_tx_dma_complete_int_callback(struct stm_uart *uart)
{
if (!uart)
return;
dma_ring_buffer_mem_to_periph_int_callback(&uart->tx_ring_buff);
}
size_t uart_dma_tx_queue_avail(struct stm_uart *uart)
{
size_t fill_level = 0UL;
if (!uart)
return 0UL;
(void)dma_ring_buffer_mem_to_periph_fill_level(&uart->tx_ring_buff, &fill_level);
return fill_level;
}
size_t uart_dma_rx_queue_avail(struct stm_uart *uart)
{
size_t fill_level = 0UL;
if (!uart)
return 0UL;
(void)dma_ring_buffer_periph_to_mem_fill_level(&uart->rx_ring_buff, &fill_level);
return fill_level;
}

View File

@@ -43,23 +43,3 @@ void stm_dev_rev_id_get(uint32_t *device_id, uint32_t *revision_id)
if (revision_id)
*revision_id = (DBGMCU->IDCODE & DBGMCU_IDCODE_REV_ID) >> 16;
}
void stm_cpuid_get(uint8_t *implementer, uint8_t *variant, uint16_t *part_no, uint8_t *rev)
{
uint32_t cpuid;
cpuid = SCB->CPUID;
if (implementer)
*implementer = (uint8_t)((cpuid >> 24) & 0xFFU);
if (variant)
*variant = (uint8_t)((cpuid >> 20) & 0x0FU);
if (part_no)
*part_no = (uint16_t)((cpuid >> 4) & 0x0FFFU);
if (rev)
*rev = (uint8_t)(cpuid & 0x0FU);
}

View File

@@ -22,7 +22,6 @@
#include <reflow-controller/ui/gui-config.h>
#include <reflow-controller/ui/menu.h>
#include <reflow-controller/ui/lcd.h>
#include <reflow-controller/sd.h>
#include <reflow-controller/ui/rotary-encoder.h>
#include <reflow-controller/systick.h>
#include <reflow-controller/adc-meas.h>
@@ -692,37 +691,6 @@ static void gui_update_firmware(struct lcd_menu *menu, enum menu_entry_func_entr
}
}
static void gui_connector_info(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
{
static void *my_parent;
enum button_state button;
if (entry_type == MENU_ENTRY_FIRST_ENTER) {
my_parent = parent;
menu_display_clear(menu);
menu_lcd_output(menu, 0, "2,4: DIGIO[0,1]");
menu_lcd_output(menu, 1, "6: DIGIO2 (TX)");
menu_lcd_output(menu, 2, "8: DIGIO3 (RX)");
menu_lcd_output(menu, 3, "10:3V3 Rest:GND");
}
if (menu_get_button_ready_state(menu)) {
/* Buttons are ready. Read button */
button = menu_get_button_state(menu);
/* Throw away any rotation */
(void)menu_get_rotary_delta(menu);
if (button == BUTTON_SHORT_RELEASED || button == BUTTON_LONG ||
button == BUTTON_LONG_RELEASED) {
/* Exit menu */
menu_entry_dropback(menu, my_parent);
}
}
}
static char *overlay_heading = NULL;
static char *overlay_text = NULL;
@@ -772,7 +740,6 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
"Error Flags",
"About",
"Update",
"Connector Info",
NULL
};
static const menu_func_t root_entry_funcs[] = {
@@ -782,7 +749,6 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
gui_menu_err_flags,
gui_menu_about,
gui_update_firmware,
gui_connector_info,
};
enum button_state push_button;
int16_t rot_delta;
@@ -790,6 +756,7 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
if (entry_type != MENU_ENTRY_CONTINUE) {
menu_changed = true;
menu_display_clear(menu);
update_display_buffer(0, "Main Menu");
menu_ack_rotary_delta(menu);
if (entry_type == MENU_ENTRY_FIRST_ENTER) {
list.entry_names = root_entry_names;
@@ -800,8 +767,6 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
}
}
update_display_buffer(0, sd_card_is_mounted() ? "Main Menu [SD]" : "Main Menu [--]");
push_button = menu_get_button_state(menu);
rot_delta = menu_get_rotary_delta(menu);

View File

@@ -48,7 +48,6 @@
#include <stm-periph/option-bytes.h>
#include <reflow-controller/ui/gui.h>
#include <reflow-controller/ui/shell-uart.h>
#include <reflow-controller/safety/flash-crc.h>
#include <stdio.h>
@@ -71,10 +70,6 @@ static shellmatta_retCode_t shell_cmd_ver(const shellmatta_handle_t handle,
uint32_t high_id;
uint32_t stm_rev_id;
uint32_t stm_dev_id;
uint8_t core_rev;
uint8_t core_implementer;
uint8_t core_variant;
uint16_t core_part_no;
const char *hw_rev_str;
enum hw_revision pcb_rev;
@@ -82,7 +77,7 @@ static shellmatta_retCode_t shell_cmd_ver(const shellmatta_handle_t handle,
stm_dev_rev_id_get(&stm_dev_id, &stm_rev_id);
shellmatta_printf(handle, "Reflow Oven Controller Firmware " xstr(GIT_VER) "\r\n"
"Compiled: " __DATE__ " at " __TIME__ "\r\n");
"Compiled: " __DATE__ " at " __TIME__ "\r\n");
shellmatta_printf(handle, "Serial: %08X-%08X-%08X\r\n", high_id, mid_id, low_id);
pcb_rev = get_pcb_hardware_version();
@@ -105,12 +100,6 @@ static shellmatta_retCode_t shell_cmd_ver(const shellmatta_handle_t handle,
shellmatta_printf(handle, "STM Device ID: 0x%04X\r\n", stm_dev_id);
shellmatta_printf(handle, "STM Revision ID: 0x%04X\r\n", stm_rev_id);
stm_cpuid_get(&core_implementer, &core_variant, &core_part_no, &core_rev);
shellmatta_printf(handle, "CPU Implementer: 0x%02X\r\n", (unsigned int)core_implementer);
shellmatta_printf(handle, "CPU Variant: 0x%02X\r\n", (unsigned int)core_variant);
shellmatta_printf(handle, "CPU Part No.: 0x%04X\r\n", (unsigned int)core_part_no);
shellmatta_printf(handle, "CPU Revision: 0x%02X\r\n", (unsigned int)core_rev);
return SHELLMATTA_OK;
}
@@ -860,7 +849,6 @@ shellmatta_retCode_t shell_cmd_execute(const shellmatta_handle_t handle, const c
shellmatta_retCode_t shell_cmd_cycle_count(const shellmatta_handle_t handle, const char *args, uint32_t len)
{
uint64_t counter;
uint32_t core_cycle_count;
(void)args;
(void)len;
char option;
@@ -868,10 +856,8 @@ shellmatta_retCode_t shell_cmd_cycle_count(const shellmatta_handle_t handle, con
uint32_t arg_len;
int opt_stat;
bool clear = false;
bool hex = false;
const shellmatta_opt_long_t options[] = {
{"clear", 'c', SHELLMATTA_OPT_ARG_NONE},
{"hex", 'h', SHELLMATTA_OPT_ARG_NONE},
{NULL, '\0', SHELLMATTA_OPT_ARG_NONE},
};
@@ -883,8 +869,6 @@ shellmatta_retCode_t shell_cmd_cycle_count(const shellmatta_handle_t handle, con
case 'c':
clear = true;
break;
case 'h':
hex = true;
default:
break;
}
@@ -892,18 +876,10 @@ shellmatta_retCode_t shell_cmd_cycle_count(const shellmatta_handle_t handle, con
counter = main_cycle_counter_get();
core_cycle_count = DWT->CYCCNT;
if (hex) {
shellmatta_printf(handle, "Main loop: 0x%016"PRIX64"\r\n", counter);
shellmatta_printf(handle, "CPU cycles: 0x%08"PRIX32"\r\n", core_cycle_count);
} else {
shellmatta_printf(handle, "Main loop: %"PRIu64"\r\n", counter);
shellmatta_printf(handle, "CPU cycles: %"PRIu32"\r\n", core_cycle_count);
}
if (clear) {
shellmatta_printf(handle, "%"PRIu64"\r\n", counter);
if (clear)
main_cycle_counter_init();
DWT->CYCCNT = 0UL;
}
return SHELLMATTA_OK;
}
@@ -1021,53 +997,6 @@ shellmatta_retCode_t shell_cmd_set_baud(const shellmatta_handle_t handle, const
return SHELLMATTA_OK;
}
static void shell_print_crc_line(const shellmatta_handle_t handle, const char *name,
uint32_t crc, uint32_t crc_expected)
{
shellmatta_printf(handle, "%-15s0x%08x 0x%08x [%s]\r\n",
name,
crc,
crc_expected,
crc != crc_expected ? "\e[1;31mERR\e[m" : "\e[32mOK\e[m");
}
shellmatta_retCode_t shell_cmd_flash_crc(const shellmatta_handle_t handle, const char *args, uint32_t len)
{
(void)args;
(void)len;
uint32_t crc = 0;
uint32_t crc_expected = 0;
int res;
shellmatta_printf(handle, " Calculated Expected State\r\n\r\n");
res = flash_crc_calc_section(FLASH_CRC_VECTOR, &crc);
crc_expected = flash_crc_get_expected_crc(FLASH_CRC_VECTOR);
if (res)
shellmatta_printf(handle, "Error during calculation!\r\n");
shell_print_crc_line(handle, "Vector CRC:", crc, crc_expected);
res = flash_crc_calc_section(FLASH_CRC_TEXT, &crc);
crc_expected = flash_crc_get_expected_crc(FLASH_CRC_TEXT);
if (res)
shellmatta_printf(handle, "Error during calculation!\r\n");
shell_print_crc_line(handle, "Code CRC:", crc, crc_expected);
res = flash_crc_calc_section(FLASH_CRC_DATA, &crc);
crc_expected = flash_crc_get_expected_crc(FLASH_CRC_DATA);
if (res)
shellmatta_printf(handle, "Error during calculation!\r\n");
shell_print_crc_line(handle, "Data CRC:", crc, crc_expected);
res = flash_crc_calc_section(FLASH_CRC_CCMDATA, &crc);
crc_expected = flash_crc_get_expected_crc(FLASH_CRC_CCMDATA);
if (res)
shellmatta_printf(handle, "Error during calculation!\r\n");
shell_print_crc_line(handle, "CCM Data CRC:", crc, crc_expected);
return SHELLMATTA_OK;
}
//typedef struct shellmatta_cmd
//{
// char *cmd; /**< command name */
@@ -1077,7 +1006,7 @@ shellmatta_retCode_t shell_cmd_flash_crc(const shellmatta_handle_t handle, const
// shellmatta_cmdFct_t cmdFct; /**< pointer to the cmd callack function */
// struct shellmatta_cmd *next; /**< pointer to next command or NULL */
//} shellmatta_cmd_t;
static shellmatta_cmd_t cmd[26] = {
static shellmatta_cmd_t cmd[25] = {
{
.cmd = "version",
.cmdAlias = "ver",
@@ -1273,18 +1202,10 @@ static shellmatta_cmd_t cmd[26] = {
},
{
.cmd = "baudrate",
.cmdAlias = "baud",
.cmdAlias = "opt-bytes",
.helpText = "Set a new temporary baudrate for the UART",
.usageText = "baudrate <new baud>",
.cmdFct = shell_cmd_set_baud,
.next = &cmd[25],
},
{
.cmd = "flashcrc",
.cmdAlias = "fcrc",
.helpText = "Calculate the Flash CRCs",
.usageText = "flashcrc",
.cmdFct = shell_cmd_flash_crc,
.next = NULL,
},

View File

@@ -0,0 +1,43 @@
LEXER := flex
YACC := bison
CC := gcc
YACC_FLAGS := -yd
LEXER_FLAGS :=
LANG_NAME := lang
ifneq ($(VERBOSE),true)
QUIET=@
else
QUIET=
endif
default: test
y.tab.c: $(LANG_NAME).yacc
$(QUIET)echo "[$(YACC)] $@"
$(QUIET)$(YACC) $(YACC_FLAGS) $<
lex.yy.c: $(LANG_NAME).lex
$(QUIET)echo "[$(LEXER)] $@"
$(QUIET)$(LEXER) $^
test: y.tab.c lex.yy.c
$(QUIET)echo "[CC] $@"
$(QUIET)$(CC) -o $@ $^
.PHONY: clean run
run: test
./test
clean:
$(QUIET)echo "Clean up..."
$(QUIET)rm -f *.c *.o y.tab.h test

View File

@@ -0,0 +1,45 @@
%{
#include <stdio.h>
#include "y.tab.h"
%}
/*
static const struct pl_command_list_map cmd_list_map[_PL_NUM_CMDS] = {
{PL_PID_CONF, "pid_conf", 6u},
{PL_SET_TEMP, "temp_set", 1u},
{PL_WAIT_FOR_TEMP, "wait_temp", 1u},
{PL_WAIT_FOR_TIME, "wait_time", 1u},
{PL_SET_RAMP, "temp_ramp", 2u},
{PL_LOUDSPEAKER_SET, "beep", 1u},
{PL_OFF, "temp_off", 0u},
{PL_CLEAR_FLAGS, "clear_flags", 0u},
{PL_DIGIO_CONF, "digio_conf", 2u},
{PL_DIGIO_SET, "digio_set", 2u},
{PL_DIGIO_WAIT, "digio_wait", 2u},
};
*/
%option yylineno
%%
#[^\n]* return COMMENT;
pid_conf return PL_PID_CONF;
temp_set return PL_SET_TEMP;
wait_temp return PL_WAIT_FOR_TEMP;
wait_time return PL_WAIT_FOR_TIME;
temp_ramp return PL_SET_RAMP;
beep return PL_LOUDSPEAKER_SET;
temp_off return PL_OFF;
clear_flags return PL_CLEAR_FLAGS;
digio_conf return PL_DIGIO_CONF;
digio_set return PL_DIGIO_SET;
digio_wait return PL_DIGIO_WAIT;
[+-]?[0-9]+ yylval.int_value=atoi(yytext); return INT_NUMBER;
[+-]?[0-9]+[.]?[0-9]* yylval.float_value=atof(yytext); return NUMBER;
[ \t]+ /* Ignore whitespaces */;
[\r]?\n return NEWLINE;
[^\t\n #]+ return LITERAL;
%%

View File

@@ -0,0 +1,137 @@
%{
#include <stdio.h>
#include <string.h>
extern int yylineno;
extern int yylex();
extern int yyparse();
void yyerror(const char *str)
{
fprintf(stderr, "Error: %s, line %d\n", str, yylineno);
}
int yywrap()
{
return 1;
}
int main()
{
yyparse();
return 0;
}
%}
%locations
%token COMMENT PL_PID_CONF PL_SET_TEMP PL_WAIT_FOR_TEMP PL_WAIT_FOR_TIME PL_SET_RAMP PL_LOUDSPEAKER_SET PL_OFF PL_CLEAR_FLAGS PL_DIGIO_CONF PL_DIGIO_SET PL_DIGIO_WAIT NEWLINE LITERAL
%token <float_value> NUMBER
%token <int_value> INT_NUMBER
%type <float_value> any_num
%union
{
int int_value;
float float_value;
}
%%
program: /* empty */
| program command
| program NEWLINE
| program cmt_line
;
command:
command_core NEWLINE
|
command_core cmt_line
;
command_core:
pid_conf | temp_set | wait_time | wait_temp | temp_ramp | beep | temp_off | clear_flags | digio_conf | digio_set | digio_wait;
pid_conf: PL_PID_CONF any_num any_num any_num any_num any_num any_num
{
printf("PID Config\n");
}
;
temp_set: PL_SET_TEMP any_num
{
printf("Target temp set: %f\n", $2);
}
;
wait_time: PL_WAIT_FOR_TIME any_num
{
printf("Wait for %f seconds\n", $2);
}
;
wait_temp: PL_WAIT_FOR_TEMP any_num
{
printf("Wait for temperature %f\n", $2);
}
;
temp_ramp: PL_SET_RAMP any_num any_num
{
printf("Temperature ramp. Target %f, duration: %f\n", $2, $3);
}
;
cmt_line: COMMENT NEWLINE
{
printf("Comment line detected\n");
};
beep: PL_LOUDSPEAKER_SET INT_NUMBER
{
printf("Beep: %d\n", $2);
}
|
PL_LOUDSPEAKER_SET NUMBER
{
printf("Warning: Float value casted to int!\n");
printf("Beep %u\n", (unsigned int)$2);
};
temp_off: PL_OFF
{
printf("Turn off oven\n");
}
;
clear_flags: PL_CLEAR_FLAGS
{
printf("Clear flags\n");
}
;
digio_conf: PL_DIGIO_CONF INT_NUMBER INT_NUMBER
{
printf("Configure digio pin\n");
};
digio_set: PL_DIGIO_SET INT_NUMBER INT_NUMBER
{
printf("Configure digio pin\n");
};
digio_wait: PL_DIGIO_WAIT INT_NUMBER INT_NUMBER
{
printf("Configure digio pin\n");
};
/* Matches any number format that can be interpreted as float */
any_num : NUMBER | INT_NUMBER
{
$$ = (float)$1;
};
%%