Hard Fault when calling bt_le_ext_adv_start

Hi

I am getting a hard fault when I am trying to call  bt_le_ext_adv_start(). I am not sure if it is related to the manufacturer data contents or something else.

The error code is -120. Any ideas what could that mean?

Can someone advise or suggest debugging techniques to understand what could be the problem?

Thanks

/* main.c - Application main entry point */

/*
 * Copyright (c) 2015-2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/types.h>
#include <zephyr/logging/log.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys/util_macro.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/direction.h>

#include <zephyr/bluetooth/hci.h>
#include <stdlib.h>
#include <math.h>
#include <hal/nrf_gpio.h>
#include <zephyr/drivers/adc.h>

#include "app_types.h"
#include "app_fram.h"
#include "app_encryption.h"
#include "app_accel.h"
#include "app_temp_pressure.h"
#include "zephyr/drivers/gpio.h"
#include <zephyr/init.h>
#include <zephyr/drivers/uart.h>

// conditional compile options
#define FORCE_TOGGLE (1)
#define FORCE_FRAM_VALS (0)
#define HAVE_ISL9122 (0)
#define USING_MG24 (0)
#define ENCR_KEY_IN_FRAM (0)

#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
#define DEVICE_ID 3

#define MANUF_DATA_CUSTOM_START_INDEX   2
#define PAYLOAD_TX_REPEAT_COUNTER_INDEX 18
#define PAYLOAD_DEVICE_ID_INDEX         19
#define PAYLOAD_STATUS_BYTE_INDEX       21
#define PAYLOAD_RFU_BYTE_INDEX          22
#define PAYLOAD_ENCRYPTION_STATUS_ENC   0
#define PAYLOAD_ENCRYPTION_STATUS_CLEAR 1
#define FRAME_LENGTH                    24

#define BLE_ADV_INTERVAL_MIN            (32) // N * 0.625. corresponds to dec. 32; 32*0.625 = 20ms
#define BLE_ADV_INTERVAL_MAX            (36) // N * 0.625. corresponds to dec. 36; 36*0.625 = 22.5ms
#define BLE_ADV_TIMEOUT                 (0)  // N * 10ms for advertiser timeout
#define BLE_ADV_EVENTS                  (1)


#define PACKET_INTERVAL_MIN (10) // ms repeat rate
#define PACKET_INTERVAL_MAX (50) // ms repeat rate

#define LOGS (1) // if printk doesn't handle it use if(LOGS) printk();

#define POL_GPIO_PIN                    13

#define FIELD_NAME_MAX_LENGTH       32

/* Length of CTE in unit of 8[us] */
#define CTE_LEN (0x14U)
/* Number of CTE send in single periodic advertising train */
#define PER_ADV_EVENT_CTE_COUNT 5


struct bt_df_adv_cte_tx_param cte_params = { .cte_len = CTE_LEN,
					     .cte_count = PER_ADV_EVENT_CTE_COUNT,
#if defined(CONFIG_BT_DF_CTE_TX_AOD)
					     .cte_type = BT_DF_CTE_TYPE_AOD_2US,
					     .num_ant_ids = ARRAY_SIZE(ant_patterns),
					     .ant_ids = ant_patterns
#else
					     .cte_type = BT_DF_CTE_TYPE_AOA,
					     .num_ant_ids = 0,
					     .ant_ids = NULL
#endif /* CONFIG_BT_DF_CTE_TX_AOD */
};

enum FRAM_TYPE {
    NUMBER = 0,
    STRING,
    BYTE_ARRAY,
};

typedef struct
{
    char name[FIELD_NAME_MAX_LENGTH];
    uint8_t type;
    uint8_t field_length;
    uint32_t min_value;
    uint32_t max_value;
}fram_info_t;

