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

Running Multiple Threads simultaneously

Hi everyone

        Program crashes after few minutes while trying to run two threads(GPS thread and a thread used for caculating the battery voltage) simultaneously. 

/*
 * Copyright (c) 2019 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
 */

#include <zephyr.h>
#include <nrf_socket.h>
#include <net/socket.h>
#include <stdio.h>
#include <device.h>
#include <sys/printk.h>
#include <at_cmd.h>
#include <sys/errno.h>
#include <sys/mutex.h>

//k_tid_t systemThread_id;   
#define AT_XSYSTEMMODE "AT\%XSYSTEMMODE=0,0,1,0"
#define AT_CFUN        "AT+CFUN=1"
#define battery_voltage "AT%XVBAT"


#define PRIORITY 7


#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE)

void gpsData();

void getBatteryVoltage();

K_THREAD_STACK_DEFINE(my_stack_area,STACK_SIZE);

K_THREAD_DEFINE(gps_id, STACK_SIZE,
                gpsData, NULL, NULL, NULL,
                PRIORITY, 0, K_NO_WAIT);

struct k_thread battery_voltage_data;
struct k_thread gps_data;


K_MUTEX_DEFINE(battery_data); 

#ifdef CONFIG_BOARD_NRF9160_PCA10090NS
#define AT_MAGPIO      "AT\%XMAGPIO=1,0,0,1,1,1574,1577"
#endif

static const char     update_indicator[] = {'\\', '|', '/', '-'};
static const char     at_commands[][31]  = {
				AT_XSYSTEMMODE,
#ifdef CONFIG_BOARD_NRF9160_PCA10090NS
				AT_MAGPIO,
#endif
				AT_CFUN
			};

static int            fd;

static char           nmea_strings[10][NRF_GNSS_NMEA_MAX_LEN];
static u32_t          nmea_string_cnt;

static bool           got_first_fix;
static bool           update_terminal;
static u64_t          fix_timestamp;
nrf_gnss_data_frame_t last_fix;


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;
}

void bsd_recoverable_error_handler(uint32_t error)
{
	printf("Err: %lu\n", (unsigned long)error);
}

void bsd_irrecoverable_error_handler(uint32_t error)
{
	printf("Irrecoverable: %lu\n", (unsigned long)error);
}

static int enable_gps(void)
{
	int  at_sock;
	int  bytes_sent;
	int  bytes_received;
	char buf[2];
        
	at_sock = socket(AF_LTE, 0, NPROTO_AT);
	if (at_sock < 0) {
		return -1;
	}

	for (int i = 0; i < ARRAY_SIZE(at_commands); i++) {
		bytes_sent = send(at_sock, at_commands[i],
				  strlen(at_commands[i]), 0);

		if (bytes_sent < 0) {
			close(at_sock);
			return -1;
		}

		do {
			bytes_received = recv(at_sock, buf, 2, 0);
		} while (bytes_received == 0);

		if (memcmp(buf, "OK", 2) != 0) {
			close(at_sock);
			return -1;
		}
	}

	close(at_sock);

	return 0;
}

static int init_app(void)
{
	u16_t fix_retry     = 0;
	u16_t fix_interval  = 1;
	u16_t nmea_mask     = NRF_CONFIG_NMEA_GSV_MASK |
			      NRF_CONFIG_NMEA_GSA_MASK |
			      NRF_CONFIG_NMEA_GLL_MASK |
			      NRF_CONFIG_NMEA_GGA_MASK |
			      NRF_CONFIG_NMEA_RMC_MASK;
	int   retval;

	if (enable_gps() != 0) {
		printk("Failed to enable GPS\n");
		return -1;
	}

	fd = nrf_socket(NRF_AF_LOCAL, NRF_SOCK_DGRAM, NRF_PROTO_GNSS);

	if (fd >= 0) {
		printk("GPS Socket created\n");
	} else {
		printk("Could not init socket (err: %d)\n", fd);
		return -1;
	}

	retval = nrf_setsockopt(fd,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_FIX_RETRY,
				&fix_retry,
				sizeof(uint16_t));

	if (retval != 0) {
		printk("Failed to set fix retry value\n");
		return -1;
	}

	retval = nrf_setsockopt(fd,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_FIX_INTERVAL,
				&fix_interval,
				sizeof(uint16_t));

	if (retval != 0) {
		printk("Failed to set fix interval value\n");
		return -1;
	}

	retval = nrf_setsockopt(fd,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_NMEA_MASK,
				&nmea_mask,
				sizeof(uint16_t));

	if (retval != 0) {
		printk("Failed to set nmea mask\n");
		return -1;
	}

	retval = nrf_setsockopt(fd,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_START,
				NULL,
				0);

	if (retval != 0) {
		printk("Failed to start GPS\n");
		return -1;
	}

	return 0;
}

static void print_satellite_stats(nrf_gnss_data_frame_t *pvt_data)
{
	u8_t  tracked          = 0;
	u8_t  in_fix           = 0;
	u8_t  unhealthy        = 0;

	for (int i = 0; i < NRF_GNSS_MAX_SATELLITES; ++i) {

		if ((pvt_data->pvt.sv[i].sv > 0) &&
		    (pvt_data->pvt.sv[i].sv < 33)) {

			tracked++;

			if (pvt_data->pvt.sv[i].flags &
					NRF_GNSS_PVT_FLAG_FIX_VALID_BIT) {
				in_fix++;
			}

			if (pvt_data->pvt.sv[i].flags &
					NRF_GNSS_SV_FLAG_UNHEALTHY) {
				unhealthy++;
			}
		}
	}

	printk("Tracking: %d Using: %d Unhealthy: %d", tracked,
						       in_fix,
						       unhealthy);

	printk("\nSeconds since last fix %lld\n",
			(k_uptime_get() - fix_timestamp) / 1000);
}

