1111 * 2012-05-18 bernard Changed SPI message to message list.
1212 * Added take/release SPI device/bus interface.
1313 * 2012-09-28 aozima fixed rt_spi_release_bus assert error.
14+ * 2025-10-30 wdfk-prog enable interrupt-safe operations using spinlocks
1415 */
1516
1617#include "drivers/dev_spi.h"
@@ -38,6 +39,9 @@ rt_err_t spi_bus_register(struct rt_spi_bus *bus,
3839
3940 /* initialize mutex lock */
4041 rt_mutex_init (& (bus -> lock ), name , RT_IPC_FLAG_PRIO );
42+ #ifdef RT_USING_SPI_ISR
43+ rt_spin_lock_init (& bus -> _spinlock );
44+ #endif /* RT_USING_SPI_ISR */
4145 /* set ops */
4246 bus -> ops = ops ;
4347 /* initialize owner */
@@ -164,13 +168,53 @@ rt_err_t rt_spi_bus_detach_device(struct rt_spi_device *device)
164168 return rt_spi_bus_detach_device_cspin (device );
165169}
166170
171+ static rt_err_t spi_lock (struct rt_spi_bus * bus )
172+ {
173+ RT_ASSERT (bus );
174+
175+ rt_err_t ret = - RT_ERROR ;
176+ /* If the scheduler is started and in thread context */
177+ if (rt_scheduler_is_available ())
178+ {
179+ ret = rt_mutex_take (& (bus -> lock ), RT_WAITING_FOREVER );
180+ }
181+ else
182+ {
183+ #ifdef RT_USING_SPI_ISR
184+ bus -> _isr_lvl = rt_spin_lock_irqsave (& bus -> _spinlock );
185+ ret = RT_EOK ;
186+ #endif /* RT_USING_SPI_ISR */
187+ }
188+ return ret ;
189+ }
190+
191+ static rt_err_t spi_unlock (struct rt_spi_bus * bus )
192+ {
193+ RT_ASSERT (bus );
194+
195+ rt_err_t ret = - RT_ERROR ;
196+ /* If the scheduler is started and in thread context */
197+ if (rt_scheduler_is_available ())
198+ {
199+ ret = rt_mutex_release (& (bus -> lock ));
200+ }
201+ else
202+ {
203+ #ifdef RT_USING_SPI_ISR
204+ rt_spin_unlock_irqrestore (& bus -> _spinlock , bus -> _isr_lvl );
205+ ret = RT_EOK ;
206+ #endif /* RT_USING_SPI_ISR */
207+ }
208+ return ret ;
209+ }
210+
167211rt_err_t rt_spi_bus_configure (struct rt_spi_device * device )
168212{
169213 rt_err_t result = - RT_ERROR ;
170214
171215 if (device -> bus != RT_NULL )
172216 {
173- result = rt_mutex_take ( & ( device -> bus -> lock ), RT_WAITING_FOREVER );
217+ result = spi_lock ( device -> bus );
174218 if (result == RT_EOK )
175219 {
176220 if (device -> bus -> owner == device )
@@ -191,7 +235,7 @@ rt_err_t rt_spi_bus_configure(struct rt_spi_device *device)
191235 result = - RT_EBUSY ;
192236 }
193237 /* release lock */
194- rt_mutex_release ( & ( device -> bus -> lock ) );
238+ spi_unlock ( device -> bus );
195239 }
196240 }
197241 else
@@ -211,7 +255,7 @@ rt_err_t rt_spi_configure(struct rt_spi_device *device,
211255 /* reset the CS pin */
212256 if (device -> cs_pin != PIN_NONE )
213257 {
214- rt_err_t result = rt_mutex_take ( & ( device -> bus -> lock ), RT_WAITING_FOREVER );
258+ rt_err_t result = spi_lock ( device -> bus );
215259 if (result == RT_EOK )
216260 {
217261 if (cfg -> mode & RT_SPI_CS_HIGH )
@@ -222,7 +266,7 @@ rt_err_t rt_spi_configure(struct rt_spi_device *device,
222266 {
223267 rt_pin_write (device -> cs_pin , PIN_HIGH );
224268 }
225- rt_mutex_release ( & ( device -> bus -> lock ) );
269+ spi_unlock ( device -> bus );
226270 }
227271 else
228272 {
@@ -258,7 +302,7 @@ rt_err_t rt_spi_send_then_send(struct rt_spi_device *device,
258302 RT_ASSERT (device != RT_NULL );
259303 RT_ASSERT (device -> bus != RT_NULL );
260304
261- result = rt_mutex_take ( & ( device -> bus -> lock ), RT_WAITING_FOREVER );
305+ result = spi_lock ( device -> bus );
262306 if (result == RT_EOK )
263307 {
264308 if (device -> bus -> owner != device )
@@ -316,7 +360,7 @@ rt_err_t rt_spi_send_then_send(struct rt_spi_device *device,
316360 }
317361
318362__exit :
319- rt_mutex_release ( & ( device -> bus -> lock ) );
363+ spi_unlock ( device -> bus );
320364
321365 return result ;
322366}
@@ -333,7 +377,7 @@ rt_err_t rt_spi_send_then_recv(struct rt_spi_device *device,
333377 RT_ASSERT (device != RT_NULL );
334378 RT_ASSERT (device -> bus != RT_NULL );
335379
336- result = rt_mutex_take ( & ( device -> bus -> lock ), RT_WAITING_FOREVER );
380+ result = spi_lock ( device -> bus );
337381 if (result == RT_EOK )
338382 {
339383 if (device -> bus -> owner != device )
@@ -391,7 +435,7 @@ rt_err_t rt_spi_send_then_recv(struct rt_spi_device *device,
391435 }
392436
393437__exit :
394- rt_mutex_release ( & ( device -> bus -> lock ) );
438+ spi_unlock ( device -> bus );
395439
396440 return result ;
397441}
@@ -407,7 +451,7 @@ rt_ssize_t rt_spi_transfer(struct rt_spi_device *device,
407451 RT_ASSERT (device != RT_NULL );
408452 RT_ASSERT (device -> bus != RT_NULL );
409453
410- result = rt_mutex_take ( & ( device -> bus -> lock ), RT_WAITING_FOREVER );
454+ result = spi_lock ( device -> bus );
411455 if (result == RT_EOK )
412456 {
413457 if (device -> bus -> owner != device )
@@ -449,7 +493,7 @@ rt_ssize_t rt_spi_transfer(struct rt_spi_device *device,
449493 }
450494
451495__exit :
452- rt_mutex_release ( & ( device -> bus -> lock ) );
496+ spi_unlock ( device -> bus );
453497
454498 return result ;
455499}
@@ -510,7 +554,7 @@ struct rt_spi_message *rt_spi_transfer_message(struct rt_spi_device *device,
510554 if (index == RT_NULL )
511555 return index ;
512556
513- result = rt_mutex_take ( & ( device -> bus -> lock ), RT_WAITING_FOREVER );
557+ result = spi_lock ( device -> bus );
514558 if (result != RT_EOK )
515559 {
516560 return index ;
@@ -548,7 +592,7 @@ struct rt_spi_message *rt_spi_transfer_message(struct rt_spi_device *device,
548592
549593__exit :
550594 /* release bus lock */
551- rt_mutex_release ( & ( device -> bus -> lock ) );
595+ spi_unlock ( device -> bus );
552596
553597 return index ;
554598}
@@ -560,7 +604,7 @@ rt_err_t rt_spi_take_bus(struct rt_spi_device *device)
560604 RT_ASSERT (device != RT_NULL );
561605 RT_ASSERT (device -> bus != RT_NULL );
562606
563- result = rt_mutex_take ( & ( device -> bus -> lock ), RT_WAITING_FOREVER );
607+ result = spi_lock ( device -> bus );
564608 if (result != RT_EOK )
565609 {
566610 return - RT_EBUSY ;
@@ -579,7 +623,7 @@ rt_err_t rt_spi_take_bus(struct rt_spi_device *device)
579623 else
580624 {
581625 /* configure SPI bus failed */
582- rt_mutex_release ( & ( device -> bus -> lock ) );
626+ spi_unlock ( device -> bus );
583627
584628 return result ;
585629 }
@@ -595,7 +639,7 @@ rt_err_t rt_spi_release_bus(struct rt_spi_device *device)
595639 RT_ASSERT (device -> bus -> owner == device );
596640
597641 /* release lock */
598- return rt_mutex_release ( & ( device -> bus -> lock ) );
642+ return spi_unlock ( device -> bus );
599643}
600644
601645rt_err_t rt_spi_take (struct rt_spi_device * device )
0 commit comments