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(¶m, &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 } }