Am using LPC55s69 Evk board
I want to implement interrupt handler for USART receive. When I use baremetal instead of FreeRtos interrupt handler works fine, but in the case of FreeRtos there seems a problem.
Basically, yield = xTaskResumeFromISR(xISRTaskHandle); this 1 when executed for the first time
After FLEXCOMM0_IRQHandler is done implementing it jumps to
portTASK_FUNCTION
and back to FLEXCOMM0_IRQHandler
and this cycle continues indefinitely
/*
* -----------------------------------------------------------
* The Idle task.
* ----------------------------------------------------------
*
* The portTASK_FUNCTION() macro is used to allow port/compiler specific
* language extensions. The equivalent prototype for this function is:
*
* void prvIdleTask( void *pvParameters );
*
*/
static portTASK_FUNCTION( prvIdleTask, pvParameters );
This piece of code is in tasks.c in kernel. Looks like this is idle task
And to answer the other question, Yes ISRTask is in ready state.
Better don’t (ab)use task suspend/resume for task synchronization !
Use task notification or a (binary) semaphore etc. designed for that.
Besides other implications resuming a non-suspended or not yet suspended task does nothing.
This is a potential source of a race condition.
The next thing to check is if PendSV_Handler is getting called after you return from the ISR. PendSV_Handler should call vTaskSwitchContext which should select the correct task.
I am not familiar with this particular CPU/platform, but is there anything that needs to be done in the ISR handler to acknowledge or ‘clear’ the pending interrupt? This almost seems like the moment the ISR handler exits, it is called again because the interrupt is still pending.
It was using USART_WriteBlocking API and was expecting USART ISR to fire. The correct API to use is USART_TransferSendNonBlocking.
It was first suspending the task and then calling UART send which would never get called as that task is suspended. The correct sequence should be - first invoke the send operation and then wait for a signal from the ISR.
If InitTask is not needed anymore, it should delete itself.
As @hs2 mentioned, it is never a good idea to use suspend/resume for synchronization and therefore, I updated the code to use semaphore instead.
Thanks for the input
But I need to use FLEXCOMM0_IRQHandler to get more involved in the code and not depend on driver code( ie task_handle)
Another thing is there is a slight misunderstanding, I want ISRTask to suspend when created and only wakeup when ISR jumps there
That means that, when recv interrupt occurs it should jump and execute remaining ISRTask
Regarding point-2 from your above reply, I found this style of execution here
(Which actually kinda makes sense, because firstly the ISRTask is suspended/semaphore_wait, then when ISR is executed it resumes ISRTask to send out the string and as it is while(1) it suspends again waiting for ISR , please let me know if I got this understanding correct)
Sure - you can do that. Look at the implementation of USART_TransferSendNonBlocking for what you need to do to kick off the transmission and look at the implementation of USART_TransferHandleIRQ for what all you need to do in your ISR. You cannot expect to call a blocking API and expect the ISR to fire.
The blocking APIs returns after the operation is complete -
Time spent inside the API
<------------------------------------------------------------------------->
+-------------------------------------------------------------------------+
^ ^
| |
| |
| |
Start Blocking Operation The blocking API returns after
the operation is complete.
<------------------------------------------------------------------------->
Time consumed in the operation
The non-blocking API, on the other hand, just starts the operation and returns. Later, when the operation is complete, the corresponding interrupt fires.
Time spent inside
the API
<----------------->
+--------------------------------------------------------------------------+
^ ^ ^
| | |
| | |
| | |
Start Non-Blocking The API returns Operation complete interrupt
Operation after starting the when the operation is complete.
operation
<------------------------------------------------------------------------->
Time consumed in the operation
As should be clear from the above, the recv interrupt will not fire until you kick off the receive operation.
This person uses a button pressed ISR which will fire whenever you press the button and that is why their solution works. I’d still recommend to use semaphore or task notification instead of suspend/resume.
The point to understand is what will cause the ISR to fire.
Also, you are sharing UART between two tasks without any synchronization which is not right. This post has very good discussion about that - Synchronizing UART TX
I am able to implement my own interrupt handler and it works fine for Tx and Rx.
This is the case where I implemented all my code in handler itself.
But when am trying to implement the ISRTask(Basically jump from interrupt handler to this task and implement the handler code inside it), it still doesnt jump to the ISRTask.
The way you phrase this question implies that you still don’t understand the control flow well enough. There is no such thing as an “ISR task,” and the ISR will never “jump” to a task. ISRs and tasks are completly disjoint and independent threads of control flow. ISRs and tasks can interact with each other unidirectionally via the mechanisms that the OS provides, and that is well documented. They can also be closely coupled in that when an ISR does its fast pre-processing of I/O, the ISR may request that the corresponding post processing task gets scheduled as soon as possible after the ISR has finished. I recommend you familiarize yourself with this (admittedly not always intuitively clear) control flow sequence to get a better understanding of the OS does foryou.