Skip to content

Commit 1cf09e8

Browse files
tklncarlescufi
authored andcommitted
drivers: i2c: nrf5: Make the driver thread-safe
Locking is added to externally callable API functions. Signed-off-by: Aapo Vienamo <[email protected]>
1 parent ddbcef4 commit 1cf09e8

File tree

1 file changed

+30
-16
lines changed

1 file changed

+30
-16
lines changed

drivers/i2c/i2c_nrf5.c

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,26 @@ struct i2c_nrf5_data {
4646
u32_t err:1;
4747
u32_t stopped:1;
4848
struct device *gpio;
49+
struct k_sem lock;
4950
};
5051

5152

5253
static int i2c_nrf5_configure(struct device *dev, u32_t dev_config_raw)
5354
{
5455
const struct i2c_nrf5_config *config = dev->config->config_info;
56+
struct i2c_nrf5_data *data = dev->driver_data;
5557
volatile NRF_TWI_Type *twi = config->base;
58+
int ret = 0;
59+
5660

5761
SYS_LOG_DBG("");
5862

5963
if (I2C_ADDR_10_BITS & dev_config_raw) {
6064
return -EINVAL;
6165
}
6266

67+
k_sem_take(&data->lock, K_FOREVER);
68+
6369
switch (I2C_SPEED_GET(dev_config_raw)) {
6470
case I2C_SPEED_STANDARD:
6571
twi->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K100;
@@ -69,10 +75,12 @@ static int i2c_nrf5_configure(struct device *dev, u32_t dev_config_raw)
6975
break;
7076
default:
7177
SYS_LOG_ERR("unsupported speed");
72-
return -EINVAL;
78+
ret = -EINVAL;
7379
}
7480

75-
return 0;
81+
k_sem_give(&data->lock);
82+
83+
return ret;
7684
}
7785

7886
static int i2c_nrf5_read(struct device *dev, struct i2c_msg *msg)
@@ -199,7 +207,11 @@ static int i2c_nrf5_transfer(struct device *dev, struct i2c_msg *msgs,
199207
u8_t num_msgs, u16_t addr)
200208
{
201209
const struct i2c_nrf5_config *config = dev->config->config_info;
210+
struct i2c_nrf5_data *data = dev->driver_data;
202211
volatile NRF_TWI_Type *twi = config->base;
212+
int ret = 0;
213+
214+
k_sem_take(&data->lock, K_FOREVER);
203215

204216
SYS_LOG_DBG("transaction-start addr=0x%x", addr);
205217

@@ -212,8 +224,6 @@ static int i2c_nrf5_transfer(struct device *dev, struct i2c_msg *msgs,
212224
twi->ENABLE = TWI_ENABLE_ENABLE_Enabled;
213225
twi->ADDRESS = addr;
214226
for (int i = 0; i < num_msgs; i++) {
215-
int r;
216-
217227
SYS_LOG_DBG("msg len=%d %s%s%s", msgs[i].len,
218228
(msgs[i].flags & I2C_MSG_READ) ? "R":"W",
219229
(msgs[i].flags & I2C_MSG_STOP) ? "S":"-",
@@ -225,19 +235,20 @@ static int i2c_nrf5_transfer(struct device *dev, struct i2c_msg *msgs,
225235
| NRF5_TWI_INT_RXDREADY
226236
| NRF5_TWI_INT_ERROR
227237
| NRF5_TWI_INT_STOPPED);
228-
r = i2c_nrf5_read(dev, msgs + i);
238+
ret = i2c_nrf5_read(dev, msgs + i);
229239
} else {
230-
r = i2c_nrf5_write(dev, msgs + i);
240+
ret = i2c_nrf5_write(dev, msgs + i);
231241
}
232242

233-
if (r != 0) {
234-
twi->ENABLE = TWI_ENABLE_ENABLE_Disabled;
235-
return r;
243+
if (ret != 0) {
244+
break;
236245
}
237246
}
238247
twi->ENABLE = TWI_ENABLE_ENABLE_Disabled;
239248

240-
return 0;
249+
k_sem_give(&data->lock);
250+
251+
return ret;
241252
}
242253

243254
static void i2c_nrf5_isr(void *arg)
@@ -313,11 +324,10 @@ static int i2c_nrf5_init(struct device *dev)
313324
| NRF5_TWI_INT_STOPPED);
314325

315326
status = i2c_nrf5_configure(dev, config->default_cfg);
316-
if (status) {
317-
return status;
318-
}
319327

320-
return 0;
328+
k_sem_give(&data->lock);
329+
330+
return status;
321331
}
322332

323333
static const struct i2c_driver_api i2c_nrf5_driver_api = {
@@ -339,7 +349,9 @@ static const struct i2c_nrf5_config i2c_nrf5_config_0 = {
339349
.scl_pin = CONFIG_I2C_NRF5_0_GPIO_SCL_PIN,
340350
};
341351

342-
static struct i2c_nrf5_data i2c_nrf5_data_0;
352+
static struct i2c_nrf5_data i2c_nrf5_data_0 = {
353+
.lock = _K_SEM_INITIALIZER(i2c_nrf5_data_0.lock, 1, 1),
354+
};
343355

344356
DEVICE_AND_API_INIT(i2c_nrf5_0, CONFIG_I2C_0_NAME, i2c_nrf5_init,
345357
&i2c_nrf5_data_0, &i2c_nrf5_config_0,
@@ -366,7 +378,9 @@ static const struct i2c_nrf5_config i2c_nrf5_config_1 = {
366378
.scl_pin = CONFIG_I2C_NRF5_1_GPIO_SCL_PIN,
367379
};
368380

369-
static struct i2c_nrf5_data i2c_nrf5_data_1;
381+
static struct i2c_nrf5_data i2c_nrf5_data_1 = {
382+
.lock = _K_SEM_INITIALIZER(i2c_nrf5_data_1.lock, 1, 1),
383+
};
370384

371385
DEVICE_AND_API_INIT(i2c_nrf5_1, CONFIG_I2C_1_NAME, i2c_nrf5_init,
372386
&i2c_nrf5_data_1, &i2c_nrf5_config_1,

0 commit comments

Comments
 (0)