概念

需要知晓:
- QNX 微内核是一条"软件总线",相关资源管理器挂载到该总线上;
- 设备节点 "/dev/i2c" 属于"设备资源管理器",由i2c-bcm2711可执行程序生成;
资源管理器
QNX 有两类资源管理器: "Device resource managers" 与 "Filesystem resource manager",其中 I2C 控制器驱动归属于 "Device resource managers"范畴。
- 所有 客户端 需要使用 open(或fopen) 向 服务器(资源管理器)发起连接;
- 一旦 客户端 检索到目标 服务端 后,将永久绑定;
- 所有 客户端 与 服务端 的交互基于 文件描述符(fd,或称句柄);
- 一旦关闭 文件描述符 或 文件流,意味着会话结束;
- 所有 客户端 的基于文件描述符(fd)的函数调用都将被转换成 信息(Message) 传递;
开发
工程创建
创建工程 ath10 并移动至 src/drivers/i2c/目录下,过程与最终目录结构如下:

工程配置
-
.vscode/launch.json
json{ "version": "2.0.0", "configurations": [ { "type": "qnx-gdb", "request": "launch", "name": "src/drivers/i2c/aht10/nto/aarch64/o-le/aht10", "gdb": "gdb", "program": "src/drivers/i2c/aht10/nto/aarch64/o-le/aht10", "remotePath": "aht10", "qnxtarget": "default", "upload": true, "stopAtEntry": true, "preLaunchTask": "${defaultBuildTask}" }, ] } -
.vscode/tasks.json
json{ "version": "2.0.0", "tasks": [ { "type": "shell", "label": "QNX: build debug", "command": "source ${HOME}/Workspaces/qnx800/qnxsdp-env.sh;make BUILD_PROFILE=debug PLATFORM=${config:qnx.arch} -C src/drivers/i2c/aht10", "options": { "cwd": "${workspaceFolder}", "env": { "QNX_HOST": "${env:QNX_HOST}", "QNX_TARGET": "${env:QNX_TARGET}", "MAKEFLAGS": "${env:MAKEFLAGS}", "PATH": "${env:PATH}" } }, "problemMatcher": [ "$gcc" ], "group": { "kind": "build", "isDefault": true } }, { "type": "shell", "label": "QNX: clean", "command": "make clean", "options": { "cwd": "${workspaceFolder}", "env": { "QNX_HOST": "${env:QNX_HOST}", "QNX_TARGET": "${env:QNX_TARGET}", "MAKEFLAGS": "${env:MAKEFLAGS}", "PATH": "${env:PATH}" } }, "problemMatcher": [ "$gcc" ], "group": { "kind": "build", "isDefault": false } }, ] }
驱动编码
Demo1. 直接访问 i2c1
已知 i2c-bcm2711 是主机驱动,所以可以借助该驱动直接与 AHT10 通信前,可以先打通与 i2c-bcm2711 节点的通信。
c
#include <stdio.h>
#include <fcntl.h>
#include <hw/i2c.h>
#include <ioctl.h>
#include <errno.h>
#include <string.h>
int main() {
int ret = 0, fd_i2c_s = 0;
i2c_driver_info_t info = {0};
fd_i2c_s = open ("/dev/i2c1", O_RDWR);
if (fd_i2c_s < 0) {
printf("ErrNo(%d) %s, failed to open I2C device\n", errno, strerror(errno));
return -1;
}
ret = ioctl(fd_i2c_s, DCMD_I2C_DRIVER_INFO, &info);
if (ret < 0) {
printf("ErrNo(%d) %s, failed to read from I2C device\n", errno, strerror(errno));
close(fd_i2c_s);
return -1;
}
printf("I2C Driver Info:\n");
printf(" Speed : %#X\n", info.speed_mode); /* supported speeds: I2C_SPEED_* */
printf(" Mode-Addr: %#X\n", info.addr_mode); /* supported address fmts: I2C_ADDRFMT_* */
printf(" Verbosity: %#X\n", info.verbosity); /* Driver verbosity level */
close(fd_i2c_s);
return 0;
}
注:中间代码提交可查看 Github 仓库 [链接]