Skip to content
Merged
12 changes: 10 additions & 2 deletions app/rev3/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ TARGET = STM32H733VGTx
# building variables
######################################
# debug build?
DEBUG = 1
DEBUG ?= 1
# optimization
OPT = -Og

# run validation?
VALIDATION ?= 0

#######################################
# paths
Expand Down Expand Up @@ -51,6 +52,7 @@ $(DRIVER_DIR)/usb/USB_DEVICE/App/usbd_desc.c \
$(DRIVER_DIR)/usb/USB_DEVICE/App/usbd_cdc_if.c \
$(DRIVER_DIR)/usb/USB_DEVICE/Target/usbd_conf.c \
$(DRIVER_DIR)/usb/usb.c \
$(DRIVER_DIR)/flash/MX25L51245GZ2I-08G.c \
$(LIB_DIR)/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd.c \
$(LIB_DIR)/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd_ex.c \
$(LIB_DIR)/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_usb.c \
Expand Down Expand Up @@ -152,6 +154,7 @@ C_INCLUDES = \
-I$(MOD_DIR)/error_sdr \
-I$(MOD_DIR)/math_sdr \
-I$(DRIVER_DIR)/led \
-I$(DRIVER_DIR)/flash \
-I$(DRIVER_DIR)/usb/USB_DEVICE/App \
-I$(DRIVER_DIR)/usb/USB_DEVICE/Target \
-I$(INIT_DIR)/config/Inc \
Expand All @@ -173,6 +176,11 @@ ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif

ifeq ($(VALIDATION), 1)
C_SOURCES += hardware_validation.c
CFLAGS += -DDO_HARDWARE_VALIDATION
endif


# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
Expand Down
141 changes: 141 additions & 0 deletions app/rev3/hardware_validation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/**
******************************************************************************
* @file : hardware_validation.c
* @brief : Routines to validate components on the FC.
******************************************************************************
* @attention
*
* Copyright (c) 2026 Sun Devil Rocketry.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is covered under the
* BSD-3-Clause.
*
* https://opensource.org/license/bsd-3-clause
*
******************************************************************************
*/

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"
#include "led.h"
#include "flash.h"
#include "error_sdr.h"

/* Global Variables ----------------------------------------------------------*/



/* Private function prototypes -----------------------------------------------*/



/* Procedures ----------------------------------------------------------------*/

static void flash_validation_routine
(
void
)
{
/* Flash */
// Begin Performance Timer
volatile uint32_t start_time = HAL_GetTick();

// Init
HFLASH_BUFFER flash_handle;
memset(&flash_handle, 0, sizeof(HFLASH_BUFFER));
FLASH_STATUS flash_status = flash_init(&flash_handle);
uint8_t flash_buf[FLASH_PAGE_SIZE];
memset(flash_buf, 0, FLASH_PAGE_SIZE);
flash_handle.pbuffer = flash_buf;

assert_fail_fast( flash_status == FLASH_OK, ERROR_FLASH_INIT_ERROR );

// Set up HW validation routine
flash_status = flash_erase(&flash_handle);

assert_fail_fast( flash_status == FLASH_OK, ERROR_FLASH_CMD_ERROR );

// Run write sequence (once per page)
flash_buf[0] = 127;
for ( uint32_t i = 0; i < FLASH_MAX_ADDR; i+=FLASH_PAGE_SIZE ) {
flash_handle.address = i;
flash_status = flash_write(&flash_handle);
assert_fail_fast( flash_status == FLASH_OK, ERROR_FLASH_CMD_ERROR );
}

// Run read sequence and verify (once per page)
memset(flash_buf, 0, FLASH_PAGE_SIZE);
for ( uint32_t i = 0; i < FLASH_MAX_ADDR; i+=FLASH_PAGE_SIZE ) {
flash_handle.address = i;
flash_status = flash_read(&flash_handle, 2);
assert_fail_fast( flash_status == FLASH_OK, ERROR_FLASH_CMD_ERROR );
assert_fail_fast( flash_buf[0] == 127, ERROR_FLASH_CMD_ERROR );
assert_fail_fast( flash_buf[1] == 0xFF, ERROR_FLASH_CMD_ERROR );
}

// Test Block Erasures
// 4K
flash_status = flash_block_erase(0, FLASH_BLOCK_4K);
assert_fail_fast( flash_status == FLASH_OK, ERROR_FLASH_CMD_ERROR );
for ( uint32_t i = 0; i < 0x1000 - 1; i+=FLASH_PAGE_SIZE ) {
flash_handle.address = i;
flash_status = flash_read(&flash_handle, 2);
assert_fail_fast( flash_status == FLASH_OK, ERROR_FLASH_CMD_ERROR );
assert_fail_fast( flash_buf[0] == 0xFF, ERROR_FLASH_CMD_ERROR );
}

// 32K
flash_status = flash_block_erase(0, FLASH_BLOCK_32K);
assert_fail_fast( flash_status == FLASH_OK, ERROR_FLASH_CMD_ERROR );
for (uint32_t i = 0; i < 0x8000 - 1; i+=FLASH_PAGE_SIZE ) {
flash_handle.address = i;
flash_status = flash_read(&flash_handle, 2);
assert_fail_fast( flash_status == FLASH_OK, ERROR_FLASH_CMD_ERROR );
assert_fail_fast( flash_buf[0] == 0xFF, ERROR_FLASH_CMD_ERROR );
}

// 64K
flash_status = flash_block_erase(0, FLASH_BLOCK_64K);
assert_fail_fast( flash_status == FLASH_OK, ERROR_FLASH_CMD_ERROR );
for ( uint32_t i = 0; i < 0x10000 - 1; i+=FLASH_PAGE_SIZE ) {
flash_handle.address = i;
flash_status = flash_read(&flash_handle, 2);
assert_fail_fast( flash_status == FLASH_OK, ERROR_FLASH_CMD_ERROR );
assert_fail_fast( flash_buf[0] == 0xFF, ERROR_FLASH_CMD_ERROR );
}

// End Performance Timer
volatile uint32_t tdelta = HAL_GetTick() - start_time;
(void)tdelta; // suppress unused

} /* flash_validation_routine */


