Skip to content

Commit 124e29f

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 <[email protected]> (cherry picked from commit 068afd92e3088bb8426c0e7667813055ef40ad7d)
1 parent 9761288 commit 124e29f

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 PINCTRL
109
help
1110
Enable support for nrfx SPI drivers for nRF MCU series.

drivers/spi/spi_context.h

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

2828
struct spi_context {
2929
const struct spi_config *config;
30+
#ifdef CONFIG_MULTITHREADING
3031
const struct spi_config *owner;
32+
#endif
3133
const struct gpio_dt_spec *cs_gpios;
3234
size_t num_cs_gpios;
3335

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

3847
#ifdef CONFIG_SPI_ASYNC
@@ -105,6 +114,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
105114
void *callback_data,
106115
const struct spi_config *spi_cfg)
107116
{
117+
#ifdef CONFIG_MULTITHREADING
108118
bool already_locked = (spi_cfg->operation & SPI_LOCK_ON) &&
109119
(k_sem_count_get(&ctx->lock) == 0) &&
110120
(ctx->owner == spi_cfg);
@@ -113,6 +123,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
113123
k_sem_take(&ctx->lock, K_FOREVER);
114124
ctx->owner = spi_cfg;
115125
}
126+
#endif /* CONFIG_MULTITHREADING */
116127

117128
#ifdef CONFIG_SPI_ASYNC
118129
ctx->asynchronous = asynchronous;
@@ -130,6 +141,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
130141
*/
131142
static inline void spi_context_release(struct spi_context *ctx, int status)
132143
{
144+
#ifdef CONFIG_MULTITHREADING
133145
#ifdef CONFIG_SPI_SLAVE
134146
if (status >= 0 && (ctx->config->operation & SPI_LOCK_ON)) {
135147
return;
@@ -147,6 +159,7 @@ static inline void spi_context_release(struct spi_context *ctx, int status)
147159
k_sem_give(&ctx->lock);
148160
}
149161
#endif /* CONFIG_SPI_ASYNC */
162+
#endif /* CONFIG_MULTITHREADING */
150163
}
151164

152165
static inline size_t spi_context_total_tx_len(struct spi_context *ctx);
@@ -172,29 +185,57 @@ static inline int spi_context_wait_for_completion(struct spi_context *ctx)
172185

173186
if (wait) {
174187
k_timeout_t timeout;
188+
uint32_t timeout_ms;
175189

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

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

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

@@ -238,10 +279,15 @@ static inline void spi_context_complete(struct spi_context *ctx,
238279
ctx->owner = NULL;
239280
k_sem_give(&ctx->lock);
240281
}
282+
241283
}
242284
#else
243285
ctx->sync_status = status;
286+
#ifdef CONFIG_MULTITHREADING
244287
k_sem_give(&ctx->sync);
288+
#else
289+
atomic_set(&ctx->ready, 1);
290+
#endif /* CONFIG_MULTITHREADING */
245291
#endif /* CONFIG_SPI_ASYNC */
246292
}
247293

@@ -315,10 +361,12 @@ static inline void spi_context_unlock_unconditionally(struct spi_context *ctx)
315361
/* Forcing CS to go to inactive status */
316362
_spi_context_cs_control(ctx, false, true);
317363

364+
#ifdef CONFIG_MULTITHREADING
318365
if (!k_sem_count_get(&ctx->lock)) {
319366
ctx->owner = NULL;
320367
k_sem_give(&ctx->lock);
321368
}
369+
#endif /* CONFIG_MULTITHREADING */
322370
}
323371

324372
/*

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)