fatfs, libm.a issues...

Go To Last Post
66 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Guys.
So I asked Cliff for help in a pm, and he told me I would do better on the main forum so here goes.
I have a simple application (relatively) that is supposed to access an sd card, and play an audio file (.raw).
It should be a very slimmed down version of the fatfs library written by elm-chan.
I am using a mega1284p in smd format so I have 44 pins.
I have attached my schematic.
Firstly I think I need to link to libm.a - after reading around the forum, I notice that "error 126" might be related to that.
Just to check I am using Eclipse with AVR plugin, and there is a box to add libraries (-l) and a box to add libraries Path (-L), based on the small and capital 'L' can anyone tell me which to add the libm.a to, and where it is located (in winAVR).

Lastly, please can someone have look at the implementation of fatfs attached, I cant get it to successfully initialize the sd card, let alone play the audio file, and would greatly appreciate the help getting this working. Pretty sure I cant be far, as Ive followed numerous tutorials to get this working.
Thanks
Alex

Attachment(s): 

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

Well, your schematic has two pins named CE. Your card code does not control the CS pin of SD card but one of the CE pin. You also initialize the pins as low, which means active. You should not do that. The pins defined for write protect and card detect are also not used for those anymore.

It also takes some effort to make a card stop driving its DO pin, so be careful as the RF chip and SD card are on the same bus.

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

Just a general comment. Both hardware and software design should be done in small steps. Start from the bottom up and implement a small part of the circuit or a small piece of the software. test that to death and when you are happy it is totally stable and foolproof use it as a building block for the next layer. Working in this way there are only ever a few "unknowns".

The alternative of bolting the entire hardware and software together switching on and finding "it doesn't work" is a very bad way to go about design. You now have 10/20/50 "unknowns". You don't know if the problem you are seeing is a hardware or a software one or which bit of either of those it is in.

Equally if you then post a schematic and the complete software and say "this doesn't work, what's wrong" the chances of anyone being able to help are very small (apart from obvious small errors such as Jepael points out which may or may not be the cause of your "big problem").

I was going to check your software against the schematic and see that in the software mmc.c has CS=PB0, CardPresent=PB4 and WriteProtect=PB5 but when I look at the schematic it does not actually identify bits PB0/PB4/PB5. The 1284 symbol you have used has the other uses of the PORT pins but does not identify which port is which or which bits are which. I suppose all I can do is dig out 1284 datasheet and check pin numbers there?

Except that when I do that something does not add up. In your schematic you have:

T0/XCK0/PCINT8 pin=40

But when I look at the datasheet it tells me that T0/XCK0/PCINT8 are on that PORTB.0 pin and that is physical pin 1. Looking at the other end of the port (that must be B) in the schematic I see you have:

SCK/OCB3/PCINT15 pin=3

but when I look at the data the pin with SCK/OCB3/PCINT15 is pin 8.

So this could just be that you drew a 1284 symbol in Eagle and just got that wrong. Or it could be that your circuit really is wired completely wrong.

Too many "unknowns", I can't tell.

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

Hi guys, thanks for comments. I havent had a chance today to deal with Jepael's comment's will when I get home.
In the mean time, I think I may have not been clear Cliff that I am using the smd version of the 1284p in TQFP format with 44 pins.
In that case PCINT8 is PB0 but on pin 40. I think you may have looked at the PDIP format chip.
The one error I have made is labelling two pins CE, but that doesnt effect the sd card I dont think.
Sorry the schematic doesnt have the actualy pin names on - I began drawing my own eagle part, and was worried was going to mess it up so I downloaded one from a libary on the web...

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

P.S
The CE pins are an error, it doesnt affect anything "SD" related, just means I lose a pin because they both connect to the same pin of the nrf module. I can just use either/OR but I need to set one into hi-Z mode as I understand it....

Whats the trick to get an SD card to stop sending DO data? I thought I just push its CS line high?

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

a.mlw.walker wrote:

Whats the trick to get an SD card to stop sending DO data? I thought I just push its CS line high?

Well after you fix the code that uses SD card CS line, you can read MMC and/or SD card datasheets for the exact sequence, but you may need to clock 1-2 dummy bytes out from the card after you deselect it before it stops driving data out.

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

