/// @file i2c.h /// @brief i2c driver /// @author Guangzong Chen /// @date 2021-08-06 /// @copyright Copyright (c) 2023 ggeta. All 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 to .h and .cpp file in order to pack this into a library #ifndef STM32U5XX_HAL_I2C_HPP #define STM32U5XX_HAL_I2C_HPP #include "global_variable.h" #include "queue.hpp" #include 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 #include "reg_i2c_gen.h" 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 based 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). ); 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_HPP