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
16 KiB
C
Executable File
Raw Permalink 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.

#include "delay.h"
#include "global_variable.h"
#include "stm32u5xx.h"
/// chapter 65
/////////////////////////// I2C CR1 //////////////////////////////////////////
/// @brief set i2c peripheral enable or disable
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[0] (rw) Peripheralenable 0: Peripheral disable 1: Peripheral enable
/// When PE = 0, the I2C SCL and SDA lines are released.
/// Internal state machines and status bits are put back to their reset value.
/// When cleared, PE must be kept low for at least three APB clock cycles.
static inline void reg_i2c_set_peripheral_enable(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_PE, state << I2C_CR1_PE_Pos);
delay_us(3, true); // wait for 3 APB clock cycles
}
/// @brief check if i2c is enabled
/// @param[in] i2c: i2c instance
/// @return true if enabled, false if disabled
/// @note bit[0]
static bool reg_i2c_is_enabled(I2C_TypeDef *i2c) {
return READ_BIT(i2c->CR1, I2C_CR1_PE) == I2C_CR1_PE;
}
/// @brief set i2c error interrupt
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[1]
/// @note A transmit interrupt status (TXIS) is generated when the I2C_TXDR register becomes empty.
/// An interrupt is generated if the TXIE bit is set in the I2C_CR1 register.
/// The TXIS bit is cleared when the I2C_TXDR register is written with the next data byte to
/// be transmitted.
static inline void reg_i2c_set_tx_interrupt(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_TXIE, state << I2C_CR1_TXIE_Pos);
}
/// @brief set i2c rx interrupt
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[2]
/// @todo verify following note
/// @note A receive interrupt status (RXNE) is generated when the I2C_RXDR register is full.
static inline void reg_i2c_set_rx_interrupt(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_RXIE, state << I2C_CR1_RXIE_Pos);
}
/// @brief set i2c address match interrupt (slave mode only)
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[3]
/// @todo verify following note
/// @note An address match interrupt status (ADDR) is generated when the address sent by the master
/// matches the own address of the slave.
static inline void reg_i2c_set_address_match_interrupt(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_ADDRIE, state << I2C_CR1_ADDRIE_Pos);
}
/// @brief set i2c nack interrupt
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[4]
/// @todo verify following note
/// @note A NACK interrupt status (NACKF) is generated when the master receives a NACK in response
/// to a transmitted byte.
static inline void reg_i2c_set_nack_interrupt(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_NACKIE, state << I2C_CR1_NACKIE_Pos);
}
/// @brief set i2c stop detection interrupt
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[5]
/// @todo verify following note
/// @note A stop detection interrupt status (STOPF) is generated when a STOP condition is detected
/// on the bus.
static inline void reg_i2c_set_stop_detection_interrupt(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_STOPIE, state << I2C_CR1_STOPIE_Pos);
}
/// @brief set i2c transfer complete interrupt
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[6]
/// @todo verify following note
/// @note A transfer complete interrupt status (TC) is generated when the data byte transfer is
/// complete.
static inline void reg_i2c_set_transfer_complete_interrupt(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_TCIE, state << I2C_CR1_TCIE_Pos);
}
/// @brief set i2c error interrupt
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[7]
/// @note Any of these errors generate an interrupt:
/// Arbitration Loss (ARLO)
/// Bus Error detection (BERR)
/// Overrun/Underrun (OVR)
/// Timeout detection (TIMEOUT)
/// PEC error detection (PECERR)
/// Alert pin event detection (ALERT)
static inline void reg_i2c_set_error_interrupt(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_ERRIE, state << I2C_CR1_ERRIE_Pos);
}
/// @brief set i2c set digital filter
/// @param[in] i2c: i2c instance
/// @param[in] filter: filter value
/// @note bit[11:8] (4 bits)
/// @note These bits are used to configure the digital noise filter on SDA and SCL input.
/// The digital filter, filters spikes with a length of up to DNF[3:0] * t_{I2CCLK}
/// 0000: Digital filter disabled
/// 0001: Digital filter enabled and filtering capability up to 1 t_{I2CCLK}
/// @note If the analog filter is also enabled, the digital filter is added to the analog filter.
/// This filter can only be programmed when the I2C is disabled (PE = 0).
static inline void reg_i2c_set_digit_filter(I2C_TypeDef *i2c, uint8_t filter) {
MODIFY_REG(i2c->CR1, I2C_CR1_DNF, filter << I2C_CR1_DNF_Pos);
}
/// @brief set i2c analog filter
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[12]
/// @note: 0 = analog filter enabled
/// 1 = analog filter disabled
/// @note This bit can only be programmed when the I2C is disabled (PE = 0).
static inline void reg_i2c_set_analog_filter(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_ANFOFF, (state ^ 1) << I2C_CR1_ANFOFF_Pos);
}
/// @brief set i2c tx dma request enable
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[14]
static inline void reg_i2c_set_tx_dma_en(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_TXDMAEN, state << I2C_CR1_TXDMAEN_Pos);
}
/// @brief set i2c rx dma request enable
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[15]
static inline void reg_i2c_set_rx_dma_en(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_RXDMAEN, state << I2C_CR1_RXDMAEN_Pos);
}
/// @brief set i2c slave byte control
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[16]
/// @todo add document for slave byte control (what is it?)
static inline void reg_i2c_set_slave_byte_control(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_SBC, state << I2C_CR1_SBC_Pos);
}
/// @brief set i2c clock no stretching
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[17]
/// @note 0 = Clock stretching enabled
/// 1 = Clock stretching disabled
/// @note This bit is used to disable clock stretching in slave mode.
/// It must be kept cleared in master mode.
static inline void reg_i2c_set_clock_stretching(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_NOSTRETCH, (state ^ 1) << I2C_CR1_NOSTRETCH_Pos);
}
/// @brief set wake up from stop mode
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[18]
/// @note If the wake-up from Stop mode feature is not supported,
/// this bit is reserved and forced by hardware to 0. Refer to Section 65.3.
/// @note WUPEN can be set only when DNF = 0000
static inline void reg_i2c_set_wake_up_from_stop_mode(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_WUPEN, state << I2C_CR1_WUPEN_Pos);
}
/// @brief set i2c general call
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[19]
/// @note 0: General call disabled. Address 0b00000000 is NACKed.
/// @note 1: General call enabled. Address 0b00000000 is ACKed.
static inline void reg_i2c_set_general_call(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR1, I2C_CR1_GCEN, state << I2C_CR1_GCEN_Pos);
}
/// @todo add document for bit 20 to 31
/////////////////////////// I2C CR2 //////////////////////////////////////////
/// @brief set i2c slave address
/// @param[in] i2c: i2c instance
/// @param[in] address: slave address
/// @note bit[9:0]
/// @note In 7-bit addressing mode (ADD10 = 0):
/// SADD[7:1] must be written with the 7-bit slave address to be sent.
/// The bits SADD[9], SADD[8] and SADD[0] are don't care.
/// In 10-bit addressing mode (ADD10 = 1):
/// SADD[9:0] must be written with the 10-bit slave address to be sent.
/// @note Changing these bits when the START bit is set is not allowed.
static inline void reg_i2c_set_slave_address(I2C_TypeDef *i2c, uint16_t address) {
MODIFY_REG(i2c->CR2, I2C_CR2_SADD, address << I2C_CR2_SADD_Pos);
}
typedef enum {
LL_I2C_WRITE = 0, ///< write
LL_I2C_READ = 1, ///< read
} LL_I2C_RW; /// @brief i2c read or write
/// @brief set i2c read or write
/// @param[in] i2c: i2c instance
/// @param[in] rw: read or write @see LL_I2C_RW
/// @note bit[10]
/// @note changing this bit when the START bit is set is not allowed.
static inline void reg_i2c_set_rd_wrn(I2C_TypeDef *i2c, LL_I2C_RW rw) {
MODIFY_REG(i2c->CR2, I2C_CR2_RD_WRN, rw << I2C_CR2_RD_WRN_Pos);
}
typedef enum {
LL_I2C_7BIT = 0, ///< 7-bit
LL_I2C_10BIT = 1, ///< 10-bit
} LL_I2C_ADD10; /// @brief i2c address mode
/// @brief set i2c address mode
/// @param[in] i2c: i2c instance
/// @param[in] mode: 7-bit or 10-bit
/// @note bit[11]
/// @note changing this bit when the START bit is set is not allowed.
static inline void reg_i2c_set_add10(I2C_TypeDef *i2c, LL_I2C_ADD10 mode) {
MODIFY_REG(i2c->CR2, I2C_CR2_ADD10, mode << I2C_CR2_ADD10_Pos);
}
/// @todo add document for bit 12
/// @brief send i2c start
/// @param[in] i2c: i2c instance
/// @note bit[13]
/// @note This bit is set by software, and cleared by hardware after the Start followed by the
/// address sequence is sent, by an arbitration loss, by an address matched in slave mode,
/// by a timeout error detection, or when PE = 0.
/// 0: No Start generation. 1: Restart/Start generation:
/// If the I2C is already in master mode with AUTOEND = 0, setting this bit generates a
/// Repeated start condition when RELOAD = 0, after the end of the NBYTES transfer. Otherwise
/// setting this bit generates a START condition once the bus is free.
/// @note Writing 0 to this bit has no effect.
/// The START bit can be set even if the bus is BUSY or I2C is in slave mode.
/// This bit has no effect when RELOAD is set.
static inline void reg_i2c_send_start(I2C_TypeDef *i2c) { SET_BIT(i2c->CR2, I2C_CR2_START); }
/// @brief send i2c stop (master mode)
/// @param[in] i2c: i2c instance
/// @note bit[14]
/// @ntoe The bit is set by software, cleared by hardware when a STOP condition is detected, or when
/// PE = 0.
/// @note writing 0 to this bit has no effect.
static inline void reg_i2c_send_stop(I2C_TypeDef *i2c) { SET_BIT(i2c->CR2, I2C_CR2_STOP); }
typedef enum {
LL_I2C_ACK = 0, ///< ACK
LL_I2C_NACK = 1, ///< NACK
} LL_I2C_NACK_MODE; /// @brief i2c NACK or ACK
/// @brief NACK generation (slave mode)
/// @param[in] i2c: i2c instance
/// @param[in] mode: NACK or ACK
/// @note bit[15]
/// @note The bit is set by software, cleared by hardware when the NACK is sent, or when a STOP
/// condition or an Address matched is received, or when PE = 0.
/// 0: an ACK is sent after current received byte.
/// 1: a NACK is sent after current received byte.
/// @note Writing 0 to this bit has no effect.
/// This bit is used in slave mode only: in master receiver mode, NACK is automatically generated
/// after last byte preceding STOP or RESTART condition, whatever the NACK bit value. When an
/// overrun occurs in slave receiver NOSTRETCH mode, a NACK is automatically generated whatever
/// the NACK bit value. When hardware PEC checking is enabled (PECBYTE = 1), the PEC acknowledge
/// value does not depend on the NACK value.
static inline void reg_i2c_set_nack(I2C_TypeDef *i2c, LL_I2C_NACK_MODE mode) {
MODIFY_REG(i2c->CR2, I2C_CR2_NACK, mode << I2C_CR2_NACK_Pos);
}
/// @brief set i2c number of bytes
/// @param[in] i2c: i2c instance
/// @param[in] nbytes: number of bytes
/// @note bit[23:16]
/// @warning change nbyte when sending is not allowed (after send start)
/// @note Changing this bit when the START bit is set is not allowed.
/// @note The number of bytes to be transmitted/received is programmed there.
/// This field is dont care in slave mode with SBC = 0.
static inline void reg_i2c_set_nbytes(I2C_TypeDef *i2c, uint8_t nbytes) {
MODIFY_REG(i2c->CR2, I2C_CR2_NBYTES, nbytes << I2C_CR2_NBYTES_Pos);
}
/// @brief nbytes reload mode
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[24]
/// @todo add document
static inline void reg_i2c_set_reload(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR2, I2C_CR2_RELOAD, state << I2C_CR2_RELOAD_Pos);
}
/// @brief set i2c autoend
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[25]
/// @todo add document
static inline void reg_i2c_set_autoend(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR2, I2C_CR2_AUTOEND, (state ^ 1) << I2C_CR2_AUTOEND_Pos);
}
/// @brief set i2c pec byte
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[26]
/// @todo add document
static inline void reg_i2c_set_pec_byte(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->CR2, I2C_CR2_PECBYTE, state << I2C_CR2_PECBYTE_Pos);
}
/////////////////////////// I2C OAR1 //////////////////////////////////////////
/// @brief set own address1
/// @param[in] i2c: i2c instance
/// @param[in] address: own address
/// @note bit[9:0]
static inline void reg_i2c_set_own_address1(I2C_TypeDef *i2c, uint16_t address) {
MODIFY_REG(i2c->OAR1, I2C_OAR1_OA1, address << I2C_OAR1_OA1_Pos);
}
/// @brief set own address mode
/// @param[in] i2c: i2c instance
/// @param[in] mode: 7-bit or 10-bit
/// @note bit[10]
static inline void reg_i2c_set_own_address_mode(I2C_TypeDef *i2c, LL_I2C_ADD10 mode) {
MODIFY_REG(i2c->OAR1, I2C_OAR1_OA1MODE, mode << I2C_OAR1_OA1MODE_Pos);
}
/// @brief set i2c own address enable
/// @param[in] i2c: i2c instance
/// @param[in] state: enable or disable
/// @note bit[15]
static inline void reg_i2c_set_own_address1_en(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->OAR1, I2C_OAR1_OA1EN, state << I2C_OAR1_OA1EN_Pos);
}
/////////////////////////// I2C OAR2 //////////////////////////////////////////
/// @brief set i2c own address2
/// @param[in] i2c: i2c instance
/// @param[in] address: own address
/// @note bit[9:0]
static inline void reg_i2c_set_own_address2(I2C_TypeDef *i2c, uint16_t address) {
MODIFY_REG(i2c->OAR2, I2C_OAR2_OA2, address << I2C_OAR2_OA2_Pos);
}
/// @brief set i2c own address2 mode
/// @param[in] i2c: i2c instance
/// @param[in] mode: 7-bit or 10-bit
/// @note bit[10]
static inline void reg_i2c_set_own_address2_mode(I2C_TypeDef *i2c, LL_I2C_ADD10 mode) {
MODIFY_REG(i2c->OAR2, I2C_OAR2_OA2, mode << I2C_OAR2_OA2_Pos);
}
/// @brief set i2c own address2 enable
/// @param[in] i2c: i2c instance
/// @param[in] address: own address
/// @note bit[15]
static inline void reg_i2c_set_own_address2_en(I2C_TypeDef *i2c, ll_state_e state) {
MODIFY_REG(i2c->OAR2, I2C_OAR2_OA2EN, state << I2C_OAR2_OA2EN_Pos);
}
/////////////////////////// I2C TIMINGR ///////////////////////////////////////////
/// todo: update timming set up using understandable names
static inline void reg_i2c_set_timing(I2C_TypeDef *i2c, uint32_t timing) {
WRITE_REG(i2c->TIMINGR, timing);
}
/////////////////////////// I2C TIMEOUTR //////////////////////////////////////////
/////////////////////////// I2C ISR ///////////////////////////////////////////////
/////////////////////////// I2C ICR ///////////////////////////////////////////////
/////////////////////////// I2C RXDR //////////////////////////////////////////////
static inline uint8_t reg_i2c_read_data(I2C_TypeDef *i2c) {
return READ_REG(i2c->RXDR);
}
/////////////////////////// I2C TXDR //////////////////////////////////////////////
static inline void reg_i2c_write_data(I2C_TypeDef *i2c, uint8_t data) {
WRITE_REG(i2c->TXDR, data);
}
/////////////////////////// I2C AUTOCR ////////////////////////////////////////////