Implementation of main SDMMC interface

Issue #196 new
Patryk Kubiak created an issue

General Description

The goal of the task is to implement SDMMC driver interface functions. All functions has to have doxygen description and have to be implemented in file oc_sdmmc.c. Prototypes of the functions should be defined in oc_sdmmc.h The interface have to use SDMMC Mode module to access a card. The interface module has to also prepare configuration and choose the correct mode.

Trello link: https://trello.com/c/3bgsEpAI

Related tasks

  • [ #191 ] - Implementation of SDMMC driver - General SDMMC architecture
  • [ #195] - Implementation of SDMMC Mode

Configuration structure

//==========================================================================================================================================
/**
 * @brief stores mode of the driver
 *
 * The type is for storing working mode of the driver. The driver architecture allows for communication with the card by using few different
 * protocols and target resources. This type allows to choose the used mode.
 */
//==========================================================================================================================================
typedef enum
{
    oC_SDMMC_Mode_Auto ,          //!< If the `Auto` mode is set, the driver will try to configure and use first mode, that will support the given configuration
    oC_SDMMC_Mode_LLD ,           //!< The driver in the `LLD` mode, uses an embedded target machine module responsible for handling SD/MMC cards. Usually it is the fastest way to communicate with the card
    oC_SDMMC_Mode_SPI ,           //!< The driver in this mode, uses `SPI` driver to communicate with the card. It is usually slower than `LLD` but it allows to use the card also with the targets that does not support embedded SDMMC module
    oC_SDMMC_Mode_SW_1Bit ,       //!< The `SW1BIT` mode is the slowest of modes. The driver in this mode handles a card with the software emulation of the 1BIT interface that uses only GPIO driver.

    oC_SDMMC_Mode_NumberOfElements  //!< This definition represents number of defined modes. In fact, there is also a mode 'Auto' that is not real mode, but the `Auto` mode has to be 0 and taking care about the real number of elements would be to much complicated. It is just easier to define it in this way
} oC_SDMMC_Mode_t;

//==========================================================================================================================================
/**
 * @brief stores transmission protocol
 *
 * The type is for storing transfer mode (transmission protocol). It is for choosing a way the driver should communicate with the card. Each
 * of the modes needs different number of pins. Required pins for the mode you can check in the SD/MMC specification.
 */
//==========================================================================================================================================
typedef enum
{
    oC_SDMMC_TransferMode_Auto ,          //!< If the `Auto` mode is set, the driver tries to configure the transmission in the fastest possible protocol.
    oC_SDMMC_TransferMode_1Bit ,          //!< The mode uses only 1 bit of data
    oC_SDMMC_TransferMode_4Bit ,          //!< The mode uses 4 bits of data
    oC_SDMMC_TransferMode_8Bit ,          //!< The mode uses 8 bits of data (MMCPlus only)
    oC_SDMMC_TransferMode_SPI ,           //!< The mode uses `SPI` driver to communicate (#oC_SDMMC_Mode_t should be set to #oC_SDMMC_Mode_Auto or #oC_SDMMC_Mode_SPI)

    oC_SDMMC_TransferMode_NumberOfElements//!< This definition represents number of defined modes. In fact, there is also a mode 'Auto' that is not real mode, but the `Auto` mode has to be 0 and taking care about the real number of elements would be to much complicated. It is just easier to define it in this way
} oC_SDMMC_TransferMode_t;

//==========================================================================================================================================
/**
 * @brief stores type of detected card
 *
 * The type is for storing type of the card. The card type is detected during initialization and can be read by the function #oC_SDMMC_ReadCardType.
 */
//==========================================================================================================================================
typedef enum
{
    oC_SDMMC_CardType_Unknown ,         //!< Unknown card type
    oC_SDMMC_CardType_SDC ,             //!< Secure Digital Card
    oC_SDMMC_CardType_MMC ,             //!< MultiMedia Card
    oC_SDMMC_CardType_MMCPlus ,         //!< MultiMedia Card Plus

    oC_SDMMC_CardType_NumberOfElements ,//!< Number of card types
} oC_SDMMC_CardType_t;

//==========================================================================================================================================
/**
 * @brief stores index in the pins array
 *
 * The type is for storing index of the pin inside the #oC_SDMMC_Pins_t array.
 */
//==========================================================================================================================================
typedef enum
{
    oC_SDMMC_PinIndex_P1 = 0 ,                                  //!< Pin number 1
    oC_SDMMC_PinIndex_P2  ,                                     //!< Pin number 2
    oC_SDMMC_PinIndex_P3  ,                                     //!< Pin number 3
    oC_SDMMC_PinIndex_P4  ,                                     //!< Pin number 4
    oC_SDMMC_PinIndex_P5  ,                                     //!< Pin number 5
    oC_SDMMC_PinIndex_P6  ,                                     //!< Pin number 6
    oC_SDMMC_PinIndex_P7  ,                                     //!< Pin number 7
    oC_SDMMC_PinIndex_P8  ,                                     //!< Pin number 8
    oC_SDMMC_PinIndex_P9  ,                                     //!< Pin number 9
    oC_SDMMC_PinIndex_P10 ,                                     //!< Pin number 10
    oC_SDMMC_PinIndex_P11 ,                                     //!< Pin number 11
    oC_SDMMC_PinIndex_P12 ,                                     //!< Pin number 12
    oC_SDMMC_PinIndex_P13 ,                                     //!< Pin number 13
    oC_SDMMC_PinIndex_NumberOfPins ,                            //!< Maximum number of pins in the #oC_SDMMC_Pins_t array

    /* SPI Mode pins */
    oC_SDMMC_PinIndex_SpiMode_nCS       = oC_SDMMC_PinIndex_P1 ,//!< Index of the pin nCS  in SPI transfer mode
    oC_SDMMC_PinIndex_SpiMode_DI        = oC_SDMMC_PinIndex_P2 ,//!< Index of the pin DI   in SPI transfer mode
    oC_SDMMC_PinIndex_SpiMode_MOSI      = oC_SDMMC_PinIndex_P2 ,//!< Index of the pin MOSI in SPI transfer mode
    oC_SDMMC_PinIndex_SpiMode_CLK       = oC_SDMMC_PinIndex_P5 ,//!< Index of the pin CLK  in SPI transfer mode
    oC_SDMMC_PinIndex_SpiMode_DO        = oC_SDMMC_PinIndex_P7 ,//!< Index of the pin DO   in SPI transfer mode
    oC_SDMMC_PinIndex_SpiMode_MISO      = oC_SDMMC_PinIndex_P7 ,//!< Index of the pin MISO in SPI transfer mode
    oC_SDMMC_PinIndex_SpiMode_nIRQ      = oC_SDMMC_PinIndex_P8 ,//!< Index of the pin nIRQ in SPI transfer mode

    /* One-Bit Mode */
    oC_SDMMC_PinIndex_1BitMode_CD     = oC_SDMMC_PinIndex_P1 ,  //!< Index of the pin CD   in 1-Bit transfer mode
    oC_SDMMC_PinIndex_1BitMode_CMD    = oC_SDMMC_PinIndex_P2 ,  //!< Index of the pin CMD  in 1-Bit transfer mode
    oC_SDMMC_PinIndex_1BitMode_CLK    = oC_SDMMC_PinIndex_P5 ,  //!< Index of the pin CLK  in 1-Bit transfer mode
    oC_SDMMC_PinIndex_1BitMode_DAT0   = oC_SDMMC_PinIndex_P7 ,  //!< Index of the pin DAT0 in 1-Bit transfer mode
    oC_SDMMC_PinIndex_1BitMode_nIRQ   = oC_SDMMC_PinIndex_P8 ,  //!< Index of the pin nIRQ in 1-Bit transfer mode

    /* Four-Bit Mode */
    oC_SDMMC_PinIndex_4BitMode_DAT3  = oC_SDMMC_PinIndex_P1 ,   //!< Index of the pin DAT3 in 4-Bits transfer mode
    oC_SDMMC_PinIndex_4BitMode_CMD   = oC_SDMMC_PinIndex_P2 ,   //!< Index of the pin CMD  in 4-Bits transfer mode
    oC_SDMMC_PinIndex_4BitMode_CLK   = oC_SDMMC_PinIndex_P5 ,   //!< Index of the pin CLK  in 4-Bits transfer mode
    oC_SDMMC_PinIndex_4BitMode_DAT0  = oC_SDMMC_PinIndex_P7 ,   //!< Index of the pin DAT0 in 4-Bits transfer mode
    oC_SDMMC_PinIndex_4BitMode_nIRQ  = oC_SDMMC_PinIndex_P8 ,   //!< Index of the pin nIRQ in 4-Bits transfer mode
    oC_SDMMC_PinIndex_4BitMode_DAT1  = oC_SDMMC_PinIndex_P8 ,   //!< Index of the pin DAT1 in 4-Bits transfer mode
    oC_SDMMC_PinIndex_4BitMode_DAT2  = oC_SDMMC_PinIndex_P9 ,   //!< Index of the pin DAT2 in 4-Bits transfer mode

    /* 8-Bit Mode */
    oC_SDMMC_PinIndex_8BitMode_DAT3  = oC_SDMMC_PinIndex_P1 ,   //!< Index of the pin DAT3 in 8-Bits transfer mode
    oC_SDMMC_PinIndex_8BitMode_CMD   = oC_SDMMC_PinIndex_P2 ,   //!< Index of the pin CMD  in 8-Bits transfer mode
    oC_SDMMC_PinIndex_8BitMode_CLK   = oC_SDMMC_PinIndex_P5 ,   //!< Index of the pin CLK  in 8-Bits transfer mode
    oC_SDMMC_PinIndex_8BitMode_DAT0  = oC_SDMMC_PinIndex_P7 ,   //!< Index of the pin DAT0 in 8-Bits transfer mode
    oC_SDMMC_PinIndex_8BitMode_DAT1  = oC_SDMMC_PinIndex_P8 ,   //!< Index of the pin DAT1 in 8-Bits transfer mode
    oC_SDMMC_PinIndex_8BitMode_DAT2  = oC_SDMMC_PinIndex_P9 ,   //!< Index of the pin DAT2 in 8-Bits transfer mode
    oC_SDMMC_PinIndex_8BitMode_DAT4  = oC_SDMMC_PinIndex_P10 ,  //!< Index of the pin DAT4 in 8-Bits transfer mode
    oC_SDMMC_PinIndex_8BitMode_DAT5  = oC_SDMMC_PinIndex_P11 ,  //!< Index of the pin DAT5 in 8-Bits transfer mode
    oC_SDMMC_PinIndex_8BitMode_DAT6  = oC_SDMMC_PinIndex_P12 ,  //!< Index of the pin DAT6 in 8-Bits transfer mode
    oC_SDMMC_PinIndex_8BitMode_DAT7  = oC_SDMMC_PinIndex_P13 ,  //!< Index of the pin DAT7 in 8-Bits transfer mode
} oC_SDMMC_PinIndex_t;

//==========================================================================================================================================
/**
 * @brief array with `SDMMC` pins
 *
 * The type is for storing pins of the `SDMMC` driver. Index of the pin can be identified with the type #oC_SDMMC_PinIndex_t
 */
//==========================================================================================================================================
typedef oC_Pin_t oC_SDMMC_Pins_t[oC_SDMMC_PinIndex_NumberOfPins];

//==========================================================================================================================================
/**
 * @brief SDMMC driver configuration structure
 *
 * This is the configuration structure for the SDMMC driver. You should fill all fields or set to 0 all that are not required.
 * To use this structure call the #oC_SDMMC_Configure function
 *
 * @note When the structure is defined as constant, the unused fields must not be filled, cause there will be set to 0 as default.
 */
//==========================================================================================================================================
typedef struct
{
    oC_SDMMC_Mode_t                 Mode;           /**!< Mode of the driver - leave it as `Auto` if you don't know which mode you should use */
    oC_SDMMC_TransferMode_t         TransferMode;   /**!< Mode of the transfer - transmission protocol */
    oC_SDMMC_Pins_t                 Pins;           /**!< Array with pins for the card. You don't have to fill all pins, not connected pins you can set to `oC_Pin_NotUsed` */
    oC_MemorySize_t                 SectorSize;     /**!< Size of the block / sector. It should be power of 2 */

    struct
    {
        oC_SPI_Context_t            SpiContext;    /**!< Keep it #NULL also in SPI mode, if the SPI should be configured automatically */
    } Advanced;
} oC_SDMMC_Config_t;

Driver interface

// Turns on the driver
extern oC_ErrorCode_t oC_SDMMC_TurnOn               ( void );
// Turns off the driver
extern oC_ErrorCode_t oC_SDMMC_TurnOff              ( void );
// Returns true if the driver is turned on
extern bool           oC_SDMMC_IsTurnedOn           ( void );
// Configures the SDMMC driver to work with the card
extern oC_ErrorCode_t oC_SDMMC_Configure            ( const oC_SDMMC_Config_t * Config , oC_SDMMC_Context_t * outContext );
// Unconfigures the SDMMC driver 
extern oC_ErrorCode_t oC_SDMMC_Unconfigure          ( const oC_SDMMC_Config_t * Config , oC_SDMMC_Context_t * outContext );
// Waits for the card detection
extern oC_ErrorCode_t oC_SDMMC_WaitForNewDisk       ( oC_SDMMC_Context_t Context , oC_DiskId_t * outDiskId, oC_Time_t Timeout );
// Returns size of the sector
extern oC_ErrorCode_t oC_SDMMC_ReadSectorSize       ( oC_SDMMC_Context_t Context , oC_DiskId_t DiskId , oC_MemorySize_t * outSectorSize , oC_Time_t Timeout );
// Returns number of sectors
extern oC_ErrorCode_t oC_SDMMC_ReadNumberOfSectors  ( oC_SDMMC_Context_t Context , oC_DiskId_t DiskId , oC_SectorNumber_t * outSectorNumber , oC_Time_t Timeout );
// Reads data to card sectors
extern oC_ErrorCode_t oC_SDMMC_ReadSectors          ( oC_SDMMC_Context_t Context , oC_DiskId_t DiskId , oC_SectorNumber_t StartSector, void *    outBuffer , oC_MemorySize_t Size , oC_Time_t Timeout );
// Writes data to card sectors
extern oC_ErrorCode_t oC_SDMMC_WriteSectors         ( oC_SDMMC_Context_t Context , oC_DiskId_t DiskId , oC_SectorNumber_t StartSector, const void * Buffer , oC_MemorySize_t Size , oC_Time_t Timeout );
// Erases card sectors
extern oC_ErrorCode_t oC_SDMMC_EraseSectors         ( oC_SDMMC_Context_t Context , oC_DiskId_t DiskId , oC_SectorNumber_t StartSector, oC_MemorySize_t Size, oC_Time_t Timeout );
// Waits until the card is not ejected
extern oC_ErrorCode_t oC_SDMMC_WaitForDiskEject     ( oC_SDMMC_Context_t Context , oC_DiskId_t * outDiskId, oC_Time_t Timeout );
// Performs special IOCTL command in the driver
extern oC_ErrorCode_t oC_SDMMC_Ioctl                ( oC_SDMMC_Context_t Context , oC_Ioctl_Command_t Command , void * Data );
// Reads type of a detected card
extern oC_ErrorCode_t oC_SDMMC_ReadCardType         ( oC_SDMMC_Context_t Context , oC_SDMMC_CardType_t * outCardType );
// Reads configured driver mode
extern oC_ErrorCode_t oC_SDMMC_ReadMode             ( oC_SDMMC_Context_t Context , oC_SDMMC_TransferMode_t * outMode , const char ** outName );

Comments (4)

  1. Log in to comment