Posted by NilRecurring: Tue. Feb 21, 2012 - 01:49 PM
1
2
3
4
5
Total votes: 0
Lately, I've been trying to shift over to Eclipse (just to see how it is compared to AVR Studio v4) but when I import all the FatFS files and my main.c, I get the following error on every function declaration in xitoa.h
../xitoa.h:27:28: error: expected ';', ',' or ')' before '*' token
Here's an example function declaration in xitoa.h
void xputs(const prog_char *string);
Anybody have any idea what this could be? This isn't happening in AVR Studio v4 at all. I am able to compile and read/write to SD Cards.
AVR-LibC version is 1.8.0. For what it's worth, I'm trying to use CrossPack-AVR on the Mac.
Then you are one of the first to be hit by this newly restructured PROGMEM support that looks like it's going to break a LOT oflegacy code. See the threads in GCC forum about GCC 4.7 and specifically those from SprinterSB to understand what's happening.
(this would now be more on-topic for one of those threads than this FatFs tutorial).
First off, thanks for a great guide. It helped me very much in getting the FatFS running! Good work!
I have a few questions that I hope you guys can help me with.
I get error 9(The file/directory object is invalid) when ever I use either f_puts or f_printf, some times the f_printf gives error 21, which I don't know what means.
for some reason I could not post the correct FORMAT_STRING in code, but it is: percent s, percent ld, percent s
The wierd thing is that all the text and numbers are printed to the file, so the functions are doing what they are supposed to. But why is the error not equal 0 then?
My second question:
In my project I need to sample two adc channels with 500-1000Hz, write the data to SD card and transfer the same data through zigbee (Atmega128RFA1). I know it might be impossible to save to sd and write to zigbee in less time then 1ms (1000hz sample rate) but none the less is this my end goal...
So I would like to create a buffer that fills one sector and flushes it to the SDcard (and possible to the zigbee as well).
I don't know how to do this, I am not quite sure if the FatFS contains a buffer system that I can use for this purpose?
Again thanks for a great guide and good support :)
Will it automatically flush the data when the buffer is full or should I do that manually?
I guess I could sample the adc, put the result into the buffer[i++] and when the buffer is full (i=511) flush the data (f_sync)?
I would like to write the two adc values countinuesly to a single file, so it will be easy to extract the data from the SDcard to excel/labview.
Will it automatically flush the data when the buffer is full or should I do that manually?
It does it - that's the nature of the beast - it always holds the sector it's currently "working on" in that buffer.
I would not access the buffer directly to write to it (use the f_put/f_write/etc. functions to do that) but you may want read access if you want to send a copy to a different destination. You may even want to "hack" ff.c so it calls-back your own function each time before it discards the buffer.
Hello, I have a project where I need to log data quickly to a SD/SDHC card. I don't plan on using a file system for now (I assume the overhead would make things slow down too much), and I believe I understand the SD card protocols well enough, but the actual specifications of the SD cards themselves are confusing me.
In short, many SD cards claim sustained write speeds of over 10MB/s, while in their documentation they will then say that it takes at least several milliseconds for a write operation to complete (I assume this refers to one block of 512 bytes). This seems to be a big contradiction, so I'm left unsure of what write speeds to expect from a given card. My goal is to get a sustained speed of at least 500KB/s, hopefully near 1MB/s. I've got a AT32UC3 with a 30MHz SPI and a couple DMA channels, and I've read that other people have achieved this with similar hardware (though some have not, and I assume the SD card itself is a big reason).
Does anyone here understand the SD card specs well enough to actually know what determines their write speeds (in SPI mode)? Does anyone have any recommendations of SD/SDHC card models which are known to get the write speeds I need?
There's a difference between using these cards in SPI mode (which is compatible with MMC) and in the 4bit SD mode. For the latter you need to become a licensee of the SD association to gain access to the docs. (though a recent thread suggests that even MMC mode requires licensing). For typical MMC speeds see:
There's a difference between using these cards in SPI mode (which is compatible with MMC) and in the 4bit SD mode. For the latter you need to become a licensee of the SD association to gain access to the docs. (though a recent thread suggests that even MMC mode requires licensing).
Well I'm planning on using SPI mode, not the 4 bit SD mode.
I think I've seen this same link come up in my previous searches, but it just redirects me to the homepage of yahoo.com.
My fundamental question is how can I look at the specifications of a card (I'm talking about the contents of its CSD register, not just its speed class or whatever) and use that to estimate what write speeds are attainable with SPI mode. Of course the SPI interface will degrade the attainable speed somewhat, but from what I've read the real bottleneck is usually in the SD card itself, specifically its program times.
If I can't get that answered, then I'd at least like to know of some card models which people have good experience with (and are capable of my desired speed).
I doubt the card's own write speed wil be the bootle-neck, it's how fast you can feed data to the card that will probably limit it (of course UC3 probably have more "oomph" in this sense than AVR).
I'd love to believe that the card won't be a bottleneck, but everything I've read by people who have actually used them says otherwise. Lots of people are using a 20MHz SPI clock with DMA control, but most people seem limited to a few hundred KB/s (while a few have been able to get speeds in excess of 1MB/s). I've read that the dominant bottleneck is just the time it takes for the card to go idle after a write is performed, so another write can begin.
Posted by NilRecurring: Tue. Mar 13, 2012 - 12:48 PM
1
2
3
4
5
Total votes: 0
A small question - I'm using FatFs on an SD Card and I also have 10 other devices on the SPI bus (all CPLDs). The very first thing that my program does is initialize the SD Card. I note that FatFs library contains the following macro.
Quote:
#define FCLK_FAST() SPCR = 0x50
which it calls after initialization succeeds. This equals about 2MHz on my AVR Mega 1281. But after the initialization, I setup SPI for my CPLDs - in this particular routine, I set my SPI speed to just 62.5KHz.
My question is, will the FatFs library now be operating at 62.5KHz? I don't think FCLK_FAST() is called anywhere else, so if I initialize the card the speed is set to 2MHz. I then call my function setupSPI() which sets the SPI speed to 62.5KHz. I then read from the SD Card and also read from the CPLDs. Unless the SPCR register is set again to 0x50, I don't think my SD Card is working at 2MHz. Am I correct?
I should add, the system is working very well. However, I have to extend the system to operate on a larger dataset - hence my concern about read/write speeds.
My question is, will the FatFs library now be operating at 62.5KHz?
Yes.
Quote:
I don't think FCLK_FAST() is called anywhere else
I agree.
You could, I guess pepper FatFs with more calls to FCLK_FAST() (perhaps in the power_on routine?) and then setupSPI() when its deselected (power_off ?) or simply accept the 62.5kHz for SD access.
As with all optimizations I wouldn't actually bother until they actually become necessary - worry about this when you get to the point of believing that the file cannot be written quickly enough.
doesn't seem consistent with this tutorial. For example:
Quote:
Continuing on, modify the #define SELECT() and #define DESELECT() as so:
There are no such lines in mmc.c--now they are functions:
static
void deselect (void)
{
CS_HIGH();
xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
}
/*-----------------------------------------------------------------------*/
/* Select the card and wait for ready */
/*-----------------------------------------------------------------------*/
static
int select (void) /* 1:Successful, 0:Timeout */
{
CS_LOW();
xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
if (wait_ready()) return 1; /* OK */
deselect();
return 0; /* Timeout */
}
I think I can still figure out what needs to be done, but is the older on which this tutorial was based still available? Or should I just use the newer version and expect only trivial differences?
As I ran into more or less the same thing that a lot has changed, I write here what things I changed in order to get FatFs version 0.09b to work.
you can download it from: http://elm-chan.org/fsw/ff/00index_e.html
On the bottom of this page you can download the "FatFs sample projects"
This is a zip file with all the projects for a lot of different processors.
From this zip file I used the "avr" folder.
I used Atmel Studio 6.0(AS6)
I have a self made board with a Atmega1281 on it.
First step is to make a new project in AS6.
Copy the following files from the AVR folder to the project folder:
- cc932_avr.c (from unicode sub directory)
- diskio.h ,
- ff.c ,
- ff.h ,
- ffconf.h ,
- integer.h ,
- main.c ,
- mmc.c ,
- rtc.c ,
- rtc.h ,
- uart.c ,
- uart.h ,
- xitoa.h ,
- xitoa.s ,
Now I have made the following changes to the files to get them to work for me:
I made a board.h file that holds a number of board specific parameters. See file for details.
In the file "cc932_avr.c"
There are 4 references do the datatype "prog_uint16_t"
as this datatype is no longer supported int the atmel studio it must be changed.
from top to bottom thrue the file:
#define FCLK_SLOW() SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(0<<SPR0) /* Set slow clock (F_CPU / 32) */
#define FCLK_FAST() SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0) /* Set fast clock (F_CPU / 8) */
The functions "power_status, power_on and power_off" are replaced byt the following block:
static
int power_status (void) /* Socket power state: 0=off, 1=on */
{
return (MMC_PWR_PIN & ~(1<<MMC_PWR_LOC)) ? 0 : 1; // if the power pin is high power is OFF
}
static
void power_on (void)
{
MMC_PWR_PORT |= (1<< MMC_PWR_LOC); // make power pin high to cut power
CS_LOW(); // make chip select line also low to not power it through that
for (Timer1 = 10; Timer1; ); /* Wait for 100ms */
MMC_PWR_PORT &= ~(1<< MMC_PWR_LOC); // make power pin low to apply power
CS_HIGH(); // disable chip select
//initialize the SPI bus;
SPSR = (1<<SPI2X); // speed = x2
FCLK_SLOW();
}
void power_off (void)
{
Stat |= STA_NOINIT; /* Set STA_NOINIT */
MMC_PWR_PORT |= (1<< MMC_PWR_LOC); // make power pin high to power off
CS_LOW(); /* Wait for card ready */
}
In the file "main.c"
I removed the include for "sound.h" as I do not have sound available.
I also removed the "FUSES" definition as I use another processor and prefer to set those one time and set them myself.
As I use timer0 instead of timer2 I changed the interrupt vector for that and also the initialization in the "ioinit" function.
Also in this file a number of references to "prog_char" have to be changed to char + PROGMEM.
A new function is added for PIO Init. The original program does this in the ioinit function, you need to set these things correct for you specific design.
with these changes done you should be able to run the example project on your system.
Just to say that there are a couple of ways to approach this. In response to a thread here the other day I too downloaded 0.09b but rather than the generic:
which is linked as "FatFs sample projects" as this possibly starts closer to what you probably want to do than the generic file which, as meslomp's post shows, may require more work. Within the "Samples" archive is an AVR sub-folder that contains:
That has support for building a number of targets but it's only the "mmc" variant that an AVR user will be interested in. So one can start by removing a majority of the files of no immediate relevance (personally I use a Subversion repository so I can easily get back anything that I modify or delete in error). Just retain the following files (in fact the uart.* are also optional):
static
int power_status (void) /* Socket power state: 0=off, 1=on */
{
return 1;
}
as my wiring did not include power control. Also:
static
void power_on (void)
{
{ /* Remove this block if no socket power control */
PORTE &= ~_BV(7); /* Socket power on (PE7=low) */
DDRE |= _BV(7);
for (Timer1 = 2; Timer1; ); /* Wait for 20ms */
}
PORTB |= 0b00000101; /* Configure SCK/MOSI/CS as output */
DDRB |= 0b00000111;
SPCR = 0x52; /* Enable SPI function in mode 0 */
SPSR = 0x01; /* SPI 2x mode */
}
static
void power_off (void)
{
SPCR = 0; /* Disable SPI function */
DDRB &= ~0b00110111; /* Set SCK/MOSI/CS as hi-z, INS#/WP as pull-up */
PORTB &= ~0b00000111;
PORTB |= 0b00110000;
{ /* Remove this block if no socket power control */
PORTE |= _BV(7); /* Socket power off (PE7=high) */
for (Timer1 = 20; Timer1; ); /* Wait for 20ms */
}
}
to be:
static
void power_on (void)
{
PORTB |= SS | MOSI; /* Configure SCK/MOSI/CS as output */
DDRB |= SS | SCK | MOSI;
SPCR = 0x52; /* Enable SPI function in mode 0 */
SPSR = 0x01; /* SPI 2x mode */
}
static
void power_off (void)
{
SPCR = 0; /* Disable SPI function */
DDRB &= ~(SS | SCK | MOSI); /* Set SCK/MOSI/CS as hi-z, INS#/WP as pull-up */
PORTB &= ~(SS | SCK | MOSI);
#if 0 // not using CP / WP
PORTB |= 0b00110000;
#endif
}
That's because I wasn't using Card Present or Write Protect signals and I just think it's easier to document the setting of I/O bits using symbols rather than meaningless 0b101010111 style values.
The point here is that you edit mmc.c to reflect how you have things wired.
Note also that the 0.09b files have an error that Chan has inadvertently introduced. It's easiest to just add the #if/#endif to remove the whole thing:
#if 0
case CTRL_ERASE_SECTOR : /* Erase a block of sectors (used when _USE_ERASE == 1) */
if (!(CardType & CT_SDC)) break; /* Check if the card is SDC */
if (disk_ioctl(drv, MMC_GET_CSD, csd)) break; /* Get CSD */
if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; /* Check if sector erase can be applied to the card */
dp = buff; st = dp[0]; ed = dp[1]; /* Load sector block */
if (!(CardType & CT_BLOCK)) {
st *= 512; ed *= 512;
}
if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 && send_cmd(CMD38, 0) == 0 && wait_ready(30000)) /* Erase sector block */
res = RES_OK; /* FatFs does not check result of this command */
break;
#endif
2) ffconf.h
Everyone who uses FatFs is going to have different requirements. Personally I edited the following lines:
#define _FS_MINIMIZE 1 /* 0 to 3 */
#define _USE_STRFUNC 1 /* 0:Disable or 1-2:Enable */
#define _USE_MKFS 0 /* 0:Disable or 1:Enable */
#define _USE_LABEL 0 /* 0:Disable or 1:Enable */
#define _CODE_PAGE 1
#define _VOLUMES 1
Of those I think it's only the last two that almost everyone will probably edit. The _CODE_PAGE one to reduce reliance on international (probably Japanese) character sets and the _VOLUMES one as almost everyone using FatFs probably only has one SD/MMC card attached, not two.
3) something.c
You need to write some C code to actually do something with FatFs. The following is a very simply example that simply opens a file called "poem.txt" and outputs the lines of text that it contains:
#include
#include
#include "diskio.h"
#include "ff.h"
#include "uart.h"
FATFS fs;
FIL fin;
char line[80];
char sec[512];
int main(void)
{
FRESULT res;
OCR0 = 0xB3; // avrcalc says that at 3.6864MHz that /8 and CTC 0xB3 will give 10ms
TIMSK = (1 << OCIE0); // use COMP interrupt
TCCR0 = (1 << WGM01) | (1 << CS01); // CTC with div 8
sei();
if (disk_initialize(0) == STA_NOINIT) {
while(1);
}
res = f_mount(0, &fs);
if (res == FR_OK) {
res = f_open(&fin, "poem.txt", FA_OPEN_EXISTING | FA_READ);
if (res == FR_OK) {
do {
f_gets(line, sizeof(line), &fin);
UART_puts(line);
UART_put('\r');
} while (!f_eof(&fin));
f_close(&fin);
}
}
while(1)
{
}
}
ISR(TIMER0_COMP_vect) {
disk_timerproc();
}
DWORD get_fattime (void)
{
/* Pack date and time into a DWORD variable */
return ((DWORD)(2013 - 1980) << 25)
| ((DWORD)3 << 21)
| ((DWORD)23 << 16)
| ((DWORD)12 << 11)
| ((DWORD)0 << 5)
| ((DWORD)0 >> 1);
}
The two key things here that all FatFs programs will have are:
(a) you need to start a timer with a 10ms period and each time it expires call disk_timerproc()
(b) you need to provide the get_fattime() function that ff.c will call to time stamp files. If you don't have an RTC then just return a fixed date/time as shown here. You shouldn't need anything from any kind of rtc.h/rtc.c as this function alone is the only API that FatFs will attempt to call. In fact it could be even simpler - just return 0.
I was wondering whether anybody was able to successfully run the ffsample (version 0.09b of FatFS) program for AVR and use the 'fr' and 'fd' commands.
It appears that the mem_cpy calls in f_read might be causing an MCU restart, possibly as these overwrite areas in RAM that they should not. I tried to run ffsample without other modifications than a simple port to ATMega644: in particular ffconf.h is as per zip provided by ChaN. The sequence of commands I tried was:
di 0
fi 0
fo 1 test.bin
fd 512
<- MCU restarts here
The same thing happens if I try the WAV playback command or data read one:
p file.wav
fr 512
If you had more luck than myself, I'd be grateful to know :)
Thank you!
It worked second try. At first, it failed "no init." I checked lines, checked my pin definitions in mmc.c, checked with an ohm meter. Then thought, "This came from a phone, I wonder how it's formatted." So I formatted it fresh (2GB with 16KB blocks) and put my poem.txt and... WOW, it shows my parnassian attempt on the display!
I am having lots of errors when I try to run the code after making these changes - functions like uart_putc and uart_getc are undefined, and variable type prog_char is not defined. Any ideas as to what I am doing wrong?
Well the uart functions aren't needed so remove anything that calls those. As for prog_char, that's deprecated in the latest compiler as it only ever worked by accident. Just use PROGMEM on char.
This is just an update of my post above to reflect that things have moved on a bit. I did the following using the Jun22 2013 copy of ffsample.zip from the FatFs site and the current issue of Studio 6 which is 6.1 with Service Pack 1.1 that is 6.1.2674
From ffsample.zip I just extracted the "avr" subdirectory and ignored everything else. This gave me:
I added those to a local SVN so I could track changes and recover anything I delete or change in error.
As I'm only interested in SD/MMC using the SPI interface most of these files are not relevant so, like last time, I cut them down using svn-delete to be:
E:\ffsamp-jun22\avr>dir /o
Volume in drive E is VBOX_windows
Volume Serial Number is 0000-0801
Directory of E:\ffsamp-jun22\avr
23/03/2013 23:20 2,890 diskio.h
24/01/2013 00:06 147,958 ff.c
24/01/2013 00:06 13,063 ff.h
16/02/2013 11:58 7,632 ffconf.h
24/04/2010 23:45 856 integer.h
22/06/2013 09:47 20,470 main.c
23/03/2013 23:42 3,207 Makefile_mmc
22/06/2013 09:43 17,920 mmc.c
22/01/2013 00:59 1,954 uart.c
22/01/2013 00:58 349 uart.h
08/06/2011 22:17 3,086 xitoa.h
15/07/2012 19:36 9,905 xitoa.S
That's still too many files as I don't really intend to use the Makefile and I'm not sure about the uart.* files but I'll cut things down further later.
Next I wanted to make this into an AS6 project. Unfortunately AS6 has a habit of creating things you don't actually want and won't create a project within a directory that already exists when you create a new project but undeterred I told it to create a new GCC C project.
Now I wanted it to use the \ffsamp-jun22\avr directory where I already had files so I pointed "Location:" to the ffsamp-jun22 directory and asked for the project to be called "FatfsAVR" and un-ticked the "Create directory for project" button. I arbitrarily chose to make the project for atmega32 as that's what I happened to have plugged into my STK500 with SD/MMC socket attached. This created a file called FatfsAVR.c in \ffsamp-jun22\FatfsAVR\ directory so at this stage my tree of files looked like this:
My plan here is not to use the FatFs supplied main.c but, instead, put a small driving test program into the FatfsAVR.c file that AS6 just created.
So next I need to make AS6 aware of the files I want compiled into the project. In the Solution Explorer I right-click the FatfsAVR project and from the Context menu use "Add" and within that "Existing item...". I then select "ff.c", "mmc.c", "uart.c" and "xitoa.S" using the "Add as link" option on the dialog's add button (don't just use [Add] or those files will be copied from the "avr" subdirectory" to the "FatfsAVR" directory.
If I try to build at this stage I get errors about PORTE being used in mmc.c. This is because the Chan supplied code is intended for a mega64 and I am building for a mega32. So, just as in my previous post, I will make some modifications to mmc.c. In Chan's code where PORTE is used he has comments such as:
{ /* Remove this block if no socket power control */
PORTE &= ~_BV(7); /* Socket power on (PE7=low) */
DDRE |= _BV(7);
for (Timer1 = 2; Timer1; ); /* Wait for 20ms */
}
As I'm not going to use socket power control I will follow this advice and remove anything that makes access to PORTE. I also modify power_status() so it always returns 1. And I apply changes as shown in my previous message to configure things for the SPI pins on mega32. SVN tells me that what I changed was:
Index: mmc.c
===================================================================
--- mmc.c (revision 14)
+++ mmc.c (working copy)
@@ -7,8 +7,13 @@
/* Port controls (Platform dependent) */
-#define CS_LOW() PORTB &= ~1 /* CS=low */
-#define CS_HIGH() PORTB |= 1 /* CS=high */
+#define SS (1<<PB4)
+#define MOSI (1<<PB5)
+#define MISO (1<<PB6)
+#define SCK (1<<PB7)
+
+#define CS_LOW() PORTB &= ~SS /* CS=low */
+#define CS_HIGH() PORTB |= SS /* CS=high */
#define SOCKINS (!(PINB & 0x10)) /* Card detected. yes:true, no:false, default:true */
#define SOCKWP (PINB & 0x20) /* Write protected. yes:true, no:false, default:false */
#define FCLK_SLOW() SPCR = 0x52 /* Set slow clock (F_CPU / 64) */
@@ -63,21 +68,15 @@
static
int power_status (void) /* Socket power state: 0=off, 1=on */
{
- return (PORTE & _BV(7)) ? 0 : 1;
+ return 1;
}
static
void power_on (void)
{
- { /* Remove this block if no socket power control */
- PORTE &= ~_BV(7); /* Socket power on (PE7=low) */
- DDRE |= _BV(7);
- for (Timer1 = 2; Timer1; ); /* Wait for 20ms */
- }
+ PORTB |= SS | MOSI; /* Configure SCK/MOSI/CS as output */
+ DDRB |= SS | SCK | MOSI;
- PORTB |= 0b00000101; /* Configure SCK/MOSI/CS as output */
- DDRB |= 0b00000111;
-
SPCR = 0x52; /* Enable SPI function in mode 0 */
SPSR = 0x01; /* SPI 2x mode */
}
@@ -87,14 +86,8 @@
{
SPCR = 0; /* Disable SPI function */
- DDRB &= ~0b00110111; /* Set SCK/MOSI/CS as hi-z, INS#/WP as pull-up */
- PORTB &= ~0b00000111;
- PORTB |= 0b00110000;
-
- { /* Remove this block if no socket power control */
- PORTE |= _BV(7); /* Socket power off (PE7=high) */
- for (Timer1 = 20; Timer1; ); /* Wait for 20ms */
- }
+ DDRB &= ~(SS | SCK | MOSI); /* Set SCK/MOSI/CS as hi-z, INS#/WP as pull-up */
+ PORTB &= ~(SS | SCK | MOSI);
}
Having cleared errors in mmc.c I then get errors in uart.c. I figure it is worth making it work for mega32 so I modify it as follows (also adding a definition of F_CPU=3686400 to the project symbols):
At this stage the project now builds without error. However there is nothing in main() actually calling any FatFs function and ffconf.h needs to be edited. If I turn off Linker garbage collection the project builds to :
Program Memory Usage : 21350 bytes 65.2 % Full
Data Memory Usage : 280 bytes 13.7 % Full
After making the following edits to ffconf.h:
Index: ffconf.h
===================================================================
--- ffconf.h (revision 14)
+++ ffconf.h (working copy)
@@ -26,7 +26,7 @@
/ f_truncate and useless f_getfree. */
-#define _FS_MINIMIZE 0 /* 0 to 3 */
+#define _FS_MINIMIZE 1 /* 0 to 3 */
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/
/ 0: Full function.
@@ -36,11 +36,11 @@
/ 3: f_lseek is removed in addition to 2. */
-#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */
+#define _USE_STRFUNC 1 /* 0:Disable or 1-2:Enable */
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
-#define _USE_MKFS 1 /* 0:Disable or 1:Enable */
+#define _USE_MKFS 0 /* 0:Disable or 1:Enable */
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
@@ -48,7 +48,7 @@
/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
-#define _USE_LABEL 1 /* 0:Disable or 1:Enable */
+#define _USE_LABEL 0 /* 0:Disable or 1:Enable */
/* To enable volume label functions, set _USE_LAVEL to 1 */
@@ -60,7 +60,7 @@
/ Locale and Namespace Configurations
/----------------------------------------------------------------------------*/
-#define _CODE_PAGE 932
+#define _CODE_PAGE 1
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
@@ -127,7 +127,7 @@
/ Physical Drive Configurations
/----------------------------------------------------------------------------*/
-#define _VOLUMES 2
+#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
that changes to be:
Program Memory Usage : 16232 bytes 49.5 % Full
Data Memory Usage : 166 bytes 8.1 % Full
Now I just need some code in the main() function. I edited FatfsAVR.c to be very like the main file from the previous thread, that is:
/*
* FatfsAVR.c
*
* Created: 11/07/2013 16:16:42
* Author: cliff
*/
#include
#include
#include "../avr/diskio.h"
#include "../avr/ff.h"
#include "../avr/uart.h"
void uart_puts(char * str);
FATFS fs;
FIL fin;
char line[80];
char sec[512];
int main(void)
{
FRESULT res;
OCR0 = 0xB3; // avrcalc says that at 3.6864MHz that /8 and CTC 0xB3 will give 10ms
TIMSK = (1 << OCIE0); // use COMP interrupt
TCCR0 = (1 << WGM01) | (1 << CS01); // CTC with div 8
sei();
if (disk_initialize(0) == STA_NOINIT) {
while(1);
}
res = f_mount(0, &fs);
if (res == FR_OK) {
res = f_open(&fin, "poem.txt", FA_OPEN_EXISTING | FA_READ);
if (res == FR_OK) {
do {
f_gets(line, sizeof(line), &fin);
uart_puts(line);
uart_putc('\r');
} while (!f_eof(&fin));
f_close(&fin);
}
}
while(1)
{
}
}
ISR(TIMER0_COMP_vect) {
disk_timerproc();
}
void uart_puts(char * str) {
while (*str) {
uart_putc(*str++);
}
}
DWORD get_fattime (void)
{
/* Pack date and time into a DWORD variable */
return ((DWORD)(2013 - 1980) << 25)
| ((DWORD)3 << 21)
| ((DWORD)23 << 16)
| ((DWORD)12 << 11)
| ((DWORD)0 << 5)
| ((DWORD)0 >> 1);
}
I switched garbage collection back on so the link would only include the functions that were called and this gave a final:
Program Memory Usage : 11086 bytes 33.8 % Full
Data Memory Usage : 1364 bytes 66.6 % Full
I've still got to actually test this but that looks pretty reasonable. The full project dir I used is zipped and attached.
I've now tested that and it works but I did have to make this following change that I had forgotten above (because I don't use the card inserted and write protect signals):
OCR0 = 0xB3; // avrcalc says that at 3.6864MHz that /8 and CTC 0xB3 will give 10ms
Probably not fundamental, but I thought to mention this. With a divider of just 8 and a 3.6864 MHz clock, an 8-bit compare value is not enough to trigger a compare interrupt every 10ms.
Shouldn't the prescaler be 256 and OCR0 preloaded with 0x8F?
@clawson: can you please try the f_read function after opening a file for read? It wouldn't have to do anything complex, just read a few bytes and show them:
BYTE buff[5], i;
UINT br;
...
res = f_open(&fin, "poem.txt", FA_OPEN_EXISTING | FA_READ);
if (res == FR_OK) {
res = f_read (&fin, (void *)buff, 5, &br);
if (res == FR_OK)
for (i = 0; i < br; i++)
uart_putc (buff[i]);
f_close (&fin);
}
@clawson: can you please try the f_read function after opening a file for read?
It appears that I am using a toolchain for which your project does not work. As it's an old toolchain from a few years back (Win AVR), I will try to update that first and then retry.
Edit: yes, even ChaN's example works now that I moved to the latest AVR toolchain.
Posted by HellsGuardian: Fri. Aug 2, 2013 - 06:10 AM
1
2
3
4
5
Total votes: 0
I get this error after i replace the power_off function with the one author gave i.e
static
void power_off (void)
{
SELECT(); /* Wait for card ready */
wait_ready();
release_spi();
Stat |= STA_NOINIT; /* Set STA_NOINIT */
}
This function has wait_ready..
well the samples.zip i downloaded seems to have a bit different code. e.g in this tutorial author said to comment the lines from PORTA to PORTG in main.c The code in your file (even though it is commented but for the sake of comparison) is different from what i have. Notice the values of Ports are different in the file i have.
static
void ioinit (void)
{
/* Pull-up all GPIO pins */
PORTA = 0b11111111; // These values are different
PORTB = 0b11111111;
PORTC = 0b11111111;
PORTD = 0b11111111;
PORTE = 0b11111111;
PORTF = 0b11111111;
PORTG = 0b00011111;
/* Start 100Hz system timer (TC2.OC) */
OCR2 = F_CPU / 1024 / 100 - 1;
TCCR2 = 0b00001101;
TIMSK |= _BV(OCIE2);
// No rtc_init(); here <<
sei();
}
next he mentioned to modify the #define SELECT() and #define DESELECT() but in my mmc.c There are no such defines... i have two functions for select and deselect though
static
void deselect (void)
{
CS_HIGH();
xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
}
/*-----------------------------------------------------------------------*/
/* Select the card and wait for ready */
/*-----------------------------------------------------------------------*/
static
int select (void) /* 1:Successful, 0:Timeout */
{
CS_LOW();
xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
if (wait_ready(500)) return 1; /* OK */
deselect();
return 0; /* Timeout */
}
Then it has SOCKWP and SOCKINS defines but no SOCKPORT. Also there is no such function chk_power(void) in my file. Are the files in avr directory updated/changed?
Edit: my AVR studio 5 does not seems to be detecting BOOL in rtc functions i.e:
BOOL rtc_settime (const RTC *rtc)
It says: Error 1 expected '=', ',', ';', 'asm' or '__attribute__' before 'rtc_gettime'
and using the replaced uart code it says: too many arguments to function 'uart_init'
Are you talking about page 1? You are only ready to start when you have read through ALL fifteen pages as there have been many updates as Chan has changed his code over the years.
For example I made this update post on Jul 11 this year using Chan's code from Jun 22nd this year:
Posted by HellsGuardian: Fri. Aug 2, 2013 - 11:43 AM
1
2
3
4
5
Total votes: 0
clawson wrote:
Quote:
this tutorial author said
Are you talking about page 1? You are only ready to start when you have read through ALL fifteen pages as there have been many updates as Chan has changed his code over the years.
For example I made this update post on Jul 11 this year using Chan's code from Jun 22nd this year:
If you have just downloaded ffsample.zip I doubt that it is very different from that and my instructions there should work.
But do read all fifteen pages as there may be other interesting facts you need to know about.
EDIT: I have now edited a note into the first post to warn other users that it is not contemporary.
yes i figured that out earlier and am already on 4th page. Actually am learning and until now i know how to send commands to SD card such as initialize read write, but i am having problems reading or writing the data sent to/by the card. And then i have to do all this using FAT32 so m quite getting lost in it.
Is interfacing SD card that hard and time consuming or am i the only one not getting the proper way to do it?
There are two levels at which you can use an SD/MMC card. You can just use it like a memory chip that has 512 byte pages. So you can say "write these 512 bytes to page 12345" and later "give me back the contents of page 12345". That's fine but does not allow you to use "files". So you cannot say "give me the 10 bytes at offset 1000 in a file called \data\mydata.txt". If you want that kind of access then you need FAT. FAT is not something you can write on your own (well not without about a year to spare). Thankfully E L Chan has done 95% of the work for us so we only have to fill in the last 5% (he doesn't know our file is called mydata.txt and that it's in the \data directory so we have to supply those details)
Posted by HellsGuardian: Mon. Aug 5, 2013 - 06:08 AM
1
2
3
4
5
Total votes: 0
Hello again,
in a post you wrote that you were able to run the Petit FATFS right out-of-the-box but i am having problems.. it keeps giving me following errors:
-undefined reference to `xputs'
-undefined reference to `xputc'
-undefined reference to `xprintf'
-undefined reference to `xmit_spi'
-undefined reference to `xitoa'
-undefined reference to `rcv_spi'
and many more undefined errors. Well these are important functions and i cant simply remove them and also i am unable to modify it since the suart, usi and xitoa are assembler files (which is quite weird for me since we are coding in C)
i have added all the files in project directory as seen in attached picture.
Also there are couple of errors in these .S files as well e.g: Error 2 number must be positive and less than 64
How did it work for you right away?
Using the petitFATfs was just an alternative, if doesn't work out ill modify the main FATfs according to your previous posts.
So you need to work out where those functions are located:
E:\pfsample\avr>grep xputs *
main.c: xputs(PSTR(" "));
main.c: xputs(PSTR("\nPFF test monitor\n"));
main.c: xputs(PSTR("Enter lines to write. A blank line finalize the write operation.\n"));
xitoa.S:;Prototype: void xputs (const prog_char *str // rom string to be output
xitoa.S:.global xputs
xitoa.S:.func xputs
xitoa.S:xputs:
xitoa.S: rcall xputs
xitoa.h:void xputs(const prog_char *string);
So clearly those functions are in xitoa.S. I'd therefore suggest that when you built the code and got those "undefined reference" errors you did not have xitoa.S listed as a component of the project.
Rather curiously, though, the picture you posted does show that (and other .S) to be present so are you really saying that you still got the error when building the project showin in the picture? I doubt it.
Quote:
(which is quite weird for me since we are coding in C)
Why is it unusual to have a project that mixes C and Asm? When you think about it all the C you write is going to be converted to Asm before it is assembled anyway.
Quote:
How did it work for you right away?
If I unpack the files and simply type the command "make" in the directory where they are located his happens:
Posted by HellsGuardian: Mon. Aug 5, 2013 - 12:40 PM
1
2
3
4
5
Total votes: 0
sorry for being ignorant, where do you type make?
I am using avr studio 5 and use the button " Build Solution" normally.
Well i simply added all the files to the project folder and here is an error in usi.S file (i know after fixing it there will be more)
Line:> ldi r24, lo8(F_CPU / 100000) /* Loop counter */ Error:>undefined symbol `F_CPU' in operation
i have however defined it in main function as
#define F_CPU 16000000UL
If i conver it to ldi r24, lo8(160) /* Loop counter */
i get: Error 7 region `text' overflowed by 266 bytes
Also there is an error regarding DRESULT disk_readp being defined in both mmc.c and diskio.c Should i delete one? Kindly note only names are the same, the code inside functions is different.
I am sorry if my questions seem annoying to you since i am somewhat new to using libraries and this SD card interface is something which i am not getting used to at all
Posted by JohanEkdahl: Mon. Aug 5, 2013 - 01:23 PM
1
2
3
4
5
Total votes: 0
Quote:
i have however defined it in main function as
#define F_CPU 16000000UL
That won't be seen when the assembler works with usi.S. Put the definition of F_CPU in your project options (and remove it from your "main function").
Quote:
sorry for being ignorant, where do you type make?
On a command prompt, with the current directory being "the directory where [the unpacked files] are located".
I am using avr studio 5 [...]
This has little or nothing to do with your current problems, but please note that AVR Studio 5 was not one of Atmels greatest moments. It had several bugs, and was quickly superseded by Atmel Studio 6. My advice to you is to upgrade to AS6.1 SP1 in the near future.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Posted by HellsGuardian: Mon. Aug 5, 2013 - 01:35 PM
1
2
3
4
5
Total votes: 0
JohanEkdahl wrote:
Quote:
i have however defined it in main function as
#define F_CPU 16000000UL
That won't be seen when the assembler works with usi.S. Put the definition of F_CPU in your project options (and remove it from your "main function").
Quote:
sorry for being ignorant, where do you type make?
On a command prompt, with the current directory being "the directory where [the unpacked files] are located".
I am using avr studio 5 [...]
This has little or nothing to do with your current problems, but please note that AVR Studio 5 was not one of Atmels greatest moments. It had several bugs, and was quickly superseded by Atmel Studio 6. My advice to you is to upgrade to AS6.1 SP1 in the near future.
Sure will. I typed it in command prompt and this is what i got..
>make
Command "make" is not valid.
I am sure it has to do with my current directory, how do i set that? Also shouldn't it already be set to the current project?
Your joking? I thought everyone knew about version 5 at this stage - it's been more than 2 years? The only "safe" version of Studio to use is the latest one. That is 6.1 wit SP1.1 which brings it to 6.1.2674. If you use an older version and especially if you are mad enough to still be using AS5 then replace it immediately.
Quote:
sorry for being ignorant, where do you type make?
At a "Command Prompt". This is the way programmers have built code for 30-40 years, long before fancy GUIs and IDEs like Windows and AS6 existed. In the pfsample.zip files there is a special one called "Makefile". If you switch to the directory where that is located and type "make" (and the GNU make.exe program is in your PATH) then it will read the Makefile and use it as a "recipe" to know how to compile and link and otherwise generate the code image. As you can see above that involved it passing a number of .c files to the linker to be compiled into .o files (-c). The .S files were passed to the assembler and it also generated .o files. All those object files were then fed to the linker (avr-gcc without the -c option) and it joined them together to make a single file called pfftest.elf. Further steps then took that file as input and used to to create both a listing file and also a .hex file. It's that .hex file that is then programmed into the AVR.
In fact when you hit [Build] inside AS5/6 exactly the same stuff occurs only most of the detail is hidden from you. AS6 takes the list of .c and .S files and uses them, together with other build options you have set in the IDE and creates a Makefile. It then issues the command "make -f Makefile" to have the rules in that file processed just as in my command line example. The Atmel generated Makefile even has those same steps to generate .lss and .hex files. The only thing is that as far as you are concerned you never actually see the Makefile and you don't isse a make command - but it's all happening behind the scenes.
So the key thing when you take a set of .c and .S files that are built with a Makefile (like ffsample.zip or pfsample.zip) is that you need to make sure the options you choose inside a newly created AS5/6 project match what would otherwise be selected by the supplied Makefile.
Quote:
Well i simply added all the files to the project folder and here is an error in usi.S file (i know after fixing it there will be more)
Line:> ldi r24, lo8(F_CPU / 100000) /* Loop counter */
Error:> undefined symbol `F_CPU' in operation
OK well that's because in the Makefile that Chan supplied it had:
All of which results in -DF_CPU=8000000 being passed to the assembler when .S files are assembled into .o files.
So you simply have to ensure the same happens in AS5/6. As it happens the way you do that in the IDE is to go to the Properties for the Project and in the section Toolchain-AVR/GNU Assembler-General in the Assembler flags text box enter "-DF_CPU=nnnnnnnnn" without the quotes and with nnnnnnnn replaced by your CPU speed in Hertz.
As F_CPU must be "seen" in usi.S it does not help that you #define'd it in main.c - it needs to be defined in place (or in the case of AS5/6 two places) where it can be seen by all files that are compiled or assembled. What I have just described is where you need to put it for Asm files to see it (but this won't work for .c) however I think that may be all you actually need:
That will clear the error you are seeing and help the code to build.
Quote:
i get: Error 7 region `text' overflowed by 266 bytes
Then you are building it for a CPU it won't fit into. That could be that you don't have the optimisation level set correctly. Again note Chan's Makefile. It has:
OPTIMIZE = -Os -mcall-prologues
You need to ensure that project options in AS5/6 lead to the same thing being used when the code is built in Studio.
there is an error regarding DRESULT disk_readp being defined in both mmc.c and diskio.c
If using SD/MMC cards then you use mmc.c, if using a hard drive you use diskio.c. You do not use both. In my set of files I have:
So again to make your AS5/6 project do the same as the Makefile you need to ensure that only those three .c files and those three .S files are listed in the project. (if you did include diskoi.c this goes some way to explaining the "region `text' overflowed by 266 bytes" error.
Posted by HellsGuardian: Tue. Aug 13, 2013 - 11:54 AM
1
2
3
4
5
Total votes: 0
Clawson, if possible, do you have a .mmc file of your SD card which is formatted and has the file poem.txt?
I do not have a sd card right now otherwise according to your instructions i can make .mmc file with winhex.
Your code works perfect even in simulation (apart from some small usart issue which i figured out myself) but i am just using a blank text file renamed as blank.mmc
Once again thankyou.
Edit: If i have to open a file do i have some command to put is hyper terminal or it has to be coded in the program like your version is doing at the moment.
Attached is a 2MB file called poem.mmc in a .zip. I simply used vbindiff in Linux to find out where "Mary" was on /dev/sdj1 and then used dd to write the first 2MB which contained that (and just a bit over) to the file from a 1GB SD/MMC card. So this should mount as if it is a 1GB card and you should be able to "see" the file. It seems to work for me in Linux:
clawson@ws-czc1138h0b:~$ sudo losetup /dev/loop0 poem.mmc
clawson@ws-czc1138h0b:~$ sudo mount /dev/loop0 /mnt/foo
clawson@ws-czc1138h0b:~$ ls /mnt/foo
1GB_test.txt AVRAP003.bin files.txt oldtest.wav poem.txt test.wav
clawson@ws-czc1138h0b:~$ cat /mnt/foo/poem.txt
Mary had a little lamb,
Its fleece was white as snow,
And every where that Mary went,
the little lamb would go.
clawson@ws-czc1138h0b:~$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sdj1 968M 1.6M 966M 1% /media/E0FD-1813
/dev/loop0 968M 1.6M 966M 1% /mnt/foo
Posted by HellsGuardian: Mon. Aug 19, 2013 - 07:39 AM
1
2
3
4
5
Total votes: 0
Hello Clawson, the code works as intended. But i am having trouble understanding how can i perform operations that i desire?
For example, using your version of the library, i want to perform couple of following actions, how will i do that?
such as Creating a file, Opening a file, add new data to the opened text file etc
If you don't know how filing works then forget FatFs and the AVR for the time being and experiment a bit with the filing functions in stdio.h on your PC (fopen, fread, fwrite, fputc, fseek, flcose, etc). When you know and understand how to create, write and read files using those functions THEN come back to FatFs and you will find the interface is remarkably similar to in fact. There are many many sites and support fora on the internet that will teach you about using stdio filing functions.
That is the description of fseek with some example code but there's similar description/examples for all the functions there. Maybe start with fopen in fact:
You can use Visual Studio, Pelles C, Code::Blocks or some other PC based C compiler to write programs using these functions and immediately see the effect of running them on your PC (and use advanced debugging tools if you hit problems). This makes it much easier to learn what's going on than trying to use FatFs on an AVR.
Lately, I've been trying to shift over to Eclipse (just to see how it is compared to AVR Studio v4) but when I import all the FatFS files and my main.c, I get the following error on every function declaration in xitoa.h
Here's an example function declaration in xitoa.h
Anybody have any idea what this could be? This isn't happening in AVR Studio v4 at all. I am able to compile and read/write to SD Cards.
- Log in or register to post comments
TopIt does not know what the typdef "prog_char" is. That actually comes from so it suggests that should be included above xitoa.h
- Log in or register to post comments
Top- Log in or register to post comments
TopThen check the pgmspace.h in your system include path and ensure it contains:
What version of AVR-LibC are you using by the way? E.g.:
My WinAVR uses 1.6.7
- Log in or register to post comments
TopYou were right: pgmspace.h does not contain that definition. Does this imply my files are out-dated?
AVR-LibC version is 1.8.0. For what it's worth, I'm trying to use CrossPack-AVR on the Mac.
EDIT: SOrry, it does contain this:
- Log in or register to post comments
TopThen you are one of the first to be hit by this newly restructured PROGMEM support that looks like it's going to break a LOT oflegacy code. See the threads in GCC forum about GCC 4.7 and specifically those from SprinterSB to understand what's happening.
(this would now be more on-topic for one of those threads than this FatFs tutorial).
- Log in or register to post comments
TopHello
First off, thanks for a great guide. It helped me very much in getting the FatFS running! Good work!
I have a few questions that I hope you guys can help me with.
I get error 9(The file/directory object is invalid) when ever I use either f_puts or f_printf, some times the f_printf gives error 21, which I don't know what means.
for some reason I could not post the correct FORMAT_STRING in code, but it is: percent s, percent ld, percent s
The wierd thing is that all the text and numbers are printed to the file, so the functions are doing what they are supposed to. But why is the error not equal 0 then?
My second question:
In my project I need to sample two adc channels with 500-1000Hz, write the data to SD card and transfer the same data through zigbee (Atmega128RFA1). I know it might be impossible to save to sd and write to zigbee in less time then 1ms (1000hz sample rate) but none the less is this my end goal...
So I would like to create a buffer that fills one sector and flushes it to the SDcard (and possible to the zigbee as well).
I don't know how to do this, I am not quite sure if the FatFS contains a buffer system that I can use for this purpose?
Again thanks for a great guide and good support :)
Regards
Tommy
- Log in or register to post comments
TopYes it already holds a sector buffer within the FATFS structure:
- Log in or register to post comments
TopWill it automatically flush the data when the buffer is full or should I do that manually?
I guess I could sample the adc, put the result into the buffer[i++] and when the buffer is full (i=511) flush the data (f_sync)?
I would like to write the two adc values countinuesly to a single file, so it will be easy to extract the data from the SDcard to excel/labview.
/Tommy
- Log in or register to post comments
TopIt does it - that's the nature of the beast - it always holds the sector it's currently "working on" in that buffer.
I would not access the buffer directly to write to it (use the f_put/f_write/etc. functions to do that) but you may want read access if you want to send a copy to a different destination. You may even want to "hack" ff.c so it calls-back your own function each time before it discards the buffer.
- Log in or register to post comments
TopAhhh good idea with the "hacking", thanks clawson!
- Log in or register to post comments
TopHello, I have a project where I need to log data quickly to a SD/SDHC card. I don't plan on using a file system for now (I assume the overhead would make things slow down too much), and I believe I understand the SD card protocols well enough, but the actual specifications of the SD cards themselves are confusing me.
In short, many SD cards claim sustained write speeds of over 10MB/s, while in their documentation they will then say that it takes at least several milliseconds for a write operation to complete (I assume this refers to one block of 512 bytes). This seems to be a big contradiction, so I'm left unsure of what write speeds to expect from a given card. My goal is to get a sustained speed of at least 500KB/s, hopefully near 1MB/s. I've got a AT32UC3 with a 30MHz SPI and a couple DMA channels, and I've read that other people have achieved this with similar hardware (though some have not, and I assume the SD card itself is a big reason).
Does anyone here understand the SD card specs well enough to actually know what determines their write speeds (in SPI mode)? Does anyone have any recommendations of SD/SDHC card models which are known to get the write speeds I need?
Thanks in advance.
- Log in or register to post comments
TopThere's a difference between using these cards in SPI mode (which is compatible with MMC) and in the 4bit SD mode. For the latter you need to become a licensee of the SD association to gain access to the docs. (though a recent thread suggests that even MMC mode requires licensing). For typical MMC speeds see:
http://elm-chan.org/fsw/ff/img/r...
- Log in or register to post comments
TopMy fundamental question is how can I look at the specifications of a card (I'm talking about the contents of its CSD register, not just its speed class or whatever) and use that to estimate what write speeds are attainable with SPI mode. Of course the SPI interface will degrade the attainable speed somewhat, but from what I've read the real bottleneck is usually in the SD card itself, specifically its program times.
If I can't get that answered, then I'd at least like to know of some card models which people have good experience with (and are capable of my desired speed).
Thanks!
- Log in or register to post comments
TopI doubt the card's own write speed wil be the bootle-neck, it's how fast you can feed data to the card that will probably limit it (of course UC3 probably have more "oomph" in this sense than AVR).
- Log in or register to post comments
TopI'd love to believe that the card won't be a bottleneck, but everything I've read by people who have actually used them says otherwise. Lots of people are using a 20MHz SPI clock with DMA control, but most people seem limited to a few hundred KB/s (while a few have been able to get speeds in excess of 1MB/s). I've read that the dominant bottleneck is just the time it takes for the card to go idle after a write is performed, so another write can begin.
- Log in or register to post comments
TopA small question - I'm using FatFs on an SD Card and I also have 10 other devices on the SPI bus (all CPLDs). The very first thing that my program does is initialize the SD Card. I note that FatFs library contains the following macro.
which it calls after initialization succeeds. This equals about 2MHz on my AVR Mega 1281. But after the initialization, I setup SPI for my CPLDs - in this particular routine, I set my SPI speed to just 62.5KHz.
My question is, will the FatFs library now be operating at 62.5KHz? I don't think FCLK_FAST() is called anywhere else, so if I initialize the card the speed is set to 2MHz. I then call my function setupSPI() which sets the SPI speed to 62.5KHz. I then read from the SD Card and also read from the CPLDs. Unless the SPCR register is set again to 0x50, I don't think my SD Card is working at 2MHz. Am I correct?
I should add, the system is working very well. However, I have to extend the system to operate on a larger dataset - hence my concern about read/write speeds.
- Log in or register to post comments
TopYes.
I agree.
You could, I guess pepper FatFs with more calls to FCLK_FAST() (perhaps in the power_on routine?) and then setupSPI() when its deselected (power_off ?) or simply accept the 62.5kHz for SD access.
As with all optimizations I wouldn't actually bother until they actually become necessary - worry about this when you get to the point of believing that the file cannot be written quickly enough.
- Log in or register to post comments
TopThe ffsample.zip I downloaded from
http://elm-chan.org/fsw/ff/00ind...
doesn't seem consistent with this tutorial. For example:
There are no such lines in mmc.c--now they are functions:
I think I can still figure out what needs to be done, but is the older on which this tutorial was based still available? Or should I just use the newer version and expect only trivial differences?
Thanks!
Dave Thomas
- Log in or register to post comments
TopAs I ran into more or less the same thing that a lot has changed, I write here what things I changed in order to get FatFs version 0.09b to work.
you can download it from:
http://elm-chan.org/fsw/ff/00index_e.html
On the bottom of this page you can download the "FatFs sample projects"
This is a zip file with all the projects for a lot of different processors.
From this zip file I used the "avr" folder.
I used Atmel Studio 6.0(AS6)
I have a self made board with a Atmega1281 on it.
First step is to make a new project in AS6.
Copy the following files from the AVR folder to the project folder:
- cc932_avr.c (from unicode sub directory)
- diskio.h ,
- ff.c ,
- ff.h ,
- ffconf.h ,
- integer.h ,
- main.c ,
- mmc.c ,
- rtc.c ,
- rtc.h ,
- uart.c ,
- uart.h ,
- xitoa.h ,
- xitoa.s ,
Now I have made the following changes to the files to get them to work for me:
I made a board.h file that holds a number of board specific parameters. See file for details.
In the file "cc932_avr.c"
There are 4 references do the datatype "prog_uint16_t"
as this datatype is no longer supported int the atmel studio it must be changed.
from top to bottom thrue the file:
In the file "ffconf.c"
I changed the following parameters:
You have to check this file what options you want to use and what not.
In the files "uart.c & uart.h"
I changed all references from uart0 to uart1.
I removed:
as this is already done during initialization.
I added:
and call that during uart initialization.
In the file "xitoa.h"
There are 4 references to "prog_char".
These all need to be replaced by "char"
The contents of the file rtc.c"
I do not have a RTC interface available. so I replaced the file contents with:
If you have a RTC available then you need to make that work here.
In the file "mmc.c"
You need to set the port controls to how your board is designed.
As the MMC card does not have a write protection option the check on that alwasy ahs to return a false:
I also changed the fast and slow clock
The functions "power_status, power_on and power_off" are replaced byt the following block:
In the file "main.c"
I removed the include for "sound.h" as I do not have sound available.
I also removed the "FUSES" definition as I use another processor and prefer to set those one time and set them myself.
As I use timer0 instead of timer2 I changed the interrupt vector for that and also the initialization in the "ioinit" function.
Also in this file a number of references to "prog_char" have to be changed to char + PROGMEM.
A new function is added for PIO Init. The original program does this in the ioinit function, you need to set these things correct for you specific design.
with these changes done you should be able to run the example project on your system.
I hope this will help others.
Attachment(s):
- Log in or register to post comments
TopJust to say that there are a couple of ways to approach this. In response to a thread here the other day I too downloaded 0.09b but rather than the generic:
http://elm-chan.org/fsw/ff/ff9b.zip
download link I think it's possibly easier to start with:
http://elm-chan.org/fsw/ff/ffsam...
which is linked as "FatFs sample projects" as this possibly starts closer to what you probably want to do than the generic file which, as meslomp's post shows, may require more work. Within the "Samples" archive is an AVR sub-folder that contains:
E:\ffavr\avr>dir /b
rtc.c
rtc.h
Makefile_mmcbb
mmc.c
ffconf.h
integer.h
sound.c
cfmm.c
diskio.h
Makefile_cfmm
uart.h
avr_ata.png
Makefile_cfc
uart.c
Makefile_mmc
main.c
ff.c
cfc.c
Makefile_ata
xitoa.S
ff.h
sound.h
avr_mmc.png
xitoa.h
avr_cfc.png
ata.c
mmcbb.c
That has support for building a number of targets but it's only the "mmc" variant that an AVR user will be interested in. So one can start by removing a majority of the files of no immediate relevance (personally I use a Subversion repository so I can easily get back anything that I modify or delete in error). Just retain the following files (in fact the uart.* are also optional):
mmc.c
ffconf.h
integer.h
diskio.h
uart.h
uart.c
ff.c
ff.h
Of these you shouldn't need to (indeed for library code you never should) edit the following:
ff.h
ff.c
diskio.h
integer.h
So the only files you may want to edit are:
1) mmc.c
Edit this to reflect your actual hardware wiring. In my case I changed:
to be:
and also:
to be:
as my wiring did not include power control. Also:
to be:
That's because I wasn't using Card Present or Write Protect signals and I just think it's easier to document the setting of I/O bits using symbols rather than meaningless 0b101010111 style values.
The point here is that you edit mmc.c to reflect how you have things wired.
Note also that the 0.09b files have an error that Chan has inadvertently introduced. It's easiest to just add the #if/#endif to remove the whole thing:
2) ffconf.h
Everyone who uses FatFs is going to have different requirements. Personally I edited the following lines:
Of those I think it's only the last two that almost everyone will probably edit. The _CODE_PAGE one to reduce reliance on international (probably Japanese) character sets and the _VOLUMES one as almost everyone using FatFs probably only has one SD/MMC card attached, not two.
3) something.c
You need to write some C code to actually do something with FatFs. The following is a very simply example that simply opens a file called "poem.txt" and outputs the lines of text that it contains:
The two key things here that all FatFs programs will have are:
(a) you need to start a timer with a 10ms period and each time it expires call disk_timerproc()
(b) you need to provide the get_fattime() function that ff.c will call to time stamp files. If you don't have an RTC then just return a fixed date/time as shown here. You shouldn't need anything from any kind of rtc.h/rtc.c as this function alone is the only API that FatFs will attempt to call. In fact it could be even simpler - just return 0.
The AS6 project for all this is attached..
Attachment(s):
- Log in or register to post comments
TopHi all.
I was wondering whether anybody was able to successfully run the ffsample (version 0.09b of FatFS) program for AVR and use the 'fr' and 'fd' commands.
It appears that the mem_cpy calls in f_read might be causing an MCU restart, possibly as these overwrite areas in RAM that they should not. I tried to run ffsample without other modifications than a simple port to ATMega644: in particular ffconf.h is as per zip provided by ChaN. The sequence of commands I tried was:
di 0
fi 0
fo 1 test.bin
fd 512
<- MCU restarts here
The same thing happens if I try the WAV playback command or data read one:
p file.wav
fr 512
If you had more luck than myself, I'd be grateful to know :)
Thank you!
SadicAVR
- Log in or register to post comments
TopClawson, Thank you. Thank you. Thank you.
(I'll not type it a thousand times.)
It worked second try. At first, it failed "no init." I checked lines, checked my pin definitions in mmc.c, checked with an ohm meter. Then thought, "This came from a phone, I wonder how it's formatted." So I formatted it fresh (2GB with 16KB blocks) and put my poem.txt and... WOW, it shows my parnassian attempt on the display!
277,232,917 -1 The largest known Mersenne Prime
Measure twice, cry, go back to the hardware store
- Log in or register to post comments
TopI am having lots of errors when I try to run the code after making these changes - functions like uart_putc and uart_getc are undefined, and variable type prog_char is not defined. Any ideas as to what I am doing wrong?
- Log in or register to post comments
TopWell the uart functions aren't needed so remove anything that calls those. As for prog_char, that's deprecated in the latest compiler as it only ever worked by accident. Just use PROGMEM on char.
- Log in or register to post comments
TopThis is just an update of my post above to reflect that things have moved on a bit. I did the following using the Jun22 2013 copy of ffsample.zip from the FatFs site and the current issue of Studio 6 which is 6.1 with Service Pack 1.1 that is 6.1.2674
From ffsample.zip I just extracted the "avr" subdirectory and ignored everything else. This gave me:
I added those to a local SVN so I could track changes and recover anything I delete or change in error.
As I'm only interested in SD/MMC using the SPI interface most of these files are not relevant so, like last time, I cut them down using svn-delete to be:
That's still too many files as I don't really intend to use the Makefile and I'm not sure about the uart.* files but I'll cut things down further later.
Next I wanted to make this into an AS6 project. Unfortunately AS6 has a habit of creating things you don't actually want and won't create a project within a directory that already exists when you create a new project but undeterred I told it to create a new GCC C project.
Now I wanted it to use the \ffsamp-jun22\avr directory where I already had files so I pointed "Location:" to the ffsamp-jun22 directory and asked for the project to be called "FatfsAVR" and un-ticked the "Create directory for project" button. I arbitrarily chose to make the project for atmega32 as that's what I happened to have plugged into my STK500 with SD/MMC socket attached. This created a file called FatfsAVR.c in \ffsamp-jun22\FatfsAVR\ directory so at this stage my tree of files looked like this:
My plan here is not to use the FatFs supplied main.c but, instead, put a small driving test program into the FatfsAVR.c file that AS6 just created.
So next I need to make AS6 aware of the files I want compiled into the project. In the Solution Explorer I right-click the FatfsAVR project and from the Context menu use "Add" and within that "Existing item...". I then select "ff.c", "mmc.c", "uart.c" and "xitoa.S" using the "Add as link" option on the dialog's add button (don't just use [Add] or those files will be copied from the "avr" subdirectory" to the "FatfsAVR" directory.
If I try to build at this stage I get errors about PORTE being used in mmc.c. This is because the Chan supplied code is intended for a mega64 and I am building for a mega32. So, just as in my previous post, I will make some modifications to mmc.c. In Chan's code where PORTE is used he has comments such as:
As I'm not going to use socket power control I will follow this advice and remove anything that makes access to PORTE. I also modify power_status() so it always returns 1. And I apply changes as shown in my previous message to configure things for the SPI pins on mega32. SVN tells me that what I changed was:
Having cleared errors in mmc.c I then get errors in uart.c. I figure it is worth making it work for mega32 so I modify it as follows (also adding a definition of F_CPU=3686400 to the project symbols):
At this stage the project now builds without error. However there is nothing in main() actually calling any FatFs function and ffconf.h needs to be edited. If I turn off Linker garbage collection the project builds to :
After making the following edits to ffconf.h:
that changes to be:
Now I just need some code in the main() function. I edited FatfsAVR.c to be very like the main file from the previous thread, that is:
I switched garbage collection back on so the link would only include the functions that were called and this gave a final:
I've still got to actually test this but that looks pretty reasonable. The full project dir I used is zipped and attached.
Attachment(s):
- Log in or register to post comments
TopI've now tested that and it works but I did have to make this following change that I had forgotten above (because I don't use the card inserted and write protect signals):
Also I modified main() with more uart stuff and remembered to initialize it...
With all that I saw...
Attachment(s):
- Log in or register to post comments
TopProbably not fundamental, but I thought to mention this. With a divider of just 8 and a 3.6864 MHz clock, an 8-bit compare value is not enough to trigger a compare interrupt every 10ms.
Shouldn't the prescaler be 256 and OCR0 preloaded with 0x8F?
- Log in or register to post comments
Top@clawson: can you please try the f_read function after opening a file for read? It wouldn't have to do anything complex, just read a few bytes and show them:
Does it work for you?
- Log in or register to post comments
TopIt appears that I am using a toolchain for which your project does not work. As it's an old toolchain from a few years back (Win AVR), I will try to update that first and then retry.
Edit: yes, even ChaN's example works now that I moved to the latest AVR toolchain.
- Log in or register to post comments
Topi am getting the following errors with function wait_ready()
Error 4 static declaration of 'wait_ready' follows non-static declaration
Error 5 previous implicit declaration of 'wait_ready' was here
any ideas?
- Log in or register to post comments
TopHave you edited the files? If I grep for wait_ready in recent FatFs files all I find is:
no mention of "static" in any of that.
- Log in or register to post comments
TopI get this error after i replace the power_off function with the one author gave i.e
This function has wait_ready..
well the samples.zip i downloaded seems to have a bit different code. e.g in this tutorial author said to comment the lines from PORTA to PORTG in main.c The code in your file (even though it is commented but for the sake of comparison) is different from what i have. Notice the values of Ports are different in the file i have.
next he mentioned to modify the #define SELECT() and #define DESELECT() but in my mmc.c There are no such defines... i have two functions for select and deselect though
Then it has SOCKWP and SOCKINS defines but no SOCKPORT. Also there is no such function chk_power(void) in my file. Are the files in avr directory updated/changed?
Edit: my AVR studio 5 does not seems to be detecting BOOL in rtc functions i.e:
BOOL rtc_settime (const RTC *rtc)
It says: Error 1 expected '=', ',', ';', 'asm' or '__attribute__' before 'rtc_gettime'
and using the replaced uart code it says: too many arguments to function 'uart_init'
- Log in or register to post comments
TopAre you talking about page 1? You are only ready to start when you have read through ALL fifteen pages as there have been many updates as Chan has changed his code over the years.
For example I made this update post on Jul 11 this year using Chan's code from Jun 22nd this year:
https://www.avrfreaks.net/index.p...
If you have just downloaded ffsample.zip I doubt that it is very different from that and my instructions there should work.
But do read all fifteen pages as there may be other interesting facts you need to know about.
EDIT: I have now edited a note into the first post to warn other users that it is not contemporary.
- Log in or register to post comments
Topyes i figured that out earlier and am already on 4th page. Actually am learning and until now i know how to send commands to SD card such as initialize read write, but i am having problems reading or writing the data sent to/by the card. And then i have to do all this using FAT32 so m quite getting lost in it.
Is interfacing SD card that hard and time consuming or am i the only one not getting the proper way to do it?
- Log in or register to post comments
TopThere are two levels at which you can use an SD/MMC card. You can just use it like a memory chip that has 512 byte pages. So you can say "write these 512 bytes to page 12345" and later "give me back the contents of page 12345". That's fine but does not allow you to use "files". So you cannot say "give me the 10 bytes at offset 1000 in a file called \data\mydata.txt". If you want that kind of access then you need FAT. FAT is not something you can write on your own (well not without about a year to spare). Thankfully E L Chan has done 95% of the work for us so we only have to fill in the last 5% (he doesn't know our file is called mydata.txt and that it's in the \data directory so we have to supply those details)
- Log in or register to post comments
TopHello again,
in a post you wrote that you were able to run the Petit FATFS right out-of-the-box but i am having problems.. it keeps giving me following errors:
-undefined reference to `xputs'
-undefined reference to `xputc'
-undefined reference to `xprintf'
-undefined reference to `xmit_spi'
-undefined reference to `xitoa'
-undefined reference to `rcv_spi'
and many more undefined errors. Well these are important functions and i cant simply remove them and also i am unable to modify it since the suart, usi and xitoa are assembler files (which is quite weird for me since we are coding in C)
i have added all the files in project directory as seen in attached picture.
Also there are couple of errors in these .S files as well e.g:
Error 2 number must be positive and less than 64
How did it work for you right away?
Using the petitFATfs was just an alternative, if doesn't work out ill modify the main FATfs according to your previous posts.
Attachment(s):
- Log in or register to post comments
TopSo you need to work out where those functions are located:
So clearly those functions are in xitoa.S. I'd therefore suggest that when you built the code and got those "undefined reference" errors you did not have xitoa.S listed as a component of the project.
Rather curiously, though, the picture you posted does show that (and other .S) to be present so are you really saying that you still got the error when building the project showin in the picture? I doubt it.
Why is it unusual to have a project that mixes C and Asm? When you think about it all the C you write is going to be converted to Asm before it is assembled anyway.
If I unpack the files and simply type the command "make" in the directory where they are located his happens:
That certainly looks like it works straight out of the box to me!
- Log in or register to post comments
Topsorry for being ignorant, where do you type make?
I am using avr studio 5 and use the button " Build Solution" normally.
Well i simply added all the files to the project folder and here is an error in usi.S file (i know after fixing it there will be more)
Line:> ldi r24, lo8(F_CPU / 100000) /* Loop counter */
Error:> undefined symbol `F_CPU' in operation
i have however defined it in main function as
#define F_CPU 16000000UL
If i conver it to ldi r24, lo8(160) /* Loop counter */
i get: Error 7 region `text' overflowed by 266 bytes
Also there is an error regarding DRESULT disk_readp being defined in both mmc.c and diskio.c Should i delete one? Kindly note only names are the same, the code inside functions is different.
I am sorry if my questions seem annoying to you since i am somewhat new to using libraries and this SD card interface is something which i am not getting used to at all
- Log in or register to post comments
TopThat won't be seen when the assembler works with usi.S. Put the definition of F_CPU in your project options (and remove it from your "main function").
On a command prompt, with the current directory being "the directory where [the unpacked files] are located".
This has little or nothing to do with your current problems, but please note that AVR Studio 5 was not one of Atmels greatest moments. It had several bugs, and was quickly superseded by Atmel Studio 6. My advice to you is to upgrade to AS6.1 SP1 in the near future.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
Topby the way build succeeded with slight modifications to your code/instructions given in page 15. Soon gonna test it out but first i must study it
and yes the instructions given by you is way simple and easily understandable. Thankyou for your time and effort
- Log in or register to post comments
TopSure will. I typed it in command prompt and this is what i got..
>make
Command "make" is not valid.
I am sure it has to do with my current directory, how do i set that? Also shouldn't it already be set to the current project?
- Log in or register to post comments
TopYour joking? I thought everyone knew about version 5 at this stage - it's been more than 2 years? The only "safe" version of Studio to use is the latest one. That is 6.1 wit SP1.1 which brings it to 6.1.2674. If you use an older version and especially if you are mad enough to still be using AS5 then replace it immediately.
At a "Command Prompt". This is the way programmers have built code for 30-40 years, long before fancy GUIs and IDEs like Windows and AS6 existed. In the pfsample.zip files there is a special one called "Makefile". If you switch to the directory where that is located and type "make" (and the GNU make.exe program is in your PATH) then it will read the Makefile and use it as a "recipe" to know how to compile and link and otherwise generate the code image. As you can see above that involved it passing a number of .c files to the linker to be compiled into .o files (-c). The .S files were passed to the assembler and it also generated .o files. All those object files were then fed to the linker (avr-gcc without the -c option) and it joined them together to make a single file called pfftest.elf. Further steps then took that file as input and used to to create both a listing file and also a .hex file. It's that .hex file that is then programmed into the AVR.
In fact when you hit [Build] inside AS5/6 exactly the same stuff occurs only most of the detail is hidden from you. AS6 takes the list of .c and .S files and uses them, together with other build options you have set in the IDE and creates a Makefile. It then issues the command "make -f Makefile" to have the rules in that file processed just as in my command line example. The Atmel generated Makefile even has those same steps to generate .lss and .hex files. The only thing is that as far as you are concerned you never actually see the Makefile and you don't isse a make command - but it's all happening behind the scenes.
So the key thing when you take a set of .c and .S files that are built with a Makefile (like ffsample.zip or pfsample.zip) is that you need to make sure the options you choose inside a newly created AS5/6 project match what would otherwise be selected by the supplied Makefile.
OK well that's because in the Makefile that Chan supplied it had:
and
and
All of which results in -DF_CPU=8000000 being passed to the assembler when .S files are assembled into .o files.
So you simply have to ensure the same happens in AS5/6. As it happens the way you do that in the IDE is to go to the Properties for the Project and in the section Toolchain-AVR/GNU Assembler-General in the Assembler flags text box enter "-DF_CPU=nnnnnnnnn" without the quotes and with nnnnnnnn replaced by your CPU speed in Hertz.
As F_CPU must be "seen" in usi.S it does not help that you #define'd it in main.c - it needs to be defined in place (or in the case of AS5/6 two places) where it can be seen by all files that are compiled or assembled. What I have just described is where you need to put it for Asm files to see it (but this won't work for .c) however I think that may be all you actually need:
It's only usi.S that uses it.
That will clear the error you are seeing and help the code to build.
Then you are building it for a CPU it won't fit into. That could be that you don't have the optimisation level set correctly. Again note Chan's Makefile. It has:
You need to ensure that project options in AS5/6 lead to the same thing being used when the code is built in Studio.
If using SD/MMC cards then you use mmc.c, if using a hard drive you use diskio.c. You do not use both. In my set of files I have:
No diskio.c there. Also the Makefile has this:
So again to make your AS5/6 project do the same as the Makefile you need to ensure that only those three .c files and those three .S files are listed in the project. (if you did include diskoi.c this goes some way to explaining the "region `text' overflowed by 266 bytes" error.
- Log in or register to post comments
TopVery well explained. Thankyou
- Log in or register to post comments
TopClawson, if possible, do you have a .mmc file of your SD card which is formatted and has the file poem.txt?
I do not have a sd card right now otherwise according to your instructions i can make .mmc file with winhex.
Your code works perfect even in simulation (apart from some small usart issue which i figured out myself) but i am just using a blank text file renamed as blank.mmc
Once again thankyou.
Edit: If i have to open a file do i have some command to put is hyper terminal or it has to be coded in the program like your version is doing at the moment.
- Log in or register to post comments
TopAttached is a 2MB file called poem.mmc in a .zip. I simply used vbindiff in Linux to find out where "Mary" was on /dev/sdj1 and then used dd to write the first 2MB which contained that (and just a bit over) to the file from a 1GB SD/MMC card. So this should mount as if it is a 1GB card and you should be able to "see" the file. It seems to work for me in Linux:
Attachment(s):
- Log in or register to post comments
TopJust a small note. You can do the mount without losetup, like
The first unused loop device will be used.
- Log in or register to post comments
TopHello Clawson, the code works as intended. But i am having trouble understanding how can i perform operations that i desire?
For example, using your version of the library, i want to perform couple of following actions, how will i do that?
such as Creating a file, Opening a file, add new data to the opened text file etc
Attachment(s):
- Log in or register to post comments
TopIf you don't know how filing works then forget FatFs and the AVR for the time being and experiment a bit with the filing functions in stdio.h on your PC (fopen, fread, fwrite, fputc, fseek, flcose, etc). When you know and understand how to create, write and read files using those functions THEN come back to FatFs and you will find the interface is remarkably similar to in fact. There are many many sites and support fora on the internet that will teach you about using stdio filing functions.
For example:
http://www.cplusplus.com/referen...
That is the description of fseek with some example code but there's similar description/examples for all the functions there. Maybe start with fopen in fact:
http://www.cplusplus.com/referen...
Here's a much more elaborate example:
http://www.dailyfreecode.com/Cod...
You can use Visual Studio, Pelles C, Code::Blocks or some other PC based C compiler to write programs using these functions and immediately see the effect of running them on your PC (and use advanced debugging tools if you hit problems). This makes it much easier to learn what's going on than trying to use FatFs on an AVR.
- Log in or register to post comments
Topis it ok if i post some questions relating to it here?
- Log in or register to post comments
TopPages