Configuring UART registers and peripheral clock
Posted: Tue Apr 04, 2023 7:29 pm
Hi,
I've been trying for days now to configure UART by playing around with the bare registers themselves. The workflow that I believe should work is (currently, I'm only figuring out the transmission part):
1. Selecting clock source as PLL_CLK (80 MHz)
2. Enabling the UART clock
3. Selecting the APB_CLK and determining the integral part as well as the fractional part to set the baud rate
4... Configuring the stop bits, data length, allocating TX buffer memory, and writing data into the TX FIFO buffer
However, when I try to set these individual bits and/or registers, they don't necessarily work with every register. Moreover, when I try to set the clock as APB_CLK for UART0 it works but when I try it for UART1, it doesn't set that bit. The same goes for selecting the integral and fractional values; it sets the wanted values for UART0 but not for UART1.
Is there something I'm missing in the workflow, or doing something wrong to begin with? I do have further questions regarding configuring UART registers but would like to get this sorted out first.
Here's the code:
I've been trying for days now to configure UART by playing around with the bare registers themselves. The workflow that I believe should work is (currently, I'm only figuring out the transmission part):
1. Selecting clock source as PLL_CLK (80 MHz)
2. Enabling the UART clock
3. Selecting the APB_CLK and determining the integral part as well as the fractional part to set the baud rate
4... Configuring the stop bits, data length, allocating TX buffer memory, and writing data into the TX FIFO buffer
However, when I try to set these individual bits and/or registers, they don't necessarily work with every register. Moreover, when I try to set the clock as APB_CLK for UART0 it works but when I try it for UART1, it doesn't set that bit. The same goes for selecting the integral and fractional values; it sets the wanted values for UART0 but not for UART1.
Is there something I'm missing in the workflow, or doing something wrong to begin with? I do have further questions regarding configuring UART registers but would like to get this sorted out first.
Here's the code:
- #include <stdio.h>
- #include <string.h>
- #include "driver/uart.h"
- #include "freertos/FreeRTOS.h"
- #include "esp_err.h"
- #include "include/soc/uart_reg.h"
- #include "include/soc/rtc_cntl_reg.h"
- #include "include/soc/dport_reg.h"
- #include "include/soc/apb_ctrl_reg.h"
- #define UART0 (0)
- #define UART1 (1)
- #define UART2 (2)
- #define BYTE_TO_BINARY_PATTERN "%c%c%c%c %c%c%c%c %c%c%c%c %c%c%c%c %c%c%c%c %c%c%c%c %c%c%c%c %c%c%c%c"
- #define BYTE_TO_BINARY(byte) \
- ((byte) & 0x80000000 ? '1' : '0'), \
- ((byte) & 0x40000000 ? '1' : '0'), \
- ((byte) & 0x20000000 ? '1' : '0'), \
- ((byte) & 0x10000000 ? '1' : '0'), \
- ((byte) & 0x08000000 ? '1' : '0'), \
- ((byte) & 0x04000000 ? '1' : '0'), \
- ((byte) & 0x02000000 ? '1' : '0'), \
- ((byte) & 0x01000000 ? '1' : '0'), \
- ((byte) & 0x00800000 ? '1' : '0'), \
- ((byte) & 0x00400000 ? '1' : '0'), \
- ((byte) & 0x00200000 ? '1' : '0'), \
- ((byte) & 0x00100000 ? '1' : '0'), \
- ((byte) & 0x00080000 ? '1' : '0'), \
- ((byte) & 0x00040000 ? '1' : '0'), \
- ((byte) & 0x00020000 ? '1' : '0'), \
- ((byte) & 0x00010000 ? '1' : '0'), \
- ((byte) & 0x00008000 ? '1' : '0'), \
- ((byte) & 0x00004000 ? '1' : '0'), \
- ((byte) & 0x00002000 ? '1' : '0'), \
- ((byte) & 0x00001000 ? '1' : '0'), \
- ((byte) & 0x00000800 ? '1' : '0'), \
- ((byte) & 0x00000400 ? '1' : '0'), \
- ((byte) & 0x00000200 ? '1' : '0'), \
- ((byte) & 0x00000100 ? '1' : '0'), \
- ((byte) & 0x00000080 ? '1' : '0'), \
- ((byte) & 0x00000040 ? '1' : '0'), \
- ((byte) & 0x00000020 ? '1' : '0'), \
- ((byte) & 0x00000010 ? '1' : '0'), \
- ((byte) & 0x00000008 ? '1' : '0'), \
- ((byte) & 0x00000004 ? '1' : '0'), \
- ((byte) & 0x00000002 ? '1' : '0'), \
- ((byte) & 0x00000001 ? '1' : '0')
- void app_main(void)
- {
- char *test = "HEY BIG BOI\n";
- // Select CPU clock source as PLL_CLK by configuring the RTC_CNTL_SOC_CLK_SEL bit to 1
- REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, (BIT(27))); // Done
- printf("CPU source PLL " BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(READ_PERI_REG(RTC_CNTL_CLK_CONF_REG)));
- // Set CPU clock to 0 to get 80 MHz PLL_CLK
- DPORT_REG_CLR_BIT(DPORT_CPU_PER_CONF_REG, (BIT(0))); // Done correctly
- printf("CLK reference " BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(DPORT_REG_READ(DPORT_CPU_PER_CONF_REG)));
- // printf("CPU CLOCK SHOULD BE ZERO: %lx\n", DPORT_REG_READ(DPORT_CPU_PER_CONF_REG));
- // Enable UART1 clock
- DPORT_REG_SET_BIT(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN | DPORT_UART_MEM_CLK_EN); // Done correctly
- printf("UART1 Clock " BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(DPORT_REG_READ(DPORT_PERIP_CLK_EN_REG)));
- // Select APB clock
- REG_SET_BITS(UART_CONF0_REG(UART1), (BIT(27)), 0x01000000); // ????
- printf("APB_CLK_SOURCE " BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(READ_PERI_REG(UART_CONF0_REG(UART1))));
- // Drive UART module by generating clock signals
- WRITE_PERI_REG(UART_CLKDIV_REG(UART1), 0x0002B6); // Integer part
- // WRITE_PERI_REG(UART_CLKDIV_REG(UART_CLKDIV_FRAG), 0x); // Decimal part
- printf("Integral clock " BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(READ_PERI_REG(UART_CLKDIV_REG(UART1))));
- // Set length of data (8 bits)
- // WRITE_PERI_REG(UART_CONF0_REG(UART_BIT_NUM), 0x00000003);
- printf("Length of data set is: %lx\n", READ_PERI_REG(UART_CONF0_REG(3 << 1)));
- // Set length of stop bit (1 bit)
- WRITE_PERI_REG(UART_CONF0_REG(UART_STOP_BIT_NUM), 0x01);
- // Allocate TX memory
- WRITE_PERI_REG(UART_MEM_CONF_REG(UART_TX_SIZE), 0x80);
- // Enable transmitter flow control function
- // WRITE_PERI_REG(UART_CONF0_REG(UART_SW_RTS), 0x01);
- // WRITE_PERI_REG(UART_CONF0_REG(UART_TX_FLOW_EN), 0x01);
- // WRITE_PERI_REG(UART_CONF1_REG(UART_RX_FLOW_EN), 0x00);
- // Enable interrupt pin for UART_TX_DONE_INT
- // WRITE_PERI_REG(UART_INT_ENA_REG(UART_TX_DONE_INT_ENA), 0x01);
- // Write data into Tx buffer | UART0 TX FIFO Buffer - 0x3FF4005C
- for (int i=0; i<strlen(test); i++) {
- WRITE_PERI_REG(UART_MEM_TX_STATUS_REG(UART_MEM_TX_WR_ADDR), test[i]);
- }
- // Read number of bytes stored in Tx buffer
- printf("%ld\n", READ_PERI_REG(UART_STATUS_REG(UART_TXFIFO_CNT)));
- // UART controller serializes data
- // UART sends data
- // Start is 0 or LOW while Stop is 1 or HIGH
- // UART_TX_DONE_INT - Interrupt raised when transmitter has sent out all FIFO data
- }
- /* void UART_SEND() {
- } */
- /* void UART_RECEIVE() {
- } */