This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

spi_resume and spi_pause functions in CC3000 SPI code

I am trying to port the CC3000 example code over to Atmel controllers. I wanted to clarify that spi_resume and spi_pause are used to enable and disable interrupts. Please confirm this. 

  • Posting mainly to see what response this gets. I asked a similar question here http://e2e.ti.com/support/low_power_rf/f/851/t/304189.aspx but never got a reply. 

    It is my understanding that all these functions do is disable/enable interrupts, but I don't understand why the SpiResumeSpi function is called from within the host driver...

  • Hi,

    @Hardik,

    Yes, SpiResumeSpi enables the interrupt. And SpiPauseSpi disables the interrupt.

    @Alan,

    The registered 'tWlanInterruptEnable' is used during the initialization, when you enable the interrupt for the first time, and can also have functionalities used for one-time. Like initializing the interrupt status register.

    Thanks & Regards,

    Raghavendra

  • @Raghavendra Sorry for the late reply. Thanks for the response, but I do not understand the reasoning for this decision.

    Any first time setup should be done by the user, in SpiOpen(). They shouldn't need to abstract this by going through the host driver's data structures, to use a function pointer they registered. 

    Indeed tWlanInterruptEnable is not even called within the Host Driver code, making it a waste of space - since its calling code that is specific to the SPI driver port In the SPI driver port.

    Since you are using function pointers, it is my opinion that SpiResumeSpi should not be called in the HostDriver,  it should be tWlanInterruptEnable along side its counterpart WlanInterruptDisable. 

    However, since SpiOpen(), SpiClose() and SpiWrite() are directly called from the HostDriver anyway, and this code is intended for embedded devices where space is at a premium, I would suggest getting rid of these function pointers completely. Just insist that SpiResumeSpi() and SpiPauseSpi() are also functions provided by the user.

    Also, I am starting to think that saying tWlanInterruptEnable and tWlanInterruptDisable are for enabling and disabling interrupts is misleading at best, and applies heavily to MSP430 concepts. 

    I believe they should be deferring the interrupt - i.e. the interrupt is still recorded after a call to tWlanInterruptDisable, but is not fully processed until tWlanInterruptEnable  is called.

    See my post here for more information on why: http://e2e.ti.com/support/low_power_rf/f/851/p/312136/1086858.aspx#1086858

    Kind Regards,

    Alan

  • In one of the original driver implementations, shipped with the SDK install, it looks like these actually do enable or disable the interrupts. But, in the SpiWrite function, there is this block straight after reenabling them,

    // 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;

    DEASSERT_CS();
    }


    So the write can be performed inside the interrupt, or in the main thread, depending on whether the edge occurred when disabled or not - messy imo.
    I don't know the MSP chips, but certainly with my STM32 ARM processor, the interrupt can just be deferred, and allow it to get handled as soon as you renable the interrupt. And it looks like if you do it this way, the above code can be scrapped, as the interrupt will occur straight after they are re-enabled, and the write will be peformed.

    From the timing diagrams from TI, the major constraint with reading and writing seems to be making sure the IRQ line goes high between different reads and writes. I assume this is essential to proper operation, but what is confusing about the example implemntation, and others that I have seen is they all seem to rely entirely on an SPI_IDLE state, which is just software. This does not ensure in any way that the IRQ line has returned to a high state between reads. As the idle state is always set before releasing CS, this only makes the assumption that the IRQ line will go high soon after.

    But nothing actually seems to wait for this to happen ?

    I have searched the sample drivers for tSLInformation.ReadWlanInterruptPin() expecting some code somewhere to be polling this check it has gone high after a transaction, before allowing the next. But, actually now that i think about this, it could never be handled anywhere but the SPI driver itself, as that is where we do the final release of CS after a transaction, and wihtout CS being released, the IRQ line will of course stay low. I would expect to see a poll on tSLInformation.ReadWlanInterruptPin() after any read, or any write in the sample SPI driver implemtations, to make sure this happens before the next transaction.

    I am not sure, but slightly suspecting that this might be the cause of spurious problems with this module that I have seen on the forums. If another write comes in straight after a previous write, or a previous read, the state may well be IDLE, and CS may well be high, but the IRQ may not yet have responded to the release of the CS line, and may still be low. If CS is then pulled low again for this new write, presumably the IRQ line will stay low? and maybe result in dead lock? 

    From the timing diagrams it certainly looks like the IRQ line MUST be allowed to go high before the CS is pulled low again, and the example code or any drivers I've seen make not attempt to ensure this happens?

    Be interested if this is true, or if there is something I have overlooked. I have certainly make efforts in my SPI implementation (basically taken from alans chibi/os port and made to work with freertos) to make sure this happens.

    Cheers

    Rob.