鸿蒙移植i.mx6ull(九) 串口移植(基于IMX6ULL)

简介: 鸿蒙移植i.mx6ull(九) 串口移植(基于IMX6ULL)

1. Liteos-a中串口的使用


1.1 内核里打印


内核打印函数是PRINT_RELEASE,它的内部调用关系如下:

PRINT_RELEASE
    LOS_LkPrint
      g_osLkHook
      OsLkDefaultFunc
        OsVprintf
        UartPuts
          UartPutsReg
          UartPutStr
            UartPutcReg


我们要实现UartPutcReg,用来输出单个字符。


1.2 APP控制台


我们编写的应用程序,调用printf时,那些信息从哪里打印出来?从控制台。 在串口上运行程序,控制台就是串口。

远程登录板子后运行程序,控制台就是远程登录终端。


控制台的实现分为4层:

image.png


1.2.1 /dev/console


init进程打开的就是/dev/console,它会打开shell。

我们在shell里执行各种APP时,这些APP会继承父进程的3个设备:标准输入、标准输出、标准错误,都对应/dev/console。

我们编写的APP,一般不需要自己去打开/dev/console,它已经继承得到了。

在串口上运行程序,/dev/console就是串口。 远程登录板子后运行程序,/dev/console就是远程登录终端。

所以/dev/console表示的是当前终端,它可能对应不同的设备,比如/dev/serial或/dev/telnet。


1.2.2 /dev/serial


在Liteos-a中,/dev/serial被称为virtual serial,虚拟串口。它只是起一个中转的作用,无论是APP还是内核,使用/dev/serial时,都是再次跳转去执行具体串口设备驱动程序的函数。比如:

1671001510659.jpg

那么,/dev/serial这个虚拟串口,怎么跟具体串口挂钩?也就是上图中,GetFileOps函数为何能得到具体串口的驱动程序?

方法如下图所示:

1671001518923.jpg

virtual_serial_init函数会找到/dev/uartdev-0的驱动程序(即它对应的struct inode,里面含有file_operations_vfs)。


1.2.3 /dev/uartddev-0


1. 总体介绍

这是真正操作硬件的驱动程序,它分为两部分:device_t、driver_t。


在device_t中设置资源,比如寄存器物理基地址、中断号等

在driver_t中提供函数,比如device_probe、device_attach函数

当内核发现有名字系统的device_t、driver_t时

就会调用driver_t中的device_probe、device_attach函数

在里面根据device_t得到资源、注册驱动register_driver

这种写驱动程序的方法,被称为分离:操作函数、资源分离。

以后想换一个硬件,只需要修改device_t就可以,driver_t保存不变。


2. device_t

示例代码:

1671001530714.jpg

3. drvier_t

先注册一个drvier_t结构体,它里面带有各类device_method_t:

1671001539408.jpg

当内核发现有同名的device_t和driver_t时,就会调用driver_t里面提供的device_probe、device_attach函数。


4. uartdev_fops

在device_attach函数里从device_t里获取硬件资源、注册驱动:

1671001548550.jpg

/dev/uartdev-0对应的驱动程序时uartdev_fops,它通过uart_ops来操作硬件。


1.2.4 uart_ops


在UART驱动程序里,我们只需要提供硬件操作部分:

1671001558180.jpg

uart_ops里有4个函数:


config:配置串口,比如波特率等

startup:启动串口,比如注册中断处理函数、启动串口

start_tx:发送字符串

shutdown:关闭串口

串口就两大功能:发送数据、接收数据。

在Liteos-a中,发送数据比较简单:没有使用中断,而是使用查询方式逐个发送,核心是UartPutcReg。

接收数据时使用中断,所以需要注册串口接收中断处理函数,它要做的事情是:


发生中断时,读取硬件获得字符,可能有多个字符

处理特殊字符:比如不`\r`换为`\n`

通知上层代码:udd->recv(udd, buf, count);


2. 串口移植


我们的目标是:让最小系统启动。 那么对于串口,不需要考虑得很全面:


不需要初始化串口:u-boot已经初始化串口了

不需要动态配置串口:固定使用某个波特率等配置就可以(在u-boot里设置过了)

移植工作只需要实现这几点:


串口发送单个字符


注册串口接收中断函数:确定中断号、使能中断、在中断函数中读取数据


2.1 最终结果


本章节做的修改会制作为补丁文件:


03_openharmony_uart_imx6ull.patch

假设目录openharmony中是未修改的代码,从没打过补丁;

假设补丁文件放在openharmony的同级目录; 打补丁方法如下:

$ cd openharmony
$ patch -p1 < ../openharmony_100ask_v1.2.patch
$ patch -p1 < ../01_openharmony_add_demo_board.patch
$ patch -p1 < ../02_openharmony_memmap_imx6ull.patch 
$ patch -p1 < ../03_openharmony_uart_imx6ull.patch


打上补丁后,可以如此编译:

$ cd kernel/liteos_a
$ cp tools/build/config/debug/demochip_clang.config .config
$ make clean
$ make


2.2 串口发送单个字符


2.3 在device_t中指定资源


需要确定2个资源:寄存器地址、中断号


2.4 实现uart_ops


在UART驱动程序里,uart_ops结构体封装了UART的硬件操作:

