Hello,
taskYIELD_FROM_ISR is not a standard macro in an FreeRTOS port from what I can tell. I would need to check how this has been implemented on the STM32.
To your question: it depends on the cpu you use, and of course of the port you are using. I assume HCS08.
So here is what will happen:
- an interrupt from the RX line happens
- PE handles the interrupt entry, plus calls the AS1_OnRxChar() function
- If you can give the semaphore, then you do a portYIELD()
- portYIELD() will set the interrupt flag for a SWI interrupt. But as you are already in an ISR (with the I bit set), interrupts are disabled. So there will be no context switch right away
- the OnRxChar() function finishes, so does the caller.
- an RTI happens (end of interrupt)
- the CPU sees that there is a pending SWI interrupt, and calls that ISR (calling the RTOS to deal with the context switch)
So in general your approach works.
The problem I see with your approach is that you disable the events for RX. So you might miss incoming traffic if you are not fast enough.
I had a similar (I think) think, where I received interrupts and needed to deal with the incoming data. Not sure why you need to block another task, but I used a buffering instead:
Queue definition:
#define RADIO_QUEUE_NOF_ITEMS 8 /* number of items in the queue */#define RADIO_QUEUE_ITEM_SIZE 32 /* size of each queue item */static xQueueHandle RADIO_MsgQueue; /* queue for messages, format is: kind(8bit) dataSize(8bit) data */
Queue Initialization:
RADIO_MsgQueue = FRTOS1_xQueueCreate(RADIO_QUEUE_NOF_ITEMS, RADIO_QUEUE_ITEM_SIZE); if (RADIO_MsgQueue==NULL) { /* queue creation failed! */ for(;;) {} /* not enough memory? */ }Then from the ISR a build a message packet (with my own special format of the message):
static void QueueMessage(uint8_t kind, const char *msg, uint8_t msgSize) { /* format is: kind(8bit) dataSize(8bit) data */ uint8_t i, buf[RADIO_QUEUE_ITEM_SIZE]; signed portBASE_TYPE pxHigherPriorityTaskWoken; buf[0] = kind; buf[1] = msgSize; i = 2; while(msgSize>0 && i<sizeof(buf)) { buf[i++] = *msg; msg++; msgSize--; } if (FRTOS1_xQueueSendToBackFromISR(RADIO_MsgQueue, &buf[0], &pxHigherPriorityTaskWoken)!=pdTRUE) { /* was not able to send to the queue. Well, not much we can do here... */ }}The problem I would have here (as noted above) if my queue is full. If anywone has a good solution, let me know.
Then I call following method from my task to handle the queue:
/*! \brief Radio application state machine */void RADIO_Handle(void) { uint8_t buf[RADIO_QUEUE_ITEM_SIZE]; /* poll radio message queue */ if (FRTOS1_xQueueReceive(RADIO_MsgQueue, buf, 0)==pdPASS) { /* received message from queue */ RADIO_HandleMessage(buf); }}That approach worked very well for me.
Hope that helps.