If (as I think you said in PM) your goal is to reduce the complexity of the FatFs parts of this project then I really would use the "Petit" version of FatFs. One of the options (if you look at the pfboot example) is to use Chan's own bit-bang SPI which allows you to put the MOSI/MISO/SCk used for the SD/MMC on any pins on the chip you choose. You could therefore forget about trying to do double duty on the single hardware SPI and just dedicate it to the RF module. The question of chip selects and worrying about one of the devices loading the shared lines would all evaporate. You can see Chan's bit-bang code here:

http://spaces.atmel.com/gf/proje...

Note how those defines at the top of the file set which PORT/pins the simulated SPI signals are on. Maybe don't use PORTB but some other port on the 1284.

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

Hi Cliff,
basically I do want to understand whats makes fatfs tick. Also my hardware has already been built so for now I want to try and get it working with both devices on the hardware spi lines. I have also wanted to understand how two devices communicate with the master using spi, so here is my chance. Going to go and make those changes mentioned above now - also realised there might be a fuse issue as the 1284p's are new, and therefore have default fuse settings etc...

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

Quote:

Also my hardware has already been built

So this becomes the 10 bazillionth thread that proves the utility of breadboarding/prototyping before committing to hardware ;-)
Quote:

there might be a fuse issue as the 1284p's are new, and therefore have default fuse settings etc.

So they'll have CKDIV8 set and be running at just 1MHz. This may well be fine but as one of your previous projects was playing back audio from WAV files I'm not sure how well that's going to go at 1MHz.

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

Currently got different issues. On trying to build fatfs, it fails (before on ff.c and now) on mmc.c

Quote:

Building file: ../mmc.c
Invoking: AVR Compiler
avr-gcc -Wall -Os -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega1284p -DF_CPU=16000000UL -MMD -MP -MF"mmc.d" -MT"mmc.d" -c -o "mmc.o" "../mmc.c"
/usr/bin/sh: /c/WinAVR-20100110/bin/avr-gcc: Bad address
make: *** [mmc.o] Error 126

Any ideas what that could be due to?

EDIT:
Also if Im not using write-protect or card detection, whats the best thing to do with this:

#define SOCKWP		(PINB & 0x20)		/* Write protected. yes:true, no:false, default:false */
#define SOCKINS		(!(PINB & 0x10))	/* Card detected.   yes:true, no:false, default:true */

- just delete those lines and any references to them?

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

BTW this is what my all options states:

Quote:

-Wl,-Map,fatFileSystem.map -L"C:\WinAVR-20100110\avr\lib\avr51\" -mmcu=atmega1284p

when I look under libraries, I can see under the "-l" box I have added an m, I just thought it would appear above...

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

Well you have to fake them so that if some functions use them, these functions return a value back saying yes the card is there and no the card is not write protected.

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

I'd forget Eclipse for the time being. Get Mfile. generate a Makefile. Either build at the command line or tell Eclipse to just use that external Makefile. When you have a set of build options that can build the code then worry about how to persuade Eclipse to put them into its autogenerate Makefile.

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

Hey,
So I tried using mfile, and that wasnt cooporating (or i wasnt) so I went to the command line to try and compile the .c's with avr-gcc. I started with main.c which failed - and said PORTB wasnt defined...

I then went back to the project in AVRStudio and that complained about "No rule to make target ff.o stop".

Now Im wondering whether winAVR is corrupted or something...
Could someone please try and compile it. I havent changed much except these two lines in mmc.c

#define CS_LOW()	PORTB &= ~0b00000010			/* MMC CS = L */
#define	CS_HIGH()	PORTB |= 0b00000010			/* MMC CS = H */
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

IT WAS THE F****** LANGUAGE STANDARD. For some reason I didnt recognise gnu99 so went searching and changed it to compiler default and now it built.
OK back to problem at hand. Sorry about detour...
Also have changed the socket protection etc to:

#define SOCKWP		0
#define SOCKINS		1

[/code]
Seemed to only be used in disk_timerproc - and that (version) was also commented out, I think Cliff gave me a modified version as I didnt need all of its features. So I suppose I could get rid of those two defines entirely...

