15 Commits

26 changed files with 665 additions and 591 deletions

View File

@@ -37,10 +37,11 @@
* If the pointer is invalid, the function using this macro will return with * If the pointer is invalid, the function using this macro will return with
* CONFIG_PARSER_PARAM_ERR * CONFIG_PARSER_PARAM_ERR
*/ */
#define config_parser_check_handle(handle) do { if (!(handle) || \ #define config_parser_check_handle(handle) do { \
((struct config_parser *)(handle))->magic != CONFIG_PARSER_MAGIC) \ if (!(handle) || \
return CONFIG_PARSER_PARAM_ERR; \ ((struct config_parser *)(handle))->magic != CONFIG_PARSER_MAGIC) \
} while (0) 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, 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) char *working_buffer, size_t buff_size)
@@ -92,17 +93,17 @@ static int parse_value(struct config_parser_entry *entry, char *value_start_toke
if (value_start_token[0] != '-') { if (value_start_token[0] != '-') {
/* Try parsing as ul */ /* Try parsing as ul */
entry->value.uint_val = strtoul(value_start_token, &endptr, 0); entry->value.uint_val = strtoul(value_start_token, &endptr, 0);
if (endptr == value_start_token) { if (endptr == value_start_token)
return -1; return -1;
}
entry->type = CONFIG_PARSER_TYPE_UINT; entry->type = CONFIG_PARSER_TYPE_UINT;
goto exit; goto exit;
} else { } else {
/* Try parsing as int */ /* Try parsing as int */
entry->value.int_val = strtod(value_start_token, &endptr); entry->value.int_val = strtod(value_start_token, &endptr);
if (endptr == value_start_token) { if (endptr == value_start_token)
return -1; return -1;
}
entry->type = CONFIG_PARSER_TYPE_INT; entry->type = CONFIG_PARSER_TYPE_INT;
} }
@@ -110,14 +111,16 @@ exit:
return 0; 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; struct config_parser *p;
config_parser_check_handle(handle);
p = CONFIG_PARSER(handle);
char *token; char *token;
int token_round = 0; int token_round = 0;
config_parser_check_handle(handle);
p = CONFIG_PARSER(handle);
if (!entry) if (!entry)
return CONFIG_PARSER_PARAM_ERR; return CONFIG_PARSER_PARAM_ERR;
@@ -131,8 +134,7 @@ enum config_parser_ret config_parser_get_line(config_parser_handle_t handle, str
if (token[0] == '#') { if (token[0] == '#') {
if (token_round == 0) if (token_round == 0)
return CONFIG_PARSER_LINE_COMMENT; return CONFIG_PARSER_LINE_COMMENT;
else break;
break;
} }
switch (token_round) { switch (token_round) {
@@ -140,9 +142,8 @@ enum config_parser_ret config_parser_get_line(config_parser_handle_t handle, str
entry->name = token; entry->name = token;
break; break;
case 1: /* = Symbol */ case 1: /* = Symbol */
if (strcmp(token, "=")) { if (strcmp(token, "="))
return CONFIG_PARSER_LINE_MALFORM; return CONFIG_PARSER_LINE_MALFORM;
}
break; break;
case 2: /* VALUE */ case 2: /* VALUE */
if (parse_value(entry, token)) if (parse_value(entry, token))
@@ -172,6 +173,7 @@ enum config_parser_ret config_parser_reset_to_start(config_parser_handle_t handl
{ {
FRESULT res; FRESULT res;
struct config_parser *p; struct config_parser *p;
config_parser_check_handle(handle); config_parser_check_handle(handle);
p = CONFIG_PARSER(handle); p = CONFIG_PARSER(handle);
@@ -194,6 +196,7 @@ enum config_parser_ret config_parser_close_file(config_parser_handle_t handle)
{ {
struct config_parser *p; struct config_parser *p;
FRESULT res; FRESULT res;
config_parser_check_handle(handle); config_parser_check_handle(handle);
p = CONFIG_PARSER(handle); p = CONFIG_PARSER(handle);

View File

@@ -70,14 +70,14 @@ struct timing_monitor_info {
* You have to call safety_controller_handle * You have to call safety_controller_handle
* If this function fails, it will hang, because errors in the safety controller are not recoverable * If this function fails, it will hang, because errors in the safety controller are not recoverable
*/ */
void safety_controller_init(); void safety_controller_init(void);
/** /**
* @brief Handle the safety controller. * @brief Handle the safety controller.
* @note This function must be executed periodically in order to prevent the watchdog from resetting the firmware * @note This function must be executed periodically in order to prevent the watchdog from resetting the firmware
* @return 0 if successful * @return 0 if successful
*/ */
int safety_controller_handle(); int safety_controller_handle(void);
/** /**
* @brief Report one or multiple errors to the safety controller * @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 * @brief Get the count of error flags
* @return Error flag count * @return Error flag count
*/ */
uint32_t safety_controller_get_flag_count(); uint32_t safety_controller_get_flag_count(void);
/** /**
* @brief Get the count of analog monitors * @brief Get the count of analog monitors
* @return Analog monitor count * @return Analog monitor count
*/ */
uint32_t safety_controller_get_analog_monitor_count(); uint32_t safety_controller_get_analog_monitor_count(void);
/** /**
* @brief Get an error flag's name by its index. * @brief Get an error flag's name by its index.

View File

@@ -28,12 +28,12 @@
* @brief Initialize the SPI for the eeprom. * @brief Initialize the SPI for the eeprom.
* @return 0 if succesful * @return 0 if succesful
*/ */
int spi_eeprom_init(); int spi_eeprom_init(void);
/** /**
* @brief Uninitialize the SPI EEPROM * @brief Uninitialize the SPI EEPROM
*/ */
void spi_eeprom_deinit(); void spi_eeprom_deinit(void);
/** /**
* @brief Read from SPI EEPROM * @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_init(bool int_enable);
void random_number_gen_deinit(); void random_number_gen_deinit(void);
void random_number_gen_reset(bool int_en); void random_number_gen_reset(bool int_en);

View File

@@ -33,4 +33,6 @@ 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_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__ */ #endif /* __UNIQUE_ID_H__ */

View File

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

View File

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

View File

@@ -1,22 +1,22 @@
/* Reflow Oven Controller /* Reflow Oven Controller
* *
* Copyright (C) 2020 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. * This file is part of the Reflow Oven Controller Project.
* *
* The reflow oven controller is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
* *
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful, * 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 * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with the reflow oven controller project. * along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
/** /**
* @addtogroup safety-controller * @addtogroup safety-controller
@@ -215,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[] = { 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_PID, 2, 5000, ERR_FLAG_TIMING_PID),
TIM_MON_ENTRY(ERR_TIMING_MEAS_ADC, 0, 50, ERR_FLAG_TIMING_MEAS_ADC), TIM_MON_ENTRY(ERR_TIMING_MEAS_ADC, 0, 50, ERR_FLAG_TIMING_MEAS_ADC),
@@ -298,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_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10 | ADC_SQR2_SQ9 |
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} {NULL, 0, 0}
}; };
@@ -314,12 +314,11 @@ static const struct crc_monitor_register safety_adc_crc_regs[] = {
ADC_SQR2_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10 | ADC_SQR2_SQ9 | ADC_SQR2_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10 | ADC_SQR2_SQ9 |
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} {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, .registers = meas_adc_crc_regs,
.monitor = ERR_CRC_MON_MEAS_ADC, .monitor = ERR_CRC_MON_MEAS_ADC,
@@ -360,7 +359,8 @@ static void set_overtemp_config(float over_temperature)
safety_controller_overtemp_config.crc_dummy_seed = 0xA4F5C7E6UL; safety_controller_overtemp_config.crc_dummy_seed = 0xA4F5C7E6UL;
safety_controller_overtemp_config.overtemp_deg_celsius = over_temperature; safety_controller_overtemp_config.overtemp_deg_celsius = over_temperature;
safety_controller_overtemp_config.overtemp_equiv_resistance = resistance; 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(); safety_controller_overtemp_config.crc = crc_unit_get_crc();
} }
@@ -369,7 +369,8 @@ static bool over_temperature_config_check(void)
if (safety_controller_overtemp_config.crc_dummy_seed != 0xA4F5C7E6UL) if (safety_controller_overtemp_config.crc_dummy_seed != 0xA4F5C7E6UL)
return true; return true;
crc_unit_reset(); 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) if (crc_unit_get_crc() != safety_controller_overtemp_config.crc)
return true; return true;
@@ -442,7 +443,7 @@ static int flag_weight_table_crc_check(void)
static int flag_persistence_table_crc_check(void) static int flag_persistence_table_crc_check(void)
{ {
crc_unit_reset(); 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) if (crc_unit_get_crc() != flag_persistencies_crc)
return -1; return -1;
@@ -519,9 +520,8 @@ static int safety_controller_check_crc_monitors(void)
if (crc_monitor_calculate_crc(mon->registers, &crc)) if (crc_monitor_calculate_crc(mon->registers, &crc))
return -1; 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); safety_controller_report_error(mon->flag_to_set);
}
mon->last_crc = crc; mon->last_crc = crc;
} }
@@ -548,7 +548,7 @@ static void init_safety_flag_weight_table_from_default(void)
} }
crc_unit_reset(); 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(); flag_weight_crc = crc_unit_get_crc();
} }
@@ -608,16 +608,14 @@ static void apply_config_overrides(void)
case SAFETY_MEMORY_CONFIG_OVERRIDE_WEIGHT: case SAFETY_MEMORY_CONFIG_OVERRIDE_WEIGHT:
flag_enum = flag_no_to_flag_enum(override.entry.weight_override.flag); flag_enum = flag_no_to_flag_enum(override.entry.weight_override.flag);
flag = find_error_flag(flag_enum); flag = find_error_flag(flag_enum);
if (flag && flag->weight) { if (flag && flag->weight)
flag->weight->weight = override.entry.weight_override.weight; flag->weight->weight = override.entry.weight_override.weight;
}
break; break;
case SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTENCE: case SAFETY_MEMORY_CONFIG_OVERRIDE_PERSISTENCE:
flag_enum = flag_no_to_flag_enum(override.entry.persistence_override.flag); flag_enum = flag_no_to_flag_enum(override.entry.persistence_override.flag);
flag = find_error_flag(flag_enum); flag = find_error_flag(flag_enum);
if (flag && flag->persistence) { if (flag && flag->persistence)
flag->persistence->persistence = override.entry.persistence_override.persistence; flag->persistence->persistence = override.entry.persistence_override.persistence;
}
break; break;
default: default:
continue; continue;
@@ -629,7 +627,7 @@ static void apply_config_overrides(void)
crc_unit_input_array((uint32_t *)flag_persistencies, wordsize_of(flag_persistencies)); crc_unit_input_array((uint32_t *)flag_persistencies, wordsize_of(flag_persistencies));
flag_persistencies_crc = crc_unit_get_crc(); flag_persistencies_crc = crc_unit_get_crc();
crc_unit_reset(); 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(); flag_weight_crc = crc_unit_get_crc();
} }
@@ -647,11 +645,10 @@ static bool error_flag_get_status(const volatile struct error_flag *flag)
if (!flag) if (!flag)
return true; return true;
if (flag->error_state == flag->error_state_inv) { if (flag->error_state == flag->error_state_inv)
return true; return true;
} else { else
return flag->error_state; return flag->error_state;
}
} }
/** /**
@@ -693,7 +690,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. * @brief Check the active timing monitors and set the appropriate flags in case of an error.
*/ */
static void safety_controller_process_active_timing_mons() static void safety_controller_process_active_timing_mons(void)
{ {
uint32_t i; uint32_t i;
volatile struct timing_mon *current_mon; volatile struct timing_mon *current_mon;
@@ -716,7 +713,8 @@ static void safety_controller_process_active_timing_mons()
* Process the analog and timing monitors and set the relevant flags in case of a monitor outside its limits. * 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 * 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) static void safety_controller_process_monitor_checks(void)
{ {
@@ -731,21 +729,18 @@ static void safety_controller_process_monitor_checks(void)
if (startup_completed) { if (startup_completed) {
analog_mon_count = safety_controller_get_analog_monitor_count(); 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)) { if (safety_controller_get_analog_mon_by_index(idx, &amon_info)) {
panic_mode(); panic_mode();
}
if (amon_info.status != ANALOG_MONITOR_OK) { if (amon_info.status != ANALOG_MONITOR_OK)
safety_controller_report_error(amon_info.associated_flag); safety_controller_report_error(amon_info.associated_flag);
}
} }
} }
adc_pt1000_get_current_resistance(&pt1000_val); 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); safety_controller_report_error(ERR_FLAG_OVERTEMP);
}
(void)safety_controller_check_crc_monitors(); (void)safety_controller_check_crc_monitors();
@@ -779,7 +774,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].error_state_inv = !flags[i].error_state;
flags[i].key = key; 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) { get_flag_weight(&flags[i]) == SAFETY_FLAG_CONFIG_WEIGHT_PANIC) {
err_mem_entry.counter = 1; err_mem_entry.counter = 1;
err_mem_entry.flag_num = flag_enum_to_flag_no(flags[i].flag); err_mem_entry.flag_num = flag_enum_to_flag_no(flags[i].flag);
@@ -820,9 +815,8 @@ void safety_controller_report_timing(enum timing_monitor monitor)
tim = find_timing_mon(monitor); tim = find_timing_mon(monitor);
if (tim) { if (tim) {
if (tim->enabled) { 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); safety_controller_report_error(tim->associated_flag);
}
} }
tim->calculated_delta = timestamp - tim->last; tim->calculated_delta = timestamp - tim->last;
@@ -870,9 +864,8 @@ static int get_safety_flags_from_error_mem(enum safety_flag *flags)
for (idx = 0; idx < count; idx++) { for (idx = 0; idx < count; idx++) {
res = safety_memory_get_error_entry(idx, &entry); 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); return_flags |= flag_no_to_flag_enum(entry.flag_num);
}
} }
*flags = return_flags; *flags = return_flags;
@@ -884,11 +877,12 @@ 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. * 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 * 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. * @note When enabled, execute the @ref external_watchdog_toggle function to reset the external watchdog.
*/ */
static void safety_controller_init_external_watchdog() static void safety_controller_init_external_watchdog(void)
{ {
rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(SAFETY_EXT_WATCHDOG_RCC_MASK)); 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); SAFETY_EXT_WATCHDOG_PORT->MODER &= MODER_DELETE(SAFETY_EXT_WATCHDOG_PIN);
@@ -899,7 +893,7 @@ static void safety_controller_init_external_watchdog()
__DSB(); __DSB();
} }
void safety_controller_init() void safety_controller_init(void)
{ {
enum safety_memory_state found_memory_state; enum safety_memory_state found_memory_state;
enum safety_flag flags_in_err_mem = ERR_FLAG_NO_FLAG; enum safety_flag flags_in_err_mem = ERR_FLAG_NO_FLAG;
@@ -967,7 +961,7 @@ void safety_controller_init()
* 1) Checking the remaining free space at the moment between stack pointer and top of heap. * 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 * 2) Checking The CRC of the corruption detect area between heap and stack
*/ */
static void safety_controller_check_stack() static void safety_controller_check_stack(void)
{ {
int32_t free_stack; int32_t free_stack;
@@ -975,18 +969,17 @@ static void safety_controller_check_stack()
if (free_stack < SAFETY_MIN_STACK_FREE) if (free_stack < SAFETY_MIN_STACK_FREE)
safety_controller_report_error(ERR_FLAG_STACK); 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); safety_controller_report_error(ERR_FLAG_STACK);
}
} }
/** /**
* @brief Handle the Safety ADC * @brief Handle the Safety ADC
* *
* This function handles the safety ADC. * This function handles the safety ADC.
* If the safety ADC ius not executing a measurment and the time since the last measurement has * 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 * passed @ref SAFETY_CONTROLLER_ADC_DELAY_MS, the safety ADC is retriggered and will automatically perform a
* on all of its channels. * measurement on all of its channels.
* When called again, this function will retrieve the data from the safety ADC and converts it into the * 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. * appropriate analog values for the analog value monitors.
* *
@@ -995,7 +988,7 @@ static void safety_controller_check_stack()
* *
* The channels, the ssafety ADC will convert is defined in its header file using the define @ref SAFETY_ADC_CHANNELS. * 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() static void safety_controller_handle_safety_adc(void)
{ {
static uint64_t last_result_timestamp = 0; static uint64_t last_result_timestamp = 0;
const uint16_t *channels; const uint16_t *channels;
@@ -1066,9 +1059,8 @@ static void safety_controller_handle_memory_checks(void)
/* Check the safety memory */ /* Check the safety memory */
if (safety_memory_check()) { if (safety_memory_check()) {
(void)safety_memory_reinit(&found_state); (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); safety_controller_report_error(ERR_FLAG_SAFETY_MEM_CORRUPT);
}
} }
/* If flag weight table is broken, reinit to default and set flag */ /* If flag weight table is broken, reinit to default and set flag */
@@ -1078,7 +1070,7 @@ static void safety_controller_handle_memory_checks(void)
} }
/* If persistence table is broken, reinit to default and set flag */ /* 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); safety_controller_report_error(ERR_FLAG_SAFETY_TAB_CORRUPT);
init_safety_flag_persistencies_from_default(); init_safety_flag_persistencies_from_default();
} }
@@ -1097,7 +1089,7 @@ static void safety_controller_handle_memory_checks(void)
* If the systick stays constant for more than 1000 calls of this function, * If the systick stays constant for more than 1000 calls of this function,
* the @ref ERR_FLAG_SYSTICK flag is set. * the @ref ERR_FLAG_SYSTICK flag is set.
*/ */
static void safety_controller_do_systick_checking() static void safety_controller_do_systick_checking(void)
{ {
static uint64_t last_systick; static uint64_t last_systick;
static uint32_t same_systick_cnt = 0UL; static uint32_t same_systick_cnt = 0UL;
@@ -1122,7 +1114,7 @@ static void safety_controller_do_systick_checking()
* @note If no flag weigth is present for a given error flag, it is treated as the most critical category * @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) * (@ref SAFETY_FLAG_CONFIG_WEIGHT_PANIC)
*/ */
static void safety_controller_handle_weighted_flags() static void safety_controller_handle_weighted_flags(void)
{ {
uint32_t flag_index; uint32_t flag_index;
volatile struct error_flag *current_flag; volatile struct error_flag *current_flag;
@@ -1132,9 +1124,8 @@ static void safety_controller_handle_weighted_flags()
current_flag = &flags[flag_index]; current_flag = &flags[flag_index];
/* Continue if this flag is not set */ /* Continue if this flag is not set */
if (!error_flag_get_status(current_flag)) { if (!error_flag_get_status(current_flag))
continue; continue;
}
flag_weigth = get_flag_weight(current_flag); flag_weigth = get_flag_weight(current_flag);
switch (flag_weigth) { switch (flag_weigth) {
@@ -1155,13 +1146,13 @@ static void safety_controller_handle_weighted_flags()
} }
#ifndef DEBUGBUILD #ifndef DEBUGBUILD
static void external_watchdog_toggle() static void external_watchdog_toggle(void)
{ {
SAFETY_EXT_WATCHDOG_PORT->ODR ^= (1<<SAFETY_EXT_WATCHDOG_PIN); SAFETY_EXT_WATCHDOG_PORT->ODR ^= (1<<SAFETY_EXT_WATCHDOG_PIN);
} }
#endif #endif
int safety_controller_handle() int safety_controller_handle(void)
{ {
int ret = 0; int ret = 0;
#ifndef DEBUGBUILD #ifndef DEBUGBUILD
@@ -1273,9 +1264,8 @@ int safety_controller_ack_flag_with_key(enum safety_flag flag, uint32_t key)
int ret = -1; int ret = -1;
volatile struct error_flag *found_flag; volatile struct error_flag *found_flag;
if (!is_power_of_two(flag)) { if (!is_power_of_two(flag))
return -1001; return -1001;
}
found_flag = find_error_flag(flag); found_flag = find_error_flag(flag);
if (found_flag) { if (found_flag) {
@@ -1306,17 +1296,17 @@ bool safety_controller_get_flags_by_mask(enum safety_flag mask)
return ret; return ret;
} }
uint32_t safety_controller_get_flag_count() uint32_t safety_controller_get_flag_count(void)
{ {
return COUNT_OF(flags); return COUNT_OF(flags);
} }
uint32_t safety_controller_get_analog_monitor_count() uint32_t safety_controller_get_analog_monitor_count(void)
{ {
return COUNT_OF(analog_mons); return COUNT_OF(analog_mons);
} }
uint32_t safety_controller_get_timing_monitor_count() uint32_t safety_controller_get_timing_monitor_count(void)
{ {
return COUNT_OF(timings); return COUNT_OF(timings);
} }
@@ -1423,9 +1413,8 @@ int safety_controller_get_timing_mon_by_index(uint32_t index, struct timing_moni
if (!info) if (!info)
return -1002; return -1002;
if (index >= COUNT_OF(timings)) { if (index >= COUNT_OF(timings))
return -1001; return -1001;
}
mon = &timings[index]; mon = &timings[index];
@@ -1462,14 +1451,13 @@ extern const uint32_t __ld_sdata;
extern const uint32_t __ld_edata; extern const uint32_t __ld_edata;
extern const uint32_t __ld_load_data; extern const uint32_t __ld_load_data;
int safety_controller_trigger_flash_crc_check() int safety_controller_trigger_flash_crc_check(void)
{ {
/* This structs needs to be volatile!! /* 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 * This prevents the compiler form optimizing out the reads to the crcs which will be patched in later by
* a separate python script! * a separate python script!
*/ */
static volatile const struct flash_crcs IN_SECTION(.flashcrc) crcs_in_flash = static volatile const struct flash_crcs IN_SECTION(.flashcrc) crcs_in_flash = {
{
.start_magic = 0xA8BE53F9UL, .start_magic = 0xA8BE53F9UL,
.crc_section_ccm_data = 0UL, .crc_section_ccm_data = 0UL,
.crc_section_text = 0UL, .crc_section_text = 0UL,
@@ -1491,9 +1479,8 @@ int safety_controller_trigger_flash_crc_check()
crc_unit_reset(); crc_unit_reset();
crc_unit_input_array(&__ld_vectors_start, len); crc_unit_input_array(&__ld_vectors_start, len);
crc = crc_unit_get_crc(); crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_vectors) { if (crc != crcs_in_flash.crc_section_vectors)
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE); safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
}
} }
/* Perform CRC check over text section */ /* Perform CRC check over text section */
@@ -1505,9 +1492,8 @@ int safety_controller_trigger_flash_crc_check()
crc_unit_reset(); crc_unit_reset();
crc_unit_input_array(&__ld_text_start, len); crc_unit_input_array(&__ld_text_start, len);
crc = crc_unit_get_crc(); crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_text) { if (crc != crcs_in_flash.crc_section_text)
safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE); safety_controller_report_error(ERR_FLAG_FLASH_CRC_CODE);
}
} }
/* Perform CRC check over data section */ /* Perform CRC check over data section */
@@ -1519,9 +1505,8 @@ int safety_controller_trigger_flash_crc_check()
crc_unit_reset(); crc_unit_reset();
crc_unit_input_array(&__ld_load_data, len); crc_unit_input_array(&__ld_load_data, len);
crc = crc_unit_get_crc(); crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_data) { if (crc != crcs_in_flash.crc_section_data)
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA); safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
}
} }
/* Perform CRC check over ccm data section */ /* Perform CRC check over ccm data section */
@@ -1533,9 +1518,8 @@ int safety_controller_trigger_flash_crc_check()
crc_unit_reset(); crc_unit_reset();
crc_unit_input_array(&__ld_load_ccm_data, len); crc_unit_input_array(&__ld_load_ccm_data, len);
crc = crc_unit_get_crc(); crc = crc_unit_get_crc();
if (crc != crcs_in_flash.crc_section_ccm_data) { if (crc != crcs_in_flash.crc_section_ccm_data)
safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA); safety_controller_report_error(ERR_FLAG_FLASH_CRC_DATA);
}
} }
ret = 0; ret = 0;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -95,9 +95,8 @@ int rcc_manager_enable_clock(volatile uint32_t *rcc_enable_register, uint8_t bit
int ret_val = 0; int ret_val = 0;
struct rcc_enable_count *entry; struct rcc_enable_count *entry;
if (!rcc_enable_register || bit_no > 31) { if (!rcc_enable_register || bit_no > 31)
return -1000; return -1000;
}
/* Enable the clock in any case, no matter what follows */ /* Enable the clock in any case, no matter what follows */
*rcc_enable_register |= (1U<<bit_no); *rcc_enable_register |= (1U<<bit_no);
@@ -132,9 +131,8 @@ int rcc_manager_disable_clock(volatile uint32_t *rcc_enable_register, uint8_t bi
int ret_val = -1; int ret_val = -1;
struct rcc_enable_count *entry; struct rcc_enable_count *entry;
if (!rcc_enable_register || bit_no > 31) { if (!rcc_enable_register || bit_no > 31)
return -1000; return -1000;
}
entry = search_enable_entry_in_list(rcc_enable_register, bit_no); 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); random_number_gen_reset(int_enable);
} }
void random_number_gen_deinit() void random_number_gen_deinit(void)
{ {
RNG->CR = 0; RNG->CR = 0;
__DSB(); __DSB();
@@ -66,5 +66,5 @@ enum random_number_error random_number_gen_get_number(uint32_t *random_number, b
*random_number = RNG->DR; *random_number = RNG->DR;
/* Return from function with proper status */ /* 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 /* Reflow Oven Controller
* *
* Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net> * Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net>
* *
* This file is part of the Reflow Oven Controller Project. * This file is part of the Reflow Oven Controller Project.
* *
* The reflow oven controller is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
* *
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful, * 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 * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with the reflow oven controller project. * along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stm-periph/spi.h> #include <stm-periph/spi.h>
#include <helper-macros/helper-macros.h> #include <helper-macros/helper-macros.h>
@@ -65,7 +65,8 @@ static struct stm_spi_dev *spi_handle_to_struct(stm_spi_handle handle)
return dev; 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; stm_spi_handle ret_handle = NULL;
uint32_t reg_val; uint32_t reg_val;
@@ -131,10 +132,14 @@ void spi_deinit(stm_spi_handle handle)
static uint8_t transfer_byte(uint8_t byte, struct stm_spi_dev *dev) 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; dev->spi_regs->DR = (uint16_t)byte;
__DSB(); __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; return (uint8_t)dev->spi_regs->DR;
} }

View File

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

View File

@@ -43,3 +43,23 @@ void stm_dev_rev_id_get(uint32_t *device_id, uint32_t *revision_id)
if (revision_id) if (revision_id)
*revision_id = (DBGMCU->IDCODE & DBGMCU_IDCODE_REV_ID) >> 16; *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

@@ -691,6 +691,37 @@ 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_heading = NULL;
static char *overlay_text = NULL; static char *overlay_text = NULL;
@@ -740,6 +771,7 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
"Error Flags", "Error Flags",
"About", "About",
"Update", "Update",
"Connector Info",
NULL NULL
}; };
static const menu_func_t root_entry_funcs[] = { static const menu_func_t root_entry_funcs[] = {
@@ -749,6 +781,7 @@ static void gui_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entr
gui_menu_err_flags, gui_menu_err_flags,
gui_menu_about, gui_menu_about,
gui_update_firmware, gui_update_firmware,
gui_connector_info,
}; };
enum button_state push_button; enum button_state push_button;
int16_t rot_delta; int16_t rot_delta;

View File

@@ -70,6 +70,10 @@ static shellmatta_retCode_t shell_cmd_ver(const shellmatta_handle_t handle,
uint32_t high_id; uint32_t high_id;
uint32_t stm_rev_id; uint32_t stm_rev_id;
uint32_t stm_dev_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; const char *hw_rev_str;
enum hw_revision pcb_rev; enum hw_revision pcb_rev;
@@ -77,7 +81,7 @@ static shellmatta_retCode_t shell_cmd_ver(const shellmatta_handle_t handle,
stm_dev_rev_id_get(&stm_dev_id, &stm_rev_id); stm_dev_rev_id_get(&stm_dev_id, &stm_rev_id);
shellmatta_printf(handle, "Reflow Oven Controller Firmware " xstr(GIT_VER) "\r\n" 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); shellmatta_printf(handle, "Serial: %08X-%08X-%08X\r\n", high_id, mid_id, low_id);
pcb_rev = get_pcb_hardware_version(); pcb_rev = get_pcb_hardware_version();
@@ -100,6 +104,12 @@ 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 Device ID: 0x%04X\r\n", stm_dev_id);
shellmatta_printf(handle, "STM Revision ID: 0x%04X\r\n", stm_rev_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; return SHELLMATTA_OK;
} }
@@ -849,6 +859,7 @@ 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) shellmatta_retCode_t shell_cmd_cycle_count(const shellmatta_handle_t handle, const char *args, uint32_t len)
{ {
uint64_t counter; uint64_t counter;
uint32_t core_cycle_count;
(void)args; (void)args;
(void)len; (void)len;
char option; char option;
@@ -856,8 +867,10 @@ shellmatta_retCode_t shell_cmd_cycle_count(const shellmatta_handle_t handle, con
uint32_t arg_len; uint32_t arg_len;
int opt_stat; int opt_stat;
bool clear = false; bool clear = false;
bool hex = false;
const shellmatta_opt_long_t options[] = { const shellmatta_opt_long_t options[] = {
{"clear", 'c', SHELLMATTA_OPT_ARG_NONE}, {"clear", 'c', SHELLMATTA_OPT_ARG_NONE},
{"hex", 'h', SHELLMATTA_OPT_ARG_NONE},
{NULL, '\0', SHELLMATTA_OPT_ARG_NONE}, {NULL, '\0', SHELLMATTA_OPT_ARG_NONE},
}; };
@@ -869,6 +882,8 @@ shellmatta_retCode_t shell_cmd_cycle_count(const shellmatta_handle_t handle, con
case 'c': case 'c':
clear = true; clear = true;
break; break;
case 'h':
hex = true;
default: default:
break; break;
} }
@@ -876,10 +891,18 @@ shellmatta_retCode_t shell_cmd_cycle_count(const shellmatta_handle_t handle, con
counter = main_cycle_counter_get(); counter = main_cycle_counter_get();
shellmatta_printf(handle, "%"PRIu64"\r\n", counter); core_cycle_count = DWT->CYCCNT;
if (clear) 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) {
main_cycle_counter_init(); main_cycle_counter_init();
DWT->CYCCNT = 0UL;
}
return SHELLMATTA_OK; return SHELLMATTA_OK;
} }
@@ -1202,7 +1225,7 @@ static shellmatta_cmd_t cmd[25] = {
}, },
{ {
.cmd = "baudrate", .cmd = "baudrate",
.cmdAlias = "opt-bytes", .cmdAlias = "baud",
.helpText = "Set a new temporary baudrate for the UART", .helpText = "Set a new temporary baudrate for the UART",
.usageText = "baudrate <new baud>", .usageText = "baudrate <new baud>",
.cmdFct = shell_cmd_set_baud, .cmdFct = shell_cmd_set_baud,