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: CSD

Hi All,

I'm trying to use the BeagleBone Blacks' eMMC as a FatFs storage device.  I make the following initialization steps (after setting up all clocks and configuring the pins):

1) checking if the card is inserted (of course, it's soldered on the board ;) )

if(!m_pMmcd->IsCardInserted())
{
	return STA_NODISK;
}

2) sending the init stream

if(!m_pMmcd->InitStreamSend())
{
	return STA_NOINIT;
}

3) Going to Idle state by repeating cmd0 till the eMMC reports it's in Idle state.

//	Go Idle State
do
{
	m_pMmcd->CommandSend(0, 0, 0, 0, false);
	bComplete = m_pMmcd->IsCmdComplete(0xFFFFFF);
	m_pMmcd->ResponseGet(Result);
}
while(0 != (Result[0] & (0x0F << 9)));

4) asking the eMMC's operating condition (looping till the response is valid (bit 31 in resp10)

do
{
	//	Send Operating Conditions
	m_pMmcd->CommandSend(	MAKE_SD_COMMAND(1, MMCHS_CMD_CMD_TYPE_NORMAL, 0, MMCHS_CMD_RSP_TYPE_48BITS, 0, MMCHS_CMD_DDIR_READ),
				0x40FF8000,
				0,
				0,
				false
			);
	bRslt = m_pMmcd->IsCmdComplete(0xFFFF);
	m_pMmcd->ResponseGet(Result);
}
while(!(Result[0] & (1 << 31)));

5) getting the eMMC's Card Identification Data

m_bSectorMode = (Result[0] & (1 << 30)) ? true : false;

//	Card Identification
m_pMmcd->CommandSend(	MAKE_SD_COMMAND(2, MMCHS_CMD_CMD_TYPE_NORMAL, 0, MMCHS_CMD_RSP_TYPE_136BITS, 0, MMCHS_CMD_DDIR_READ),
			0,
			0,
			0,
			false
		);
bRslt = m_pMmcd->IsCmdComplete(0xFFFF);
m_pMmcd->GetResponse128((uint32_t*)&m_CID);

6) setting the eMMC's relative address to 0x0001

m_RCA = ++sm_NextRCA;

//	Set Relative Card Address
m_pMmcd->CommandSend(	MAKE_SD_COMMAND(3, MMCHS_CMD_CMD_TYPE_NORMAL, 0, MMCHS_CMD_RSP_TYPE_48BITS, 0, MMCHS_CMD_DDIR_READ),
			(m_RCA << 16),
			0,
			0,
			false
		);
bRslt = m_pMmcd->IsCmdComplete(0xFFFF);
m_pMmcd->ResponseGet(Result);

7) getting the eMMC's Card Specific Data (over the CMD-line)

//	get Card Specific Data over CMD line
m_pMmcd->CommandSend(	MAKE_SD_COMMAND(9, MMCHS_CMD_CMD_TYPE_NORMAL, 0, MMCHS_CMD_RSP_TYPE_136BITS, 0, MMCHS_CMD_DDIR_READ),
			(m_RCA << 16),
			0,
			0,
			false
		);
bRslt = m_pMmcd->IsCmdComplete(0xFFFF);
m_pMmcd->GetResponse128((uint32_t*)&m_RawCSD);

8) setting the host's blocklength (the MMCD peripheral in the SoC) to 512

//	Set BlkLen in Host
m_pMmcd->BlkLenSet(512);

9) select the card

//	Select Card
m_pMmcd->CommandSend(	MAKE_SD_COMMAND(7, MMCHS_CMD_CMD_TYPE_NORMAL, 0, MMCHS_CMD_RSP_TYPE_48BITS, 0, MMCHS_CMD_DDIR_READ),
			(m_RCA << 16),
			0,
			0,
			false
		);
bRslt = m_pMmcd->IsCmdComplete(0xFFFF);
m_pMmcd->ResponseGet(Result);

10) get the Extended Card Specific Data (over the data lines)

//	get Extended Card Specific Data
m_pMmcd->CommandSend(	MAKE_SD_COMMAND(8, MMCHS_CMD_CMD_TYPE_NORMAL, 1, MMCHS_CMD_RSP_TYPE_48BITS, 0, MMCHS_CMD_DDIR_READ),
			(m_RCA << 16),
			m_RawExtCSD,
			1,
			false
		);
bRslt = m_pMmcd->IsCmdComplete(0xFFFF);

m_pMmcd->DataGet(m_RawExtCSD, 512);

I'm stuck in step 10 : the returned data doesn't even looks like an extended CSD register....

There is activity on the DAT0 line as shown in this picture:

