Calling Pin read from different tasks have different results

Hello,

We use FreeRTOS in our board.

I’ve the Task1 and Task2. Task1’s priority is 2, while Task2’s is 3. There is an external IRQ. When there is data ready on the SPI line, the 3rd party chip will set the PIN to high - the 3rd party chip uses this way to notify the host that the data is ready on SPI.
I have an IRQ_ISR() which will give the semaphore once the interrupt is triggered. Then Task2 will get chance to run. In Task1, after sending the data, normally the PIN will be turned to high by the 3rd party chip immediately. Then the host MCU will need to read the data from SPI. Once the data is read from the 3rd party chip, the PIN will be turned to low by the 3rd party chip.

bool GetPINValue(void)
{
  bool result = FALSE;
  io_level pin_value = IO_LEVEL_LOW;

  if (SUCCESS == PinRead(&gpio, MY_IRQ_PIN, &pin_value))
  {
    result = (pin_value == IO_LEVEL_HIGH) ? TRUE : FALSE;
  }

  return result;
}

void IRQ_ISR(callback_args_t *p_args)
{
  portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
   
  xSemaphoreGiveFromISR(mySemaphore, &xHigherPriorityTaskWoken);
  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void Task1(void)
{
  char ch = 0x00;
  
  for (;;)
  {
    SendDataOverSPI();
    printf("Task1 PIN Value: %d\n", GetPINValue());
    DelayMS(500);
    printf("Task1 PIN Value again: %d\n", GetPINValue());
    ReadDataFromSPI(&ch);
    printf("Data: 0x%02X\n", ch);
    . . .
  }
}

void Task2(void)
{
  unsigned portBASE_TYPE uxHighWaterMark;
    
  for (;;)
  {
    xSemaphoreTake(mySemaphore, MAX_DELAY);
    printf("Task2 PIN Value: %d\n", GetPINValue());
    . . .
  }
}

// Printed output:
Task1 PIN Value: 1
Task1 PIN Value again: 1
Task2 PIN Value: 0
Data: 0x30

From the printed output, as you can see:

  • Apprantely after the host MCU sending the data, the PIN is set to high. Then Task2 get a chance to run the printf statement.
  • Of course, the Task1 PIN value is high because the 3rd party chip will turn it to high once the 3rd party chip receives the data. That’s why we see “Task1 PIN Value: 1”.
  • Even if I delay 500ms, the PIN value is still high because the data isn’t read yet. So we see “Task1 PIN Value again: 1”.
  • However, the “Task2 PIN value: 0” doesn’t make sense. It should be 1 because the data isn’t read yet.
  • As we can see later, the host read the data back. Meaning, the PIN value is still high when reading the data.

The weird thing is, why the Task2 PIN value is 0? Calling PinRead() from different tasks can have different PIN value? Is there a way to fix it?

Thanks!

Usually just reading the I/O state of an input pin shouldn’t be a problem even when done in concurrent tasks (depending on the implemenation of GetPINValue, of course).
How is the interrupt configured ? Edge triggered on falling or rising edge or both ? What’s the pin state before sending data (in Task1) ?

Hi hs2,
Thanks for your info.
The PIN trigger is configured on falling edge. The PIN was low before sending data in Task1.
The weird thing is, the PIN must be high when IRQ_ISR is triggered. Otherwise, the “mySemaphore” won’t be given. The printf statement in Task2 won’t get chance to run. But the PIN value is low on that printf statement. This doesn’t make sense.
Thanks.

If the interrupt is configured to occur on falling edge, the ISR is triggered when the input pin goes from high to low. So the pin is low when entering the ISR … :thinking:

Hi hs2,
Thank you so much! You’re right.
I changed the trigger from falling edge to rising edge. It seems working now. I appreciate it!

Based on the above code, I found a new problem. As we can see, Task2 waits for mySemaphore. Normally the “Task2 PIN Value:” is 1. But sometimes its value is 0. The PIN is an input pin. Meaning it’s controlled by the 3rd party chip. As Task2’s priority is higher, it should be really fast for Task2 to get the mySemaphore. I’m not sure why the PIN value goes to 0 even if the value is 1 in IRQ_ISR, which is because the interrupt trigger is set to be rising edge. Does anybody know the reason?
Thanks!

Since it happens sometimes, it may be related to some sequence of events or timing. Can you control the amount and rate of data coming from your third party chip? If yes, try to slow it down and see if that helps. If not, try to use some tracing tool to capture runtime trace.

<duplicate of @aggarg, apologies>