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.

cc26xxcc26xx SSI (interrupt driven) action after each SPI sent

Hi,


short version: We need to poll the input of an GPIO pin very time after a word was received by the SSI module BUT before frame pin level goes high. How do one accomplish that using cc26xx family MCUs (without using SW/bitbanging)?

problems related to this topic (but answers not applicable here afaik):
e2e.ti.com/.../59710
e2e.ti.com/.../270502


long version: currently we using a CC430 MCU to read out a RHD2164 (datasheet: www.intantech.com/.../Intan_RHD2164_datasheet.pdf ) which comes along with a strangly modified double data rate SPI. But it is possible to read it out properly if one USCI is set as SPI Master with phase=0, the other USCI is set as SPI Slave with phase=1 and by "picking up" the last bit of every 16bit word  "manually" (this is needed because data presented on raising flank are shifted by one bit and the last bit is valid as long as chip select is active).
In need of increased wireless data rate we consider to switch to CC26xx family but there an (immediate) interrupt after every receive is missing. Abusing µDMA as an interrupt provider seems not adequate because in fact it can be forced to work in burst only but not in single only mode.
I am wondering if SSI really does not provide something like "one transfer-one trigger" (maybe using the µDMA?).

Any help/idea/hint would be appreciated.

best regards,
Christian B.

  • Hi Christian,

    Using DMA for this is not feasible because you will only get an interrupt once the transfer length in the DMA descriptor is reached.
    Do you need to collect a stream of words at the time or only one word?

    Your idea might work but requires you to set the CSN pin for SSI0 (master) to PIN_UNASSIGNED in the board file and rather control it manually using the PIN driver (ti/drivers/PIN.h).

    Once the transfer is done and you are missing the last bit it will remain set from the RHD2164. You can then either:

    • Connect the MISO signal to a separate pin and read it out using the PIN driver
    • Bypass the PIN driver and re-route the MISO pin in the IO Controller from the SSI0 module to the GPIO module and read out the last bit and then route it back (or run SPI_close to have it routed back).

    Regards,
    Svend

  • its a stream of words i need but the RHD2164 interface requires to pull CS up after every word. So the (current) action scheme on the CC430 is like:

    -pull CS down

    -send one word

    -receive one word (well it is a bit more tricky because a word is 16 bit but CC430 only handles 8bit)

    -poll MISO state to get last bit (currently we simply short wire a GPIO pin with the MISO pin)

    -release CS

    -repeat

    On the CC430 this can be done easily by RX interrupt handling. The question is how to archive the same thing on a CC26xx. So far the only solutions i see is to feed SSI word by word and constantly poll state (i.e. render FIFO useless and impact performance massively) or use GPIO interrupts to count CLK cycles and then trigger the "manual" MISO poll which is for sure not as reliable as an RX interrupt approach.

    Regards,

    Christian

  • Christian,

    Even if DMA were not used the SSI module would not give you an interrupt until after 4 or more entries are stored in the RX FIFO so there are no options in the current HW to achieve what you are trying to do without transferring word by word and read out a GPIO value after the transfer.

    The only alternative I could think of would be two set both SSI modules as master and start them "simultaneously" (but not connect CLK,MOSI ,CSN from e.g. SSI1). Connect CSN on SSI0 to the sensor and feed back CSN on SSI1 back to a GPIO and use the interrupt from this to read out the last bit.

    It would require modification of the SPI driver though so it is admittedly not a very clean solution. SSIEnable must be removed from SPICC26XXDMA_transfer and called after both SPI_transfer()'s has been called.
    You should also wrap the two SSIEnable calls in a critical section (driverLib/cpu.h - CPUcpsid/CPUcpsie) to ensure they are started fast enough after each other and it will possible also limit the maximum bitrate you can use due to the phase offset between the two modules.

    Regards,
    Svend
  • Svend,

    I am not sure if there is a missunderstanding on my side. How would setting both SSIs as master help with the issue?
    Furthermore using CS raise flank as interrupt might work sometimes but RHD2164 garantues validy of last bit until CS is raised. So if i trigger on the flank and then read out the last bit might already be invalid. I could of course use an analog "hull curve" circuit to perserve the last bit state between CS raising flank and read out but this seems fish to me.


    To the best of my knowlegde transfering the action scheme from CC430 to CC26xx would look like:
    1. setup SSI0 as master with Phase=0
    2. connect clock pin from SSI0 to SSI1 clock pin and setup SSI1 as slave with Phase=1
    3. pull GPIO CS down
    4. send one word via SSI0
    5. poll busy state of SSI1 (here is the main difference/issue)
    6. read out GPIO pin connected to SSI0 MISO
    7. pull GPIO CS up
    8. repeat

    This scheme should work but requires a) manual handling of CS b) manual word by word feeding c) continuous state polling. Do not get me wrong. Currently on the CC430 a) and b) are required as well. But only c) seems really troublesome and would not be required if an RX or busy/nonbusy interrupt would exists.

    Regards,
    Christian B.
  • Christian B said:
    How would setting both SSIs as master help with the issue?

    The idea was to use the HW-controlled unconnected CSN from one of them to trigger the interrupt on rising edge from this but you would not need two masters to do that. Anyway, it will not work due to the time limitations on CSN in the RHD2164.

    If you manually control CSN then you will only be able to transfer one word at the time due to the timing requirements of the RHD2164. Otherwise the SSI module will just continue transferring new data.

    If you limit the bitrate used with SPI so that you end up within the timing requirements of the RHD2164 you might get around needing involvement from the Cortex M3 at all.

    - Use one SSI as master and one as slave with opposite phases, let the HW SSI0 CSN control the transfer. HW CSN toggles between each word.
    - Connect CSN and CLK between SSI0 and SSI1.
    - Wake up the Sensor Controller CPU on negative edge of CSN (requires connection externally) and count 16 SCLK cycles by "bit-banging".
    - Store the input value on the IO to the Sensor Controller RAM, after completing N transfers you can simply interrupt the Cortex M3 and have it copy out the data.

    I think power-wise the optimal solution here would be to perform the transfers using bit-banging with the Sensor Controller CPU and store all data internally in the Sensor Controller RAM. Once the transfer is done you interrupt the CM3 and copy over the samples. It will require quite a bit of assembly programming though :]

    Svend

  • Your suggestion is interesting although i would like to avoid the clk counting/bit-banging part.
    How fast (latency wise) is the GPIO interrupt handling? What if i would route CSN SSI0 to GPIO pin to generate interrupts and use another GPIO Pin as "real" CS? This way one could CS let follow SSI0 CSN and include the last bit picking. Of course interrupt handling has to be fast compared to SSI. Is this approach feasable?
  • A Cortex M3 uses 14 CPU cycles @ 48MHz to enter an interrupt and then you have the TI RTOS interrupt handler on top of that adding some delay. You would probably need to reduce the SPI bit rate to somewhere around 100-500kHz to have enough time to do what you want.
  • Lets give it a shot. As we want to avoid RTOS and stick with the thin driver layer things might work out.
    Thank you so far your yielding inputs.