Home network hardware Connecting an SD card to a microcontroller. Data recovery from monolithic SD and MicroSD cards SD card slot pinout

Connecting an SD card to a microcontroller. Data recovery from monolithic SD and MicroSD cards SD card slot pinout

Artem Makarov aka Robin

27.09.2014

Recently, flash drives made on a monocrystal basis, so-called monoliths, are increasingly being brought in for data recovery. Today we will talk about the process of recovering data from such a monolith - an SD memory card sent by a partner from the city of Kemerovo. The video of the wedding was recorded on the card, and when the celebration was successfully completed and it was time to start editing and releasing gift DVDs, the flash drive died for a long time.

Recovery of monolithic SD memory cards

It is noteworthy that from the outside it is not clear whether this is a “classic” SD card, with a PCB board, NAND memory and a controller, or a single crystal. Until the plastic case is opened. Most often, the failure of such memory cards is due to a failure in the translation tables. Less often - electromechanical damage.

To recover files from such a card, the first thing you need to do is read dumps from the crystal. To do this, the protective varnish that hides the tracks and contact pads of the monolith is removed mechanically (cleaning and grinding). After which the flash drive starts to look like this:

Tracks and pinout of a monolithic SD card

The contact pads to which the data bus, chip enable, read/write busy, power, etc. are connected are visible. Of course, nothing is marked, and datasheets detailing what to connect where are also not freely available. The pinout can be found either by taking exactly the same working flash drive (and there are a great many types of them, and having found the same conventional Kingston SD in appearance, you can get a completely different device inside) and, armed with a logic analyzer, painstakingly find out what goes where and why. Or by purchasing the pinout from a person/office that has already done such work for you.

The result is something like this:

Or this:

Now we need to eliminate internal transformations in the resulting dumps. The first step is to remove the XOR mask that the flash drive controller applied when writing information to NAND cells. With this mask the sector looks like this:

and when the required XOR mask is selected and applied, the sector takes on a meaningful appearance:

After eliminating XOR transformations, you need to set the correct sector geometry, describe the markers and the ECC data correction area. Correct bit errors using the ECC algorithm. Find out in what sequence the blocks were located and their size. Since the controller type is unknown (it’s a monolith!), it is necessary to determine which collector to use in this particular case. Will it be assembling the final image using a sector marker or using the rest of the translation tables?

After the image is assembled, check conflict blocks that have the same marker for relevance and substitute into the image those with which the final result will be the best. Having received a familiar image with a file system, you can open it in any disk editor and upload the files the user needs.

Of course, many operations are quite automated, but nevertheless the amount of work involved in recovering data from monoliths (single crystals) is very large. Not every engineer or company that recovers information is eager to get involved in such work. And the price tag for this kind of restoration is very far from the concept of “budget”.

Here is another case using the example of SD Sandisk recovery - the same monolith, only made a little differently inside:

Ready to Read

Recovery of MicroSD flash drives

And here is what the contact pads look like on a Micro SD card. It should be noted right away that these are just a few examples of many layout options.

And here is the pinout option for a monolithic Memory Stick Pro Duo memory card

This is not to say that it is a monolith, but it is not an ordinary USB flash drive either. The memory chip (crystal) is filled with compound (glue).

And here’s what a monolithic Olympus XD Picture card looks like, from which it was necessary to restore photographs:

Restoring broken Micro SDs

Separately, it is worth mentioning the successful completion of tasks to recover information from MicroSD flash drives that were broken into pieces, with a broken piece, with cracks in the body, etc. Some examples in the pictures below:

In all cases, when we are talking about a flash drive broken into pieces, with a broken part, etc. It is possible to restore information if the NAND crystal remains intact. For example, in the Sandisk microflash drive from the example below, as a result of careless operation, a piece broke off and damaged the tracks marked with a red oval.

The Hardmaster laboratory is one of the few that have experience and qualifications in data recovery from monolithic USB, SD, microSD, Memory Stick, etc. memory cards. If there are important files on your monolithic broken flash drive that you would like to return, please contact us!

