Skip to content

Commit df65918

Browse files
nordic-mik7kartben
authored andcommitted
drivers: spi: spi_context.h: remove multithreading dependency
Replace semaphores with proper atomic flags when used without multithreading enabled. Signed-off-by: Michal Kozikowski <[email protected]>
1 parent 7af5523 commit df65918

File tree

6 files changed

+94
-11
lines changed

6 files changed

+94
-11
lines changed

drivers/spi/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ config SPI_SHELL
2424

2525
config SPI_ASYNC
2626
bool "Asynchronous call support"
27+
depends on MULTITHREADING
2728
select POLL
2829
help
2930
This option enables the asynchronous API calls.

drivers/spi/Kconfig.nrfx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ menuconfig SPI_NRFX
55
bool "nRF SPI nrfx drivers"
66
default y
77
depends on SOC_FAMILY_NORDIC_NRF
8-
depends on MULTITHREADING
98
select GPIO
109
select PINCTRL
1110
help

drivers/spi/spi_context.h

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,21 @@ enum spi_ctx_runtime_op_mode {
2828

2929
struct spi_context {
3030
const struct spi_config *config;
31+
#ifdef CONFIG_MULTITHREADING
3132
const struct spi_config *owner;
33+
#endif
3234
const struct gpio_dt_spec *cs_gpios;
3335
size_t num_cs_gpios;
3436

37+
#ifdef CONFIG_MULTITHREADING
3538
struct k_sem lock;
3639
struct k_sem sync;
40+
#else
41+
/* An atomic flag that signals completed transfer
42+
* when threads are not enabled.
43+
*/
44+
atomic_t ready;
45+
#endif /* CONFIG_MULTITHREADING */
3746
int sync_status;
3847

3948
#ifdef CONFIG_SPI_ASYNC
@@ -106,6 +115,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
106115
void *callback_data,
107116
const struct spi_config *spi_cfg)
108117
{
118+
#ifdef CONFIG_MULTITHREADING
109119
bool already_locked = (spi_cfg->operation & SPI_LOCK_ON) &&
110120
(k_sem_count_get(&ctx->lock) == 0) &&
111121
(ctx->owner == spi_cfg);
@@ -114,6 +124,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
114124
k_sem_take(&ctx->lock, K_FOREVER);
115125
ctx->owner = spi_cfg;
116126
}
127+
#endif /* CONFIG_MULTITHREADING */
117128

118129
#ifdef CONFIG_SPI_ASYNC
119130
ctx->asynchronous = asynchronous;
@@ -131,6 +142,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
131142
*/
132143
static inline void spi_context_release(struct spi_context *ctx, int status)
133144
{
145+
#ifdef CONFIG_MULTITHREADING
134146
#ifdef CONFIG_SPI_SLAVE
135147
if (status >= 0 && (ctx->config->operation & SPI_LOCK_ON)) {
136148
return;
@@ -148,6 +160,7 @@ static inline void spi_context_release(struct spi_context *ctx, int status)
148160
k_sem_give(&ctx->lock);
149161
}
150162
#endif /* CONFIG_SPI_ASYNC */
163+
#endif /* CONFIG_MULTITHREADING */
151164
}
152165

153166
static inline size_t spi_context_total_tx_len(struct spi_context *ctx);
@@ -173,29 +186,57 @@ static inline int spi_context_wait_for_completion(struct spi_context *ctx)
173186

174187
if (wait) {
175188
k_timeout_t timeout;
189+
uint32_t timeout_ms;
176190

177191
/* Do not use any timeout in the slave mode, as in this case
178192
* it is not known when the transfer will actually start and
179193
* what the frequency will be.
180194
*/
181195
if (IS_ENABLED(CONFIG_SPI_SLAVE) && spi_context_is_slave(ctx)) {
182196
timeout = K_FOREVER;
197+
timeout_ms = UINT32_MAX;
183198
} else {
184199
uint32_t tx_len = spi_context_total_tx_len(ctx);
185200
uint32_t rx_len = spi_context_total_rx_len(ctx);
186-
uint32_t timeout_ms;
187201

188202
timeout_ms = MAX(tx_len, rx_len) * 8 * 1000 /
189203
ctx->config->frequency;
190204
timeout_ms += CONFIG_SPI_COMPLETION_TIMEOUT_TOLERANCE;
191205

192206
timeout = K_MSEC(timeout_ms);
193207
}
194-
208+
#ifdef CONFIG_MULTITHREADING
195209
if (k_sem_take(&ctx->sync, timeout)) {
196210
LOG_ERR("Timeout waiting for transfer complete");
197211
return -ETIMEDOUT;
198212
}
213+
#else
214+
if (timeout_ms == UINT32_MAX) {
215+
/* In slave mode, we wait indefinitely, so we can go idle. */
216+
unsigned int key = irq_lock();
217+
218+
while (!atomic_get(&ctx->ready)) {
219+
k_cpu_atomic_idle(key);
220+
key = irq_lock();
221+
}
222+
223+
ctx->ready = 0;
224+
irq_unlock(key);
225+
} else {
226+
const uint32_t tms = k_uptime_get_32();
227+
228+
while (!atomic_get(&ctx->ready) && (k_uptime_get_32() - tms < timeout_ms)) {
229+
k_busy_wait(1);
230+
}
231+
232+
if (!ctx->ready) {
233+
LOG_ERR("Timeout waiting for transfer complete");
234+
return -ETIMEDOUT;
235+
}
236+
237+
ctx->ready = 0;
238+
}
239+
#endif /* CONFIG_MULTITHREADING */
199240
status = ctx->sync_status;
200241
}
201242

@@ -239,10 +280,15 @@ static inline void spi_context_complete(struct spi_context *ctx,
239280
ctx->owner = NULL;
240281
k_sem_give(&ctx->lock);
241282
}
283+
242284
}
243285
#else
244286
ctx->sync_status = status;
287+
#ifdef CONFIG_MULTITHREADING
245288
k_sem_give(&ctx->sync);
289+
#else
290+
atomic_set(&ctx->ready, 1);
291+
#endif /* CONFIG_MULTITHREADING */
246292
#endif /* CONFIG_SPI_ASYNC */
247293
}
248294

