cancel
Showing results for 
Search instead for 
Did you mean: 

FileX - does any one know how to close_media without the system hanging? - BUG-

matt-crc
Associate II

Hello,

I'm using AzRTOS with FileX.  Currently, I can detect when the SD card is plugged in, then I initialize the hardware, and call fx_media_open().   The filesystem works as expected.

I can also unmount the media with fx_media_close(), and the user can pull out the card.  That works.

The problem is when the user pulls the SDcard when the media is open.  I detect the card removal and try to call fx_media_close(), but that just hangs the system when calling fx_media_close().  Is there a special procedure needed to recover when the media is removed?

thanks

Matthew

 

1 ACCEPTED SOLUTION

Accepted Solutions
matt-crc
Associate II

Ok, it seems that re-initializing the SD card hardware using MX_SDMMC1_SD_Init(void) does everything except clear the old error flags in the driver.  So when I try to reset the driver it gives a SDMMC_ERROR_CMD_RSP_TIMEOUT error from the last time the card was pulled out and then jumps into the error_handler().

To get around this, I call HAL_SD_DeInit(&hsd1) which clears the errors in the driver when the card is removed. then call fx_media_abort() to clean up all the AzRtos stuff.

 

Now the only problem is  how to fix the extra long timeout delay without CubeMX wiping out the fix???

 

View solution in original post

4 REPLIES 4
matt-crc
Associate II

There is a coding bug in stm32h7xx_II_sdmmc.c.  The code:

/**
  * @brief  Checks for error conditions for R1 response.
  * @PAram  hsd: SD handle
  * @PAram  SD_CMD: The sent command index
  * @retval SD Card error state
  */
uint32_t SDMMC_GetCmdResp1(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint32_t Timeout)
{
  uint32_t response_r1;
  uint32_t sta_reg;

  /* 8 is the number of required instructions cycles for the below loop statement.
  The Timeout is expressed in ms */
  uint32_t count = Timeout * (SystemCoreClock / 8U / 1000U);

  do
  {
    if (count-- == 0U)
    {
      return SDMMC_ERROR_TIMEOUT;
    }
    sta_reg = SDMMCx->STA;
  } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT |
                        SDMMC_FLAG_BUSYD0END)) == 0U) || ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));

  if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
  {
    __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);

    return SDMMC_ERROR_CMD_RSP_TIMEOUT;
  }
  else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
  {
    __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);

    return SDMMC_ERROR_CMD_CRC_FAIL;
  }
  else
  {
    /* Nothing to do */
  }

  /* Clear all the static flags */
  __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);

  /* Check response received is of desired command */
  if (SDMMC_GetCommandResponse(SDMMCx) != SD_CMD)
  {
    return SDMMC_ERROR_CMD_CRC_FAIL;
  }

  /* We have received response, retrieve it for analysis  */
  response_r1 = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);

  if ((response_r1 & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO)
  {
    return SDMMC_ERROR_NONE;
  }
  else if ((response_r1 & SDMMC_OCR_ADDR_OUT_OF_RANGE) == SDMMC_OCR_ADDR_OUT_OF_RANGE)
  {
    return SDMMC_ERROR_ADDR_OUT_OF_RANGE;
  }
  else if ((response_r1 & SDMMC_OCR_ADDR_MISALIGNED) == SDMMC_OCR_ADDR_MISALIGNED)
  {
    return SDMMC_ERROR_ADDR_MISALIGNED;
  }
  else if ((response_r1 & SDMMC_OCR_BLOCK_LEN_ERR) == SDMMC_OCR_BLOCK_LEN_ERR)
  {
    return SDMMC_ERROR_BLOCK_LEN_ERR;
  }
  else if ((response_r1 & SDMMC_OCR_ERASE_SEQ_ERR) == SDMMC_OCR_ERASE_SEQ_ERR)
  {
    return SDMMC_ERROR_ERASE_SEQ_ERR;
  }
  else if ((response_r1 & SDMMC_OCR_BAD_ERASE_PARAM) == SDMMC_OCR_BAD_ERASE_PARAM)
  {
    return SDMMC_ERROR_BAD_ERASE_PARAM;
  }
  else if ((response_r1 & SDMMC_OCR_WRITE_PROT_VIOLATION) == SDMMC_OCR_WRITE_PROT_VIOLATION)
  {
    return SDMMC_ERROR_WRITE_PROT_VIOLATION;
  }
  else if ((response_r1 & SDMMC_OCR_LOCK_UNLOCK_FAILED) == SDMMC_OCR_LOCK_UNLOCK_FAILED)
  {
    return SDMMC_ERROR_LOCK_UNLOCK_FAILED;
  }
  else if ((response_r1 & SDMMC_OCR_COM_CRC_FAILED) == SDMMC_OCR_COM_CRC_FAILED)
  {
    return SDMMC_ERROR_COM_CRC_FAILED;
  }
  else if ((response_r1 & SDMMC_OCR_ILLEGAL_CMD) == SDMMC_OCR_ILLEGAL_CMD)
  {
    return SDMMC_ERROR_ILLEGAL_CMD;
  }
  else if ((response_r1 & SDMMC_OCR_CARD_ECC_FAILED) == SDMMC_OCR_CARD_ECC_FAILED)
  {
    return SDMMC_ERROR_CARD_ECC_FAILED;
  }
  else if ((response_r1 & SDMMC_OCR_CC_ERROR) == SDMMC_OCR_CC_ERROR)
  {
    return SDMMC_ERROR_CC_ERR;
  }
  else if ((response_r1 & SDMMC_OCR_STREAM_READ_UNDERRUN) == SDMMC_OCR_STREAM_READ_UNDERRUN)
  {
    return SDMMC_ERROR_STREAM_READ_UNDERRUN;
  }
  else if ((response_r1 & SDMMC_OCR_STREAM_WRITE_OVERRUN) == SDMMC_OCR_STREAM_WRITE_OVERRUN)
  {
    return SDMMC_ERROR_STREAM_WRITE_OVERRUN;
  }
  else if ((response_r1 & SDMMC_OCR_CID_CSD_OVERWRITE) == SDMMC_OCR_CID_CSD_OVERWRITE)
  {
    return SDMMC_ERROR_CID_CSD_OVERWRITE;
  }
  else if ((response_r1 & SDMMC_OCR_WP_ERASE_SKIP) == SDMMC_OCR_WP_ERASE_SKIP)
  {
    return SDMMC_ERROR_WP_ERASE_SKIP;
  }
  else if ((response_r1 & SDMMC_OCR_CARD_ECC_DISABLED) == SDMMC_OCR_CARD_ECC_DISABLED)
  {
    return SDMMC_ERROR_CARD_ECC_DISABLED;
  }
  else if ((response_r1 & SDMMC_OCR_ERASE_RESET) == SDMMC_OCR_ERASE_RESET)
  {
    return SDMMC_ERROR_ERASE_RESET;
  }
  else if ((response_r1 & SDMMC_OCR_AKE_SEQ_ERROR) == SDMMC_OCR_AKE_SEQ_ERROR)
  {
    return SDMMC_ERROR_AKE_SEQ_ERR;
  }
  else
  {
    return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
  }
}

