Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

SD Card thought

Status
Not open for further replies.

AtomSoft

Well-Known Member
Ok i have a bunch of PIC micros and most with small amounts of memory and the large PICs are overkill so i was thinking of a way to use a SD Card without needing alot of memory.

This will work well for reading ONLY! no write feature unless you are writing RAW data. But no FILE access tho since it requires to write 512 bytes. I got a theory on this too tho.

Ok to READ with small amount of memory... well a custom amount even 1 byte!
Code:
int readCustom( LBA a, unsigned int start,unsigned int length, char *p)
// a        LBA of sector requested
// p        pointer to sector buffer
// start    Start Byte
// length   Length of bytes
// returns  TRUE if successful
{
    int r, i;
    int x;
    x = (512 - length) - start;
    READ_LED = 0;
        
    // 1. send READ command
    r = sendSDCmd( READ_SINGLE, ( a << 9));
    if ( r == 0)    // check if command was accepted
    {  
        // 2. wait for a response
        for( i=0; i<R_TIMEOUT; i++)
        {
            r = readSPI();     
            if ( r == DATA_START) 
                break;
        } 

        // 3. if it did not timeout, read 512 byte of data
        if ( i != R_TIMEOUT)
        {
          for(i=0;i<start;i++)  //Skip the bytes until we hit our start byte
            readSPI();

            i = length;         //get our bytes using the length as a count
            do{
                *p++ = readSPI();
            } while (--i>0);

            // 4. ignore CRC
            readSPI();
            readSPI();

          for(i=0;i<x;i++)      //skip the rest if any
            readSPI();
        } // data arrived
    } // command accepted
    // 5. remember to disable the card
    disableSD();

    READ_LED = 1;

    return ( r == DATA_START);    // return TRUE if successful
} // readSECTOR

EDIT:

To write we would need 1 512 buffer since we can only write 512 block and the SD handles that so we can just ask it to skip... (not tha ti know of lol)
 
Last edited:
This can help alot because we dont waste space. Like if we need to verify:
Code:
Address   Desciption                   DEFAULT   SIZE
1FEh        Boot Signature Code   55h AAh    2 bytes
we just setup a small variable about 2 bytes aka a INT or a 2 Byte Array and :
Code:
//Get Boot Signature Code (sector 0x00000000)
//0x01FE =our byte start
//2 = our byte length
//buff = our buffer (2 byte array or 1 int)

//unsigned char buff[2];
unsigned int buff;
atmp  = 0x00000000
result = readCustom(atmp, 0x01FE, 2, buff);
 
Last edited:
...
To write we would need 1 512 buffer since we can only write 512 block and the SD handles that so we can just ask it to skip... (not tha ti know of lol)

Actually I developed a "kludge" for that. You don't need to write 512 bytes of DATA, you just need to write 512 bytes.

The easiest way I found was to write 4 bytes for every real data byte, so you write a 512 byte block to the card but it only has 128 actual bytes (every 4th byte is real the other 3 are zeros).

Then on the PC when you read the file from the card you can simply read it as 128 "words" which are a 4byte data type so it reads the data with no conversion needed.

So the PIC only needs a 128 byte buffer, which just about all PICs can do.

Of course this is a little wasteful of the memory card, but since you can buy a 4Gbyte memory card for about 6 peanuts these days that doesn't really matter. ;)
 
Mr RB so you would still have to read 512 bytes dude lol what if i want to edit data in on the 100th byte? how would i edit it without losing the other data?
If its fine to waster space then i would do this..

Setup a #define to set the max to write or what ever our pic can handle like

#define SIZE 128

So we know how much data the pic can buffer and just read from start of 512 byte and read those 128 bytes then you can skip the rest.

Then you can alter the 128 bytes and write it back to start of sector you are on.

.. this way you can have it set the max size your pic can handle.
 
The below code will only use the first 128 Bytes of each sector (512 byte).
You define the max your pic can handle like:
#define B_SIZE 512 //Full sector
#define B_SIZE 384 //3/4 of a sector
#define B_SIZE 256 //half a sector
#define B_SIZE 128 //4th of a sector


Code:
#define B_SIZE              128

int writeSECTOR( LBA a, char *p)
// a        LBA of sector requested
// p        pointer to sector buffer
// returns  TRUE if successful
{
    unsigned int r, i;
    char x;

    x = 512 - B_SIZE;
    // 0. check Write Protect
    //if ( getWP())
        //return FAIL;

    // 1. send WRITE command
    r = sendSDCmd( WRITE_SINGLE, ( a << 9));
    if ( r == 0)    // check if command was accepted
    {  
        // 2. send data
        writeSPI( DATA_START);
        
        // send B_SIZE bytes of data
        for( i=0; i<B_SIZE; i++)
            writeSPI( *p++);

        for(i=0;i<x;i++)      //skip the rest if any
            writeSPI(0x00);

        // 3. send dummy CRC
        clockSPI();
        clockSPI();
    
        // 4. check if data accepted
        r = readSPI(); 
        if ( (r & 0xf) == DATA_ACCEPT)
        {   
    
            WRITE_LED = 0;

            // 5. wait for write completion
            for( i=0; i<W_TIMEOUT; i++)
            { 
                r = readSPI();
                if ( r != 0 )
                    break;
            } 

            WRITE_LED = 1;


        } // accepted
        else
            r = FAIL;

    } // command accepted

    // 6. disable the card
    disableSD();

    return ( r);      // return TRUE if successful

} // writeSECTOR

