[TUT] [C] Getting SD/MMC card working painlessly with FatFS

Go To Last Post
355 posts / 0 new

Pages

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, sorry, of course. I was the one who was confused. Well, as for the proto board, mine was spread out over several centimeters of free-hanging wire, with no attempt whatsoever to shield. I didn't have any problems running SPI at the maximum transmission speed of the processor, which I guess was around 2MHz.

Some SD card libraries start off by communicating with the SD card at the lowest speed possible, and then incrementally ratchet up the speed until the maximum stable speed is found. Have you thought about something similar?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi gang,

been scratching my head for a couple of days now, trying to get communications up and running with a SD Card using this tutorial.

What I've done so far is adapting the FatFS AVR example to a AtMega128 chip (Mainly - 128 use different pins on PORTB for SPI communications than the 64.) The code compiled successfully.

I've also connected the SD Card via a SD Card holder soldered to the correct pins on the AtMega128 (using a STK 600 btw). I've triple and quadroupled checked the pins - they are exactly like the start of this tutorial.

Now, firing up the 128, I get the welcome message via the RS 232 interface - I type di 0, and get a RC = 1 response. This seems to indicate that the card is initialized, correct? Then I run fi 0 and get a RC=0 FR_OK. So, the file system is initialized, if I understand the code correctly?

However, running fl, fi, any file read, directory read and other such commands yields me a rc = 1 FR_NOT_READY or rc=11 FR_NO_FILESYSTEM error. I've tried the format command fm, and this will be running for several minutes, until it quits with a FR_NOT_READY or similar error somehwere in the middle of the formatting process( I assume).

I've tested two different cars (1GB and 2 GB from Kingston), and they both work flawlessly when read from a computer - I've even tried the Panasonic SD-Card Format program to ensure that the cards are properly formatted.

Any suggestions/hints would be most welcome.

Thanks in advance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not sure, as I don't really remember how the original code is written and don't have it before me, but you can the only 0 means success. So if you're getting a RC = 1 for the disk initialize, then things aren't quite right on the disk.

I can confirm from personal experience that FatFS will return a "file system initialized" when the disk fails to initialize. So not quite sure what your problem here is, but if my experience is any indication, it's the SPI bus that's not configured correctly.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the response - I'm going to have a gander at the SPI codes, make sure everything is right. What clock speed are you using for your project, I've adapted the code to run a F_clk of 8MHz - but I might running your original speed to see if I've done a error somewehere.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sounds familiar. I could only get disk_initialize() to work by slowing down the SPI, still can't run at full speed.

You might have to add

