void SpiFormat(Spi_t *obj, int8_t bits, int8_t cpol, int8_t cpha, int8_t slave) { spi_clock_polarity_t clockPolarity; spi_clock_phase_t clockPhase; spi_data_bitcount_mode_t bitCount; /* Disable Spi module */ SPI_HAL_Disable(obj->Spi); clockPolarity = ((cpol != 1) ? kSpiClockPolarity_ActiveHigh : kSpiClockPolarity_ActiveLow); clockPhase = ((cpha != 1) ? kSpiClockPhase_FirstEdge : kSpiClockPhase_SecondEdge); bitCount = ((bits != 8) ? kSpi16BitMode : kSpi8BitMode); if (obj->isSlave) { /* Set SPI to master mode */ SPI_HAL_SetMasterSlave(obj->Spi, kSpiSlave); } else { /* Set SPI to master mode */ SPI_HAL_SetMasterSlave(obj->Spi, kSpiMaster); // Set slave select to automatic output mode SPI_HAL_SetSlaveSelectOutputMode(obj->Spi, kSpiSlaveSelect_AutomaticOutput); } SPI_HAL_SetDataFormat(obj->Spi, clockPolarity, clockPhase, kSpiMsbFirst); SPI_HAL_Set8or16BitMode(obj->Spi, bitCount); /* Enable Spi module */ SPI_HAL_Enable(obj->Spi); }
/*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; }
/*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]); } } }