/** * @addtogroup stm32u5xx_ll_driver * @{ * @addtogroup stm32u5xx_ll_spi * @{ */ /// @file ll_spi.h /// @breif spi driver /// @version 0.1 /// @author Guangzong Chen /// @date 2023-03-14 /// @copyright Copyright (c) 2022 zongpitt All Rights Reserved. #ifndef REG_SPI_H #define REG_SPI_H #include "global_variable.h" #include "stm32u575xx.h" #include //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI CR1 register////////////////////////////////// /// @brief set spi peripheral enable /// @param[in] spi: spi instance /// @param[in] state: enable or disable /// @note bit 0 static inline void reg_spi_set_peripheral_enable(SPI_TypeDef *spi, ll_state_e state) { MODIFY_REG(spi->CR1, SPI_CR1_SPE, state << SPI_CR1_SPE_Pos); } typedef enum { SPI_SSI_LOW = 0, ///< @brief spi slave select pin is low SPI_SSI_HIGH = 1, ///< @brief spi slave select pin is high } REG_SPI_SSI_STATE; ///< @brief spi slave select pin state /// @brief spi set slave select pin /// @param[in] spi: spi instance /// @param[in] state: slave select pin state /// @note bit 12 /// @note This bit has an effect only when the SSM bit is set. The value of this bit is forced onto the peripheral SS /// input internally and the I/O value of the SS pin is ignored. static inline void reg_spi_set_slave_select_pin(SPI_TypeDef *spi, REG_SPI_SSI_STATE state) { MODIFY_REG(spi->CR1, SPI_CR1_SSI, state << SPI_CR1_SSI_Pos); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI CR2 register////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI CFG1 register//////////////////////////////// /// @brief spi master clock divider typedef enum { SPI_MBR_DIV2 = 0, ///< @brief spi master clock/2 SPI_MBR_DIV4 = 1, ///< @brief spi master clock/4 SPI_MBR_DIV8 = 2, ///< @brief spi master clock/8 SPI_MBR_DIV16 = 3, ///< @brief spi master clock/16 SPI_MBR_DIV32 = 4, ///< @brief spi master clock/32 SPI_MBR_DIV64 = 5, ///< @brief spi master clock/64 SPI_MBR_DIV128 = 6, ///< @brief spi master clock/128 SPI_MBR_DIV256 = 7, ///< @brief spi master clock/256 } REG_SPI_MBR; /// @brief spi set master baud rate prescaler /// @param[in] spi: spi instance /// @param[in] mbr: spi master baud rate prescalar static inline void reg_spi_set_master_baud_rate(SPI_TypeDef *spi, REG_SPI_MBR mbr) { MODIFY_REG(spi->CFG1, SPI_CFG1_MBR, mbr << SPI_CFG1_MBR_Pos); } /// @brief spi set data size /// @param[in] spi: spi instance /// @param[in] size: spi data size (3-16) static inline void reg_spi_set_data_size(SPI_TypeDef *spi, uint8_t size) { MODIFY_REG(spi->CFG1, SPI_CFG1_DSIZE, (size - 1) << SPI_CFG1_DSIZE_Pos); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI CFG2 register//////////////////////////////// typedef enum { SPI_SLAVE = 0, ///< @brief spi slave SPI_MASTER = 1, ///< @brief spi master } REG_SPI_MASTER; /// @brief spi set master /// @param[in] spi: spi instance /// @param[in] state: spi master or slave. static inline void reg_spi_set_master(SPI_TypeDef *spi, REG_SPI_MASTER state) { // todo: I don't know why it need set twice. Then the register will be set correctly. MODIFY_REG(spi->CFG2, SPI_CFG2_MASTER, state << SPI_CFG2_MASTER_Pos); MODIFY_REG(spi->CFG2, SPI_CFG2_MASTER, state << SPI_CFG2_MASTER_Pos); } typedef enum { SPI_CPOL_LOW = 0, ///< @brief spi clock idle state is low SPI_CPOL_HIGH = 1, ///< @brief spi clock idle state is high } REG_SPI_CPOL; /// @brief spi set clock polarity /// @param[in] spi: spi instance /// @param[in] polarity: spi clock idle state (low or high) static inline void reg_spi_set_clock_polarity(SPI_TypeDef *spi, REG_SPI_CPOL polarity) { MODIFY_REG(spi->CFG2, SPI_CFG2_CPOL, polarity << SPI_CFG2_CPOL_Pos); } typedef enum { SPI_CPHA_FIRST = 0, ///< @brief spi clock phase is first edge SPI_CPHA_SECOND = 1, ///< @brief spi clock phase is second edge } REG_SPI_CPHA; /// @brief spi set clock phase /// @param[in] spi: spi instance /// @param[in] phase: spi clock phase (first or second edge) static inline void reg_spi_set_clock_phase(SPI_TypeDef *spi, REG_SPI_CPHA phase) { MODIFY_REG(spi->CFG2, SPI_CFG2_CPHA, phase << SPI_CFG2_CPHA_Pos); } typedef enum { SPI_FIRST_BIT_MSB = 0, ///< @brief spi first bit is MSB SPI_FIRST_BIT_LSB = 1, ///< @brief spi first bit is LSB } REG_SPI_FIRST_BIT; /// @brief spi set first bit static inline void reg_spi_set_first_bit(SPI_TypeDef *spi, REG_SPI_FIRST_BIT first_bit) { MODIFY_REG(spi->CFG2, SPI_CFG2_LSBFRST, first_bit << SPI_CFG2_LSBFRST_Pos); } /// @brief spi slave select pin management typedef enum { SPI_SS_MANAGER_SOFTWARE = 1, ///< @brief software slave select management SPI_SS_MANAGER_HARDWARE = 0, ///< @brief hardware slave select management } REG_SPI_SS_MANAGEMENT; /// @brief spi set slave select /// @see doc/rm0456 68.4.7 Slave select(SS) pin management. Page 2898 static inline void reg_spi_set_slave_select(SPI_TypeDef *spi, REG_SPI_SS_MANAGEMENT ssm) { MODIFY_REG(spi->CFG2, SPI_CFG2_SSM, ssm << SPI_CFG2_SSM_Pos); } /// @brief alternate function GPIO contorol /// @param[in] spi: spi instance /// @param[in] state: enable or disable /// @note bit 31 /// @note This bit taken into account when SPE=0 only (SPI disabled). /// 0: The peripheral takes no control of GPIOs while it is disabled /// 1: The peripheral keeps always control of all associated GPIOs /// When SPI must be disabled temporary for a specific configuration reason /// (for example CRC reset, CPHA or HDDIR change) setting this bit prevents any glitches on the associated /// outputs configured at alternate function mode by keeping them forced at state corresponding the current SPI configuration static inline void reg_spi_set_af_control(SPI_TypeDef *spi, ll_state_e state) { MODIFY_REG(spi->CFG2, SPI_CFG2_AFCNTR, state << SPI_CFG2_AFCNTR_Pos); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI IER register///////////////////////////////// /// @brief set spi receive interrupt /// @param[in] spi: spi instance /// @param[in] state: enable or disable /// @note bit 0: RXPIE: Rx buffer not empty interrupt enable /// @note Interrupt Event: RxFIFO not empty static inline void reg_spi_set_rx_interrupt(SPI_TypeDef *spi, ll_state_e state) { MODIFY_REG(spi->IER, SPI_IER_RXPIE, state << SPI_IER_RXPIE_Pos); } /// @brief set spi transmit interrupt /// @param[in] spi: spi instance /// @param[in] state: enable or disable /// @note bit 1: TXPIE: Tx buffer empty interrupt enable /// @note Interrupt Event: TxFIFO ready to be loaded (space available for one data packet - FIFO threshold) static inline void reg_spi_set_tx_interrupt(SPI_TypeDef *spi, ll_state_e state) { MODIFY_REG(spi->IER, SPI_IER_TXPIE, state << SPI_IER_TXPIE_Pos); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI SR register////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI IFCR register//////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI AUTOCR register////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI TXDR register//////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI RXDR register//////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI CRCPOLY register///////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI TXCRC register/////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI RXCRC register/////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////SPI UDRDR register/////////////////////////////// /// @brief spi clock mode typedef enum { SPI_CLOCK_MODE_0 = 0, ///< @brief spi clock idle state is low and clock phase is first edge SPI_CLOCK_MODE_1 = 1, ///< @brief spi clock idle state is low and clock ///< phase is second edge SPI_CLOCK_MODE_2 = 2, ///< @brief spi clock idle state is high and clock ///< phase is first edge SPI_CLOCK_MODE_3 = 3, ///< @brief spi clock idle state is high and clock ///< phase is second edge } REG_SPI_CLOCK_MODE; /// @brief spi set mode /// @param[in] spi: spi instance /// @param[in] mode: spi mode (0, 1, 2, 3) /// @return void static inline void reg_spi_set_clock_mode(SPI_TypeDef *spi, REG_SPI_CLOCK_MODE mode) { reg_spi_set_clock_polarity(spi, static_cast(mode & 0x1)); reg_spi_set_clock_phase(spi, static_cast((mode >> 1) & 0x1)); } #endif /** * @} * @} */