STM32F412使用 FreeRTOS 和 USB 进行音频处理



我正在使用stm32f4核板。我可以在没有 FreeRTOS 的情况下通过 USB 将音频数据传输到 PC。现在我想学习如何将 FreeRTOS 和 USB 集成在一起。但是我对线程和 ISR 如何从根本上相互作用有一些疑问。
下面我有两个文件。

在 main.c 中,创建了两个线程。
在usb_thread中,我初始化了 usb 目录,什么都不做。
在vr_thread中,它等待状态 == 1 并处理PCM_Buffer。

/* main.c */
extern uint16_t PCM_Buffer[16];
int state = 0;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
osThreadDef(usb_t, usb_thread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE);
osThreadDef(vr_t, vr_thread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE);
usb_thread_handle = osThreadCreate (osThread(usb_t), NULL);
usb_thread_handle = osThreadCreate (osThread(vr_t), NULL);
osKernelStart();
for (;;) {}
}
static void usb_thread(void const *argument)
{       
/*Do some initialization here.*/
for (;;) {}
}
static void vr_thread(void const *argument)
{
/*Do some initialization here.*/
for (;;) {
if (state == 1) {
state = 0;
process_buffer(PCM_Buffer);
}
}
}

在 app.c 中,USB ISR 将每 1 毫秒调用一次USB_AUDIO_CallBack。它首先将PCM_Buffer传输到PC,因为它非常重要,然后将状态更改为1。

/* app.c */
uint16_t PCM_Buffer[16];
extern int state;
void USB_AUDIO_CallBack(void) //It will be called by usb ISR every 10^-3 second.
{
Send_Audio_to_USB((int16_t *)(PCM_Buffer), NUM_AUDIO_BUF);
state = 1;
}

这是我的问题。
1. 如何找出 FreeRTOS 的单位计数刻度?USB_AUDIO_CallBack将是 每 1 毫秒调用一次,如何知道 FreeRTOS 基本即时报价是更快还是更慢 大于 1 毫秒。FreeRTOS tick 等于 systick 吗?
2.假设process_buffer的处理时间小于1毫秒。我想在这里完成的内容描述如下

hardware trigger
|
usb ISR
|
USB_AUDIO_CallBack
|
state=1
|
vr_thread process_buffer
|
state=0, then wait for hardware trigger again.

我真的怀疑这是正确的方法。还是我应该使用 suspend(( 和 resume((?
3. 使用 extern 声明全局PCM_Buffer是在线程之间传递变量的正确方法,还是应该在 FreeRTOS 中使用队列?
我知道这些问题是微不足道的,但我真的很想理解它们。欢迎任何有用的文档或网站。谢谢。

  1. 要将实时转换为 sysstick,您可以使用宏pdMS_TO_TICKS(xTimeInMS)
  2. 您也可以将USB_AUDIO_CallBack定义为线程(或任务(,或者将回调中的代码粘贴到vr_thread(因为应用程序仅在一个处理器上运行(。然后在USB ISR内部,您可以使用功能vTaskNotifyGiveFromISR发送通知,并通过调用ulTaskNotifyTakevr_thread内接收通知。收到通知后,您可以拨打Send_Audio_to_USB((int16_t *)(PCM_Buffer), NUM_AUDIO_BUF);
    ,然后process_buffer(PCM_Buffer);。最好将代码从回调带到任务,因为 ISR 处理程序将更快地完成其工作Send_Audio_to_USB因为函数可以运行很长时间。您还可以根据需要按相同的顺序保留要执行的内容。
  3. 我认为你的意思是volatile而不是extern.如果要在不同的线程和 ISR 中使用此缓冲区,则应将其定义为易失性,但如果仅对一个任务使用此方法,则可以将此缓冲区声明为本地缓冲区。

最新更新