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

112 lines
4.1 KiB
C++
Executable File

/// @file i2c.h
/// @brief i2c driver
/// @author Guangzong Chen <chen-gz@outlook.com>
/// @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 <cstdint>
#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