1

I am using stm32f4 nucleuo board. I can transmit the audio data through usb to PC without FreeRTOS. Now I want to learn how to integrate the FreeRTOS and usb together. But I have some questions about how fundamentally threads and ISR interact with each other.
Below I have two files.

In main.c, there are two threads created.
In usb_thread, I initialize usb dirver and do nothing else.
In vr_thread, it waits state == 1 and process 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);
    }
  }
}

In app.c, USB_AUDIO_CallBack will be called by usb ISR every 1 millisecond. It transmit PCM_Buffer to PC first because it is really important, then it changes state to 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;

}

Here are my questions.
1. How to find out the unit counting tick of FreeRTOS? USB_AUDIO_CallBack will be called every 1 millisecond, how to know FreeRTOS basic tick is faster or slower than 1 millisecond. Is FreeRTOS tick equal to systick?
2. Let's assume the process time of process_buffer is less than 1 millisecond. What I want to accomplish here is described below

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

I really doubt it is the correct way to do it. Or should I use suspend() and resume()?
3. Is using extern to declare global PCM_Buffer the correct way to pass variable between threads or should I use queue in FreeRTOS?
I know these questions are trivial but I really want to understand them. Any helpful document or website is welcome. Thanks.

Lion Lai
  • 1,862
  • 2
  • 20
  • 41

1 Answers1

1
  1. To convert real time to systick you can use macro pdMS_TO_TICKS(xTimeInMS).
  2. You can define your USB_AUDIO_CallBack also as a thread (or task) or paste the code from the callback to vr_thread (as your application works on only one processor). Then inside the USB ISR you can send a notification using function vTaskNotifyGiveFromISR and receive it inside vr_thread by calling ulTaskNotifyTake. After receiving the notification you can call Send_Audio_to_USB((int16_t *)(PCM_Buffer), NUM_AUDIO_BUF);
    and then process_buffer(PCM_Buffer);. It is better to bring out the code from callback to task, because the ISR handler will finish it's job faster as Send_Audio_to_USB function could run long time. You also keep things to be executed in the same order as you needed.
  3. I think that you mean volatile instead of extern. If you want to use this buffer along different threads and ISRs you should define it as volatile, but if you will use the approach with only one task you can declare this buffer as local buffer.
K. Koovalsky
  • 596
  • 4
  • 17
  • Hi, thank you for your response, but currently I am occupied by other tasks that I can not try this. I will try it immediately when I can. – Lion Lai Aug 12 '17 at 08:24