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