Other Parts Discussed in Thread: SYSCONFIG, C2000WARE
Tool/software:
Hello everyone,
I am trying to adapt the provided sdspi.c driver to be able to use SPI via DMA to communicate with the SD Card. Without using DMA everything works fine, so there is no hardware issue here. By using DMA I am getting the correct interrupts, and the SPI clock and chips select are working like expected. The issue is that MOSI starts at 1 (3.3V) and after configuration stays at 0. MISO stays high all along. I checked the address registers and the memory, which is pointed to, and it seems fine. TXBuf stays always 0, it seems like the DMA never writes to TXBuf.
Here is a snipped of the code I have written in sdpi.c:
SPI_pollingFIFOTransactionWithNullSupport(uint32_t base, uint32_t dmaRxHandle, uint32_t dmaTxHandle, uint16_t* dmaSPIRxAddr, uint16_t* dmaSPITxAddr, uint16_t charLength, uint16_t *pTxBuffer, uint16_t *pRxBuffer, uint16_t numOfWords, uint16_t txDelay) { ASSERT((charLength >= 1U) && (charLength <= 16U)); ASSERT(DMA_isBaseValid(dmaRxHandle)); ASSERT(DMA_isBaseValid(dmaTxHandle)); SPI_setcharLength(base, charLength); SPI_disableFIFO(base); //Disable FIFO register SPI_enableFIFO(base); //Enable FIFO register //Configure the FIFO Transmit Delay SPI_setTxFifoTransmitDelay(base, txDelay); // // Determine the number of 16-level words from number of words to be // transmitted / received // uint16_t const numOfSixteenWords = numOfWords / SPI_FIFO_TXFULL; // // Determine the number of remaining words from number of words to be // transmitted / received // uint16_t const remainingWords = numOfWords % SPI_FIFO_TXFULL; uint16_t burst_size = 0u; uint16_t transfer_size = 1u; if( (charLength < 16u) && (pTxBuffer != NULL) ) { for(size_t i = 0u; i < numOfWords; i++) { pTxBuffer[i] = pTxBuffer[i] << (16u - charLength); } } /* In init phase enable interrupts for the SPI transaction */ if( !usingRTOS ) { Interrupt_enablePIE(); // Enable Interrupts at the CPU level EINT; ERTM; (void)__enable_interrupts(); } uint16_t dummy = 0xFFFFu; DMA_initController(); // // Number of transactions is based on numOfSixteenWords // Each transaction will transmit and receive 16 words. // if( numOfSixteenWords ) { SPI_setFIFOInterruptLevel(base, SPI_FIFO_TXEMPTY, SPI_FIFO_RXFULL); burst_size = 16u; transfer_size = numOfSixteenWords; if( pTxBuffer == NULL ) { DMA_configAddresses(dmaTxHandle, (uint16_t *)(base + SPI_O_TXBUF), &dummy); DMA_configBurst(dmaTxHandle, burst_size, 0, 0); DMA_configTransfer(dmaTxHandle, transfer_size, 0, 0); } else { DMA_configAddresses(dmaTxHandle, (uint16_t *)(base + SPI_O_TXBUF), pTxBuffer); DMA_configBurst(dmaTxHandle, burst_size, 1, 0); DMA_configTransfer(dmaTxHandle, transfer_size, 1, 0); } if( pRxBuffer == NULL ) { DMA_configAddresses(dmaRxHandle, &dummy, (uint16_t *)(base + SPI_O_RXBUF)); DMA_configBurst(dmaRxHandle, burst_size, 0, 0); DMA_configTransfer(dmaRxHandle, transfer_size, 0, 0); } else { DMA_configAddresses(dmaRxHandle, pRxBuffer, (uint16_t *)(base + SPI_O_RXBUF)); DMA_configBurst(dmaRxHandle, burst_size, 0, 1); DMA_configTransfer(dmaRxHandle, transfer_size, 0, 1); } DMA_configMode(dmaTxHandle, DMA_TRIGGER_SOFTWARE, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT); DMA_configMode(dmaRxHandle, DMA_TRIGGER_SPIDRX, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT); DMA_setEmulationMode(DMA_EMULATION_FREE_RUN); DMA_setInterruptMode(dmaRxHandle, DMA_INT_AT_END); DMA_setInterruptMode(dmaTxHandle, DMA_INT_AT_END); DMA_enableInterrupt(dmaRxHandle); DMA_enableInterrupt(dmaTxHandle); DMA_enableTrigger(dmaTxHandle); DMA_enableTrigger(dmaRxHandle); DMA_startChannel(dmaTxHandle); DMA_startChannel(dmaRxHandle); DMA_forceTrigger(dmaTxHandle); if( !usingRTOS ) { while( !rxDMADone ); rxDMADone = false; } else { CHK_RC_CODE(WaitEvent(WAIT_EVT_TIMER_T3P)); } } if( remainingWords > 0u ) { burst_size = remainingWords; SPI_setFIFOInterruptLevel(base, (SPI_TxFIFOLevel)burst_size, (SPI_RxFIFOLevel)burst_size); transfer_size = 1u; uint16_t const transferedWords = numOfSixteenWords * 16u; uint16_t* srcPtr = &pTxBuffer[transferedWords]; uint16_t* dstPtr = &pRxBuffer[transferedWords]; if( pTxBuffer == NULL ) { DMA_configAddresses(dmaTxHandle, (uint16_t *)(base + SPI_O_TXBUF), &dummy); DMA_configBurst(dmaTxHandle, burst_size, 0, 0); } else { DMA_configAddresses(dmaTxHandle, (uint16_t *)(base + SPI_O_TXBUF), srcPtr); DMA_configBurst(dmaTxHandle, burst_size, 1, 0); } if( pRxBuffer == NULL ) { DMA_configAddresses(dmaRxHandle, &dummy, (uint16_t *)(base + SPI_O_RXBUF)); DMA_configBurst(dmaRxHandle, burst_size, 0, 0); } else { DMA_configAddresses(dmaRxHandle, dstPtr, (uint16_t *)(base + SPI_O_RXBUF)); DMA_configBurst(dmaRxHandle, burst_size, 0, 1); } DMA_configTransfer(dmaTxHandle, transfer_size, 0, 0); DMA_configTransfer(dmaRxHandle, transfer_size, 0, 0); DMA_configMode(dmaTxHandle, DMA_TRIGGER_SOFTWARE, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT); DMA_configMode(dmaRxHandle, DMA_TRIGGER_SPIDRX, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT); DMA_setEmulationMode(DMA_EMULATION_FREE_RUN); DMA_setInterruptMode(dmaRxHandle, DMA_INT_AT_END); DMA_setInterruptMode(dmaTxHandle, DMA_INT_AT_END); DMA_enableInterrupt(dmaRxHandle); DMA_enableInterrupt(dmaTxHandle); DMA_enableTrigger(dmaTxHandle); DMA_enableTrigger(dmaRxHandle); DMA_startChannel(dmaTxHandle); DMA_startChannel(dmaRxHandle); DMA_forceTrigger(dmaTxHandle); if( !usingRTOS ) { while( !rxDMADone ); rxDMADone = false; } else { CHK_RC_CODE(WaitEvent(WAIT_EVT_TIMER_T3P)); } } /* In init phase disable interrupts after the SPI transaction */ if( !usingRTOS ) { Interrupt_disablePIE(); // Enable Interrupts at the CPU level DINT; DRTM; (void)__disable_interrupts(); }
SDSPI_Handle SDSPI_open(SDSPI_Handle handle) { if (handle->isOpen) { return (NULL); } handle->isOpen = true; /* Already done : */ /* Configure the SPI CS pin as output set high */ GPIO_setDirectionMode(handle->spiCsGpioIndex, GPIO_DIR_MODE_OUT); GPIO_setPadConfig(handle->spiCsGpioIndex, GPIO_PIN_TYPE_STD); // // GPIO_setMasterCore(handle->spiCsGpioIndex, GPIO_CORE_CPU1); // GPIO_setQualificationMode(handle->spiCsGpioIndex, GPIO_QUAL_SYNC); GPIO_writePin(handle->spiCsGpioIndex, 1); /* * SPI is initially set to 400 kHz to perform SD initialization. This is * is done to ensure compatibility with older SD cards. Once the card has * been initialized (in SPI mode) the SPI peripheral will be closed & * reopened at 10 MHz. */ //spiHandle initialization SPI_disableModule(handle->spiHandle); SPI_setConfig(handle->spiHandle, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA1, SPI_MODE_CONTROLLER, 400000, 8); SPI_enableFIFO(handle->spiHandle); SPI_disableLoopback(handle->spiHandle); SPI_setEmulationMode(handle->spiHandle, SPI_EMULATION_STOP_AFTER_TRANSMIT); SPI_enableModule(handle->spiHandle); /* Ensure the CS line is de-asserted. */ deassertCS(handle->spiCsGpioIndex); return (handle); }
Here is the first configuration of the SPI:
uint32_t const mySDCardCS = 94UL; uint32_t const mySDCardSPI_BASE = SPID_BASE; uint32_t const mySDCardSPI_BITRATE = 1000000UL; // GPIO103 -> mySDCardCS Pinmux GPIO_setPinConfig(GPIO_94_GPIO94); // // SPIC -> mySDCardSPI Pinmux // GPIO_setPinConfig(GPIO_91_SPID_SIMO); GPIO_setPinConfig(GPIO_92_SPID_SOMI); GPIO_setPinConfig(GPIO_93_SPID_CLK); GPIO_writePin(mySDCardCS, 1u); //mySDCardCS initialization GPIO_setDirectionMode(mySDCardCS, GPIO_DIR_MODE_OUT); GPIO_setPadConfig(mySDCardCS, GPIO_PIN_TYPE_STD); GPIO_setControllerCore(mySDCardCS, GPIO_CORE_CPU1); GPIO_setQualificationMode(mySDCardCS, GPIO_QUAL_SYNC); //mySDCardSPI initialization SPI_disableModule(mySDCardSPI_BASE); SPI_setConfig(mySDCardSPI_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA1, SPI_MODE_CONTROLLER, mySDCardSPI_BITRATE, 8); SPI_enableFIFO(mySDCardSPI_BASE); SPI_disableLoopback(mySDCardSPI_BASE); SPI_setEmulationMode(mySDCardSPI_BASE, SPI_EMULATION_STOP_AFTER_TRANSMIT); SPI_enableModule(mySDCardSPI_BASE); SPI_enableInterrupt(mySDCardSPI_BASE, SPI_INT_RXFF); SPI_enableInterrupt(mySDCardSPI_BASE, SPI_INT_TXFF);
Interrupts are enabled and registered:
// Register SD card DMA interrupts Interrupt_enable(INT_DMA_CH2); Interrupt_register(INT_DMA_CH2, &dma_rx_sd_card_isr); Interrupt_enable(INT_DMA_CH3); Interrupt_register(INT_DMA_CH3, &dma_tx_sd_card_isr);
The ISR look like this:
TI_RAMFUNC __interrupt void dma_rx_sd_card_isr(void) { DMA_stopChannel(DMA_CH2_BASE); if( usingRTOS ) { SignalEvent(WAIT_EVT_TIMER_T3P); } else { rxDMADone = true; } Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7); } TI_RAMFUNC __interrupt void dma_tx_sd_card_isr(void) { DMA_stopChannel(DMA_CH3_BASE); DMA_clearErrorFlag(DMA_CH3_BASE); DMA_clearTriggerFlag(DMA_CH3_BASE); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7); }
Is there something I forgot to configure ?