Sign in

Not a member? | Forgot your Password?


Search msp430

Search tips

Subscribe to msp430

Free PDF Downloads

Beginning Microcontrollers with the MSP430

Advanced Linux Programming

What Every Programmer Should Know About Memory

Introduction to Embedded Systems

C++ Tutorial

Embedded Systems - Theory and Design Methodology

Microcontroller Programming and Interfacing

Introduction to Microcontrollers


More Free PDF Downloads

Discussion Groups

See Also

ElectronicsDSPFPGA

Find us on Facebook





Discussion Groups | MSP430 | Having trouble with SPI for SD Card

The purpose of this group is to foster exchange of information on the Texas Instruments MSP430 family of microcontrollers and related tools. Everyone welcome, all levels of familiarity/expertise.

Having trouble with SPI for SD Card - mastarre - May 26 18:52:32 2010

Hello Everyone,

I have code for a MSP430FG4618 / RF2500 combo running SimpliciTI that is working very well and I would now like to add an SD card.

I am looking at the guide in SLAA281B (http://focus.ti.com/lit/an/slaa281b/slaa281b.pdf) and am using the associated example code.

I believe that USCI_B is used by the radio so I would like to communicate with the SD card using USCI_A. Apparently I am missing something as I have spent several a long time working on this without much success.

Here is where I am:
I have configured the hardware as follows:

1 (CS) ---------------> P7.0 (UCA0STE), H6.1
2 (DI) ----------------> P7.1 (UCA0SIMO), H6.2
3 (VSS) -------------> GND
4 (VCC) -------------> VCC
5 (SCK) -------------> P7.3 (UCA0CLK), H6.4
6 (CD) ---------------> P7.4, H6.5
7 (DO) ---------------> P7.2(UCA0SOMI), H6.3

And updated the software in hal_MMC_hardware_board.h to reflect those pin assignments and my MCU, the MSP430fg4618, as shown below.

Additionally, I modified SPI_SER_INTF as follows:

#define SPI_SER_INTF SER_INTF_USCIA0 // Interface to MMC

However, when debugging that I recieve many errors to the effect of :

Error[Pe020]: identifier "UTXIFG0" is undefined C:\\MCU\examples\sd_for_ti_SLAA281B\MMC_lib\hal_SPI.c 286

Etc. Looking in msp430xG46x.h I find that they are in fact not defined. As a test, I tried switching the definition above to SER_INTF_USCIB0 and it did compile in that case but of course it didn't actually work because my wiring does not reflect that change.

Again, I want to use USCI_A as I believe the radio is using USCI_B

What am I not seeing? I would really appreciate some help.

#include // Adjust this according to the
// MSP430 device being used.
// SPI port definitions // Adjust the values for the chosen
#define SPI_PxSEL P7SEL // interfaces, according to the pin
#define SPI_PxDIR P7DIR // assignments indicated in the
#define SPI_PxIN P7IN // chosen MSP430 device datasheet.
#define SPI_PxOUT P7OUT
#define SPI_SIMO 0x02
#define SPI_SOMI 0x04
#define SPI_UCLK 0x08
//----
// SPI/UART port selections. Select which port will be used for the interface
//----
#define SPI_SER_INTF SER_INTF_USCIB0 // Interface to MMC

// SPI port definitions // Adjust the values for the chosen
#define MMC_PxSEL SPI_PxSEL // interfaces, according to the pin
#define MMC_PxDIR SPI_PxDIR // assignments indicated in the
#define MMC_PxIN SPI_PxIN // chosen MSP430 device datasheet.
#define MMC_PxOUT SPI_PxOUT
#define MMC_SIMO SPI_SIMO
#define MMC_SOMI SPI_SOMI
#define MMC_UCLK SPI_UCLK

// Chip Select
#define MMC_CS_PxOUT P7OUT
#define MMC_CS_PxDIR P7DIR
#define MMC_CS 0x01

// Card Detect
#define MMC_CD_PxIN P7IN
#define MMC_CD_PxDIR P7DIR
#define MMC_CD 0x10

#define CS_LOW() MMC_CS_PxOUT &= ~MMC_CS // Card Select
#define CS_HIGH() while(!halSPITXDONE); MMC_CS_PxOUT |= MMC_CS // Card Deselect

#define DUMMY_CHAR 0xFF



Re: Having trouble with SPI for SD Card - mastarre - May 26 19:02:38 2010

Oh, and if I configure:
#define SPI_SER_INTF SER_INTF_BITBANG // Interface to MMC

It will not proceed past mmcReadCardSize();

--- In m..., "mastarre" wrote:
>
> Hello Everyone,
>
> I have code for a MSP430FG4618 / RF2500 combo running SimpliciTI that is working very well and I would now like to add an SD card.
>
> I am looking at the guide in SLAA281B (http://focus.ti.com/lit/an/slaa281b/slaa281b.pdf) and am using the associated example code.
>
> I believe that USCI_B is used by the radio so I would like to communicate with the SD card using USCI_A. Apparently I am missing something as I have spent several a long time working on this without much success.
>
> Here is where I am:
> I have configured the hardware as follows:
>
> 1 (CS) ---------------> P7.0 (UCA0STE), H6.1
> 2 (DI) ----------------> P7.1 (UCA0SIMO), H6.2
> 3 (VSS) -------------> GND
> 4 (VCC) -------------> VCC
> 5 (SCK) -------------> P7.3 (UCA0CLK), H6.4
> 6 (CD) ---------------> P7.4, H6.5
> 7 (DO) ---------------> P7.2(UCA0SOMI), H6.3
>
>
>
> And updated the software in hal_MMC_hardware_board.h to reflect those pin assignments and my MCU, the MSP430fg4618, as shown below.
>
> Additionally, I modified SPI_SER_INTF as follows:
>
> #define SPI_SER_INTF SER_INTF_USCIA0 // Interface to MMC
>
> However, when debugging that I recieve many errors to the effect of :
>
> Error[Pe020]: identifier "UTXIFG0" is undefined C:\\MCU\examples\sd_for_ti_SLAA281B\MMC_lib\hal_SPI.c 286
>
> Etc. Looking in msp430xG46x.h I find that they are in fact not defined. As a test, I tried switching the definition above to SER_INTF_USCIB0 and it did compile in that case but of course it didn't actually work because my wiring does not reflect that change.
>
> Again, I want to use USCI_A as I believe the radio is using USCI_B
>
> What am I not seeing? I would really appreciate some help.
>
>
>
> #include // Adjust this according to the
> // MSP430 device being used.
> // SPI port definitions // Adjust the values for the chosen
> #define SPI_PxSEL P7SEL // interfaces, according to the pin
> #define SPI_PxDIR P7DIR // assignments indicated in the
> #define SPI_PxIN P7IN // chosen MSP430 device datasheet.
> #define SPI_PxOUT P7OUT
> #define SPI_SIMO 0x02
> #define SPI_SOMI 0x04
> #define SPI_UCLK 0x08
> //----
> // SPI/UART port selections. Select which port will be used for the interface
> //----
> #define SPI_SER_INTF SER_INTF_USCIB0 // Interface to MMC
>
> // SPI port definitions // Adjust the values for the chosen
> #define MMC_PxSEL SPI_PxSEL // interfaces, according to the pin
> #define MMC_PxDIR SPI_PxDIR // assignments indicated in the
> #define MMC_PxIN SPI_PxIN // chosen MSP430 device datasheet.
> #define MMC_PxOUT SPI_PxOUT
> #define MMC_SIMO SPI_SIMO
> #define MMC_SOMI SPI_SOMI
> #define MMC_UCLK SPI_UCLK
>
> // Chip Select
> #define MMC_CS_PxOUT P7OUT
> #define MMC_CS_PxDIR P7DIR
> #define MMC_CS 0x01
>
> // Card Detect
> #define MMC_CD_PxIN P7IN
> #define MMC_CD_PxDIR P7DIR
> #define MMC_CD 0x10
>
> #define CS_LOW() MMC_CS_PxOUT &= ~MMC_CS // Card Select
> #define CS_HIGH() while(!halSPITXDONE); MMC_CS_PxOUT |= MMC_CS // Card Deselect
>
> #define DUMMY_CHAR 0xFF
>



Re: Having trouble with SPI for SD Card - Microbit_Ubuntu - May 26 19:19:05 2010

Hi,

Have you checked that - in case it's bit banged like the code suggests -
the proper SPI mode is used ?
The card will init on its pulse train to switch to SPI, but with the
wrong CLK/DATA phase, it will stay mute and deaf.
Perhaps worth double check ?

HTH
Kris

On Wed, 2010-05-26 at 22:57 +0000, mastarre wrote:
> Oh, and if I configure:
> #define SPI_SER_INTF SER_INTF_BITBANG // Interface to MMC
>
> It will not proceed past mmcReadCardSize();
>
> --- In m..., "mastarre" wrote:
> >
> > Hello Everyone,
> >
> > I have code for a MSP430FG4618 / RF2500 combo running SimpliciTI that is working very well and I would now like to add an SD card.
> >
> > I am looking at the guide in SLAA281B (http://focus.ti.com/lit/an/slaa281b/slaa281b.pdf) and am using the associated example code.
> >
> > I believe that USCI_B is used by the radio so I would like to communicate with the SD card using USCI_A. Apparently I am missing something as I have spent several a long time working on this without much success.
> >
> > Here is where I am:
> > I have configured the hardware as follows:
> >
> > 1 (CS) ---------------> P7.0 (UCA0STE), H6.1
> > 2 (DI) ----------------> P7.1 (UCA0SIMO), H6.2
> > 3 (VSS) -------------> GND
> > 4 (VCC) -------------> VCC
> > 5 (SCK) -------------> P7.3 (UCA0CLK), H6.4
> > 6 (CD) ---------------> P7.4, H6.5
> > 7 (DO) ---------------> P7.2(UCA0SOMI), H6.3
> >
> >
> >
> > And updated the software in hal_MMC_hardware_board.h to reflect those pin assignments and my MCU, the MSP430fg4618, as shown below.
> >
> > Additionally, I modified SPI_SER_INTF as follows:
> >
> > #define SPI_SER_INTF SER_INTF_USCIA0 // Interface to MMC
> >
> > However, when debugging that I recieve many errors to the effect of :
> >
> > Error[Pe020]: identifier "UTXIFG0" is undefined C:\\MCU\examples\sd_for_ti_SLAA281B\MMC_lib\hal_SPI.c 286
> >
> > Etc. Looking in msp430xG46x.h I find that they are in fact not defined. As a test, I tried switching the definition above to SER_INTF_USCIB0 and it did compile in that case but of course it didn't actually work because my wiring does not reflect that change.
> >
> > Again, I want to use USCI_A as I believe the radio is using USCI_B
> >
> > What am I not seeing? I would really appreciate some help.
> >
> >
> >
> > #include // Adjust this according to the
> > // MSP430 device being used.
> > // SPI port definitions // Adjust the values for the chosen
> > #define SPI_PxSEL P7SEL // interfaces, according to the pin
> > #define SPI_PxDIR P7DIR // assignments indicated in the
> > #define SPI_PxIN P7IN // chosen MSP430 device datasheet.
> > #define SPI_PxOUT P7OUT
> > #define SPI_SIMO 0x02
> > #define SPI_SOMI 0x04
> > #define SPI_UCLK 0x08
> >
> >
> > //----
> > // SPI/UART port selections. Select which port will be used for the interface
> > //----
> > #define SPI_SER_INTF SER_INTF_USCIB0 // Interface to MMC
> >
> > // SPI port definitions // Adjust the values for the chosen
> > #define MMC_PxSEL SPI_PxSEL // interfaces, according to the pin
> > #define MMC_PxDIR SPI_PxDIR // assignments indicated in the
> > #define MMC_PxIN SPI_PxIN // chosen MSP430 device datasheet.
> > #define MMC_PxOUT SPI_PxOUT
> > #define MMC_SIMO SPI_SIMO
> > #define MMC_SOMI SPI_SOMI
> > #define MMC_UCLK SPI_UCLK
> >
> > // Chip Select
> > #define MMC_CS_PxOUT P7OUT
> > #define MMC_CS_PxDIR P7DIR
> > #define MMC_CS 0x01
> >
> > // Card Detect
> > #define MMC_CD_PxIN P7IN
> > #define MMC_CD_PxDIR P7DIR
> > #define MMC_CD 0x10
> >
> > #define CS_LOW() MMC_CS_PxOUT &= ~MMC_CS // Card Select
> > #define CS_HIGH() while(!halSPITXDONE); MMC_CS_PxOUT |= MMC_CS // Card Deselect
> >
> > #define DUMMY_CHAR 0xFF
> >
>


Re: Having trouble with SPI for SD Card - Dan Bloomquist - May 26 21:14:03 2010

Here, maybe this will help. Get the PDF, Application notes link after
'background'.


His code worked right out of the box with DMA. I wrote a much simpler
version for the 149, non DMA from that. As I didn't post it there, I'll
include it below. This is tested code, it worked at the time I was using
it :)

Best, Dan.

sd.h~~~~~~~
#ifndef SD_H
#define SD_H

#define SD_BLOCKSIZE 512
#define SD_BLOCKSIZE_NBITS 9
#define SD_CLK_SLOW_DIV 400000
#define SD_TIMEOUT_READ 20
#define MSK_TOK_ERROR 0x01
#define MSK_TOK_DATAERROR 0xE0
#define SD_TOK_WRITE_STARTBLOCK 0xFE
#define SD_IDLE_WAIT_MAX 100
#define SD_CMD_TIMEOUT 100

//Standard voltage range expected
#define SD_ORC_RESPONSE 0x80ff0001

//the new commands, add as needed
//first is we don' t need any commands that return the type 'R1B'
//the comand is high byte and response count is low byte

//Must or mask all commands with 01000000
#define SD_CMDMASK 0x4000
#define SDRTN_R1 1
#define SDRTN_R3 5

#define SDCMD_0 ( SD_CMDMASK | ( 0 << 8 ) | SDRTN_R1 )
#define SDCMD_55 ( SD_CMDMASK | ( 55 << 8 ) | SDRTN_R1 )
#define SDCMD_A41 ( SD_CMDMASK | ( 41 << 8 ) | SDRTN_R1 )
#define SDCMD_58 ( SD_CMDMASK | ( 58 << 8 ) | SDRTN_R3 )
#define SDCMD_17 ( SD_CMDMASK | ( 17 << 8 ) | SDRTN_R1 )
#define SDCMD_24 ( SD_CMDMASK | ( 24 << 8 ) | SDRTN_R1 )

extern BYTE* secBuf;
extern BYTE response[5];
extern WORD block_count;

/* User functions */
bool sd_initialize( );

bool sd_read_block( DWORD blockaddr, const BYTE* pData );

bool sd_write_block( DWORD blockaddr, const BYTE* pData );

bool sd_send_command( WORD cmd, DWORD arg );

void sd_delay( BYTE number );

#endif

sd.c~~~~~~~~~
#include "Device_430.h"
#include "spi.h"
#include "sd.h"

/* SPI SD initialization sequence:
* CMD0
* CMD55
* ACMD41
* CMD58
*/

bool sd_initialize( )
{
// Delay for at least 74 clock cycles. This means to actually
// *clock* out at least 74 clock cycles with no data present on
// the clock. In SPI mode, send at least 10 idle bytes (0xFF).

//initialize the SPI port
spi_initialize( );

//Start out with a slow SPI clock, 400kHz, as required by the SD spec
spi_set_divisor( SD_CLK_SLOW );

//spi_cs_assert( );
SPI_CS_ASSERT;
sd_delay( 100 );

SPI_CS_DEASSERT;
sd_delay( 10 );

// Put the card in the idle state
if( ! sd_send_command( SDCMD_0, 0 ) )
return false;

//wait until idle clear
int j;
for( j= 0; j < SD_IDLE_WAIT_MAX; ++j )
{
if( sd_send_command( SDCMD_55, 0 ) )
{
/* Tell the card to send its OCR */
sd_send_command( SDCMD_A41, 0 );
}

if( ! response[0] )
break;
}
if( j == SD_IDLE_WAIT_MAX )
return false;

if( ! sd_send_command( SDCMD_58, 0 ) )
return false;

//Set the maximum SPI clock rate possible
spi_set_divisor( 2 );

return true;
}

bool sd_read_block( DWORD blockaddr, const BYTE* data )
{
unsigned long int i= 0;
unsigned char tmp;
block_count= 0;

// Adjust the block address to a linear address
blockaddr<<= SD_BLOCKSIZE_NBITS;

//Send block read command
if( ! sd_send_command( SDCMD_17, blockaddr ) )
return false;

// Check for an error, like a misaligned read
if( response[0] )
return false;

// Re-assert CS to continue the transfer
SPI_CS_ASSERT;

// Wait for the token
for( i= 0, tmp= 0xff; ( tmp == 0xFF ) && i < SD_TIMEOUT_READ; ++i )
tmp= spi_rcv_byte( );

if( ! ( tmp & MSK_TOK_DATAERROR ) )
{
// The card returned an error response. Bail and return false
// Clock out a byte before returning
spi_send_byte( 0xFF );

return 0;
}

//No dma, just do bulk transfer in code
for( block_count= 0; block_count < SD_BLOCKSIZE; ++block_count )
secBuf[ block_count ]= spi_rcv_byte( );

return 1;
}

bool sd_write_block( DWORD blockaddr, const BYTE *data )
{
// Adjust the block address to a linear address
blockaddr <<= SD_BLOCKSIZE_NBITS;

// Pack the address
//sd_packarg( argument, blockaddr );

if( ! sd_send_command( SDCMD_24, blockaddr ) )
return false;

// Check for an error, like a misaligned write
if( response[0] )
return false;

// Re-assert CS to continue the transfer
SPI_CS_ASSERT;

// The write command needs an additional 8 clock cycles before the
block write is started
spi_rcv_byte( );

// Kick off the transfer by sending the first byte, the "start
block" token
SD_UTXBUF = SD_TOK_WRITE_STARTBLOCK;

//Write the block
for( block_count= 0; block_count < SD_BLOCKSIZE; ++block_count )
spi_send_byte( secBuf[ block_count ] );

//need to pad some clocks or get Erase_Seq_Error
// on the next write, and a rcv_byte...
sd_delay( 4 );

//TODO ? might get hung here? Or should this be left for next op?
for( ; spi_rcv_byte( ) != 0xFF; )
;

return true;
}

bool sd_send_command( WORD cmd, DWORD arg )
{
volatile int i;
int rpos;
unsigned char tmp= 0;

SPI_CS_ASSERT;
spi_send_byte( cmd >> 8 );

for( i= 3; i >= 0 ; --i )
spi_send_byte( ( (BYTE*)&arg )[ i ] );

// This is the CRC. It only matters what we put here for the first
//command. Otherwise, the CRC is ignored for SPI mode unless we
//enable CRC checking.
spi_send_byte( 0x95 );

rpos= (BYTE)cmd - 1;

/* Wait for a response. A response can be recognized by the
start bit (a zero) */
for( i= 0; i < SD_CMD_TIMEOUT; ++i )
{
tmp= spi_rcv_byte( );
if( !( tmp & 0x80 ) )
break;
}
/* Just bail if we never got a response */
if( i >= SD_CMD_TIMEOUT )
{
SPI_CS_DEASSERT;
return false;
}
for(; rpos >= 0; --rpos )
{
response[ rpos ]= tmp;
tmp= spi_rcv_byte( );
}

SPI_CS_DEASSERT;
return true;
}

void sd_delay( BYTE number )
{
//clocks out idle bytes...
for( ; number--; )
spi_send_byte( 0xFF );
}

spi.h~~~~~~~~~~~~~~~~~~
#define SS_PORT_DIR P5DIR
#define SS_PORT_OUT P5OUT
#define SS_PIN BIT4

#define SPI_PORT_SEL P5SEL
#define SPI_PINS_SEL ( BIT1 | BIT2 | BIT3 )

//defines that set which port
#define SD_UCTL U1CTL
#define SD_UTCTL U1TCTL
#define SD_UBR0 U1BR0
#define SD_UBR1 U1BR1
#define SD_UMCTL U1MCTL
#define SD_MOD_REG ME2
#define SD_USPIE USPIE1
#define SPI_IFG IFG2
#define SD_UTXIFG UTXIFG1
#define SD_URXIFG URXIFG1
#define SD_UTXBUF U1TXBUF
#define SD_URXBUF U1RXBUF
#define SD_IE IE2
#define SD_URXIE URXIE1

// ...........................
void spi_initialize( );
void spi_set_divisor( WORD divisor );
void spi_send_byte( BYTE input );
BYTE spi_rcv_byte( );
void spi_enable( );
void spi_disable( );

#define SPI_CS_ASSERT SS_PORT_OUT&= ~SS_PIN
#define SPI_CS_DEASSERT SS_PORT_OUT|= SS_PIN

sdi.c~~~~~~~~~~~~~~~~~~~~~~~~
#include "Device_430.h"
#include "spi.h"

/* Initialize and enable the SPI module */
void spi_initialize( )
{
SPI_PORT_SEL = SPI_PINS_SEL; // Setup Px for SPI mode
SS_PORT_DIR|= SS_PIN; // Setup the SS as output
// low. So, initialize it high.
SS_PORT_OUT|= SS_PIN; // Set SS High

SD_UCTL= (CHAR | SYNC | MM | SWRST); // 8-bit, SPI, Master
SD_UTCTL= (SSEL1 | STC | CKPH); // Normal polarity, 3-wire
SD_UBR0= 0x002; // SPICLK = SMCLK/2 (2=Minimum divisor)
SD_UBR1= 0x000;
SD_UMCTL= 0x000;
SD_MOD_REG|= SD_USPIE; // Module enable
SD_UCTL&= ~SWRST; // SPI enable
}

/* Set the baud-rate divisor. The correct value is computed by dividing
the clock rate by the desired baud rate. The minimum divisor allowed
is 2. */
void spi_set_divisor( WORD divisor )
{
SD_UCTL|= SWRST; // Temporarily disable the SPI module
SD_UBR1= divisor >> 8;
SD_UBR0= divisor;
SD_UCTL&= ~SWRST; // Re-enable SPI
}

/* Send a single byte over the SPI port */
void spi_send_byte( BYTE input )
{
SPI_IFG&= ~SD_UTXIFG;
/* Send the byte */
SD_UTXBUF= input;
/* Wait for the byte to be sent */
while ( ! ( SPI_IFG & SD_UTXIFG ) )
;
}

/* Receive a byte. Output an 0xFF (the bus idles high) to receive the
byte */
BYTE spi_rcv_byte( )
{
unsigned char tmp;
SPI_IFG&= ~SD_URXIFG;

/* Send the byte */
SD_UTXBUF= 0xFF;

/* Wait for the byte to be received */
while( ! ( SPI_IFG & SD_URXIFG ) )
;
tmp= SD_URXBUF;
return tmp;
}



Re: Having trouble with SPI for SD Card - "Hayashi, Steve" - May 27 8:32:37 2010

That Appnote was written with the MSP430F1xxx series in mind. Those didn't have the USCI modules that all MSPs have now, they had USART. Instead of having UCA0TXBUF, they had U0TXBUF.

I'd crack open the header file they used in that appnote, search through those files, and replace all the old USART commands with USCI commands.

-Steve

From: m... [mailto:m...] On Behalf Of mastarre
Sent: Wednesday, May 26, 2010 6:52 PM
To: m...
Subject: [msp430] Having trouble with SPI for SD Card

Hello Everyone,

I have code for a MSP430FG4618 / RF2500 combo running SimpliciTI that is working very well and I would now like to add an SD card.

I am looking at the guide in SLAA281B (http://focus.ti.com/lit/an/slaa281b/slaa281b.pdf) and am using the associated example code.

I believe that USCI_B is used by the radio so I would like to communicate with the SD card using USCI_A. Apparently I am missing something as I have spent several a long time working on this without much success.

Here is where I am:
I have configured the hardware as follows:

1 (CS) ---------------> P7.0 (UCA0STE), H6.1
2 (DI) ----------------> P7.1 (UCA0SIMO), H6.2
3 (VSS) -------------> GND
4 (VCC) -------------> VCC
5 (SCK) -------------> P7.3 (UCA0CLK), H6.4
6 (CD) ---------------> P7.4, H6.5
7 (DO) ---------------> P7.2(UCA0SOMI), H6.3

And updated the software in hal_MMC_hardware_board.h to reflect those pin assignments and my MCU, the MSP430fg4618, as shown below.

Additionally, I modified SPI_SER_INTF as follows:

#define SPI_SER_INTF SER_INTF_USCIA0 // Interface to MMC

However, when debugging that I recieve many errors to the effect of :

Error[Pe020]: identifier "UTXIFG0" is undefined C:\\MCU\examples\sd_for_ti_SLAA281B\MMC_lib\hal_SPI.c 286

Etc. Looking in msp430xG46x.h I find that they are in fact not defined. As a test, I tried switching the definition above to SER_INTF_USCIB0 and it did compile in that case but of course it didn't actually work because my wiring does not reflect that change.

Again, I want to use USCI_A as I believe the radio is using USCI_B

What am I not seeing? I would really appreciate some help.

#include // Adjust this according to the
// MSP430 device being used.
// SPI port definitions // Adjust the values for the chosen
#define SPI_PxSEL P7SEL // interfaces, according to the pin
#define SPI_PxDIR P7DIR // assignments indicated in the
#define SPI_PxIN P7IN // chosen MSP430 device datasheet.
#define SPI_PxOUT P7OUT
#define SPI_SIMO 0x02
#define SPI_SOMI 0x04
#define SPI_UCLK 0x08

//----------------------
// SPI/UART port selections. Select which port will be used for the interface
//----------------------
#define SPI_SER_INTF SER_INTF_USCIB0 // Interface to MMC

// SPI port definitions // Adjust the values for the chosen
#define MMC_PxSEL SPI_PxSEL // interfaces, according to the pin
#define MMC_PxDIR SPI_PxDIR // assignments indicated in the
#define MMC_PxIN SPI_PxIN // chosen MSP430 device datasheet.
#define MMC_PxOUT SPI_PxOUT
#define MMC_SIMO SPI_SIMO
#define MMC_SOMI SPI_SOMI
#define MMC_UCLK SPI_UCLK

// Chip Select
#define MMC_CS_PxOUT P7OUT
#define MMC_CS_PxDIR P7DIR
#define MMC_CS 0x01

// Card Detect
#define MMC_CD_PxIN P7IN
#define MMC_CD_PxDIR P7DIR
#define MMC_CD 0x10

#define CS_LOW() MMC_CS_PxOUT &= ~MMC_CS // Card Select
#define CS_HIGH() while(!halSPITXDONE); MMC_CS_PxOUT |= MMC_CS // Card Deselect

#define DUMMY_CHAR 0xFF





Re: Having trouble with SPI for SD Card - mastarre - May 27 10:20:34 2010

Thank you for the replies! I actually have the Foust note but forgot about the code on the bottom. I am going to look through both of them thoroughly.

One thing that is really bugging me, though, is why the msp430xG46x.h

Does not include definitions for things like U0RXBUF (mentioned in the foust paper). I can see it clear as day on 18-13 in the manual but yet it is not defined in the header file. I am trying to figure out why. Any ideas?

--- In m..., Dan Bloomquist wrote:
> Here, maybe this will help. Get the PDF, Application notes link after
> 'background'.
> His code worked right out of the box with DMA. I wrote a much simpler
> version for the 149, non DMA from that. As I didn't post it there, I'll
> include it below. This is tested code, it worked at the time I was using
> it :)
>
> Best, Dan.
>
> sd.h~~~~~~~
> #ifndef SD_H
> #define SD_H
>
> #define SD_BLOCKSIZE 512
> #define SD_BLOCKSIZE_NBITS 9
> #define SD_CLK_SLOW_DIV 400000
> #define SD_TIMEOUT_READ 20
> #define MSK_TOK_ERROR 0x01
> #define MSK_TOK_DATAERROR 0xE0
> #define SD_TOK_WRITE_STARTBLOCK 0xFE
> #define SD_IDLE_WAIT_MAX 100
> #define SD_CMD_TIMEOUT 100
>
> //Standard voltage range expected
> #define SD_ORC_RESPONSE 0x80ff0001
>
> //the new commands, add as needed
> //first is we don' t need any commands that return the type 'R1B'
> //the comand is high byte and response count is low byte
>
> //Must or mask all commands with 01000000
> #define SD_CMDMASK 0x4000
> #define SDRTN_R1 1
> #define SDRTN_R3 5
>
> #define SDCMD_0 ( SD_CMDMASK | ( 0 << 8 ) | SDRTN_R1 )
> #define SDCMD_55 ( SD_CMDMASK | ( 55 << 8 ) | SDRTN_R1 )
> #define SDCMD_A41 ( SD_CMDMASK | ( 41 << 8 ) | SDRTN_R1 )
> #define SDCMD_58 ( SD_CMDMASK | ( 58 << 8 ) | SDRTN_R3 )
> #define SDCMD_17 ( SD_CMDMASK | ( 17 << 8 ) | SDRTN_R1 )
> #define SDCMD_24 ( SD_CMDMASK | ( 24 << 8 ) | SDRTN_R1 )
>
> extern BYTE* secBuf;
> extern BYTE response[5];
> extern WORD block_count;
>
> /* User functions */
> bool sd_initialize( );
>
> bool sd_read_block( DWORD blockaddr, const BYTE* pData );
>
> bool sd_write_block( DWORD blockaddr, const BYTE* pData );
>
> bool sd_send_command( WORD cmd, DWORD arg );
>
> void sd_delay( BYTE number );
>
> #endif
>
> sd.c~~~~~~~~~
> #include "Device_430.h"
> #include "spi.h"
> #include "sd.h"
>
> /* SPI SD initialization sequence:
> * CMD0
> * CMD55
> * ACMD41
> * CMD58
> */
>
> bool sd_initialize( )
> {
> // Delay for at least 74 clock cycles. This means to actually
> // *clock* out at least 74 clock cycles with no data present on
> // the clock. In SPI mode, send at least 10 idle bytes (0xFF).
>
> //initialize the SPI port
> spi_initialize( );
>
> //Start out with a slow SPI clock, 400kHz, as required by the SD spec
> spi_set_divisor( SD_CLK_SLOW );
>
> //spi_cs_assert( );
> SPI_CS_ASSERT;
> sd_delay( 100 );
>
> SPI_CS_DEASSERT;
> sd_delay( 10 );
>
> // Put the card in the idle state
> if( ! sd_send_command( SDCMD_0, 0 ) )
> return false;
>
> //wait until idle clear
> int j;
> for( j= 0; j < SD_IDLE_WAIT_MAX; ++j )
> {
> if( sd_send_command( SDCMD_55, 0 ) )
> {
> /* Tell the card to send its OCR */
> sd_send_command( SDCMD_A41, 0 );
> }
>
> if( ! response[0] )
> break;
> }
> if( j == SD_IDLE_WAIT_MAX )
> return false;
>
> if( ! sd_send_command( SDCMD_58, 0 ) )
> return false;
>
> //Set the maximum SPI clock rate possible
> spi_set_divisor( 2 );
>
> return true;
> }
>
> bool sd_read_block( DWORD blockaddr, const BYTE* data )
> {
> unsigned long int i= 0;
> unsigned char tmp;
> block_count= 0;
>
> // Adjust the block address to a linear address
> blockaddr<<= SD_BLOCKSIZE_NBITS;
>
> //Send block read command
> if( ! sd_send_command( SDCMD_17, blockaddr ) )
> return false;
>
> // Check for an error, like a misaligned read
> if( response[0] )
> return false;
>
> // Re-assert CS to continue the transfer
> SPI_CS_ASSERT;
>
> // Wait for the token
> for( i= 0, tmp= 0xff; ( tmp == 0xFF ) && i < SD_TIMEOUT_READ; ++i )
> tmp= spi_rcv_byte( );
>
> if( ! ( tmp & MSK_TOK_DATAERROR ) )
> {
> // The card returned an error response. Bail and return false
> // Clock out a byte before returning
> spi_send_byte( 0xFF );
>
> return 0;
> }
>
> //No dma, just do bulk transfer in code
> for( block_count= 0; block_count < SD_BLOCKSIZE; ++block_count )
> secBuf[ block_count ]= spi_rcv_byte( );
>
> return 1;
> }
>
> bool sd_write_block( DWORD blockaddr, const BYTE *data )
> {
> // Adjust the block address to a linear address
> blockaddr <<= SD_BLOCKSIZE_NBITS;
>
> // Pack the address
> //sd_packarg( argument, blockaddr );
>
> if( ! sd_send_command( SDCMD_24, blockaddr ) )
> return false;
>
> // Check for an error, like a misaligned write
> if( response[0] )
> return false;
>
> // Re-assert CS to continue the transfer
> SPI_CS_ASSERT;
>
> // The write command needs an additional 8 clock cycles before the
> block write is started
> spi_rcv_byte( );
>
> // Kick off the transfer by sending the first byte, the "start
> block" token
> SD_UTXBUF = SD_TOK_WRITE_STARTBLOCK;
>
> //Write the block
> for( block_count= 0; block_count < SD_BLOCKSIZE; ++block_count )
> spi_send_byte( secBuf[ block_count ] );
>
> //need to pad some clocks or get Erase_Seq_Error
> // on the next write, and a rcv_byte...
> sd_delay( 4 );
>
> //TODO ? might get hung here? Or should this be left for next op?
> for( ; spi_rcv_byte( ) != 0xFF; )
> ;
>
> return true;
> }
>
> bool sd_send_command( WORD cmd, DWORD arg )
> {
> volatile int i;
> int rpos;
> unsigned char tmp= 0;
>
> SPI_CS_ASSERT;
> spi_send_byte( cmd >> 8 );
>
> for( i= 3; i >= 0 ; --i )
> spi_send_byte( ( (BYTE*)&arg )[ i ] );
>
> // This is the CRC. It only matters what we put here for the first
> //command. Otherwise, the CRC is ignored for SPI mode unless we
> //enable CRC checking.
> spi_send_byte( 0x95 );
>
> rpos= (BYTE)cmd - 1;
>
> /* Wait for a response. A response can be recognized by the
> start bit (a zero) */
> for( i= 0; i < SD_CMD_TIMEOUT; ++i )
> {
> tmp= spi_rcv_byte( );
> if( !( tmp & 0x80 ) )
> break;
> }
> /* Just bail if we never got a response */
> if( i >= SD_CMD_TIMEOUT )
> {
> SPI_CS_DEASSERT;
> return false;
> }
> for(; rpos >= 0; --rpos )
> {
> response[ rpos ]= tmp;
> tmp= spi_rcv_byte( );
> }
>
> SPI_CS_DEASSERT;
> return true;
> }
>
> void sd_delay( BYTE number )
> {
> //clocks out idle bytes...
> for( ; number--; )
> spi_send_byte( 0xFF );
> }
>
> spi.h~~~~~~~~~~~~~~~~~~
> #define SS_PORT_DIR P5DIR
> #define SS_PORT_OUT P5OUT
> #define SS_PIN BIT4
>
> #define SPI_PORT_SEL P5SEL
> #define SPI_PINS_SEL ( BIT1 | BIT2 | BIT3 )
>
> //defines that set which port
> #define SD_UCTL U1CTL
> #define SD_UTCTL U1TCTL
> #define SD_UBR0 U1BR0
> #define SD_UBR1 U1BR1
> #define SD_UMCTL U1MCTL
> #define SD_MOD_REG ME2
> #define SD_USPIE USPIE1
> #define SPI_IFG IFG2
> #define SD_UTXIFG UTXIFG1
> #define SD_URXIFG URXIFG1
> #define SD_UTXBUF U1TXBUF
> #define SD_URXBUF U1RXBUF
> #define SD_IE IE2
> #define SD_URXIE URXIE1
>
> // ...........................
> void spi_initialize( );
> void spi_set_divisor( WORD divisor );
> void spi_send_byte( BYTE input );
> BYTE spi_rcv_byte( );
> void spi_enable( );
> void spi_disable( );
>
> #define SPI_CS_ASSERT SS_PORT_OUT&= ~SS_PIN
> #define SPI_CS_DEASSERT SS_PORT_OUT|= SS_PIN
>
> sdi.c~~~~~~~~~~~~~~~~~~~~~~~~
> #include "Device_430.h"
> #include "spi.h"
>
> /* Initialize and enable the SPI module */
> void spi_initialize( )
> {
> SPI_PORT_SEL = SPI_PINS_SEL; // Setup Px for SPI mode
> SS_PORT_DIR|= SS_PIN; // Setup the SS as output
> // low. So, initialize it high.
> SS_PORT_OUT|= SS_PIN; // Set SS High
>
> SD_UCTL= (CHAR | SYNC | MM | SWRST); // 8-bit, SPI, Master
> SD_UTCTL= (SSEL1 | STC | CKPH); // Normal polarity, 3-wire
> SD_UBR0= 0x002; // SPICLK = SMCLK/2 (2=Minimum divisor)
> SD_UBR1= 0x000;
> SD_UMCTL= 0x000;
> SD_MOD_REG|= SD_USPIE; // Module enable
> SD_UCTL&= ~SWRST; // SPI enable
> }
>
> /* Set the baud-rate divisor. The correct value is computed by dividing
> the clock rate by the desired baud rate. The minimum divisor allowed
> is 2. */
> void spi_set_divisor( WORD divisor )
> {
> SD_UCTL|= SWRST; // Temporarily disable the SPI module
> SD_UBR1= divisor >> 8;
> SD_UBR0= divisor;
> SD_UCTL&= ~SWRST; // Re-enable SPI
> }
>
> /* Send a single byte over the SPI port */
> void spi_send_byte( BYTE input )
> {
> SPI_IFG&= ~SD_UTXIFG;
> /* Send the byte */
> SD_UTXBUF= input;
> /* Wait for the byte to be sent */
> while ( ! ( SPI_IFG & SD_UTXIFG ) )
> ;
> }
>
> /* Receive a byte. Output an 0xFF (the bus idles high) to receive the
> byte */
> BYTE spi_rcv_byte( )
> {
> unsigned char tmp;
> SPI_IFG&= ~SD_URXIFG;
>
> /* Send the byte */
> SD_UTXBUF= 0xFF;
>
> /* Wait for the byte to be received */
> while( ! ( SPI_IFG & SD_URXIFG ) )
> ;
> tmp= SD_URXBUF;
> return tmp;
> }
>


_____________________________
 Free pdf download: Beginning Microcontrollers with the MSP430.


Re: Having trouble with SPI for SD Card - mastarre - May 27 12:13:16 2010

Ah okay, that makes sense. I was wondering about that but didn't have the history to know!

I have since made the change and it now compiles fine and runs. However, when running it gets to the initialization:
mmcInit()

Which calls:
CS_HIGH()

Which is:
#define CS_HIGH() while(!halSPITXDONE); MMC_CS_PxOUT |= MMC_CS

Which is:
#define halSPITXDONE (UCA0STAT&UCBUSY) /* Wait for TX to finish */
However, as I watch the registers in IAR in debug mode,
UCA0STAT___SPI = 0x00

Thus:
UCBUSY = 0

However, it will not proceed past CS_HIGH, it just continues to loop there.

At this point I feel like I have done so much searching and reading that I am spinning a little bit. This might be simple but I can't get the clarity I need to figure it out.

Does anyone have a suggestion?

And may I also say that the help here is just tremendous. I really appreciate it.



Re: Having trouble with SPI for SD Card - "Hayashi, Steve" - May 27 12:46:25 2010

You're suffering from too many macros IMHO, and it hides the obvious problem.

You have CS_HIGH defined (effectively) as:
While (!(UCA0STAT&UCBUSY));

So you're looping while USCI A0 is not busy.

-Steve

From: m... [mailto:m...] On Behalf Of mastarre
Sent: Thursday, May 27, 2010 12:12 PM
To: m...
Subject: [msp430] Re: Having trouble with SPI for SD Card

Ah okay, that makes sense. I was wondering about that but didn't have the history to know!

I have since made the change and it now compiles fine and runs. However, when running it gets to the initialization:
mmcInit()

Which calls:
CS_HIGH()

Which is:
#define CS_HIGH() while(!halSPITXDONE); MMC_CS_PxOUT |= MMC_CS

Which is:
#define halSPITXDONE (UCA0STAT&UCBUSY) /* Wait for TX to finish */

However, as I watch the registers in IAR in debug mode,
UCA0STAT___SPI = 0x00

Thus:
UCBUSY = 0

However, it will not proceed past CS_HIGH, it just continues to loop there.

At this point I feel like I have done so much searching and reading that I am spinning a little bit. This might be simple but I can't get the clarity I need to figure it out.

Does anyone have a suggestion?

And may I also say that the help here is just tremendous. I really appreciate it.





Re: Having trouble with SPI for SD Card - mastarre - May 27 13:22:16 2010

Steve,

I agree. The example is, in my opinion, WAY overly abstracted. I was planning to reduce it when I got something functional going but didn't want to before hand because it is a TI example and *should* work as written.

I see what you are saying but what I can't figure out is why it was written that way in the first place. That is why I feel like I might have read it somewhere in the past but am not able to think of it now, etc. Remember, this is working directly with a TI example so they wrote it to have that behavior. I am not saying that I am taking that for what it is and not trying to understand it - I am trying very hard to figure out why they did that - but I am having some trouble understanding the behavior that they expect to justify that and, thus, why my device is not behaving that way.

--- In m..., "Hayashi, Steve" wrote:
>
> You're suffering from too many macros IMHO, and it hides the obvious problem.
>
> You have CS_HIGH defined (effectively) as:
> While (!(UCA0STAT&UCBUSY));
>
> So you're looping while USCI A0 is not busy.
>
> -Steve
>
> From: m... [mailto:m...] On Behalf Of mastarre
> Sent: Thursday, May 27, 2010 12:12 PM
> To: m...
> Subject: [msp430] Re: Having trouble with SPI for SD Card
>
> Ah okay, that makes sense. I was wondering about that but didn't have the history to know!
>
> I have since made the change and it now compiles fine and runs. However, when running it gets to the initialization:
> mmcInit()
>
> Which calls:
> CS_HIGH()
>
> Which is:
> #define CS_HIGH() while(!halSPITXDONE); MMC_CS_PxOUT |= MMC_CS
>
> Which is:
> #define halSPITXDONE (UCA0STAT&UCBUSY) /* Wait for TX to finish */
>
> However, as I watch the registers in IAR in debug mode,
> UCA0STAT___SPI = 0x00
>
> Thus:
> UCBUSY = 0
>
> However, it will not proceed past CS_HIGH, it just continues to loop there.
>
> At this point I feel like I have done so much searching and reading that I am spinning a little bit. This might be simple but I can't get the clarity I need to figure it out.
>
> Does anyone have a suggestion?
>
> And may I also say that the help here is just tremendous. I really appreciate it.
>
>
>


_____________________________
 Free pdf download: Beginning Microcontrollers with the MSP430.


Re: Having trouble with SPI for SD Card - "Hayashi, Steve" - May 27 14:02:18 2010

The original flag was U0TCTL & TXEPT.
Translated into English, it will return 0 if the TX buffer is NOT empty.

USCI changed that functionality to busy, so that the closest equivalent function returns 0 if the USCI IS empty.

-Steve

From: m... [mailto:m...] On Behalf Of mastarre
Sent: Thursday, May 27, 2010 1:22 PM
To: m...
Subject: [msp430] Re: Having trouble with SPI for SD Card

Steve,

I agree. The example is, in my opinion, WAY overly abstracted. I was planning to reduce it when I got something functional going but didn't want to before hand because it is a TI example and *should* work as written.

I see what you are saying but what I can't figure out is why it was written that way in the first place. That is why I feel like I might have read it somewhere in the past but am not able to think of it now, etc. Remember, this is working directly with a TI example so they wrote it to have that behavior. I am not saying that I am taking that for what it is and not trying to understand it - I am trying very hard to figure out why they did that - but I am having some trouble understanding the behavior that they expect to justify that and, thus, why my device is not behaving that way.

--- In m..., "Hayashi, Steve" wrote:
>
> You're suffering from too many macros IMHO, and it hides the obvious problem.
>
> You have CS_HIGH defined (effectively) as:
> While (!(UCA0STAT&UCBUSY));
>
> So you're looping while USCI A0 is not busy.
>
> -Steve
>
> From: m... [mailto:m...] On Behalf Of mastarre
> Sent: Thursday, May 27, 2010 12:12 PM
> To: m...
> Subject: [msp430] Re: Having trouble with SPI for SD Card
>
> Ah okay, that makes sense. I was wondering about that but didn't have the history to know!
>
> I have since made the change and it now compiles fine and runs. However, when running it gets to the initialization:
> mmcInit()
>
> Which calls:
> CS_HIGH()
>
> Which is:
> #define CS_HIGH() while(!halSPITXDONE); MMC_CS_PxOUT |= MMC_CS
>
> Which is:
> #define halSPITXDONE (UCA0STAT&UCBUSY) /* Wait for TX to finish */
>
> However, as I watch the registers in IAR in debug mode,
> UCA0STAT___SPI = 0x00
>
> Thus:
> UCBUSY = 0
>
> However, it will not proceed past CS_HIGH, it just continues to loop there.
>
> At this point I feel like I have done so much searching and reading that I am spinning a little bit. This might be simple but I can't get the clarity I need to figure it out.
>
> Does anyone have a suggestion?
>
> And may I also say that the help here is just tremendous. I really appreciate it.
>
>
>





Re: Having trouble with SPI for SD Card - mastarre - May 27 15:57:48 2010

Ohh! Okay. Jeez!

Is there some way I could have figured that out more quickly on my own? I really appreciate your help but its a bit embarrassing really to have to post so many follow ups :)

--- In m..., "Hayashi, Steve" wrote:
>
> The original flag was U0TCTL & TXEPT.
> Translated into English, it will return 0 if the TX buffer is NOT empty.
>
> USCI changed that functionality to busy, so that the closest equivalent function returns 0 if the USCI IS empty.
>
> -Steve
>
> From: m... [mailto:m...] On Behalf Of mastarre
> Sent: Thursday, May 27, 2010 1:22 PM
> To: m...
> Subject: [msp430] Re: Having trouble with SPI for SD Card
>
> Steve,
>
> I agree. The example is, in my opinion, WAY overly abstracted. I was planning to reduce it when I got something functional going but didn't want to before hand because it is a TI example and *should* work as written.
>
> I see what you are saying but what I can't figure out is why it was written that way in the first place. That is why I feel like I might have read it somewhere in the past but am not able to think of it now, etc. Remember, this is working directly with a TI example so they wrote it to have that behavior. I am not saying that I am taking that for what it is and not trying to understand it - I am trying very hard to figure out why they did that - but I am having some trouble understanding the behavior that they expect to justify that and, thus, why my device is not behaving that way.
>
> --- In m..., "Hayashi, Steve" wrote:
> >
> > You're suffering from too many macros IMHO, and it hides the obvious problem.
> >
> > You have CS_HIGH defined (effectively) as:
> > While (!(UCA0STAT&UCBUSY));
> >
> > So you're looping while USCI A0 is not busy.
> >
> > -Steve
> >
> > From: m... [mailto:m...] On Behalf Of mastarre
> > Sent: Thursday, May 27, 2010 12:12 PM
> > To: m...
> > Subject: [msp430] Re: Having trouble with SPI for SD Card
> >
> >
> >
> > Ah okay, that makes sense. I was wondering about that but didn't have the history to know!
> >
> > I have since made the change and it now compiles fine and runs. However, when running it gets to the initialization:
> > mmcInit()
> >
> > Which calls:
> > CS_HIGH()
> >
> > Which is:
> > #define CS_HIGH() while(!halSPITXDONE); MMC_CS_PxOUT |= MMC_CS
> >
> > Which is:
> > #define halSPITXDONE (UCA0STAT&UCBUSY) /* Wait for TX to finish */
> >
> > However, as I watch the registers in IAR in debug mode,
> > UCA0STAT___SPI = 0x00
> >
> > Thus:
> > UCBUSY = 0
> >
> > However, it will not proceed past CS_HIGH, it just continues to loop there.
> >
> > At this point I feel like I have done so much searching and reading that I am spinning a little bit. This might be simple but I can't get the clarity I need to figure it out.
> >
> > Does anyone have a suggestion?
> >
> > And may I also say that the help here is just tremendous. I really appreciate it.
> >
> >
> >
> >
> >
>


_____________________________
 Free pdf download: Beginning Microcontrollers with the MSP430.


Re: Having trouble with SPI for SD Card - "Hayashi, Steve" - May 27 17:10:06 2010

The original code was written for the 1xx series processors (the #include header should have given that away), so it's probably better to comment out any unusual line from the original and look up in the family guide on what it does. It's slau049f.pdf, IIRC.

Granted, It's a lot more work, but you will understand better what they're trying to do.

-Steve

From: m... [mailto:m...] On Behalf Of mastarre
Sent: Thursday, May 27, 2010 3:47 PM
To: m...
Subject: [msp430] Re: Having trouble with SPI for SD Card

Ohh! Okay. Jeez!

Is there some way I could have figured that out more quickly on my own? I really appreciate your help but its a bit embarrassing really to have to post so many follow ups :)

--- In m..., "Hayashi, Steve" wrote:
>
> The original flag was U0TCTL & TXEPT.
> Translated into English, it will return 0 if the TX buffer is NOT empty.
>
> USCI changed that functionality to busy, so that the closest equivalent function returns 0 if the USCI IS empty.
>
> -Steve
>
> From: m... [mailto:m...] On Behalf Of mastarre
> Sent: Thursday, May 27, 2010 1:22 PM
> To: m...
> Subject: [msp430] Re: Having trouble with SPI for SD Card
>
> Steve,
>
> I agree. The example is, in my opinion, WAY overly abstracted. I was planning to reduce it when I got something functional going but didn't want to before hand because it is a TI example and *should* work as written.
>
> I see what you are saying but what I can't figure out is why it was written that way in the first place. That is why I feel like I might have read it somewhere in the past but am not able to think of it now, etc. Remember, this is working directly with a TI example so they wrote it to have that behavior. I am not saying that I am taking that for what it is and not trying to understand it - I am trying very hard to figure out why they did that - but I am having some trouble understanding the behavior that they expect to justify that and, thus, why my device is not behaving that way.
>
> --- In m..., "Hayashi, Steve" wrote:
> >
> > You're suffering from too many macros IMHO, and it hides the obvious problem.
> >
> > You have CS_HIGH defined (effectively) as:
> > While (!(UCA0STAT&UCBUSY));
> >
> > So you're looping while USCI A0 is not busy.
> >
> > -Steve
> >
> > From: m... [mailto:m...] On Behalf Of mastarre
> > Sent: Thursday, May 27, 2010 12:12 PM
> > To: m...
> > Subject: [msp430] Re: Having trouble with SPI for SD Card
> >
> >
> >
> > Ah okay, that makes sense. I was wondering about that but didn't have the history to know!
> >
> > I have since made the change and it now compiles fine and runs. However, when running it gets to the initialization:
> > mmcInit()
> >
> > Which calls:
> > CS_HIGH()
> >
> > Which is:
> > #define CS_HIGH() while(!halSPITXDONE); MMC_CS_PxOUT |= MMC_CS
> >
> > Which is:
> > #define halSPITXDONE (UCA0STAT&UCBUSY) /* Wait for TX to finish */
> >
> > However, as I watch the registers in IAR in debug mode,
> > UCA0STAT___SPI = 0x00
> >
> > Thus:
> > UCBUSY = 0
> >
> > However, it will not proceed past CS_HIGH, it just continues to loop there.
> >
> > At this point I feel like I have done so much searching and reading that I am spinning a little bit. This might be simple but I can't get the clarity I need to figure it out.
> >
> > Does anyone have a suggestion?
> >
> > And may I also say that the help here is just tremendous. I really appreciate it.
> >
> >
> >
> >
> >
>





Re: Having trouble with SPI for SD Card - mastarre - May 27 19:53:32 2010

Okay, this is beginning to get beyond frustrating and I am starting to feel inept after a full year of getting projects done quickly and confidently on this uC.

I still cannot get it to proceed past mmcInit(); because the SD card just will not respond back.

The hardware and pins are configured the same as my original post shows.

The USCI register is configured as follows:
void halSPISetup(void)
{
UCA0CTL0 = UCMST+UCCKPL+UCMSB+UCSYNC; // 3-pin, 8-bit SPI master
UCA0CTL1 = UCSSEL_2 + UCSWRST; // SMCLK
UCA0BR0 |= 0x02; // UCLK/2
UCA0BR1 = 0;
UCA0MCTL = 0;
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
}

And I have the following:
#define halSPITXREADY (IFG1&UCA0TXIFG) /* Wait for TX to be ready (UCAxTXIFG = 1) from 19-7 and more of manual*/
#define halSPITXDONE (!(UCA0STAT&UCBUSY)) /* Wait for TX to finish, UCBUSY = 0 when idle */
#define halSPIRXREADY (!(IFG1&UCA0RXIFG)) /* Wait for TX to be ready */

HOWEVER, UCA0TXIFG is always 0. It never resets to 1, even as I send data out. So..

in mmcInit() it proceeds all the way to the bottom:
----------
CS_HIGH();
for(i=0;i<=9;i++)
spiSendByte(DUMMY_CHAR);

return (mmcGoIdle());
}
------

