Skip to content

Commit 9e44861

Browse files
committed
[nrf fromlist] drivers: spi: spi_context.h: remove multithreading dependency
Replace semaphores with proper atomic flags when used without multithreading enabled. Upstream PR #: 90647 Related: NCSDK-33699 Signed-off-by: Michal Kozikowski <michal.kozikowski@nordicsemi.no> (cherry picked from commit 1add805bca88a9fbcb4daf983b6b3816da824170)
1 parent 47828ec commit 9e44861

File tree

6 files changed

+93
-11
lines changed

6 files changed

+93
-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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ menuconfig SPI_NRFX
55
bool "nRF SPI nrfx drivers"
66
default y
77
depends on SOC_FAMILY_NORDIC_NRF
8-
depends on MULTITHREADING
8+
select GPIO
99
select PINCTRL
1010
help
1111
Enable support for nrfx SPI drivers for nRF MCU series.

drivers/spi/spi_context.h

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,15 @@ struct spi_context {
3131
const struct gpio_dt_spec *cs_gpios;
3232
size_t num_cs_gpios;
3333

34+
#ifdef CONFIG_MULTITHREADING
3435
struct k_sem lock;
3536
struct k_sem sync;
37+
#else
38+
/* An atomic flag that signals completed transfer
39+
* when threads are not enabled.
40+
*/
41+
atomic_t ready;
42+
#endif /* CONFIG_MULTITHREADING */
3643
int sync_status;
3744

3845
#ifdef CONFIG_SPI_ASYNC
@@ -105,6 +112,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
105112
void *callback_data,
106113
const struct spi_config *spi_cfg)
107114
{
115+
#ifdef CONFIG_MULTITHREADING
108116
bool already_locked = (spi_cfg->operation & SPI_LOCK_ON) &&
109117
(k_sem_count_get(&ctx->lock) == 0) &&
110118
(ctx->owner == spi_cfg);
@@ -119,6 +127,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
119127
ctx->callback = callback;
120128
ctx->callback_data = callback_data;
121129
#endif /* CONFIG_SPI_ASYNC */
130+
#endif /* CONFIG_MULTITHREADING */
122131
}
123132

124133
/*
@@ -130,6 +139,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
130139
*/
131140
static inline void spi_context_release(struct spi_context *ctx, int status)
132141
{
142+
#ifdef CONFIG_MULTITHREADING
133143
#ifdef CONFIG_SPI_SLAVE
134144
if (status >= 0 && (ctx->config->operation & SPI_LOCK_ON)) {
135145
return;
@@ -147,6 +157,7 @@ static inline void spi_context_release(struct spi_context *ctx, int status)
147157
k_sem_give(&ctx->lock);
148158
}
149159
#endif /* CONFIG_SPI_ASYNC */
160+
#endif /* CONFIG_MULTITHREADING */
150161
}
151162

152163
static inline size_t spi_context_total_tx_len(struct spi_context *ctx);
@@ -172,29 +183,57 @@ static inline int spi_context_wait_for_completion(struct spi_context *ctx)
172183

