This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MMC SDcard BeagleBone bare metal drivers

Other Parts Discussed in Thread: CSD, SYSCONFIG

Hi Javier. Here is the bare metal driver for the BeagleBone MMC/SDcard. 
It uses the petit FAT32 filesystem utilities from elm-chan which is very small-code. 
elm-chan.org/.../00index_p.html

The following is diskio.c which should replace the existing generic file of the same 
name in the pFAT system, a separate library/project in CCS6: 

/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for Petit FatFs (C)ChaN, 2014 */
/* BBB drivers from Jan Kees, github.com/keesj/bonecode */
/*-----------------------------------------------------------------------*/

#include <stdio.h>
#include <inttypes.h>
#include "pff.h"
#include "diskio.h"

#include "bbbMMC.h"

struct sd_card
{
uint32_t cid[4]; /* Card Identification */
uint32_t rca; /* Relative card address */
uint32_t dsr; /* Driver stage register */
uint32_t csd[4]; /* Card specific data */
uint32_t scr[2]; /* SD configuration */
uint32_t ocr; /* Operation conditions */
uint32_t ssr[5]; /* SD Status */
uint32_t csr; /* Card status */
};

struct sd_card card;

/**
* Write a uint32_t value to a memory address
*/
inline void write32(uint32_t address, uint32_t value)
{
REG(address)= value;
}
/**
* Read an uint32_t from a memory address
*/
inline uint32_t read32(uint32_t address)
{
return REG(address);
}
/**
* Set a 32 bits value depending on a mask
*/
inline void set32(uint32_t address, uint32_t mask, uint32_t value)
{
uint32_t val;
val= read32(address);
val&= ~(mask); /* clear the bits */
val|= (value & mask); /* apply the value using the mask */
write32(address, val);
}

