nRF5340 SPI slave doesnt seem to receive

Hi,

I have ported my already working nRF52840 SPI slave code to a nRF5340, but it doesnt seem to receive any data. I have verified the CS, SCK and MOSI signals, but no MISO from nRF5340.

.
.
static const struct spi_config spis_cfg = {
	.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_OP_MODE_SLAVE | SPI_MODE_CPOL | SPI_MODE_CPHA,
	.slave = 1,
};
.
.
static void spi_slave_init(void)
{
	spis_dev = DEVICE_DT_GET(MY_SPI_SLAVE);
	
	if (!device_is_ready(spis_dev)) {
		printk("SPI slave device not ready!\n");
	}
	else
		LOG_INF ("SPI slave ready");
}
.
.
static int spi_slave_check_for_message(void)
{
	int signaled, result;

	k_poll_signal_check(&spi_slave_done_sig, &signaled, &result);
	
	if (signaled != 0){
		slave_tx_buffer [0] = 0x01;	// init slave tx buffer
		return 0;
	}
	
	else return -1;
}
.
.
static int spi_slave_wait_msg(uint8_t txlen, uint8_t rxlen)
{
	const struct spi_buf s_tx_buf = {
		.buf = slave_tx_buffer,
		.len = txlen 
	};
	const struct spi_buf_set s_tx = {
		.buffers = &s_tx_buf,
		.count = 1
	};

	struct spi_buf s_rx_buf = {
		.buf = slave_rx_buffer,
		.len = rxlen
	};
	const struct spi_buf_set s_rx = {
		.buffers = &s_rx_buf,
		.count = 1
	};

	// Reset signal - this flag the next msg check 
	k_poll_signal_reset(&spi_slave_done_sig);
	
	// Start transaction
	int error = spi_transceive_signal(spis_dev, &spis_cfg, &s_tx, &s_rx, &spi_slave_done_sig);	// once a cycle is complete, the 'spi_slave_done_sig' will get signelled

	if(error != 0){
		LOG_ERR("SPI slave transceive error: %i\n", error);
		return error;
	}
	
	return 0;
}
.
.
static void spis_handler (struct k_work *item) {

static uint8_t txlen, rxlen;
int8_t i=0, loopCnt=0;
static uint8_t startRec=0;
uint16_t hostFWRev;

	if (spi_slave_check_for_message() == 0){
		
		LOG_INF ("---- Received SPI msg -----");

		switch (slave_rx_buffer [0]) {
			case 'V':	// Feature 7
				hostFWRev = EncVerString ();
				LOG_INF ("Host radio FW : %04x", hostFWRev);
				
				slave_tx_buffer[0] = 'A';
				slave_tx_buffer[1] = (uint8_t)(hostFWRev >> 8);
				slave_tx_buffer[2] = (uint8_t)(hostFWRev & 0x00ff);
				txlen = 3;
				rxlen = 1;
				break;
			

			case 'A':	// ACK/NAK request. This is the second byte send by host after the command. Only thing we need is to send the ACK/NAK of last command
				//LOG_INF ("ACK/NAK command");
				break;

			default :
				LOG_ERR ("default %x, %c", slave_rx_buffer [0], slave_rx_buffer [0]);
				slave_tx_buffer[0] = 'K';
				txlen = 1;
				rxlen = 1;
		}
		// Prepare the next SPI slave transaction -  this means the ACK/NAK doesnt get send immediately, but in next rx cycle. 
		// This means we have to either send same command twice or have a ACK/NAK request command, which is send after each command
		spi_slave_wait_msg(txlen, rxlen);	
	}

	k_msleep (1);
	k_work_submit (item);
}
.
.
void main(void)
{
.
.
    k_poll_signal_reset(&spi_slave_done_sig);
	spi_slave_init ();
	spi_slave_wait_msg (1, 1);	// this starts the k_poll event to wait for next spi rx

	k_work_init(&spis_work, spis_handler);		// spis handling is done in system queue to avoid issues with spi async transfers
	k_work_submit (&spis_work);
	.
	.
}

I get 'SPI slave ready' as a result of invoking spi_slave_init () function.

I can see the spis_handler () is invoked repeatedly, but 'spi_slave_check_for_message() == 0' seems to fail all the time.

I use nordic SDK 2.9.0.

I saw in the nRF5340 user guide that there is a hardware semaphore for accessing spi buffers, which was not available in nRF52840. Is there anything I need to implement in the application level to do that?

I have tried all I can think of and need some help urgently.

Thanks,

Kaushalya

