Devicetree SPI node interrupt asserts

Hi,

I want to connect X-NUCLEO-NFC08A1 with ST25R3916B to nRF5340 board by adding a SPI node to device-tree source. After compiling and flashing the board, triggering interrupt causes an assertion.

For tests, I trigger interrupt manually with a wire. I couldn't find the root cause.

Device-tree file nrf5340dk_nrf5340_cpuapp.overlay:

&spi1 {
	compatible = "nordic,nrf-spim";
	status = "okay";
	cs-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;

	pinctrl-0 = <&spi0_default_alt>;
	pinctrl-1 = <&spi0_sleep_alt>;
	pinctrl-names = "default", "sleep";
	st25r3916b@0 {
		compatible = "st,st25r3916b";
		reg = <0>;
		spi-max-frequency = <4000000>;
		irq-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
		//led-nfca-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
	};
};

&arduino_spi {
	status = "disabled";
};

&arduino_i2c {
	status = "disabled";
};

&arduino_serial {
	status = "disabled";
};

&arduino_header{
	status = "disabled";	
};

&arduino_adc{
	status = "disabled";	
};

&pinctrl {
	spi0_default_alt: spi0_default_alt {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
				<NRF_PSEL(SPIM_MOSI, 1, 13)>,
				<NRF_PSEL(SPIM_MISO, 1, 14)>;
		};
	};

	spi0_sleep_alt: spi0_sleep_alt {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
				<NRF_PSEL(SPIM_MOSI, 1, 13)>,
				<NRF_PSEL(SPIM_MISO, 1, 14)>;
			low-power-enable;
		};
	};
};
 

Logs:

ASSERTION FAIL @ WEST_TOPDIR/zephyr/kernel/sem.c:136
E: r0/a1:  0x00000004  r1/a2:  0x00000088  r2/a3:  0x00000000
E: r3/a4:  0x00010ed1 r12/ip:  0x80000000 r14/lr:  0x000168ef
E:  xpsr:  0x6100003f
E: Faulting instruction address (r15/pc): 0x00018f5c
E: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
E: Fault during interrupt handling

Converting address to source code line number...

C:\arm-none-eabi-addr2line.exe build\zephyr\zephyr.elf 0x00018f5c

..gives C:/ncs/v2.6.0/zephyr/lib/os/assert.c:44

And the r14/lr:  0x000168ef gives:

C:\arm-none-eabi-addr2line.exe build\zephyr\zephyr.elf 0x000168ef

C:/ncs/v2.6.0/zephyr/include/zephyr/spinlock.h:136

Parents
  • Actually, the problem exists still. Compiling device-tree and flashing work, but as you can see in the logs, I am still getting spinlock error " during interrupt handling".
    What can the problem be? I don't use any spinlock or mutex for interrupt service routine? Should I use a spinlock or mutex for interrupt? If yes, how?

  • You need to debug where the error is coming from.

    Looks like you have changed the overlay, and the error might be actually coming from the sensor (driver).

  • Error is coming from kernel. I am posting the code.

    Device-Tree overlay:

    &pinctrl {
    	spi1_default_alt: spi1_default_alt {
    		group1 {
    			psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
    					<NRF_PSEL(SPIM_MOSI, 1, 13)>,
    					<NRF_PSEL(SPIM_MISO, 1, 14)>;
    		};
    	};
    
    	spi1_sleep_alt: spi1_sleep_alt {
    		group1 {
    			psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
    					<NRF_PSEL(SPIM_MOSI, 1, 13)>,
    					<NRF_PSEL(SPIM_MISO, 1, 14)>;
    			low-power-enable;
    		};
    	};
    };
    
    spi_master: &spi1 {
    	compatible = "nordic,nrf-spim";
    	status = "okay";
    	cs-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
    	pinctrl-0 = <&spi1_default_alt>;
    	pinctrl-1 = <&spi1_sleep_alt>;
    	pinctrl-names = "default", "sleep";
    	st25r3916b:st25r3916b@0 {
    		reg = <0>;
    	};
    };
    
    /{
    	leds {
    		led_tv: led_tv {
    			gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
    			label = "Green LED TV";
    		};
    		
    		led_ap2p: led_ap2p {
    			gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
    			label = "Green LED AP2P";
    		};
    			irq_gpio: irq_gpio {
    			gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
    			label = "Interrupt line";
    		}; 
    	};
    		
    	aliases {
    		led-tv = &led_tv;
    		led-ap2p = &led_ap2p;
    		irq-gpio = &irq_gpio;
    	};
    };
    

    prj.conf:

    CONFIG_LOG=y
    CONFIG_DEBUG_OPTIMIZATIONS=y
    CONFIG_DEBUG_THREAD_INFO=y
    CONFIG_HEAP_MEM_POOL_SIZE=16384
    CONFIG_MAIN_STACK_SIZE=8192

    main.c:

    #define SPI_MASTER_NODE DT_NODELABEL(spi_master)
    
    const struct device *spi_dev = DEVICE_DT_GET(SPI_MASTER_NODE);
    
    #define INT_NODE DT_ALIAS(irq_gpio)
    static const struct gpio_dt_spec irq_gpio = GPIO_DT_SPEC_GET_OR(INT_NODE, gpios, {0});
    
    struct spi_config spi_cfg = {
        .operation = (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) |
                      SPI_TRANSFER_MSB | SPI_LINES_SINGLE |
                      SPI_MODE_CPHA),
         .frequency = 400000,
        .slave = DT_REG_ADDR(DT_NODELABEL(st25r3916b)),
        .cs = {
            .gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(st25r3916b)),
            .delay = T_NCS_SCLK
        }
    };
    static struct gpio_callback gpio_cb;
    
    st25r3916Isr() {
     /* SPI communication for reading INT registers*/    
    }
    
    
    static void irq_pin_cb(const struct device *gpiob, struct gpio_callback *cb, uint32_t pins) {
        //LOG_DBG("Received interrupt %s pin %d\n", gpiob->name, pins);
        st25r3916Isr();
    }
    
    int main() {
    
    if(!device_is_ready(irq_gpio.port) || !device_is_ready(spi_dev) || !device_is_ready(spi_cfg.cs.gpio.port)) {
        //error log
    }
    int err = gpio_pin_configure_dt(&irq_gpio, GPIO_INPUT);
    if (err) { /*error log */}
    gpio_init_callback(&gpio_cb, irq_pin_cb, BIT(irq_gpio.pin));
    err = gpio_add_callback(irq_gpio.port, &gpio_cb);
    if (err) { /*error log */}
    gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
    while(true) {}
    return 0;
    }