A few years ago in May 2011, the creator of the cult game “Elite” David Braben presented the first concept of a single-board computer Raspberry Pi. This moment became a turning point in my life. The idea of ​​making a computer the size of a flash drive was on the surface, but it only gained momentum with the help of the Raspberry Pi Foundation.

Already on July 25, 2011, the alpha version of the computer was put into production. Unfortunately, the concept of the project has changed, and it is now positioned as a computer the size of a credit card. Despite this circumstance, millions of people followed him. I too obeyed the crowd effect, checking the official project page every day. A long and painful wait began for the “miracle”, which happened on February 29, 2012 - the start of sales.

The Raspberry Pi could be purchased through the Farnell network or from RS Components. As it turned out, only pre-orders could be made on February 29th. None of the offices had these boards in stock. The first batch of devices was only 10,000 copies, so given the hype around the project, placing an order was very difficult. However, having overcome all difficulties, at 14:06 on the same day the computer was purchased for £46.73 from Farnell.

None of my foreign orders were fulfilled for so long. I was extremely upset that Farnell, having charged £20 for delivery, sent the parcel on May 29, 2012 (2 months later) by regular mail without a tracking number. Surprisingly, the symbiosis of the Royal and Russian Mail delivered the parcel safe and sound on June 22. This was the most desired package in the last few months, so, unable to withstand the stress, I had to take time off from work and run to the post office.

There is no point in talking about how to configure the Raspberry Pi for the first launch. I’m a couple of years late with an article on this topic; many lines about this have already been written on other resources, and on Youtube A sufficient number of videos have been posted. I want to talk about a significant design flaw for me - the inconvenient location of the SD card slot. When the card is inserted, it protrudes greatly beyond the board, which spoils the appearance of the homemade case.

There are two options for solving this problem: solder an SD->microSD adapter parallel to the connector installed on the Raspberry Pi (you can read how to do this operation in the article on Habré), or use a Low-profile MicroSD->SD adapter. The first option is simply unacceptable for me - well, I don’t dare to solder the board, because... I'm afraid of ruining the presentation of my Raspberry. I think that the best choice is to use a Low-profile adapter.

Initially, it was decided to purchase such an adapter in one of the foreign online stores. There is a choice, but the cost of such trinkets is simply prohibitive. The cheapest copies cost $10, and some samples frankly look homemade. The final decision to make the adapter yourself was made after visiting the DIYGadget website; note how easy it is to repeat their creation.

Ready? Let's move from words to action. To make the adapter correctly, let’s study the specifications for SD and microSD cards. I tried to systematize everything that is necessary for production in tables 1, 2.

Table 2: SD memory card pinout

By connecting the corresponding contacts on the memory cards, and combining Vss1, Vss2, we get the electrical circuit diagram of the adapter.

To make an adapter we need:
1) Holder for microSD (CF TFC-WPCE-08 MICROSD CARD) – 52.22 rub.
2) A piece of double-sided foil fiberglass laminate with an area of ​​about 4 cm 2 (2% of the position FOIL GLASS TEXT LITE. 1.5MM 2 SIDES) – 3 rubles.
3) Materials for installation (ferric chloride, tin, flux) – 10 rubles.

Then the cost of the project will be 65 rubles 22 kopecks and a certain amount of free time. In order to reduce the cost of the design, you can replace the microSD card holder with a CF TFC-WPCER-08 MICROSD CARD. Unfortunately, this item was not available in the Promelektronika JSC warehouse, so I purchased a more expensive option. I draw your attention to the fact that if you change the type of holder, you may not be able to use my template for LUT (laser ironing technology).

I used Autocad to design the PCB because... my favorite SprintLayout could not please me with the presence of the required template. For those who like to modify a printed circuit board, you can download the source in DWG format, and if there is no such need, then a blank in PDF format (I recommend checking the dimensions before applying the PDF template).

After the template is transferred to the board, I recommend drilling holes with a diameter of 0.5 mm to transition from one layer to another.

