openHAL
openHAL对硬件资源统一管理,对上层提供统一的硬件层API接口,对底层芯片层API如CMSIS进行二次封装,提供类Android Things、PikaPython、linux等风格接口。
- 提供可靠且稳定的标准化接口,统一管理外设,实现资源的灵活复用;
- 提供和主流软件平台兼容或适配的操作层,例如各种开源工程及系统;
- openHAL和openAPP、openDDK构建open开发框架,可用于对接各类SDK;
开发准则
- 暴露的接口尽量统一,用户可用的接口尽量全面,参数尽量封装在内部
- 时间测量接口,初始化对应时间数组,每次调用会计时,通过导出数据可以分析时间消耗
功能矩阵
HAL | startup | create/delete | open/close | read/write | ioctl/pmctl | query |
---|---|---|---|---|---|---|
PAD | √ | √ | √ | √ | √ | √ |
GPIO | √ | √ | √ | √ | √ | √ |
UART | √ | √ | √ | √ | √ | √ |
I2C | √ | √ | √ | √ | √ | √ |
KPC | - | - | - | - | - | - |
SCR | - | - | - | - | - | - |
- EC7XX系列PAD类比传统MCU的GPIO,具有唯一标识,作为其余外设的依赖;
- 除依赖IO的,还有DMA/TIM等不依赖IO的IP
接口分类
OPEN API | param[in] | param[out] | return | brief |
---|---|---|---|---|
api_xxx_startup | - | - | - | 上电初始化 |
api_xxx_default | - | - | - | 数据解析 |
api_xxx_query | √ | - | enum | 查询接口 |
api_xxx_create | √ | √ | 创建设备,动态表更新 | |
api_xxx_open | timeout | inf | enum | 开启,回调,系统通知 |
api_xxx_apply | func | cnf | enum | 预注册 |
api_xxx_ioctl | enum | 配置设备 | ||
api_xxx_pmctl | enum | 配置设备功耗/模式 | ||
api_xxx_write | √ | - | 写操作 | |
api_xxx_read | - | √ | 读操作 | |
api_xxx_close | func | - | enum | 关闭,回调,系统通知 |
api_xxx_delete | √ | - | enum | 删除设备,动态表更新 |
api_test_xxx | 测试接口 |
基本功能接口(兼容接口):
- 获取/释放资源create()/delete()
- 针对状态的查询接口 query()
- 针对设备的操作和配置 ioctl()
- startup()用于执行上电初始化,相关数据可配置传入或读特定区域flash
- default()用于解析对应数据存储到该模块的flash区域,结构化数据读取
调用类接口:
- create兼容传统api参数,实现对资源初始化,和delete接口都会更新设备列表
- open接口获取操作接口,超时返回,和close接口组合实现实现分时复用
- apply接口预申请资源,注册预配置接口,在预申请资源被释放同时执行
- ioctl是一个多功能可扩展接口,可配置硬件参数,直接操作底层设备
释放类接口:
- close接口用于释放设备占用,可传入执行函数用于配置在idle状态的执行内容
- delete将还原设备状态,发送系统通知,之后设备可以被重新create和apply
单元测试:
- 通过api_test_xxx()执行所有接口调用遍历,通过返回值确认执行情况
参考
Android Things
gpio.setEdgeTriggerType(Gpio.EDGE_BOTH);
gpio.registerGpioCallback(mGpioCallback);
gpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_HIGH);// 低电平有效
gpio.setActiveType(Gpio.ACTIVE_LOW);... // 将值切换为LOW
gpio.setValue(true);
Pika Python
采用类linux的设计,所有类型的设备操作有且仅有类似于文件的5个标准API:open()、close()、write()、read()、ioctl()
pika_dev* pika_hal_open(PIKA_HAL_DEV_TYPE dev_type, char* name);
int pika_hal_close(pika_dev* dev);
int pika_hal_ioctl(pika_dev* dev, PIKA_HAL_IOCTL_CMD cmd, ...);
int pika_hal_read(pika_dev* dev, void* buf, size_t len);
int pika_hal_write(pika_dev* dev, void* buf, size_t len);
使用方式
SUBSYS_OPENHAL_ENABLE = y
配置文件通过CSV表格打包,烧录内部文件系统,更新方式包括:
- 在工程路径下,通过编译打包直接烧录
- 通过Python脚本上传文件到文件系统
转存逻辑:从文件中提取配置信息生成响应数据结构体,再将对应的RAM结构体数据备份到指定区域,开机加载指定区域校验后写入硬件配置。
相较于devicemanage的目标芯片属性,openHAL支持更多外设资源扩展,可以作为驱动标准件。
pad
API | param[in] | param[out] | return | brief |
---|---|---|---|---|
api_pad_startup | - | √ | √ | 加载默认配置 |
api_pad_default | - | enum | ||
api_pad_create | paddr | config | enum | 申请接口 |
api_pad_open | timeout | enum | 申请接口 | |
api_pad_apply | cb | - | 申请接口 | |
api_pad_query | paddr/usrId | - | enum | 查询接口 |
api_pad_ioctl | 配置接口 | |||
api_pad_pmctl | 运行状态/功耗模式 | |||
api_pad_close | usrId | enum | 关闭接口 | |
api_pad_delete | usrId | enum | 删除接口 | |
api_test_pad | usrId | 测试接口 |
- 如果其他虚拟设备占用了IO,需要从所有可用IO列表中删除对应IO,避免再分配
api_pad_startup
默认配置数据导出,加载pad默认配置并初始化,配置文件存储区域固定,存储内容可通过文件升级方式更新;
api_pad_default
默认配置数据的解析导入
api_pad_create
api_pad_open
系统级接口,和close接口成对使用,会malloc相应任务堆栈,依赖freeRTOS消息机制管理状态和超时。
api_ret_t api_pad_open(uint32_t usrId,PadConfig_t *config,uint32_t timeout);
- 如果在超时时间内,申请的usrId是free状态,则获取成功,并以传入的config参数初始化;
- 如果在超时时间内,申请的usrId是close状态,则获取成功,pad的配置参数以config传出;
- 超时未获取成功,通过open_hal_ack_t枚举返回状态;
api_pad_apply
系统级接口,非阻塞,获取pad成功后回调,可用于共用外设端口情况
int api_pad_apply(uint32_t usrId,void *cb);
gpio
- 当前实现是基于单IO为单位,所以不需要bit操作,如果以port为单位,可以进行16bit组合封装
uart
i2c
kpc
KpcConfig_t kpcConfig;
KPC_getDefaultConfig(&kpcConfig);
kpcConfig.validRowMask = KPC_ROW_3 | KPC_ROW_2 | KPC_ROW_1 | KPC_ROW_0;
kpcConfig.validColumnMask = KPC_COLUMN_2 | KPC_COLUMN_1 | KPC_COLUMN_0;
// 480ms (12*40ms) autorepeat delay
kpcConfig.autoRepeat.delay = 12;
KPC_init(&kpcConfig, KPC_callback);
KPC_eventQueueInit();
KPC_startScan();