/*! * @brief DSPI master Polling. * * Thid function uses DSPI master to send an array to slave * and receive the array back from slave, * thencompare whether the two buffers are the same. */ int main(void) { uint32_t i; uint32_t loopCount = 1; SPI_Type * dspiBaseAddr = (SPI_Type*)SPI0_BASE; uint32_t dspiSourceClock; uint32_t calculatedBaudRate; dspi_device_t masterDevice; dspi_command_config_t commandConfig = { .isChipSelectContinuous = false, .whichCtar = kDspiCtar0, .whichPcs = kDspiPcs0, .clearTransferCount = true, .isEndOfQueue = false }; // Init hardware hardware_init(); // Init OSA layer, used in DSPI_DRV_MasterTransferBlocking. OSA_Init(); // Call this function to initialize the console UART. This function // enables the use of STDIO functions (printf, scanf, etc.) dbg_uart_init(); // Print a note. printf("\r\n DSPI board to board polling example"); printf("\r\n This example run on instance 0 "); printf("\r\n Be sure DSPI0-DSPI0 are connected "); // Configure SPI pins. configure_spi_pins(DSPI_MASTER_INSTANCE); // Enable DSPI clock. CLOCK_SYS_EnableSpiClock(DSPI_MASTER_INSTANCE); // Initialize the DSPI module registers to default value, which disables the module DSPI_HAL_Init(dspiBaseAddr); // Set to master mode. DSPI_HAL_SetMasterSlaveMode(dspiBaseAddr, kDspiMaster); // Configure for continuous SCK operation DSPI_HAL_SetContinuousSckCmd(dspiBaseAddr, false); // Configure for peripheral chip select polarity DSPI_HAL_SetPcsPolarityMode(dspiBaseAddr, kDspiPcs0, kDspiPcs_ActiveLow); // Disable FIFO operation. DSPI_HAL_SetFifoCmd(dspiBaseAddr, false, false); // Initialize the configurable delays: PCS-to-SCK, prescaler = 0, scaler = 1 DSPI_HAL_SetDelay(dspiBaseAddr, kDspiCtar0, 0, 1, kDspiPcsToSck); // DSPI system enable DSPI_HAL_Enable(dspiBaseAddr); // Configure baudrate. masterDevice.dataBusConfig.bitsPerFrame = 8; masterDevice.dataBusConfig.clkPhase = kDspiClockPhase_FirstEdge; masterDevice.dataBusConfig.clkPolarity = kDspiClockPolarity_ActiveHigh; masterDevice.dataBusConfig.direction = kDspiMsbFirst; DSPI_HAL_SetDataFormat(dspiBaseAddr, kDspiCtar0, &masterDevice.dataBusConfig); // Get DSPI source clock. dspiSourceClock = CLOCK_SYS_GetSpiFreq(DSPI_MASTER_INSTANCE); calculatedBaudRate = DSPI_HAL_SetBaudRate(dspiBaseAddr, kDspiCtar0, TRANSFER_BAUDRATE, dspiSourceClock); printf("\r\n Transfer at baudrate %lu \r\n", calculatedBaudRate); while(1) { // Initialize the transmit buffer. for (i = 0; i < TRANSFER_SIZE; i++) { sendBuffer[i] = i + loopCount; } // Print out transmit buffer. printf("\r\n Master transmit:"); for (i = 0; i < TRANSFER_SIZE; i++) { // Print 16 numbers in a line. if ((i & 0x0F) == 0) { printf("\r\n "); } printf(" %02X", sendBuffer[i]); } // Reset the receive buffer. for (i = 0; i < TRANSFER_SIZE; i++) { receiveBuffer[i] = 0; } // Restart the transfer by stop then start again, this will clear out the shift register DSPI_HAL_StopTransfer(dspiBaseAddr); // Flush the FIFOs DSPI_HAL_SetFlushFifoCmd(dspiBaseAddr, true, true); // Clear status flags that may have been set from previous transfers. DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxComplete); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiEndOfQueue); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoUnderflow); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoFillRequest); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoOverflow); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest); // Clear the transfer count. DSPI_HAL_PresetTransferCount(dspiBaseAddr, 0); // Start the transfer process in the hardware DSPI_HAL_StartTransfer(dspiBaseAddr); // Send the data to slave. for (i = 0; i < TRANSFER_SIZE; i++) { // Write data to PUSHR DSPI_HAL_WriteDataMastermodeBlocking(dspiBaseAddr, &commandConfig, sendBuffer[i]); // Delay to wait slave is ready. OSA_TimeDelay(1); } // Delay to wait slave is ready. OSA_TimeDelay(10); // Restart the transfer by stop then start again, this will clear out the shift register DSPI_HAL_StopTransfer(dspiBaseAddr); // Flush the FIFOs DSPI_HAL_SetFlushFifoCmd(dspiBaseAddr, true, true); //Clear status flags that may have been set from previous transfers. DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxComplete); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiEndOfQueue); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoUnderflow); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoFillRequest); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoOverflow); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest); // Clear the transfer count. DSPI_HAL_PresetTransferCount(dspiBaseAddr, 0); // Start the transfer process in the hardware DSPI_HAL_StartTransfer(dspiBaseAddr); // Receive the data from slave. for (i = 0; i < TRANSFER_SIZE; i++) { // Write command to PUSHR. DSPI_HAL_WriteDataMastermodeBlocking(dspiBaseAddr, &commandConfig, 0); // Check RFDR flag while (DSPI_HAL_GetStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest)== false) {} // Read data from POPR receiveBuffer[i] = DSPI_HAL_ReadData(dspiBaseAddr); // Clear RFDR flag DSPI_HAL_ClearStatusFlag(dspiBaseAddr,kDspiRxFifoDrainRequest); // Delay to wait slave is ready. OSA_TimeDelay(1); } // Print out receive buffer. printf("\r\n Master receive:"); for (i = 0; i < TRANSFER_SIZE; i++) { // Print 16 numbers in a line. if ((i & 0x0F) == 0) { printf("\r\n "); } printf(" %02X", receiveBuffer[i]); } // Check receiveBuffer. for (i = 0; i < TRANSFER_SIZE; ++i) { if (receiveBuffer[i] != sendBuffer[i]) { // Master received incorrect. printf("\r\n ERROR: master received incorrect "); return -1; } } printf("\r\n DSPI Master Sends/ Recevies Successfully"); // Wait for press any key. printf("\r\n Press any key to run again"); getchar(); // Increase loop count to change transmit buffer. loopCount++; } }
/*! * @brief Initiate (start) a transfer using DMA. This is not a public API as it is called from * other driver functions */ static dspi_status_t DSPI_DRV_DmaMasterStartTransfer(uint32_t instance, const dspi_dma_device_t * device, const uint8_t * sendBuffer, uint8_t * receiveBuffer, size_t transferByteCount) { /* instantiate local variable of type dspi_dma_master_state_t and point to global state */ dspi_dma_master_state_t * dspiDmaState = (dspi_dma_master_state_t *)g_dspiStatePtr[instance]; /* For temporarily storing DMA instance and channel */ uint8_t transferSizeInBytes = 1U; uint32_t calculatedBaudRate; dspi_command_config_t command; /* create an instance of the data command struct*/ SPI_Type *base = g_dspiBase[instance]; uint32_t txTransferByteCnt = 0; uint32_t rxTransferByteCnt = 0; /* Initialize s_wordToSend */ s_wordToSend = 0; /* Check that we're not busy.*/ if (dspiDmaState->isTransferInProgress) { return kStatus_DSPI_Busy; } /* Calculate the transfer size on bits/frame */ if (dspiDmaState->bitsPerFrame <= 8) { transferSizeInBytes = 1U; } else if (dspiDmaState->bitsPerFrame <= 16) { transferSizeInBytes = 2U; } else { transferSizeInBytes = 4U; } /* Configure bus for this device. If NULL is passed, we assume the caller has * preconfigured the bus using DSPI_DRV_DmaMasterConfigureBus(). * Do nothing for calculatedBaudRate. If the user wants to know the calculatedBaudRate * then they can call this function separately. */ if (device) { DSPI_DRV_DmaMasterConfigureBus(instance, device, &calculatedBaudRate); dspiDmaState->bitsPerFrame = device->dataBusConfig.bitsPerFrame; /*update bits/frame*/ } /* Check the transfer byte count. If bits/frame > 8, meaning 2 bytes, and if * the transfer byte count is an odd count we'll have to increase the TX transfer byte count * by one and assert a flag to indicate to the send functions that it will * need to handle an extra byte. * For receive, we actually round down the transfer count to the next lowest even number. * Then in the interrupt handler, we take care of geting this last byte. */ if ((dspiDmaState->bitsPerFrame > 8) && (transferByteCount & 1UL)) { dspiDmaState->extraByte = true; txTransferByteCnt = transferByteCount + 1U; /* Increment to next even byte count */ rxTransferByteCnt = transferByteCount & ~1U; /* Decrement to next even byte count */ } else { dspiDmaState->extraByte = false; txTransferByteCnt = transferByteCount; rxTransferByteCnt = transferByteCount; } /* Store the receiveBuffer pointer and receive byte count to the run-time state struct * for later use in the interrupt handler. */ dspiDmaState->rxBuffer = (uint8_t *)receiveBuffer; dspiDmaState->rxTransferByteCnt = rxTransferByteCnt; /* Save information about the transfer for use by the ISR.*/ dspiDmaState->isTransferInProgress = true; /* Reset the transfer counter to 0. Normally this is done via the PUSHR[CTCNT], but as we * are under DMA controller, we won't be able to change this bit dynamically after the * first word is transferred. */ DSPI_HAL_PresetTransferCount(base, 0); /* flush the fifos*/ DSPI_HAL_SetFlushFifoCmd(base, true, true); /* Clear status flags that may have been set from previous transfers */ DSPI_HAL_ClearStatusFlag(base, kDspiTxComplete); DSPI_HAL_ClearStatusFlag(base, kDspiEndOfQueue); DSPI_HAL_ClearStatusFlag(base, kDspiTxFifoUnderflow); DSPI_HAL_ClearStatusFlag(base, kDspiTxFifoFillRequest); DSPI_HAL_ClearStatusFlag(base, kDspiRxFifoOverflow); DSPI_HAL_ClearStatusFlag(base, kDspiRxFifoDrainRequest); /************************************************************************************ * Set up the RX DMA channel Transfer Control Descriptor (TCD) * Do this before filling the TX FIFO. * Note, if there is no remaining receive count, then bypass RX DMA set up. * This means we only have one byte to read of a 16-bit data word and will read this * in the complete transfer function. ***********************************************************************************/ /* If a receive buffer is used and if rxTransferByteCnt > 0 */ if (rxTransferByteCnt) { if (!receiveBuffer) { /* Set up this channel's control which includes enabling the DMA interrupt */ DMA_DRV_ConfigTransfer(&dspiDmaState->dmaRxChannel, kDmaPeripheralToPeripheral, transferSizeInBytes, DSPI_HAL_GetPoprRegAddr(base), /* src is data register */ (uint32_t)(&s_rxBuffIfNull), /* dest is temporary location */ (uint32_t)(rxTransferByteCnt)); } else { /* Set up this channel's control which includes enabling the DMA interrupt */ DMA_DRV_ConfigTransfer(&dspiDmaState->dmaRxChannel, kDmaPeripheralToMemory, transferSizeInBytes, DSPI_HAL_GetPoprRegAddr(base), /* src is data register */ (uint32_t)(receiveBuffer), /* dest is rx buffer */ (uint32_t)(rxTransferByteCnt)); /* Destination size is only 1 byte */ DMA_DRV_SetDestTransferSize(&dspiDmaState->dmaRxChannel, 1U); } /* Enable the DMA peripheral request */ DMA_DRV_StartChannel(&dspiDmaState->dmaRxChannel); } else if (dspiDmaState->extraByte) { /* Need to receive only one frame - extra byte by calling Rx callback function*/ DSPI_DRV_DmaRxCallback((void *)instance, kDmaIdle); } /************************************************************************************ * Set up the Last Command/data Word Intermediate Buffer and fill up the TX FIFO. ***********************************************************************************/ /* Before sending the data, we first need to initialize the data command struct * Configure the data command attributes for the desired PCS, CTAR, and continuous PCS * which are derived from the run-time state struct */ command.whichPcs = dspiDmaState->whichPcs; command.whichCtar = dspiDmaState->whichCtar; command.clearTransferCount = false; /* don't clear the transfer count */ /************************************************************************ * Next, set up the Last Command/data Word Intermediate Buffer before * filling up the TX FIFO * Create a 32-bit word with the final 16-bit command settings. This means * that EOQ = 1 and CONT = 0. * This 32-bit word will also be initialized with the final data byte/word * from the send source buffer and then the entire 32-bit word will be * transferred to the DSPI PUSHR. ************************************************************************/ /* Declare a variable for storing the last send data (either 8- or 16-bit) */ uint32_t lastWord = 0; /* If a send buffer was provided, the word comes from there. Otherwise we just send * a zero (initialized above). */ if (sendBuffer) { /* Store the last byte from the send buffer */ if (dspiDmaState->bitsPerFrame <= 8) { lastWord = sendBuffer[txTransferByteCnt-1]; /* Last byte */ } /* Store the last two bytes the send buffer */ else { /* If 16-bit transfers and odd transfer byte count then an extra byte was added * to the transfer byte count, but we cannot access more of the send buffer */ if(!dspiDmaState->extraByte) { lastWord = sendBuffer[txTransferByteCnt-1] ; /* Save off the last byte */ lastWord = lastWord << 8U; /* Shift to MSB (separate step due to MISHA) */ } lastWord |= sendBuffer[txTransferByteCnt-2]; /* OR with next to last byte */ } } /* Now, build the last command/data word intermediate buffer */ command.isChipSelectContinuous = false; /* Always clear CONT for last data word */ command.isEndOfQueue = true; /* Set EOQ for last data word */ s_lastCmdData = DSPI_HAL_GetFormattedCommand(base, &command) | lastWord; /************************************************************************ * Begin TX DMA channels transfer control descriptor set up. * 1. First, set up intermediate buffers which contain 16-bit commands. * 2. Set up the DMA Software Transfer Control Descriptors (STCD) for various * scenarios: * - Channel for intermediate buffer to TX FIFO * - Channel for source buffer to intermediate buffer * - STCD for scatter/gather for end of previous channel to replace * intermediate buffer with last-command buffer. ************************************************************************/ /************************************************************************ * Intermediate Buffer * Create a 32-bit word with the 16-bit command settings. Data from * the send source buffer will be transferred here and then the entire * 32-bit word will be transferred to the DSPI PUSHR. * This buffer will be preloaded with the next data word in the send buffer ************************************************************************/ /* restore the isChipSelectContinuous setting to the original value as it was cleared above */ command.isChipSelectContinuous = dspiDmaState->isChipSelectContinuous; command.isEndOfQueue = false; /* Clear End of Queue (previously set for last cmd/data word)*/ s_cmdData = DSPI_HAL_GetFormattedCommand(base, &command); /* Place the next data from the send buffer into the intermediate buffer (preload it) * based on whether it is one byte or two. */ if (dspiDmaState->bitsPerFrame <= 8) { /* If a send buffer was provided, the word comes from there. Otherwise we just send * a zero (initialized above). */ if (sendBuffer) { s_wordToSend = *sendBuffer; /* queue up the next data */ ++sendBuffer; /* increment to next data word*/ } --txTransferByteCnt; /* decrement txTransferByteCnt*/ } else { /* If a send buffer was provided, the word comes from there. Otherwise we just send * a zero (initialized above). */ if (sendBuffer) { s_wordToSend = *sendBuffer; ++sendBuffer; /* increment to next data byte */ /* Note, if the extraByte flag is set and we're down to the last two bytes we can still * do this even though we're going past the sendBuffer size. We're just reading data we * don't care about anyways since it is dummy data to make up for the last byte. */ s_wordToSend |= (unsigned)(*sendBuffer) << 8U; ++sendBuffer; /* increment to next data byte */ } txTransferByteCnt -= 2; /* decrement txTransferByteCnt by 2 bytes */ } s_cmdData |= s_wordToSend; /* write s_wordToSend to intermediate buffer */ /* For Tx, DSPI need two DMA channel, one for calculate the command and data into one value * (dmaTxCmdChannel), and another for push the value into DSPI PUSHR register (dmaTxDataChannel). * The dmaTxCmdChannel DMA channel will be triggered by DSPI Tx FIFO, and the dmaTxDataChannel * DMA channel will be linked to calculate DMA channel and triggered by this channel also. */ /* If the transfer size is less than size of one frame, only transmit the last byte that calculated */ if (!txTransferByteCnt) { DMA_DRV_ConfigTransfer(&dspiDmaState->dmaTxDataChannel, kDmaMemoryToPeripheral, 4u, (uint32_t)(&s_lastCmdData), DSPI_HAL_GetMasterPushrRegAddr(base), 4u); /* Register callback for last byte transmitting */ DMA_DRV_RegisterCallback(&dspiDmaState->dmaTxDataChannel, DSPI_DRV_DmaTxLastCallback, (void *)instance); } else { /* Config DMA to copy data from generated cmd data to FIFO */ if (dspiDmaState->bitsPerFrame <= 8) { DMA_DRV_ConfigTransfer(&dspiDmaState->dmaTxDataChannel, kDmaPeripheralToPeripheral, 4u, (uint32_t)(&s_cmdData), DSPI_HAL_GetMasterPushrRegAddr(base), (uint32_t)((txTransferByteCnt) * 4)); } else { DMA_DRV_ConfigTransfer(&dspiDmaState->dmaTxDataChannel, kDmaPeripheralToPeripheral, 4u, (uint32_t)(&s_cmdData), DSPI_HAL_GetMasterPushrRegAddr(base), (uint32_t)((txTransferByteCnt) * 2)); } /* Register Tx callback function */ DMA_DRV_RegisterCallback(&dspiDmaState->dmaTxDataChannel, DSPI_DRV_DmaTxCallback, (void *)instance); /* Config dmaTxCmdChannel channel if send buffer is provided */ if (sendBuffer) { dma_channel_link_config_t config; DMA_DRV_ConfigTransfer(&dspiDmaState->dmaTxCmdChannel, kDmaMemoryToPeripheral, 1u, (uint32_t)(sendBuffer), (uint32_t)(&s_cmdData), (uint32_t)(txTransferByteCnt - transferSizeInBytes)); if (dspiDmaState->bitsPerFrame > 8) { DMA_DRV_SetDestTransferSize(&dspiDmaState->dmaTxCmdChannel, 2U); } /* Link dmaTxCmdChannel after dmaTxDataChannel */ config.channel1 = dspiDmaState->dmaTxCmdChannel.channel; config.channel2 = 0; config.linkType = kDmaChannelLinkChan1; DMA_DRV_ConfigChanLink(&dspiDmaState->dmaTxDataChannel, &config); /* start channel */ DMA_DRV_StartChannel(&dspiDmaState->dmaTxCmdChannel); } } /* Register callback */ DMA_DRV_RegisterCallback(&dspiDmaState->dmaRxChannel, DSPI_DRV_DmaRxCallback, (void *)instance); /* Enable the Receive FIFO Drain DMA Request */ DSPI_HAL_SetRxFifoDrainDmaIntMode(base, kDspiGenerateDmaReq, true); /* Enable TFFF DMA request */ DSPI_HAL_SetTxFifoFillDmaIntMode(base, kDspiGenerateDmaReq, true); /* Enable the DMA peripheral request */ DMA_DRV_StartChannel(&dspiDmaState->dmaTxDataChannel); return kStatus_DSPI_Success; }
/*! * @brief DSPI slave Polling. * * This function sends back received buffer from master through DSPI interface. */ int main(void) { uint32_t i; SPI_Type * dspiBaseAddr = (SPI_Type*)SPI0_BASE; dspi_slave_user_config_t slaveConfig; // Init hardware hardware_init(); // Init OSA layer, used in DSPI_DRV_MasterTransferBlocking. OSA_Init(); // Call this function to initialize the console UART. This function // enables the use of STDIO functions (printf, scanf, etc.) dbg_uart_init(); // Configure SPI pins. configure_spi_pins(DSPI_SLAVE_INSTANCE); // Print a note. printf("\r\n DSPI board to board polling example"); printf("\r\n This example run on instance 0 "); printf("\r\n Be sure DSPI0-DSPI0 are connected "); // Enable clock for DSPI CLOCK_SYS_EnableSpiClock(DSPI_SLAVE_INSTANCE); // Reset the DSPI module, which also disables the DSPI module DSPI_HAL_Init(dspiBaseAddr); // Set to slave mode. DSPI_HAL_SetMasterSlaveMode(dspiBaseAddr, kDspiSlave); // Set data format slaveConfig.dataConfig.clkPhase = kDspiClockPhase_FirstEdge; slaveConfig.dataConfig.clkPolarity = kDspiClockPolarity_ActiveHigh; slaveConfig.dataConfig.bitsPerFrame = 8; DSPI_HAL_SetDataFormat(dspiBaseAddr, kDspiCtar0, &(slaveConfig.dataConfig)); // DSPI system enable DSPI_HAL_Enable(dspiBaseAddr); // Disable FIFO operation. DSPI_HAL_SetFifoCmd(dspiBaseAddr, false, false); while(1) { printf("\r\n Slave example is running..."); // Reset the receive buffer. for (i = 0; i < TRANSFER_SIZE; i++) { receiveBuffer[i] = 0; } // Restart the transfer by stop then start again, this will clear out the shift register DSPI_HAL_StopTransfer(dspiBaseAddr); // Flush the FIFOs DSPI_HAL_SetFlushFifoCmd(dspiBaseAddr, true, true); // Clear status flags that may have been set from previous transfers DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxComplete); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiEndOfQueue); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoUnderflow); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoFillRequest); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoOverflow); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest); // Clear the transfer count DSPI_HAL_PresetTransferCount(dspiBaseAddr, 0); // Start the transfer process in the hardware DSPI_HAL_StartTransfer(dspiBaseAddr); for (i = 0; i < TRANSFER_SIZE; i++) { // Check RFDR flag while (DSPI_HAL_GetStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest)== false) {} // Read data from POPR receiveBuffer[i] = DSPI_HAL_ReadData(dspiBaseAddr); // Clear RFDR flag DSPI_HAL_ClearStatusFlag(dspiBaseAddr,kDspiRxFifoDrainRequest); } // Restart the transfer by stop then start again, this will clear out the shift register DSPI_HAL_StopTransfer(dspiBaseAddr); // Flush the FIFOs DSPI_HAL_SetFlushFifoCmd(dspiBaseAddr, true, true); // Clear status flags that may have been set from previous transfers DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxComplete); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiEndOfQueue); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoUnderflow); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiTxFifoFillRequest); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoOverflow); DSPI_HAL_ClearStatusFlag(dspiBaseAddr, kDspiRxFifoDrainRequest); // Clear the transfer count DSPI_HAL_PresetTransferCount(dspiBaseAddr, 0); // Start the transfer process in the hardware DSPI_HAL_StartTransfer(dspiBaseAddr); // Send the data to slave. for (i = 0; i < TRANSFER_SIZE; i++) { // Write data to PUSHR DSPI_HAL_WriteDataSlavemodeBlocking(dspiBaseAddr, receiveBuffer[i]); } // Print out receive buffer. printf("\r\n Slave receive:"); for (i = 0; i < TRANSFER_SIZE; i++) { // Print 16 numbers in a line. if ((i & 0x0F) == 0) { printf("\r\n "); } printf(" %02X", receiveBuffer[i]); } } }
/************************************************************************* * Function Name: SPI0_init * Parameters: none * Return: none * Description: SPI initialization *************************************************************************/ void SPI0_init(void) { dspi_baud_rate_divisors_t divisors; divisors.doubleBaudRate = 0; divisors.baudRateDivisor = 3; divisors.prescaleDivisor = 3; dspi_data_format_config_t config; config.clkPhase = kDspiClockPhase_SecondEdge; config.bitsPerFrame = 8; config.clkPolarity = kDspiClockPolarity_ActiveHigh; config.direction = kDspiMsbFirst; #if defined(KV10Z7_SERIES) PORT_HAL_SetMuxMode(PORTC_BASE_PTR,2,kPortMuxAsGpio);// MC33937 RESET GPIO_HAL_SetPinDir(GPIOC_BASE_PTR, 2, kGpioDigitalOutput); PORT_HAL_SetMuxMode(PORTD_BASE_PTR,7,kPortMuxAsGpio);// MC33937 DRV_EN GPIO_HAL_SetPinDir(GPIOD_BASE_PTR, 7, kGpioDigitalOutput); #elif (defined(KV10Z1287_SERIES) || defined(KV11Z7_SERIES)) PORT_HAL_SetMuxMode(PORTE_BASE_PTR,29,kPortMuxAsGpio);// MC33937 DRV_EN GPIO_HAL_SetPinDir(GPIOE_BASE_PTR, 29, kGpioDigitalOutput); #endif GPIO_HAL_SetPinOutput(GPIOC_BASE_PTR, 2);//MC33937_RESET_HIGH; #if defined(KV10Z7_SERIES) GPIO_HAL_SetPinOutput(GPIOD_BASE_PTR, 7);//MC33937_ENABLE_HIGH; #elif (defined(KV10Z1287_SERIES) || defined(KV11Z7_SERIES)) GPIO_HAL_SetPinOutput(GPIOE_BASE_PTR, 29); #endif DSPI_HAL_StopTransfer(SPI0_BASE_PTR);// halt SPI before SPI setting DSPI_HAL_Enable(SPI0_BASE_PTR);//Enables the DSPI peripheral and sets the MCR MDIS to 0. DSPI_HAL_SetMasterSlaveMode(SPI0_BASE_PTR, kDspiMaster);//Enable Master Mode DSPI_HAL_SetPcsPolarityMode(SPI0_BASE_PTR, kDspiPcs0,kDspiPcs_ActiveLow);//The setting for either "active high, inactive low (0)" or "active low, inactive high(1)" of type dspi_pcs_polarity_config_t. DSPI_HAL_SetFifoCmd(SPI0_BASE_PTR, false, false);//Disable the DSPI FIFOs. DSPI_HAL_PresetTransferCount(SPI0_BASE_PTR, 0x0000);//Pre-sets the transfer count. DSPI_HAL_SetDelay(SPI0_BASE_PTR, kDspiCtar0,3,0, kDspiPcsToSck); // CTAR0 selection option for master or slave mode DSPI_HAL_SetDelay(SPI0_BASE_PTR, kDspiCtar0,2,0, kDspiLastSckToPcs); DSPI_HAL_SetDelay(SPI0_BASE_PTR, kDspiCtar0,0,2, kDspiAfterTransfer); DSPI_HAL_SetBaudDivisors(SPI0_BASE_PTR, kDspiCtar0, &divisors); DSPI_HAL_SetDataFormat(SPI0_BASE_PTR, kDspiCtar0, &config); DSPI_HAL_ClearStatusFlag(SPI0_BASE_PTR ,kDspiTxComplete);///*!< TCF status/interrupt enable */ DSPI_HAL_ClearStatusFlag(SPI0_BASE_PTR ,kDspiEndOfQueue);///*!< EOQF status/interrupt enable*/ DSPI_HAL_ClearStatusFlag(SPI0_BASE_PTR ,kDspiTxFifoUnderflow);///*!< TFUF status/interrupt enable*/ DSPI_HAL_ClearStatusFlag(SPI0_BASE_PTR ,kDspiTxFifoFillRequest);///*!< TFFF status/interrupt enable*/ DSPI_HAL_ClearStatusFlag(SPI0_BASE_PTR ,kDspiRxFifoOverflow);///*!< RFOF status/interrupt enable*/ DSPI_HAL_SetIntMode(SPI0_BASE_PTR,kDspiTxComplete, false);/*!< TCF status/interrupt disable */ DSPI_HAL_SetIntMode(SPI0_BASE_PTR,kDspiEndOfQueue, false);/*!< EOQF status/interrupt disable */ DSPI_HAL_SetIntMode(SPI0_BASE_PTR,kDspiTxFifoUnderflow, false);/*!< TFUF status/interrupt disable*/ DSPI_HAL_SetIntMode(SPI0_BASE_PTR,kDspiTxFifoFillRequest, false);/*!< TFFF status/interrupt disable*/ DSPI_HAL_SetIntMode(SPI0_BASE_PTR,kDspiRxFifoOverflow, false);/*!< RFOF status/interrupt disable*/ DSPI_HAL_SetIntMode(SPI0_BASE_PTR,kDspiRxFifoDrainRequest, false);/*!< RFDF status/interrupt disable*/ DSPI_HAL_StartTransfer(SPI0_BASE_PTR);// Starts the DSPI transfers, clears HALT bit in MCR. PORT_HAL_SetMuxMode(PORTD_BASE_PTR, 3, kPortMuxAlt2); PORT_HAL_SetMuxMode(PORTD_BASE_PTR, 2, kPortMuxAlt2); PORT_HAL_SetMuxMode(PORTC_BASE_PTR, 0, kPortMuxAlt7); PORT_HAL_SetMuxMode(PORTC_BASE_PTR, 5, kPortMuxAlt2); }
/*! * @brief Initiate (start) a transfer. This is not a public API as it is called from other * driver functions */ static dspi_status_t DSPI_DRV_MasterStartTransfer(uint32_t instance, const dspi_device_t * device) { /* instantiate local variable of type dspi_master_state_t and point to global state */ dspi_master_state_t * dspiState = (dspi_master_state_t *)g_dspiStatePtr[instance]; SPI_Type *base = g_dspiBase[instance]; uint32_t calculatedBaudRate; /* Check that we're not busy.*/ if (dspiState->isTransferInProgress) { return kStatus_DSPI_Busy; } /* Configure bus for this device. If NULL is passed, we assume the caller has * preconfigured the bus using DSPI_DRV_MasterConfigureBus(). * Do nothing for calculatedBaudRate. If the user wants to know the calculatedBaudRate * then they can call this function separately. */ if (device) { DSPI_DRV_MasterConfigureBus(instance, device, &calculatedBaudRate); dspiState->bitsPerFrame = device->dataBusConfig.bitsPerFrame;/*update dspiState bits/frame*/ } /* Check the transfer byte count. If bits/frame > 8, meaning 2 bytes and if * the transfer byte count is an odd count we'll have to increase the transfer byte count * by one and assert a flag to indicate to the send and receive functions that it will * need to handle an extra byte. */ if ((dspiState->bitsPerFrame > 8) && (dspiState->remainingSendByteCount & 1UL)) { dspiState->remainingSendByteCount += 1; dspiState->remainingReceiveByteCount += 1; dspiState->extraByte = true; } else { dspiState->extraByte = false; } /* Save information about the transfer for use by the ISR.*/ dspiState->isTransferInProgress = true; /* Restart the transfer by stop then start again, this will clear out the shift register */ DSPI_HAL_StopTransfer(base); /* flush the fifos*/ DSPI_HAL_SetFlushFifoCmd(base, true, true); /* Clear status flags that may have been set from previous transfers */ DSPI_HAL_ClearStatusFlag(base, kDspiTxComplete); DSPI_HAL_ClearStatusFlag(base, kDspiEndOfQueue); DSPI_HAL_ClearStatusFlag(base, kDspiTxFifoUnderflow); DSPI_HAL_ClearStatusFlag(base, kDspiTxFifoFillRequest); DSPI_HAL_ClearStatusFlag(base, kDspiRxFifoOverflow); DSPI_HAL_ClearStatusFlag(base, kDspiRxFifoDrainRequest); /* Clear the transfer count */ DSPI_HAL_PresetTransferCount(base, 0); /* Start the transfer, make sure to do this before filling the FIFO */ DSPI_HAL_StartTransfer(base); /* Fill up the DSPI FIFO (even if one word deep, data still written to data buffer) */ DSPI_DRV_MasterFillupTxFifo(instance); /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt * Since SPI is a synchronous interface, we only need to enable the RX interrupt. * The IRQ handler will get the status of RX and TX interrupt flags. */ DSPI_HAL_SetRxFifoDrainDmaIntMode(base, kDspiGenerateIntReq, true); return kStatus_DSPI_Success; }
uint16_t SpiInOut(Spi_t *obj, uint16_t outData) { uint16_t data = 0x00; if ((obj == NULL) || (obj->Spi) == NULL) { while (1) ; } if (obj->isSlave) { } else { dspi_command_config_t commandConfig = { .isChipSelectContinuous = false, .whichCtar = kDspiCtar0, .whichPcs = kDspiPcs0, .clearTransferCount = true, .isEndOfQueue = false }; if (outData != 0x00) { // Restart the transfer by stop then start again, this will clear out the shift register DSPI_HAL_StopTransfer(obj->Spi); // Flush the FIFOs DSPI_HAL_SetFlushFifoCmd(obj->Spi, true, true); // Clear status flags that may have been set from previous transfers. DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxComplete); DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiEndOfQueue); DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxFifoUnderflow); DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxFifoFillRequest); DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiRxFifoOverflow); DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiRxFifoDrainRequest); // Clear the transfer count. DSPI_HAL_PresetTransferCount(obj->Spi, 0); // Start the transfer process in the hardware DSPI_HAL_StartTransfer(obj->Spi); // Send the data to slave. // Write data to PUSHR DSPI_HAL_WriteDataMastermode(obj->Spi, &commandConfig, outData); } else { // Restart the transfer by stop then start again, this will clear out the shift register DSPI_HAL_StopTransfer(obj->Spi); // Flush the FIFOs DSPI_HAL_SetFlushFifoCmd(obj->Spi, true, true); //Clear status flags that may have been set from previous transfers. DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxComplete); DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiEndOfQueue); DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxFifoUnderflow); DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiTxFifoFillRequest); DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiRxFifoOverflow); DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiRxFifoDrainRequest); // Clear the transfer count. DSPI_HAL_PresetTransferCount(obj->Spi, 0); // Start the transfer process in the hardware DSPI_HAL_StartTransfer(obj->Spi); // Write command to PUSHR. DSPI_HAL_WriteDataMastermode(obj->Spi, &commandConfig, 0); // Check RFDR flag while (DSPI_HAL_GetStatusFlag(obj->Spi, kDspiRxFifoDrainRequest) == false) { } // Read data from POPR data = DSPI_HAL_ReadData(obj->Spi); // Clear RFDR flag DSPI_HAL_ClearStatusFlag(obj->Spi, kDspiRxFifoDrainRequest); } } return data; }