Compare commits

..

10 Commits
master ... dev

8 changed files with 128 additions and 44 deletions

View File

@ -69,6 +69,7 @@ enum safety_flag {
ERR_FLAG_FLASH_CRC_DATA = (1<<20), ERR_FLAG_FLASH_CRC_DATA = (1<<20),
ERR_FLAG_CFG_CRC_MEAS_ADC = (1<<21), ERR_FLAG_CFG_CRC_MEAS_ADC = (1<<21),
ERR_FLAG_CFG_CRC_SAFETY_ADC = (1<<22), ERR_FLAG_CFG_CRC_SAFETY_ADC = (1<<22),
ERR_FLAG_CFG_CRC_MISC = (1<<23),
}; };
/** /**
@ -87,6 +88,7 @@ enum timing_monitor {
enum crc_monitor { enum crc_monitor {
ERR_CRC_MON_MEAS_ADC = 0, ERR_CRC_MON_MEAS_ADC = 0,
ERR_CRC_MON_SAFETY_ADC, ERR_CRC_MON_SAFETY_ADC,
ERR_CRC_MON_MISC,
N_ERR_CRC_MON N_ERR_CRC_MON
}; };
@ -124,7 +126,15 @@ enum analog_value_monitor {
#define WATCHDOG_HALT_DEBUG (0) #define WATCHDOG_HALT_DEBUG (0)
#endif #endif
#define WATCHDOG_PRESCALER 16 /**
* @brief Watchdog clock prescaler value
*/
#define WATCHDOG_PRESCALER (16)
/**
* @brief Watchdog reload value
*/
#define WATCHDOG_RELOAD_VALUE (2500)
/** /**
* @brief Minimum number of bytes that have to be free on the stack. If this is not the case, an error is detected * @brief Minimum number of bytes that have to be free on the stack. If this is not the case, an error is detected
@ -167,6 +177,12 @@ enum analog_value_monitor {
*/ */
#define SAFETY_CRC_MON_SAFETY_ADC_PW 0xA8DF2368 #define SAFETY_CRC_MON_SAFETY_ADC_PW 0xA8DF2368
/**
* @brief Password for resetting ERR_CRC_MON_MISC
*
*/
#define SAFETY_CRC_MON_MISC_PW 0x9A62E96A
/** /**
* @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.
*/ */
@ -192,7 +208,8 @@ enum analog_value_monitor {
ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_FLASH_CRC_CODE, true), \ 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_FLASH_CRC_DATA, true), \
ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_CFG_CRC_MEAS_ADC, 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), \
ERR_FLAG_PERSIST_ENTRY(ERR_FLAG_CFG_CRC_MISC, 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.
*/ */
@ -218,6 +235,7 @@ enum analog_value_monitor {
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_FLASH_CRC_CODE, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \ 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_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_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_CFG_CRC_SAFETY_ADC, SAFETY_FLAG_CONFIG_WEIGHT_PANIC), \
ERR_FLAG_WEIGHT_ENTRY(ERR_FLAG_CFG_CRC_MISC, SAFETY_FLAG_CONFIG_WEIGHT_PANIC)
#endif /* __SAFETY_CONFIG_H__ */ #endif /* __SAFETY_CONFIG_H__ */

View File

@ -27,11 +27,19 @@
/** /**
* @brief Setup the watchdog for the safety controller * @brief Setup the watchdog for the safety controller
* @param Prescaler to use for the 32 KHz LSI clock *
* The watchdog timeout can be calculated with:
* \f[ t = \frac{(\mathrm{RELOAD_VAL} + 1)\cdot \mathrm{PRESCALER}}{32000 } s\f]
*
* Valid prescaler values are: 4, 8, 16, 32, 64, 128, 256.
* @param prescaler Prescaler to use for the 32 KHz LSI clock
* @param reload_value Reload value to reload the timer with when reset. 0 to 0xFFF
* @return 0 if successful * @return 0 if successful
* @return -1 if prescaler is wrong
* @return -2 if a reload value > 0xFFF is selected. 0xFFF will be used in this case
* @note Once the watchdog is enabled, it cannot be turned off! * @note Once the watchdog is enabled, it cannot be turned off!
*/ */
int watchdog_setup(uint8_t prescaler); int watchdog_setup(uint16_t prescaler, uint16_t reload_value);
/** /**
* @brief Reset watchdog counter * @brief Reset watchdog counter

View File

@ -23,6 +23,7 @@
* @brief Main file for firmware * @brief Main file for firmware
*/ */
#include "reflow-controller/safety/safety-config.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -215,6 +216,9 @@ static inline void setup_system(void)
/** - Enable the ADC for PT1000 measurement */ /** - Enable the ADC for PT1000 measurement */
adc_pt1000_setup_meas(); adc_pt1000_setup_meas();
/** - Enable the misc CRC config monitor to supervise clock, systick and flash settings */
(void)safety_controller_set_crc_monitor(ERR_CRC_MON_MISC, SAFETY_CRC_MON_MISC_PW);
} }
/** /**

View File

@ -23,6 +23,7 @@
* @{ * @{
*/ */
#include "stm32/stm32f407xx.h"
#include <reflow-controller/safety/safety-controller.h> #include <reflow-controller/safety/safety-controller.h>
#include <reflow-controller/safety/safety-config.h> #include <reflow-controller/safety/safety-config.h>
#include <reflow-controller/safety/watchdog.h> #include <reflow-controller/safety/watchdog.h>
@ -163,9 +164,15 @@ struct crc_monitor_register {
#define CRC_MON_REGISTER_ENTRY(_addr, _mask, _size) {.reg_addr = &(_addr), .mask = (_mask), .size = (_size)} #define CRC_MON_REGISTER_ENTRY(_addr, _mask, _size) {.reg_addr = &(_addr), .mask = (_mask), .size = (_size)}
/**
* @brief Sentinel Element for crc monitor register list
*
*/
#define CRC_MON_REGISTER_SENTINEL {.reg_addr = NULL, .mask = 0, .size = 0}
struct crc_mon { struct crc_mon {
/** /**
* @brief Array of registers to monitor. Terminated by NULL sentinel! * @brief Array of registers to monitor. Terminated by NULL sentinel @ref CRC_MON_REGISTER_SENTINEL
*/ */
const struct crc_monitor_register *registers; const struct crc_monitor_register *registers;
const enum crc_monitor monitor; const enum crc_monitor monitor;
@ -204,6 +211,7 @@ static volatile struct error_flag IN_SECTION(.ccm.data) flags[] = {
ERR_FLAG_ENTRY(ERR_FLAG_FLASH_CRC_DATA), ERR_FLAG_ENTRY(ERR_FLAG_FLASH_CRC_DATA),
ERR_FLAG_ENTRY(ERR_FLAG_CFG_CRC_MEAS_ADC), ERR_FLAG_ENTRY(ERR_FLAG_CFG_CRC_MEAS_ADC),
ERR_FLAG_ENTRY(ERR_FLAG_CFG_CRC_SAFETY_ADC), ERR_FLAG_ENTRY(ERR_FLAG_CFG_CRC_SAFETY_ADC),
ERR_FLAG_ENTRY(ERR_FLAG_CFG_CRC_MISC),
}; };
/** /**
@ -291,7 +299,7 @@ static const struct crc_monitor_register meas_adc_crc_regs[] = {
ADC_SQR2_SQ8 | ADC_SQR2_SQ7, 4), ADC_SQR2_SQ8 | ADC_SQR2_SQ7, 4),
CRC_MON_REGISTER_ENTRY(ADC_PT1000_PERIPH->SQR3, ADC_SQR3_SQ6 | ADC_SQR3_SQ5 | ADC_SQR3_SQ4 | 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} CRC_MON_REGISTER_SENTINEL
}; };
static const struct crc_monitor_register safety_adc_crc_regs[] = { static const struct crc_monitor_register safety_adc_crc_regs[] = {
@ -307,7 +315,24 @@ static const struct crc_monitor_register safety_adc_crc_regs[] = {
ADC_SQR2_SQ8 | ADC_SQR2_SQ7, 4), 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 | 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} CRC_MON_REGISTER_ENTRY(RCC->APB2ENR, SAFETY_ADC_ADC_RCC_MASK, 4),
CRC_MON_REGISTER_SENTINEL
};
static const struct crc_monitor_register misc_config_crc_regs[] = {
/* Check clock tree settings */
CRC_MON_REGISTER_ENTRY(RCC->CR, RCC_CR_PLLON | RCC_CR_HSEON | RCC_CR_PLLI2SON | RCC_CR_HSION, 4),
CRC_MON_REGISTER_ENTRY(RCC->CSR, RCC_CSR_LSION, 4),
CRC_MON_REGISTER_ENTRY(RCC->CFGR, RCC_CFGR_SWS | RCC_CFGR_HPRE | RCC_CFGR_PPRE1 | RCC_CFGR_PPRE2, 4),
CRC_MON_REGISTER_ENTRY(RCC->PLLCFGR, RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLQ | RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLP | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLM , 4),
/* Check Flash settings */
CRC_MON_REGISTER_ENTRY(FLASH->ACR, FLASH_ACR_LATENCY | FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN, 4),
/* Check vector table offset */
CRC_MON_REGISTER_ENTRY(SCB->VTOR, 0xFFFFFFFF, 4),
/* Check system tick configuration */
CRC_MON_REGISTER_ENTRY(SysTick->CTRL, SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk, 4),
CRC_MON_REGISTER_ENTRY(SysTick->LOAD, 0xFFFFFFFF, 4),
CRC_MON_REGISTER_SENTINEL
}; };
static struct crc_mon IN_SECTION(.ccm.data) crc_monitors[] = { static struct crc_mon IN_SECTION(.ccm.data) crc_monitors[] = {
@ -331,6 +356,16 @@ static struct crc_mon IN_SECTION(.ccm.data) crc_monitors[] = {
.last_crc = 0UL, .last_crc = 0UL,
.active = false, .active = false,
}, },
{
.registers = misc_config_crc_regs,
.monitor = ERR_CRC_MON_MISC,
.pw = SAFETY_CRC_MON_MISC_PW,
.flag_to_set = ERR_FLAG_CFG_CRC_MISC,
.expected_crc = 0UL,
.expected_crc_inv = ~0UL,
.last_crc = 0UL,
.active = false,
}
}; };
/** /**
@ -938,7 +973,7 @@ void safety_controller_init(void)
MEAS_ADC_SAFETY_FLAG_KEY); MEAS_ADC_SAFETY_FLAG_KEY);
safety_adc_init(); safety_adc_init();
watchdog_setup(WATCHDOG_PRESCALER); (void)watchdog_setup(WATCHDOG_PRESCALER, WATCHDOG_RELOAD_VALUE);
if (rcc_manager_get_reset_cause(false) & RCC_RESET_SOURCE_IWDG) if (rcc_manager_get_reset_cause(false) & RCC_RESET_SOURCE_IWDG)
safety_controller_report_error(ERR_FLAG_WTCHDG_FIRED); safety_controller_report_error(ERR_FLAG_WTCHDG_FIRED);

View File

@ -42,9 +42,10 @@
*/ */
#define STM32_WATCHDOG_REGISTER_ACCESS_KEY 0x5555 #define STM32_WATCHDOG_REGISTER_ACCESS_KEY 0x5555
int watchdog_setup(uint8_t prescaler) int watchdog_setup(uint16_t prescaler, uint16_t reload_value)
{ {
uint32_t prescaler_reg_val; uint32_t prescaler_reg_val;
int ret = 0;
/** - Activate the LSI oscillator */ /** - Activate the LSI oscillator */
RCC->CSR |= RCC_CSR_LSION; RCC->CSR |= RCC_CSR_LSION;
@ -53,20 +54,24 @@ int watchdog_setup(uint8_t prescaler)
while (!(RCC->CSR & RCC_CSR_LSIRDY)) while (!(RCC->CSR & RCC_CSR_LSIRDY))
; ;
if (prescaler == 4U) if (prescaler == 4U) {
prescaler_reg_val = 0UL; prescaler_reg_val = 0UL;
else if (prescaler == 8U) } else if (prescaler == 8U) {
prescaler_reg_val = 1UL; prescaler_reg_val = 1UL;
else if (prescaler == 16U) } else if (prescaler == 16U) {
prescaler_reg_val = 2UL; prescaler_reg_val = 2UL;
else if (prescaler == 32U) } else if (prescaler == 32U) {
prescaler_reg_val = 3UL; prescaler_reg_val = 3UL;
else if (prescaler == 64U) } else if (prescaler == 64U) {
prescaler_reg_val = 4UL; prescaler_reg_val = 4UL;
else if (prescaler == 128U) } else if (prescaler == 128U) {
prescaler_reg_val = 5UL; prescaler_reg_val = 5UL;
else } else if (prescaler == 256U) {
prescaler_reg_val = 6UL; prescaler_reg_val = 6UL;
} else {
prescaler_reg_val = 6UL;
ret = -1;
}
/** - (De)activate the watchdog during debug access according to @ref WATCHDOG_HALT_DEBUG */ /** - (De)activate the watchdog during debug access according to @ref WATCHDOG_HALT_DEBUG */
if (WATCHDOG_HALT_DEBUG) if (WATCHDOG_HALT_DEBUG)
@ -88,8 +93,12 @@ int watchdog_setup(uint8_t prescaler)
while (IWDG->SR & IWDG_SR_RVU) while (IWDG->SR & IWDG_SR_RVU)
; ;
/** - Set reload value fixed to 0xFFF */ /** - Set reload value */
IWDG->RLR = 0xFFFU; if (reload_value > 0xFFFu) {
reload_value = 0xFFFFu;
ret = -2;
}
IWDG->RLR = reload_value;
/** - Write enable key */ /** - Write enable key */
IWDG->KR = STM32_WATCHDOG_ENABLE_KEY; IWDG->KR = STM32_WATCHDOG_ENABLE_KEY;
@ -97,7 +106,7 @@ int watchdog_setup(uint8_t prescaler)
/** - Do a first reset of the counter. This also locks the config regs */ /** - Do a first reset of the counter. This also locks the config regs */
watchdog_ack(WATCHDOG_MAGIC_KEY); watchdog_ack(WATCHDOG_MAGIC_KEY);
return 0; return ret;
} }
int watchdog_ack(uint32_t magic) int watchdog_ack(uint32_t magic)