1671001599583.jpg

uart_ops里有4个函数:


config:配置串口,比如波特率等

startup:启动串口,比如注册中断处理函数、启动串口

start_tx:发送字符串

shutdown:关闭串口

我们只需要实现startup、start_tx,其他函数可以设为空:


startup:确定中断号、request_irq、使能中断、提供中断处理函数

start_tx:发送字符串


2.5 GIC


在kernel\liteos_a\platform\main.c中,调用OsSystemInfo打印系统信息时,代码如下:

PRINT_RELEASE("\n******************Welcome******************\n\n"
            "Processor   : %s"
#if (LOSCFG_KERNEL_SMP == YES)
            " * %d\n"
            "Run Mode    : SMP\n"
#else
            "\n"
            "Run Mode    : UP\n"
#endif
            "GIC Rev     : %s\n"
            "build time  : %s %s\n"
            "Kernel      : %s %d.%d.%d.%d/%s\n"
            "\n*******************************************\n",
            LOS_CpuInfo(),
#if (LOSCFG_KERNEL_SMP == YES)
            LOSCFG_KERNEL_SMP_CORE_NUM,
#endif
            HalIrqVersion(), __DATE__, __TIME__,\
            KERNEL_NAME, KERNEL_MAJOR, KERNEL_MINOR, KERNEL_PATCH, KERNEL_ITRE, buildType);


里面的HalIrqVersion函数用到的GIC的虚拟地址,要正确设置,否则没有打印信息。

IMX6ULL的内存映射代码里,设备空间从GIC开始映射,所以GIC的虚拟地址就是PERIPH_DEVICE_BASE:

// kernel/liteos_a/kernel/base/include/los_vm_zone.h
#define GIC_VIRT_BASE    PERIPH_DEVICE_BASE
// vendor/democom/demochip/board/include/asm/platform.h
#define GIC_BASE_ADDR             (GIC_VIRT_BASE)
相关文章
|
Linux 芯片
鸿蒙移植i.mx6ull(十) 系统时钟
鸿蒙移植i.mx6ull(十) 系统时钟
303 0
鸿蒙移植i.mx6ull(十) 系统时钟
|
Shell Python
鸿蒙移植i.mx6ull(十二) 根文件系统
鸿蒙移植i.mx6ull(十二) 根文件系统
200 0
鸿蒙移植i.mx6ull(十二) 根文件系统
|
存储 Linux 内存技术
鸿蒙移植i.mx6ull(十一) 存储设备驱动程序(基于IMX6ULL)
鸿蒙移植i.mx6ull(十一) 存储设备驱动程序(基于IMX6ULL)
320 0
鸿蒙移植i.mx6ull(十一) 存储设备驱动程序(基于IMX6ULL)
|
C语言
鸿蒙移植i.mx6ull(八) 添加一个单板(下)
鸿蒙移植i.mx6ull(八) 添加一个单板
133 0
鸿蒙移植i.mx6ull(八) 添加一个单板(下)
|
芯片
鸿蒙移植i.mx6ull(八) 添加一个单板(上)
鸿蒙移植i.mx6ull(八) 添加一个单板
306 0
鸿蒙移植i.mx6ull(八) 添加一个单板(上)
|
物联网
鸿蒙移植i.mx6ull (七) Liteos-a的编译系统(下)
鸿蒙移植i.mx6ull (七) Liteos-a的编译系统
332 0
鸿蒙移植i.mx6ull (七) Liteos-a的编译系统(下)
|
6天前
|
UED
鸿蒙next版开发:相机开发-适配不同折叠状态的摄像头变更(ArkTS)
在HarmonyOS 5.0中,ArkTS提供了强大的相机开发能力,特别是针对折叠屏设备的摄像头适配。本文详细介绍了如何在ArkTS中检测和适配不同折叠状态下的摄像头变更,确保相机应用在不同设备状态下的稳定性和用户体验。通过代码示例展示了具体的实现步骤。
29 8
|
6天前
|
API 内存技术
鸿蒙next版开发:相机开发-拍照(ArkTS)
在HarmonyOS 5.0中,ArkTS提供了一套完整的API来管理相机功能,特别是拍照功能。本文详细介绍如何在ArkTS中实现拍照功能,包括导入接口、创建会话、配置会话、触发拍照及监听拍照输出流状态,并提供代码示例进行详细解读。通过本文,你将掌握如何在HarmonyOS 5.0中使用ArkTS实现高效的拍照功能。
25 7
|
6天前
|
监控 开发者
鸿蒙next版开发:使用HiDebug获取调试信息(ArkTS)
在HarmonyOS 5.0中,HiDebug是一个强大的应用调试工具,可帮助开发者获取系统的CPU使用率、内存信息等关键性能数据。本文详细介绍了如何在ArkTS中使用HiDebug,并提供了示例代码,帮助开发者进行性能分析和问题诊断。
24 7
|
1天前
|
Android开发
鸿蒙开发:自定义一个简单的标题栏
本身就是一个很简单的标题栏组件,没有什么过多的技术含量,有一点需要注意,当使用沉浸式的时候,注意标题栏的位置,需要避让状态栏。
鸿蒙开发:自定义一个简单的标题栏