This repository has been archived on 2024-05-28. You can view files and clone it, but cannot push or open issues or pull requests.
2023-11-14 16:25:09 -05:00

401 lines
18 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by Guangzong Chen on 4/5/23.
//
#ifndef STM32U5XX_HAL_REG_SDMMC_H
#define STM32U5XX_HAL_REG_SDMMC_H
#include "global_variable.h"
#include "stm32u5xx.h"
////////////////////////////////////////////////////////////////////////////////
///////////////// sdmmc power control register (SDMCC_POWER) ///////////////////
typedef enum {
sdmmc_power_vswitchen_reset =
0x00U, ///< Reset: the voltage switch sequence is not started and not active.
sdmmc_power_vswitchen_start =
0x01U, ///< Start: the voltage switch sequence is started or active.
} reg_sdmmc_power_vswitchen;
typedef enum {
sdmmc_power_pwrctrl_reset = 0x00U,
sdmmc_power_pwrctrl_reserved = 0x01U,
sdmmc_power_pwrctrl_power_cycle = 0x02U,
sdmmc_power_pwrctrl_power_on = 0x03U,
} reg_sdmmc_power_pwrctrl; ///< SDMMC_POWER_PWRCTRL
typedef struct {
reg_sdmmc_power_pwrctrl pwrctrl : 2; ///< 1:0 Power supply control bits
reg_sdmmc_power_vswitchen vswitch : 1; ///< 2 Voltage switch sequence start
uint32_t vswitchen : 1; ///< 3 Voltage switch procedure enable
uint32_t dirpol : 1; ///< 4 Data and Command direction signals polarity selection
uint32_t reserved : 27; ///< 31:5 Reserved1
} reg_sdmmc_power_t;
//static inline reg_sdmmc_power_t sdmmc_reg_get_power(SDMMC_TypeDef *sdmmc) {
// reg_sdmmc_power_t ret;
// uint32_t tmp = sdmmc->POWER;
// ret.RESERVED = tmp >> 5;
// ret.DIRPOL = (tmp >> 4) & 0x1;
// ret.VSWITCH = static_cast<reg_sdmmc_power_vswitchen>((tmp >> 3) & 0x1);
// ret.PWRCTRL = static_cast<reg_sdmmc_power_pwrctrl>(tmp & 0x3);
// return ret;
//}
//static inline void sdmmc_reg_set_power(SDMMC_TypeDef *sdmmc, reg_sdmmc_power_t val) {
// uint32_t tmp = 0;
// tmp |= val.RESERVED << 5;
// tmp |= val.DIRPOL << 4;
// tmp |= val.VSWITCH << 3;
// tmp |= val.PWRCTRL;
// sdmmc->POWER = tmp;
//}
////////////////////////////////////////////////////////////////////////////////
///////// sdmmc clock control register (SDMMC_CLKCR) //////////////////////////
typedef enum {
REG_SDMMC_WIDBUS_1BIT = 0, ///< 1-bit wide bus mode: SDMMC_D0 used (Does not support DDR)
REG_SDMMC_WIDBUS_4BIT = 1, ///< 4-bit wide bus mode: SDMMC_D[3:0] used
REG_SDMMC_WIDBUS_8BIT = 2, ///< 8-bit wide bus mode: SDMMC_D[7:0] used
} reg_sdmmc_clkcr_widbus;
// reverse the bit order of the enum reg_sdmmc_clkcr_t
typedef struct {
uint32_t
clkdiv : 10; ///< 9:0 Clock divide factor (SDMMC_CK frequency = SDMMCCLK / [2 × CLKDIV])
uint32_t reserved2 : 2; ///< 11:10 Reserved
uint32_t pwr_sav : 1; ///< 12 Power saving configuration bit
uint32_t reserved1 : 1; ///< 13 Reserved
reg_sdmmc_clkcr_widbus widbus : 2; ///< 15:14 Wide bus mode enable bit
uint32_t negedge : 1; ///< 16 SDMMC_CK dephasing selection bit for data and command
uint32_t hwfc_en : 1; ///< 17 Hardware Flow Control enable
uint32_t ddr : 1; ///< 18 Data rate signaling selection
uint32_t busspeed : 1; ///< 19 Bus speed mode selection of SDMMC operating modes
uint32_t selclkrx : 2; ///< 21:20 Receive clock selection
uint32_t reserved : 10; ///< 31:22 Reserved
} reg_sdmmc_clkcr_t;
static inline reg_sdmmc_clkcr_t sdmmc_reg_get_clkcr(SDMMC_TypeDef *sdmmc) {
reg_sdmmc_clkcr_t ret;
uint32_t tmp = sdmmc->CLKCR;
ret.reserved = (tmp >> 22) & 0x3FF;
ret.selclkrx = (tmp >> 21) & 0x1;
ret.busspeed = (tmp >> 19) & 0x1;
ret.ddr = (tmp >> 18) & 0x1;
ret.hwfc_en = (tmp >> 17) & 0x1;
ret.negedge = (tmp >> 16) & 0x1;
ret.widbus = static_cast<reg_sdmmc_clkcr_widbus>((tmp >> 14) & 0x3);
ret.reserved1 = (tmp >> 13) & 0x1;
ret.pwr_sav = (tmp >> 12) & 0x1;
ret.reserved2 = (tmp >> 10) & 0x3;
ret.clkdiv = tmp & 0x3FF;
return ret;
}
static inline void sdmmc_reg_set_clkcr(SDMMC_TypeDef *sdmmc, reg_sdmmc_clkcr_t val) {
uint32_t tmp = 0;
tmp |= val.reserved << 22;
tmp |= val.selclkrx << 21;
tmp |= val.busspeed << 19;
tmp |= val.ddr << 18;
tmp |= val.hwfc_en << 17;
tmp |= val.negedge << 16;
tmp |= val.widbus << 14;
tmp |= val.reserved1 << 13;
tmp |= val.pwr_sav << 12;
tmp |= val.reserved2 << 10;
tmp |= val.clkdiv;
sdmmc->CLKCR = tmp;
}
//////////////////////////////////////////////////// CMD register ///////////////
typedef enum {
REG_SDMMC_CMD_WAITRESP_NO = 0, ///< No response
REG_SDMMC_CMD_WAITRESP_SHORT_CRC = 1, ///< Short response
REG_SDMMC_CMD_WAITRESP_SHORT_NOCRC = 2, ///< Short response, no CRC check
REG_SDMMC_CMD_WAITRESP_LONG = 3, ///< Long response
} REG_SDMMC_CMD_WAITRESP;
typedef struct {
uint32_t cmdindex : 6; ///< 5:0 Command index.
uint32_t cmdtrans : 1; ///< 6 CPSM treats the command as a data transfer command, stops the
///< interrupt period, and signals DataEnable to the DPSM.
uint32_t cmdstop : 1; ///< 7 CPSM treats the command as a Stop Transmission command and signals
///< Abort to the DPSM.
REG_SDMMC_CMD_WAITRESP waitresp : 2; ///< 9:8 Wait for response bits. 0 no response, 1 short
///< response, 2 short response(NON CRC), 3 long response
uint32_t waitint : 1; ///< 10 CPSM waits for interrupt request.
uint32_t waitpend : 1; ///< 11 CPSM Waits for ends of data transfer (CmdPend internal signal).
uint32_t cpsmen : 1; ///< 12 Command path state machine (CPSM) Enable bit.
uint32_t dthold : 1; ///< 13 Hold the data block transmission/reception in the DPSM.
uint32_t bootmode : 1; ///< 14 Select the boot mode procedure to be used.
uint32_t booten : 1; ///< 15 enable boot mode procedure
uint32_t cmdsuspend : 1; ///< 16 The CPSM treats the command as a Suspend Command or Resume
///< Command and signals interrupt period start/end.
uint32_t reserved : 15; ///< 31-17 Reserved, must be kept at reset value.
} reg_sdmmc_cmd_t;
//static inline void sdmmc_reg_set_cmd(SDMMC_TypeDef *sdmmc, sdmmc_cmd_t value) {
// uint32_t ret =
// (value.cmdindex << SDMMC_CMD_CMDINDEX_Pos) | (value.cmdtrans << SDMMC_CMD_CMDTRANS_Pos) |
// (value.cmdstop << SDMMC_CMD_CMDSTOP_Pos) | (value.waitresp << SDMMC_CMD_WAITRESP_Pos) |
// (value.waitint << SDMMC_CMD_WAITINT_Pos) | (value.waitpend << SDMMC_CMD_WAITPEND_Pos) |
// (value.cpsmen << SDMMC_CMD_CPSMEN_Pos) | (value.dthold << SDMMC_CMD_DTHOLD_Pos) |
// (value.bootmode << SDMMC_CMD_BOOTMODE_Pos) | (value.booten << SDMMC_CMD_BOOTEN_Pos) |
// (value.cmdsuspend << SDMMC_CMD_CMDSUSPEND_Pos);
// sdmmc->CMD = ret;
//}
//
//static inline sdmmc_cmd_t sdmmc_reg_get_cmd(SDMMC_TypeDef *sdmmc) {
// uint32_t value = sdmmc->CMD;
// sdmmc_cmd_t ret = {0};
// ret.cmdindex = (value & SDMMC_CMD_CMDINDEX_Msk) >> SDMMC_CMD_CMDINDEX_Pos;
// ret.cmdtrans = (value & SDMMC_CMD_CMDTRANS_Msk) >> SDMMC_CMD_CMDTRANS_Pos;
// ret.cmdstop = (value & SDMMC_CMD_CMDSTOP_Msk) >> SDMMC_CMD_CMDSTOP_Pos;
// ret.waitresp = static_cast<REG_SDMMC_CMD_WAITRESP>((value & SDMMC_CMD_WAITRESP_Msk) >>
// SDMMC_CMD_WAITRESP_Pos);
// ret.waitint = (value & SDMMC_CMD_WAITINT_Msk) >> SDMMC_CMD_WAITINT_Pos;
// ret.waitpend = (value & SDMMC_CMD_WAITPEND_Msk) >> SDMMC_CMD_WAITPEND_Pos;
// ret.cpsmen = (value & SDMMC_CMD_CPSMEN_Msk) >> SDMMC_CMD_CPSMEN_Pos;
// ret.dthold = (value & SDMMC_CMD_DTHOLD_Msk) >> SDMMC_CMD_DTHOLD_Pos;
// ret.bootmode = (value & SDMMC_CMD_BOOTMODE_Msk) >> SDMMC_CMD_BOOTMODE_Pos;
// ret.booten = (value & SDMMC_CMD_BOOTEN_Msk) >> SDMMC_CMD_BOOTEN_Pos;
// ret.cmdsuspend = (value & SDMMC_CMD_CMDSUSPEND_Msk) >> SDMMC_CMD_CMDSUSPEND_Pos;
// return ret;
//}
//////////////////////////////////////////////////// END CMD register ///////////
//////////////////////////////////////////////////// Status register(STAR) ////////////
// reverse and lower case of reg_sdmmc_sta_t
typedef struct {
uint32_t ccrcfail : 1; ///< 0 Command response received (CRC check failed)
uint32_t dcrcfail : 1; ///< 1 Data block sent/received (CRC check failed)
uint32_t ctimeout : 1; ///< 2 Command response timeout
uint32_t dtimeout : 1; ///< 3 Data timeout
uint32_t
txunderr : 1; ///< 4 Transmit FIFO underrun error (masked by hardware when IDMA is enabled)
uint32_t
rxoverr : 1; ///< 5 Received FIFO overrun error (masked by hardware when IDMA is enabled)
uint32_t cmdrend : 1; ///< 6 Command response received (CRC check passed, or no CRC)
uint32_t cmdsent : 1; ///< 7 Command sent (no response required)
uint32_t dataend : 1; ///< 8 Data transfer ended correctly
uint32_t dhold : 1; ///< 9 Data transfer Hold
uint32_t dbckend : 1; ///< 10 Data block sent/received
uint32_t dabort : 1; ///< 11 Data transfer aborted by CMD12
uint32_t dpsmact : 1; ///< 12 Data path state machine active, i.e. not in Idle state /// Not
///< an interrupt
uint32_t cpsmact : 1; ///< 13 Command path state machine active, i.e. not in Idle state /// Not
///< an interrupt
uint32_t txfifohe : 1; ///< 14 Transmit FIFO half empty
uint32_t rxfifohf : 1; ///< 15 Receive FIFO half full
uint32_t txfifof : 1; ///< 16 Transmit FIFO full
uint32_t rxfifof : 1; ///< 17 Receive FIFO full
uint32_t txfifoe : 1; ///< 18 Transmit FIFO empty
uint32_t rxfifoe : 1; ///< 19 Receive FIFO empty
uint32_t busyd0 : 1; ///< 20 Inverted value of SDMMC_DO line (Busy) // Not an interrupt
uint32_t busydoend : 1; ///< 21 end of SDMMC_D0 Busy following a CMD response detected
uint32_t sdioit : 1; ///< 22 SDIO interrupt received
uint32_t ackfail : 1; ///< 23 Boot acknowledgment received (boot acknowledgment check fail)
uint32_t acktimeout : 1; ///< 24 Boot acknowledgment timeout
uint32_t vswend : 1; ///< 25 Voltage switch critical timing section completion
uint32_t ckstop : 1; ///< 26 SDMMC_CK stopped in Voltage switch procedure
uint32_t idmate : 1; ///< 27 IDMA transfer error
uint32_t idmabtc : 1; ///< 28 IDMA buffer transfer complete
uint32_t reserved : 3; ///< 29-31 Reserved
} reg_sdmmc_sta_t; ///< SDMMC status register read only bits
static inline reg_sdmmc_sta_t sdmmc_reg_get_sta(SDMMC_TypeDef *sdmmc) {
uint32_t value = sdmmc->STA;
reg_sdmmc_sta_t ret;
ret.reserved = (value >> 29) & 0x7;
ret.idmabtc = (value >> 28) & 0x1;
ret.idmate = (value >> 27) & 0x1;
ret.ckstop = (value >> 26) & 0x1;
ret.vswend = (value >> 25) & 0x1;
ret.acktimeout = (value >> 24) & 0x1;
ret.ackfail = (value >> 23) & 0x1;
ret.sdioit = (value >> 22) & 0x1;
ret.busydoend = (value >> 21) & 0x1;
ret.busyd0 = (value >> 20) & 0x1;
ret.rxfifoe = (value >> 19) & 0x1;
ret.txfifoe = (value >> 18) & 0x1;
ret.rxfifof = (value >> 17) & 0x1;
ret.txfifof = (value >> 16) & 0x1;
ret.rxfifohf = (value >> 15) & 0x1;
ret.txfifohe = (value >> 14) & 0x1;
ret.cpsmact = (value >> 13) & 0x1;
ret.dpsmact = (value >> 12) & 0x1;
ret.dabort = (value >> 11) & 0x1;
ret.dbckend = (value >> 10) & 0x1;
ret.dhold = (value >> 9) & 0x1;
ret.dataend = (value >> 8) & 0x1;
ret.cmdsent = (value >> 7) & 0x1;
ret.cmdrend = (value >> 6) & 0x1;
ret.rxoverr = (value >> 5) & 0x1;
ret.txunderr = (value >> 4) & 0x1;
ret.dtimeout = (value >> 3) & 0x1;
ret.ctimeout = (value >> 2) & 0x1;
ret.dcrcfail = (value >> 1) & 0x1;
ret.ccrcfail = (value >> 0) & 0x1;
return ret;
}
//////////////////////// Data control register ////////////////////////
// reverse and low case of reg_sdmmc_dctrl_t
typedef struct {
uint32_t data_en : 1; ///< 0 DTEN: Data transfer enabled bit
uint32_t data_dir : 1; ///< 1 DTDIR: Data transfer direction selection 0: From controller to
///< card 1: From card to controller
uint32_t data_mode : 2; ///< 3:2 DTMODE: Data transfer mode selection 0: Block data transfer 1:
///< Stream or SDIO multibyte data transfer
uint32_t data_blocksize : 4; ///< 7:4 DBLOCKSIZE[3:0]: Data block size
uint32_t rwstart : 1; ///< 8 RWSTART: Read Wait start
uint32_t rwstop : 1; ///< 9 RWSTOP: Read Wait stop
uint32_t rwmod : 1; ///< 10 RWMOD: Read Wait mode
uint32_t sdioen : 1; ///< 11 SDIOEN: SD I/O interrupt enable functions
uint32_t bootacken : 1; ///< 12 BOOTACKEN: Enable the reception of the boot acknowledgment
uint32_t fifo_reset : 1; ///< 13 FIFORST: FIFO reset, flushes any remaining data
uint32_t reserved : 18; ///< 31:14 Reserved, must be kept at reset value.
} reg_sdmmc_dctrl_t; ///< SDMMC data control register
// static inline uint32_t sdmmc_dctrl_to_uint32(sdmmc_dctrl_t value) {
static inline void sdmmc_reg_set_dctrl(SDMMC_TypeDef *sdmmc, reg_sdmmc_dctrl_t value) {
uint32_t ret =
(value.fifo_reset << SDMMC_DCTRL_FIFORST_Pos) |
(value.bootacken << SDMMC_DCTRL_BOOTACKEN_Pos) | (value.sdioen << SDMMC_DCTRL_SDIOEN_Pos) |
(value.rwmod << SDMMC_DCTRL_RWMOD_Pos) | (value.rwstop << SDMMC_DCTRL_RWSTOP_Pos) |
(value.rwstart << SDMMC_DCTRL_RWSTART_Pos) |
(value.data_blocksize << SDMMC_DCTRL_DBLOCKSIZE_Pos) |
(value.data_mode << SDMMC_DCTRL_DTMODE_Pos) | (value.data_dir << SDMMC_DCTRL_DTDIR_Pos) |
(value.data_en << SDMMC_DCTRL_DTEN_Pos);
sdmmc->DCTRL = ret;
}
static inline reg_sdmmc_dctrl_t sdmmc_reg_get_dctrl(SDMMC_TypeDef *sdmmc) {
uint32_t value = sdmmc->DCTRL;
reg_sdmmc_dctrl_t ret;
ret.fifo_reset = (value >> SDMMC_DCTRL_FIFORST_Pos) & SDMMC_DCTRL_FIFORST_Msk;
ret.bootacken = (value >> SDMMC_DCTRL_BOOTACKEN_Pos) & SDMMC_DCTRL_BOOTACKEN_Msk;
ret.sdioen = (value >> SDMMC_DCTRL_SDIOEN_Pos) & SDMMC_DCTRL_SDIOEN_Msk;
ret.rwmod = (value >> SDMMC_DCTRL_RWMOD_Pos) & SDMMC_DCTRL_RWMOD_Msk;
ret.rwstop = (value >> SDMMC_DCTRL_RWSTOP_Pos) & SDMMC_DCTRL_RWSTOP_Msk;
ret.rwstart = (value >> SDMMC_DCTRL_RWSTART_Pos) & SDMMC_DCTRL_RWSTART_Msk;
ret.data_blocksize = (value >> SDMMC_DCTRL_DBLOCKSIZE_Pos) & SDMMC_DCTRL_DBLOCKSIZE_Msk;
ret.data_mode = (value >> SDMMC_DCTRL_DTMODE_Pos) & SDMMC_DCTRL_DTMODE_Msk;
ret.data_dir = (value >> SDMMC_DCTRL_DTDIR_Pos) & SDMMC_DCTRL_DTDIR_Msk;
ret.data_en = (value >> SDMMC_DCTRL_DTEN_Pos) & SDMMC_DCTRL_DTEN_Msk;
return ret;
}
////////////////////// idma control register /////////////////////////
// reverse and low case of reg_sdmmc_idmactrl_t
typedef struct {
uint32_t idma_en : 1; ///< 0 IDMAEN: IDMA enable bit
uint32_t idma_buffer_mode : 1; ///< 1 IDMABMODE: IDMA buffer mode selection. 0: Single buffer
///< mode 1: Linked buffer mode
uint32_t reserved : 30; ///< 31:2 Reserved, must be kept at reset value.
} reg_sdmmc_idmactrl_t; ///< SDMMC IDMA control register
static inline void sdmmc_reg_set_idma(SDMMC_TypeDef *sdmmc, reg_sdmmc_idmactrl_t value) {
uint32_t ret = (value.idma_buffer_mode << SDMMC_IDMA_IDMABMODE_Pos) |
(value.idma_en << SDMMC_IDMA_IDMAEN_Pos);
sdmmc->IDMACTRL = ret;
}
static inline reg_sdmmc_idmactrl_t sdmmc_reg_get_idma(SDMMC_TypeDef *sdmmc) {
uint32_t value = sdmmc->IDMACTRL;
reg_sdmmc_idmactrl_t ret;
ret.idma_buffer_mode = (value >> SDMMC_IDMA_IDMABMODE_Pos) & SDMMC_IDMA_IDMABMODE_Msk;
ret.idma_en = (value >> SDMMC_IDMA_IDMAEN_Pos) & SDMMC_IDMA_IDMAEN_Msk;
return ret;
}
////////////////////// idma buffer size register /////////////////////////
// reverse and low case of reg_sdmmc_idmabsize_t
typedef struct {
uint32_t reserved : 5; ///< 4:0 Reserved, must be kept at reset value.
uint32_t size : 12; ///< 16:5 number of bytes per buffer // multiple by 8 get 32-bit words and
///< by 32 to get the size of bytes. 1 --> 32 bytes, 0x800 -->64Kbyte
uint32_t reserved2 : 20; ///< 31:17 Reserved, must be kept at reset value.
} reg_sdmmc_idmabsize_t; ///< SDMMC IDMA buffer size register
/// \brief Set the IDMA size
/// \param size number of bytes per buffer int byte
/// \todo the maximum value of parameter
/// \note this is used for dma when link list is used
static inline hal_status_e sdmmc_set_idma_buffer_size(SDMMC_TypeDef *sdmmc, uint32_t size) {
uint16_t tmp = size / 32;
sdmmc->IDMABSIZE = tmp << 5;
if (size % 32 != 0) { return SDMMC_ERROR; }
return HAL_OK;
}
////////////////////// idma butter base address register /////////////////////////
/// \brief Set the IDMA base address
/// \param address base address of the IDMA buffer (for the buffer)
/// \todo the maximum value of parameter
static inline hal_status_e sdmmc_reg_set_idma_base_address(SDMMC_TypeDef *sdmmc, uint32_t address) {
sdmmc->IDMABASER = address;
return HAL_OK;
}
////////////////////// idma linked list address register /////////////////////////
typedef struct {
uint32_t reserved : 2; ///< 1:0 Reserved, must be kept at reset value.
uint32_t la : 14; ///< 15:2 IDMALA. Word aligned linked list address offset
uint32_t reserved1 : 13; ///< 28:16 Reserved, must be kept at reset value.
uint32_t abr : 1; ///< 29 ABR: Acknowledge buffer ready
uint32_t uls : 1; ///< 30 ULS: Update linked list size (SMDDC_IDMABSIZE)
uint32_t ula : 1; ///< 31 ULA: Update linked list address (SMDDC_IDMALAR)
} reg_sdmmc_idmalar_t; ///< SDMMC IDMA linked list address register
////////////////////// idma linked list address register /////////////////////////
/// for the linked list
static inline hal_status_e sdmmc_set_idma_linked_list_address(uint32_t address) {
SDMMC1->IDMABAR = address;
return HAL_OK;
}
/////////////////////// data length register ///////////////////////
static inline void sdmmc_reg_set_dlen(SDMMC_TypeDef *sdmmc, uint32_t value) { sdmmc->DLEN = value; }
typedef struct {
reg_sdmmc_power_t power;
reg_sdmmc_clkcr_t clkcr;
uint32_t arg;
reg_sdmmc_cmd_t cmd;
uint32_t respcmd;
uint32_t resp1;
uint32_t resp2;
uint32_t resp3;
uint32_t resp4;
uint32_t dtimer;
uint32_t dlen;
reg_sdmmc_dctrl_t dctrl;
uint32_t dcount;
reg_sdmmc_sta_t sta;
uint32_t icr;
uint32_t mask;
uint32_t acktime;
uint32_t reserved0[3];
reg_sdmmc_idmactrl_t idmactrl;
reg_sdmmc_idmabsize_t idmabsize;
uint32_t idmabaser;
uint32_t reserved1[2];
reg_sdmmc_idmalar_t idmalar;
uint32_t idmabar;
uint32_t reserved2[5];
uint32_t fifo;
} reg_sdmmc_s;
#endif // STM32U5XX_HAL_REG_SDMMC_H