Assistance Required with Edge Impulse CMSIS Deployment on ST IoT Discovery board

I have successfully trained a keyword spotting model using Edge Impulse and deployed it by generating a binary image and flashing it to the STM32L475 IoT Discovery board.

When I run the model using the AT+RUNIMPULSECONT command, it performs impressively, predicting keywords with over 85% accuracy. I would like to sincerely thank you for developing such a powerful and accessible platform.

However, since the binary image cannot be modified, I opted to regenerate the deployment using the Cube.MX CMSIS-PACK option. I successfully installed the required software packs and integrated the Edge Impulse SDK into a custom STM32CubeIDE project.

I followed your documentation and referenced your GitHub project:

:link: firmware-st-b-l475e-iot01a/main.cpp

To record audio for inference, I reused your MP34DT01 microphone driver and ei_microphone_interface.cpp.

Here is the content of my main() function:

int main(void)
{

/* USER CODE BEGIN 1 */

/* 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 clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_CRC_Init();

/* USER CODE BEGIN 2 */
microphone_present = ei_microphone_init();

if (EI_CLASSIFIER_FREQUENCY != 16000) {
ei_printf(“ERR: Frequency is %d but can only sample at 16000Hz\r\n”, (int)EI_CLASSIFIER_FREQUENCY);
}

int print_results = -(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW);

// summary of inferencing settings (from model_metadata.h)
ei_printf(“Inferencing settings:\r\n”);
ei_printf(“\tInterval: %.2f ms.\r\n”, (float)EI_CLASSIFIER_INTERVAL_MS);
ei_printf(“\tFrame size: %d\r\n”, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE);
ei_printf(“\tSample length: %d ms.\r\n”, EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16);
ei_printf(“\tNo. of classes: %d\r\n”, sizeof(ei_classifier_inferencing_categories) / sizeof(ei_classifier_inferencing_categories[0]));

run_classifier_init();

ei_microphone_inference_start(EI_CLASSIFIER_SLICE_SIZE);

/* USER CODE END 2 */

/* Infinite loop /
/
USER CODE BEGIN WHILE */
while (1)
{
bool m = ei_microphone_inference_record();
if (!m) {
ei_printf(“ERR: Failed to record audio…\r\n”);
break;
}

  signal_t signal;
  signal.total_length = EI_CLASSIFIER_SLICE_SIZE;
  signal.get_data = &ei_microphone_audio_signal_get_data;
  ei_impulse_result_t result = { 0 };

  EI_IMPULSE_ERROR r = run_classifier_continuous(&signal, &result, debug_nn);
  if (r != EI_IMPULSE_OK) {
	  ei_printf("ERR: Failed to run classifier (%d)\r\n", r);
	  break;
  }

  // print the predictions
  ei_printf("[");
  for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
	  ei_printf_float(result.classification[ix].value);
  #if EI_CLASSIFIER_HAS_ANOMALY == 1
		  ei_printf(", ");
  #else
		  if (ix != EI_CLASSIFIER_LABEL_COUNT - 1) {
			  ei_printf(", ");
		  }
  #endif
	  }
  #if EI_CLASSIFIER_HAS_ANOMALY == 1
	  ei_printf_float(result.anomaly);
  #endif
  ei_printf("]\r\n\n");

  if(result.classification[2].value > 0.5)
  {
	  ei_printf("off\r\n");
  }
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
ei_microphone_inference_end();
run_classifier_deinit();
/* USER CODE END 3 */
}

The application builds and runs without errors. However, when I monitor the serial output, I notice that the model fails to accurately recognize some keywords. The accuracy is significantly lower than when using the original binary from Edge Impulse Studio.

I’ve been troubleshooting this issue for nearly two weeks without success.

Here are a few relevant configuration details:

#define SAMPLE_BUFFER_SIZE 4000

#define BSP_AUDIO_IN_DEFAULT_BUFFER_SIZE 4000U

And here is the:

bool ei_microphone_inference_start(uint32_t n_samples)
{
inference.buffers[0] = (int16_t *)malloc(n_samples * sizeof(int16_t));

if (inference.buffers[0] == NULL) {
    return false;
}

inference.buffers[1] = (int16_t *)malloc(n_samples * sizeof(int16_t));

if (inference.buffers[1] == NULL) {
    free(inference.buffers[0]);
    return false;
}

inference.buf_select = 0;
inference.buf_count = 0;
inference.n_samples = n_samples;
inference.buf_ready = 0;

ei_microphone_inference_set_bsp_callback(&pdm_data_ready_inference_callback);

int32_t ret;
uint32_t state;
ret = BSP_AUDIO_IN_GetState(AUDIO_INSTANCE, &state);
if (ret != BSP_ERROR_NONE) {
    printf("Cannot start recording: Error getting audio state (%ld)\n", ret);
    return false;
}
if (state == AUDIO_IN_STATE_RECORDING) {
    printf("Cannot start recording: Already recording\n");
    return false;
}

ret = BSP_AUDIO_IN_Record(AUDIO_INSTANCE, (uint8_t *)sampleBuffer, SAMPLE_BUFFER_SIZE * 2);

if (ret != BSP_ERROR_NONE) {
    printf("Error failed to start recording (%ld)\n", ret);
    return false;
}

record_ready = true;

return true;

}

I’ve verified that the microphone clock is running at approximately 2.04 MHz, which is consistent with the binary image.

I’m using the default DFSDM configuration from your GitHub reference.

Despite this, I suspect that either:

  1. Some parameters are misconfigured in the CMSIS-based project, or
  2. The DMA/buffer handling is not functioning identically to the prebuilt binary.

I would truly appreciate your guidance in identifying what might be missing or misconfigured.

My project ID is 690540.

Kind regards,
Ahmad

Hi @ahmad.shokati

The first thing to check is that you have the matching number of features set in your Edge Impulse project and the CMSIS source code.

@ei_francesco can you comment on the microphone driver / buffering is that an ok route to take for customisation? Do they need to increase the buffer etc to align with the expected or take any further action?

Best

Eoin

We have had some inaccurate results with the CubeMX CMSIS pack in the past as well. Did you also tried the Open CMSIS pack deployment? This is also supported in the Cube IDE and import process is similar to the CubeMX CMSIS pack.

Hi @ahmad.shokati

which toolchain are you using ?
I think the default in Cube IDE is ST gcc v12, can you confirm ?
I saw wrong result when using it, especially for audio model.
One quick think is to use the ARM one v13 or v10.

regards,
fv

Hi Gents,

I’ve managed to identify the issue after reviewing a few posts.

Thank you for your response. It turns out that the CubeMX CMSIS pack isn’t compatible with the latest GCC version in STM32CubeIDE. Downgrading GCC to version 9 resolved the problem.

Warm regards,
Ahmad