Hi,
at the moment I am trying to interface a SD Card with the MSP430G2231.
Therefore I´m using the MMC library functions provided by TI.
Now the problem is after sending the Go_Idle command to the SD Card it always responses
with a TIMEOUT_ERROR and I really can´t imagine why.
Maybe a bit more precise explanation :
First I raise Chip select and send some dummy bytes to the sd card for about 80 clock cycles.
Then I pull CS low and send the Go_Idle command to the sd. Afterwards I try to read the response of the
sd card and that´s where it answers with the timeout error.
The voltage levels are perfectly correct ( I just measured it).
But I don´t know if the MSP430 clocks properly (can´t measure it because I have no scope).
So here´s my port initialization :
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer P1OUT = 0x10; // P1.4 set, else reset P1DIR = 0x01; // P1.0 output, else input P1DIR |= SD_CS; // Set P1.4 to output direction Chip Select P1DIR |= SPI_SCLK; // Set P1.5 to output direction Master Clock P1DIR |= SPI_SDO; // Set P1.6 to output direction Data Output USICTL0 |= USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE; // Port, SPI master USICKCTL = USIDIV_4 + USISSEL_2 + USICKPL; // /16 SMCLK USICTL0 &= ~USISWRST; // USI released for operation USISRL = 0x00; for (i = 0xFFF; i > 0; i--); // Time for slave to ready USICNT = 1; // init-load counter
Hope somebody could help me.
Regards, Max
MaxE for (i = 0xFFF; i > 0; i--); // Time for slave to ready USICNT = 1; // init-load counter
This sets the USI to send one bit with SMCLK/16. However, the loop itself is faster than 16 MCLK (and therefore most likely SMCLK too) cycles.
So you program the USI for another bit before it has sent the first bit, probably resettign the baudrate divider and nothing is ever sent. Jsu ta guess.
You should do
for(i=10;i>0;i--){ // send 80 bits USICNT = 8; // clears USIIFG, as long as USIIFGCC is clear while(USICTL1& USIIFG); // wait for 8 bits sent}
Also, it might be necessary to set USICKPL. IIRC I had to do it on the USCI module (MSP430F1611) for SD card access for correct clock polarity (clock is inactive high and active low)
_____________________________________Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.
Hi Jens,
I tried to get it run with the for loop you suggested but it didn´t work anyway. So what should the USICKPL look like ??
It is set in this line :
USICKCTL = USISSEL_2 + USICKPL +USIDIV_4;
should I set it up like this :
USICKPL.IIRC
And in my main function there´s this while loop :
while(status!=0){ status = SD_Init(); timeout++; if(timeout==150){ break; } }the SD_Init() returns the Init_Error all the time.
It looks like this :
// Initialize SD cardunsigned short SD_Init(void){ //raise CS and MOSI for 80 clock cycles //SendByte(0xff) 10 times with CS high //RAISE CS int i; //initialization sequence on PowerUp CS_HIGH(); for(i=0;i<=9;i++) spiSendByte(DUMMY_CHAR); return (SD_GoIdle());}
So the SD_GoIdle returns the Timeout_Error.
// set SD in Idle modeunsigned short SD_GoIdle(){ unsigned short response=0x01; CS_LOW(); //Send Command 0 to put SD in SPI mode SDSendCmd(SD_GOIDLE,0,0x95); //Now wait for READY RESPONSE if(SDGetResponse()!=0x01) return SD_INIT_ERROR; while(response==0x01) { CS_HIGH(); spiSendByte(DUMMY_CHAR); CS_LOW(); SDSendCmd(SD_SEND_OP_COND,0x00,0xff); response=SDGetResponse(); } CS_HIGH(); spiSendByte(DUMMY_CHAR); return (SD_SUCCESS);}
It always happens after sending the SD_GOIDLE command. The following SDGetResponse
returns the Timeout_Error.
MaxEUSICKCTL = USISSEL_2 + USICKPL +USIDIV_4;
MaxEthe SD_Init() returns the Init_Error all the time.
What library do you use? I only know the MMC libary (slaa281b), which more or less also applies to CD cards.
However, a general quesiton: what size is your SD card? Newer cards, usually SDHC/SDXC cards, Especially those which claim to be 'high speed' do not implement the serial/SPI protocol anymore.Cards above 4GB (or sometimes even 2GB types), require a larger blocksize than the original 512 bytes and have a completely different configuration structure. Along with changing the internal organization, most manufacturers have also dropped the serial support.
That SD_GOIDLE returns a timeout may indicate that your card doesn't support serial mode at all.
Of course there's still a chance of a hardware problem. Does the card support the MSPs supply voltage? If they have separate supplies, what about the logic levels?
I'm not sure what the TI libraries do. But the following info might help.
SPI mode in an SD card can only be engaged after a power cycle.
Pin 1 (CS) must be held low as the power comes up or you will go into API mode.
I had problems engaging a few SD cards and it turned out that although I thought I was power cycling SD card (SD Vcc On then Off) I was still driving some of the IO lines on the SD card so it didn't always see a true power cycle, and consequently stayed in API mode.
I've got some SD-SPI code I could post but is written for a Freescale S08.....
(cue boo's and hisses)
When I´m debugging the code I can check the variable for the error code and it´s always the
timeout error.
Thw library I am using is the slaa281b.
I´m using a Sandisk 1GB MicroSD card. So I think the 512 bytes blocksize is ok.
It needs 2.7 V up to 3.6 V supply voltage and I´m driving it
with the 3.6 V provided by the MSP430 Launch Pad.
Is it possible that it doesn´t work with this card ??
Does anybody know a card that surely works ??
@Jens : SPI mode should be fine on SDHC and SDXC. RE block size it was fixed at 512 bytes in SDHC and SDXC. SDSC can also use 512 bytes, but optionally less if the mfg supported it.
@MaxE: In my experience if anything is going to work a SANDISK will.
Mark GreenPin 1 (CS) must be held low as the power comes up or you will go into API mode.
My code works with MMC, SD (up to 2GB) and microSD cards (which behave a bit different than normal SD cards in that they don't accept CMD1 whereas normal MMC cards do accept CMD1 and ACMD41 and MMC cards of course won't accept ACMD41). So I don't think it is necessary to have CS low on power-up. Or I was just lucky getting only cards that didn't require it :)
I just took a look into the SD card specs V1.01 and it reads:
"The SD Memory Card wakes up in the SD mode. It will enter SPI mode if the CS signal is asserted (negative) during the reception of the reset command (CMD0) and the card is in idle_state"
So it always enters SD mode (the parallel mode, which I think is what you call API mode) on power-up and the state of CS determines whether it goes into SPI mode or not.Independently of mode, commands are always transmitted serially, only data transfers are done parallel.Of course there might have been an update to the standard since I wrote my code a few years ago. (Well, there definitely was, for SDHC and SDXC), but I don't have the newer specs.
Mark GreenSPI mode should be fine on SDHC and SDXC.
C_SIZE_MULT is 512 max, and C_SIZE is 4095 max, which gives a factor of 2097152*READ_BL_LEN. 1GB for 512 byte read block length. And since READ_BL_LEN is 2048 max, 4GB is the maximum size that can be expressed at all - with 2k block size then. Also, the data read command only has a 32 bit address (which isn't a block address but a byte address).
For anything above, the CSD needed to be changed, which is then no longer compatible to SD cards with the older CSD or MMC cards. And I noticed that manufacturers seemed to drop SPI mode at all for those cards, as those cards didn't respond at all. So I turned them down. 1GB was more than enough for all projects so far.Maybe it's time to think about a code extension. :) Do you have a link for the newest specs?
Jens-Michael GrossSure about this?
Obviously not... Just pulled up some of my old screen shots from the setup on this and your right, my CS is not held low from the get go. It goes low just before the first CMD. But the screen shot did remind me of what my original problem was.
The problem I had was the following:
- I would plug an SD card in and sometimes it would enter SPI mode, sometimes it wouldn't.
- Power cycle of the SD card rail would not cure the problem. (i.e. if it didn;t respond the first time, it wouldn't respond after a rail cycle.)
- But if the whole board was powered down then brought back up again it might work.
I think the problem was that if an SD card was plugged in while the socket was live then this would sometimes be interpreted as a false command by the SD card. Stopping entry into SPI mode (since this must be the first command after a power cycle). Subesequent rail cycles were not working because although the rail was dropped, the SPI lines were kept up (so keeping the SD card alive) .
The cure was to drop all interface lines to 0V. Then the rail to 0V. Then bring the rail back up followed by the interface lines.
It doesn't matter if CS is brought up at this point so long as it goes back down before the first command as Jens rightly points out.
So to finish the sequence I found to be quite reliable was:
- All lines low, and SD rail low
- SD rail up
- SPI on, (CS can go up as well)
- Send lots of 0xFF over the SPI (~80+clocks should do)
- CS low
- CMD0 (0x40) and off you go.....
Apologies for the CS low on powerup curveball....
I should point out by off you go I mean carry on with the config, not your ready for data transfer.
See p114 in the spec for more on the config command sequence:
https://www.sdcard.org/downloads/pls/
Jens-Michael GrossI got a couple of SDHC cards that refused to run in SPI mode. But maybe this was because these cards will indeed require CS low on power-up
Nope not due to the CS that my false info.
Jens-Michael GrossC_SIZE_MULT is 512 max, and C_SIZE is 4095 max, which
Page 125 of the spec explains this. But briefly:
Block size is fixed at 512 bytes for SDHC and SDXC. i.e. CMD16 (SET_BLOCKLEN) no longer does anything.
With blocks fixed at 512 bytes in HC/XC this gave them a bit of flexibility on the read commands (CMD17, CMD18). For these cards the 32bit address field is no longer a byte address it is a block address. 512 bytes * 2^32 = 2048 GB (if my maths is correct...)
So to point this out very clearly.
How should I do the init.
This is my code :
unsigned short status=1; unsigned int timeout=0; // SPI_Setup volatile unsigned int i; WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer P1OUT = 0x10; // P1.4 set, else reset P1DIR = 0x01; // P1.0 output, else input P1DIR |= SD_CS; // Set P1.4 to output direction Chip Select P1DIR |= SPI_SCLK; // Set P1.5 to output direction Master Clock P1DIR |= SPI_SDO; // Set P1.6 to output direction Data Output USICTL0 |= USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE + USISWRST; // Port, SPI master USICKCTL = USISSEL_2 + USICKPL +USIDIV_4; // /16 SMCLK USICTL0 &= ~USISWRST; // USI released for operation USISRL = 0x00; USICNT = 1; for(i=10;i>0;i--){ // send 80 bits USICNT = 8; // clears USIIFG, as long as USIIFGCC is clear while(USICTL1& USIIFG); // wait for 8 bits sent } while(status!=0){ status = SD_Init(); timeout++; if(timeout==150){ break; } }
You can read the SD_Init code a few posts above.
Could it work like this ??
Hi Max,
You are using CMD1 to initialise an SD card. Not all SD cards support the MMC method of initialisation, and it is not recommended even if they do.
If its an SD card you should be using CMD0 >> CMD8 >> ACMD41.
I'll post a step through of the ACMD process on Monday.... If you can't wait download the physical spec (link above) then read section 7 SPI.
@Jean: If you were doing the same, then this is why your SDHC cards were not responding. SPI mode for these cards will not proceed without going down the correct route.
Mark.
Mark Green If you were doing the same, then this is why your SDHC cards were not responding. SPI mode for these cards will not proceed without going down the correct route.
- wait for CARD_DETECT signal- init SPI- 80 clock pulses- GO_IDLE_STATE- no response? go back to init SPI- MMC_APP_CMD- response == 4: try GO_IDLE_STATE/MMC_SEND_OP_COND istead (MMC)- response == 1: retry MMC_APP_CMD- response == 2: MMC_READ_CSD- check for valid (supported) card geometry.- done
Well, the last step needs ot be expanded, as well as the address field in the data read/write functions.
Mark GreenNot all SD cards support the MMC method of initialisation, and it is not recommended even if they do.
The initialization seems to work now at least the card responds with a 0x00 which
means success.
I just modified the SDGetResponse() function a bit
here`s the code :
// SD Get Responseunsigned short SDGetResponse(void){ //Response comes 1-8bytes after command //the first bit will be a 0 //followed by an error code //data will be 0xff until response int i=0; unsigned short response; while(i<=64) { //response=spiSendByte(DUMMY_CHAR); response=SPIRXBUF; if(response==0x00)break; if(response==0x01)break; i++; } return response;}
Sending the DUMMY_CHAR seems to cause trouble. Though when I write
response=SPIRXBUF;
it works (not every time but at least 90 % of the tries).
But now there´s another problem which I will mention in another thread.
It´s about malloc. The debugger says there´s no source for malloc.