Is MISO supposed to be an input. I.e is the following correct?

   DDRB  =  0b10110010;
	PORTB = 0b00000000; // PB7 = SCK, PB6 = MISO, PB5 = MOSI, PB4 = SS, PB1 = custom CS (SD)
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

It should be a very slimmed down version of the fatfs

That's the confusing part. You have a 128k flash part, near the largest of AVR8. And the model has the most onboard SRAM of any AVR8 model.

Yet you crave a "very slimmed down" FatFS? Does 4k or 6k or even 8k bother at all?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Ok. I am after an sd filing system that can be read on a computer.

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

Quote:

Ok. I am after an sd filing system that can be read on a computer.


??? Is that in reply to my question?

Generally (and perhaps in all cases?) a factory-fresh SD card is FAT formatted. Generally, it used to be FAT16 but nowadays it is FAT32 on 2GB+ (and perhaps on smaller as well).

So you can plunk it into the memory card reader on your "computer". A Windows machine will let you manipulate it with e.g. Explorer and other tools. Is that good enough?

The FatFS, properly configured, will let your AVR read/write/create files on that card. In fact, if you include the option I believe that it will format the card as well.

You can move it back-and-forth between AVR and computer as many times as you care to.

Now, what does all that have to do with the need for "should be a very slimmed down version of the fatfs "?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

oh god.
My last response was in reply to you to try and stop that being the focus of the thread.
I have used fatfs before - with Claswon's help but I lost that code, and Im struggling to get it working again. On that basis I happen to know there are options within fatfs to not include japanase language, and a whole load of other features that can be removed. So that is what I meant by:

Quote:

should be a very slimmed down version of the fatfs

But that really isnt the focus of the thread, and was not meant to be the detail that was picked out of my original thread. Hopefully this answers that question and we can get back to the other points raised...

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

can the disk not initialze if the card is coorupt? does programming the chip corrupt an sd card?

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

Quote:

On that basis I happen to know there are options within fatfs to not include japanase language, and a whole load of other features that can be removed. So that is what I meant by:

Well all that stuff comes down to a properly configured ffconf.h. Chan gives lots of options in there for things to switch on/off. I agree that it makes sense to switch off Japanese language support (that is _CODE_PAGE by the way which should be defined as 1). I personally don't see the need for LFN either so you might as well switch that off and stick to 8.3 filenames (_USE_LFN set to 0). But as Lee says this is just about the biggest mega AVR you can buy so I don't really see much point in switching off other stuff. I suppose if you really wanted to save some of that precious 128K flash then look at using:

#define _FS_MINIMIZE	1

or perhaps even take that all the way to 3 if you don't want directory support and don't want to f_lseek()? Also set all of _USE_STRFUNC, _USE_MKFS, _USE_FORWARD, _USE_FASTSEEK to 0 too.

With those options and an empty main() I get:

Device: atmega64

Program:   10118 bytes (15.4% Full)
(.text + .data + .bootloader)

Data:         25 bytes (0.6% Full)
(.data + .bss + .noinit)

Obviously that .data will increase with a FATFS and FIL structure added.

Programming the chip should not corrupt the card. disk_initialize() should not return an error code as long as the card is intact whether it contains a valid filesystem or not (otherwise f_mkfs() could not be used!). If the FAT structures on the card are invalid there's a strong chance f_mout() *will* return an error code (though actually FAT is not very robust and some failures may not be spotted at this stage).

Are you saying disk_initialize() itself fails? If so what error code?

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

Do you try to use the SD card while your programmer is still plugged in?

I tend to post off-topic replies when I've noticed some interesting detail.
Feel free to stop me.

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

Managed to get some debugging done this morning. I have traced the problem back to this method:

static
BYTE rcvr_spi (void)
{
	SPDR = 0xFF;
	uint8_t spd = SPDR;
	uart_puts("SPDR1 = ");
		uart_put(spd);
	loop_until_bit_is_set(SPSR, SPIF);
	uart_puts("SPDR2 = ");
	uart_put(SPDR);
	return SPDR;
}

which returns:
SPDR1 = [00]SPDR2 = [00]
(uart_put takes a uint8_t and casts to to an unsigned char to be "transmit"ted to serial).
That was called from wait_ready() whic does the check:

int wait_ready (void)	/* 1:OK, 0:Timeout */
{
	BYTE d;


	Timer2 = 50;	/* Wait for ready in timeout of 500ms */
	do
		d = rcvr_spi();
	while (d != 0xFF && Timer2);
	uint8_t ret = (d == 0xFF) ? 1 : 0;
	uart_puts("ret = ");
	uart_put(ret);
	return ret;
}

which in turn is called from select and times out if wait_ready() doesnt return 1.
So my hypothesis is spi hasnt been initialized correctly. Two options I can see: my pin config is incorrect - if so I think the problem would lie here:

 DDRB  =  0b10110010;
	PORTB = 0b00000010;

or here:

#define CS_LOW()	PORTB &= ~0b00000010
#define	CS_HIGH()	PORTB |= 0b00000010
#define SOCKWP		0
#define SOCKINS		1

If so, is there a very simple SPI test I can do that will conclude whether SPI is working correctly?
Otherwise it can therefore be conluded its a hardware problem?

EDIT: sorry hadnt refreshed in a while missed your comments.
Thanks for those fconfig tips Cliff, will play with that when its working...
Yeah its disk_init..() that fails. error code [01]
then opening failed with error code [03] unsurprisingly.
I have tried reading the card with sip plugged in and not plugged in. Better not in a presume, and therefore have conitnued with that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   SPDR = 0xFF;
   uint8_t spd = SPDR; 

That appears to immediately read SPDR after starting a transfer?? Surely you want something like:

   SPDR = 0xFF;
   while(!(SPCR & (1<< SPIF))));
   uint8_t spd = SPDR; 

which starts the transfer, waits for it to complete and THEN reads the received byte from SPDR. I wondered why you have hacked around with chan's mmc.c because when I look at the original copy of rcvr_spi() I see exactly what I'd expect:

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

So why on earth have you destroyed Chan's great, tested, working code and replaced it with something so inferior?

If I were you I would take a virgin copy of ffsample.zip, just configure it to build for your 1284, maybe make some build choice options in ffconf.h then build it and test it and prove that the SD/MMC is working just fine. Then, if you really feel the need to hack about with it make small changes, one at a time, and see the effect of each. Wind back anything that breaks operation. A code control system like SVN is very good for this kind of thing.

Regarding your edit: what would be the point of letting the code go on an do f_mount() or f_open() if disk_initialize() failed? You have to track and fix that one and the code should generally be of the form:

