2025-10-22 3:17 PM
Hey I am very new to this world. I study Data science and AI and I am currently writing my thesis on Federated Learning on Edge Devices.
I am currently really really struggling on the device side. I have a quantized Yolov8n model fine tuned on weed detection dataset. My goal is to first upload the model onto my board which is a NUCLEO-U575ZI-Q with STM32U575ZIT6QU mcu. I tried the systemPerformance template from X-Cube-AI it works but I can not manage to run my code (mostly ChatGPTs). I tried a lot of different things but could only make the device print over UART for now. I need someone who is familiar with the app and mcu programming. Here is the code of my last attempt which failed. I tried to follow DigiKey's X-Cube-AI tutorial. The device seems to crash into the void HardFault_Handler(void).
Here is my main.c :
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* 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 provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "app_x-cube-ai.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "ai_datatypes_defines.h"
#include "ai_platform.h"
#include "yolov8n.h"
#include "yolov8n_data.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
CRC_HandleTypeDef hcrc;
TIM_HandleTypeDef htim16;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
uint8_t msg[] = "Hello from USART3\r\n";
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void SystemPower_Config(void);
static void MX_GPIO_Init(void);
static void MX_ICACHE_Init(void);
static void MX_CRC_Init(void);
static void MX_TIM16_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
char buf[50];
int buf_len = 0;
ai_error ai_err;
ai_i32 nbatch;
uint32_t timestamp;
float y_val;
// Chunk of memory used to hold intermediate values for neural network
AI_ALIGNED(4) ai_u8 activations[AI_YOLOV8N_DATA_ACTIVATIONS_SIZE];
// Buffers used to store input and output tensors
AI_ALIGNED(4) ai_i8 in_data[AI_YOLOV8N_IN_1_SIZE_BYTES];
AI_ALIGNED(4) ai_i8 out_data[AI_YOLOV8N_OUT_1_SIZE_BYTES];
// Pointer to our model
ai_handle yolov8n = AI_HANDLE_NULL;
// Initialize wrapper structs that hold pointers to data and info about the
// data (tensor height, width, channels)
// Input/Output buffer handles
ai_buffer *ai_input;
ai_buffer *ai_output;
// Get I/O buffer descriptors at runtime
ai_input = ai_yolov8n_inputs_get(AI_HANDLE_NULL, NULL);
ai_output = ai_yolov8n_outputs_get(AI_HANDLE_NULL, NULL);
// Fill network parameters at runtime
ai_network_params ai_params;
ai_params.params = ai_yolov8n_data_weights_buffer_get(ai_yolov8n_data_weights_get());
ai_params.activations = ai_yolov8n_data_activations_buffer_get(activations);
// Set pointers wrapper structs to our data buffers
ai_input[0].data = AI_HANDLE_PTR(in_data);
ai_output[0].data = AI_HANDLE_PTR(out_data);
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the System Power */
SystemPower_Config();
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ICACHE_Init();
MX_CRC_Init();
MX_TIM16_Init();
MX_X_CUBE_AI_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Transmit(&huart1, msg, sizeof(msg), 100);
// Start timer/counter
HAL_TIM_Base_Start(&htim16);
// Greetings!
buf_len = sprintf(buf, "\r\n\r\nSTM32 X-Cube-AI test\r\n");
HAL_UART_Transmit(&huart1, (uint8_t *)buf, buf_len, 100);
// Create instance of neural network
ai_err = ai_yolov8n_create(&yolov8n, AI_YOLOV8N_DATA_CONFIG);
if (ai_err.type != AI_ERROR_NONE)
{
buf_len = sprintf(buf, "Error: could not create NN instance\r\n");
HAL_UART_Transmit(&huart1, (uint8_t *)buf, buf_len, 100);
while(1);
}
// Initialize neural network
if (!ai_yolov8n_init(yolov8n, &ai_params))
{
buf_len = sprintf(buf, "Error: could not initialize NN\r\n");
HAL_UART_Transmit(&huart1, (uint8_t *)buf, buf_len, 100);
while(1);
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// Fill input buffer (use test value)
for (uint32_t i = 0; i < AI_YOLOV8N_IN_1_SIZE; i++)
{
((ai_float *)in_data)[i] = (ai_float)2.0f;
}
// Get current timestamp
timestamp = htim16.Instance->CNT;
// Perform inference
nbatch = ai_yolov8n_run(yolov8n, &ai_input[0], &ai_output[0]);
if (nbatch != 1) {
buf_len = sprintf(buf, "Error: could not run inference\r\n");
HAL_UART_Transmit(&huart1, (uint8_t *)buf, buf_len, 100);
}
// Read output (predicted y) of neural network
y_val = ((float *)out_data)[0];
// Print output of neural network along with inference time (microseconds)
buf_len = sprintf(buf,
"Output: %f | Duration: %lu\r\n",
y_val,
htim16.Instance->CNT - timestamp);
HAL_UART_Transmit(&huart1, (uint8_t *)buf, buf_len, 100);
// Wait before doing it again
HAL_Delay(500);
/* USER CODE END WHILE */
//MX_X_CUBE_AI_Process();
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 10;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 1;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_PCLK3;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief Power Configuration
* @retval None
*/
static void SystemPower_Config(void)
{
/*
* Switch to SMPS regulator instead of LDO
*/
if (HAL_PWREx_ConfigSupply(PWR_SMPS_SUPPLY) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN PWR */
/* USER CODE END PWR */
}
/**
* @brief CRC Initialization Function
* @PAram None
* @retval None
*/
static void MX_CRC_Init(void)
{
/* USER CODE BEGIN CRC_Init 0 */
/* USER CODE END CRC_Init 0 */
/* USER CODE BEGIN CRC_Init 1 */
/* USER CODE END CRC_Init 1 */
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CRC_Init 2 */
/* USER CODE END CRC_Init 2 */
}
/**
* @brief ICACHE Initialization Function
* @PAram None
* @retval None
*/
static void MX_ICACHE_Init(void)
{
/* USER CODE BEGIN ICACHE_Init 0 */
/* USER CODE END ICACHE_Init 0 */
/* USER CODE BEGIN ICACHE_Init 1 */
/* USER CODE END ICACHE_Init 1 */
/** Enable instruction cache (default 2-ways set associative cache)
*/
if (HAL_ICACHE_Enable() != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ICACHE_Init 2 */
/* USER CODE END ICACHE_Init 2 */
}
/**
* @brief TIM16 Initialization Function
* @PAram None
* @retval None
*/
static void MX_TIM16_Init(void)
{
/* USER CODE BEGIN TIM16_Init 0 */
/* USER CODE END TIM16_Init 0 */
/* USER CODE BEGIN TIM16_Init 1 */
/* USER CODE END TIM16_Init 1 */
htim16.Instance = TIM16;
htim16.Init.Prescaler = 80 - 1;
htim16.Init.CounterMode = TIM_COUNTERMODE_UP;
htim16.Init.Period = 65535;
htim16.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim16.Init.RepetitionCounter = 0;
htim16.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim16) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM16_Init 2 */
/* USER CODE END TIM16_Init 2 */
}
/**
* @brief USART1 Initialization Function
* @PAram None
* @retval None
*/
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 1000000;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @PAram None
* @retval None
*/
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @PAram file: pointer to the source file name
* @PAram line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
I would really appreciate any help. I will also have to calculate backpropagation for the federated learning so anyone who's nice enough to mentor me for this project is welcomed.
Thank you,
Adhygame