|
|
View previous topic :: View next topic |
Author |
Message |
CoverUp
Joined: 04 May 2010 Posts: 7
|
fat.c + mmcsd.c Working but Windows can't read the files |
Posted: Tue May 04, 2010 8:33 pm |
|
|
I'm using a PIC18f4525 and the fat.c + mmcsd.c library.
Everything works good on PIC.
I can initialize the SD card, format the card, make a file and append data to it.
I can read all the data written...very happy so far.
BUT
Then I put the SD card in a PC running Windows XP and the directory appears to be empty... but if you see the properties of the disk, there's 17mb used (my data written with the PIC).
I'm using a Kingston 2GB SD card.
Any idea what could be wrong??
I format the SD card from pic.. everything work but Windows can read the directory listing
Then I format from Windows using FAT32.. again the PIC can write and read, but nothing appears on Windows.
:(
PD: English is not my native language, sorry for any mistake. |
|
|
CoverUp
Joined: 04 May 2010 Posts: 7
|
|
Posted: Tue May 25, 2010 10:49 pm |
|
|
Solved!!
if any one want the solution, post but i'll explain it in spanish. sorry for that |
|
|
blackdragon
Joined: 24 May 2010 Posts: 10
|
|
Posted: Wed May 26, 2010 1:59 pm |
|
|
CoverUp wrote: | Solved!!
if any one want the solution, post but i'll explain it in spanish. sorry for that |
CoverUp, could you please share your code and solution?
I think source code is source code such as basic sciences(physics, math, etc.) or you can draw a picture like hieroglyphics :-)
thanks |
|
|
rigomm
Joined: 17 Mar 2010 Posts: 13
|
Please share your solution |
Posted: Thu May 27, 2010 5:57 am |
|
|
Hi CoverUp
CoverUp wrote: | Solved!!
if any one want the solution, post but i'll explain it in spanish. sorry for that |
Por favor comparte tu solución. Aunque sea en español. :-)
Please, share the solution, even if it´s in spanish.
I´m waiting for it. Regards. |
|
|
SpoonBilly
Joined: 25 May 2010 Posts: 16
|
|
Posted: Sat May 29, 2010 7:54 am |
|
|
CoverUp wrote: | Solved!!
if any one want the solution, post but i'll explain it in spanish. sorry for that |
Can you please share your code?
I'm working on similar thing using PIC18F2553.
http://www.ccsinfo.com/forum/viewtopic.php?p=132795#132795
mmcsd.c reads and writes using logical address. There is an offset between logical and physical sectors. I modified mmcsd.c to scan the offset such that mmcsd_read_data() is able to read correct information from the boot sector (Physical address 0x0 ~ 0x1FF). Did you do the same? or you found better solution?
However, mmcsd_read_data() is still unable to read the correct Next_Free_Clust (Physical address 0x3EC ~ 0x3EF). The reason is that it is located inside the reserved sector and somehow, mmcsd_read_data() isn't able to read correctly from reserved sector. Have you seen the same problem?
Thanks. |
|
|
CoverUp
Joined: 04 May 2010 Posts: 7
|
|
Posted: Wed Jun 02, 2010 10:23 pm |
|
|
The problem with all of this is in the FAT library, basically in the function that is responsible for formatting the card: format(int32 mediaSize).
The problem is the following function creates a partition and then formats the card. This means adding an offset between the logical sector and the physical sector, and this offset is not scheduled later in the FAT library. Then none of functions really points to the logical address that was created when formatting.
The solution is to modify the FAT library and include the offset in all directions, however this is a pain. I do not think anyone has time for that.
My solution:
Never use the function format(), instead format the card directly from Windows when it is new.
If you already formatted using format(), format from Windows does not work, because the offset will be present, even if formatting a thousand times.
If you are in this situation (which is what happened to me) the SD card must be returned to its original state, i.e., it must delete information which was introduced in the famous format(). For this it is sufficient to write (using the library mmcsd) values in the directions 0x00 0x00 0x01 0x02 0x03 0x04 0x05 ... etc. with 0-512 being more than enough.
This translates to reset the first physical sector that contains the information of the partition table.
After you have done this, you can delete the entire contents of the SD card using WinHex and finally format it using Windows.
In this way the logical address and physical address match and both depart from the direction 0, and therefore all the FAT library functions operate.
No attached code. The only code needed is Fat.c and mmcsd.c in its original state. The steps described do not require modifying the libraries.
Greetings and enjoy the solution.
Now the English speakers will have to learn Spanish as well as we learn English: P
+++++++++++++++++++++++
Translated with Google Translator
-- Forum Moderator
+++++++++++++++++++++++
------------------
El problema de todo esto esta en la libreria fat, puntualmente en la funcion que se encarga de formatear la tarjeta [ format(int32 mediaSize) ]
El problema es el siguiente, la funcion crea una particion y luego da formato a la tarjeta, esto se traduce en agregar un offset entre el sector logico y el sector fisico, como este offset no esta programado posteriormente en la libreria fat, entonces ninguna de las funciones apunta realmente a la direccion logica que se creo al momento de formatear. la solucion pasa por modificar la libreria fat e incluir el offset en todas las direcciones, sin embargo es una lata.. y no creo que nadie tenga tiempo para eso.
Mi solucion:
No usar nunca la funcion format(), formatear la tarjeta directamente desde windows cuando esta esta nueva.
Si ya formatearon usando format() formatear desde windows no sirve, por que el offset seguira estando presente, aunque formateen mil veces.
Si estan en esta situacion (que fue lo que me paso a mi) deben volver la tarjeta sd a su estado original, es decir, deben eliminar la informacion que introdujo el famoso format(), para ello basta con que escriban (utilizando la libreria mmcsd) valores 0x00 en las direcciones 0x00 0x01 0x02 0x03 0x04 0x05...etc. con un for de 0 a 512 basta y sobra.
Esto se traduce en resetear el primer sector fisico que contiene la informacion de la tabla de particiones.
Luego que han hecho esto, pueden borrar el contenido completo de la tarjeta sd usando el winhex y finalmente formatean usando windows.
De esta forma la direccion logica y la direccion fisica concuerdan y ambas parten desde la direccion 0.
y por tanto todas las funciones de la libreria fat funcionaran.
No adjunto codigo, por que el unico codigo necesario es fat.c y mmcsd.c en su estado original, los pasos que describi no requieren modificar las librerias.
Saludos y disfruten la solucion.
ahora los gringos tendran que aprender español asi como nosotros aprendemos ingles :P |
|
|
SpoonBilly
Joined: 25 May 2010 Posts: 16
|
|
Posted: Thu Jun 03, 2010 2:34 am |
|
|
CoverUp wrote: | The problem with all of this is in the FAT library, basically in the function that is responsible for formatting the card: format(int32 mediaSize). |
Thanks CoverUp. Spanish is a beautiful language :D
The offset (shift) between physical and logical sector is inherent in my SD cards. So, I guess most people will find it the same way when they buy a new SD card.
What I did was write a function in mmcsd.c to scan the offset.
Code: | /*
uint32_t mmcsd_addr_shift()
Summary: Every SD card communicates with PIC through logical address. There is an
address shift between logical address and physical address. The shift is
depending on the manufacturer. Address shift = Hidden Bytes, while
Hidden Bytes = Hidden Sectors*Bytes_Per_Sector.
SD Card with FAT16/FAT32 file system has strings Hidden Sectors and
Bytes_Per_Sector information stored in physical addresses 0xB~0xC and
0x1C~0x1F respectively.
This function scans the addresses to determine the address shift.
Param: No parameter needed.
Returns: Address shift.
*/
uint32_t mmcsd_addr_shift()
{
int count ;
unsigned int16 Bytes_Per_Sector ;
unsigned int32 addr1, Hidden_Sectors, Hidden_Bytes ;
union
{
uint32_t offset ;
uint8_t bin[4] ;
}addr_offset ; // both variables share the same address
addr_offset.bin[0] = read_eeprom(0) ;
addr_offset.bin[1] = read_eeprom(1) ;
addr_offset.bin[2] = read_eeprom(2) ;
addr_offset.bin[3] = read_eeprom(3) ;
addr1 = addr_offset.offset ;
mmcsd_read_data(addr1+11, 2, &Bytes_Per_Sector) ; // Byte Per Sector
mmcsd_read_data(addr1+28, 4, &Hidden_Sectors) ; // Hidden Sectors
Hidden_Bytes = Bytes_Per_Sector*Hidden_Sectors ;
if(Hidden_Bytes == addr1)
{
printf("Old SD card found. Address shift: %lX\n\r", addr1) ;
return addr1 ;
}
else
{
printf("New SD card found. Scanning, please wait.\n\r") ;
for(addr1 = 0x10D00; addr1 <= 0x20000; addr1 = addr1 + 0x100)
{
mmcsd_read_data(addr1+11, 2, &Bytes_Per_Sector) ; // Byte Per Sector
mmcsd_read_data(addr1+28, 4, &Hidden_Sectors) ; // Hidden Sectors
Hidden_Bytes = Bytes_Per_Sector*Hidden_Sectors ;
if(Hidden_Bytes == addr1) // found the match
{
printf("New SD card scan completed. Address shift: %lX\n\r", addr1) ;
addr_offset.offset = addr1 ;
write_eeprom(0,addr_offset.bin[0]) ;
write_eeprom(1,addr_offset.bin[1]) ;
write_eeprom(2,addr_offset.bin[2]) ;
write_eeprom(3,addr_offset.bin[3]) ;
return addr1 ;
break ;
}
}
}
} |
Declare this at the beginning:
Code: | uint32_t g_addr_shift ;
uint32_t mmcsd_addr_shift(); |
Add this at the end of MMCSD_err mmcsd_init():
Code: | mmcsd_deselect();
r1 = mmcsd_load_buffer();
g_addr_shift = mmcsd_addr_shift() ; // added by SpoonBilly 20100527
return r1; |
Add this in MMCSD_err mmcsd_move_buffer(uint32_t new_addr):
Code: | uint32_t
//cur_block,
new_block;
new_addr = new_addr + g_addr_shift ; // added by SpoonBilly 20100527
// make sure we're still on the same block
//cur_block = g_mmcsdBufferAddress - (g_mmcsdBufferAddress % MMCSD_MAX_BLOCK_SIZE);
new_block = new_addr - (new_addr % MMCSD_MAX_BLOCK_SIZE) ; |
Do the following modification in MMCSD_err mmcsd_read_byte(uint32_t addr, char* data) and MMCSD_err mmcsd_write_byte(uint32_t addr, char data):
Code: | MMCSD_err mmcsd_read_byte(uint32_t addr, char* data)
{
MMCSD_err ec;
ec = mmcsd_move_buffer(addr);
if(ec != MMCSD_GOODEC)
{
return ec;
}
*data = g_mmcsd_buffer[addr+g_addr_shift % MMCSD_MAX_BLOCK_SIZE]; // modified by SpoonBilly 20100527
return MMCSD_GOODEC;
}
MMCSD_err mmcsd_write_byte(uint32_t addr, char data)
{
MMCSD_err ec;
ec = mmcsd_move_buffer(addr);
if(ec != MMCSD_GOODEC)
return ec;
g_mmcsd_buffer[addr+g_addr_shift % MMCSD_MAX_BLOCK_SIZE] = data; // modified by SpoonBilly 20100527
g_MMCSDBufferChanged = TRUE;
return MMCSD_GOODEC;
} |
This should solve the physical and logical offset problem, but it is still unable to read correctly from reserved sectors. |
|
|
SpoonBilly
Joined: 25 May 2010 Posts: 16
|
|
Posted: Thu Jun 03, 2010 2:57 am |
|
|
But I did solved the problem of unable to read correctly from reserved sector... eventually... accidently...
I was so frustrated that at one point, using the modified mmcsd.c that I posted above, I wrote data into the reserved sectors (address 0x200 to 0x500). forgot what I wrote, but should be something like 0xFF. Then my SD card failed. It couldn't be formatted by computer, and I thought this is it, the SD card is broken...
Then, again, using the modified mmcsd.c, I wrote 0xAA into the reserved sectors (address 0x200 to 0x500). Eventually, the SD card can be formatted and it was back to life.
Since then, the problem of unable to read correctly from reserved sector is gone, the physical and logical sector offset is gone too, and the modified mmcsd.c no longer working (not sure why). I'm using the original mmcsd.c now.
Tried it with another SD card. It works. But this method is extremely dangerous. There is no guarantee that the card will be back to life. So, before someone can explain what happened, better don't try it. |
|
|
CoverUp
Joined: 04 May 2010 Posts: 7
|
|
Posted: Thu Jun 03, 2010 1:25 pm |
|
|
I don't know why you say that SD card communicates with PIC through logical address. When you write a byte, the SD store the data pointing to the physical address. In fact, you can write data in a raw mode without any file system.
The reserved sector that you mentioned before, are present due to the partition info in the SD card.. added from format() or may be added by the manufacturer. Anyway, the partition info put the offset to the logical address 0, that Windows use to format the card. In fact all the info that must be in sector 0, are stored in the offset.
So when you delete the data present in the reserved sectors, you are deleting part of the MBR. (this is why I delete the first physical sector using mmcsd library), and this explain why your card stop to function and then work again.
If you delete the MBR the system assume that there is no format at all in the media, allowing to you to re-format the media, this time without the offset.
I recommend to use Winhex or some similar software to see the hex content of the sdcard. This help a lot in the debugging process.
Code: |
// this code reset any filesystem in your sd card (using the PIC)
// after use, fill your sdcard with zeros 0x00 (using winhex or similar)
// and finally, re-format the card in windows (FAT32) (FAT 16 has no sense these days, every card in the market is >2GB now and cost nothing)
int32 j;
int r = 0; //0:ok !0:error
for (j=0; j<66536; ++j) {
r = mmcsd_write_data(j, 1, 0);
}//end for
|
Please don't confuse the reserved sectors due a filesystem, with the real reserved sector in the sdcard, which contain info about the sdcard itself.
It easy be confused due the relativity of the things. |
|
|
szkrep
Joined: 13 Oct 2010 Posts: 3
|
|
Posted: Thu Feb 03, 2011 5:11 am |
|
|
I'm using an old 128MB SD card. I understood, that the original format() function is buggy (it's also written in a comment in fat.c...) When I format to FAT32 with 512byte sectors in Windows, i can't do anything with the pic library. If I format it with the provided format(), pic works, but windows sees an empty card. I cleared the whole card with the methods above, in winhex the first values are 0. After that windows prompts me to format it, everything ends easily, but in the end the pic won't do anything with the card.
Does Windows 7 have any difference from xp in formatting cards? Any ideas? |
|
|
szkrep
Joined: 13 Oct 2010 Posts: 3
|
|
Posted: Thu Feb 03, 2011 7:09 am |
|
|
After a few tries it started to work correctly. The funny thing, that it's formatted with the PIC, and that was the solution. Now the computer can also read it -though the printer's SD reader blinks red, that the card is corrupted. Using a laptops internal SD reader (connected to the USB bus) everything works fine.
The "(Example: 'format 5524288' formats a 512MB card)" in the help is incorrect. That value is <desired value in MB>*2*1024 (512*1024*2=1048576; it's the half of it, and mispelled...) |
|
|
evsource
Joined: 21 Nov 2006 Posts: 129
|
|
Posted: Fri Feb 25, 2011 5:22 pm |
|
|
szkrep wrote: | After a few tries it started to work correctly. The funny thing, that it's formatted with the PIC, and that was the solution. Now the computer can also read it -though the printer's SD reader blinks red, that the card is corrupted. Using a laptops internal SD reader (connected to the USB bus) everything works fine.
The "(Example: 'format 5524288' formats a 512MB card)" in the help is incorrect. That value is <desired value in MB>*2*1024 (512*1024*2=1048576; it's the half of it, and mispelled...) |
So what exactly did you do to get the PC to read it okay? I have a PIC working great with reading and writing to a card, but can't see anything on the PC. If I open a disk editor, I can see the contents that I wrote using the PIC. Any suggestions? |
|
|
CoverUp
Joined: 04 May 2010 Posts: 7
|
|
Posted: Tue Apr 26, 2011 10:58 am |
|
|
Ok. some Updates:
Almost all SD card's manufacturers sell their products allready formated.
(With a VBR on it, ready for use)
So Logical and Physical address never match on new cards, and this library works on Physical address.
Now the quick solution is delete the MBR information of the card using this code:
Code: |
// this code reset any filesystem in your sd card (using the PIC)
// after use, fill your sdcard with zeros 0x00 (using winhex or similar)
// and finally, re-format the card in windows (FAT32) (FAT 16 has no sense these days, every card in the market is >2GB now and cost nothing)
int32 j;
int r = 0; //0:ok !0:error
for (j=0; j<66536; ++j) {
r = mmcsd_write_data(j, 1, 0);
}//end for
|
Then you got two options, Format from windows (Preferred method) or Format from PIC.
Both works, but when you format from windows all the MBR have valid information and thus works on everywhere.
If you format from PIC, the MBR only have sufficient information to work properly on some systems (Windows XP at least)
Well, as i mentioned before this is the quick solution, but not the final solution. Because if you ever need to change the SD card, you will need a "special one", pre-formated by you with the previous steps.
If your "customer" use another SD card the system won`t work.
The final solution is re-write the library to work with the offset.
The best way to know what is going on is using winhex or similar and analyze the entire card,You will find something like this..
MBR (on real physical address) with
offset (pointing to a different address (logical address))
Then on the offset address (logical address)
you will find another MBR (because logical is being confused with physical)
and the second offset (pointed to a second physical address)
After delete all the card and re format, the only MBR is located at physical address 0.
The origin of confusion between physical and logical is the VBR, the library only handles MBR and not VBR. |
|
|
championx
Joined: 28 Feb 2006 Posts: 151
|
|
Posted: Tue Aug 02, 2011 1:41 pm |
|
|
Hi! I'm trying to read and write a 4Gb SD card (SDHC). I'm using the library provided by ccs, but I can't make it work.
Is this library compatible with SDHC cards?
Thanks! |
|
|
sigma-mx
Joined: 02 Jun 2008 Posts: 3
|
|
Posted: Wed Aug 03, 2011 3:54 am |
|
|
CCS fat library supports up to 32GB
but i think mmcsd library (physical layer library) dont support SDHC command yet. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|