View File

@ -2,7 +2,7 @@ project(updater-ram-code)
set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_CROSSCOMPILING 1) set(CMAKE_CROSSCOMPILING 1)
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.18)
set(CMAKE_TOOLCHAIN_FILE "arm-none-eabi-gcc.cmake") set(CMAKE_TOOLCHAIN_FILE "arm-none-eabi-gcc.cmake")

View File

@ -1,35 +1,45 @@
#!env python #!env python
# Convert a file to a c array """
# bin2carray <output file> <input file> Convert a file to a c array
bin2carray <output file> <input file>
"""
import os import os
import os.path import os.path
import sys import sys
if len(sys.argv) < 3: def main():
sys.exit(-1) """
Main script function
"""
if len(sys.argv) < 3:
return -1
source_file = sys.argv[2] source_file = sys.argv[2]
dest_file = sys.argv[1] dest_file = sys.argv[1]
print("%s --> %s" % (source_file, dest_file)) print(f'{source_file} --> {dest_file}')
with open(source_file, "rb") as src: with open(source_file, 'rb') as src:
data = src.read() data = src.read()
with open(dest_file, "w") as dest: with open(dest_file, 'w', encoding='utf-8') as dest:
header_guard = "__" + os.path.basename(dest_file).replace('.', '_').replace('-', '_') + "_H__" header_guard = '_' + os.path.basename(dest_file).replace('.', '_').replace('-', '_') + '_H_'
dest.write("#ifndef %s\n" % (header_guard)) header_guard = header_guard.upper()
dest.write("#define %s\n" % (header_guard)) dest.write(f'#ifndef {header_guard}\n')
dest.write("static const char binary_blob[%d] = {\n" % (len(data))) dest.write(f'#define {header_guard}\n')
for current,idx in zip(data, range(len(data))): dest.write(f'static const char binary_blob[{len(data)}] = {{\n')
if ((idx+1) % 4 == 0): for idx, current in enumerate(data, start=1):
dest.write(hex(current)+",\n") if idx % 4 == 0:
dest.write(hex(current)+',\n')
else: else:
dest.write(hex(current)+",") dest.write(hex(current)+',')
dest.write("};\n") dest.write('};\n')
dest.write("#endif /* %s */\n" % (header_guard)) dest.write(f'#endif /* {header_guard} */\n')
sys.exit(0) return 0
if __name__ == '__main__':
sys.exit(main())