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.
This commit is contained in:
René van Dorst
2026-01-09 07:52:35 +01:00
parent 5b4b0efb16
commit c5c6b97ad1
2 changed files with 45 additions and 18 deletions
+42 -17
View File
@@ -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
+3 -1
View File
@@ -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
}