#include  
#include "xitoa.h"
DSTATUS disk_initialize(BYTE drv) // Physical drive nmuber (0)
{
	BYTE n = 0;
   BYTE cmd = 0;
   BYTE ty = 0;
   BYTE ocr[4] = {0};


   if(drv)
   {
      return STA_NOINIT; /* supports only single drive */
   }
	
   if(Stat & STA_NODISK)
   {
      return Stat; /* no card in the socket */
   }
   
   power_on();	/* force socket power on */

// set SPI speed lower until it works, F_CPU/32 = 115kHz with a 3.6864MHz xtal
   SPSR |= (1<<SPI2X);
   SPCR |= (1<<SPR1);

	for(n = 10; n; n--)
   {
      rcvr_spi();	/* 80 dummy clocks */
   }
   
	ty = 0;
   
   if(send_cmd(CMD0, 0) == 1) // enter Idle state
   { 	
      Timer1 = 100; // initialisation timeout of 1000 msec
		
      if(send_cmd(CMD8, 0x1AA) == 1) // SDHC
      {	
         for(n = 0; n < 4; n++)
         {
            ocr[n] = rcvr_spi(); // get trailing return value of R7 resp
         }

         if(ocr[2] == 0x01 && ocr[3] == 0xAA) // card can work at Vdd range of 2.7-3.6V
         {
            while(Timer1 && send_cmd(ACMD41, 1UL << 30)) // wait for leaving idle state (ACMD41 with HCS bit)
               {;}

            if(Timer1 && send_cmd(CMD58, 0) == 0) // check CCS bit in the OCR
            {
               for (n = 0; n < 4; n++)
               {
                  ocr[n] = rcvr_spi();
               }
   
               ty = (ocr[0] & 0x40) ? 12 : 4;
            }
         }
      }
      else // SDSC or MMC
      {							
         if(send_cmd(ACMD41, 0) <= 1)
         {
            ty = 2;
            cmd = ACMD41; // SDSC
			}
         else
         {
            ty = 1;
            cmd = CMD1; // MMC 
			}

         while (Timer1 && send_cmd(cmd, 0)) // wait for leaving idle state
            {;}
            
         if(!Timer1 || send_cmd(CMD16, 512) != 0)	// set R/W block length to 512
         {
            ty = 0;
         }   
      }
   }
   else
   {
      xputs(PSTR("\nYou failed to talk to the disc\n")); 
   }
 
// set SPI speed back to F_CPU/4 = 912.6KHz with a 3.6864MHz xtal
//   SPSR &= ~(1<<SPI2X);
//   SPCR &= ~(1<<SPR1);
  
   CardType = ty;
   release_spi();

   if(ty) // initialisation succeded
   {
      Stat &= ~STA_NOINIT;		/* Clear STA_NOINIT */
   }
   else // initialisation failed
   {			
      xputs(PSTR("\nYou failed to initialise the disc\n"));
      
      power_off();
   }

   return Stat;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

krifos wrote:
Thanks for the response - I'm going to have a gander at the SPI codes, make sure everything is right. What clock speed are you using for your project, I've adapted the code to run a F_clk of 8MHz - but I might running your original speed to see if I've done a error somewehere.

I'm running with the internal oscillator at 8Mhz, just as I guess you are. My thoughts are to try the code that davef posted and see if it works.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the responses. The code davef provided did indeed help - I've now been able to properly initialize the card, and even read the disk status. Altough I have more work to do on tweaking the SPI timings, as initialiation is still flaky, I usually have to try a couple of times before it will work - and I still cant get the fl or fs commands to return anything but various errors.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And you do have the voltage divider resistors or something like that between the SD card and the MCU?

Or are you running the MCU on 3.3V?

So.. Has anyone got the ATMega128 working with this at full speed (XTAL 20MHz)?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I finally got the time to fully test this..

Works without any modifications on ATMega128, BUT I cannot make any sense of the UART when running at full speed. On 8MHz it works ok, though.

Well.. Good enough for me! Time to write a program! :D

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JussiS wrote:
And you do have the voltage divider resistors or something like that between the SD card and the MCU?

Or are you running the MCU on 3.3V?

Running the MCU at 3.3V, yes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, I was reading this post and I got the FatFS module working at a MC56F8013 CPU (freescale). I made a routine to write a txt for a datalogger, but it was taking some minutes to write a file. So I increased the SPI CLK frequency (that was at 250kHz, because initialization of the Card) and functions like f_open, f_write and f_read work, but f_sync always returns FR_RW_ERROR at this clock speed.
When I put CLK at 250kHz f_sync works perfectly.
Anyone got this module working and writing files and got this problem or can help me?

Thx a lot!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok.. I have another problem.

I have several 512MB cards and if I use them, the system either refuses to even open a file or then just reboots.

I do also have a 32MB card, with which the system runs OK.

I've tried several options here.. Reduced the written buffer size, tried different initialize options etc. nothing works! Only the 32MB card functions!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've had similar experiences with cards. My 2GB cards work fine, but a 512MB didn't. No idea why, nor how to fix it. I've tried multiple SD programs from different authors and a card has either worked with all of them, or none.

If anyone ever comes across the answer, I'd love to see it. In between time, since a 2GB card costs $2 at the local supermarket, for all practical purposes the problem can just be worked around.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well.. I'm glad to hear that at least someone has got bigger cards working. I was already looking for obsolete, below 128MB cards. :D I'll give the local shop a call and try bigger ones.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have been trying to fix this for weeks now, I sure hope some one out thier may have the answer. The process is as follows:
Open file, write data to it, then close it.
When I open it again, it will not write to it, send_cmd fn return error code 0xff.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can we assume if you leave the file open you can repetitively write to it?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not sure what EsanAcc wants to say, but, yes, you can repetitively write to an open file. If you're going to do that, don't forget to do an f_sync() periodically, or otherwise the data won't be saved. In my logging application, I did an f_sync() after every write.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kubark42,

I was wondering if he was able do that! Maybe, it would be useful information for someone who understands FatFS better to suggest a solution for him.

Following someone's excellent example I am doing a f_sync after each write!

The reason I am interested in this issue is that it was suggested to me that I should close the file after each write and then open it before the next write. The recommendation was based on concerns about corrupting an open file while the uP was off doing other work. However, I haven't seen a problem for the last 2-3months leaving the file open for weeks at a time.

Thanks again for providing enough information for guys like me to get a SD card file system working on their favourite uP.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi

Someone has already used f_lseek to do cluster pre-allocations like ELM Chan says in his page?
I am trying to do so, just like the code we can find at http://elm-chan.org/fsw/ff/en/ls..., but the file doesn't get any longer.

I am having problems on creating big files, it goes writing data, but suddenly it stops and f_write only gives me FR_RW_ERROR, and it is always on cluster change.

Someone could help me?

Tks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PLUS:

I am creating a new file:
f_open(&file,FileName[0],FA_CREATE_NEW | FA_WRITE)
f_lseek(&file,12582912) //allocates 12MB

I´m looking to the "file" variable (FIL type) that gives the fsize and fptr

When I do the f_lseek fptr don't go to those 12582912 bytes, it goes to around 520000, and fsize is still 0 bytes.

Hows can I fix this? If I need to use f_truncate, please tell me how. This can be some problems with SPI clock?

Tks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You seem to misunderstand fundamental file access programming (maybe try writing some file programs using the POSIX routines in Windows or Linux first to get the hang of it?). An fopen() and an fseek() does nothing more than move the read pointer in an open file. Try following it with an fputc() to actually write a byte at the offset and then fclose().

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Tks for the answer.

But I can write data in the card. I already created some files, and actualy saw the fsize rising, then checking at windows.

I'm having this trouble with the size of the file. I don´t know why, but at some point the system broke and f_write only give me FR_RW_ERROR. I try to remount, re-open, sync, re-write, and nothing, just some bytes are sent. What I could find out is that this error happens near cluster changes and reading the FAT table I see that more the last cluster is already signed as "last of chain (0xFFFF).

So, as I am using Chan's library, I´m trying to use the pre-allocation that he explain, and he uses f_lseek(). He says: "[...]When an offset above the file size is specified in write mode, the file size is extended to the offset and the data in the extended area is undefined[...]"

Need some more help.

Tks a lot.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys!

Please, see if this info helps:

I started logging again and at some point it stopped, one f_write() returned FR_RW_ERROR. I used read_disk() to read 3 FAT TABLE sectors (8,9,10) and the first ROOT SECTOR(488)

What I found out

a) My file starts at cluster #257 (that's because there was another LOG file at the card)
b) This cluster is pointed at the 2nd sector of the FAT Table (sector 9).
c) The cluster chain goes perfectly (cluster 257 points to 258 (0x0102) etc ), until it reaches the end
of that sector
d) Still reading sector 9, I see that cluster #510 points to cluster #511, but #511 DOES NOT points to next cluster it signals END OF FILE (0xFFFF)
e) f_write() returns also the ByteWritten variable, verifying it I see that it could only write the bytes that completes the last sector (90).
f) I was sending 183 bytes, the file would have to go to 522,333 bytes. But due to the error it "wrote" 90 bytes, fsize was 522,150 (because it could not write) and fptr 522,240 which is the size of the allocation (and of cluster)
g) Looking the properties of the file at windows explorer, I see that: Size 522,150 and Size on disc is 522,240.

