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

nrf_drv_spi_xfer, descriptor, pointers

I want to send packets of 16 bit data over SPI at regular periods from a buffer. I'd appreciate a bit of clarification how to use the SPI xfer function (I already have the timer & PPI set up).

Code snippet below, I have a couple of questions:

1. How to set the pointer in the descriptor? I get an "incompatible pointer type" warning (this may be my inexperience with 'C' showing)

2. What to do with the RX values when the application is transmit only? Leave blank, or set up a dummy receive buffer?

// EasyDMA stuff

static BYTE data_buffer[16];
nrf_drv_spi_xfer_desc_t spi_xfer_desc;

typedef struct ArrayList{	
							uint8_t sample[2];
						} ArrayList_type;

ArrayList_type spi_buffer1[sizeof data_buffer];

  spi_xfer_desc.p_tx_buffer = &spi_buffer1; //warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
  spi_xfer_desc.tx_length = sizeof(spi_buffer1);
  
  nrf_drv_spi_xfer(&spi, &spi_xfer_desc, 0);

  • Hello,

    1. How to set the pointer in the descriptor? I get an "incompatible pointer type" warning (this may be my inexperience with 'C' showing)

     As you can see in the nrf_drv_spi_xfer_desc_t documentation the pointer to tx buffer must be a unint8_t type pointer. You are providing a pointer to a ArrayList_type struct. You could set the buffer as demonstrated in the SPI example:

    ..
    
    #define SPI_INSTANCE  0 /**< SPI instance index. */
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
    
    ..
    
    #define TEST_STRING "Nordic"
    static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
    static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];    /**< RX buffer. */
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    ..
    
        nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length);
    
    ..

    2. What to do with the RX values when the application is transmit only? Leave blank, or set up a dummy receive buffer?

    Just supply a dummy buffer. If the slave is not sending anything, it will remain empty.

    As a side note, I notice that you are using the nrf_drv, which is deprecated, and would suggest that you instead move to use the SPIM or SPIS driver - if this is not done for a particular reason? the nrf_drv drivers are fully functional, but will be discontinued in future(not immediate) SDK releases, so using the nrfx_ drivers will be easier to maintain.

    For further detail you should see the SPIM API Reference.
    Additionally, I can also recommend you to have a look at the SPIM and SPIS examples.

    Let me know if you should encounter any more issues or questions in the future!

    Best regards,
    Karl

     

  • OK firstly as to which libraries - I'm just picking up bits & pieces from the web and examples (many of the SDK examples seem to use the old libraries) in order to get a proof of concept working.

    Regarding the buffer type, I need to use PPI to send the buffer with a timer event & SPI task and was going by this article hence using EasyDMA as per the article (and according to EasyDMA docs ArrayList_type is the only data type supported).

    I'm not even sure if I need EasyDMA... the job here is to write out 16 bits at a time from a buffer at a rate of 44100 per sec which as you can probably guess is for playing audio. This by the way will be with a Softdevice running and an active GATT connection which is why I opted for DMA to keep CPU overhead down. 

    So I presume it can be done from the article I linked? If so I'm pretty impressed with this device even if getting to grips with the libraries can be a little daunting Confused

  • Hello again,

    Nick_RA said:
    OK firstly as to which libraries - I'm just picking up bits & pieces from the web and examples (many of the SDK examples seem to use the old libraries) in order to get a proof of concept working.

    I understand. This is correct, many of the examples use the nrf_drv_* - which is still fully functional -  but for new developments we recommend going with the nrfx_* right off the bat, to make future development and maintenance easier.

    Nick_RA said:
    Regarding the buffer type, I need to use PPI to send the buffer with a timer event & SPI task and was going by this article hence using EasyDMA as per the article (and according to EasyDMA docs ArrayList_type is the only data type supported).

    Are you working on a Development kit? If so, is it the nRF52 DK, or the nRF52840 DK?
    Are you here referring to the array list section of the easyDMA documentation?

    Nick_RA said:
    This by the way will be with a Softdevice running and an active GATT connection which is why I opted for DMA to keep CPU overhead down. 

    Yes, using easyDMA is a great strength when using peripherals such as SPIM in combination with the SoftDevice and other CPU tasks.

    Nick_RA said:
    So I presume it can be done from the article I linked?

    Yes, you may very well connect a peripheral to a timer/other peripheral using PPI. Do I understand you correctly that you would like the SPIM transfer to happen at a given interval?
    As Kenneth mentions in the DevZone ticket you linked to, the saadc example demonstrates how to set up a peripheral(the SAADC in this case) with PPI, and link the PPI to a given timer.

    Nick_RA said:
    I'm pretty impressed with this device even if getting to grips with the libraries can be a little daunting

    Thanks, I am glad to hear you are impressed with our product!
    You are right that there is a small threshold to get to know all the different libraries and functionality, but feel free to ask around here on DevZone with any questions or issues you might encounter.
    We are happy to help! :)

    Best regards,
    Karl

     

  • IHi

    'm using the nRF52 DK currently, which is hooked up to a SD card adapter and 2-channel DAC both by SPI.

    Yes, I need to fire the SPI from the timer hence the PPI. I've already got the timer and PPI working, currently it's just toggling a gpio so the next progression is to move tfrom a gpio to a SPI task.

    The 52832 docs differ from the 52840 docs, this is what I was reading

    EasyDMA list
    EasyDMA supports one list type.

    The supported list type is:

    Array list

    ..which infers that one MUST use a list, and that's the only reason I was. Quite happy to use a simple byte array!

    Thanks

    Nick

  • Hi Nick,

    Yes, the list feature is useful when requiring the least possible CPU inference between transfers - using arraylist allows you to allocate a long buffer to be used in the repeated transfers triggered by PPI, without requiring CPU interference.
    But as you state, you may very well just use uint8_t arrays instead, as long as they are in the easyDMA region.

    Does this answer your questions?

    Feel free to come back if you should encounter any more issues or questions in the future! :)

    Best regards,
    Karl

Related