Hello,
i'm writing a code for NRF9160DK where i plan to send a HTTP POST request to a test server when i push BUTTON1 on DK. To achieve this result i studied separately how to use GPIO interrupt and HTTP Post basing my work on examples i found on nrf repositories (and not only). By now, the GPIO interrupt code works fine and the HTTP POST code, even if really slow, works too.
NOTE: I read many posts about Zephyr slow boot when using net due to band scan so for now i didn't worry about HTTP POST code being slow.
This is the merged code:
#include <zephyr.h> #include <sys/printk.h> #include <drivers/gpio.h> #include <device.h> //NEW LIBRARIES FROM HTTP POST CODE #include <net/socket.h> //#include <stdio.h> //#include <stdlib.h> //#include <drivers/uart.h> //#include <string.h> //DEFINES FOR HTTP POST REQUEST #define HTTP_HOST "ptsv2.com" #define HTTP_PATH "/t/snag8-1583942838/post" #define HTTP_PORT 80 #define MAX_MTU_SIZE 1000 #define RECV_BUF_SIZE 2048 #define SEND_BUF_SIZE MAX_MTU_SIZE #define TEST_STRING "Hello from Frax" #define POST_TEMPLATE "POST %s? HTTP/1.1\r\n"\ "Host: %s\r\n"\ "Connection: keep-alive\r\n"\ "Content-Type: text/plain\r\n"\ "Content-length: %d\r\n\r\n"\ "%s" //PIN ASSOCIATION IN NRF9160DK #define GPIO_BUTTON1 6 #define GPIO_BUTTON2 7 //STRUCT OF THE GPIO INTERRUPT DEVICE struct device *gpio_btn1_int_dev; struct device *gpio_btn2_int_dev; //STRUCTS NEEDED TO CREATE INTERRUPT CALLBACK struct gpio_callback gpio_btn1_cb; struct gpio_callback gpio_btn2_cb; bool isBtn1Pressed= false; bool isBtn2Pressed= false; 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_http_start(void) { struct sockaddr_in local_addr; struct addrinfo *res; int send_data_len; int num_bytes; int mtu_size = MAX_MTU_SIZE; char send_buf[SEND_BUF_SIZE]; local_addr.sin_family = AF_INET; local_addr.sin_port = htons(0); local_addr.sin_addr.s_addr = 0; printk("HTTP routine started\n\r"); int err = getaddrinfo(HTTP_HOST, NULL, NULL, &res); printk("getaddrinfo err: %d\n\r", err); ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(HTTP_PORT); int client_fd = socket(AF_INET, SOCK_STREAM, 0); printk("client_fd: %d\n\r", client_fd); err = bind(client_fd, (struct sockaddr *)&local_addr, sizeof(local_addr)); printk("bind err: %d\n\r", err); err = blocking_connect(client_fd, (struct sockaddr *)res->ai_addr, sizeof(struct sockaddr_in)); printk("connect err: %d\n\r", err); printk("\n\rPrepare send buffer:\n\r"); send_data_len = snprintf(send_buf, mtu_size, POST_TEMPLATE, HTTP_PATH, HTTP_HOST, strlen(TEST_STRING), TEST_STRING); printk("\n\rSend HTTP post request.\n\r"); do { num_bytes = blocking_send(client_fd, send_buf, send_data_len, 0); if (num_bytes < 0) { printk("ret: %d, errno: %s\n", num_bytes, strerror(errno)); }; } while (num_bytes < 0); printk("\n\rFinished. Closing socket\n"); err = close(client_fd); } //INTERRUPT SERVICE ROUTINE void button1_interrupt(struct device *gpio, struct gpio_callback *cb, u32_t pins) { isBtn1Pressed = true; } void button2_interrupt(struct device *gpio, struct gpio_callback *cb, u32_t pins) { isBtn2Pressed = true; } //INTERRUPT INIT ROUTINE int8_t init_button1_interrupt_gpio() { int8_t ret; //GET GPIO DEVICE - Name can't be anything //It needs to be DT_GPIO_P0_DEV_NAME or "GPIO_0" gpio_btn1_int_dev = device_get_binding(DT_GPIO_P0_DEV_NAME); if (!gpio_btn1_int_dev) { printk("gpio_dev init error\r\n"); return -1; } //CONFIGURE PIN TO INTERRUPT ON RISING EDGE ret = gpio_pin_configure(gpio_btn1_int_dev, GPIO_BUTTON1, (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_PUD_PULL_UP|GPIO_INT_ACTIVE_LOW|GPIO_INT_DEBOUNCE)); if (ret) { printk("Error configuring GPIO interrupt pin: %d!\n", GPIO_BUTTON1); return -1; } //INIT INTERRUPT CALLBACK gpio_init_callback(&gpio_btn1_cb, button1_interrupt, BIT(GPIO_BUTTON1)); //REGISTER INTERRUPT CALLBACK ret = gpio_add_callback(gpio_btn1_int_dev, &gpio_btn1_cb); if (ret){ printk("Cannot setup callback!\n"); return -1; } ret = gpio_pin_enable_callback(gpio_btn1_int_dev, GPIO_BUTTON1); if (ret){ printk("Error enabling callback!\n"); return -1; } return 0; } int8_t init_button2_interrupt_gpio() { int8_t ret; //GET GPIO DEVICE - Name can't be anything //It needs to be DT_GPIO_P0_DEV_NAME or "GPIO_0" gpio_btn2_int_dev = device_get_binding(DT_GPIO_P0_DEV_NAME); if (!gpio_btn2_int_dev) { printk("gpio_dev init error\r\n"); return -1; } //CONFIGURE PIN TO INTERRUPT ON RISING EDGE ret = gpio_pin_configure(gpio_btn2_int_dev, GPIO_BUTTON2, (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_PUD_PULL_UP|GPIO_INT_ACTIVE_LOW|GPIO_INT_DEBOUNCE)); if (ret) { printk("Error configuring GPIO interrupt pin: %d!\n", GPIO_BUTTON1); return -1; } //INIT INTERRUPT CALLBACK gpio_init_callback(&gpio_btn2_cb, button2_interrupt, BIT(GPIO_BUTTON2)); //REGISTER INTERRUPT CALLBACK ret = gpio_add_callback(gpio_btn2_int_dev, &gpio_btn2_cb); if (ret){ printk("Cannot setup callback!\n"); return -1; } ret = gpio_pin_enable_callback(gpio_btn2_int_dev, GPIO_BUTTON2); if (ret){ printk("Error enabling callback!\n"); return -1; } return 0; } void main(void) { printk("Interrupt test application started!\n"); k_sleep(200); int err=init_button1_interrupt_gpio(); if (err){ printk("Error on button 1 interrupt init: %d\n",err); } err=init_button2_interrupt_gpio(); if (err){ printk("Error on button 2 interrupt init: %d\n",err); } /*while (1) { //k_cpu_idle(); //can use this line or the bottom one indifferently k_sleep(200); if(isBtn1Pressed) { printk("Button 1 pressed\n"); gpio_pin_write(gpio_led_dev, GPIO_LED1, true); k_sleep(200); gpio_pin_write(gpio_led_dev, GPIO_LED1, false); isBtn1Pressed=false; } if(isBtn2Pressed) { printk("Button 2 pressed\n"); gpio_pin_write(gpio_led_dev, GPIO_LED1, true); k_sleep(200); gpio_pin_write(gpio_led_dev, GPIO_LED1, false); isBtn2Pressed=false; } }*/ }
This is the prj.conf content:
CONFIG_SERIAL=y CONFIG_UART_0_NRF_UARTE=y CONFIG_BSD_LIBRARY=y CONFIG_GPIO=n CONFIG_STDOUT_CONSOLE=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NETWORKING=y CONFIG_NET_BUF_USER_DATA_SIZE=1 CONFIG_NET_SOCKETS_OFFLOAD=y CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_POSIX_NAMES=y CONFIG_TRUSTED_EXECUTION_NONSECURE=y CONFIG_LOG=n CONFIG_LOG_DEFAULT_LEVEL=4 CONFIG_HEAP_MEM_POOL_SIZE=8192 CONFIG_MAIN_STACK_SIZE=8192 CONFIG_ISR_STACK_SIZE=4096 CONFIG_PRIVILEGED_STACK_SIZE=4096 CONFIG_IDLE_STACK_SIZE=4096 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 CONFIG_OFFLOAD_WORKQUEUE_STACK_SIZE=4096 CONFIG_NEWLIB_LIBC=y # LTE link control CONFIG_LTE_LINK_CONTROL=y CONFIG_BSD_LIBRARY_TRACE_ENABLED=y
When i try to run this code i am not able to make anything works. Boot becomes incredibly slow (up to 15min to see the first serial print "Interrupt test application started!) and nothing works.
Any idea?
Please consider i'm pretty new to this SiP.
Thx,
Frax