UART Interrupt without UART driver
Posted: Fri May 20, 2022 6:56 pm
Hi there,
ESP32-C3, VSCode.
I am used to work with AT(X)mega and PIC32 microcontrollers in C. For ATXmega, all I need to do is to configure the UART by writing few registers and write the interrupt handler like this:
As a beginner with ESP32, I would like to be able to work in the same way. I do not need a ring buffer other than the hardware one. I do not use RTOS, WIFI nor Bluetooth for this project.
So far I got the GPIO working and the timer with alarm, and configured USART except the receiving interrupt. I can send and receive bytes by writing directly to hardware registers. My code so far is like this:
This gives me some nice pulses and sends some bytes.
Is it possible to modify some files, or add to them so all I would have to do is declare and write my own interrupt handler by just dealing with the hardware registers ? I expect from the interrupt handler to deal with the preamble and postamble. I plan to use only one interrupt level among all interrupts I use. I am looking for help as to how to configure VSCode to achieve this. I am not knowledgeable enough to walk this step by myself.
If the effort is high, I am open to pay for the help.
To not waste time, please do not come with questions as why I want it this way, and tell what are the benefits of a UART driver, RTOS are etc.
Thank you.
ESP32-C3, VSCode.
I am used to work with AT(X)mega and PIC32 microcontrollers in C. For ATXmega, all I need to do is to configure the UART by writing few registers and write the interrupt handler like this:
Code: Select all
ISR(USARTC1_RXC_vect) {
// Interrupt handler code
}
So far I got the GPIO working and the timer with alarm, and configured USART except the receiving interrupt. I can send and receive bytes by writing directly to hardware registers. My code so far is like this:
Code: Select all
#include <stdio.h>
#include "soc/soc.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_reg.h"
#include "soc/system_reg.h"
#include "soc/timer_group_reg.h"
#include "soc/uart_reg.h"
#include "rom/ets_sys.h"
uint16_t u16Cnt1s;
uint16_t u16Cnt4ms;
uint32_t a;
uint32_t u32GpFlag1s;
uint32_t u32GpFlag4ms;
void app_main(void)
{
WRITE_PERI_REG(IO_MUX_GPIO0_REG, 1 << 7 | 1 << 2 | 1 << 0);
WRITE_PERI_REG(GPIO_ENABLE_W1TS_REG, 1);
// UART
WRITE_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG, READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG) | 1 << SYSTEM_UART_MEM_CLK_EN_S | 1 << SYSTEM_UART_CLK_EN_S); // set bits
WRITE_PERI_REG(SYSTEM_PERIP_RST_EN0_REG, READ_PERI_REG(SYSTEM_PERIP_RST_EN0_REG) & ~(1 << SYSTEM_UART_RST_S)); // clear bit
// write 1 to UART_RST_CORE in UART_CLK_CONF_REG
WRITE_PERI_REG(UART_CLK_CONF_REG(0), (READ_PERI_REG(UART_CLK_CONF_REG(0)) | (1 << UART_RST_CORE_S)));
// write 1 to SYSTEM_UARTn_RST in SYSTEM_PERIP_RST_EN0_REG
WRITE_PERI_REG(SYSTEM_PERIP_RST_EN0_REG, (READ_PERI_REG(SYSTEM_PERIP_RST_EN0_REG) | (1 << SYSTEM_UART_RST_S)));
// clear SYSTEM_UARTn_RST in SYSTEM_PERIP_RST_EN0_REG
WRITE_PERI_REG(SYSTEM_PERIP_RST_EN0_REG, (READ_PERI_REG(SYSTEM_PERIP_RST_EN0_REG) & ~(1 << SYSTEM_UART_RST_S)));
// clear UART_RST_CORE in UART_CLK_CONF_REG
WRITE_PERI_REG(UART_CLK_CONF_REG(0), (READ_PERI_REG(UART_CLK_CONF_REG(0)) & ~(1 << UART_RST_CORE_S)));
// enable register synchronization by clearing UART_UPDATE_CTRL
WRITE_PERI_REG(UART_ID_REG(0), (READ_PERI_REG(UART_ID_REG(0)) & ~(1 << UART_HIGH_SPEED_S)));
// 24.5.2.2 Configuring UARTn Communication
while(READ_PERI_REG(UART_ID_REG(0)) & (1 << UART_UPDATE_S)) {}
// write 3 (XTAL 40MHz clock select) to UART_CLK_CONF_REG
WRITE_PERI_REG(UART_CLK_CONF_REG(0), (1 << UART_RX_SCLK_EN_S | 1 << UART_TX_SCLK_EN_S | 1 << UART_SCLK_EN_S | 3 << UART_SCLK_SEL_S | 2 << UART_SCLK_DIV_NUM_S | 1 << UART_SCLK_DIV_A_S | 1 << UART_SCLK_DIV_B_S));
// configure baudrate in UART_CLKDIV_REG register
WRITE_PERI_REG(UART_CLKDIV_REG(0), (40 << UART_CLKDIV_S)); // UART baudrate, no fraction
// configure0 UART
WRITE_PERI_REG(UART_CONF0_REG(0), (1 << UART_MEM_CLK_EN_S | 1 << UART_CLK_EN_S | 1 << UART_TXFIFO_RST_S | 1 << UART_RXFIFO_RST_S | 2 << UART_STOP_BIT_NUM_S | 3 << UART_BIT_NUM_S)); // UART baudrate, no fraction
// clear bits UART_TXFIFO_RST, UART_RXFIFO_RST
WRITE_PERI_REG(UART_CONF0_REG(0), (1 << UART_MEM_CLK_EN_S | 1 << UART_CLK_EN_S | 3 << UART_STOP_BIT_NUM_S | 3 << UART_BIT_NUM_S)); // UART baudrate, no fraction
// configure1 UART
WRITE_PERI_REG(UART_CONF1_REG(0), (4 << UART_TXFIFO_EMPTY_THRHD_S | 0 << UART_RXFIFO_FULL_THRHD_S));
// no interrupts
WRITE_PERI_REG(UART_INT_ENA_REG(0), 0);
// synchronize
WRITE_PERI_REG(UART_ID_REG(0), (1 << UART_UPDATE_S));
// TC
WRITE_PERI_REG(TIMG_T0CONFIG_REG(0), (1 << TIMG_T0_INCREASE_S | 1 << TIMG_T0_AUTORELOAD_S | 32 << TIMG_T0_DIVIDER_S | 1 << TIMG_T0_ALARM_EN_S));
WRITE_PERI_REG(TIMG_T0CONFIG_REG(0), (1 << TIMG_T0_INCREASE_S | 1 << TIMG_T0_AUTORELOAD_S | 32 << TIMG_T0_DIVIDER_S | 1 << TIMG_T0_DIVCNT_RST_S | 1 << TIMG_T0_ALARM_EN_S));
WRITE_PERI_REG(TIMG_T0LOADLO_REG(0), 1);
WRITE_PERI_REG(TIMG_T0LOADHI_REG(0), 0);
WRITE_PERI_REG(TIMG_T0LOAD_REG(0), 0);
WRITE_PERI_REG(TIMG_T0ALARMLO_REG(0), 10000);
WRITE_PERI_REG(TIMG_T0ALARMHI_REG(0), 0);
WRITE_PERI_REG(TIMG_T0CONFIG_REG(0), (1 << TIMG_T0_EN_S | 1 << TIMG_T0_INCREASE_S | 1 << TIMG_T0_AUTORELOAD_S | 32 << TIMG_T0_DIVIDER_S | 1 << TIMG_T0_ALARM_EN_S));
while (1) {
WRITE_PERI_REG(TIMG_T0UPDATE_REG(0), 0); // read raw timer value
if ((READ_PERI_REG(TIMG_T0CONFIG_REG(0)) & (1 << TIMG_T0_ALARM_EN_S)) == 0) {
WRITE_PERI_REG(TIMG_T0CONFIG_REG(0), (1 << TIMG_T0_EN_S | 1 << TIMG_T0_INCREASE_S | 1 << TIMG_T0_AUTORELOAD_S | 32 << TIMG_T0_DIVIDER_S | 1 << TIMG_T0_ALARM_EN_S));
u32GpFlag4ms = 0xFFFFFFFF; // set 4ms flags for general registers
u16Cnt4ms ++;
// place here code to run every 4ms
WRITE_PERI_REG(GPIO_OUT_W1TS_REG, 1);
ets_delay_us(100);
WRITE_PERI_REG(GPIO_OUT_W1TC_REG, 1);
ets_delay_us(100);
if (u16Cnt4ms > 249) {
u16Cnt4ms = 0;
u32GpFlag1s = 0xFFFFFFFF;
u16Cnt1s ++;
// place here code to run every second
// send some bytes
WRITE_PERI_REG(UART_FIFO_REG(0), 0);
WRITE_PERI_REG(UART_FIFO_REG(0), 1);
WRITE_PERI_REG(UART_FIFO_REG(0), 2);
WRITE_PERI_REG(UART_FIFO_REG(0), 3);
WRITE_PERI_REG(UART_FIFO_REG(0), 4);
WRITE_PERI_REG(UART_FIFO_REG(0), 5);
}
}
}
}
Is it possible to modify some files, or add to them so all I would have to do is declare and write my own interrupt handler by just dealing with the hardware registers ? I expect from the interrupt handler to deal with the preamble and postamble. I plan to use only one interrupt level among all interrupts I use. I am looking for help as to how to configure VSCode to achieve this. I am not knowledgeable enough to walk this step by myself.
If the effort is high, I am open to pay for the help.
To not waste time, please do not come with questions as why I want it this way, and tell what are the benefits of a UART driver, RTOS are etc.
Thank you.