Checking nrf21540-DK registers using SPI3

I am attempting to do a simple read from the FEM on the nrf21540-DK board. I should be able to use the zephyr driver with spi3 (or fem_spi) to do a simple read/write from the fem chip correct?

I seem to be able to get the device - 

const struct device *spi_dev = DEVICE_DT_GET(DT_NODELABEL(spi3))

but the gpio don't seem to show up (the following is just done for validation):

struct gpio_dt_spec spim_cs_gpio =SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(spi3))
    if(!device_is_ready(spim_cs_gpio.port)){
        printk("SPI master chip select device not ready!\n");
    }


The above will always report the cs_gpio is not ready.


There is no other FEM libraries used at this point (that I am aware of )
The project file is essentially
CONFIG_GPIO=y

CONFIG_SPI=y
CONFIG_SPI_ASYNC=y

Any quick ideas what I am doing wrong ?

This code in its sort of simplest form is the following.

	static uint8_t tx_buffer[2];
	static uint8_t rx_buffer[2];

static struct spi_config spi_cfg = {
	.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB ,
	.frequency = 4000000,
	.slave = 0,
	.cs = {.gpio = MY_SPI_MASTER_CS_DT_SPEC, .delay = 0},
};

	const struct spi_buf tx_buf = {
		.buf = tx_buffer,
		.len = sizeof(tx_buffer)
	};
	const struct spi_buf_set tx = {
		.buffers = &tx_buf,
		.count = 1
	};

	struct spi_buf rx_buf = {
		.buf = rx_buffer,
		.len = sizeof(rx_buffer),
	};
	const struct spi_buf_set rx = {
		.buffers = &rx_buf,
		.count = 1
	};

	// Reset signal
	k_poll_signal_reset(&spi_done_sig);
	
	// Start transaction
	int error = spi_transceive_signal(spi_dev, &spi_cfg, &tx, &rx, &spi_done_sig);
	if(error != 0){
		printk("SPI transceive error: %i\n", error);
		return error;
	}

	// Wait for the done signal to be raised and log the rx buffer
	int spi_signaled, spi_result;
	do{
		k_poll_signal_check(&spi_done_sig, &spi_signaled, &spi_result);
	} while(spi_signaled == 0);

Parents Reply Children
  • Great, thanks. I will look into this and report back to you ... asap.

  • Yup, added in a few items to point to the FEM on the nrf21540dk/nrf52840 target, enabled the power pin and it appears to work. The HW_REVISION doesn't match the pdf I have. I received 0x30 and expected a 0x03.

    *** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***
    *** Using Zephyr OS v3.6.99-100befc70c74 ***
    [00:00:00.365,356] <inf> app: Hello World! nrf21540dk/nrf52840
    [00:00:00.365,356] <inf> app: spi_is_ready_dt() returned 0x1
    [00:00:01.365,661] <inf> app: spi_tranceive_dt() returned 0
    [00:00:01.365,692] <inf> app: data returned 80 0c
    [00:00:02.365,905] <inf> app: spi_tranceive_dt() returned 0
    [00:00:02.365,936] <inf> app: data returned 80 30
    [00:00:03.366,180] <inf> app: spi_tranceive_dt() returned 0
    [00:00:03.366,210] <inf> app: data returned 80 02
    [00:00:04.366,455] <inf> app: spi_tranceive_dt() returned 0
    [00:00:04.366,485] <inf> app: data returned 80 1c


    Just for clarity the code (enclosed) is reading registers 0x14,0x15,0x16, and 0x17 from the FEM.

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <stdio.h>
    #include <errno.h>
    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/sys/byteorder.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/drivers/spi.h>
    #include <nrfx_gpiote.h>
    
    
    #include <zephyr/irq.h>
    
    #define LOG_MODULE_NAME app
    LOG_MODULE_REGISTER(LOG_MODULE_NAME);
    
    #define SPIOP       SPI_WORD_SET(8) | SPI_TRANSFER_MSB
    
    struct spi_dt_spec spispec = SPI_DT_SPEC_GET(DT_NODELABEL(nrf_radio_fem_spi), SPIOP, 0);
    
    #define NRF_FEM_GPIO ((NRF_GPIO_Type *)DT_REG_ADDR(DT_GPIO_CTLR(DT_PHANDLE(DT_NODELABEL(radio), fem), pdn_gpios)))
    #define NRF_GPIO_PDN_PIN    DT_GPIO_PIN(DT_PHANDLE(DT_NODELABEL(radio), fem), pdn_gpios)
    
    
    void test_spi(void)
    {
        int err;
    
        err = spi_is_ready_dt(&spispec);
        LOG_INF("spi_is_ready_dt() returned 0x%0x", err);
    
        NRF_FEM_GPIO->DIRSET = BIT(NRF_GPIO_PDN_PIN);
        NRF_FEM_GPIO->OUTSET = BIT(NRF_GPIO_PDN_PIN); // power on the nrf21540
    
        uint8_t tx_buffer[2] = {0xff, 0xff};
        tx_buffer[0] = 0x80 | 0x14; // read = register 14
    
        uint8_t data[100];
        uint16_t size = sizeof(data);
        struct spi_buf tx_spi_buf		= {.buf = (void *)&tx_buffer, .len = sizeof(tx_buffer)};
        struct spi_buf_set tx_spi_buf_set 	= {.buffers = &tx_spi_buf, .count = 1};
        struct spi_buf rx_spi_bufs 		= {.buf = data, .len = size};
        struct spi_buf_set rx_spi_buf_set	= {.buffers = &rx_spi_bufs, .count = 1};
    
        k_sleep(K_MSEC(1000));
    
        tx_buffer[0] = 0x80 | 0x14; // read = register 14
        err = spi_transceive_dt(&spispec, &tx_spi_buf_set, &rx_spi_buf_set);
        LOG_INF("spi_tranceive_dt() returned %d", err);
        LOG_INF("data returned %02x %02x", data[0],data[1] );
    
        k_sleep(K_MSEC(1000));
    
        tx_buffer[0] = 0x80 | 0x15; 
        err = spi_transceive_dt(&spispec, &tx_spi_buf_set, &rx_spi_buf_set);
        LOG_INF("spi_tranceive_dt() returned %d", err);
        LOG_INF("data returned %02x %02x", data[0],data[1] );
    
        k_sleep(K_MSEC(1000));
    
        tx_buffer[0] = 0x80 | 0x16; 
        err = spi_transceive_dt(&spispec, &tx_spi_buf_set, &rx_spi_buf_set);
        LOG_INF("spi_tranceive_dt() returned %d", err);
        LOG_INF("data returned %02x %02x", data[0],data[1] );
    
        k_sleep(K_MSEC(1000));
    
        tx_buffer[0] = 0x80 | 0x17; 
        err = spi_transceive_dt(&spispec, &tx_spi_buf_set, &rx_spi_buf_set);
        LOG_INF("spi_tranceive_dt() returned %d", err);
        LOG_INF("data returned %02x %02x", data[0],data[1] );
    
        while (true) {
            err = spi_transceive_dt(&spispec, &tx_spi_buf_set, &rx_spi_buf_set);
            if (err) {
                LOG_ERR("Transceive failed %d", err);
            }
            k_sleep(K_MSEC(1000));
        }
    }
    
    int main(void)
    {
    	LOG_INF("Hello World! %s", CONFIG_BOARD_TARGET);
        
        test_spi();
    	return 0;
    }
    

Related