cancel
Showing results for 
Search instead for 
Did you mean: 

STM322xg Eval board SDIO Problems

stbbrad3
Associate II
Posted on October 05, 2011 at 19:18

Hello all,

I have search through the forums and google for the exact problem I am having to no avail.

The issue I am having is regarding finding the filesystem on the SD card, in particular the check_fs function inside of chk_mounted. From what I understand the function will check for two different signatures. One is the BS_55AA at the end of the 512 byte block and the other is the FAT string somewhere within the block ( depending on the FAT subtype ).

The first signature 55AA is found, but only when I use the f_mkfs ( make filesystem ) in Chan's code. Using windows does not make the signature which I thought was part of any FAT file system. Regardless of which method I use to format the disk I cannot see the FAT string in the block anywhere.

Anyone have/had this issue or have insight as to what might be the problem? I have tried multiple allocation unit sizes when calling makefs.

EDIT: I have tried with both a 256MB and 2GB card. I have actually seen mixed results, but I always see FR_NO_FILESYSTEM.

EDIT2: So I can see when I am reading from the Volume Boot Record the MS DOS string is still at the top where it belongs but aftet that I get a bunch of FF's, enough to overwrite the FAT string.
16 REPLIES 16
stbbrad3
Associate II
Posted on October 10, 2011 at 16:45

Thanks again for your insight Frank.

I have reduced the block I am sending to just one word testword [] = { 0xa5, 0x01, 0xa5, 0x10 }. 

In main, I call SD_WriteBlock ( testword, 0x00, 4 );

( I noticed after calling the function to get card status, the size of the protected area was 0x28, so I modified the address to 0x29, 0x30, and 0x80 to see if it helped and it did not )

I modified the write block to be.......

SD_Error SD_WriteBlock ( uint8_t *pWriteBuff,

                         uint32_t WriteAddr,

                         uint16_t BlockSize )

{

    SD_Error errorstatus = SD_OK;

#if defined ( SD_POLLING_MODE )

    uint32_t bytestransferred = 0;

    uint32_t count = 0;

    uint32_t restwords = 0;

    uint32_t *tempbuff = (uint32_t *)pWriteBuff;

#endif

    TransferError = SD_OK;

    TransferEnd   = 0;

    StopCondition = 0;

   

    SDIO->DCTRL = 0;

       

    if ( CardType == SDIO_HIGH_CAPACITY_SD_CARD )

    {

        BlockSize = 512;

        WriteAddr /= 512;

    }

     

   

    /* Send CMD24 WRITE_SINGLE_BLOCK */

    SDIO_CmdInitStructure.SDIO_Argument = WriteAddr;

    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK;

    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 );

   

    errorstatus = CmdResp1Error ( SD_CMD_WRITE_SINGLE_BLOCK );

    if ( errorstatus != SD_OK )

    {

        return ( errorstatus );

    }

   

    SDIO_DataInitStructure.SDIO_DataTimeOut   = SD_DATATIMEOUT;      SDIO_DataInitStructure.SDIO_DataLength    = BlockSize;

    SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) 9 << 4;

    SDIO_DataInitStructure.SDIO_TransferDir   = SDIO_TransferDir_ToCard;

    SDIO_DataInitStructure.SDIO_TransferMode  = SDIO_TransferMode_Block;

    SDIO_DataInitStructure.SDIO_DPSM          = SDIO_DPSM_Enable;

    SDIO_DataConfig ( &SDIO_DataInitStructure );

    SDIO_WriteData ( *tempbuff );

    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_TXUNDERR ) != RESET )

    {

        SDIO_ClearFlag ( SDIO_FLAG_TXUNDERR );

        errorstatus = SD_TX_UNDERRUN;

        return ( errorstatus );

    }

    else if ( SDIO_GetFlagStatus ( SDIO_FLAG_STBITERR ) != RESET )

    {

        SDIO_ClearFlag ( SDIO_FLAG_STBITERR );

        errorstatus = SD_START_BIT_ERR;

        return ( errorstatus );

    }

    return ( errorstatus );

}

And for some odd reason I am getting the DCRCFAIL, which is datablock sent but CRC failed. Should I see the CRC make it into the FIFO register? 

What I am seeing when SDIO_WriteData is called is all 32 words in the FIFO register get populated with my testword array instead of just the first word.. is this normal? It seems quite odd to me that it would fill the entire register with copies of the single word I want to write.