const fram_info_t FRAM_INFO[MAX_FRAM_FIELDS] = {
    {"EVENT Counter", NUMBER, FRAM_COUNTER_NUM_BYTES, 0, 0xFFFFFFFF},
    {"SERIAL NUMBER", NUMBER, SER_NUM_BYTES, 0, 0xFFFFFFFF},
    {"TYPE", NUMBER, TYPE_NUM_BYTES, 0, 0xFF},
    {"EVENT INTERVAL", NUMBER, EV_INT_NUM_BYTES, 10, 100},  // advertising interval within an event
    {"EVENT MAXIMUM LIMITS", NUMBER,EV_MAX_NUM_BYTES, 1, 0xF0}, // max advertising repeats within an event
    {"EVENT MINIMUM SLEEP", NUMBER, EV_SLP_NUM_BYTES, 0, 10000}, // sleep time before next event, 0 just wastes rest of power.
    {"SLEEP AFTER WAKEUP", NUMBER, IN_SLP_NUM_BYTES, 0, 100}, // 
    {"VOLT of ISL9122", NUMBER, ISL9122_NUM_BYTES, 0, 0xFF},
    {"POL METHOD", NUMBER, POL_MET_NUM_BYTES, 0, 2},
    {"ENCRYPTED KEY", BYTE_ARRAY, ENCRYPTED_KEY_NUM_BYTES, NULL, NULL},
    {"TX dBM 10", NUMBER, TX_DBM_NUM_BYTES, 0, 200},
    {"Device NAME", STRING, NAME_NUM_BYTES, NULL, NULL}
};
/*
const char FRAM_FIELD_NAMES[MAX_FRAM_FIELDS][FIELD_NAME_MAX_LENGTH] = {
    "EVENT Counter", "SERIAL NUMBER", "TYPE", "EVENT INTERVAL", "EVENT MAXIMUM LIMITS", "EVENT MINIMUM SLEEP",
	"SLEEP AFTER WAKEUP", "VOLT of ISL9122", "POL METHOD", "ENCRYPTED KEY", "TX dBM 10", "Device NAME",};

const uint8_t FRAM_FIELD_LENGTH[MAX_FRAM_FIELDS] = {
    (FRAM_COUNTER_NUM_BYTES), SER_NUM_BYTES, TYPE_NUM_BYTES, EV_INT_NUM_BYTES, EV_MAX_NUM_BYTES, 
    EV_SLP_NUM_BYTES, IN_SLP_NUM_BYTES, ISL9122_NUM_BYTES, POL_MET_NUM_BYTES, NAME_NUM_BYTES,
};

const uint8_t bIsNumeric[MAX_FRAM_FIELDS] = {NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, BYTE_ARRAY, NUMBER, STRING};

const uint32_t MinValue[MAX_FRAM_FIELDS] = {0, 0, 0, 20, 1, 0, 0, 0, 0, 0, 0, 0};
const uint32_t MaxValue[MAX_FRAM_FIELDS] = {0xFFFFFF, 0xFFFF, 0xFF, 30, 0xF0, 100, 1000, 1700, 1, 0xFF, 0xFF, 0xFF};
*/

/* Data of ADC io-channels specified in devicetree. */
static const struct adc_dt_spec adc_channel =
    ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0);

#define UART_DEVICE_NODE DT_CHOSEN(zephyr_shell_uart)
#define UART_MSG_SIZE 256
/* queue to store up to 1 messages (aligned to 4-byte boundary) */
K_MSGQ_DEFINE(uart_msgq, UART_MSG_SIZE, 1, 4);
static const struct device *const uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);
static struct k_work process_command_task;

/* receive buffer used in UART ISR callback */
static uint8_t rx_buf[UART_MSG_SIZE];
static int rx_buf_pos;

static void timer_event_handler(struct k_timer *dummy);
static void timer_event_handler2(struct k_timer *dummy);

K_TIMER_DEFINE(timer_event, timer_event_handler, NULL);
K_TIMER_DEFINE(timer_event2, timer_event_handler2, NULL);

static struct k_work start_advertising_worker;
static struct k_work start_timer_task;
static struct k_work_delayable update_frame_work;

static we_power_data_ble_adv_t we_power_data;
static struct bt_data we_power_adv_data;
static struct bt_le_ext_adv *adv;

// variable to store the FRAM data
static fram_data_t fram_data = {0};
//static u16_u8_t device_id;
static uint8_t TX_Repeat_Counter;
static uint8_t TX_Repeat_Counter_Init = 1;  

uint32_t serial_number = DEVICE_ID;
uint8_t  type = 1;
uint8_t  event_inteval = 20;
uint16_t event_max_limits = 240;
uint16_t sleep_min_interval = 200;
uint16_t sleep_after_wake = 0; // assumes sleep(0) is just a yield()
uint8_t u8Polarity = 0;

uint8_t bPressureRequested = 0;

extern uint8_t ecb_key[16];
static const struct device *dev_uart;


struct bt_le_adv_param param =
		BT_LE_ADV_PARAM_INIT(
				     BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_USE_IDENTITY | BT_LE_ADV_OPT_USE_NAME,
				     BLE_ADV_INTERVAL_MIN,
				     BLE_ADV_INTERVAL_MAX,
				     NULL);




typedef struct
{
    uint8_t type;
    int8_t field_index;
    uint8_t data_len;
    uint8_t data[(UART_MSG_SIZE - 3)];
}command_data_t;

command_data_t command_data = {0};
//                                                    |--------- ENCRYPTED ENCRYPTED ENCRYPTED ENCRYPTED ENCRYPTED ENCRYPTED ENCRYPTED ------------ |  cnt    id    id  status RFU
static uint8_t manf_data[FRAME_LENGTH] = { 0x50, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F};
static struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
    BT_DATA(BT_DATA_MANUFACTURER_DATA, manf_data, FRAME_LENGTH),
	BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x50, 0x57)
};


//JPTV Vars
static uint16_t timer_flag = 0;
#define DURATION 1000
#define PERIOD 50

