L61 附录导读:SOWL HDF 服务一览
L61
学习目标
HDF 是 OpenHarmony 的硬件驱动框架。本课教学版应用侧签名对齐官方(HdfIoService + HdfSBuf Dispatch),非 hdf_core 二进制兼容;应用只认服务名和命令,不写死寄存器。
- 能说明 HDF 在 I/O 分层中的位置:应用 → 服务绑定 → 驱动 Dispatch/Write → 仿真宿主或真机 HAL。
- 能区分 moduleName(驱动模块)与 serviceName(应用打开的名字)。
- 能默写应用侧入口:HdfSowlBoardInit、HdfIoServiceBind、Dispatch(HdfSBuf)、HdfDeviceWrite、HdfIoServiceRecycle。
- 能按服务名对照本板 19 项外设及后续附录实验课号。
- 仿真与真机共用 Bind/READ 等应用接口;▼ 面板只负责给仿真喂传感器数值。
原理 · 深入理解
HDF 是什么
HDF(Hardware Driver Foundation)是 OpenHarmony 的硬件驱动框架:把「找设备、发命令、传数据」从芯片寄存器细节里抽出来,让应用按服务名访问外设。官方用 HCS 描述板级配置,驱动实现 HdfDriverEntry 的 Bind、Init、Release。
本课是教学子集,不是官方 hdf_core 的二进制兼容实现。配置改成静态设备表 g_sowl_devices;应用侧签名对齐官方:HdfIoServiceBind / Recycle,Dispatch(cmdId, HdfSBuf *data, HdfSBuf *reply)。概念与第六章对齐,便于在 MixGo SOWL 上把 LiteOS-M 和板载外设接起来。
把 IDeviceIoService 挂到设备对象上,上层才能按名找到它。
初始化硬件或仿真通道;Bind 失败就不应 Init。
对称拆掉服务、释放资源,防止重复加载泄漏。
当前实现:从应用到板
附录实验的共同入口是 HdfSowlBoardInit():先注册 uart/gpio 以及全部 SOWL 外设驱动,再按优先级加载设备表。应用随后只做两件事:按名绑定,再发命令或写字节。
- HdfSowlBoardInit:注册驱动 + HdfDeviceManagerInit(g_sowl_devices)。
- HdfIoServiceBind("rgb"):按 serviceName 取得 HdfIoService*(官方同形)。
- Dispatch:serv->dispatcher->Dispatch(&serv->object, cmdId, data, reply),载荷为 HdfSBuf;便捷可用 HdfIoCall。
- HdfDeviceWrite / HdfDeviceRead:字节流;本板主要用于 uart0 打日志。
- HdfIoServiceRecycle:用毕释放服务句柄(教学静态池)。
签名对齐官方:Bind 得 HdfIoService*,命令经 HdfSBuf。教学便捷 HdfIoCall 内部 Obtain/Write/Dispatch/Read/Recycle。像素参数仍可用 SowlRgbPixelArg 打成 uint32 再写入 data。
struct HdfIoService *rgb = HdfIoServiceBind("rgb");
HdfIoCall(rgb, HDF_RGB_CMD_SET_PIXEL, SowlRgbPixelArg(0, 255, 0, 0), 1, NULL);
HdfIoCall(rgb, HDF_RGB_CMD_SHOW, 0, 0, NULL);仿真与真机用同一套应用代码:Bind + Dispatch/Write。差别只在驱动底下——仿真时工作台把按键、触摸、▼ 传感器写入 0x6000FE00 起的 MMIO,驱动 READ 读到的就是这些数;真机则读真实芯片。点灯/画屏经 FX 邮箱或串口 @MIXOS_JSON 映到壳上,便于对照。应用课不要自己拼 JSON。
服务一览(19 项)
moduleName 决定加载哪份驱动,serviceName 是应用 Bind 的名字。priority 越小越先加载:uart0 为 10,便于所有实验打日志。杜邦 LED/蜂鸣/按键没有单独服务名,走 gpio 的 P1/P7/P4;电位器另有 adc。
| 服务名 | 模块 | 类别 | 附录课 |
|---|---|---|---|
| uart0 | hdf_uart | 总线 · 写日志 | 本课 / 第六章 |
| gpio | hdf_gpio | 总线 · 杜邦脚 | L77 |
| rgb | hdf_sowl_rgb | 执行 · RGB×4 | L62 |
| tft | hdf_sowl_tft | 执行 · 128×128 | L63 |
| led | hdf_sowl_led | 执行 · L1/L2 | L64 |
| keys | hdf_sowl_keys | 输入 · A1–A4/B1/B2 | L65 |
| touch | hdf_sowl_touch | 输入 · T0/T1/滑条 | L66 |
| buzzer | hdf_sowl_buzzer | 执行 · 板载喇叭 | L67 |
| adc | hdf_sowl_adc | 输入 · 电位器 0..100 | L78 |
| als | hdf_sowl_als | 传感 · 光强/接近 | L68 |
| ths | hdf_sowl_ths | 传感 · 温度/湿度×10 | L69 |
| acc | hdf_sowl_acc | 传感 · 加速度 XYZ | L70 |
| bps | hdf_sowl_bps | 传感 · 气压 Pa | L71 |
| mgs | hdf_sowl_mgs | 传感 · 地磁 XYZ | L72 |
| rfid | hdf_sowl_rfid | 传感 · UID/数据 | L73 |
| asr | hdf_sowl_asr | 传感 · 语音命令号 | L74 |
| audio | hdf_sowl_audio | 传感 · 麦克风 | L75 |
| rtc | hdf_sowl_rtc | 传感 · 时分秒 | L76 |
| wifi | hdf_sowl_wifi | 网络 · STA 教学 | 本课 / 自学 |
接口函数与命令号
执行类外设用专用 CMD 宏;传感类用 HDF_SENSOR_CMD_READ / READ2 / READ3,读数写入 reply(HdfSbufReadInt32),返回值只表示成功/失败。网络类 wifi 可用 WifiConstruct / IWiFi,或直接 Bind("wifi") + Dispatch。表中的 INJECT 不是给学生实验写的:工作台 ▼ 面板改滑条时,由壳把数值写入仿真 MMIO;真机则从 I2C/HAL 读真实芯片。应用永远只 Bind + Dispatch/READ,不必分支「是不是仿真」。gpio 的 data:低 8 位为脚号,次 8 位为电平或模式。
| 服务 | 命令 | cmd | 参数与返回 |
|---|---|---|---|
| rgb | SET_PIXEL | 1 | arg:idx<<24 | r<<16 | g<<8 | b |
| rgb | FILL / SHOW / CLEAR | 2 / 3 / 4 | FILL 的 arg 为 r<<16|g<<8|b;SHOW 提交到板 |
| tft | FILL / PIXEL / SET_XY / BRIGHT / CLEAR | 1…5 | 颜色为 RGB565;SET_XY 为 x<<8|y |
| led | SET / ONOFF / GET | 1 / 2 / 3 | arg:index<<8 | duty 或 on;index=1|2 |
| keys | READ / IS_DOWN / INJECT | 1 / 2 / 3 | 返回位图;B1=bit0 … A4=bit5 |
| touch | READ / SLIDE / VALUE / INJECT | 1…4 | bit0=T0 bit1=T1;滑条 0..100 |
| buzzer | TONE / BEEP | 1 / 2 | TONE 的 arg 为频率 Hz,0 静音 |
| adc | READ | 1 | 返回 0..100,默认对接杜邦电位器 |
| gpio | SET_MODE / WRITE / READ | 1 / 2 / 3 | 写 P1/P7 会同步杜邦 LED/蜂鸣可视化 |
| als | READ / READ2 | 1 / 2 | 光强;接近 |
| ths | READ / READ2 | 1 / 2 | 温度×10;湿度×10 |
| acc / mgs | READ / READ2 / READ3 | 1 / 2 / 3 | X / Y / Z |
| bps / audio | READ | 1 | 气压 Pa;麦克风 0..65535 |
| rfid | READ / READ2 / INJECT | 1 / 2 / 4 | UID;块数据;按下刷卡后非 0 |
| asr | READ / INJECT | 1 / 4 | 命令号,0 表示空闲 |
| rtc | READ / READ2 / READ3 | 1 / 2 / 3 | 时 / 分 / 秒 |
| wifi | ENABLE/CONNECT/STATUS/RSSI/SCAN… | 1..7 | STA:写 SSID;读状态/RSSI/扫描数 |
| uart0 | Write / Read | — | 按字节打日志;Dispatch 本板不用 |
本课实验怎么读串口
overview 实验不点灯、不读传感器:它只 Bind 上表每一个名字。成功打印「名字 ok」,缺驱动打印「MISSING」。全部通过后打印 overview ok。若某行 MISSING,先查 HdfSowlBoardInit 是否编译进 LOS_HAVE_HDF,再核对设备表里的 serviceName 拼写。
从 L62 起,每一课只深入一个服务:在本页表里找到命令,再到对应 main.c 里看 Dispatch 怎么用。仿真与真机共用同一份 main;若行为不同,查驱动里是读 MMIO 还是读 HAL,而不是改应用分支。
术语表
- HDF(硬件驱动框架)
- OpenHarmony Hardware Driver Foundation。本课为教学子集:按名发布服务,不是官方 hdf_core 的二进制兼容实现。
- HdfIoServiceBind(绑定服务)
- 按 serviceName 取得 HdfIoService*,之后才能 Write/Read/Dispatch;用毕 HdfIoServiceRecycle。
- HdfSBuf(序列化缓冲区)
- 官方 Dispatch 用 data/reply 传参;本课为教学实现(静态池),非 hdf_core ABI。
- Dispatch(命令分发)
- serv->dispatcher->Dispatch(object, cmdId, data, reply);读数在 reply,返回值是成功/失败。
- WifiConstruct(WiFi 对象)
- 教学薄封装,对齐官方名字;内部仍 Bind("wifi") + SBuf。
- MMIO(仿真寄存器)
- 基址 0x6000FE00,工作台把按键、滑条、NFC 等写入对应偏移,驱动读这些单元。
自学 · 建议步骤
先读「原理」,再动手;不要跳过检查点。
- 复习 L33/L36:Bind、Init、Release 与 I/O 分层。
- 打开 hdf_device.h,对照 HdfDriverEntry 与 IDeviceIoService。
- 浏览 hdf_sowl_board.c 的 g_sowl_devices,记下 19 个 serviceName。
- 对照 hdf_sowl_periph.h,把执行类(rgb/tft/led/buzzer)、传感类(als…rtc)和网络类(wifi)分成三列。
- 上工作台跑 overview,把串口名单勾到设备表上。
做 · 实验
- 打开工作台 lab=appendix-hdf-overview,编译后看串口是否逐行打印 uart0 ok … wifi ok。
- 对照 hdf_sowl_board.c 的设备表,核对串口名单与表中 serviceName 一致。
- 任选 rgb / keys / als / wifi,在 hdf_sowl_periph.h 中标出对应 CMD 宏。
代码导读
先读 user/appendix-hdf-overview/main.c:HdfSowlBoardInit 后 Bind/Recycle,以及 WifiConstruct 演示。再读 kernel/include/hdf/hdf_device.h 与 hdf_sbuf.h,对照官方 Dispatch(data,reply)。驱动表见 hdf_sowl_board.c。
总结与提升
- 能用自己的话解释为何应用不要直接写 GPIO 号去点灯。
- 串口出现 MixOSLesson | appendix-overview 与 overview ok。
- 能指出至少三个服务的 Bind 名和一条 Dispatch 命令。
延伸思考
- 若新增一块 I2C 温湿度芯片,应改设备表、驱动入口还是每个实验的 main?
- 仿真 MMIO 与真机 I2C 在 Dispatch 里如何分叉,而不让应用感知?
- 多任务同时 Dispatch 同一 uart0,锁应放在驱动还是应用?