/// @file i2c.h /// @brief i2c driver /// @author Guangzong Chen /// @date 2021-08-06 /// @copyright Copyright (c) 2023 ggeta. All rights reserved. /// @note this only for i2c master mode /// @version 0.1 initial version /// @version 0.11 replace read_block adn send_block by read_it (interrupt) and send_it (interrupt) /// add send, receive for blocking sending mode /// new initialization function /// @version 0.12 Seperate the file to cpp and h file. #ifndef STM32U5XX_HAL_I2C_H #define STM32U5XX_HAL_I2C_H #include "global_variable.h" //#include #include "delay.h" #include "queue.hpp" #include "reg_i2c_gen.h" typedef enum { I2C_STATE_WAIT = 1, ///< idle I2C_STATE_SENDING, ///< sending data I2C_STATE_RECEIVING, ///< receiving data I2C_STATE_ERROR, ///< error occur } i2c_state_e; ///< i2c state machine typedef struct _i2c_err_t { uint32_t buf_overflow : 1; // 0 Buffer overflow (for reception) uint32_t buf_underflow : 1; // 1 Buffer underflow (for transmission) uint32_t resv0 : 2; // 2 uint32_t nackf : 1; // 4 Not acknowledge received flag uint32_t resv1 : 3; // 7 uint32_t berr : 1; // 8 Bus error uint32_t arlo : 1; // 9 Arbitration lost uint32_t ovr : 1; // 10 Overrun/Underrun (slave mode) uint32_t pecerr : 1; // 10 PEC Error in reception uint32_t timeout : 1; // 10 Timeout or t_low detection flag uint32_t alert : 1; // 10 SMBus alert uint32_t resv2 : 18; // 14 Reserve void update_error(reg_i2c_isr_t isr) { this->arlo = isr.arlo, this->berr = isr.berr, this->ovr = isr.ovr, this->pecerr = isr.pecerr, this->timeout = isr.timeout, this->alert = isr.alert; } bool has_error() const { return this->buf_overflow | this->buf_underflow | this->nackf | this->berr | this->arlo | this->ovr | this->pecerr | this->timeout | this->alert; } void clean_error() { this->buf_overflow = buf_underflow = nackf = berr = arlo = ovr = pecerr = timeout = alert = 0; } } i2c_err_t; // this should match with i2c_isr_t class I2c { private: I2C_TypeDef *ins = nullptr; ///< i2c register reg_i2c_t *reg = nullptr; void (*user_tc_cb)() = nullptr; ///< user callback function void (*user_err_cb)(i2c_err_t err) = nullptr; ///< user callback function i2c_err_t errors = {}; ///< i2c error public: queue20u8 send_queue; queue20u8 recv_queue; i2c_state_e state = I2C_STATE_WAIT; ///< i2c state I2c(); void setup(I2C_TypeDef *i2c); void init(uint32_t timing = 0x30909DEC, // should be calculated by clock_speed ll_state_e autoend = LL_DISABLE, // auto send 'stop' after send/receive uint16_t own_address1 = 0x00, ll_state_e own_address1_en = LL_DISABLE, // slave address 1 uint16_t own_address2 = 0x00, ll_state_e own_address2_en = LL_DISABLE, // slave address 2 ll_state_e analog_filter = LL_ENABLE, uint32_t digital_filter = 0x00, ll_state_e clock_stretching = LL_DISABLE, ll_state_e general_call = LL_DISABLE // Address 0b00000000 is NACKed (enable to ACKed). ); /// \brief send data to slave. /// This function will send data, return until all data is sent or error occured. /// \param slave_addr /// \param data /// \param size size of data (should be less than 255) /// \return hal_status_e send(uint16_t slave_addr, const uint8_t *data, uint32_t len); hal_status_e send_it(uint16_t slave_addr, const uint8_t *data, uint8_t len, void (*cmp_cb)() = nullptr, void (*err_cb)(i2c_err_t) = nullptr); hal_status_e read(uint16_t slave_addr, uint8_t *data, uint8_t len); hal_status_e read_it(uint16_t slave_add, uint8_t len, void (*cmp_cb)() = nullptr, void (*err_cb)(i2c_err_t) = nullptr); void error_handler(); void i2c_ev_irq_handler(); void i2c_er_irq_handler(); }; #endif // STM32U5XX_HAL_I2C_H