I am trying to write bare-metal code for ESP8266 (for learning how embedded system works).
My GPIO code is working and now I am trying to play around with UART.
In ESP8266 REG = 0x60000000 is FIFO for Uart0.
REG = 0x60000014 is used to change CLK Divisor for UART0.
Now in SDK, they are using uart_div_modify(uint32_t uart, uint32_t div) to change baud rate of ESP8266 with CPU Clock frequency (80Mhz).
Now when I do not change baudrate of ESP (default is 74880, set by ROM)), I can write to FIFO Reg and I can see output on serial monitor. ESP code -
void write(char c) {
WRITE_TO_REG(UART_BASE(0), c);
}
...
...
while (1) {
write('A');
for (rx = 0; rx < 800000; rx++);
}
But the thing is, ESP8266 changes baudrate of UART0 after booting, to 115200, which means if you want to read data, you need to put baud rate of serial monitor as 115200. But the thing is, if you read at 115200 baud rate, you get garbage value. You need to read at 74880 baud rate.
Now, I tried to change baud rate by change value of UART_CLKDIV using this formula -
CPU_FREQ/baudrate.
uint32_t clk_div = CPU_CLK_80MHZ / (baud_rate);
WRITE_TO_REG(UART_CLKDIV(uart),
(clk_div & UART_CLKDIV_MASK) |
(READ_FROM_REG(UART_CLKDIV(uart)) &
(~UART_CLKDIV_MASK)));
But it doesn't work, it gives me garbage value on Serial Monitor. I can't even read at 74880 baud rate too, after changing its default baud rate.
I tried to use Lib (libcore.a) given by SDK,
uart_div_modify(0, CPU_80MHZ / 115200)
but still same issue.
Is there something I am missing? Btw I am trying to do this because I want learn how this ESP8266 SDK actually works.
EDIT - As @the-busybee asked me to do, I sent some patterns using UART.
I sent 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x8 with two different baud rates (9600 and 115200).
Here what I got -
| Byte | 9600 Out | 9600 Out Binary | 115200 Out | 115200 Out Binary |
|---|---|---|---|---|
| 0x01 | 0x02 | 0B10 | 0x02 | 0B10 |
| 0x02 | 0x0c | 0B1100 | 0x0c | 0B1100 |
| 0x03 | 0x0e | 0B1110 | 0x0e | 0B1110 |
| 0x04 | 0x30 | 0B110000 | 0x10 | 0B10000 |
| 0x05 | 0x32 | 0B110010 | 0x12 | 0B10010 |
| 0x06 | 0x3c | 0B111100 | 0x1c | 0B11100 |
| 0x07 | 0x3e | 0B111110 | 0x1e | 0B11110 |
| 0x08 | 0x40 | 0B1000000 | 0x60 | 0B1100000 |
I think problem is with stop bits and flow control. Btw I have default config (stop bits - 1, flow control - Disabled, Parity check - Disabled)
EDIT AGAIN - SCREENSHOTS OF LOGIC ANALYZER -
When I send 0x01 from esp8266, I get this on logic analyzer.

Now when I send 0x05 from esp8266, I get this.

Why some bits are repeated? like it sends 0 two times consecutively?
Or it the problem in Logic Analyzer?
Actual issue was with how ESP8266 generate CPU clock with crystal.
When ESP8266 comes out of Boot rom, its actual CPU clock frequency is 52MHz (because of 26MHz crystal).
Official SDK and Platformio framework for Esp8266 calls a function os_update_cpu_frequency(uint32_t freq) to change frequency of ESP8266 from 52MHz to 80MHz or 160MHz, but in my cause I don't have this function because I am doing baremetal.
So all these time I was assuming that my ESP8266 is running at 80MHz and not at 56MHz by default. Which caused this issue.
This os_update_cpu_frequency(uint32_t freq) function is defined at 0x40002f04 address if you are using Official SDK.