BUS FAULT in application code using k_poll

Hi,

I am using an nRF52833dk to run a simple async SPI transceive API using k_poll
My code is as below, for some reason it always returns BUS FAULT error

Code:

void main(void)
{
	struct k_poll_signal async_sig;
	uint8_t data = 40, val =0, sz = 9;
	    struct spi_buf bufs = {
            .buf = &data,
            .len = sizeof(data)
    };
    struct spi_buf_set tx = {
        .buffers = &bufs
    };

    tx.count = 1;

	struct spi_buf rbufs = {
            .buf = &val,
            .len = sizeof(val)
    };
    struct spi_buf_set rx = {
        .buffers = &rbufs
    };

 spi_config spi_cfg;
spi_cs_control cs_ctrl;
    cs_ctrl.gpio_dev = device_get_binding("GPIO_0");
    cs_ctrl.gpio_pin = 11;
    cs_ctrl.delay = 0;
    spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_MASTER 
    //                    | SPI_MODE_CPOL | SPI_MODE_CPHA 
                        | SPI_LINES_SINGLE; 
    spi_cfg.frequency = 1000000;
	spi_cfg.cs = &cs_ctrl;

	const device * sp;
	sp = device_get_binding("SPI_0");

		data++;
			struct k_poll_event  async_evt =
		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
					 K_POLL_MODE_NOTIFY_ONLY,
					 &async_sig);

			printk("transmitted data: %u \n", data);
			int error = spi_transceive_async(sp,&spi_cfg,&tx, &rx,&async_sig);
			int ret = k_poll(&async_evt, 1, K_MSEC(1000));
			printk("received data: %u \n", val);

}

Error:


Kindly help to solve this.

Thanks,

