Compare commits
3 Commits
2c7eae4de1
...
5b4353d94f
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b4353d94f | |||
| 302df0230d | |||
| 82be5cae52 |
71
app.overlay
71
app.overlay
@@ -2,16 +2,7 @@
|
|||||||
|
|
||||||
/ {
|
/ {
|
||||||
chosen {
|
chosen {
|
||||||
zephyr,display = &st7789v3;
|
zephyr,boot-mode = &boot_mode0;
|
||||||
};
|
|
||||||
|
|
||||||
aliases {
|
|
||||||
backlight = &backlight;
|
|
||||||
};
|
|
||||||
|
|
||||||
zephyr,user {
|
|
||||||
vbat-en-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
|
|
||||||
io-channels = <&adc 5>, <&adc 7>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
hid_dev_0: hid_dev_0 {
|
hid_dev_0: hid_dev_0 {
|
||||||
@@ -45,64 +36,12 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&gpio0 {
|
&gpregret1 {
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&gpio1 {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&gpiote {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&led_0 {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&led_1 {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 使能 SAADC,mode_switch_module 使用 channel 7 采样模式拨码电压。 */
|
|
||||||
&adc {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&i2c1 {
|
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
ip5305: pmic@75 {
|
boot_mode0: boot_mode@0 {
|
||||||
|
compatible = "zephyr,retention";
|
||||||
status = "okay";
|
status = "okay";
|
||||||
keepalive-interval-ms = <10000>;
|
reg = <0x0 0x1>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&usbd {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
qdec: &qdec {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&spi3 {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&mipi_dbi {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&st7789v3 {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&pwm_leds {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&pwm0 {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|||||||
118
docs/nordic_ncs_官方知识索引.md
Normal file
118
docs/nordic_ncs_官方知识索引.md
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# new_kbd 项目 Nordic NCS 官方知识索引
|
||||||
|
|
||||||
|
## 说明
|
||||||
|
|
||||||
|
- 生成时间:2026-03-30
|
||||||
|
- 文档来源:仅收录 `docs.nordicsemi.com` 上可直接访问的 Nordic 官方文档
|
||||||
|
- 版本基线:按项目当前环境优先核对 `ncs-3.2.3`
|
||||||
|
- 项目芯片基线:`atguigu_mini_keyboard/nrf52840`
|
||||||
|
- 芯片依据:项目板级文件 [atguigu_mini_keyboard.yaml](E:/extra/boards/atguigu/atguigu_mini_keyboard/atguigu_mini_keyboard.yaml) 与 [atguigu_mini_keyboard.dts](E:/extra/boards/atguigu/atguigu_mini_keyboard/atguigu_mini_keyboard.dts) 明确基于 `nrf52840`
|
||||||
|
- 收录范围:仅收录 `E:\projects\new_kbd` 实际使用到的 NCS 官方知识,以及 Nordic 站点中同时存在的 Zephyr 镜像文档
|
||||||
|
- 不收录原则:如果没有核到 Nordic 官方页面,则不写入本索引
|
||||||
|
- 本版校验方式:使用浏览器渲染后再判定,凡标题或正文渲染为 `Error 404 - Page Not Found` / `ERROR CODE: 404` 的页面,均视为无效并移除
|
||||||
|
|
||||||
|
## NCS 托管的 Zephyr 文档镜像
|
||||||
|
|
||||||
|
### 构建与配置
|
||||||
|
|
||||||
|
- [应用开发总览(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/develop/application/index.html)
|
||||||
|
- [CMake 构建系统(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/build/cmake/index.html)
|
||||||
|
- [Kconfig 配置系统(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/build/kconfig/index.html)
|
||||||
|
- [Sysbuild 系统构建(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/build/sysbuild/index.html)
|
||||||
|
|
||||||
|
### 设备树与设备模型
|
||||||
|
|
||||||
|
- [设备树入门(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/build/dts/intro.html)
|
||||||
|
- [设备树 HOWTO(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/build/dts/howtos.html)
|
||||||
|
- [设备树 C/C++ API 用法(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/build/dts/api-usage.html)
|
||||||
|
- [zephyr,user 自定义节点(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/build/dts/zephyr-user-node.html)
|
||||||
|
|
||||||
|
### 内核与并发
|
||||||
|
|
||||||
|
- [工作队列与延迟工作(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/kernel/services/threads/workqueue.html)
|
||||||
|
- [原子操作(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/kernel/services/other/atomic.html)
|
||||||
|
- [自旋锁 API(NCS 镜像)](https://docs.nordicsemi.com/bundle/zephyr-apis-3.2.3/page/spinlock_8h.html)
|
||||||
|
- [时钟、超时与 uptime(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/kernel/services/timing/clocks.html)
|
||||||
|
|
||||||
|
### 日志与存储
|
||||||
|
|
||||||
|
- [日志子系统(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/services/logging/index.html)
|
||||||
|
- [Settings 设置子系统(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/services/storage/settings/index.html)
|
||||||
|
- [NVS 非易失存储(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/services/storage/nvs/nvs.html)
|
||||||
|
- [Flash Map 闪存映射(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/services/storage/flash_map/flash_map.html)
|
||||||
|
|
||||||
|
### 蓝牙 Low Energy
|
||||||
|
|
||||||
|
- [Bluetooth GAP 概览(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/connectivity/bluetooth/api/gap.html)
|
||||||
|
- [Bluetooth 连接管理(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/connectivity/bluetooth/api/connection_mgmt.html)
|
||||||
|
- [Bluetooth GATT 概览(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/connectivity/bluetooth/api/gatt.html)
|
||||||
|
- [Bluetooth 标准服务总览(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/connectivity/bluetooth/api/services.html)
|
||||||
|
|
||||||
|
### USB 与 HID
|
||||||
|
|
||||||
|
- [USB 设备栈(Device Stack Next,NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/connectivity/usb/device_next/usb_device.html)
|
||||||
|
- [USB HID 设备 API(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/connectivity/usb/device_next/api/usbd_hid_device.html)
|
||||||
|
- [HID 通用定义与报告描述符(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/connectivity/usb/api/hid.html)
|
||||||
|
|
||||||
|
### 外设驱动
|
||||||
|
|
||||||
|
- [ADC 外设概览(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/hardware/peripherals/adc.html)
|
||||||
|
- [GPIO 外设概览(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/hardware/peripherals/gpio.html)
|
||||||
|
- [I2C 外设概览(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/hardware/peripherals/i2c.html)
|
||||||
|
- [传感器子系统概览(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/hardware/peripherals/sensor/index.html)
|
||||||
|
- [LED 外设概览(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/hardware/peripherals/led.html)
|
||||||
|
|
||||||
|
### 显示与 GUI
|
||||||
|
|
||||||
|
- [显示子系统概览(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/hardware/peripherals/display/index.html)
|
||||||
|
- [PWM LEDs 设备树绑定(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/build/dts/api/bindings/led/pwm-leds.html)
|
||||||
|
- [GPIO LEDs 设备树绑定(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/build/dts/api/bindings/led/gpio-leds.html)
|
||||||
|
- [LVGL 官方示例入口(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/samples/modules/lvgl/lvgl.html)
|
||||||
|
|
||||||
|
### 通用工具宏与字节序
|
||||||
|
|
||||||
|
- [sys/byteorder 字节序 API(NCS 镜像)](https://docs.nordicsemi.com/bundle/zephyr-apis-3.2.3/page/sys_2byteorder_8h.html)
|
||||||
|
- [spinlock 文件参考(NCS API 镜像)](https://docs.nordicsemi.com/bundle/zephyr-apis-3.2.3/page/spinlock_8h.html)
|
||||||
|
|
||||||
|
## Partition Manager 与存储布局
|
||||||
|
|
||||||
|
- [Partition Manager](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/nrf/scripts/partition_manager/partition_manager.html)
|
||||||
|
|
||||||
|
## CAF 总览与基础设施
|
||||||
|
|
||||||
|
- [Common Application Framework (CAF) 总览](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/nrf/libraries/caf/caf_overview.html)
|
||||||
|
- [Application Event Manager](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/nrf/libraries/others/app_event_manager.html)
|
||||||
|
- [Application Event Manager Profiler Tracer](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/nrf/libraries/others/app_event_manager_profiler_tracer.html)
|
||||||
|
|
||||||
|
## CAF 模块
|
||||||
|
|
||||||
|
- [CAF Buttons 模块](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/nrf/libraries/caf/buttons.html)
|
||||||
|
- [CAF LEDs 模块](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/nrf/libraries/caf/leds.html)
|
||||||
|
- [CAF BLE Advertising 模块](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/nrf/libraries/caf/ble_adv.html)
|
||||||
|
- [CAF BLE State 模块](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/nrf/libraries/caf/ble_state.html)
|
||||||
|
- [CAF Power Manager 模块](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/nrf/libraries/caf/power_manager.html)
|
||||||
|
- [Settings Loader](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/nrf/applications/nrf_desktop/doc/settings_loader.html)
|
||||||
|
|
||||||
|
## CAF API / 辅助定义
|
||||||
|
|
||||||
|
- [led_effect API](https://docs.nordicsemi.com/bundle/nrf-apis-3.2.3/page/group_led_effect_CAF.html)
|
||||||
|
|
||||||
|
## 芯片与 Nordic 外设相关
|
||||||
|
|
||||||
|
- [nRF52840 驱动索引](https://docs.nordicsemi.com/bundle/nrfx-apis-3.2.3/page/nrf52840_drivers.html)
|
||||||
|
- [nRF52840 DK 用户指南](https://docs.nordicsemi.com/bundle/ug_nrf52840_dk)
|
||||||
|
- [Nordic nRF USBD 设备树绑定(NCS 镜像)](https://docs.nordicsemi.com/bundle/ncs-3.2.3/page/zephyr/build/dts/api/bindings/usb/nordic_nrf-usbd.html)
|
||||||
|
- [nrf_qdec HAL / 寄存器 API](https://docs.nordicsemi.com/bundle/nrfx-apis-3.2.3/page/group_nrf_qdec.html)
|
||||||
|
- [nrf_saadc HAL / 寄存器 API](https://docs.nordicsemi.com/bundle/nrfx-apis-3.2.3/page/group_nrf_saadc.html)
|
||||||
|
- [nrf_usbd HAL / 寄存器 API](https://docs.nordicsemi.com/bundle/nrfx-apis-3.2.3/page/group_nrf_usbd.html)
|
||||||
|
- [nrf_gpio HAL / 寄存器 API](https://docs.nordicsemi.com/bundle/nrfx-apis-3.2.3/page/group_nrf_gpio.html)
|
||||||
|
- [nrf_pwm HAL / 寄存器 API](https://docs.nordicsemi.com/bundle/nrfx-apis-3.2.3/page/group_nrf_pwm.html)
|
||||||
|
- [nrf_spi HAL / 寄存器 API](https://docs.nordicsemi.com/bundle/nrfx-apis-3.2.3/page/group_nrf_spi.html)
|
||||||
|
- [nrf_twim HAL / 寄存器 API](https://docs.nordicsemi.com/bundle/nrfx-apis-3.2.3/page/group_nrf_twim.html)
|
||||||
|
|
||||||
|
## 备注
|
||||||
|
|
||||||
|
- `pm_static.yml` 相关内容,本次仅核到 Nordic 官方的 Partition Manager 页面;未单独核到专门以 `pm_static.yml` 命名的独立官方页面,因此这里索引到 Partition Manager 官方文档
|
||||||
|
- Zephyr 侧已经收录的知识,只要在 Nordic 站点存在并通过浏览器渲染校验,本索引也一并收录
|
||||||
|
- 芯片相关知识本次按项目实际硬件基线 `nrf52840` 收录,没有扩展到未使用的其他 Nordic SoC
|
||||||
|
- 当前 Nordic 站点里,很多 `zephyr-apis-3.2.3`、`nrf-apis-3.2.3` 与部分 CAF 事件页虽然返回 `200`,但浏览器渲染后是 `Error 404 - Page Not Found`,因此已从本索引移除
|
||||||
96
docs/zephyr_官方知识索引.md
Normal file
96
docs/zephyr_官方知识索引.md
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# new_kbd 项目 Zephyr 官方知识索引
|
||||||
|
|
||||||
|
## 说明
|
||||||
|
|
||||||
|
- 生成时间:2026-03-30
|
||||||
|
- 扫描范围:`src/`、`inc/`、`prj.conf`、`sysbuild.conf`、`app.overlay`、`pm_static.yml`
|
||||||
|
- 收录原则:仅收录 `E:\projects\new_kbd` 当前实际用到、且已确认页面真实存在的 Zephyr 官方文档
|
||||||
|
- 链接范围:`https://docs.zephyrproject.org/latest/`、`https://docs.zephyrproject.org/apidoc/latest/`、`https://docs.zephyrproject.org/latest/doxygen/html/`
|
||||||
|
- 不收录范围:Nordic NCS/CAF/App Event Manager/Partition Manager 文档,以及项目自定义驱动或项目私有协议说明
|
||||||
|
- Nordic NCS 官方补充索引见:[new_kbd 项目 Nordic NCS 官方知识索引](./nordic_ncs_官方知识索引.md)
|
||||||
|
|
||||||
|
## 构建与配置
|
||||||
|
|
||||||
|
- [应用开发总览](https://docs.zephyrproject.org/latest/develop/application/index.html)
|
||||||
|
- [CMake 构建系统](https://docs.zephyrproject.org/latest/build/cmake/index.html)
|
||||||
|
- [Kconfig 配置系统](https://docs.zephyrproject.org/latest/build/kconfig/index.html)
|
||||||
|
- [Sysbuild 系统构建](https://docs.zephyrproject.org/latest/build/sysbuild/index.html)
|
||||||
|
|
||||||
|
## 设备树与设备模型
|
||||||
|
|
||||||
|
- [设备树入门](https://docs.zephyrproject.org/latest/build/dts/intro.html)
|
||||||
|
- [设备树 HOWTO](https://docs.zephyrproject.org/latest/build/dts/howtos.html)
|
||||||
|
- [设备树 C/C++ API 用法](https://docs.zephyrproject.org/latest/build/dts/api-usage.html)
|
||||||
|
- [zephyr,user 自定义节点](https://docs.zephyrproject.org/latest/build/dts/zephyr-user-node.html)
|
||||||
|
- [设备模型 API](https://docs.zephyrproject.org/apidoc/latest/group__device__model.html)
|
||||||
|
- [设备树通用标识符 API](https://docs.zephyrproject.org/apidoc/latest/group__devicetree-generic-id.html)
|
||||||
|
|
||||||
|
## 内核与并发
|
||||||
|
|
||||||
|
- [工作队列与延迟工作](https://docs.zephyrproject.org/latest/kernel/services/threads/workqueue.html)
|
||||||
|
- [原子操作](https://docs.zephyrproject.org/latest/kernel/services/other/atomic.html)
|
||||||
|
- [自旋锁 API](https://docs.zephyrproject.org/apidoc/latest/spinlock_8h.html)
|
||||||
|
- [时钟、超时与 uptime](https://docs.zephyrproject.org/latest/kernel/services/timing/clocks.html)
|
||||||
|
|
||||||
|
## 日志与存储
|
||||||
|
|
||||||
|
- [日志子系统](https://docs.zephyrproject.org/latest/services/logging/index.html)
|
||||||
|
- [Settings 设置子系统](https://docs.zephyrproject.org/latest/services/storage/settings/index.html)
|
||||||
|
- [NVS 非易失存储](https://docs.zephyrproject.org/latest/services/storage/nvs/nvs.html)
|
||||||
|
- [Flash Map 闪存映射](https://docs.zephyrproject.org/latest/services/storage/flash_map/flash_map.html)
|
||||||
|
|
||||||
|
## 蓝牙 Low Energy
|
||||||
|
|
||||||
|
- [Bluetooth GAP 概览](https://docs.zephyrproject.org/latest/connectivity/bluetooth/api/gap.html)
|
||||||
|
- [Bluetooth GAP API](https://docs.zephyrproject.org/apidoc/latest/group__bt__gap.html)
|
||||||
|
- [Bluetooth 连接管理](https://docs.zephyrproject.org/latest/connectivity/bluetooth/api/connection_mgmt.html)
|
||||||
|
- [Bluetooth 连接管理 API](https://docs.zephyrproject.org/apidoc/latest/group__bt__conn.html)
|
||||||
|
- [Bluetooth GATT 概览](https://docs.zephyrproject.org/latest/connectivity/bluetooth/api/gatt.html)
|
||||||
|
- [Bluetooth GATT Server API](https://docs.zephyrproject.org/apidoc/latest/group__bt__gatt__server.html)
|
||||||
|
- [Bluetooth UUID API](https://docs.zephyrproject.org/apidoc/latest/group__bt__uuid.html)
|
||||||
|
- [Bluetooth Battery Service (BAS) API](https://docs.zephyrproject.org/apidoc/latest/group__bt__bas.html)
|
||||||
|
- [Bluetooth 标准服务总览](https://docs.zephyrproject.org/latest/connectivity/bluetooth/api/services.html)
|
||||||
|
- [BLE HID 外设官方示例](https://docs.zephyrproject.org/latest/samples/bluetooth/peripheral_hids/README.html)
|
||||||
|
|
||||||
|
## USB 与 HID
|
||||||
|
|
||||||
|
- [USB 设备栈(Device Stack Next)](https://docs.zephyrproject.org/latest/connectivity/usb/device_next/usb_device.html)
|
||||||
|
- [USB Device API](https://docs.zephyrproject.org/apidoc/latest/group__usbd__api.html)
|
||||||
|
- [USB HID 设备 API](https://docs.zephyrproject.org/latest/connectivity/usb/device_next/api/usbd_hid_device.html)
|
||||||
|
- [USB HID Device API 参考](https://docs.zephyrproject.org/apidoc/latest/group__usbd__hid__device.html)
|
||||||
|
- [HID 通用定义与报告描述符](https://docs.zephyrproject.org/latest/connectivity/usb/api/hid.html)
|
||||||
|
- [zephyr,hid-device 设备树绑定](https://docs.zephyrproject.org/latest/build/dts/api/bindings/usb/zephyr%2Chid-device.html)
|
||||||
|
|
||||||
|
## 外设驱动
|
||||||
|
|
||||||
|
- [ADC 外设概览](https://docs.zephyrproject.org/latest/hardware/peripherals/adc.html)
|
||||||
|
- [ADC API](https://docs.zephyrproject.org/apidoc/latest/group__adc__interface.html)
|
||||||
|
- [GPIO 外设概览](https://docs.zephyrproject.org/latest/hardware/peripherals/gpio.html)
|
||||||
|
- [GPIO API](https://docs.zephyrproject.org/apidoc/latest/group__gpio__interface.html)
|
||||||
|
- [I2C 外设概览](https://docs.zephyrproject.org/latest/hardware/peripherals/i2c.html)
|
||||||
|
- [传感器子系统概览](https://docs.zephyrproject.org/latest/hardware/peripherals/sensor/index.html)
|
||||||
|
- [传感器 API](https://docs.zephyrproject.org/apidoc/latest/group__sensor__interface.html)
|
||||||
|
- [LED 外设概览](https://docs.zephyrproject.org/latest/hardware/peripherals/led.html)
|
||||||
|
- [LED API](https://docs.zephyrproject.org/apidoc/latest/group__led__interface.html)
|
||||||
|
- [Nordic nRF QDEC 设备树绑定](https://docs.zephyrproject.org/latest/build/dts/api/bindings/sensor/nordic%2Cnrf-qdec.html)
|
||||||
|
|
||||||
|
## 显示与 GUI
|
||||||
|
|
||||||
|
- [显示子系统概览](https://docs.zephyrproject.org/latest/hardware/peripherals/display/index.html)
|
||||||
|
- [MIPI-DBI SPI 设备树绑定](https://docs.zephyrproject.org/latest/build/dts/api/bindings/mipi-dbi/zephyr%2Cmipi-dbi-spi.html)
|
||||||
|
- [ST7789V 设备树绑定](https://docs.zephyrproject.org/latest/build/dts/api/bindings/display/sitronix%2Cst7789v.html)
|
||||||
|
- [PWM LEDs 设备树绑定](https://docs.zephyrproject.org/latest/build/dts/api/bindings/led/pwm-leds.html)
|
||||||
|
- [GPIO LEDs 设备树绑定](https://docs.zephyrproject.org/latest/build/dts/api/bindings/led/gpio-leds.html)
|
||||||
|
- [LVGL 官方示例入口](https://docs.zephyrproject.org/latest/samples/modules/lvgl/lvgl.html)
|
||||||
|
|
||||||
|
## 通用工具宏与字节序
|
||||||
|
|
||||||
|
- [sys/util 通用工具宏 API](https://docs.zephyrproject.org/apidoc/latest/group__sys-util.html)
|
||||||
|
- [sys/byteorder 字节序 API](https://docs.zephyrproject.org/latest/doxygen/html/sys_2byteorder_8h.html)
|
||||||
|
|
||||||
|
## 未纳入本索引的项目项
|
||||||
|
|
||||||
|
- `zephyr/drivers/power/ip5305.h`、`CONFIG_IP5305`:当前项目使用的是自定义驱动/自定义绑定,Zephyr 官方 latest 站点未核到对应官方页面,因此未纳入
|
||||||
|
- `pm_static.yml` 对应的 Partition Manager 规划:属于 Nordic NCS 范畴,不属于 Zephyr 官方 docs 站点范围;Nordic 官方索引见 [nordic_ncs_官方知识索引.md](./nordic_ncs_官方知识索引.md)
|
||||||
|
- `CAF`、`App Event Manager`、`settings_loader`、`ble_state`、`ble_common_event`、`power_manager`、`buttons_def.h` 等:属于 Nordic NCS/CAF 文档范围,不属于本 Zephyr 官方索引;Nordic 官方索引见 [nordic_ncs_官方知识索引.md](./nordic_ncs_官方知识索引.md)
|
||||||
|
- 项目私有协议与实现,如时间同步私有 GATT 服务、主机 HID 命令协议、显示主题持久化逻辑等:只索引其依赖的 Zephyr 通用能力,不索引项目私有设计本身
|
||||||
@@ -1,37 +1,31 @@
|
|||||||
mcuboot:
|
mcuboot:
|
||||||
address: 0x0
|
address: 0x0
|
||||||
end_address: 0xc000
|
end_address: 0x10000
|
||||||
region: flash_primary
|
region: flash_primary
|
||||||
size: 0xc000
|
size: 0x10000
|
||||||
|
|
||||||
mcuboot_pad:
|
mcuboot_pad:
|
||||||
address: 0xc000
|
address: 0x10000
|
||||||
end_address: 0xc200
|
end_address: 0x10200
|
||||||
region: flash_primary
|
region: flash_primary
|
||||||
size: 0x200
|
size: 0x200
|
||||||
|
|
||||||
app:
|
app:
|
||||||
address: 0xc200
|
address: 0x10200
|
||||||
end_address: 0x82000
|
end_address: 0xf8000
|
||||||
region: flash_primary
|
region: flash_primary
|
||||||
size: 0x75e00
|
size: 0xe7e00
|
||||||
|
|
||||||
mcuboot_primary:
|
mcuboot_primary:
|
||||||
address: 0xc000
|
address: 0x10000
|
||||||
end_address: 0x82000
|
end_address: 0xf8000
|
||||||
orig_span: &id001
|
orig_span: &id001
|
||||||
- mcuboot_pad
|
- mcuboot_pad
|
||||||
- app
|
- app
|
||||||
region: flash_primary
|
region: flash_primary
|
||||||
size: 0x76000
|
size: 0xe8000
|
||||||
span: *id001
|
span: *id001
|
||||||
|
|
||||||
mcuboot_secondary:
|
|
||||||
address: 0x82000
|
|
||||||
end_address: 0xf8000
|
|
||||||
region: flash_primary
|
|
||||||
size: 0x76000
|
|
||||||
|
|
||||||
settings_storage:
|
settings_storage:
|
||||||
address: 0xf8000
|
address: 0xf8000
|
||||||
end_address: 0x100000
|
end_address: 0x100000
|
||||||
|
|||||||
7
prj.conf
7
prj.conf
@@ -16,6 +16,10 @@ CONFIG_MCUMGR_GRP_OS=n
|
|||||||
CONFIG_IMG_MANAGER=n
|
CONFIG_IMG_MANAGER=n
|
||||||
CONFIG_STREAM_FLASH=n
|
CONFIG_STREAM_FLASH=n
|
||||||
|
|
||||||
|
CONFIG_RETAINED_MEM=y
|
||||||
|
CONFIG_RETENTION=y
|
||||||
|
CONFIG_RETENTION_BOOT_MODE=y
|
||||||
|
|
||||||
CONFIG_BT=y
|
CONFIG_BT=y
|
||||||
CONFIG_BT_PERIPHERAL=y
|
CONFIG_BT_PERIPHERAL=y
|
||||||
CONFIG_BT_SMP=y
|
CONFIG_BT_SMP=y
|
||||||
@@ -55,6 +59,9 @@ CONFIG_BT_HIDS_ATTR_MAX=40
|
|||||||
CONFIG_BT_HIDS_INPUT_REP_MAX=4
|
CONFIG_BT_HIDS_INPUT_REP_MAX=4
|
||||||
CONFIG_BT_HIDS_OUTPUT_REP_MAX=3
|
CONFIG_BT_HIDS_OUTPUT_REP_MAX=3
|
||||||
CONFIG_BT_HIDS_FEATURE_REP_MAX=0
|
CONFIG_BT_HIDS_FEATURE_REP_MAX=0
|
||||||
|
CONFIG_BT_BAS=y
|
||||||
|
CONFIG_BT_DIS=y
|
||||||
|
CONFIG_BT_DIS_PNP=y
|
||||||
|
|
||||||
CONFIG_USB_DEVICE_STACK_NEXT=y
|
CONFIG_USB_DEVICE_STACK_NEXT=y
|
||||||
CONFIG_USBD_HID_SUPPORT=y
|
CONFIG_USBD_HID_SUPPORT=y
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <zephyr/device.h>
|
#include <zephyr/device.h>
|
||||||
#include <zephyr/drivers/adc.h>
|
|
||||||
#include <zephyr/drivers/gpio.h>
|
|
||||||
#include <zephyr/drivers/power/ip5305.h>
|
#include <zephyr/drivers/power/ip5305.h>
|
||||||
|
#include <zephyr/drivers/sensor.h>
|
||||||
|
#include <zephyr/pm/device.h>
|
||||||
#include <zephyr/sys/atomic.h>
|
#include <zephyr/sys/atomic.h>
|
||||||
#include <zephyr/sys/util.h>
|
#include <zephyr/sys/util.h>
|
||||||
|
|
||||||
@@ -20,11 +20,8 @@
|
|||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
LOG_MODULE_REGISTER(MODULE);
|
LOG_MODULE_REGISTER(MODULE);
|
||||||
|
|
||||||
#define BATTERY_USER_NODE DT_PATH(zephyr_user)
|
#define BATTERY_SENSE_NODE DT_NODELABEL(battery_sense)
|
||||||
#define BATTERY_ADC_IO_CH_IDX 1
|
|
||||||
#define BATTERY_SAMPLE_INTERVAL_MS 1000
|
#define BATTERY_SAMPLE_INTERVAL_MS 1000
|
||||||
#define BATTERY_VDIV_NUM 2
|
|
||||||
#define BATTERY_VDIV_DEN 1
|
|
||||||
#define BATTERY_MV_WINDOW_SIZE 10
|
#define BATTERY_MV_WINDOW_SIZE 10
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -35,18 +32,26 @@ LOG_MODULE_REGISTER(MODULE);
|
|||||||
#define BATTERY_EMPTY_MV 3300
|
#define BATTERY_EMPTY_MV 3300
|
||||||
#define BATTERY_FULL_MV 4100
|
#define BATTERY_FULL_MV 4100
|
||||||
|
|
||||||
static const struct adc_dt_spec battery_adc =
|
static const struct device *const ip5305_dev = DEVICE_DT_GET(DT_NODELABEL(ip5305));
|
||||||
ADC_DT_SPEC_GET_BY_IDX(BATTERY_USER_NODE, BATTERY_ADC_IO_CH_IDX);
|
static const struct device *const battery_sensor_dev = DEVICE_DT_GET(BATTERY_SENSE_NODE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 电池采样使能脚从 zephyr,user/vbat-en-gpios 读取,避免把引脚号硬编码在 C 里。
|
* 板级电源采样结果:
|
||||||
* 后续板级改脚位只需改 DTS,不需要改固件代码。
|
* - 由 board provider 负责给出“原始但可用”的充电状态与电压值;
|
||||||
|
* - 本模块基于这些采样结果做滤波、SOC 估算和事件发布。
|
||||||
*/
|
*/
|
||||||
static const struct gpio_dt_spec battery_en_gpio =
|
struct board_power_sample
|
||||||
GPIO_DT_SPEC_GET(BATTERY_USER_NODE, vbat_en_gpios);
|
{
|
||||||
|
int32_t voltage_mv;
|
||||||
static const struct device *const ip5305_dev = DEVICE_DT_GET(DT_NODELABEL(ip5305));
|
bool charging;
|
||||||
|
bool full;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 对外上报状态:
|
||||||
|
* - 保持现有 battery_status_event 语义不变;
|
||||||
|
* - 只承载业务层需要的 charging/full/soc 三元组。
|
||||||
|
*/
|
||||||
struct battery_status
|
struct battery_status
|
||||||
{
|
{
|
||||||
bool charging;
|
bool charging;
|
||||||
@@ -62,10 +67,16 @@ struct battery_filter_state
|
|||||||
size_t index;
|
size_t index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 模块上下文:
|
||||||
|
* - sample_work 周期性拉取 board power sample;
|
||||||
|
* - filter 负责平滑电池电压;
|
||||||
|
* - last_status 用于抑制重复事件;
|
||||||
|
* - pm_restrict_level 跟踪当前对 power manager 的限制等级。
|
||||||
|
*/
|
||||||
struct battery_ctx
|
struct battery_ctx
|
||||||
{
|
{
|
||||||
struct k_work_delayable sample_work;
|
struct k_work_delayable sample_work;
|
||||||
int16_t adc_sample_buffer;
|
|
||||||
atomic_t active;
|
atomic_t active;
|
||||||
struct battery_status last_status;
|
struct battery_status last_status;
|
||||||
bool has_last_status;
|
bool has_last_status;
|
||||||
@@ -77,17 +88,14 @@ static struct battery_ctx battery = {
|
|||||||
.pm_restrict_level = POWER_MANAGER_LEVEL_MAX,
|
.pm_restrict_level = POWER_MANAGER_LEVEL_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void battery_module_resume(void);
|
/* 线性 SOC 估算:把平滑后的电池电压映射到 0~100%。 */
|
||||||
|
|
||||||
static uint8_t soc_from_mv(int32_t mv)
|
static uint8_t soc_from_mv(int32_t mv)
|
||||||
{
|
{
|
||||||
if (mv <= BATTERY_EMPTY_MV)
|
if (mv <= BATTERY_EMPTY_MV) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mv >= BATTERY_FULL_MV)
|
if (mv >= BATTERY_FULL_MV) {
|
||||||
{
|
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,109 +103,126 @@ static uint8_t soc_from_mv(int32_t mv)
|
|||||||
return (uint8_t)CLAMP(soc, 0, 100);
|
return (uint8_t)CLAMP(soc, 0, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int adc_sample_once_mv(int32_t *mv)
|
/* 初始化/恢复时清空滤波器,避免旧样本影响新一轮估算。 */
|
||||||
|
static void battery_filter_reset(void)
|
||||||
{
|
{
|
||||||
struct adc_sequence sequence = {0};
|
battery.filter.sum = 0;
|
||||||
int err = adc_sequence_init_dt(&battery_adc, &sequence);
|
battery.filter.count = 0;
|
||||||
if (err)
|
battery.filter.index = 0;
|
||||||
{
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
sequence.buffer = &battery.adc_sample_buffer;
|
|
||||||
sequence.buffer_size = sizeof(battery.adc_sample_buffer);
|
|
||||||
|
|
||||||
err = adc_read_dt(&battery_adc, &sequence);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
LOG_WRN("adc_read_dt failed (err=%d)", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
*mv = battery.adc_sample_buffer;
|
|
||||||
err = adc_raw_to_millivolts_dt(&battery_adc, mv);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
LOG_WRN("adc_raw_to_millivolts_dt failed (err=%d raw=%d)",
|
|
||||||
err, battery.adc_sample_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int read_battery_mv(int32_t *mv)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
int32_t sensed_mv;
|
|
||||||
|
|
||||||
err = adc_sample_once_mv(&sensed_mv);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 板级电池检测存在分压,ADC 读到的是分压后电压。
|
* 将最新电压样本写入固定窗口平均滤波器。
|
||||||
* 这里按分压比还原电池端真实电压,供 SOC 估算与事件上报使用。
|
* 返回值始终是“窗口平均后的电池电压”,供上层做 SOC 估算。
|
||||||
*/
|
*/
|
||||||
int32_t battery_mv = (sensed_mv * BATTERY_VDIV_NUM) / BATTERY_VDIV_DEN;
|
static int32_t battery_filter_apply(int32_t voltage_mv)
|
||||||
|
|
||||||
/*
|
|
||||||
* 使用固定窗口平均抑制采样抖动。
|
|
||||||
* 窗口未填满前按当前样本数求平均,填满后使用环形缓冲滚动更新。
|
|
||||||
*/
|
|
||||||
if (battery.filter.count < BATTERY_MV_WINDOW_SIZE)
|
|
||||||
{
|
{
|
||||||
battery.filter.window[battery.filter.index] = battery_mv;
|
if (battery.filter.count < BATTERY_MV_WINDOW_SIZE) {
|
||||||
battery.filter.sum += battery_mv;
|
battery.filter.window[battery.filter.index] = voltage_mv;
|
||||||
|
battery.filter.sum += voltage_mv;
|
||||||
battery.filter.count++;
|
battery.filter.count++;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
battery.filter.sum -= battery.filter.window[battery.filter.index];
|
battery.filter.sum -= battery.filter.window[battery.filter.index];
|
||||||
battery.filter.window[battery.filter.index] = battery_mv;
|
battery.filter.window[battery.filter.index] = voltage_mv;
|
||||||
battery.filter.sum += battery_mv;
|
battery.filter.sum += voltage_mv;
|
||||||
}
|
}
|
||||||
|
|
||||||
battery.filter.index = (battery.filter.index + 1U) % BATTERY_MV_WINDOW_SIZE;
|
battery.filter.index = (battery.filter.index + 1U) % BATTERY_MV_WINDOW_SIZE;
|
||||||
*mv = (int32_t)(battery.filter.sum / (int64_t)battery.filter.count);
|
return (int32_t)(battery.filter.sum / (int64_t)battery.filter.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 控制 board-provided battery_sense sensor 的供电状态。
|
||||||
|
* 这里不直接操纵 GPIO,而是走 sensor 的 PM action,让 power-gpios
|
||||||
|
* 与 ADC runtime PM 都由 voltage-divider 驱动统一管理。
|
||||||
|
*/
|
||||||
|
static int board_power_monitor_set_voltage_sensor_enabled(bool enable)
|
||||||
|
{
|
||||||
|
return pm_device_action_run(battery_sensor_dev,
|
||||||
|
enable ? PM_DEVICE_ACTION_RESUME :
|
||||||
|
PM_DEVICE_ACTION_SUSPEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 从 battery_sense 读取一次当前电池电压(单位 mV)。 */
|
||||||
|
static int board_power_monitor_read_voltage_mv(int32_t *voltage_mv)
|
||||||
|
{
|
||||||
|
struct sensor_value value;
|
||||||
|
int err = sensor_sample_fetch(battery_sensor_dev);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
LOG_WRN("sensor_sample_fetch(battery) failed (err=%d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sensor_channel_get(battery_sensor_dev, SENSOR_CHAN_VOLTAGE, &value);
|
||||||
|
if (err) {
|
||||||
|
LOG_WRN("sensor_channel_get(battery) failed (err=%d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*voltage_mv = (int32_t)sensor_value_to_milli(&value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 从 IP5305 读取一次充电态与满电态。 */
|
||||||
|
static int board_power_monitor_read_charge_state(bool *charging, bool *full)
|
||||||
|
{
|
||||||
|
int err = ip5305_is_charging(ip5305_dev, charging);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
LOG_WRN("ip5305_is_charging failed (err=%d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ip5305_is_charge_full(ip5305_dev, full);
|
||||||
|
if (err) {
|
||||||
|
LOG_WRN("ip5305_is_charge_full failed (err=%d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_battery_status(struct battery_status *status)
|
/*
|
||||||
|
* 聚合一次完整的 board power sample:
|
||||||
|
* 1) 先读 PMIC 状态;
|
||||||
|
* 2) 再读 battery_sense 电压;
|
||||||
|
* 3) 最后对电压做窗口平均,输出稳定值。
|
||||||
|
*/
|
||||||
|
static int board_power_monitor_collect_sample(struct board_power_sample *sample)
|
||||||
{
|
{
|
||||||
int err;
|
int32_t voltage_mv;
|
||||||
int32_t mv;
|
int err = board_power_monitor_read_charge_state(&sample->charging, &sample->full);
|
||||||
|
|
||||||
err = ip5305_is_charging(ip5305_dev, &status->charging);
|
if (err) {
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ip5305_is_charge_full(ip5305_dev, &status->full);
|
err = board_power_monitor_read_voltage_mv(&voltage_mv);
|
||||||
if (err)
|
if (err) {
|
||||||
{
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = read_battery_mv(&mv);
|
sample->voltage_mv = battery_filter_apply(voltage_mv);
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
LOG_WRN("read_battery_mv failed (err=%d)", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
status->soc = soc_from_mv(mv);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 将 board sample 映射成对外 battery status。 */
|
||||||
|
static void battery_status_from_sample(const struct board_power_sample *sample,
|
||||||
|
struct battery_status *status)
|
||||||
|
{
|
||||||
|
status->charging = sample->charging;
|
||||||
|
status->full = sample->full;
|
||||||
|
status->soc = soc_from_mv(sample->voltage_mv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 统一封装 battery_status_event 发布,隔离事件总线细节。 */
|
||||||
static void publish_battery_status_event(const struct battery_status *status)
|
static void publish_battery_status_event(const struct battery_status *status)
|
||||||
{
|
{
|
||||||
battery_status_event_submit(status->charging, status->full, status->soc);
|
battery_status_event_submit(status->charging, status->full, status->soc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 判断本轮状态是否值得上报,避免重复事件淹没总线。 */
|
||||||
static bool battery_status_changed(const struct battery_status *lhs,
|
static bool battery_status_changed(const struct battery_status *lhs,
|
||||||
const struct battery_status *rhs)
|
const struct battery_status *rhs)
|
||||||
{
|
{
|
||||||
@@ -223,99 +248,79 @@ static void update_power_restrict_by_charging(bool charging)
|
|||||||
power_manager_restrict(MODULE_IDX(MODULE), target);
|
power_manager_restrict(MODULE_IDX(MODULE), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 启停采样:
|
||||||
|
* - enable=true 时恢复 battery_sense,等待前端稳定后开始周期采样;
|
||||||
|
* - enable=false 时停止 work 并挂起 battery_sense,避免持续耗电。
|
||||||
|
*/
|
||||||
static void battery_sampling_set_enabled(bool enable)
|
static void battery_sampling_set_enabled(bool enable)
|
||||||
{
|
{
|
||||||
atomic_set(&battery.active, enable);
|
atomic_set(&battery.active, enable);
|
||||||
(void)gpio_pin_set_dt(&battery_en_gpio, enable ? GPIO_OUTPUT_ACTIVE : GPIO_OUTPUT_INACTIVE);
|
int err = board_power_monitor_set_voltage_sensor_enabled(enable);
|
||||||
|
|
||||||
if (enable)
|
if (err) {
|
||||||
{
|
LOG_WRN("board_power_monitor_set_voltage_sensor_enabled(%d) failed (err=%d)",
|
||||||
// 延迟2s开始采样等待电池电压稳定
|
enable, err);
|
||||||
k_work_reschedule(&battery.sample_work, K_MSEC(2000));
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
if (enable) {
|
||||||
|
/* 延迟开始采样,等待板上采样前端和分压网络稳定。 */
|
||||||
|
k_work_reschedule(&battery.sample_work, K_MSEC(2000));
|
||||||
|
} else {
|
||||||
(void)k_work_cancel_delayable(&battery.sample_work);
|
(void)k_work_cancel_delayable(&battery.sample_work);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 周期性读取 board power sample,并在需要时上报业务状态。 */
|
||||||
static void battery_sample_fn(struct k_work *work)
|
static void battery_sample_fn(struct k_work *work)
|
||||||
{
|
{
|
||||||
ARG_UNUSED(work);
|
ARG_UNUSED(work);
|
||||||
|
|
||||||
if (!atomic_get(&battery.active))
|
if (!atomic_get(&battery.active)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct board_power_sample sample;
|
||||||
|
struct battery_status status;
|
||||||
|
int err = board_power_monitor_collect_sample(&sample);
|
||||||
|
|
||||||
struct battery_status sampled;
|
if (err) {
|
||||||
int err = read_battery_status(&sampled);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
goto out_reschedule;
|
goto out_reschedule;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_power_restrict_by_charging(sampled.charging);
|
battery_status_from_sample(&sample, &status);
|
||||||
|
update_power_restrict_by_charging(status.charging);
|
||||||
|
|
||||||
/*
|
|
||||||
* 仅在状态发生变化时上报,避免重复事件淹没总线。
|
|
||||||
* 变化条件:充电标志、满电标志、SOC 任意一个变化。
|
|
||||||
*/
|
|
||||||
if (!battery.has_last_status ||
|
if (!battery.has_last_status ||
|
||||||
battery_status_changed(&sampled, &battery.last_status))
|
battery_status_changed(&status, &battery.last_status)) {
|
||||||
{
|
battery.last_status = status;
|
||||||
battery.last_status = sampled;
|
|
||||||
battery.has_last_status = true;
|
battery.has_last_status = true;
|
||||||
publish_battery_status_event(&sampled);
|
publish_battery_status_event(&status);
|
||||||
}
|
}
|
||||||
|
|
||||||
out_reschedule:
|
out_reschedule:
|
||||||
k_work_reschedule(&battery.sample_work, K_MSEC(BATTERY_SAMPLE_INTERVAL_MS));
|
k_work_reschedule(&battery.sample_work, K_MSEC(BATTERY_SAMPLE_INTERVAL_MS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 初始化 board power monitor consumer,并拉起首轮采样。 */
|
||||||
static int battery_module_init(void)
|
static int battery_module_init(void)
|
||||||
{
|
{
|
||||||
if (!device_is_ready(ip5305_dev))
|
if (!device_is_ready(ip5305_dev)) {
|
||||||
{
|
|
||||||
LOG_ERR("IP5305 device not ready");
|
LOG_ERR("IP5305 device not ready");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!adc_is_ready_dt(&battery_adc))
|
if (!device_is_ready(battery_sensor_dev)) {
|
||||||
{
|
LOG_ERR("Battery sense device not ready");
|
||||||
LOG_ERR("Battery ADC device not ready");
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!device_is_ready(battery_en_gpio.port))
|
|
||||||
{
|
|
||||||
LOG_ERR("Battery EN GPIO device not ready");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
int err = gpio_pin_configure_dt(&battery_en_gpio, GPIO_OUTPUT_INACTIVE);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
LOG_ERR("Battery EN GPIO configure failed (err=%d)", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = adc_channel_setup_dt(&battery_adc);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
LOG_ERR("Battery ADC channel setup failed (err=%d)", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 默认非充电态允许进入 SUSPENDED,但禁止进入 OFF。 */
|
/* 默认非充电态允许进入 SUSPENDED,但禁止进入 OFF。 */
|
||||||
update_power_restrict_by_charging(false);
|
update_power_restrict_by_charging(false);
|
||||||
|
|
||||||
k_work_init_delayable(&battery.sample_work, battery_sample_fn);
|
k_work_init_delayable(&battery.sample_work, battery_sample_fn);
|
||||||
battery.has_last_status = false;
|
battery.has_last_status = false;
|
||||||
battery.filter.sum = 0;
|
battery_filter_reset();
|
||||||
battery.filter.count = 0;
|
|
||||||
battery.filter.index = 0;
|
|
||||||
atomic_set(&battery.active, false);
|
atomic_set(&battery.active, false);
|
||||||
|
|
||||||
battery_sampling_set_enabled(true);
|
battery_sampling_set_enabled(true);
|
||||||
@@ -323,10 +328,10 @@ static int battery_module_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 响应系统挂起:停止采样,并把本模块切到 STANDBY。 */
|
||||||
static void battery_module_suspend(void)
|
static void battery_module_suspend(void)
|
||||||
{
|
{
|
||||||
if (!atomic_get(&battery.active))
|
if (!atomic_get(&battery.active)) {
|
||||||
{
|
|
||||||
/* 已经处于挂起态,避免重复上报 STANDBY 造成 power_down 循环。 */
|
/* 已经处于挂起态,避免重复上报 STANDBY 造成 power_down 循环。 */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -335,10 +340,10 @@ static void battery_module_suspend(void)
|
|||||||
module_set_state(MODULE_STATE_STANDBY);
|
module_set_state(MODULE_STATE_STANDBY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 响应系统唤醒:恢复电压传感器并重启周期采样。 */
|
||||||
static void battery_module_resume(void)
|
static void battery_module_resume(void)
|
||||||
{
|
{
|
||||||
if (atomic_get(&battery.active))
|
if (atomic_get(&battery.active)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,21 +351,18 @@ static void battery_module_resume(void)
|
|||||||
module_set_state(MODULE_STATE_READY);
|
module_set_state(MODULE_STATE_READY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 仅处理模块 ready 和系统电源状态事件,保持模块职责单一。 */
|
||||||
static bool app_event_handler(const struct app_event_header *aeh)
|
static bool app_event_handler(const struct app_event_header *aeh)
|
||||||
{
|
{
|
||||||
if (is_module_state_event(aeh))
|
if (is_module_state_event(aeh)) {
|
||||||
{
|
|
||||||
const struct module_state_event *event = cast_module_state_event(aeh);
|
const struct module_state_event *event = cast_module_state_event(aeh);
|
||||||
|
|
||||||
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY))
|
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
|
||||||
{
|
|
||||||
int err = battery_module_init();
|
int err = battery_module_init();
|
||||||
if (err)
|
|
||||||
{
|
if (err) {
|
||||||
module_set_state(MODULE_STATE_ERROR);
|
module_set_state(MODULE_STATE_ERROR);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
module_set_state(MODULE_STATE_READY);
|
module_set_state(MODULE_STATE_READY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
#include <errno.h>
|
#include <zephyr/bluetooth/services/bas.h>
|
||||||
|
|
||||||
#include <zephyr/kernel.h>
|
|
||||||
#include <zephyr/bluetooth/gatt.h>
|
|
||||||
|
|
||||||
#include <app_event_manager.h>
|
#include <app_event_manager.h>
|
||||||
|
|
||||||
@@ -13,50 +10,13 @@
|
|||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
|
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
|
||||||
|
|
||||||
static bool notify_enabled;
|
|
||||||
static uint8_t battery_level = 100U;
|
|
||||||
|
|
||||||
static void bas_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
|
|
||||||
{
|
|
||||||
ARG_UNUSED(attr);
|
|
||||||
notify_enabled = (value == BT_GATT_CCC_NOTIFY);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t read_battery_level(struct bt_conn *conn,
|
|
||||||
const struct bt_gatt_attr *attr,
|
|
||||||
void *buf,
|
|
||||||
uint16_t len,
|
|
||||||
uint16_t offset)
|
|
||||||
{
|
|
||||||
const uint8_t *value = attr->user_data;
|
|
||||||
|
|
||||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, value, sizeof(*value));
|
|
||||||
}
|
|
||||||
|
|
||||||
BT_GATT_SERVICE_DEFINE(ble_battery_svc,
|
|
||||||
BT_GATT_PRIMARY_SERVICE(BT_UUID_BAS),
|
|
||||||
BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_LEVEL,
|
|
||||||
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
|
|
||||||
BT_GATT_PERM_READ_ENCRYPT,
|
|
||||||
read_battery_level, NULL, &battery_level),
|
|
||||||
BT_GATT_CCC(bas_ccc_cfg_changed,
|
|
||||||
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
|
|
||||||
);
|
|
||||||
|
|
||||||
static bool handle_battery_status_event(const struct battery_status_event *event)
|
static bool handle_battery_status_event(const struct battery_status_event *event)
|
||||||
{
|
{
|
||||||
battery_level = battery_status_event_get_soc(event);
|
uint8_t battery_level = battery_status_event_get_soc(event);
|
||||||
|
int err = bt_bas_set_battery_level(battery_level);
|
||||||
|
|
||||||
if (!notify_enabled) {
|
if (err) {
|
||||||
return false;
|
LOG_ERR("bt_bas_set_battery_level failed: %d", err);
|
||||||
}
|
|
||||||
|
|
||||||
int err = bt_gatt_notify(NULL, &ble_battery_svc.attrs[1], &battery_level, sizeof(battery_level));
|
|
||||||
|
|
||||||
if (err == -ENOTCONN) {
|
|
||||||
LOG_WRN("BAS notify skipped: peer disconnecting");
|
|
||||||
} else if (err) {
|
|
||||||
LOG_ERR("BAS notify failed: %d", err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <zephyr/device.h>
|
#include <zephyr/device.h>
|
||||||
#include <zephyr/drivers/adc.h>
|
#include <zephyr/drivers/sensor.h>
|
||||||
#include <zephyr/drivers/gpio.h>
|
|
||||||
#include <zephyr/sys/atomic.h>
|
#include <zephyr/sys/atomic.h>
|
||||||
#include <zephyr/sys/util.h>
|
#include <zephyr/sys/util.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -18,35 +17,25 @@
|
|||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
LOG_MODULE_REGISTER(MODULE);
|
LOG_MODULE_REGISTER(MODULE);
|
||||||
|
|
||||||
#define MODE_USER_NODE DT_PATH(zephyr_user)
|
#define MODE_SENSE_NODE DT_NODELABEL(mode_sense)
|
||||||
#define MODE_ADC_IO_CH_IDX 0
|
|
||||||
#define MODE_SAMPLE_INTERVAL_MS 50
|
#define MODE_SAMPLE_INTERVAL_MS 50
|
||||||
|
|
||||||
static const struct adc_dt_spec mode_adc =
|
static const struct device *const mode_sensor_dev = DEVICE_DT_GET(MODE_SENSE_NODE);
|
||||||
ADC_DT_SPEC_GET_BY_IDX(MODE_USER_NODE, MODE_ADC_IO_CH_IDX);
|
|
||||||
|
|
||||||
static struct k_work_delayable mode_sample_work;
|
static struct k_work_delayable mode_sample_work;
|
||||||
static int16_t adc_sample_buffer;
|
|
||||||
|
|
||||||
static atomic_t active;
|
static atomic_t active;
|
||||||
static mode_type_t current_mode;
|
static mode_type_t current_mode;
|
||||||
static uint8_t mode_stable_status;
|
static uint8_t mode_stable_status;
|
||||||
|
|
||||||
static int init_adc(void)
|
static int init_mode_sensor(void)
|
||||||
{
|
{
|
||||||
if (!adc_is_ready_dt(&mode_adc))
|
if (!device_is_ready(mode_sensor_dev))
|
||||||
{
|
{
|
||||||
LOG_ERR("ADC device not ready");
|
LOG_ERR("Mode sense device not ready");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = adc_channel_setup_dt(&mode_adc);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
LOG_ERR("ADC channel setup failed (err=%d)", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,29 +70,22 @@ static mode_type_t classify_mode_from_mv(int32_t mv)
|
|||||||
|
|
||||||
static int read_mode(mode_type_t *mode)
|
static int read_mode(mode_type_t *mode)
|
||||||
{
|
{
|
||||||
struct adc_sequence sequence = {0};
|
struct sensor_value value;
|
||||||
int err = adc_sequence_init_dt(&mode_adc, &sequence);
|
int err = sensor_sample_fetch(mode_sensor_dev);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
|
LOG_WRN("sensor_sample_fetch(mode) failed (err=%d)", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
sequence.buffer = &adc_sample_buffer;
|
err = sensor_channel_get(mode_sensor_dev, SENSOR_CHAN_VOLTAGE, &value);
|
||||||
sequence.buffer_size = sizeof(adc_sample_buffer);
|
|
||||||
|
|
||||||
err = adc_read_dt(&mode_adc, &sequence);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t v = adc_sample_buffer;
|
|
||||||
err = adc_raw_to_millivolts_dt(&mode_adc, &v);
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
|
LOG_WRN("sensor_channel_get(mode) failed (err=%d)", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t v = (int32_t)sensor_value_to_milli(&value);
|
||||||
*mode = classify_mode_from_mv(v);
|
*mode = classify_mode_from_mv(v);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -187,7 +169,7 @@ static void init_mode_switch(void)
|
|||||||
if (atomic_get(&active))
|
if (atomic_get(&active))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (init_adc())
|
if (init_mode_sensor())
|
||||||
{
|
{
|
||||||
module_set_state(MODULE_STATE_ERROR);
|
module_set_state(MODULE_STATE_ERROR);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
SB_CONFIG_BOOTLOADER_MCUBOOT=y
|
SB_CONFIG_BOOTLOADER_MCUBOOT=y
|
||||||
|
SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y
|
||||||
|
|||||||
25
sysbuild/mcuboot.conf
Normal file
25
sysbuild/mcuboot.conf
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
CONFIG_LOG=n
|
||||||
|
CONFIG_CONSOLE=n
|
||||||
|
CONFIG_UART_CONSOLE=n
|
||||||
|
|
||||||
|
CONFIG_SERIAL=y
|
||||||
|
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||||
|
CONFIG_UART_LINE_CTRL=y
|
||||||
|
|
||||||
|
CONFIG_USB_DEVICE_STACK=y
|
||||||
|
CONFIG_USB_DEVICE_REMOTE_WAKEUP=n
|
||||||
|
CONFIG_USB_CDC_ACM=y
|
||||||
|
CONFIG_USB_NRFX=y
|
||||||
|
CONFIG_USB_DEVICE_PRODUCT="MCUBOOT"
|
||||||
|
CONFIG_USB_DEVICE_MANUFACTURER="new_kbd"
|
||||||
|
CONFIG_USB_DEVICE_VID=0x1209
|
||||||
|
CONFIG_USB_DEVICE_PID=0x0002
|
||||||
|
|
||||||
|
CONFIG_RETAINED_MEM=y
|
||||||
|
CONFIG_RETENTION=y
|
||||||
|
CONFIG_RETENTION_BOOT_MODE=y
|
||||||
|
|
||||||
|
CONFIG_MCUBOOT_SERIAL=y
|
||||||
|
CONFIG_BOOT_SERIAL_CDC_ACM=y
|
||||||
|
CONFIG_BOOT_SERIAL_BOOT_MODE=y
|
||||||
|
CONFIG_BOOT_SERIAL_NO_APPLICATION=y
|
||||||
23
sysbuild/mcuboot.overlay
Normal file
23
sysbuild/mcuboot.overlay
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zephyr,boot-mode = &boot_mode0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&usbd {
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
cdc_acm_uart0: cdc_acm_uart0 {
|
||||||
|
compatible = "zephyr,cdc-acm-uart";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&gpregret1 {
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
boot_mode0: boot_mode@0 {
|
||||||
|
compatible = "zephyr,retention";
|
||||||
|
status = "okay";
|
||||||
|
reg = <0x0 0x1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user