This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Can't transmit single byte over SPIM with DMA

Hi,

We are trying to transmit a single byte over SPIM using easyDMA but our logic analyzer shows that 16 bits are being clocked out. The first 8 are our message and the second 8 are unknown (possibly the over-read char?). This can be reproduced with the spi_master example in the nrf52 0.9.1 SDK by enabling DMA and configuring 1 byte transmissions:


spi_master/main.c

Replace line 42 with: #define TX_RX_MSG_LENGTH 1

spi_master/config/spi_master_pca10036/nrf_drv_config.h

Replace line 128 with: #define SPI0_USE_EASY_DMA 1

Replace line 138 with: #define SPI1_ENABLE 0

patchfile: spi_master.patch


The project will now attempt to send the byte 0x00 over spi with easyDMA.

Logic trace of what we are seeing.: SPIM_EasyDMA_1Byte_Tx.logicdata image description

Any Idea what is happening here and how we might be able to send 1 byte over SPI & DMA without the 8 extra clock cycles?

  • Hi

    So sorry for the late response. It seems like you have found a product anomaly. We are working on it, but currently we have not found any workarounds.

  • Hello I came across this post and am having the same issue. I was wondering if you have found any solutions? What I noticed was that the CS signal goes low and then stays low when I try to send 8 bits in a format such as:

    uint8_t bytebuffer = 0x4E;

    spi_send_recv(&bytebuffer, NULL, 1);

    However if I set the length to 2, the CS behaves normally. But the functionality that I need requires 8 bits to be sent with only 8 clock cycles and then the CS should go high after the 8th. Which i haven't been able to find a way to do yet using the nRF52 Preview DK. If you could let me know about any progress on this issue or how to solve it, it would be appreciated. Thanks

  • There is a PAN for this with the workaround, you can see this here

    [58] SPIM: SPIM clocks out an additional byte when RXD.MAXCNT = 1

    You can use the SPI module same as nRF51 (depreciated but still available at same register addresses) That SPI module can be use for one byte transfers. Else you need to use below workaround

    /**
     * @brief Work-around for transmitting 1 byte with SPIM.
     *
     * @param spim: The SPIM instance that is in use.
     * @param ppi_channel: An unused PPI channel that will be used by the
     workaround.
     * @param gpiote_channel: An unused GPIOTE channel that will be used by
     the workaround.
     *
     * @warning Must not be used when transmitting multiple bytes.
     * @warning After this workaround is used, the user must reset the PPI
     channel and the GPIOTE channel before attempting to transmit multiple
     bytes.
     */
    void setup_workaround_for_ftpan_58(NRF_SPIM_Type * spim, uint32_t
     ppi_channel, uint32_t gpiote_channel)
    {
     // Create an event when SCK toggles.
     NRF_GPIOTE->CONFIG[gpiote_channel] = (
     GPIOTE_CONFIG_MODE_Event <<
     GPIOTE_CONFIG_MODE_Pos
     ) | (
     spim->PSEL.SCK <<
     GPIOTE_CONFIG_PSEL_Pos
     ) | (
     GPIOTE_CONFIG_POLARITY_Toggle <<
     GPIOTE_CONFIG_POLARITY_Pos
     );
     // Stop the spim instance when SCK toggles.
     NRF_PPI->CH[ppi_channel].EEP = (uint32_t)&NRF_GPIOTE-
    >EVENTS_IN[gpiote_channel];
     NRF_PPI->CH[ppi_channel].TEP = (uint32_t)&spim->TASKS_STOP;
     NRF_PPI->CHENSET = 1U << ppi_channel;
    3 New and inherited anomalies
    Page 12
     // The spim instance cannot be stopped mid-byte, so it will finish
     // transmitting the first byte and then stop. Effectively ensuring
     // that only 1 byte is transmitted.
    }
    

    What this workaround does is that it uses GPIOTE and PPI to trigger the SPI->TASKS_STOP when the SPI_CLOCK toggles. And since the SPI transaction cannot be stopped mid byte, it will complete that one byte transfer.

    You have to remember to enable the GPIOTE and PPI channel used for this workaround just before one byte transfer and then disable them when you want to transfer multiple bytes. I verified this and it works.

  • I found another way to solve this problem. Just try RXD.MAXCNT = 0.

  • I noticed the same behavior. CS goes low and goes high before next transfer(if any). Any updates on this issue??

Related