@@ -355,10 +401,12 @@ static inline void spi_context_unlock_unconditionally(struct spi_context *ctx)
355401
/* Forcing CS to go to inactive status */
356402
_spi_context_cs_control(ctx, false, true);
357403

404+
#ifdef CONFIG_MULTITHREADING
358405
if (!k_sem_count_get(&ctx->lock)) {
359406
ctx->owner = NULL;
360407
k_sem_give(&ctx->lock);
361408
}
409+
#endif /* CONFIG_MULTITHREADING */
362410
}
363411

364412
/*

drivers/spi/spi_nrfx_spi.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,11 @@ static int transceive(const struct device *dev,
278278
finish_transaction(dev, -ETIMEDOUT);
279279

280280
/* Clean up the driver state. */
281+
#ifdef CONFIG_MULTITHREADING
281282
k_sem_reset(&dev_data->ctx.sync);
283+
#else
284+
dev_data->ctx.ready = 0;
285+
#endif /* CONFIG_MULTITHREADING */
282286
}
283287

284288
spi_context_cs_control(&dev_data->ctx, false);
@@ -432,8 +436,10 @@ static int spi_nrfx_init(const struct device *dev)
432436
nrfx_isr, nrfx_spi_##idx##_irq_handler, 0); \
433437
} \
434438
static struct spi_nrfx_data spi_##idx##_data = { \
435-
SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx), \
436-
SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx), \
439+
IF_ENABLED(CONFIG_MULTITHREADING, \
440+
(SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx),)) \
441+
IF_ENABLED(CONFIG_MULTITHREADING, \
442+
(SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx),)) \
437443
SPI_CONTEXT_CS_GPIOS_INITIALIZE(SPI(idx), ctx) \
438444
.dev = DEVICE_DT_GET(SPI(idx)), \
439445
.busy = false, \

