기타등등
This commit is contained in:
+148
-30
@@ -15,6 +15,8 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/dfu/mcuboot.h>
|
||||
#include <hal/nrf_power.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "debug_print.h"
|
||||
@@ -79,6 +81,8 @@ static bool power_btn_suspended; /* 측정 중 전원 버튼 상태
|
||||
* k_work를 사용하면 시스템 워크큐 스레드에서 실행되므로 안전하게 BLE API 호출 가능.
|
||||
* main_s() 타이머 콜백에서 k_work_submit()으로 예약하여 사용한다.
|
||||
*/
|
||||
static bool resume_without_power_button;
|
||||
static uint32_t boot_reset_reason;
|
||||
static struct k_work adv_start_work;
|
||||
static struct k_work adv_stop_work;
|
||||
|
||||
@@ -111,13 +115,15 @@ static void ble_cmd_work_handler(struct k_work *work)
|
||||
uint16_t local_len = 0U;
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&ble_cmd_lock);
|
||||
if (ble_cmd_pending) {
|
||||
if (ble_cmd_pending)
|
||||
{
|
||||
local_len = ble_cmd_len;
|
||||
memcpy(local_buf, ble_cmd_buf, local_len);
|
||||
}
|
||||
k_spin_unlock(&ble_cmd_lock, key);
|
||||
|
||||
if (local_len == 0U) {
|
||||
if (local_len == 0U)
|
||||
{
|
||||
DBG_ERR("[BLE RX] worker: empty\r\n");
|
||||
return;
|
||||
}
|
||||
@@ -204,17 +210,43 @@ static void ble_rx_handler(const uint8_t *data, uint16_t len)
|
||||
/* 전원 유지 핀(P0.08) 초기화 - 아직 래치하지 않음
|
||||
* 버튼을 물리적으로 누르고 있는 동안만 전원 유지됨
|
||||
* 2초 후 main_s()에서 래치(HIGH) 설정 */
|
||||
static void boot_context_detect(void)
|
||||
{
|
||||
boot_reset_reason = nrf_power_resetreas_get(NRF_POWER);
|
||||
resume_without_power_button =
|
||||
(boot_reset_reason & (NRF_POWER_RESETREAS_SREQ_MASK |
|
||||
NRF_POWER_RESETREAS_DOG_MASK |
|
||||
NRF_POWER_RESETREAS_LOCKUP_MASK |
|
||||
NRF_POWER_RESETREAS_RESETPIN_MASK)) != 0U;
|
||||
|
||||
if (boot_reset_reason != 0U)
|
||||
{
|
||||
nrf_power_resetreas_clear(NRF_POWER, boot_reset_reason);
|
||||
}
|
||||
}
|
||||
|
||||
static void power_hold_init(void)
|
||||
{
|
||||
gpio_pin_configure_dt(&power_hold, GPIO_OUTPUT_INACTIVE);
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||
bool dfu_confirm_pending = !boot_is_img_confirmed();
|
||||
#else
|
||||
bool dfu_confirm_pending = false;
|
||||
#endif
|
||||
|
||||
gpio_pin_configure_dt(&power_hold,
|
||||
(resume_without_power_button || dfu_confirm_pending) ? GPIO_OUTPUT_ACTIVE
|
||||
: GPIO_OUTPUT_INACTIVE);
|
||||
}
|
||||
|
||||
/* 전원 ON/OFF 제어 - P0.08 핀으로 물리적 전원 래치/해제 */
|
||||
static void power_control_handler(on_off_cont_t device_power_st)
|
||||
{
|
||||
if (device_power_st == OFF) {
|
||||
if (device_power_st == OFF)
|
||||
{
|
||||
gpio_pin_set_dt(&power_hold, 0); /* P0.08 LOW → 전원 래치 해제 → 전원 차단 */
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_pin_set_dt(&power_hold, 1); /* P0.08 HIGH → 전원 유지 */
|
||||
DBG_PRINTF("[PWR] ON\r\n");
|
||||
}
|
||||
@@ -239,13 +271,16 @@ static void load_default_config(void)
|
||||
size_t hw_len = strlen(HARDWARE_VERSION);
|
||||
size_t passkey_len = strlen(DEFAULT_PASSKEY);
|
||||
|
||||
if (serial_len > SERIAL_NO_LENGTH) {
|
||||
if (serial_len > SERIAL_NO_LENGTH)
|
||||
{
|
||||
serial_len = SERIAL_NO_LENGTH;
|
||||
}
|
||||
if (hw_len > HW_NO_LENGTH) {
|
||||
if (hw_len > HW_NO_LENGTH)
|
||||
{
|
||||
hw_len = HW_NO_LENGTH;
|
||||
}
|
||||
if (passkey_len > PASSKEY_LENGTH) {
|
||||
if (passkey_len > PASSKEY_LENGTH)
|
||||
{
|
||||
passkey_len = PASSKEY_LENGTH;
|
||||
}
|
||||
|
||||
@@ -403,11 +438,7 @@ static void timers_init(void)
|
||||
k_work_init(&adv_start_work, adv_start_work_handler);
|
||||
k_work_init(&adv_stop_work, adv_stop_work_handler);
|
||||
k_work_init(&ble_cmd_work, ble_cmd_work_handler);
|
||||
k_work_queue_start(&ble_cmd_work_q,
|
||||
ble_cmd_workq_stack,
|
||||
K_THREAD_STACK_SIZEOF(ble_cmd_workq_stack),
|
||||
BLE_CMD_WORKQ_PRIORITY,
|
||||
NULL);
|
||||
k_work_queue_start(&ble_cmd_work_q, ble_cmd_workq_stack, K_THREAD_STACK_SIZEOF(ble_cmd_workq_stack), BLE_CMD_WORKQ_PRIORITY, NULL);
|
||||
power_timer_init();
|
||||
}
|
||||
|
||||
@@ -417,59 +448,145 @@ static void timers_start(void)
|
||||
k_timer_start(&m_power_on_delay_timer, K_MSEC(POWER_ON_DELAY), K_NO_WAIT);
|
||||
}
|
||||
|
||||
static void resume_device_after_soft_reset(void)
|
||||
{
|
||||
if (!resume_without_power_button)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
device_on = true;
|
||||
cnt_s = 0;
|
||||
boot_btn_released = (gpio_pin_get_dt(&power_btn) != 1);
|
||||
m_reset_status = 1;
|
||||
|
||||
power_control_handler(ON);
|
||||
led_set_state(LED_STATE_ADVERTISING);
|
||||
battery_timer_start();
|
||||
k_work_submit(&adv_start_work);
|
||||
|
||||
DBG_CORE("[BOOT] Resume after resetreas=0x%08x\r\n", boot_reset_reason);
|
||||
}
|
||||
|
||||
static void confirm_running_image(void)
|
||||
{
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||
if (!boot_is_img_confirmed())
|
||||
{
|
||||
int err = boot_write_img_confirmed();
|
||||
if (err == 0)
|
||||
{
|
||||
DBG_CORE("[DFU] Running image confirmed\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_ERR("[DFU] Image confirm failed (err %d)\r\n", err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_CORE("[DFU] Running image already confirmed\r\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *swap_type_to_str(int swap_type)
|
||||
{
|
||||
switch (swap_type)
|
||||
{
|
||||
case BOOT_SWAP_TYPE_NONE:
|
||||
return "none";
|
||||
case BOOT_SWAP_TYPE_TEST:
|
||||
return "test";
|
||||
case BOOT_SWAP_TYPE_PERM:
|
||||
return "perm";
|
||||
case BOOT_SWAP_TYPE_REVERT:
|
||||
return "revert";
|
||||
case BOOT_SWAP_TYPE_FAIL:
|
||||
return "fail";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void log_mcuboot_state(void)
|
||||
{
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
|
||||
struct mcuboot_img_header header;
|
||||
uint8_t active_slot = boot_fetch_active_slot();
|
||||
int swap_type = mcuboot_swap_type();
|
||||
int err = boot_read_bank_header(active_slot, &header, sizeof(header));
|
||||
|
||||
DBG_CORE("[DFU] active_slot=%u swap_type=%s(%d) confirmed=%d\r\n",
|
||||
active_slot,
|
||||
swap_type_to_str(swap_type),
|
||||
swap_type,
|
||||
boot_is_img_confirmed());
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
DBG_CORE("[DFU] image version %u.%u.%u+%u size=0x%x\r\n",
|
||||
header.h.v1.sem_ver.major,
|
||||
header.h.v1.sem_ver.minor,
|
||||
header.h.v1.sem_ver.revision,
|
||||
header.h.v1.sem_ver.build_num,
|
||||
header.h.v1.image_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_ERR("[DFU] image header read failed (slot %u, err %d)\r\n",
|
||||
active_slot,
|
||||
err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* 메인 함수
|
||||
*============================================================================*/
|
||||
int main(void)
|
||||
{
|
||||
boot_context_detect();
|
||||
|
||||
/*── Phase 1: 하드웨어 기본 초기화 ──*/
|
||||
power_hold_init();
|
||||
cnt_s = 0;
|
||||
|
||||
/*
|
||||
* 현재는 전원 버튼/mbb 문제를 같이 디버깅 중이라
|
||||
* "버튼을 2초 이상 눌러야 래치 ON" 규칙이 오히려 부팅 자체를 막고 있다.
|
||||
*
|
||||
* 그래서 디버깅 동안만, MCU가 main()까지 올라오면 바로 P0.08 래치를 ON으로 잡는다.
|
||||
*
|
||||
* 의미:
|
||||
* - 사용자는 전원 버튼을 "부팅이 시작될 만큼만" 누르면 된다.
|
||||
* - 예전처럼 2초를 정확히 맞춰 길게 누를 필요가 없다.
|
||||
* - 일단 켜진 뒤의 BLE/측정/로그 문제를 보기 쉬워진다.
|
||||
*
|
||||
* 나중에 전원 시퀀스 디버깅이 끝나면 이 블록은 다시 제거하면 된다.
|
||||
*/
|
||||
device_on = false;
|
||||
boot_btn_released = false;
|
||||
confirm_running_image();
|
||||
|
||||
DBG_CORE("\r\n========================================\r\n");
|
||||
DBG_CORE(" TEST BUILD %s (Zephyr)\r\n", FIRMWARE_VERSION);
|
||||
DBG_CORE(" BUILD TAG: TEST-ADV-UNIT-042\r\n");
|
||||
DBG_CORE(" BUILD TAG: TEST-ADV-UNIT-000\r\n");
|
||||
DBG_CORE("========================================\r\n");
|
||||
|
||||
DBG_CORE("[1] HW Init\r\n");
|
||||
gpio_init();
|
||||
timers_init();
|
||||
log_mcuboot_state();
|
||||
load_default_config();
|
||||
led_init();
|
||||
battery_adc_init();
|
||||
battery_timer_init();
|
||||
imu_init();
|
||||
temp_init();
|
||||
DBG_CORE(" gpio/timer/config/led/batt/imu/temp OK\r\n");
|
||||
piezo_config_init();
|
||||
DBG_CORE(" gpio/timer/config/led/batt/imu/temp/piezo-cfg OK\r\n");
|
||||
|
||||
/*── Phase 2: BLE 스택 + NUS ──*/
|
||||
DBG_CORE("[2] BLE Init\r\n");
|
||||
if (ble_service_init(ble_rx_handler) == 0)
|
||||
{
|
||||
DBG_CORE(" ble/nus OK\r\n");
|
||||
resume_device_after_soft_reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_ERR(" ble FAIL\r\n");
|
||||
}
|
||||
|
||||
/*── Phase 3: FDS/NVS (TODO) ──*/
|
||||
/*── Phase 3: FDS/NVS ──*/
|
||||
/*── Phase 4: 애플리케이션 (TODO) ──*/
|
||||
|
||||
DBG_CORE("\r\n========================================\r\n");
|
||||
@@ -480,7 +597,8 @@ int main(void)
|
||||
timers_start();
|
||||
|
||||
/* 메인 루프 - idle */
|
||||
for (;;) {
|
||||
for (;;)
|
||||
{
|
||||
k_msleep(100);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user