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

255 lines
9.3 KiB
C
Executable File

/**
* @addtogroup stm32u5xx_ll_driver
* @{
* @addtogroup stm32u5xx_ll_spi
* @{
*/
/// @file ll_spi.h
/// @breif spi driver
/// @version 0.1
/// @author Guangzong Chen <chen-gz@outlook.com>
/// @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 <stm32u5xx.h>
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////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<REG_SPI_CPOL>(mode & 0x1));
reg_spi_set_clock_phase(spi, static_cast<REG_SPI_CPHA>((mode >> 1) & 0x1));
}
#endif
/**
* @}
* @}
*/