I make the transition from layer to layer using a thin wire, having previously irradiated the tracks of the future adapter. In those places where the holes are located under the microSD holder, it is necessary to grind off drops of tin with a file so that it is installed without distortion. Lastly, we install the holder. If various fluxes were used during the manufacturing process of the board, be sure to wash the board before pushing it into your Raspberry Pi.

Make an adapter yourself or buy it – the choice is yours. To make your choice more informed, I have selected several links for purchase especially for you:
1) Raspberry Pi Premium Low-profile MicroSD (TF) to SD Card Adapter. Protect Board.
2) Raspberry Pi Low-profile MicroSD to SD Card Adapter, SD card won't get damaged!!
3) MicroSD to "short" SD / RS-MMC adapter. For Everdrive carts, Raspberry Pi, etc.
4) Low-profile MicroSD to SD Card Adapter for Raspberry Pi.
5) SD card adapter for Raspberry pi REV2 +free shipping.

In conclusion, I would like to say that all material is intended for informational purposes only. The use of developments for commercial purposes is strictly prohibited. Reproduction of materials is possible only with my permission and in compliance with references to the original source. Those who want to support not only in word, but also in deed, and also thank me, please email me.

To assemble the device yourself, you need to download the following files:
1. Source board for LUT in DWG format
2. Payment for LUT in PDF format

Good luck in your endeavors!!!

Lesson 33

Part 1

SPI. SD card. FAT

Today we will continue our favorite topic on the SPI interface. We are done with this bus to each other of the Atmega8a and ATTtiny2313 controllers. And today we will try to connect a memory card to the microcontroller via this bus using this interface SD (Secure Digital).

This card can also be connected via the SDIO interface, but since such an interface is not supported in hardware by our controller, we will not touch on it in this lesson. We are interested in the type of bus connection SPI, since we already have good accumulated knowledge on this topic, as well as hardware support in the controller that we are programming.

Nevertheless, we will look at the pinout of the card legs for both types

Well, since we are interested in the second type, we will deal with it.

And there’s not much to understand here. We know all these abbreviations. All standard SPI interface pins are here and there is nothing superfluous here.

Now about the map in general. This card allows us to store data; its memory type is FLASH, which, compared to EEPROM type memory, is also non-volatile, that is, when the power is turned off, the data does not disappear anywhere, but remains stored. Also, this memory has differences, we will get to know them during the programming process. One of the main differences is that, just like in EEPROM memory, we cannot write one byte to this memory. Theoretically, of course we can, but either only ones from our byte or only zeros will be written there, depending on the type of FLASH - NOR or NAND. That is, before writing a byte, you need to erase it, and due to the organization of this memory, we can only erase in blocks, so we can therefore write only in blocks. But there is the greatest difference from EEPROM - this is the price. It is many times cheaper, sometimes even orders of magnitude cheaper for one stored unit of information (per megabyte, per gigabyte). Therefore, FLASH memory usually always has a much larger amount of information.

There are 4 types of SD, but we will study this a little later.

Let's connect this card while in Proteus

Everything is simple here. Actually not quite like that. More resistors needed

These resistors are needed to ensure appropriate levels, since the card is powered by 3.3 volts. In general, according to technical documentation, from 2.7 to 3.6 volts.

Also, it is not indicated in the proteus, but in fact we will power our card from a separate power supply by installing a microcircuit that converts 5 volts to 3.3 volts.

Or rather, we will not install anything, but will use a ready-made module in which everything is already installed.

We also have a display connected, as in expanding the functionality of the display library.

This is how it all looks in practical terms:

This is what the module with holder looks like

You can find such a module everywhere, it costs a penny. The module that connects via SDIO costs more. We also see that the module already has a microcircuit installed to reduce the voltage to 3.3 volts. And we connect power only to the 5 volt contact, and don’t connect anything to 3.3

Also, all level dividers are installed on the module, that is, this module is designed specifically for connection to 5-volt devices.

