diff --git a/src/uart-transmit/esp32-c3-uart-interface.c b/src/uart-transmit/esp32-c3-uart-interface.c new file mode 100644 index 0000000000000000000000000000000000000000..a5ec44ef947ae1972666fcb1459f6034fb372524 --- /dev/null +++ b/src/uart-transmit/esp32-c3-uart-interface.c @@ -0,0 +1,148 @@ +#include "esp32-c3-uart-interface.h" + +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_reg = *C3_SYSTEM_PERIP_CLK_EN0_REG; + perip_clk_en0_reg |= 1<<24; + perip_clk_en0_reg |= 1<<5; + perip_clk_en0_reg |= 1<<2; + *C3_SYSTEM_PERIP_CLK_EN0_REG = perip_clk_en0_reg; +} + +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_reg = *C3_UART_RX_FILT_REG; + uint32_t core_value = *C3_UART_CLK_CONF_REG; + // clear UARTn_RST + rx_filt_reg &= (uint32_t)~(1<<5); + rx_filt_reg &= (uint32_t)~(1<<2); + *C3_UART_RX_FILT_REG = rx_filt_reg; + // set UART_RST_CORE + core_value |= 1<<23; + *C3_UART_CLK_CONF_REG = core_value; + // set UARTn_RST + rx_filt_reg |= 1<<5; + rx_filt_reg |= 1<<2; + *C3_UART_RX_FILT_REG = rx_filt_reg; + // clear UARTn_RST + rx_filt_reg &= (uint32_t)~(1<<5); + rx_filt_reg &= (uint32_t)~(1<<2); + *C3_UART_RX_FILT_REG = rx_filt_reg; + // clear UART_RST_CORE + core_value &= (uint32_t)~(1<<23); + *C3_UART_CLK_CONF_REG = core_value; +} + +static void init_uart_clear_update(){ + // enable register synchronization by clearing UART_UPDATE_CTRL. + uint32_t id_value = *C3_UART_ID_REG; + id_value &= (uint32_t)~(1<<30); + *C3_UART_ID_REG = 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; + // 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 = 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 = clockSelect; + + // calculate Baud rate to be 9600 (6Mhz/625) + uint32_t baudRateDivs = *C3_UART_CLKDIV_REG; + baudRateDivs |= 1<<0; + baudRateDivs |= 1<<4; + baudRateDivs |= 1<<5; + baudRateDivs |= 1<<6; + baudRateDivs |= 1<<9; + *C3_UART_CLKDIV_REG = baudRateDivs; +} + +static void disable_parity(){ + uint32_t uart_conf_reg = *C3_UART_CONF0_REG; + uart_conf_reg &= (uint32_t)~(1<<0); + uart_conf_reg &= (uint32_t)~(1<<1); + *C3_UART_CONF0_REG = uart_conf_reg; +} + +static void set_max_data_lenght(){ + uint32_t uart_conf_reg = *C3_UART_CONF0_REG; + uart_conf_reg |= (1<<2); + uart_conf_reg |= (1<<3); + *C3_UART_CONF0_REG = uart_conf_reg; +} + +void config_uart(){ + printf("Try to config %d\n", 1); + // wait for UART_REG_UPDATE to become 0, which indicates the completion of the last synchronization; + uint32_t reg_update = *C3_UART_ID_REG; + if ((bool)(reg_update & (uint32_t)(1<<31))){ + return; + } + + printf("Ready to config %d\n", 1); + + // 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 = reg_update; +} + +void enable_uart_transmitter(){ + // configure TX FIFO’s empty threshold via UART_TXFIFO_EMPTY_THRHD; + // disable UART_TXFIFO_EMPTY_INT interrupt by clearing UART_TXFIFO_EMPTY_INT_ENA; + // write data to be sent to UART_RXFIFO_RD_BYTE; + // clear UART_TXFIFO_EMPTY_INT interrupt by setting UART_TXFIFO_EMPTY_INT_CLR; + // enable UART_TXFIFO_EMPTY_INT interrupt by setting UART_TXFIFO_EMPTY_INT_ENA; + // detect UART_TXFIFO_EMPTY_INT and wait for the completion of data transmission. +} + +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/src/uart-transmit/esp32-c3-uart-interface.h b/src/uart-transmit/esp32-c3-uart-interface.h new file mode 100644 index 0000000000000000000000000000000000000000..34a5ad50bb683dc87fa129a6bf899fef7389f33e --- /dev/null +++ b/src/uart-transmit/esp32-c3-uart-interface.h @@ -0,0 +1,36 @@ +#ifndef ESP32_C3_UART_INTERFACE_H +#define ESP32_C3_UART_INTERFACE_H + +#define C3_SYSTEM_PERIP_CLK_EN0_REG ((volatile uint32_t *)0x0010) +// SYSTEM_UART_MEM_CLK_EN is on 24 +// SYSTEM_UARTn_CLK_EN n=0 is on 2, n=1 is on 5 + +#define C3_UART_CLKDIV_REG ((volatile uint32_t *)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 ((volatile uint32_t *)0x0018) +// SYSTEM_UARTn_RST n=0 is on 2, n=1 is on 5 + +#define C3_UART_CONF0_REG ((volatile uint32_t *)0x0020) +// UART_PARITY is on 0 +// UART_PARITY_EN is on 1 +// UART_BIT_NUM is on 2 and 3 + +#define C3_UART_CLK_CONF_REG ((volatile uint32_t *)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 ((volatile uint32_t *)0x0080) +// UART_UPDATE_CTRL is on 30 +// UART_REG_UPDATE is on 31 + +void config_uart(); +void init_uart(); +void reset_uart(); +void enable_uart_transmitter(); + +#endif \ No newline at end of file diff --git a/src/uart-transmit/main.c b/src/uart-transmit/main.c index 703e323584bceecce9f6e96a4ced871b7c1f98e7..77fa3d3e0c7a87f5e0ac2e7a12d075f59794bfb5 100644 --- a/src/uart-transmit/main.c +++ b/src/uart-transmit/main.c @@ -3,183 +3,9 @@ #include <mdk.h> -#define C3_SYSTEM_PERIP_CLK_EN0_REG ((volatile uint32_t *)0x0010) -// SYSTEM_UART_MEM_CLK_EN is on 24 -// SYSTEM_UARTn_CLK_EN n=0 is on 2, n=1 is on 5 - -#define C3_UART_CLKDIV_REG ((volatile uint32_t *)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 ((volatile uint32_t *)0x0018) -// SYSTEM_UARTn_RST n=0 is on 2, n=1 is on 5 - -#define C3_UART_CONF0_REG ((volatile uint32_t *)0x0020) -// UART_PARITY is on 0 -// UART_PARITY_EN is on 1 -// UART_BIT_NUM is on 2 and 3 - -#define C3_UART_CLK_CONF_REG ((volatile uint32_t *)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 ((volatile uint32_t *)0x0080) -// UART_UPDATE_CTRL is on 30 -// UART_REG_UPDATE is on 31 - // On the ESP32C3 dev boards, the WS2812 LED is connected to GPIO 8 static int ws_2812_pin = 8; -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_reg = *C3_SYSTEM_PERIP_CLK_EN0_REG; - perip_clk_en0_reg |= 1<<24; - perip_clk_en0_reg |= 1<<5; - perip_clk_en0_reg |= 1<<2; - *C3_SYSTEM_PERIP_CLK_EN0_REG = perip_clk_en0_reg; -} - -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_reg = *C3_UART_RX_FILT_REG; - uint32_t core_value = *C3_UART_CLK_CONF_REG; - // clear UARTn_RST - rx_filt_reg &= (uint32_t)~(1<<5); - rx_filt_reg &= (uint32_t)~(1<<2); - *C3_UART_RX_FILT_REG = rx_filt_reg; - // set UART_RST_CORE - core_value |= 1<<23; - *C3_UART_CLK_CONF_REG = core_value; - // set UARTn_RST - rx_filt_reg |= 1<<5; - rx_filt_reg |= 1<<2; - *C3_UART_RX_FILT_REG = rx_filt_reg; - // clear UARTn_RST - rx_filt_reg &= (uint32_t)~(1<<5); - rx_filt_reg &= (uint32_t)~(1<<2); - *C3_UART_RX_FILT_REG = rx_filt_reg; - // clear UART_RST_CORE - core_value &= (uint32_t)~(1<<23); - *C3_UART_CLK_CONF_REG = core_value; -} - -static void init_uart_clear_update(){ - // enable register synchronization by clearing UART_UPDATE_CTRL. - uint32_t id_value = *C3_UART_ID_REG; - id_value &= (uint32_t)~(1<<30); - *C3_UART_ID_REG = 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; - // 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 = 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 = clockSelect; - - // calculate Baud rate to be 9600 (6Mhz/625) - uint32_t baudRateDivs = *C3_UART_CLKDIV_REG; - baudRateDivs |= 1<<0; - baudRateDivs |= 1<<4; - baudRateDivs |= 1<<5; - baudRateDivs |= 1<<6; - baudRateDivs |= 1<<9; - *C3_UART_CLKDIV_REG = baudRateDivs; -} - -static void disable_parity(){ - uint32_t uart_conf_reg = *C3_UART_CONF0_REG; - uart_conf_reg &= (uint32_t)~(1<<0); - uart_conf_reg &= (uint32_t)~(1<<1); - *C3_UART_CONF0_REG = uart_conf_reg; -} - -static void set_max_data_lenght(){ - uint32_t uart_conf_reg = *C3_UART_CONF0_REG; - uart_conf_reg |= (1<<2); - uart_conf_reg |= (1<<3); - *C3_UART_CONF0_REG = uart_conf_reg; -} - -static void config_uart(){ - printf("Try to config %d\n", 1); - // wait for UART_REG_UPDATE to become 0, which indicates the completion of the last synchronization; - uint32_t reg_update = *C3_UART_ID_REG; - if ((bool)(reg_update & (uint32_t)(1<<31))){ - return; - } - - printf("Ready to config %d\n", 1); - - // 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 = reg_update; -} - -static void enable_uart_transmitter(){ - // configure TX FIFO’s empty threshold via UART_TXFIFO_EMPTY_THRHD; - // disable UART_TXFIFO_EMPTY_INT interrupt by clearing UART_TXFIFO_EMPTY_INT_ENA; - // write data to be sent to UART_RXFIFO_RD_BYTE; - // clear UART_TXFIFO_EMPTY_INT interrupt by setting UART_TXFIFO_EMPTY_INT_CLR; - // enable UART_TXFIFO_EMPTY_INT interrupt by setting UART_TXFIFO_EMPTY_INT_ENA; - // detect UART_TXFIFO_EMPTY_INT and wait for the completion of data transmission. -} - -//static void reset_uart(){ - // 26.4.1 Clock and Reset -// init_uart_enable_clk(); -// init_uart_toggle_rst(); -//} - -static void init_uart(){ - // from technical reference manual 543 f - init_uart_enable_clk(); - init_uart_toggle_rst(); - init_uart_clear_update(); -} - // Simple hue function for generation of smooth rainbow. static uint8_t hueval(int value) { value = value % 1536;