独立服务模式——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接口调用流程

 

 

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