123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- /**
- *****************************************************************************
- * @file cmem7_i2c.c
- *
- * @brief CMEM7 I2C source file
- *
- *
- * @version V1.0
- * @date 3. September 2013
- *
- * @note
- *
- *****************************************************************************
- * @attention
- *
- * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
- * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
- * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
- * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
- * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
- * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
- *
- * <h2><center>© COPYRIGHT 2013 Capital-micro </center></h2>
- *****************************************************************************
- */
-
- #include "cmem7_i2c.h"
- #define I2C_INNER_INT_ALL 0x3FF
- typedef struct {
- union {
- uint32_t DATA_CMD;
-
- struct {
- uint32_t DATA : 8;
- uint32_t RD_CMD : 1;
- uint32_t WR_CMD : 1;
- uint32_t WR_RD_CMD : 1;
- } DATA_CMD_b;
- } INNER;
- } I2C_INNER_DATA_CMD;
- static uint32_t i2c_GetClock(I2C0_Type* I2Cx) {
- uint32_t dividor;
- if ((uint32_t)I2Cx == (uint32_t)I2C0) {
- dividor = GLOBAL_CTRL->CLK_SEL_0_b.I2C0_CLK;
- } else if ((uint32_t)I2Cx == (uint32_t)I2C1) {
- dividor = GLOBAL_CTRL->CLK_SEL_0_b.I2C1_CLK;
- }
-
- return SYSTEM_CLOCK_FREQ / (1 << (dividor + 1));
- }
- static uint16_t i2c_NormalizeAddr(I2C0_Type* I2Cx, uint16_t addr) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
-
- if (I2Cx->CTRL_b.MODE == I2C_Mode_Master) {
- if (I2Cx->CTRL_b.MASTER_ADDR_WIDTH == I2C_ADDR_WIDTH_7BIT) {
- addr &= 0x007F;
- } else {
- addr &= 0x3FF;
- }
- }
-
- if (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) {
- if (I2Cx->CTRL_b.SLAVE_ADDR_WIDTH == I2C_ADDR_WIDTH_7BIT) {
- addr &= 0x007F;
- } else {
- addr &= 0x3FF;
- }
- }
-
- return addr;
- }
- static void i2c_ReadClear(uint32_t bit) {
- uint32_t tmp;
- tmp = bit;
- tmp = tmp;
- }
-
- void I2C_Init(I2C0_Type* I2Cx, I2C_InitTypeDef* I2C_Init) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
- assert_param(I2C_Init);
- assert_param(IS_I2C_MODE(I2C_Init->I2C_Mode));
- assert_param(IS_I2C_ADDR_WIDTH(I2C_Init->I2C_AddressWidth));
-
- // reset
- I2Cx->ENABLE_b.RESET = FALSE;
- I2Cx->ENABLE_b.RESET = TRUE;
-
- // clear interrupt
- I2Cx->INT_MASK = I2C_INNER_INT_ALL;
- i2c_ReadClear(I2Cx->CLR_ALL_INT_b.CLEAR);
-
- I2Cx->CTRL_b.MODE = I2C_Init->I2C_Mode;
- if (I2Cx->CTRL_b.MODE == I2C_Mode_Master) {
- I2Cx->CTRL_b.MASTER_ADDR_WIDTH = I2C_Init->I2C_AddressWidth;
- I2Cx->TAR_b.START_BYTE = TRUE;
- I2Cx->TAR_b.ADDR10 = i2c_NormalizeAddr(I2Cx, I2C_Init->I2C_Address);
- }
- if (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) {
- I2Cx->CTRL_b.SLAVE_ADDR_WIDTH = I2C_Init->I2C_AddressWidth;
- I2Cx->SAR_b.ADDR10 = i2c_NormalizeAddr(I2Cx, I2C_Init->I2C_Address);
- }
-
- I2Cx->RX_TL_b.THRESHOLD = 0;
- I2Cx->TX_TL_b.THRESHOLD = 0;
-
- I2Cx->SLAVE_NACK_b.NACK = FALSE;
-
- if (I2C_Init->timing) {
- I2Cx->SCL_CNT_b.HIGH_LEVEL_TICK =
- i2c_GetClock(I2Cx) / I2C_Init->timing->I2C_Freq / 2;
- I2Cx->SCL_CNT_b.LOW_LEVEL_TICK =
- i2c_GetClock(I2Cx) / I2C_Init->timing->I2C_Freq / 2;
- I2Cx->SDA_SETUP_b.TSU_DAT = ((uint64_t)I2C_Init->timing->I2C_TsuDat) *
- i2c_GetClock(I2Cx) / 1000000000;
- I2Cx->SDA_SETUP_b.TSETUP = ((uint64_t)I2C_Init->timing->I2C_Tsetup) *
- i2c_GetClock(I2Cx) / 1000000000;
- I2Cx->TSU_STA_SETUP_b.TBUF = ((uint64_t)I2C_Init->timing->I2C_Tbuf) *
- i2c_GetClock(I2Cx) / 1000000000;
- I2Cx->TSU_STA_SETUP_b.TSU_STA = ((uint64_t)I2C_Init->timing->I2C_TsuSta) *
- i2c_GetClock(I2Cx) / 1000000000;
- I2Cx->TSU_STA_SETUP_b.SDA_FILTER_EN = I2C_Init->timing->I2C_SdaFilterEn;
- I2Cx->TSU_STA_SETUP_b.SDA_FILTER_CNT = I2C_Init->timing->I2C_SdaFilterSpike;
- I2Cx->TSU_STA_SETUP_b.SCL_FILTER_EN = I2C_Init->timing->I2C_SclFilterEn;
- I2Cx->TSU_STA_SETUP_b.SCL_FILTER_CNT = I2C_Init->timing->I2C_SclFilterSpike;
- }
- }
- void I2C_Enable(I2C0_Type* I2Cx, BOOL enable) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
-
- I2Cx->ENABLE_b.EN = enable;
- }
- void I2C_EnableInt(I2C0_Type* I2Cx, uint32_t Int, BOOL enable) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
- assert_param(IS_I2C_INT(Int));
-
- if (enable) {
- I2Cx->INT_MASK &= ~Int;
- } else {
- I2Cx->INT_MASK |= Int;
- }
- }
- BOOL I2C_GetIntStatus(I2C0_Type* I2Cx, uint32_t Int) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
- assert_param(IS_I2C_INT(Int));
-
- if (0 != (I2Cx->INT_STATUS & Int)) {
- return TRUE;
- }
-
- return FALSE;
- }
- void I2C_ClearInt(I2C0_Type* I2Cx, uint32_t Int) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
- assert_param(IS_I2C_INT(Int));
-
- if (Int == I2C_INT_RX_FIFO_NOT_EMPTY) {
- // It can't be clear by sw but read data
- }
-
- if (Int == I2C_INT_RD_REQUEST) {
- i2c_ReadClear(I2Cx->CLR_RD_REQ_b.CLEAR);
- }
-
- if (Int == I2C_INT_TX_ABORT) {
- i2c_ReadClear(I2Cx->CLR_TX_ABRT_b.CLEAR);
- }
-
- if (Int == I2C_INT_RX_DONE) {
- i2c_ReadClear(I2Cx->CLR_RX_DONE_b.CLEAR);
- }
-
- if (Int == I2C_INT_TX_DONE) {
- i2c_ReadClear(I2Cx->CLR_TX_DONE_b.CLEAR);
- }
- }
- BOOL I2C_GetStatus(I2C0_Type* I2Cx, uint32_t Status) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
- assert_param(IS_I2C_STATUS(Status));
-
- if (0 != (I2Cx->STATUS & Status)) {
- return TRUE;
- }
-
- return FALSE;
- }
- void I2C_ClearStatus(I2C0_Type* I2Cx, uint32_t Status) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
- assert_param(IS_I2C_STATUS(Status));
-
- if (Status & I2C_STATUS_RX_FIFO_NOT_EMPTY) {
- // It can't be clear by sw but read
- }
-
- if (Status & I2C_STATUS_RD_REQUEST) {
- i2c_ReadClear(I2Cx->CLR_RD_REQ_b.CLEAR);
- }
-
- if (Status & I2C_STATUS_TX_ABORT) {
- i2c_ReadClear(I2Cx->CLR_TX_ABRT_b.CLEAR);
- }
-
- if (Status & I2C_STATUS_RX_DONE) {
- i2c_ReadClear(I2Cx->CLR_RX_DONE_b.CLEAR);
- }
-
- if (Status & I2C_STATUS_TX_DONE) {
- i2c_ReadClear(I2Cx->CLR_TX_DONE_b.CLEAR);
- }
- }
- BOOL I2C_MasterReadReq(I2C0_Type* I2Cx, uint8_t size) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
-
- if (!I2Cx->ENABLE_b.EN || I2Cx->STATUS_b.BUSY) {
- return FALSE;
- }
- if (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) {
- return FALSE;
- }
-
- if (size == 0) {
- return FALSE;
- }
-
- I2Cx->WRITE_READ_CNT_b.RD_BYTE_CNT = size;
- if (size != 0) {
- I2C_INNER_DATA_CMD inner;
-
- inner.INNER.DATA_CMD_b.DATA = 0;
- inner.INNER.DATA_CMD_b.RD_CMD = TRUE;
- inner.INNER.DATA_CMD_b.WR_CMD = FALSE;
- inner.INNER.DATA_CMD_b.WR_RD_CMD = FALSE;
-
- I2Cx->DATA_CMD = inner.INNER.DATA_CMD;
- }
-
- return TRUE;
- }
- uint8_t I2C_ReadFifo(I2C0_Type* I2Cx, uint8_t size, uint8_t* data) {
- uint8_t count;
-
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
- assert_param(data);
-
- if (!I2Cx->ENABLE_b.EN) {
- return 0;
- }
-
- count = 0;
- while (I2Cx->STATUS_b.RX_FIFO_NOT_EMPTY && count < size) {
- *(data + count++) = I2Cx->DATA_CMD_b.DATA;
- }
-
- return count;
- }
- BOOL I2C_WriteReq(I2C0_Type* I2Cx, uint8_t size, uint8_t firstData) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
-
- if (!I2Cx->ENABLE_b.EN || I2Cx->STATUS_b.BUSY) {
- return FALSE;
- }
-
- if (size == 0) {
- return FALSE;
- }
-
- I2Cx->WRITE_READ_CNT_b.WR_BYTE_CNT = size;
- if (size != 0) {
- I2C_INNER_DATA_CMD inner;
-
- inner.INNER.DATA_CMD_b.DATA = firstData ;
- inner.INNER.DATA_CMD_b.RD_CMD = FALSE;
- inner.INNER.DATA_CMD_b.WR_CMD =
- (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) ? FALSE : TRUE;
- inner.INNER.DATA_CMD_b.WR_RD_CMD = FALSE;
- I2Cx->DATA_CMD = inner.INNER.DATA_CMD;
- }
- return TRUE;
- }
- uint8_t I2C_WriteFifo(I2C0_Type* I2Cx, uint8_t size, uint8_t* data) {
- uint8_t count;
-
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
- assert_param(data);
-
- if (!I2Cx->ENABLE_b.EN) {
- return 0;
- }
- count = 0;
- while (I2Cx->STATUS_b.TX_FIFO_NOT_FULL && count < size) {
- I2Cx->DATA_CMD_b.DATA = *(data + count++);
- }
-
- return count;
- }
- BOOL I2C_StopReq(I2C0_Type* I2Cx) {
- assert_param(IS_I2C_ALL_PERIPH(I2Cx));
-
- udelay(600);
-
- return TRUE;
- }
|