0

I am running an application which reads ADC data through DMA at a frequency of 12kHz and transfers the captured data in a queue as soon as I get an interrupt.

Following is the configuration

  • STM32L496
  • CMSIS RTOS 2

Following are the problems I am facing:

  1. Higher priority task gets initialized and running before other tasks are initialized.
  2. Getting different errors when queue size is changed
osThreadId_t main_task_id;
osThreadId_t acquisition_task_id;

const osThreadAttr_t main_thread_attr = {
    .stack_size = 1024U,
    .priority = osPriorityAboveNormal3,
};
const osThreadAttr_t acq_thread_attr = {
    .stack_size = 1024U,
    .priority = osPriorityAboveNormal2,
};

osMessageQueueId_t main_queue_id = NULL;
osMessageQueueId_t acquisition_queue_id = NULL;


main(void)
{
    osKernelInitialize();
    main_task_init();
    acquisition_task_init();
    osKernelStart();
}

void main_task(void *argument)
{
    osStatus_t status;
    message_t msg;
    switch_state swt_state;

    swt_state = get_switch_state();
    if(swt_state == SWITCH_ON)
    {
        msg.type = START_ADC_CAPTURE;
        status = osMessageQueuePut(main_queue_id, &msg, 0U, 0U);
        if (status != osOK)
        {
            // Handle error
        }
    }

    memset(msg, 0x00, sizeof(msg));

    while(1)
    {
        status = osMessageQueueGet(main_queue_id, &msg, NULL, osWaitForever);
        if (status != osOK)
        {
            // Handle error
        }
        
        if (msg.type == START_ADC_CAPTURE)
        {
            // start capturing ADC data
        }
    }
}

void main_task_init(void)
{
    main_queue_id = osMessageQueueNew(10, sizeof(message_t), NULL);
    if (main_queue_id == NULL)
    {
        // Handle error
    }

    main_task_id = osThreadNew(main_task, NULL, &main_thread_attr);
    if (main_task_id == NULL)
    {
        // Handle error
    }
}

void acquisition_task(void *argument)
{
    message_t msg;
    osStatus_t status;
    while(1)
    {
        status = osMessageQueueGet(acquisition_queue_id, &msg, NULL, osWaitForever);
        if (status != osOK)
        {
            // Handle error
        }
    }
}

void acquisition_task_init(void)
{
    acquisition_queue_id = osMessageQueueNew(10, sizeof(message_t), NULL);
    if (acquisition_queue_id == NULL)
    {
        // Handle error
    }

    acquisition_task_id = osThreadNew(acquisition_task, NULL, &acq_thread_attr);
    if (acquisition_task_id == NULL)
    {
        // Handle error
    }
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    osStatus_t status;
    message_t msg;

    memcpy(msg.buff, l_buff, l_buff_size * sizeof(uint16_t));
    msg.type = ADC_DATA;

    status = osMessageQueuePut(acquisition_queue_id, &msg, 0U, 0U);
    if (status != osOK)
    {
        // Handle error
    }
}

When I set acquisition_queue msg_count to 10, osMessageQueueGet(acquisition_queue_id, &msg, NULL, osWaitForever); in acquisition_task is never called and queue becomes full resulting in osErrorResource error. If I set msg_count to 20, osMessageQueueGet(acquisition_queue_id, &msg, NULL, osWaitForever); gets called but it keeps on waiting and immediately get osRtxErrorISRQueueOverflow error.

How to resolve this issue?

I tried adding random delay before starting capture to see what happens, no change is observed.

4
  • You never put anything in the main queue, so the main thread will just block forever and let the other thread run. The other thread will read from the acquisition as quickly as it can (since there are no other tasks). If the acquisition queue gets full then you need to process the data quicker. Try turning the rate down to 100Hz or so, and check that everything works, and then turn it back up until you have a problem.. Commented Jan 17, 2023 at 19:22
  • My bad. Based on switch button state I start capturing ADC data. I have edited the code. Will try changing sampling rate and check if the problem persists. Commented Jan 18, 2023 at 2:37
  • If you're just looking to have the main thread wait for the acquisition thread to start, then Thread Flags look like an easy way to go about it. This might not help with your problem if the acquisition thread doesn't actually get time to run, though. Commented Jan 18, 2023 at 9:50
  • Thread Flags seems like a solution for now; far better than osDelay. After debugging further I am finding the issue has something to do with ISR FIFO Queue. Currently ISR FIFO Queue is set to 16 and queue length is 10. osMessageQueueGet from acquisition_task is never getting called if ADC with DMA is enabled. Commented Jan 20, 2023 at 13:48

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.