static void adv_sent(struct bt_le_ext_adv *instance,
		     struct bt_le_ext_adv_sent_info *info)
{	
	if (FORCE_TOGGLE || (fram_data.u8_POLmethod == OUT_POL)) nrf_gpio_pin_toggle(POL_GPIO_PIN);
}


static const struct bt_le_ext_adv_cb adv_cb = {
		.sent = adv_sent,
	};


static void init_gpio_fn(void)
{
    #if (FORCE_TOGGLE)
    	nrf_gpio_cfg_output(POL_GPIO_PIN); 
        nrf_gpio_pin_toggle(POL_GPIO_PIN);
    #endif 
}

SYS_INIT(init_gpio_fn, POST_KERNEL, 0); // Define the Initi function of System

void print_uart(char *buffer)
{
	int msg_len = strlen(buffer);

	for (int i = 0; i < msg_len; i++) {
		uart_poll_out(dev_uart, buffer[i]);
	}

    uart_poll_out(dev_uart, '\n');
}

void parse_command(uint8_t *buf)
{
    uint8_t space_idx = 0;
    uint8_t data_idx = 0;

    memset(&command_data, 0x00, sizeof(command_data_t));

    for (uint8_t i=0; buf[i]!='\0'; i++){
        if ((buf[i] == ' ') && (space_idx < 2)){
            space_idx++;

            if ((space_idx == 2) || (command_data.field_index == NAME)){
                memset(&command_data.data, ' ', NAME_NUM_BYTES); // init cName with space character
            }
        }
        else{
            if (space_idx == 0){
                command_data.type = buf[i];
            }
            else if (space_idx == 1){
                if (command_data.type == 'K') { // K command
                    command_data.type = 'S';
                    command_data.field_index = ENCRYPTED_KEY;
                    space_idx = 2;
                }
                else if (command_data.type == 'N'){ // N command
                    command_data.type = 'S';
                    command_data.field_index = NAME;
                    memset(&command_data.data, ' ', NAME_NUM_BYTES); // init cName with space character
                    space_idx = 2;
                }
                else {
                    if ((buf[i] >= 48) && (buf[i] <= 57)){
                        command_data.field_index = command_data.field_index * 10 + (buf[i] - 48);
                    }
                    else {
                        command_data.field_index = -1;
                    }
                }
            }
            
            if(space_idx == 2){
                if(command_data.field_index == ENCRYPTED_KEY){
                    if((buf[i] >= '0') && (buf[i] <= '9')) {
                        command_data.data[data_idx] = command_data.data[data_idx] * 16 + (buf[i] - 48);
                    }
                    else if ((buf[i] >= 'a') && (buf[i] <= 'f')){
                        command_data.data[data_idx] = command_data.data[data_idx] * 16 + (buf[i] - 87);
                    }
                    else if ((buf[i] >= 'A') && (buf[i] <= 'F')){
                        command_data.data[data_idx] = command_data.data[data_idx] * 16 + (buf[i] - 55);
                    }
                    else if (buf[i] == ' '){
                        data_idx++;
                    }
                }
                else {
                    command_data.data[data_idx] = buf[i];
                    data_idx++;
                }
            }
        }
    }

    command_data.data_len = data_idx;
}

