Using a blocking loop inside a task to see if ISR is done (nRF2401)

So I am using nRF2401 radio module and inside the transmit function, I have a blocking call that waits till the ISR is done executing, but if I were to use this in an RTOS task, it seems to go into an infinite loop due to an unexpected interrupt.
Plus it’s not a good idea to have a blocking call inside a task anyways?

    NRF_STATUS nRF24_TransmitPayload(nrfl2401 *nrf, uint8_t *data, uint8_t size)
    {
      printf ("\n ********** Sending payload data %c ************\n", *data);
      nrf->state = NRF_TX_BUSY;

      char txt[20] = "\nTX payload_";

      nRF24_WriteRegister(nrf, nRF24_CMD_W_PAYLOAD, data, size, txt);

      SET_CE();

      while (nrf->state == NRF_TX_BUSY);   //blocking loop

      RESET_CE();

    }

    void vTaskQueryTemperature(void *params)
    {

      while(1) {

       	    nRF24_TransmitPayload(&nrfRadio, payload, 2);
      }
   }

Your blocking loop is not exactly blocking because in the common sense blocking means a task is waiting for something (e.g. a semaphore, queue or notification) while sleeping/giving up the CPU. Your loop is called a busy loop because the task is busy with polling a certain flag fully using the CPU.
This is sometimes useful and the best solution if the expected poll time is very short.
Sometimes there is no other way because there is no interrupt or other signaling available. But keep in mind that no other lower prio task is able to run while a task is spinning in a busy loop and equal prio tasks are scheduled at the next systick if time sliced preemptive scheduling scheme is configured.
If there is a chance that a polled flag might not be set, better limit such busy loops to bail out with an error after a timeout to avoid that the task hangs forever.

BTW if nrf->state is set by an ISR and checked in a task it should be defined as volatile.
On the other hand why not signaling e.g. a notification in the ISR to wait for/block on by the task…

yeah, you’re right about the busy loop. yeah, I guess maybe having a timeout for a busy loop would be ideal cause you don’t want to wait forever in the loop in case you don’t receive any interrupt. In case of returning an error from this function, how’d you handle in the task knowing tasks are supposed to run forever?

Also, I don’t have any low priority tasks so that’s not a concern.

yeah I could use a notification to inform the ISR instead of a mere flag but does it make a difference logically?
And yes nrf->state is set as volatile

Right, logically there is no difference. If you have no other lower/equal prio tasks which could starve polling the flag is ok.
Well, error handling … is often not as easy as it seems.
For fatal errors which can occur during development (while soft- and hardware is not yet stable) but should never occur in the final version I’d use an assert or logging output if possible. If it’s possible that something might fail it’s not really a fatal error. Sometimes hardware is not 100% reliable and/or can’t be fixed. In this case a retry loop with an empiric number of retries might be the only workaround to get something done (in time).

Why not create a queue that u push the state flag to inside the isr with (with the function that has fromisr at the end) and then just pull from taht queue with maxDelay as timeout value, this will cause the task to yield and give other tasks time to run while there is nothign to do for this perticulair task. The schedulair will reschedule the task when something is put in the queue.

like this for example with buttons:

QueueHandle_t BUTTONS_QUEUE;
BUTTONS_QUEUE = xQueueCreate(1, sizeof(uint8_t));

task:

 while(1)
{
  xQueueReceive(BUTTONS_QUEUE, &(buttonStatus), (TickType_t) portMAX_DELAY);
  //do what needs to be done for this button.
}

isr:

void EXTI9_5_IRQHandler(void)
{ 
       static signed long xHigherPriorityTaskWoken = pdFALSE;
       uint8_t buttonstate = HAL_GPIO_read(GPIOH,GPIO_PIN_9);
       xQueueSendFromISR(BUTTONS_QUEUE, (void* ) 
       &buttonstate,&xHigherPriorityTaskWoken);
       portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

This example is for stm32 devices and just part of the code but it shoudl give the gist of what i mean. U replace the while loop for with the xQueueReceive call and inside the isr u send the end state of the isr to the queue.

That’s what the previous discussion in this thread was about.
Having a busy loop would prevent other tasks from running?

Yes it will, that is why busy loops arent a good solution unless u dont have any other tasks that need to do work in the meantime. Generally speaking its a better practice to use queues or other non blocking methodes of waiting.