add i2c slave
This commit is contained in:
parent
788250b089
commit
6322001857
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue