# VesiScan BASIC - Zephyr (nRF Connect SDK) nRF52840 기반 VesiScan BASIC 펌웨어의 Zephyr 포팅 프로젝트 ## 현재 구현 상태 | Stage | 내용 | 상태 | |-------|------|------| | 1 | GPIO + 전원 래치 + 버튼 상태머신 | 완료 | | 1 | LED 제어 (green/orange 패턴) | 완료 | | 2 | BLE 스택 + NUS (advertising, 연결, 재연결) | 완료 | | 3 | 배터리 ADC (AIN2, 12bit) | 완료 | | 3 | 온도 센서 TMP235 (AIN3) | 완료 | | 3 | IMU ICM42670P (I2C0) | 완료 | | 3 | 피에조 TX + mux 제어 | 완료 | | 3 | ADC121S051 echo capture (nrfx SPIM3) | 완료 | | 3 | BLE 커맨드 파서 (TAG+DATA+CRC16) | 진행중 | | 4 | MCUboot + MCUmgr BLE DFU 설정 | 진행중 | | 4 | Flash 저장소 (NVS/settings, piezo config) | 완료 | | - | BLE 보안 (본딩, 패스키) | 미구현 | | - | HW/SN/Passkey 저장/복원 | 미구현 | ## 프로젝트 구조 ``` blinky/ ├── CMakeLists.txt # 빌드 설정 (소스 파일 등록) ├── prj.conf # Kconfig 설정 (기능 ON/OFF) ├── boards/ │ └── nrf52840dk_nrf52840.overlay # Devicetree Overlay (핀 매핑) └── src/ ├── main.c # 메인 진입점 + 부팅 시퀀스 + 버튼 상태머신 ├── main.h # 전역 상수/변수/타입 정의 ├── debug_print.h # 디버그 출력 매크로 (RTT) ├── parser.c / .h # BLE 커맨드 파서 (TAG+DATA+CRC16) ├── power_control.c / .h # 전원 시퀀스 상태머신 ├── ble/ │ └── ble_service.c / .h # BLE NUS 서비스 (advertising, 연결, TX/RX) └── drivers/ ├── battery/ │ └── battery_adc.c / .h # 배터리 전압 ADC (AIN2, 12bit) ├── echo_adc/ │ └── echo_adc.c / .h # ADC121S051 echo capture (SPIM3) ├── imu/ │ └── imu_i2c.c / .h # ICM42670P IMU (I2C0) ├── led/ │ └── led_control.c / .h # LED 패턴 제어 (k_timer 기반) ├── piezo/ │ └── piezo.c / .h # 피에조 전원, mux, SW burst └── temperature/ └── tmp235.c / .h # TMP235 온도 센서 (AIN3) ``` ## 빌드 방법 ### 일반 빌드 소스 파일(.c/.h)만 변경한 경우 ### Pristine Build 아래 파일을 변경한 경우 반드시 Pristine Build: - `prj.conf` (Kconfig 설정) - `boards/*.overlay` (Devicetree 핀 매핑) - `CMakeLists.txt` (소스/include 경로 추가) nRF Connect for VS Code → Build 패널 → **Pristine Build** 또는 `build` 폴더 삭제 후 빌드 ## 핀 매핑 (Devicetree Overlay) | 이름 | 핀 | 방향 | 역할 | |------|-----|------|------| | `PWR_HOLD` | P0.08 | Output, Active HIGH | 전원 래치 | | `BUTTON_CHECK` | P1.08 | Input, Pull-up, Active LOW | 전원 버튼 | | `LED_BLE` | P0.12 | Output, Active LOW | 초록 LED | | `FUNCTION_LED` | P0.29 | Output, Active LOW | 주황 LED | | ADC AIN2 | P0.04 | Analog Input | 배터리 전압 분압 | | ADC AIN3 | P0.05 | Analog Input | TMP235 온도 센서 | | I2C0 SCL | P1.14 | I2C | ICM42670P SCL | | I2C0 SDA | P1.15 | I2C | ICM42670P SDA | | `PIEZO_PWR` | P1.09 | Output, Active HIGH | 피에조/TMP235 전원 enable | | `PIEZO_PE` | P0.25 | Output, Active HIGH | 피에조 pulse enable | | `PIEZO_P_OUT` | P1.07 | Output | 피에조 P 출력 | | `PIEZO_N_OUT` | P1.06 | Output | 피에조 N 출력 | | `PIEZO_DMP` | P1.00 | Output | 피에조 dump | | `MUX_EN_A` | P0.21 | Output | 피에조 mux enable A | | `MUX_EN_B` | P0.23 | Output | 피에조 mux enable B | | `MUX_SEL0` | P1.10 | Output | 피에조 mux select 0 | | `MUX_SEL1` | P0.28 | Output | 피에조 mux select 1 | | `ECHO_SCLK` | P0.14 | SPIM/GPIO | ADC121S051 SCLK | | `ECHO_MISO` | P0.15 | SPIM/GPIO | ADC121S051 MISO | | `ECHO_CS` | P0.19 | Output, Active LOW | ADC121S051 CS | > UART0은 P0.08 충돌 방지를 위해 비활성화 (`status = "disabled"`) ## 전원 버튼 동작 | 동작 | 조건 | 결과 | |------|------|------| | 부팅 (OFF→ON) | 2초 이상 홀드 | 전원 래치 + LED 깜빡임 + BLE advertising | | 무시 | 부팅 후 2초 미만 릴리스 | 전원 OFF (래치 안 됨) | | 전원 OFF (ON→OFF) | 버튼 놓은 뒤 다시 2초 홀드 | advertising 중지 + LED OFF + 3초 후 전원 차단 | ## BLE 커맨드 프로토콜 ### 패킷 포맷 ``` [TAG 4바이트] [DATA N바이트] [CRC16 2바이트] ``` - TAG: ASCII 4글자 (예: `msn?`, `mfv?`) - DATA: uint16 little-endian 값들 - CRC16: CRC-CCITT (초기값 0xFFFF) - 응답 TAG: 첫 글자 `m` → `r` (예: `msn?` → `rsn:`) ### 구현된 커맨드 | 커맨드 | 응답 | 기능 | |--------|------|------| | `msn?` | `rsn:` + uint16 mV | 배터리 전압 측정 | | `mls?` | `rls:` + state | LED 상태 변경 | | `msp?` | `rsp:` + accel/gyro | IMU 단발 측정 | | `mst?` | `rso:` + int16 cdeg | TMP235 온도 측정 | | `mpa?` | `rpa:` + status | 피에조 전원 ON | | `mpb?` | `rpb:` + status | 피에조 전원 OFF | | `mpc?` | `rpc:` + cycles/status | 피에조 burst 테스트 | | `mec?` | `reb:` + `raa:` | 단일 채널 echo capture | | `maa?` | `reb:` x6 + `raa:` | 6채널 echo sweep | | `mbb?` | `rbb:` + `reb:` x6 + `raa:` | 배터리+IMU+온도+6채널 echo | | `mcf?` | `rcf:` | 측정 파라미터 읽기(현재 설정값 반환) | | `mcs?` | `rcs:` + status | 측정 파라미터 쓰기 + NVS 저장 | | `mfv?` | `rfv:` | FW version 읽기 | | `mrh?` | `rrh:` | HW version 읽기(RAM/default) | | `mwh?` | `rwh:` | HW version 쓰기(RAM only) | | `mrs?` | `rrs:` | Serial number 읽기(RAM/default) | | `mws?` | `rws:` | Serial number 쓰기(RAM only) | | `mqz?` | `rqz:` | Passkey 읽기(RAM/default) | | `mpz?` | `rpz:` | Passkey 쓰기(RAM only) | ### 전체 커맨드 목록 | # | 내용 | 명령 | 응답 | 비고 | |---|------|------|------|------| | 1 | 전원 OFF | `msq?` | `rsq:` | 미구현 | | 2 | 재부팅 | `mss?` | `rss:` | 미구현 | | 3 | 본딩 삭제 + 재부팅 | `msr?` | `rsr:` | 미구현 | | 4 | LED 상태 | `mls?` | `rls:` | 구현 완료 | | 5 | HW Version 읽기 | `mrh?` | `rrh:` | 구현 완료, RAM/default | | 6 | HW Version 쓰기 | `mwh?` | `rwh:` | 구현 완료, RAM only | | 7 | Serial Number 읽기 | `mrs?` | `rrs:` | 구현 완료, RAM/default | | 8 | Serial Number 쓰기 | `mws?` | `rws:` | 구현 완료, RAM only | | 9 | FW Version 읽기 | `mfv?` | `rfv:` | 구현 완료 | | 10 | Passkey 읽기 | `mqz?` | `rqz:` | 구현 완료, RAM/default | | 11 | Passkey 쓰기 | `mpz?` | `rpz:` | 구현 완료, RAM only | | 12 | 배터리 측정 | `msn?` | `rsn:` | 구현 완료 | | 13 | IMU 단발 측정 | `msp?` | `rsp:` | 구현 완료 | | 14 | 온도 측정 | `mst?` | `rso:` | 구현 완료 | | 15 | 피에조 전원 ON | `mpa?` | `rpa:` | 구현 완료 | | 16 | 피에조 전원 OFF | `mpb?` | `rpb:` | 구현 완료 | | 17 | 피에조 burst 테스트 | `mpc?` | `rpc:` | 구현 완료, `freq_option`은 아직 미사용 | | 18 | 단일 채널 측정 | `mec?` | `reb:` → `raa:` | 구현 완료, 테스트용 | | 19 | 모든 채널(6) 측정 | `maa?` | `reb:`(6개) → `raa:` | 구현 완료 | | 20 | 전체 측정 | `mbb?` | `rbb:` → `reb:`(6개) → `raa:` | 구현 완료 | | 21 | 측정 파라미터 읽기 | `mcf?` | `rcf:` | 구현 완료, 현재 설정값 반환 | | 22 | 측정 파라미터 쓰기 | `mcs?` | `rcs:` | 구현 완료, NVS 저장 | ## 남은 포팅 작업 | 항목 | 현재 상태 | 다음 작업 | |------|-----------|-----------| | NVS/settings | piezo config 저장/복원 구현 완료 | HW/SN/Passkey 저장으로 확장 | | 측정 파라미터 | `piezo_config` 구조체 사용 | 실제 하드웨어에서 값별 파형 검증 | | `mcs?` | 구현 완료 | 앱/테스트툴에서 쓰기 후 재부팅 유지 확인 | | HW/SN/Passkey 저장 | RAM only | `mwh?`, `mws?`, `mpz?` 값을 NVS에 저장 | | BLE 보안 | `CONFIG_BT_SMP=n`, dev mode | bonding, fixed passkey, MITM/LESC 적용 | | BLE DFU | MCUboot/mcumgr 설정 있음 | SMP 광고/업로드/리셋 후 confirm 검증 | ## 디버그 로그 (RTT) - **VS Code**: nRF Connect 패널 → Connected Devices → 보드 선택 → 터미널 아이콘 - **J-Link RTT Viewer**: Connection: USB, Target Device: NRF52840_XXAA ### 로그 태그 | 태그 | 내용 | |------|------| | `[BTN]` | 버튼 이벤트 (2s 홀드, 릴리스) | | `[PWR]` | 전원 래치 ON/OFF | | `[BOOT]` | 부팅 시퀀스 완료 | | `[BLE]` | BLE 연결/해제/advertising/파라미터 | | `[BLE RX]` | NUS 수신 데이터 (hex dump) | | `[NUS TX]` | NUS 송신 | | `[CMD]` | 커맨드 파서 처리 결과 | | `[BATT]` | 배터리 ADC 측정값 | | `[IMU]` | IMU 초기화/측정 | | `[ECHO]` | ADC121S051 echo capture | | `[PIEZO]` | 피에조 mux/burst/power | | `[MBB]` | 전체 측정 시퀀스 | | `[DFU]` | MCUboot 이미지 상태 | | `[SYS]` | 슬립 진입 | ## prj.conf 주요 설정 | 설정 | 값 | 역할 | |------|-----|------| | `CONFIG_GPIO` | y | GPIO 드라이버 | | `CONFIG_LOG` | y | 로깅 시스템 | | `CONFIG_LOG_BACKEND_RTT` | y | RTT 로그 출력 | | `CONFIG_SERIAL` | n | UART 비활성화 (P0.08 충돌 방지) | | `CONFIG_BT` | y | BLE 스택 | | `CONFIG_BT_NUS` | y | Nordic UART Service | | `CONFIG_BT_L2CAP_TX_MTU` | 247 | MTU 크기 | | `CONFIG_BT_CTLR_TX_PWR_PLUS_8` | y | TX power +8dBm | | `CONFIG_ADC` | y | ADC 드라이버 (배터리, 온도) | | `CONFIG_I2C` | y | IMU I2C 드라이버 | | `CONFIG_NRFX_SPIM` | y | ADC121S051용 nrfx SPIM | | `CONFIG_BOOTLOADER_MCUBOOT` | y | MCUboot 사용 | | `CONFIG_MCUMGR_TRANSPORT_BT` | y | BLE mcumgr transport | | `CONFIG_NVS` | y | NVS 플래시 저장소 | | `CONFIG_SETTINGS` | y | Zephyr settings subsystem | | `CONFIG_SETTINGS_NVS` | y | settings NVS backend | | `CONFIG_BT_SMP` | n | BLE 보안 비활성화(개발 모드) |