기타등등

This commit is contained in:
2026-06-11 17:48:35 +09:00
parent d7c5b34da3
commit 1f7436e27d
14 changed files with 714 additions and 124 deletions
+148 -30
View File
@@ -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);
}