Skip to content

Commit f10c340

Browse files
committed
i2c: stm32_v2: implement slave support
This patch adds I2C Slave support conforming to the syscalls and funcs, only for the STM32 V2 I2C Driver for the moment. Signed-off-by: Neil Armstrong <[email protected]>
1 parent 4c0bcb4 commit f10c340

File tree

3 files changed

+170
-1
lines changed

3 files changed

+170
-1
lines changed

drivers/i2c/i2c_ll_stm32.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_I2C_LEVEL
1919
#include <logging/sys_log.h>
2020

21-
static int i2c_stm32_runtime_configure(struct device *dev, u32_t config)
21+
int i2c_stm32_runtime_configure(struct device *dev, u32_t config)
2222
{
2323
const struct i2c_stm32_config *cfg = DEV_CFG(dev);
2424
struct i2c_stm32_data *data = DEV_DATA(dev);
@@ -54,10 +54,16 @@ static int i2c_stm32_transfer(struct device *dev, struct i2c_msg *msg,
5454
u8_t num_msgs, u16_t slave)
5555
{
5656
const struct i2c_stm32_config *cfg = DEV_CFG(dev);
57+
struct i2c_stm32_data *data = DEV_DATA(dev);
5758
struct i2c_msg *current, *next;
5859
I2C_TypeDef *i2c = cfg->i2c;
5960
int ret = 0;
6061

62+
#if defined(CONFIG_I2C_SLAVE)
63+
if (data->slave_attached)
64+
return -EBUSY;
65+
#endif
66+
6167
LL_I2C_Enable(i2c);
6268

6369
current = msg;
@@ -120,6 +126,11 @@ static int i2c_stm32_transfer(struct device *dev, struct i2c_msg *msg,
120126
static const struct i2c_driver_api api_funcs = {
121127
.configure = i2c_stm32_runtime_configure,
122128
.transfer = i2c_stm32_transfer,
129+
#if defined(CONFIG_I2C_SLAVE) && defined(CONFIG_I2C_STM32_V2)
130+
.slave_is_supported = i2c_stm32_slave_is_supported,
131+
.slave_attach = i2c_stm32_slave_attach,
132+
.slave_detach = i2c_stm32_slave_detach,
133+
#endif
123134
};
124135

125136
static int i2c_stm32_init(struct device *dev)

drivers/i2c/i2c_ll_stm32.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,32 @@ struct i2c_stm32_data {
4040
unsigned int len;
4141
u8_t *buf;
4242
} current;
43+
#ifdef CONFIG_I2C_SLAVE
44+
const struct i2c_slave_api *slave_funcs;
45+
void *slave_priv;
46+
bool slave_attached;
47+
#endif
4348
};
4449

4550
s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, u8_t *flg,
4651
u16_t sadr);
4752
s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, u8_t *flg,
4853
u16_t sadr);
4954
s32_t stm32_i2c_configure_timing(struct device *dev, u32_t clk);
55+
int i2c_stm32_runtime_configure(struct device *dev, u32_t config);
5056

5157
void stm32_i2c_event_isr(void *arg);
5258
void stm32_i2c_error_isr(void *arg);
5359

60+
#if defined(CONFIG_I2C_SLAVE) && defined(CONFIG_I2C_STM32_V2)
61+
bool i2c_stm32_slave_is_supported(struct device *dev);
62+
int i2c_stm32_slave_attach(struct device *dev, u8_t address,
63+
const struct i2c_slave_api *funcs,
64+
void *priv);
65+
int i2c_stm32_slave_detach(struct device *dev, u8_t address,
66+
void *priv);
67+
#endif
68+
5469
#define DEV_DATA(dev) ((struct i2c_stm32_data * const)(dev)->driver_data)
5570
#define DEV_CFG(dev) \
5671
((const struct i2c_stm32_config * const)(dev)->config->config_info)

drivers/i2c/i2c_ll_stm32_v2.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <board.h>
1616
#include <errno.h>
1717
#include <i2c.h>
18+
#include "i2c-priv.h"
1819
#include "i2c_ll_stm32.h"
1920

2021
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_I2C_LEVEL
@@ -61,6 +62,70 @@ void stm32_i2c_event_isr(void *arg)
6162
struct i2c_stm32_data *data = DEV_DATA((struct device *)arg);
6263
I2C_TypeDef *i2c = cfg->i2c;
6364

