FatFs is really strange to me. Here's the description of it:
"FatFs is a generic FAT/exFAT filesystem module for small embedded systems. The FatFs module is written in compliance with ANSI C (C89) and completely separated from the disk I/O layer. Therefore it is independent of the platform. It can be incorporated into small microcontrollers with limited resource, such as 8051, PIC, AVR, ARM, Z80, RX and etc. Also Petit FatFs module for tiny microcontrollers is available here."
"Since FatFs module is the filesystem layer independent of platforms and storage media, it is completely separated from the physical devices, such as memory card, harddisk and any type of storage device. The low level device control module is not any part of FatFs module and it needs to be provided by implementer. FatFs accesses the storage devices via a simple media access interface shown below. Also sample implementations for some platforms are available in the downloads. A function checker for low level disk I/O module is available here."
This means that it'll perform all the operations that the FAT filesystem requires, as long as you provide a way for it to read and write sectors to a physical device. Since that means diving into the SD card specification somewhat, I was kinda hoping that that would be something the library would do for me.
I'm incredibly lucky that in the sample implementations shipped with FatFs, there's a sample for PIC24! It's going to be set up for whatever application the person who used it last wanted it for, but I ought to be able to untangle it. Let's have a look.
Okay. The
ffsample\pic24 directory contains instructions for building a breadboard project based on the PIC24FJ64GA002, a DIP PIC similar to the one used in the PSCD32. It's a complicated beast, but I think I can tilt my head and intuit what it's intended to be. It has the standard power connections, connects to a PICKIT, connects to an SD card through SPI, but the user interface is a serial terminal. In the sample program, the user can use a PC with a serial connection to send text commands to the project, and it'll output data and status updates back to you.
I need to unravel what parts of this are important and what aren't. Ideally, I'd like to find a set of functions which provide the necessary missing ham slice that FatFs needs to talk to an SD card, and I can leave the rest.
Surprisingly, it didn't take all that much adaptation to make this sample project work with the Game Raccoon board.
Here's a list of all the files in the FatFs project and the modifications I made to get it working with the Game Raccoon's PIC24FJ64GA006:
•
diskio.h - This file contains return value enums and function prototypes that collectively define the software interface that FatFs requires you to implement on top of the physical layer. I used this file unchanged.
•
ff.c - This contains FatFs' implementation of FAT. I used this file unchanged.
•
ff.h - This contains headers FatFs' implementation of FAT. I used this file unchanged.
•
ffconf.h - This contains configuration options for FatFs. I don't need write functions in the Game Raccoon, but I didn't edit this file to disable them yet. In the end I used this file unchanged.
•
ffunicode.c - This file contains huge tables and functions for converting and handling Unicode characters. I don't need these, and I don't intend to draw a complete Unicode bitmap tileset for the menu... however, there was no pressing need to remove this just yet. I used this file unchanged.
•
mmc_pic24f.c - Physical layer interface implementation for PIC24. The magic macro definitions used for memory-mapped variables in MPLAB X's headers have a slightly different naming convention to the one used by the sample project, plus my chip has a different set of peripherals, so I changed this file in a few places near the top:
• • My version includes the
generic Microchip header.
• •
CS_LOW() and
CS_HIGH() macros required by FatFs to control the
!SS signal to select SD card are changed to refer to the GPIO pin linked to
SPI2!SS.
• •
MMC_CD magic macro variable returns the state of the card detection physical contact. Game Raccoon doesn't connect to this, so I force this to 1 for 'card always present'.
• •
MMC_WP magic macro variable returns the state of the write protection physical contact. Game Raccoon doesn't connect to this, so I force this to 0 for 'card always write-enabled'.
• •
FCLK_SLOW() and
FCLK_FAST() macros are unchanged and still blank. I think these are to force certain PIC chips to dynamically underclock themselves to become compatible with SD cards temporarily. That functionality isn't needed here since I can configure the SD card SPI transfer rate in software.
• •
power_on() sets up the SPI channel for the SD card and enables it. I needed to set this to SPI2 and choose sensible clock prescale values.
• •
power_off() disables the SPI channel.
• •
xchg_spi() non asynchronously exchanges (sends) a byte with the SPI channel used by the SD card. I only needed to change this to SPI2.
• •
xmit_spi_multi() non asynchronously exchanges (sends) a byte series with the SPI channel used by the SD card. I only needed to change this to SPI2.
• •
rcvr_spi_multi() non asynchronously exchanges (receives) a byte series with the SPI channel used by the SD card. I only needed to change this to SPI2.
• • The rest of
mmc_pic24f.c is surprisingly unchanged!
•
main.c - I didn't use any of the code from the sample project's
main.c as it wasn't necessary. In my own
main.c I added the following:
• • FatFs requires the function
disk_timerproc() to be called at 1000Hz frequency, so I used Timer2 for this.
• • And that's about it. The only other set up required to use the SD card is to call the FatFs external interface to mount the filesystem, etc.
•
pic24f.h - Preprocessor defines holding processor clock speed and macros for enabling and disabling interrupts used within FatFs. I use
FCY in my code anyway, and I copied the macros into my
main.c before other headers. I haven't looked into where these macros are called, but I assume they're necessary so I kept them.
The rest of the files are specific to the sample project and I didn't need anything from them.
•
Makefile - Sample project makefile. Unneeded.
•
pic24sp.ini - Various configuarion for sample project. Unneeded.
•
picmmc.map - Various compilation object/symbol/map files. Unneeded.
•
picmmc.mcp - Various compilation object/symbol/map files. Unneeded.
•
picmmc.mcs - Various compilation object/symbol/map files. Unneeded.
•
picmmc.mcw - Various compilation object/symbol/map files. Unneeded.
•
pic_mmc.png - This is the above image. Unneeded.
•
tt.ini - Configuration options for the terminal program recommended by the sample project. Unneeded.
•
uart_pic24f.c - UART functions for the sample project. Unneeded.
•
uart_pic24f.h - UART functions for the sample project. Unneeded.
•
xprintf.c - Formatted text input and output routines for the terminal interface. Unneeded.
•
xprintf.h - Formatted text input and output routines for the terminal interface. Unneeded.
It was very surreal to be able to call the FatFs functions and see realistic data coming back.
To slowly integrate FatFs' functionality into the Game Raccoon, I'd use one function at a time, stepping over its invocation in a debugger, watching the output variables and making sure each function did what I expected of it:
f_open() on a valid path to a file should return success and give you a handle,
f_size() returns the size, directory scanning with
f_readdir() ought to populate the
fname field with the currently identified item, and so on. I didn't have any problems with any of these.
FatFs takes up over half the ROM space within the PIC, but that's exactly as expected. It's welcome to it, considering the amount of heavy lifting it's destined for. If I wanted (or rather
needed) to reduce this, I could set the configuration flags to exclude write functionality, remove Unicode support, and so on.
Sorry, Microchip, but you made no sense and I couldn't get you compiling. See ya later.