@@ -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
397461static 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
0 commit comments