ESP32-S3 Bare metal UART not working
Posted: Sat Aug 16, 2025 1:52 pm
I have been trying to write code for the ESP32-S3 without using the IDF that initializes the uart and writes something to it, but i have been unable to get it to work with many attempts.
Here is my current code:
I am sorry if this is not the right place to ask, but I am new to these forums and didn't see a forum specifically for esp32 development without the IDF. Sorry if i didn't provide enough information.
Here is my current code:
Code: Select all
#define UART_TX_PIN 1
#define UART_RX_PIN 2
void uart_init(uint32_t baud_rate) {
// ESP32-S3 TRM (Version 1.7)
// 26.5.2.1 Initializing UARTn
// Reset uart peripheral
system->PERIP_CLK_EN0 |= 1UL << 24; // Set bit 24 (SYSTEM_UART_MEM_CLK_EN)
system->PERIP_CLK_EN0 |= 1UL << 2;// Enable APB_CLK for UART
// system->PERIP_RST_EN0 |= 1UL << 2; // Write 1 to SYSTEM_UART_RST
system->PERIP_RST_EN0 &= ~(1UL << 2); // Clear SYSTEM_UART_RST
uart0->CLK_CONF |= 1UL << 23; // Write 1 to UART_RST_CORE
system->PERIP_RST_EN0 |= 1UL << 2; // Write 1 to SYSTEM_UART_RST
system->PERIP_RST_EN0 &= ~(1UL << 2); // Clear SYSTEM_UART_RST
uart0->CLK_CONF &= ~(1UL << 23); // Clear UART_RST_CORE
// Enable register synchronization
uart0->ID &= ~(1UL << 30); // clear UART_UPDATE_CTRL
// 26.5.2.2 Configuring UARTn Communication
while (uart0->ID & (1UL << 31)); // wait for UART_REG_UPDATE to become 0
// Configure static registers here if needed
uart0->CLK_CONF &= ~(1UL << 21);
uart0->CLK_CONF |= 1UL << 20;
// For now it will be hardcoded at 115200 baud
// Setting the clock divisor is not needed, but recommended to save power
// configure the baud rate for transmission
const uint32_t uart_clock_freq = 80000000;
const uint32_t divider = (uart_clock_freq / baud_rate);
const uint32_t fractional_part = ((uart_clock_freq % baud_rate) * 65536 / baud_rate);
uart0->CLKDIV = (divider << 0) | (fractional_part << 20);
// the bit width is set to 3 by default (REG-5 so 8-5 = 3)
// the parity is disabled by default
// the stop bits are set to 1 by default
uart0->ID |= 1UL << 31; // Synchronize the values by writing 1 to UART_REG_UPDATE
// 26.5.2.3 Enabling UARTn
// I dont think ill be using interrupts
// Set up pins
// Set GPIO1 to be a digital output
// The GPIO_ENABLE register controls output enable for each pin.
// Set the mux values
gpio->FUNC_OUT_SEL_CFG[UART_TX_PIN] = 12 | (1UL << 10); //U0TXD_out | OEN_SEL
// gpio->FUNC_OUT_SEL_CFG[UART_TX_PIN] = 12; //U0TXD_out | OEN_SEL
gpio->ENABLE_W1TS = (1UL << UART_TX_PIN);
// gpio->ENABLE_W1TC = (1UL << UART_RX_PIN);
// // Set the mux values
// gpio->FUNC_IN_SEL_CFG[UART_RX_PIN ] = 12 | (1UL << 10); //U0TXD_out | OEN_SEL
}
void uartTx(unsigned const char x) {
uart0->CONF1 &= ~(0xFFFFFUL << 10);
uart0->CONF1 |= (0x01UL << 10);
uart0->INT_ENA &= ~(1UL << 1);
while (((uart0->STATUS >> 16) & 0x1FF) >= 128); // Wait until there's space in the TX FIFO
uart0->FIFO = (x & 0xFF);
uart0->INT_CLR |= (1UL << 1);
uart0->INT_ENA |= (1UL << 1);
}
// void uartTx(unsigned const char x) {
// extern int uart_tx_one_char(int);
// (void) uart_tx_one_char(x);
// }