int res;
res = disk_initialize();
if (res != STA_NOINIT) {
  res = f_mount(...);
  if (res == FR_OK) {
    res = f_open(...);
    is (res == FR_OK) {
      res = fwrite(...)
      if (res != FR_OK) {
         PANIC!!();

if the programmer went to all the trouble to implement routines that return pass/fail results don't just ignore those and write:

disk_initialize();
f_mount(...);
f_open(...);
fwrite(...)

Sure it's less code but it's stupid code.

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

Hey,
I only put that read of SPDR in before the transfer to see if I did indeed get 0xFF as the current value of SPDR. I didnt make all those changes in one go, i was just working back through the code to see where the error was occuring, by putting in print statements. I started with ffsample, and all I did was chance out his main for a hacked together one, that as you say should and could do more checks before continuing to try and open/read/write if init failed. It was just for testing. Its not permanent. I also read the value of SPDR after the transfer, to see if its any different. All in all, Im not affecting the value that SPDR takes on after the transfer though am I? Its only print statements...

P.S Set MISO as an input and init CS as Low right?

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

You can't do that. SPI has an "active phase" during which one byte is being shifted out and one is being shifted in. You should not access SPDR during this time. As I say the active phase starts when SPDR is written. This initiates 8 SCK pulses. You know when this phase has ended because SPIF in SPCR is set. It is cleared when you then read SPDR. So the sequence must be exactly as Chan wrote. Before SPDR is written to start you could print the byte that's been passed into the routine and after SPIF has been set and SPDR is read you could print that byte. Do not be tempted to make multiple reads/writes of SPDR. Just do one write and one read. If you need to "see" the received value then read it once into a variable, print that, then return that.

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

OK so going back to chan's method rather than my "hacked" one, I only did those prints to see what was failing there as in wait_ready() it is never getting passed
[code]
while (d != 0xFF && Timer2). so i went into rcvr_spi() to see what was going on. Maybe it is Timer2 that is failing... unlikely I think however...

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

Quote:

Maybe it is Timer2 that is failing... unlikely I think however...

You HAVE implemented it haven't you? One of the few pieces of work you, the user of FatFs has to provide is a regular timer interrupt. (Chan cannot know what speed your AVR is going to be running at or which timers you want to use for other things). In ffsample.zip the example main.c has this:

static
void IoInit ()
{
	

	OCR2 = 0x4E;		// Timer2: 100Hz interval (OC2)
	TCCR2 = 0b00001101;

	TIMSK = 0b10000000;	// Enable TC2.oc, interrupt

	sei();
}

that starts timer2 on his particular micro at 100Hz (so 10ms interrupts). The interrupt handler does this:

ISR(TIMER2_COMP_vect)
{
	Timer++;			/* Performance counter for this module */
	disk_timerproc();	/* Drive timer procedure of low level disk I/O module */
}

And the disk_timerproc() this calls (which is in mmc.c) does this:

/*-----------------------------------------------------------------------*/
/* Device Timer Interrupt Procedure                                      */
/*-----------------------------------------------------------------------*/
/* This function must be called in period of 10ms                        */

void disk_timerproc (void)
{
	BYTE n, s;

	n = Timer1;				/* 100Hz decrement timer */
	if (n) Timer1 = --n;
	n = Timer2;
	if (n) Timer2 = --n;

	s = Stat;

	if (SOCKWP)				/* Write protected */
		s |= STA_PROTECT;
	else					/* Write enabled */
		s &= ~STA_PROTECT;

	if (SOCKINS)			/* Card inserted */
		s &= ~STA_NODISK;
	else					/* Socket empty */
		s |= (STA_NODISK | STA_NOINIT);

	Stat = s;				/* Update MMC status */
}

Amongst other things that "ticks" a couple of counters called Timer1 and Timer2. Other parts of the disk system use these when waiting for things to happen so these global counters MUST exist and they must tick down at 100Hz when non-zero.

You may have edited your code to change disk_timerproc() to remove the code for SOCKWP and SOCKINS if you haven't got those signals but you cannot get rid of the timers.

So, yes, it's very likely that you are wrong about:

Quote:
unlikely I think

BTW the example main.c has "Timer++" in the timer interrupt but it's only used within that same main.c. You may not need that one.

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

haha, that was a funny post.
my ioInit() looks like this:

   DDRB  =  0b10110010;
	PORTB = 0b00000010; // PB7 = SCK, PB6 = MISO, PB5 = MOSI, PB4 = SS

	uart_init();		// Initialize UART driver
	OCR2A = 0x0b;      // Timer2: 100Hz interval (OC2) (0b for 16Mh, 4E for 8z).
   TCCR2A = 0b00000010; //CTC mode
   TCCR2B = 0b00000111; //1024 prescaler

   TIMSK2 = 0b00000010;   // Enable TC2.oc interrupt 
	sei();

I havent re-done the calculation, but Im pretty sure that its correct (16Mhz timer).
The only difference then is my dick_timer_proc() which is a simpler version (removing SOCKINS and SOCKWP:

    BYTE n, s = 0;

    n = Timer1; /* 100Hz decrement timer */
    if (n) Timer1 = --n;
    n = Timer2;
    if (n) Timer2 = --n;
 
    s &= ~STA_NODISK;
    s &= ~STA_PROTECT;
 
    Stat = s;
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh OK, that looks fine then. Well the while loop and your prints from rcvr_spi() seem to suggest that it is always returning 0x00. That would possibly suggest your MISO line is inadvertently tied to Gnd. If you have a scope or logic analyser then scope it and see if there is activity. Maybe try removing anything else on that line apart from the SD/MMC (ie the other SPI device) and see if that helps (just lifting its single pin may be enough for this).

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

Ok well, good to hear that. I'll try and scope it, can probably get a probe down there, in the mean time, is there the equivelent of a loop back test for spi? Or can I output the state of MISO or something continually after trying to ask the card for data?

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

Well the loop back is to connect MOSI to MISO but you would have to detach other connections.

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

a.mlw.walker wrote:

P.S Set MISO as an input and init CS as Low right?

Yes and no! MISO is input, CS is set high.

You don't have any pull-up resistors to set state of pins while AVR is in reset or ISP programming mode. So it is possible that card sees ISP programming traffic and gets invalid commands (or correct commands to corrupt it with writes), or it interferes the ISP by driving the output pin. So ISP with card removed, use card with ISP removed.

Then there is the other SPI chip.

Have you initialized the SPI/IO pins for the NRF module correctly, so that it does not drive the MISO pin at the same time while card is driving it? If not, of course all devices on SPI bus interfere with each other.

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

Quote:
Have you initialized the SPI/IO pins for the NRF module correctly, so that it does not drive the MISO pin at the same time while card is driving it? If not, of course all devices on SPI bus interfere with each other.

Interesting Jepael. I have not intialized it at all. I am trying to just work on the sd card. So should I initialize it, and then set its CS line HIGH delay for a bit and then try to use the sd card? I thought totally uninitialized it would not respond to commands...

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

The way you start an SD/MMC initialisation is by sending it CMD1. That may look exotic but it's simply a 0x01. There's every chance a 0x01 may pass by on the SPI bus when an AVR is being programmed. It's quite possible that whatever is used to init the NRF is just some similar command byte that could also pass by.

The way SPI is supposed to work is that you have one master and all the lines are common. You then arrange for only ONE slave at a time to be active (usually by taking some kind of _SS or _CS signal low) and make sure all the others remain high and so don't listen and don't drive their outputs. The master would/should have an individual IO line to each slave's _SS/_CS so it can keep them in a known state (also it is the 1->0 transition on a slave's select line that resets its shift register in case it's got out of step). There's also the issue Jepael mentions of what about when the AVR itself is held in _RESET (such as during ISP programming) at that time all its output lines (including slave selecting IO lines) will float so the devices might see lows and think they are activated. Really you should have pull-ups (assuming active low) on all such lines so that when no master is around to drive them they are pulled into the non-active state.

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

a.mlw.walker wrote:

Interesting Jepael. I have not intialized it at all. I am trying to just work on the sd card. So should I initialize it, and then set its CS line HIGH delay for a bit and then try to use the sd card? I thought totally uninitialized it would not respond to commands...

No, you don't need to initialize the chip. And in fact you cannot if you are not sure if your SPI works or not. And how could it work if a chip might be enabled because you don't set their CS pins to disabled state.

The point is, you need to configure the CS pins of the chips so the chips are kept disabled at first. Then enable the CS pin of the chip you want to talk to. Or in fact, the provided MMC code already does the CS handling for you, so don't touch the SD CS pin yourself.

Edit: Just noticed, if you don't have any pull-up resistors to keep NRF chip disabled during programming, maybe even the programming does not work properly.

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

Right couple of things then:
firstly I have changed the method recvr_spi so I am only reading SPDR once.

static
BYTE rcvr_spi (void)
{
	SPDR = 0xFF;
	loop_until_bit_is_set(SPSR, SPIF);
	uint8_t value = SPDR;
	uart_puts("SPDR = ");
	uart_put(value);
	return value;
}

Next I have looked at the pinouts for the nrf in my original schematic (posted) and have set PCINT8 - PB0 into high-Z mode so that it is now a redundant pin.
I have then taken CSN from the NRF module and set it as a HIGH output (on PB3)
IRQ (interrrupt of NRF+) is also in HIGH-Z mode. I think it gets setup by the initialization of the NRF+ (which is not being done) (PB2).
Lastly CE of the NRF is connected to SS of the 1284p. So I have driven it HIGH for start. That way fatfs can bring SD CS low and it will be the only one communicating?

static
void IoInit ()
{

   DDRB  =  0b10111010;
	PORTB = 0b00011010; // PB7 = SCK, PB6 = MISO, PB5 = MOSI, PB4 = SS
						//PB3 = CSN on NRF+, PB4 = SS = CE on NRF+
						//PB0 is an error pin keep as input low.
						//PB2 = IRQ = HIGH-Z for init.

	uart_init();		// Initialize UART driver
	OCR2A = 0x0b;      // Timer2: 100Hz interval (OC2 )(0b for 16Mh, 4E for 8z)..
   TCCR2A = 0b00000010; //CTC mode
   TCCR2B = 0b00000111; //1024 prescaler

   TIMSK2 = 0b00000010;   // Enable TC2.oc interrupt 
	sei();
}

On init I stuck a probe to MISO and when it tries to access it, it flutters (just above 0v). However after thinking about it, surely there cant be a short because I am using an ISP programmer which requires those SPI lines...

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

Quote:

because I am using an ISP programmer which requires those SPI lines...

You are detaching it before the AVR tries to use the same lines for SD or NRF aren't you?

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

yep, and SPDR is still 0.

P.S I have two identical boards here, except one of them does not have the nrf24L01+ module soldered on. I have just tried with that one and I get the same response - cannot initialize.
So now I feel it must be pins...
If I have an SPI device on the SS line and an SPI device on ANother pin, the SS line must be OUTPU for the 1284p to be the master. Then SS must be HIGH to stop that SPI device from communicating with the master? (just thinking out loud).
Next, fuses.
BOD disabled, dont div/8, JTAG off, clock external > 8Mhz 64ms startup... SPIEN not set.

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

P.S There are "sparks" on the MISO line. every so often (relative to how long it is 0v for) there is a jump to 3.3v

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

Google says that some SD cards might require a pullup on MISO and MOSI. Does this sound familiar? Im running at 3.3v with SD connected directly to Master.

As long as the SD card is physically good - i.e a computer can read it, then disk init failiure shouldnt be the problem right?

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

Might be. The SD card is in SD native bus mode until it is initialized to SPI bus mode.

Having a pull-up on MISO should handle it, but it might be too weak if communications is too fast (SCK speed).

When AVR talks to card, MOSI is of course output, so it is not absolutely necessary to have a pull-up.

There are two unused pins in SPI mode, they should have pull-ups so they do not float. I have witnessed several milliamps of excess supply current usage when there was no pull-ups.

Some SD cards do not necessarily support SPI mode. I think I have seen a few of those, or my code was unable to initialize them. And remember that SD, MMC and SDHC cards are all different.

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

Quote:

There are two unused pins in SPI mode, they should have pull-ups so they do not float. I have witnessed several milliamps of excess supply current usage when there was no pull-ups.

What on the mega or the sd card?

These SD cards have worked before though Im sure.

While we're here, what format should I put the sd card in? Fat32 with sector size of 512?

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

a.mlw.walker wrote:

What on the mega or the sd card?

These SD cards have worked before though Im sure.

While we're here, what format should I put the sd card in? Fat32 with sector size of 512?

Two data pins on SD card are unused in SPI mode. I am sure it will still work even if there are no pull-ups. It is just not good design (as you have seen why pull-ups on chip select pins are quite necessary).

I think FAT filesystems and SD cards only support a filesystem sector size of 512. flash block size can be whatever of course. Just like modern hard drives with 4k sectors are presented as 512-byte sectors by default.

Cluster size will vary based on used filesystem and card size. Depending on card size it will select FAT16 or FAT32, but the rule of thumb is SD cards should use FAT16 and SDHC cards should use FAT32.

Also the rule of thumb is that SD cards go up to and including 2GB and SDHC cards go from 4GB (and including) upwards.

Basically, don't reformat the card to different file system type from what you bought it with. And also do not repartition it with different layout, or repartition it with different starting offset. Most likely someone who knows about the underlying flash organization has determined if the SD card should have a hard disk alike master boot record type of partitioning scheme, or floppy disk alike scheme where the card starts directly with the filesystem boot record (no partitioning). Also the various starting offsets of partitions and filesystem records have most likely been calculated so that they best match the underlying flash block layout, meaning for example that the master boot record sits alone in the first flash block so using the filesystem never writes to this block, and the first few blocks may have different kind of wear-leveling algorithm for the flash blocks containing the FAT cluster table than for the actual data area.

So it is best to try not to change these filesystem types and layouts, but they are of course lost if something corrupts the filesystem boot sector or master boot sector.

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

So ok, I cant guarantee the sd cards have not been formatted differently to when they were first received, Ive had them a while.
Is there any chance that you have an sd socket wired up to an avr and could test my code so that I can be convinced that it is a hardware issue, and not a software issue? As one of my boards does not have the nrf module shown in the schematic, when I test against that one I can be sure that that is not inteferring.

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

I have one board with SD socket, and I have been thinking about writing a driver for it. Board/compiler manufacturer has some example code for using it, but license permits only to use with that compiler. It is not an AVR though.

But I seriously think you should debug what happens on the SPI bus, with a scope or logic analyzer. Try to initialize the card in a loop until it succeeds, and monitor the bus. Take a note of SPI clock speed, clock polarity and phase regarding the output data, CS pin and supply voltage, and see if they are within SD specs.

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

Quote:

So ok, I cant guarantee the sd cards have not been formatted differently to when they were first received, Ive had them a while.
You have read fatgen103 haven't you? If you have you'll know that the choice of FAT12/16/32 and the cluster size is made automatically when Windows formats the drive based solely on the size. So if you start with a FAT16 card and don't go out of your way to tell Windows to do something "unusual" when it formats it will just create FAT16 again.

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

Right I'll get scope and camera out later, and check the spi clock speed - i suppose I need to be careful about accessing any spi register - i.e if I want to output spi clock speed to terminal...
Is there somewhere I can check against, i.e what the clock polarity should be at any time, or the phase etc...

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

Chan does this in mmc.c (for mega64):

SPCR = 0x52 // slow
SPCR = 0x50 // fast

If you look at the m64 datasheet 5 sets just SPE and MSTR. Therefore CPOL and CPHA are set to their 0 defaults. that means SCK low when idle and input data is sampled on the leading edge (rising) and setup on the falling edge.

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

So that works out the same then I think for the 1284 in that "slow" sets a prescaler on the spi line of 64, sets the 1284 as master and turns on spi. "fast" does the same but no prescaler.

Onto other things....
Tests I have just done:
SD card in.
Set PB7 (SCK) high. When SD card is in and test with scope, PB7 is high, but also so is MISO and MOSI.
Set PB6 (MISO) high. When SD card in, only MISO high.
Set PB5 (MOSI) high. MOSI and MISO both high.

SD card not in.
PB5 (MOSI) high. Only MOSI high
PB6 (MISO) high. Only MISO high
PB7 (SCK) high. Only SCK high.

I have attached a picture. From left to right that is MOSI(the very square wave), SCK(the broken wave) MISO(the flat line). (with SD card in).

Interesting spot. I have a connection to PB2 quite near MOSI. When the SD card is in - and the initiation process is trying to take place MOSI is a sharp square wave. However touching a probe on PB2 is also showing a sharp square wave. If I re flash the chip with a simple program that just sends PB5 (MOSI) high, I dont get this occuring - even with the sd still in. i.e it seems as though either the code is getting PB2 to follow suit of MOSI, OR there is something dodgy going on the intitiation sequence with the card that somehow is flicking PB2 high... Dunno if its relevant as (for one of the boards - the one I am using) there is nothing on PB2...

Attachment(s): 

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

Have I just noticed something strange? Its giving me brain freeze trying to work it out...
in power_on/_off there are these lines:
power_on:

PORTB |= 0x04;            /* Socket power on */ 
PORTB |= 1; // CS the card

power_off:

PORTB &= ~1;         // remove CS to the card
PORTB &=  ~0x04;         /* Socket power off */ 

0x04 is the SS line. I dont have the sd card on the SS line but it needs to be an output to state that the 1284 is master. So a) PORTB &= ~0x04 is just setting the SS line low - If the sd card was on SS for CS then that would be saying "get ready for data". But thats in the power_off function?
Then the other line, PORTB |= 1; what is that supposed to be doing? is that setting PB0 high or something? All in all they are wrong I think? I have CS on PB1 and also have the two defines setup:

#define CS_LOW()	PORTB &= ~0b00000010		
#define	CS_HIGH()	PORTB |= 0b00000010	

so why are those lines in power_on/_off not using the defines instead of the 0x04 lines? In fact those two lines have completely confused me...

Pages