diff --git a/.gitignore b/.gitignore index f73a3a4..fd9ca40 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,52 @@ -# editors -*.swp -*~ +# Zephyr build outputs +build/ +build_*/ +twister-out/ +.vscode/.west/ -# build -/build*/ -log.log +# West / Zephyr local metadata +.zephyr/ +.cmake/ +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +compile_commands.json + +# Generated binaries / firmware images +*.hex +*.bin +*.elf +*.map +*.lst +*.uf2 +*.zip +*.signed +*.merged.hex + +# Logs +*.log +*.rtt +*.jlink + +# Python / test cache +__pycache__/ +*.pyc +.pytest_cache/ + +# Editor / OS +.vscode/ipch/ +.vs/ +.idea/ +.DS_Store +Thumbs.db + +# Local env / secrets +.env +*.pem +*.key + +# Vim swap files +*.swp +*.swo +.*.swp +.*.swo \ No newline at end of file diff --git a/README.md b/README.md index 42212d3..9043dd9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # VesiScan BASIC - Zephyr -- nRF52840 기반 VesiScan BASIC 펌웨어의 Zephyr/nRF Connect SDK 포팅 프로젝트 -- 현재 빌드 대상은 `nrf52840dk_nrf52840` 기준이며, MCUboot + BLE MCUmgr DFU, BLE NUS 명령, 배터리/IMU/피에조/echo ADC 측정 기능 포함 +- nRF52840 기반 VesiScan BASIC 펌웨어의 Zephyr/nRF Connect SDK 프로젝트 +- 현재 빌드 대상은 `nrf52840dk_nrf52840` 기준 +- MCUboot + BLE MCUmgr DFU, BLE NUS 명령, 배터리/IMU/Piezo/echo ADC capture 등 포함 ## 프로젝트 구조 @@ -42,7 +43,7 @@ VesiScan-Basic_Zephyr/ ## 빌드 -권장 빌드 (nRF Connect SDK / west 사용): +nRF Connect SDK / west 사용: ```powershell west build -b nrf52840dk_nrf52840 -p auto @@ -83,7 +84,7 @@ west flash | `ECHO_MISO` | P0.15 | ADC121S051 MISO | | `ECHO_CS` | P0.19 | ADC121S051 CS | -`CONFIG_SERIAL=n`으로 UART0를 비활성화하여 P0.08 충돌 피함 +`CONFIG_SERIAL=n`으로 UART0를 비활성화하여 P0.08 충돌 회피 ## 전원 동작 @@ -102,7 +103,6 @@ west flash - Normal advertising timeout: 10분 - DFU advertising: SMP UUID, timeout 미적용 - NUS UUID 광고 포함 -- 연결 시 LED 광고 패턴 OFF - 연결 파라미터 선호값: 15ms / latency 0 / supervision timeout 10s - NUS TX는 mutex + completion semaphore로 순차 전송 - BLE RX는 별도 work queue에서 명령 처리 @@ -118,7 +118,6 @@ west flash - DATA: 명령별 payload - CRC16: CRC-CCITT, initial `0xFFFF` - 응답 TAG: 보통 요청의 `m`을 `r`로 바꾼 형태, 예: `msn?` -> `rsn:` -- 알 수 없는 명령은 `rxn:` 응답 ## 구현된 명령 @@ -131,15 +130,15 @@ west flash | `msn?` | `rsn:` | 배터리 전압 측정 | 구현 완료 | | `mls?` | `rls:` | LED 상태 변경 | 구현 완료 | | `msp?` | `rsp:` | IMU accel/gyro 단발 측정 | 구현 완료 | -| `mst?` | `rso:` | IMU internal temperature | 구현 완료 | -| `mpa?` | `rpa:` | 피에조 전원 ON | 구현 완료 | -| `mpb?` | `rpb:` | 피에조 전원 OFF | 구현 완료 | -| `mpc?` | `rpc:` | 피에조 burst 테스트 | 구현 완료, 주파수 옵션은 제한적 | -| `mec?` | `reb:` -> `raa:` | 단일 채널 burst + echo capture | 구현 완료 | -| `mad?` | `reb:` -> `raa:` | ADC only capture | 구현 완료 | -| `maa?` | `reb:` x6 -> `raa:` | 6채널 echo sweep | 구현 완료 | +| `mst?` | `rst:` | IMU internal temperature | 구현 완료 | +| `mpa?` | `rpa:` | Piezo 전원 ON | 구현 완료, 테스트용 | +| `mpb?` | `rpb:` | Piezo 전원 OFF | 구현 완료, 테스트용 | +| `mpc?` | `rpc:` | Piezo burst only | 구현 완료, 테스트용 | +| `mec?` | `reb:` -> `raa:` | 단일 채널 burst + echo capture | 구현 완료, 테스트용 | +| `mad?` | `reb:` -> `raa:` | ADC only capture | 구현 완료, 테스트용 | +| `maa?` | `reb:` x6 -> `raa:` | 6채널 echo sweep | 구현 완료, 테스트용 | | `mbb?` | `rbb:` -> `reb:` x6 -> `raa:` | 배터리 + IMU + 온도 + 6채널 echo | 구현 완료 | -| `mtb?` | `reb:` x6 + `rim:` -> `raa:` | 피에조 sweep + IMU FIFO | 구현 완료, 실측 검증 필요 | +| `mtb?` | `reb:` x6 + `rim:` -> `raa:` | Piezo sweep + IMU FIFO | 구현 완료 | | `mcf?` | `rcf:` | 측정 파라미터 읽기 | 구현 완료 | | `mcs?` | `rcs:` | 측정 파라미터 쓰기 | 구현 완료, NVS 저장 | | `mid?` | `rid:` | HW/SN/FW identity 읽기 | 구현 완료 | @@ -149,7 +148,8 @@ west flash | `mws?` | `rws:` | Serial number 쓰기 | 구현 완료, NVS 저장 | | `mrs?` | `rrs:` | Serial number 읽기 | 구현 완료 | | `mpz?` | `rpz:` | Passkey 쓰기 | 구현 완료, NVS 저장, 최초 1회만 가능 | -| `mqz?` | `rqz:` | Passkey 읽기 | 구현 완료 | +| `mqz?` | `rqz:` | Passkey 읽기 | 구현 완료, 삭제 예정 | +| `mim?` | `rim:` | IMU FIFO | 구현 완료 | ## 저장되는 설정 diff --git a/src/command/handlers/cmd_sensor.c b/src/command/handlers/cmd_sensor.c index bb40a89..cf49635 100644 --- a/src/command/handlers/cmd_sensor.c +++ b/src/command/handlers/cmd_sensor.c @@ -70,13 +70,13 @@ int cmd_mst(const uint8_t *data, uint8_t data_len) if ((ret != 0) || (t_cdeg == INT16_MIN)) { - cmd_send_response_u16("rso:", 0xFFFF); + cmd_send_response_u16("rst:", 0xFFFF); DBG_PRINTF("[CMD] mst: imu temp read fail ret=%d\r\n", ret); return 1; } // 음수 온도도 2's complement로 그대로 전송 (앱이 int16로 해석) - cmd_send_response_u16("rso:", (uint16_t)t_cdeg); + cmd_send_response_u16("rst:", (uint16_t)t_cdeg); DBG_PRINTF("[CMD] mst -> %d.%02d C\r\n", t_cdeg / 100, (t_cdeg < 0 ? -t_cdeg : t_cdeg) % 100); return 1; } diff --git a/tests/boot_route_sim.c b/tests/boot_route_sim.c deleted file mode 100644 index db566c9..0000000 --- a/tests/boot_route_sim.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include "../src/main.h" - -#define BOOT_THRESHOLD 200 - -typedef struct { - bool device_on; - bool boot_btn_released; - bool power_btn_suspended; - uint16_t cnt_s; -} boot_sm_t; - -static void route_step(const char *name) -{ - printf(" -> %s\n", name); -} - -static void print_main_boot_route(bool resume_without_button, - bool dfu_confirm_pending, - bool dfu_reset_resume) -{ - printf("main() boot route\n"); - route_step("boot_context_detect()"); - printf(" resume_without_power_button=%u, dfu_confirm_pending=%u, dfu_reset_resume=%u\n", - resume_without_button ? 1U : 0U, - dfu_confirm_pending ? 1U : 0U, - dfu_reset_resume ? 1U : 0U); - - route_step("power_hold_init()"); - printf(" POWER_HOLD initial=%s\n", - (resume_without_button || dfu_confirm_pending || dfu_reset_resume) ? "ON" : "OFF"); - - route_step("confirm_running_image()"); - route_step("gpio_init()"); - route_step("timers_init()"); - route_step("log_mcuboot_state()"); - route_step("load_default_config()"); - route_step("led_init()"); - route_step("battery_adc_init()"); - route_step("battery_timer_init()"); - route_step("imu_init()"); - route_step("piezo_config_init()"); - route_step("ble_service_init(ble_rx_handler)"); - - if (resume_without_button || dfu_confirm_pending || dfu_reset_resume) { - route_step("resume_device_after_soft_reset()"); - route_step("POWER_HOLD ON, LED_ADVERTISING, battery_timer_start(), adv_start_work"); - } - - route_step("timers_start()"); - route_step("idle loop"); -} - -static void power_control(bool on, const char *reason) -{ - printf(" POWER_HOLD=%s reason=%s\n", on ? "ON" : "OFF", reason); -} - -static void boot_button_tick(boot_sm_t *sm, bool button_pressed) -{ - if (sm->power_btn_suspended) { - return; - } - - if (!sm->device_on) { - if (!button_pressed) { - power_control(false, "boot-button-released-before-latch"); - sm->cnt_s = 0; - } else { - sm->cnt_s++; - if (sm->cnt_s == BOOT_THRESHOLD) { - sm->device_on = true; - sm->cnt_s = 0; - power_control(true, "button-2s-latch"); - printf(" led_set_state(LED_STATE_ADVERTISING)\n"); - printf(" adv_start_work submitted\n"); - printf(" battery_timer_start()\n"); - } - } - return; - } - - if (!sm->boot_btn_released) { - if (!button_pressed) { - sm->boot_btn_released = true; - printf(" boot button released after latch\n"); - } - } else if (button_pressed) { - sm->cnt_s++; - if (sm->cnt_s >= BOOT_THRESHOLD) { - printf(" battery_timer_stop()\n"); - printf(" adv_stop_work submitted\n"); - sm->device_on = false; - sm->boot_btn_released = false; - sm->cnt_s = 0; - printf(" sleep_mode_enter_reason(button-long-press)\n"); - } - } else { - sm->cnt_s = 0; - } -} - -static void simulate_short_press(void) -{ - boot_sm_t sm = {0}; - - printf("\nscenario: short press during boot\n"); - for (int i = 0; i < 80; i++) { - boot_button_tick(&sm, true); - } - boot_button_tick(&sm, false); - printf(" result: device_on=%u cnt_s=%u\n", sm.device_on ? 1U : 0U, sm.cnt_s); -} - -static void simulate_long_press_boot(void) -{ - boot_sm_t sm = {0}; - - printf("\nscenario: hold button until boot latch\n"); - for (int i = 0; i < BOOT_THRESHOLD; i++) { - boot_button_tick(&sm, true); - } - boot_button_tick(&sm, false); - printf(" result: device_on=%u boot_btn_released=%u cnt_s=%u\n", - sm.device_on ? 1U : 0U, - sm.boot_btn_released ? 1U : 0U, - sm.cnt_s); -} - -static void simulate_power_off_after_boot(void) -{ - boot_sm_t sm = { - .device_on = true, - .boot_btn_released = true, - }; - - printf("\nscenario: long press while already ON\n"); - for (int i = 0; i < BOOT_THRESHOLD; i++) { - boot_button_tick(&sm, true); - } - printf(" result: device_on=%u cnt_s=%u\n", sm.device_on ? 1U : 0U, sm.cnt_s); -} - -int main(void) -{ - printf("PC GCC boot-route simulator for %s\n\n", FIRMWARE_VERSION); - - print_main_boot_route(false, false, false); - - printf("\nsoft-reset/DFU resume route\n"); - print_main_boot_route(true, false, false); - - simulate_short_press(); - simulate_long_press_boot(); - simulate_power_off_after_boot(); - - return 0; -}