173184
if (wait) {
174185
k_timeout_t timeout;
186+
uint32_t timeout_ms;
175187

176188
/* Do not use any timeout in the slave mode, as in this case
177189
* it is not known when the transfer will actually start and
178190
* what the frequency will be.
179191
*/
180192
if (IS_ENABLED(CONFIG_SPI_SLAVE) && spi_context_is_slave(ctx)) {
181193
timeout = K_FOREVER;
194+
timeout_ms = UINT32_MAX;
182195
} else {
183196
uint32_t tx_len = spi_context_total_tx_len(ctx);
184197
uint32_t rx_len = spi_context_total_rx_len(ctx);
185-
uint32_t timeout_ms;
186198

187199
timeout_ms = MAX(tx_len, rx_len) * 8 * 1000 /
188200
ctx->config->frequency;
189201
timeout_ms += CONFIG_SPI_COMPLETION_TIMEOUT_TOLERANCE;
190202

191203
timeout = K_MSEC(timeout_ms);
192204
}
193-
205+
#ifdef CONFIG_MULTITHREADING
194206
if (k_sem_take(&ctx->sync, timeout)) {
195207
LOG_ERR("Timeout waiting for transfer complete");
196208
return -ETIMEDOUT;
197209
}
210+
#else
211+
if (timeout_ms == UINT32_MAX) {
212+
/* In slave mode, we wait indefinitely, so we can go idle. */
213+
unsigned int key = irq_lock();
214+
215+
while (!atomic_get(&ctx->ready)) {
216+
k_cpu_atomic_idle(key);
217+
key = irq_lock();
218+
}
219+
220+
ctx->ready = 0;
221+
irq_unlock(key);
222+
} else {
223+
const uint32_t tms = k_uptime_get_32();
224+
225+
while (!atomic_get(&ctx->ready) && (k_uptime_get_32() - tms < timeout_ms)) {
226+
k_busy_wait(1);
227+
}
228+
229+
if (!ctx->ready) {
230+
LOG_ERR("Timeout waiting for transfer complete");
231+
return -ETIMEDOUT;
232+
}
233+
234+
ctx->ready = 0;
235+
}
236+
#endif /* CONFIG_MULTITHREADING */
198237
status = ctx->sync_status;
199238
}
200239

@@ -238,10 +277,15 @@ static inline void spi_context_complete(struct spi_context *ctx,
238277
ctx->owner = NULL;
239278
k_sem_give(&ctx->lock);
240279
}
280+
241281
}
242282
#else
243283
ctx->sync_status = status;
284+
#ifdef CONFIG_MULTITHREADING
244285
k_sem_give(&ctx->sync);
286+
#else
287+
atomic_set(&ctx->ready, 1);
288+
#endif /* CONFIG_MULTITHREADING */
245289
#endif /* CONFIG_SPI_ASYNC */
246290
}
247291

@@ -315,10 +359,12 @@ static inline void spi_context_unlock_unconditionally(struct spi_context *ctx)
315359
/* Forcing CS to go to inactive status */
316360
_spi_context_cs_control(ctx, false, true);
317361

362+
#ifdef CONFIG_MULTITHREADING
318363
if (!k_sem_count_get(&ctx->lock)) {
319364
ctx->owner = NULL;
320365
k_sem_give(&ctx->lock);
321366
}
367+
#endif /* CONFIG_MULTITHREADING */
322368
}
323369

324370
/*

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
@@ -592,7 +592,11 @@ static int transceive(const struct device *dev,
592592
finish_transaction(dev, -ETIMEDOUT);
593593

594594
/* Clean up the driver state. */
595+
#ifdef CONFIG_MULTITHREADING
595596
k_sem_reset(&dev_data->ctx.sync);
597+
#else
598+
dev_data->ctx.ready = 0;
599+
#endif /* CONFIG_MULTITHREADING */
596600
#ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58
597601
anomaly_58_workaround_clear(dev_data);
598602
#endif
@@ -804,8 +808,10 @@ static int spi_nrfx_init(const struct device *dev)
804808
[CONFIG_SPI_NRFX_RAM_BUFFER_SIZE] \
805809
SPIM_MEMORY_SECTION(idx);)) \
806810
static struct spi_nrfx_data spi_##idx##_data = { \
807-
SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx), \
808-
SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx), \
811+
IF_ENABLED(CONFIG_MULTITHREADING, \
812+
(SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx),)) \
813+
IF_ENABLED(CONFIG_MULTITHREADING, \
814+
(SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx),)) \
809815
SPI_CONTEXT_CS_GPIOS_INITIALIZE(SPIM(idx), ctx) \
810816
IF_ENABLED(SPI_BUFFER_IN_RAM, \
811817
(.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)