I don´t know what else to do. Hope u could provide me some answers.

Tks a lot for everything!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sorry for the confusion. The aplication would open a file and wirte data to at the user's desire. When done, the application should close the file,but it don't have to. Here are some notes about FatFs.
- f_sync is called from within f_close fn to insure data are not lost.
- I use a function called, fprintf that is wrap around function of f_puts that calls fputc that calls f_write fn.
- when calling f_write fn, it does not necessary means, it would be written to sd card. f_write function saves data to the open file buffer (512 bytes).
- To ensure data are written to sd card, f_sync must calles. f_sync calls disk_write that writes data to sd with two steps:
1- send write command via send_cmd(CMD24,sector) fn
2- send data to be written via xmit_datablock(buffer,0xfe) fn.
so here is what happens,
- I open the file,
f_open(&RFile,"/rec.xls,FA_WRITE | FA_OPEN_ALWAYS)
- I write data with fprintf as such
fprintf(&RFile,"%s",strcd);
--
--
up to 512 bytes

when done

- I call f_close as such: f_close(&RFile);
note f_close function calls for f_sync(fp)

now so far data are writen correctly to file and file closed successfully.

Now when this file is opened the second time and process is repeated, the process fails at disk_write function. In particular when send_cmd(CMD24,sector) is called, it returns 0xff. it should return 0. When 0xff is returned, the function abort writing to disk and flag that file as FA_ERROR.
One more note, I am using 1GB micro SD from Kingston.
I would like to thank davef and kubark42 for thier comments.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Everybody.

I was debuging my code again, but this time I set some breakpoints inside f_write() and move_window() functions to see what is happening.

The problem my f_write() returns FR_RW_ERROR happens when FatFS calls disk_read() inside move_window(sect) (that was called by f_write() fc).

Inside move_window() there is this code:

if (sector) {
	Stat=disk_read(0, fs->win, sector, 1);
	if (Stat != RES_OK)
		return FALSE_Value;
	fs->winsect = sector;
}

So move_window() returns FALSE_Value (0).

And in f_write()

if (!move_window(sect)) /* Move sector window */
  goto fw_error;
[...]
fw_error:/* Abort this file due to an unrecoverable error */
	fp->flag |= FA__ERROR;
	return FR_RW_ERROR;

We can assume that the problem is in the implementation of the disk_read() function??
Like the card isn´t prepared yet to send data, is busy, something like that?

The f_sync() calls the move_window() as well and many times it returns FR_RW_ERROR, but the program continues to write bytes on my file.

I would appreciate a lot if u could provide me some answers.

Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JussiS wrote:
ok.. I have another problem.

I have several 512MB cards and if I use them, the system either refuses to even open a file or then just reboots.

I do also have a 32MB card, with which the system runs OK.

I've tried several options here.. Reduced the written buffer size, tried different initialize options etc. nothing works! Only the 32MB card functions!

You might try reformatting the cards (on your PC) that don't work to fat32 or fat16 --- lots and lots of cards are formatted with ntfs -- which is not a fat based file system so won't be recognized.

LEs

next time for shure.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ajpinotti wrote:
We can assume that the problem is in the implementation of the disk_read() function??
Like the card isn´t prepared yet to send data, is busy, something like that?

The f_sync() calls the move_window() as well and many times it returns FR_RW_ERROR, but the program continues to write bytes on my file.

I would love to help you, but, honestly, I'm as lost as you are. I had problems with FatFS keeping up with my write speeds (I write a full buffer 3-5 times per second), so I in a sense abandoned the full functionality in favor of some reduced, but more efficient code.

It is entirely possible that move_window is borked. I don't know exactly what it should do, nor how it should do it. Maybe you can set up debugging so when you get an error, you immediately repeat the write/read process in order to see if asking a second time helps? What's important is that you're getting data back from the SD card, even if it's not the data you want in the style you expect it. If you get data back, then you can fix the problem yourself by looking at the specs. That's how I did things for the SD Bootloader tutorial I wrote.

Another idea occurs to me (sort of like what we used to tell people at Lexmark: "If your printer doesn't work, reinstall the drivers.") is to suggest running at a slower speed.

Keep trying to debug it and report back here. You might even try contacting the original author, or, even better, going to the BBS channel, http://elm-chan.org/bbs/?lang=en. Not as elegant as avrfreaks, of course, but if it works? (And if you HATE the stupid white on black contrast the way I do, add this to your bookmark bar and load the "bookmark" when you're on those kind of websites:

javascript:(function(){var%20newSS,%20styles='*%20{%20background:%20white%20
!%20important;%20color:%20black%20!important%20}%20:
link,%20:link%20*%20{%20color:%20#0000EE%20!important
%20}%20:visited,%20:visited%20*%20{%20color:%20#551A8B%20
!important%20}';%20if(document.createStyleSheet)%20
{%20document.createStyleSheet(%22javascript:'%22+
styles+%22'%22);%20}%20else%20{%20newSS=
document.createElement('link');%20newSS.rel='stylesheet'
;%20newSS.href='data:text/css,'+escape(styles);
%20document.getElementsByTagName(%22head%22)[0].appendChild(newSS);%20}%20})();

NOTE: this should all be on one line, but it really wreaks havoc with phpBB's formatting [makes the webpage monde characters wide], so I put some newlines in.)

Cheers,
Kenn

Last Edited: Wed. Mar 4, 2009 - 10:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

EsanAcc wrote:
Now when this file is opened the second time and process is repeated, the process fails at disk_write function. In particular when send_cmd(CMD24,sector) is called, it returns 0xff. it should return 0. When 0xff is returned, the function abort writing to disk and flag that file as FA_ERROR.
One more note, I am using 1GB micro SD from Kingston.
I would like to thank davef and kubark42 for thier comments.

I saw you got an answer on ELM's BB. Did it work?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kubark42 thanks for asking. I have deleted the following line from f_sync function:
dir[DIR_Attr] |=AM_ARC; //set archive bit
also made sure, the file is not archived by Windows
(right click the file, select properties, unchecked archive)
Though this may not make sense, but it did help. I may have to deal with this issue again....

its has been extremly hard to debug this FatFs firmware. The main issue here when the code encounter a problem with the file setup, it exit the function and aband the process, it does not deal with the issue, in other word their is no error handler. I am learning about this code every day;
Regards
:cry:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

EsanAcc wrote:
its has been extremly hard to debug this FatFs firmware. The main issue here when the code encounter a problem with the file setup, it exit the function and aband the process, it does not deal with the issue, in other word their is no error handler. I am learning about this code every day;

Yes, that is pretty common of FatFS. I guess error handling is all about how much space you have to spare for it. FatFS already takes up a monstrous amount of space compared to what is available in the Atmel DIP packages. Error, checking, however, would come in handy. Hve you considered making a fork?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This

static
BYTE rcvr_spi (void)
{
  SPDR = 0xFF;
  loop_until_bit_is_set(SPSR, SPIF);
  return SPDR;
}

(mmc.c)
is not working if I don't write

PORTB |= (1<<DDB6); // <- power_on

or, if you prefer,

#define DD_MISO DDB6
PORTB |= (1<<DD_MISO); // <- power_on

Am I right?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wouldn't that just be taking the port to HI, instead of turning it into an output? Or is that not what you meant?

In any case, I'm not sure that having it as an output is necessary. I don't quite remember right now, but I can check Monday when I'm back in front of the code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm trying the same FatFS driver, but i will only read files and put them to glcd. I'm running AtMega64 @16MHz what changes are required? my schematic is in attachment

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not sure we can help you with that kind of question. It's quite vague, and doesn't even pose a problem to be solved. Furthermore, your schematic doesn't show an ATMega at all, so I wonder if you've posted the right.

I suggest you rethink your questions and schematic, and be very clear. I'd love to help you, but I'm not a mind reader.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kubark42 wrote:
I'm not sure we can help you with that kind of question. It's quite vague, and doesn't even pose a problem to be solved. Furthermore, your schematic doesn't show an ATMega at all, so I wonder if you've posted the right.

I suggest you rethink your questions and schematic, and be very clear. I'd love to help you, but I'm not a mind reader.

Oh sorry i did a mistake i posteted only connection of the SD card socket. here is the mcu schematic with the lines. PortA and PortC is reserved for display, PortD is reserved for buttons and some diodes. and the problem which changes in the code are requied to comunicate with the SD card when i'm using 16MHz crystal and i will do some read options with keys connected to atmega, write it to my display and disuse uart (nothing goes via uart)

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think any changes should be required when communicating at 16MHz. You _might_ have a speed problem, as you're approaching 25MHz, which I've heard is the maximum speed for the SPI connection to the SD card. Even if you do, though, the solution is simple: slow down the SPI bus by writing the right bit to the register. I suggest you do some read/write tests and see if everything is okay. If it's not, slow it down, and if it is... perfect!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi kubark42 I am a newbie to AVR and C so sorry if my question sounds unreasonable! First of all thanks for the tutorial that you've written. I have modified the code according to my AVR162 but I don't really know which PORT/PINs are used for uSD function (I will need other pins for other functions). I tried reading the code from ffsample.zip but I couldn't understand the port assignments. I understand that 1 is output and 0 is input but can you please list down the pins that is used, for example:

MOSI, MISO, SCK, OC0 etc. Or a schemnatic of your circuit will do. MANY THANKS!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, there's really no schematic to be made. In fact, there's no choice of pins to be made. You don't have a choice. You must hook up the ATMega's MISO (Master In/Slave Out) pin to the SD's data out, the MOSI (Master Out/Slave In) to the SD's data in, the SCLK (system clock) to the SD's system clock, and then (take a deep breath) designate another pin, ANY other pin, as the CS (chip select) pin. The other SD pins are all unnecessary, with the obvious exception of the power and ground pins.

The exact pins used by SPI, i.e MOSI, MISO, and SCLK, are detailed in the documentation of whatever chip you're using. Best of luck.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the reply :)
Just wondering, you stated that your pinout is CS --SS (PC1) in the fist tutorial. I had a look at the pin configuration of your uC and I am slightly confused. Did you mean !SS pin on AVR or ANY other pin (eg. PC1) as you just said?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I meant not to use SS, but if you read through the thread, you'll see that others have a diametrically opposed opinion. You just have to be more careful if you use SS not to make a stupid coding mistake that will cost you hours of frustration tracking down two months into the project. Ask me how I know. ;) That being said, SS is actually sort of foreseen for exactly that purpose, so it's up to you. In any case, the chip select is nothing more nor less than a pin that controls if the peripheral is listening. If the peripheral has a HI at its chip select, it ignores everything. If it has a LO, it listens and responds (if appropriate). So you can use any pin in the entire world that you like.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But the key thing about SS when SPI is being used is that even if you don't use it the pin should either be tied high or set as an output and driven. If left as a (floating) input then if it gets pulled low the master switches to become a slave and disaster ensues.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you, Cliff, that's a good point.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Alright thank you guys! I will opt for normal pin and tie !SS high. Cheers! :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks
first login the abroad websit!
the avrfreaks is good!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ken - Thanks for a GREAT tutorial!

I have loaded this into a Mega644 just like yours and am successfully reading my 4Meg SDHC Card. So that much works. BTW, I have used the /SS pin (PB4) as part of my SPI protocol. Works fine.

Now a couple of questions.

First, regarding the changes in Main.c. Why do you comment out the sei() instruction? That appears to leave the interrupts off and the timer will never run. If I try running the program without a card in the socket, it just hangs! If I put sei() back in, then I get a time out like I'd expect. Am I missing something?

Nother question: While I'm reading my 4M SDHC just fine, I can't access my 2M SD card. (It reads just fine on my PC.) Could this be because it has 1024 byte block length?? Is there a utility to force a smaller block size on the 2M card? Is there a way to postively determine the block size?

Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

doctek wrote:
First, regarding the changes in Main.c. Why do you comment out the sei() instruction? That appears to leave the interrupts off and the timer will never run. If I try running the program without a card in the socket, it just hangs! If I put sei() back in, then I get a time out like I'd expect. Am I missing something?

Well, disabling the sei() instruction certainly has the downside that the program doesn't behave the way it should with regard to the timeout, but that's the trade-off I made for simplicity's sake. In the tutorial, it's important that you level the playing field as much as possible. With sei() turned off, when someone asks a question I know that it's never because of some random interrupt that's causing a problem.

That being said, my loggigg program has interrupts, and lots of them. It works just fine, but that's clearly because the interrupts are neither long enough, nor often enough to perturb the read/write process. Your mileage may vary.

Quote:
Nother question: While I'm reading my 4M SDHC just fine, I can't access my 2M SD card. (It reads just fine on my PC.) Could this be because it has 1024 byte block length?? Is there a utility to force a smaller block size on the 2M card? Is there a way to postively determine the block size?

It seems logical to me that 1024 byte blocks cause problems, as most of the time you're reading/writing in 512 byte blocks, but without looking through the code I can't swear by it. However, one thing is for certain and that's that if the read/write buffers are limited to 512 bytes, there ain't no way in hay-yell that 1024 byte block operations will work successfully.

As for forcing smaller block sizes, I have no idea. I think I'll have to pass the buck on this one to some of our more knowledgeable members.

Glad you enjoyed the tutorial and it worked out for you. Cheers!

Last Edited: Wed. Mar 25, 2009 - 11:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Could this be because it has 1024 byte block length??

Are you sure - can you dump the boot/BPB sector? - it's very unusual if it hasn't got 512 byte blocks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks to kubark42 (Ken) and clawson for your responses. I am completely lost about why my 2G SD card won't work, so thanks for any insights.

Here's the source of my confusion about the block size > 512 bytes.
http://en.wikipedia.org/wiki/Sec...
have a look at the sections titled Compatibility issues with 2 GB and larger cards and SD (non-SDHC) cards with greater than 1 GB capacity. Are Block size and Sector size the same thing? I'll be glad to post the Master Blocks (Sector 0? is that right?), if I can manage to add the figures. I've used Winhex to read them.

Again, thanks for the help. Since several others seem to have had problems with certain SD cards, I'd like to get to the bottom of this.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The BPB data is in the first of those two pictures. The key field is the int16 at offset 0x0B/0x0C which has the value 0x200 - this is "bytes per sector" and is the fairly standard value of 512.

The next byte (offset 0x0D) is the sectors per cluster - this is set to 0x40 - 64. So there are 32K clusters on the disk

Offset 0x0E/0x0F is interesting as this is the "reserved sectors" and is set to 0x186c so there's a LOT (6,252) of wasted sectors between the BPB and the first FAT

Offset 0x10 shows there are two FATs (as expected)

At 0x20 we're told that there are 0x795400 (7,951,360) sectors on the device. As the sectors are 0.5KiB this means there's 3,975,680KiB of storage available. That is 3,882.5MiB or ~3.79GB

Offset 0x24 tells us there are 0xF800 (63,488) sectors per FAT

0x2C says the root starts at cluster 2 (as usual)

So I'd have said this entire boot/BPB was "normal" with nothing unusual in it.

Cliff

PS As that's Winhex I guess you know you can use the template manager to cast a boot/BPB template onto that sector which makes this kind of decode totally automatic?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The first picture is for the 4G SDHC card - the one that works. The second is for the 2G SC card that doesn't work.

Thanks to pointing me to the Templates in Winhex. Using the one for the 2G card implies that all is well - 512 bytes per sector. The rest of the parameters look OK also. So the problem remains: Why doesn't this card (and lots of others) work? All I can think is that the responses to the queries the program sends don't come back as expected. I'm going to try to chase this a bit with some "printf" statements.

If anyone has any suggestions or insights, I'll be very interested.

Thanks.

Pages