FatFs, freertos, interrupt

Hi, I am new at freertos and I need some help. I am using STM32F429 with CubeMx 1.7.0. FreeRTOS and STemWin and fatFs included. I have 2 tasks blinky task – blinking a led on the board interval = 100ms main task – read a bmp from sd card and draw it on LCD then clears LCD and start again until this point everything works fine. Now I would like to detect touch screen from EXTI interrupt. interrupt works fine if I touch the screen almost ~10 interrupts triggered. There is only on thing in the interrupt handler -> print “ISRrn” to serial port. This also works fine. BUT! After some touch (randomy changes but surely happens) my fatFs file systems responds that there is a timeout with the semaphor at fopen. And after this happened once then no more picture drawed on LCD bacause fopen reports this error. My drawing function looks like this ~~~~ void guiFiledrawBmp(char* path) { FIL file; /* File object */ FRESULT result; /* FatFs return code */ result = fopen(&file, path, FAREAD); if (result != FROK) { printf(“no file”); return; } GUIDrawStreamedBitmapExAuto(StreamGetData, &file, 0, 0);
f_close(&file);
} ~~~~ Everything works fine until I press the touch screen and generate some interrups. Interrupt handler: ~~~~ /** * @brief This function handles EXTI Line[15:10] interrupts. / void EXTI15_10_IRQHandler(void) { / USER CODE BEGIN EXTI1510IRQn 0 / printf(“ISR!!rn”); / USER CODE END EXTI1510IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); /* USER CODE BEGIN EXTI1510IRQn 1 */ //CTP_INT_Callback(); /* USER CODE END EXTI1510IRQn 1 */ } ~~~~ Any help would be appreciated, thank you in advance Dave

FatFs, freertos, interrupt

Is the printf routine in you system safe to use from interrupts?

FatFs, freertos, interrupt

Thank you for fast answer Good point but! if I blink my system LED it works ~~~~ void EXTI1510IRQHandler(void) { /* USER CODE BEGIN EXTI1510IRQn 0 / HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_3); / USER CODE END EXTI1510IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); /* USER CODE BEGIN EXTI1510IRQn 1 */ //CTP_INT_Callback(); /* USER CODE END EXTI1510IRQn 1 */ } ~~~~ but if I am doing this ~~~~ void EXTI1510IRQHandler(void) { /* USER CODE BEGIN EXTI1510IRQn 0 */
for (int i=0;i<1000;i++)
{
    HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_3);
}
/* USER CODE END EXTI1510IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); /* USER CODE BEGIN EXTI1510IRQn 1 */ //CTP_INT_Callback(); /* USER CODE END EXTI1510IRQn 1 */ } ~~~~ maybe the problem has something to do with timing? If the routine in ISR takes too long then fatFs semaphore corrupted somehow?

FatFs, freertos, interrupt

of course my final goal is to get touch event parameters from screen and add it to a queue than later process them in a task. I have just simlify the problem example where the problem still exists.

FatFs, freertos, interrupt

I made another test. Completely removed the ISR just two tasks. blinkyTask ~~~~ for(;;) { HALGPIOTogglePin(GPIOD,GPIOPIN3); osDelay(100); } ~~~~ drawBmpTask ~~~~ for(;;) { FIL file; /* File object / FRESULT result; / FatFs return code */ result = f_open(&file, path, FA_READ); if (result != FR_OK) { printf(“no file”); return; } GUI_DrawStreamedBitmapExAuto(Stream_GetData, &file, 0, 0);
    f_close(&file);
}
~~~~ if I made a small modification on blinkyTask like this ~~~~ for(;;) { for (int i=0;i<1000;i++) { HALGPIOTogglePin(GPIOD,GPIOPIN3); } osDelay(100); } ~~~~ Then the problem occurs again: fopen gives me FRDISK_ERR HALSDErrorTypedef HALSDReadBlocks(SDHandleTypeDef *hsd, uint32t *pReadBuffer, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks) returns MSD_ERROR;

FatFs, freertos, interrupt

Hi Dávid,
of course my final goal is to get touch event parameters from screen and add it to a queue than later process them in a task. I have just simlify the problem example where the problem still exists.
It surprises me that fatFS is suffering from an interrupt that is taking too much time. I would think it is related to the (hardware) disk driver, but I don’t know for sure. What I do know (and you most probably also) is that all hw interrupts are to be kept as short as possible 🙂 If your ISR is triggered by a touch event, let it use one of these calls: ~~~~ xTaskNotifyFromISR(); xQueueSendFromISR(); xSemaphoreGiveFromISR(); ~~~~ … in order to wake up a task which will handle the touch event(s). I wouldn’t even bother to fetch the actual touch event data from within the ISR, just let the task do that. Regards.

FatFs, freertos, interrupt

Hi Hein, Thank you for your answer. I choosen the solution you suggested. Unfortunately the continous picture update gives me the same result (FRDISKERR). Keep digging … until that I will turn off that feaure. Here is what I did ~~~~ /** * @brief This function handles EXTI Line[15:10] interrupts. / void EXTI15_10_IRQHandler(void) { / USER CODE BEGIN EXTI1510IRQn 0 */ long lHigherPriorityTaskWoken = pdFALSE;
/* USER CODE END EXTI15_10_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);

/* This interrupt does nothing more than demonstrate how to synchronise a
task with an interrupt.  First the handler releases a semaphore.
lHigherPriorityTaskWoken has been initialised to zero. */
xSemaphoreGiveFromISR( touchBinarySemHandle, &lHigherPriorityTaskWoken );