And I dug up a flash card for testing with 32 megabytes, exactly a megabyte and not a gigabyte

This flash card was given as a gift along with some camera and it is best suited for our tests, at least we will not think that this or that glitch is due to too much memory on the card.

The entire code was also taken from the last lesson along with the display library, since we will be using the function that we created in the last lesson very actively, but of course a new project was created and named accordingly MYSD_SPI.

Let's remove unnecessary lines, in main() we will only have this

intmain( void)

unsignedinti;

Port_ini();

LCD_ini(); //initialize the display

Clearlcd(); //clear the display

Setpos(0,0);

Str_lcd( "String 1");

Setpos(2,1);

Str_lcd( "String 2");

Setpos(4,2);

Str_lcd( "String 3");

Setpos(6,3);

Str_lcd( "String 4");

Delay_ms(2000);

// for (i=0;i<=22;i++) {str80_lcd(buffer2+i*20);_delay_ms(1000);}

While(1)

Since we will not output the text character by character, we can use the char type in the variable

unsignedchar i;

Now one more nuance.

In order for us to work with an SD card in Proteus, it is not enough for us to add the holder itself with the card; we also need to attach the flash card image file in its properties.

It's not difficult to create one. One way is to create using the WinImage program.

We create a new file in it using the menu item File -> New. Select the very last item in the dialog and click "OK"

For the test in Proteus, a size of 4 megabytes is enough for us, so in the next dialog we will change the field with the number of sectors, and also select the FAT12/16 format, because the specifics of working with a 32-bit file system are slightly different, and we will also click “OK”

In general, of course, we can leave FAT32, since we do not work with the file system yet, but in further parts of the lesson we will work with the file system and we will work with 12/16.

Then we save our created file using the File -> Save As menu item. And we save it in the folder where we have the saved proteus project. Let's name the file and click "Save"

Also, then we will need to make sure that this file is not with the “read-only” attribute, and after that we will be able to connect it in Proteus. You will have to manually enter the file name, since Proteus requires some kind of its own format and our file will simply not be visible

We don’t need any path, since the file is located in the project folder. Click "OK".

We don’t need to initialize the bus, since our SPI will be software-based; not all flash cards work correctly with hardware, so we won’t need to use any registers. Hardware is, of course, better, but in order to thoroughly understand the operation of the protocol, you also need to work with the software, that is, twitch the legs of the ports. In general, looking at the diagram, it may seem that we have everything in hardware, since I chose exactly these legs, this is because I just chose it that way, so that later, maybe someone will try to work with the hardware implementation tires.

Let's add macro substitutions for the port legs

#include"main.h"

#defineMOSI3

#defineMISO4

#defineSCK5

#defineSS2

Let's add code to initialize the legs to the port initialization function

voidport_ini( void)

PORTD=0x00;

DDRD=0xFF;

PORTB|=(1<< SS)|(1<< MISO)|(1<< MOSI);

DDRB|=(1<< SS)|(1<< MOSI)|(1<< SCK);

We leave the MISO pin at the input, since by default all the bits in the register are zero, and we simply do not touch it. We also immediately turn on the high level in MOSI and SS, and pull up a resistor to MISO.

Let's write a function for transferring a byte over the SPI bus

voidSPI_SendByte( unsignedcharbyte)

{

}

Let's add a variable for the loop and the loop itself

voidSPI_SendByte( unsignedcharbyte)

unsignedchari;

for( i=0; i<8; i++) //move by bits of the byte

{

}

I think it’s clear why we count to 8, since we are transmitting exactly 8 bits.

Well, let’s start transmitting them little by little.

Let's first check the leftmost bit, isolating it from the entire byte by masking, and if it is equal to 1, then we will set it to 1 on the MOSI bus, and if it is 0, then we will not touch the bus

for( i=0; i<8; i++) //move by bits of the byte

We displayed the image on the display from an SD card, but some points were missed in it, the first was connecting the card itself, the second was that only part of the library’s functions was considered Petit FatFs, let's look at these points in more detail.