int process_command_fn(struct k_work *work)
{
    uint8_t response[256] = {0};
    uint8_t encrypted_key_str[(3 * ENCRYPTED_KEY_NUM_BYTES) + 1] = {0};
    uint32_t field_data = 0;

    printk("Parsed Command is Type: %c, field: %d, data: %s\n", command_data.type, command_data.field_index, command_data.data);

    if(command_data.field_index >= MAX_FRAM_FIELDS){
        sprintf(response, "FRAM field %d does not exist\n", command_data.field_index);
        printk("%s\n", response);
        print_uart(response);
        return -EINVAL;
    }
    else if (command_data.field_index < 0){
        sprintf(response, "FRAM field %d is invalid.\n", command_data.field_index);
        printk("%s\n", response);
        print_uart(response);
        return -EINVAL;
    }

    if ((command_data.type == 'G') || (command_data.type == 'g'))
    {
        if ( app_fram_read_field(command_data.field_index, command_data.data) == FRAM_SUCCESS){
            if (FRAM_INFO[command_data.field_index].type == NUMBER){
                memcpy(&field_data, command_data.data, FRAM_INFO[command_data.field_index].field_length);
                sprintf(response, "FRAM field %s, length, %d, value is %d.\n", 
                        FRAM_INFO[command_data.field_index].name, FRAM_INFO[command_data.field_index].field_length, field_data);
            }
            else if (FRAM_INFO[command_data.field_index].type == STRING){
                sprintf(response, "FRAM field %s, length, %d, value is %s.\n", 
                        FRAM_INFO[command_data.field_index].name, FRAM_INFO[command_data.field_index].field_length, command_data.data);
            }
            else if (FRAM_INFO[command_data.field_index].type == BYTE_ARRAY){
                for (uint8_t i = 0; i < ENCRYPTED_KEY_NUM_BYTES; i++){
                    sprintf(&encrypted_key_str[(i * 3)], "%02X ", command_data.data[i]);
                }
                encrypted_key_str[(3*ENCRYPTED_KEY_NUM_BYTES - 1)] = '.';
                sprintf(response, "FRAM field %s, length, %d, value is 0x%s\n", 
                        FRAM_INFO[command_data.field_index].name, FRAM_INFO[command_data.field_index].field_length, encrypted_key_str);
            }
        }
        else{
            sprintf(response, "Access to FRAM failed.\n");
        }
    }
    else if ((command_data.type == 'S') || (command_data.type == 's')){
        if (FRAM_INFO[command_data.field_index].type == NUMBER){ //Numeric
            for (uint8_t i = 0; i < command_data.data_len; i++){
                field_data = field_data * 10 + (command_data.data[i] - 48);
            }

            printk(" Numeric Data: %d\n", field_data);

            if(field_data < FRAM_INFO[command_data.field_index].min_value){
                if (app_fram_read_field(command_data.field_index, &field_data) == FRAM_SUCCESS){
                    sprintf(response, "FRAM field %s, Min limit %d, Value is %d.\n", 
                        FRAM_INFO[command_data.field_index].name, FRAM_INFO[command_data.field_index].min_value, field_data);
                }else{
                    sprintf(response, "Access to FRAM failed.\n");
                }
            }
            else if (field_data > FRAM_INFO[command_data.field_index].max_value){
                if (app_fram_read_field(command_data.field_index, &field_data) == FRAM_SUCCESS){
                    sprintf(response, "FRAM field %s, Max limit %d exceeded, Value is %d.\n", 
                        FRAM_INFO[command_data.field_index].name, FRAM_INFO[command_data.field_index].max_value, field_data);
                } else {
                    sprintf(response, "Access to FRAM failed.\n");
                }
            }
            else {
                if (app_fram_write_field(command_data.field_index, &field_data) == FRAM_SUCCESS){
                    sprintf(response, "FRAM field %s, Value is %d.\n", FRAM_INFO[command_data.field_index].name, field_data);
                }
                else {
                    sprintf(response, "Access to FRAM failed.\n");
                }
            }   
        }
        else if(FRAM_INFO[command_data.field_index].type == STRING){ //String
            if (command_data.data_len > FRAM_INFO[command_data.field_index].field_length){
                if (app_fram_read_field(command_data.field_index, &command_data.data) == FRAM_SUCCESS){
                    sprintf(
                        response, 
                        "Number of characters exceeds maximum length of 10 bytes. FRAM field %s, length exceeded, Value is %s.\n", 
                        FRAM_INFO[command_data.field_index].name, command_data.data
                    );
                }
                else{
                    sprintf(response, "Access to FRAM failed.\n");
                }
            }
            else{
                if(app_fram_write_field(command_data.field_index, command_data.data) == FRAM_SUCCESS){
                    sprintf(
                        response, 
                        "Fram field %s, length %d, value is %s.\n",
                        FRAM_INFO[command_data.field_index].name, FRAM_INFO[command_data.field_index].field_length, command_data.data
                    );
                } else {
                    sprintf(response, "Access to FRAM failed.\n");
                }
            }
        }
        else if (FRAM_INFO[command_data.field_index].type == BYTE_ARRAY){
            if(app_fram_write_field(command_data.field_index, command_data.data) == FRAM_SUCCESS){
                for (uint8_t i = 0; i < ENCRYPTED_KEY_NUM_BYTES; i++){
                    sprintf(&encrypted_key_str[(i * 3)], "%02X ", command_data.data[i]);
                }
                encrypted_key_str[(3*ENCRYPTED_KEY_NUM_BYTES - 1)] = '.';
                sprintf(response, "FRAM field %s, length, %d, value is 0x%s\n", 
                        FRAM_INFO[command_data.field_index].name, FRAM_INFO[command_data.field_index].field_length, encrypted_key_str);       
            } else {
                sprintf(response, "Access to FRAM failed.\n");
            }
        }
    }
    else if ((command_data.type == 'C') || (command_data.type == 'c')){
        if (FRAM_INFO[command_data.field_index].type == NUMBER){
            field_data = 0;
            if (app_fram_write_field(command_data.field_index, &field_data) == FRAM_SUCCESS){
                sprintf(response, "FRAM field %s, Value is %d.\n", FRAM_INFO[command_data.field_index].name, field_data);
            }
            else {
                sprintf(response, "Access to FRAM failed.\n");
            }
        }
        else if (FRAM_INFO[command_data.field_index].type == STRING){
            memset(command_data.data, ' ', FRAM_INFO[command_data.field_index].field_length);
            if(app_fram_write_field(command_data.field_index, command_data.data) == FRAM_SUCCESS){
                sprintf(response, "FRAM field %s, Value is \"%s\".\n", FRAM_INFO[command_data.field_index].name, field_data);
            }
            else{
                sprintf(response, "Access to FRAM failed.\n");
            }
        }
        else if (FRAM_INFO[command_data.field_index].type == BYTE_ARRAY){
            memset(command_data.data, 0x00, FRAM_INFO[command_data.field_index].field_length);
            if(app_fram_write_field(command_data.field_index, command_data.data) == FRAM_SUCCESS){
                sprintf(response, "FRAM field %s, Value is \"%s\".\n", FRAM_INFO[command_data.field_index].name, field_data);
            }
            else{
                sprintf(response, "Access to FRAM failed.\n");
            }
        }
    }

    printk("%s",response);
    print_uart(response);
    return 0;
}
/*
 * Read characters from UART until line end is detected. Afterwards push the
 * data to the message queue.
 */
