Skip to content

Commit 6b4a928

Browse files
committed
pbio/drv/block_device/block_device_ev3: Implement functions for ADC use
The ADC driver will be rewritten to use DMA, but the code for setting it up is placed in the SPI flash driver in order to centralize the logic in one place.
1 parent 859c996 commit 6b4a928

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

lib/pbio/drv/block_device/block_device_ev3.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ enum {
159159
// This controls things such as the clock speed, SPI CPOL/CPHA, and timing parameters.
160160
// We use the following:
161161
// - Format 0: Flash
162-
// - Format 1: ADC (TODO)
162+
// - Format 1: ADC
163163
//
164164
// The EDMA3 peripheral has 128 parameter sets. 32 of them are triggered by events, but the others
165165
// can be used by "linking" to them from a previous one. Instead of having an allocator for these,
@@ -393,6 +393,70 @@ static pbio_error_t spi_begin_for_flash(
393393
return PBIO_SUCCESS;
394394
}
395395

396+
/**
397+
* Initiates an SPI transfer via DMA, specifically designed for the ADC.
398+
*
399+
* @param [in] cmds Data (both ADC chip commands and SPI peripheral commands) to be sent.
400+
* Lifetime must remain valid until after the completion of the entire transfer.
401+
* @param [in] data Buffer for ADC chip outputs.
402+
* Lifetime must remain valid until after the completion of the entire transfer.
403+
* @param [in] len Length of \p cmds and \p data
404+
* @return ::PBIO_SUCCESS on success.
405+
* ::PBIO_ERROR_BUSY if SPI is busy.
406+
* ::PBIO_ERROR_INVALID_ARG if argument is too big
407+
* ::PBIO_ERROR_IO for other errors.
408+
*/
409+
pbio_error_t pbdrv_block_device_ev3_spi_begin_for_adc(const uint32_t *cmds, volatile uint16_t *data, unsigned int len) {
410+
EDMA3CCPaRAMEntry_ ps;
411+
412+
if (len > SPI_MAX_DATA_SZ) {
413+
// Maximum size exceeded
414+
return PBIO_ERROR_INVALID_ARG;
415+
}
416+
if (bdev.spi_status & SPI_STATUS_WAIT_ANY) {
417+
// Another read operation is already in progress.
418+
return PBIO_ERROR_BUSY;
419+
}
420+
if (bdev.spi_status == SPI_STATUS_ERROR) {
421+
// Previous transmission went wrong.
422+
return PBIO_ERROR_IO;
423+
}
424+
425+
ps.p.srcAddr = (unsigned int)(cmds);
426+
ps.p.destAddr = SOC_SPI_0_REGS + SPI_SPIDAT1;
427+
ps.p.aCnt = sizeof(uint32_t);
428+
ps.p.bCnt = len;
429+
ps.p.cCnt = 1;
430+
ps.p.srcBIdx = sizeof(uint32_t);
431+
ps.p.destBIdx = 0;
432+
ps.p.srcCIdx = 0;
433+
ps.p.destCIdx = 0;
434+
ps.p.linkAddr = 0xffff;
435+
ps.p.bCntReload = 0;
436+
ps.p.opt = EDMA3CC_OPT_TCINTEN | (EDMA3_CHA_SPI0_TX << EDMA3CC_OPT_TCC_SHIFT);
437+
edma3_set_param(EDMA3_CHA_SPI0_TX, &ps);
438+
439+
ps.p.srcAddr = SOC_SPI_0_REGS + SPI_SPIBUF;
440+
ps.p.destAddr = (unsigned int)(data);
441+
ps.p.aCnt = sizeof(uint16_t);
442+
ps.p.bCnt = len;
443+
ps.p.srcBIdx = 0;
444+
ps.p.destBIdx = sizeof(uint16_t);
445+
ps.p.opt = EDMA3CC_OPT_TCINTEN | (EDMA3_CHA_SPI0_RX << EDMA3CC_OPT_TCC_SHIFT);
446+
edma3_set_param(EDMA3_CHA_SPI0_RX, &ps);
447+
448+
bdev.spi_status = SPI_STATUS_WAIT_TX | SPI_STATUS_WAIT_RX;
449+
450+
// TODO: pbio probably needs a framework for memory barriers and DMA cache management
451+
__asm__ volatile("":::"memory");
452+
453+
EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, EDMA3_CHA_SPI0_TX, EDMA3_TRIG_MODE_EVENT);
454+
EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, EDMA3_CHA_SPI0_RX, EDMA3_TRIG_MODE_EVENT);
455+
SPIIntEnable(SOC_SPI_0_REGS, SPI_DMA_REQUEST_ENA_INT);
456+
457+
return PBIO_SUCCESS;
458+
}
459+
396460

397461
static void set_address_be(uint8_t *buf, uint32_t address) {
398462
buf[0] = address >> 16;
@@ -650,4 +714,8 @@ void pbdrv_block_device_init(void) {
650714
pbio_os_process_start(&pbdrv_block_device_ev3_init_process, pbdrv_block_device_ev3_init_process_thread, NULL);
651715
}
652716

717+
int pbdrv_block_device_ev3_is_busy() {
718+
return bdev.spi_status & SPI_STATUS_WAIT_ANY;
719+
}
720+
653721
#endif // PBDRV_CONFIG_BLOCK_DEVICE_EV3

lib/pbio/drv/block_device/block_device_ev3.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,12 @@
1313
void pbdrv_block_device_ev3_spi_tx_complete();
1414
void pbdrv_block_device_ev3_spi_rx_complete();
1515

16+
// XXX The SPI flash and ADC both use the SPI0 peripheral.
17+
// Since we do not have a fully-fledged "bus" abstraction,
18+
// these two drivers have tight dependencies on each other.
19+
// These functions orchestrate the connection.
20+
21+
int pbdrv_block_device_ev3_is_busy();
22+
pbio_error_t pbdrv_block_device_ev3_spi_begin_for_adc(const uint32_t *cmds, volatile uint16_t *data, unsigned int len);
23+
1624
#endif // _INTERNAL_PBDRV_BLOCK_DEVICE_EV3_H_

0 commit comments

Comments
 (0)