Communication with the card is possible via one of two interfaces, SPI or SD.



It must be said that the SD interface can operate in one-bit and four-bit modes.

The card connection diagram via SPI is standard and looks like this; unused card pins need to be connected to the power supply using a 10K resistor.


But in amateur designs, pull-up resistors are often neglected, simplifying the connection diagram.

It should be noted that when connected via SPI, the card is very demanding on the supply voltage and a slight drop in the supply voltage leads to the card not working, this has been tested from personal experience, there is nothing to say about the SD interface, I have not tried it yet. I wrote all this to mean that For power supply, be sure to install capacitors. As for the inductor, it should be designed for a current of up to 100mA, but it is not necessary to install it.

The diagrams shown above show that the card needs 3.3 volts to operate; accordingly, the voltage in the data transmission lines should not go beyond the range of 0 - 3.3 volts, and here the question arises, what to do if the MK is powered by 5 volts?
The answer is simple, you need to match the data lines, and this can be done using a conventional resistive divider.


The diagram shows that the MISO line does not need to be coordinated in the same way as data is transmitted via this line from card to MK.
In fact, few people connect the card directly to the MK; it is much more convenient to connect a card connector to the MK or buy a shield with a connector and all the necessary wiring.

We've sorted out the connection, let's now look at how to use the library Petit FatFs, which is designed for 8-bit microcontrollers with small memory sizes.

The library consists of 5 files:
integer.h- a header file that describes the main data types.

diskio.h- a header file in which prototypes of low-level functions for working with disk and the status codes that they return are declared.

diskio.c- low-level functions must be implemented in this file; initially there are “stubs” there.

pffсonf.h- configuration file.

pff.h- a header file in which prototypes of functions for interacting with the disk file system are declared.

pff.c- the file contains implementations of functions for interacting with the disk file system.

It can be seen that in order for the library to work, it is necessary to implement low-level functions. But if we are talking about AVR or PIC, for them on the website you can download an example of working with the library, which contains the file mmc, it already implements low-level functions. It is also necessary to set the library configuration in the pff.h file and write the functions necessary for SPI operation.

Functions of Petit FatFs.

FRESULT pf_mount (FATFS*)- the function mounts/unmounts the disk. This function must be called before working with the disk; if you call the function with a null pointer, the disk is dismounted. The function can be called at any time.

Options
FATFS* fs- a pointer to an object of type FATFS; a description of this structure can be found in the file pff.h. We just need to declare a variable of this type.

Return values:
FR_OK (0)
FR_NOT_READY- the device cannot be initialized
FR_DISK_ERR- an error occurred while reading from disk
FR_NO_FILESYSTEM- the disk does not have a valid FAT partition

FATFS fs;//declare an object of type FATFS //mount the disk if (pf_mount(&fs) == FR_OK) ( //the disk is mounted, we work with it //unmount the disk pf_mount(NULL); ) else ( //failed to mount the disk )

FRESULT pf_open (const char* path)- the function opens an existing file. Once the file is opened, you can work with it, that is, read from it and write to it. You can work with an open file until another file is open. The function can be called at any time.

Options
const char* path- pointer to a string indicating the path to the file. The path must be specified completely relative to the root directory, separating the directories with a slash.

Return values:
FR_OK (0)- returned if the function is successful
FR_NO_FILE- file not found
FR_DISK_ERR- disk error
FR_NOT_ENABLED- the disk was not mounted

FATFS fs;//declare an object of type FATFS //mount the disk if (pf_mount(&fs) == FR_OK) ( //open the file located in the root directory if(pf_open("hello.txt") == FR_OK) ( //do something ) //open the file located in the folder new if(pf_open("new/hello.txt") == FR_OK) ( //do something ) //dismount the disk pf_mount(NULL) else ( //); Failed to mount disk)

FRESULT pf_read(void* buff, WORD btr, WORD* br)- the function reads the specified number of bytes from the file and stores them in a buffer. If the number of bytes read is less than indicated, then the end of the file has been reached.
#define _USE_READ 1

