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.

5509A CSL and MMC_write

Hi There,

We have been having problems the MMC_write routine hanging lately on the 5509A using CSL (not Lowpower). The example in the CSL shows a number of delay loops after MMC_write. I'm wondering what those are for because our code (which uses the suggested routine) seems to always hang when I remove them. Documentation says the MMC_write is suppose to be blocking and return when the process is complete but it appears the delays are to give time for completion because if you return too soon, it will hang. I tried to watch for several flags (BSYDNE for example) but they don't seem to work. 

I am using CCS6 and the latest DSPBIOS 5.42.01.09

Any suggestions? or is the only option to use delay loops after the MMC_write and experiment. It seems SD cards work with less delay than MMC cards. 

Thanks,

Cam

  • Hi,

    Your request is been forwarded to right experts and will provide an update shortly.

    Thanks & regards,

    Sivaraj K

  • Have you truied with different classes of cards? They are speed graded.

    Regards.

  • Yes. Different cards need different delays. SD cards are better than MMC being faster.

  • The MMC_write function does check the DATDNE bit for the completion of data transfer but waits upon only MMCST0 DXRDY. MMCST0 DXRDY and DATDNE are dependent upon data being transmitted out of the C55 MMC_SD controller. That is, the MMC_write is blocking vis-a-vis transmission to be complete from the C55 end.

    The delay, is probably provided so that the MMC/SD card gets enough time to have the transmitted data received and written on it, and be ready for a data read operation.

    Could you try a few experiments as to find out where exactly the program gets hung up? For ex. when you see your application hung up, pause the execution (pause button in CCS, assuming your app runs on CCS) and see where it lands up.. Checking if the count variable has reached the intended number - if it doesn't it would mean something in the transaction went wrong and DXRDY wasn't being set at all.

    Or you could try varying the delay count/number of delay loops, see if it helps in anyway?

    Best Regards.

  • Hope Section 2.5, Pg. 2-12 in the following document helps as well: http://www.ti.com/lit/ug/spru593a/spru593a.pdf

    Best Regards.

  • Cam,

    I deleted all the delay loops from the code.  They are bad practice, because when you change your CPU clock frequency, suddenly the delay durations are all changed.  Also, any fixed delay loop is guaranteed to be sub-optimal, as it will always wait longer than it needs to.  Much better to wait on flags from the hardware.

    See this attached file for some example code.

    0245.sd_write.c
    #include <csl.h>
    #include <csl_mmc.h>
    
    
    #define SECTOR_SIZE   512
    
    // Non-zero if this is a high-capacity SD card:
    int highCapacity;
    
    // Array contains your data packed into uint16, MSB, LSB.
    unsigned packed[SECTOR_SIZE/2];
    
    void sd_write(Uint32 addr_sectors)
    {		
    	int ii, result = 0;
    	Uint32 card_addr;   // bytes for std capacity, sectors for high capacity
    	unsigned word, old_intm, st1; // drsp, csh=-1, csl=-1; 
    	ioport MMC_MmcRegObj *regs = ...  // regs appropriate for your interface
    	
    	if (highCapacity) {
    		card_addr = addr_sectors;
    	} else {
    		card_addr = addr_sectors * SECTOR_SIZE;
    	}
    		
    	// If the card is in BUSY mode, it will pull DAT low.  Wait until done.
    	for (;;) {
    		st1 = regs->mmcst1;
    		if ((st1 & MMC_ST1_BUSY) == 0) break;
    	}
    	
    	old_intm = IRQ_globalDisable();
    	
    	if (addr_sectors > hwInf->sectorCount) for (;;) ;
    	MMC_clearResponse(hwInf->hDisk);
    	
    	// Send the write command:
    	regs->mmcnblk = 1;
    	regs->mmcdxr = packed[0];  // junk?
    	regs->mmcargh = card_addr >> 16;
    	regs->mmcargl = card_addr & 0xFFFF;
    	
    	// Don't use MMC_WRITE_BLOCK.  They changed the definition between 3.1 and
    	//   3.3!!!
    	regs->mmccmd = MMC_CMD24 | MMC_RSP1 | MMC_CMD_DATA | MMC_CMD_WRITE
    			| MMC_CMD_DCLR; // might need this.  
    			//  Setting it does not send DXR, use 0 for ii
    	
    	IRQ_globalRestore(old_intm);
    	
    	ii = 0;
    	do {
    		word = regs->mmcst0;
    		if (word & MMC_ST0_DXRDY) {
    			// When data ready is indicated, write another byte:
    			regs->mmcdxr = packed[ii++];
    		}
    		// If DATDNE is signalled prematurely, exit the loop.
    	} while (ii < SECTOR_SIZE/2 && (word & MMC_ST0_DATDNE) == 0);
    
    	// Now, we need DATDNE to be high for the controller to survive.  So, we
    	//  must write out junk until it is.  The card will ignore it.
    	while ((word & MMC_ST0_DATDNE) == 0) {
    		word = regs->mmcst0;
    		if (word & MMC_ST0_DXRDY) regs->mmcdxr = 0xDEAD;
    	}
    }
    

    Regards,

    Bill

  • Thanks very much Bill and Kravis. Sorry for the delayed response. Had some other projects I got side tracked to.

    I agree that delay loops are bad practice which is partly what got me into this in the first place. I wanted to make the routine more reliable despite different memory chip speeds and clock rates but I wasn't having much success probing most of the flags. I'll check into your info above and see how it goes. 

    Cheers!

  • I've been able to do some more testing. 

    When I do a MMC_write and then afterword do an MMC_read, MMC_read gets stuck as follows

    02580c: BTST #2,port(*AR3),TC1
    025810: BCC #0x02580c,!TC1

    (looks like it is waiting for RSPDNE

    or,

    025b85: BTST #9,port(*AR3),TC1
    025b89: BCC#0x025b85,!TC1

    (looks like it is waiting for DXRDY)

    When I put a breakpoint or delay at the end of the MMC_write, the problem goes away.

    I need more loop iterations for writing to an MMC then I do for writing to an SD card.

    It also seems worse the farther into memory the write is being made. 

    So, it looks like it is a problem with controller not finishing up the transfer and setting the flags properly (or being read properly by CSL).

  • Actually when it gets stuck at 

    025b85: BTST #9,port(*AR3),TC1
    025b89: BCC#0x025b85,!TC1

    That seems to be when it enters an MMC_write.

  • What is the return value on MMC_write? The CSL manual for the 5509 says it is a void but in the header it is an integer. 

  • OK, looks like I found the solution. 

    From  0245.sd_write.c I noticed the comment

    // Now, we need DATDNE to be high for the controller to survive. So, we
    // must write out junk until it is. The card will ignore it.

    which would explain why the controller is dying if I don't wait long enough. 

    I also found the CSL function:

    MMC_waitForFlag(card, MMC_ST0_DATDNE);

    I used it after my MMC_write(); and all is good in the world again. 

    I tried reading the flags directly before but with no success. I see in the comment and code of sd_write that says junk is written out until the flag changes. Don't quite know why this is necessary, but I guess MMC_waitForFlag takes care of that. 

    Thanks for the help and suggestions!