Skip to content

Commit 8524781

Browse files
hengchuan.qimysterywolf
hengchuan.qi
authored andcommitted
[bsp][mcxn236] Add software i2c driver.
1 parent 053373c commit 8524781

File tree

3 files changed

+253
-0
lines changed

3 files changed

+253
-0
lines changed

bsp/nxp/mcx/mcxn/Libraries/drivers/SConscript

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ if GetDepend('BSP_USING_SDIO'):
2222
if GetDepend('BSP_USING_I2C'):
2323
src += ['drv_i2c.c']
2424

25+
if GetDepend('BSP_USING_SW_I2C'):
26+
src += ['drv_soft_i2c.c']
27+
2528
if GetDepend('BSP_USING_ADC'):
2629
src += ['drv_adc.c']
2730

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/*
2+
* Copyright (c) 2006-2024 RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2024-06-25 Andeyqi the first version
9+
*/
10+
#include <rtthread.h>
11+
#include <rthw.h>
12+
#include <rtdevice.h>
13+
#include <board.h>
14+
15+
#ifdef BSP_USING_SW_I2C
16+
17+
#define LOG_TAG "drv.i2c"
18+
#include <rtdbg.h>
19+
20+
/* MCXNXXX config class */
21+
struct mcxnxxx_soft_i2c_config
22+
{
23+
rt_uint8_t scl;
24+
rt_uint8_t sda;
25+
const char *bus_name;
26+
};
27+
28+
/* MCXNXXX i2c dirver class */
29+
struct mcxnxxx_i2c
30+
{
31+
struct rt_i2c_bit_ops ops;
32+
struct rt_i2c_bus_device i2c2_bus;
33+
};
34+
35+
#if defined(BSP_USING_SW_I2C0)
36+
#define SW_I2C0_BUS_CONFIG \
37+
{ \
38+
.scl = BSP_SW_I2C0_SCL_PIN, \
39+
.sda = BSP_SW_I2C0_SDA_PIN, \
40+
.bus_name = "swi2c0", \
41+
}
42+
#endif
43+
44+
static const struct mcxnxxx_soft_i2c_config soft_i2c_config[] =
45+
{
46+
#if defined(BSP_USING_SW_I2C0)
47+
SW_I2C0_BUS_CONFIG,
48+
#endif
49+
};
50+
51+
static struct mcxnxxx_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])];
52+
53+
/**
54+
* @brief This function initializes the i2c pin.
55+
* @param i2c
56+
* @retval None
57+
*/
58+
static void mcxnxxx_i2c_gpio_init(struct mcxnxxx_i2c *i2c)
59+
{
60+
struct mcxnxxx_soft_i2c_config* cfg = (struct mcxnxxx_soft_i2c_config*)i2c->ops.data;
61+
62+
rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
63+
rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
64+
65+
rt_pin_write(cfg->scl, PIN_HIGH);
66+
rt_pin_write(cfg->sda, PIN_HIGH);
67+
}
68+
69+
/**
70+
* @brief This function sets the sda pin.
71+
* @param data, state
72+
* @retval None
73+
*/
74+
static void mcxnxxx_set_sda(void *data, rt_int32_t state)
75+
{
76+
struct mcxnxxx_soft_i2c_config* cfg = (struct mcxnxxx_soft_i2c_config*)data;
77+
78+
rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);
79+
80+
if (state)
81+
{
82+
rt_pin_write(cfg->sda, PIN_HIGH);
83+
}
84+
else
85+
{
86+
rt_pin_write(cfg->sda, PIN_LOW);
87+
}
88+
}
89+
90+
/**
91+
* @brief This function sets the scl pin.
92+
* @param data, state
93+
* @retval None
94+
*/
95+
static void mcxnxxx_set_scl(void *data, rt_int32_t state)
96+
{
97+
struct mcxnxxx_soft_i2c_config* cfg = (struct mcxnxxx_soft_i2c_config*)data;
98+
99+
rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD);
100+
101+
if (state)
102+
{
103+
rt_pin_write(cfg->scl, PIN_HIGH);
104+
}
105+
else
106+
{
107+
rt_pin_write(cfg->scl, PIN_LOW);
108+
}
109+
}
110+
111+
/**
112+
* @brief This function gets the sda pin state.
113+
* @param data
114+
* @retval None
115+
*/
116+
static rt_int32_t mcxnxxx_get_sda(void *data)
117+
{
118+
struct mcxnxxx_soft_i2c_config* cfg = (struct mcxnxxx_soft_i2c_config*)data;
119+
120+
rt_pin_mode(cfg->sda, PIN_MODE_INPUT);
121+
122+
return rt_pin_read(cfg->sda);
123+
}
124+
125+
126+
/**
127+
* @brief This function gets the scl pin state.
128+
* @param data
129+
* @retval None
130+
*/
131+
static rt_int32_t mcxnxxx_get_scl(void *data)
132+
{
133+
struct mcxnxxx_soft_i2c_config* cfg = (struct mcxnxxx_soft_i2c_config*)data;
134+
135+
rt_pin_mode(cfg->scl,PIN_MODE_INPUT);
136+
137+
return rt_pin_read(cfg->scl);
138+
}
139+
140+
/**
141+
* @brief The time delay function.
142+
* @param us
143+
* @retval None
144+
*/
145+
static void mcxnxxx_udelay(rt_uint32_t us)
146+
{
147+
rt_uint32_t frequency = CLOCK_GetCoreSysClkFreq();
148+
149+
int i = (frequency/ 4000000 * us);
150+
while(i)
151+
{
152+
i--;
153+
}
154+
}
155+
156+
static const struct rt_i2c_bit_ops mcxnxxx_bit_ops_default =
157+
{
158+
.data = RT_NULL,
159+
.set_sda = mcxnxxx_set_sda,
160+
.set_scl = mcxnxxx_set_scl,
161+
.get_sda = mcxnxxx_get_sda,
162+
.get_scl = mcxnxxx_get_scl,
163+
.udelay = mcxnxxx_udelay,
164+
.delay_us = 1,
165+
.timeout = 100
166+
};
167+
168+
/**
169+
* @brief if i2c is locked, this function will unlock it
170+
* @param cfg
171+
* @retval RT_EOK indicates successful unlock.
172+
*/
173+
static rt_err_t mcxnxxx_i2c_bus_unlock(const struct mcxnxxx_soft_i2c_config *cfg)
174+
{
175+
rt_int32_t i = 0;
176+
177+
if (PIN_LOW == rt_pin_read(cfg->sda))
178+
{
179+
while (i++ < 9)
180+
{
181+
rt_pin_write(cfg->scl, PIN_HIGH);
182+
mcxnxxx_udelay(100);
183+
rt_pin_write(cfg->scl, PIN_LOW);
184+
mcxnxxx_udelay(100);
185+
}
186+
}
187+
if (PIN_LOW == rt_pin_read(cfg->sda))
188+
{
189+
return -RT_ERROR;
190+
}
191+
192+
return RT_EOK;
193+
}
194+
195+
/**
196+
* @brief I2C initialization function
197+
* @param None
198+
* @retval RT_EOK indicates successful initialization.
199+
*/
200+
int rt_hw_soft_i2c_init(void)
201+
{
202+
rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct mcxnxxx_i2c);
203+
rt_err_t result;
204+
205+
for (int i = 0; i < obj_num; i++)
206+
{
207+
i2c_obj[i].ops = mcxnxxx_bit_ops_default;
208+
i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
209+
i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops;
210+
mcxnxxx_i2c_gpio_init(&i2c_obj[i]);
211+
212+
result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);
213+
214+
RT_ASSERT(result == RT_EOK);
215+
216+
mcxnxxx_i2c_bus_unlock(&soft_i2c_config[i]);
217+
218+
LOG_D("software simulation %s init done, pin scl: %d, pin sda %d",
219+
soft_i2c_config[i].bus_name,
220+
soft_i2c_config[i].scl,
221+
soft_i2c_config[i].sda);
222+
}
223+
224+
return RT_EOK;
225+
}
226+
INIT_APP_EXPORT(rt_hw_soft_i2c_init);
227+
228+
#endif /* RT_USING_I2C */

bsp/nxp/mcx/mcxn/frdm-mcxn236/board/Kconfig

+22
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ menu "On-chip Peripheral Drivers"
5353
default y
5454
endif
5555

56+
menuconfig BSP_USING_SW_I2C
57+
bool "Enable I2C BUS (software simulation)"
58+
default n
59+
select RT_USING_I2C
60+
select RT_USING_I2C_BITOPS
61+
select RT_USING_PIN
62+
if BSP_USING_SW_I2C
63+
config BSP_USING_SW_I2C0
64+
bool "Enable soft I2C0"
65+
default y
66+
if BSP_USING_SW_I2C0
67+
config BSP_SW_I2C0_SCL_PIN
68+
int "SWI2C0 scl pin number"
69+
range 0 159
70+
default 129
71+
config BSP_SW_I2C0_SDA_PIN
72+
int "SWI2C0 sda pin number"
73+
range 0 159
74+
default 128
75+
endif
76+
endif
77+
5678
menuconfig BSP_USING_SPI
5779
config BSP_USING_SPI
5880
bool "Enable SPI"

0 commit comments

Comments
 (0)