Raspberry Pi 4裸机操作系统开发:Hello World串口通信实践
前言
在嵌入式系统开发中,串口通信是最基础也是最重要的调试手段之一。本文将详细介绍如何在Raspberry Pi 4裸机环境下通过UART串口实现"Hello World"输出,这是操作系统开发中一个重要的里程碑。
UART串口通信基础
UART(Universal Asynchronous Receiver/Transmitter)是一种异步串行通信协议,它只需要两根信号线(TX和RX)就能实现全双工通信。在嵌入式开发中,UART常用于:
- 系统调试信息输出
- 设备间通信
- 固件更新
Raspberry Pi 4内置了多个UART控制器,我们将使用其中的Mini UART来实现基础通信功能。
硬件准备
要实现PC与RPi4的串口通信,需要以下硬件:
- USB转TTL串口线(推荐使用CP2102或PL2303芯片的转换器)
- Raspberry Pi 4开发板
- 杜邦线若干
接线方式如下:
- 串口线的GND连接RPi4的GPIO Pin6(GND)
- 串口线的RX连接RPi4的GPIO Pin8(TXD)
- 串口线的TX连接RPi4的GPIO Pin10(RXD)
注意:不要连接电源线(VCC),RPi4应由独立电源供电。
软件配置
开发机终端设置
在PC端需要使用终端模拟软件,配置参数如下:
- 波特率:115200
- 数据位:8
- 停止位:1
- 校验位:无
- 流控制:无
RPi4固件配置
在SD卡的config.txt文件中添加以下配置:
core_freq_min=500
这一行确保UART时钟稳定,保证通信可靠性。
代码实现
工程结构
项目包含以下关键文件:
- kernel.c:主程序入口
- io.h:硬件抽象层接口声明
- io.c:硬件操作具体实现
主程序实现
kernel.c中实现了简单的main函数:
#include "io.h"
void main()
{
uart_init(); // 初始化UART
uart_writeText("Hello world!\n"); // 发送字符串
while (1); // 主循环
}
硬件抽象层实现
io.h中定义了硬件操作接口:
void uart_init();
void uart_writeText(char *buffer);
io.c中实现了完整的UART驱动,包含以下关键部分:
- GPIO控制:设置引脚功能和上下拉
void gpio_useAsAlt5(unsigned int pin_number) {
gpio_pull(pin_number, Pull_None);
gpio_function(pin_number, GPIO_FUNCTION_ALT5);
}
- UART初始化:配置通信参数
void uart_init() {
mmio_write(AUX_ENABLES, 1); // 启用UART1
mmio_write(AUX_MU_LCR_REG, 3); // 8位数据
mmio_write(AUX_MU_BAUD_REG, AUX_MU_BAUD(115200)); // 波特率115200
gpio_useAsAlt5(14); // GPIO14作为TXD
gpio_useAsAlt5(15); // GPIO15作为RXD
mmio_write(AUX_MU_CNTL_REG, 3); // 启用收发
}
- 数据发送:实现阻塞式发送
void uart_writeByteBlockingActual(unsigned char ch) {
while (!uart_isWriteByteReady()); // 等待发送就绪
mmio_write(AUX_MU_IO_REG, (unsigned int)ch);
}
工作原理详解
-
内存映射IO(MMIO):RPi4通过将外设寄存器映射到内存地址空间来实现硬件控制。我们通过读写特定内存地址来配置UART。
-
波特率计算:UART通信需要双方使用相同的波特率。RPi4使用公式
(时钟频率/(波特率*8))-1
来计算波特率分频值。 -
GPIO复用功能:GPIO14和15默认是普通IO口,需要设置为ALT5功能才能作为UART的TXD和RXD使用。
常见问题排查
-
无输出:
- 检查接线是否正确(TX-RX交叉连接)
- 确认终端软件配置正确
- 检查config.txt配置
-
乱码:
- 确认双方波特率一致
- 检查时钟配置
-
部分字符丢失:
- 可能是硬件连接不稳定
- 检查接地是否良好
总结
通过本实验,我们实现了:
- Raspberry Pi 4裸机环境下的串口初始化
- 基本的字符串输出功能
- 硬件抽象层的简单设计
这是操作系统开发中的重要一步,为后续更复杂的功能开发奠定了基础。掌握了串口通信,我们就可以方便地输出调试信息,显著简化开发过程。
下一步可以考虑实现串口输入功能,或者更复杂的格式化输出,为构建完整的操作系统开发环境做准备。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考