CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

fat.c + mmcsd.c Working but Windows can't read the files
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
CoverUp



Joined: 04 May 2010
Posts: 7

View user's profile Send private message

fat.c + mmcsd.c Working but Windows can't read the files
PostPosted: Tue May 04, 2010 8:33 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue May 25, 2010 10:49 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed May 26, 2010 1:59 pm     Reply with quote

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

View user's profile Send private message

Please share your solution
PostPosted: Thu May 27, 2010 5:57 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat May 29, 2010 7:54 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jun 02, 2010 10:23 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jun 03, 2010 2:34 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jun 03, 2010 2:57 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jun 03, 2010 1:25 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Feb 03, 2011 5:11 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Feb 03, 2011 7:09 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 5:22 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 26, 2011 10:58 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Aug 02, 2011 1:41 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 03, 2011 3:54 am     Reply with quote

CCS fat library supports up to 32GB
but i think mmcsd library (physical layer library) dont support SDHC command yet.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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