2025-09-19 9:55 AM
Hello,
I am currently trying to collect acceleration data at 16 kHz from a USB accelerometer using an STM32F401RET6 in USB Host mode.
I created two tasks: vUSBInitTask and vUSBReadTask as shown below.
void vUSBInitTask(void *pvParameters)
{
MX_USB_HOST_Init();
for (;;)
{
MX_USB_HOST_Process();
vTaskDelay(pdMS_TO_TICKS(10));
}
}
void vUSBReadTask(void *pvParameters)
{
AUDIO_HandleTypeDef *audio_handle;
uint8_t *buf;
char msg[64];
static int32_t sample_buffer[SAMPLES_TO_SAVE];
int collected_samples = 0;
while (Appli_state != APPLICATION_READY) // wait until USB is ready
{
vPrintString("Waiting for USB ready...\r\n");
vTaskDelay(pdMS_TO_TICKS(500));
}
for (;;)
{
audio_handle = (AUDIO_HandleTypeDef *)hUsbHostFS.pActiveClass->pData;
if (audio_handle && audio_handle->microphone.supported) {
buf = audio_handle->microphone.buf;
if (buf) {
USBH_StatusTypeDef status = USBH_IsocReceiveData(&hUsbHostFS,
buf,
audio_handle->microphone.frame_length,
audio_handle->microphone.Pipe);
if (status == USBH_OK) {
int frames_in_buf = audio_handle->microphone.frame_length / FRAME_SIZE;
for (int i = 0; i < frames_in_buf; i += DOWNSAMPLE_FACTOR)
{
if (collected_samples < SAMPLES_TO_SAVE)
{
int32_t sample_val = convert24bitToInt32(&buf[i * FRAME_SIZE]);
sample_buffer[collected_samples++] = sample_val;
}
if (collected_samples >= SAMPLES_TO_SAVE) {
for (int i = 0; i < SAMPLES_TO_SAVE; i++) {
float sample_val = (float)sample_buffer[i] * SCALE_FACTOR;
uint8_t packet[6]; // header 2 + float 4
packet[0] = 0xAA;
packet[1] = 0x55;
memcpy(&packet[2], &sample_val, sizeof(float));
HAL_UART_Transmit(&huart2, packet, sizeof(packet), HAL_MAX_DELAY);
}
collected_samples = 0;
}
}
}
}
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
Below is my main.c initialization (simplified):
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
const char *boot = "[BOOT] UART ready\r\n";
HAL_UART_Transmit(&huart2, (uint8_t*)boot, strlen(boot), 100);
MX_I2C1_Init();
lcd_init();
xBinarySemaphore = xSemaphoreCreateBinary();
if (xBinarySemaphore != NULL) {
xTaskCreate(vUSBInitTask, "USB Task", 512, NULL, 1, NULL);
xTaskCreate(vUSBReadTask, "USBRead", 1024, NULL, 2, NULL);
vTaskStartScheduler();
}
while (1) {
// MX_USB_HOST_Process();
}
}
The problem:
With vTaskDelay(pdMS_TO_TICKS(10)) inside vUSBReadTask, the actual sampling rate is only ~1600 Hz, far below the target 16 kHz.
When I change it to pdMS_TO_TICKS(5), I only get repeated identical data values.
When I change it to pdMS_TO_TICKS(1), I only get a single sample.
So it seems that the sampling rate strongly depends on the task delay, and the behavior becomes inconsistent.
If anyone has experience with USB Audio Class accelerometers on STM32 (especially STM32F4 series), could you please help me understand the root cause of this issue? Is it a problem with how I am handling isochronous transfers, buffering, or scheduling in FreeRTOS?
Any advice or guidance would be greatly appreciated. Thank you so much!
2025-09-19 12:36 PM
What is your RTOS configTICK_RATE_HZ?