void run_hardware_validation
(
void
)
{
/* LED */
led_set_color(LED_WHITE);
HAL_Delay(1000);
led_set_color(LED_RED);
HAL_Delay(1000);
led_set_color(LED_BLUE);
HAL_Delay(1000);
led_set_color(LED_GREEN);
HAL_Delay(1000);

/* flash */
flash_validation_routine();

led_set_color(LED_WHITE);
//buzzer_num_beeps(/*2 beeps when buzzer is implemented to signal the end*/);
led_set_color(LED_GREEN);


} /* run_hardware_validation */
Comment on lines +134 to +141

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add some indication that the routine is finished

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My intention is to eventually set this up to use the uart debug interface for driver development, which should come soon.

14 changes: 11 additions & 3 deletions app/rev3/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "flash.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
Expand Down Expand Up @@ -78,7 +78,6 @@ static void MX_USART3_UART_Init(void);

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
Expand Down Expand Up @@ -125,8 +124,17 @@ int main(void)
MX_SPI4_Init();
MX_USART3_UART_Init();
MX_USB_DEVICE_Init();

/* USER CODE BEGIN 2 */

#ifdef DO_HARDWARE_VALIDATION
run_hardware_validation();
while (1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like there's a good chance that while(1) and the way the validation is done her in general is accidentally going to cost someone a particularly frustrating 45 minutes one day when they're trying to figure out why the firmware is seemingly not working, only to find out they had forgotten to remove this flag during a previous debug session.

I feel like we need some warning for this; at the very least, we could have a well-documented LED sequence to signal that it's a hardware validation build, and I also wonder if we could do something to tell SDEC and have it warn a user that they're on a hardware validation build.

@ETSells ETSells Jun 1, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is temporary. If we keep these routines after the initial HW bring up, they'll live in test and need a different way to be compiled into the FW. Right now, this is the only way we'll be running rev 3 until we port the app. Gonna go NAT.

Also, I intend to have our debug logging indicate the results of HW validation once implemented for rev 3.

#endif

/* Flash */
HFLASH_BUFFER flash_handle;
memset(&flash_handle, 0, sizeof(HFLASH_BUFFER));
FLASH_STATUS flash_status = flash_init(&flash_handle);
/* USER CODE END 2 */

/* Infinite loop */
Expand Down
8 changes: 7 additions & 1 deletion app/rev3/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ extern "C" {

/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_hal.h"
#include "sdr_pin_defines_A0010.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
Expand All @@ -53,7 +54,12 @@ extern "C" {
void Error_Handler(void);

/* USER CODE BEGIN EFP */

#ifdef DO_HARDWARE_VALIDATION
void run_hardware_validation
(
void
);
#endif
/* USER CODE END EFP */

/* Private defines -----------------------------------------------------------*/
Expand Down
2 changes: 1 addition & 1 deletion driver
2 changes: 1 addition & 1 deletion mod
Submodule mod updated 1 files
+20 −1 error_sdr/error_sdr.h
9 changes: 8 additions & 1 deletion test/app/rev2/error_int/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ TARGET = error_int
################################################################

# Debug build?
DEBUG = 1
DEBUG ?= 0
# Optimization
OPT = -Og

Expand Down Expand Up @@ -112,6 +112,13 @@ C_DEFS = \
-DUSE_CALLBACK_TABLE \
-DUNIT_TEST

# Add debug/release flags
ifeq ($(DEBUG), 1); then
C_DEFS += -DDEBUG
else
C_DEFS += -DRELBLD
endif

CFLAGS = $(C_INCLUDES) $(C_DEFS) $(OPT) -Wall -g

# Disable some warnings
Expand Down
59 changes: 58 additions & 1 deletion test/app/rev2/error_int/test_error_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,62 @@ TEST_ASSERT_FALSE( "Robustness: Test that attempting to get a message from an em
} /* test_warning_messages */


/*******************************************************************************
* *
* PROCEDURE: *
* test_assert_constructs *
* *
* DESCRIPTION: *
* Test the assert macros (no coverage provided). *
* *
*******************************************************************************/
void test_assert_constructs
(
void
)
{
/*------------------------------------------------------------------------------
Case 1: Assert Fail
------------------------------------------------------------------------------*/
default_error_handler.error_callback = TEST_CALLBACK_dflt_handler; // can't be reset
default_handler_hit = false;
assert_fail_fast( 1 == 0, ERROR_COMMON_CLOCK_CONFIG_ERROR );
TEST_ASSERT_EQ_UINT( "Test whether the default handler was hit.", default_handler_hit, true );

/*------------------------------------------------------------------------------
Case 2: Assert Pass
------------------------------------------------------------------------------*/
default_handler_hit = false;
assert_fail_fast( 1 == 1, ERROR_COMMON_CLOCK_CONFIG_ERROR );
TEST_ASSERT_EQ_UINT( "Test whether the default handler was hit.", default_handler_hit, false );

/*------------------------------------------------------------------------------
Case 3: Debug Assert in Release Mode
------------------------------------------------------------------------------*/
#ifndef DEBUG
default_handler_hit = false;
debug_assert( 0 == 1, ERROR_COMMON_CLOCK_CONFIG_ERROR );
TEST_ASSERT_EQ_UINT( "Test whether the default handler was hit.", default_handler_hit, false );
#else

/*------------------------------------------------------------------------------
Case 4: Debug Assert Fail in Debug Mode
------------------------------------------------------------------------------*/
default_handler_hit = false;
debug_assert( 0 == 1, ERROR_COMMON_CLOCK_CONFIG_ERROR );
TEST_ASSERT_EQ_UINT( "Test whether the default handler was hit.", default_handler_hit, true );

/*------------------------------------------------------------------------------
Case 5: Debug Assert Pass in Debug Mode
------------------------------------------------------------------------------*/
default_handler_hit = false;
debug_assert( 1 == 1, ERROR_COMMON_CLOCK_CONFIG_ERROR );
TEST_ASSERT_EQ_UINT( "Test whether the default handler was hit.", default_handler_hit, false );
#endif

} /* test_assert_constructs */


/*******************************************************************************
* *
* PROCEDURE: *
Expand All @@ -317,7 +373,8 @@ unit_test tests[] =
{ "error_fail_fast: I2C (IMU and Baro) initialization callbacks.", test_i2c_init_errors },
{ "error_fail_fast: Test callback table miss.", test_callback_table_miss }, /* ensure you're done with the default handler! cannot reset. */
{ "Test log-severity messages.", test_log_messages },
{ "Test warning-severity messages.", test_warning_messages }
{ "Test warning-severity messages.", test_warning_messages },
{ "Test assertion macros.", test_assert_constructs }
};

/*------------------------------------------------------------------------------
Expand Down