After the execution of CMD8 (getting the ECSD) the host controller reports that the card is READY_FOR_DATA and is in the Tran state (bits 8 and 11 are on in the controller's Resp10 register.)

Any ideas how to get the correct data from the eMMC's ECSD?

Thanks.

  • FYI,MAKE_SD_COMMAND is a macro defined as

    #define MAKE_SD_COMMAND(INDX, TYPE, DATAPRESENT, RESPTYPE, MULTIBLOCK, DATADIR) \
    	(																			\
    			(INDX << MMCHS_CMD_INDX_SHIFT)										\
    		|	(TYPE << MMCHS_CMD_CMD_TYPE_SHIFT)									\
    		|	(DATAPRESENT << 21)													\
    		|	(RESPTYPE << MMCHS_CMD_RSP_TYPE_SHIFT)								\
    		|	(MULTIBLOCK << 5)													\
    		|	(DATADIR << MMCHS_CMD_DDIR_SHIFT)									\
    	)

    The m_pMmcd is a pointer to this class:

    /**
    
     +==================================================================
     |		Project BPg (BeagleBonePlayground)
     +==================================================================
    
     File:		MMCD.h
    
     Created:	Sep 22, 2015 10:52:36 AM
     Author:		Paul
    
     Copyright (C) 2015 Paul Van den Bergh.  All rights reserved.
     <www.paulvandenbergh.be>
    
     Some parts of this code can be based on Texas Instruments StarterWare
     and are copyrighted under the following terms:
    
     * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
     *
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
    
    
     Subversion info:
     ================
    
     File name:
     $HeadURL: server-paul/.../MMCD.h $
    
     Revision:
     $LastChangedRevision: 391 $
    
     Last modified:
     $Date: 2015-10-06 01:29:58 +0200 (Tue, 06 Oct 2015) $
    
     **/
    
    /*
     * MMCD.h
     *
     *  Created on: Sep 22, 2015
     *      Author: Paul
     */
    
    #ifndef PERIPHERALS_MMCD_H_
    #define PERIPHERALS_MMCD_H_
    
    #include "stdint.h"
    
    namespace BPg
    {
    	/*****************************************************************************/
    	/*
    	** Macros that can be passed to configure Standby mode
    	*/
    	#define HS_MMCSD_STANDBY_FORCE      (MMCHS_SYSCONFIG_STANDBYMODE_FORCE  << MMCHS_SYSCONFIG_STANDBYMODE_SHIFT)
    	#define HS_MMCSD_STANDBY_NONE       (MMCHS_SYSCONFIG_STANDBYMODE_NOIDLE << MMCHS_SYSCONFIG_STANDBYMODE_SHIFT)
    	#define HS_MMCSD_STANDBY_SMART      (MMCHS_SYSCONFIG_STANDBYMODE_SMART  << MMCHS_SYSCONFIG_STANDBYMODE_SHIFT)
    	#define HS_MMCSD_STANDBY_SMARTWAKE  (MMCHS_SYSCONFIG_STANDBYMODE_SMARTWAKE << MMCHS_SYSCONFIG_STANDBYMODE_SHIFT)
    
    	/*
    	** Macros that can be passed to configure clock activity during wake up period
    	*/
    	#define HS_MMCSD_CLOCK_OFF          (MMCHS_SYSCONFIG_CLOCKACTIVITY_NONE << MMCHS_SYSCONFIG_CLOCKACTIVITY_SHIFT)
    	#define HS_MMCSD_FCLK_OFF           (MMCHS_SYSCONFIG_CLOCKACTIVITY_OCP << MMCHS_SYSCONFIG_CLOCKACTIVITY_SHIFT)
    	#define HS_MMCSD_ICLK_OFF           (MMCHS_SYSCONFIG_CLOCKACTIVITY_FUNC << MMCHS_SYSCONFIG_CLOCKACTIVITY_SHIFT)
    	#define HS_MMCSD_CLOCK_ON           (MMCHS_SYSCONFIG_CLOCKACTIVITY_BOTH << MMCHS_SYSCONFIG_CLOCKACTIVITY_SHIFT)
    
    	/*
    	** Macros that can be passed to configure idle modes
    	*/
    	#define HS_MMCSD_SMARTIDLE_FORCE     (MMCHS_SYSCONFIG_SIDLEMODE_FORCE << MMCHS_SYSCONFIG_SIDLEMODE_SHIFT)
    	#define HS_MMCSD_SMARTIDLE_NONE      (MMCHS_SYSCONFIG_SIDLEMODE_NOIDLE << MMCHS_SYSCONFIG_SIDLEMODE_SHIFT)
    	#define HS_MMCSD_SMARTIDLE_SMART     (MMCHS_SYSCONFIG_SIDLEMODE_SMART << MMCHS_SYSCONFIG_SIDLEMODE_SHIFT)
    	#define HS_MMCSD_SMARTIDLE_SMARTWAKE (MMCHS_SYSCONFIG_SIDLEMODE_SMARTWAKE << MMCHS_SYSCONFIG_SIDLEMODE_SHIFT)
    
    	/*
    	** Macros that can be passed to configure wakeup modes
    	*/
    	#define HS_MMCSD_WAKEUP_ENABLE       (MMCHS_SYSCONFIG_ENAWAKEUP_ENABLED << MMCHS_SYSCONFIG_ENAWAKEUP_SHIFT)
    	#define HS_MMCSD_WAKEUP_DISABLE      (MMCHS_SYSCONFIG_ENAWAKEUP_DISABLED << MMCHS_SYSCONFIG_ENAWAKEUP_SHIFT)
    
    	/*
    	** Macros that can be passed to configure auto idle modes
    	*/
    	#define HS_MMCSD_AUTOIDLE_ENABLE     (MMCHS_SYSCONFIG_AUTOIDLE_ON << MMCHS_SYSCONFIG_AUTOIDLE_SHIFT)
    	#define HS_MMCSD_AUTOIDLE_DISABLE    (MMCHS_SYSCONFIG_AUTOIDLE_OFF << MMCHS_SYSCONFIG_AUTOIDLE_SHIFT)
    
    	/*****************************************************************************/
    	/*
    	** Macros that can be used for SD controller DMA request configuration
    	*/
    	#define HS_MMCSD_DMAREQ_EDGETRIG    (MMCHS_CON_SDMA_LNE_EARLYDEASSERT << MMCHS_CON_DMA_LNE_SHIFT)
    	#define HS_MMCSD_DMAREQ_LVLTRIG     (MMCHS_CON_SDMA_LNE_LATEDEASSERT << MMCHS_CON_DMA_LNE_SHIFT)
    
    	/*
    	** Macros that can be used for SD controller dual rate configuration
    	*/
    	#define HS_MMCSD_DUALRATE_ENABLE    (MMCHS_CON_DDR_DDRMODE <<  MMCHS_CON_DDR_SHIFT)
    	#define HS_MMCSD_DUALRATE_DISABLE   (MMCHS_CON_DDR_NORMALMODE << MMCHS_CON_DDR_SHIFT)
    
    	/*
    	** Macros that can be used for selecting the bus/data width
    	*/
    	#define HS_MMCSD_BUS_WIDTH_8BIT    (0x8)
    	#define HS_MMCSD_BUS_WIDTH_4BIT    (0x4)
    	#define HS_MMCSD_BUS_WIDTH_1BIT    (0x1)
    
    	/*
    	** Macros that can be used for starting/stopping a init stream
    	*/
    	#define HS_MMCSD_INIT_START         (MMCHS_CON_INIT_INITSTREAM << MMCHS_CON_INIT_SHIFT)
    	#define HS_MMCSD_INIT_STOP          (MMCHS_CON_INIT_NOINIT << MMCHS_CON_INIT_SHIFT)
    
    	/*
    	** Macros that can be used for setting drain type
    	*/
    	#define HS_MMCSD_OPENDRAIN          (MMCHS_CON_OD_OPENDRAIN << MMCHS_CON_OD_SHIFT)
    
    
    	#define MMCHS_CMD_INDX_SHIFT   (0x00000018u)
    	/*
    	** Macros that can be used for forming the MMC/SD command
    	*/
    	/* Here\n
    	** cmd     : SD/MMC command number enumeration
    	** type    : specifies suspend upon CMD52 or resume upon CMD52 or abort upon CMD52/12.
    	** restype : no response, or response with or without busy
    	** rw      : direction of data transfer
    	*/
    	#define HS_MMCSD_CMD(cmd, type, restype, rw)    (cmd << MMCHS_CMD_INDX_SHIFT | type | restype | rw )
    
    	#define HS_MMCSD_NO_RESPONSE            (MMCHS_CMD_RSP_TYPE_NORSP << MMCHS_CMD_RSP_TYPE_SHIFT)
    	#define HS_MMCSD_136BITS_RESPONSE       (MMCHS_CMD_RSP_TYPE_136BITS << MMCHS_CMD_RSP_TYPE_SHIFT)
    	#define HS_MMCSD_48BITS_RESPONSE        (MMCHS_CMD_RSP_TYPE_48BITS << MMCHS_CMD_RSP_TYPE_SHIFT)
    	#define HS_MMCSD_48BITS_BUSY_RESPONSE   (MMCHS_CMD_RSP_TYPE_48BITS_BUSY << MMCHS_CMD_RSP_TYPE_SHIFT)
    
    	#define HS_MMCSD_CMD_TYPE_NORMAL        (MMCHS_CMD_CMD_TYPE_NORMAL << MMCHS_CMD_CMD_TYPE_SHIFT)
    	#define HS_MMCSD_CMD_TYPE_SUSPEND       (MMCHS_CMD_CMD_TYPE_SUSPEND << MMCHS_CMD_CMD_TYPE_SHIFT)
    	#define HS_MMCSD_CMD_TYPE_FUNCSEL       (MMCHS_CMD_CMD_TYPE_FUNC_SELECT << MMCHS_CMD_CMD_TYPE_SHIFT)
    	#define HS_MMCSD_CMD_TYPE_ABORT         (MMCHS_CMD_CMD_TYPE_ABORT << MMCHS_CMD_CMD_TYPE_SHIFT)
    
    	#define HS_MMCSD_CMD_DIR_READ           (MMCHS_CMD_DDIR_READ <<  MMCHS_CMD_DDIR_SHIFT)
    	#define HS_MMCSD_CMD_DIR_WRITE          (MMCHS_CMD_DDIR_WRITE <<  MMCHS_CMD_DDIR_SHIFT)
    	#define HS_MMCSD_CMD_DIR_DONTCARE       (MMCHS_CMD_DDIR_WRITE <<  MMCHS_CMD_DDIR_SHIFT)
    	/*
    	** Macros that can be used for checking the present state of the host controller
    	*/
    	#define HS_MMCSD_CARD_WRITEPROT        (MMCHS_PSTATE_WP)
    	#define HS_MMCSD_CARD_INSERTED         (MMCHS_PSTATE_CINS)
    	#define HS_MMCSD_CARD_STABLE           (MMCHS_PSTATE_CSS)
    	#define HS_MMCSD_BUFFER_READABLE       (MMCHS_PSTATE_BRE)
    	#define HS_MMCSD_BUFFER_WRITEABLE      (MMCHS_PSTATE_BWE)
    	#define HS_MMCSD_READ_INPROGRESS       (MMCHS_PSTATE_RTA)
    	#define HS_MMCSD_WRITE_INPROGRESS      (MMCHS_PSTATE_WTA)
    
    	/*
    	** Macros that can be used for configuring the power and transfer parameters
    	*/
    	#define HS_MMCSD_BUS_VOLT_1P8          (MMCHS_HCTL_SDVS_1V8 << MMCHS_HCTL_SDVS_SHIFT)
    	#define HS_MMCSD_BUS_VOLT_3P0          (MMCHS_HCTL_SDVS_3V0 << MMCHS_HCTL_SDVS_SHIFT)
    	#define HS_MMCSD_BUS_VOLT_3P3          (MMCHS_HCTL_SDVS_3V3 << MMCHS_HCTL_SDVS_SHIFT)
    	#define HS_MMCSD_BUS_POWER_ON          (MMCHS_HCTL_SDBP_PWRON << MMCHS_HCTL_SDBP_SHIFT)
    	#define HS_MMCSD_BUS_POWER_OFF         (MMCHS_HCTL_SDBP_PWROFF << MMCHS_HCTL_SDBP_SHIFT)
    	#define HS_MMCSD_BUS_HIGHSPEED         (MMCHS_HCTL_HSPE_HIGHSPEED << MMCHS_HCTL_HSPE_SHIFT)
    	#define HS_MMCSD_BUS_STDSPEED          (MMCHS_HCTL_HSPE_NORMALSPEED << MMCHS_HCTL_HSPE_SHIFT)
    
    	/*
    	** Macros that can be used for setting the clock, timeout values
    	*/
    	#define HS_MMCSD_DATA_TIMEOUT(n)        ((((n) - 13) & 0xF) << MMCHS_SYSCTL_DTO_SHIFT)
    	#define HS_MMCSD_CLK_DIVIDER(n)         ((n & 0x3FF) << MMCHS_SYSCTL_CLKD_SHIFT)
    	#define HS_MMCSD_CARDCLOCK_ENABLE       (MMCHS_SYSCTL_CEN_ENABLE << MMCHS_SYSCTL_CEN_SHIFT)
    	#define HS_MMCSD_CARDCLOCK_DISABLE      (MMCHS_SYSCTL_CEN_DISABLE << MMCHS_SYSCTL_CEN_SHIFT)
    	#define HS_MMCSD_INTCLOCK_ON            (MMCHS_SYSCTL_ICE_OSCILLATE << MMCHS_SYSCTL_ICE_SHIFT)
    	#define HS_MMCSD_INTCLOCK_OFF           (MMCHS_SYSCTL_ICE_STOP << MMCHS_SYSCTL_ICE_SHIFT)
    
    	/*
    	** Macros that can be used for resetting controller lines
    	*/
    	#define HS_MMCSD_DATALINE_RESET         (MMCHS_SYSCTL_SRD)
    	#define HS_MMCSD_CMDLINE_RESET          (MMCHS_SYSCTL_SRC)
    	#define HS_MMCSD_ALL_RESET              (MMCHS_SYSCTL_SRA)
    
    	/*
    	** Macros that can be used for interrupt enable/disable and status get operations
    	*/
    	#define HS_MMCSD_INTR_BADACCESS         (MMCHS_IE_BADA_ENABLE)
    	#define HS_MMCSD_INTR_CARDERROR         (MMCHS_IE_CERR_ENABLE)
    	#define HS_MMCSD_INTR_ADMAERROR         (MMCHS_IE_ADMAE_ENABLE)
    	#define HS_MMCSD_INTR_ACMD12ERR         (MMCHS_IE_ACE_ENABLE)
    	#define HS_MMCSD_INTR_DATABITERR        (MMCHS_IE_DEB_ENABLE)
    	#define HS_MMCSD_INTR_DATACRCERR        (MMCHS_IE_DCRC_ENABLE)
    	#define HS_MMCSD_INTR_DATATIMEOUT       (MMCHS_IE_DTO_ENABLE)
    	#define HS_MMCSD_INTR_CMDINDXERR        (MMCHS_IE_CIE_ENABLE)
    	#define HS_MMCSD_INTR_CMDBITERR         (MMCHS_IE_CEB_ENABLE)
    	#define HS_MMCSD_INTR_CMDCRCERR         (MMCHS_IE_CCRC_ENABLE)
    	#define HS_MMCSD_INTR_CMDTIMEOUT        (MMCHS_IE_CTO_ENABLE)
    	#define HS_MMCSD_INTR_CARDINS           (MMCHS_IE_CINS_ENABLE)
    	#define HS_MMCSD_INTR_BUFRDRDY          (MMCHS_IE_BRR_ENABLE)
    	#define HS_MMCSD_INTR_BUFWRRDY          (MMCHS_IE_BWR_ENABLE)
    	#define HS_MMCSD_INTR_TRNFCOMP          (MMCHS_IE_TC_ENABLE)
    	#define HS_MMCSD_INTR_CMDCOMP           (MMCHS_IE_CC_ENABLE)
    
    	#define HS_MMCSD_STAT_BADACCESS         (MMCHS_STAT_BADA)
    	#define HS_MMCSD_STAT_CARDERROR         (MMCHS_STAT_CERR)
    	#define HS_MMCSD_STAT_ADMAERROR         (MMCHS_STAT_ADMAE)
    	#define HS_MMCSD_STAT_ACMD12ERR         (MMCHS_STAT_ACE)
    	#define HS_MMCSD_STAT_DATABITERR        (MMCHS_STAT_DEB)
    	#define HS_MMCSD_STAT_DATACRCERR        (MMCHS_STAT_DCRC)
    	#define HS_MMCSD_STAT_ERR				(MMCHS_STAT_ERRI)
    	#define HS_MMCSD_STAT_DATATIMEOUT       (MMCHS_STAT_DTO)
    	#define HS_MMCSD_STAT_CMDINDXERR        (MMCHS_STAT_CIE)
    	#define HS_MMCSD_STAT_CMDBITERR         (MMCHS_STAT_CEB)
    	#define HS_MMCSD_STAT_CMDCRCERR         (MMCHS_STAT_CCRC)
    	#define HS_MMCSD_STAT_CMDTIMEOUT        (MMCHS_STAT_CTO)
    	#define HS_MMCSD_STAT_CARDINS           (MMCHS_STAT_CINS)
    	#define HS_MMCSD_STAT_BUFRDRDY          (MMCHS_STAT_BRR)
    	#define HS_MMCSD_STAT_BUFWRRDY          (MMCHS_STAT_BWR)
    	#define HS_MMCSD_STAT_TRNFCOMP          (MMCHS_STAT_TC)
    	#define HS_MMCSD_STAT_CMDCOMP           (MMCHS_STAT_CC)
    
    	#define HS_MMCSD_SIGEN_BADACCESS        (MMCHS_ISE_BADA_SIGEN)
    	#define HS_MMCSD_SIGEN_CARDERROR        (MMCHS_ISE_CERR_SIGEN)
    	#define HS_MMCSD_SIGEN_ADMAERROR        (MMCHS_ISE_ADMAE_SIGEN)
    	#define HS_MMCSD_SIGEN_ACMD12ERR        (MMCHS_ISE_ACE_SIGEN)
    	#define HS_MMCSD_SIGEN_DATABITERR       (MMCHS_ISE_DEB_SIGEN)
    	#define HS_MMCSD_SIGEN_DATACRCERR       (MMCHS_ISE_DCRC_SIGEN)
    	#define HS_MMCSD_SIGEN_DATATIMEOUT      (MMCHS_ISE_DTO_SIGEN)
    	#define HS_MMCSD_SIGEN_CMDINDXERR       (MMCHS_ISE_CIE_SIGEN)
    	#define HS_MMCSD_SIGEN_CMDBITERR        (MMCHS_ISE_CEB_SIGEN)
    	#define HS_MMCSD_SIGEN_CMDCRCERR        (MMCHS_ISE_CCRC_SIGEN)
    	#define HS_MMCSD_SIGEN_CMDTIMEOUT       (MMCHS_ISE_CTO_SIGEN)
    	#define HS_MMCSD_SIGEN_CARDINS          (MMCHS_ISE_CINS_SIGEN)
    	#define HS_MMCSD_SIGEN_BUFRDRDY         (MMCHS_ISE_BRR_SIGEN)
    	#define HS_MMCSD_SIGEN_BUFWRRDY         (MMCHS_ISE_BWR_SIGEN)
    	#define HS_MMCSD_SIGEN_TRNFCOMP         (MMCHS_ISE_TC_SIGEN)
    	#define HS_MMCSD_SIGEN_CMDCOMP          (MMCHS_ISE_CC_SIGEN)
    
    	/*
    	** Macros that can be used for checking the capabilites of the controller
    	*/
    	#define HS_MMCSD_SUPPORT_VOLT_1P8       (MMCHS_CAPA_VS18)
    	#define HS_MMCSD_SUPPORT_VOLT_3P0       (MMCHS_CAPA_VS30)
    	#define HS_MMCSD_SUPPORT_VOLT_3P3       (MMCHS_CAPA_VS33)
    	#define HS_MMCSD_SUPPORT_DMA            (MMCHS_CAPA_DS)
    	#define HS_MMCSD_SUPPORT_HIGHSPEED      (MMCHS_CAPA_HSS)
    	#define HS_MMCSD_SUPPORT_BLOCKLEN       (MMCHS_CAPA_MBL)
    
    	/*
    	** Structure to save the I2C context
    	*/
    	typedef struct MMCSDContext {
    	    unsigned int capa;
    	    unsigned int systemConfig;
    	    unsigned int ctrlInfo;
    	    unsigned int hctl;
    	    unsigned int sysCtl;
    	    unsigned int pState;
    	}MMCSDCONTEXT;
    
    
    	enum MMCDID
    	{
    		MMCD0 = 0,	//	µSD on BeagleBone Black
    		MMCD1,		//	eMMC on BeagleBone Black
    		MMCD2,
    		MAXMMCDInstances
    	};
    
    	/**
    	 * \brief	The AM335x device contains three instances of the Multimedia Card (MMC), Secure Digital (SD), and Secure Digital I/O (SDIO) high speed interface module (MMCHS).
    	 *
    	 *  The controller provides an interface to an MMC, SD memory card or SDIO card.
    	 *  The application interface is responsible for managing transaction semantics; the MMC/SDIO host controller deals with MMC/SDIO protocol at transmission level, packing data, adding CRC, start/end bit and checking for syntactical correctness.
    	 *  MMCHS Module SDIO Application through MMCHS Module MMC Application below show examples of systems using the MMCHS controller.
    	 *  Note that the power switch control is only available on the MMCHS0 interface.
    	 *
    	 *  The general features of the MMCHS host controller IP are:
    	 * 	- Built-in 1024-byte buffer for read or write
    	 * 	- Two DMA channels, one interrupt line
    	 * 	- Clock support
    	 * 		* 96-MHz functional clock source input
    	 * 		* up to 384Mbit/sec (48MByte/sec) in MMC mode 8-bit data transfer
    	 * 		* up to 192Mbit/sec (24MByte/sec) in High-Speed SD mode 4-bit data transfer
    	 * 		* up to 24Mbit/sec (3MByte/sec) in Default SD mode 1-bit data transfer
    	 * 	- Support for SDA 3.0 Part A2 programming model
    	 * 	- Serial link supports full compliance with:
    	 * 		* MMC command/response sets as defined in the MMC standard specification v4.3.
    	 * 		* SD command/response sets as defined in the SD Physical Layer specification v2.00
    	 * 		* SDIO command/response sets and interrupt/read-wait suspend-resume operations as defined in the SD part E1 specification v 2.00
    	 * 		* SD Host Controller Standard Specification sets as defined in the SD card specification Part A2 v2.00
    	 */
    	class MMCD
    	{
    		public:
    			static MMCD* getInstance(MMCDID id);
    			virtual ~MMCD();
    
    			void		BlkLenSet(uint32_t blklen);
    			bool		BusFreqSet(uint32_t freq_in, uint32_t freq_out, bool bypass);
    			bool 		BusPower(uint32_t pwr);
    			void 		BusVoltSet(uint32_t volt);
    			void 		BusWidthSet(uint32_t width);
    			void 		CommandSend(uint32_t cmd, uint32_t cmdarg, void* data, uint32_t nblks, bool dmaEn);
    			void 		DataGet(uint8_t* pData, uint32_t len);
    			void		DataPut(uint8_t* pData, uint32_t len);
    			void 		DataTimeoutSet(uint32_t timeout);
    			bool 		InitStreamSend(void);
    			bool 		IntClock(uint32_t pwr);
    			void 		IntrEnable(uint32_t flag);
    			void 		IntrStatusClear(uint32_t flag);
    			void 		IntrStatusDisable(uint32_t flag);
    			void 		IntrStatusEnable(uint32_t flag);
    			uint32_t	IntrStatusGet(uint32_t flag);
    			bool		IsCardInserted(void);
    			bool		IsCardWriteProtected(void);
    			bool		IsCmdComplete(uint32_t retry);
    			bool		IsHSupported(void);
    			bool		IsIntClockStable(uint32_t retry);
    			bool		IsXferComplete(uint32_t retry);
    			bool		LinesReset(uint32_t flag);
    			void		ResponseGet(uint32_t* rsp);
    			bool		SoftReset(void);
    			void		SupportedVoltSet(uint32_t volt);
    			void		SystemConfig(uint32_t config);
    			void		XferSetup(bool bRead);
    
    			void		getResponse32(uint32_t* pResponse);
    			void		GetResponse128(uint32_t* pResponse);
    
    		protected:
    			MMCD(MMCDID id);
    
    		private:
    			MMCDID			m_ID;
    			uint32_t		m_baseAddr;
    			static MMCD*	sm_pInstances[MAXMMCDInstances];
    	};
    
    } /* namespace BPg */
    
    #endif /* PERIPHERALS_MMCD_H_ */
    

    Implementation :

    /**
    
     +==================================================================
     |		BPg Project (BeagleBonePlayground)
     +==================================================================
    
     File:		MMCD.cpp
    
     Created:	Sep 22, 2015 10:52:36 AM
     Author:		Paul
    
     Copyright (C) 2015 Paul Van den Bergh.  All rights reserved.
     <www.paulvandenbergh.be>
    
     Some parts of this code can be based on Texas Instruments StarterWare
     and are copyrighted under the following terms:
    
     * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
     *
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
    
    
     Subversion info:
     ================
    
     File name:
     $HeadURL: server-paul/.../MMCD.cpp $
    
     Revision:
     $LastChangedRevision: 393 $
    
     Last modified:
     $Date: 2015-10-08 10:09:24 +0200 (Thu, 08 Oct 2015) $
    
     **/
    
    /*
     * MMCD.cpp
     *
     *  Created on: Sep 22, 2015
     *      Author: Paul
     */
    
    #include "MMCD.h"
    
    #include "soc_AM335x.h"
    #include "hw_types.h"
    #include "hw_cm_per.h"
    #include "hw_hs_mmcsd.h"
    #include "hw_control_AM335X.h"
    
    namespace BPg
    {
    
    	MMCD* MMCD::getInstance(MMCDID id)
    	{
    		if(0 != sm_pInstances[id])
    		{
    			return sm_pInstances[id];
    		}
    
    		return sm_pInstances[id] = new MMCD(id);
    	}
    
    	/**
    	 * \brief    Set the block length/size for data transfer
    	 *
    	 * \param    blklen      Command to be passed to the controller/card
    	 *
    	 * \note: blklen should be within the limits specified by the controller/card
    	 *
    	 * \return   none
    	 **/
    	void MMCD::BlkLenSet(uint32_t blklen)
    	{
    		HWREG(m_baseAddr + MMCHS_BLK) &= ~MMCHS_BLK_BLEN;
    		HWREG(m_baseAddr + MMCHS_BLK) |= blklen;
    	}
    
    	/**
    	 * \brief   Set output bus frequency
    	 *
    	 * \param   freq_in       The input/ref frequency to the controller
    	 * \param   freq_out      The required output frequency on the bus
    	 * \param   bypass        If the reference clock is to be bypassed
    	 *
    	 * \return  true   on clock enable success
    	 *          false  on clock enable fail
    	 *
    	 * \note: If the clock is set properly, the clocks are enabled to the card with
    	 * the return of this function
    	 **/
    	bool MMCD::BusFreqSet(uint32_t freq_in, uint32_t freq_out, bool bypass)
    	{
    	    volatile unsigned int clkd = 0;
    		volatile unsigned int regVal = 0;
    
    	    /* First enable the internal clocks */
    	    if (IntClock(HS_MMCSD_INTCLOCK_ON) == false)
    	    {
    	        return false;
    	    }
    
    	    if (false == bypass)
    	    {
    	        /* Calculate and program the divisor */
    	        clkd = freq_in / freq_out;
    	        clkd = (clkd < 2) ? 2 : clkd;
    	        clkd = (clkd > 1023) ? 1023 : clkd;
    
    			/* Do not cross the required freq */
    			while((freq_in/clkd) > freq_out)
    			{
    				if (clkd == 1023)
    				{
    					/* Return we we cannot set the clock freq */
    				   return false;
    				}
    
    				clkd++;
    			}
    
    	        regVal = HWREG(m_baseAddr + MMCHS_SYSCTL) & ~MMCHS_SYSCTL_CLKD;
    	        HWREG(m_baseAddr + MMCHS_SYSCTL) = regVal | (clkd << MMCHS_SYSCTL_CLKD_SHIFT);
    
    	        /* Wait for the interface clock stabilization */
    	        if(IsIntClockStable(0xFFFF) == 0)
    	        {
    	            return false;
    	        }
    
    	        /* Enable clock to the card */
    	        HWREG(m_baseAddr + MMCHS_SYSCTL) |= MMCHS_SYSCTL_CEN;
    	    }
    
    	    return true;
    	}
    
    	/**
    	 * \brief   Turn MMC/SD bus power on / off
    	 *
    	 * \param   pwr           power on / off setting
    	 *
    	 * pwr can take the values \n
    	 *     HS_MMCSD_BUS_POWER_ON \n
    	 *     HS_MMCSD_BUS_POWER_OFF \n
    	 *
    	 * \return  0 if the operation succeeded
    	 *         -1 if the operation failed
    	 *
    	 **/
    	bool MMCD::BusPower(uint32_t pwr)
    	{
    	    volatile uint32_t timeout = 0xFFFFF;
    
    	    HWREG(m_baseAddr + MMCHS_HCTL) =
    	            (HWREG(m_baseAddr + MMCHS_HCTL) & ~MMCHS_HCTL_SDBP) | pwr;
    
    	    if (pwr == HS_MMCSD_BUS_POWER_ON)
    	    {
    	        do
    	        {
    	        	if ((HWREG(m_baseAddr + MMCHS_HCTL) & MMCHS_HCTL_SDBP) != 0)
    	            {
    	        		break;
    	            }
    	        } while(--timeout);
    	    }
    
    	    if (timeout == 0)
    	    {
    	        return false;
    	    }
    	    else
    	    {
    	        return true;
    	    }
    	}
    
    	/**
    	 * \brief   Configure the MMC/SD bus voltage
    	 *
    	 * \param   volt          SD/MMC bus voltage
    	 *
    	 * volt can take the values \n
    	 *     HS_MMCSD_BUS_VOLT_1P8 \n
    	 *     HS_MMCSD_BUS_VOLT_3P0 \n
    	 *     HS_MMCSD_BUS_VOLT_3P3 \n
    	 *
    	 * \return  None.
    	 *
    	 **/
    	void MMCD::BusVoltSet(uint32_t volt)
    	{
    	    HWREG(m_baseAddr + MMCHS_HCTL) &= ~MMCHS_HCTL_SDVS;
    	    HWREG(m_baseAddr + MMCHS_HCTL) |= volt;
    	}
    
    	/**
    	 * \brief   Configure the MMC/SD bus width
    	 *
    	 * \param   width         SD/MMC bus width
    	 *
    	 * width can take the values \n
    	 *     HS_MMCSD_BUS_WIDTH_8BIT \n
    	 *     HS_MMCSD_BUS_WIDTH_4BIT \n
    	 *     HS_MMCSD_BUS_WIDTH_1BIT \n
    	 *
    	 * \return  None.
    	 *
    	 **/
    	void MMCD::BusWidthSet(uint32_t width)
    	{
    	    switch (width)
    	    {
    	        case HS_MMCSD_BUS_WIDTH_8BIT:
    	            HWREG(m_baseAddr + MMCHS_CON) |= MMCHS_CON_DW8;
    	        break;
    
    	        case HS_MMCSD_BUS_WIDTH_4BIT:
    	            HWREG(m_baseAddr + MMCHS_CON) &= ~MMCHS_CON_DW8;
    	            HWREG(m_baseAddr + MMCHS_HCTL) |=
    	                    (MMCHS_HCTL_DTW_4_BITMODE << MMCHS_HCTL_DTW_SHIFT);
    	        break;
    
    	        case HS_MMCSD_BUS_WIDTH_1BIT:
    	            HWREG(m_baseAddr + MMCHS_CON) &= ~MMCHS_CON_DW8;
    	            HWREG(m_baseAddr + MMCHS_HCTL) &= ~MMCHS_HCTL_DTW;
    	            HWREG(m_baseAddr + MMCHS_HCTL) |=
    	                    (MMCHS_HCTL_DTW_1_BITMODE << MMCHS_HCTL_DTW_SHIFT);
    	        break;
    	    }
    	}
    
    	/**
    	 * \brief    Pass the MMC/SD command to the controller/card
    	 *
    	 * \param   cmd         Command to be passed to the controller/card
    	 * \param   cmdArg      argument for the command
    	 * \param   data        data pointer, if it is a data command, else must be null
    	 * \param   nblks       data length in number of blocks (multiple of BLEN)
    	 * \param   dmaEn       Should dma be enabled (1) or disabled (0)
    	 *
    	 * \note: Please use HS_MMCSD_CMD(cmd, type, restype, rw) to form command
    	 *
    	 * \return   none
    	 **/
    	void MMCD::CommandSend(uint32_t cmd, uint32_t cmdArg, void* data, uint32_t nblks, bool dmaEn)
    	{
    	    if (NULL != data)
    	    {
    	        cmd |= (MMCHS_CMD_DP);
    
    	        if(nblks > 1)
    	        {
    	        	cmd |= (MMCHS_CMD_MSBS | MMCHS_CMD_BCE);
    	        }
    	        else
    	        {
    	        	cmd &= ~(MMCHS_CMD_MSBS | MMCHS_CMD_BCE);
    	        }
    	    }
    
    	    if (1 == dmaEn)
    	    {
    	        cmd |= MMCHS_CMD_DE;
    	    }
    
    	    /* Set the block information; block length is specified separately */
    	    HWREG(m_baseAddr + MMCHS_BLK) &= ~MMCHS_BLK_NBLK;
    	    HWREG(m_baseAddr + MMCHS_BLK) |= nblks << MMCHS_BLK_NBLK_SHIFT;
    
    	    /* Set the command/command argument */
    	    HWREG(m_baseAddr + MMCHS_ARG) = cmdArg;
    	    HWREG(m_baseAddr + MMCHS_CMD) = cmd;
    	}
    
    	/**
    	 * \brief    Send the data to the card from the conntroller
    	 *
    	 * \param    pData       pointer to buffer which is to be filled with the data
    	 * \param    len         length of the data
    	 *
    	 * \note: this function reads the data in chunks of 32 bits (4-byte words).
    	 * Hence, the len should be multiple of 4-byte words
    	 *
    	 * \return   none
    	 **/
    	void MMCD::DataGet(uint8_t* pData, uint32_t len)
    	{
    		uint32_t i;
    		uint32_t temp;
    
    		for (i = 0; i < len; i += 4)
    		{
    			temp = HWREG(m_baseAddr + MMCHS_DATA);
    			pData[i] = *((uint8_t*)&temp + 3);
    			pData[i + 1] = *((uint8_t*)&temp + 2);
    			pData[i + 2] = *((uint8_t*)&temp + 1);
    			pData[i + 3] = *((uint8_t*)&temp + 0);
    		}
    	}
    
    	void MMCD::DataPut(uint8_t* pData, uint32_t len)
    	{
    		for(uint32_t i = 0; i < len / 4; i++)
    		{
    			HWREG(m_baseAddr + MMCHS_DATA) = ((uint32_t)pData[i]);
    		}
    	}
    
    	/**
    	 * \brief   Set data timeout value
    	 *
    	 * \param   timeout       the data time out value
    	 *
    	 * Timeout value is the exponential of 2, as mentioned in the controller
    	 * reference manual.\n
    	 *
    	 * \note: Please use HS_MMCSD_DATA_TIMEOUT(n) for setting this value\n
    	 *        13 <= n <= 27
    	 *
    	 * \return  None.
    	 *
    	 **/
    	void MMCD::DataTimeoutSet(uint32_t timeout)
    	{
    	    HWREG(m_baseAddr + MMCHS_SYSCTL) &= ~(MMCHS_SYSCTL_DTO);
    	    HWREG(m_baseAddr + MMCHS_SYSCTL) |= timeout;
    	}
    
    	/**
    	 * \brief   Sends INIT stream to the card
    	 *
    	 *
    	 * \return  true   If INIT command could be initiated
    	 *          false  If INIT command could not be completed/initiated
    	 *
    	 **/
    	bool MMCD::InitStreamSend(void)
    	{
    	    bool status;
    
    	    /* Enable the command completion status to be set */
    	    IntrStatusEnable(HS_MMCSD_SIGEN_CMDCOMP);
    
    	    /* Initiate the INIT command */
    	    HWREG(m_baseAddr + MMCHS_CON) |= MMCHS_CON_INIT;
    	    HWREG(m_baseAddr + MMCHS_CMD) = 0x00;
    
    	    status = IsCmdComplete(0xFFFF);
    
    	    HWREG(m_baseAddr + MMCHS_CON) &= ~MMCHS_CON_INIT;
    	    /* Clear all status */
    	    IntrStatusClear(0xFFFFFFFF);
    
    	    return status;
    	}
    
    	/**
    	 * \brief   Turn Internal clocks on / off
    	 *
    	 * \param   pwr           clock on / off setting
    	 *
    	 * pwr can take the values \n
    	 *     HS_MMCSD_INTCLOCK_ON \n
    	 *     HS_MMCSD_INTCLOCK_OFF \n
    	 *
    	 * \return true  if the operation succeeded
    	 *         false if the operation failed
    	 *
    	 **/
    	bool MMCD::IntClock(uint32_t pwr)
    	{
    	    HWREG(m_baseAddr + MMCHS_SYSCTL) =
    	            (HWREG(m_baseAddr + MMCHS_SYSCTL) & ~MMCHS_SYSCTL_ICE) | pwr;
    
    	    if (pwr == HS_MMCSD_INTCLOCK_ON)
    	    {
    	        if(IsIntClockStable(0xFFFF) == 0)
    	        {
    	            return false;
    	        }
    	    }
    
    	    return true;
    	}
    
    	/**
    	 * \brief   Enables the controller events to generate a h/w interrupt request
    	 *
    	 * \param   flag        Specific event required;
    	 *
    	 * flag can take the following (or combination of) values \n
    	 * HS_MMCSD_SIGEN_xxx
    	 *
    	 * \return   none
    	 *
    	 **/
    	void MMCD::IntrEnable(uint32_t flag)
    	{
    	    HWREG(m_baseAddr + MMCHS_ISE) |= flag;
    		IntrStatusEnable(flag);
    	}
    
    	/**
    	 * \brief   Clear the status bits from the controller
    	 *
    	 * \param   flag        Specific status required;
    	 *
    	 * flag can take the following (or combination of) values \n
    	 * HS_MMCSD_STAT_xxx
    	 *
    	 * \return   none
    	 *
    	 **/
    	void MMCD::IntrStatusClear(uint32_t flag)
    	{
    	    HWREG(m_baseAddr + MMCHS_STAT) = flag;
    	}
    
    	/**
    	 * \brief   Disables the controller events to set flags in status register
    	 *
    	 * \param   flag        Specific event required;
    	 *
    	 * flag can take the following (or combination of) values \n
    	 * HS_MMCSD_INTR_xxx
    	 *
    	 * \note: This function only enables the reflection of events in status register.
    	 * To disable events to generate a h/w interrupt request \see HSMMCSDIntrEnable()
    	 *
    	 * \return   none
    	 *
    	 **/
    	void MMCD::IntrStatusDisable(uint32_t flag)
    	{
    	    HWREG(m_baseAddr + MMCHS_IE) &= ~flag;
    	}
    
    	/**
    	 * \brief   Enables the controller events to set flags in status register
    	 *
    	 * \param   flag        Specific event required;
    	 *
    	 * flag can take the following (or combination of) values \n
    	 * HS_MMCSD_INTR_xxx
    	 *
    	 * \note: This function only enables the reflection of events in status register.
    	 * To enable events to generate a h/w interrupt request \see HSMMCSDIntrEnable()
    	 *
    	 * \return   none
    	 *
    	 **/
    	void MMCD::IntrStatusEnable(uint32_t flag)
    	{
    	    HWREG(m_baseAddr + MMCHS_IE) |= flag;
    	}
    
    	/**
    	 * \brief   Gets the status bits from the controller
    	 *
    	 * \param   flag        Specific status required;
    	 *
    	 * flag can take the following (or combination of) values \n
    	 * HS_MMCSD_STAT_xxx
    	 *
    	 * \return   status flags
    	 *
    	 **/
    	uint32_t MMCD::IntrStatusGet(uint32_t flag)
    	{
    	    return HWREG(m_baseAddr + MMCHS_STAT) & flag;
    	}
    
    	/**
    	 * \brief    Check if the card is inserted and detected
    	 *
    	 *
    	 * \return   false  if the card is not inserted and detected
    	 *           true   if the card is inserted and detected
    	 *
    	 * \note: that this functional may not be available for all instances of the
    	 * controler. This function, is only useful of the controller has a dedicated
    	 * card detect pin. If not, the card detection mechanism is application
    	 * implementation specific
    	 **/
    	bool MMCD::IsCardInserted(void)
    	{
    	    return 1 == ((HWREG(m_baseAddr + MMCHS_PSTATE) & MMCHS_PSTATE_CINS) >> MMCHS_PSTATE_CINS_SHIFT);
    	}
    
    	/**
    	 * \brief    Check if the card is write protected
    	 *
    	 *
    	 * \return   false  if the card is not write protected
    	 *           true   if the card is write protected
    	 *
    	 * \note: that this functional may not be available for all instances of the
    	 * controler. This function, is only useful of the controller has a dedicated
    	 * write protect detect pin. If not, the write protect detection mechanism is
    	 * application implementation specific
    	 **/
    	bool MMCD::IsCardWriteProtected(void)
    	{
    	    return 1 == ((HWREG(m_baseAddr + MMCHS_PSTATE) & MMCHS_PSTATE_WP) >> MMCHS_PSTATE_WP_SHIFT);
    	}
    
    	/**
    	 * \brief    Checks if the command is complete
    	 *
    	 * \param    retry       retry times to poll for completion
    	 *
    	 * \return   true  if the command is complete
    	 *           false if the command is not complete
    	 **/
    	bool MMCD::IsCmdComplete(uint32_t retry)
    	{
    	    volatile unsigned int status = 0;
    
    	    do
    	    {
    	        status = (HWREG(m_baseAddr + MMCHS_STAT) & MMCHS_STAT_CC) >>
    	                                    MMCHS_STAT_CC_SHIFT;
    	        if (( 1 == status) || (0  == retry))
    	        {
    	            break;
    	        }
    	    } while (retry--);
    
    	    if(1 == status)
    	    {
    	    	HWREG(m_baseAddr + MMCHS_STAT) |= ((MMCHS_STAT_CC) << MMCHS_STAT_CC_SHIFT);
    	    }
    	    return 1 == status;
    	}
    
    	/**
    	 * \brief   Check if the controller supports high speed
    	 *
    	 *
    	 * \return  false if high speed is not supported
    	 *          true  if high speed is supported
    	 *
    	 **/
    	bool MMCD::IsHSupported(void)
    	{
    	    return 1 == ((HWREG(m_baseAddr + MMCHS_CAPA) & MMCHS_CAPA_HSS) >> MMCHS_CAPA_HSS_SHIFT);
    	}
    
    	/**
    	 * \brief   Get the internal clock stable status
    	 *
    	 * \param   retry         retry times to poll for stable
    	 *
    	 * \note: if retry is zero the status is not polled. If it is non-zero status
    	 *        is polled for retry times
    	 *
    	 * \return  true  if the clock is stable
    	 *          false if the clock is not stable
    	 *
    	 **/
    	bool MMCD::IsIntClockStable(uint32_t retry)
    	{
    	    volatile unsigned int status = 0;
    
    	    do {
    	            status = (HWREG(m_baseAddr + MMCHS_SYSCTL) & MMCHS_SYSCTL_ICS) >>
    	                                            MMCHS_SYSCTL_ICS_SHIFT;
    	            if ((status == 1) || (retry == 0))
    	            {
    	                break;
    	            }
    	    } while (retry--);
    
    	    return 1 == status;
    	}
    
    	/**
    	 * \brief    Checks if the transfer is complete
    	 *
    	 * \param    retry       retry times to poll for completion
    	 *
    	 * \return   true  if the transfer is complete
    	 *           false if the transfer is not complete
    	 **/
    	bool MMCD::IsXferComplete(uint32_t retry)
    	{
    	    volatile unsigned int status = 0;
    
    	    do
    	    {
    	        status = (HWREG(m_baseAddr + MMCHS_STAT) & MMCHS_STAT_TC) >>
    	                                    MMCHS_STAT_TC_SHIFT;
    	        if ((1 == status) || (0 == retry))
    	        {
    	            break;
    	        }
    	    } while (retry--);
    
    	    return 1 == status;
    	}
    
    	/**
    	 * \brief   Soft reset the MMC/SD controller lines
    	 *
    	 * \param   flag          reset flags indicating the lines to be reset.
    	 *
    	 * flag can take the following values.
    	 * 	- HS_MMCSD_DATALINE_RESET
    	 * 	- HS_MMCSD_CMDLINE_RESET
    	 * - HS_MMCSD_ALL_RESET
    	 *
    	 * \return  true    on reset success
    	 *          false   on reset fail
    	 *
    	 **/
    	bool MMCD::LinesReset(uint32_t flag)
    	{
    	    volatile unsigned int timeout = 0xFFFF;
    
    	    HWREG(m_baseAddr + MMCHS_SYSCTL) |= flag;
    
    	    do
    	    {
    	        if ((HWREG(m_baseAddr + MMCHS_SYSCTL) & flag) == 0)
    	        {
    	            break;
    	        }
    	    } while(timeout--);
    
    	    if (0 == timeout)
    	    {
    	        return false;
    	    }
    	    else
    	    {
    	        return true;
    	    }
    	}
    
    	/**
    	 * \brief    Get the command response from the conntroller
    	 *
    	 * \param    rsp         pointer to buffer which is to be filled with the response
    	 *
    	 * \note: that this function shall return the values from all response registers.
    	 * Hence, rsp, must be a pointer to memory which can hold max response length.
    	 * It is the responsibility of the caller to use only the required/relevant
    	 * parts of the response
    	 *
    	 * \return   none
    	 **/
    	void MMCD::ResponseGet(uint32_t* rsp)
    	{
    	    uint32_t i;
    
    	    for (i = 0; i <= 3; i++)
    	    {
    	        rsp[i] = HWREG(m_baseAddr + MMCHS_RSP(i));
    	    }
    	}
    
    	/**
    	 * \brief   Soft reset the MMC/SD controller
    	 *
    	 *
    	 * \return  true    on reset success
    	 *          false   on reset fail
    	 *
    	 **/
    
    	bool MMCD::SoftReset(void)
    	{
    	    volatile uint32_t timeout = 0xFFFF;
    
    	    HWREG(m_baseAddr + MMCHS_SYSCONFIG) |= MMCHS_SYSCONFIG_SOFTRESET;
    
    	    do
    	    {
    	        if ((HWREG(m_baseAddr + MMCHS_SYSSTATUS) & MMCHS_SYSSTATUS_RESETDONE) ==
    	                                               MMCHS_SYSSTATUS_RESETDONE)
    	        {
    	            break;
    	        }
    	    } while(--timeout);
    
    	    if (0 == timeout)
    	    {
    	        return false;
    	    }
    	    else
    	    {
    	        return true;
    	    }
    	}
    
    	/**
    	 * \brief   Set the supported voltage list
    	 *
    	 * \param   volt          Supported bus voltage
    	 *
    	 * volt can take the values (or a combination of) :
    	 *
    	 * 	- HS_MMCSD_SUPPORT_VOLT_1P8
    	 * 	- HS_MMCSD_SUPPORT_VOLT_3P0
    	 *	- HS_MMCSD_SUPPORT_VOLT_3P3
    	 *
    	 * \return  None.
    	 *
    	 **/
    	void MMCD::SupportedVoltSet(uint32_t volt)
    	{
    	    HWREG(m_baseAddr + MMCHS_CAPA) &= ~(MMCHS_CAPA_VS18 | MMCHS_CAPA_VS30 |
    	                                      MMCHS_CAPA_VS33);
    	    HWREG(m_baseAddr + MMCHS_CAPA) |= volt;
    	}
    
    	/**
    	 * \brief   Configure the MMC/SD controller standby, idle and wakeup modes
    	 *
    	 * \param   config        The standby, idle and wakeup modes
    	 *
    	 * flag can take the values (or a combination of the following) :
    	 *
    	 *	- HS_MMCSD_STANDBY_xxx - Standby mode configuration
    	 *	- HS_MMCSD_CLOCK_xxx - Clock mode configuration
    	 *	- HS_MMCSD_SMARTIDLE_xxx - Smart IDLE mode configuration
    	 *	- HS_MMCSD_WAKEUP_xxx - Wake up configuration
    	 *	- HS_MMCSD_AUTOIDLE_xxx - Auto IDLE mode configuration
    	 *
    	 * \return  None.
    	 *
    	 **/
    	void MMCD::SystemConfig(uint32_t config)
    	{
    	    HWREG(m_baseAddr + MMCHS_SYSCONFIG) &= ~(MMCHS_SYSCONFIG_STANDBYMODE |
    	                                          MMCHS_SYSCONFIG_CLOCKACTIVITY |
    	                                          MMCHS_SYSCONFIG_SIDLEMODE |
    	                                          MMCHS_SYSCONFIG_ENAWAKEUP |
    	                                          MMCHS_SYSCONFIG_AUTOIDLE);
    
    	    HWREG(m_baseAddr + MMCHS_SYSCONFIG) |= config;
    	}
    
    	/**
    	*\brief This function setup the controller and DMA for Xfer.
    	*
    	*
    	* \param - bRead  - Read/Write flag.
    	*
    	* \param - nBlks   - Number of Blocks.
    	*
    	* \return none.\n
    	*
    	*/
    	void MMCD::XferSetup(bool bRead)
    	{
    		IntrStatusClear(MMCHS_IE_TC_ENABLE);
    
    		if(bRead)
    		{
    			IntrStatusClear(MMCHS_IE_BRR_ENABLE);
    			IntrStatusEnable(MMCHS_IE_BRR_ENABLE);
    			IntrStatusDisable(MMCHS_IE_BWR_ENABLE);
    		}
    		else
    		{
    			IntrStatusClear(MMCHS_IE_BWR_ENABLE);
    			IntrStatusEnable(MMCHS_IE_BWR_ENABLE);
    			IntrStatusDisable(MMCHS_IE_BRR_ENABLE);
    		}
    	}
    
    	void MMCD::GetResponse128(uint32_t* pResponse)
    	{
    		uint8_t* pResp = (uint8_t*)pResponse;
    
    		uint32_t	data = HWREG(m_baseAddr + MMCHS_RSP(3));
    		pResp[ 3] = data & 0xFF;
    		pResp[ 2] = (data & 0xFF00) >> 8;
    		pResp[ 1] = (data & 0xFF0000) >> 16;
    		pResp[ 0] = (data & 0xFF000000) >> 24;
    
    		data = HWREG(m_baseAddr + MMCHS_RSP(2));
    		pResp[ 7] = data & 0xFF;
    		pResp[ 6] = (data & 0xFF00) >> 8;
    		pResp[ 5] = (data & 0xFF0000) >> 16;
    		pResp[ 4] = (data & 0xFF000000) >> 24;
    
    		data = HWREG(m_baseAddr + MMCHS_RSP(1));
    		pResp[11] = data & 0xFF;
    		pResp[10] = (data & 0xFF00) >> 8;
    		pResp[ 9] = (data & 0xFF0000) >> 16;
    		pResp[ 8] = (data & 0xFF000000) >> 24;
    
    		data = HWREG(m_baseAddr + MMCHS_RSP(0));
    		pResp[15] = data & 0xFF;
    		pResp[14] = (data & 0xFF00) >> 8;
    		pResp[13] = (data & 0xFF0000) >> 16;
    		pResp[12] = (data & 0xFF000000) >> 24;
    	}
    
    	MMCD::MMCD(MMCDID id)
    	:	m_ID(id)
    	{
    		switch(id)
    		{
    			case MMCD0:
    			{
    				m_baseAddr = SOC_MMCHS_0_REGS;
    
    				//	Configure Clocks
    			    HWREG(SOC_PRCM_REGS + CM_PER_MMC0_CLKCTRL) |= CM_PER_MMC0_CLKCTRL_MODULEMODE_ENABLE;
    
    			    while((HWREG(SOC_PRCM_REGS + CM_PER_MMC0_CLKCTRL) & CM_PER_MMC0_CLKCTRL_MODULEMODE) != CM_PER_MMC0_CLKCTRL_MODULEMODE_ENABLE);
    
    			    //	PinMux
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_MMC0_DAT3) =
    			                   (0 << CONTROL_CONF_MMC0_DAT3_CONF_MMC0_DAT3_MMODE_SHIFT)    |
    			                   (0 << CONTROL_CONF_MMC0_DAT3_CONF_MMC0_DAT3_PUDEN_SHIFT)    |
    			                   (1 << CONTROL_CONF_MMC0_DAT3_CONF_MMC0_DAT3_PUTYPESEL_SHIFT)|
    			                   (1 << CONTROL_CONF_MMC0_DAT3_CONF_MMC0_DAT3_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_MMC0_DAT2) =
    			                   (0 << CONTROL_CONF_MMC0_DAT2_CONF_MMC0_DAT2_MMODE_SHIFT)    |
    			                   (0 << CONTROL_CONF_MMC0_DAT2_CONF_MMC0_DAT2_PUDEN_SHIFT)    |
    			                   (1 << CONTROL_CONF_MMC0_DAT2_CONF_MMC0_DAT2_PUTYPESEL_SHIFT)|
    			                   (1 << CONTROL_CONF_MMC0_DAT2_CONF_MMC0_DAT2_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_MMC0_DAT1) =
    			                   (0 << CONTROL_CONF_MMC0_DAT1_CONF_MMC0_DAT1_MMODE_SHIFT)    |
    			                   (0 << CONTROL_CONF_MMC0_DAT1_CONF_MMC0_DAT1_PUDEN_SHIFT)    |
    			                   (1 << CONTROL_CONF_MMC0_DAT1_CONF_MMC0_DAT1_PUTYPESEL_SHIFT)|
    			                   (1 << CONTROL_CONF_MMC0_DAT1_CONF_MMC0_DAT1_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_MMC0_DAT0) =
    			                   (0 << CONTROL_CONF_MMC0_DAT0_CONF_MMC0_DAT0_MMODE_SHIFT)    |
    			                   (0 << CONTROL_CONF_MMC0_DAT0_CONF_MMC0_DAT0_PUDEN_SHIFT)    |
    			                   (1 << CONTROL_CONF_MMC0_DAT0_CONF_MMC0_DAT0_PUTYPESEL_SHIFT)|
    			                   (1 << CONTROL_CONF_MMC0_DAT0_CONF_MMC0_DAT0_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_MMC0_CLK) =
    			                   (0 << CONTROL_CONF_MMC0_CLK_CONF_MMC0_CLK_MMODE_SHIFT)    |
    			                   (0 << CONTROL_CONF_MMC0_CLK_CONF_MMC0_CLK_PUDEN_SHIFT)    |
    			                   (1 << CONTROL_CONF_MMC0_CLK_CONF_MMC0_CLK_PUTYPESEL_SHIFT)|
    			                   (1 << CONTROL_CONF_MMC0_CLK_CONF_MMC0_CLK_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_MMC0_CMD) =
    			                   (0 << CONTROL_CONF_MMC0_CMD_CONF_MMC0_CMD_MMODE_SHIFT)    |
    			                   (0 << CONTROL_CONF_MMC0_CMD_CONF_MMC0_CMD_PUDEN_SHIFT)    |
    			                   (1 << CONTROL_CONF_MMC0_CMD_CONF_MMC0_CMD_PUTYPESEL_SHIFT)|
    			                   (1 << CONTROL_CONF_MMC0_CMD_CONF_MMC0_CMD_RXACTIVE_SHIFT);
    
    			     HWREG(SOC_CONTROL_REGS + CONTROL_CONF_SPI0_CS1) =
    			                   (5 << CONTROL_CONF_SPI0_CS1_CONF_SPI0_CS1_MMODE_SHIFT)    |
    			                   (0 << CONTROL_CONF_SPI0_CS1_CONF_SPI0_CS1_PUDEN_SHIFT)    |
    			                   (1 << CONTROL_CONF_SPI0_CS1_CONF_SPI0_CS1_PUTYPESEL_SHIFT)|
    			                   (1 << CONTROL_CONF_SPI0_CS1_CONF_SPI0_CS1_RXACTIVE_SHIFT);
    
    				break;
    			}
    
    			case MMCD1:
    			{
    				m_baseAddr = SOC_MMCHS_1_REGS;
    
    				//	Configure Clocks
    			    HWREG(SOC_PRCM_REGS + CM_PER_MMC1_CLKCTRL) |= CM_PER_MMC1_CLKCTRL_MODULEMODE_ENABLE;
    
    			    while((HWREG(SOC_PRCM_REGS + CM_PER_MMC1_CLKCTRL) & CM_PER_MMC1_CLKCTRL_MODULEMODE) != CM_PER_MMC1_CLKCTRL_MODULEMODE_ENABLE);
    
    			    //	PinMux
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_AD(7)) =
    			               (1 << CONTROL_CONF_GPMC_AD7_CONF_GPMC_AD7_MMODE_SHIFT)    |
    			               (0 << CONTROL_CONF_GPMC_AD7_CONF_GPMC_AD7_PUDEN_SHIFT)    |
    			               (1 << CONTROL_CONF_GPMC_AD7_CONF_GPMC_AD7_PUTYPESEL_SHIFT)|
    			               (1 << CONTROL_CONF_GPMC_AD7_CONF_GPMC_AD7_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_AD(6)) =
    		                   (1 << CONTROL_CONF_GPMC_AD6_CONF_GPMC_AD6_MMODE_SHIFT)    |
    		                   (0 << CONTROL_CONF_GPMC_AD6_CONF_GPMC_AD6_PUDEN_SHIFT)    |
    		                   (1 << CONTROL_CONF_GPMC_AD6_CONF_GPMC_AD6_PUTYPESEL_SHIFT)|
    		                   (1 << CONTROL_CONF_GPMC_AD6_CONF_GPMC_AD6_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_AD(5)) =
    		                   (1 << CONTROL_CONF_GPMC_AD5_CONF_GPMC_AD5_MMODE_SHIFT)    |
    		                   (0 << CONTROL_CONF_GPMC_AD5_CONF_GPMC_AD5_PUDEN_SHIFT)    |
    		                   (1 << CONTROL_CONF_GPMC_AD5_CONF_GPMC_AD5_PUTYPESEL_SHIFT)|
    		                   (1 << CONTROL_CONF_GPMC_AD5_CONF_GPMC_AD5_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_AD(4)) =
    		                   (1 << CONTROL_CONF_GPMC_AD4_CONF_GPMC_AD4_MMODE_SHIFT)    |
    		                   (0 << CONTROL_CONF_GPMC_AD4_CONF_GPMC_AD4_PUDEN_SHIFT)    |
    		                   (1 << CONTROL_CONF_GPMC_AD4_CONF_GPMC_AD4_PUTYPESEL_SHIFT)|
    		                   (1 << CONTROL_CONF_GPMC_AD4_CONF_GPMC_AD4_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_AD(3)) =
    		                   (1 << CONTROL_CONF_GPMC_AD3_CONF_GPMC_AD3_MMODE_SHIFT)    |
    		                   (0 << CONTROL_CONF_GPMC_AD3_CONF_GPMC_AD3_PUDEN_SHIFT)    |
    		                   (1 << CONTROL_CONF_GPMC_AD3_CONF_GPMC_AD3_PUTYPESEL_SHIFT)|
    		                   (1 << CONTROL_CONF_GPMC_AD3_CONF_GPMC_AD3_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_AD(2)) =
    		                   (1 << CONTROL_CONF_GPMC_AD2_CONF_GPMC_AD2_MMODE_SHIFT)    |
    		                   (0 << CONTROL_CONF_GPMC_AD2_CONF_GPMC_AD2_PUDEN_SHIFT)    |
    		                   (1 << CONTROL_CONF_GPMC_AD2_CONF_GPMC_AD2_PUTYPESEL_SHIFT)|
    		                   (1 << CONTROL_CONF_GPMC_AD2_CONF_GPMC_AD2_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_AD(1)) =
    		                   (1 << CONTROL_CONF_GPMC_AD1_CONF_GPMC_AD1_MMODE_SHIFT)    |
    		                   (0 << CONTROL_CONF_GPMC_AD1_CONF_GPMC_AD1_PUDEN_SHIFT)    |
    		                   (1 << CONTROL_CONF_GPMC_AD1_CONF_GPMC_AD1_PUTYPESEL_SHIFT)|
    		                   (1 << CONTROL_CONF_GPMC_AD1_CONF_GPMC_AD1_RXACTIVE_SHIFT);
    
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_AD(0)) =
    		                   (1 << CONTROL_CONF_GPMC_AD0_CONF_GPMC_AD0_MMODE_SHIFT)    |
    		                   (0 << CONTROL_CONF_GPMC_AD0_CONF_GPMC_AD0_PUDEN_SHIFT)    |
    		                   (1 << CONTROL_CONF_GPMC_AD0_CONF_GPMC_AD0_PUTYPESEL_SHIFT)|
    		                   (1 << CONTROL_CONF_GPMC_AD0_CONF_GPMC_AD0_RXACTIVE_SHIFT);
    
    			    //	MMC1_CLK is on pin GPIO1_30
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_CSN(1)) =
    			    			(2 << CONTROL_CONF_GPMC_CSN1_CONF_GPMC_CSN1_MMODE_SHIFT)    |
    			                (0 << CONTROL_CONF_GPMC_CSN1_CONF_GPMC_CSN1_PUDEN_SHIFT)    |
    			                (1 << CONTROL_CONF_GPMC_CSN1_CONF_GPMC_CSN1_PUTYPESEL_SHIFT)|
    			                (1 << CONTROL_CONF_GPMC_CSN1_CONF_GPMC_CSN1_RXACTIVE_SHIFT);
    
    			    //	MMC1_CMD id on pin GPIO1_31
    			    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_CSN(2)) =
    			                (2 << CONTROL_CONF_GPMC_CSN2_CONF_GPMC_CSN2_MMODE_SHIFT)    |
    			                (0 << CONTROL_CONF_GPMC_CSN2_CONF_GPMC_CSN2_PUDEN_SHIFT)    |
    			                (1 << CONTROL_CONF_GPMC_CSN2_CONF_GPMC_CSN2_PUTYPESEL_SHIFT)|
    			                (1 << CONTROL_CONF_GPMC_CSN2_CONF_GPMC_CSN2_RXACTIVE_SHIFT);
    /*
    			    //	MMC1 RSTn is on pin GPIO1_20
    			     HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_A(4)) =
    			                (7 << CONTROL_CONF_GPMC_A4_CONF_GPMC_A4_MMODE)    |
    			                (0 << CONTROL_CONF_GPMC_A4_CONF_GPMC_A4_PUDEN_SHIFT)    |
    			                (1 << CONTROL_CONF_GPMC_A4_CONF_GPMC_A4_PUTYPESEL_SHIFT)|
    			                (1 << CONTROL_CONF_GPMC_A4_CONF_GPMC_A4_RXACTIVE_SHIFT);
    */
    				break;
    			}
    		}
    	}
    
    	MMCD::~MMCD()
    	{
    		// TODO Auto-generated destructor stub
    	}
    
    	MMCD* MMCD::sm_pInstances[MAXMMCDInstances];
    
    } /* namespace BPg */
    

  • Before inventing the wheel again: why don't you use the community version of StarterWare from http://sourceforge.net/projects/starterwarefree/ 

  • Hi Paul,

    BBB eMMC support is planned for an upcoming ProcessorSDK release.
    Also, note that you may want to base your development on ProcessorSDK RTOS for AM335x which was just released.
    This release has a starterware package which has updates (pdk_am335x_1_0_0\packages\ti). You would need the latest CCS 6.1.1 to work with this package.

    Lali

  • Lalindra Jayatilleke said:
    ProcessorSDK for AM335x which was just released

    Where can one find this SDK? The only thing I have seen is a ProcessorSDK for Linux - which has absolutely nothing to do with StarterWare.

     

  • qxc said:
    Where can one find this SDK?

    +1

  • Hi Paul,

    you can get it out of GIT from sourceforge.net/.../ , internal structure is the same like the one known from TI's package

    qxc
  • My apologies. I had put the link in my previous post, but didn't get included. Here it is.

     

    Lali

  • Hi Paul. I revamped the mmc driver demo to work in gcc. I can't see how to upload it to this forum, so get it at www.baremetal.tech
    I should have the interrupt version ready in a month. later............dd

    ps your site is cool, i can't login. we have alot in common. go to my site and message me.

    4617.bbbMMCdemo.zip

  • Lalindra: does this include working eMMC drivers for BBB?
  • qxc,

    Please see my post above. It's planned for an upcoming release of AM335x Processor SDK RTOS.

    Lali
  • Thanks Lali,

    Starterware is a bit better documented, but by the looks of it is still in development. The platform layer(where all the boards are defined) add a lot of confusion, this is not even considering the SDK.

    I got it all to compile under Crossworks(GCC), but I quit after seeing example demo app pulled into the pll configuraion of the bootloader code. The bootloader code is not an example, and clearly there was a good amount of laziness.

    I love the Sitara chip, but the hardware libraries have much to improve, and this SDK just convolutes it even more.

    Question for the community: What is the best choice for Sitara in regards to a clean and working device lib source? Surely some out there must be using the Sitara in a bare metal RTOS environment.
  • Try StarterWareFree ( https://sourceforge.net/projects/starterwarefree ), it contains a lot of bugfixes and support for eMMC and PRU - things the original from TI never has seen.

  • Javier Fernandez1 said:

    Question for the community: What is the best choice for Sitara in regards to a clean and working device lib source? Surely some out there must be using the Sitara in a bare metal RTOS environment.

    There is no such thing here.  But, you can take what they have and do a total rewrite.  I am doing this.

     I am giving away everything I have done thus far.  So you will have a big jump on the learning curve. 

    The old CCS version is here.  The GCC version is at github.com/ddlawrence and www.baremetal.tech

    I chose not to have an RTOS.  Your main program is the OS.  You have full unrestricted access to the h/w. 

    And the tools used are minimal.  It is not as hard as one would think.   This includes an MMC driver. 

    later.................dd

  • Yep. You are correct DD, there is no such thing.

    Starterware(TI and free) doesn't work, as in the sd card won't mount and the emmc won't work period, and the new SDK may work, but is awful, like in no one in their right mind will use it in a real product, it seems like a lab experiment. It is really shameful that TI can't get this right.

    I will give the baremetal another go, if it works, I'll go with it.

    Thanks.

  • > like in no one in their right mind will use it in a real product, it seems like a lab experiment

    The support from TI is lousy, but this is definitely not true. Our product is working and selling smoothly for more than a year meanwhile.