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

nRF52 sending an octet

Hello,

I have been trying to use the nRF52 preview DK board as a master device with another chip as its slave device. Now I know that to read or write the function used is spi_send_recv which is provided in the example code for spi master. The chip requires specific registers to be written to so that it can be initialized.The problem is that I only want to send one byte but it appears that the minimum being sent to the MOSI pin is 2 bytes. Currently when I want to write to a specific register in the chip I use this function:

void as3911WriteRegister(uint8_t reg, uint8_t val){

uint8_t write_buffer[2];

SEGGER_RTT_WriteString(0, "Entered Write Register\n");

write_buffer[0] = reg | AS3911_WRITE_MODE;

write_buffer[1] = val;

spi_send_recv(write_buffer, NULL, 2);

}

Which sends 2 bytes as expected and as wanted, however there is another method where I only wish to send one byte which is:

void as3911ExecuteCommand(uint8_t cmd){

SEGGER_RTT_WriteString(0, "Entered Execute Command\n");

cmd |= AS3911_CMD_MODE;

spi_send_recv(&cmd, NULL, 1);

}

But after this method executes I still get 16 bits at MOSI, the first 8 are the cmd which is all thats wanted but the next 8 are the overrun characters 0xCC. I only need the first 8 and then the SS signal should turn high (so that the direct command begins execution on the chip) but that is not the case at the moment.

Why does this happen and how do I go about sending only an octet when needed?

Thank you in advance

  • Have not looked into this driver but, if it is using DMA then there is a known issue regarding this. You can find the related post here

  • Yes, that post covers the same issue. Ok, so I was wondering if it is possible to shorten the time for which SS is set to low by half then? Because the 8 bits that I need to send contain a command that will execute on the rising edge of the SS after those 8 bits have been sent.

  • 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. This is little ugly but works.

  • Thanks for letting me know about this, sorry for replying so late. I was wondering if this is still the only way around to send an octet? Or has the issue with using the DMA been fixed?

  • No it is not fixed yet, so for one byte transfers using DMA, you have to use this workaround.

Related