void serial_cb(const struct device *dev, void *user_data)
{
	uint8_t c;

	if (!uart_irq_update(uart_dev)) {
		return;
	}

	if (!uart_irq_rx_ready(uart_dev)) {
		return;
	}

	/* read until FIFO empty */
	while (uart_fifo_read(uart_dev, &c, 1) == 1) {
		if ((c == '\n' || c == '\r') && rx_buf_pos > 0) {
			/* terminate string */
			rx_buf[rx_buf_pos] = '\0';

            if(LOGS){
                printk("--------- UART Received Data -------------\n ");
                for (int i = 0; i < rx_buf_pos; i++){
                    printk("%c", rx_buf[i]);
                }
                printk("\n");
            }

			/* if queue is full, message is silently dropped */
			k_msgq_put(&uart_msgq, &rx_buf, K_NO_WAIT);
            parse_command(rx_buf);
            /* reset the buffer (it was copied to the msgq) */
			rx_buf_pos = 0;

            k_work_submit(&process_command_task);

          
		} else if (rx_buf_pos < (sizeof(rx_buf) - 1)) {
			rx_buf[rx_buf_pos++] = c;
		}
		/* else: characters beyond buffer size are dropped */
	}
}

static int init_uart(void)
{
    dev_uart = device_get_binding("UART_0");
	if (dev_uart == NULL) {
		printk("Failed to get UART binding\n");
		return;
	}

    if (!device_is_ready(dev_uart)) {
		printk("UART device not found!");
		return 0;
	}

	// configure interrupt and callback to receive data 
	int ret = uart_irq_callback_user_data_set(dev_uart, serial_cb, NULL);

	if (ret < 0) {
		if (ret == -ENOTSUP) {
			printk("Interrupt-driven UART API support not enabled\n");
		} else if (ret == -ENOSYS) {
			printk("UART device does not support interrupt-driven API\n");
		} else {
			printk("Error setting UART callback: %d\n", ret);
		}
		return 0;
	}
	uart_irq_rx_enable(dev_uart);
    
    printk("UART is initiated.\n");

    return 0;
}


static int create_advertising(void)
{
	int err;

	err = bt_le_ext_adv_create(&param, &adv_cb, &adv);
	if (err) {
		printk("Failed to create advertiser set (%d)\n", err);
		return err;
	}

	printk("Created adv: %p\n", adv);

	return 0;
}

void start_advertising(struct k_work *work)
{
	int err;

     if(LOGS){
        printk("Manufacturer Data: ");
        for (uint8_t i = 0; i < FRAME_LENGTH; i++){
            printk("%02X ", manf_data[i]);
        }
        printk("\n");
    }

	err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0);
	if (err) {
		printk("Failed to set advertising data (%d)\n", err);
		return err;
	}

	err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_PARAM(BLE_ADV_TIMEOUT, BLE_ADV_EVENTS));
	if (err) {
		printk("Failed to start advertising set (%d)\n", err);
		return;
	}
}


void start_task_periodic(struct k_work *work)
{


}



void start_ble_adv(void)
{
	int err;

     if(LOGS){
        printk("Manufacturer Data: ");
        for (uint8_t i = 0; i < FRAME_LENGTH; i++){
            printk("%02X ", manf_data[i]);
        }
        printk("\n");
    }

	err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0);
	if (err) {
		printk("Failed to set advertising data (%d)\n", err);
		return err;
	}

	err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_PARAM(BLE_ADV_TIMEOUT, BLE_ADV_EVENTS));
	if (err) {
		printk("Failed to start advertising set (%d)\n", err);
		return;
	}
}


static void bt_ready(void)
{
	int err = 0;

	printk("Bluetooth initialized\n");

	err = create_advertising();
	if (err) {
		printk("Advertising failed to create (err %d)\n", err);
		return;
	}
    
}

// hopefully it is valid to do this in a timer event
void burn_energy()
{
	volatile double foo = 3.0;
	while (1)
	{
		foo = sqrt(foo);
		foo = foo * foo;
	}
}