I seen this same kind of thing when I was trying to write a 512 byte block.. the first word would take up the entire FIFO data register and the FIFO count would get set to zero on the first write... subsequently the calls to SDIO_WriteData after that change nothing in the data register.

stbbrad3
Associate II
Posted on October 10, 2011 at 17:43

I got ahold of a nice oscillloscope and found that the last byte of the word is not being transmitted when I call write block. But, when I call SD_GetCardStatus i see plenty of words transmitted.

This leads me to believe it is definatley an internal issue a not a problem with the actual SD card.
aqueisser
Senior
Posted on October 10, 2011 at 18:17

I think you're supposed to set the SDIO_DataBlockSize to the value indicating the power-of-2 of your block length. Your overall data length is determined by the SDIO_DataLength but after each SDIO_DataBlockSize the CRC exchange will happen. The other side (SD/SDIO card) has to agree on what that length is. If you're trying to send 4 bytes the SDIO_DataBlockSize should be 0x20, from stm32f2xx_sdio.h:

#define SDIO_DataBlockSize_4b               ((uint32_t)0x00000020)

From the looks of it you're always using 9<<4, which is the right value for standard 512 byte blocks but won't work for 4 byte blocks.

Hope that helps,

Andrew

stbbrad3
Associate II
Posted on October 10, 2011 at 18:44

Andrew that was great! That did the trick.

The main issue I was having was defining the block size before any reading and/or writing by..

    /* Set block size for card if it is not equal to current block size for card. */

    SDIO_CmdInitStructure.SDIO_Argument = BlockSize;

    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_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 );

   

    errorstatus = CmdResp1Error ( SD_CMD_SET_BLOCKLEN );

    if ( errorstatus != SD_OK )

    {

      return ( errorstatus );

    }

Thanks everyone for all your help... Now I can get back to getting this file system up and running!

Cheers,

Brad

 

bob239955_stm1_st
Associate
Posted on October 17, 2011 at 20:14

Been working on this for a couple weeks but you're further along than I have gotten. Are you using Chans FAT system with your own I/O system or some complete system for the F2 family ?

bob239955_stm1_st
Associate
Posted on October 17, 2011 at 23:22

Now that I spent more time on it I have the same issue with the 55AA and the formatting.  Could you explain a little how you got past it?  I tried playing around with the block size but no luck yet.

Thanks a ton

stbbrad3
Associate II
Posted on October 18, 2011 at 17:22

Hi Bob,

Actually it was a combination of finding the correct clock speed and setting the block length at the correct time.

I am sure there is a better way to do it than I am right now as each time I do a read or write I send a command to set the blocklength to 512 bytes.

Here is a beginning snippet of my write block routine:

SD_Error DIL_SD_Write_Block ( uint8_t *pWriteBuff, 

 

                                                       uint32_t WriteAddr, 

 

                                                       uint16_t BlockSize )

 

{

 

      SD_Error errorstatus = SD_OK;

#if defined ( SD_POLLING_MODE )

 

      uint32_t bytestransferred = 0;

 

      uint32_t count = 0;

 

      uint32_t restwords = 0;

 

      uint32_t *tempbuff = (uint32_t *)pWriteBuff;

 

#endif

      TransferError = SD_OK;

 

      TransferEnd   = 0;

 

      StopCondition = 0;

 

   

 

      SDIO->DCTRL = 0;

 

       

 

      if ( CardType == SDIO_HIGH_CAPACITY_SD_CARD )

 

      {

 

          BlockSize = 512;

 

          WriteAddr /= 512;

 

      }

 

        

 

        /* Set block size for card if it is not equal to current block size for card. */

 

       SDIO_CmdInitStructure.SDIO_Argument = 512;

 

       SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_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 );

 

    

 

       errorstatus = CmdResp1Error ( SD_CMD_SET_BLOCKLEN );    

 

       if ( errorstatus != SD_OK )

 

      {

 

          return ( errorstatus );

 

      }

 

   

 

      /* Send CMD24 WRITE_SINGLE_BLOCK */

 

      SDIO_CmdInitStructure.SDIO_Argument = WriteAddr;

 

      SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK;

 

      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 ); ALSO, be sure to set your SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_512b;   before you do your write or read a well on the data config.

Happy coding,

Brad