This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Send AT commands on button press on nRF9160dk

Hello,

I have to send hardcoded AT commands on button press on nRF9160dk. So for that, first I did program for button press. It is working fine. Then I did simple_at program, which is also working fine. So now I have merged these 2 programs. But it is not working.

I have pasted the code. In the interrupt callback function button_pressed, all other functions are working, except app_socket_start. It stucks inside callback function. when I call app_socket_start function in main, it is working fine, but get stucked when I call inside the callbak function. What is the solution for this?

#include <net/socket.h>
#include <stdio.h>
#include <string.h>
#include <uart.h>
#include <gpio.h>
#include <device.h>
#include <zephyr.h>
#include <misc/util.h>
#include <misc/printk.h>

#define HTTP_HOST "google.com"
#define HTTP_PORT 80
#define RECV_BUF_SIZE 1024

char recv_buf[RECV_BUF_SIZE + 1];

#define LED_PORT LED1_GPIO_CONTROLLER
#define LED	LED1_GPIO_PIN

/* change this to use another GPIO port */
#ifndef SW1_GPIO_CONTROLLER
#ifdef SW1_GPIO_NAME
#define SW1_GPIO_CONTROLLER SW1_GPIO_NAME
#else
#error SW1_GPIO_NAME or SW1_GPIO_CONTROLLER needs to be set in board.h
#endif
#endif
#define PORT	SW1_GPIO_CONTROLLER

/* change this to use another GPIO pin */
#ifdef SW1_GPIO_PIN
#define PIN     SW1_GPIO_PIN
#else
#error SW1_GPIO_PIN needs to be set in board.h
#endif

/* change to use another GPIO pin interrupt config */
#ifdef SW1_GPIO_FLAGS
#define EDGE    (SW1_GPIO_FLAGS | GPIO_INT_EDGE)
#else
/*
 * If SW0_GPIO_FLAGS not defined used default EDGE value.
 * Change this to use a different interrupt trigger
 */
#define EDGE    (GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW)
#endif

/* change this to enable pull-up/pull-down */
#ifndef SW1_GPIO_FLAGS
#ifdef SW1_GPIO_PIN_PUD
#define SW1_GPIO_FLAGS SW1_GPIO_PIN_PUD
#else
#define SW1_GPIO_FLAGS 0
#endif
#endif
#define PULL_UP SW1_GPIO_FLAGS

/* Sleep time */
#define SLEEP_TIME	500

const char *at_commands[] = {
	"AT+CFUN?", "AT+CFUN=1", "AT+CFUN?", "AT+CEREG?",
	"AT+CNMI=3,2,0,1", 
        "AT+CMGS=19\r07913386094000F011000B913367390898F80000AA05C8329BFD06\x1A",
	/* Add more here if needed */
};

int blocking_recv(int fd, u8_t *buf, u32_t size, u32_t flags)
{
	int err;

	do {
		err = recv(fd, buf, size, flags);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_send(int fd, u8_t *buf, u32_t size, u32_t flags)
{
	int err;

	do {
		err = send(fd, buf, size, flags);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_connect(int fd, struct sockaddr *local_addr, socklen_t len)
{
	int err;

	do {
		err = connect(fd, local_addr, len);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

void app_socket_start(void)
{
	int at_socket_fd = socket(AF_LTE, 0, NPROTO_AT);

	printk("Starting simple AT socket application\n\r");

	if (at_socket_fd < 0) {
		printk("Socket err: %d, errno: %d\r\n", at_socket_fd, errno);
	}
	for (int i = 0; i < ARRAY_SIZE(at_commands); i++) {
		int bytes_written = send(at_socket_fd, at_commands[i],
					 strlen(at_commands[i]), 0);
		if (bytes_written > 0) {
			int r_bytes =
				blocking_recv(at_socket_fd, recv_buf,
					      sizeof(recv_buf), MSG_DONTWAIT);
			if (r_bytes > 0) {
				printk("%s", recv_buf);
			}
		}
	}
	printk("Closing socket\n\r");
	(void)close(at_socket_fd);
}


void button_pressed(struct device *gpiob, struct gpio_callback *cb,
		    u32_t pins)
{
        printk("Button pressed\n");
        app_socket_start();
        struct device *dev;

	dev = device_get_binding(LED_PORT);
        gpio_pin_configure(dev, LED, GPIO_DIR_OUT);

        u32_t val = 0U;
        gpio_pin_read(gpiob, PIN, &val);

        if(val == 0)
        {
            gpio_pin_write(dev, LED, 1);
        }
        else if(val == 1)
        {
            gpio_pin_write(dev, LED, 0);
        }
//        app_socket_start();
}


static struct gpio_callback gpio_cb;

void main(void)
{
      
	struct device *gpiob;
	printk("Press the user defined button on the board\n");
	gpiob = device_get_binding(PORT);
	if (!gpiob) {
		printk("error\n");
		return;
	}


	gpio_pin_configure(gpiob, PIN,
			   GPIO_DIR_IN | GPIO_INT |  PULL_UP | EDGE | GPIO_INT_DOUBLE_EDGE | GPIO_INT_DEBOUNCE);

	gpio_init_callback(&gpio_cb, button_pressed, BIT(PIN));

	gpio_add_callback(gpiob, &gpio_cb);
	gpio_pin_enable_callback(gpiob, PIN);
}

  • Try this instead, remove the app_socket_start() function from your callback. This shouldn't be here as an ISR should be returned from as quickly as possible. From my experience with ISRs in Zephyr, trying to run a function from the ISR will hang.

    Place a boolean flag in the ISR for button_pressed = true, place a while loop in your main function that can run a k_sleep() delay (reduce idle current by yielding main thread via sleep). In the while loop place a function that can react to the boolean button_pressed. Something like app_socket_start(button_pressed), where inside app_socket_start() is a boolean if-true check. Remember to clear the ISR flag when completing app_socket_start().

    Side note:

    You do realise you are calling app_socket_start() twice right? I helped you set up that ISR last week but you have continued to use it in rising and falling edge operation. That will call the ISR when you press and release the button, running the code for app_socket_start() and the LED with each press and de-press.

  • Hello,

    Thank you for the reply. I will try what you have suggested.

    Yes I realized that app_socket_start() is called twice as ISR is called on both press and release. I observed that.

Related