@@ -27,12 +27,21 @@ enum spi_ctx_runtime_op_mode {
2727
2828struct 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 */
131142static 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
152165static 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/*
0 commit comments