Thingy91 How to manually configure SPI chip select pin as GPIO output pin

I am having some issues with the Thingy91 and SPI. I want to configure GPIO0 8 as GPIO_OUTPUT pin.

This is my source code:

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

#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(main);


// Define the CS pin
#define CS_PIN 8
const struct device *gpio_dev;

int main(void)
{
	int err;
	printk("Program started \n");
	gpio_pin_configure(gpio_dev, CS_PIN, GPIO_OUTPUT);

	if (err < 0)
	{
		printk("GPIO pin configure failed with error %d\n", err);
		return 0;
	}
	k_msleep(1000);
	printk("getting into while loop \n");
	return 0;
}

You can also access my code at github:

https://github.com/krupis/thingy91_spi_test

gpio_configure_bug branch.

It is also important to mention that on the Thing91 nRF52840, Connectivity Bridge application is running. I am only interested in programming nRF9160.

I have read about how to configure CS pin as GPIO from the following post:

 Is it possible to control SPI chip select pin with Zephyr GPIO API? 

and basically copy and pasted the code that has been suggested.

But for me it does not seem to work. The code just halts when gpio_pin_configure(gpio_dev, CS_PIN, GPIO_OUTPUT)is called. I have tried looking at the serial monitor but no logs are coming out even though I have added multiple printk statements.

After launching debugger, I have discovered that the Securefault_hanlder is triggered when the gpio_pin_configure is called:

I have 2 questions

  1. Am I configuring the GPIO correctly? (gpio0 8). If not, could you suggest an alternative way?
  2. Why am I not seeing a single printk statement being printed to the serial console? I have printk("Program started \n"); statement before the gpio_pin_configure call but that never gets printed.
Thanks in advance.
Parents
  • UPDATE

     

    I have tried different method of configuring GPIO pin. Check the code below:

    #include <stdio.h>
    #include <stdlib.h>
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/spi.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/gpio.h>
    
    #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(main);
    
    
    // Define the CS pin
    // #define CS_PIN 8
    // const struct device *gpio_dev;
    
    #define MY_GPIO0 DT_NODELABEL(gpio0)
    #define GPIO0_8_CS 8
    const struct device* gpio0_dev = DEVICE_DT_GET(MY_GPIO0);
    
    int main(void)
    {
    	int err;
    	printk("Program started \n");
    	gpio_pin_configure(gpio0_dev, GPIO0_8_CS, GPIO_OUTPUT);
    
    	if (err < 0)
    	{
    		printk("GPIO pin configure failed with error %d\n", err);
    		return 0;
    	}
    	k_msleep(1000);
    	printk("getting into while loop \n");
    	return 0;
    }
    
    

    The above code seem to work fine and no longer crashed at gpio_pin_conifigure call.

    I believe the method that has been suggested in the post below

     Is it possible to control SPI chip select pin with Zephyr GPIO API? 

    is not even a valid method and should not be used. In the above method, it is not even specified which gpio port to use (gpio0 or gpio1 or others)?

Reply
  • UPDATE

     

    I have tried different method of configuring GPIO pin. Check the code below:

    #include <stdio.h>
    #include <stdlib.h>
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/spi.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/gpio.h>
    
    #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(main);
    
    
    // Define the CS pin
    // #define CS_PIN 8
    // const struct device *gpio_dev;
    
    #define MY_GPIO0 DT_NODELABEL(gpio0)
    #define GPIO0_8_CS 8
    const struct device* gpio0_dev = DEVICE_DT_GET(MY_GPIO0);
    
    int main(void)
    {
    	int err;
    	printk("Program started \n");
    	gpio_pin_configure(gpio0_dev, GPIO0_8_CS, GPIO_OUTPUT);
    
    	if (err < 0)
    	{
    		printk("GPIO pin configure failed with error %d\n", err);
    		return 0;
    	}
    	k_msleep(1000);
    	printk("getting into while loop \n");
    	return 0;
    }
    
    

    The above code seem to work fine and no longer crashed at gpio_pin_conifigure call.

    I believe the method that has been suggested in the post below

     Is it possible to control SPI chip select pin with Zephyr GPIO API? 

    is not even a valid method and should not be used. In the above method, it is not even specified which gpio port to use (gpio0 or gpio1 or others)?

Children
  • Glad to hear it works now. 

    Regarding question two. Did you include the header file for printk? I could not see it when I looked over the code. 

    I will take a look at the case you linked. From a short glance the verified response was not from a Nordic employee and was verified by another user

    Regards

    Runar

  • Thanks for a quick response.

    I was not aware that printk statement requires any include.

    Could it be because I am using CONFIG_LOG_MODE_DEFERRED (i think its the default mode)

    and it simply does not have enough time to process the print statement and send it out to the console as the CPU crashes too fast?

  • It might be that there are some default include for printk in for board. I will have to check, but I know that in our devAcademy course we write that you need to include printk.h. 

    we also write the following "The output of the printk() is not deferred, meaning the output is sent immediately to the console without any mutual exclusion or buffering".  I have replicated the behavior on my end I will need to investigate as it does not make sense for me. I will update the case when I understand why. 

    In your case you are not using any logging, just printk which is a less powerful version of printf. I would recommend using "log_inf/log_err.." as I normally find it more powerful during debugging. I specifically really like the log_dbg do to this ""If you use LOG_DBG(), you can choose not to include that level of logging when you compile the production version of your code."

    Regards

    Runar

     

  • Update: 

    The reason "printk" works is that it is included as a part of zephyr/include/zephyr/kernel_includes.h 

    Regards

    Runar

  • Since you mentioned printf and log_dbg, I have tried something out. Please see the source code below:

    #include <stdio.h>
    #include <stdlib.h>
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/spi.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/gpio.h>
    
    #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(main);
    
    
    // Define the CS pin
    #define CS_PIN 8
    const struct device *gpio_dev;
    
    int main(void)
    {
    	int err;
    	printk("Program started printk\n");
    	printf("Program started pritnf \n");
    	LOG_DBG("Program started log_dbg\n");
    	gpio_pin_configure(gpio_dev, CS_PIN, GPIO_OUTPUT);
    
    	if (err < 0)
    	{
    		printk("GPIO pin configure failed with error %d\n", err);
    		return 0;
    	}
    	k_msleep(1000);
    	printk("getting into while loop \n");
    	return 0;
    }

    with the following prj.conf:

    CONFIG_LOG=y
    CONFIG_SPI=y
    CONFIG_GPIO=y
    
    

    As you can see from the code above, I am trying 3 different print methods (printf, printk, and log_dbg).

    From the serial terminal I see that only printf is being printed before the CPU crashed at the function gpio_pin_configure

    This tells me that printf prints to the console instantly whereas log_dbg and printk is not.

Related