/*! * \file xc_drv_i2c.c * * \brief Target xc i2c driver implementation * * \copyright Revised BSD License, see section \ref LICENSE. * * \code * * _ __ _ ________ _ * | |/ /(_)___ / ____/ /_ (_)___ * | // / __ \/ / / __ \/ / __ \ * / |/ / / / / /___/ / / / / /_/ / * /_/|_/_/_/ /_/\____/_/ /_/_/ .___/ * /_/ * (C) 2022-2025 XinChip * * \endcode * * \author ( XinChip ) Alex-J * * \author ( XinChip ) */ /*------------------------------------------------------------------------------------ INCLUDE HEADE FILES -------------------------------------------------------------------------------------*/ #include "xc_drv_i2c.h" /*------------------------------------------------------------------------------------ Macros -------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------ Global Variables -------------------------------------------------------------------------------------*/ I2C_Block_t i2c_ctl_block; /*------------------------------------------------------------------------------------ TypeDef -------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------ Local Variables -------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------ Func Prototype -------------------------------------------------------------------------------------*/ void xc_i2c_ctl_block_reset(void); /*------------------------------------------------------------------------------------ Functions -------------------------------------------------------------------------------------*/ void xc_i2c_init(I2C_InitCfg_t *init_cfg) { cpr_ctlapbclken_grctl__i2c_pclk_en__setf(ENABLE); cpr_rstctl_subrst_sw__i2c_rstn__setf(RSTCTL_ENABLE); cpr_rstctl_subrst_sw__i2c_rstn__setf(RSTCTL_DISABLE); cpr_i2c_clk_ctl__i2c_clk_en__setf(ENABLE); cpr_i2c_clk_ctl__i2c_clk_div__setf(init_cfg->DivClk); i2c_flag_status_get(I2C_STATUS_ACTIVITY_SET); i2c_enable__enable__setf(I2C_ENABLE_EN_DISABLE); i2c_rx_tl__rx_tl__setf(I2C_RX_TL_FIFO_1); i2c_tx_tl__tx_tl__setf(I2C_TX_TL_FIFO_0); i2c_intr_en_set(I2C_INTR_EN_RX_UNDER_DISABLE | I2C_INTR_EN_RX_OVER_DISABLE | I2C_INTR_EN_RX_FULL_DISABLE | I2C_INTR_EN_TX_OVER_DISABLE | I2C_INTR_EN_TX_EMPTY_DISABLE | I2C_INTR_EN_RD_REQ_DISABLE | I2C_INTR_EN_TX_ABRT_DISABLE | I2C_INTR_EN_RX_DONE_DISABLE | I2C_INTR_EN_ACTIVITY_DISABLE | I2C_INTR_EN_STOP_DET_DISABLE | I2C_INTR_EN_START_DET_DISABLE | I2C_INTR_EN_GEN_CALL_DISABLE); i2c_tar__i2c_10bitaddr_master__setf(I2C_TAR_I2C_7BITADDR_MODE); if (init_cfg->I2C_Mode == I2C_MODE_MASTER) { i2c_tar__i2c_tar__setf(init_cfg->I2C_SlaveAddr); i2c_con__master_mode__setf(I2C_CON_MASTER_MODE_ENABLE); i2c_con__slave_disable__setf(I2C_CON_SLAVE_DISABLE_DISABLE); } else if (init_cfg->I2C_Mode == I2C_MODE_SLAVE) { i2c_sar__setf(init_cfg->I2C_SlaveAddr); i2c_con__master_mode__setf(I2C_CON_MASTER_MODE_DISABLE); i2c_con__slave_disable__setf(I2C_CON_SLAVE_DISABLE_ENABLE); i2c_con__addr_10bit_slave__setf(I2C_CON_7BITADDR_SLAVE_MODE); i2c_con__restart_en__setf(I2C_CON_RESTART_EN_DISABLE); } xc_i2c_ctl_block_reset(); if (init_cfg->I2C_ClockSpeed == I2C_FREQUENCY_100K) { i2c_con__speed__setf(I2C_CON_SPEED_STANDARD_MODE); if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) { i2c_ss_scl_hcnt__ss_scl_hcnt__setf(I2C_MLCK32M_FREQUENCY_HCNT_100K); i2c_ss_scl_lcnt__ss_scl_lcnt__setf(I2C_MLCK32M_FREQUENCY_LCNT_100K); } else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M) { i2c_ss_scl_hcnt__ss_scl_hcnt__setf(I2C_MLCK48M_FREQUENCY_HCNT_100K); i2c_ss_scl_lcnt__ss_scl_lcnt__setf(I2C_MLCK48M_FREQUENCY_LCNT_100K); } else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M) { i2c_ss_scl_hcnt__ss_scl_hcnt__setf(I2C_MLCK64M_FREQUENCY_HCNT_100K); i2c_ss_scl_lcnt__ss_scl_lcnt__setf(I2C_MLCK64M_FREQUENCY_LCNT_100K); } } else if (init_cfg->I2C_ClockSpeed == I2C_FREQUENCY_400K) { i2c_con__speed__setf(I2C_CON_SPEED_FAST_MODE); if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) { i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK32M_FREQUENCY_HCNT_400K); i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MLCK32M_FREQUENCY_LCNT_400K); } else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M) { i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK48M_FREQUENCY_HCNT_400K); i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MLCK48M_FREQUENCY_LCNT_400K); } else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M) { i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK64M_FREQUENCY_HCNT_400K); i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MLCK64M_FREQUENCY_LCNT_400K); } } else { i2c_con__speed__setf(I2C_CON_SPEED_FAST_MODE); if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_32M) { i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK32M_FREQUENCY_HCNT_1M); i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MCLK32M_FREQUENCY_LCNT_1M); } else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_48M) { i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK48M_FREQUENCY_HCNT_1M); i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MCLK48M_FREQUENCY_LCNT_1M); } else if (xc_clock_hfclk_in_get() == CLOCK_HFCLK_IN_64M) { i2c_fs_scl_hcnt__fs_scl_hcnt__setf(I2C_MLCK64M_FREQUENCY_HCNT_1M); i2c_fs_scl_lcnt__fs_scl_lcnt__setf(I2C_MCLK64M_FREQUENCY_LCNT_1M); } } i2c_flag_status_get(I2C_STATUS_ACTIVITY_SET); i2c_enable__enable__setf(I2C_ENABLE_EN_ENABLE); } void xc_i2c_enable_it(uint32_t val) { i2c_intr_en_set(val); } void xc_i2c_fifo_rxtl_set(uint32_t val) { i2c_rx_tl__rx_tl__setf(val); } void xc_i2c_fifo_txtl_set(uint32_t val) { i2c_tx_tl__tx_tl__setf(val); } void xc_i2c_ctl_block_reset(void) { memset(&i2c_ctl_block, 0, sizeof(i2c_ctl_block)); i2c_ctl_block.i2c_read_cb = NULL; i2c_ctl_block.i2c_write_cb = NULL; } void xc_i2c_register_read_cb(i2c_read_callback i2c_cb) { i2c_ctl_block.i2c_read_cb = i2c_cb; } void xc_i2c_register_write_cb(i2c_write_callback i2c_cb) { i2c_ctl_block.i2c_write_cb = i2c_cb; } void xc_i2c_slave_addr_set(uint8_t addr) { i2c_enable__enable__setf(I2C_ENABLE_EN_DISABLE); i2c_tar__i2c_tar__setf(addr); i2c_enable__enable__setf(I2C_ENABLE_EN_ENABLE); } uint32_t xc_i2c_write_block(uint8_t dev_addr, uint8_t *src, size_t len, uint16_t reset, uint16_t stop) { xc_i2c_slave_addr_set(dev_addr); uint32_t abort_reason = 0; uint16_t timeout = 0xFFFF; for (int i = 0; i < len; i++) { i2c_data_cmd_set(I2C_DATA_CMD_CMD_WRITE | stop | reset | *src++); do { } while (timeout-- && !(i2c_raw_intr_stat_get() & I2C_RAW_INTR_STAT_TX_EMPTY_SET)); if (!timeout) { break; } abort_reason = i2c_tx_abrt_source_get(); if (abort_reason) { i2c_clr_tx_abrt_get(); break; } } return abort_reason; } uint32_t xc_i2c_read_block(uint8_t dev_addr, uint8_t *dst, size_t len, uint16_t reset, uint16_t stop) { xc_i2c_slave_addr_set(dev_addr); uint32_t abort_reason; uint16_t timeout = 0xFFFF; for (int i = 0; i < len; i++) { while (!(I2C_FIFO_LEN - i2c_txflr_get())) ; i2c_data_cmd_set(I2C_DATA_CMD_CMD_READ | stop | reset); do { } while (timeout-- && !i2c_rxflr_get()); if (!timeout) { DEBUG("xc_i2c_read_block timeout\n"); break; } abort_reason = i2c_tx_abrt_source_get(); if (abort_reason) { DEBUG("xc_i2c_read_block tx_abrt\n"); i2c_clr_tx_abrt_get(); break; } *dst++ = i2c_data_cmd_get(); } return abort_reason; } void i2c_user_handler() { uint8_t val; uint32_t stat; stat = i2c_intr_stat_get(); val = i2c_clr_intr_get(); if (stat & I2C_INTR_STAT_RX_DONE_SET) { } if (stat & I2C_INTR_STAT_RX_FULL_SET) { val = i2c_data_cmd__dat__getf(); if (i2c_ctl_block.i2c_read_cb != NULL) { i2c_ctl_block.i2c_read_cb(&val, 1); } } if (stat & I2C_INTR_STAT_RD_REQ_SET) { if (i2c_ctl_block.i2c_write_cb != NULL) { i2c_ctl_block.i2c_write_cb(); } } if (stat & I2C_INTR_STAT_TX_EMPTY_SET) { } if (stat & I2C_INTR_STAT_STOP_DET_SET) { } } FlagStatus i2c_flag_status_get(uint32_t i2c_flag) { FlagStatus bitstatus = RESET; if ((i2c_status_get() & i2c_flag) != (uint32_t)RESET) { bitstatus = SET; } else { bitstatus = RESET; } return bitstatus; } void I2C_Handler() { i2c_user_handler(); }