This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC3200 SD Card Write Hangs with Muli-Sector Writes

Other Parts Discussed in Thread: CC3200

Hello- 

I'm attempting to download a file from a server and save it on a SD card attached to the cc3200.  I've found that the SD card driver library freezes when you write more the 2 complete blocks with a multi-sector write.

diskio.c hangs at line 625, the while loop, waiting for a multi block transfer to complete. 

      //
      // Wait for transfer complete
      //
      while( !(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC) )
      {
          
      }
      CardSendCmd(CMD_STOP_TRANS,0);
      Res = RES_OK;

For example, modifying the sdhost_fatfs example code, to write files of varying sizes, a 600 byte write is works fine because fatfs creates 2 single sector writes. However, if you change the file write size from 600 to say 1400 the SD driver hangs because it cannot complete a multi-sector write, and hangs waiting for completion. 

    char test[600];
    
    for (int y = 0; y < 600; ++y)
      test[y] = 't';
    
    Message("\n\n\rWriting system file...\n\r");
    res = f_open(&fp,SYSFILE,FA_CREATE_ALWAYS|FA_WRITE);
    if(res == FR_OK)
    {
        //f_write(&fp,SYSTEXT,sizeof(SYSTEXT),&Size);
      
        f_write(&fp,test,sizeof(test),&Size);
        Report("Wrote : %d Bytes",Size);
        res = f_close(&fp);
    }
    else
    {
        Message("Failed to create a new file\n\r");
    }

Please help me figure out how I can successfully write more than a single sector at a time using the cc3200 SDK.

  • Hi Andrew,

    Can you try with calling f_sync() function after f_write() as this solve hanging issue for me.

    Regards,

    Aashish Bhanawat

  • My code was never getting past the fwrite function, and was getting stuck in the block write. 

    As a hack I replaced the block write routine disk_write in diskio.c with a for loop making single block writes.  

      for (int k = 0; k < bSectorCount; ++k)
      {
        MAP_SDHostBlockCountSet(SDHOST_BASE,1);
        ulSize = (512*1)/4;
      
      
        //
        // Send single block write command
        //
        if( CardSendCmd(CMD_WRITE_SINGLE_BLK, ulSectorNumber + k) == 0 )
        {
          //
          // Write the data
          //
          while(ulSize--)
          {
            MAP_SDHostDataWrite(SDHOST_BASE,(*(unsigned long *)pBuffer));
            pBuffer+=4;
          }
          
          //
          // Wait for data transfer complete
          //
          while( !(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC) )
          {
            
          }
          Res = RES_OK;
        }
      
      }
      
      return Res;

  • I'm having the same issue but single block writes isn't an option due to the performance hit. Is this a known issue? I see no mention of this issue in the errata.

  • Hi all ,

    I am having the same issue while reading , if I take the sdhost_fatfs demo and I change the following lines:

            f_read(&fp,pBuffer,100,&Size);
            Report("Read : %d Bytes\n\n\r",Size);
            Report("%s",pBuffer);
            f_close(&fp); 
    
    

    to:      

            f_read(&fp,pBuffer,1024,&Size);
            Report("Read : %d Bytes\n\n\r",Size);
            //Report("%s",pBuffer);
            f_read(&fp,pBuffer,1024,&Size);
            Report("Read : %d Bytes\n\n\r",Size);
            //Report("%s",pBuffer);
            f_close(&fp);

    on the second read it hangs in the "CardSendCmd" function in diskio.c while waiting for completion :

    //
    // Wait for command complete or error
    //
    do
    {
       ulStatus = SDHostIntStatus(SDHOST_BASE);
       ulStatus = (ulStatus & (SDHOST_INT_CC|SDHOST_INT_ERRI));
    }
    while( !ulStatus );

    if I change the size to 1023 it works.



    Regards

    Bruno Duarte Gouveia

  • Hi

    I have the same problem as mentioned above.

    In addition I found a problem in "ff.c" implemention in "f_read" function. Because it uses "FIL*" (a pointer to file handle), any change on this pointer affects the original variable, So when the "f_read" function is called again, the file pointer values are not correct. to solve this problem I did this changes:

    FRESULT f_read_byOffset (
        FIL fpin,         /* Pointer to the file object */
        void *buff,        /* Pointer to data buffer */
        WORD offset,	/* Number of bytes to skip at begining */
        WORD btread,        /* Number of bytes to read */
        WORD *br        /* Pointer to number of bytes read */
    )
    {
    	FIL temp = fpin; //copy the input argument
    	FIL *fp = &temp; //obtain the pointer of copied object, now use this pointer instead of input argument
    
    //the remain code without any change

    some problems solved but still in some situations when multiple sector read is called it hangs in while loop in "diskio.c"

  • I may be wrong, but isnt this the correct implementation of f_read? The idea is you can read small chunks of data at a time without having to track yourself the offset into the file. e.g. you read a line from a log file -> some process -> repeat.
  • Has anyone found a solution to this yet? I have been working against this for the past week, except attempting Multi-sector reads.

    I found a workaround (it is NOT the solution):

    int counter = 0;
    while( !(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC) )
    {
    if(++counter==10000)
    {
    break;
    }
    }

    This allows you to do a read of up to 8192 bytes (why this magic number? - I dont know, happens to be 12 sectors, there are 13 sectors per cluster?)

    Applying my workaround causes the next call to read (untested write) to become stuck within ''CardSendCmd'' within ''diskio.c''within the following loop:
    do
    {
    ulStatus = MAP_SDHostIntStatus(SDHOST_BASE);
    ulStatus = (ulStatus & (SDHOST_INT_CC|SDHOST_INT_ERRI));
    }
    while( !ulStatus );

    However, backtracking slightly. If I let the code execute properly once, and then put in breakpoints within "disk_read" within "diskio.c" and step through, there is no issue with CardSendCmd. There is clearly a timing issue.

    As far as I am aware there are two possible problem:
    1) Timing is setup wrong for multiblock reads
    2) The line is not treated correctly for multiblock reads. Possibly "CMD_STOP_TRANS" is not correct, or there needs to be an additional step to free the line.

    The magic value I have before hanging occurs is "2047 bytes".

    I hope this information sheds some light on the problem / can help someone direct me to somewhere else to look/try.