add i2c slave

This commit is contained in:
jiangxiangbing 2018-11-02 11:24:26 +08:00
parent 788250b089
commit 6322001857
2 changed files with 76 additions and 0 deletions

View File

@ -21,6 +21,14 @@
#include "string.h"
#include "sysctl.h"
typedef struct _i2c_slave_context
{
uint32_t i2c_num;
const i2c_slave_handler_t *slave_handler;
} i2c_slave_context_t;
i2c_slave_context_t slave_context;
volatile i2c_t* const i2c[3] =
{
(volatile i2c_t*)I2C0_BASE_ADDR,
@ -65,6 +73,58 @@ void i2c_init(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t addr
i2c_adapter->enable = I2C_ENABLE_ENABLE;
}
static int i2c_slave_irq(void *userdata)
{
i2c_slave_context_t *context = (i2c_slave_context_t *)userdata;
volatile i2c_t *i2c_adapter = i2c[context->i2c_num];
uint32_t status = i2c_adapter->intr_stat;
if (status & I2C_INTR_STAT_START_DET)
{
context->slave_handler->on_event(I2C_EV_START);
readl(&i2c_adapter->clr_start_det);
}
if (status & I2C_INTR_STAT_STOP_DET)
{
context->slave_handler->on_event(I2C_EV_STOP);
readl(&i2c_adapter->clr_stop_det);
}
if (status & I2C_INTR_STAT_RX_FULL)
{
context->slave_handler->on_receive(i2c_adapter->data_cmd);
}
if (status & I2C_INTR_STAT_RD_REQ)
{
i2c_adapter->data_cmd = context->slave_handler->on_transmit();
readl(&i2c_adapter->clr_rd_req);
}
return 0;
}
void i2c_init_as_slave(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
const i2c_slave_handler_t *handler)
{
configASSERT(address_width == 7 || address_width == 10);
volatile i2c_t *i2c_adapter = i2c[i2c_num];
slave_context.i2c_num = i2c_num;
slave_context.slave_handler = handler;
i2c_clk_init(i2c_num);
i2c_adapter->enable = 0;
i2c_adapter->con = (address_width == 10 ? I2C_CON_10BITADDR_SLAVE : 0) | I2C_CON_SPEED(1) | I2C_CON_STOP_DET_IFADDRESSED;
i2c_adapter->ss_scl_hcnt = I2C_SS_SCL_HCNT_COUNT(37);
i2c_adapter->ss_scl_lcnt = I2C_SS_SCL_LCNT_COUNT(40);
i2c_adapter->sar = I2C_SAR_ADDRESS(slave_address);
i2c_adapter->rx_tl = I2C_RX_TL_VALUE(0);
i2c_adapter->tx_tl = I2C_TX_TL_VALUE(0);
i2c_adapter->intr_mask = I2C_INTR_MASK_RX_FULL | I2C_INTR_MASK_START_DET | I2C_INTR_MASK_STOP_DET | I2C_INTR_MASK_RD_REQ;
plic_set_priority(IRQN_I2C0_INTERRUPT + i2c_num, 1);
plic_irq_register(IRQN_I2C0_INTERRUPT + i2c_num, i2c_slave_irq, &slave_context);
plic_irq_enable(IRQN_I2C0_INTERRUPT + i2c_num);
i2c_adapter->enable = I2C_ENABLE_ENABLE;
}
int i2c_send_data(i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len)
{
configASSERT(i2c_num < I2C_MAX_NUM);

View File

@ -340,6 +340,20 @@ typedef enum _i2c_bus_speed_mode
I2C_BS_HIGHSPEED
} i2c_bus_speed_mode_t;
typedef enum _i2c_event
{
I2C_EV_START,
I2C_EV_RESTART,
I2C_EV_STOP
} i2c_event_t;
typedef struct _i2c_slave_handler
{
void(*on_receive)(uint32_t data);
uint32_t(*on_transmit)();
void(*on_event)(i2c_event_t event);
} i2c_slave_handler_t;
/**
* @brief Set i2c params
*
@ -363,6 +377,8 @@ void i2c_init(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t addr
* - Other Fail
*/
int i2c_send_data(i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t send_buf_len);
void i2c_init_as_slave(i2c_device_number_t i2c_num, uint32_t slave_address, uint32_t address_width,
const i2c_slave_handler_t *handler);
/**
* @brief I2c send data by dma