/*
* Initialize the card
*/
int mmchs_init()
{
int counter;
counter= 0;
/*
* Soft reset of the controller
*/
/* Write 1 to sysconfig[0] to trigger a reset*/
set32(MMCHS0_REG_BASE + MMCHS_SD_SYSCONFIG, MMCHS_SD_SYSCONFIG_SOFTRESET,
MMCHS_SD_SYSCONFIG_SOFTRESET);
/* read sysstatus to know it's done */
while (!(read32(MMCHS0_REG_BASE + MMCHS_SD_SYSSTATUS)
& MMCHS_SD_SYSSTATUS_RESETDONE)) {
counter++;
}
/*
* Set SD default capabilities
*/
set32(MMCHS0_REG_BASE + MMCHS_SD_CAPA, MMCHS_SD_CAPA_VS_MASK,
MMCHS_SD_CAPA_VS18 | MMCHS_SD_CAPA_VS30);
/*
* wake-up configuration
*/
set32(
MMCHS0_REG_BASE + MMCHS_SD_SYSCONFIG,
MMCHS_SD_SYSCONFIG_AUTOIDLE | MMCHS_SD_SYSCONFIG_ENAWAKEUP
| MMCHS_SD_SYSCONFIG_STANDBYMODE
| MMCHS_SD_SYSCONFIG_CLOCKACTIVITY
| MMCHS_SD_SYSCONFIG_SIDLEMODE,
MMCHS_SD_SYSCONFIG_AUTOIDLE_EN /* Automatic clock gating strategy */
| MMCHS_SD_SYSCONFIG_ENAWAKEUP_EN /* Enable wake-up capability */
| MMCHS_SD_SYSCONFIG_SIDLEMODE_IDLE /* Smart-idle */
| MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_OFF /* Booth the interface and functional can be switched off */
| MMCHS_SD_SYSCONFIG_STANDBYMODE_WAKEUP_INTERNAL /* Go info wake-up mode when possible */
);
/* Wake-up on sd interrupt SDIO */
set32(MMCHS0_REG_BASE + MMCHS_SD_HCTL, MMCHS_SD_HCTL_IWE,
MMCHS_SD_HCTL_IWE_EN);
/*
* MMC host and bus configuration
*/
/* Configure data and command transfer (1 bit mode)*/
set32(MMCHS0_REG_BASE + MMCHS_SD_CON, MMCHS_SD_CON_DW8,
MMCHS_SD_CON_DW8_1BIT);
set32(MMCHS0_REG_BASE + MMCHS_SD_HCTL, MMCHS_SD_HCTL_DTW,
MMCHS_SD_HCTL_DTW_1BIT);
/* Configure card voltage */
set32(MMCHS0_REG_BASE + MMCHS_SD_HCTL, MMCHS_SD_HCTL_SDVS,
MMCHS_SD_HCTL_SDVS_VS30 /* Configure 3.0 volt */
);
/* Power on the host controller and wait for the MMCHS_SD_HCTL_SDBP_POWER_ON to be set */
set32(MMCHS0_REG_BASE + MMCHS_SD_HCTL, MMCHS_SD_HCTL_SDBP,
MMCHS_SD_HCTL_SDBP_ON);
while ((read32(MMCHS0_REG_BASE + MMCHS_SD_HCTL) & MMCHS_SD_HCTL_SDBP)
!= MMCHS_SD_HCTL_SDBP_ON) {
counter++;
}
/* Enable internal clock and clock to the card*/
set32(MMCHS0_REG_BASE + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_ICE,
MMCHS_SD_SYSCTL_ICE_EN);
//@TODO Fix external clock enable , this one is very slow
set32(MMCHS0_REG_BASE + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD,
(0x3ff << 6));
set32(MMCHS0_REG_BASE + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CEN,
MMCHS_SD_SYSCTL_CEN_EN);
while ((read32(MMCHS0_REG_BASE + MMCHS_SD_SYSCTL) & MMCHS_SD_SYSCTL_ICS)
!= MMCHS_SD_SYSCTL_ICS_STABLE);
/*
* See spruh73e page 3576 Card Detection, Identification, and Selection
*/
/* enable command interrupt */
set32(MMCHS0_REG_BASE + MMCHS_SD_IE, MMCHS_SD_IE_CC_ENABLE,
MMCHS_SD_IE_CC_ENABLE_ENABLE);
/* enable transfer complete interrupt */
set32(MMCHS0_REG_BASE + MMCHS_SD_IE, MMCHS_SD_IE_TC_ENABLE,
MMCHS_SD_IE_TC_ENABLE_ENABLE);
/* enable error interrupts */
/* NOTE: We are currently skipping the BADA interrupt it does get raised for unknown reasons */
set32(MMCHS0_REG_BASE + MMCHS_SD_IE, MMCHS_SD_IE_ERROR_MASK, 0x0fffffffu);
//set32(MMCHS0_REG_BASE + MMCHS_SD_IE,MMCHS_SD_IE_ERROR_MASK, 0xffffffffu);
/* clean the error interrupts */
set32(MMCHS0_REG_BASE + MMCHS_SD_STAT, MMCHS_SD_STAT_ERROR_MASK,
0xffffffffu); // clear errors
//set32(MMCHS0_REG_BASE + MMCHS_SD_STAT,MMCHS_SD_STAT_ERROR_MASK, 0xffffffffu);// clear errors
/* send a init signal to the host controller. This does not actually
* send a command to a card manner
*/
set32(MMCHS0_REG_BASE + MMCHS_SD_CON, MMCHS_SD_CON_INIT,
MMCHS_SD_CON_INIT_INIT);
write32(MMCHS0_REG_BASE + MMCHS_SD_CMD, 0x00); /* command 0 , type other commands , not response etc) */
while ((read32(MMCHS0_REG_BASE + MMCHS_SD_STAT) & MMCHS_SD_STAT_CC)
!= MMCHS_SD_STAT_CC_RAISED) {
if (read32(MMCHS0_REG_BASE + MMCHS_SD_STAT) & 0x8000) {
// read32(MMCHS0_REG_BASE + MMCHS_SD_STAT));
return 1;
}
counter++;
}
/* clear the cc interrupt status */
set32(MMCHS0_REG_BASE + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE,
MMCHS_SD_IE_CC_ENABLE_ENABLE);
// Set Set SD_CON[1] INIT bit to 0x0 to end the initialization sequence
set32(MMCHS0_REG_BASE + MMCHS_SD_CON, MMCHS_SD_CON_INIT,
MMCHS_SD_CON_INIT_NOINIT);
return 0;
}
/*
* Send a command to card
*/
int send_cmd(uint32_t command, uint32_t arg)
{
int count= 0;
/* Read current interrupt status and fail if an interrupt is already asserted */
if ((read32(MMCHS0_REG_BASE + MMCHS_SD_STAT) & 0xffffu)) {
// read32(MMCHS0_REG_BASE + MMCHS_SD_STAT));
return 1;
}
/* Set arguments */
write32(MMCHS0_REG_BASE + MMCHS_SD_ARG, arg);
/* Set command */
set32(MMCHS0_REG_BASE + MMCHS_SD_CMD, MMCHS_SD_CMD_MASK, command);
/* Wait for completion */
while ((read32(MMCHS0_REG_BASE + MMCHS_SD_STAT) & 0xffffu) == 0x0) {
count++;
}
if (read32(MMCHS0_REG_BASE + MMCHS_SD_STAT) & 0x8000) {
// read32(MMCHS0_REG_BASE + MMCHS_SD_STAT));
set32(MMCHS0_REG_BASE + MMCHS_SD_STAT, MMCHS_SD_STAT_ERROR_MASK,
0xffffffffu); // clear errors
// We currently only support 2.0, not responding to
return 1;
}
if ((command & MMCHS_SD_CMD_RSP_TYPE) == MMCHS_SD_CMD_RSP_TYPE_48B_BUSY) {
// Command with busy repsonse *CAN* also set the TC bit if they exit busy
while ((read32(MMCHS0_REG_BASE + MMCHS_SD_STAT)
& MMCHS_SD_IE_TC_ENABLE_ENABLE) == 0) {
count++;
}
write32(MMCHS0_REG_BASE + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR);
}
/* clear the cc status */
write32(MMCHS0_REG_BASE + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE_CLEAR);
return 0;
}
/*
* read a SINGLE block 
*/
int read_single_block(struct sd_card *card, uint32_t blknr, unsigned char *buf)
{
uint32_t count;
uint32_t value;
count= 0;
set32(MMCHS0_REG_BASE + MMCHS_SD_IE, MMCHS_SD_IE_BRR_ENABLE,
MMCHS_SD_IE_BRR_ENABLE_ENABLE);
set32(MMCHS0_REG_BASE + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);
if (send_cmd(MMCHS_SD_CMD_CMD17 /* read single block */
| MMCHS_SD_CMD_DP_DATA /* Command with data transfer */
| MMCHS_SD_CMD_RSP_TYPE_48B /* type (R1) */
| MMCHS_SD_CMD_MSBS_SINGLE /* single block */
| MMCHS_SD_CMD_DDIR_READ /* read data from card */
, blknr)) {
return 1;
}
while ((read32(MMCHS0_REG_BASE + MMCHS_SD_STAT)
& MMCHS_SD_IE_BRR_ENABLE_ENABLE) == 0) {
count++;
}
if (!(read32(MMCHS0_REG_BASE + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BRE_EN)) {
return 1; /* We are not allowed to read data from the data buffer */
}
for (count= 0; count < 512; count += 4) {
value= read32(MMCHS0_REG_BASE + MMCHS_SD_DATA);
buf[count]= *((char*) &value);
buf[count + 1]= *((char*) &value + 1);
buf[count + 2]= *((char*) &value + 2);
buf[count + 3]= *((char*) &value + 3);
}
/* Wait for TC */
while ((read32(MMCHS0_REG_BASE + MMCHS_SD_STAT)
& MMCHS_SD_IE_TC_ENABLE_ENABLE) == 0) {
count++;
}
write32(MMCHS0_REG_BASE + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR);
/* clear and disable the bbr interrupt */
write32(MMCHS0_REG_BASE + MMCHS_SD_STAT, MMCHS_SD_IE_BRR_ENABLE_CLEAR);
set32(MMCHS0_REG_BASE + MMCHS_SD_IE, MMCHS_SD_IE_BRR_ENABLE,
MMCHS_SD_IE_BRR_ENABLE_DISABLE);
return 0;
}
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (void)
{
DSTATUS stat;
int result;
result = mmchs_init();
if(result) return RES_ERROR;
stat = RES_OK;
return stat;
}
/*-----------------------------------------------------------------------*/
/* Read Partial Sector */
/*-----------------------------------------------------------------------*/
DRESULT disk_readp (
BYTE* buff, /* Pointer to the destination object */
DWORD sector, /* Sector number (LBA) */
UINT offset, /* Offset in the sector */
UINT count /* Byte count (bit15:destination) */
)
{
unsigned char temp[0x1500]; // ddl
unsigned char *pbuf = temp; // ddl
DRESULT res;
int i, result;

if(offset > 511) return RES_PARERR;
if(offset + count > 512) count = 512 - offset;
result = read_single_block(&card, sector, pbuf);
if(result) return RES_ERROR;
for (i = 0; i < count; i++) {
buff[i] = temp[i + offset];

res = RES_OK;
return res;
}
/*-----------------------------------------------------------------------*/
/* Write Partial Sector */
/*-----------------------------------------------------------------------*/
DRESULT disk_writep (
const BYTE* buff, /* Pointer to the data to be written, NULL:Initiate/Finalize write operation */
DWORD sc /* Sector number (LBA) or Number of bytes to send */
) {
DRESULT res;
uint32_t i;
uint32_t value;
UINT bc; // tx byte count
static UINT wc; // write count (count down from 512)

i = 0;
if (!buff) {
if (sc) { // Initiate write process
set32(MMCHS0_REG_BASE + MMCHS_SD_IE, MMCHS_SD_IE_BWR_ENABLE, MMCHS_SD_IE_BWR_ENABLE_ENABLE);
//set32(MMCHS0_REG_BASE + MMCHS_SD_IE, 0xfff , 0xfff);
set32(MMCHS0_REG_BASE + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);
// Set timeout
set32(MMCHS0_REG_BASE + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_DTO, MMCHS_SD_SYSCTL_DTO_2POW27);
if (send_cmd(MMCHS_SD_CMD_CMD24 // write single block
| MMCHS_SD_CMD_DP_DATA // Command with data transfer 
| MMCHS_SD_CMD_RSP_TYPE_48B // type (R1b)
| MMCHS_SD_CMD_MSBS_SINGLE // single block
| MMCHS_SD_CMD_DDIR_WRITE // write to the card
, sc)) {
return RES_ERROR;
}
// Wait for the MMCHS_SD_IE_BWR_ENABLE interrupt
while ((read32(MMCHS0_REG_BASE + MMCHS_SD_STAT) & MMCHS_SD_IE_BWR_ENABLE) == 0) {
i++;
}
if (!(read32(MMCHS0_REG_BASE + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BWE_EN)) {
return RES_NOTRDY; // not ready to write data
}
wc = 512; // Set byte counter
res = RES_OK;
} else { // Finalize write process
bc = wc>>2; // xmit 4 bytes in a single go
while (bc--) write32(MMCHS0_REG_BASE + MMCHS_SD_DATA, 0); // backfill block and CRC with 0s
// Wait for TC
while ((read32(MMCHS0_REG_BASE + MMCHS_SD_STAT) & MMCHS_SD_IE_TC_ENABLE_ENABLE) == 0) {
i++;
}
write32(MMCHS0_REG_BASE + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR);
write32(MMCHS0_REG_BASE + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE_CLEAR); // finished
// clear the bwr interrupt FIXME is this right when writing?
write32(MMCHS0_REG_BASE + MMCHS_SD_STAT, MMCHS_SD_IE_BWR_ENABLE_CLEAR);
set32(MMCHS0_REG_BASE + MMCHS_SD_IE, MMCHS_SD_IE_BWR_ENABLE, MMCHS_SD_IE_BWR_ENABLE_DISABLE);
res = RES_OK;
}
} else { // Send data to the disk
bc = (UINT)sc;
i = 0;
while (bc && wc) { // Send data bytes to the card
*((char*) &value)= buff[i];
*((char*) &value + 1)= buff[i + 1];
*((char*) &value + 2)= buff[i + 2];
*((char*) &value + 3)= buff[i + 3];
write32(MMCHS0_REG_BASE + MMCHS_SD_DATA, value);
i = i + 4;
wc = wc - 4;
bc = bc - 4;
}
res = RES_OK;
}
return res;
}


And the header file bbbMMC.h :

/*-----------------------------------------------------------------------*/
/* bbbMMC.h - driver defines for Petit FatFs (C)ChaN, 2014 */
/* BBB drivers from Jan Kees, github.com/keesj/bonecode */
/*-----------------------------------------------------------------------*/

#define MMCHS0_REG_BASE 0x48060000

#define MMCHS_SD_SYSCONFIG 0x110 /* SD system configuration */
#define MMCHS_SD_SYSSTATUS 0x114 /* SD system status */
#define MMCHS_SD_CON 0x12c /* Configuration (functional mode,card initialization etc) */
#define MMCHS_SD_BLK 0x204 /* Transfer length configuration */
#define MMCHS_SD_ARG 0x208 /* Command argument bit 38-8 of command format*/
#define MMCHS_SD_CMD 0x20c /* Command and transfer mode */
#define MMCHS_SD_RSP10 0x210 /* Command response 0 and 1 */
#define MMCHS_SD_RSP32 0x214 /* Command response 2 and 3 */
#define MMCHS_SD_RSP54 0x218 /* Command response 4 and 5 */
#define MMCHS_SD_RSP76 0x21c /* Command response 6 and 7 */
#define MMCHS_SD_DATA 0x220 /* Data register */
#define MMCHS_SD_PSTATE 0x224 /* Present state */
#define MMCHS_SD_HCTL 0x228 /* Host control(power ,wake-up and transfer) */
#define MMCHS_SD_SYSCTL 0x22c /* SD System control (reset,clocks and timeout) */
#define MMCHS_SD_STAT 0x230 /* SD Interrupt status */
#define MMCHS_SD_IE 0x234 /* SD Interrupt Enable register */
#define MMCHS_SD_CAPA 0x240 /* Capabilities of the host controller */

#define MMCHS_SD_SYSCONFIG_AUTOIDLE (0x1 << 0) /* Internal clock gating strategy */
#define MMCHS_SD_SYSCONFIG_AUTOIDLE_DIS (0x0 << 0) /* Clocks are free running */
#define MMCHS_SD_SYSCONFIG_AUTOIDLE_EN (0x1 << 0) /* Automatic clock gating strategy */
#define MMCHS_SD_SYSCONFIG_SOFTRESET (0x1 << 1) /* Software reset bit writing */
#define MMCHS_SD_SYSCONFIG_ENAWAKEUP (0x1 << 2) /* Wake-up feature control */
#define MMCHS_SD_SYSCONFIG_ENAWAKEUP_DIS (0x0 << 2) /* Disable wake-up capability */
#define MMCHS_SD_SYSCONFIG_ENAWAKEUP_EN (0x1 << 2) /* Enable wake-up capability */
#define MMCHS_SD_SYSCONFIG_SIDLEMODE (0x3 << 3) /* Power management */
#define MMCHS_SD_SYSCONFIG_SIDLEMODE_UNCONDITIONAL (0x0 << 3) /* Go into idle mode unconditionally upon request */
#define MMCHS_SD_SYSCONFIG_SIDLEMODE_IGNORE (0x1 << 3) /* Ignore ILDE requests */
#define MMCHS_SD_SYSCONFIG_SIDLEMODE_IDLE (0x2 << 3) /* Acknowledge IDLE request switch to wake-up mode */
#define MMCHS_SD_SYSCONFIG_SIDLEMODE_SMART_IDLE (0x3 << 3) /* Smart-idle */
#define MMCHS_SD_SYSCONFIG_CLOCKACTIVITY (0x3 << 8) /* Clock activity during wake-up */
#define MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_OFF (0x0 << 8) /* Interface and functional clock can be switched off */
#define MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_IF (0x1 << 8) /* Only Interface clock (functional can be switched off*/
#define MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_FUNC (0x2 << 8) /* Only Functional clock (interface clock can be switched off) */
#define MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_BOOTH (0x3 << 8) /* Booth the interface and functional clock are maintained */
#define MMCHS_SD_SYSCONFIG_STANDBYMODE (0x3 << 12) /*Configuration for standby */
#define MMCHS_SD_SYSCONFIG_STANDBYMODE_FORCE_STANDBY (0x0 << 12) /* Force standby mode upon idle request*/
#define MMCHS_SD_SYSCONFIG_STANDBYMODE_NO_STANDBY (0x1 << 12) /* Never go into standby mode */
#define MMCHS_SD_SYSCONFIG_STANDBYMODE_WAKEUP_INTERNAL (0x2 << 12) /* Go into wake-up mode based on internal knowledge */
#define MMCHS_SD_SYSCONFIG_STANDBYMODE_WAKEUP_SMART (0x3 << 12) /* Go info wake-up mode when possible */

#define MMCHS_SD_SYSSTATUS_RESETDONE 0x01

#define MMCHS_SD_CON_DW8 (0x1 << 5) /* 8-bit mode MMC select , For SD clear this bit */
#define MMCHS_SD_CON_DW8_1BIT (0x0 << 5) /* 1 or 4 bits data width configuration(also set SD_HCTL) */
#define MMCHS_SD_CON_DW8_8BITS (0x1 << 5) /* 8 bits data width configuration */
#define MMCHS_SD_CON_INIT (0x1 << 1) /* Send initialization stream (all cards) */
#define MMCHS_SD_CON_INIT_NOINIT (0x0 << 1) /* Do nothing */
#define MMCHS_SD_CON_INIT_INIT (0x1 << 1) /* Send initialization stream */

#define MMCHS_SD_BLK_NBLK (0xffffu << 16) /* Block count for the current transfer */
#define MMCHS_SD_BLK_BLEN (0xfff << 0) /* Transfer block size */
#define MMCHS_SD_BLK_BLEN_NOTRANSFER (0x0 << 0) /* No transfer */

#define MMCHS_SD_CMD_INDX (0x3f << 24) /* Command index */
#define MMCHS_SD_CMD_INDX_CMD(x) (x << 24) /* MMC command index binary encoded values from 0 to 63 */
#define MMCHS_SD_CMD_CMD0 MMCHS_SD_CMD_INDX_CMD(0) /* GO_IDLE_STATE */
#define MMCHS_SD_CMD_CMD2 MMCHS_SD_CMD_INDX_CMD(2) /* ALL_SEND_CID */
#define MMCHS_SD_CMD_CMD3 MMCHS_SD_CMD_INDX_CMD(3) /* SEND_RELATIVE_ADDR */
#define MMCHS_SD_CMD_CMD7 MMCHS_SD_CMD_INDX_CMD(7) /* (D)SELECT_CARD */
#define MMCHS_SD_CMD_CMD8 MMCHS_SD_CMD_INDX_CMD(8) /* SEND_IF_COND */
#define MMCHS_SD_CMD_CMD9 MMCHS_SD_CMD_INDX_CMD(9) /* SEND_CSD */
#define MMCHS_SD_CMD_CMD17 MMCHS_SD_CMD_INDX_CMD(17) /* READ_SINGLE_BLOCK */
#define MMCHS_SD_CMD_CMD24 MMCHS_SD_CMD_INDX_CMD(24) /* WRITE_SINGLE_BLOCK */
#define MMCHS_SD_CMD_CMD55 MMCHS_SD_CMD_INDX_CMD(55) /* Next command is application specific */

#define MMCHS_SD_CMD_ACMD41 MMCHS_SD_CMD_INDX_CMD(41) /*Send host capacity support */
#define SD_SEND_OP_COND MMCHS_SD_CMD_ACMD41 /* alias for ACMD41 */

#define MMCHS_SD_ARG_MASK (0xffffffffu) /* Mask everything */
#define MMCHS_SD_ARG_CMD8_VHS (0x1 << (16 - 8)) /* Voltage between 2.7 and 3.6 v*/
#define MMCHS_SD_ARG_CMD8_CHECK_PATTERN (0xaa <<(8 - 8)) /* 10101010b pattern */

#define MMCHS_SD_CMD_TYPE (0x3 << 22) /* Command type. */
#define MMCHS_SD_CMD_TYPE_OTHER (0x0 << 22) /* Other type of commands (like go idle) */
#define MMCHS_SD_CMD_TYPE_BUS_SUSPEND (0x1 << 22) /* Upon CMD52 "Bus Suspend" operation */
#define MMCHS_SD_CMD_TYPE_FUNCTION_SELECT (0x2 << 22) /* Upon CMD52 "Function Select" operation */
#define MMCHS_SD_CMD_TYPE_IOABORT (0x3 << 22) /* Upon CMD12 and CMD21 "I/O Abort */
#define MMCHS_SD_CMD_DP (0x1 << 21) /* Data present select */
#define MMCHS_SD_CMD_DP_DATA (0x1 << 21) /* Additional data is present on the data lines */
#define MMCHS_SD_CMD_DP_NODATA (0x0 << 21) /* No additional data is present on the data lines */
#define MMCHS_SD_CMD_CICE (0x1 << 20) /* Command index response check enable */
#define MMCHS_SD_CMD_CICE_ENABLE (0x1 << 20) /* Enable index check response */
#define MMCHS_SD_CMD_CICE_DISABLE (0x0 << 20) /* Disable index check response */
#define MMCHS_SD_CMD_CCCE (0x1 << 19) /* Command CRC7 Check enable on responses*/
#define MMCHS_SD_CMD_CCCE_ENABLE (0x1 << 19) /* Enable CRC7 Check on response */
#define MMCHS_SD_CMD_CCCE_DISABLE (0x0 << 19) /* Disable CRC7 Check on response */
#define MMCHS_SD_CMD_RSP_TYPE (0x3 << 16) /* Response type */
#define MMCHS_SD_CMD_RSP_TYPE_NO_RESP (0x0 << 16) /* No response */
#define MMCHS_SD_CMD_RSP_TYPE_136B (0x1 << 16) /* Response length 136 bits */
#define MMCHS_SD_CMD_RSP_TYPE_48B (0x2 << 16) /* Response length 48 bits */
#define MMCHS_SD_CMD_RSP_TYPE_48B_BUSY (0x3 << 16) /* Response length 48 bits with busy after response */
#define MMCHS_SD_CMD_MSBS (0x1 << 5) /* Multi/Single block select */
#define MMCHS_SD_CMD_MSBS_SINGLE (0x0 << 5) /* Single block mode */
#define MMCHS_SD_CMD_MSBS_MULTI (0x0 << 5) /* Multi block mode */
#define MMCHS_SD_CMD_DDIR (0x1 << 4) /* Data transfer direction */
#define MMCHS_SD_CMD_DDIR_READ (0x1 << 4) /* Data read (card to host) */
#define MMCHS_SD_CMD_DDIR_WRITE (0x0 << 4) /* Data write (host to card) */
#define MMCHS_SD_CMD_ACEN (0x1 << 2) /* Auto CMD12 Enable */
#define MMCHS_SD_CMD_ACEN_DIS (0x0 << 2) /* Auto CMD12 Disable */
#define MMCHS_SD_CMD_ACEN_EN (0x1 << 2) /* Auto CMD12 Enable */
#define MMCHS_SD_CMD_BCE (0x1 << 1) /* Block Count Enable(for multi block transfer) */
#define MMCHS_SD_CMD_BCE_DIS (0x0 << 1) /* Disabled block count for infinite transfer*/
#define MMCHS_SD_CMD_BCE_EN (0x1 << 1) /* Enabled for multi block transfer with know amount of blocks */
#define MMCHS_SD_CMD_DE (0x1 << 0) /* DMA enable */
#define MMCHS_SD_CMD_DE_DIS (0x0 << 0) /* Disable DMA */
#define MMCHS_SD_CMD_DE_EN (0x1 << 0) /* Enable DMA */
#define MMCHS_SD_CMD_MASK ~(0x1 << 30 | 0x1 << 31 | 0x1 << 18 | 0x1 <<3) /* bits 30 , 31 and 18 are reserved */

#define MMCHS_SD_PSTATE_CI (0x1 << 16) /* Card Inserted */
#define MMCHS_SD_PSTATE_CI_INSERTED (0x1 << 16) /* Card Inserted is inserted*/
#define MMCHS_SD_PSTATE_BRE (0x0 << 11) /* Buffer read enable */
#define MMCHS_SD_PSTATE_BRE_DIS (0x0 << 11) /* Read BLEN bytes disabled*/
#define MMCHS_SD_PSTATE_BRE_EN (0x1 << 11) /* Read BLEN bytes enabled*/
#define MMCHS_SD_PSTATE_BWE (0x0 << 10) /* Buffer Write enable */
#define MMCHS_SD_PSTATE_BWE_DIS (0x0 << 10) /* There is no room left in the buffer to write BLEN bytes of data */
#define MMCHS_SD_PSTATE_BWE_EN (0x1 << 10) /* There is enough space in the buffer to write BLEN bytes of data*/

#define MMCHS_SD_HCTL_DTW (0x1 << 1) /*Data transfer width.(must be set after a successful ACMD6) */
#define MMCHS_SD_HCTL_DTW_1BIT (0x0 << 1) /*1 bit transfer with */
#define MMCHS_SD_HCTL_DTW_4BIT (0x1 << 1) /*4 bit transfer with */
#define MMCHS_SD_HCTL_SDBP (0x1 << 8) /*SD bus power */
#define MMCHS_SD_HCTL_SDBP_OFF (0x0 << 8) /*SD Power off (start card detect?) */
#define MMCHS_SD_HCTL_SDBP_ON (0x1 << 8) /*SD Power on (start card detect?) */
#define MMCHS_SD_HCTL_SDVS (0x7 << 9) /*SD bus voltage select */
#define MMCHS_SD_HCTL_SDVS_VS18 (0x5 << 9) /*1.8 V */
#define MMCHS_SD_HCTL_SDVS_VS30 (0x6 << 9) /*3.0 V */
#define MMCHS_SD_HCTL_SDVS_VS33 (0x7 << 9) /*3.3 V */
#define MMCHS_SD_HCTL_IWE (0x1 << 24)/* wake-up event on SD interrupt */
#define MMCHS_SD_HCTL_IWE_DIS (0x0 << 24)/* Disable wake-up on SD interrupt */
#define MMCHS_SD_HCTL_IWE_EN (0x1 << 24)/* Enable wake-up on SD interrupt */

#define MMCHS_SD_SYSCTL_CLKD (0x3ff << 6) /* 10 bits clock frequency select */
#define MMCHS_SD_SYSCTL_SRD (0x1 << 26) /* Soft reset for mmc_dat line */
#define MMCHS_SD_SYSCTL_SRC (0x1 << 25) /* Soft reset for mmc_cmd line */
#define MMCHS_SD_SYSCTL_SRA (0x1 << 24) /* Soft reset all (host controller) */

#define MMCHS_SD_SYSCTL_ICE (0x1 << 0) /* Internal clock enable register */
#define MMCHS_SD_SYSCTL_ICE_DIS (0x0 << 0) /* Disable internal clock */
#define MMCHS_SD_SYSCTL_ICE_EN (0x1 << 0) /* Enable internal clock */
#define MMCHS_SD_SYSCTL_ICS (0x1 << 1) /* Internal clock stable register */
#define MMCHS_SD_SYSCTL_ICS_UNSTABLE (0x0 << 1) /* Internal clock is unstable */
#define MMCHS_SD_SYSCTL_ICS_STABLE (0x1 << 1) /* Internal clock is stable */
#define MMCHS_SD_SYSCTL_CEN (0x1 << 2) /* Card lock enable provide clock to the card */
#define MMCHS_SD_SYSCTL_CEN_DIS (0x0 << 2) /* Internal clock is unstable */
#define MMCHS_SD_SYSCTL_CEN_EN (0x1 << 2) /* Internal clock is stable */

#define MMCHS_SD_SYSCTL_DTO (0xf << 16) /* Data timeout counter */
#define MMCHS_SD_SYSCTL_DTO_2POW13 (0x0 << 16) /* TCF x 2^13 */
#define MMCHS_SD_SYSCTL_DTO_2POW14 (0x1 << 16) /* TCF x 2^14 */
#define MMCHS_SD_SYSCTL_DTO_2POW27 (0x3 << 16) /* TCF x 2^27 */

#define MMCHS_SD_STAT_ERRI (0x01 << 15) /* Error interrupt */
#define MMCHS_SD_STAT_ERROR_MASK (0xff << 15 | 0x3 << 24 | 0x03 << 28)
#define MMCHS_SD_STAT_CC (0x1 << 0) /* Command complete status */
#define MMCHS_SD_STAT_CC_UNRAISED (0x0 << 0) /* Command not completed */
#define MMCHS_SD_STAT_CC_RAISED (0x1 << 0) /* Command completed */

#define MMCHS_SD_IE_ERROR_MASK (0xff << 15 | 0x3 << 24 | 0x03 << 28)

#define MMCHS_SD_IE_CC_ENABLE (0x1 << 0) /* Command complete interrupt enable */
#define MMCHS_SD_IE_CC_ENABLE_ENABLE (0x1 << 0) /* Command complete Interrupts are enabled */
#define MMCHS_SD_IE_CC_ENABLE_CLEAR (0x1 << 0) /* Clearing is done by writing a 0x1 */

#define MMCHS_SD_IE_TC_ENABLE (0x1 << 1) /* Transfer complete interrupt enable */
#define MMCHS_SD_IE_TC_ENABLE_ENABLE (0x1 << 1) /* Transfer complete Interrupts are enabled */
#define MMCHS_SD_IE_TC_ENABLE_CLEAR (0x1 << 1) /* Clearing TC is done by writing a 0x1 */

#define MMCHS_SD_IE_BRR_ENABLE (0x1 << 5) /* Buffer read ready interrupt */
#define MMCHS_SD_IE_BRR_ENABLE_DISABLE (0x0 << 5) /* Buffer read ready interrupt disable */
#define MMCHS_SD_IE_BRR_ENABLE_ENABLE (0x1 << 5) /* Buffer read ready interrupt enable */
#define MMCHS_SD_IE_BRR_ENABLE_CLEAR (0x1 << 5) /* Buffer read ready interrupt clear */

#define MMCHS_SD_IE_BWR_ENABLE (0x1 << 4) /* Buffer write ready interrupt */
#define MMCHS_SD_IE_BWR_ENABLE_DISABLE (0x0 << 4) /* Buffer write ready interrupt disable */
#define MMCHS_SD_IE_BWR_ENABLE_ENABLE (0x1 << 4) /* Buffer write ready interrupt enable */
#define MMCHS_SD_IE_BWR_ENABLE_CLEAR (0x1 << 4) /* Buffer write ready interrupt clear */

#define MMCHS_SD_CAPA_VS_MASK (0x7 << 24 ) /* voltage mask */
#define MMCHS_SD_CAPA_VS18 (0x01 << 26 ) /* 1.8 volt */
#define MMCHS_SD_CAPA_VS30 (0x01 << 25 ) /* 3.0 volt */
#define MMCHS_SD_CAPA_VS33 (0x01 << 24 ) /* 3.3 volt */

#define REG(x)(*((volatile uint32_t *)(x)))
#define BIT(x)(0x1 << x)



Insert the following changes into ppfconf.h : 

#define _USE_DIR 1 /* Enable pf_opendir() and pf_readdir() function */ // was 0
#define _USE_LSEEK 1 /* Enable pf_lseek() function */ // was 0
#define _USE_WRITE 1 /* Enable pf_write() function */ // was 0
#define _FS_FAT16 0 /* Enable FAT16 */ // was 1
#define _FS_FAT32 1 /* Enable FAT32 */ // was 0

Here is the main program, a separate project in CCS6:
It uses the binary libraries drivers.lib , system.lib , platform.lib , utils.lib

//
// pFATx.c
//
// petit FAT filesystem test prog
//
//#include <stdio.h>
#include "pff.h"
#include "consoleUtils.h"

int main(void) {
FATFS fs; // Work area (file system object) for the volume
BYTE buff[0x1000]; // File read buffer
UINT br; // File read count
UINT bw; // File write count
FRESULT res = FR_NOT_READY; // Petit FatFs function common result code
char filename[16]; // file to open, old DOS filename convention
UINT nbytes = 1040; // bytes read/written, must be divisible by 4

ConsoleUtilsInit();
ConsoleUtilsSetType(CONSOLE_UART);
ConsoleUtilsPrintf("\n\n\n-----pFATfs test-----\n"); 
// Mount the volume
res = pf_mount(&fs);
ConsoleUtilsPrintf("pf_mount return 0x%x\n", res);
if (res) return res;
// Open a file
sprintf(filename, "BIGFILE.TXT");
ConsoleUtilsPrintf("opening %s\n", filename);
res = pf_open(filename);
ConsoleUtilsPrintf("pf_open return 0x%x\n", res);
if (res) return res;
// Read data to memory
res = pf_read(buff, nbytes, &br);
ConsoleUtilsPrintf("pf_read 0x%x bytes return 0x%x\n", br, res);
if (res) return res;
buff[br] = 0x0;
ConsoleUtilsPrintf("file contents>\n%s< 0x%x bytes read\n", buff, br);
// advance a few bytes
bw = 0;
ConsoleUtilsPrintf("pf_lseek to offset 0x%x\n", bw); 
res = pf_lseek(bw);
ConsoleUtilsPrintf("pf_lseek return 0x%x\n", res);
if (res) return res;
// make a small change to buffer data
if(buff[2] == 0x58) buff[2] = 0x43;
else buff[2] = 0x58;
// write to file
res = pf_write(buff, nbytes, &bw);
ConsoleUtilsPrintf("pf_write 0x%x bytes return 0x%x\n", bw, res);
if (res) return res;
// terminate file write process
res = pf_write(0, 0, &bw);
ConsoleUtilsPrintf("pf_write close return 0x%x\n", res);
// Read data to memory and display it
bw = 0;
res = pf_lseek(bw);
res = pf_read(buff, nbytes, &br);
if (res) return res;
buff[br] = 0x0;
ConsoleUtilsPrintf("new file contents>\n%s< 0x%x bytes read\n", buff, br);
}

Also, use this command file, from one of the starterware examples. 
I wasted alot of time with flakey-intermittently failing images that weren't linked/built properly. 
None of this is documented for noobs. Copy it into your FAT workspace dir. 

/****************************************************************************/
/* LNK32.CMD - v4.5.0 COMMAND FILE FOR LINKING TMS470 32BIS C/C++ PROGRAMS */
/* */
/* Usage: lnk470 <obj files...> -o <out file> -m <map file> lnk32.cmd */
/* cl470 <src files...> -z -o <out file> -m <map file> lnk32.cmd */
/* */
/* Description: This file is a sample command file that can be used */
/* for linking programs built with the TMS470 C/C++ */
/* Compiler. Use it as a guideline; you may want to change */
/* the allocation scheme according to the size of your */
/* program and the memory layout of your target system. */
/* */
/* Notes: (1) You must specify the directory in which run-time support */
/* library is located. Either add a "-i<directory>" line to */
/* this file, or use the system environment variable C_DIR */
/* to specify a search path for libraries. */
/* */
/* (2) If the run-time support library you are using is not */
/* named below, be sure to use the correct name here. */
/* */
/****************************************************************************/
-stack 0x0008 /* SOFTWARE STACK SIZE */
-heap 0x2000 /* HEAP AREA SIZE */
-e Entry
/* Since we used 'Entry' as the entry-point symbol the compiler issues a */
/* warning (#10063-D: entry-point symbol other than "_c_int00" specified: */
/* "Entry"). The CCS Version (5.1.0.08000) stops building from command */
/* line when there is a warning. So this warning is suppressed with the */
/* below flag. */

--diag_suppress=10063

/* SPECIFY THE SYSTEM MEMORY MAP */

MEMORY
{
DDR_MEM : org = 0x80000000 len = 0x7FFFFFF /* RAM */
}

/* SPECIFY THE SECTIONS ALLOCATION INTO MEMORY */

SECTIONS
{
.text:Entry : load > 0x80000000

.text : load > DDR_MEM /* CODE */
.data : load > DDR_MEM /* INITIALIZED GLOBAL AND STATIC VARIABLES */
.bss : load > DDR_MEM /* UNINITIALIZED OR ZERO INITIALIZED */
/* GLOBAL & STATIC VARIABLES */
RUN_START(bss_start)
RUN_END(bss_end)
.const : load > DDR_MEM /* GLOBAL CONSTANTS */
.stack : load > 0x87FFFFF0 /* SOFTWARE SYSTEM STACK */
}

The main program uses starterware consoleUtils. I did not hack that out. 
See the BBB UART driver I posted on this forum if you want to remove it yourself. 
All the other pFAT system header and code files are unchanged. 
In summary, I think the pFAT and FAT filesystem utils by elm-chan are great. 
They are used by many other microsystems, they are small, tight and FREE. 
It would be nice to have the full FAT32 file system, I may get around to it in a few months. 

happy hacking...........................dd