2025-07-13 4:41 AM - last edited on 2025-07-14 8:38 AM by Amel NASRI
Hi everyone,
I'm working on deploying an MLP model on STM32F746 using X-CUBE-AI. The model was converted from ONNX format, and I’m running into trouble feeding the input features and retrieving the prediction result
I want to run inference with the following flow:
float input_data[60] = { /* preprocessed features */ };
float output_data[1]; // expecting softmax probabilities
int output_label; // expecting predicted class label
I'm unclear on how to actually use the interface generated by Cube.AI:
What are the correct steps to initialize and fill the ai_buffer structs?
Do I need to manually align my input/output arrays, or use the data_ins[] / data_outs[] generated by default?
What is the purpose of macros like AI_HANDLE_PTR(...) and AI_MNETWORK_IN?
I tried calling ai_mlp_run(...) like this:
but I get build errors or invalid pointer types
model information :
app_X-cube-ai.h:
2025-07-21 1:17 AM
Hello @Stone_chan,
When you create your project in CubeMX, select the last version of X Cube AI and the application Template.
Then in the generated code, you will find app_x-cube-ai.c in /X-Cube-AI-App.
The main functions here are the MX_X_CUBE_AI_Init and MX_X_CUBE_AI_Process.
In the MX_X_CUBE_AI_Process you will find 3 parts:
The way to pass data is through the function acquire_and_process_data(data_ins). By default, it looks like this:
int acquire_and_process_data(ai_i8* data[])
{
/* fill the inputs of the c-model
for (int idx=0; idx < AI_NETWORK_IN_NUM; idx++ )
{
data[idx] = ....
}
*/
return 0;
}
The for loop here is used if you have multiple input to give your model. In most case you have one, so you will only pass 1 time and fill data[0].
Same for the post_process(data_outs) function.
The data that you have to pass are 1D array of size of your input/output and be careful, by default the data_ins and data_outs are in int8 (ai_i8). So if you are using float32 for example, make sure to adapt the code.
For your board in particular, the MX_X_CUBE_AI_Process is not called in the main.c.
You can add it in the while(1) in the main function:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* Enable the CPU Cache */
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
/* 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 clock */
SystemClock_Config();
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC3_Init();
MX_CRC_Init();
MX_DCMI_Init();
MX_DMA2D_Init();
MX_ETH_Init();
MX_FMC_Init();
MX_I2C1_Init();
MX_I2C3_Init();
MX_LTDC_Init();
MX_QUADSPI_Init();
MX_RTC_Init();
MX_SAI2_Init();
MX_SDMMC1_SD_Init();
MX_SPDIFRX_Init();
MX_SPI2_Init();
MX_TIM1_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_TIM5_Init();
MX_TIM8_Init();
MX_TIM12_Init();
MX_USART1_UART_Init();
MX_USART6_UART_Init();
MX_FATFS_Init();
MX_X_CUBE_AI_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* definition and creation of defaultTask */
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 4096);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
MX_X_CUBE_AI_Process();
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Have a good day,
Julian