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

操作系统原理及应用(操作系统原理及应用(linux)(第二版))svg xmlns http www w3 org 2000 svg style display none svg

大家好,我是讯享网,很高兴认识大家。



 <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path> </svg> 

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

了解virt机器

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

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

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

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

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

讯享网<ol><li>编译设备树源文件&#xff1a;将设备树源文件&#xff08;通常是以或为扩展名的文件&#xff09;编译成二进制格式&#xff0c;以便在系统引导过程中加载和使用。</li><li>反编译设备树二进制文件&#xff1a;将设备树二进制文件反编译成可读的设备树源文件&#xff0c;方便查看和修改。</li><li>转换设备树格式&#xff1a;可以将设备树源文件从一种格式转换为另一种格式&#xff0c;例如从DTS&#xff08;Device Tree Source&#xff09;格式转换为DTSI&#xff08;Device Tree Source Include&#xff09;格式&#xff0c;或者将设备树源文件转换为设备树二进制文件。</li><li>验证设备树&#xff1a;通过编译设备树源文件来验证设备树的语法和语义&#xff0c;以确保设备树描述的硬件配置是正确的。</li></ol> </li><li> <p>通过QEMU导出设备树并转成可读格式:</p> <pre></pre> </li></ol> </li></ol> 

实现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

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


小讯
上一篇 2025-05-26 15:35
下一篇 2025-05-02 20:37

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/170328.html