英特尔伽利略裸机UART [英] Intel Galileo bare metal UART
问题描述
我想在 Intel Galileo 板上编写一个小hello world"裸机应用程序.当然,使用 UEFI 打印文本(到 UART-1)效果很好,但我想在没有 UEFI 任何帮助的情况下手动"访问 UART.
I want to program a little "hello world" bare metal application on the Intel Galileo board. Using UEFI to print out text (to UART-1) works well, of course, but I want to access the UART "manually", without any help from UEFI.
在 QEMU 中,我的代码运行良好:
In QEMU my code works well:
#define COM1_PORT (0x03F8)
#define UART_PORT (COM1_PORT)
enum uart_port_offs_t
{ // DLAB RW
THR = 0, // 0 W Transmitter Holding Buffer
RBR = 0, // 0 R Receiver Buffer
DLL = 0, // 1 RW Divisor Latch Low Byte
IER = 1, // 0 RW Interrupt Enable Register
DLH = 1, // 1 RW Divisor Latch High Byte
IIR = 2, // - R Interrupt Identification Register
FCR = 2, // - RW FIFO Control Register
LCR = 3, // - RW Line Control Register
MCR = 4, // - RW Modem Control Register
LSR = 5, // - R Line Status Register
MSR = 6, // - R Modem Status Register
SR = 7, // - RW Scratch Register
};
.c 文件
void uart_init(void)
{
outb(UART_PORT + IER, 0x00); // Disable all interrupts
outb(UART_PORT + LCR, LCR_DLAB);
outb(UART_PORT + DLL, BAUD_LL); // Set divisor (lo byte)
outb(UART_PORT + DLH, BAUD_HL); // (hi byte)
outb(UART_PORT + LCR, LCR_WORD_BITS_8 | LCR_PAR_NONE | LCR_STOP_BITS_1);
outb(UART_PORT + FCR, FCR_ENABLE | FCR_CLR_RECV | FCR_CLR_SEND | FCR_TRIGGER_16);
outb(UART_PORT + MCR, MCR_DSR | MCR_RTS | MCR_AUX2);
}
ssize_t uart_write(const char *buf, size_t len)
{
size_t written = 0;
while (written < len) {
while (!is_output_empty()) {
asm volatile ("pause");
}
outb(UART_PORT + THR, buf[written]);
++written;
}
return written;
}
主要
SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Exiting EFI boot services ...\r\n");
SystemTable->BootServices->ExitBootServices(ImageHandle, map_key);
uart_init();
while (1) {
const char s[] = "UART\r\n";
uart_write(s, sizeof (s) - 1);
}
规格对我没有太大帮助.我猜英特尔 Galileo 板上的 UART 不使用/模拟普通/传统 COM 端口 3F8h、2F8h、3E8h 或 2E8h.
The specs did not help me very much. I guess that the UARTs on the Intel Galileo board don't use/emulate the normal/legacy COM ports 3F8h, 2F8h, 3E8h, or 2E8h.
谁能告诉我我做错了什么,甚至可以发布一个最小的裸机 hello world 示例?
Can anyone tell me what I am doing wrong, or even post a minimal bare metal hello world example?
推荐答案
我假设您的目标是串行端口,它是 Intel Galileo 板上的类音频"连接器.
I assume you are aiming at the serial port that is the "audio-like" connector on the Intel Galileo board.
以下是一些应该会有所帮助的资源:
Here are a few resources that should help:
- 伽利略原理图
- 英特尔 Quark SoC X1000 数据表
- 英特尔伽利略 IO 映射
- Sergey 的关于为伽利略配置串行端口的博客条目
- 英特尔 Quark 板支持包下载,包括
- 板级支持包来源(目前为 ver.1.0.0)
- 英特尔 Quark SoC X1000 UEFI 固件编写者指南
- Galileo schematic
- Intel Quark SoC X1000 datasheet
- Intel Galileo IO Mapping
- Sergey's blog entry about Configuring the Serial Port for Galileo
- Intel Quark Board Support Package downloads, including
- Board Support Package Sources (currently ver.1.0.0)
- Intel Quark SoC X1000 UEFI Firmware Writer’s Guide
关于此 UART 的注意事项:
- 这个串口作为 UART1 从 QUARK 芯片出来(见原理图).
- 您可能需要操作一些 GPIO(有关在 Linux 中执行此操作的信息,请参阅 Sergey 的博客):
- gpio4:此 GPIO 控制 UART 信号和一些其他连接到 Quark SoC 的信号(例如 SPI 和快速 I/O)的电平转换器.向该 GPIO 写入1"可启用电平转换器.
- gpio40:此 GPIO 控制引脚 0 的多路复用器.向此 GPIO 写入0"会将引脚 0 连接到 UART 的 RxD(接收数据)信号.
- gpio41:此 GPIO 控制引脚 1 的多路复用器.向此 GPIO 写入0"会将引脚 1 连接到 UART 的 TxD(传输数据)信号.
- This serial port comes out of the QUARK chip as UART1 (see the schematics).
- There are a few GPIOs that you may need to manipulate (see Sergey's blog for doing this in Linux):
- gpio4: This GPIO controls level shifter for UART signals and some other signals connected to Quark SoC, such as SPI and fast I/O. Writing '1' to this GPIO enables level shifter.
- gpio40: This GPIO controls multiplexer for pin 0. Writing '0' to this GPIO connects pin 0 to UART's RxD (receive data) signal.
- gpio41: This GPIO controls multiplexer for pin 1. Writing '0' to this GPIO connects pin 1 to UART's TxD (transmit data) signal.
- 寄存器DLH,DLL指定波特率
- 决定您是需要 DMA 模式(第 18.3.1 章)、FIFO 中断模式(第 18.3.2 章)还是 FIFO 轮询模式(第 18.3.3 章).恕我直言,后者更简单但效果较差.前者还要求您正确配置 DMA.
由于第 18 章(大约 67 页的有用信息)有很多内容需要阅读,因此我不会在此处重新输入所有内容,请阅读数据表并相应地配置寄存器.
Since there is quite a bit to read for chapter 18 (~67 pages of useful information), I'm not going to retype all that here, please read the datasheet and configure the registers accordingly.
一般注意事项:
对于裸机方法,首先确保您的启动程序正确,配置所有时钟选项、GPIO 默认模式和值、计时器(如果有)等.对于启动清单,请阅读 X1000UEFI 固件编写者指南(启动该芯片需要做的大约 18 件事).之后,我将使用 GPIO 上的简单LED 闪烁"应用程序对其进行验证.
For bare-metal approach first make sure that your boot procedure is correct, configuring all the clocking options, GPIO default modes and values, timers if any, etc. For Boot checklist read chapter 4.12 in X1000 UEFI Firmware Writer’s Guide (~18 things to do to boot this chip). After that I'd verify it with a simple "LED blinking" application on a GPIO.
修补 3F8h 和类似端口对这款 SoC 的裸机"没有帮助.您需要直接处理寄存器,或者找到并使用合适的库或框架(可能是 UEFI BIOS?).
Tinkering with 3F8h and similar ports is not going to help on "bare metal" of this SoC. You need to deal with the registers directly, or find and use appropriate library or framework (maybe UEFI BIOS?).
特定平台的编程源代码应该是很好的例子.例如,在 英特尔 Quark 的板级支持包源 存档
Quark_EDKII_v1.0.0.tar.gz
是 Quark/Galileo 的 UEFI 源代码.在那里,Serial.c 和 Serial.h 文件可能正是您要找的:Programming sources for the particular platform should be a good read for examples. For example, in Board Support Package Sources for Intel Quark the archive
Quark_EDKII_v1.0.0.tar.gz
is the UEFI source code for Quark/Galileo. It there, the Serial.c and Serial.h files might just be what you are looking for:Quark_EDKII_v1.0.0/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.*
Quark_EDKII_v1.0.0/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.*
这篇关于英特尔伽利略裸机UART的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!