操作系统原理及应用(操作系统原理及应用(linux)(第二版))

操作系统原理及应用(操作系统原理及应用(linux)(第二版))理解操作系统与硬件的接口方法 实现一个可打印字符的函数 非系统调用 用于后续的调试和开发 了解 virt 机器 查看 QEMU 关于 virt 的描述 或者查看 QEMU 的源码 如 github 上的 virt h 和 virt c virt c 中可见如下有关内存映射的内容 这段代码定义了一个静态常量数组 用于描述虚拟地址空间中各个内存区域的映射关系 例如是实际 RAM 区域的描述



  • 理解操作系统与硬件的接口方法
  • 实现一个可打印字符的函数(非系统调用),用于后续的调试和开发。

了解virt机器

  1. 查看QEMU关于 virt的描述 , 或者查看QEMU的源码,如github上的 virt.h 和 virt.c。virt.c中可见如下有关内存映射的内容。
 
  

这段代码定义了一个静态常量数组,用于描述虚拟地址空间中各个内存区域的映射关系。例如是实际RAM区域的描述,其大小取决于初始RAM和设备内存设置,并且指定了RAM的起始地址和长度。

  1. 通过QEMU导出设备树
    1. 安装设备树格式转换工具:
       

      设备树编译器(device tree compiler,DTC)是一个用于编译、反编译和转换设备树源文件的工具。设备树是一种用于描述硬件平台信息和设备配置的数据结构,它在嵌入式系统中广泛应用于描述硬件设备的信息,包括处理器、外围设备、总线、中断控制器等。

      设备树编译器的主要用途包括:

      1. 编译设备树源文件:将设备树源文件(通常是以或为扩展名的文件)编译成二进制格式,以便在系统引导过程中加载和使用。
      2. 反编译设备树二进制文件:将设备树二进制文件反编译成可读的设备树源文件,方便查看和修改。
      3. 转换设备树格式:可以将设备树源文件从一种格式转换为另一种格式,例如从DTS(Device Tree Source)格式转换为DTSI(Device Tree Source Include)格式,或者将设备树源文件转换为设备树二进制文件。
      4. 验证设备树:通过编译设备树源文件来验证设备树的语法和语义,以确保设备树描述的硬件配置是正确的。
    2. 通过QEMU导出设备树并转成可读格式:
       

实现PRT_Printf

新建 src/bsp/print.c 文件,完成如下部分。

image-20240412190329418

宏定义

在 print.c 中包含所需头文件,并定义后续将会用到的宏:

 
  
串口的初始化
 
  

函数的主要作用是初始化UART的FIFO功能。它通过读取LCR寄存器,设置FIFO启用位,然后写回LCR寄存器来完成这一操作。

往串口发送字符
 
  

定义了将基址reg_base+偏移offset处寄存器的值读出寄存器,并向该寄存器中写入值的函数;定义了一个检查函数,通过Flag register中的TXFF位来判断发送缓冲是否已满,最后在最大时间范围内轮询,若发送缓冲区未满则向数据寄存器写入字符,实现发送字符到串口,达到输出字符的目的。

上面的代码很简单,就是通过轮询的方式向 PL011 的数据寄存器 DR 写入数据即可实现往串口发送字符,实现字符输出。

支持格式化输出
 
  

这段代码实现了一个基于格式化字符串的输出函数,并在内部使用了函数来实现格式化输出。函数的作用是根据给定的格式化字符串,将格式化后的字符串输出到某个设备上。

实现 vsnprintf_s 函数

新建 src/bsp/vsnprintf_s.c 实现 vsnprintf_s 函数:

image-20240412192153916

调用 PRT_Printf 函数

main.c 修改为调用 PRT_Printf 函数输出信息:

 
  
将新增文件纳入构建系统

image-20240412195634194

构建项目并执行

image-20241025181042703

  1. 不启用 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 缓冲区发送数据。

    image-20241025181153351

原代码中是通过与DW_XFIFO_NOT_FULL值进行与运算来判断缓冲区是否满。

 
  

现在禁用FIFO换成检测UARTFR寄存器的TXEF位来进行判断。TXEF位是第8位,当处于空闲状态时,该位为1,有数据发送进寄存器时,该位为0,因此可以将该函数可修改为:

 
  

并将FIFO操作注释掉:

 
  

编译运行:

image-20241025181812275

  1. 采用 UniProton 提供的 libboundscheck 库实现 vsnprintf_s 函数(可选)。

在的开源网站中,我们找到了vsnprintf_s.c文件:

 
  

将必要的头文件加入到我们的系统中:

image-20240425203907173

我们将要使用到头文件中定义的函数,但头文件的函数只被定义,无函数体,在的原代码中,函数体都在单独定义的c文件中,我们将其粘贴过来,加入头文件中:

image-20240425204235607

最后构建我们的系统:

image-20241025182702425

尽管有一些警告,这些警告来自我的目标平台不支持这些特定的标准库函数,但这些警告通常可以被忽略。

今天的文章 操作系统原理及应用(操作系统原理及应用(linux)(第二版))分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2025-09-03 16:01
下一篇 2026-03-16 14:30

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/54604.html