Ubaid

  • Could you upload the whole project (main.c, prj.conf, CMakeLists.txt, .overlay files and so on...) in zipped format.

    Best regards,

    Simon

  • Hello ,

    Could you upload the whole project (main.c, prj.conf, CMakeLists.txt, .overlay files and so on...) in zipped format.

    SPI_Sample.7z

    Please suggest 

    It seems even now the code is throwing faults:
    Please find the sequence of code execution leading to faults as in below:
  • I'm not too familiar with spi_transceive_async(), so I decided to run the sample zephyr\tests\drivers\spi\spi_loopback, which demonstrates how to properly use spi_transceive_async(). I don't have an nRF52833 DK at hand at the moment, but I built it for the nRF52840 DK. Then I connected P1.03 and P1.04 together and it worked fine. I also added a conf file for the nRF5232 and that also worked.

    Could you add a file nrf52833dk_nrf52833.conf to zephyr\tests\drivers\spi\spi_loopback\boards with the following content:

    CONFIG_SPI_3_NRF_ORC=0x00
    CONFIG_SPI_3_NRF_RX_DELAY=1
    
    CONFIG_SPI_LOOPBACK_DRV_NAME="SPI_1"
    CONFIG_SPI_LOOPBACK_CS_GPIO=y
    CONFIG_SPI_LOOPBACK_CS_CTRL_GPIO_DRV_NAME="GPIO_0"
    CONFIG_SPI_LOOPBACK_CS_CTRL_GPIO_PIN=28
    

    Then connect together P0.30 and P1.08 (doublecheck \zephyr\tests\drivers\spi\spi_loopback\build\zephyr\zephyr.dts to see that this is the pins "SPI_1" uses), build and flash zephyr\tests\drivers\spi\spi_loopback and see if you get the following output:

    *** Booting Zephyr OS build v2.7.0-ncs1  ***
    Running test suite test_spi
    ===================================================================
    START - test_spi_loopback
    I: SPI test on buffers TX/RX 0x200001ad/0x2000096a
    I: SPI test slow config
    I: Start complete multiple
    I: Passed
    I: Start complete loop
    I: Passed
    I: Start null tx
    I: Passed
    I: Start half start
    I: Passed
    I: Start half end
    I: Passed
    I: Start every 4
    I: Passed
    I: Start async call
    I: Passed
    I: SPI test fast config
    I: Start complete multiple
    I: Passed
    I: Start complete loop
    I: Passed
    I: Start null tx
    I: Passed
    I: Start half start
    I: Passed
    I: Start half end
    I: Passed
    I: Start every 4
    I: Passed
    I: Start async call
    I: Passed
    I: Start complete loop
    I: Passed
    I: Start complete loop
    I: Passed
    I: All tx/rx passed
     PASS - test_spi_loopback in 0.60 seconds
    ===================================================================
    Test suite test_spi succeeded
    ===================================================================
    PROJECT EXECUTION SUCCESSFUL
    

    If you see these lines printed, it means the spi_transceive_async() call worked:

    I: Start async call
    I: Passed

    If you get that to work, you can strip down the test sample and remove everything you don't need. If you don't get it to work, please tell me and I will get a hold of an nRF52833 and test it myself.

    Best regards,

    Simon

  • If you get that to work

    Many Thanks @ for helping me out, I was able to execute the spi_loopback with a few tweaks on nRF52833. As in the snap below:

    Actually, my understanding of:

    ret = k_poll(async_evt, 1, K_MSEC(200));

    Is that every 200ms it should poll the API "spi_transceive_async", 

    So kindly help me understand what is the implication of the 2 arguments 

    int num_events & k_timeout_t timeout in API k_poll..?

    And how can I test their variations for "spi_transceive_async"..?
    Thanking you in anticipation,
  • Hello ,


    you can strip down the test sample and remove everything you don't need

    I did just this in hopes to get the polling to work twice, as in below code:

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <sys/printk.h>
    #include <string.h>
    #include <stdio.h>
    #include <drivers/spi.h>
    #include <drivers/gpio.h>
    
    
    #define STACK_SIZE 512
    #define BUF_SIZE 17
    uint8_t buffer_tx[] = "0123456789abcdef\0";
    uint8_t buffer_rx[BUF_SIZE] = {};
    
    struct spi_cs_control spi_cs = {
    	.gpio_pin = 11,
    	.gpio_dt_flags = GPIO_ACTIVE_LOW,
    	.delay = 0,
    };
    
    /*
     * We need 5x(buffer size) + 1 to print a comma-separated list of each
     * byte in hex, plus a null.
     */
    uint8_t buffer_print_tx[BUF_SIZE * 5 + 1];
    uint8_t buffer_print_rx[BUF_SIZE * 5 + 1];
    
    #define SPI_CS (&spi_cs)
    
    struct spi_config spi_cfg_slow = {
    	.frequency = 250000,
    
    	.operation = SPI_OP_MODE_MASTER | SPI_MODE_CPOL |
    	SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE,
    	.slave = 1,
    	.cs = SPI_CS,
    };
    
    #if (CONFIG_SPI_ASYNC)
    static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig);
    static struct k_poll_event async_evt =
    	K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
    				 K_POLL_MODE_NOTIFY_ONLY,
    				 &async_sig);
    static K_SEM_DEFINE(caller, 0, 1);
    K_THREAD_STACK_DEFINE(spi_async_stack, STACK_SIZE);
    static int result = 1;
    
    static void spi_async_call_cb(struct k_poll_event *async_evt,
    			      struct k_sem *caller_sem,
    			      void *unused)
    {
    	int ret;
    
    	printk("Polling...");
    
    	while (1) {
    		ret = k_poll(async_evt, 2, K_MSEC(200));
    
    		result = async_evt->signal->result;
    		k_sem_give(caller_sem);
    
    		/* Reinitializing for next call */
    		async_evt->signal->signaled = 0U;
    		async_evt->state = K_POLL_STATE_NOT_READY;
    	}
    }
    
    static int spi_async_call(const struct device *dev,
    			  struct spi_config *spi_conf)
    {
    	const struct spi_buf tx_bufs[] = {
    		{
    			.buf = buffer_tx,
    			.len = BUF_SIZE,
    		},
    	};
    	const struct spi_buf rx_bufs[] = {
    		{
    			.buf = buffer_rx,
    			.len = BUF_SIZE,
    		},
    	};
    	const struct spi_buf_set tx = {
    		.buffers = tx_bufs,
    		.count = ARRAY_SIZE(tx_bufs)
    	};
    	const struct spi_buf_set rx = {
    		.buffers = rx_bufs,
    		.count = ARRAY_SIZE(rx_bufs)
    	};
    	int ret;
    
    	printk("Start async call");
    
    	ret = spi_transceive_async(dev, spi_conf, &tx, &rx, &async_sig);
    	if (ret == -ENOTSUP) {
    		printk("Not supported");
    		return 0;
    	}
    
    	if (ret) {
    		printk("Code %d", ret);
    		return -1;
    	}
    
    	k_sem_take(&caller, K_FOREVER);
    
    	if (result)  {
    		printk("Call code %d", ret);
    		return -1;
    	}
    
    	printk("Passed");
    
    	return 0;
    }
    #endif
    
    
    void test_spi_loopback(void)
    {
    #if (CONFIG_SPI_ASYNC)
    	struct k_thread async_thread;
    	k_tid_t async_thread_id;
    #endif
    	const struct device *spi_slow;
    	const struct device *spi_fast;
    
    	printk("SPI test on buffers TX/RX %p/%p", buffer_tx, buffer_rx);
    
    #if defined(CONFIG_SPI_LOOPBACK_CS_GPIO)
    	if (cs_ctrl_gpio_config()) {
    		return;
    	}
    #endif /* CONFIG_SPI_LOOPBACK_CS_GPIO */
    
    	spi_slow = device_get_binding("SPI_0");
    	if (!spi_slow) {
    		printk("Cannot find !\n");
    		return;
    	}
    
    	spi_fast = spi_slow;
    
    #if (CONFIG_SPI_ASYNC)
    	async_thread_id = k_thread_create(&async_thread,
    					  spi_async_stack, STACK_SIZE,
    					  (k_thread_entry_t)spi_async_call_cb,
    					  &async_evt, &caller, NULL,
    					  K_PRIO_COOP(7), 0, K_NO_WAIT);
    #endif
    
    	printk("SPI test slow config");
    
    	if (
    #if (CONFIG_SPI_ASYNC)
    	    spi_async_call(spi_slow, &spi_cfg_slow)
    #endif
    	    ) {
    		goto end;
    	}
    
    	printk("All tx/rx passed");
    end:
    #if (CONFIG_SPI_ASYNC)
    	k_thread_abort(async_thread_id);
    #else
    	;
    #endif
    }
    
    
    
    void main(void)
    {
    	printk("Hello World! %s\n", CONFIG_BOARD);
    	test_spi_loopback();
    }
    

    But still it polls only once, even after adding number of events to 2:

    ret = k_poll(async_evt, 2, K_MSEC(200));

    Kindly suggest how I can get above code to poll twice

    Thanks,

Related