Establecer tamaño de bloque (CMD16) para la tarjeta SD devuelve Comando ilegal como respuesta

0

Estoy conectando una tarjeta SD (16Gb Clase 10 Micro Sd HC) a STM32F407VET utilizando el protocolo SDIO. Estoy usando Chan FatFs versión 13a para este proyecto. Puedo abrir un archivo existente (con algo de contenido) y escribir contenido nuevo para un clúster.

He formateado una tarjeta SD con un tamaño de unidad de 8Kb, de modo que puedo escribir hasta 8Kb, que es un grupo. Cuando intento escribir datos en un nuevo clúster, la función f_write devuelve el éxito pero la función f_close devuelve FR_DISK_ERR. Si creo un archivo nuevo, el archivo se crea pero los datos no se escriben, aunque f_write proporciona FR_OK y el número de bytes escritos es correcto, pero f_close lanza FR_DISK_ERR. Entré en profundidad y descubrí que dentro de la función f_close , f_sync se invoca. Aquí, si el número de sector actual en FatFs y el número de sector actual en File Pointer son diferentes (esta verificación ocurre dentro de la función move_window que se invoca desde f_sync ) y luego se invoca la función disk_read para Rellena la ventana del sector con nuevos datos. Este es el lugar donde me da error. Dentro de disk_read , envío Cmd16 para establecer el tamaño de bloque y la tarjeta SD devuelve un Comando ilegal como respuesta.

Este comportamiento se encuentra solo cuando intento crear un nuevo archivo y escribir datos o editar un archivo existente con datos y escribir hasta 8Kb. En ambos casos, el número de sector actual en FatFs y el número de sector actual en File Pointer son iguales, por lo que no hay problema en f_close . Si se selecciona un nuevo clúster para escribir datos, terminaré con un error.

Pasé por muchos foros y probé todas las soluciones posibles, pero nada está funcionando. No dudo de la asignación de RAM porque el controlador tiene 192Kb de RAM y he asignado 0x4000 para Stack y 0x1000 para Heap. Estoy suministrando la tarjeta SD con 3.3V

No estoy seguro de si mi lógica de lectura tiene un error porque cuando lo hago f_open, invoco disk_read y en ese momento la lectura se realiza correctamente sin ningún problema. La lectura de la lectura se produce solo cuando finalizo f_close después de escribir datos en un nuevo clúster. Cualquier solución para solucionar este problema es muy apreciada. Si se requiere más información, por favor comente que lo actualizaré.

Abajo está el código para Read_Block

Parameters passed for addr = sector << 9
Parameters passed for readbuff =(u32 *)(&buff[0])
Parameters passed for BlockSize = BlockSize = 512

    SD_Error SD_ReadBlock(uint32_t addr, uint32_t *readbuff, uint16_t BlockSize)
{
   SD_Error errorstatus = SD_OK;
  uint32_t count = 0, *tempbuff = readbuff;
  uint8_t power = 0/*, timeout = 0x3*/;

  if (NULL == readbuff)
  {
    errorstatus = SD_INVALID_PARAMETER;
    return(errorstatus);
  }

  TransferError = SD_OK;
  TransferEnd = 0;
  TotalNumberOfBytes = 0;

  /* Clear all DPSM configuration */
  SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
  SDIO_DataInitStructure.SDIO_DataLength = 0;
  SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_1b;
  SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
  SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
  SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Disable;
  SDIO_DataConfig(&SDIO_DataInitStructure);
  SDIO_DMACmd(DISABLE);

  if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED)
  {
    errorstatus = SD_LOCK_UNLOCK_FAILED;
    return(errorstatus);
  }

  if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  {
    BlockSize = 512;
    addr /= 512;
  }
  if ((BlockSize > 0) && (BlockSize <= 2048) && ((BlockSize & (BlockSize - 1)) == 0))
  {
    power = convert_from_bytes_to_power_of_two(BlockSize);

    /* Set Block Size for Card */
    SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
    SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_SET_BLOCKLEN;
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);

        //do
        //{
            errorstatus = CmdResp1Error(SDIO_SET_BLOCKLEN);
            printf("SD_ReadBlock CmdResp1Error for SDIO_SET_BLOCKLEN- Error Status = %d\n\r", errorstatus);
    //      timeout--;
    //  }while(errorstatus != SD_OK && timeout > 0);

    if (SD_OK != errorstatus)
    {
      return(errorstatus);
    }
  }
  else
  {
    errorstatus = SD_INVALID_PARAMETER;
    return(errorstatus);
  }

  SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
  SDIO_DataInitStructure.SDIO_DataLength = BlockSize;
  SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) power << 4;
  SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;
  SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
  SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
  SDIO_DataConfig(&SDIO_DataInitStructure);

  TotalNumberOfBytes = BlockSize;
  StopCondition = 0;
  DestBuffer = readbuff;

  /* Send CMD17 READ_SINGLE_BLOCK */
  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)addr;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_READ_SINGLE_BLOCK;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  //SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_Pend;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SDIO_READ_SINGLE_BLOCK);
    //printf("SD_ReadBlock CmdResp1Error for SDIO_READ_SINGLE_BLOCK- Error Status = %d\n\r", errorstatus);
  if (errorstatus != SD_OK)
  {
    return(errorstatus);
  }
  /* In case of single block transfer, no need of stop transfer at all.*/
  if (DeviceMode == SD_POLLING_MODE)
  {
    /* Polling mode */
    while (!(SDIO->STA &(SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR)))
    {
      if (SDIO_GetFlagStatus(SDIO_FLAG_RXFIFOHF) != RESET)
      {
        for (count = 0; count < 8; count++)
        {
          *(tempbuff + count) = SDIO_ReadData();
        }
        tempbuff += 8;
      }
    }

    if (SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET)
    {
      SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT);
      errorstatus = SD_DATA_TIMEOUT;
      return(errorstatus);
    }
    else if (SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET)
    {
      SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL);
      errorstatus = SD_DATA_CRC_FAIL;
      return(errorstatus);
    }
    else if (SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR) != RESET)
    {
      SDIO_ClearFlag(SDIO_FLAG_RXOVERR);
      errorstatus = SD_RX_OVERRUN;
      return(errorstatus);
    }
    else if (SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET)
    {
      SDIO_ClearFlag(SDIO_FLAG_STBITERR);
      errorstatus = SD_START_BIT_ERR;
      return(errorstatus);
    }
    while (SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)
    {
      *tempbuff = SDIO_ReadData();
      tempbuff++;
    }

    /* Clear all the static flags */
    SDIO_ClearFlag(SDIO_STATIC_FLAGS);
  }
  else if (DeviceMode == SD_INTERRUPT_MODE)
  {
    SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_RXFIFOHF | SDIO_IT_STBITERR, ENABLE);
    while ((TransferEnd == 0) && (TransferError == SD_OK))
    {}
    if (TransferError != SD_OK)
    {
      return(TransferError);
    }
  }
  else if (DeviceMode == SD_DMA_MODE)
  {
    SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE);
    SDIO_DMACmd(ENABLE);
    DMA_RxConfiguration(readbuff, BlockSize);
    while (DMA_GetFlagStatus(DMA2_Stream3,DMA_FLAG_TCIF3) == RESET)
    {}
  }
  return(errorstatus);
}

Gracias

    

0 respuestas

Lea otras preguntas en las etiquetas