
概念需要知晓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{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{version:2.0.0,tasks:[{type:shell,label:QNX: build debug,command:source ${HOME}/Workspaces/qnx800/qnxsdp-env.sh;make BUILD_PROFILEdebug 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 节点的通信。#includestdio.h#includefcntl.h#includehw/i2c.h#includeioctl.h#includeerrno.h#includestring.hintmain(){intret0,fd_i2c_s0;i2c_driver_info_tinfo{0};fd_i2c_sopen(/dev/i2c1,O_RDWR);if(fd_i2c_s0){printf(ErrNo(%d) %s, failed to open I2C device\n,errno,strerror(errno));return-1;}retioctl(fd_i2c_s,DCMD_I2C_DRIVER_INFO,info);if(ret0){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);return0;}注中间代码提交可查看 Github 仓库 [链接]Demo2. 间接访问 AHT10已知 i2c-bcm2711 是主机驱动借助主机驱动直接与 AHT10 通信前在QNX下需要使用设备资源管理器 /dev/i2c1。intmain(){intret0,fd_i2c_s0;floathumidity,temp;fd_i2c_sopen(/dev/i2c1,O_RDWR);if(fd_i2c_s0){printf(ErrNo(%d) %s, failed to open I2C device\n,errno,strerror(errno));return-1;}retaht1x_begin(fd_i2c_s,AHTX0_I2CADDR_DEFAULT);if(ret0){printf([%12s|%4u] ErrNo(%d), failed to init AHT1x\n,__FILE_NAME__,__LINE__,ret);close(fd_i2c_s);return-1;}while(1){humidity0.0f;temp0.0f;retaht1x_getEvent(fd_i2c_s,AHTX0_I2CADDR_DEFAULT,humidity,temp);if(ret0){printf([%12s|%4u] ErrNo(%d), failed to read data from AHT1x\n,__FILE_NAME__,__LINE__,ret);returnret;}printf(Temperature: %2.3f ℃\n,temp);printf(Humidity : %2.3f %%rH\n,humidity);sleep(1);// wait 500ms before next read}close(fd_i2c_s);return0;}...// 核心API devctlstaticint_i2c_read(uint8_taddress,uint8_t*data,size_tlength,uint8_tstop){intret0;char*data_recvNULL;unsignedintrecv_lentsizeof(i2c_recv_t)length;// 参考 DCMD_I2C_RECV 的使用数据附加在结构体之后i2c_recv_t*data_msgNULL,*data_bufNULL;data_recvmalloc(recv_lent);if(data_recvNULL){printf(Failed to allocate memory for I2C read\n);return-1;}memset(data_recv,0,recv_lent);data_msg(i2c_recv_t*)data_recv;data_buf(char*)data_recvsizeof(*data_msg);data_msg-slave.addraddress;data_msg-slave.fmtI2C_ADDRFMT_7BIT;data_msg-lenlength;data_msg-stopstop;retdevctl(fd_i2c,DCMD_I2C_RECV,data_msg,recv_lent,NULL);if(ret0){printf([%s|%u] ErrNo(%d) %s, failed to read I2C data\n,__FILE__,__LINE__,errno,strerror(errno));returnret;}memcpy(data,data_buf,length);returnret;}注参考 QNX I2C驱动开发中对 DCMD_I2C_RECV 的说明 [链接]数据附加在结构体之后代码提交可查看 Github 仓库 [链接]演示参考About the QNX OS Programmer’s GuideDevice resource managersClient summaryQNX 框架与概念Single-threaded device resource manager