Parents
  • Hello,

    I suggest to look at the driver test examples for spi, which also include spis:
    \zephyr\tests\drivers\spi\spi_controller_peripheral\src\main.c

    By default I can see there is no overlay for nRF5340, but I would expect you can rename nrf52840dk_nrf52840.overlay to nrf5340dk_nrf5340_cpuapp.overlay, and update the pins used for spi and spis, and then it should work.

    Kenneth

  • Hi,

    We need some help urgently as we are stuck at this point.

    After refering bit more on NORA B1 user guide, I come across this.

    "SPIM4: For the fastest SPI mode, the special purpose GPIO pins are enabled using the Peripheral setting of the MCUSEL pin of the PIN_CNF register. When activated, the SPIM PSEL settings are ignored, and the dedicated pins are used. The GPIO must use the extra high drive E0E1 configuration in the DRIVE field of the PIN_CNF GPIO register."

    I tried setting the MCUSEL to peripheral as follows.

    	#define SPIM4_SCK  NRF_GPIO_PIN_MAP(0,8)
    	#define SPIM4_MOSI NRF_GPIO_PIN_MAP(0,9)
    	#define SPIM4_MISO NRF_GPIO_PIN_MAP(0,10)
    
    	nrf_gpio_cfg(SPIM4_SCK, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
    	nrf_gpio_cfg(SPIM4_MOSI, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
    	nrf_gpio_cfg(SPIM4_MISO, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
    
    	nrf_gpio_pin_control_select(SPIM4_SCK, NRF_GPIO_PIN_SEL_PERIPHERAL);
    	nrf_gpio_pin_control_select(SPIM4_MOSI, NRF_GPIO_PIN_SEL_PERIPHERAL);
    	nrf_gpio_pin_control_select(SPIM4_MISO, NRF_GPIO_PIN_SEL_PERIPHERAL);

    But when I debug and check register at GPIO0-Pin 8, I see it is still set as APPMCU.

    So I have following questions.

    1. Can P0.8, P0.9 and P0.10 only be used as SPI4 in master mode, not as a slave?

    2. If SPI4 on the above pins can be used as a slave, how to do it?

    Cheers,

    Kaushalya

  • Hi,

    It's a bit hard to decode the files, but looks like uart1 might be using port1 pin1. I would start looking there. Does the pin work as a normal gpio (if you don't use it for spis)?

    Kenneth

  • Hi Kenneth, 

    Yes uart1 was using it, but I had disabled uart1 in my overlay file. However I tried to reassign different pins to uart1 as in this overlay file.

    8306.zmhostradio.overlay

    Also I assigned gpio1, 1 as led3 under leds node and tried to drive it.

    I tried like 

    	ret = dk_leds_init();
    	if (ret) {
    		LOG_ERR("Could not initialize leds, err code: %d", ret);
    		goto end;
    	}
    	dk_set_led_on(DK_LED4);
    	dk_set_led_off(DK_LED4);

    and also

    #define LED3_NODE DT_ALIAS(led3)
    	int ret;
    	
    	static const struct gpio_dt_spec gpio11 = GPIO_DT_SPEC_GET(LED3_NODE, gpios);
    
    	if (!gpio_is_ready_dt(&gpio11)) {
    		return 0;
    	}
    
    	ret = gpio_pin_configure_dt(&gpio11, GPIO_OUTPUT_ACTIVE);
    	if (ret < 0) {
    		return 0;
    	}
    
    	ret = gpio_pin_toggle_dt(&gpio11);

    No matter what, gpio1, 1 doesn't seem like its configured as an output. 

    I then tried debugging into it (both nrf connect debugger and ozone debugger) and check DIR register of P1_NS peripheral, and it shoes pin 1 as an input!!

    Can this pin be assigned to something in network processor? How to verify it?

    I checked the zephyr.dts and it seems my led3 mapping is correct. 

    I am totally puzzled. What is going on here??

    Thanks,

    Kaushalya

  • Hello,

    I notice you are mentioning P1_NS, does this mean you are working with non-secure and have TF-M? If yes, try to set CONFIG_TFM_LOG_LEVEL_SILENCE=y, ref:
    https://docs.nordicsemi.com/bundle/ncs-2.9.0/page/nrf/security/tfm.html#building 

    Kenneth

  • Hi Kenneth,

    Yes we use NS+TF-M. When I add ' CONFIG_TFM_LOG_LEVEL_SILENCE=y' to my prj.conf, I get 

    d:/Projects/nrf/zm2hostradiofw/prj.conf:89: warning: ignoring malformed line ' CONFIG_TFM_LOG_LEVEL_SILENCE=y'

    It seems I have not built TF-M with my application. So I added CONFIG_BUILD_WITH_TFM=y and then the project got built, but then the app doesnt seem to run. (I have disabled UART1 from my overlay as explained in https://docs.nordicsemi.com/bundle/ncs-2.9.0/page/nrf/security/tfm.html#building

    Apparently TF-M uses UART1. I have tried assigning different pins to the UART1 in my overlay as follows.

        uart1_default: uart1_default {
            group1 {
                psels = <NRF_PSEL(UART_TX, 1, 5)>,
                    <NRF_PSEL(UART_RTS, 0, 11)>;
            };
            group2 {
                psels = <NRF_PSEL(UART_RX, 1, 0)>,
                    <NRF_PSEL(UART_CTS, 0, 10)>;
                bias-pull-up;
            };
        };

        uart1_sleep: uart1_sleep {
            group1 {
                psels = <NRF_PSEL(UART_TX, 1, 5)>,
                    <NRF_PSEL(UART_RX, 1, 0)>,
                    <NRF_PSEL(UART_RTS, 0, 11)>,
                    <NRF_PSEL(UART_CTS, 0, 10)>;
                low-power-enable;
            };
        };
    But still P0.01 doesnt seem to work for SPI slave.
    My time limit for this project has almost finished. So any help is much appreciated.

    Cheers,

    Kaushalya

  • Can you at least make sure it works without TF-M?

    The overlay you refer to , what is the name of that file?

    Kenneth

Reply Children
No Data
Related