SD Controller PSL Implementation

Describes how to implement the Platform-Specific Layer (PSL) of the SD controller.

The SD controller derives from the MMC controller. Most of the porting procedure is similar between the two controllers, with the addition of SD-specific functions and behaviours.

Prerequisites

Porting the SD controller for your platform requires to be familiar with the following material:

Source code

The source code organization for the MMC controller is described here.

The Platform-Independent Layer (PIL) of the SD controller can be found here: ..\eka\drivers\pbus\sdcard\sdcard3c\

The suggested location for the main source file of the PSL is ..\<VARIANT>\specific\sdcard3c\sdstack.cpp

Implementations

The core class of the PSL must derive from DSDStack instead of DMMCStack (see the SD class diagram). In addition to the DMMCStack methods described in the MMC's Platform Specific Layer Implementation, there is an additional SD-specific abstract virtual method to implement, and several other features to support.

The following functions require SD-specific porting effort:

For all the other classes (DMMCPsu, DMMCMediaChange, TMMCardControllerInterface), see the corresponding sections of the MMC's Platform Specific Layer Implementation: DMMCPsu, DMMCMediaChange, TMMCardControllerInterface.

AddressCard()

The SD card protocol uses a star topology. In a multi-card stack, it is possible to select each card socket independently via the hardware interface, or to broadcast to all the SD cards. The MultiMediaCard protocol relies on a bus topology, which corresponds to the broadcast mode.

The DSDStack::AddressCard() function configures the hardware to select the specified card socket for future commands. Alternatively, the KBroadcastToAllCards value selects the broadcast mode.

This function takes a TInt parameter containing the number of the specified card socket. This parameter must be between 0 and one less than the maximum number of card sockets supported, or KBroadcastToAllCards.

MachineInfo()

See DMMCStack::MachineInfo(). This function returns configuration information for the SD stack.

By default, the platform-independent layer configures the response type for CMD8 as R1. However, if you implement a controller for SD 2.00 cards, you should set the ESupportsR7 flag in the iFlags variable so the stack sets the CMD8 response type as R7.

InitClockOnSM()

See DMMCStack::InitClockOnSM(). The function turns on the clock to the hardware interface. This clock is always turned on at the Card Identification Mode frequency, and switched to the Data Transfer Mode later by the InitClockOff() function.

The SD 2.0 Specification states that when in Card Identification Mode, the bus clock frequency must be between 100KHz and 400KHz. This function should enforce this frequency range.

This function also sets the Data Read Timeout value. The SD 2.00 Specification states this value as 100ms.

InitClockOff()

See DMMCStack::InitClockOff(). The function switches from Card Identification Mode to Data Transfer Mode.

Note that for SD cards supporting it, this function should also switch to high-speed mode with the CMD6 command.

This function should check that the clock rate for data transfer is below the maximum value. The SD Specifications define this maximum as 25MHz in revision 1.01 and 50MHz in revision 1.10. The maximum bus clock value for MultiMediaCards version 4.0+ is 52MHz.

AdjustPartialRead()

See DMMCStack::AdjustPartialRead().

If you want your PSL to support 2GB SD cards (compliant with the Specification v1.10), you should be aware that these cards' CSD register define the maximum block length(READ_BL_LEN) as 1024 bytes, but the block length set by the CMD16 command must be 512 bytes.

The TMMCCard::MaxReadBlLen() function returns the maximum block length as a logarithm: for example, it returns 9 for 2GB cards, as 2^9 = 512. You should use the MaxRedBlLen() function whenever the block length is needed. It is usually only appropriate in the AdjustPartialRead() function, but depending on your implementation you may want to check the rest of the platform-specific layer.

For SD cards complying with the SD Specification 2.00 (with a capacity of 4GB and more), the READ_BL_LEN field is always 512 bytes.

IssueMMCCommandSM()

See DMMCStack::IssueMMCCommandSM() and the Note on SD commands section.

The card type is identified by the response to the CMD55 command. If this command generates a timeout, then the card is a MultiMediaCard; otherwise, it is an SD card.

When receiving the response to a SET_BUS_WIDTH command (ACMD6), this function must update the configuration register by calling the DSDStack::SetBusWidth() function.

To comply with the SD 2.0 Specification, the IssueMMCCommandSM() function must not perform the following operations:

  • Modify the CMD55 command and its arguments

  • Modify the ACMD41 command and its arguments

  • Modify reserved bits of any command argument

Note on SD commands

Most SD commands and MMC commands are compatible. However, there are some significant differences: the table below lists some of the additional commands supported by SD cards, and one behaviour change.

Command

Abbreviation

Description

CMD3

SET_BUS_WIDTH

Requests a relative address from the SD card, instead of assigning the address to the card with this command (in the MMC case).

ACMD6

SET_BUS_WIDTH

Defines the width of the data transfer bus.

ACMD13

SD_STATUS

Requests the status of the addressed SD card.

ACMD22

SEND_NUM_WR_BLOCKS

Sends/Requests the number of blocks written without error.

ACMD41

SD_APP_OP_COND

Requests the operating conditions of the addressed SD card (equivalent to CMD1 in the MMC case).

ACMD51

SEND_SCR

Reads the SD configuration register (SCR).

The following example illustrates how to detect an ACMD6 command:

if ((cmd.iSpec.iCommandClass == KMMCCmdClassApplication) && (cmd.iCommand == ECmd6))
     {
         /* [...] */ 
     }