feat add i2c driver for hc32f4a0 board

This commit is contained in:
Liu_Weichao 2022-12-05 11:01:47 +08:00
parent e5bf0cee41
commit d0902ca37f
16 changed files with 587 additions and 12 deletions

View File

@ -478,7 +478,7 @@ static x_err_t I2cBitSendAddress(struct I2cBus *bus, struct I2cDataStandard *msg
retries = ignore_nack ? 0 : msg->retries;
if (flags & I2C_ADDR_10BIT) {
if (flags & I2C_ADDR_10BIT_MODE) {
addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
addr2 = msg->addr & 0xff;

View File

@ -385,7 +385,7 @@ static x_err_t I2cBitSendAddress(struct I2cBus *bus, struct I2cDataStandard *msg
retries = ignore_nack ? 0 : msg->retries;
if (flags & I2C_ADDR_10BIT) {
if (flags & I2C_ADDR_10BIT_MODE) {
addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
addr2 = msg->addr & 0xff;

View File

@ -376,7 +376,7 @@ static x_err_t I2cBitSendAddress(struct I2cBus *bus, struct I2cDataStandard *msg
retries = ignore_nack ? 0 : msg->retries;
if (flags & I2C_ADDR_10BIT) {
if (flags & I2C_ADDR_10BIT_MODE) {
addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
addr2 = msg->addr & 0xff;

View File

@ -42,6 +42,10 @@ Modification:
#include <connect_spi.h>
#endif
#ifdef BSP_USING_I2C
#include <connect_i2c.h>
#endif
#ifdef BSP_USING_USB
#include <connect_usb.h>
#endif
@ -151,6 +155,9 @@ struct InitSequenceDesc _board_init[] =
#ifdef BSP_USING_SPI
{ "spi", HwSpiInit },
#endif
#ifdef BSP_USING_I2C
{ "i2c", HwI2cInit },
#endif
#ifdef BSP_USING_USB
{ "usb", HwUsbHostInit },
#endif

View File

@ -14,6 +14,14 @@ menuconfig BSP_USING_SPI
source "$BSP_DIR/third_party_driver/spi/Kconfig"
endif
menuconfig BSP_USING_I2C
bool "Using I2C device"
default n
select RESOURCES_I2C
if BSP_USING_I2C
source "$BSP_DIR/third_party_driver/i2c/Kconfig"
endif
menuconfig BSP_USING_SDIO
bool "Using SD CARD device"
default n

View File

@ -8,6 +8,10 @@ ifeq ($(CONFIG_BSP_USING_SPI),y)
SRC_DIR += spi
endif
ifeq ($(CONFIG_BSP_USING_I2C),y)
SRC_DIR += i2c
endif
ifeq ($(CONFIG_BSP_USING_SDIO),y)
SRC_DIR += sdio
endif

View File

@ -12,6 +12,10 @@ ifeq ($(CONFIG_BSP_USING_SPI),y)
SRC_FILES += hc32_ll_spi.c
endif
ifeq ($(CONFIG_BSP_USING_I2C),y)
SRC_FILES += hc32_ll_i2c.c
endif
ifeq ($(CONFIG_BSP_USING_USB),y)
SRC_FILES += hc32_ll_usb.c
endif

View File

@ -0,0 +1,22 @@
config I2C_BUS_NAME_1
string "i2c 1 bus name"
default "i2c1"
config I2C_DRV_NAME_1
string "i2c bus 1 driver name"
default "i2c1_drv"
config I2C_1_DEVICE_NAME_0
string "i2c bus 1 device 0 name"
default "i2c1_dev0"
config I2C_DEVICE_MODE
bool "choose i2c device mode as master or slave"
default y
choice
prompt "choose i2c mode"
default I2C_DEVICE_MASTER
config I2C_DEVICE_MASTER
bool "set i2c master"
config I2C_DEVICE_SLAVE
bool "set i2c slave"
endchoice

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_i2c.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,485 @@
/*
*******************************************************************************
* Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/**
* @file connect_i2c.c
* @brief support hc32f4a0-board i2c function and register to bus framework
* @version 3.0
* @author AIIT XUOS Lab
* @date 2022-12-05
*/
/*************************************************
File name: connect_i2c.c
Description: support hc32f4a0-board i2c configure and i2c bus register function
Others: take projects/ev_hc32f4a0_lqfp176/examples/i2c/i2c_master_polling/source/main.c for references
History:
1. Date: 2022-12-05
Author: AIIT XUOS Lab
Modification:
1. support hc32f4a0-board i2c configure, write and read
2. support hc32f4a0-board i2c bus device and driver register
*************************************************/
#include <connect_i2c.h>
#define I2C_UNIT (CM_I2C1)
#define I2C_FCG_USE (FCG1_PERIPH_I2C1)
#define I2C_TIMEOUT (0x40000UL)
#define I2C_BAUDRATE (400000UL)
/* Define port and pin for SDA and SCL */
#define I2C_SCL_PORT (GPIO_PORT_D)
#define I2C_SCL_PIN (GPIO_PIN_03)
#define I2C_SDA_PORT (GPIO_PORT_F)
#define I2C_SDA_PIN (GPIO_PIN_10)
#define I2C_GPIO_SCL_FUNC (GPIO_FUNC_49)
#define I2C_GPIO_SDA_FUNC (GPIO_FUNC_48)
static x_err_t I2cGpioInit(void)
{
GPIO_SetFunc(I2C_SDA_PORT, I2C_SDA_PIN, I2C_GPIO_SDA_FUNC);
GPIO_SetFunc(I2C_SCL_PORT, I2C_SCL_PIN, I2C_GPIO_SCL_FUNC);
return EOK;
}
static uint32 I2cInit(struct I2cDriver *i2c_drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(i2c_drv);
struct I2cHardwareDevice *i2c_dev = (struct I2cHardwareDevice *)i2c_drv->driver.owner_bus->owner_haldev;
stc_i2c_init_t i2c_init;
(void)I2C_StructInit(&i2c_init);
i2c_init.u32Baudrate = I2C_BAUDRATE;
i2c_init.u32SclTime = 3UL;
i2c_init.u32ClockDiv = I2C_CLK_DIV4;
if (configure_info->private_data) {
i2c_dev->i2c_dev_addr = *((uint16 *)configure_info->private_data);
} else {
KPrintf("I2cInit need set i2c dev addr\n");
return ERROR;
}
/* Configure I2C */
float32_t f32Error;
int32_t i32Ret = LL_ERR;
I2C_DeInit(I2C_UNIT);
i32Ret = I2C_Init(I2C_UNIT, &i2c_init, &f32Error);
#ifdef I2C_DEVICE_SLAVE
if (LL_OK == i32Ret) {
/* Set slave address */
I2C_SlaveAddrConfig(I2C_UNIT, I2C_ADDR0, I2C_ADDR_7BIT, i2c_dev->i2c_dev_addr);
}
#endif
if(i32Ret != LL_OK) {
return ERROR;
}
I2C_BusWaitCmd(I2C_UNIT, ENABLE);
return EOK;
}
static uint32 I2cDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
struct I2cDriver *i2c_drv = (struct I2cDriver *)drv;
switch (configure_info->configure_cmd)
{
case OPE_INT:
ret = I2cInit(i2c_drv, configure_info);
break;
default:
break;
}
return ret;
}
static uint32 I2cMasterWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
{
uint32 i32Ret;
I2C_Cmd(I2C_UNIT, ENABLE);
DDL_DelayMS(20UL);
I2C_SWResetCmd(I2C_UNIT, ENABLE);
I2C_SWResetCmd(I2C_UNIT, DISABLE);
DDL_DelayMS(20UL);
i32Ret = I2C_Start(I2C_UNIT, I2C_TIMEOUT);
if (LL_OK == i32Ret) {
i32Ret = I2C_TransAddr(I2C_UNIT, i2c_dev->i2c_dev_addr, I2C_DIR_TX, I2C_TIMEOUT);
if (i32Ret == LL_OK) {
i32Ret = I2C_TransData(I2C_UNIT, msg->buf, msg->len, I2C_TIMEOUT);
KPrintf("Master Send Success!\n");
}
}
(void)I2C_Stop(I2C_UNIT, I2C_TIMEOUT);
I2C_Cmd(I2C_UNIT, DISABLE);
return i32Ret;
}
static uint32 I2cMasterReadData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
{
uint32 i32Ret;
I2C_Cmd(I2C_UNIT, ENABLE);
I2C_SWResetCmd(I2C_UNIT, ENABLE);
I2C_SWResetCmd(I2C_UNIT, DISABLE);
i32Ret = I2C_Start(I2C_UNIT, I2C_TIMEOUT);
if (LL_OK == i32Ret) {
if (msg->len == 1U) {
I2C_AckConfig(I2C_UNIT, I2C_NACK);
}
i32Ret = I2C_TransAddr(I2C_UNIT, i2c_dev->i2c_dev_addr, I2C_DIR_RX, I2C_TIMEOUT);
if (LL_OK == i32Ret) {
i32Ret = I2C_MasterReceiveDataAndStop(I2C_UNIT, msg->buf, msg->len, I2C_TIMEOUT);
KPrintf("Master Receive Success!\n");
}
I2C_AckConfig(I2C_UNIT, I2C_ACK);
}
if (LL_OK != i32Ret) {
(void)I2C_Stop(I2C_UNIT, I2C_TIMEOUT);
}
I2C_Cmd(I2C_UNIT, DISABLE);
return i32Ret;
}
static uint32 I2cSlaveWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg) {
uint32 i32Ret;
I2C_Cmd(I2C_UNIT, ENABLE);
/* Clear status */
I2C_ClearStatus(I2C_UNIT, I2C_CLR_STOPFCLR | I2C_CLR_NACKFCLR);
/* Wait slave address matched */
while (RESET == I2C_GetStatus(I2C_UNIT, I2C_FLAG_MATCH_ADDR0)) {
;
}
I2C_ClearStatus(I2C_UNIT, I2C_CLR_SLADDR0FCLR);
if (RESET == I2C_GetStatus(I2C_UNIT, I2C_FLAG_TRA)) {
i32Ret = LL_ERR;
} else {
i32Ret = I2C_TransData(I2C_UNIT, msg->buf, msg->len, I2C_TIMEOUT);
KPrintf("Slave send success!\r\n");
if ((LL_OK == i32Ret) || (LL_ERR_TIMEOUT == i32Ret)) {
/* Release SCL pin */
(void)I2C_ReadData(I2C_UNIT);
/* Wait stop condition */
i32Ret = I2C_WaitStatus(I2C_UNIT, I2C_FLAG_STOP, SET, I2C_TIMEOUT);
}
}
I2C_Cmd(I2C_UNIT, DISABLE);
return i32Ret;
}
static uint32 I2cSlaveReadData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg) {
uint32 i32Ret;
I2C_Cmd(I2C_UNIT, ENABLE);
/* Clear status */
I2C_ClearStatus(I2C_UNIT, I2C_CLR_STOPFCLR | I2C_CLR_NACKFCLR);
/* Wait slave address matched */
while (RESET == I2C_GetStatus(I2C_UNIT, I2C_FLAG_MATCH_ADDR0)) {
;
}
I2C_ClearStatus(I2C_UNIT, I2C_CLR_SLADDR0FCLR);
if (RESET == I2C_GetStatus(I2C_UNIT, I2C_FLAG_TRA)) {
/* Slave receive data*/
i32Ret = I2C_ReceiveData(I2C_UNIT, msg->buf, msg->len, I2C_TIMEOUT);
KPrintf("Slave receive success!\r\n");
if ((LL_OK == i32Ret) || (LL_ERR_TIMEOUT == i32Ret)) {
/* Wait stop condition */
i32Ret = I2C_WaitStatus(I2C_UNIT, I2C_FLAG_STOP, SET, I2C_TIMEOUT);
}
} else {
i32Ret = LL_ERR;
}
I2C_Cmd(I2C_UNIT, DISABLE);
return i32Ret;
}
/* manage the i2c device operations*/
static const struct I2cDevDone i2c_dev_done =
{
.dev_open = NONE,
.dev_close = NONE,
#ifdef I2C_DEVICE_SLAVE
.dev_write = I2cSlaveWriteData,
.dev_read = I2cSlaveReadData,
#else
.dev_write = I2cMasterWriteData,
.dev_read = I2cMasterReadData,
#endif
};
/* Init i2c bus */
static int BoardI2cBusInit(struct I2cBus *i2c_bus, struct I2cDriver *i2c_driver)
{
x_err_t ret = EOK;
/* Init the i2c bus */
ret = I2cBusInit(i2c_bus, I2C_BUS_NAME_1);
if (EOK != ret) {
KPrintf("board_i2c_init I2cBusInit error %d\n", ret);
return ERROR;
}
/* Init the i2c driver*/
ret = I2cDriverInit(i2c_driver, I2C_DRV_NAME_1);
if (EOK != ret) {
KPrintf("board_i2c_init I2cDriverInit error %d\n", ret);
return ERROR;
}
/* Attach the i2c driver to the i2c bus*/
ret = I2cDriverAttachToBus(I2C_DRV_NAME_1, I2C_BUS_NAME_1);
if (EOK != ret) {
KPrintf("board_i2c_init I2cDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/* Attach the i2c device to the i2c bus*/
static int BoardI2cDevBend(void)
{
x_err_t ret = EOK;
static struct I2cHardwareDevice i2c_device0;
memset(&i2c_device0, 0, sizeof(struct I2cHardwareDevice));
i2c_device0.i2c_dev_done = &i2c_dev_done;
ret = I2cDeviceRegister(&i2c_device0, NONE, I2C_1_DEVICE_NAME_0);
if (EOK != ret) {
KPrintf("board_i2c_init I2cDeviceInit device %s error %d\n", I2C_1_DEVICE_NAME_0, ret);
return ERROR;
}
ret = I2cDeviceAttachToBus(I2C_1_DEVICE_NAME_0, I2C_BUS_NAME_1);
if (EOK != ret) {
KPrintf("board_i2c_init I2cDeviceAttachToBus device %s error %d\n", I2C_1_DEVICE_NAME_0, ret);
return ERROR;
}
return ret;
}
/* HC32F4A0 BOARD I2C INIT*/
int HwI2cInit(void)
{
x_err_t ret = EOK;
static struct I2cBus i2c_bus;
memset(&i2c_bus, 0, sizeof(struct I2cBus));
static struct I2cDriver i2c_driver;
memset(&i2c_driver, 0, sizeof(struct I2cDriver));
I2cGpioInit();
/* Enable I2C Peripheral*/
FCG_Fcg1PeriphClockCmd(I2C_FCG_USE, ENABLE);
i2c_driver.configure = I2cDrvConfigure;
ret = BoardI2cBusInit(&i2c_bus, &i2c_driver);
if (ret != EOK) {
KPrintf("board_i2c_init error ret %u\n", ret);
return ERROR;
}
ret = BoardI2cDevBend();
if (EOK != ret) {
KPrintf("board_i2c_init error ret %u\n", ret);
return ERROR;
}
return ret;
}
//#define I2C_TEST
#ifdef I2C_TEST
#define USER_KEY_PORT (GPIO_PORT_I)
#define USER_KEY_PIN (GPIO_PIN_07)
#define DEVICE_ADDR (0x06U)
static struct Bus *bus1;
static struct I2cDriver *i2c_drv1;
void I2cInitTest(void)
{
x_err_t ret = EOK;
stc_gpio_init_t stcGpioInit;
/* KEY initialize */
(void)GPIO_StructInit(&stcGpioInit);
stcGpioInit.u16PinState = PIN_STAT_RST;
stcGpioInit.u16PinDir = PIN_DIR_IN;
(void)GPIO_Init(USER_KEY_PORT, USER_KEY_PIN, &stcGpioInit);
bus1 = BusFind(I2C_BUS_NAME_1);
bus1->owner_driver = BusFindDriver(bus1, I2C_DRV_NAME_1);
bus1->owner_haldev = BusFindDevice(bus1, I2C_1_DEVICE_NAME_0);
struct BusConfigureInfo configure_info;
configure_info.configure_cmd = OPE_INT;
configure_info.private_data = (void *)DEVICE_ADDR;
ret = I2cDrvConfigure(bus1->owner_driver, &configure_info);
if (ret != EOK) {
KPrintf("initialize %s failed!\n", I2C_UNIT);
return;
}
i2c_drv1 = (struct I2cDriver *)bus1->owner_driver;
return;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
I2cInitTest, I2cInitTest, i2c init);
void I2cMasterTest(void)
{
x_err_t ret = EOK;
struct I2cHardwareDevice *i2c_dev1 = (struct I2cHardwareDevice *)i2c_drv1->driver.owner_bus->owner_haldev;
struct I2cDataStandard msg;
uint8 u8TxBuf[256U] = {1, 2, 3, 4, 5};
uint8 u8RxBuf[256U];
(void)memset(u8RxBuf, 0, 256U);
msg.len = 5;
msg.buf = u8TxBuf;
while (SET == GPIO_ReadInputPins(USER_KEY_PORT, USER_KEY_PIN)) {
;
}
KPrintf("I2C send data\n");
ret = I2cMasterWriteData(i2c_dev1, &msg);
if (EOK != ret) {
KPrintf("I2C send failed! ret %d\n", ret);
return;
}
KPrintf("Master send data: ");
for (uint16 i = 0; i < msg.len; i++) {
KPrintf("%d ", (msg.buf)[i]);
}
KPrintf("\n");
/* 50mS delay for device*/
DDL_DelayMS(50UL);
msg.buf = u8RxBuf;
(void)I2cMasterReadData(i2c_dev1, &msg);
KPrintf("Master receive data: ");
for (uint16 i = 0; i < msg.len; i++) {
KPrintf("%d ", (msg.buf)[i]);
}
KPrintf("\n");
return;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
I2cMasterTest, I2cMasterTest, i2c master send and receive data);
void I2cSlaveTest(void)
{
x_err_t ret = EOK;
struct I2cHardwareDevice *i2c_dev1 = (struct I2cHardwareDevice *)i2c_drv1->driver.owner_bus->owner_haldev;
struct I2cDataStandard msg;
uint8 u8RxBuf[256U];
(void)memset(u8RxBuf, 0, 256U);
msg.len = 5;
msg.buf = u8RxBuf;
KPrintf("I2C receive data\n");
for (;;) {
ret = I2cSlaveReadData(i2c_dev1, &msg);
if (ret != EOK) {
KPrintf("I2C receive failed!\n");
break;
} else {
KPrintf("Slave receive data: ");
for (uint16 i = 0; i < msg.len; i++) {
KPrintf("%d ", (msg.buf)[i]);
}
KPrintf("\n");
}
ret = I2cSlaveWriteData(i2c_dev1, &msg);
if (ret != EOK) {
KPrintf("I2C send failed!\n");
break;
} else {
KPrintf("Slave send data: ");
for (uint16 i = 0; i < msg.len; i++) {
KPrintf("%d ", (msg.buf)[i]);
}
KPrintf("\n");
}
}
return;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
I2cSlaveTest, I2cSlaveTest, i2c slave receive and send data);
#endif

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_i2c.h
* @brief define hc32f4a0-board i2c function and struct
* @version 3.0
* @author AIIT XUOS Lab
* @date 2022-12-05
*/
#ifndef CONNECT_I2C_H
#define CONNECT_I2C_H
#include <device.h>
#include <hc32_ll.h>
#include <hc32_ll_i2c.h>
#include <hc32_ll_utility.h>
#include <hc32_ll_fcg.h>
#include <hc32_ll_gpio.h>
#include <hc32_ll_def.h>
#ifdef __cplusplus
extern "C" {
#endif
int HwI2cInit(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -376,7 +376,7 @@ static x_err_t I2cBitSendAddress(struct I2cBus *bus, struct I2cDataStandard *msg
retries = ignore_nack ? 0 : msg->retries;
if (flags & I2C_ADDR_10BIT) {
if (flags & I2C_ADDR_10BIT_MODE) {
addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
addr2 = msg->addr & 0xff;

View File

@ -376,7 +376,7 @@ static x_err_t I2cBitSendAddress(struct I2cBus *bus, struct I2cDataStandard *msg
retries = ignore_nack ? 0 : msg->retries;
if (flags & I2C_ADDR_10BIT) {
if (flags & I2C_ADDR_10BIT_MODE) {
addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
addr2 = msg->addr & 0xff;

View File

@ -479,7 +479,7 @@ static x_err_t I2cBitSendAddress(struct I2cBus *bus, struct I2cDataStandard *msg
retries = ignore_nack ? 0 : msg->retries;
if (flags & I2C_ADDR_10BIT) {
if (flags & I2C_ADDR_10BIT_MODE) {
addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
addr2 = msg->addr & 0xff;

View File

@ -376,7 +376,7 @@ static x_err_t I2cBitSendAddress(struct I2cBus *bus, struct I2cDataStandard *msg
retries = ignore_nack ? 0 : msg->retries;
if (flags & I2C_ADDR_10BIT) {
if (flags & I2C_ADDR_10BIT_MODE) {
addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
addr2 = msg->addr & 0xff;

View File

@ -27,12 +27,12 @@
extern "C" {
#endif
#define I2C_WR 0x0000
#define I2C_RD (1u << 0)
#define I2C_ADDR_10BIT (1u << 2)
#define I2C_NO_START (1u << 4)
#define I2C_WR 0x0000
#define I2C_RD (1u << 0)
#define I2C_ADDR_10BIT_MODE (1u << 2)
#define I2C_NO_START (1u << 4)
#define I2C_IGNORE_NACK (1u << 5)
#define I2C_NO_READ_ACK (1u << 6)
#define I2C_NO_READ_ACK (1u << 6)
struct I2cDataStandard
{