65+
#if defined(CONFIG_I2C_SLAVE)
66+
if (data->slave_attached) {
67+
if (LL_I2C_IsActiveFlag_ADDR(i2c)) {
68+
u32_t dir;
69+
70+
LL_I2C_ClearFlag_ADDR(i2c);
71+
72+
dir = LL_I2C_GetTransferDirection(i2c);
73+
if (dir == LL_I2C_DIRECTION_WRITE) {
74+
data->slave_funcs->write_request(
75+
data->slave_priv);
76+
LL_I2C_EnableIT_RX(i2c);
77+
} else {
78+
u8_t val;
79+
data->slave_funcs->read_request(
80+
data->slave_priv, &val);
81+
LL_I2C_TransmitData8(i2c, val);
82+
LL_I2C_EnableIT_TX(i2c);
83+
LL_I2C_EnableIT_NACK(i2c);
84+
}
85+
86+
LL_I2C_EnableIT_STOP(i2c);
87+
LL_I2C_EnableIT_ERR(i2c);
88+
} else if (LL_I2C_IsActiveFlag_NACK(i2c) ||
89+
LL_I2C_IsActiveFlag_STOP(i2c)) {
90+
if (LL_I2C_IsActiveFlag_NACK(i2c)) {
91+
LL_I2C_ClearFlag_NACK(i2c);
92+
}
93+
94+
if (LL_I2C_IsActiveFlag_STOP(i2c)) {
95+
LL_I2C_ClearFlag_STOP(i2c);
96+
}
97+
98+
data->slave_funcs->stop(data->slave_priv);
99+
100+
LL_I2C_DisableIT_NACK(i2c);
101+
LL_I2C_DisableIT_TX(i2c);
102+
LL_I2C_DisableIT_RX(i2c);
103+
LL_I2C_DisableIT_STOP(i2c);
104+
LL_I2C_DisableIT_ERR(i2c);
105+
106+
LL_I2C_AcknowledgeNextData(i2c, LL_I2C_ACK);
107+
108+
/* Flush remaining TX byte */
109+
LL_I2C_Disable(i2c);
110+
LL_I2C_Enable(i2c);
111+
} else if (LL_I2C_IsActiveFlag_TXIS(i2c)) {
112+
u8_t val;
113+
114+
data->slave_funcs->read_done(data->slave_priv);
115+
data->slave_funcs->read_request(data->slave_priv, &val);
116+
LL_I2C_TransmitData8(i2c, val);
117+
} else if (LL_I2C_IsActiveFlag_RXNE(i2c)) {
118+
u8_t val = LL_I2C_ReceiveData8(i2c);
119+
120+
if (data->slave_funcs->write_done(data->slave_priv,
121+
val))
122+
LL_I2C_AcknowledgeNextData(i2c, LL_I2C_NACK);
123+
}
124+
125+
return;
126+
}
127+
#endif
128+
64129
if (data->current.len) {
65130
/* Interrupts for sending/receiving next byte */
66131

@@ -354,3 +419,81 @@ int stm32_i2c_configure_timing(struct device *dev, u32_t clock)
354419

355420
return 0;
356421
}
422+
423+
#if defined(CONFIG_I2C_SLAVE)
424+
bool i2c_stm32_slave_is_supported(struct device *dev)
425+
{
426+
struct i2c_stm32_data *data = DEV_DATA(dev);
427+
428+
return !(data->slave_attached);
429+
}
430+
431+
/* Attach and start I2C as slave */
432+
int i2c_stm32_slave_attach(struct device *dev, u8_t address,
433+
const struct i2c_slave_api *funcs,
434+
void *priv)
435+
{
436+
const struct i2c_stm32_config *cfg = DEV_CFG(dev);
437+
struct i2c_stm32_data *data = DEV_DATA(dev);
438+
I2C_TypeDef *i2c = cfg->i2c;
439+
u32_t bitrate_cfg;
440+
int ret;
441+
442+
if (!funcs)
443+
return -EINVAL;
444+
445+
bitrate_cfg = _i2c_map_dt_bitrate(cfg->bitrate);
446+
447+
ret = i2c_stm32_runtime_configure(dev, bitrate_cfg);
448+
if (ret < 0) {
449+
SYS_LOG_ERR("i2c: failure initializing");
450+
return ret;
451+
}
452+
453+
data->slave_funcs = funcs;
454+
data->slave_priv = priv;
455+
456+
LL_I2C_Enable(i2c);
457+
458+
LL_I2C_SetOwnAddress1(i2c, address << 1, LL_I2C_OWNADDRESS1_7BIT);
459+
LL_I2C_EnableOwnAddress1(i2c);
460+
461+
data->slave_attached = true;
462+
463+
SYS_LOG_DBG("i2c: slave attached");
464+
465+
LL_I2C_EnableIT_ADDR(i2c);
466+
467+
return 0;
468+
}
469+
470+
int i2c_stm32_slave_detach(struct device *dev, u8_t address,
471+
void *priv)
472+
{
473+
const struct i2c_stm32_config *cfg = DEV_CFG(dev);
474+
struct i2c_stm32_data *data = DEV_DATA(dev);
475+
I2C_TypeDef *i2c = cfg->i2c;
476+
477+
if (!data->slave_attached)
478+
return -EINVAL;
479+
480+
LL_I2C_DisableOwnAddress1(i2c);
481+
482+
LL_I2C_DisableIT_ADDR(i2c);
483+
LL_I2C_DisableIT_NACK(i2c);
484+
LL_I2C_DisableIT_TX(i2c);
485+
LL_I2C_DisableIT_RX(i2c);
486+
LL_I2C_DisableIT_STOP(i2c);
487+
LL_I2C_DisableIT_ERR(i2c);
488+
489+
LL_I2C_ClearFlag_NACK(i2c);
490+
LL_I2C_ClearFlag_STOP(i2c);
491+
LL_I2C_ClearFlag_ADDR(i2c);
492+
493+
LL_I2C_Disable(i2c);
494+
495+
SYS_LOG_DBG("i2c: slave detached");
496+
497+
return 0;
498+
}
499+
#endif

0 commit comments

Comments
 (0)