Initial Commit
This commit is contained in:
+51
-6
@@ -1,7 +1,52 @@
|
|||||||
# editors
|
# Zephyr build outputs
|
||||||
*.swp
|
build/
|
||||||
*~
|
build_*/
|
||||||
|
twister-out/
|
||||||
|
.vscode/.west/
|
||||||
|
|
||||||
# build
|
# West / Zephyr local metadata
|
||||||
/build*/
|
.zephyr/
|
||||||
log.log
|
.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
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
# VesiScan BASIC - Zephyr
|
# VesiScan BASIC - Zephyr
|
||||||
|
|
||||||
- nRF52840 기반 VesiScan BASIC 펌웨어의 Zephyr/nRF Connect SDK 포팅 프로젝트
|
- nRF52840 기반 VesiScan BASIC 펌웨어의 Zephyr/nRF Connect SDK 프로젝트
|
||||||
- 현재 빌드 대상은 `nrf52840dk_nrf52840` 기준이며, MCUboot + BLE MCUmgr DFU, BLE NUS 명령, 배터리/IMU/피에조/echo ADC 측정 기능 포함
|
- 현재 빌드 대상은 `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
|
```powershell
|
||||||
west build -b nrf52840dk_nrf52840 -p auto
|
west build -b nrf52840dk_nrf52840 -p auto
|
||||||
@@ -83,7 +84,7 @@ west flash
|
|||||||
| `ECHO_MISO` | P0.15 | ADC121S051 MISO |
|
| `ECHO_MISO` | P0.15 | ADC121S051 MISO |
|
||||||
| `ECHO_CS` | P0.19 | ADC121S051 CS |
|
| `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분
|
- Normal advertising timeout: 10분
|
||||||
- DFU advertising: SMP UUID, timeout 미적용
|
- DFU advertising: SMP UUID, timeout 미적용
|
||||||
- NUS UUID 광고 포함
|
- NUS UUID 광고 포함
|
||||||
- 연결 시 LED 광고 패턴 OFF
|
|
||||||
- 연결 파라미터 선호값: 15ms / latency 0 / supervision timeout 10s
|
- 연결 파라미터 선호값: 15ms / latency 0 / supervision timeout 10s
|
||||||
- NUS TX는 mutex + completion semaphore로 순차 전송
|
- NUS TX는 mutex + completion semaphore로 순차 전송
|
||||||
- BLE RX는 별도 work queue에서 명령 처리
|
- BLE RX는 별도 work queue에서 명령 처리
|
||||||
@@ -118,7 +118,6 @@ west flash
|
|||||||
- DATA: 명령별 payload
|
- DATA: 명령별 payload
|
||||||
- CRC16: CRC-CCITT, initial `0xFFFF`
|
- CRC16: CRC-CCITT, initial `0xFFFF`
|
||||||
- 응답 TAG: 보통 요청의 `m`을 `r`로 바꾼 형태, 예: `msn?` -> `rsn:`
|
- 응답 TAG: 보통 요청의 `m`을 `r`로 바꾼 형태, 예: `msn?` -> `rsn:`
|
||||||
- 알 수 없는 명령은 `rxn:` 응답
|
|
||||||
|
|
||||||
## 구현된 명령
|
## 구현된 명령
|
||||||
|
|
||||||
@@ -131,15 +130,15 @@ west flash
|
|||||||
| `msn?` | `rsn:` | 배터리 전압 측정 | 구현 완료 |
|
| `msn?` | `rsn:` | 배터리 전압 측정 | 구현 완료 |
|
||||||
| `mls?` | `rls:` | LED 상태 변경 | 구현 완료 |
|
| `mls?` | `rls:` | LED 상태 변경 | 구현 완료 |
|
||||||
| `msp?` | `rsp:` | IMU accel/gyro 단발 측정 | 구현 완료 |
|
| `msp?` | `rsp:` | IMU accel/gyro 단발 측정 | 구현 완료 |
|
||||||
| `mst?` | `rso:` | IMU internal temperature | 구현 완료 |
|
| `mst?` | `rst:` | IMU internal temperature | 구현 완료 |
|
||||||
| `mpa?` | `rpa:` | 피에조 전원 ON | 구현 완료 |
|
| `mpa?` | `rpa:` | Piezo 전원 ON | 구현 완료, 테스트용 |
|
||||||
| `mpb?` | `rpb:` | 피에조 전원 OFF | 구현 완료 |
|
| `mpb?` | `rpb:` | Piezo 전원 OFF | 구현 완료, 테스트용 |
|
||||||
| `mpc?` | `rpc:` | 피에조 burst 테스트 | 구현 완료, 주파수 옵션은 제한적 |
|
| `mpc?` | `rpc:` | Piezo burst only | 구현 완료, 테스트용 |
|
||||||
| `mec?` | `reb:` -> `raa:` | 단일 채널 burst + echo capture | 구현 완료 |
|
| `mec?` | `reb:` -> `raa:` | 단일 채널 burst + echo capture | 구현 완료, 테스트용 |
|
||||||
| `mad?` | `reb:` -> `raa:` | ADC only capture | 구현 완료 |
|
| `mad?` | `reb:` -> `raa:` | ADC only capture | 구현 완료, 테스트용 |
|
||||||
| `maa?` | `reb:` x6 -> `raa:` | 6채널 echo sweep | 구현 완료 |
|
| `maa?` | `reb:` x6 -> `raa:` | 6채널 echo sweep | 구현 완료, 테스트용 |
|
||||||
| `mbb?` | `rbb:` -> `reb:` x6 -> `raa:` | 배터리 + IMU + 온도 + 6채널 echo | 구현 완료 |
|
| `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:` | 측정 파라미터 읽기 | 구현 완료 |
|
| `mcf?` | `rcf:` | 측정 파라미터 읽기 | 구현 완료 |
|
||||||
| `mcs?` | `rcs:` | 측정 파라미터 쓰기 | 구현 완료, NVS 저장 |
|
| `mcs?` | `rcs:` | 측정 파라미터 쓰기 | 구현 완료, NVS 저장 |
|
||||||
| `mid?` | `rid:` | HW/SN/FW identity 읽기 | 구현 완료 |
|
| `mid?` | `rid:` | HW/SN/FW identity 읽기 | 구현 완료 |
|
||||||
@@ -149,7 +148,8 @@ west flash
|
|||||||
| `mws?` | `rws:` | Serial number 쓰기 | 구현 완료, NVS 저장 |
|
| `mws?` | `rws:` | Serial number 쓰기 | 구현 완료, NVS 저장 |
|
||||||
| `mrs?` | `rrs:` | Serial number 읽기 | 구현 완료 |
|
| `mrs?` | `rrs:` | Serial number 읽기 | 구현 완료 |
|
||||||
| `mpz?` | `rpz:` | Passkey 쓰기 | 구현 완료, NVS 저장, 최초 1회만 가능 |
|
| `mpz?` | `rpz:` | Passkey 쓰기 | 구현 완료, NVS 저장, 최초 1회만 가능 |
|
||||||
| `mqz?` | `rqz:` | Passkey 읽기 | 구현 완료 |
|
| `mqz?` | `rqz:` | Passkey 읽기 | 구현 완료, 삭제 예정 |
|
||||||
|
| `mim?` | `rim:` | IMU FIFO | 구현 완료 |
|
||||||
|
|
||||||
## 저장되는 설정
|
## 저장되는 설정
|
||||||
|
|
||||||
|
|||||||
@@ -70,13 +70,13 @@ int cmd_mst(const uint8_t *data, uint8_t data_len)
|
|||||||
|
|
||||||
if ((ret != 0) || (t_cdeg == INT16_MIN))
|
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);
|
DBG_PRINTF("[CMD] mst: imu temp read fail ret=%d\r\n", ret);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 음수 온도도 2's complement로 그대로 전송 (앱이 int16로 해석)
|
// 음수 온도도 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);
|
DBG_PRINTF("[CMD] mst -> %d.%02d C\r\n", t_cdeg / 100, (t_cdeg < 0 ? -t_cdeg : t_cdeg) % 100);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,161 +0,0 @@
|
|||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user