From f5e4f9524940984c929bc48505b9435c1a89468e Mon Sep 17 00:00:00 2001
From: Jakob <Jakob.knitter@bettermarks.com>
Date: Mon, 19 Jun 2023 15:44:05 +0200
Subject: [PATCH] feat: new simpler and working approach to initilize the uart

---
 src/simple-uart-transmit/Makefile             |   3 +
 .../esp32-c3-uart-interface.c                 | 108 ++++++++
 .../esp32-c3-uart-interface.h                 | 253 ++++++++++++++++++
 src/simple-uart-transmit/main.c               |  14 +
 4 files changed, 378 insertions(+)
 create mode 100644 src/simple-uart-transmit/Makefile
 create mode 100644 src/simple-uart-transmit/esp32-c3-uart-interface.c
 create mode 100644 src/simple-uart-transmit/esp32-c3-uart-interface.h
 create mode 100644 src/simple-uart-transmit/main.c

diff --git a/src/simple-uart-transmit/Makefile b/src/simple-uart-transmit/Makefile
new file mode 100644
index 0000000..2171daa
--- /dev/null
+++ b/src/simple-uart-transmit/Makefile
@@ -0,0 +1,3 @@
+SOURCES = main.c esp32-c3-uart-interface.c
+
+include $(MDK)/$(ARCH)/build.mk
diff --git a/src/simple-uart-transmit/esp32-c3-uart-interface.c b/src/simple-uart-transmit/esp32-c3-uart-interface.c
new file mode 100644
index 0000000..cac1024
--- /dev/null
+++ b/src/simple-uart-transmit/esp32-c3-uart-interface.c
@@ -0,0 +1,108 @@
+#include "esp32-c3-uart-interface.h"
+#include <stdbool.h>
+
+static void config_clock_freq_and_baud_rate(){
+  //freq = clock source rate / (UART_SCLK_DIV_NUM+UART_SCLK_DIV_A/UART_SCLK_DIV_B)
+  // baud rate = freq / (UART_CLKDIV + UART_CLKDIV_FRAG / 16)
+
+  uart_clk_conf_reg_t *clk_config = UART_CLK_CONF_REG(1);
+  uart_clkdiv_reg_t *clk_div = UART_CLKDIV_REG(1);
+
+  // select the clock source via UART_SCLK_SEL;  
+  // 1 is ABP_CLK with 80 MHz
+  // 2 is RC_FAST_CLK with default of 17.5 MHz
+  // 3 is XTAL_CLK with 40 MHz
+  clk_config->sclk_sel = 1;
+
+  // dividing clock to 6 Mhz (divisor should be 13+1/3)
+  // UART_SCLK_DIV_NUM
+  clk_config->sclk_div_num=13;
+  clk_config->sclk_div_a=1;
+  clk_config->sclk_div_b=3;
+
+  // calculate Baud rate to be 9600 (6Mhz/625)
+  clk_div->div_int=625;
+}
+
+void config_uart(){
+  // wait for UART_REG(1)_UPDATE to become 0, which indicates the completion of the last synchronization;
+  uart_id_reg_t *id = UART_ID_REG(1);
+  uart_conf0_reg_t *conf0 = UART_CONF0_REG(1);
+
+  while((bool)(id->reg_update)){
+    __asm__("ADDI x0, x0, 0");
+  }
+
+  // configure static registers (if any) following Section 26.5.1.2;
+
+  // set clock freq to 6MHz
+  // baud rate to 9600
+  config_clock_freq_and_baud_rate();
+
+  // configure data length via UART_BIT_NUM;
+  conf0->bit_num=3;
+
+  // configure odd or even parity check via UART_PARITY_EN and UART_PARITY;
+  conf0->parity=0;
+  conf0->parity_en=0;
+  
+  // synchronize the configured values to the Core Clock domain by writing 1 to UART_REG_UPDATE.
+  id->reg_update=1;
+}
+
+void enable_uart_transmitter(){
+  uart_conf1_reg_t *uart_conf1 = UART_CONF1_REG(1);
+  uart_fifo_reg_t *fifo = UART_FIFO_REG(1);
+  uart_int_clr_reg_t *int_clr = UART_INT_CLR_REG(1);
+  uart_int_ena_reg_t *int_ena = UART_INT_ENA_REG(1);
+
+  // configure TX FIFO’s empty threshold via UART_TXFIFO_EMPTY_THRHD;
+  uart_conf1->txfifo_empty_thrhd=4;
+
+  // disable UART_TXFIFO_EMPTY_INT interrupt by clearing UART_TXFIFO_EMPTY_INT_ENA;
+  int_ena->txfifo_empty_int_ena=0;
+
+  // write data to be sent to UART_RXFIFO_RD_BYTE;
+  fifo->rw_byte=63;
+
+  // clear UART_TXFIFO_EMPTY_INT interrupt by setting UART_TXFIFO_EMPTY_INT_CLR;
+  int_clr->txfifo_empty_int_clr=1;
+
+  // enable UART_TXFIFO_EMPTY_INT interrupt by setting UART_TXFIFO_EMPTY_INT_ENA;
+  int_ena->txfifo_empty_int_ena=1;
+
+  // detect UART_TXFIFO_EMPTY_INT and wait for the completion of data transmission.
+}
+
+void init_uart(){
+  // from technical reference manual 543 f
+
+  uart_id_reg_t *id = UART_ID_REG(1);
+  uart_clk_conf_reg_t *clk_config = UART_CLK_CONF_REG(1);
+  system_perip_clk_en0_reg_t *perip_clk_en0 = SYSTEM_PERIP_CLK_EN0_REG;
+  system_perip_rst_en0_reg_t *perip_rst_en0 = SYSTEM_PERIP_RST_EN0_REG;
+
+  // enable the clock for UART RAM by setting SYSTEM_UART_MEM_CLK_EN to 1;
+  perip_clk_en0->uart_mem_clk_en = 1;
+
+  // enable APB_CLK for UARTn by setting SYSTEM_UARTn_CLK_EN to 1;
+  perip_clk_en0->uart1_clk_en = 1;
+
+  // clear SYSTEM_UARTn_RST;
+  perip_rst_en0->uart1_rst = 0;
+
+  // write 1 to UART_RST_CORE;
+  clk_config->rst_core = 1;
+
+  // write 1 to SYSTEM_UARTn_RST;
+  perip_rst_en0->uart1_rst = 1;
+
+  // clear SYSTEM_UARTn_RST;
+  perip_rst_en0->uart1_rst = 0;
+
+  // clear UART_RST_CORE;
+  clk_config->rst_core = 0;
+
+  // enable register synchronization by clearing UART_UPDATE_CTRL
+  id->update_ctrl = 0;
+}
\ No newline at end of file
diff --git a/src/simple-uart-transmit/esp32-c3-uart-interface.h b/src/simple-uart-transmit/esp32-c3-uart-interface.h
new file mode 100644
index 0000000..d34e5e2
--- /dev/null
+++ b/src/simple-uart-transmit/esp32-c3-uart-interface.h
@@ -0,0 +1,253 @@
+#ifndef ESP32_C3_REGISTER_INTERFACE_H
+#define ESP32_C3_REGISTER_INTERFACE_H
+
+#include <stdint.h>
+
+#define C3_BASE_OFFSET_SYSTEM_REGISTERS ((uint32_t)0x600C0000)
+
+#define C3_UART_CONTROLLER_0_BASE ((uint32_t)0x60000000)
+#define C3_UART_CONTROLLER_1_BASE ((uint32_t)0x60010000)
+#define C3_UART_CONTROLLER_SELECT(base_select) ((uint32_t)((base_select == 1) ? C3_UART_CONTROLLER_1_BASE : C3_UART_CONTROLLER_0_BASE))
+
+typedef volatile struct {
+    uint32_t rw_byte;
+} uart_fifo_reg_t;
+
+typedef volatile struct {
+    uint32_t rxfifo_full:              1;
+    uint32_t txfifo_empty:             1;
+    uint32_t parity_err:               1;
+    uint32_t frm_err:                  1;
+    uint32_t rxfifo_ovf:               1;
+    uint32_t dsr_chg:                  1;
+    uint32_t cts_chg:                  1;
+    uint32_t brk_det:                  1;
+    uint32_t rxfifo_tout:              1;
+    uint32_t sw_xon:                   1;
+    uint32_t sw_xoff:                  1;
+    uint32_t glitch_det:               1;
+    uint32_t tx_brk_done:              1;
+    uint32_t tx_brk_idle_done:         1;
+    uint32_t tx_done:                  1;
+    uint32_t rs485_parity_err:         1;
+    uint32_t rs485_frm_err:            1;
+    uint32_t rs485_clash:              1;
+    uint32_t at_cmd_char_det:          1;
+    uint32_t wakeup:                   1;
+    uint32_t reserved:              12;
+} uart_int_raw_t;
+
+typedef volatile struct {
+    uint32_t rxfifo_full_int_ena:              1;
+    uint32_t txfifo_empty_int_ena:             1;
+    uint32_t parity_err_int_ena:               1;
+    uint32_t frm_err_int_ena:                  1;
+    uint32_t rxfifo_ovf_int_ena:               1;
+    uint32_t dsr_chg_int_ena:                  1;
+    uint32_t cts_chg_int_ena:                  1;
+    uint32_t brk_det_int_ena:                  1;
+    uint32_t rxfifo_tout_int_ena:              1;
+    uint32_t sw_xon_int_ena:                   1;
+    uint32_t sw_xoff_int_ena:                  1;
+    uint32_t glitch_det_int_ena:               1;
+    uint32_t tx_brk_done_int_ena:              1;
+    uint32_t tx_brk_idle_done_int_ena:         1;
+    uint32_t tx_done_int_ena:                  1;
+    uint32_t rs485_parity_err_int_ena:         1;
+    uint32_t rs485_frm_err_int_ena:            1;
+    uint32_t rs485_clash_int_ena:              1;
+    uint32_t at_cmd_char_det_int_ena:          1;
+    uint32_t wakeup_int_ena:                   1;
+    uint32_t reserved:                        12;
+} uart_int_ena_reg_t;
+
+typedef volatile struct {
+    uint32_t rxfifo_full_int_clr:              1;
+    uint32_t txfifo_empty_int_clr:             1;
+    uint32_t parity_err_int_clr:               1;
+    uint32_t frm_err_int_clr:                  1;
+    uint32_t rxfifo_ovf_int_clr:               1;
+    uint32_t dsr_chg_int_clr:                  1;
+    uint32_t cts_chg_int_clr:                  1;
+    uint32_t brk_det_int_clr:                  1;
+    uint32_t rxfifo_tout_int_clr:              1;
+    uint32_t sw_xon_int_clr:                   1;
+    uint32_t sw_xoff_int_clr:                  1;
+    uint32_t glitch_det_int_clr:               1;
+    uint32_t tx_brk_done_int_clr:              1;
+    uint32_t tx_brk_idle_done_int_clr:         1;
+    uint32_t tx_done_int_clr:                  1;
+    uint32_t rs485_parity_err_int_clr:         1;
+    uint32_t rs485_frm_err_int_clr:            1;
+    uint32_t rs485_clash_int_clr:              1;
+    uint32_t at_cmd_char_det_int_clr:          1;
+    uint32_t wakeup_int_clr:                   1;
+    uint32_t reserved:              12;
+} uart_int_clr_reg_t;
+
+typedef volatile struct {
+    uint32_t div_int:       12;
+    uint32_t reserved:    8;
+    uint32_t div_frag:      4;
+    uint32_t reserved1:    8;
+} uart_clkdiv_reg_t;
+
+typedef volatile struct {
+    uint32_t glitch_filt:    8;
+    uint32_t glitch_filt_en: 1;
+    uint32_t reserved:     23;
+} uart_rx_filt_reg_t;
+
+typedef volatile struct {
+    uint32_t parity:       1;
+    uint32_t parity_en:    1;
+    uint32_t bit_num:      2;
+    uint32_t stop_bit_num: 2;
+    uint32_t sw_rts:       1;
+    uint32_t sw_dtr:       1;
+    uint32_t txd_brk:      1;
+    uint32_t irda_dplx:    1;
+    uint32_t irda_tx_en:   1;
+    uint32_t irda_wctl:    1;
+    uint32_t irda_tx_inv:  1;
+    uint32_t irda_rx_inv:  1;
+    uint32_t loopback:     1;
+    uint32_t tx_flow_en:   1;
+    uint32_t irda_en:      1;
+    uint32_t rxfifo_rst:   1;
+    uint32_t txfifo_rst:   1;
+    uint32_t rxd_inv:      1;
+    uint32_t cts_inv:      1;
+    uint32_t dsr_inv:      1;
+    uint32_t txd_inv:      1;
+    uint32_t rts_inv:      1;
+    uint32_t dtr_inv:      1;
+    uint32_t clk_en:       1;
+    uint32_t err_wr_mask:  1;
+    uint32_t autobaud_en:  1;
+    uint32_t mem_clk_en:   1;
+    uint32_t reserved:   3;
+} uart_conf0_reg_t;
+
+typedef volatile struct {
+    uint32_t rxfifo_full_thrhd:  9;
+    uint32_t txfifo_empty_thrhd: 9;
+    uint32_t dis_rx_dat_ovf:     1;
+    uint32_t rx_tout_flow_dis:   1;
+    uint32_t rx_flow_en:         1;
+    uint32_t rx_tout_en:         1;
+    uint32_t reserved:        10;
+} uart_conf1_reg_t;
+
+typedef volatile struct {
+    uint32_t sclk_div_b:   6;
+    uint32_t sclk_div_a:   6;
+    uint32_t sclk_div_num: 8;
+    uint32_t sclk_sel:     2;
+    uint32_t sclk_en:      1;
+    uint32_t rst_core:     1;
+    uint32_t tx_sclk_en:   1;
+    uint32_t rx_sclk_en:   1;
+    uint32_t tx_rst_core:  1;
+    uint32_t rx_rst_core:  1;
+    uint32_t reserved:   4;
+} uart_clk_conf_reg_t;
+
+typedef volatile struct {
+    uint32_t id             :30;
+    uint32_t update_ctrl    :1;
+    uint32_t reg_update     :1;
+} uart_id_reg_t;
+
+typedef volatile struct {
+    uint32_t timers_clk_en:     1;
+    uint32_t spi01_clk_en:      1;
+    uint32_t uart_clk_en:       1;
+    uint32_t reserved:          2;
+    uint32_t uart1_clk_en:      1;
+    uint32_t spi2_clk_en:       1;
+    uint32_t ext0_clk_en:       1;
+    uint32_t uhci0_clk_en:      1;
+    uint32_t rmt_clk_en:        1;
+    uint32_t reserved1:         1;
+    uint32_t ledc_clk_en:       1;
+    uint32_t reserved2:         1;
+    uint32_t timergroup_clk_en:  1;
+    uint32_t reserved3:         1;
+    uint32_t timergroup1_clk_en: 1;
+    uint32_t reserved4:         3;
+    uint32_t can_clk_en:        1;
+    uint32_t reserved5:         1;
+    uint32_t i2s1_clk_en:       1;
+    uint32_t reserved6:         1;
+    uint32_t usb_device_clk_en: 1;
+    uint32_t uart_mem_clk_en:   1;
+    uint32_t reserved7:         2;
+    uint32_t spi3_dma_clk_en:   1;
+    uint32_t apb_saradc_clk_en: 1;
+    uint32_t systimer_clk_en:   1;
+    uint32_t adc2_arb_clk_en:   1;
+    uint32_t reserved8:         1;
+} system_perip_clk_en0_reg_t;
+
+typedef volatile struct {
+    uint32_t timers_rst:        1;
+    uint32_t spi01_rst:         1;
+    uint32_t uart_rst:          1;
+    uint32_t reserved:          2;
+    uint32_t uart1_rst:         1;
+    uint32_t spi2_rst:          1;
+    uint32_t ext0_rst:          1;
+    uint32_t uhci0_rst:         1;
+    uint32_t rmt_rst:           1;
+    uint32_t reserved1:         1;
+    uint32_t ledc_rst:          1;
+    uint32_t reserved2:         1;
+    uint32_t timergroup_rst:    1;
+    uint32_t reserved3:         1;
+    uint32_t timergroup1_rst:   1;
+    uint32_t reserved4:         3;
+    uint32_t can_rst:           1;
+    uint32_t reserved5:         1;
+    uint32_t i2s1_rst:          1;
+    uint32_t reserved6:         1;
+    uint32_t usb_device_rst:    1;
+    uint32_t uart_mem_rst:      1;
+    uint32_t reserved7:         2;
+    uint32_t spi3_dma_rst:      1;
+    uint32_t apb_saradc_rst:    1;
+    uint32_t systimer_rst:      1;
+    uint32_t adc2_arb_rst:      1;
+    uint32_t reserved8:         1;
+} system_perip_rst_en0_reg_t;
+
+
+#define UART_FIFO_REG(base_select) ((uart_fifo_reg_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0000))
+
+#define UART_INT_RAW(base_select) ((uart_int_raw_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0004))
+
+#define UART_INT_ENA_REG(base_select) ((uart_int_ena_reg_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x000C))
+
+#define UART_INT_CLR_REG(base_select) ((uart_int_clr_reg_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0010))
+
+#define UART_CLKDIV_REG(base_select) ((uart_clkdiv_reg_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0014))
+
+#define UART_RX_FILT_REG(base_select) ((uart_rx_filt_reg_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0018))
+
+#define UART_CONF0_REG(base_select) ((uart_conf0_reg_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0020))
+
+#define UART_CONF1_REG(base_select) ((uart_conf1_reg_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0024))
+
+#define UART_CLK_CONF_REG(base_select) ((uart_clk_conf_reg_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0078))
+
+#define UART_ID_REG(base_select) ((uart_id_reg_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0080))
+
+#define SYSTEM_PERIP_CLK_EN0_REG ((system_perip_clk_en0_reg_t *)(C3_BASE_OFFSET_SYSTEM_REGISTERS+0x0010))
+
+#define SYSTEM_PERIP_RST_EN0_REG ((system_perip_rst_en0_reg_t *)(C3_BASE_OFFSET_SYSTEM_REGISTERS+0x0018))
+
+void config_uart();
+void init_uart();
+void enable_uart_transmitter();
+
+#endif
\ No newline at end of file
diff --git a/src/simple-uart-transmit/main.c b/src/simple-uart-transmit/main.c
new file mode 100644
index 0000000..1cdad6f
--- /dev/null
+++ b/src/simple-uart-transmit/main.c
@@ -0,0 +1,14 @@
+// All rights reserved
+
+#include <mdk.h>
+#include "esp32-c3-uart-interface.h"
+
+int main(void) {
+  wdt_disable();
+
+  init_uart();
+  config_uart();
+  enable_uart_transmitter();
+
+  return 0;
+}
\ No newline at end of file
-- 
GitLab