Add UART sensor support with MS overlay and diagnostics

Group UART sensors into channel slots and add an MS board overlay
with per-port speed and sensor mode configuration. Also add optional
per-second channel diagnostic output controlled by APP_DEBUG_PRINT.
This commit is contained in:
zhangyisong 2026-08-06 20:10:08 +08:00
parent 0e5d15c814
commit 214af410e4
8 changed files with 125 additions and 4 deletions

View File

@ -21,5 +21,6 @@ else()
src/led.cpp
src/temp.cpp
src/watdog.cpp
src/com.cpp
)
endif()

71
boards/use_ms.overlay Normal file
View File

@ -0,0 +1,71 @@
&ch9438_uart0 {
status = "okay";
current-speed = <9600>;
};
&gd_sensor0 {
mode = "wrist";
};
&ch9438_uart1 {
status = "okay";
current-speed = <9600>;
};
&gd_sensor1 {
mode = "wrist";
};
&ch9438_uart2 {
status = "okay";
current-speed = <9600>;
};
&gd_sensor2 {
mode = "wrist";
};
&ch9438_uart3 {
status = "okay";
current-speed = <9600>;
};
&gd_sensor3 {
mode = "wrist";
};
&ch9438_uart4 {
status = "okay";
current-speed = <9600>;
};
&gd_sensor4 {
mode = "wrist";
};
&ch9438_uart5 {
status = "okay";
current-speed = <9600>;
};
&gd_sensor5 {
mode = "wrist";
};
&ch9438_uart6 {
status = "okay";
current-speed = <9600>;
};
&gd_sensor6 {
mode = "wrist";
};
&ch9438_uart7 {
status = "okay";
current-speed = <9600>;
};
&gd_sensor7 {
mode = "wrist";
};

View File

@ -6,6 +6,7 @@
#include <etl/tuple.h>
#include <utility>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/sensor.h>
#include <zpp/result.hpp>
#include <zpp/value.hpp>
@ -71,6 +72,17 @@ public:
return out;
}
/* Bitmask of channels that have received at least one sample (diag). */
static auto GetChannelValidMask() -> uint32_t {
uint32_t mask = 0;
for (size_t id = 0; id < s_dev.size(); ++id) {
if (s_latest_valid[id]) {
mask |= (1u << id);
}
}
return mask;
}
private:
/* Per-sensor trigger handler; the channel index is a compile-time
* constant. Runs in the UART trigger context (workqueue thread for
@ -121,9 +133,20 @@ private:
return ret != 0 ? zpp::error{-ENODEV} : zpp::ok();
}
#define INFRARED_DEV(node) DEVICE_DT_GET(node),
/* Channel order: ch0~7 = CH9438 SPI-UART ports, ch8 = on-chip usart2 inner
* sensor. DT_FOREACH follows .dtsi soc node order (usart2 before spi2), so
* split by parent compatible instead of relying on node order. */
#define INFRARED_DEV(node) \
COND_CODE_1(DT_NODE_HAS_COMPAT(DT_PARENT(node), wch_ch9438_uart), \
(DEVICE_DT_GET(node), ), ())
#define INFRARED_INNER_DEV(node) \
COND_CODE_1(DT_NODE_HAS_COMPAT(DT_PARENT(node), st_stm32_usart), \
(DEVICE_DT_GET(node), ), ())
inline static etl::array s_dev{
DT_FOREACH_STATUS_OKAY(godtek_temp_uart, INFRARED_DEV)};
DT_FOREACH_STATUS_OKAY(godtek_temp_uart, INFRARED_DEV)
DT_FOREACH_STATUS_OKAY(godtek_temp_uart, INFRARED_INNER_DEV)};
#undef INFRARED_DEV
#undef INFRARED_INNER_DEV
/* Field-level volatile caches: written by the trigger handlers, read by
* GetMaxSensorValue. sensor_value itself cannot be volatile (no volatile
* copy/assign), so the two 32-bit fields are cached separately. A torn

6
src/com.cpp Normal file
View File

@ -0,0 +1,6 @@
#include <com.hpp>
#include <zephyr/init.h>
static auto Init() -> int { return static_cast<int>(ther::Com::Init()); }
inline SYS_INIT(Init, APPLICATION, 50);

View File

@ -1,8 +1,7 @@
#include <com.hpp>
#include <zephyr/device.h>
#include <zephyr/kernel.h>
auto main(void) -> int {
ther::Com::Init();
printk("[main] init on %s\n", CONFIG_BOARD);
while (1) {
k_sleep(K_SECONDS(1));

View File

@ -4,6 +4,11 @@
#include <zephyr/init.h>
#include <zephyr/kernel.h>
/* 1 = enable verbose diagnostics (per-second channel dump). */
#ifndef APP_DEBUG_PRINT
#define APP_DEBUG_PRINT 0
#endif
using namespace ther;
/* 调试打印开关:
@ -42,6 +47,18 @@ static void OnSendTick(struct k_work *work) {
if (auto r = Infrared::GetMaxSensorValue(); r.ok()) {
Com::SendTemp(r.value().second);
}
#if APP_DEBUG_PRINT
static uint32_t s_send_tick; /* diag: send counter, ~1s cadence */
if (++s_send_tick % 50 == 0) { /* every ~1 s */
const auto all = Infrared::GetAllSensorValues();
printk("[%s]diag tick=%u mask=0x%02X val:", MODULE, (unsigned)s_send_tick,
(unsigned)Infrared::GetChannelValidMask());
for (size_t i = 0; i < all.size(); ++i) {
printk(" %u=%d.%d", (unsigned)i, all[i].val1, all[i].val2);
}
printk("\n");
}
#endif /* APP_DEBUG_PRINT */
k_work_schedule(&s_send_work, K_MSEC(kPeriodSend.count()));
}
} // namespace

View File

@ -9,3 +9,7 @@ tests:
sample.ntc:
extra_configs:
- CONFIG_SAMPLE_NTC=y
sample.ms:
extra_args:
- DTC_OVERLAY_FILE=boards/use_ms.overlay
extra_configs: