diff --git a/stm-firmware/Makefile b/stm-firmware/Makefile index 88cab6d..8e4e703 100644 --- a/stm-firmware/Makefile +++ b/stm-firmware/Makefile @@ -36,18 +36,18 @@ DEFINES += -DSHELLMATTA_HELP_ALIAS=\"?\" # RCC Manager CFILES += stm-periph/clock-enable-manager.c CFILES += stm-periph/uart.c stm-periph/dma-ring-buffer.c stm-periph/backup-ram.c +CFILES += stm-periph/rng.c CFILES += digio.c CFILES += stm-periph/unique-id.c CFILES += calibration.c CFILES += temp-converter.c CFILES += rotary-encoder.c button.c -CFILES += stack-check.c CFILES += ui/lcd.c ui/menu.c reflow-menu.c CFILES += fatfs/diskio.c fatfs/ff.c fatfs/ffsystem.c fatfs/ffunicode.c fatfs/shimatta_sdio_driver/shimatta_sdio.c CFILES += pid-controller.c oven-driver.c CFILES += settings/settings.c settings/settings-sd-card.c CFILES += stm-periph/crc-unit.c -CFILES += safety/safety-adc.c safety/safety-controller.c safety/watchdog.c safety/fault.c safety/safety-memory.c +CFILES += safety/safety-adc.c safety/safety-controller.c safety/watchdog.c safety/fault.c safety/safety-memory.c safety/stack-check.c DEBUG_DEFINES = -DDEBUGBUILD RELEASE_DEFINES = diff --git a/stm-firmware/include/reflow-controller/stack-check.h b/stm-firmware/include/reflow-controller/safety/stack-check.h similarity index 93% rename from stm-firmware/include/reflow-controller/stack-check.h rename to stm-firmware/include/reflow-controller/safety/stack-check.h index 8e0e290..c51a3a7 100644 --- a/stm-firmware/include/reflow-controller/stack-check.h +++ b/stm-firmware/include/reflow-controller/safety/stack-check.h @@ -50,4 +50,8 @@ static inline uint32_t read_stack_pointer() return stack_pointer; } +int stack_check_init_corruption_detect_area(void); + +int stack_check_corruption_detect_area(void); + #endif /* __STACK_CHECK_H__ */ diff --git a/stm-firmware/include/stm-periph/rng.h b/stm-firmware/include/stm-periph/rng.h new file mode 100644 index 0000000..e8d9d7a --- /dev/null +++ b/stm-firmware/include/stm-periph/rng.h @@ -0,0 +1,42 @@ +/* Reflow Oven Controller + * + * Copyright (C) 2020 Mario Hüttel + * + * This file is part of the Reflow Oven Controller Project. + * + * The reflow oven controller is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * GDSII-Converter is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the reflow oven controller project. + * If not, see . + */ + +#ifndef __STM_RNG_H__ +#define __STM_RNG_H__ + +#include +#include + +enum random_number_error { + RNG_ERROR_OK = 0, + RNG_ERROR_INACT, + RNG_ERROR_INTERNAL_ERROR, + RNG_ERROR_NOT_READY +}; + +void random_number_gen_init(bool int_enable); + +void random_number_gen_deinit(); + +void random_number_gen_reset(bool int_en); + +enum random_number_error random_number_gen_get_number(uint32_t *random_number, bool wait_for_valid_value); + +#endif /* __STM_RNG_H__ */ diff --git a/stm-firmware/safety/safety-controller.c b/stm-firmware/safety/safety-controller.c index 42396ba..79cf6db 100644 --- a/stm-firmware/safety/safety-controller.c +++ b/stm-firmware/safety/safety-controller.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -347,6 +347,8 @@ void safety_controller_init() /* This is usually done by the safety memory already. But, since this module also uses the CRC... */ crc_unit_init(); + stack_check_init_corruption_detect_area(); + init_safety_flag_weight_table_from_default(); if (found_memory_state == SAFETY_MEMORY_INIT_CORRUPTED) @@ -374,6 +376,10 @@ static void safety_controller_check_stack() free_stack = stack_check_get_free(); if (free_stack < SAFETY_MIN_STACK_FREE) safety_controller_report_error(ERR_FLAG_STACK); + + if (stack_check_corruption_detect_area()) { + safety_controller_report_error(ERR_FLAG_STACK); + } } static void safety_controller_handle_safety_adc() @@ -430,7 +436,7 @@ static int safety_controller_handle_memory_checks(void) enum safety_memory_state found_state; int panic_request = 0; - if (systick_ticks_have_passed(ts, 1000)) { + if (systick_ticks_have_passed(ts, 250)) { ts = systick_get_global_tick(); /* Check the safety memory */ diff --git a/stm-firmware/safety/stack-check.c b/stm-firmware/safety/stack-check.c new file mode 100644 index 0000000..9940c8c --- /dev/null +++ b/stm-firmware/safety/stack-check.c @@ -0,0 +1,110 @@ +/* Reflow Oven Controller +* +* Copyright (C) 2020 Mario Hüttel +* +* This file is part of the Reflow Oven Controller Project. +* +* The reflow oven controller is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* The Reflow Oven Control Firmware is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with the reflow oven controller project. +* If not, see . +*/ + +#include +#include +#include +#include + +extern char __ld_top_of_stack; +extern char __ld_end_stack; + +int32_t stack_check_get_usage() +{ + uint32_t stack_top; + uint32_t stack_ptr; + + stack_ptr = read_stack_pointer(); + stack_top = (uint32_t)&__ld_top_of_stack; + + return stack_top - stack_ptr; +} + +int32_t stack_check_get_free() +{ + uint32_t upper_heap_boundary; + uint32_t stack_ptr; + + stack_ptr = read_stack_pointer(); + upper_heap_boundary = (uint32_t)&__ld_end_stack; + + return stack_ptr - upper_heap_boundary; +} + + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + +extern uint32_t __ld_start_stack_corruption_detect_area; +extern uint32_t __ld_end_stack_corruption_detect_area; + +int stack_check_init_corruption_detect_area(void) +{ + uint32_t *ptr = &__ld_start_stack_corruption_detect_area; + uint32_t *end_ptr = &__ld_end_stack_corruption_detect_area; + const uint32_t area_size_in_words = &__ld_end_stack_corruption_detect_area - + &__ld_start_stack_corruption_detect_area; + enum random_number_error rng_stat; + uint32_t rng_number; + uint32_t crc_val; + int ret = 0; + + random_number_gen_init(false); + + while (ptr < &end_ptr[-1]) { + rng_stat = random_number_gen_get_number(&rng_number, true); + + if (rng_stat != RNG_ERROR_OK) { + ret = -1; + goto exit_deinit_rng; + } + + *ptr = rng_number; + ptr++; + } + + /* Init CRC unit and leave it on */ + crc_unit_init(); + crc_unit_reset(); + + crc_unit_input_array(&__ld_start_stack_corruption_detect_area, area_size_in_words - 1); + crc_val = crc_unit_get_crc(); + end_ptr[-1] = crc_val; + +exit_deinit_rng: + random_number_gen_deinit(); + + return ret; +} + +#pragma GCC diagnostic pop + +int stack_check_corruption_detect_area(void) +{ + const uint32_t area_size_in_words = &__ld_end_stack_corruption_detect_area - + &__ld_start_stack_corruption_detect_area; + crc_unit_reset(); + crc_unit_input_array(&__ld_start_stack_corruption_detect_area, area_size_in_words); + if (crc_unit_get_crc() == 0UL) { + return 0; + } else { + return -1; + } +} diff --git a/stm-firmware/shell.c b/stm-firmware/shell.c index db8ef9d..e03c31c 100644 --- a/stm-firmware/shell.c +++ b/stm-firmware/shell.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/stm-firmware/stack-check.c b/stm-firmware/stack-check.c deleted file mode 100644 index 666014d..0000000 --- a/stm-firmware/stack-check.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Reflow Oven Controller -* -* Copyright (C) 2020 Mario Hüttel -* -* This file is part of the Reflow Oven Controller Project. -* -* The reflow oven controller is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -* -* The Reflow Oven Control Firmware is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with the reflow oven controller project. -* If not, see . -*/ - -#include -#include - -extern char __ld_top_of_stack; -extern char __ld_eheap; - -int32_t stack_check_get_usage() -{ - uint32_t stack_top; - uint32_t stack_ptr; - - stack_ptr = read_stack_pointer(); - stack_top = (uint32_t)&__ld_top_of_stack; - - return stack_top - stack_ptr; -} - -int32_t stack_check_get_free() -{ - uint32_t upper_heap_boundary; - uint32_t stack_ptr; - - stack_ptr = read_stack_pointer(); - upper_heap_boundary = (uint32_t)&__ld_eheap; - - return stack_ptr - upper_heap_boundary; -} diff --git a/stm-firmware/stm-periph/rng.c b/stm-firmware/stm-periph/rng.c new file mode 100644 index 0000000..042e061 --- /dev/null +++ b/stm-firmware/stm-periph/rng.c @@ -0,0 +1,70 @@ +/* Reflow Oven Controller + * + * Copyright (C) 2020 Mario Hüttel + * + * This file is part of the Reflow Oven Controller Project. + * + * The reflow oven controller is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The Reflow Oven Control Firmware is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the reflow oven controller project. + * If not, see . + */ + +#include +#include +#include + +void random_number_gen_init(bool int_enable) +{ + rcc_manager_enable_clock(&RCC->AHB2ENR, BITMASK_TO_BITNO(RCC_AHB2ENR_RNGEN)); + __DSB(); + + random_number_gen_reset(int_enable); +} + +void random_number_gen_deinit() +{ + RNG->CR = 0; + __DSB(); + rcc_manager_disable_clock(&RCC->AHB2ENR, BITMASK_TO_BITNO(RCC_AHB2ENR_RNGEN)); +} + +void random_number_gen_reset(bool int_en) +{ + RNG->CR = 0; + __DSB(); + RNG->CR = RNG_CR_RNGEN | (int_en ? RNG_CR_IE : 0U); +} + +enum random_number_error random_number_gen_get_number(uint32_t *random_number, bool wait_for_valid_value) +{ + bool value_ready; + + if (!(RNG->CR & RNG_CR_RNGEN)) + return RNG_ERROR_INACT; + + if (RNG->SR & RNG_SR_SEIS || RNG->SR & RNG_SR_CEIS) { + /* Error detected */ + return RNG_ERROR_INTERNAL_ERROR; + } + + /* Check if the value is ready. Wait if wait_for_valid_value is true */ + do { + value_ready = !!(RNG->SR & RNG_SR_DRDY); + } while (!value_ready && wait_for_valid_value); + + /* If the value is valid, return it */ + if (value_ready && random_number) + *random_number = RNG->DR; + + /* Return from function with proper status */ + return (value_ready ? RNG_ERROR_OK : RNG_ERROR_NOT_READY); +} diff --git a/stm-firmware/stm32f407vet6_flash.ld b/stm-firmware/stm32f407vet6_flash.ld index e1f503a..10e0d90 100644 --- a/stm-firmware/stm32f407vet6_flash.ld +++ b/stm-firmware/stm32f407vet6_flash.ld @@ -25,6 +25,7 @@ /* USER PARAMETERS */ __ld_stack_size = 0x3000; __ld_heap_size = 0x2100; +__stack_corruption_area_size = 128; /* END OF USER PARAMETERS */ ENTRY(Reset_Handler) @@ -150,6 +151,12 @@ SECTIONS __ld_sheap = .; . = . + __ld_heap_size; __ld_eheap = .; + . = ALIGN(4); + __ld_start_stack_corruption_detect_area = .; + . = . + __stack_corruption_area_size; + . = ALIGN(4); + __ld_end_stack_corruption_detect_area = .; + __ld_end_stack = .; . = . + __ld_stack_size; . = ALIGN(4); } >RAM