Issue #20: Add stack checking based on protection area between stack and heap
This commit is contained in:
		@@ -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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@
 | 
			
		||||
#include <reflow-controller/stack-check.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stm-periph/rng.h>
 | 
			
		||||
#include <stm-periph/crc-unit.h>
 | 
			
		||||
 | 
			
		||||
extern char __ld_top_of_stack;
 | 
			
		||||
extern char __ld_end_stack;
 | 
			
		||||
@@ -47,22 +48,27 @@ int32_t stack_check_get_free()
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	volatile uint32_t *ptr = &__ld_start_stack_corruption_detect_area;
 | 
			
		||||
	volatile uint32_t *end_ptr = &__ld_end_stack_corruption_detect_area;
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	end_ptr--;
 | 
			
		||||
 | 
			
		||||
	random_number_gen_init(false);
 | 
			
		||||
 | 
			
		||||
	while (ptr < end_ptr) {
 | 
			
		||||
	while (ptr < &end_ptr[-1]) {
 | 
			
		||||
		rng_stat = random_number_gen_get_number(&rng_number, true);
 | 
			
		||||
 | 
			
		||||
		if (rng_stat != RNG_ERROR_OK) {
 | 
			
		||||
@@ -74,13 +80,31 @@ int stack_check_init_corruption_detect_area(void)
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@
 | 
			
		||||
/* USER PARAMETERS */
 | 
			
		||||
__ld_stack_size = 0x3000;
 | 
			
		||||
__ld_heap_size  = 0x2100;
 | 
			
		||||
__stack_corruption_area_size = 64;
 | 
			
		||||
__stack_corruption_area_size = 128;
 | 
			
		||||
 | 
			
		||||
/* END OF USER PARAMETERS */
 | 
			
		||||
ENTRY(Reset_Handler)
 | 
			
		||||
@@ -151,12 +151,12 @@ SECTIONS
 | 
			
		||||
		__ld_sheap = .;
 | 
			
		||||
		. = . + __ld_heap_size;
 | 
			
		||||
		__ld_eheap = .;
 | 
			
		||||
		. = ALIGN(4)
 | 
			
		||||
		. = ALIGN(4);
 | 
			
		||||
		__ld_start_stack_corruption_detect_area = .;
 | 
			
		||||
		. = . + __stack_corruption_area_size;
 | 
			
		||||
		. = ALIGN(4);
 | 
			
		||||
		__ld_end_stack_corruption_detect_area = .;
 | 
			
		||||
		__ld_end_stack = .
 | 
			
		||||
		__ld_end_stack = .;
 | 
			
		||||
		. = . + __ld_stack_size;
 | 
			
		||||
		. = ALIGN(4);
 | 
			
		||||
	} >RAM
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user