summaryrefslogtreecommitdiff
path: root/ports/risc-v64/gnu/example_build/erbium/uart.c
diff options
context:
space:
mode:
authorFrédéric Desbiens <[email protected]>2026-10-02 10:42:44 -0400
committerGitHub <[email protected]>2026-10-02 10:42:44 -0400
commit93387b0a60382a29579bbad5045c68328e3751df (patch)
tree42be790d602cb76f55090e5a7c418df7ea2b3428 /ports/risc-v64/gnu/example_build/erbium/uart.c
parent44d7c95c582d415c4ad84527180b29c93c3bf664 (diff)
parent28281cd5647d4671236ca08d19bd18ed15b2265a (diff)
Merge pull request #783 from eclipse-threadx/devv6.5.2.202603_rel
Merged changes ahead of the v6.5.2.202603 release
Diffstat (limited to 'ports/risc-v64/gnu/example_build/erbium/uart.c')
-rw-r--r--ports/risc-v64/gnu/example_build/erbium/uart.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/ports/risc-v64/gnu/example_build/erbium/uart.c b/ports/risc-v64/gnu/example_build/erbium/uart.c
new file mode 100644
index 00000000..1b8f2dfc
--- /dev/null
+++ b/ports/risc-v64/gnu/example_build/erbium/uart.c
@@ -0,0 +1,109 @@
+/***************************************************************************
+ * Copyright (c) 2026 Eclipse ThreadX contributors
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the MIT License which is available at
+ * https://opensource.org/licenses/MIT.
+ *
+ * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5).
+ * The AI-generated portions may be considered public domain (CC0-1.0)
+ * and not subject to the project's licence. The human contributor has
+ * reviewed and verified that the code is correct.
+ *
+ * SPDX-License-Identifier: MIT and CC0-1.0
+ **************************************************************************/
+
+/* Polling console driver for the Erbium UART (original Shakti integration).
+ *
+ * Offset Name Access Description
+ * ────── ──────────── ────── ─────────────────────────────────────
+ * 0x00 BaudReg R/W Divisor: clock / (16 * baud)
+ * 0x08 TxReg W Transmit data
+ * 0x10 RxReg R Receive data
+ * 0x18 StatusReg R FIFO and error status
+ * 0x20 DelayReg R/W Transmit delay
+ * 0x28 ControlReg R/W Character size, parity, stop bits
+ * 0x30 InterruptEn R/W Interrupt enables
+ * 0x40 Rx_Threshold R/W Receive FIFO threshold
+ *
+ * All registers are accessed as 32-bit words. The transmit and receive
+ * FIFOs hold 16 entries each.
+ */
+
+#include "uart.h"
+#include "csr.h"
+#include <stdint.h>
+
+#define UART_DIVISOR (ERBIUM_UART_CLOCK_HZ / (16UL * ERBIUM_UART_BAUD))
+
+#if (UART_DIVISOR == 0) || (UART_DIVISOR > 0xFFFF)
+#error "The Erbium UART baud divisor must be in the range 1..65535."
+#endif
+
+/* SystemConfig in the system register block gates the UART. */
+#define SYSREG_SYSTEM_CONFIG 0x02000008UL
+#define SYSTEM_CONFIG_UART_EN (1u << 6)
+
+#define UART_BAUD 0x00
+#define UART_TX 0x08
+#define UART_STATUS 0x18
+#define UART_DELAY 0x20
+#define UART_CONTROL 0x28
+#define UART_IEN 0x30
+#define UART_RX_THRESHOLD 0x40
+
+#define STATUS_TX_FULL (1u << 1)
+
+#define CONTROL_CHARSIZE_SHIFT 5 /* bits 10:5; stop bits and parity 0 */
+
+#define REG32(addr) (*(volatile uint32_t *)(addr))
+#define UART_REG(off) REG32(UART0 + (off))
+
+int uart_init(void)
+{
+ /* Ungate the UART. Read-modify-write keeps the watchdog and the
+ other peripheral enables as the boot flow left them. */
+ REG32(SYSREG_SYSTEM_CONFIG) = REG32(SYSREG_SYSTEM_CONFIG) | SYSTEM_CONFIG_UART_EN;
+
+ /* Polling only: no UART interrupts. */
+ UART_REG(UART_IEN) = 0;
+
+ /* 8 data bits, no parity, one stop bit. */
+ UART_REG(UART_BAUD) = (uint32_t)UART_DIVISOR;
+ UART_REG(UART_CONTROL) = 8u << CONTROL_CHARSIZE_SHIFT;
+ UART_REG(UART_DELAY) = 0;
+ UART_REG(UART_RX_THRESHOLD) = 0;
+
+ puts("[UART0] : Erbium UART initialized");
+ return 0;
+}
+
+int uart_putc(int ch)
+{
+ int intr_enable;
+
+ for (;;)
+ {
+ while ((UART_REG(UART_STATUS) & STATUS_TX_FULL) != 0u)
+ ;
+
+ intr_enable = riscv_mintr_save();
+ if ((UART_REG(UART_STATUS) & STATUS_TX_FULL) == 0u)
+ {
+ UART_REG(UART_TX) = (uint32_t)(ch & 0xFF);
+ riscv_mintr_restore(intr_enable);
+ return 1;
+ }
+ riscv_mintr_restore(intr_enable);
+ }
+}
+
+int uart_puts(const char *str)
+{
+ int i;
+ for (i = 0; str[i] != 0; i++)
+ uart_putc(str[i]);
+ uart_putc('\r');
+ uart_putc('\n');
+ return i;
+}