Options:
void* buff- pointer to the buffer in which the read data is stored
WORD btr- number of bytes to be read
WORD*br- pointer to a variable that stores the number of bytes read.

Return values:
FR_OK (0)- returned if the function was executed successfully
FR_DISK_ERR- disk error
FR_NOT_OPENED- the file was not opened
FR_NOT_ENABLED- the disk was not mounted

FATFS fs;//declare an object of type FATFS BYTE buff;//buffer for reading the file WORD br; //counter of bytes read //mount the disk if (pf_mount(&fs) == FR_OK) ( //open the file located in the root directory if(pf_open("hello.txt") == FR_OK) ( //read 10 bytes from it pf_read(buff, 10, &br); if(br != 10) ( //if br is not equal to 10 //it means we have reached the end of the file) ) )

FRESULT pf_write(const void* buff, WORD btw, WORD* bw)- the function allows you to write data to an open file. In order for the function to work, you need to write in the pffconf.h file
#define_USE_WRITE 1

Options:
void* buff- pointer to the buffer we want to write, a zero value finalizes the recording
WORD btw- the number of bytes we want to write
WORD* bw- a pointer to a variable storing the number of bytes that were able to be written. By analyzing this variable, you can find out whether the end of the file has been reached.

Return values:
FR_OK (0)- returned if the function was executed successfully
FR_DISK_ERR- disk error
FR_NOT_OPENED- the file was not opened
FR_NOT_ENABLED- the disk was not mounted

Due to the fact that the library is designed for microcontrollers with small amounts of memory, this function has a number of limitations:

  • You cannot create new files, and you can only write to existing ones
  • you can't increase the file size
  • can't update timestamp
  • The write operation can only be started/stopped at the sector boundary
  • read-only file attribute cannot prevent writing

In order to understand the penultimate point, you need to know that the card’s memory is divided into blocks (sectors) of 512 bytes each and recording can only be started from the beginning of the sector. Thus, if we want to write 1000 bytes, then the first sector will be written completely, and only 488 bytes will be written to the second, and the remaining 24 bytes will be filled with zeros.

To write to an open file, you must perform the following steps:

  • set the pointer to the sector boundary; if set not to the boundary, the pointer will be rounded to the lower sector boundary
  • call the recording function the required number of times
  • finalize the record by calling the function with a null pointer

In order to give an example of how the recording function works, it is necessary to consider one more function.

FRESULT pf_lseek(DWORD offset)- sets the read/write pointer in the open file. You can set the pointer by absolute or relative offset; for absolute offset you need to pass a number to the function
pf_lseek(5000);
for relative, pass the value of the pointer to the current position fs.fptr and the amount of displacement
pf_lseek(fs.fptr + 3000);
In order for the function to work, you need to write in the pffconf.h file
#define_USE_LSEEK 1

Options:
DWORD offset- the number of bytes by which the pointer needs to be shifted.

Return values:
FR_OK (0)- returned if the function was executed successfully
FR_DISK_ERR- disk error
FR_NOT_OPENED- the file was not opened

You can write data to a file as follows.
FATFS fs;//declare an object of type FATFS BYTE buff;//buffer for reading the file WORD br; //counter of bytes read //mount the disk if (pf_mount(&fs) == FR_OK) ( //open the file located in the root directory if(pf_open("hello.txt") == FR_OK) ( //set the pointer to the first sector pf_lseek(0); //write pf_write(buff, 10, &br); //finalize the recording pf_write(0, 0, &br) )

