CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

MicroSD question (SOLVED!)
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

MicroSD question (SOLVED!)
PostPosted: Tue Jan 29, 2013 6:03 pm     Reply with quote

Been trying to get this working for a while now... and it's close, but so far no joy.

CPU: PIC18F46J53
Compiler: PCWH 4.128
#include "mmcsd.c" - with changes for MBR suggested by andrewg.
#include <fat.c>
Hardware: MicroSD card socket, wired like this:

Pin 1: No connection
Pin 2: To PIC pin 2, RD4 (#define MMCSD_PIN_SELECT PIN_D4)
Pin 3: To PIC pin 40, RD2 (#define MMCSD_PIN_SDO PIN_D2)
Pin 4: 3.3V
Pin 5: To PIC pin 3, RD5 (#define MMCSD_PIN_SCL PIN_D5)
Pin 6: Ground
Pin 7: To PIC pin 41, RD3 (#define MMCSD_PIN_SDI PIN_D3)
Pin 8: No connection

I also have 10K pullup resistors to 3.3V on all four lines.

OK... so apparently the PIC can see the memory card. I tossed in calls to mmcsd_print_cid() and mmcsd_print_csd() and get this:

Code:
Init returned 0

Manufacturer ID: 02
OEM/Application ID: TM
OEM/Application ID: SD02G
Product Revision: 38
Serial Number: A6ACED8D
Manufacturer Date Code: 0084
CRC-7 Checksum: 2D


CSD_STRUCTURE: 00
TAAC: 2E
NSAC: 00
TRAN_SPEED: 32
CCC: 05B5
READ_BL_LEN: 0A
READ_BL_PARTIAL: 01
WRITE_BLK_MISALIGN: 00
READ_BLK_MISALIGN: 00
DSR_IMP: 00
C_SIZE: A7
VDD_R_CURR_MIN: 07
VDD_R_CURR_MAX: 07
VDD_W_CURR_MIN: 07
VDD_W_CURR_MAX: 07
C_SIZE_MULT: 07
ERASE_BLK_EN: 01
SECTOR_SIZE: 7F
WP_GRP_SIZE: 00
WP_GRP_ENABLE: 00
R2W_FACTOR: 05
WRITE_BL_LEN: 0A
WRITE_BL_PARTIAL: 00
FILE_FORMAT_GRP: 00
COPY: 00
PERM_WRITE_PROTECT: 00
TMP_WRITE_PROTECT: 00
FILE_FORMAT: 00
CRC: 91


I rolled most of ex_fat.c into my program so I would have a mini command shell to try various things. I formatted the card with FAT32 and put one directory (named 111) and a text file (named abc.txt) on it. I get no error messages other than what shows below:

Code:

/> dir

/> mkdir 222
Making directory '/222/': Error creating directory
(NOTE: This took about half a minute)

/> cd 111
Error changing directory

/> cd 222
Error changing directory

/> cat abc.txt
Error opening file

/> make test.txt
Making file '/test.txt': OK

/> append test.txt "hello world"
Appending 'hello world' to '/test.txt': Error opening file

/> dir

/>


I can also try formatting the card, which reports "OK" but doesn't really do anything. When I read the card with my Windows or Linux machine, it's unchanged.

What am I missing here? It feels like I'm close... but no cigar yet. And yeah, I'm sure it's a MicroSD and not SDHC... it's a 2GB card, smallest one I have.


Last edited by dbotkin on Sat Feb 02, 2013 2:04 pm; edited 1 time in total
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Jan 30, 2013 8:01 am     Reply with quote

What voltage is your PIC running? If it is 5V than you'll need some 'glue' logic to convert from / to the 3.3V for the SD card.

SD cards start with their data bus in Open Collector mode until the initialization to SPI mode databus has completed. Do you have a pull up resistor at the DO from the Mini SD card (pin 7, 10k will do).

What decoupling capacitors do you have at the SD card?

When writing data the power consumed by the SD card is a lot higher than when reading. Perhaps the 3.3V power supply can't cope with this power surge?
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Jan 30, 2013 9:11 am     Reply with quote

The 46J53, is a 3.3v PIC, so he should be OK on this one, unless he has copied circuits with a resistive divider to the card.

Other comment he has set the file system type in fat.c to FAT32?.

He says he has pullups on all four lines (essential on CS as well, since otherwise it can 'glitch select' when the unit is waking up).

Obvious comment card must be MicroSD, not MicroSDHC.

He seems very close, getting the ID etc..

Best Wishes
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Jan 30, 2013 9:19 am     Reply with quote

ckielstra wrote:
What voltage is your PIC running? If it is 5V than you'll need some 'glue' logic to convert from / to the 3.3V for the SD card.

Yes, as noted I'm not a student. ;) The entire board is 3.3V.

ckielstra wrote:
SD cards start with their data bus in Open Collector mode until the initialization to SPI mode databus has completed. Do you have a pull up resistor at the DO from the Mini SD card (pin 7, 10k will do).

Yes, 10K pullups on all four pins. The PIC has internal WPU on PORTD, but I put resistors in place just in case those were not sufficient.

ckielstra wrote:
What decoupling capacitors do you have at the SD card?

When writing data the power consumed by the SD card is a lot higher than when reading. Perhaps the 3.3V power supply can't cope with this power surge?

The 3.3V supply is coming from a 78L33 regulator, and the PIC is maybe drawing 20-25 mA at most. Nothing else on the board, and the power supply is via USB. There's a .1 uF decoupling cap but it could stand to be closer to the card -- the scope does show some noise but no serious sags in the supply voltage.

I set up a loop to just use mmcsd_write_byte() and mmcsd_read_byte() to see if the card is actually getting written to and read from. I used that to write data to the first 2048 bytes on the card -- it works. Everything writes and reads back as it should. I then plugged the card into my Linux machine and used dd to verify that the data was indeed written to the card, which wiped the partition table of course.

So... it seems I've narrowed this down to a FAT issue. And yes, FAT32 in fat.c.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Jan 30, 2013 9:54 am     Reply with quote

The weak pull-ups are not enough. The maximum specified is for SPI is 100K, and they don't switch on till the code says to do so. This can still give the CS glitch on boot. The external resistors are the way to go.
I'd triple check the mods you have done for MBR.
Also try FAT16, and see if anything changes.

I don't remember any specific problems around 4.128, though there did seem to be some oddities with some chips around then. Not a version I've 'kept' so can't try to see if it works.

Best Wishes
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Jan 30, 2013 3:15 pm     Reply with quote

Progress...

Between andrewg's fixes to fat.c (and using my LOCAL copy with those changes applied, instead of the original from CCS), and finding a format that it likes, I'm able to do most of the things I need to. fat_init() works, and with the routines from ex_fat.c I can see the directory, tail a file, etc. From my program I can use fatread() to fill a buffer. There are some unexplained delays I need to chase down, but I'm almost there.
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Jan 30, 2013 3:48 pm     Reply with quote

Now all I need to do is figure out how to make this all work with #pin_select, SPI2 and FORCE_HW. I can read a file... but slowly, around 3K byte/sec. Ugh. I need about 4x that speed at minumum, preferably 10x.

Back to the grind... sigh.
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Jan 30, 2013 4:30 pm     Reply with quote

dbotkin wrote:
Now all I need to do is figure out how to make this all work with #pin_select, SPI2 and FORCE_HW. I can read a file... but slowly, around 3K byte/sec. Ugh. I need about 4x that speed at minumum, preferably 10x.

Back to the grind... sigh.


Check the speed you are running the SPI bus at.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Jan 30, 2013 5:25 pm     Reply with quote

And how would you suggest I change that? Looking at #use_spi...
Quote:
BAUD=n
Target bits per second, default is as fast as possible.

CLOCK_HIGH=n
High time of clock in us (not needed if BAUD= is used). (default=0)

CLOCK_LOW=n
Low time of clock in us (not needed if BAUD= is used). (default=0)

I tried setting BAUD to some different settings... none seemed to have a big impact.

No BAUD setting: 13 seconds to read a 41K file.
BAUD=1000000 -- Slower. 16 seconds for the same file.
BAUD=4000000 -- No change, same 16 seconds to read the file.
BAUD=8000000 -- Looks like 15 seconds.
BAUD=12000000 -- Won't read the card.

If I were using hardware SPI, I'd know for sure what the clock rate is. As it is I'm left wondering if this is a data transfer rate issue, or just atrocious delays in mmscd.c and fat.c.
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Jan 31, 2013 11:58 pm     Reply with quote

OK, so a little more digging into mmcsd.c... not the one I had, but a new one Darren emailed me. Thanks, Darren!

mmcsd.c sets the baud to 400000 during mmcsd_init(). Darren's sets it to a more realistic speed, IF you're using the MSSP hardware. He also thoughtfully included some new code to make it easy to specify the MSSP hardware SPI. So... great.

Unfortunately, it still fails to detect the card any time I specify the hardware SPI. Software works great... hardware no. MOSI looks normal, but not CS or CLK. And of course without that, there's no MISO... and no love from the SD card.

I tried setting BAUD to several values far higher than the 400K to which it's initially set with the software SPI. No dice. The improvement in transfer rate is very slight. While waiting on more from CCS support, I'm continuing to look for any mistakes in my own code.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Feb 01, 2013 6:20 am     Reply with quote

I don't have your v4.128, but early versions of the mmcsd.c contained a bug where the SPI was initialized in a wrong SPI mode (mode 2). SD cards only work in mode 0 or 3.
In V4.138 the setup is correct:
Code:
#use spi(MASTER, DI=MMCSD_PIN_SDI, DO=MMCSD_PIN_SDO, CLK=MMCSD_PIN_SCL, BITS=8, MSB_FIRST, MODE=0, stream=mmcsd_spi)


Quote:
mmcsd.c sets the baud to 400000 during mmcsd_init().
In the first MMC standard it was defined compulsory for the host device to start up with about 80 clock pulses at 400kHz. So CCS is correct here. Perhaps this requirement was dropped in newer versions of the standard but it's your risk to remove this. Only the slow start up is required, after that you can go full speed.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Fri Feb 01, 2013 8:05 am     Reply with quote

It's still there in the spec for SPI mode.

SPI mode itself is now 'optional' for MicroSD, _but_ since the cards all generally use variants of the same chipsets used for SD ((where it is still required), I've yet to see a card that doesn't have it.

It also raises a question, since how could a MicroSD card then work in an adapter to SD, where this mode is required....

Best Wishes
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Feb 01, 2013 8:25 am     Reply with quote

ckielstra wrote:
In the first MMC standard it was defined compulsory for the host device to start up with about 80 clock pulses at 400kHz. So CCS is correct here. Perhaps this requirement was dropped in newer versions of the standard but it's your risk to remove this. Only the slow start up is required, after that you can go full speed.

The new change to mmcsd.c only changes the speed after the startup, for that reason. After that it switches the clock to Fosc with a divisor (depending on the clock frequency) instead of using a timer for the clock. I don't know if this driver file is something CCS has released with newer compiler versions, or if it's just a modification Darren made.
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

Frustrating.
PostPosted: Fri Feb 01, 2013 7:15 pm     Reply with quote

OK, so we've pared this down to the bare minimum. Maybe someone here can see something that explains what we're not getting.

When this code is run, I get positive-going pulses on the chip select pin (PIN_D4) -- and nothing else. No SPI clock or data. It's as if the SPI2 module isn't even there. I've been through the .LST file and everything looks OK to me -- PPS seems to be getting set up correctly, SPI2 initialized, data getting stuffed into the SPI2 buffer. But I get nada on the actual device pins. It's enough to make me think about getting out the heat gun and replacing the chip.

Code:
#include <main.h>
#include "usb_bootloader.h"

#pin_select SDO2=PIN_D2
#pin_select SDI2=PIN_D3
#pin_select SCK2=PIN_D5
#pin_select SCK2IN=PIN_D5  // Per data sheet, page 296.  Also tried without this.

#define MMCSD_PIN_SELECT    PIN_D4

#use spi(SPI2, MASTER, bits=8, mode=0, ENABLE=MMCSD_PIN_SELECT, ENABLE_ACTIVE=1)

void main(void)
{

   output_drive(PIN_D5);
   output_drive(PIN_D2);
   output_float(PIN_D3);
   output_low(MMCSD_PIN_SELECT);
   setup_spi2(spi_master |spi_l_to_h |spi_clk_div_4);
   
   while(TRUE)
   {
      spi_xfer(0x55);
      delay_ms(5);
   }
}

Code:
.................... #pin_select SDO2=PIN_D2
.................... #pin_select SDI2=PIN_D3
.................... #pin_select SCK2=PIN_D5
.................... #pin_select SCK2IN=PIN_D5
.................... 
.................... #define MMCSD_PIN_SELECT    PIN_D4
.................... 
.................... #use spi(SPI2, MASTER, bits=8, mode=0, ENABLE=MMCSD_PIN_SELECT, ENABLE_ACTIVE=1)
*
01C08:  BCF    F95.4
01C0A:  BSF    F8C.4
01C0C:  MOVF   F75,W
01C0E:  MOVFF  05,F75
01C12:  RRCF   F73,W
01C14:  BNC   1C12
01C16:  MOVFF  F75,01
01C1A:  BCF    F95.4
01C1C:  BCF    F8C.4
01C1E:  GOTO   1CC2 (RETURN)
.................... 
.................... void main(void)
.................... {
*
01C4C:  CLRF   FF8
01C4E:  BCF    FD0.7
01C50:  MOVLB  E
01C52:  MOVLW  55
01C54:  MOVWF  FA7
01C56:  MOVLW  AA
01C58:  MOVWF  FA7
01C5A:  BCF    xBF.0
01C5C:  MOVLW  14
01C5E:  MOVWF  xFC
01C60:  MOVLW  16
01C62:  MOVWF  xFD
01C64:  MOVLW  0A
01C66:  MOVWF  xD3
01C68:  MOVLW  0B
01C6A:  MOVWF  xD6
01C6C:  MOVLW  55
01C6E:  MOVWF  FA7
01C70:  MOVLW  AA
01C72:  MOVWF  FA7
01C74:  BSF    xBF.0
01C76:  CLRF   FEA
01C78:  CLRF   FE9
01C7A:  BCF    F72.5
01C7C:  MOVLW  22
01C7E:  MOVWF  F72
01C80:  MOVLW  40
01C82:  MOVWF  F73
01C84:  BCF    F95.4
01C86:  BCF    F95.4
01C88:  BSF    F8C.4
01C8A:  MOVLB  1
01C8C:  CLRF   x88
01C8E:  MOVLW  FF
01C90:  MOVLB  F
01C92:  MOVWF  x48
01C94:  BCF    FC2.6
01C96:  BCF    FC2.7
01C98:  MOVF   x49,W
01C9A:  ANDLW  E0
01C9C:  IORLW  1F
01C9E:  MOVWF  x49
01CA0:  CLRF   x25
01CA2:  CLRF   FD1
01CA4:  CLRF   FD2
.................... 
....................    output_drive(PIN_D5);
01CA6:  BCF    F95.5
....................    output_drive(PIN_D2);
01CA8:  BCF    F95.2
....................    output_float(PIN_D3);
01CAA:  BSF    F95.3
....................    output_low(MMCSD_PIN_SELECT);
01CAC:  BCF    F95.4
01CAE:  BCF    F8C.4
....................    setup_spi2(spi_master |spi_l_to_h |spi_clk_div_4);
01CB0:  BCF    F72.5
01CB2:  MOVLW  20
01CB4:  MOVWF  F72
01CB6:  MOVLW  00
01CB8:  MOVWF  F73
....................     
....................    while(TRUE)
....................    {
....................       spi_xfer(0x55);
01CBA:  MOVLW  55
01CBC:  MOVWF  05
01CBE:  MOVLB  0
01CC0:  BRA    1C08
....................       delay_ms(5);
01CC2:  MOVLW  05
01CC4:  MOVWF  05
01CC6:  BRA    1C22
....................    }
01CC8:  MOVLB  F
01CCA:  BRA    1CBA
.................... }
.................... 
01CCC:  SLEEP

Configuration Fuses:
   Word  1: F7BE   NOWDT PLL1 NOPLLEN STVREN NOXINST NODEBUG NOCPUDIV NOPROTECT
   Word  2: F71A   INTRC_PLL_IO SOSC_HIGH NOCLOCKOUT NOFCMEN NOIESO WDT128
   Word  3: FAF3   DSWDTOSC_INT RTCOSC_T1 NODSBOR NODSWDT DSWDT2147483648 NOIOL1WAY ADC10 MSSPMSK7
   Word  4: FBFF   WPFP NOWPCFG WPDIS WPEND LS48MHZ
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sat Feb 02, 2013 2:48 am     Reply with quote

You are using SPI streams, and then _not_ using these for the transfer.
You need to use:

SPI_XFER(SPI2,0x55);

Then, get rid of the setup_spi2.
There are two distinct ways of using SPI with CCS. #use spi with spi_xfer, and streams, or setup_spix with spi_write/spi_read (no streams). You need to use one or the other, not both.

Your #use spi, needs to select SPI2 and the correct format.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group