关键流程设计
寄存器地址空间映射
由于寄存器是在用户空间配置,VE 驱动需要实现 mmap 接口,将寄存器地址空间映射到用户态进程的虚拟地址空间,以便用户态程序读写寄存器。
不同 VE 硬件版本,寄存器基地址和寄存器地址范围可能不一样,因此需要在 board.dts 中针对不同平台正确配置 reg 项(如下所示)。
ve: ve@0x18c00000 {
...
reg = <0x0 0x18c00000 0x0 0x4000>;
...
};
用户态程序映射寄存器地址空间步骤如下:
-
通过 ioctl 获取寄存器地址范围。
-
调用 mmap 映射寄存器地址空间到虚拟地址空间,并得到寄存器在虚拟地址空间的起始地址。
-
根据寄存器起始地址和偏移地址读写 VE 寄存器。
中断处理流程
VE 中断类型有三种,包括:
-
finish 中断:VE 任务正常结束
-
error 中断:VE 处理任务过程中出错
-
bit request 中断:当前数据不足以完成一次完整的任务,需要继续发送数据
- 内核 VE 驱动的中断处理比较简单,只是把中断状态返回到用户态
- 读模块的状态寄存器,并将状态值返回到用户态,由用户态程序处理。
- 关闭中断,避免中断重复发送。
- 中断超时处理,当中断在规定时间(默认值为 2 s)内未收到,则表示出现异常,此时返回出错由用户态处理。注:
- 不同模块(H264/JPEG/PNG 等)的状态寄存器不一样,读状态寄存器时需要根据模块获取相应状态寄存器的值。
- VE 每次任务处理完后,都会关闭中断,因此在下次启动 VE 前,必须再次使能 VE 中断。
- 用户态程序根据 VE 驱动返回的中断状态并处理中断
- finish 中断处理:VE 正常结束,释放 VE 硬件设备独占权限
- bit request 中断处理:再次发送一笔数据,重新启动 VE 执行任务,重复以上过程,直到 VE 返回 finish 或 error 中断
- error 中断:VE 执行出错,必须对 VE 进行硬件复位避免错误影响下次任务
- 等中断超时:此时 VE 出现未知异常,必须对 VE 进行硬件复位
注: 处理 bit request 中断时,不能释放 VE 硬件设备独占权限,因为两次任务处理有相关性。如果这两次任务之间执行其他任务,会影响 VE 内部状态,从而导致该次任务执行出错。
多进程支持
VE 设备只有一个,所以同一时间只能执行一个任务。当多个进程同时操作 VE 驱动时,VE 只能分时复用。因此用户态进程在操作 VE 之前,必须获得 VE 的独占权限。 VE 驱动通过 IOC_VE_GET_CLIENT/IOC_VE_PUT_CLIENT 这两个 ioctl 接口为用户态进程提供获取和释放 VE 独占权限功能。
- client:与进程相关的对象,保存该进程的信息,包括:进程 pid、该进程的 task、该进程使用的 dmabuf 队列等
- service:与 VE 资源相关的唯一对象,所有 client 通过 service 获取 VE 硬件的使用权限
-
VE 驱动在 probe 中创建一个唯一的 service 对象,用于管理 VE 资源
-
VE 驱动为每个进程创建一个 client 对象,用于维护该进程的 VE 状态
-
用户态进程调用 IOC_VE_GET_CLIENT 接口时,对应进程的 client 会通过 service 判断当前 VE 是否正在运行。如果是,当前 client 在此等待 VE 资源释放信号。否则得到 VE 操作权限
-
用户态进程等待当前解码任务执行完成后(等到中断),调用 IOC_VE_PUT_CLIENT 接口,当前 client 发出释放 VE 资源信号通知其它 client
多线程支持
当一个进程中的多个线程同时操作 VE 驱动时,VE 只能分时复用。为避免每个线程都执行 VE 驱动初始化等重复操作,建议用户态程序使用单例模式实现 VE 驱动调用。具体实现可参考 mpp 代码(base/ve/ve.c)。