Skip to content

Commit df73830

Browse files
committed
feat[spi]: enable interrupt-safe operations using spinlocks
1 parent ba509f9 commit df73830

File tree

5 files changed

+106
-18
lines changed

5 files changed

+106
-18
lines changed

components/drivers/include/drivers/dev_spi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ struct rt_spi_bus
181181
#endif /* RT_USING_DM */
182182

183183
struct rt_mutex lock;
184+
#ifdef RT_USING_SPI_ISR
185+
rt_base_t _isr_lvl;
186+
struct rt_spinlock _spinlock;
187+
#endif /* RT_USING_SPI_ISR */
184188
struct rt_spi_device *owner;
185189
};
186190

components/drivers/spi/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ menuconfig RT_USING_SPI
44

55
if RT_USING_SPI
66

7+
menuconfig RT_USING_SPI_ISR
8+
bool "Enable ISR SPI"
9+
default y
10+
711
menuconfig RT_USING_SOFT_SPI
812
bool "Use GPIO to simulate SPI"
913
default n

components/drivers/spi/dev_spi_core.c

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ rt_err_t spi_bus_register(struct rt_spi_bus *bus,
3838

3939
/* initialize mutex lock */
4040
rt_mutex_init(&(bus->lock), name, RT_IPC_FLAG_PRIO);
41+
#ifdef RT_USING_SPI_ISR
42+
rt_spin_lock_init(&bus->_spinlock);
43+
#endif /* RT_USING_SPI_ISR */
4144
/* set ops */
4245
bus->ops = ops;
4346
/* initialize owner */
@@ -164,13 +167,53 @@ rt_err_t rt_spi_bus_detach_device(struct rt_spi_device *device)
164167
return rt_spi_bus_detach_device_cspin(device);
165168
}
166169