the way the timeout is calculated is completely wrong...

count = Timeout * (SystemCoreClock / 8U / 1000U)

Timeout = 5000

SystemCoreClock = 480,000,000

That's one very long timeout....

Now the question is how to fix this without CubeMX wiping out the fix???

 

Have you tried using the debugger to find where, exactly, it "hangs" ?

 

Looking at the source code, it seems that it will write to the media:

/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _fx_media_close                                     PORTABLE C      */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    William E. Lamie, Microsoft Corporation                             */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function examines the list of open files for this media and    */
/*    closes each file.  If a file has been written to, the file's        */
/*    directory information is also written out to the media.  After      */
/*    the files have been closed, the internal logical sector is          */
/*    flushed and a flush command is sent to the attached driver.         */
/*    Finally, this media control block is removed from the list of       */
/*    opened media control blocks and is marked as closed.                */
/*                                                                        */

https://github.com/eclipse-threadx/filex/blob/master/common/src/fx_media_close.c

so maybe not surprising that it fails when the media has been removed?

 

maybe fx_media_abort() is what you need?

https://github.com/eclipse-threadx/filex/blob/master/common/src/fx_media_abort.c

Hi Andrew,

Well, the fx_media_abort() cleans up all the AzRtos stuff, so that's half the battle.   I waited for the extra long timeout to expire, but it ended up in the error handler... So I will check that next.

Thanks for the fx_media_abort() tip

matt-crc
Associate II

Ok, it seems that re-initializing the SD card hardware using MX_SDMMC1_SD_Init(void) does everything except clear the old error flags in the driver.  So when I try to reset the driver it gives a SDMMC_ERROR_CMD_RSP_TIMEOUT error from the last time the card was pulled out and then jumps into the error_handler().

To get around this, I call HAL_SD_DeInit(&hsd1) which clears the errors in the driver when the card is removed. then call fx_media_abort() to clean up all the AzRtos stuff.

 

Now the only problem is  how to fix the extra long timeout delay without CubeMX wiping out the fix???