123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- /*
- * Copyright (c) 2006-2024, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-4-1 IceBear003 the first version
- */
- #include "board.h"
- #include "drv_i2c.h"
- #ifdef BSP_USING_HWI2C
- #define LOG_TAG "drv.hwi2c"
- #include "drv_log.h"
- #if !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2)
- #error "Please define at least one BSP_USING_I2Cx"
- /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
- #endif
- #define TIMEOUT 0xFF
- #ifdef BSP_USING_I2C1
- struct i2c_bus_device i2c_bus1;
- #endif
- #ifdef BSP_USING_I2C2
- struct i2c_bus_device i2c_bus2;
- #endif
- static int i2c_read(I2C_TypeDef *i2c_periph,
- rt_uint16_t addr,
- rt_uint8_t flags,
- rt_uint16_t len,
- rt_uint8_t *buf)
- {
- rt_uint16_t try = 0;
- while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_BUSY))
- if (try++ >= TIMEOUT) return -1;
- I2C_GenerateSTART(i2c_periph, ENABLE);
- try = 0;
- while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT)) //EVT5
- if (try++ >= TIMEOUT) return -1;
- if(flags & RT_I2C_ADDR_10BIT) //10-bit address mode
- {
- rt_uint8_t frame_head = 0xF0 + (addr >> 8) << 1; //11110XX0
- I2C_SendData(i2c_periph, frame_head); //FrameHead
- try = 0;
- while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_ADDRESS10)) //EVT9
- if (try++ >= TIMEOUT) return -1;
- I2C_SendData(i2c_periph,0xff & addr);
- try = 0;
- while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //EVT6
- if (try++ >= TIMEOUT) return -1;
- I2C_GenerateSTART(i2c_periph, ENABLE); //Sr
- try = 0;
- while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT)) //EVT5
- if (try++ >= TIMEOUT) return -1;
- I2C_SendData(i2c_periph,frame_head); //Resend FrameHead
- }
- else
- {
- I2C_Send7bitAddress(i2c_periph, addr << 1, I2C_Direction_Receiver);
- }
- try = 0;
- while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) //EVT6
- if (try++ >= TIMEOUT) return -1;
- while(len-- > 0)
- {
- try = 0;
- while (!I2C_GetFlagStatus(i2c_periph, I2C_FLAG_RXNE)) //Got ACK For the Last Byte
- if (try++ >= TIMEOUT) return -1;
- *(buf++)=I2C_ReceiveData(i2c_periph);
- }
- I2C_GenerateSTOP(i2c_periph, ENABLE);
- }
- static int i2c_write(I2C_TypeDef *i2c_periph,
- rt_uint16_t addr,
- rt_uint8_t flags,
- rt_uint8_t *buf,
- rt_uint16_t len)
- {
- rt_uint16_t try = 0;
- while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_BUSY))
- if (try++ >= TIMEOUT) return -1;
- I2C_GenerateSTART(i2c_periph, ENABLE);
- try = 0;
- while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT)) //EVT5
- if (try++ >= TIMEOUT) return -1;
- if(flags & RT_I2C_ADDR_10BIT) //10-bit address mode
- {
- I2C_SendData(i2c_periph,0xF0 + (addr >> 8) << 1); //FrameHead 11110XX0
- try = 0;
- while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_ADDRESS10)) //EVT9
- if (try++ >= TIMEOUT) return -1;
- I2C_SendData(i2c_periph,0xff & addr);
- }
- else //7-bit address mode
- {
- I2C_Send7bitAddress(i2c_periph, addr << 1, I2C_Direction_Transmitter);
- }
- try = 0;
- while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //EVT6
- if (try++ >= TIMEOUT) return -1;
- //Missing Evt8_1 (No definition)
- while(len-- > 0)
- {
- try = 0;
- while (!I2C_GetFlagStatus(i2c_periph, I2C_FLAG_TXE)) //Got ACK For the Last Byte
- if (try++ >= TIMEOUT) return -1;
- I2C_SendData(i2c_periph,*(buf++));
- }
- try = 0;
- while(!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) //Last byte sent successfully
- if (try++ >= TIMEOUT) return -1;
- I2C_GenerateSTOP(i2c_periph, ENABLE);
- }
- rt_size_t i2c_master_xfer(struct rt_i2c_bus_device *bus,
- struct rt_i2c_msg msgs[],
- rt_uint32_t num)
- {
- struct rt_i2c_msg *msg;
- struct i2c_bus_device *i2c_bus_dev;
- rt_uint32_t index;
- i2c_bus_dev = (struct i2c_bus_device *)bus;
- for (index = 0; index < num; index++)
- {
- msg = &msgs[index];
- if (msg->flags & RT_I2C_RD)
- {
- i2c_read(i2c_bus_dev->periph,
- msg->addr,
- msg->flags,
- msg->len,
- msg->buf);
- }
- else
- {
- i2c_write(i2c_bus_dev->periph,
- msg->addr,
- msg->flags,
- msg->buf,
- msg->len);
- }
- }
- return index;
- }
- static const struct rt_i2c_bus_device_ops ch32_i2c_ops =
- {
- .master_xfer = i2c_master_xfer,
- .slave_xfer = RT_NULL, //Not Used in i2c_core?
- .i2c_bus_control = RT_NULL
- };
- int rt_hw_i2c_init(struct i2c_config *config = &{5000, I2C_DutyCycle_2, 0, I2C_Ack_Disable, I2C_AcknowledgedAddress_7bit})
- {
- int result = RT_EOK;
- GPIO_InitTypeDef GPIO_InitStructure = {0};
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
- I2C_InitTypeDef I2C_InitTSturcture = {0};
- I2C_StructInit(&I2C_InitTSturcture);
- I2C_InitTSturcture.I2C_ClockSpeed = config->clock_speed;
- I2C_InitTSturcture.I2C_DutyCycle = config->duty_cycle;
- I2C_InitTSturcture.I2C_OwnAddress1 = config->own_address;
- I2C_InitTSturcture.I2C_Ack = config->enable_ack ? I2C_Ack_Enable : I2C_Ack_Disable;
- I2C_InitTSturcture.I2C_AcknowledgedAddress = config->is_7_bit_address ? I2C_AcknowledgedAddress_7bit : I2C_AcknowledgedAddress_10bit;
- #ifdef BSP_USING_I2C1
- i2c_bus1.periph = I2C1;
- //Clock & IO Initialization
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);
- //I2C Initialization Config
- I2C_Init(I2C1, &I2C_InitTSturcture);
- I2C_Cmd(I2C1, ENABLE);
- //Hook to RT-Thread
- i2c_bus1.parent.ops = &ch32_i2c_ops;
- result += rt_i2c_bus_device_register(&i2c_bus1.parent, "i2c1");
- #endif
- #ifdef BSP_USING_I2C2
- i2c_bus2.periph = I2C2;
- //Clock & IO Initialization
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- //I2C Initialization Config
- I2C_Init(I2C2, &I2C_InitTSturcture);
- I2C_Cmd(I2C2, ENABLE);
- //Hook to RT-Thread
- i2c_bus2.parent.ops = &ch32_i2c_ops;
- result += rt_i2c_bus_device_register(&i2c_bus2.parent, "i2c2");
- #endif
- return result;
- }
- #endif //BSP_USING_HWI2C
|