/*FUNCTION********************************************************************** * * Function Name : SPI_DRV_DmaMasterDeinit * Description : Shuts down a SPI instance with DMA support. * * This function resets the SPI peripheral, gates its clock, disables any used interrupts to * the core, and releases any used DMA channels. * *END**************************************************************************/ spi_status_t SPI_DRV_DmaMasterDeinit(uint32_t instance) { /* instantiate local variable of type spi_dma_master_state_t and point to global state */ spi_dma_master_state_t * spiDmaState = (spi_dma_master_state_t *)g_spiStatePtr[instance]; SPI_Type *base = g_spiBase[instance]; /* Restore the module to defaults which includes disabling the SPI then power it down.*/ SPI_HAL_Init(base); /* destroy the interrupt sync object.*/ OSA_SemaDestroy(&spiDmaState->irqSync); /* Disable SPI interrupt.*/ INT_SYS_DisableIRQ(g_spiIrqId[instance]); /* Gate the clock for SPI.*/ CLOCK_SYS_DisableSpiClock(instance); /* Free DMA channels */ DMA_DRV_FreeChannel(&spiDmaState->dmaReceive); DMA_DRV_FreeChannel(&spiDmaState->dmaTransmit); /* Clear state pointer. */ g_spiStatePtr[instance] = NULL; return kStatus_SPI_Success; }
/*FUNCTION********************************************************************** * * Function Name : SPI_DRV_MasterInit * Description : Initialize a SPI instance for master mode operation. * This function uses a CPU interrupt driven method for transferring data. * This function initializes the run-time state structure to track the ongoing * transfers, ungates the clock to the SPI module, resets and initializes the module * to default settings, configures the IRQ state structure, enables * the module-level interrupt to the core, and enables the SPI module. * *END**************************************************************************/ spi_status_t SPI_DRV_MasterInit(uint32_t instance, spi_master_state_t * spiState) { SPI_Type *base = g_spiBase[instance]; /* Clear the state for this instance.*/ memset(spiState, 0, sizeof(* spiState)); /* Enable clock for SPI*/ CLOCK_SYS_EnableSpiClock(instance); /* configure the run-time state struct with the source clock value */ spiState->spiSourceClock = CLOCK_SYS_GetSpiFreq(instance); /* Reset the SPI module to it's default state, which includes SPI disabled */ SPI_HAL_Init(base); /* Init the interrupt sync object.*/ OSA_SemaCreate(&spiState->irqSync, 0); /* Set SPI to master mode */ SPI_HAL_SetMasterSlave(base, kSpiMaster); /* Set slave select to automatic output mode */ SPI_HAL_SetSlaveSelectOutputMode(base, kSpiSlaveSelect_AutomaticOutput); /* Set the SPI pin mode to normal mode */ SPI_HAL_SetPinMode(base, kSpiPinMode_Normal); #if FSL_FEATURE_SPI_FIFO_SIZE if (g_spiFifoSize[instance] != 0) { /* If SPI module contains a FIFO, enable it and set watermarks to half full/empty */ SPI_HAL_SetFifoMode(base, true, kSpiTxFifoOneHalfEmpty, kSpiRxFifoOneHalfFull); } #endif /* Save runtime structure pointers to irq handler can point to the correct state structure*/ g_spiStatePtr[instance] = spiState; /* Enable SPI interrupt.*/ INT_SYS_EnableIRQ(g_spiIrqId[instance]); /* SPI system Enable*/ SPI_HAL_Enable(base); return kStatus_SPI_Success; }
void SpiInit(Spi_t *obj, PinNames mosi, PinNames miso, PinNames sclk, PinNames nss) { /* Check if a proper channel was selected */ if (g_spiBase[obj->instance] == NULL) return; obj->Spi = g_spiBase[obj->instance]; GpioInit(&obj->Mosi, mosi, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, 0); GpioInit(&obj->Miso, miso, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, 0); GpioInit(&obj->Sclk, sclk, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, 0); if (nss != NC) GpioInit(&obj->Nss, nss, PIN_ALTERNATE_FCT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1); /* Enable clock for SPI.*/ CLOCK_SYS_EnableSpiClock(obj->instance); // Initialize the SPI module registers to default value, which disables the module SPI_HAL_Init(obj->Spi); // Set the SPI pin mode to normal mode SPI_HAL_SetPinMode(obj->Spi, kSpiPinMode_Normal); #if FSL_FEATURE_SPI_FIFO_SIZE if (g_spiFifoSize[obj->instance] != 0) { // If SPI module contains a FIFO, disable it and set watermarks to half full/empty SPI_HAL_SetFifoMode(obj->Spi, false, kSpiTxFifoOneHalfEmpty, kSpiRxFifoOneHalfFull); } #endif if (!obj->isSlave) { // 8 bits, CPOL = 0, CPHA = 0, MASTER SpiFormat(obj, 8, 0, 0, 0); } else { // 8 bits, CPOL = 0, CPHA = 0, SLAVE SpiFormat(obj, 8, 0, 0, 1); } SpiFrequency(obj, 10000000); /* Enable Spi module */ SPI_HAL_Enable(obj->Spi); }
/*FUNCTION********************************************************************** * * Function Name : SPI_DRV_DmaSlaveDeinit * Description : De-initializes the device. * Clears the control register and turns off the clock to the module. * *END**************************************************************************/ spi_status_t SPI_DRV_DmaSlaveDeinit(uint32_t instance) { spi_dma_slave_state_t * spiState = (spi_dma_slave_state_t *)g_spiStatePtr[instance]; SPI_Type *base = g_spiBase[instance]; assert(instance < SPI_INSTANCE_COUNT); /* Disable SPI interrupt */ INT_SYS_DisableIRQ(g_spiIrqId[instance]); /* Reset the SPI module to its default settings including disabling SPI and its interrupts */ SPI_HAL_Init(base); #if FSL_FEATURE_SPI_16BIT_TRANSFERS if (g_spiFifoSize[instance] != 0) { SPI_HAL_SetFifoIntCmd(base, kSpiRxFifoNearFullInt, false); } /* disable transmit interrupt */ SPI_HAL_SetIntMode(base, kSpiTxEmptyInt, false); #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */ /* Free DMA channels */ DMA_DRV_FreeChannel(&spiState->dmaReceive); DMA_DRV_FreeChannel(&spiState->dmaTransmit); /* Disable clock for SPI */ CLOCK_SYS_DisableSpiClock(instance); /* Destroy the event */ OSA_EventDestroy(&spiState->event); /* Clear state pointer */ g_spiStatePtr[instance] = NULL; return kStatus_SPI_Success; }
/*FUNCTION********************************************************************** * * Function Name : SPI_DRV_DmaSlaveInit * Description : Initializes the SPI module for slave mode. * Saves the application callback info, turns on the clock to the module, * enables the device, and enables interrupts. Sets the SPI to a slave mode. * *END**************************************************************************/ spi_status_t SPI_DRV_DmaSlaveInit(uint32_t instance, spi_dma_slave_state_t * spiState, const spi_dma_slave_user_config_t * slaveConfig) { SPI_Type *base = g_spiBase[instance]; assert(slaveConfig); assert(instance < SPI_INSTANCE_COUNT); assert(spiState); #if FSL_FEATURE_SPI_16BIT_TRANSFERS if (slaveConfig->bitCount > kSpi16BitMode) { /* bits/frame larger than hardware support */ return kStatus_SPI_InvalidParameter; } #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */ /* Check if the slave already initialized */ if (g_spiStatePtr[instance]) { return kStatus_SPI_AlreadyInitialized; } /* Clear the state for this instance. */ memset(spiState, 0, sizeof(* spiState)); spiState->hasExtraByte = false; /* Update dummy pattern value */ spiState->dummyPattern = slaveConfig->dummyPattern; /* Enable clock for SPI */ CLOCK_SYS_EnableSpiClock(instance); /* Reset the SPI module to its default settings including disabling SPI */ SPI_HAL_Init(base); /* Initialize the event structure */ if (OSA_EventCreate(&spiState->event, kEventAutoClear) != kStatus_OSA_Success) { return kStatus_SPI_Error; } /* Set SPI to slave mode */ SPI_HAL_SetMasterSlave(base, kSpiSlave); /* Configure the slave clock polarity, phase and data direction */ SPI_HAL_SetDataFormat(base, slaveConfig->polarity, slaveConfig->phase, slaveConfig->direction); /* Set the SPI pin mode to normal mode */ SPI_HAL_SetPinMode(base, kSpiPinMode_Normal); #if FSL_FEATURE_SPI_16BIT_TRANSFERS SPI_HAL_Set8or16BitMode(base, slaveConfig->bitCount); #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */ #if FSL_FEATURE_SPI_FIFO_SIZE if (g_spiFifoSize[instance] != 0) { /* If SPI module contains a FIFO, enable it and set watermarks to half full/empty */ SPI_HAL_SetFifoMode(base, true, kSpiTxFifoOneHalfEmpty, kSpiRxFifoOneHalfFull); /* Set the interrupt clearing mechansim select for later use in driver to clear * status flags */ SPI_HAL_SetIntClearCmd(base, true); } #endif /* FSL_FEATURE_SPI_FIFO_SIZE */ /***************************************** * Request DMA channel for RX and TX FIFO *****************************************/ /* This channel transfers data from RX FIFO to receiveBuffer */ if (instance == 0) { /* Request DMA channel for RX FIFO */ if (kDmaInvalidChannel == DMA_DRV_RequestChannel(kDmaAnyChannel, kDmaRequestMux0SPI0Rx, &spiState->dmaReceive)) { return kStatus_SPI_DMAChannelInvalid; } /* Request DMA channel for TX FIFO */ if (kDmaInvalidChannel == DMA_DRV_RequestChannel(kDmaAnyChannel, kDmaRequestMux0SPI0Tx, &spiState->dmaTransmit)) { return kStatus_SPI_DMAChannelInvalid; } } #if (SPI_INSTANCE_COUNT > 1) else if (instance == 1) { /* Request DMA channel for RX FIFO */ if (kDmaInvalidChannel == DMA_DRV_RequestChannel(kDmaAnyChannel, kDmaRequestMux0SPI1Rx, &spiState->dmaReceive)) { return kStatus_SPI_DMAChannelInvalid; } /* Request DMA channel for TX FIFO */ if (kDmaInvalidChannel == DMA_DRV_RequestChannel(kDmaAnyChannel, kDmaRequestMux0SPI1Tx, &spiState->dmaTransmit)) { return kStatus_SPI_DMAChannelInvalid; } } else { return kStatus_SPI_OutOfRange; } #endif /* Save runtime structure pointers to irq handler can point to the correct state structure */ g_spiStatePtr[instance] = spiState; /* Enable SPI interrupt. The transmit interrupt should immediately cause an interrupt * which will fill in the transmit buffer and will be ready to send once the slave initiates * transmission. */ INT_SYS_EnableIRQ(g_spiIrqId[instance]); /* SPI module enable */ SPI_HAL_Enable(base); return kStatus_SPI_Success; }
/*FUNCTION********************************************************************** * * Function Name : SPI_DRV_DmaMasterInit * Description : Initializes a SPI instance for master mode operation to work with DMA. * This function uses a dma driven method for transferring data. * this function initializes the run-time state structure to track the ongoing * transfers, ungates the clock to the SPI module, resets the SPI module, initializes the module * to user defined settings and default settings, configures the IRQ state structure, enables * the module-level interrupt to the core, and enables the SPI module. * * This initialization function also configures the DMA module by requesting channels for DMA * operation. * *END**************************************************************************/ spi_status_t SPI_DRV_DmaMasterInit(uint32_t instance, spi_dma_master_state_t * spiDmaState) { SPI_Type *base = g_spiBase[instance]; /* Clear the state for this instance.*/ memset(spiDmaState, 0, sizeof(* spiDmaState)); /* Enable clock for SPI*/ CLOCK_SYS_EnableSpiClock(instance); /* configure the run-time state struct with the source clock value */ spiDmaState->spiSourceClock = CLOCK_SYS_GetSpiFreq(instance); /* Reset the SPI module to it's default state, which includes SPI disabled */ SPI_HAL_Init(base); /* Init the interrupt sync object.*/ if (OSA_SemaCreate(&spiDmaState->irqSync, 0) != kStatus_OSA_Success) { return kStatus_SPI_Error; } /* Set SPI to master mode */ SPI_HAL_SetMasterSlave(base, kSpiMaster); /* Set slave select to automatic output mode */ SPI_HAL_SetSlaveSelectOutputMode(base, kSpiSlaveSelect_AutomaticOutput); /* Set the SPI pin mode to normal mode */ SPI_HAL_SetPinMode(base, kSpiPinMode_Normal); #if FSL_FEATURE_SPI_FIFO_SIZE if (g_spiFifoSize[instance] != 0) { /* If SPI module contains a FIFO, enable it and set watermarks to half full/empty */ SPI_HAL_SetFifoMode(base, true, kSpiTxFifoOneHalfEmpty, kSpiRxFifoOneHalfFull); /* Set the interrupt clearing mechansim select for later use in driver to clear * status flags */ SPI_HAL_SetIntClearCmd(base, true); } #endif /* Save runtime structure pointers to irq handler can point to the correct state structure*/ g_spiStatePtr[instance] = spiDmaState; /***************************************** * Request DMA channel for RX and TX FIFO *****************************************/ /* This channel transfers data from RX FIFO to receiveBuffer */ if (instance == 0) { /* Request DMA channel for RX FIFO */ DMA_DRV_RequestChannel(kDmaAnyChannel, kDmaRequestMux0SPI0Rx, &spiDmaState->dmaReceive); /* Request DMA channel for TX FIFO */ DMA_DRV_RequestChannel(kDmaAnyChannel, kDmaRequestMux0SPI0Tx, &spiDmaState->dmaTransmit); } #if (SPI_INSTANCE_COUNT > 1) else { /* Request DMA channel for RX FIFO */ DMA_DRV_RequestChannel(kDmaAnyChannel, kDmaRequestMux0SPI1Rx, &spiDmaState->dmaReceive); /* Request DMA channel for TX FIFO */ DMA_DRV_RequestChannel(kDmaAnyChannel, kDmaRequestMux0SPI1Tx, &spiDmaState->dmaTransmit); } #endif /* Enable SPI interrupt.*/ INT_SYS_EnableIRQ(g_spiIrqId[instance]); /* SPI system Enable */ SPI_HAL_Enable(base); return kStatus_SPI_Success; }
/*! * @brief SPI slave polling. * * This function sends back received buffer from master through SPI interface. */ int main (void) { uint32_t j; SPI_Type * spiBaseAddr = g_spiBase[SPI_SLAVE_INSTANCE]; // init the hardware, this also sets up up the SPI pins for each specific SoC hardware_init(); OSA_Init(); PRINTF("\r\nSPI board to board polling example"); PRINTF("\r\nThis example run on instance %d", (uint32_t)SPI_SLAVE_INSTANCE); PRINTF("\r\nBe sure master's SPI%d and slave's SPI%d are connected", (uint32_t)SPI_SLAVE_INSTANCE, (uint32_t)SPI_SLAVE_INSTANCE); // Enable clock for SPI CLOCK_SYS_EnableSpiClock(SPI_SLAVE_INSTANCE); // Reset the SPI module to its default settings including disabling SPI SPI_HAL_Init(spiBaseAddr); // Set SPI to slave mode SPI_HAL_SetMasterSlave(spiBaseAddr, kSpiSlave); // Set the SPI pin mode to normal mode SPI_HAL_SetPinMode(spiBaseAddr, kSpiPinMode_Normal); #if FSL_FEATURE_SPI_FIFO_SIZE if (g_spiFifoSize[SPI_SLAVE_INSTANCE] != 0) { // If SPI module contains a FIFO, disable it and set watermarks to half full/empty SPI_HAL_SetFifoMode(spiBaseAddr, false, kSpiTxFifoOneHalfEmpty, kSpiRxFifoOneHalfFull); } #endif //USER CONFIGURABLE OPTION FOR 8 or 16-BIT MODE (if applicable) #if FSL_FEATURE_SPI_16BIT_TRANSFERS SPI_HAL_Set8or16BitMode(spiBaseAddr, kSpi8BitMode); #endif // SPI system Enable SPI_HAL_Enable(spiBaseAddr); // Setup format as same as master SPI_HAL_SetDataFormat(spiBaseAddr, kSpiClockPolarity_ActiveHigh, kSpiClockPhase_FirstEdge, kSpiMsbFirst); while(1) { PRINTF("\r\nSlave example is running...\r\n"); // Reset the sink buffer for (j = 0; j < TRANSFER_SIZE; j++) { s_spiSinkBuffer[j] = 0; } SPI_HAL_Disable(spiBaseAddr); SPI_HAL_Enable(spiBaseAddr); // Disable module to clear shift register for (j = 0; j <TRANSFER_SIZE; j++) { // Check if data received while(SPI_HAL_IsReadBuffFullPending(spiBaseAddr)==0){} #if FSL_FEATURE_SPI_16BIT_TRANSFERS // Read data from data register s_spiSinkBuffer[j] = SPI_HAL_ReadDataLow(spiBaseAddr); #else s_spiSinkBuffer[j] = SPI_HAL_ReadData(spiBaseAddr); #endif } // Disable module to clear shift register SPI_HAL_Disable(spiBaseAddr); SPI_HAL_Enable(spiBaseAddr); // Send data back to master for (j = 0; j <TRANSFER_SIZE; j++) { #if FSL_FEATURE_SPI_16BIT_TRANSFERS SPI_HAL_WriteDataBlocking(spiBaseAddr, kSpi8BitMode, 0, s_spiSinkBuffer[j]); #else SPI_HAL_WriteDataBlocking(spiBaseAddr, s_spiSinkBuffer[j]); #endif } // Print out receive buffer PRINTF("\r\nSlave receive:"); for (j = 0; j < TRANSFER_SIZE; j++) { // Print 16 numbers in a line. if ((j & 0x0F) == 0) { PRINTF("\r\n "); } PRINTF(" %02X", s_spiSinkBuffer[j]); } } }