Intel Galileo Bare Metal UART

I want to program a small bare metal hello world application on an Intel Galileo board. Using UEFI to print text (for UART-1) works well, of course, but I want to access UART “manually” without the help of UEFI.

In QEMU, my code works well:

.h file

#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 file

 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; } 

Main

 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); } 

Speculation didn't help me much. I believe that UARTs on Intel Galileo motherboards do not use / emulate regular / legacy COM ports 3F8h, 2F8h, 3E8h or 2E8h.

Can someone tell me what I'm doing wrong, or even post an example with a minimal bare metal greeting?

+6
source share
1 answer

I assume that you are targeting the serial port, which is the “audio-like” connector on the Intel Galileo board.

Here are some resources that should help:

Notes on this UART :

  • This serial port exits the QUARK chip as UART1 (see diagram).
  • There are several GPIOs you may need to manage (see Sergey's blog for this on Linux):
    • gpio4 . This GPIO controls the level shift of the UART signal and some other signals connected to Quark SoC, such as SPI and fast I / O. Writing '1' to this GPIO allows level switching.
    • gpio40 . This GPIO controls the multiplexer for pin 0. Writing '0' to this GPIO connects pin 0 to the UART RxD signal (data reception).
    • gpio41 . This GPIO controls the multiplexer for pin 1. Writing "0" to this GPIO connects pin 1 to the UART TxD signal (data transfer).
  • Refer to Chapter 18 (High Speed ​​UART) in the Quark datasheet for entering UART registers:
    • DLH, DLL registers indicate baud rate
    • Determine if you want DMA mode (chapter 18.3.1), FIFO interrupt mode (chapter 18.3.2) or FIFO polling mode (chapter 18.3.3). The latter is simpler, but less effective, IMHO. The first requires that you also configure DMA correctly.

Since quite a bit is read for chapter 18 (~ 67 pages of useful information), I will not repeat all of this here, please read the table and configure the corresponding registers.

General notes :

  • First of all, make sure that your boot procedure is correct, configure all synchronization parameters, default GPIO modes and values, timers, if any, etc. For a download checklist, read Chapter 4.12 in the X1000 UEFI Firmware Guide (~ 18 things to do to download this chip). After that, I would test it with a simple “LED flashing” GPIO application.

  • Interaction with 3F8h and similar ports will not help on the "bare metal" of this SoC. You need to deal with registers directly or find and use the appropriate library or framework (perhaps a UEFI BIOS?).

  • Platform-specific programming sources should be well read for examples. For example, in the Support Board Support Sources for Intel Quark, the Quark_EDKII_v1.0.0.tar.gz archive is the UEFI source code for Quark / Galileo. 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. *

+4
source

All Articles