I’m also leaving here a piece of actually working code that uses all the functions described above.
#define F_CPU 8000000UL #define buff_size 10 #include #include #include "diskio.h" #include "pff.h" #include "spi.h" FATFS fs;//declare an object of type FATFS BYTE read_buff;//buffer for reading the file BYTE write_buff = "hello word";/// /buffer for writing to file UINT br; //counter of bytes read int main(void) ( //mount the disk if (pf_mount(&fs) == FR_OK) ( //open the file located in the new folder if(pf_open("new/hello.txt") == FR_OK) ( //set the write pointer pf_lseek(0); //write pf_write(write_buff, buff_size, &br); //finalize the write pf_write(0, 0, &br); //set the read pointer pf_lseek(0); //read then what was written pf_read(read_buff, buff_size, &br); if(br != buff_size) ( //if br is not equal to buff_size //it means we have reached the end of the file) ) //dismount the disk pf_mount(NULL) while(1) ( ) )

FRESULT pf_opendir(DIR* dp, const char * path)- the function opens an existing directory and creates a pointer to an object of type DIR, which will be used to obtain a list of files in the open directory.
In order for the function to work, you need to write in the pffconf.h file
#define_USE_DIR 1

Options:
DIR *dp- pointer to a variable of type DIR.

const char * path- pointer to a string that contains the path to the directory, directories are separated by a slash

Return values:
FR_OK (0)- returned if the function is successful
FR_NO_PATH- could not find the path
FR_NOT_READY- failed to initialize disk
FR_DISK_ERR- disk error
FR_NOT_ENABLED- the disk was not mounted

//declare variables FATFS fs; DIR dir; //mount the disk pf_mount(&fs); //open the directory pf_opendir(&dir, "MY_FOLDER");

FRESULT pf_readdir(DIR* dp, FILINFO* fno)- function allows you to read the contents of a directory. To do this, you need to open the directory using the pf_opendir() function and call pf_readdir(). Each time the function is called, it will return the name of the object (folder/file) located in the specified directory. When it iterates through all objects, it will return a null string in the fno.fname array element.
In order for the function to work, you need to write in the pffconf.h file
#define_USE_DIR 1

Options:
DIR *dp- pointer to a variable of type DIR, which must be previously declared

FILINFO *fno- a pointer to a variable of type FILINFO, which must be previously declared.

Return values:
FR_OK- successful completion of the function
FR_DISK_ERR- disk error
FR_NOT_OPENED- directory is not open

FATFS fs; FRESULT res; FILINFO fno; DIR dir; //mount the disk pf_mount(&fs); //open the directory res = pf_opendir(&dir, MY_FOLDER); //read the contents of the directory for(;;)( res = pf_readdir(&dir, &fno); //check if there were any errors while reading //and if there are other files in the specified directory if ((res != FR_OK) || ( fno.fname == 0))( break; ) //output in a convenient way fno.fname usart_sendStr(fno.name);

And finally, I’ll leave the working draft here

  • Andreas says:

    Assembling a Memory Stick adapter with your own hands is not difficult if you know the purpose of the functional pins of a particular memory card. Usually called the pinout of a memory card or, for example, a microcircuit, chip, etc. In general, the technology is simple. The layout of the MMC (MultiMedia Card) memory card is cut out from PCB. 7 tracks are cut out on the breadboard (MMC has 7 pins). Then, in accordance with the pinout shown in the figure below, the tracks are soldered to the pins of the SD memory card (has 9 pins, of which 2 are not used), microSD (has 8 pins, of which 2 are also not used, but note that the card microSD memory has no Vcc output) or microM2 (microM2 pinout in the related topic Memory Stick Micro M2 Adapter). That's all. The Memory Stick adapter is ready.

    P.S. We have 1 and 2 GB MMC memory cards in stock. The cost, respectively, is 285 and 360 rubles. Delivery is included in the stated price.

    You can also cheaply buy the following sizes of memory cards:
    - Memory Stick and Memory Stick M2;
    - Secure Digital (SD);
    - Mini SD;
    - Micro SD (TF);
    - Compact Flash;
    -XD;
    - USB Flash Drives of various designs and capacities.
    For example, these:

  • slava says:

    By the way, I’m not very clear in these writings. You can’t get the tracks from MicroCD to MMC on that page, I’ll be very grateful.

  • Andreas says:

    This is what the microSD to MMC adapter will look like:

  • slava says:
  • New on the site

    >

    Most popular