THB2/bthome_phy6222/SDK/components/driver/i2c/i2c_slave.c

239 lines
9.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*******************************************************************************
@file i2c_slave.c
@brief i2c slave function
@version 1.0
SDK_LICENSE
*******************************************************************************/
/*******************************************************************************
@ Module : Includes
@ Description : NULL
*******************************************************************************/
#include "i2c_slave.h"
#include "gpio.h"
#include "error.h"
#include "osal.h"
#include "clock.h"
#include "log.h"
/*******************************************************************************
@ Module : IIC_Slave status
@ Description : NULL
*******************************************************************************/
typedef enum
{
Slave_Closed = 0,
Slave_Opened,
} IIC_Slave_status;
/*******************************************************************************
@ Module : IIC_Slave_cfg structure
@ Description : NULL
*******************************************************************************/
typedef struct
{
AP_I2C_TypeDef* addr; // get by software
MODULE_e module; // get by software
uint8_t INTR_ID; // get by software
gpio_pin_e SDA_PIN; // I2C Pin
gpio_pin_e SCL_PIN;
Fmux_Type_e Fmux_SCL; // get by software
Fmux_Type_e Fmux_SDA; // get by software
IIC_Slave_status state;
} IIC_Slave_cfg;
/*******************************************************************************
@ Module : Global Variable
@ Description : NULL
*******************************************************************************/
IIC_Slave_cfg Slave_cfg_g[IIC_COUNT];
/*******************************************************************************
@ Module : Internal Function statement
@ Description : NULL
*******************************************************************************/
void I2C_Slave_Handler(I2C_Evt_t* pev);
/*******************************************************************************
@ Module : Function Statement
@ Description : NULL
*******************************************************************************/
uint8_t Hal_I2C_Slave_Init(I2C_Slave_Parameter* para,uint8_t* handle)
{
uint8_t ret;
LOG("Hal_I2C_Slave_Init wakeup id:%02X \r\n",para->id);
ret = Hal_IIC_Valid_Check(para->id);
if( ret == TRUE )
{
return PPLUS_ERR_IIC_BUSY;
}
else if( ret == PPlus_ERR_IIC_ID)
{
return PPlus_ERR_IIC_ID;
}
else
{
if( Hal_IIC_Addr_Valid(para->Slave_Address) != PPlus_IIC_SUCCESS)
return PPlus_ERR_IIC_ADDRESS;
osal_memset(&Slave_cfg_g[para->id],0,sizeof(IIC_Slave_cfg));
// pre-para get
Slave_cfg_g[para->id].addr = Hal_Get_IIC_Instance(para->id);
Slave_cfg_g[para->id].module = Hal_GetIIC_ModuleID(para->id);
Slave_cfg_g[para->id].INTR_ID = Hal_GetIIC_IRQID(para->id);
Hal_GetIIC_PIN_Fmux(para->id,&(Slave_cfg_g[para->id].Fmux_SCL),&(Slave_cfg_g[para->id].Fmux_SDA));
Slave_cfg_g[para->id].state = Slave_Closed;
// io init
Slave_cfg_g[para->id].SCL_PIN = para->SCL_PIN;
Slave_cfg_g[para->id].SDA_PIN = para->SDA_PIN;
hal_gpio_fmux_set(para->SCL_PIN, Slave_cfg_g[para->id].Fmux_SCL);
hal_gpio_fmux_set(para->SDA_PIN, Slave_cfg_g[para->id].Fmux_SDA);
hal_gpio_pull_set(para->SCL_PIN,STRONG_PULL_UP);
hal_gpio_pull_set(para->SDA_PIN,STRONG_PULL_UP);
// init
hal_clk_gate_enable(Slave_cfg_g[para->id].module);
Slave_cfg_g[para->id].addr->IC_ENABLE = FALSE;
Slave_cfg_g[para->id].addr->IC_CON = para->workmode | para->AddressMode;
Slave_cfg_g[para->id].addr->IC_SAR = para->Slave_Address;
Slave_cfg_g[para->id].addr->IC_RX_TL = para->RX_FIFO_Len - 1;
Slave_cfg_g[para->id].addr->IC_TX_TL = para->Tx_FIFO_Len - 1;
Slave_cfg_g[para->id].addr->IC_INTR_MASK = para->IRQ_Source;
Hal_IIC_Register_CallBack(para->id,para->evt_handler);
Hal_I2c_Slave_Open(para->id);
// NVIC Config
NVIC_EnableIRQ((IRQn_Type)(Slave_cfg_g[para->id].INTR_ID));
NVIC_SetPriority((IRQn_Type)(Slave_cfg_g[para->id].INTR_ID), IRQ_PRIO_HAL);
*handle = para->id;
return PPlus_IIC_SUCCESS;
}
}
/*******************************************************************************
@ Module : Open I2C Slave
@ Description : NULL
*******************************************************************************/
uint8_t Hal_I2c_Slave_Open(uint8_t handle)
{
if( Slave_cfg_g[handle].state == Slave_Closed )
{
Slave_cfg_g[handle].state = Slave_Opened;
Slave_cfg_g[handle].addr->IC_ENABLE = TRUE;
return PPlus_IIC_SUCCESS;
}
else
return PPlus_ERR_IIC_FAILURE;
}
/*******************************************************************************
@ Module : Close I2C Slave
@ Description : NULL
*******************************************************************************/
void Hal_I2c_Slave_Close(uint8_t handle)
{
Slave_cfg_g[handle].addr->IC_ENABLE = FALSE;
}
/*******************************************************************************
@ Module : Close I2C Slave
@ Description : Should check close states,if closed completed
a delay occurs when IC_ENABLE is set to 0, because close iic module depends
on the iic bus activity
*******************************************************************************/
uint8_t Hal_Check_I2C_Slave_Closed(uint8_t handle)
{
if( Hal_Check_IIC_Closed(Slave_cfg_g[handle].addr) == PPlus_IIC_SUCCESS )
{
Slave_cfg_g[handle].state = Slave_Closed;
return PPlus_IIC_SUCCESS;
}
else
return PPLUS_ERR_IIC_ENABLE;
}
/*******************************************************************************
@ Module : Close I2C Slave
@ Description : NULL
*******************************************************************************/
uint8_t Hal_I2C_Slave_Deinit(uint8_t* handle)
{
LOG("HAL I2C SLAVE DINIT handle Value %d \n",*handle);
if( Hal_IIC_unRegister_CallBack(*handle) != PPlus_IIC_SUCCESS )
return PPlus_ERR_IIC_FAILURE;
*handle = PPlus_INVALID_HANDLE;
return PPlus_IIC_SUCCESS;
}
/*******************************************************************************
@ Module : Read data from rx fifo
@ Description : NULL
*******************************************************************************/
void Hal_I2C_Slave_ReadRX_FIFO(uint8_t handle,uint8_t* p,uint8_t len)
{
for(uint8_t i =0; i<len; i++)
*p++ = Hal_IIC_Read_RXFIFO(Slave_cfg_g[handle].addr);
}
/*******************************************************************************
@ Module : Clear interrupt status
@ Description : NULL
*******************************************************************************/
void Hal_I2C_Slave_CLR_IRQs(uint8_t handle,uint32_t irqs)
{
Hal_INTR_SOURCE_Clear(Slave_cfg_g[handle].addr,irqs);
}
/*******************************************************************************
@ Module : Hal_I2C_Slave_WriteTX_FIFO
@ Description : NULL
*******************************************************************************/
void Hal_I2C_Slave_WriteTX_FIFO(uint8_t handle,uint8_t* p,uint8_t len)
{
for(uint8_t i=0; i<len; i++)
Hal_IIC_Write_TXFIFO(Slave_cfg_g[handle].addr,*p++);
}
/*******************************************************************************
@ Module : I2C Slave Init steps:
@ Description : NULL
*******************************************************************************/
/*
1、IC_ENABLE=0;
2、IC_SAR = ? Master和Slave不能设置相同的地址类型
3、IC_CON(配置地址模式和SLAVE模式)
4、IC_ENABLE=1;
*/
/*******************************************************************************
@ Module : I2C Slave 单字节发<E88A82><E58F91>?
@ Description : NULL
*******************************************************************************/
/*
1、IIC MASTER 寻址
2、IIC SLAVE ACK
3、IIC SLAVE 触发 RD_REQ 中断<E4B8AD><E696AD>?同时 HOLD THE SCL LOW , WAIT UNTIL THE SOFTWARE RESPONDS(数据响应<E5938D><E5BA94>?
SOFTWARE RESPONDS的时间间隔10倍SCL周期 <20><>?00K--->25us一个byte传输完成的时间
4、读请求触发前如果TXFIFO,总线触发TX_ABRT中断清除旧数据 (通过软件读取 IC_CLR_TX_ABRT register释放总线<E680BB><E7BABF>?
5、写数据<E695B0><E68DAE>?IC_DATA_CMD
6、清除RD_REQ,TX_ABRT中断标志位如果中断被屏蔽则需要清除IC_RAW_INTR_STAT<41><54>?
7、总线释放SCL并传输数据<E68DAE><EFBC88>?对应<E5AFB9><E5BA94>?
8、MASTER 通过RESTART <20><>?STOP 继续操作总线
*/
/*******************************************************************************
@ Module : I2C Slave 单字节接<E88A82><E68EA5>?
@ Description : NULL
*******************************************************************************/
/*
1、IIC MASTER 寻址
2、IIC SLAVE ACK
3、receives the transmitted byte and places it in the receive buffer
如果RX FIFO已经满了再来数据的时候将会触发R_RX_OVER中断于此同时
IIC数据将会继续传输没有NACK信号并无法保证后续数据的完整
4、RX_FULL 中断
5、从IC_DATA_CMD 中读取数<E58F96><E695B0>?
6、MASTER 通过RESTART <20><>?STOP 继续操作总线
*/