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.

f_write (specifically xmit_datablock and rcvr_spi) failing when attempting to write to SD card.

Other Parts Discussed in Thread: TMS320F28379D

I've been working on a datalogger and banging my head against the wall because what I expected to be trivial has instead been quite difficult for me.

I can create a file on the SD card, but have been unable to actually write to it. f_write() returns FR_RW_ERROR. In f_write, it calls create_chain at line 1000 of ff.c and stepping through calls get_cluster() at line 290. The file system is FAT32, so it jumps to line 162 and calls move_window. In move_window, it goes to line 76 and calls disk_write (contained in mmc-F2837x.c at line 641). Count == 1 so it goes to the conditional:

if ((send_cmd(CMD24, sector) == 0)    /* WRITE_BLOCK */
                && xmit_datablock(buff, 0xFE))
     count = 0;

I determined that xmit_datablock is what is creating the issue.

static
BOOL xmit_datablock (
    const BYTE *buff,    /* 512 byte data block to be transmitted */
    BYTE token            /* Data/Stop token */
)
{
    BYTE resp, wc;


    if (wait_ready() != 0xFF) return FALSE;

    xmit_spi(token);                    /* Xmit data token */
    if (token != 0xFD)      /* Is data token */
    {
        wc = 0;
        do                              /* Xmit the 512 byte data block to MMC */
        {
            xmit_spi(*buff++);
            xmit_spi(*buff++);
        }
        while (--wc);
        xmit_spi(0xFF);                    /* CRC (Dummy) */
        xmit_spi(0xFF);
        resp = rcvr_spi();                /* Reveive data response */
        if ((resp & 0x1F) != 0x05)        /* If not accepted, return with error */
            return FALSE;
    }

    return TRUE;
}

Specifically, it returns FALSE due to the last if statement. This is because of the return of rcvr_spi:

static
BYTE rcvr_spi (void)		//EDITED
{
    volatile DWORD rcvdat;

    //Disable transmission channel
    //SpicRegs.SPICTL.bit.TALK = 0;

    /* write dummy data */
    while(SpicRegs.SPISTS.bit.BUFFULL_FLAG);	//Wait for space to write
    SpicRegs.SPITXBUF = 0xFF00;						//Write dummy data

    /* read data from RX fifo */
    while(SpicRegs.SPISTS.bit.INT_FLAG !=1);		//May be possible to switch to '!SpicRegs.SPISTS.bit.INT_FLAG'
    rcvdat = (SpicRegs.SPIRXBUF & 0xFF);					//Read Transferred data

    return (BYTE)rcvdat;
}

Evidently the read data is incorrect as rcvdat = (spicRegs.SPIRSBUF & 0xFF) is resulting in a 255 (assigned to resp), which results in resp & 0x1F = 0 and !=5 as the code expects in xmit_datablock (and that then rolls back through all the function calls to result in the FR_RW_ERROR).

So the question is this: is this a buggy driver provided by TI, an issue with the SD card I'm using, or something I'm doing incorrectly? I can post any relevant code needed as either snippets or whole files.

  • Oh and for clarification this is on a Delfino F2837xD.
  • Eric,

    Can you tell if it is writing incorrectly or not writing at all?

    Can you scope the SPI pins to see if the SPI is working as expected?

    Some coworkers believe that the original project used byte addressing, which the C2000 does not. see if you can verify you the addressing to ensure that it is not offset.

    -Mark
  • I won't be able to actually probe the signals until this Tuesday when I can get access to the proper tools (I'm an undergrad and the labs with the digital o-scopes are locked during the weekends). However, I'm fairly certain that the SPI itself is working correctly, as I can create a file on the SD card with any name I like (e.g. "data.txt"). Additionally, I can read data from a file on the SD card. What doesn't seem to be working is actually writing any data TO that file -- it isn't writing incorrectly, its just not writing at all.

    mmc-2837x.c has a conditional:

        if (!(CardType & 4)) sector *= 512;    /* Convert to byte address if needed */

    which I believe is checking for the byte adressing conversion you mentioned. This fails, and the value of "sector" remains unchanged, so I don't believe it is using byte addressing. I'm unsure of what you mean for "offset?"

    I will be able to properly scope it on Tuesday, if needed.

  • Hello,

    Is your problem resolved? I am also working on a project that involves data logging of several sensors connected via ADC and SPI. I am having hard time to make writing to SD card work. Would you mind sharing a sample code? I have TMS320F28379D. I appreciate your help.

    Regards,

    Archit
  • Sure, do me a favor and look in your mmc-F2837x.c file, at about line 370, do you see the following snippet?

    /*-----------------------------------------------------------------------*/
    /* Send a data packet to MMC                                             */
    /*-----------------------------------------------------------------------*/
    
    #if _READONLY == 0
    static
    BOOL xmit_datablock (
        const BYTE *buff,    /* 512 byte data block to be transmitted */
        BYTE token            /* Data/Stop token */
    )
    {
        BYTE resp, wc;
    
    
        if (wait_ready() != 0xFF) return FALSE;
    
        xmit_spi(token);                    /* Xmit data token */
        if (token != 0xFD)      /* Is data token */
        {
            wc = 0;
            do                              /* Xmit the 512 byte data block to MMC */
            {
                xmit_spi(*buff++);
                xmit_spi(*buff++);
            }
            while (--wc);
            xmit_spi(0xFF);                    /* CRC (Dummy) */
            xmit_spi(0xFF);
            resp = rcvr_spi();                /* Reveive data response */
            if ((resp & 0x1F) != 0x05)        /* If not accepted, return with error */
                return FALSE;
        }
    
        return TRUE;
    }
    #endif /* _READONLY */
    

    If you do, this might be your problem. Specifically:

    BYTE resp, wc;

    and

     wc = 0;
            do                              /* Xmit the 512 byte data block to MMC */
            {
                xmit_spi(*buff++);
                xmit_spi(*buff++);
            }
            while (--wc);

    This should write 512 bytes to the card -- wc is a byte, so max value of 256, so this loop will run 256 times, writing 2 bytes each time...right?

    WRONG.

    The C2000 series does NOT have any variable that is shorter than 16 bits (yes, even bytes). So instead of repeating 256 times, its repeating 65536 times, writing 131072 bytes out and obliterating whatever you had written. This issue was reported AGES ago and, as far as I know, still hasn't been fixed in their code despite repeated posts regarding it.

    Let me know if this fixes it for you.

  • Hello Eric,

    Thank you for your message. So, I was able to write to the SD Card in CSV format. How ever its extremely slow and I am not able to understand the reason and what can I modify to fix the issue. The requirement is to write about 24 floating point numbers to the SD Card every 50 micro seconds. However, CPU takes about 20 micro seconds to compute those numbers and so essentially CPU shall not take more than about 25 micro seconds to write 24 floating point numbers to the card. Below is the sample code that I have been using.

    f_open(&g_sFileObject, "0:/Message.csv", FA_READ |  FA_WRITE |  FA_OPEN_ALWAYS );
    ReadCount = 512;
    size = (&g_sFileObject)->fsize;
    
    ////////////////////////////// SECTION 2 //////////////////////////////////////
    
    fresult = f_lseek(&g_sFileObject,size);
    f_write(&g_sFileObject, "1000.00,1001.00,1002.00,1003.00,1004.00,1005.00,1006.00,150,151,152,1,10000,10001,10002,360.1234\n", sizeof("1000.00,1001.00,1002.00,1003.00,1004.00,1005.00,1006.00,150,151,152,1,10000,10001,10002,360.1234\n"), &Count);
    f_sync(&g_sFileObject);
    
    ////////////////////////////// END SECTION 2 //////////////////////////////////////
    
    f_close(&g_sFileObject);

    So, basically the code enclosed in "SECTION 2" has to occure every 50 micro seconds. Using the clock tool in Debug Mode, I tried to calculate the ticks and it turns out that the logic in "Section 2" takes about 5 milli seconds. I then tried to dubug the code even further and here is what I found:

    1.) f_lseek takes about 2 milliseconds

    2.) f_write actually only takes about 10 micro seconds. (And I have not even enabled FIFO and DMA)

    3.) f_sync takes about 2.9 milliseconds.

    So then I tried not to use f_sync to reduce the time, but if I dont execute it every cycle, data is not being written. And for the f_lseek function there is a f_read statement which takes all the time. And so, I tried to comment out that statement and data is not being written then. So, it seems that I am stuck now and have no idea what can I do to achieve the requirement.

    Please provide some insight on what and how to modify the code to make the timing achievable and reliably perform data logging. Also, at this point I am converting all the floats to string using "ltoa" and thats an inefficient way to do the data logging. Suggestions please.

    I thank you for your time and appreciate your help.

    Regards,

    Archit

  • Hi Archit,

    Did you ever have any luck resolving your issue?  I am working on a similar project.

    Regards,

    Mark

  • I am able to write to the SD Card now, but its very slow. I am in the process of enabling DMA support to speed up the process but its not working yet. I will let you know if I have any luck. Meanwhile, I will also appreciate your feedback too! Thanks.

  • Hi Archit,

    I managed to get my sd to write quickly, but the way I did it is very situation specific.  I'd be willing to take a look at your code to see if I can help you if you'd be willing to zip it to me.

    Regards,

    Mark

  • Hello Mark,

    I sent you a zip file with my code a few weeks before. By any chance did you get to see the code and try to help me out? Please let me know. Again, I appreciate all your help! Awaiting your reply. Thanks

    Regards,

    Archit