170+
static rt_err_t spi_lock(struct rt_spi_bus *bus)
171+
{
172+
RT_ASSERT(bus);
173+
174+
rt_err_t ret = -RT_ERROR;
175+
/* If the scheduler is started and in thread context */
176+
if (rt_scheduler_is_available())
177+
{
178+
ret = rt_mutex_take(&(bus->lock), RT_WAITING_FOREVER);
179+
}
180+
else
181+
{
182+
#ifdef RT_USING_SPI_ISR
183+
bus->_isr_lvl = rt_spin_lock_irqsave(&bus->_spinlock);
184+
ret = RT_EOK;
185+
#endif /* RT_USING_SPI_ISR */
186+
}
187+
return ret;
188+
}
189+
190+
static rt_err_t spi_unlock(struct rt_spi_bus *bus)
191+
{
192+
RT_ASSERT(bus);
193+
194+
rt_err_t ret = -RT_ERROR;
195+
/* If the scheduler is started and in thread context */
196+
if (rt_scheduler_is_available())
197+
{
198+
ret = rt_mutex_release(&(bus->lock));
199+
}
200+
else
201+
{
202+
#ifdef RT_USING_SPI_ISR
203+
rt_spin_unlock_irqrestore(&bus->_spinlock, bus->_isr_lvl);
204+
ret = RT_EOK;
205+
#endif /* RT_USING_SPI_ISR */
206+
}
207+
return ret;
208+
}
209+
167210
rt_err_t rt_spi_bus_configure(struct rt_spi_device *device)
168211
{
169212
rt_err_t result = -RT_ERROR;
170213

171214
if (device->bus != RT_NULL)
172215
{
173-
result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
216+
result = spi_lock(device->bus);
174217
if (result == RT_EOK)
175218
{
176219
if (device->bus->owner == device)
@@ -191,7 +234,7 @@ rt_err_t rt_spi_bus_configure(struct rt_spi_device *device)
191234
result = -RT_EBUSY;
192235
}
193236
/* release lock */
194-
rt_mutex_release(&(device->bus->lock));
237+
spi_unlock(device->bus);
195238
}
196239
}
197240
else
@@ -211,7 +254,7 @@ rt_err_t rt_spi_configure(struct rt_spi_device *device,
211254
/* reset the CS pin */
212255
if (device->cs_pin != PIN_NONE)
213256
{
214-
rt_err_t result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
257+
rt_err_t result = spi_lock(device->bus);
215258
if (result == RT_EOK)
216259
{
217260
if (cfg->mode & RT_SPI_CS_HIGH)
@@ -222,7 +265,7 @@ rt_err_t rt_spi_configure(struct rt_spi_device *device,
222265
{
223266
rt_pin_write(device->cs_pin, PIN_HIGH);
224267
}
225-
rt_mutex_release(&(device->bus->lock));
268+
spi_unlock(device->bus);
226269
}
227270
else
228271
{
@@ -258,7 +301,7 @@ rt_err_t rt_spi_send_then_send(struct rt_spi_device *device,
258301
RT_ASSERT(device != RT_NULL);
259302
RT_ASSERT(device->bus != RT_NULL);
260303

261-
result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
304+
result = spi_lock(device->bus);
262305
if (result == RT_EOK)
263306
{
264307
if (device->bus->owner != device)
@@ -316,7 +359,7 @@ rt_err_t rt_spi_send_then_send(struct rt_spi_device *device,
316359
}
317360

318361
__exit:
319-
rt_mutex_release(&(device->bus->lock));
362+
spi_unlock(device->bus);
320363

321364
return result;
322365
}
@@ -333,7 +376,7 @@ rt_err_t rt_spi_send_then_recv(struct rt_spi_device *device,
333376
RT_ASSERT(device != RT_NULL);
334377
RT_ASSERT(device->bus != RT_NULL);
335378

336-
result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
379+
result = spi_lock(device->bus);
337380
if (result == RT_EOK)
338381
{
339382
if (device->bus->owner != device)
@@ -391,7 +434,7 @@ rt_err_t rt_spi_send_then_recv(struct rt_spi_device *device,
391434
}
392435

393436
__exit:
394-
rt_mutex_release(&(device->bus->lock));
437+
spi_unlock(device->bus);
395438

396439
return result;
397440
}
@@ -407,7 +450,7 @@ rt_ssize_t rt_spi_transfer(struct rt_spi_device *device,
407450
RT_ASSERT(device != RT_NULL);
408451
RT_ASSERT(device->bus != RT_NULL);
409452

410-
result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
453+
result = spi_lock(device->bus);
411454
if (result == RT_EOK)
412455
{
413456
if (device->bus->owner != device)
@@ -449,7 +492,7 @@ rt_ssize_t rt_spi_transfer(struct rt_spi_device *device,
449492
}
450493

451494
__exit:
452-
rt_mutex_release(&(device->bus->lock));
495+
spi_unlock(device->bus);
453496

454497
return result;
455498
}
@@ -510,7 +553,7 @@ struct rt_spi_message *rt_spi_transfer_message(struct rt_spi_device *device,
510553
if (index == RT_NULL)
511554
return index;
512555

513-
result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
556+
result = spi_lock(device->bus);
514557
if (result != RT_EOK)
515558
{
516559
return index;
@@ -548,7 +591,7 @@ struct rt_spi_message *rt_spi_transfer_message(struct rt_spi_device *device,
548591

549592
__exit:
550593
/* release bus lock */
551-
rt_mutex_release(&(device->bus->lock));
594+
spi_unlock(device->bus);
552595

553596
return index;
554597
}
@@ -560,7 +603,7 @@ rt_err_t rt_spi_take_bus(struct rt_spi_device *device)
560603
RT_ASSERT(device != RT_NULL);
561604
RT_ASSERT(device->bus != RT_NULL);
562605

563-
result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
606+
result = spi_lock(device->bus);
564607
if (result != RT_EOK)
565608
{
566609
return -RT_EBUSY;
@@ -579,7 +622,7 @@ rt_err_t rt_spi_take_bus(struct rt_spi_device *device)
579622
else
580623
{
581624
/* configure SPI bus failed */
582-
rt_mutex_release(&(device->bus->lock));
625+
spi_unlock(device->bus);
583626

584627
return result;
585628
}
@@ -595,7 +638,7 @@ rt_err_t rt_spi_release_bus(struct rt_spi_device *device)
595638
RT_ASSERT(device->bus->owner == device);
596639

597640
/* release lock */
598-
return rt_mutex_release(&(device->bus->lock));
641+
return spi_unlock(device->bus);
599642
}
600643

601644
rt_err_t rt_spi_take(struct rt_spi_device *device)

components/drivers/spi/dev_spi_flash.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ struct spi_flash_device
2020
struct rt_device_blk_geometry geometry;
2121
struct rt_spi_device * rt_spi_device;
2222
struct rt_mutex lock;
23+
#ifdef RT_USING_SPI_ISR
24+
rt_base_t _isr_lvl;
25+
struct rt_spinlock _spinlock;
26+
#endif /* RT_USING_SPI_ISR */
2327
void * user_data;
2428
};
2529

components/drivers/spi/dev_spi_flash_sfud.c

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,17 @@ static void spi_lock(const sfud_spi *spi) {
233233
RT_ASSERT(sfud_dev);
234234
RT_ASSERT(rtt_dev);
235235

236-
rt_mutex_take(&(rtt_dev->lock), RT_WAITING_FOREVER);
236+
/* If the scheduler is started and in thread context */
237+
if (rt_scheduler_is_available())
238+
{
239+
rt_mutex_take(&(rtt_dev->lock), RT_WAITING_FOREVER);
240+
}
241+
else
242+
{
243+
#ifdef RT_USING_SPI_ISR
244+
rtt_dev->_isr_lvl = rt_spin_lock_irqsave(&rtt_dev->_spinlock);
245+
#endif /* RT_USING_SPI_ISR */
246+
}
237247
}
238248

239249
static void spi_unlock(const sfud_spi *spi) {
@@ -244,12 +254,32 @@ static void spi_unlock(const sfud_spi *spi) {
244254
RT_ASSERT(sfud_dev);
245255
RT_ASSERT(rtt_dev);
246256

247-
rt_mutex_release(&(rtt_dev->lock));
257+
/* If the scheduler is started and in thread context */
258+
if (rt_scheduler_is_available())
259+
{
260+
rt_mutex_release(&(rtt_dev->lock));
261+
}
262+
else
263+
{
264+
#ifdef RT_USING_SPI_ISR
265+
rt_spin_unlock_irqrestore(&rtt_dev->_spinlock, rtt_dev->_isr_lvl);
266+
#endif /* RT_USING_SPI_ISR */
267+
}
248268
}
249269

250270
static void retry_delay_100us(void) {
251271
/* 100 microsecond delay */
252-
rt_thread_delay((RT_TICK_PER_SECOND * 1 + 9999) / 10000);
272+
if (rt_scheduler_is_available())
273+
{
274+
rt_thread_delay((RT_TICK_PER_SECOND * 1 + 9999) / 10000);
275+
}
276+
else
277+
{
278+
#ifdef RT_USING_SPI_ISR
279+
extern void rt_hw_us_delay(rt_uint32_t us);
280+
rt_hw_us_delay(100);
281+
#endif /* RT_USING_SPI_ISR */
282+
}
253283
}
254284

255285
sfud_err sfud_spi_port_init(sfud_flash *flash) {
@@ -320,6 +350,9 @@ rt_spi_flash_device_t rt_sfud_flash_probe_ex(const char *spi_flash_dev_name, con
320350
if (rtt_dev) {
321351
rt_memset(rtt_dev, 0, sizeof(struct spi_flash_device));
322352
/* initialize lock */
353+
#ifdef RT_USING_SPI_ISR
354+
rt_spin_lock_init(&rtt_dev->_spinlock);
355+
#endif /* RT_USING_SPI_ISR */
323356
rt_mutex_init(&(rtt_dev->lock), spi_flash_dev_name, RT_IPC_FLAG_PRIO);
324357
}
325358

0 commit comments

Comments
 (0)