and in mmcGoIdle:
--------
char mmcGoIdle()
{
char response=0x01;
CS_LOW();

//Send Command 0 to put MMC in SPI mode
mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);
//Now wait for READY RESPONSE
if(mmcGetResponse()!=0x01)
return MMC_INIT_ERROR;
----------

mmcGetResponse always returns 0 because RX buffer is always 0.

mmcGetResponse is follows:
char mmcGetResponse(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;

char response;

while(i {
response=spiSendByte(DUMMY_CHAR);
if(response==0x00)break;
if(response==0x01)break;
i++;
}
return response;
}

and I have modified spiSendByte given what I said about the TX buffer IFG:
unsigned char spiSendByte(const unsigned char data)
{
//while (halSPITXREADY == 0); // wait while not ready for TX
halSPI_SEND(data); // write
while (halSPIRXREADY == 0); // wait for RX buffer (full)
return (halSPIRXBUF);
}

What I can't figure out is why the heck the SD card isn't talking back AND why the TX IFG flag is never set to zero. I crossed the register configuration with the FG4618 manual and it looks just fine.

Are there any ideas? I am so sorry for posting question after question. I can assure you I am working on this on my own time and bang my head against the wall MANY times before posting in here.



Re: Having trouble with SPI for SD Card - Microbit_Ubuntu - May 27 20:31:15 2010

Sounds like you're at a stage where lowest level needs to be questioned.
Probe w/ CRO on the clk and miso/mosi lines while repeatedly banging a
familiar byte, iow bit pattern.
Check your clk/phase is correct.

FWIW, I'd be paranoid about simply adding constants (unless I know I can
trust 'em).
To be on the safe side, use | instead of + ::

> UCA0CTL0 = UCMST+UCCKPL+UCMSB+UCSYNC; // 3-pin, 8-bit SPI master
> UCA0CTL1 = UCSSEL_2 + UCSWRST; // SMCLK

UCA0CTL0 = UCMST|UCCKPL|UCMSB|UCSYNC; // 3-pin, 8-bit SPI master
UCA0CTL1 = UCSSEL_2 | UCSWRST; // SMCLK

Normally these vendor headers are checked well. But if there's
overlapping bits, you would end up with nasty carry effects on bits when
you use '+' to build constants.

Just my $0.02...

HTH
Kris
On Thu, 2010-05-27 at 23:53 +0000, mastarre wrote:
> Okay, this is beginning to get beyond frustrating and I am starting to feel inept after a full year of getting projects done quickly and confidently on this uC.
>
> I still cannot get it to proceed past mmcInit(); because the SD card just will not respond back.
>
> The hardware and pins are configured the same as my original post shows.
>
> The USCI register is configured as follows:
> void halSPISetup(void)
> {
> UCA0CTL0 = UCMST+UCCKPL+UCMSB+UCSYNC; // 3-pin, 8-bit SPI master
> UCA0CTL1 = UCSSEL_2 + UCSWRST; // SMCLK
> UCA0BR0 |= 0x02; // UCLK/2
> UCA0BR1 = 0;
> UCA0MCTL = 0;
> UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
> }
>
> And I have the following:
> #define halSPITXREADY (IFG1&UCA0TXIFG) /* Wait for TX to be ready (UCAxTXIFG = 1) from 19-7 and more of manual*/
> #define halSPITXDONE (!(UCA0STAT&UCBUSY)) /* Wait for TX to finish, UCBUSY = 0 when idle */
> #define halSPIRXREADY (!(IFG1&UCA0RXIFG)) /* Wait for TX to be ready */
>
> HOWEVER, UCA0TXIFG is always 0. It never resets to 1, even as I send data out. So..
>
> in mmcInit() it proceeds all the way to the bottom:
> ----------
> CS_HIGH();
> for(i=0;i<=9;i++)
> spiSendByte(DUMMY_CHAR);
>
> return (mmcGoIdle());
> }
> ------
>
> and in mmcGoIdle:
> --------
> char mmcGoIdle()
> {
> char response=0x01;
> CS_LOW();
>
> //Send Command 0 to put MMC in SPI mode
> mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);
> //Now wait for READY RESPONSE
> if(mmcGetResponse()!=0x01)
> return MMC_INIT_ERROR;
> ----------
>
> mmcGetResponse always returns 0 because RX buffer is always 0.
>
> mmcGetResponse is follows:
> char mmcGetResponse(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;
>
> char response;
>
> while(i > {
> response=spiSendByte(DUMMY_CHAR);
> if(response==0x00)break;
> if(response==0x01)break;
> i++;
> }
> return response;
> }
>
> and I have modified spiSendByte given what I said about the TX buffer IFG:
> unsigned char spiSendByte(const unsigned char data)
> {
> //while (halSPITXREADY == 0); // wait while not ready for TX
> halSPI_SEND(data); // write
> while (halSPIRXREADY == 0); // wait for RX buffer (full)
> return (halSPIRXBUF);
> }
>
> What I can't figure out is why the heck the SD card isn't talking back AND why the TX IFG flag is never set to zero. I crossed the register configuration with the FG4618 manual and it looks just fine.
>
> Are there any ideas? I am so sorry for posting question after question. I can assure you I am working on this on my own time and bang my head against the wall MANY times before posting in here.
>


Re: Having trouble with SPI for SD Card - Dan Bloomquist - May 27 21:24:58 2010

I decided not to use TI's example, I think for a very good reason. For
one, it is not pretty to look at, I just looked at my copy. It looks
messy and there are no timeouts.

And the Foust rules for the 430 work. I don't see where you set the
clock to 400khz unless your SMCLK is 800khz. I see you are sending 72
clocks before starting, the doc says > 73. I take it DUMMY_CHAR is 0xff.
I do a:

spi_set_divisor( SD_CLK_SLOW );

//spi_cs_assert( );
SPI_CS_ASSERT;
sd_delay( 100 );

SPI_CS_DEASSERT;
sd_delay( 10 );

// Put the card in the idle state
if( ! sd_send_command( SDCMD_0, 0 ) )
return false;

And sd_delay is a byte of 0xff so I'm sending 800 idle clocks before
even starting, and another 80 after de-assert. It works for me with my
protocal, ask Jack Bauer.

I recall playing around with the card. I do recall you have to give it
room to breath before using it. You have to stay at 400khz until you
have read the ORC. Then you can go full speed.

Best, Dan.

mastarre wrote:
> Okay, this is beginning to get beyond frustrating and I am starting to feel inept after a full year of getting projects done quickly and confidently on this uC.
>
> I still cannot get it to proceed past mmcInit(); because the SD card just will not respond back.
>
> The hardware and pins are configured the same as my original post shows.
>
> The USCI register is configured as follows:
> void halSPISetup(void)
> {
> UCA0CTL0 = UCMST+UCCKPL+UCMSB+UCSYNC; // 3-pin, 8-bit SPI master
> UCA0CTL1 = UCSSEL_2 + UCSWRST; // SMCLK
> UCA0BR0 |= 0x02; // UCLK/2
> UCA0BR1 = 0;
> UCA0MCTL = 0;
> UCA0CTL1&= ~UCSWRST; // **Initialize USCI state machine**
> }
>
> And I have the following:
> #define halSPITXREADY (IFG1&UCA0TXIFG) /* Wait for TX to be ready (UCAxTXIFG = 1) from 19-7 and more of manual*/
> #define halSPITXDONE (!(UCA0STAT&UCBUSY)) /* Wait for TX to finish, UCBUSY = 0 when idle */
> #define halSPIRXREADY (!(IFG1&UCA0RXIFG)) /* Wait for TX to be ready */
>
> HOWEVER, UCA0TXIFG is always 0. It never resets to 1, even as I send data out. So..
>
> in mmcInit() it proceeds all the way to the bottom:
> ----------
> CS_HIGH();
> for(i=0;i<=9;i++)
> spiSendByte(DUMMY_CHAR);
>
> return (mmcGoIdle());
> }
> ------
>
> and in mmcGoIdle:
> --------
> char mmcGoIdle()
> {
> char response=0x01;
> CS_LOW();
>
> //Send Command 0 to put MMC in SPI mode
> mmcSendCmd(MMC_GO_IDLE_STATE,0,0x95);
> //Now wait for READY RESPONSE
> if(mmcGetResponse()!=0x01)
> return MMC_INIT_ERROR;
> ----------
>
> mmcGetResponse always returns 0 because RX buffer is always 0.
>
> mmcGetResponse is follows:
> char mmcGetResponse(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;
>
> char response;
>
> while(i > {
> response=spiSendByte(DUMMY_CHAR);
> if(response==0x00)break;
> if(response==0x01)break;
> i++;
> }
> return response;
> }
>
> and I have modified spiSendByte given what I said about the TX buffer IFG:
> unsigned char spiSendByte(const unsigned char data)
> {
> //while (halSPITXREADY == 0); // wait while not ready for TX
> halSPI_SEND(data); // write
> while (halSPIRXREADY == 0); // wait for RX buffer (full)
> return (halSPIRXBUF);
> }
>
> What I can't figure out is why the heck the SD card isn't talking back AND why the TX IFG flag is never set to zero. I crossed the register configuration with the FG4618 manual and it looks just fine.
>
> Are there any ideas? I am so sorry for posting question after question. I can assure you I am working on this on my own time and bang my head against the wall MANY times before posting in here.
>

_____________________________
 Free pdf download: Beginning Microcontrollers with the MSP430.


Re: Having trouble with SPI for SD Card - mastarre - May 27 21:30:15 2010

I have never actually debugging a uC with a scope, my problems have always been in the software -- the only external hardware I have used is just the RF daughter board.

I've got it on and running now but with the scope on the clock pin of the experimenters board I am not seeing any meaningful signal (its zero). Checked it on another board and got the same. I am not sure exactly what amplitude the output should be at, assuming vcc, but either way what I have clearly is not right.

However, I do have:
#define SPI_UCLK 0x08

and

#define MMC_UCLK SPI_UCLK

and I am breaking AFTER this point:
-------------------
// Initialize MMC card
char mmcInit(void)
{
//raise CS and MOSI for 80 clock cycles
//SendByte(0xff) 10 times with CS high
//RAISE CS
int i;

// Port x Function Dir On/Off
// mmcCS Out 0 - Active 1 - none Active
// Dout Out 0 - off 1 - On -> init in SPI_Init
// Din Inp 0 - off 1 - On -> init in SPI_Init
// Clk Out - -> init in SPI_Init
// mmcCD In 0 - card inserted

// Init Port for MMC (default high)
MMC_PxOUT |= MMC_SIMO + MMC_UCLK;
MMC_PxDIR |= MMC_SIMO + MMC_UCLK;
// Chip Select
MMC_CS_PxOUT |= MMC_CS;
MMC_CS_PxDIR |= MMC_CS;

// Card Detect
MMC_CD_PxDIR &= ~MMC_CD;

// Init SPI Module
halSPISetup();

// Enable secondary function
#if SPI_SER_INTF != SER_INTF_BITBANG
MMC_PxSEL |= MMC_SIMO + MMC_SOMI + MMC_UCLK;
#endif

//initialization sequence on PowerUp
CS_HIGH();
-------------------
And I am breaking on CS_HIGH();



Re: Having trouble with SPI for SD Card - Microbit_Ubuntu - May 27 22:06:58 2010

You have to write a tiny bit of test code.
With logic analyser it's a lot easier, but you can make do with CRO.
If your CRO doesn't trigger as well, output a sync pulse of some sort
into 2nd channel. (this could be for example the CS asserting and
de-asserting). Whatever your CRO is happy with....

Just write test code where you sit in a constant loop, wait for SPI
free, TX a byte, back to start of loop (do this eg. right after init)
Make the TX'd byte such that you have a clear bit pattern, eg. (binary)
01001100.
This will allow you to
(i) confirm that SPI is set up properly
(ii) inspect clock phase & polarity

Once that's OK, you can start looking at sending something which will
invoke a response from SPI slave. Then you can check with a breakpoint
(or print it out) that you're RXing the proper byte.

Once that's going, I'm sure your SD card will finally wake UP !! :-)

HTH
Kris

On Fri, 2010-05-28 at 01:28 +0000, mastarre wrote:
> I have never actually debugging a uC with a scope, my problems have always been in the software -- the only external hardware I have used is just the RF daughter board.
>
> I've got it on and running now but with the scope on the clock pin of the experimenters board I am not seeing any meaningful signal (its zero). Checked it on another board and got the same. I am not sure exactly what amplitude the output should be at, assuming vcc, but either way what I have clearly is not right.
>
> However, I do have:
> #define SPI_UCLK 0x08
>
> and
>
> #define MMC_UCLK SPI_UCLK
>
> and I am breaking AFTER this point:
> -------------------
> // Initialize MMC card
> char mmcInit(void)
> {
> //raise CS and MOSI for 80 clock cycles
> //SendByte(0xff) 10 times with CS high
> //RAISE CS
> int i;
>
> // Port x Function Dir On/Off
> // mmcCS Out 0 - Active 1 - none Active
> // Dout Out 0 - off 1 - On -> init in SPI_Init
> // Din Inp 0 - off 1 - On -> init in SPI_Init
> // Clk Out - -> init in SPI_Init
> // mmcCD In 0 - card inserted
>
> // Init Port for MMC (default high)
> MMC_PxOUT |= MMC_SIMO + MMC_UCLK;
> MMC_PxDIR |= MMC_SIMO + MMC_UCLK;
> // Chip Select
> MMC_CS_PxOUT |= MMC_CS;
> MMC_CS_PxDIR |= MMC_CS;
>
> // Card Detect
> MMC_CD_PxDIR &= ~MMC_CD;
>
> // Init SPI Module
> halSPISetup();
>
> // Enable secondary function
> #if SPI_SER_INTF != SER_INTF_BITBANG
> MMC_PxSEL |= MMC_SIMO + MMC_SOMI + MMC_UCLK;
> #endif
>
> //initialization sequence on PowerUp
> CS_HIGH();
> -------------------
> And I am breaking on CS_HIGH();
>
>

_____________________________
 Free pdf download: Beginning Microcontrollers with the MSP430.


Re: Having trouble with SPI for SD Card - mastarre - May 30 18:07:23 2010

I have been trying to get SPI working to work with an SD card but have had no success after almost a full week. I've gotten so frustrated that I decided to try to back up a bit and use the simple examples provided by the TI website.

I used:

USART:
msp430xG46x_usart1_spi0_09.c

USCI:
msp430xG46x_uscia0_spi_09.c

Regardless of which one I run, the corresponding TXIFG flag is never set. According to the manual it should be set after SWRST with either USCI or USART however as I watch the register and step through it (or run it to a break point) it is always zero, never, ever, set.

As an example, using msp430xG46x_uscia0_spi_09.c (code below), if I break on any line beginning with P5OUT &= ~0x04; I find UCA0RXIE is set and if I let it proceed and break at _BIS_SR(LPM0_bits + GIE); UCA0TXBUF is filled with the correct byte however, no matter what, UCA0TXIFG is zero.
Why is it always zero???
Finally, as a double check, in the USCI example, the initial comments show `Slave reset <-|P5.2` . I was wondering how people are doing this as not only is P5.2 COM1 and not GPIO, it is also not accesible by a header and I am not sure how to connect any pin to slave reset anyhow. Could use some clarity on that as well..

Thank you in advance,

Mike


_____________________________
 Free pdf download: Beginning Microcontrollers with the MSP430.


Re: Having trouble with SPI for SD Card - mastarre - May 30 19:28:59 2010

Wow..

I upgraded my version of IAR for another project I was working on. This one switched to simulator for debugger. For whatever reason, SWT in simulator does not work.

Back to the board and the TXIFG is set. I can't believe it took me that long to figure it out. It is ALWAYS something small with uCs!

Now, to start actually trying to get the SD card to work.. hah

--- In m..., "mastarre" wrote:
>
> I have been trying to get SPI working to work with an SD card but have had no success after almost a full week. I've gotten so frustrated that I decided to try to back up a bit and use the simple examples provided by the TI website.
>
> I used:
>
> USART:
> msp430xG46x_usart1_spi0_09.c
>
> USCI:
> msp430xG46x_uscia0_spi_09.c
>
> Regardless of which one I run, the corresponding TXIFG flag is never set. According to the manual it should be set after SWRST with either USCI or USART however as I watch the register and step through it (or run it to a break point) it is always zero, never, ever, set.
>
> As an example, using msp430xG46x_uscia0_spi_09.c (code below), if I break on any line beginning with P5OUT &= ~0x04; I find UCA0RXIE is set and if I let it proceed and break at _BIS_SR(LPM0_bits + GIE); UCA0TXBUF is filled with the correct byte however, no matter what, UCA0TXIFG is zero.
> Why is it always zero???
> Finally, as a double check, in the USCI example, the initial comments show `Slave reset <-|P5.2` . I was wondering how people are doing this as not only is P5.2 COM1 and not GPIO, it is also not accesible by a header and I am not sure how to connect any pin to slave reset anyhow. Could use some clarity on that as well..
>
>
>
> Thank you in advance,
>
> Mike
>



Re: Having trouble with SPI for SD Card - mastarre - May 30 19:30:32 2010

Aaaaaaaaaaaaaaand it works perfectly. Wow.

--- In m..., "mastarre" wrote:
>
> I have been trying to get SPI working to work with an SD card but have had no success after almost a full week. I've gotten so frustrated that I decided to try to back up a bit and use the simple examples provided by the TI website.
>
> I used:
>
> USART:
> msp430xG46x_usart1_spi0_09.c
>
> USCI:
> msp430xG46x_uscia0_spi_09.c
>
> Regardless of which one I run, the corresponding TXIFG flag is never set. According to the manual it should be set after SWRST with either USCI or USART however as I watch the register and step through it (or run it to a break point) it is always zero, never, ever, set.
>
> As an example, using msp430xG46x_uscia0_spi_09.c (code below), if I break on any line beginning with P5OUT &= ~0x04; I find UCA0RXIE is set and if I let it proceed and break at _BIS_SR(LPM0_bits + GIE); UCA0TXBUF is filled with the correct byte however, no matter what, UCA0TXIFG is zero.
> Why is it always zero???
> Finally, as a double check, in the USCI example, the initial comments show `Slave reset <-|P5.2` . I was wondering how people are doing this as not only is P5.2 COM1 and not GPIO, it is also not accesible by a header and I am not sure how to connect any pin to slave reset anyhow. Could use some clarity on that as well..
>
>
>
> Thank you in advance,
>
> Mike
>


_____________________________
 Free pdf download: Beginning Microcontrollers with the MSP430.