了解virt机器
- 查看QEMU关于 virt的描述 , 或者查看QEMU的源码,如github上的 virt.h 和 virt.c。virt.c中可见如下有关内存映射的内容。
这段代码定义了一个静态常量数组,用于描述虚拟地址空间中各个内存区域的映射关系。例如是实际RAM区域的描述,其大小取决于初始RAM和设备内存设置,并且指定了RAM的起始地址和长度。
- 通过QEMU导出设备树
- 安装设备树格式转换工具:
设备树编译器(device tree compiler,DTC)是一个用于编译、反编译和转换设备树源文件的工具。设备树是一种用于描述硬件平台信息和设备配置的数据结构,它在嵌入式系统中广泛应用于描述硬件设备的信息,包括处理器、外围设备、总线、中断控制器等。
设备树编译器的主要用途包括:
- 编译设备树源文件:将设备树源文件(通常是以或为扩展名的文件)编译成二进制格式,以便在系统引导过程中加载和使用。
- 反编译设备树二进制文件:将设备树二进制文件反编译成可读的设备树源文件,方便查看和修改。
- 转换设备树格式:可以将设备树源文件从一种格式转换为另一种格式,例如从DTS(Device Tree Source)格式转换为DTSI(Device Tree Source Include)格式,或者将设备树源文件转换为设备树二进制文件。
- 验证设备树:通过编译设备树源文件来验证设备树的语法和语义,以确保设备树描述的硬件配置是正确的。
- 通过QEMU导出设备树并转成可读格式:
- 安装设备树格式转换工具:
实现PRT_Printf
新建 src/bsp/print.c 文件,完成如下部分。
宏定义
在 print.c 中包含所需头文件,并定义后续将会用到的宏:
串口的初始化
函数的主要作用是初始化UART的FIFO功能。它通过读取LCR寄存器,设置FIFO启用位,然后写回LCR寄存器来完成这一操作。
往串口发送字符
定义了将基址reg_base+偏移offset处寄存器的值读出寄存器,并向该寄存器中写入值的函数;定义了一个检查函数,通过Flag register中的TXFF位来判断发送缓冲是否已满,最后在最大时间范围内轮询,若发送缓冲区未满则向数据寄存器写入字符,实现发送字符到串口,达到输出字符的目的。
上面的代码很简单,就是通过轮询的方式向 PL011 的数据寄存器 DR 写入数据即可实现往串口发送字符,实现字符输出。
支持格式化输出
这段代码实现了一个基于格式化字符串的输出函数,并在内部使用了函数来实现格式化输出。函数的作用是根据给定的格式化字符串,将格式化后的字符串输出到某个设备上。
实现 vsnprintf_s 函数
新建 src/bsp/vsnprintf_s.c 实现 vsnprintf_s 函数:
调用 PRT_Printf 函数
main.c 修改为调用 PRT_Printf 函数输出信息:
将新增文件纳入构建系统
构建项目并执行
- 不启用 fifo,通过检测 UARTFR 寄存器的 TXFE 位来发送数据。
- FIFO(First In, First Out)是一种常见的数据结构,用于在数据传输过程中临时存储数据。在 UART(Universal Asynchronous Receiver/Transmitter)通信中,FIFO 用于缓冲待发送的数据和接收到的数据,以允许更高效地传输数据。UART 控制器中的 FIFO 通常包括发送 FIFO 和接收 FIFO。
发送 FIFO:用于临时存储待发送的数据,当 UART 控制器准备好发送新的数据时,会从发送 FIFO 中取出数据进行发送。
接收 FIFO:用于临时存储接收到的数据,当 UART 控制器接收到新的数据时,会将其存储到接收 FIFO 中,以便后续处理。
使用 FIFO 可以减少对 CPU 的频繁中断,提高数据传输的效率。
- TXFE 是 UARTFR 寄存器中的一个位,用于指示发送 FIFO 缓冲区是否为空。在一些 UART 控制器中,TXFE 位为 1 表示发送 FIFO 缓冲区为空,可以安全地向其中写入新的数据。因此,当 TXFE 位为 1 时,表示可以向 FIFO 缓冲区发送数据。
- FIFO(First In, First Out)是一种常见的数据结构,用于在数据传输过程中临时存储数据。在 UART(Universal Asynchronous Receiver/Transmitter)通信中,FIFO 用于缓冲待发送的数据和接收到的数据,以允许更高效地传输数据。UART 控制器中的 FIFO 通常包括发送 FIFO 和接收 FIFO。
原代码中是通过与DW_XFIFO_NOT_FULL值进行与运算来判断缓冲区是否满。
现在禁用FIFO换成检测UARTFR寄存器的TXEF位来进行判断。TXEF位是第8位,当处于空闲状态时,该位为1,有数据发送进寄存器时,该位为0,因此可以将该函数可修改为:
并将FIFO操作注释掉:
编译运行:
- 采用 UniProton 提供的 libboundscheck 库实现 vsnprintf_s 函数(可选)。
在的开源网站中,我们找到了vsnprintf_s.c文件:
将必要的头文件加入到我们的系统中:
我们将要使用到头文件中定义的函数,但头文件的函数只被定义,无函数体,在的原代码中,函数体都在单独定义的c文件中,我们将其粘贴过来,加入头文件中:
最后构建我们的系统:
尽管有一些警告,这些警告来自我的目标平台不支持这些特定的标准库函数,但这些警告通常可以被忽略。
到此这篇操作系统原理及应用(操作系统原理及应用(linux)(第二版))的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/kjbd-yiny/35976.html