Skip to content
Snippets Groups Projects
Commit 3dd30d56 authored by davip00's avatar davip00
Browse files

Merge branch 'initilize-and-use-uart-transmitter' into 'main'

copied and adapted example from mdk, added init and config uart

See merge request !1
parents b9844818 ce6e7402
No related branches found
No related tags found
1 merge request!1copied and adapted example from mdk, added init and config uart
Showing
with 808 additions and 0 deletions
File added
File moved
File moved
SOURCES = main.c esp32-c3-register-interface.c
include $(MDK)/$(ARCH)/build.mk
#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
#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
#include <mdk.h>
#include "esp32-c3-register-interface.h"
int main(void) {
wdt_disable();
readSetClear();
return 0;
}
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
{
// 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
TOOLCHAIN=riscv32-unknown-elf
EXTRA_CFLAGS ?= -Og -g
SOURCES = main.c esp32-c3-uart-interface.c
include $(MDK)/$(ARCH)/build.mk
#!/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
#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
#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
// 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
SOURCES = main.c esp32-c3-uart-interface.c esp32-c3-led-helpers.c
include $(MDK)/$(ARCH)/build.mk
#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
#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
#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
#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
#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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment