forked from EmbeddedTeam/app_photomagnetic
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:
parent
0e5d15c814
commit
214af410e4
@ -21,5 +21,6 @@ else()
|
|||||||
src/led.cpp
|
src/led.cpp
|
||||||
src/temp.cpp
|
src/temp.cpp
|
||||||
src/watdog.cpp
|
src/watdog.cpp
|
||||||
|
src/com.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
71
boards/use_ms.overlay
Normal file
71
boards/use_ms.overlay
Normal 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";
|
||||||
|
};
|
||||||
@ -6,6 +6,7 @@
|
|||||||
#include <etl/tuple.h>
|
#include <etl/tuple.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <zephyr/device.h>
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/devicetree.h>
|
||||||
#include <zephyr/drivers/sensor.h>
|
#include <zephyr/drivers/sensor.h>
|
||||||
#include <zpp/result.hpp>
|
#include <zpp/result.hpp>
|
||||||
#include <zpp/value.hpp>
|
#include <zpp/value.hpp>
|
||||||
@ -71,6 +72,17 @@ public:
|
|||||||
return out;
|
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:
|
private:
|
||||||
/* Per-sensor trigger handler; the channel index is a compile-time
|
/* Per-sensor trigger handler; the channel index is a compile-time
|
||||||
* constant. Runs in the UART trigger context (workqueue thread for
|
* constant. Runs in the UART trigger context (workqueue thread for
|
||||||
@ -121,9 +133,20 @@ private:
|
|||||||
return ret != 0 ? zpp::error{-ENODEV} : zpp::ok();
|
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{
|
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
|
/* Field-level volatile caches: written by the trigger handlers, read by
|
||||||
* GetMaxSensorValue. sensor_value itself cannot be volatile (no volatile
|
* GetMaxSensorValue. sensor_value itself cannot be volatile (no volatile
|
||||||
* copy/assign), so the two 32-bit fields are cached separately. A torn
|
* copy/assign), so the two 32-bit fields are cached separately. A torn
|
||||||
|
|||||||
6
src/com.cpp
Normal file
6
src/com.cpp
Normal 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);
|
||||||
@ -1,8 +1,7 @@
|
|||||||
|
|
||||||
#include <com.hpp>
|
#include <zephyr/device.h>
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
auto main(void) -> int {
|
auto main(void) -> int {
|
||||||
ther::Com::Init();
|
|
||||||
printk("[main] init on %s\n", CONFIG_BOARD);
|
printk("[main] init on %s\n", CONFIG_BOARD);
|
||||||
while (1) {
|
while (1) {
|
||||||
k_sleep(K_SECONDS(1));
|
k_sleep(K_SECONDS(1));
|
||||||
|
|||||||
17
src/temp.cpp
17
src/temp.cpp
@ -4,6 +4,11 @@
|
|||||||
#include <zephyr/init.h>
|
#include <zephyr/init.h>
|
||||||
#include <zephyr/kernel.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;
|
using namespace ther;
|
||||||
|
|
||||||
/* 调试打印开关:
|
/* 调试打印开关:
|
||||||
@ -42,6 +47,18 @@ static void OnSendTick(struct k_work *work) {
|
|||||||
if (auto r = Infrared::GetMaxSensorValue(); r.ok()) {
|
if (auto r = Infrared::GetMaxSensorValue(); r.ok()) {
|
||||||
Com::SendTemp(r.value().second);
|
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()));
|
k_work_schedule(&s_send_work, K_MSEC(kPeriodSend.count()));
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -9,3 +9,7 @@ tests:
|
|||||||
sample.ntc:
|
sample.ntc:
|
||||||
extra_configs:
|
extra_configs:
|
||||||
- CONFIG_SAMPLE_NTC=y
|
- CONFIG_SAMPLE_NTC=y
|
||||||
|
sample.ms:
|
||||||
|
extra_args:
|
||||||
|
- DTC_OVERLAY_FILE=boards/use_ms.overlay
|
||||||
|
extra_configs:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user