//***************************************************************************** // //! This function enter point for write flow //! //! \param buffer //! //! \return none //! //! \brief ... // //***************************************************************************** long SpiFirstWrite(uint8_t *ucBuf, uint16_t usLength) { // // workaround for first transaction // AssertWlanCS(); usleep(70); // SPI writes first 4 bytes of data SpiWriteDataSynchronous(ucBuf, 4); usleep(70); SpiWriteDataSynchronous(ucBuf + 4, usLength - 4); sSpiInformation.ulSpiState = eSPI_STATE_IDLE; DeassertWlanCS(); //printf("Executed SpiFirstWrite!\n"); return(0); }
//***************************************************************************** // //! The IntSpiGPIOHandler interrupt handler //! //! \param none //! //! \return none //! //! \brief GPIO A interrupt handler. When the external SSI WLAN device is //! ready to interact with Host CPU it generates an interrupt signal. //! After that Host CPU has registrated this interrupt request //! it set the corresponding /CS in active state. // //***************************************************************************** //#pragma vector=PORT2_VECTOR //__interrupt void IntSpiGPIOHandler(void) int CC3000InterruptHandler(int irq, void *context) { uint32_t regval = 0; regval = getreg32(KL_PORTA_ISFR); if (regval & (1 << PIN4)) { if(spiEnabled) printf("Receive an Interrupt!\n"); if (!SPIInterruptsEnabled) { if(spiEnabled) printf("SPIInterrupt was disabled!\n"); goto out; } if(spiEnabled) printf("SPIInterrupt was enabled!\n"); if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) { /* This means IRQ line was low call a callback of HCI Layer to inform on event */ sSpiInformation.ulSpiState = eSPI_STATE_INITIALIZED; } else if (sSpiInformation.ulSpiState == eSPI_STATE_IDLE) { sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ; /* IRQ line goes down - start reception */ AssertWlanCS(); // // Wait for TX/RX Complete which will come as DMA interrupt // SpiReadHeader(); sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; SSIContReadOperation(); } else if (sSpiInformation.ulSpiState == eSPI_STATE_WRITE_IRQ) { SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); sSpiInformation.ulSpiState = eSPI_STATE_IDLE; DeassertWlanCS(); } else { } out: regval = (1 << PIN4); putreg32(regval, KL_PORTA_ISFR); } return 0; }
//***************************************************************************** // //! This function enter point for write flow //! //! \param SpiTriggerRxProcessing //! //! \return none //! //! \brief The function triggers a user provided callback for // //***************************************************************************** void SpiTriggerRxProcessing(void) { // // Trigger Rx processing // SpiPauseSpi(); DeassertWlanCS(); // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun // occurred - and we will stuck here forever! if (sSpiInformation.pRxPacket[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { while (1) ; } sSpiInformation.ulSpiState = eSPI_STATE_IDLE; sSpiInformation.SPIRxHandler(sSpiInformation.pRxPacket + SPI_HEADER_SIZE); }
void Wlan_Setup(void) { int ret; uint32_t regval; printf("\nExecuting kl_irq_initialize!\n"); /* Configure the PIN used to enable the chip */ kl_configgpio(GPIO_WIFI_EN); /* Configure PIN to detect interrupts */ kl_configgpio(GPIO_WIFI_IRQ); /* Configure PIN used as SPI CS */ kl_configgpio(GPIO_WIFI_CS); /* Make sure the chip is OFF before we start */ WriteWlanEnablePin(false); /* Make sure the SPI CS pin is deasserted */ DeassertWlanCS(); /* Configure pin to detect interrupt on falling edge */ regval = getreg32(KL_PORTA_PCR16); regval |= PORT_PCR_IRQC_FALLING; putreg32(regval, KL_PORTA_PCR16); ret = irq_attach(KL_IRQ_PORTA, CC3000InterruptHandler); if (ret == OK) { up_enable_irq(KL_IRQ_PORTA); } }
long SpiWrite(uint8_t *pUserBuffer, uint16_t usLength) { uint8_t ucPad = 0; // // Figure out the total length of the packet in order to figure out if there is padding or not // if(!(usLength & 0x0001)) { ucPad++; } pUserBuffer[0] = WRITE; pUserBuffer[1] = HI(usLength + ucPad); pUserBuffer[2] = LO(usLength + ucPad); pUserBuffer[3] = 0; pUserBuffer[4] = 0; usLength += (SPI_HEADER_SIZE + ucPad); // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) // for the purpose of overrun detection. If the magic number is overwritten - buffer overrun // occurred - and we will be stuck here forever! if (wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { while (1) ; } if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) { while (sSpiInformation.ulSpiState != eSPI_STATE_INITIALIZED) { } } if (sSpiInformation.ulSpiState == eSPI_STATE_INITIALIZED) { // // This is time for first TX/RX transactions over SPI: // the IRQ is down - so need to send read buffer size command // SpiFirstWrite(pUserBuffer, usLength); } else { // // We need to prevent here race that can occur in case two back to back packets are sent to the // device, so the state will move to IDLE and once again to not IDLE due to IRQ // tSLInformation.WlanInterruptDisable(); while (sSpiInformation.ulSpiState != eSPI_STATE_IDLE) { ; } sSpiInformation.ulSpiState = eSPI_STATE_WRITE_IRQ; sSpiInformation.pTxPacket = pUserBuffer; sSpiInformation.usTxPacketLength = usLength; // // Assert the CS line and wait till SSI IRQ line is active and then initialize write operation // AssertWlanCS(); // // Re-enable IRQ - if it was not disabled - this is not a problem... // tSLInformation.WlanInterruptEnable(); // // check for a missing interrupt between the CS assertion and enabling back the interrupts // if (tSLInformation.ReadWlanInterruptPin() == 0) { SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); sSpiInformation.ulSpiState = eSPI_STATE_IDLE; DeassertWlanCS(); } } // // Due to the fact that we are currently implementing a blocking situation // here we will wait till end of transaction // while (eSPI_STATE_IDLE != sSpiInformation.ulSpiState) ; return(0); }