From c5c6b97ad138986b8408f83c69a67b6e44a5e501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Mon, 5 Jan 2026 21:55:19 +0100 Subject: [PATCH] installer: SERIAL: Use Timer1 instead of Timer2 Same as in the main code. Use Timer1 as baudrate generator. Timer1 can be programmed to have the same accuracy and deviation as Timer2, up to 115200 at F_SYS = 125 Mhz. See comment setup_serial_timer1() comment for valid baudrates and settings. Timer1 is used in 8-bit auto-reload mode. Only differance is that the serial is transmit only and poll-based so no interrupts are used to transmit data. --- installer/installer.c | 59 ++++++++++++++++++++++++++++++------------- rtlplayground.c | 4 ++- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/installer/installer.c b/installer/installer.c index 4764ff4..e4063fc 100644 --- a/installer/installer.c +++ b/installer/installer.c @@ -11,6 +11,7 @@ #include "../rtl837x_sfr.h" #include "../rtl837x_regs.h" +// See setup_serial_timer1() for valid baudrate settings! #define SERIAL_BAUD_RATE 57600 #define CLOCK_HZ 125000000 @@ -87,25 +88,52 @@ void print_short(uint16_t a) } } -void setup_serial(void) +/* Set up serial port 0 using Timer 1 as baudrate generator. + * For x Bd these settings are needed, see table below. + * NOTE: Settings only valid for F_SYS = 125 MHz! + * | Wanted | | TMR | F_SYS | | Actual | | + * | baudrate | SMOD0 | DIV | DIV | TH1 | baudrate | Error | + * | -------- | ----- | --- | ----- | ---- | -------- | ------ | + * | 1200 | 0 | 12 | 255 | 0x01 | 1276.6 | 6.00% | + * | 2400 | 0 | 12 | 136 | 0x78 | 2393.5 | −0.27% | + * | 4800 | 0 | 4 | 203 | 0x35 | 4810.7 | 0.22% | + * | 9600 | 1 | 4 | 203 | 0x35 | 9621.3 | 0.22% | + * | 14400 | 1 | 4 | 136 | 0x78 | 14361.2 | −0.27% | + * | 19200 | 1 | 4 | 102 | 0x9a | 19148.3 | −0.27% | + * | 38400 | 1 | 4 | 51 | 0xcd | 38296.6 | −0.27% | + * | 57600 | 1 | 4 | 34 | 0xde | 57444.9 | −0.27% | + * | 115200 | 1 | 4 | 17 | 0xef | 114889.7 | −0.27% | + */ +#if CLOCK_HZ != 125000000 +#warning "SERIAL 0 baudrate setting may only valid for F_CPU = 125 MHz!" +#endif +void setup_serial_timer1(void) { - IE = 0; + // Timer 1: Mode 2: automatic reload + TMOD &= 0x0F; + TMOD |= 0xA0; // Timer1: GATE, Mode2: Timer, 8-bit with auto-reload + CKCON |= 0x10; // Timer1 clock divider: F_SYS / 4: T2M = 1, Timer 1 uses clk/4 - T2CON = 0x34; // Enable RCLK/TCLK (serial transmit/receive clock for T2), TR2 (Timer 2 RUN), disable CP/RL2 (bit 0) - SCON = 0x50; // Mode = 1: ASYNC 8N1 with T2 as baud-rate generator, REN_0 Receive enable + PCON |= 0x80; // SMOD0 = 1; Double the Baud Rate, don't divide Timer 1 Overflag signal. - // The RCAP2 registers contain the high/low byte that is loaded into - // timer2 when T2 overflows to 0x10000 - RCAP2H = (0x10000 - (CLOCK_HZ / SERIAL_BAUD_RATE / 32)) >> 8; - RCAP2L = (0x10000 - (CLOCK_HZ / SERIAL_BAUD_RATE / 32)) % 0xff; + SCON = 0x50; // Mode = 1: ASYNC 8N1 with Timer 2 as baud-rate generator, REN_0 Receive enable - PCON |= 0x80; // Double the Baud Rate + /* The TH1 register contain the reload value, timer1 when T1 overflows to 0x100. + * NOTE: compiler computs the wrong value. 0xF0 is calculated but 0xEF is the right value for 115200. + * Also https://www.keil.com/products/c51/baudrate.asp confirms this. + * Added 32 before div by 64 to make sure rounding is correct so that the results are right. + * + * TH1 = 0x100 - (2^SMOD0 * F_SYS) / ( TMR1_DIV / BAUDRATE * 32) + */ + TH1 = (0x100 - (((CLOCK_HZ / SERIAL_BAUD_RATE) + 32) / (4 * 16))) & 0xff; - SCON = 0x50; - TI = 1; - RI = 0; + TCON |= 0x40; // Start timer 1 - ES = 1; // Enable serial IRQ + ET1 = 0; // Timer1 Interrupt is NOT wanted! + TI = 1; // Set TI-interrupt/flag, to flag that the TX-buf is empty. + RI = 0; // Clear RI-interrupt flag + + ES = 0; // Disable serial IRQ, software is only printing data and just polls TI-flag. } /* @@ -330,10 +358,7 @@ void installer(void) IE = 0; EIE = 0; // SFR e8: EIE. Disable all external IRQs - // Disable all interrupts (global interrupt enable bit) - EA = 0; // SFR A8.7 / IE.7 - - setup_serial(); + setup_serial_timer1(); print_string("\nRTLPlayground installer starting...\n"); // Initialize flash functions with disable DIO because writing does not work otherwise diff --git a/rtlplayground.c b/rtlplayground.c index 53c9cd7..94e75c4 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -121,7 +121,7 @@ __xdata char sfp_module_vendor[2][17]; __xdata char sfp_module_model[2][17]; __xdata char sfp_module_serial[2][17]; __xdata uint8_t sfp_options[2]; -__sbit tx_buf_empty = 1; +__sbit tx_buf_empty; #define ETHERTYPE_OFFSET (12 + VLAN_TAG_SIZE + RTL_TAG_SIZE) @@ -1713,6 +1713,8 @@ void setup_serial_timer1(void) TI = 0; // Clear TI-interrupt flag RI = 0; // Clear RI-interrupt flag + tx_buf_empty = 1; // Set tx `serial buffer is empty`-software flag. + ES = 1; // Enable serial IRQ }