static void timer_event_handler(struct k_timer *dummy)
{
    TX_Repeat_Counter++;
    //TODO JPTV: Replace back the FRAM Variable
    //if (TX_Repeat_Counter <= fram_data.event_max_limits) // starts at 0, we send 1 if max is 1 by incrementing after the test.
    if (TX_Repeat_Counter <= 5) // starts at 0, we send 1 if max is 1 by incrementing after the test.
    {
        manf_data[PAYLOAD_TX_REPEAT_COUNTER_INDEX] = TX_Repeat_Counter;
        k_work_submit(&start_advertising_worker);
    }
    else {
        printk(">>> Sent maximum packets.\n");
        TX_Repeat_Counter = TX_Repeat_Counter_Init;
        k_timer_stop(&timer_event);
		if (fram_data.sleep_min_interval)
			k_work_schedule(&update_frame_work, K_MSEC(fram_data.sleep_min_interval));
		//else
		//	burn_energy(); // TODO - if it is not legal to do a while(1) in a handler, then queue this up.
    }
}


static void timer_event_handler2(struct k_timer *dummy)
{
    timer_flag++;

    if(timer_flag<500)
        start_ble_adv();
    else
        timer_flag = 600;
}


static void measure_sensors(we_power_data_ble_adv_t *we_power_data)
{
     // Get the accelerometer data
    static accel_data_t accel_data;
    if(app_accel_service(&accel_data) == ACCEL_SUCCESS)
    {
        // Success!
        we_power_data->data_fields.accel_x.i16 = accel_data.x_accel;
        we_power_data->data_fields.accel_y.i16 = accel_data.y_accel;
        we_power_data->data_fields.accel_z.i16 = accel_data.z_accel;
    }
    else
    {
        we_power_data->data_fields.accel_x.i16 = 0xFFFF;
        we_power_data->data_fields.accel_y.i16 = 0xFFFF;
        we_power_data->data_fields.accel_z.i16 = 0xFFFF;
    }

    // Get temp and pressure
    temp_pressure_data_t temp_pressure_data;
    if(app_temp_pressure_service(&temp_pressure_data) == TEMP_PRESSURE_SUCCESS)
    {
        we_power_data->data_fields.pressure.i16 = temp_pressure_data.pressure;
        we_power_data->data_fields.temp.i16 = temp_pressure_data.temp;
    }
    else
    {
        we_power_data->data_fields.pressure.i16 = 0xFFFF;
        we_power_data->data_fields.temp.i16 = 0xFFFF;
    }

}

void encryptedData(uint8_t* clear_text_buf, uint8_t* encrypted_text_buf, uint8_t len )
{
#define ENCRYPT
#ifdef ENCRYPT
    // Not we want to encrypt the data
    if(app_encrypt_payload(clear_text_buf, len, encrypted_text_buf, len) == ENCRYPTION_ERROR)
    {
        memcpy(encrypted_text_buf, clear_text_buf, 16);
        manf_data[PAYLOAD_STATUS_BYTE_INDEX] = PAYLOAD_ENCRYPTION_STATUS_CLEAR;
    }
    else
    {
        manf_data[PAYLOAD_STATUS_BYTE_INDEX] = PAYLOAD_ENCRYPTION_STATUS_ENC;
    }
#else
    memcpy(cipher_text, encrypted_text_buf, 16);
    manf_data[PAYLOAD_STATUS_BYTE_INDEX] = PAYLOAD_ENCRYPTION_STATUS_CLEAR;
#endif
    if (LOGS){
        printk("Payload - Cleartext: ");
        for(int i = 0; i < len; i++)
        {
            printk("%02X ", clear_text_buf[i]);
        }
        printk("\n");

        printk("Payload - Encrypted: ");
        for(int i = 0; i < len; i++)
        {
            printk("%02X ", encrypted_text_buf[i]);
        }
        printk("\n");
    }
}

// only call this ONCE per EventCounter (FRAM[0:3])
void updateManufacturerData(void){
    printk(">>> Updating the Manufacturer Data\n");
   //Get sensor data
	switch (type)
	{
	default: 
		measure_sensors(&we_power_data);
		break;

	case 3: 
		we_power_data.data_bytes[4] = u8Polarity;
		memcpy(&we_power_data.data_bytes[5], fram_data.cName, 9);
		break;

	case 4: 
		memcpy(&we_power_data.data_bytes[4], fram_data.cName, 10);
		break;

	}

    // increase the FRAM Event counter and set first four bytes
	fram_data.event_counter++;
    app_fram_write_counter(&fram_data);

	we_power_data.data_fields.type = fram_data.type;
	we_power_data.data_fields.event_counter24[0] = (uint8_t)((fram_data.event_counter & 0x000000FF));
	we_power_data.data_fields.event_counter24[1] = (uint8_t)((fram_data.event_counter & 0x0000FF00)>>8);
	we_power_data.data_fields.event_counter24[2] = (uint8_t)((fram_data.event_counter & 0x00FF0000)>>16);
    we_power_data.data_fields.id.u16 = fram_data.serial_number & 0xFFFF;

    // initialize the TX counter

	TX_Repeat_Counter = TX_Repeat_Counter_Init;
	manf_data[PAYLOAD_TX_REPEAT_COUNTER_INDEX] = TX_Repeat_Counter;
   
    // Handle encryption
    static uint8_t cipher_text[DATA_SIZE_BYTES];

    encryptedData(we_power_data.data_bytes, cipher_text, DATA_SIZE_BYTES);
    // Build the BLE adv data
    memcpy(&manf_data[MANUF_DATA_CUSTOM_START_INDEX], cipher_text, DATA_SIZE_BYTES);
    memcpy(&manf_data[PAYLOAD_DEVICE_ID_INDEX], &(fram_data.serial_number), 2);

    we_power_adv_data.type = BT_DATA_SVC_DATA16;
    we_power_adv_data.data = manf_data;
    we_power_adv_data.data_len = sizeof(manf_data);

}

