FATFS on the PIC32MZ post

How to use FATFS with the PIC32MZ

Update 06/09/2018: I haven't implemented the writing part yet so there may still be some compatibility issues with the latest FatFs. You may need to make the following changes to ffconf.h:

#define FF_FS_NORTC     1
#define FF_NORTC_MON    9
#define FF_NORTC_MDAY   6
#define FF_NORTC_YEAR   2018
#define FF_FS_READONLY  0
#define FF_FS_RPATH     1

This is part 2 of 2 of the article on SPI on the PIC32MZ. Last time I discussed how to set up SPI and all the tricks and traps involved therein. Today I will be discussing how to use the FATFS library with our code in order to give us access to the files on the SD card. I'm only covering reading of the files today, maybe at some point in the future I'll cover writing.

<TL;DR>

A bit of background and an explanation of what I'll cover today

The problem I set out to solve was that I needed to read 320x240 30fps 16-bit video data from an SD card and show it on an LCD. This is a huge amount of data and the built-in Harmony SD library is far too slow for this. I needed about 4.5MB/s and at the time it was giving me reads of 2MB/s. I came across some code by Riccardo Leonardi and Aiden Morrison (who can be found on the Microchip forums). They'd ported the FatFs interface to PIC32 for the old MX series in a file titled mmcpic32.c. The problem with this was it was also far too slow (it's 7 years old so I can understand that!). After examination of the file I realised I could use a combination of Enhanced Buffers mode and 32-bit SPI reads to speed up the reading section.

I bought a good SD card (Samsung Evo 32GB) and formatted it at 32kB/cluster. After implementing these changes I can get read rates of 4.6MB/s when using 32kB read buffers. Today I'll be discussing these changes. Please bear in mind that SD cards vary wildly in terms of speeds and your results will vary.

</TL;DR>

Before we get down to business, credit where credit is due:
- Most of the work was done by Riccardo Leonardi and Aiden Morrison from the Microchip forums, so thanks to them for their mmcpic32.c file.
- My friend Bryn Thomas did a lot of work in finding out the root cause of why SD transfers were so slow and in using 32-bit SPI and Enchanced Buffers modes
- The FatFs library by ChaN is what made this all possible, so huge thanks to ChaN and all their hard work. The project is being updated to this day (last update was September 3 2018, yesterday at the time of writing).

STEP 1

OK, before we get started you will need to download the FATFS library and extract the contents to your project folder. I'm using version R0.13b for reference.

STEP 2

The next step is to include the header files needed:

#include "ff.h"
#include "diskio.h"

STEP 3

Next, download the mmcpic32.c file and copy it into your project folder.

STEP 4

Open mmcpic32.c and modify the following to make it work with your project:

/* Port Controls  (Platform dependent) */
#define CS_SETOUT() TRISBbits.TRISB4 = 0 
#define CS_LOW()  LATBbits.LATB4 = 0    //MMC CS = L
#define CS_HIGH() LATBbits.LATB4 = 1    //MMC CS = H
//Change the SPI port number as needed on the following 4 lines
#define SPIBRG  SPI2BRG
#define SPIBUF  SPI2BUF
#define SPISTATbits SPI2STATbits
#define SPICONbits SPI2CONbits

For my example, I'm using SPI2 and I have CS on pin RB4.

STEP 5

In your main C file, you need to add the following code:

// Global variables
FIL file; // File handle for the file we open
DIR dir; // Directory information for the current directory
FATFS fso; // File System Object for the file system we are reading from
FILINFO fileInfo; // Information for the file we have opened (not really necessary to have this)

void init_disk()
{
    // Wait for the disk to initialise
    while(disk_initialize(0));
    // Mount the disk
    f_mount(&fso, "", 0);
    // Change dir to the root directory
    f_chdir("/");
    // Open the directory
    f_opendir(&dir, ".");
}

STEP 6

Finally, in main() or setup() or whatever you use, call:

init_disk();

And... that's that! Now using files can be done just like you would on any other platform. For example, to open a file called "test.txt" in the root directory, you'd do this:

f_open(&file, "/test.txt", FA_READ);

Now you have the file handle stored in file and can use it as you please. For example, to read 32768 bytes into an array, do this:

unsigned char buffer[32768]; // buffer stores the data read from the file
int bytes_read; // bytes_read stores how many bytes were actually read

f_read(&file, buffer, 32768, &bytes_read);

If count has a different number of bytes to 32768 that means the end of the file was reached before it could read 32768 bytes or an error occurred.that I intended it to be. Next time we'll use this code and understanding of SPI to communicate with an SD card.

Here's the code

Categories: pic32

Tags: code