drivers/spi/spi_nrfx_spim.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,11 @@ static int transceive(const struct device *dev,
598598
finish_transaction(dev, -ETIMEDOUT);
599599

600600
/* Clean up the driver state. */
601+
#ifdef CONFIG_MULTITHREADING
601602
k_sem_reset(&dev_data->ctx.sync);
603+
#else
604+
dev_data->ctx.ready = 0;
605+
#endif /* CONFIG_MULTITHREADING */
602606
#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
603607
anomaly_58_workaround_clear(dev_data);
604608
#endif
@@ -817,8 +821,10 @@ static int spi_nrfx_init(const struct device *dev)
817821
[CONFIG_SPI_NRFX_RAM_BUFFER_SIZE] \
818822
SPIM_MEMORY_SECTION(idx);)) \
819823
static struct spi_nrfx_data spi_##idx##_data = { \
820-
SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx), \
821-
SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx), \
824+
IF_ENABLED(CONFIG_MULTITHREADING, \
825+
(SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx),)) \
826+
IF_ENABLED(CONFIG_MULTITHREADING, \
827+
(SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx),)) \
822828
SPI_CONTEXT_CS_GPIOS_INITIALIZE(SPIM(idx), ctx) \
823829
IF_ENABLED(SPI_BUFFER_IN_RAM, \
824830
(.tx_buffer = spim_##idx##_tx_buffer, \

drivers/spi/spi_nrfx_spis.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED));
3939
struct spi_nrfx_data {
4040
struct spi_context ctx;
4141
const struct device *dev;
42+
#ifdef CONFIG_MULTITHREADING
4243
struct k_sem wake_sem;
44+
#else
45+
atomic_t woken_up;
46+
#endif
4347
struct gpio_callback wake_cb_data;
4448
};
4549

@@ -193,7 +197,11 @@ static void wake_callback(const struct device *dev, struct gpio_callback *cb,
193197

194198
(void)gpio_pin_interrupt_configure_dt(&dev_config->wake_gpio,
195199
GPIO_INT_DISABLE);
200+
#ifdef CONFIG_MULTITHREADING
196201
k_sem_give(&dev_data->wake_sem);
202+
#else
203+
atomic_set(&dev_data->woken_up, 1);
204+
#endif /* CONFIG_MULTITHREADING */
197205
}
198206

199207
static void wait_for_wake(struct spi_nrfx_data *dev_data,
@@ -206,7 +214,19 @@ static void wait_for_wake(struct spi_nrfx_data *dev_data,
206214
dev_config->wake_gpio.pin) == 0) {
207215
(void)gpio_pin_interrupt_configure_dt(&dev_config->wake_gpio,
208216
GPIO_INT_LEVEL_HIGH);
217+
#ifdef CONFIG_MULTITHREADING
209218
(void)k_sem_take(&dev_data->wake_sem, K_FOREVER);
219+
#else
220+
unsigned int key = irq_lock();
221+
222+
while (!atomic_get(&dev_data->woken_up)) {
223+
k_cpu_atomic_idle(key);
224+
key = irq_lock();
225+
}
226+
227+
dev_data->woken_up = 0;
228+
irq_unlock(key);
229+
#endif /* CONFIG_MULTITHREADING */
210230
}
211231
}
212232

@@ -482,11 +502,14 @@ static int spi_nrfx_init(const struct device *dev)
482502
nrfx_isr, nrfx_spis_##idx##_irq_handler, 0); \
483503
} \
484504
static struct spi_nrfx_data spi_##idx##_data = { \
485-
SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx), \
486-
SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx), \
505+
IF_ENABLED(CONFIG_MULTITHREADING, \
506+
(SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx),)) \
507+
IF_ENABLED(CONFIG_MULTITHREADING, \
508+
(SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx),)) \
487509
.dev = DEVICE_DT_GET(SPIS(idx)), \
488-
.wake_sem = Z_SEM_INITIALIZER( \
489-
spi_##idx##_data.wake_sem, 0, 1), \
510+
IF_ENABLED(CONFIG_MULTITHREADING, \
511+
(.wake_sem = Z_SEM_INITIALIZER( \
512+
spi_##idx##_data.wake_sem, 0, 1),)) \
490513
}; \
491514
PINCTRL_DT_DEFINE(SPIS(idx)); \
492515
static const struct spi_nrfx_config spi_##idx##z_config = { \

0 commit comments

Comments
 (0)