void update_frame_work_fn(struct k_work *work)
{
    updateManufacturerData();
    k_timer_start(&timer_event, K_MSEC(fram_data.event_inteval), K_MSEC(fram_data.event_inteval)); // Start 20ms timer event
}

// TODO - make this run much faster
int32_t read_vcc10(void)
{
    int8_t err;

    uint16_t buf;
	struct adc_sequence sequence = {
		.buffer = &buf,
		/* buffer size in bytes, not number of samples */
		.buffer_size = sizeof(buf),
	};

    int32_t val_mv;

    if (!device_is_ready(adc_channel.dev)) {
		printk("ADC controller device %s not ready\n", adc_channel.dev->name);
		return -EINVAL;
	}

    err = adc_channel_setup_dt(&adc_channel);
	if (err < 0) {
		printk("Could not setup channel (%d)\n", err);
		return -EINVAL;
	}

    printk("- %s, channel %d: ",
			       adc_channel.dev->name,
			       adc_channel.channel_id);
    (void)adc_sequence_init_dt(&adc_channel, &sequence);

    err = adc_read(adc_channel.dev, &sequence);
	if (err < 0) {
		printk("Could not read (%d)\n", err);
        return -EINVAL;
	}

    val_mv = (int32_t)buf;

    printk("%"PRId32, val_mv);

    err = adc_raw_to_millivolts_dt(&adc_channel, &val_mv);

	if (err < 0) {
		printk(" (value in mV not available)\n");
        return -EINVAL;
	} else {
		printk(" = %"PRId32" mV\n", val_mv);
	}
    return val_mv;
}