int readCustom( LBA a, char *p)
// a        LBA of sector requested
// p        pointer to sector buffer
// start    Start Byte
// length   Length of bytes
// returns  TRUE if successful
{
    int r, i;
    int x;
    x = 512 - B_SIZE;
    READ_LED = 0;
        
    // 1. send READ command
    r = sendSDCmd( READ_SINGLE, ( a << 9));
    if ( r == 0)    // check if command was accepted
    {  
        // 2. wait for a response
        for( i=0; i<R_TIMEOUT; i++)
        {
            r = readSPI();     
            if ( r == DATA_START) 
                break;
        } 

        // 3. if it did not timeout, read 512 byte of data
        if ( i != R_TIMEOUT)
        {
            i = B_SIZE;         //get our bytes using the length as a count
            do{
                *p++ = readSPI();
            } while (--i>0);

            // 4. ignore CRC
            readSPI();
            readSPI();

          for(i=0;i<x;i++)      //skip the rest if any
            readSPI();
        } // data arrived
    } // command accepted
    // 5. remember to disable the card
    disableSD();

    READ_LED = 1;

    return ( r == DATA_START);    // return TRUE if successful
} // readSECTOR

Since:
2 gigabytes = 2,147,483,648 bytes / 512 (sector length) = 4,194,304 So you can have about 4 million buffers on the card. Depending on B_SIZE:

B_SIZE = 128 = 0.5GB (500MB)
B_SIZE = 256 = 1.0GB
B_SIZE = 384 = 1.5GB
B_SIZE = 512 = 2.0GB

2GB cards go for about $5 which is cheap anyway. Even if using only 500MB of space from it :D
https://www.google.com/products/catalog?hl=en&q=2gb+SD&cid=17626130196514867655&scoring=p#ps-sellers
 
Last edited:
Hey guys i just made a program using VB6 to read sectors on a HDD or SD card. You can select the sector and target and then view a 512 chunk of hex and charaters. Also have a next and prev. button.
Nice simple fast nothing special.

I made it because im making my own Filesystem on a SD card and needed RAW access so i though this might help alot of people tho..

ENJOY!

EDIT

In all the hype i forgot to post it lol

BTW this is the full source no EXE file ok! so you can know its safe lol its read only i havent added the option to write yet.
 

Attachments

  • vbread.zip
    2.5 KB · Views: 216
Last edited:
NOTICED a problem with MDD-FS demonstration code:

Code:
	// Read one four-byte object
	if (FSfread (receiveBuffer, 4, 1, pointer) != 1)
		while(1);

If you try the above with READ or WRITE it may fail if you dont use there exact stuff. This is because they used " != 1" . Which is BAD. If it fails it returns 0 or another number not always 1 so why did they do that? i got lost cuz of that ... here is a fix ...when ever you use something like the above try using "==0" or "!" like:

Code:
	// Read one four-byte object
	if ([B]![/B]FSfread (receiveBuffer, 4, 1, pointer) )
		while(1);

//or
	// Read one four-byte object
	if (FSfread (receiveBuffer, 4, 1, pointer) [B]== 0[/B] )
		while(1);
 
Last edited:
...
If its fine to waster space then i would do this..

Setup a #define to set the max to write or what ever our pic can handle like

#define SIZE 128

So we know how much data the pic can buffer and just read from start of 512 byte and read those 128 bytes then you can skip the rest.

Then you can alter the 128 bytes and write it back to start of sector you are on.
...

OK, that is a very obvious solution and it works. :) But now when your PC reads the data file from the card you have 2 problems;
1. It needs to know the chunk SIZE
2. It needs special software to parse the file, ie read the chunks and ignore the padding.

With my method the data in the file is contiguous, and can be read simply as a file by any PC. It just stores the data as "word" 32bit not as "char" 8bit. Since "word" is a default for most windows software that is all fine.

Mr RB so you would still have to read 512 bytes dude lol what if i want to edit data in on the 100th byte? how would i edit it without losing the other data?

The system I used for reading the data from a file was just to read a whole block of 512 (because you have to read a whole block) and just keep the data required by the PIC. In the example above the PIC reads a 512 byte block, keeps every 4th byte and stores in its 128 byte ram array. So you have seamless reading and writing of a whole memory card in blocks of 512 using just 128 bytes of PIC ram.

Now if you need the PIC to read data written by the PC, you can get the PC to write 1byte data as "words" as explained above.

If the PC has written 512 actual bytes, then you can read that 512 byte block and just keep the 128 (etc) bytes you need. But you cant write 512 actual data bytes unless you have 512 bytes of ram or buffer with the PIC eeprom memory (there are some examples of that on the net).

In my first post I was not saying anything you did was wrong, you said you weren't using file access as you didnt have 512 bytes of ram and I suggested a nice kludge solution I developed that works, to allow proper file systems with only 128 bytes of ram needed. There's a lot of people think you just CAN'T do memory card file systems on the 16F PICs, but my system lets you do it quite elegantly, the only drawback is the 1:4 data size wasted in the memory card.
 
heh i never said yours was wrong either.

A solution for telling the PC software the size it having my own boot sector type. Have it on a sector with no reserved data.

So you can place information like buffer size and such on it and have that be like a custom MBR.

Your solution also requires custom PC software regardless since it is also raw .
 
but its cool now i got the MDD-FS to work so im using it for now. Im going to try and make a few files using my bmp to hex and the glcd and see if i can read them from the sd card.
 
I've never heard of the petite FS. I'm currently working on a project with a dsPIC33 and SD card using the MDD-FS. Have you done something similar? I'm having trouble getting past the initialization.

Thanks for your help,
- Michael
 
OK, so the petit file system is only for 8-bit controllers. I'm using a 16-bit controller. Thanks for the links, I'll see if they can help me understand the initialization sequence.

- Michael
 
8 bit, 16 bit 3000 bit micro controller, won't change the interface.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top