diff --git a/esp32c3_rev3_rom.elf b/esp32c3_rev3_rom.elf
new file mode 100755
index 0000000000000000000000000000000000000000..73da118674d4d2c84fb2c1940269a9d9e48dafec
Binary files /dev/null and b/esp32c3_rev3_rom.elf differ
diff --git a/Makefile b/nothing/Makefile
similarity index 100%
rename from Makefile
rename to nothing/Makefile
diff --git a/src/nothing.c b/nothing/nothing.c
similarity index 100%
rename from src/nothing.c
rename to nothing/nothing.c
diff --git a/reading-writing-registers/Makefile b/reading-writing-registers/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..687c03977905c209ad00fb7b2870f36d156690fd
--- /dev/null
+++ b/reading-writing-registers/Makefile
@@ -0,0 +1,3 @@
+SOURCES = main.c esp32-c3-register-interface.c
+
+include $(MDK)/$(ARCH)/build.mk
diff --git a/reading-writing-registers/esp32-c3-register-interface.c b/reading-writing-registers/esp32-c3-register-interface.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c9e22e0270635754791b4e30487226b04cdbc15
--- /dev/null
+++ b/reading-writing-registers/esp32-c3-register-interface.c
@@ -0,0 +1,11 @@
+#include "esp32-c3-register-interface.h"
+
+void readSetClear(){
+  esp32c3_uart_clk_conf_t *clockConfig = UART_CLK_CONF_REG(0);
+  
+  // set UART_RST_CORE
+  clockConfig->REST_CORE = 1;
+  
+  // clear UART_RST_CORE
+  clockConfig->REST_CORE = 0;
+}
\ No newline at end of file
diff --git a/reading-writing-registers/esp32-c3-register-interface.h b/reading-writing-registers/esp32-c3-register-interface.h
new file mode 100644
index 0000000000000000000000000000000000000000..be75bca10367fd4162aa835062ff9f3070dc4e22
--- /dev/null
+++ b/reading-writing-registers/esp32-c3-register-interface.h
@@ -0,0 +1,28 @@
+#ifndef ESP32_C3_REGISTER_INTERFACE_H
+#define ESP32_C3_REGISTER_INTERFACE_H
+
+#include <stdint.h>
+
+#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 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 REST_CORE:     1;
+    uint32_t TX_SCLK_EN:    1;
+    uint32_t RX_SCLK_EN:    1;
+    uint32_t TX_REST_CORE:  1;
+    uint32_t RX_REST_CORE:  1;
+    uint32_t RESERVED:      4;
+} esp32c3_uart_clk_conf_t;
+
+#define UART_CLK_CONF_REG(base_select) ((esp32c3_uart_clk_conf_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0078))  // Assuming the offset of clk_conf is 0x18 from the base address
+
+void readSetClear();
+
+#endif
\ No newline at end of file
diff --git a/reading-writing-registers/main.c b/reading-writing-registers/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f0fc67ed202bd3210fbc5b118388dd93d3269b2
--- /dev/null
+++ b/reading-writing-registers/main.c
@@ -0,0 +1,10 @@
+#include <mdk.h>
+#include "esp32-c3-register-interface.h"
+
+int main(void) {
+  wdt_disable();
+
+  readSetClear();
+
+  return 0;
+}
diff --git a/simple-uart-transmit/.gdbinit b/simple-uart-transmit/.gdbinit
new file mode 100644
index 0000000000000000000000000000000000000000..5b36086158fc5c78eadcf99eaa92c4d7b350f0c9
--- /dev/null
+++ b/simple-uart-transmit/.gdbinit
@@ -0,0 +1,8 @@
+target extended-remote :3333
+set remote hardware-watchpoint-limit 2
+
+add-symbol-file ../esp32c3_rev3_rom.elf
+file ./firmware.elf
+
+mon reset halt
+flushregs
\ No newline at end of file
diff --git a/simple-uart-transmit/.vscode/launch.json b/simple-uart-transmit/.vscode/launch.json
new file mode 100644
index 0000000000000000000000000000000000000000..62a99f442017995786277def1231b958b9763d11
--- /dev/null
+++ b/simple-uart-transmit/.vscode/launch.json
@@ -0,0 +1,25 @@
+{
+    // Use IntelliSense to learn about possible attributes.
+    // Hover to view descriptions of existing attributes.
+    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Debug on real board",
+            "type": "gdb",
+            "request": "attach",
+            "cwd": "${workspaceRoot}",
+            "valuesFormatting": "parseText",
+            "target": "extended-remote 127.0.0.1:3333",
+            "executable": "./firmware.elf",
+            "autorun": [
+                "add-symbol-file ./firmware.elf",
+                "add-symbol-file ../esp32c3_rev3_rom.elf",
+                "set remote hardware-watchpoint-limit 2",
+                "mon reset halt",
+                "maintenance flush register-cache",
+            ],
+            "gdbpath": "riscv32-unknown-elf-gdb"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/simple-uart-transmit/Makefile b/simple-uart-transmit/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d9da72ed97e94c6e367e5dba0adb870ea87d92a7
--- /dev/null
+++ b/simple-uart-transmit/Makefile
@@ -0,0 +1,6 @@
+TOOLCHAIN=riscv32-unknown-elf
+EXTRA_CFLAGS ?= -Og -g
+
+SOURCES = main.c esp32-c3-uart-interface.c
+
+include $(MDK)/$(ARCH)/build.mk
diff --git a/simple-uart-transmit/debug-hw.sh b/simple-uart-transmit/debug-hw.sh
new file mode 100755
index 0000000000000000000000000000000000000000..894d70a226c7ea67c714aaaf7d38d9bdec4b496e
--- /dev/null
+++ b/simple-uart-transmit/debug-hw.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+set -eo pipefail
+
+# In case previous instance still lingers
+killall openocd || true
+
+make build
+
+# Use espressif's openocd for now
+source ../../esp-idf/export.sh
+openocd -f board/esp32c3-builtin.cfg -c "program_esp firmware.bin 0x10000 verify"
+OPENOCD_PID=$!
+_term() {
+  echo "Caught signal!" 
+  kill -TERM "$OPENOCD_PID"
+  killall openocd
+}
+trap _term SIGTERM
+trap _term SIGINT
+
+#dir=$(pwd)
+#echo "LAUNCHING GDB!"
+#riscv32-unknown-elf-gdb -x .gdbinit ./firmware.elf
\ No newline at end of file
diff --git a/simple-uart-transmit/esp32-c3-uart-interface.c b/simple-uart-transmit/esp32-c3-uart-interface.c
new file mode 100644
index 0000000000000000000000000000000000000000..970f2dc457ed8393a94b09c6fa2e1d6de4795ee7
--- /dev/null
+++ b/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(0);
+  uart_clkdiv_reg_t *clk_div = UART_CLKDIV_REG(0);
+
+  // 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(0)_UPDATE to become 0, which indicates the completion of the last synchronization;
+  uart_id_reg_t *id = UART_ID_REG(0);
+  uart_conf0_reg_t *conf0 = UART_CONF0_REG(0);
+
+  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(0);
+  uart_fifo_reg_t *fifo = UART_FIFO_REG(0);
+  uart_int_clr_reg_t *int_clr = UART_INT_CLR_REG(0);
+  uart_int_ena_reg_t *int_ena = UART_INT_ENA_REG(0);
+
+  // 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(0);
+  uart_clk_conf_reg_t *clk_config = UART_CLK_CONF_REG(0);
+  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->uart_clk_en = 1;
+
+  // clear SYSTEM_UARTn_RST;
+  perip_rst_en0->uart_rst = 0;
+
+  // write 1 to UART_RST_CORE;
+  clk_config->rst_core = 1;
+
+  // write 1 to SYSTEM_UARTn_RST;
+  perip_rst_en0->uart_rst = 1;
+
+  // clear SYSTEM_UARTn_RST;
+  perip_rst_en0->uart_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/simple-uart-transmit/esp32-c3-uart-interface.h b/simple-uart-transmit/esp32-c3-uart-interface.h
new file mode 100644
index 0000000000000000000000000000000000000000..d34e5e2af73e6042cf8616d7be89394d3be71426
--- /dev/null
+++ b/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/simple-uart-transmit/main.c b/simple-uart-transmit/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..128c6bdf8eebe6f9aef4072cfb55ba32ebd7adf0
--- /dev/null
+++ b/simple-uart-transmit/main.c
@@ -0,0 +1,15 @@
+// All rights reserved
+
+#include <mdk.h>
+#include "esp32-c3-uart-interface.h"
+
+int main(void) {
+  wdt_disable();
+
+  delay_ms(1000);
+  init_uart();
+  config_uart();
+  enable_uart_transmitter();
+
+  return 0;
+}
\ No newline at end of file
diff --git a/uart-transmit/Makefile b/uart-transmit/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..1cabc439ec8717e71de36f741d00668386a3863b
--- /dev/null
+++ b/uart-transmit/Makefile
@@ -0,0 +1,3 @@
+SOURCES = main.c esp32-c3-uart-interface.c esp32-c3-led-helpers.c
+
+include $(MDK)/$(ARCH)/build.mk
diff --git a/uart-transmit/esp32-c3-led-helpers.c b/uart-transmit/esp32-c3-led-helpers.c
new file mode 100644
index 0000000000000000000000000000000000000000..7195205c6b7476e572c07c80ed2779a9d7ea6e6d
--- /dev/null
+++ b/uart-transmit/esp32-c3-led-helpers.c
@@ -0,0 +1,31 @@
+#include "esp32-c3-led-helpers.h"
+#include <mdk.h>
+
+// used for debugging
+
+// On the ESP32C3 dev boards, the WS2812 LED is connected to GPIO 8
+static int ws_2812_pin = 8;
+
+void setupLED(){
+  wdt_disable();
+  gpio_output(ws_2812_pin);
+}
+
+void blinkGreen(int count, unsigned long delay_millis) {
+  uint8_t green[3] = {1, 0, 0}, black[3] = {0, 0, 0};
+  for (int i = 0; i < count; i++) {
+    ws2812_show(ws_2812_pin, green, sizeof(green));
+    delay_ms(delay_millis);
+    ws2812_show(ws_2812_pin, black, sizeof(black));
+    delay_ms(delay_millis);
+  }
+}
+
+void showColorForDuration(uint8_t grb[3], uint32_t durationInMs){
+    ws2812_show(ws_2812_pin, grb, sizeof(uint8_t)*3);
+    delay_ms(durationInMs);
+}
+
+void showColor(uint8_t grb[3]){
+    ws2812_show(ws_2812_pin, grb, sizeof(uint8_t)*3);
+}
\ No newline at end of file
diff --git a/uart-transmit/esp32-c3-led-helpers.h b/uart-transmit/esp32-c3-led-helpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..d51f91a48d8a7d77cb84e852a4b6045c7b2bf9d5
--- /dev/null
+++ b/uart-transmit/esp32-c3-led-helpers.h
@@ -0,0 +1,9 @@
+#ifndef ESP32_C3_LED_HELPERS_H
+#define ESP32_C3_LED_HELPERS_H
+
+void showColorForDuration();
+void showColor();
+void blinkGreen();
+void setupLED();
+
+#endif
\ No newline at end of file
diff --git a/uart-transmit/esp32-c3-uart-interface.c b/uart-transmit/esp32-c3-uart-interface.c
new file mode 100644
index 0000000000000000000000000000000000000000..a838e2d7a41444bfd47f5cb9343397cabd940a91
--- /dev/null
+++ b/uart-transmit/esp32-c3-uart-interface.c
@@ -0,0 +1,197 @@
+#include "esp32-c3-uart-interface.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <mdk.h>
+
+
+static void clearBits(volatile uint32_t *registerAddress, uint32_t bitPositions, uint32_t numBits) {
+    uint32_t mask = (uint32_t)(1 << numBits) - 1;  // Create a mask with the specified number of bits set to 1
+    mask <<= bitPositions;               // Shift the mask to the correct bit positions
+    *registerAddress &= ~mask;           // Clear the bits in the register using bitwise AND with the inverse of the mask
+}
+
+static void setBit(volatile uint32_t *registerAddress, uint32_t bitPositions) {
+    uint32_t mask = (uint32_t)(1 << bitPositions);
+    *registerAddress |= ~mask;
+}
+
+static void setSpecificBitsInRegister(volatile uint32_t *reg, uint32_t *bits, size_t numBits) {
+  uint32_t rx_fifo = *reg;
+  for (size_t i = 0; i < numBits; i++) {
+      uint32_t bitPos = bits[i];
+      rx_fifo |= (1 << bitPos);
+  }
+  *reg = rx_fifo;
+}
+
+static void init_uart_enable_clk(){
+  // enable the clock for UART RAM by setting SYSTEM_UART_MEM_CLK_EN to 1;
+  // enable APB_CLK for UARTn by setting SYSTEM_UARTn_CLK_EN to 1;
+  uint32_t perip_clk_en0 = *C3_SYSTEM_PERIP_CLK_EN0_REG;
+  perip_clk_en0 |= 1<<24;
+  perip_clk_en0 |= 1<<5;
+  perip_clk_en0 |= 1<<2;
+  *C3_SYSTEM_PERIP_CLK_EN0_REG = perip_clk_en0;
+}
+
+static void init_uart_toggle_rst(){
+  // Detailed steps explained in 26.5.2.1
+  // for resetting and initilizing of uart
+  // get current regestry values
+  uint32_t rx_filt = *C3_UART_RX_FILT_REG(0);
+  uint32_t core_value = *C3_UART_CLK_CONF_REG(0);
+  // clear UARTn_RST
+  rx_filt &= (uint32_t)~(1<<5);
+  rx_filt &= (uint32_t)~(1<<2);
+  *C3_UART_RX_FILT_REG(0) = rx_filt;
+  // set UART_RST_CORE
+  core_value |= 1<<23;
+  *C3_UART_CLK_CONF_REG(0) = core_value;
+  // set UARTn_RST
+  rx_filt |= 1<<5;
+  rx_filt |= 1<<2;
+  *C3_UART_RX_FILT_REG(0) = rx_filt;
+  // clear UARTn_RST
+  rx_filt &= (uint32_t)~(1<<5);
+  rx_filt &= (uint32_t)~(1<<2);
+  *C3_UART_RX_FILT_REG(0) = rx_filt;
+  // clear UART_RST_CORE
+  core_value &= (uint32_t)~(1<<23);
+  *C3_UART_CLK_CONF_REG(0) = core_value;
+}
+
+static void init_uart_clear_update(){  
+  // enable register synchronization by clearing UART_UPDATE_CTRL.
+  uint32_t id_value = *C3_UART_ID_REG(0);
+  id_value &= (uint32_t)~(1<<30);
+  *C3_UART_ID_REG(0) = id_value;
+}
+
+static void config_clock_freq(){
+  //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)
+
+  // select the clock source via UART_SCLK_SEL;
+  uint32_t clockSelect = *C3_UART_CLK_CONF_REG(0);
+  // making sure we start with 0
+  clockSelect &= (uint32_t)~(1<<20);
+  clockSelect &= (uint32_t)~(1<<21);
+  // 01 is ABP_CLK with 80 MHz
+  // 10 is RC_FAST_CLK with default of 17.5 MHz
+  // 11 is XTAL_CLK with 40 MHz
+  clockSelect |= 1<<20;
+  *C3_UART_CLK_CONF_REG(0) = clockSelect;
+  // selected ABP_CLK with 80 MHz
+
+  // dividing clock to 6 Mhz (divisor should be 13+1/3)
+  // UART_SCLK_DIV_NUM
+  clockSelect |= 1<<12;
+  clockSelect |= 1<<14;
+  clockSelect |= 1<<15;
+
+  // UART_SCLK_DIV_A
+  clockSelect |= 1<<6;
+
+  // UART_SCLK_DIV_B
+  clockSelect |= 1<<1;
+  clockSelect |= 1<<0;
+
+  *C3_UART_CLK_CONF_REG(0) = clockSelect;
+
+  // calculate Baud rate to be 9600 (6Mhz/625)
+  uint32_t baudRateDivs = *C3_UART_CLKDIV_REG(0);
+  baudRateDivs |= 1<<0;
+  baudRateDivs |= 1<<4;
+  baudRateDivs |= 1<<5;
+  baudRateDivs |= 1<<6;
+  baudRateDivs |= 1<<9;
+  *C3_UART_CLKDIV_REG(0) = baudRateDivs;
+}
+
+static void disable_parity(){
+  uint32_t uart_conf = *C3_UART_CONF0_REG(0);
+  uart_conf &= (uint32_t)~(1<<0);
+  uart_conf &= (uint32_t)~(1<<1);
+  *C3_UART_CONF0_REG(0) = uart_conf;
+}
+
+static void set_max_data_lenght(){
+  uint32_t uart_conf = *C3_UART_CONF0_REG(0);
+  uart_conf |= (1<<2);
+  uart_conf |= (1<<3);
+  *C3_UART_CONF0_REG(0) = uart_conf;
+}
+
+void config_uart(){
+  // wait for UART_REG(0)_UPDATE to become 0, which indicates the completion of the last synchronization;
+  uint32_t reg_update = *C3_UART_ID_REG(0);
+
+  while((bool)(reg_update & (uint32_t)(1<<31))){
+    __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();
+
+  // configure data length via UART_BIT_NUM;
+  set_max_data_lenght();
+
+  // configure odd or even parity check via UART_PARITY_EN and UART_PARITY;
+  disable_parity();
+  
+  // synchronize the configured values to the Core Clock domain by writing 1 to UART_REG_UPDATE.
+  reg_update |= (uint32_t)(1<<31);
+  *C3_UART_ID_REG(0) = reg_update;
+}
+
+void writeSomething(){
+  uint32_t bitPositions[] = {0,1,7};
+  size_t numBits = sizeof(bitPositions) / sizeof(bitPositions[0]);
+  setSpecificBitsInRegister(C3_UART_FIFO_REG(0), bitPositions, numBits);
+
+  //uint32_t rx_fifo = *C3_UART_FIFO_REG(0);
+  //rx_fifo |= 1<<7;
+  //rx_fifo |= 1<<6;
+  //rx_fifo |= 1<<5;
+  //*C3_UART_FIFO_REG(0) = rx_fifo;
+
+}
+
+void enable_uart_transmitter(){
+  for(int i = 0; i < 100; i++){
+    delay_ms(10);
+    // configure TX FIFO’s empty threshold via UART_TXFIFO_EMPTY_THRHD;
+    clearBits(C3_UART_CONF1_REG(0), 9, 9);
+    setBit(C3_UART_CONF1_REG(0),3);
+
+    // disable UART_TXFIFO_EMPTY_INT interrupt by clearing UART_TXFIFO_EMPTY_INT_ENA;
+    clearBits(C3_UART_INT_ENA_REG(0), 1, 1);
+
+    // write data to be sent to UART_RXFIFO_RD_BYTE;
+    writeSomething();
+    
+    // clear UART_TXFIFO_EMPTY_INT interrupt by setting UART_TXFIFO_EMPTY_INT_CLR;
+    setBit(C3_UART_INT_CLR_REG(0), 1);
+    
+    // enable UART_TXFIFO_EMPTY_INT interrupt by setting UART_TXFIFO_EMPTY_INT_ENA;
+    setBit(C3_UART_INT_ENA_REG(0), 1);
+  }
+}
+
+void reset_uart(){
+  // 26.4.1 Clock and Reset
+  init_uart_enable_clk();
+  init_uart_toggle_rst();
+}
+
+void init_uart(){
+  // from technical reference manual 543 f
+  init_uart_enable_clk();
+  init_uart_toggle_rst();
+  init_uart_clear_update();
+}
\ No newline at end of file
diff --git a/uart-transmit/esp32-c3-uart-interface.h b/uart-transmit/esp32-c3-uart-interface.h
new file mode 100644
index 0000000000000000000000000000000000000000..3d187ad64d60307f6d6eb43c8d7e2720818fce35
--- /dev/null
+++ b/uart-transmit/esp32-c3-uart-interface.h
@@ -0,0 +1,59 @@
+#ifndef ESP32_C3_UART_INTERFACE_H
+#define ESP32_C3_UART_INTERFACE_H
+
+// all addresses are relative to some other register....
+
+#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) ((volatile uint32_t *)((base_select == 1) ? C3_UART_CONTROLLER_1_BASE : C3_UART_CONTROLLER_0_BASE))
+
+#define C3_UART_FIFO_REG(base_select) ((volatile uint32_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0000))
+
+#define C3_UART_INT_RAW(base_select) ((volatile uint32_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0004))
+// UART_TXFIFO_EMPTY_INT_RAW is on 1
+
+#define C3_UART_INT_ENA_REG(base_select) ((volatile uint32_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x000C))
+// UART_TXFIFO_EMPTY_INT_ENA is on 1
+
+#define C3_UART_INT_CLR_REG(base_select) ((volatile uint32_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0010))
+// UART_TXFIFO_EMPTY_INT_CLR
+
+#define C3_UART_CLKDIV_REG(base_select) ((volatile uint32_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0014))
+// UART_CLKDIV - integer part of baud rate calculator devisor - 0 to 11
+// UART_CLKDIV_FRAG - numerator of devisor in baud rate calculator devisor
+
+#define C3_UART_RX_FILT_REG(base_select) ((volatile uint32_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0018))
+// SYSTEM_UARTn_RST n=0 is on 2, n=1 is on 5
+
+#define C3_UART_CONF0_REG(base_select) ((volatile uint32_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0020))
+// UART_PARITY is on 0
+// UART_PARITY_EN is on 1
+// UART_BIT_NUM is on 2 and 3
+
+#define C3_UART_CONF1_REG(base_select) ((volatile uint32_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0024))
+// UART_TXFIFO_EMPTY_THRHD is 9 to 17
+
+#define C3_UART_CLK_CONF_REG(base_select) ((volatile uint32_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0078))
+// UART_RST_CORE is on 23
+// UART_SCLK_SEL is on 20 and 21 (2 bits), selcetion is between 1 and 3
+// UART_SCLK_DIV_NUM - The integral part of the frequency divisor - 12 to 19
+// UART_SCLK_DIV_A - The numerator of the frequency divisor - 6 to 11
+// UART_SCLK_DIV_B - The denominator of the frequency divisor - 0 to 5
+
+#define C3_UART_ID_REG(base_select) ((volatile uint32_t *)(C3_UART_CONTROLLER_SELECT((base_select)) + 0x0080))
+// UART_UPDATE_CTRL is on 30
+// UART_REG_UPDATE is on 31
+
+#define C3_SYSTEM_PERIP_CLK_EN0_REG ((volatile uint32_t *)(C3_BASE_OFFSET_SYSTEM_REGISTERS+0x0010))
+// SYSTEM_UART_MEM_CLK_EN is on 24
+// SYSTEM_UARTn_CLK_EN n=0 is on 2, n=1 is on 5
+
+void config_uart();
+void init_uart();
+void reset_uart();
+void enable_uart_transmitter();
+void writeSomething();
+
+#endif
\ No newline at end of file
diff --git a/uart-transmit/main.c b/uart-transmit/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..d757d238ff2fb1fa452fe612011340ffa4c54bfd
--- /dev/null
+++ b/uart-transmit/main.c
@@ -0,0 +1,19 @@
+#include <mdk.h>
+#include "esp32-c3-uart-interface.h"
+#include "esp32-c3-led-helpers.h"
+
+int main(void) {
+  uint8_t green[3] = {1,0,0};
+  uint8_t black[3] = {0,0,0};
+  setupLED();
+  showColor(black);
+  // for some reason the first time we show a color, it's always a bright green...
+  showColorForDuration(green,1000);
+
+  init_uart();
+  config_uart();
+
+  showColor(black);
+
+  return 0;
+}