static void print_pvt_data(nrf_gnss_data_frame_t *pvt_data)
{
	printf("Longitude:  %f\n", pvt_data->pvt.longitude);
	printf("Latitude:   %f\n", pvt_data->pvt.latitude);
	printf("Altitude:   %f\n", pvt_data->pvt.altitude);
	printf("Speed:      %f\n", pvt_data->pvt.speed);
	printf("Heading:    %f\n", pvt_data->pvt.heading);
	printk("Date:       %02u-%02u-%02u\n", pvt_data->pvt.datetime.day,
					       pvt_data->pvt.datetime.month,
					       pvt_data->pvt.datetime.year);
	printk("Time (UTC): %02u:%02u:%02u\n", pvt_data->pvt.datetime.hour,
					       pvt_data->pvt.datetime.minute,
					      pvt_data->pvt.datetime.seconds);
}

static void print_nmea_data(void)
{
	printk("NMEA strings:\n");

	for (int i = 0; i < nmea_string_cnt; ++i) {
		printk("%s\n", nmea_strings[i]);
	}
}

int process_gps_data(nrf_gnss_data_frame_t *gps_data)
{
	int retval;

	retval = nrf_recv(fd, gps_data, sizeof(nrf_gnss_data_frame_t), NRF_MSG_DONTWAIT);

	if (retval > 0) {

		switch (gps_data->data_id) {
		case NRF_GNSS_PVT_DATA_ID:

			if ((gps_data->pvt.flags &
				NRF_GNSS_PVT_FLAG_FIX_VALID_BIT)
				== NRF_GNSS_PVT_FLAG_FIX_VALID_BIT) {

				if (!got_first_fix) {
					got_first_fix = true;
				}

				fix_timestamp = k_uptime_get();
				memcpy(&last_fix, gps_data, sizeof(nrf_gnss_data_frame_t));

				nmea_string_cnt = 0;
				update_terminal = true;
			}
			break;

		case NRF_GNSS_NMEA_DATA_ID:
			if (nmea_string_cnt < 10) {
				memcpy(nmea_strings[nmea_string_cnt++],
				       gps_data->nmea,
				       retval);
			}
			break;

		default:
			break;
		}
	}

	return retval;
}






void gpsData(){
        nrf_gnss_data_frame_t gps_data;
	u8_t		      cnt = 0;

	printk("Staring GPS application\n");

	if (init_app() != 0) {
		//return -1;
	}

	printk("Getting GPS data...\n");

	while (1) {

		do {
			/* Loop until we don't have more
			 * data to read*/
			 
		} while (process_gps_data(&gps_data) > 0);

		if (!got_first_fix) {
			cnt++;
			//printk("\033[1;1H");
			//printk("\033[2J");
			print_satellite_stats(&gps_data);
			printk("\nScanning [%c]\n ",
					update_indicator[cnt%4]);
		}

		if (((k_uptime_get() - fix_timestamp) >= 1) &&
		     (got_first_fix)) {
			printk("\033[1;1H");
			printk("\033[2J");

			print_satellite_stats(&gps_data);

			printk("---------------------------------\n");
			print_pvt_data(&last_fix);
			printk("\n");
			print_nmea_data();
			printk("---------------------------------");

			update_terminal = false;
		}

		k_sleep(K_MSEC(500));
	}
}


void getBatteryVoltage(){
        
        enum at_cmd_state at_state;
        int actual_voltage;
        char recv_buf[1024];

        printk("Getting battery voltage\n");
      
        int at_socket_fd=socket(AF_LTE, 0, NPROTO_AT);

        if (at_socket_fd < 0) {
		printk("Socket err: %d, errno: %d\r\n", at_socket_fd, errno);
	}
	
      


       while(1){

              k_mutex_lock(&battery_data,K_FOREVER);
              
              
              int bytes_written = send(at_socket_fd, battery_voltage,
                                       strlen(battery_voltage), 0);
              k_sleep(K_MSEC(50));
              if (bytes_written > 0) {
                      int r_bytes =
                              blocking_recv(at_socket_fd, recv_buf,
                                            sizeof(recv_buf), MSG_DONTWAIT);
                      if (r_bytes > 0) {
                              char *s=strstr(recv_buf," ");
                              actual_voltage=atoi(s);
                              printk("Actual battery voltage:%d V\n",actual_voltage);
                      }
              }
             k_mutex_unlock(&battery_data);
            
             k_sleep(K_MSEC(1000));
       }

        printk("Closing socket\n\n");
	    close(at_socket_fd);


       
	
}

int main(void)
{
    
        printk("Application started\n");


       
       

        k_tid_t battery_tid = k_thread_create(&battery_voltage_data, 
                                               my_stack_area,
                                               STACK_SIZE,
                                               getBatteryVoltage,
                                               NULL, NULL, NULL,
                                               PRIORITY,0,K_FOREVER);
              
       k_thread_start(battery_tid);

       k_sleep(K_MSEC(2000));
        
       k_tid_t gps_tid = k_thread_create( &gps_data, 
                                           my_stack_area,
                                           STACK_SIZE,
                                           gpsData,
                                           NULL, NULL, NULL,
                                           PRIORITY,0,K_FOREVER);

        k_thread_start(gps_tid);

       

      
        while(1){
             k_sleep(K_MSEC(2000));
             
             printk("Inside while loop\n");
             k_thread_suspend(battery_tid);
        
             k_sleep(K_MSEC(2000));
             k_thread_resume(battery_tid);
         
         
         
        }
   
   
       
	return 0;
}

Please help me resolve this issue

Thanks

Related