SPIS with nRF54L15 with the current Development Kit

Hello ! 
I'm trying to adapt the code from the master-slave SPI example (https://github.com/too1/ncs-spi-master-slave-example) for my nRF54L15 development kit.

The master part runs smoothly, but when it comes to the slave, I get a linking error on build (undefined reference to `__device_dts_ord_72' ).

When I look in build/zephyr/include/generated.devicetree_generated.h, I have Node 72 =  /soc/peripheral@50000000/spi@c8000

When I look in build/zephyr/zephyr.dts, I have : 

			spi22: spi_slave: spi@c8000 {
				compatible = "nordic,nrf-spis";
				#address-cells = < 0x1 >;
				#size-cells = < 0x0 >;
				reg = < 0xc8000 0x1000 >;
				interrupts = < 0xc8 0x1 >;
				max-frequency = < 0x7a1200 >;
				easydma-maxcnt-bits = < 0x10 >;
				status = "okay";
				pinctrl-0 = < &spi_slave_default >;
				pinctrl-1 = < &spi_slave_sleep >;
				pinctrl-names = "default", "sleep";
				cs-gpios = < &gpio1 0x0 0x1 >;
				def-char = < 0x0 >;
			};

My .overlay file look like this : 

//Disable everything that could collide, test only
&spi20 {
    status = "disabled";
};

&spi21 {
    status = "disabled";
};

&spi30 {
    status = "disabled";
};

&i2c20 {
    status = "disabled";
};

&i2c21 {
    status = "disabled";
};

&i2c22 {
    status = "disabled";
};

&i2c30 {
    status = "disabled";
};

&uart30 {
    status = "disabled";
};

&uart22 {
    status = "disabled";
};

&spi22{
    status = "okay";
};


&pinctrl {
    spi_slave_default: spi_slave_default {
        group1 {
            psels = <NRF_PSEL(SPIS_MOSI, 1, 2)>,
                    <NRF_PSEL(SPIS_SCK, 1, 1)>,
                    <NRF_PSEL(SPIS_MISO, 1, 3)>;
        };
    };

    spi_slave_sleep: spi_slave_sleep {
        group1 {
            psels = <NRF_PSEL(SPIS_MOSI, 1, 2)>,
                    <NRF_PSEL(SPIS_SCK, 1, 1)>,
                    <NRF_PSEL(SPIS_MISO, 1, 3)>;
            low-power-enable;
        };
    };
};

spi_slave: &spi22 {
	compatible = "nordic,nrf-spis";
    status = "okay";
	max-frequency = <DT_FREQ_M(8)>;
    pinctrl-0 = <&spi_slave_default>;
    pinctrl-1 = <&spi_slave_sleep>;
    pinctrl-names = "default", "sleep";
	cs-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
	def-char = <0>;
};

In my .conf file, I have enabled CONFIG_SPI and CONFIG_SPI_SLAVE.

the simplified main.c looks like this : 

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/spi.h>

#include <zephyr/logging/log.h>

#define SPI_SLAVE DT_NODELABEL(spi_slave)
const struct device *my_spi_slave;

static void spi_slave_init(void)
{
	my_spi_slave = DEVICE_DT_GET(SPI_SLAVE);
	if(!device_is_ready(my_spi_slave)){
		LOG_ERR("SPI master device not ready!");
	}
}

...

int main(void){
spi_slave_init();
}

Whenever I call spi_slave_init(), I have the error on build.
I tried using :

#if !DT_NODE_EXISTS(DT_NODELABEL(spi_slave))
#error "Invalid Node Identifier !"
#endif

But it builds correctly (without the spi_slave_init() line).

I also tried to build the same main.c with a nRF52 config by adapting the .overlay file, and it runs smoothly.

If anyone has a clue, I would appreciate this !
Have a good day,
Hugo

Parents
  • Hi Hugo

    Do you have access to logic analyzer just to verify there is traffic on the pins?  I will try to replicate it on my side

    Regards

    Runar

  • I have plugged an oscilloscope and I can't see any traffic either. Still I know my logic is running because led1 blinks correctly.

  • At this point I didn't manage to see anything on my CLK or MOSI.
    I agree that it seems to be a CS problem. When I look in the register un DEBUG mode, it seems that it's inactive : 

    While the other pins are set correctly. But it seems really weird to me, because when I build for CS = gpio2 6, I can see it HIGH on the scope (whereas on gpio2 5, it's always LOW). The definition in my code is really basic, like the sample code provided

    #define SPI_MASTER DT_NODELABEL(spi_master)
    #define MY_SPI_MASTER_CS_DT_SPEC SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(reg_my_spi_master))
    const struct device *my_spi_master;
    //SPI configs
    static struct spi_config spi_master_cfg = {
    	.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_OP_MODE_MASTER,
    	.frequency = 4000000,
    	.slave = 0,
    	.cs = {.gpio = MY_SPI_MASTER_CS_DT_SPEC, .delay = 0},
    };
    And I didn't touch the overlay file.
    Is there maybe any issue i'm not aware off regarding GPIO2 pins ? Or the selection of the CS pin ? I'm kinda new to Zephyr & nRF SOC so it's a little bit blury on this side.
    Thanks,

    Hugo

  • I forgot to ask if you tested it on a nRF54 on your side. It would be helpful to know if it works on yours. Plus, if I don't manage to use Zephyr API, I can still use nrfx drivers defined in the nordic SDK right ?

  • Hi thank you for your patience 

    I'm testing right now, I wonder if maybe the different domains are causing us a bit of confusion. I don't see anything wrong 

    As long as mx25r64: mx25r6435f@0 is disabled there should not be anything on P2 from what I can see. 

    Edit: I think this might be the issue since we did not see anything on the clk pin. 

    P1.03, P1.04 and P1.08 can be used for SPICLK.

    I will do another test tomorrow morning

    Regards

    Runar

  • Thanks for you answer !  
    I already tried with explicitly mx25r64: mx25r6435f@0  disabled, it didn't change much for me. When I read the documentation, I don't see any pinout for my N54L15QFAAAB, but I assume it's the same as N54L15QFN48 pinout. On this pinout I read that both P2.01 and P2.06 could be used as SPICLK, that's why I chose P2.01 (to ensure that the data signals associated are close as recommended p.844). I just ran a test with P2.06 instead, not much change. When I run in debug mode, I still can see the PSEL CLK change (screen below), but nothing on my CS.

    I wonder if it's the good way to initialise it in my code ? It might be the issue but it's surprising because everything happens before the debugger breaks for the first time and I assume that the spi_config is only used when transceiving messages.

    #define SPI_MASTER DT_NODELABEL(spi_master)
    #define MY_SPI_MASTER_CS_DT_SPEC SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(reg_my_spi_master))
    
    const struct device *my_spi_master;
    
    static void spi_master_init(void)
    {
    	my_spi_master = DEVICE_DT_GET(SPI_MASTER);
    	if(!device_is_ready(my_spi_master)){
    		LOG_ERR("SPI master device not ready!");
    	}
    	struct gpio_dt_spec spim_cs_gpio = MY_SPI_MASTER_CS_DT_SPEC;
    	if(!device_is_ready(spim_cs_gpio.port)){
    		LOG_ERR("SPI master chip select device not ready!");
    	}
    }
    
    //SPI configs
    static struct spi_config spi_master_cfg = {
    	.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_OP_MODE_MASTER,
    	.frequency = 4000000,
    	.slave = 0,
    	.cs = {.gpio = MY_SPI_MASTER_CS_DT_SPEC, .delay = 0},
    };

  • Hi, 

    I spent more time to get this up and running then what I would expect. I did not pay attention to the small letters on the pdk where it states that the pin number with parentheses can not be used without modification to the pdk. Your setup looks fine to me. I was able to get it up and running with the following overlay

    // To get started, press Ctrl+Space to bring up the completion menu and view the available nodes.
    
    // You can also use the buttons in the sidebar to perform actions on nodes.
    // Actions currently available include:
    
    // * Enabling / disabling the node
    // * Adding the bus to a bus
    // * Removing the node
    // * Connecting ADC channels
    
    // For more help, browse the DeviceTree documentation at https://docs.zephyrproject.org/latest/guides/dts/index.html
    // You can also visit the nRF DeviceTree extension documentation at https://docs.nordicsemi.com/bundle/nrf-connect-vscode/page/guides/ncs_configure_app.html#devicetree-support-in-the-extension
    &pinctrl {
        spi_master_default: spi_master_default {
            
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 2, 6)>,
                        <NRF_PSEL(SPIM_MOSI, 2, 8)>,
                        <NRF_PSEL(SPIM_MISO, 2, 9)>;
            };
        };
    
        spi_master_sleep: spi_master_sleep {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 2, 6)>,
                        <NRF_PSEL(SPIM_MOSI, 2, 8)>,
                        <NRF_PSEL(SPIM_MISO, 2, 9)>;
                low-power-enable;
            };
        };
    
        spi_slave_default: spi_slave_default {
            group1 {
                psels = <NRF_PSEL(SPIS_CSN, 1, 13)>,
                        <NRF_PSEL(SPIS_MOSI, 1, 0)>,
                        <NRF_PSEL(SPIS_MISO, 1, 4)>,
                        <NRF_PSEL(SPIS_SCK, 1, 11)>;
            };
        };
    
        spi_slave_sleep: spi_slave_sleep {
            group1 {
                psels = <NRF_PSEL(SPIS_CSN, 1, 13)>,
                        <NRF_PSEL(SPIS_MOSI, 1, 0)>,
                        <NRF_PSEL(SPIS_MISO, 1, 4)>,
                        <NRF_PSEL(SPIS_SCK, 1, 11)>;
                low-power-enable;
            };
        };
    };
    
    my_spi_master: &spi00 {
        compatible = "nordic,nrf-spim";
        status = "okay";
        pinctrl-0 = <&spi_master_default>;
        pinctrl-1 = <&spi_master_sleep>;
        pinctrl-names = "default", "sleep";
        cs-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
        /delete-node/ mx25r64;
        reg_my_spi_master: spi-dev-a@0 {
            reg = <0>;
            
        };
    };
    
    my_spi_slave: &spi20 {
        compatible = "nordic,nrf-spis";
        status = "okay";
        pinctrl-0 = <&spi_slave_default>;
        pinctrl-1 = <&spi_slave_sleep>;
        pinctrl-names = "default", "sleep";
        def-char = <0x00>;
        /delete-property/ rx-delay;
        /delete-property/ rx-delay-supported;
    };
    
    &uart20 {
        status = "disabled";
    };
    
    
    

    Note I had to disable uart20 as it uses some of the same pins, so I printed out the data over RTT. To output the data over RTT add the following Kconfig. I selected nrf52840 as target for RTT to see any text

    CONFIG_USE_SEGGER_RTT=y
    CONFIG_LOG=y
    CONFIG_LOG_BACKEND_RTT=y
    
    CONFIG_RTT_CONSOLE=y
    CONFIG_UART_CONSOLE=n

    Regards

    Runar

Reply
  • Hi, 

    I spent more time to get this up and running then what I would expect. I did not pay attention to the small letters on the pdk where it states that the pin number with parentheses can not be used without modification to the pdk. Your setup looks fine to me. I was able to get it up and running with the following overlay

    // To get started, press Ctrl+Space to bring up the completion menu and view the available nodes.
    
    // You can also use the buttons in the sidebar to perform actions on nodes.
    // Actions currently available include:
    
    // * Enabling / disabling the node
    // * Adding the bus to a bus
    // * Removing the node
    // * Connecting ADC channels
    
    // For more help, browse the DeviceTree documentation at https://docs.zephyrproject.org/latest/guides/dts/index.html
    // You can also visit the nRF DeviceTree extension documentation at https://docs.nordicsemi.com/bundle/nrf-connect-vscode/page/guides/ncs_configure_app.html#devicetree-support-in-the-extension
    &pinctrl {
        spi_master_default: spi_master_default {
            
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 2, 6)>,
                        <NRF_PSEL(SPIM_MOSI, 2, 8)>,
                        <NRF_PSEL(SPIM_MISO, 2, 9)>;
            };
        };
    
        spi_master_sleep: spi_master_sleep {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 2, 6)>,
                        <NRF_PSEL(SPIM_MOSI, 2, 8)>,
                        <NRF_PSEL(SPIM_MISO, 2, 9)>;
                low-power-enable;
            };
        };
    
        spi_slave_default: spi_slave_default {
            group1 {
                psels = <NRF_PSEL(SPIS_CSN, 1, 13)>,
                        <NRF_PSEL(SPIS_MOSI, 1, 0)>,
                        <NRF_PSEL(SPIS_MISO, 1, 4)>,
                        <NRF_PSEL(SPIS_SCK, 1, 11)>;
            };
        };
    
        spi_slave_sleep: spi_slave_sleep {
            group1 {
                psels = <NRF_PSEL(SPIS_CSN, 1, 13)>,
                        <NRF_PSEL(SPIS_MOSI, 1, 0)>,
                        <NRF_PSEL(SPIS_MISO, 1, 4)>,
                        <NRF_PSEL(SPIS_SCK, 1, 11)>;
                low-power-enable;
            };
        };
    };
    
    my_spi_master: &spi00 {
        compatible = "nordic,nrf-spim";
        status = "okay";
        pinctrl-0 = <&spi_master_default>;
        pinctrl-1 = <&spi_master_sleep>;
        pinctrl-names = "default", "sleep";
        cs-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
        /delete-node/ mx25r64;
        reg_my_spi_master: spi-dev-a@0 {
            reg = <0>;
            
        };
    };
    
    my_spi_slave: &spi20 {
        compatible = "nordic,nrf-spis";
        status = "okay";
        pinctrl-0 = <&spi_slave_default>;
        pinctrl-1 = <&spi_slave_sleep>;
        pinctrl-names = "default", "sleep";
        def-char = <0x00>;
        /delete-property/ rx-delay;
        /delete-property/ rx-delay-supported;
    };
    
    &uart20 {
        status = "disabled";
    };
    
    
    

    Note I had to disable uart20 as it uses some of the same pins, so I printed out the data over RTT. To output the data over RTT add the following Kconfig. I selected nrf52840 as target for RTT to see any text

    CONFIG_USE_SEGGER_RTT=y
    CONFIG_LOG=y
    CONFIG_LOG_BACKEND_RTT=y
    
    CONFIG_RTT_CONSOLE=y
    CONFIG_UART_CONSOLE=n

    Regards

    Runar

Children
No Data
Related