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.

Beaglebone Black eMMC

Other Parts Discussed in Thread: AM3359, CSD, SYSCONFIG

Does Starterware include drivers for the eMMC chip of the Beaglebone Black? 

Is the plain MMC driver sufficient to access eMMC? At first look it does not seem so.

Please if anyone is successfully talking to the eMMC(bare metal), please advice.

Thanks. 

  • Hi

    I also have same problem. I have my custom board including AM3359 and Micron eMMC. I am using starterware and I am stuck in eMMC driver. Is there any help?

    thanks,

    Mohsen

  • Javier

    I finally succeeded in accessing the eMMC using startware. You need to change MMCSD_proto.c file.

    If you are still interested I can share the edited file.

    Mohsen

  • So, you can run starterware on your Beaglebone Black? I just can't. I wonder why.

    When powered on, minicom prints out:

    StarterWare AM335x Boot Loader                                                 
    Copying application image from MMC/SD card to RAM                              
    Jumping to StarterWare Application...

    But the app doesn't run.

  • Hi,

    Currently StarterWare does not have official support for BeagleBone Black. For now, you can search for, and refer to one of the several forum posts on this topic, which give good suggestions. Type 'BeagleBone Black' in the top right search box to get the suggestions.

    For example, some relevant results:

    http://e2e.ti.com/support/embedded/starterware/f/790/t/271176.aspx

    http://e2e.ti.com/support/embedded/starterware/f/790/p/275997/1040770.aspx#1040770

    Regards,
    Mugdha

  • Hi MugdhaK,

    I am using starterware 2.0.1.1, I would like to know that can I use the eMMC of BBB for data storage as in controllers EEPROM is used, or is there any alternative to store data which can be accessed, edited and can be retained after powerup.

    Thanks

  • @Mohsen: could you please be so kind and share your changes in MMCSD_proto.c?

    Thanks :-)

  • @Mohsen:

    Hello

    I'm also very interested at your changers to get the eMMC run.

    Thanks

  • Hello. Can tell me exactly what you changed in the MMCSD_proto.c file to get eMMC working with Starterware?

    Thanks,

    Anthony

  • hi,

         I want to know that mmc controller in the Beaglebone black and OMAP 35x EVM board are same??

    if not can you give the controller details..

  • hi,

         I want to know that mmc controller in the Beaglebone black and OMAP 35x EVM board are same??

    if not can you give the controller details..

  • Hello Mohsen,

    I am also working on ,accessing eMMC using starterware.

    (eMMC used : MTFC32gjved) .

    I did make changes in MMCSD_proto.c file required for eMMC initialization. I did refer the eMMC specification (JESD84-A441) for initialization sequence and eMMC specific commands.

    I am able to get read the registers of eMMC (CID,CSD and ECSD) successfully.

    But I am not able to perform read block or write block commands.

    Please suggest.

  • All, can share the changes of the driver file, I working to the same driver to access the eMMC, but I'm stuck on reading the CSD.


    This is the code:

            ctrl->card->cardType = MMCSD_CARD_MMC;

            /* CMD0 - reset card */
            status = MMCSDCardReset(ctrl);

            if (status == 0)
            {
                return 0;
            }

            /* Poll until we get the card status (BIT31 of OCR) is powered up */
            do {
                    cmd.idx = SD_CMD(1);
                    cmd.flags = 0;
                    cmd.arg = SD_OCR_HIGH_CAPACITY | SD_OCR_VDD_WILDCARD | 1<<7;

                    MMCSDCmdSend(ctrl,&cmd);

            } while (!(cmd.rsp[0] & ((unsigned int)BIT(31))) && --retry);

            if (retry == 0)
            {
                /* No point in continuing */
                return 0;
            }

            card->ocr = cmd.rsp[0];

            card->highCap = (card->ocr & SD_OCR_HIGH_CAPACITY) ? 1 : 0;

            /* Send CMD2, to get the card identification register */
            cmd.idx = SD_CMD(2);
            cmd.flags = SD_CMDRSP_136BITS;
            cmd.arg = 0;

            status = MMCSDCmdSend(ctrl,&cmd);

            memcpy(card->raw_cid, cmd.rsp, 16);

            if (status == 0)
            {
                return 0;
            }

            /* Send CMD3, to set the card relative address */
            cmd.idx = SD_CMD(3);
            cmd.flags = 0;
            cmd.arg = 0xFFFF << 16;

            status = MMCSDCmdSend(ctrl,&cmd);

            card->rca = 0xFFFF;//SD_RCA_ADDR(cmd.rsp[0]);

            if (status == 0)
            {
                return 0;
            }

            /* Send CMD9, to get the card specific data */
            cmd.idx = SD_CMD(9);
            cmd.flags = SD_CMDRSP_136BITS;
            cmd.arg = card->rca << 16;

            status = MMCSDCmdSend(ctrl,&cmd);

            memcpy(card->raw_csd, cmd.rsp, 16);

            if (status == 0)
            {
                return 0;
            }

            /* Select the card */
            cmd.idx = SD_CMD(7);
            cmd.flags = SD_CMDRSP_BUSY;
            cmd.arg = card->rca << 16;

            status = MMCSDCmdSend(ctrl,&cmd);

            if (status == 0)
            {
                return 0;
            }

            ctrl->xferSetup(ctrl, 1, dataBuffer, 512, 1);

            cmd.idx = SD_CMD(8);/* Read extended CSD */
            cmd.flags = SD_CMDRSP_READ | SD_CMDRSP_DATA;
            cmd.arg = 0;
            cmd.nblks = 1;
            cmd.data = (signed char*)dataBuffer;

            status = MMCSDCmdSend(ctrl,&cmd);
            if (status == 0)
            {
                return 0;
            }

            status = ctrl->xferStatusGet(ctrl);

            if (status == 0)
            {
                return 0;
            }

    it stuck on status = ctrl->xferStatusGet(ctrl); , the mmc controller don't generate any interrupt, the MMCSD1 controller is dead :D

    the "dataBuffer" has been increased from 128 to 512 bytes.

    All the changes can be downloaded from here: https://github.com/MorgothCreator/mSdk

  • The code in the zip file is working on a Beagleboe Black with a 2 GB emmc card (can't remember the revision).
    , 6567.mmclib.zip

    You might have to clean up the code. There is a lot of unused variables, you can use them to verify that you read the correct data from the emmc card.

    Good luck.  

  • Thanks for sharing this code.

    I have the same sequence on my code, but after sending MMCSDCmdSend(ctrl,&cmd); with cmd8 it return '1' but after this the controller it freeze and xferStatusGet remain in infinite loop.

    The controller don't generate any interrupt and I don't know the reason.

  • Mi fault, the xfer function don't setup the correct int number.

    I propose a change in your code:

        extCsd.sec_count                    = (buffer[215] << 24) | (buffer[124] << 16) | (buffer[213] << 8) | buffer[213];    // [215:212] Sector Count
     with:

        extCsd.sec_count                    = (buffer[215] << 24) | (buffer[214] << 16) | (buffer[213] << 8) | buffer[212];    // [215:212] Sector Count

    Thank you again for your code.

    I done the initialization and communication with eMMC 4GB on BBB.

  • Javier Fernandez1 you can download and use the eMMC code from here, from here you can download two compiled application, this app bridge the USB0 dev MSC to uSD or eMMC.

  • 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);
    }

    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 thing 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
  • For anybody wanting to use the code posted by Martin Boel you need to change this because it is very wrong:

    	mult = 2^(CSDInfo.c_size + 2);
    	blockNr = (CSDInfo.c_size + 1) * mult;
    	ctrl->card->size = blockNr * mult;
    
    
    	//ctrl->card->blkLen = 1 << (CSDInfo.read_bl_len);
    	ctrl->card->blkLen = 1 << (CSDInfo.read_bl_len - 1); // Set it to 512 /////////////////////////////////////////////////////////
    
    	ctrl->card->nBlks = ctrl->card->size/ctrl->card->blkLen;

    I think I found the forum this was copied and pasted from and this is the mathematical explanation the C was below, ie 2^ is a power to xor. 

    I also think the maths in its self isn't quite right (at least it is different to the mmc driver in linux.  I used the linux method which looks like this:

    	ctrl->card->size = (CSDInfo.c_size + 1) << (CSDInfo.c_size_mult + 2);
    	ctrl->card->blkLen = 1 << (CSDInfo.read_bl_len);
    	ctrl->card->nBlks = ctrl->card->size/ctrl->card->blkLen;

    If you are on a beaglebone black this will give you a size equivalent to (4096*512) which is a magic size indicating that the ExtCsd should be used.  So you need to make sure you use Iulian Gheorghiu's correction and put this at the bottom of decodeExtCsd():

    	ctrl->card->size = extCsd.sec_count * 512;
    	ctrl->card->blkLen = 512;
    	ctrl->card->nBlks = extCsd.sec_count;

    I also had to put delays between the two mmc_switch() calls to get them to work reliably and they still report "error status failed\r\n" however the code does all seem to be working.  I would be interested to hear if anyone has looked into this?

    Sean

  • @Sean: is this eMMC code out of the community variant of StarterWare (from sourceforge.net/.../ ) which also contains an eMMC-implementation or is it from somewhere else?
  • As I said above it was from the link posted by Martin Boel which looks to be the same as what is in the community version you just posted.
  • Thanks, I just haven't found the link you mentioned.

    I'd guess the guys from the community version are happy when they get a patch with your changes :-)
  • I'm a bit late to this post, but I want to give BBB and Starterware another go.

    Lulian, thanks for the contribution and I appreciate your work. It seems that you are successfully accessing the eMMC. Unfortunately, I'm unable to use your code. There are many dependencies, of which many lead to dead-ends. There must have been changes to your sdk, because it does not compile out of the box. 

    Question for the community. Has anyone been able to use Starterware(either TI ver or the community ver) to access eMMC, and if so please share.

    Thanks guys.

  • yeah, no problem. see
    e2e.ti.com/.../1700125
    also baremetal.tech

    later...................dd
  • Both variants of StarterWare are working smoothly. What "dead ends" do you get exactly? May be you did not compile the libraries your project may depend on?

  • Glad to hear. Thanks fellows.

  • They are not. And I have no compiler/linker issues. The simple things and GPIO, UART, SPI are fine, but the more complex such as MMC aren't. 

    Anyone should be able to take a source(+depedencies) file for any one module and have it work out the box. Most of the other IC companies are this way, to mention one that this is always so, Atmel.

    To comment on the new SDK, which has improved some, but it is tied to a platform API that requires you to configure it ahead, and later one must call getboard and get module and all this other stuff. It is perfectly ok to spend time at front configuring the board and later make a single call to an init function. It is not ok to spend time setting-up at front to later have you taxed with additional calls for it. After configuration, It should be simple from there forward. It is the concept of abstraction.

    And I'm not asking for support, or beautiful looking code, but it is something more fundamental, basic code that works, giving that the pin mux are configured correctly. It is that simple. You said that your product is working, but miss to ask why is not working for me and fail to demonstrate that it works for you.

    Thanks qnx and I do appreciate you effort.

  • My SDK is in continue evolution, some applications can remain incompatible with SDK because I develop the SDK for platform that I have at that moment.

    I try not to do huge changes to SDK to be compatible with a new platform.


    Take the latest changed example application and port to your platform.The latest changed application example will always be compatible with SDK.

    The SDK for AM335x is based on StarterWare with some changes that make SDK to be completely dynamic.

    To make it work you need to modify only the functions from mmcsd_proto.c ( the MMCSDCardInit function and his dependencies )

  • Lulian,

    I was refering to the new TI SDK, not yours. I know yours is in work-in-progress stage. thanks.
  • > Anyone should be able to take a source(+depedencies) file for any one module and have it work out the box. Most of the other IC companies are this way, to mention one that this is always so, Atmel.

    This is obviously not true. You are right, Atmel offers fairly good documentation and code examples, but most of their processors are way more simple than the AM335x.

    And all the others...forget it! NXP provides headers/sources somewhat similar to TI. And for other ARM SoC's like Broadcom or AllWinner you get nothing, no examples, no headers with definitions, not even a manual!

    StarterWare is a complex and sometimes buggy piece of software which needs some time to get into it, but I'm quite sure you will not be able to show me a better solution for a comparable complex SoC.

  • My intention is not to turn this into a competition, but to make TI better. But I'm compelled to answer.

    >but most of their processors are way more simple than the AM335x.

    SAMA5 and SAM9G are about equal to the Sitara with added benefit of best in class low power for the SAMA5, yes lower frequency and no gpu, but does have a SIMD, but most important, you plug it and go.

    >And all the others...forget it! NXP...

    You are bringing up companies that cater exclusively to the largest players in the market, apples and oranges....

    >will not be able to show me a better solution

    You are right, I wouldn't be chasing this otherwise. I will say that have an alternative, that is maybe off by 10%. Atmel's SAMA5 series.

     

    bu

    t most of their processors are way more simple than the AM335x.

  • > SAMA5 and SAM9G are about equal to the Sitara with added benefit of best in class low power for the SAMA5, yes lower frequency and no gpu, but does have a SIMD, but most important, you plug it and go.

    Lower frequency, no GPU, no McASP interfaces, no PRUs, less timers, available timers with less features, no quadrature encoders, no GPI-capturing, no waveform generation on PWM outputs - just to list a few more.

    >> And all the others...forget it! NXP...

    > You are bringing up companies that cater exclusively to the largest players in the market, apples and oranges....

    Broadcom SoC is used in RaspberryPi, Allwinner SoC is used in a lot of embedded boards - both platforms which would be a perfect target for bare metal programming. And by the way, what do you think how small TI and their output of Sitara-SoC's is?

    Just to avoid misunderstandings, I'm definitely no fan of TI's strange user support, especially this webboard here has been ignored by TI for month and I have one heavy timer problem unsolved until now, where guys from TI simply ignore there is something wrong. But don't blame TI for things they are not responsible for/where competitors are not better.
  • Hi Mohsen

    Can you share the change MMCSD_proto.c file.
  • Please check out sourceforge.net/.../ - thisrepository contains all changes, enhancements and fixes which have been done during the past years and which never became part of an official StarterWare package from TI.
  • Dear Mohsen
    Can you share MMCSD_proto.c file because I am same proble.m
  • can u share modified MMCSD_proto.c file