OpenHarmony平台驱动——Uart
独立服务模式——UART 1、概念 UART指异步收发传输器(Universal Asynchronous Receiver/Transmitter),是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。 UART与其他模块一般用2线或4线相连,它们分别是: TX:发送数据端,和对端的RX相连。 RX:接收数据端,和对端的TX相连。 RTS:发送请求信号,用于指示本设备是否准备好
独立服务模式——UART
1、概念
UART指异步收发传输器(Universal Asynchronous Receiver/Transmitter),是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。
UART与其他模块一般用2线或4线相连,它们分别是:
-
TX:发送数据端,和对端的RX相连。
-
RX:接收数据端,和对端的TX相连。
-
RTS:发送请求信号,用于指示本设备是否准备好,可接受数据,和对端CTS相连。
-
CTS:允许发送信号,用于判断是否可以向对端发送数据,和对端RTS相连。
UART通信之前,收发双方需要约定好一些参数:波特率、数据格式(起始位、数据位、校验位、停止位)等。通信过程中,UART通过TX发送给对端数据,通过RX接收对端发送的数据。当UART接收缓存达到预定的门限值时,RTS变为不可发送数据,对端的CTS检测到不可发送数据,则停止发送数据。
2、运作机制
在HDF框架中,UART接口适配模式采用独立服务模式(如图3所示)。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDF设备管理器的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
独立服务模式下,核心层不会统一发布一个服务供上层使用,因此这种模式下驱动要为每个控制器发布一个服务,具体表现为:
-
驱动适配者需要实现HdfDriverEntry的Bind钩子函数以绑定服务。
-
device_info.hcs文件中deviceNode的policy字段为1或2,不能为0。
3、UART模块各分层作用
-
接口层提供打开UART设备、UART设备读取指定长度数据、UART设备写入指定长度数据、设置UART设备波特率、获取设UART设备波特率、设置UART设备属性、获取UART设备波特率、设置UART设备传输模式、关闭UART设备的接口。
-
核心层主要提供UART控制器的创建、移除以及管理的能力,通过钩子函数与适配层交互。
-
适配层主要是将钩子函数的功能实例化,实现具体的功能。
图1 平台驱动独立服务模式结构图
4、Uart驱动启动过程
图2 Uart驱动启动过程
配置文件
//vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs
device_uart :: device {
device0 :: deviceNode {
policy = 2;
priority = 40;
permission = 0644;
moduleName = "HDF_PLATFORM_UART";
serviceName = "HDF_PLATFORM_UART_0";
deviceMatchAttr = "rockchip_rk3568_uart_0";
}
device1 :: deviceNode {
policy = 2;
permission = 0644;
priority = 40;
moduleName = "HDF_PLATFORM_UART";
serviceName = "HDF_PLATFORM_UART_1";
deviceMatchAttr = "rockchip_rk3568_uart_1";
}
device2 :: deviceNode {
policy = 2;
permission = 0644;
priority = 40;
moduleName = "HDF_PLATFORM_UART";
serviceName = "HDF_PLATFORM_UART_3";
deviceMatchAttr = "rockchip_rk3568_uart_3";
}
}
//vendor/hihope/rk3568/hdf_config/khdf/platform/rk3568_uart_config.hcs
root {
platform {
uart_config {
template uart_device {
serviceName = "";
match_attr = "";
driver_name = "ttyS";
num = 0;
}
device_uart_0x0000 :: uart_device {
match_attr = "rockchip_rk3568_uart_0";
}
device_uart_0x0001 :: uart_device {
num = 1;
match_attr = "rockchip_rk3568_uart_1";
}
device_uart_0x0003 :: uart_device {
num = 3;
match_attr = "rockchip_rk3568_uart_3";
}
}
}
}
适配层
//drivers/hdf_core/adapter/khdf/linux/platform/uart/uart_adapter.c
//驱动入口
struct HdfDriverEntry g_hdfUartchdog = {
.moduleVersion = 1,
.moduleName = "HDF_PLATFORM_UART",
.Bind = HdfUartBind,
.Init = HdfUartInit,
.Release = HdfUartRelease,
};
HDF_INIT(g_hdfUartchdog);
static int32_t HdfUartBind(struct HdfDeviceObject *obj)
{
HDF_LOGI("HdfUartBind: entry!");
if (obj == NULL) {
HDF_LOGE("HdfUartBind: device is null!");
return HDF_ERR_INVALID_OBJECT;
}
//创建uarthost并绑定服务接口,函数实现在核心层
return (UartHostCreate(obj) == NULL) ? HDF_FAILURE : HDF_SUCCESS;
}
static int32_t HdfUartInit(struct HdfDeviceObject *obj)
{
//......
//初始化host对象,绑定属性和方法
if (iface->GetUint32(obj->property, "num", &host->num, 0) != HDF_SUCCESS) {
HDF_LOGE("HdfUartInit: read num fail!");
return HDF_FAILURE;
}
if (iface->GetString(obj->property, "driver_name", &drName, "ttyAMA") != HDF_SUCCESS) {
HDF_LOGE("HdfUartInit: read driver_name fail!");
return HDF_FAILURE;
}
g_driverName[UART_NAME_LEN - 1] = 0;
if (strlen(drName) > (UART_NAME_LEN - 1)) {
HDF_LOGE("HdfUartInit: illegal length of drName!");
return HDF_FAILURE;
}
ret = memcpy_s(g_driverName, UART_NAME_LEN, drName, strlen(drName));
if (ret != EOK) {
HDF_LOGE("HdfUartInit: memcpy_s fail!");
return HDF_FAILURE;
}
host->method = &g_uartHostMethod;
return HDF_SUCCESS;
}
//实现钩子函数
static struct UartHostMethod g_uartHostMethod = {
.Init = UartAdapterInit,
.Deinit = UartAdapterDeInit,
.Read = UartAdapterRead,
.Write = UartAdapterWrite,
.SetBaud = UartAdapterSetBaud,
.GetBaud = UartAdapterGetBaud,
.SetAttribute = UartAdapterSetAttribute,
.GetAttribute = UartAdapterGetAttribute,
.SetTransMode = UartAdapterSetTransMode,
};
核心层
//drivers/hdf_core/framework/support/platform/src/uart/uart_core.c
struct UartHost *UartHostCreate(struct HdfDeviceObject *device)
{
struct UartHost *host = NULL;
if (device == NULL) {
HDF_LOGE("UartHostCreate: device is null!");
return NULL;
}
host = (struct UartHost *)OsalMemCalloc(sizeof(*host));
if (host == NULL) {
HDF_LOGE("UartHostCreate: memcalloc error!");
return NULL;
}
host->device = device;
device->service = &(host->service);
//给host对象绑定服务接口
host->device->service->Dispatch = UartIoDispatch;
OsalAtomicSet(&host->atom, 0);
host->priv = NULL;
host->method = NULL;
return host;
}
//drivers/hdf_core/framework/support/platform/src/uart/uart_service.c
int32_t UartIoDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
{
//... ....
host = (struct UartHost *)client->device->service;
//根据用户态程序传过来的命令调用相应的接口
switch (cmd) {
case UART_IO_REQUEST:
return UartHostRequest(host);
case UART_IO_RELEASE:
return UartHostRelease(host);
case UART_IO_READ:
return UartIoRead(host, data, reply);
case UART_IO_WRITE:
return UartIoWrite(host, data);
case UART_IO_GET_BAUD:
return UartIoGetBaud(host, reply);
case UART_IO_SET_BAUD:
return UartIoSetBaud(host, data);
case UART_IO_GET_ATTRIBUTE:
return UartIoGetAttribute(host, reply);
case UART_IO_SET_ATTRIBUTE:
return UartIoSetAttribute(host, data);
case UART_IO_SET_TRANSMODE:
return UartIoSetTransMode(host, data);
default:
HDF_LOGE("UartIoDispatch: cmd %d is not support!", cmd);
return HDF_ERR_NOT_SUPPORT;
}
}
int32_t UartHostRequest(struct UartHost *host)
{
ret = host->method->Init(host);//调用钩子函数Init,与linux内核交互
if (ret != HDF_SUCCESS) {
HDF_LOGE("UartHostRequest: host init fail!");
OsalAtomicDec(&host->atom);
return ret;
}
return HDF_SUCCESS;
}
接口层
//drivers/hdf_core/framework/include/platform/uart_if.h
DevHandle UartOpen(uint32_t port);
void UartClose(DevHandle handle);
int32_t UartRead(DevHandle handle, uint8_t *data, uint32_t size);
int32_t UartWrite(DevHandle handle, uint8_t *data, uint32_t size);
int32_t UartGetBaud(DevHandle handle, uint32_t *baudRate);
int32_t UartSetBaud(DevHandle handle, uint32_t baudRate);
int32_t UartGetAttribute(DevHandle handle, struct UartAttribute *attribute);
int32_t UartSetAttribute(DevHandle handle, struct UartAttribute *attribute);
int32_t UartSetTransMode(DevHandle handle, enum UartTransMode mode);
int32_t UartBlockWrite(DevHandle handle, uint8_t *data, uint32_t size);
5、Uart接口调用流程
表1 Uart接口调用流程
更多推荐
所有评论(0)