Problems related to nrf5340 brighton/off

Hello.
We are testing nrf5340 - nrf7002 using the example of blpovisioning.
I try to put on/off function using button, but if I reset pcb and turn on, it will connect to wifi and tcp server normally, but if I turn on -> off -> an error occurred in bt hci.
I looked it up
devzone.nordicsemi.com/.../473790
github.com/.../files
It's related, so I modified the nrf53_support.c file and built it

[00:00:17.729,492] <inf> Provisioning: Configuring server address...
[00:00:17.729,797] <inf> Provisioning: Attempting to create socket...
[00:00:17.730,285] <inf> Provisioning: Attempting to connect to server...
[00:00:17.731,048] <err> net_arp: Gateway not set for iface 0x20002718
[00:00:18.425,598] <err> net_arp: Gateway not set for iface 0x20002718
[00:00:19.119,750] <err> net_arp: Gateway not set for iface 0x20002718
[00:00:19.813,903] <err> net_arp: Gateway not set for iface 0x20002718
[00:00:20.508,056] <err> net_arp: Gateway not set for iface 0x20002718

This error is occurring.

Is there any additional data to refer to??

The sdk you are using is v2.8.0

  • Hello,

    We are testing nrf5340 - nrf7002 using the example of blpovisioning.

    Do you have a link to the example source code or documentation?

    Best regards,

    Maria

  • main.c

    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(Provisioning, CONFIG_LOG_DEFAULT_LEVEL);
    
    #include <stdlib.h>
    
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/i2c.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/drivers/mfd/npm1300.h>
    #include <zephyr/drivers/sensor.h>
    #include <zephyr/drivers/led.h>
    
    #include "Algo/TCP_Client.h"
    #include "Algo/Provisioning.h"
    #include "Algo/ADC.h"
    #include "Algo/fuel_gauge.h"
    
    #include "Algo/deviceInformation.h"
    
    #define SLEEP_TIME_MS 1000
    
    static const struct device *pmic = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_pmic));
    static const struct device *charger = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_charger));
    static const struct device *leds = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_leds));
    static volatile bool vbus_connected;
    
    #define NPM1300_CHARGER_BASE        0x03U
    #define REG_BCHGDISABLESET_OFFSET   0x6
    #define BCHGDISABLE_NTC_MASK        BIT(1)
    
    // VBUS 관련 레지스터 주소 정의
    #define NPM1300_VBUS_BASE           0x02U       // VBUS 베이스 주소
    #define VBUS_OFFSET_STATUS          0x07U       // VBUS 상태 플래그가 포함된 오프셋
    
    // VBUSINSTATUS 레지스터의 비트 정의
    #define VBUS_DETECTED_BIT     (1 << 0)  // Bit 0: VBUS detected
    #define VBUS_OVERVOLTAGE_BIT  (1 << 2)  // Bit 2: Overvoltage protection active
    #define VBUS_UNDERVOLTAGE_BIT (1 << 3)  // Bit 3: Undervoltage detected
    
    // SHIP Mode Base Address
    #define SHIP_MODE_BASE       0x0BU
    
    // SHIP Mode 관련 레지스터 오프셋
    #define TASKENTERSHIPMODE    0x02U  // Ship Mode 진입 명령
    
    
    // Button
    #define POWER_ON_THRESHOLD_MS 3000  // 3초 이상 눌릴 때 POWER ON 로그
    #define LONG_PRESS_THRESHOLD_MS 7000 // 7초 이상 눌릴 때 LONG PRESS 로그
    
    /** 🟢 `button0`을 DT_NODELABEL로 정의 */
    static const struct gpio_dt_spec button0 = GPIO_DT_SPEC_GET_OR(DT_NODELABEL(button0), gpios, {0});
    static struct gpio_callback button_cb_data;
    static struct k_timer button_timer;
    
    volatile bool button_pressed = false;
    static bool power_on_logged = false;  // 3초 로그 중복 방지
    static bool long_press_logged = false;  // 7초 로그 중복 방지
    static int64_t button_press_start_time = 0;  // 버튼이 눌린 시작 시간
    
    //Power Mode
    #define Power_Default           0
    #define Power_Off           1
    #define Power_On            2
    #define Power_DeepSleep     3
    #define Power_LightSleep    4
    
    static int powerMode = Power_Default;
    
    bool poweron_initialized = false;
    bool poweroff_initialized = false;
    
    /** 🔥 버튼이 3초, 7초 이상 눌린 경우 실행되는 콜백 */
    void button_hold_check(struct k_timer *timer_id) {
        if (button_pressed) {
            int64_t elapsed_time = k_uptime_get() - button_press_start_time;
    
            if (elapsed_time >= POWER_ON_THRESHOLD_MS && !power_on_logged) {
                LOG_INF("⚡ POWER ON! Button held for %d ms", POWER_ON_THRESHOLD_MS);
                power_on_logged = true;
            }
            
            if (elapsed_time >= LONG_PRESS_THRESHOLD_MS && !long_press_logged) {
                LOG_INF("🔴 LONG PRESS DETECTED (Button held for %d ms)", LONG_PRESS_THRESHOLD_MS);
                long_press_logged = true;
            }
        }
    }
    
    /** 🟢 버튼 인터럽트 핸들러 */
    static void button_event_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins) {
        if (pins & BIT(button0.pin)) {
            int val = gpio_pin_get_dt(&button0);
    
            if (val) {
                /* 🟢 버튼이 눌렸을 때 */
                button_pressed = true;
                power_on_logged = false;
                long_press_logged = false;
                button_press_start_time = k_uptime_get();  // 버튼이 눌린 시간 기록
                LOG_INF("🔵 Button Pressed! Timer Started...");
                k_timer_start(&button_timer, K_MSEC(100), K_MSEC(100));  // 100ms마다 체크
    
            } else {
                /* ⚫ 버튼이 떼어졌을 때 */
                button_pressed = false;
                k_timer_stop(&button_timer);
                LOG_INF("⚫ Button Released! Timer Reset.");
    
                if((power_on_logged == true) && ((powerMode == Power_Off) || (powerMode == Power_Default)))
                {
                    LOG_INF("       POWER ON       ");
                    powerMode = Power_On;
                }
                else if((power_on_logged == true) && (powerMode == Power_On))
                {
                    LOG_INF("       POWER OFF       ");
                    powerMode = Power_Off;
                }
            }
        }
    }
    
    /** 🟢 버튼 초기화 함수 */
    void button_init(void) {
        int ret;
    
        if (!gpio_is_ready_dt(&button0)) {
            LOG_ERR("Error: Button device %s is not ready", button0.port->name);
            return;
        }
    
        ret = gpio_pin_configure_dt(&button0, GPIO_INPUT);
        if (ret != 0) {
            LOG_ERR("Error %d: Failed to configure button pin", ret);
            return;
        }
    
        /* 🟢 눌릴 때와 뗄 때 모두 인터럽트 발생 */
        ret = gpio_pin_interrupt_configure_dt(&button0, GPIO_INT_EDGE_BOTH);
        if (ret != 0) {
            LOG_ERR("Error %d: Failed to configure interrupt on button", ret);
            return;
        }
    
        gpio_init_callback(&button_cb_data, button_event_callback, BIT(button0.pin));
        gpio_add_callback(button0.port, &button_cb_data);
    
        /* 타이머 초기화 */
        k_timer_init(&button_timer, button_hold_check, NULL);
    
        LOG_INF("Button initialized successfully");
    }
    
    // SHIP Mode 진입 함수
    int enter_ship_mode(void) {
        int ret = mfd_npm1300_reg_write(pmic, SHIP_MODE_BASE, TASKENTERSHIPMODE, 1U);
        if (ret == 0) {
            printf("Device is entering Ship Mode...\n");
        } else {
            printf("Failed to enter Ship Mode. Error: %d\n", ret);
        }
    }
    
    
    // VBUS 상태 확인 함수
    int check_vbus_status(void) {
        int ret;
        uint8_t vbus_status;
    
        // VBUS 상태 레지스터 읽기
        ret = mfd_npm1300_reg_read(pmic, NPM1300_VBUS_BASE, VBUS_OFFSET_STATUS, &vbus_status);
        if (ret != 0) {
            return ret; // 읽기 실패 시 오류 코드 반환
        }
    
        // VBUS 상태 출력
        if (vbus_status & VBUS_DETECTED_BIT) {
            printf("VBUS detected.\n");
            vbus_connected = true;
        } else {
            printf("VBUS not detected.\n");
            vbus_connected = false;
        }
    
        if (vbus_status & VBUS_OVERVOLTAGE_BIT) {
            printf("VBUS overvoltage detected.\n");
        }
    
        if (vbus_status & VBUS_UNDERVOLTAGE_BIT) {
            printf("VBUS undervoltage detected.\n");
        }
    }
    
    
    /** 🔧 NTC 체크 비활성화 */
    void disable_ntc_check(void) {
        int ret;
        uint8_t read_val = 0;
    
        uint8_t val = read_val | BCHGDISABLE_NTC_MASK;
        ret = mfd_npm1300_reg_write(pmic, NPM1300_CHARGER_BASE, REG_BCHGDISABLESET_OFFSET, val);
        if (ret < 0) {
            LOG_ERR("ERROR: Failed to write BCHGDISABLESET! (ret=%d)", ret);
            return;
        }
    
        LOG_INF("NTC check disable command sent.");
    }
    
    
    int main( void ) {
    	int err;
    	LOG_INF("npm1300 fuel gauge\n");
    
        if (!device_is_ready(pmic)) {
    		LOG_INF("Pmic device not ready.\n");
    		return 0;
    	}
    
    	if (!device_is_ready(charger)) {
    		LOG_INF("Charger device not ready.\n");
    		return 0;
    	}
    
    	if (fuel_gauge_init(charger) < 0) {
    		LOG_INF("Could not initialise fuel gauge.\n");
    		return 0;
    	}
    
        if (!device_is_ready(leds)) {
    		printk("Error: led device is not ready\n");
    		return 0;
    	}
    
    	static struct gpio_callback event_cb;
    
    	err = mfd_npm1300_add_callback(pmic, &event_cb);
    	if (err) {
    		LOG_INF("Failed to add pmic callback.\n");
    		return 0;
    	}
    
    	/* ✅ 초기 설정 */
        disable_ntc_check();  // 🔹 NTC 체크 비활성화
        button_init();  // 🔹 버튼 초기화
    
    	LOG_INF("SC50 device ok\n");
    
        // led_on(leds, 0U);
        // led_on(leds, 1U);
        led_off(leds, 1U);
    
        // ship mode 들어감감
        // check_vbus_status();
        // if(vbus_connected != true) enter_ship_mode();
    
    	while (1) {
    
            
            if(powerMode == Power_On)
            {
                // LOG_INF("--------------------------------------------------------");
                poweroff_initialized = false;
    
                if(poweron_initialized == false)
                {
                    poweron_initialized = true;
    
                    Task_Provisioning_Init();
                    Task_TCP_Client_Init();
                    Task_ADC_Init();
                }
    
                /* 🔄 주기적으로 상태 확인 */
                // check_vbus_status();
                // fuel_gauge_update(charger, vbus_connected);
            }
            else if(powerMode == Power_Off)
            {
                LOG_INF("Power Off___---");
                poweron_initialized = false;
    
                if(poweroff_initialized == false)
                {
                    poweroff_initialized = true;
    
                    Task_ADC_Delete();
                    Task_TCP_Client_Delete();
                    Task_Provisioning_Delete();
                }
            }
            else if(powerMode == Power_DeepSleep)
            {
    
            }
            else if(powerMode == Power_LightSleep)
            {
    
            }
    
                k_msleep(SLEEP_TIME_MS);
            }
    
    	k_sleep( K_FOREVER );
    }

    Provisioning.c

    #include <zephyr/logging/log.h>
    LOG_MODULE_DECLARE(Provisioning, LOG_LEVEL_DBG);
    
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <string.h>
    #include <errno.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/kernel.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    
    #include <zephyr/net/wifi.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <net/wifi_credentials.h>
    #include <net/wifi_mgmt_ext.h>
    
    #include <bluetooth/services/wifi_provisioning.h>
    
    #include "Provisioning.h"
    #include "deviceInformation.h"
    
    tContext context;
    
    static struct k_thread ProvisioningThread;
    #define Provisioning_STACK_SIZE 8*1024
    #define Provisioning_PRIORITY 2
    K_THREAD_STACK_DEFINE(PROVISIONING_STACK, Provisioning_STACK_SIZE);
    static bool provisioning_thread_running = false;
    
    
    #ifdef CONFIG_WIFI_PROV_ADV_DATA_UPDATE
    #define ADV_DATA_UPDATE_INTERVAL      CONFIG_WIFI_PROV_ADV_DATA_UPDATE_INTERVAL
    #endif /* CONFIG_WIFI_PROV_ADV_DATA_UPDATE */
    
    #define ADV_PARAM_UPDATE_DELAY        1
    
    #define ADV_DATA_VERSION_IDX          (BT_UUID_SIZE_128 + 0)
    #define ADV_DATA_FLAG_IDX             (BT_UUID_SIZE_128 + 1)
    #define ADV_DATA_FLAG_PROV_STATUS_BIT BIT(0)
    #define ADV_DATA_FLAG_CONN_STATUS_BIT BIT(1)
    #define ADV_DATA_RSSI_IDX             (BT_UUID_SIZE_128 + 3)
    
    #define PROV_BT_LE_ADV_PARAM_FAST BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE, \
    						BT_GAP_ADV_FAST_INT_MIN_2, \
    						BT_GAP_ADV_FAST_INT_MAX_2, NULL)
    
    #define PROV_BT_LE_ADV_PARAM_SLOW BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE, \
    						BT_GAP_ADV_SLOW_INT_MIN, \
    						BT_GAP_ADV_SLOW_INT_MAX, NULL)
    
    #define ADV_DAEMON_STACK_SIZE 4096
    #define ADV_DAEMON_PRIORITY 5
    
    K_THREAD_STACK_DEFINE(adv_daemon_stack_area, ADV_DAEMON_STACK_SIZE);
    
    static struct k_work_q adv_daemon_work_q;
    
    static uint8_t device_name[] = {'P', 'V', '0', '0', '0', '0', '0', '0'};
    
    static uint8_t prov_svc_data[] = {BT_UUID_PROV_VAL, 0x00, 0x00, 0x00, 0x00};
    
    static const struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_PROV_VAL),
    	BT_DATA(BT_DATA_NAME_COMPLETE, device_name, sizeof(device_name)),
    };
    
    static const struct bt_data sd[] = {
    	BT_DATA(BT_DATA_SVC_DATA128, prov_svc_data, sizeof(prov_svc_data)),
    };
    
    static struct k_work_delayable update_adv_param_work;
    static struct k_work_delayable update_adv_data_work;
    
    static void restart_network_interface(void) {
        struct net_if *iface = net_if_get_default();
    
        if (!iface) {
            printk("❌ No network interface found!\n");
            return;
        }
    
        printk("🔄 Restarting network interface...\n");
    
        net_if_down(iface);
        k_sleep(K_MSEC(500));  
        net_dhcpv4_stop(iface);
        net_if_up(iface);
        k_sleep(K_MSEC(500));
        net_dhcpv4_start(iface);
    
        printk("✅ Network interface restarted successfully.\n");
    }
    
    static void update_wifi_status_in_adv(void)
    {
    	int rc;
    	struct net_if *iface = net_if_get_default();
    	struct wifi_iface_status status = { 0 };
    
    	prov_svc_data[ADV_DATA_VERSION_IDX] = PROV_SVC_VER;
    
    	/* If no config, mark it as unprovisioned. */
    	if (!bt_wifi_prov_state_get()) {
            printk("No Wi-Fi provisioning data available.\n");
    		prov_svc_data[ADV_DATA_FLAG_IDX] &= ~ADV_DATA_FLAG_PROV_STATUS_BIT;
    
            memset(&status, 0, sizeof(status));
    	} else {
            printk("Wi-Fi provisioning data found.\n");
    		prov_svc_data[ADV_DATA_FLAG_IDX] |= ADV_DATA_FLAG_PROV_STATUS_BIT;
    	}
    
    	rc = net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &status,
    				sizeof(status));
    	/* If WiFi is not connected or error occurs, mark it as not connected. */
    	if ((rc != 0) || (status.state < WIFI_STATE_ASSOCIATED)) {
    		context.connected = false;
            printk("Failed to get Wi-Fi status (err %d). Assuming no connection.\n", rc);
    		prov_svc_data[ADV_DATA_FLAG_IDX] &= ~ADV_DATA_FLAG_CONN_STATUS_BIT;
    		prov_svc_data[ADV_DATA_RSSI_IDX] = INT8_MIN;
    	} else if (status.state < WIFI_STATE_ASSOCIATED) {
            printk("Wi-Fi not connected.\n");
    		context.connected = false;
            prov_svc_data[ADV_DATA_FLAG_IDX] &= ~ADV_DATA_FLAG_CONN_STATUS_BIT;
            prov_svc_data[ADV_DATA_RSSI_IDX] = INT8_MIN;
        } else {
            context.connected = true;
            /* Log retrieved Wi-Fi credentials */
            printk("Wi-Fi Status : Wi-Fi connected.\n");
            printk("SSID: %s\n", status.ssid[0] ? status.ssid : "N/A");
            printk("State: %d\n", status.state);
            printk("RSSI: %d dBm\n", status.rssi);
            printk("Channel: %d\n", status.channel);
            printk("BSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",
               status.bssid[0], status.bssid[1], status.bssid[2],
               status.bssid[3], status.bssid[4], status.bssid[5]);
    		/* WiFi is connected. */
    		prov_svc_data[ADV_DATA_FLAG_IDX] |= ADV_DATA_FLAG_CONN_STATUS_BIT;
    		/* Currently cannot retrieve RSSI. Use a dummy number. */
    		prov_svc_data[ADV_DATA_RSSI_IDX] = status.rssi;
    	}
    }
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (err) {
    		printk("BT Connection failed (err 0x%02x).\n", err);
    		return;
    	}
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	printk("BT Connected: %s", addr);
    
    	k_work_cancel_delayable(&update_adv_data_work);
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	printk("BT Disconnected: %s (reason 0x%02x).\n", addr, reason);
    
    	k_work_reschedule_for_queue(&adv_daemon_work_q, &update_adv_param_work,
    				K_SECONDS(ADV_PARAM_UPDATE_DELAY));
    	k_work_reschedule_for_queue(&adv_daemon_work_q, &update_adv_data_work, K_NO_WAIT);
    }
    
    static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
    				const bt_addr_le_t *identity)
    {
    	char addr_identity[BT_ADDR_LE_STR_LEN];
    	char addr_rpa[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(identity, addr_identity, sizeof(addr_identity));
    	bt_addr_le_to_str(rpa, addr_rpa, sizeof(addr_rpa));
    
    	printk("BT Identity resolved %s -> %s.\n", addr_rpa, addr_identity);
    }
    
    static void security_changed(struct bt_conn *conn, bt_security_t level,
    				enum bt_security_err err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (!err) {
    		printk("BT Security changed: %s level %u.\n", addr, level);
    	} else {
    		printk("BT Security failed: %s level %u err %d.\n", addr, level,
    			   err);
    	}
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected = connected,
    	.disconnected = disconnected,
    	.identity_resolved = identity_resolved,
    	.security_changed = security_changed,
    };
    
    static void auth_cancel(struct bt_conn *conn)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("BT Pairing cancelled: %s.\n", addr);
    }
    
    static struct bt_conn_auth_cb auth_cb_display = {
    	.cancel = auth_cancel,
    };
    
    static void pairing_complete(struct bt_conn *conn, bool bonded)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	printk("BT pairing completed: %s, bonded: %d\n", addr, bonded);
    }
    
    static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
    {
    	printk("BT Pairing Failed (%d). Disconnecting.\n", reason);
    	bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
    }
    
    static struct bt_conn_auth_info_cb auth_info_cb_display = {
    
    	.pairing_complete = pairing_complete,
    	.pairing_failed = pairing_failed,
    };
    
    static void update_adv_data_task(struct k_work *item)
    {
    	int rc;
    
    	update_wifi_status_in_adv();
    	rc = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
    	if (rc != 0) {
    		printk("Cannot update advertisement data, err = %d\n", rc);
    	}
    #ifdef CONFIG_WIFI_PROV_ADV_DATA_UPDATE
    	k_work_reschedule_for_queue(&adv_daemon_work_q, &update_adv_data_work,
    				K_SECONDS(ADV_DATA_UPDATE_INTERVAL));
    #endif /* CONFIG_WIFI_PROV_ADV_DATA_UPDATE */
    }
    
    static void update_adv_param_task(struct k_work *item)
    {
    	int rc;
    
    	rc = bt_le_adv_stop();
    	if (rc != 0) {
    		printk("Cannot stop advertisement: err = %d\n", rc);
    		return;
    	}
    
    	rc = bt_le_adv_start(prov_svc_data[ADV_DATA_FLAG_IDX] & ADV_DATA_FLAG_PROV_STATUS_BIT ?
    		PROV_BT_LE_ADV_PARAM_SLOW : PROV_BT_LE_ADV_PARAM_FAST,
    		ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
    	if (rc != 0) {
    		printk("Cannot start advertisement: err = %d\n", rc);
    	}
    }
    
    static void byte_to_hex(char *ptr, uint8_t byte, char base)
    {
    	int i, val;
    
    	for (i = 0, val = (byte & 0xf0) >> 4; i < 2; i++, val = byte & 0x0f) {
    		if (val < 10) {
    			*ptr++ = (char) (val + '0');
    		} else {
    			*ptr++ = (char) (val - 10 + base);
    		}
    	}
    }
    
    static void update_dev_name(struct net_linkaddr *mac_addr)
    {
    	byte_to_hex(&device_name[2], mac_addr->addr[3], 'A');
    	byte_to_hex(&device_name[4], mac_addr->addr[4], 'A');
    	byte_to_hex(&device_name[6], mac_addr->addr[5], 'A');
    }
    
    
    static void print_credential(void *cb_arg, const char *ssid, size_t ssid_len)
    {
        struct wifi_credentials_personal creds;
        int ret;
    
        memset(&creds, 0, sizeof(creds));
    
        ret = wifi_credentials_get_by_ssid_personal_struct(ssid, ssid_len, &creds);
        if (ret == 0) {
            printk("-------------------------------\n");
            printk("Stored Wi-Fi Credential:\n");
            printk("SSID: %s\n", creds.header.ssid);
            printk("Security Type: %d\n", creds.header.type);
            printk("Password: %s\n", creds.password);
        } else {
            printk("Failed to retrieve credentials for SSID: %s (error: %d)\n", ssid, ret);
        }
    }
    
    static void log_stored_wifi_credentials(void)
    {
        if (wifi_credentials_is_empty()) {
            printk("No stored Wi-Fi credentials found.\n");
        } else {
            wifi_credentials_for_each_ssid(print_credential, NULL);
        }
    }
    
    
    void disconnect_wifi(void) {
        struct net_if *iface = net_if_get_default();
        int rc = net_mgmt(NET_REQUEST_WIFI_DISCONNECT, iface, NULL, 0);
    
        if (rc == 0) {
            printk("Wi-Fi disconnected successfully.\n");
    
    		context.connected = false;
    		
            printk("✅ Bluetooth disabled.\n");
        } else {
            printk("Failed to disconnect Wi-Fi (err: %d)\n", rc);
        }
    }
    static void disconnect_callback(struct bt_conn *conn, void *data) {
        int err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
        if (err) {
            printk("⚠️ Failed to disconnect BLE connection (err %d)\n", err);
        } else {
            printk("✅ BLE connection disconnected.\n");
        }
        bt_conn_unref(conn);  // 연결 해제
    }
    
    void Task_Provisioning_Delete( void ){
        printk("🔴 Task_Provisioning_Delete: Stopping Bluetooth and Wi-Fi.\n");
    
        /* ✅ Wi-Fi 연결 해제 */
        disconnect_wifi();
    
        /* ✅ Work Queue에서 실행 중인 작업 취소 */
        k_work_cancel_delayable(&update_adv_param_work);
        k_work_cancel_delayable(&update_adv_data_work);
        printk("✅ Work queue tasks canceled.\n");
    
        /* ✅ Bluetooth 광고 및 연결 중단 */
        bt_le_adv_stop();
        printk("✅ Bluetooth advertising stopped.\n");
    
        /* ✅ 모든 Bluetooth 연결을 끊음 */
        bt_conn_foreach(BT_CONN_TYPE_ALL, disconnect_callback, NULL);
        k_sleep(K_MSEC(500));  // 안정적인 연결 해제 대기
    
        /* ✅ HCI Reset 수행 (강제 리셋) */
        // struct net_buf *rsp = NULL;
        // int err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, &rsp);
        // if (err) {
        //     printk("⚠️ HCI Reset failed (err %d)\n", err);
        // } else {
        //     printk("✅ HCI Reset successful.\n");
        // }
        // if (rsp) {
        //     net_buf_unref(rsp);
        // }
        // k_sleep(K_MSEC(500)); // HCI Reset 후 안정적인 상태 대기
        nrf_reset_network_force_off();
        /* ✅ BLE 기능 완전히 종료 */
        err = bt_disable();
        if (err) {
            printk("⚠️ Bluetooth disable failed (err %d)\n", err);
        } else {
            printk("✅ Bluetooth disabled successfully.\n");
        }
        k_sleep(K_MSEC(1000)); // Bluetooth 리소스 완전히 해제 대기
    
        /* ❌ `bt_hci_driver_unregister()` 호출 제거 → Zephyr에서 제공되지 않음 */
    
        
    
        /* ✅ Provisioning 쓰레드 중단 */
        if (provisioning_thread_running) {
            k_thread_abort(&ProvisioningThread);
            provisioning_thread_running = false;
            printk("✅ Provisioning thread aborted.\n");
        }
    
        // printk("🔴 Task_Provisioning_Delete: Stopping Bluetooth advertising and Wi-Fi.\n");
    
        // /* ✅ Work Queue에서 실행 중인 작업 취소 */
        // k_work_cancel_delayable(&update_adv_param_work);
        // k_work_cancel_delayable(&update_adv_data_work);
        // printk("✅ Work queue tasks canceled.\n");
    
        // /* ✅ Bluetooth 광고 중단 */
        // int rc = bt_le_adv_stop();
        // if (rc) {
        //     printk("⚠️ Bluetooth advertising stop failed (err %d)\n", rc);
        // } else {
        //     printk("✅ Bluetooth advertising stopped.\n");
        // }
    
        // /* ✅ Wi-Fi 연결 해제 */
        // disconnect_wifi();
    
        // /* ✅ 기존의 Bluetooth 연결을 모두 끊음 */
        // uint8_t reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN;
        // bt_conn_foreach(BT_CONN_TYPE_ALL, disconnect_callback, &reason);
        // k_sleep(K_MSEC(200)); // 안정적인 연결 해제 대기
    
        // /* ❌ bt_disable() 제거 */
    
        // printk("✅ Task_Provisioning_Delete completed.\n");
    
        // printk("Task_Provisioning_Delete\n");
    
        // /* ✅ Work Queue에서 실행 중인 작업 취소 */
        // k_work_cancel_delayable(&update_adv_param_work);
        // k_work_cancel_delayable(&update_adv_data_work);
        // printk("✅ Work queue tasks canceled.\n");
    	
        // /* ✅ Bluetooth 광고 중단 */
        // bt_le_adv_stop();
        // printk("✅ Bluetooth advertising stopped.\n");
    
        // /* ✅ Wi-Fi 연결 해제 */
        // disconnect_wifi();
    
        // /* ✅ Bluetooth 종료 (필요한 경우) */
        // bt_disable();
        // k_sleep(K_MSEC(500));  // Bluetooth 종료 후 안정적인 상태로 대기
        // printk("✅ Bluetooth disabled.\n");
    
        // /* ✅ Provisioning 쓰레드 중단 */
        // k_thread_abort(&ProvisioningThread);
        // printk("✅ Provisioning thread aborted.\n");
    };
    
    
    int Provisioning(void)
    {
        // int rc;
        // struct net_if *iface = net_if_get_default();
        // struct net_linkaddr *mac_addr = net_if_get_link_addr(iface);
        // char device_name_str[sizeof(device_name) + 1];
    
        // /* Sleep 1 second to allow initialization of Wi-Fi driver */
        // k_sleep(K_SECONDS(1));
    
        // bt_conn_auth_cb_register(&auth_cb_display);
        // bt_conn_auth_info_cb_register(&auth_info_cb_display);
    
        // /* ✅ Bluetooth가 이미 활성화된 경우 `bt_enable()`을 실행하지 않음 */
        // if (!bt_is_ready()) {  
        //     int retry = 0;
        //     while (retry < 3) {
        //         rc = bt_enable(NULL);
        //         if (rc == 0) {
        //             printk("✅ Bluetooth initialized successfully.\n");
        //             break;
        //         } else if (rc == -11) {
        //             printk("⚠️ bt_enable() failed with -11. Retrying...\n");
        //             k_sleep(K_MSEC(500));  // 500ms 대기 후 재시도
        //         } else {
        //             printk("❌ Bluetooth init failed (err %d)\n", rc);
        //             return 0;
        //         }
        //         retry++;
        //     }
    
        //     if (rc != 0) {
        //         printk("❌ Bluetooth initialization failed after retries.\n");
        //         return 0;
        //     }
        // } else {
        //     printk("✅ Bluetooth is already initialized. Skipping bt_enable().\n");
        // }
    
        // /* ✅ Wi-Fi Provisioning Service 초기화 */
        // rc = bt_wifi_prov_init();
        // if (rc == 0) {
        //     printk("✅ Wi-Fi provisioning service started successfully.\n");
        // } else {
        //     printk("❌ Error initializing Wi-Fi provisioning service.\n");
        //     return 0;
        // }
    
        // /* ✅ Bluetooth Device Name 설정 */
        // if (mac_addr) {
        //     update_dev_name(mac_addr);
        // }
        // device_name_str[sizeof(device_name_str) - 1] = '\0';
        // memcpy(device_name_str, device_name, sizeof(device_name));
        // bt_set_name(device_name_str);
    
        // /* ✅ Bluetooth Advertising 시작 */
        // rc = bt_le_adv_start(prov_svc_data[ADV_DATA_FLAG_IDX] & ADV_DATA_FLAG_PROV_STATUS_BIT ?
        //     PROV_BT_LE_ADV_PARAM_SLOW : PROV_BT_LE_ADV_PARAM_FAST,
        //     ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
        
        // if (rc) {
        //     printk("❌ BT Advertising failed to start (err %d)\n", rc);
        //     return 0;
        // }
        // printk("✅ BT Advertising successfully started.\n");
    
        // /* ✅ Wi-Fi 상태 업%EB%8D%B0이트 */
        // update_wifi_status_in_adv();
    
        // return 0;
    	
        int rc;
        struct net_if *iface = net_if_get_default();
        struct net_linkaddr *mac_addr = net_if_get_link_addr(iface);
        char device_name_str[sizeof(device_name) + 1];
    
        /* Sleep 1 second to allow initialization of Wi-Fi driver */
        k_sleep(K_SECONDS(1));
    
        bt_conn_auth_cb_register(&auth_cb_display);
        bt_conn_auth_info_cb_register(&auth_info_cb_display);
    
        /* ✅ IPC(HCI) 상태 확인 후 Bluetooth 활성화 */
        // int retry = 0;
        // while (retry < 3) {
        //     rc = bt_enable(NULL);
        //     if (rc == 0) {
        //         printk("✅ Bluetooth initialized successfully.\n");
        //         break;
        //     } else if (rc == -11) {
        //         printk("⚠️ bt_enable() failed with -11. Retrying...\n");
        //         k_sleep(K_MSEC(500));  // 500ms 대기 후 재시도
        //     } else {
        //         printk("❌ Bluetooth init failed (err %d)\n", rc);
        //         return 0;
        //     }
        //     retry++;
        // }
    
        // if (rc != 0) {
        //     printk("❌ Bluetooth initialization failed after retries.\n");
        //     return 0;
        // }
    
        /* ✅ Wi-Fi Provisioning Service 초기화 */
        rc = bt_wifi_prov_init();
        if (rc == 0) {
            printk("✅ Wi-Fi provisioning service started successfully.\n");
        } else {
            printk("❌ Error initializing Wi-Fi provisioning service.\n");
            return 0;
        }
    
        /* ✅ Bluetooth Device Name 설정 */
        if (mac_addr) {
            update_dev_name(mac_addr);
        }
        device_name_str[sizeof(device_name_str) - 1] = '\0';
        memcpy(device_name_str, device_name, sizeof(device_name));
        bt_set_name(device_name_str);
    
        /* ✅ Bluetooth Advertising 시작 */
        rc = bt_le_adv_start(prov_svc_data[ADV_DATA_FLAG_IDX] & ADV_DATA_FLAG_PROV_STATUS_BIT ?
            PROV_BT_LE_ADV_PARAM_SLOW : PROV_BT_LE_ADV_PARAM_FAST,
            ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
        
        if (rc) {
            printk("❌ BT Advertising failed to start (err %d)\n", rc);
            return 0;
        }
        printk("✅ BT Advertising successfully started.\n");
    
        /* ✅ Wi-Fi 상태 업데이트 */
        update_wifi_status_in_adv();
    
        /* ✅ Work Queue 설정 */
        k_work_queue_init(&adv_daemon_work_q);
        k_work_queue_start(&adv_daemon_work_q, adv_daemon_stack_area,
            K_THREAD_STACK_SIZEOF(adv_daemon_stack_area), ADV_DAEMON_PRIORITY,
            NULL);
    
        k_work_init_delayable(&update_adv_param_work, update_adv_param_task);
        k_work_init_delayable(&update_adv_data_work, update_adv_data_task);
    
    #ifdef CONFIG_WIFI_PROV_ADV_DATA_UPDATE
        k_work_schedule_for_queue(&adv_daemon_work_q, &update_adv_data_work,
            K_SECONDS(ADV_DATA_UPDATE_INTERVAL));
    #endif /* CONFIG_WIFI_PROV_ADV_DATA_UPDATE */
    
        /* ✅ 저장된 Wi-Fi Credentials 적용 */
        net_mgmt(NET_REQUEST_WIFI_CONNECT_STORED, iface, NULL, 0);
    
        /* ✅ DHCP Hostname 설정 */
        char *hostname = "SC50_rev1";
        rc = net_hostname_set(hostname, strlen(hostname));
        if (rc < 0) {
            printk("❌ Failed to set hostname: %d\n", rc);
        } else {
            printk("✅ Hostname set to: %s\n", hostname);
        }
    
        /* ✅ 저장된 Wi-Fi Credentials 로그 출력 */
        log_stored_wifi_credentials();
    
        return 0;
    }
    
    
    
    /*! Task_ADC_Init initializes the task ADC
    *
    * @brief ADC initialization
    */
    void Task_Provisioning_Init( void ){
        if (provisioning_thread_running) {
            printk("⚠️ Provisioning thread already running. Skipping init.\n");
            return;
        }
    
        printk("Task_Provisioning_Init\n");
    
        /* ✅ Provisioning 쓰레드 실행 중 상태 설정 */
        provisioning_thread_running = true;
    
        /* ✅ Bluetooth가 이미 활성화된 경우 실행하지 않음 */
        if (!bt_is_ready()) {  
            int retry = 0;
            int rc;
            while (retry < 3) {
                rc = bt_enable(NULL);
                if (rc == 0) {
                    printk("✅ Bluetooth initialized successfully.\n");
                    break;
                } else if (rc == -11) {
                    printk("⚠️ bt_enable() failed with -11. Retrying... (Attempt %d)\n", retry + 1);
                    k_sleep(K_MSEC(1000));  // 1초 대기 후 재시도
                } else {
                    printk("❌ Bluetooth init failed (err %d)\n", rc);
                    provisioning_thread_running = false; // 초기화 실패 시 다시 실행 가능하도록 설정
                    return;
                }
                retry++;
            }
    
            if (rc != 0) {
                printk("❌ Bluetooth initialization failed after retries.\n");
                provisioning_thread_running = false;
                return;
            }
        } else {
            printk("✅ Bluetooth is already initialized. Skipping bt_enable().\n");
        }
    
    	k_thread_create	(														
    					&ProvisioningThread,										
    					PROVISIONING_STACK,										
    					Provisioning_STACK_SIZE,									
    					(k_thread_entry_t)Provisioning,							
    					NULL,													
    					NULL,													
    					NULL,													
    					Provisioning_PRIORITY,									
    					0,														
    					K_NO_WAIT);	
    
    	 k_thread_name_set(&ProvisioningThread, "Provisioning");
    	 k_thread_start(&ProvisioningThread);
    };

     

    TcpClient.c

    #include <zephyr/logging/log.h>
    LOG_MODULE_DECLARE( Provisioning, CONFIG_LOG_DEFAULT_LEVEL );
    
    #include <zephyr/kernel.h>
    #include <errno.h>
    #include <stdio.h>
    
    //#include <arpa/inet.h>
    #include <zephyr/net/socket.h>
    #include <zephyr/net/net_if.h>
    #include <zephyr/net/net_ip.h>
    #include <unistd.h> 
    
    #include <zephyr/storage/flash_map.h>
    #include <zephyr/drivers/flash.h>
    
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>	
    
    #include "TCP_Client.h"
    #include "deviceInformation.h"
    #include "ADC.h"
    
    uint16_t *adc_fsr_converted = NULL;
    size_t adc_fsr_converted_size = 0;
    bool fsr_data_flag = false;
    
    //! Stack size for the TCP_CLIENT thread
    #define TCP_CLIENT_STACK_SIZE 2*1024
    //! TCP_CLIENT thread priority level
    #define TCP_CLIENT_PRIORITY 4
    //! Time in miliseconds to wait to send the TCP message since the board gets a
    // stable IP address
    #define TCP_CLIENT_WAIT_TO_SEND_MS 6000
    
    //! TCP Client stack definition
    K_THREAD_STACK_DEFINE(TCP_CLIENT_STACK, TCP_CLIENT_STACK_SIZE);
    //! Variable to identify the TCP Client thread
    static struct k_thread tcpClientThread;
    
    //! TCP message sent by the client.
    static uint8_t TCPClientMessage[] = {0xfb, 0xa4, 0xcf, 0x12, 0xa1, 0xe2, 0x6d, 0x53, 0x43, 0x53, 0x43, 0x35, 0x30, 0x41, 0x47, 0xff, 0xfe};
    
    //! Receiver buffer
    // static uint8_t receiverBuffer[20];
                                          
    static bool context_connected = false;  // Simulated context flag
    static bool send_flag = false;
    static bool packet_start = false;
    
    FdsData received_tcp_data = {0};  // TCP 데이터 저장 구조체
    bool received_tcp_data_flag = false;      // 새 데이터가 들어왔는지 체크하는 플래그
    
    // #define FLASH_DEVICE DT_LABEL(DT_NODELABEL(flash0))   // Flash Device 지정
    #define FLASH_DEVICE DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)) // ✅ 수정
    #define FLASH_STORAGE_OFFSET FLASH_AREA_OFFSET(storage)
    #define FLASH_STORAGE_SIZE   FLASH_AREA_SIZE(storage)
    
    
    // ✅ 기본값 (초기값 설정)
    #define DEFAULT_SPEED  0x64
    #define DEFAULT_AMP    0x80
    #define DEFAULT_SENS   0xFF
    #define DEFAULT_RES3   0x01
    
    static int tcpClientSocket = -1;  // ✅ TCP 소켓 핸들을 전역 변수로 선언
    
    
    // Flash에서 데이터 읽어오기
    void flash_load_data(void) {
        const struct device *flash_dev = FLASH_DEVICE;
        if (!device_is_ready(flash_dev)) {
            printk("Flash device not ready!\n");
            return;
        }
    
        // Flash에서 데이터 읽기
        int err = flash_read(flash_dev, FLASH_STORAGE_OFFSET, &received_tcp_data, sizeof(received_tcp_data));
    
        if (err != 0 || received_tcp_data.speed == 0xFFFFFFFF) {  // Flash 데이터가 없거나 초기화되지 않은 경우 // Falsh에 데이터가 없으면 기본적으로 0xFFFFFFFF으로 되어 있고, 구조체 첫번째 인자만 확인으로 판별할 수 있음
            printk("Flash data not found! Saving default values...\n");
    
            flash_save_data(0, DEFAULT_SPEED);
            flash_save_data(1, DEFAULT_AMP);
            flash_save_data(2, DEFAULT_SENS);
            flash_save_data(3, DEFAULT_RES3);
        } else {
            printk("Loaded Flash Data -> SPEED: %d, AMP: %d, SENS: %d, RES3: %d\n",
                   received_tcp_data.speed, received_tcp_data.amp, received_tcp_data.sens, received_tcp_data.res3);
        }
    }
    
    
    // Flash 데이터 저장
    void flash_save_data(int field, uint32_t value) {
        const struct device *flash_dev = FLASH_DEVICE;
        if (!device_is_ready(flash_dev)) {
            printk("Flash device not ready!\n");
            return;
        }
    
        // ✅ 특정 필드 값만 변경 (구조체 순서 기반)
        uint32_t *fields[] = {
            &received_tcp_data.speed,  // 0
            &received_tcp_data.amp,    // 1
            &received_tcp_data.sens,   // 2
            &received_tcp_data.res3    // 3
        };
    
        if (field < 0 || field >= (sizeof(fields) / sizeof(fields[0]))) {
            printk("Invalid field index: %d\n", field);
            return;
        }
    
        *fields[field] = value;
    
        // Flash에 기존 데이터 삭제 후 저장
        flash_erase(flash_dev, FLASH_STORAGE_OFFSET, FLASH_STORAGE_SIZE);
        int err = flash_write(flash_dev, FLASH_STORAGE_OFFSET, &received_tcp_data, sizeof(received_tcp_data));
    
        if (err != 0) {
            printk("Flash write failed: %d\n", err);
        } else {
            printk("Flash Saved Data -> SPEED: %d, AMP: %d, SENS: %d, RES3: %d\n",
                   received_tcp_data.speed, received_tcp_data.amp, received_tcp_data.sens, received_tcp_data.res3);
        }
    }
    
    
    void close_socket(int *socket_fd) {
        if (*socket_fd >= 0) {
            shutdown(*socket_fd, SHUT_RDWR);  // 소켓 완전 종료
            k_msleep(100);  // 소켓 정리 후 약간의 대기
            close(*socket_fd);
            *socket_fd = -1;
            LOG_INF("Socket closed.");
        }
    }
    
    
    void configure_static_ip(void) {
        struct net_if *iface = net_if_get_default();
        struct in_addr my_ip, netmask, gateway;
    
        LOG_INF("Configuring static IP address...");
    
        if (net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &my_ip) < 0) {
            LOG_ERR("Invalid IP address format");
            return;
        }
        if (net_addr_pton(AF_INET, "255.255.255.0", &netmask) < 0) {
            LOG_ERR("Invalid netmask format");
            
            return;
        }
        if (net_addr_pton(AF_INET, "192.168.1.1", &gateway) < 0) {
            LOG_ERR("Invalid gateway format");
            return;
        }
    
        net_if_ipv4_addr_add(iface, &my_ip, NET_ADDR_MANUAL, 0);
        net_if_ipv4_set_netmask(iface, &netmask);
        net_if_ipv4_set_gw(iface, &gateway);
    
        LOG_INF("Static IP address configured: %s", CONFIG_NET_CONFIG_MY_IPV4_ADDR);
        context_connected = true;
    }
    
    
    #define RECEIVER_BUFFER_SIZE 8192  // 최대 8KB 설정
    static uint8_t receiverBuffer[RECEIVER_BUFFER_SIZE];
    
    void receive_server_data(int tcpClientSocket) {
        uint16_t receivepacket_size = 0;
        struct pollfd fds = {
            .fd = tcpClientSocket,
            .events = POLLIN,
        };
    
        int poll_result = poll(&fds, 1, 5000);  // 타임아웃 5초
        if (poll_result < 0) {
            LOG_ERR("Poll error: %d (%s)", errno, strerror(errno));
            return;
        }
    
        if (poll_result > 0 && (fds.revents & POLLIN)) 
        {
            int receivedBytes = recv(tcpClientSocket, receiverBuffer, sizeof(receiverBuffer), 0);
            // int receivedBytes = recv(tcpClientSocket, receiverBuffer, MIN(RECEIVER_BUFFER_SIZE, 2048), 0);
    
            if (receivedBytes > 0) 
            {
                LOG_INF("Received data length: %d", receivedBytes);
                for (int i = 0; i < receivedBytes; i++) {
                    // LOG_INF("Received data[%d]: %x", i, receiverBuffer[i]);
                }
    
                receivepacket_size = ((uint32_t)receiverBuffer[0]        |
                                     ((uint32_t)receiverBuffer[1] << 8)  |
                                     ((uint32_t)receiverBuffer[2] << 16) |
                                     ((uint32_t)receiverBuffer[3] << 24));
                LOG_INF("---------- My Received Packet Size : %d", receivepacket_size);
    
                if(	receiverBuffer[4] == 0x86 &&
    				receiverBuffer[5] == 0x00 )
                {    //맥어드레스 등 초기 정보 확인인
                    packet_start = true; 
    				send_flag = true;
    
                    LOG_INF("-- Start packet Receive --");
                }
                else if( receiverBuffer[4] == 0x84 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Amp, Sens, 베터리 등 설정 정보 한번에 받기
                    LOG_INF("pcb setting info.");
                }
                else if( receiverBuffer[4] == 0x88 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Battery Voltage 정보 받기
                    LOG_INF("Battery info");
                }
                else if( receiverBuffer[4] == 0x31 &&
    				     receiverBuffer[5] == 0x00 )
                {   //센서 Data 1개 받기
                    LOG_INF("Sensor Data 1ea receive");
                }
                else if( receiverBuffer[4] == 0x33 &&
    				     receiverBuffer[5] == 0x00 )
                {   //저장된 센서 Data를 최근 최대 60개 받기
                    LOG_INF("Sensor Data 60ea receive");
                }
                else if( receiverBuffer[4] == 0x35 &&
    				     receiverBuffer[5] == 0x00 )
                {   //데이터가 N개 쌓이면 Stream Data를 자동으로 전송하는 Data Stream Mode 시작
                    LOG_INF("N ea Data recweive Start");
                }
                else if( receiverBuffer[4] == 0x37 &&
    				     receiverBuffer[5] == 0x00 )
                {   //데이터가 N개 쌓이면 Stream Data를 자동으로 전송하는 Data Stream Mode 종료
                    LOG_INF("N ea Data recweive Stop");
                }
                else if( receiverBuffer[4] == 0x42 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Sleep Mode 시작하기
                    LOG_INF("Sleep Mode Start");
                }
                else if( receiverBuffer[4] == 0x41 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Light Sleep Mode 시작하기
                    LOG_INF("Light Sleep Mode Start");
                }
                else if( receiverBuffer[4] == 0x01 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Firmware Version 받기
                    LOG_INF("Firmware Version Receive");
                }
                else if( receiverBuffer[4] == 0x04 &&
    				     receiverBuffer[5] == 0x00 )
                {   //TCP 통신 서버의 IP 받기
                    LOG_INF("TCO Server IP Receive");
                }
                else if( receiverBuffer[4] == 0x24 &&
    				     receiverBuffer[5] == 0x00 )
                {   //TCP 통신 서버의 IP 설정하기
                    LOG_INF("TCP Server IP Setting");
                }
                else if( receiverBuffer[4] == 0x05 &&
    				     receiverBuffer[5] == 0x00 )
                {   //TCP 통신 서버의 Port 받기
                    LOG_INF("TCP Server Port receive");
                }
                else if( receiverBuffer[4] == 0x25 &&
    				     receiverBuffer[5] == 0x00 )
                {   //TCP 통신 서버의 Port 설정하기
                    LOG_INF("TCP Server Port Setting");
                }
                else if( receiverBuffer[4] == 0x06 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Client Mode 도중
                    LOG_INF("Client Mode ing?,,");
                }
                else if( receiverBuffer[4] == 0x07 &&
    				     receiverBuffer[5] == 0x00 )
                {   //센서 측정 간격 받기
                    LOG_INF("Sensor Speed Receive");
                }
                else if( receiverBuffer[4] == 0x27 &&
    				     receiverBuffer[5] == 0x00 )
                {   //센서 측정 간격 설정하기
                    flash_save_data(0, receiverBuffer[6]);
                    received_tcp_data_flag = true;
                    LOG_INF("Sensor Speed Setting");
                }
                else if( receiverBuffer[4] == 0x08 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Amplification 받기
                    LOG_INF("Amp Data receive");
                }
                else if( receiverBuffer[4] == 0x28 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Amplification 설정하기
                    flash_save_data(1, receiverBuffer[6]);
                    received_tcp_data_flag = true;
                    LOG_INF("Amp Value Setting : %d", received_tcp_data.amp);
                }
                else if( receiverBuffer[4] == 0x09 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Sensitivity 받기기
                    LOG_INF("Sens Data receive");
                }
                else if( receiverBuffer[4] == 0x29 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Sensitivity 설정하기
                    flash_save_data(2, receiverBuffer[6]);
                    received_tcp_data_flag = true;
                    LOG_INF("Sens Value Setting : %d", received_tcp_data.sens);
                }
                else if( receiverBuffer[4] == 0x0a &&
    				     receiverBuffer[5] == 0x00 )
                {   //저항 3 값 받기
                    LOG_INF("Res3 Data receive");
                }
                else if( receiverBuffer[4] == 0x2a &&
    				     receiverBuffer[5] == 0x00 )
                {   //저항3 값 설정하기
                    flash_save_data(3, receiverBuffer[6]);
                    received_tcp_data_flag = true;
                    LOG_INF("Res3 Value Setting : %d", received_tcp_data.res3);
                }
                else if( receiverBuffer[4] == 0x0f &&
    				     receiverBuffer[5] == 0x00 )
                {   //Wake up 값 받기
                    LOG_INF("Wake Up Value receive");
                }
                else if( receiverBuffer[4] == 0x2f &&
    				     receiverBuffer[5] == 0x00 )
                {   //Wake up 값 설정하기
                    LOG_INF("Wake up value setting");
                }
                else if( receiverBuffer[4] == 0x51 &&
    				     receiverBuffer[5] == 0x00 )
                {   //모터 동작하기
                    LOG_INF("Motor Start");
                }
                else if( receiverBuffer[4] == 0x91 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Firmware 업데이트 Mode 시작하기기
                    LOG_INF("Firmware Update Mode Start");
                }
                else if( receiverBuffer[4] == 0x92 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Firmware 파일 업로드드
                    LOG_INF("Firmware file upload");
                }
                else if( receiverBuffer[4] == 0x93 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Formware 파일 체크섬섬
                    LOG_INF("Firmware file checksum");
                }
                else if( receiverBuffer[4] == 0x64 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Data Stream Mode의 60개마다 자동으로 전송하는 Data Stream 기기에서 송신(기기 -> 서버) / 스트림 모드 동작시 센서 데이터 보내는 패킷
                    LOG_INF("      1");
                }
                else if( receiverBuffer[4] == 0x66 &&
    				     receiverBuffer[5] == 0x00 )
                {   //10초 이상 Wake up value 이상과 이하가 바뀌었을 때 기기에서 송신(기기 -> 서버) / 착좌감지지
                    LOG_INF("         2");
                }
                else if( receiverBuffer[4] == 0x62 &&
    				     receiverBuffer[5] == 0x00 )
                {   //Disconnect될 때 기기에서 송신(기기 -> 서버버)
                    LOG_INF("         3  ");
                }
    
            } else if (receivedBytes == 0) {
                LOG_INF("Server closed the connection.");
            } else {
                LOG_ERR("Receive error: %d", errno);
            }
        } else {
            LOG_ERR("No data received from server within timeout.");
        }
    }
    
    
    #define MAX_PACKET_SIZE 1000  // MSS 값
    
    void send_sensor_data(int tcpClientSocket) {
        if (!send_flag) return;
    
    	int sentBytes = 0;
        int retry_count = 0;
        const int max_retries = 5; // 최대 5번 %EC%9E%AC시도 후 재연결
    
        if (send_flag) {
    		if(packet_start == true)
    		{
                LOG_INF("normal data send--");
                packet_start = false;
    			sentBytes = send(tcpClientSocket, TCPClientMessage, sizeof(TCPClientMessage), 0);
    
                if (sentBytes > 0) {
                    k_msleep(10);  // 데이터 전송 후 10ms 대기 (TCP 윈도우가 열릴 시간 제공)
                } else if (sentBytes < 0) {
                    LOG_ERR("Send error: %d", errno);
                    return; // 연결 상태를 체크해야 함
                }
    
    			// if (--packet_start <= 0) {
                //     send_flag = false;
    			// 	packet_start = 0;
                // }
    		}
    		else
    		{
    			send_flag = false;
    			
    			if (fsr_data_flag == true) {
    				fsr_data_flag = false;  // 플래그 초기화
    
                    // ✅ adc_fsr_converted가 NULL이거나 크기가 0이면 오류 처리
                    if (!adc_fsr_converted || adc_fsr_converted_size == 0) {
                        LOG_ERR("ADC data is NULL or empty, cannot send");
                        return;
                    }
    
    				LOG_INF("Sending ADC sensor data to server...\n");
    
                    size_t total_size = adc_fsr_converted_size;
                    size_t sent = 0;
                    LOG_INF("-----total_size: %d bytes-----", total_size);
    
                    while (sent < total_size) {
                        size_t chunk_size = MIN(MAX_PACKET_SIZE, total_size - sent);
    
                        struct pollfd fds;
                        fds.fd = tcpClientSocket;
                        fds.events = POLLOUT;  // 송신 가능 여부 체크
                    
                        int ret = poll(&fds, 1, 1000);  // 최대 1초 대기
                        if (ret > 0 && (fds.revents & POLLOUT)) {
                            sentBytes = send(tcpClientSocket, ((uint8_t*)adc_fsr_converted) + sent, chunk_size, 0);
    
                            if (sentBytes > 0) {
                                k_msleep(10);  // 데이터 전송 후 10ms 대기 (TCP 윈도우가 열릴 시간 제공)
                                sent += sentBytes;
                                retry_count = 0; // 성공하면 재시도 횟수 초기화
                            } else {
                                LOG_ERR("Send error: %d", errno);
                                retry_count++;
                            }
                    
                            // if (sentBytes < 0) {
                            //     LOG_ERR("Send error: %d", errno);
                            //     break;
                            // }
                            // sent += sentBytes;
                        } else {
                            // k_msleep(500);  // 딜레이 추가
                            LOG_ERR("Socket not ready for sending, retrying...");
                            retry_count++;
                        }
    
                        if (retry_count >= max_retries) {
                            LOG_ERR("Max send retries reached. Closing socket and reconnecting...");
                            k_msleep(10000);
    
                            retry_count = 0;
                            close_socket(&tcpClientSocket);
                            tcpClientSocket = -1;
                            
                            return; // TCP_Client 루프에서 재연결 시도
                        }
                    }
    
                    printk("************************************************************\n");
                    printk("Total Sent ADC data length: %d bytes\n", sent);
    				//for(uint8_t i = 0; i < 16; i+=4) printk("%d, %d, %d, %d \n", adc_fsr_converted[i], adc_fsr_converted[i+1], adc_fsr_converted[i+2], adc_fsr_converted[i+3]);
    				printk("\n");
    
                    // ✅ 전송이 성공적으로 완료되었을 때만 메모리 해제
                    if (sent == total_size) {
                        LOG_INF("Send ADC data completed. Freeing memory.");
                        LOG_INF("Send ADC data length: %d", sent);
                        k_free(adc_fsr_converted);  // ✅ 여기가 올바른 위치
                        adc_fsr_converted = NULL;   // ✅ 해제 후 NULL로 초기화
                        adc_fsr_converted_size = 0;  // ✅ 크기 초기화
                    } else {
                        LOG_ERR("Partial send error, not freeing memory");
                    }
    
    				if (sentBytes < 0) {
    					LOG_ERR("Send error: %d", errno);
    				} else {
    					LOG_INF("Send ADC data length: %d", sentBytes);
    				}
    			}
    		}
        }
    }
    
    
    bool monitor_connection_status(int tcpClientSocket) {
        struct pollfd fds = {
            .fd = tcpClientSocket,
            .events = POLLIN | POLLHUP | POLLERR,
        };
    
        int poll_result = poll(&fds, 1, 100);  // 100ms 대기
    
        if (poll_result > 0) {
            if (fds.revents & (POLLHUP | POLLERR)) {
                LOG_ERR("Connection closed by server or socket error.");
                return false;  // 연결 끊김
            } 
            // else if (fds.revents & POLLERR) {
            //     LOG_ERR("Socket error detected.");
            //     return false;  // 소켓 에러
            // }
        } else if (poll_result < 0) {
            LOG_ERR("Poll error: %d", errno);
            return false;  // Poll 에러 발생
        }
    
        return true;  // 연결 유지 중
    }
    
    
    /*! TCP_Client implements the TCP Client task.
    * @brief TCP_Client uses a BSD socket estabilish a connection with a defined
    * 		TCP server. 
    * 		A sample message will be sent to the IP address defined on the 
    *		configuration file as Peer address.
    * 		This function is used on an independent thread.
    */
    
    // bool send_flag = false;
    // bool receive_flag = false;
    // int packet_start = 0;
    // bool packet_flag = false;
    void TCP_Client(void) {
        // int tcpClientSocket;
        struct sockaddr_in serverAddress;
        int retry_count = 0;
        const int max_retries = 5;
    
        LOG_INF("Waiting for network to be ready...");
        while (context.connected != true) {
    		k_msleep( TCP_CLIENT_SLEEP_TIME_MS );
        }
    
        LOG_INF("Configuring server address...");       // 서버 주소 설정
        serverAddress.sin_family = AF_INET;
        serverAddress.sin_port = htons(TCP_CLIENT_PORT);
        inet_pton(AF_INET, CONFIG_NET_CONFIG_PEER_IPV4_ADDR, &serverAddress.sin_addr);
    
        while (1) {
            retry_count = 0;  // ✅ 5회 재시도 후 1분 대기 후 다시 5회 재시도할 때 초기화
    
            while (retry_count < max_retries) {
                LOG_INF("Attempting to create socket...");
                tcpClientSocket = socket(serverAddress.sin_family, SOCK_STREAM, IPPROTO_TCP);
    
                if (tcpClientSocket < 0) {
                    LOG_ERR("Socket creation failed: %d", errno);
                    k_msleep(5000);
                    retry_count++;
                    continue;
                }
    
                LOG_INF("Attempting to connect to server...");
                if (connect(tcpClientSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) {
                    LOG_ERR("Connection failed: %d", errno);
                    close_socket(&tcpClientSocket);
                    k_msleep(5000);
                    retry_count++;
                    continue;
                }
    
                LOG_INF("Connected to server successfully.");
                retry_count = 0;  // ✅ 연결 성공 시 카운터 초기화
    
                
                // 소켓 옵션 설정
                // 1. SO_KEEPALIVE 설정
                int optval = 1;
                setsockopt(tcpClientSocket, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
    
                // 소켓 재사용 옵션 추가
                setsockopt(tcpClientSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
    
                struct timeval timeout = {.tv_sec = 5, .tv_usec = 0};
                setsockopt(tcpClientSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
                setsockopt(tcpClientSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
    
                // 송수신 병렬 처리 루프
                while (1) 
                {
                    if(fsr_data_flag == true) send_flag = true;
                    
                    receive_server_data(tcpClientSocket);
                    send_sensor_data(tcpClientSocket);
    
                    // 연결 상태 확인
                    if (!monitor_connection_status(tcpClientSocket)) {
                        LOG_ERR("Connection lost. Attempting to reconnect...");
                        packet_start = false;
                        close_socket(&tcpClientSocket);
                        k_msleep(5000);  // 재연결 전 5초 대기
                        break;  // 연결 재시도 루프로 이동
                    }
                    k_msleep(100);
                }
            }
            LOG_ERR("Max connection attempts (5) reached. Waiting 1 minute before retrying...");
            k_msleep(60000);  // ⏳ 1분 대기 후 다시 재연결 시도
        }
    }
    
    
    void Task_TCP_Client_Delete( void ) {
    	printk("Task_TCP_Client_Delete\n");
    	
        close_socket(&tcpClientSocket);
    	k_thread_abort(&tcpClientThread);
    }
    
    /*! Task_TCP_Client_Init initializes the task TCP Client
    *
    * @brief TCP Client initialization
    */
    void Task_TCP_Client_Init( void ){
    	printk("Task_TCP_Client_Init\n");
    	
        // configure_static_ip();
    	update_sampling_interval_from_server(500);
    	
    	k_thread_create	(														\
    					&tcpClientThread,										\
    					TCP_CLIENT_STACK,										\
    					TCP_CLIENT_STACK_SIZE,									\
    					(k_thread_entry_t)TCP_Client,							\
    					NULL,													\
    					NULL,													\
    					NULL,													\
    					TCP_CLIENT_PRIORITY,									\
    					0,														\
    					K_NO_WAIT);	
    
    	 k_thread_name_set(&tcpClientThread, "tcpClient");
    	 k_thread_start(&tcpClientThread);
    
    
    };
    
    


    nrf53_support.c

    #include <soc.h>
    #include <zephyr/device.h>
    #include <hal/nrf_reset.h>
    #if defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP)
    #include <../subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h>
    #else
    #define DEBUG_SETUP()
    #endif /* defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP) */
    #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(bt_hci_nrf53_support);
    int bt_hci_transport_teardown(const struct device *dev)
    {
    	ARG_UNUSED(dev);
        /* Put core into reset */
    	NRF_RESET->NETWORK.FORCEOFF = RESET_NETWORK_FORCEOFF_FORCEOFF_Hold;
    	LOG_DBG("Network MCU reseted.");
        /* Put the Network MCU in Forced-OFF mode. */
    	nrf_reset_network_force_off(NRF_RESET, true);
    	LOG_DBG("Network MCU placed in Forced-OFF mode");
    
    	return 0;
    }
    int bt_hci_transport_setup(const struct device *dev)
    {
    	ARG_UNUSED(dev);
    #if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM)
    	/* Route Bluetooth Controller Debug Pins */
    	DEBUG_SETUP();
    #endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) || defined(CONFIG_BUILD_WITH_TFM) */
    #if !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE)
    	/* Retain nRF5340 Network MCU in Secure domain (bus
    	 * accesses by Network MCU will have Secure attribute set).
    	 */
    	NRF_SPU->EXTDOMAIN[0].PERM = 1 << 4;
    #endif /* !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) */
    
    	NRF_RESET->NETWORK.FORCEOFF = RESET_NETWORK_FORCEOFF_FORCEOFF_Release;
    	/* Release the Network MCU, 'Release force off signal' */
    	nrf_reset_network_force_off(NRF_RESET, false);
    
    	return 0;
    }

Related