Trouble with Zephyr SPI slave

Hi,

I've got a two-processor board (i.e. another processor in addition to the two-core nrf5340) where the other processor is sending data to my nrf5340 via SPI. The Nordic is the SPI slave.

*Oh, I'm currently using SDK version 1.5.1. I tried upgrading to the current 1.7.0 but the peripheral_uart example (which I'm using as my starting point) doesn't compile in that version. I get an error about a missing psa_crypto_slot_manager file or something? For now I'm just going to proceed with my v1.5.1 project unless someone thinks my issue was fixed in a newer version.

I can see the data on my logic analyzer. The clock is pretty quick (6.5MHz) but it looks like it should work.

I'm getting NRFX_SPIS_XFER_DONE interrupts, but the rx_amount is always 0.

In chasing the problem I was concerned about making sure that the pin setup macros worked for GPIO on port 1 because my chip select pin is pin 1.02. I found that none of the PSEL registers for SPIS0_NS are getting set to what I want them to, and I assume this is the source of my problem.

Here's the current state of my code:

#define GPIO_PORT_1_OFFSET 32

#define PIN_SCK            12
#define PIN_MOSI           22
#define PIN_MISO           20
#define PIN_CSN            GPIO_PORT_1_OFFSET + 2

#define SPIS_NR            0     // Using SPI0

#define SPI_BUFFER_SIZE    256

//== Global Variables ========================================================
nrfx_spis_t spi_slave_instance = NRFX_SPIS_INSTANCE(SPIS_NR);

nrfx_spis_config_t spis_config = NRFX_SPIS_DEFAULT_CONFIG(PIN_SCK,PIN_MOSI,PIN_MISO,PIN_CSN);

uint8_t rx_buffer[SPI_BUFFER_SIZE];
uint8_t tx_buffer[SPI_BUFFER_SIZE];

//== Function prototypes =====================================================
void spis_event_handler(nrfx_spis_evt_t const *p_event, void *p_context);

//============================================================================

//----------------------------------------------------------------------------
// Name  :
// Desc  :
// Ins   : none
// Outs  : none
//----------------------------------------------------------------------------
void spi_comms_init(void)
{
   int err;

    err = nrfx_spis_init(&spi_slave_instance, &spis_config, spis_event_handler, NULL);
    if(err != NRFX_SUCCESS){
        LOG_WRN("Error with init.\n");
    } else {
        LOG_WRN("SPIS started.\n");
    }

    err = nrfx_spis_buffers_set(&spi_slave_instance, tx_buffer, sizeof(tx_buffer), rx_buffer, sizeof(rx_buffer));
    if(err != NRFX_SUCCESS)
    {
        LOG_WRN("Error with setting.\n");
    }

    IRQ_DIRECT_CONNECT(SPIM0_SPIS0_TWIM0_TWIS0_UARTE0_IRQn, 0, nrfx_spis_0_irq_handler, 0);
    irq_enable(SPIM0_SPIS0_TWIM0_TWIS0_UARTE0_IRQn);
}


//----------------------------------------------------------------------------
// Name  :
// Desc  :
// Ins   : none
// Outs  : none
//----------------------------------------------------------------------------
void spis_event_handler(nrfx_spis_evt_t const *p_event, void *p_context)
{
    int err;
    switch(p_event->evt_type){
        case NRFX_SPIS_XFER_DONE:
            if (p_event->rx_amount > 0)
            {
               LOG_INF("received 0x%02x 0x%02x 0x%02x 0x%02x\n", rx_buffer[0], rx_buffer[1], rx_buffer[2], rx_buffer[3]);
            }
            
            //LOG_INF("Rx bytes: %u\n", p_event->rx_amount);
            err = nrfx_spis_buffers_set(&spi_slave_instance, tx_buffer, sizeof(tx_buffer), rx_buffer, sizeof(rx_buffer));
            if(err != NRFX_SUCCESS){
                LOG_WRN("Error with setting.\n");
            }
            break;
        case NRFX_SPIS_BUFFERS_SET_DONE:
            //LOG_WRN("buffers set\n");
            break;
        case NRFX_SPIS_EVT_TYPE_MAX:
        
            break;
        default:
            ;
    }
}

I wondered if it would make a difference if I tried to assign my pins using the project overlay file, so I added a prj.overlay file as follows - no difference in behavior

&spi0 {
	compatible = "nordic,nrf52-spis";
	label = "SPI_0";
	status = "okay";
	mosi-pin = <22>;
	miso-pin = <20>;
	sck-pin  = <12>;
	csn-pin  = <34>;
	def-char = <0xFF>;
};

I stopped the debugger as soon as I get to main and those SPIS0_NS PSEL values are there as soon as I hit my breakpoint, and none of my SPI setup code changes them. I also tried changing my prj.overlay to assign completely different pin numbers and that has no effect either.

Any ideas?

Thanks!

Glen

Parents Reply Children
  • So both this example and the other one I found have the slave actively performing transfers in order to receive things. I was expecting that since my device is a slave that all I had to do was configure the peripheral and then wait for an interrupt to tell me that data had arrived. Is that not the case? Do I have to actively poll for received data?

    Also, I found a function called nrf_spis_subscribe_set in the driver. Is that something I need to use? The InfoCenter doesn't tell me anything more about it than what I already guessed from the function name.

    Is there an appnote or something on how the SPI slave peripheral works? I can't find any real documentation.

  • Glen M said:
    So both this example and the other one I found have the slave actively performing transfers in order to receive things. I was expecting that since my device is a slave that all I had to do was configure the peripheral and then wait for an interrupt to tell me that data had arrived. Is that not the case? Do I have to actively poll for received data?

    The SPIS handling uses a mutex in the zephyr port "spi_nrfx_spis.c", so even if it looks to be a blocking/polling implementation, it is actually event driven underneath.

    Glen M said:
    Is there an appnote or something on how the SPI slave peripheral works? I can't find any real documentation.

    I'm not aware of any appnote here, but we have the PS: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf5340%2Fspis.html

Related