cancel
Showing results for 
Search instead for 
Did you mean: 

Resum Task from ISR: CMSIS osThreadResume does not use xTaskResumeFromISR , how can that be solved?

Hello,

for acquiring Data I run a timer that does a I2CRead with DMA transfer and using a ISR for averaging

HAL_TIM_PeriodElapsedCallback -> HAL_I2C_Mem_Read_DMA

HAL_I2C_MemRxCpltCallback -> "Ava-Function"/Lowpassfilter

"AvgCnt ==16" -> "Schedule a Task"

After 16 Averages I'd like to schedule a task(resume a suspended task) to do further calculation. For that purpose I think a task would solve the issue by using xTaskResumeFromISR  buth that is not used in the osThreadResume, it presents an error of called from an ISR.

osStatus_t osThreadResume (osThreadId_t thread_id) {
  TaskHandle_t hTask = (TaskHandle_t)thread_id;
  osStatus_t stat;
 
  if (IS_IRQ()) {
    stat = osErrorISR;
  }
  else if (hTask == NULL) {
    stat = osErrorParameter;
  }
  else {
    stat = osOK;
    vTaskResume (hTask);
  }
 
  return (stat);
}
#endif /* (configUSE_OS2_THREAD_SUSPEND_RESUME == 1) */

Why is that and how can that be resolved using the CMSIS abstraction-layer? Or did I miss something in the CMCIS?

Thanks a lot for the help.

Best regards, Seppel

8 REPLIES 8
KnarfB
Principal III

Don't know why that is, it may make porting the CMSIS layer to other RTOSes simpler. You seem to use CMSIS v2 API, v1 supports it.

Anyway, I would use a semaphore, i.e. osSemaphoreRelease in the ISR and osSemaphoreAcquire in the task. Or a message queue.

Suspending a task does not give you control on where in the task loop excatly the suspended task will stop, and later continue.

Hello,

interesting, do you know why it was removed from CMSIS V2?

To give you more inside information, the processing takes longer than one ISR-Interval triggered by the timer. The Averaging is very simple, so it can be done in the ISR. The processing takes longer, it cannot be done within the ISR. That is why I need to do it in a high priority task.

I use a queue, but as far as I'm aware there is no "Task-Scheduling" attached, no resuming of tasks when a queue has new elements. This means a Task may be delayed/"suspended by a timer" and would have to asynchronously poll for values in the queue. However, I'd like to synchronize the value-processing so I get a better Realtime behavior. 

To have some loose synchronization, within the Task itself is suspending the task. If the ISR is executed, it put values into the queue and then resume the task. The task will run and process the data and suspends itself once it is finished all elements in the queue. Even if the Task-execution takes longer, resuming it a 2nd time will not be a problem and the values of the following ISR's that may occur simultaneously will just be put into the queue.

Maybe there are better ways, I must admit I'm not a FreeRTOS-expert.

Thanks a lot.

Best Regards, Seppel

P.S. What is very interesting is that the STM32CubeIDE has a checkbox for "xTaskResumeFromISR", however ARM's CMSIS V2 does not use it.

0693W00000FBZywQAH.png 

KnarfB
Principal III

> I use a queue, but as far as I'm aware there is no "Task-Scheduling" attached

It should. In the implementation of osMessageQueuePut there are lines

      if (xQueueSendToBackFromISR (hQueue, msg_ptr, &yield) != pdTRUE) {
        stat = osErrorResource;
      } else {
        portYIELD_FROM_ISR (yield);
      }

If a task waiting for the queue is unblocked by xQueueSendToBackFromISR , yield is set to 1 and portYIELD_FROM_ISR will set the scheduler interrupt pending, such that the scheduler will run after the (all) interrupts finished. This is in accordance to the docs https://www.freertos.org/xQueueSendToBackFromISR.html

hth

KnarfB

Hello @KnarfB​ ,

what is "yield" actually, I do not know that from other OS'es. So far I was out of luck to find a good explainaition/tutorial on what it really is, how it should be used, etc. .

Thanks a lot, Best Regards, Seppel

Hello,

there is a good article: https://stackoverflow.com/questions/58631246/freertos-why-to-call-taskyield-from-isr-method-within-the-isrhandler

As far as I understand it, by calling taskYIELD_FROM_ISR at the end of the ISR, the scheduler is called and checks the priorities of the tasks, so the context can immediately switch from the ISR to the highest priority task that is ready to run.

Did I get that right?

I still struggle on "portYield", "taskYield",... what does port mean, what is a port in an RTOS?

Best Regards,

Best Regards, Seppel

KnarfB
Principal III

> Did I get that right?

Yes, that's it. Nice article.

port... means here ported to a certain MCU architecture like ARMv7 Cortex-M. The macros implement the interface to architecture specific code like assembly code or fiddling with the interrupt controller. Most of the FreeRTOS source code is architecture agnostic.

My first contact with yield was in Windows 3.11 🙂 which didn't use preemption for task switching but cooperative multitasking. I.e. a task called yield (or similar functions) to indicate that it is ready to be descheduled. Like a yield sign indicates that you should be ready to stop if required by the traffic (scheduler) rules.

For preemptive multitasking, IMHO yield shouldn't be used in user code.

BTW: For real-time tracing of scheduling events, I revived a tool used for another processor years ago: https://gitlab.com/KnarfB/timedoctor. Maybe you want to try it out.

hth

KnarfB

Piranha
Chief II

Hello,

sorry for the late reply, I have found a solution that works, I have it running with two I2C's:

0693W00000GXU9SQAX.gif 

I do a avery simple PT1 average in the "TransferComplete" and every 32 averages I fill the Queue. If I have more time I will write a small documentation/tutorial.

Thanks eveyone in the forum supporting, great community.

Best Regards, Seppel