/* If there was a task that was blocked on the semaphore, and giving the
semaphore caused the task to unblock, and the unblocked task has a priority
higher than the currently executing task (the task that this interrupt
interrupted), then lHigherPriorityTaskWoken will have been set to pdTRUE.
Passing pdTRUE into the following macro call will cause this interrupt to
return directly to the unblocked, higher priority, task. */
portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
} ~~~~ ~~~~ /* StartTouchTask function / void StartTouchTask(void const * argument) { / USER CODE BEGIN StartTouchTask / I2C_Init(); FT5206_Init(); FT5206_Wake(1); xSemaphoreTake(touchBinarySemHandle,100); HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); / Infinite loop */ for(;;) {
  if (xSemaphoreTake(touchBinarySemHandle,portMAX_DELAY ) == pdTRUE)
  {
      CTP_INT_Callback(); 

  }
}
/* USER CODE END StartTouchTask */
} ~~~~ ~~~~ /** Interrupt Handlers ——————————————————-*/ void CTP_INT_Callback() { uint8_t reg = prvBaseRegisterForPoint[FT5206Point_1 – 1]; I2C_Transmit(FT5206_ADDRESS, &reg, 1); uint8_t storage[4] = {0x00}; I2C_Receive(FT5206_ADDRESS, storage, 4); LCDEventMessage message; message.event = LCDEventTouchEvent; message.data[0] = ((storage[0] & 0x0F) << 8) | storage[1]; message.data[1] = ((storage[2] & 0x0F) << 8) | storage[3]; message.data[2] = (storage[0] & 0xC0) >> 6; message.data[3] = FT5206Point1; xQueueSendToBack(xLCDEventQueue, &message, NULL); } ~~~~ Main taks ~~~~ /* USER CODE BEGIN 5 / / Infinite loop */ for(;;) { //graphicsTest_RGB565BMPStreamed();
      if( xLCDEventQueue != 0 )
      {
          LCDEventMessage receivedMessage;
          // Peek a message on the created queue.  Block for 10 ticks if a
          // message is not immediately available.

          if( xQueueReceive( xLCDEventQueue, & (receivedMessage), ( TickType_t ) 10 ) )
          {

              if (receivedMessage.data[3] == FT5206Point_1 )
              {
                  printf("%lu: %lu %lurn",receivedMessage.data[2],receivedMessage.data[0],receivedMessage.data[1]);
                  if (receivedMessage.data[2] ==1)
                  {
                      uint32_t result;
                      HAL_RNG_GenerateRandomNumber(&hrng,&result);
                      uint32_t color = result &0xFFFFFF;
                      GUI_SetColor(color);

                  }
                  else if (receivedMessage.data[2]==2)
                  {
                      GUI_FillCircle(480-receivedMessage.data[1],receivedMessage.data[0],10);
                  }
              }
              // pcRxedMessage now points to the struct AMessage variable posted
              // by vATask, but the item still remains on the queue.
          }
      }
}
~~~~ Thank you for your help. If I will find the error I will post again. Regards, Dave

FatFs, freertos, interrupt

solution on the way… if I am doing this the problem solved there is a function which continously draws bmp onto the picture. If I disable interrupt before f_read and then reenable file system stays consistent ~~~~ static int Stream_GetData(void * p, U8 ** ppData, unsigned NumBytesReq, U32 Off) {
FRESULT result;    /* FatFs return code */
static int FileAddress = 0;
UINT NumBytesRead;
FIL *PicFile;
PicFile = (FIL *)p;
/*
* Check buffer size
*/

/*
* Set file pointer to the required position
*/
if(Off == 1) FileAddress = 0;
else FileAddress = Off;
result = f_lseek(PicFile, FileAddress);
if (result != FR_OK) return -1;
/*
* Read data into buffer (directly to gui buffer)
*/
__disable_irq();
result = f_read(PicFile, *ppData, NumBytesReq, &NumBytesRead);
__enable_irq();
//printf("f_read: %d read:%drn ",result,NumBytesRead);
/*
* Return number of available bytes
*/

return NumBytesRead;
} ~~~~

FatFs, freertos, interrupt

I am getting closer ~~~~ /** * @brief Reads block(s) from a specified address in an SD card, in polling mode. * @param pData: Pointer to the buffer that will contain the data to transmit * @param ReadAddr: Address from where data is to be read
* @param BlockSize: SD card data block size, that should be 512 * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks) { HAL_SD_ErrorTypedef status=HAL_SD_ReadBlocks(&hsd, pData, ReadAddr, BlockSize, NumOfBlocks); if( status != SD_OK) { return MSD_ERROR; } else { return MSD_OK; } } ~~~~ gives me SDRXOVERRUN

FatFs, freertos, interrupt

Hi My final solution is in bspdriversd.c. Need to disable OS during readblocks. It is somehow correlated with a timeout. Until I had short tasks for example led blink the problem not occurs. regards, Dave ~~~~ /** * @brief Reads block(s) from a specified address in an SD card, in polling mode. * @param pData: Pointer to the buffer that will contain the data to transmit * @param ReadAddr: Address from where data is to be read
* @param BlockSize: SD card data block size, that should be 512 * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks) { vPortEnterCritical(); //context switch cause SD_RX_OVERRUN (maybe takes too much time) HAL_SD_ErrorTypedef status=HAL_SD_ReadBlocks(&hsd, pData, ReadAddr, BlockSize, NumOfBlocks); vPortExitCritical(); if( status != SD_OK) { return MSD_ERROR; } else { return MSD_OK; } } ~~~~