Reply
  • Error is coming from kernel. I am posting the code.

    Device-Tree overlay:

    &pinctrl {
    	spi1_default_alt: spi1_default_alt {
    		group1 {
    			psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
    					<NRF_PSEL(SPIM_MOSI, 1, 13)>,
    					<NRF_PSEL(SPIM_MISO, 1, 14)>;
    		};
    	};
    
    	spi1_sleep_alt: spi1_sleep_alt {
    		group1 {
    			psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
    					<NRF_PSEL(SPIM_MOSI, 1, 13)>,
    					<NRF_PSEL(SPIM_MISO, 1, 14)>;
    			low-power-enable;
    		};
    	};
    };
    
    spi_master: &spi1 {
    	compatible = "nordic,nrf-spim";
    	status = "okay";
    	cs-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
    	pinctrl-0 = <&spi1_default_alt>;
    	pinctrl-1 = <&spi1_sleep_alt>;
    	pinctrl-names = "default", "sleep";
    	st25r3916b:st25r3916b@0 {
    		reg = <0>;
    	};
    };
    
    /{
    	leds {
    		led_tv: led_tv {
    			gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
    			label = "Green LED TV";
    		};
    		
    		led_ap2p: led_ap2p {
    			gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
    			label = "Green LED AP2P";
    		};
    			irq_gpio: irq_gpio {
    			gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
    			label = "Interrupt line";
    		}; 
    	};
    		
    	aliases {
    		led-tv = &led_tv;
    		led-ap2p = &led_ap2p;
    		irq-gpio = &irq_gpio;
    	};
    };
    

    prj.conf:

    CONFIG_LOG=y
    CONFIG_DEBUG_OPTIMIZATIONS=y
    CONFIG_DEBUG_THREAD_INFO=y
    CONFIG_HEAP_MEM_POOL_SIZE=16384
    CONFIG_MAIN_STACK_SIZE=8192

    main.c:

    #define SPI_MASTER_NODE DT_NODELABEL(spi_master)
    
    const struct device *spi_dev = DEVICE_DT_GET(SPI_MASTER_NODE);
    
    #define INT_NODE DT_ALIAS(irq_gpio)
    static const struct gpio_dt_spec irq_gpio = GPIO_DT_SPEC_GET_OR(INT_NODE, gpios, {0});
    
    struct spi_config spi_cfg = {
        .operation = (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) |
                      SPI_TRANSFER_MSB | SPI_LINES_SINGLE |
                      SPI_MODE_CPHA),
         .frequency = 400000,
        .slave = DT_REG_ADDR(DT_NODELABEL(st25r3916b)),
        .cs = {
            .gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(st25r3916b)),
            .delay = T_NCS_SCLK
        }
    };
    static struct gpio_callback gpio_cb;
    
    st25r3916Isr() {
     /* SPI communication for reading INT registers*/    
    }
    
    
    static void irq_pin_cb(const struct device *gpiob, struct gpio_callback *cb, uint32_t pins) {
        //LOG_DBG("Received interrupt %s pin %d\n", gpiob->name, pins);
        st25r3916Isr();
    }
    
    int main() {
    
    if(!device_is_ready(irq_gpio.port) || !device_is_ready(spi_dev) || !device_is_ready(spi_cfg.cs.gpio.port)) {
        //error log
    }
    int err = gpio_pin_configure_dt(&irq_gpio, GPIO_INPUT);
    if (err) { /*error log */}
    gpio_init_callback(&gpio_cb, irq_pin_cb, BIT(irq_gpio.pin));
    err = gpio_add_callback(irq_gpio.port, &gpio_cb);
    if (err) { /*error log */}
    gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
    while(true) {}
    return 0;
    }

Children
No Data
Related