@@ -28,12 +28,21 @@ enum spi_ctx_runtime_op_mode {
28
28
29
29
struct spi_context {
30
30
const struct spi_config * config ;
31
+ #ifdef CONFIG_MULTITHREADING
31
32
const struct spi_config * owner ;
33
+ #endif
32
34
const struct gpio_dt_spec * cs_gpios ;
33
35
size_t num_cs_gpios ;
34
36
37
+ #ifdef CONFIG_MULTITHREADING
35
38
struct k_sem lock ;
36
39
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 */
37
46
int sync_status ;
38
47
39
48
#ifdef CONFIG_SPI_ASYNC
@@ -106,6 +115,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
106
115
void * callback_data ,
107
116
const struct spi_config * spi_cfg )
108
117
{
118
+ #ifdef CONFIG_MULTITHREADING
109
119
bool already_locked = (spi_cfg -> operation & SPI_LOCK_ON ) &&
110
120
(k_sem_count_get (& ctx -> lock ) == 0 ) &&
111
121
(ctx -> owner == spi_cfg );
@@ -114,6 +124,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
114
124
k_sem_take (& ctx -> lock , K_FOREVER );
115
125
ctx -> owner = spi_cfg ;
116
126
}
127
+ #endif /* CONFIG_MULTITHREADING */
117
128
118
129
#ifdef CONFIG_SPI_ASYNC
119
130
ctx -> asynchronous = asynchronous ;
@@ -131,6 +142,7 @@ static inline void spi_context_lock(struct spi_context *ctx,
131
142
*/
132
143
static inline void spi_context_release (struct spi_context * ctx , int status )
133
144
{
145
+ #ifdef CONFIG_MULTITHREADING
134
146
#ifdef CONFIG_SPI_SLAVE
135
147
if (status >= 0 && (ctx -> config -> operation & SPI_LOCK_ON )) {
136
148
return ;
@@ -148,6 +160,7 @@ static inline void spi_context_release(struct spi_context *ctx, int status)
148
160
k_sem_give (& ctx -> lock );
149
161
}
150
162
#endif /* CONFIG_SPI_ASYNC */
163
+ #endif /* CONFIG_MULTITHREADING */
151
164
}
152
165
153
166
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)
173
186
174
187
if (wait ) {
175
188
k_timeout_t timeout ;
189
+ uint32_t timeout_ms ;
176
190
177
191
/* Do not use any timeout in the slave mode, as in this case
178
192
* it is not known when the transfer will actually start and
179
193
* what the frequency will be.
180
194
*/
181
195
if (IS_ENABLED (CONFIG_SPI_SLAVE ) && spi_context_is_slave (ctx )) {
182
196
timeout = K_FOREVER ;
197
+ timeout_ms = UINT32_MAX ;
183
198
} else {
184
199
uint32_t tx_len = spi_context_total_tx_len (ctx );
185
200
uint32_t rx_len = spi_context_total_rx_len (ctx );
186
- uint32_t timeout_ms ;
187
201
188
202
timeout_ms = MAX (tx_len , rx_len ) * 8 * 1000 /
189
203
ctx -> config -> frequency ;
190
204
timeout_ms += CONFIG_SPI_COMPLETION_TIMEOUT_TOLERANCE ;
191
205
192
206
timeout = K_MSEC (timeout_ms );
193
207
}
194
-
208
+ #ifdef CONFIG_MULTITHREADING
195
209
if (k_sem_take (& ctx -> sync , timeout )) {
196
210
LOG_ERR ("Timeout waiting for transfer complete" );
197
211
return - ETIMEDOUT ;
198
212
}
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 */
199
240
status = ctx -> sync_status ;
200
241
}
201
242
@@ -239,10 +280,15 @@ static inline void spi_context_complete(struct spi_context *ctx,
239
280
ctx -> owner = NULL ;
240
281
k_sem_give (& ctx -> lock );
241
282
}
283
+
242
284
}
243
285
#else
244
286
ctx -> sync_status = status ;
287
+ #ifdef CONFIG_MULTITHREADING
245
288
k_sem_give (& ctx -> sync );
289
+ #else
290
+ atomic_set (& ctx -> ready , 1 );
291
+ #endif /* CONFIG_MULTITHREADING */
246
292
#endif /* CONFIG_SPI_ASYNC */
247
293
}
248
294
@@ -355,10 +401,12 @@ static inline void spi_context_unlock_unconditionally(struct spi_context *ctx)
355
401
/* Forcing CS to go to inactive status */
356
402
_spi_context_cs_control (ctx , false, true);
357
403
404
+ #ifdef CONFIG_MULTITHREADING
358
405
if (!k_sem_count_get (& ctx -> lock )) {
359
406
ctx -> owner = NULL ;
360
407
k_sem_give (& ctx -> lock );
361
408
}
409
+ #endif /* CONFIG_MULTITHREADING */
362
410
}
363
411
364
412
/*
0 commit comments