// Main Application
void main(void)
{
    int err;
    int32_t vext10_mv;
    // read VEXT10 ADC, decide to run this or the configuration app.
    vext10_mv = read_vcc10() * 11;

#if (FORCE_TOGGLE)
    nrf_gpio_pin_toggle(POL_GPIO_PIN);
#endif

	// if VEXT10 > 0.165V we have external power
    if (vext10_mv > 1700){
        //Init UART
        init_uart();
        //Process the UART Command
        k_work_init(&process_command_task, process_command_fn);
    }
    else{
        // ask for temp/pressure data now so we don't sleep(10) later
		if (TEMP_PRESSURE_SUCCESS == app_temp_pressure_trigger())
			bPressureRequested = 1;
        
        // Reading FRAM.
        if(app_fram_read_data(&fram_data) == FRAM_SUCCESS)
        {
            // Success! Add it to the payload

            if (LOGS){
                printk(">> ------- Writing FRAM Data -------\n");
		        printk(">>[FRAM INFO]->Event Counter: 0x%08X\n", fram_data.event_counter);
		        printk(">>[FRAM INFO]->Serial Number: 0x%08X\n", fram_data.serial_number);
		        printk(">>[FRAM INFO]->Device Type: %d\n", fram_data.type);
		        printk(">>[FRAM INFO]->Frame Interval: %d ms\n", fram_data.event_inteval);
		        printk(">>[FRAM INFO]->Frame Maximum Number: %d\n", fram_data.event_max_limits);
		        printk(">>[FRAM INFO]->Minimum Sleeping Interval: %d\n", fram_data.sleep_min_interval);
		        printk(">>[FRAM INFO]->Sleep time After Wake up: %d\n", fram_data.sleep_after_wake);
		        printk(">>[FRAM INFO]->Voltage of ISL9122: %d\n", fram_data.u8_voltsISL9122);
		        printk(">>[FRAM INFO]->POL Method: %d\n", fram_data.u8_POLmethod);
		        printk(">>[FRAM INFO]->Encrypted Key: ");
		        for (uint8_t i = 0; i < ENCRYPTED_KEY_NUM_BYTES; i++){
			        printk("0x%02X,", fram_data.encrypted_key[i]);
		        }
		        printk("\n");
		        printk(">>[FRAM INFO]->TX dBM 10: %d\n", fram_data.tx_dbm_10);
		        printk(">>[FRAM INFO]->cName: %s\n", fram_data.cName);
            }
		
			// TODO - use the same limits as the UART code
            serial_number = fram_data.serial_number?fram_data.serial_number&0xFFFF:DEVICE_ID;
		    type = (fram_data.type ? (fram_data.type < 0xFF ? fram_data.type : 1) : 1);
		    event_inteval = (fram_data.event_inteval >= PACKET_INTERVAL_MIN ? (fram_data.event_inteval <= PACKET_INTERVAL_MAX ? fram_data.event_inteval : PACKET_INTERVAL_MAX) : PACKET_INTERVAL_MIN); //
		    event_max_limits = (fram_data.event_max_limits >= 3 ? (fram_data.event_max_limits < 0xF0 ? fram_data.event_max_limits : 3) : 0xF0);
		    sleep_min_interval = (fram_data.sleep_min_interval >= 50 ? fram_data.sleep_min_interval : 50);
		    sleep_after_wake = (fram_data.sleep_after_wake ? (fram_data.sleep_after_wake < 20 ? fram_data.sleep_after_wake : 20) : 0);
#if (FORCE_FRAM_VALS)
            fram_data.event_inteval=20;
            fram_data.event_max_limits = 0xF0;
            fram_data.serial_number = DEVICE_ID;
            fram_data.sleep_after_wake = 0;
            fram_data.sleep_min_interval = 50;
            fram_data.u8_POLmethod = OUT_POL;
            fram_data.u8_voltsISL9122 = 0;
#endif
#if (HAVE_ISL9122)  
            if (fram_data.u8_voltsISL9122 >= 72 && fram_data.u8_voltsISL9122 <= 132)
		    {// // write fram_data.u8_voltsISL9122 to addr 0x18, reg 0x11
		    };
#endif	
#if (!FORCE_TOGGLE)		
		    if (fram_data.u8_POLmethod == OUT_POL) {// toggle output POL_GPIO_PIN
    			nrf_gpio_cfg_output(POL_GPIO_PIN);
			    nrf_gpio_pin_toggle(POL_GPIO_PIN);
		    }
		    else if (fram_data.u8_POLmethod == IN_POL) {// sleep sleep_after_wake then read GPIO --> u8Polarity
                // sleep sleep_after_wake
                k_sleep(K_MSEC(fram_data.sleep_after_wake));
			    nrf_gpio_cfg_input(POL_GPIO_PIN, NRF_GPIO_PIN_PULLUP);
			    u8Polarity = nrf_gpio_pin_read(POL_GPIO_PIN);
		    }
#if (USING_MG24)
		    else if (fram_data.u8_POLmethod == CMP_POL) {/* not possible on nRF design.  sleep sleep_after_wake then read ACMP0 on EFR32*/
                // init ACMP0

				// sleep
				k_sleep(K_MSEC(fram_data.sleep_after_wake));

				// read ACMP0
            }
#endif
#endif           
            if(ENCR_KEY_IN_FRAM){
                for(uint8_t i = 0; i < ENCRYPTED_KEY_NUM_BYTES; i++){
                    ecb_key[i] = fram_data.encrypted_key[i];
                }
            }
        }
        else
        {
		     fram_data.event_counter = 0;
        }
    
        // Init and run the BLE
	    err = bt_enable(NULL);
	    if (err) {
		    printk("Bluetooth init failed (err %d)\n", err);
		    return;
	    }
	
        //Create Advertiser Set Create
	    bt_ready();

        /*
        err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0);
        if (err) {
            printk("Failed to set advertising data (%d)\n", err);
            return err;
        }

        err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_PARAM(BLE_ADV_TIMEOUT, BLE_ADV_EVENTS));
        if (err) {
            printk("Failed to start advertising set (%d)\n", err);
            return;
        }

              
        //k_timer_start(&timer_event2, K_MSEC(DURATION), K_MSEC(PERIOD)); // Start 20ms timer event
       */
       
       if (FORCE_TOGGLE || (fram_data.u8_POLmethod == OUT_POL)) 
		   nrf_gpio_pin_toggle(POL_GPIO_PIN);

        updateManufacturerData();
        TX_Repeat_Counter_Init = 0; // TODO - figure out why init changes and make sure TX packets always go 1, 2, 3, ...

        if (FORCE_TOGGLE || (fram_data.u8_POLmethod == OUT_POL)) 
			nrf_gpio_pin_toggle(POL_GPIO_PIN);

        // Init works for advertising and measuring data
        k_work_init(&start_advertising_worker, start_advertising);
        k_work_init_delayable(&update_frame_work, update_frame_work_fn);
        k_timer_start(&timer_event, K_MSEC(fram_data.event_inteval), K_MSEC(fram_data.event_inteval)); // Start 20ms timer event
        k_work_submit(&start_advertising_worker);// submit the first packet // TODO - see if inter event delay is event_interval + sleep_min_interval or just sleep_min_interval

        
    }
}

Related