FatFs and SD mmc ?

Go To Last Post
114 posts / 0 new

Pages

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

Guys,

I tried to compile the FatFS for AVR example, but I got :

Error	1	undefined reference to `get_fattime'	C:\Users\antonius\Documents\Atmel Studio\6.1\FatFsAVR\Debug\ff.c	1	1	FatfsAVR

I can't find "get_fattime" anywhere on the example,

Does anyone have a same experience with me ?
How to fix it ?

Thanks

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

did you check out the 2 (or already 3 ) tutorials on using fatfs?
they should get you up to speed.....

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

I just typed get_fattime into the search engine here. There were a lot of very useful results. Apart from this thread the next hit was a 17 page thread in the tutorial forum that explains how to make FatFs work for you. I wonder if it's a coincidence that thread contains a mention of get_fattime?

When you read that thread note you MUST read all 17 pages. FatFs is a developing project and there have been many issues of it over the time that thread has existed. So the early parts talk about old versions. Later versions have subtle differences and as it's one of those later versions you are trying to use you must read to the end to see the latest info.

From time to time someone (sometimes me, sometimes others) have taken the "latest" release and worked through the steps you now need to follow to make it work. I think the last time I did it was last July with version 0.09.

Looking at the FatFs pages I see 0.10a is actually the latest so there might be yet more subtle changes.

(however the get_fattime() thing has been the same for a LONG time!).

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

I can compile the last version of example but I can't see it's doing what I want...
Is it because of the clock ? My clock is 16Mhz and I change the code from 14 to 18Mhz
I use ATMEGA128. I can compile if I don't use the "makefile" from the package...
Any suggestions ?

Please have a look on my code

#include 			/* Include device specific declareation file here */


#define DO_INIT()					/* Initialize port for MMC DO as input */
#define DO			(PINB &	0x01)	/* Test for MMC DO ('H':true, 'L':false) */

#define DI_INIT()	DDRB  |= 0x04	/* Initialize port for MMC DI as output */
#define DI_H()		PORTB |= 0x04	/* Set MMC DI "high" */
#define DI_L()		PORTB &= 0xFB	/* Set MMC DI "low" */

#define CK_INIT()	DDRB  |= 0x02	/* Initialize port for MMC SCLK as output */
#define CK_H()		PORTB |= 0x02	/* Set MMC SCLK "high" */
#define	CK_L()		PORTB &= 0xFD	/* Set MMC SCLK "low" */

#define CS_INIT()	DDRB  |= 0x01	/* Initialize port for MMC CS as output */
#define	CS_H()		PORTB |= 0x01	/* Set MMC CS "high" */
#define CS_L()		PORTB &= 0xFE	/* Set MMC CS "low" */


static
void dly_us (UINT n)	/* Delay n microseconds (avr-gcc -Os) */
{
	do {
		PINB;
#if F_CPU >= 6000000
		PINB;
#endif
#if F_CPU >= 7000000
		PINB;
#endif
#if F_CPU >= 8000000
		PINB;
#endif
#if F_CPU >= 9000000
		PINB;
#endif
#if F_CPU >= 10000000
		PINB;
#endif
#if F_CPU >= 12000000
		PINB; PINB;
#endif
#if F_CPU >= 18000000
#error Too fast clock
#endif
	} while (--n);
}




/*----------------------------------------------------------------------*/
/* Foolproof FatFs sample project for AVR              (C)ChaN, 2013    */
/*----------------------------------------------------------------------*/

#include 	/* Device specific declarations */
#include "ff.h"		/* Declarations of FatFs API */

FATFS FatFs;		/* FatFs work area needed for each volume */
FIL Fil;			/* File object needed for each open file */


int main (void)
{
	UINT bw;


	f_mount(&FatFs, "", 0);		/* Give a work area to the default drive */

	if (f_open(&Fil, "newfile.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {	/* Create a file */

		f_write(&Fil, "It works!\r\n", 11, &bw);	/* Write data to the file */

		f_close(&Fil);								/* Close the file */

		if (bw == 11) {		/* Lights green LED if data written well */
			DDRB |= 0x10; PORTB |= 0x10;	/* Set PB4 high */
		}
	}

	for (;;) ;
}



/*---------------------------------------------------------*/
/* User Provided RTC Function called by FatFs module       */

DWORD get_fattime (void)
{
	/* Returns current time packed into a DWORD variable */
	return	  ((DWORD)(2013 - 1980) << 25)	/* Year 2013 */
			| ((DWORD)7 << 21)				/* Month 7 */
			| ((DWORD)28 << 16)				/* Mday 28 */
			| ((DWORD)0 << 11)				/* Hour 0 */
			| ((DWORD)0 << 5)				/* Min 0 */
			| ((DWORD)0 >> 1);				/* Sec 0 */
}

Thanks

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

Quote:

but I can't see it's doing what I want

You mean newfile.txt is not being created?

Well one thing you are doing wrong here is calling all the FatFs functions (which almost all return some kind of pass/fail result) without taking any notice of the return values.

Do you even know if the f_mount() call worked or not?

In fact what many of us do is actually call the lower level disk_initialize() function first and check its result. If that fails nothing beyond it is going to work. It generally fails if you got something wrong with the wiring/electronics.

BTW you should see that in disk_initialize it uses a macro called FCLK_SLOW() near the start before it starts the initial SPI. Once it has done the init it uses FCLK_FAST(). These use the SPI prescaler to ensure that even with a fast (16MHz) clock the initial dialog with the SD/MMC is done slowly to be within spec.

Oh and as with all things SPI if you have access to a DSO or logic analyzer it makes diagnosing hardware operation 100 times easier as you can watch it wiggling the wires and see if naything does not look right (like no SCKs or data only on MOSI but none back on MISO or whatever the problem may be - you can also check the pulse timing to make sure it's within spec.)

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

Yea, I haven't seen newfile.txt, so I call disk_initialize and see on my logic analyzer, to make sure it's doing something ?

Thanks for the suggestion, I'm striving to make FatFs working...
I'm sure there's nothing wrong with wiring (hardware) since I tested with other software for SDcard, it's working, but it's not using FatFs.....wish me luck...

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

I tried with logic analyzer, but I can't see MOSI ?

while(1)
	{
		disk_initialize (0);
	}

Any clues ?

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

Do you see SCK ?

power_on() and power_off are platform dependent.
Check that the correct SPI pins are being used for yourhardware.

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

Yes I see SCK

Here's the hardware connection (bit bang non SPI ) following the example:



#define DO_INIT()					/* Initialize port for MMC DO as input */
#define DO			(PINB &	0x08)	/* Test for MMC DO ('H':true, 'L':false) */

#define DI_INIT()	DDRB  |= 0x04	/* Initialize port for MMC DI as output */
#define DI_H()		PORTB |= 0x04	/* Set MMC DI "high" */
#define DI_L()		PORTB &= 0xFB	/* Set MMC DI "low" */

#define CK_INIT()	DDRB  |= 0x02	/* Initialize port for MMC SCLK as output */
#define CK_H()		PORTB |= 0x02	/* Set MMC SCLK "high" */
#define	CK_L()		PORTB &= 0xFD	/* Set MMC SCLK "low" */

#define CS_INIT()	DDRB  |= 0x01	/* Initialize port for MMC CS as output */
#define	CS_H()		PORTB |= 0x01	/* Set MMC CS "high" */
#define CS_L()		PORTB &= 0xFE	/* Set MMC CS "low" */

disk initialize :


/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive                                                 */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
	BYTE drv		/* Physical drive nmuber (0) */
)
{
	BYTE n, ty, cmd, buf[4];
	UINT tmr;
	DSTATUS s;


	if (drv) return RES_NOTRDY;

	dly_us(10000);			/* 10ms */
	CS_INIT(); CS_H();		/* Initialize port pin tied to CS */
	CK_INIT(); CK_L();		/* Initialize port pin tied to SCLK */
	DI_INIT();				/* Initialize port pin tied to DI */
	DO_INIT();				/* Initialize port pin tied to DO */

	for (n = 10; n; n--) rcvr_mmc(buf, 1);	/* Apply 80 dummy clocks and the card gets ready to receive command */

	ty = 0;
	if (send_cmd(CMD0, 0) == 1) {			/* Enter Idle state */
		if (send_cmd(CMD8, 0x1AA) == 1) {	/* SDv2? */
			rcvr_mmc(buf, 4);							/* Get trailing return value of R7 resp */
			if (buf[2] == 0x01 && buf[3] == 0xAA) {		/* The card can work at vdd range of 2.7-3.6V */
				for (tmr = 1000; tmr; tmr--) {			/* Wait for leaving idle state (ACMD41 with HCS bit) */
					if (send_cmd(ACMD41, 1UL << 30) == 0) break;
					dly_us(1000);
				}
				if (tmr && send_cmd(CMD58, 0) == 0) {	/* Check CCS bit in the OCR */
					rcvr_mmc(buf, 4);
					ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;	/* SDv2 */
				}
			}
		} else {							/* SDv1 or MMCv3 */
			if (send_cmd(ACMD41, 0) <= 1) 	{
				ty = CT_SD1; cmd = ACMD41;	/* SDv1 */
			} else {
				ty = CT_MMC; cmd = CMD1;	/* MMCv3 */
			}
			for (tmr = 1000; tmr; tmr--) {			/* Wait for leaving idle state */
				if (send_cmd(cmd, 0) == 0) break;
				dly_us(1000);
			}
			if (!tmr || send_cmd(CMD16, 512) != 0)	/* Set R/W block length to 512 */
				ty = 0;
		}
	}
	CardType = ty;
	s = ty ? 0 : STA_NOINIT;
	Stat = s;

	deselect();

	return s;
}

anything missing here ?

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

We seem to be looking at different examples.

Show send_cmd(,) and rcvr_mmc(,)

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

I use the latest I downloaded from chan website

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

Quote:

Any clues ?

Did you not understand my post above. I said that all the FatFs functions return codes to say whether they worked or not (and often an indication of what went wrong). How is:

while(1)
   {
      disk_initialize (0);
   } 

actually testing the return code from the call to disk_initialize()? Also don't call it in a while(1). Do it just once before you enter your infinite loop. I suggest reporting the return value to UART or an LCD or something. If that isn't possible write it to EEPROM then inspect it after running the code by extracting EEPROM using ISP. Or if you have a debugger just break after the call to disk_initialize() and see what is in the return register(s).

Quote:

I tried with logic analyzer, but I can't see MOSI ?

Well that is a pretty fundamental problem. For disk_initiliaze() to complete with a "success" return code there needs to be visible activity on all of MOSI, MISO and SCK. So I'd start by looking at your wiring.

BTW something you said above worries me:

Quote:

My clock is 16Mhz and I change the code from 14 to 18Mhz
I use ATMEGA128.

You do know that an SD/MMC is a 3.3V not 5.0V device don' you? Now either you are just running the 3.3V chip at 16MHz which is out of spec. but will probably still work or you have made a big mistake and have connected to a 3.3V SD/MMC cad to a 5V system - there's a strong chance this may have damaged the memory card. (though they *may* have sufficient protection against this).

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

Yes I have used 3.3V already for SD/MMC.
I put disk_initialize on the loop so I can start logic analyzer when it's running, if I put one time only, I can't see on logic analyzer.....it's finished running before I start logic analyzer.

I can use UART, easy, I'll call my UART library

Is my port init correct ?


#define DO_INIT()					/* Initialize port for MMC DO as input */
#define DO			(PINB &	0x08)	/* Test for MMC DO ('H':true, 'L':false) */  (MISO)

#define DI_INIT()	DDRB  |= 0x04	/* Initialize port for MMC DI as output */         (MOSI)
#define DI_H()		PORTB |= 0x04	/* Set MMC DI "high" */
#define DI_L()		PORTB &= 0xFB	/* Set MMC DI "low" */

#define CK_INIT()	DDRB  |= 0x02	/* Initialize port for MMC SCLK as output */   (SCK)
#define CK_H()		PORTB |= 0x02	/* Set MMC SCLK "high" */
#define	CK_L()		PORTB &= 0xFD	/* Set MMC SCLK "low" */

#define CS_INIT()	DDRB  |= 0x01	/* Initialize port for MMC CS as output */      (SS)
#define	CS_H()		PORTB |= 0x01	/* Set MMC CS "high" */
#define CS_L()		PORTB &= 0xFE	/* Set MMC CS "low" */

Please have a look and correct me if there's a mistake...

Thanks

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

Do you redefine the direction of PB3 ? (By default the IO ports are set to be inputs after startup)
FatFs expects DO to be an input and you have not explicitly set it to be an input in DO_INIT()

Does CS go low to select the SDCard ?

The symbol F_CPU might not be defined which will cause dly_us() to not operate correctly.

Your SDCard might be faulty or not correctly connected.

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

I put it already on top and see what happens...
Yes it goes low, as I can see on logic analyzer..

#define F_CPU 16000000UL // 16 MHz

It's still the same, no MOSI only SCK an CS, I can see from logic analyzer..

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

Your logic analyzer should show 80 SCK with MOSI and CS high, then CS should go low and you should see hex 40 00 00 00 on MOSI and the SDCard should eventually respond.

As an experiment disconnect the SDCard and see if anything is being transmitted on MOSI.

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

Quote:

Yes I have used 3.3V already for SD/MMC.

Doesn't that mean that if the m128 is on 3.3V then running it at 16MHz is out of spec? Or are you employing level translators? If so I'd check the signals either side of that - maybe that's where the problem lies?

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

yup m128 on 5V,16MHz, I have no problem with the connector, because I have another SDcard software which is running fine, only want to do experiment with FATFs....not succeed yet....

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

Yes I can see CS,SCK,MOSI and MISO,

while(1)
	{
		disk_initialize (0);
		send_cmd(8, 0x1AA);
	}

any ideas for the next step to trace ?
thanks

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

Those SCK pulses look very irregular., not what I would expect.
I cannot decipher what that response code is and that CMD0 command doesn't look anything like hex 40 00 00 00 00 95
That capture also doesn't appear to agree with your test code because where does CS does go low for the CMD8 command ?

Quote:
... m128 on 5V,16MHz, I have no problem with the connector, because I have another SDcard software which is running fine, ...
does that mean that your other software works on this hardware that you are using to test Fatfs ?
As clawson said, the SDCard is a 3.6V device so if you're operating the micro on 5V then I'd expect the SDCard to have a 3.3V supply and some form of signal-level translators.

NOTE : Initialising an SDCard via the SPI interface has to be done at 400kHz maximum.

If you're running the Mega128 at 16MHz system clock then my rough estimate is that the bit-banged SPI is generating 4MHz clock pulses., way too high for the SDCard initialisation.
An easy way out is to use the clock divider (XDIV) in the M128 to reduce your speed during initialisation, then when disk_initialize() returns success you increase the system clock.

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

Yes I'm using 16Mhz, how can I make it 400KHz? How can I use XDIV ?
thanks

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

if you downloaded ffsample.zip (the 0.10a version) are you using avr_complex or avr_foolproof from it?

Looking at the avr_foolproof in sdmm.c he appears to be using bit-bang. I guess this is what makes it "foolproof" as it should still work on any AVR that doesn't have SPI. However, as it does NOT appear to be working for you I'd fall back to what we have all used in the past from previous versions of ffsample.zip (0.09 and previous). In that the AVR example is actually written for the mega64 (just small version of mega128) and it uses the hardware SPI.

So I'd use the avr_complex\mmc_avr.c file to provide the low level services. This uses the real SPI and it does this:

#define	FCLK_SLOW()	SPCR = 0x52		/* Set slow clock (F_CPU / 64) */
#define	FCLK_FAST()	SPCR = 0x50		/* Set fast clock (F_CPU / 2) */

The SLOW macro is used during disk_initialize. It will set the clock for SPI to be 16MHz/64 = 250kHz which should be "safe".

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

Quote:
if you downloaded ffsample.zip (the 0.10a version) are you using avr_complex or avr_foolproof from it?

I used avr_foolproof

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

Ok, I'll switch to avr_complex later on...from the name "complex"...make me abit nervous...because I want to test for the first time :)

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

The name "avr foolproof" was a lie then!

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

Kartman wrote:
The name "avr foolproof" was a lie then!

yea, it was

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

I diff'd the avr_complex and avr_foolproof directories (kdiff3 is nice for this - also "beyond compare"). In the common files there were a few differences. The "foolproof" is configured to have far less activated and the main difference is the main() test program that does not have the huge test harness of "complex" (and previous FatFs issues). The actual driver files have different names so are not directly comparable but, as I say, I'd be tempted to just take the SPI driver from complex and use the rest from foolproof.

It does seem to me that rather than split the files into two sets it might have been better to just have conditional compilation and an overall -D for COMPLEX/FOOLPROOF and similarly a -D to pick what driver to use.

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

so combine between complex and foolproof, only use the SPI setting from complex ?

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

Yes.

This is the joy of modular software. You can just "plug and play". Chan made the split himself between low and high level code and dictated that the application programming interface (API) that connects one to the other would simply be six routines called disk_initialize(), disk_status(), disk_read(), disk_write(), disk_ioctl() and get_fattime() (yeah I know!).

You can have ten different implementations of the low level "driver" for different devices (SD/MMC, CompactFlash, IDE-ATA hard drive, whatever) and as long as they all present the same API of those 6 routines to the higher level it doesn't care whether it's CompactFlash or SD/MMC it is "talking" to (this is exactly how "big systems" like Linux and Widows work too).

It just so happens that he supplies avr_foolproof/sdmm.c, avr_complex/mmc_bb.c, avr_complex/mmc_avr.c that are three different drivers, interfacing to SD/MMC in different ways but each providing that same API.

So you should just be able to "plug and play". Replace sdmm.c in the build with mmc_avr.c and the rest should work the same.

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

I'd better create a new project separate with avr_foolprof, so it's understandable...;)

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

I tried to compile avr_complex but got issue with :

Error 16 wide character array initialized from non-wide string C:\Users\antonius\Documents\Atmel Studio\6.1\FatFsAVR V1.1\FATFs_AVR_apps\FATFs_AVR_apps\main.c 185 3 FATFs_AVR_apps

const PROGMEM *p;
	static const PROGMEM str[] =
		"OK\0" "DISK_ERR\0" "INT_ERR\0" "NOT_READY\0" "NO_FILE\0" "NO_PATH\0"
		"INVALID_NAME\0" "DENIED\0" "EXIST\0" "INVALID_OBJECT\0" "WRITE_PROTECTED\0"
		"INVALID_DRIVE\0" "NOT_ENABLED\0" "NO_FILE_SYSTEM\0" "MKFS_ABORTED\0" "TIMEOUT\0"
		"LOCKED\0" "NOT_ENOUGH_CORE\0" "TOO_MANY_OPEN_FILES\0";

any workarounds ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
static const PROGMEM str[] = 

Just sit back and ask yourself what type the elements of that array are ;-)

(if you thought it was char you'd be wrong).

Also you do realise that what you are creating there is still just one long string not an array of strings right? To get to "WRITE_PROTECTED" for example you will have to start at the beginning of the string and count across ten 0x00 bytes to find the start of that "sub string". Is that really what you planned?

As the many articles about PROGMEM suggest the usual way to make an addressable array of strings in progmem is first to define each string separately as PROGMEM then also create an array of pointers to array (also in PROGMEM) that holds the flash start address of each string. Something like:

static const __flash char msg1[] = "OK";
static const __flash char msg2[] = "DISK_ERR";
static const __flash char msg3[] = "INT_ERR";
static const __flash char msg4[] = "NOT_READY";
static const __flash char msg5[] = "NO_FILE"; 
static const __flash char msg6[] = "NO_PATH"; 
etc.

static const __flash char * strings[] = {
   msg1, msg2, msg3, msg4, msg5, msg6
};

Also you are using PROGMEM - is your compiler too old to use the better __flash then?

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

bianchi77 wrote:
Kartman wrote:
The name "avr foolproof" was a lie then!

yea, it was

You can usually figure "Foolproof" is an exaggeration. Interpret it to mean, "someone with half a brain can make it work," except I usually find myself on the wrong side of that boundary.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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

The 'foolproof' (software SPI) port has a diagram that shows the processor running at 8MHz. (not 16MHz as the OP used)
The SDCard was not labelled, but it is plausible that it does not strictly adhere to the official specs and can be initialised with a >400kHz SCK.

Last Edited: Thu. Feb 20, 2014 - 07:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried to compile avr_complex, it worked but after I uploaded to my board it didn't give me any responses on uart ?
any clues ?

Please have a look on the file I compiled,
I used atmel studio 6.1

Attachment(s): 

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

Quote:
any clues ?

FAQ#3

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

do you mean this one ?

#define F_CPU 16000000UL    // AVR clock frequency in Hz, used by util/delay.h

#include 
#include 
#include "uart.h"

#define	UART_BPS		115200
#define	UART_BUFF		64

I put 16MHz crystal and set the fuse to external clock already...anything else missing ?

thanks

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

Park FatFs for the time being. Just try a simple UART test. Does it work?

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

clawson wrote:
Park FatFs for the time being. Just try a simple UART test. Does it work?

Is this the right init for atmega128 ?

void uart_init (uint32_t bps)
{
	UCSR0B = 0;

	PORTE |= _BV(1); DDRE |= _BV(1);	/* Set TXD as output */
	DDRE &= ~_BV(0); PORTE &= ~_BV(0); 	/* Set RXD as input */

	RxFifo.ct = 0; RxFifo.ri = 0; RxFifo.wi = 0;
	TxFifo.ct = 0; TxFifo.ri = 0; TxFifo.wi = 0;

	UBRR0L = F_CPU / bps / 16 - 1;
	UCSR0B = _BV(RXEN0) | _BV(RXCIE0) | _BV(TXEN0);
}

I tried my other init code which is working in another software but not in FATFs code

void usart_init( unsigned int ubrr )
{
	/* Set baud rate */

	UBRR0H = (unsigned char)(ubrr>>8);
	UBRR0L = (unsigned char)ubrr;
	/* Enable receiver and transmitter */
	UCSR0B = (1<<RXEN)|(1<<TXEN);
	/* Set frame format: 8data, 2stop bit */
	UCSR0C = (1<<USBS)|(3<<UCSZ0);
}

I couldn't get what missing here ?

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

Don't mess with DDR/PORT when using UART, on mega (but not Xmega) as soon as you TXEN / RXEN the UART takes control of the pin and sets direction anyway. Why not read the UART threads in the Tutorial Forum?

Also don't go trying to mess with interrupts until you get simple, synchronous, polling code working first.

Also why would anyone set 2 stop bits? In 2014 almost every UART device on planet Earth is 8N1 which means you never need to touch the C control register.

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

The first function I got it from FatFS example the second one I created myself,

To turn uart on,

UBRR0H = (unsigned char)(ubrr>>8);
   UBRR0L = (unsigned char)ubrr;
   /* Enable receiver and transmitter */
   UCSR0B = (1<<RXEN)|(1<<TXEN); 

Which interrupt you're talking about ?
I don't play with interrupt ..?? do I ?

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

I rewrite it :

void uart_init (uint32_t bps)
{
	//UCSR0B = 0;

	RxFifo.ct = 0; RxFifo.ri = 0; RxFifo.wi = 0;
	TxFifo.ct = 0; TxFifo.ri = 0; TxFifo.wi = 0;

	
	/* Set baud rate */

	UBRR0H = (unsigned char)(bps>>8);
	UBRR0L = (unsigned char)bps;
	/* Enable receiver and transmitter */
	UCSR0B = (1<<RXEN)|(1<<TXEN);

}

am I right until this point ? thanks

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

You have heard of the Tutorial Forum I take it?

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

The routines in uart.c use interrupts to receive and transmit characters.
Not enabling the receive interrupt in uart_init() will stop you from receiving characters via uart_getc() and uart_getline() and because they do not have a timeout your program will stall when you read a character/line.

Important question : Can you transmit a string of known characters (eg to a PC) ?

In main.c of your 700kbyte zipped project (of which 699kb was unnecessary .o .d .elf .hex .lss and Fatfs code, but I digress), there is a uart_init(9600) and what puzzles me now is what you are doing with your modified uart_init(uint32_t bps).
You do not show how you are calling that modified uart_init(uint32_t bps) but if you are doing uart_init(9600) then please read the datasheet about the baudrate divider, or look at what your uart_init (uint32_t bps) (5 posts back) does to UBRR0.

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

this is the original function from avr_complex example,
I'm not sure it's working with atmega128, I got no response...

void uart_init (uint32_t bps)

{
	UCSR0B = 0;

	//PORTE |= _BV(1); DDRE |= _BV(1);	/* Set TXD as output */
	//DDRE &= ~_BV(0); PORTE &= ~_BV(0); 	/* Set RXD as input */

	RxFifo.ct = 0; RxFifo.ri = 0; RxFifo.wi = 0;
	TxFifo.ct = 0; TxFifo.ri = 0; TxFifo.wi = 0;

	UBRR0L = F_CPU / bps / 16 - 1;
	UCSR0B = _BV(RXEN0) | _BV(RXCIE0) | _BV(TXEN0);
	
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tested the uart function with avr_foolproof,
it's working.....

Please have a look on the code I uploaded,

cheers

Attachment(s): 

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

Quote:

I tested the uart function with avr_foolproof,
it's working.....


OK so what happens when you now add the SPI driver from "complex" to that? Surely you then have the solution you are looking for with working UART code?

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

I change the driver to SPI
Please advice if I need to do something else ?

Attachment(s): 

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

I got until this step, please have look on the attachment, what's the next level ?....

Attachment(s): 

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

shall I format the SDcard to FAT32 ? I have 1Gb Sdcard....

Attachment(s): 

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

now it's stopping until :

f_mount(&FatFs, "", 0);		/* Give a work area to the default drive */
    usart_pstr("FMOUNT \n");
	if (f_open(&Fil, "newfile.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {	/* Create a file */

On terminal :

TEST FAT FS
MAIN
FMOUNT
POWER ON
DISK INITIALIZE SUCCEDED!
DISK INITIALIZE FINISHED

it can't do f_open, why is it ?
any clues guys ?

Thank you

Pages