โ Home ยท Devices
serial.device โ UART and RS-232 Communication
Overview
serial.device provides access to the Amiga's built-in UART (Universal Asynchronous Receiver/Transmitter) for RS-232 serial communication. The hardware UART is implemented using CIA-B shift registers and custom chip DMA. Serial I/O is fundamental for debugging (serial console), modem communication, MIDI, and inter-machine networking.
Hardware
Serial Port Pins (DB-25)
| Pin |
Signal |
Direction |
Description |
| 2 |
TxD |
Output |
Transmit data |
| 3 |
RxD |
Input |
Receive data |
| 4 |
RTS |
Output |
Request to send (active low) |
| 5 |
CTS |
Input |
Clear to send (active low) |
| 6 |
DSR |
Input |
Data set ready |
| 7 |
GND |
โ |
Signal ground |
| 8 |
CD |
Input |
Carrier detect |
| 20 |
DTR |
Output |
Data terminal ready |
Custom Chip Registers
| Register |
Address |
Description |
SERDAT |
$DFF030 |
Serial data write (transmit) โ 9 bits: stop bit + 8 data |
SERDATR |
$DFF018 |
Serial data read (receive) โ status + received byte |
SERPER |
$DFF032 |
Serial period (baud rate divider) |
ADKCON |
$DFF09E |
UARTBRK bit for break signal |
Baud Rate Calculation
/* SERPER value = (system_clock / baud_rate) - 1 */
/* PAL system clock for serial = 3,546,895 Hz */
/* NTSC = 3,579,545 Hz */
#define SERIAL_CLOCK_PAL 3546895
#define SERIAL_CLOCK_NTSC 3579545
UWORD serper_from_baud(ULONG baud, BOOL isPAL) {
return (isPAL ? SERIAL_CLOCK_PAL : SERIAL_CLOCK_NTSC) / baud - 1;
}
| Baud Rate |
SERPER (PAL) |
SERPER (NTSC) |
| 1200 |
2955 |
2982 |
| 2400 |
1477 |
1491 |
| 9600 |
368 |
372 |
| 19200 |
184 |
185 |
| 31250 (MIDI) |
112 |
113 |
| 57600 |
60 |
61 |
| 115200 |
29 |
30 |
Using serial.device
struct MsgPort *serialPort = CreateMsgPort();
struct IOExtSer *serialReq = (struct IOExtSer *)
CreateIORequest(serialPort, sizeof(struct IOExtSer));
/* Open serial.device unit 0: */
BYTE err = OpenDevice("serial.device", 0,
(struct IORequest *)serialReq, 0);
/* Configure: */
serialReq->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
serialReq->io_Baud = 9600;
serialReq->io_ReadLen = 8; /* 8 data bits */
serialReq->io_WriteLen = 8;
serialReq->io_StopBits = 1;
serialReq->io_RBufLen = 4096; /* receive buffer size */
serialReq->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO((struct IORequest *)serialReq);
Write Data
serialReq->IOSer.io_Command = CMD_WRITE;
serialReq->IOSer.io_Data = "Hello Serial\r\n";
serialReq->IOSer.io_Length = 14;
DoIO((struct IORequest *)serialReq);
Read Data
/* Check how many bytes are waiting: */
serialReq->IOSer.io_Command = SDCMD_QUERY;
DoIO((struct IORequest *)serialReq);
ULONG waiting = serialReq->IOSer.io_Actual;
if (waiting > 0) {
serialReq->IOSer.io_Command = CMD_READ;
serialReq->IOSer.io_Data = buffer;
serialReq->IOSer.io_Length = waiting;
DoIO((struct IORequest *)serialReq);
/* buffer now contains received data */
}
Serial Debugging
Many developers use a null-modem cable to a terminal for kernel debugging:
/* Kprintf โ ROM debug output via serial (ROMTags/exec): */
/* This bypasses serial.device entirely โ writes directly to SERDAT */
void KPrintF(const char *fmt, ...); /* available in debug ROMs */
/* Sushi/Sashimi โ capture serial debug output on another Amiga */
References
- NDK39:
devices/serial.h
- HRM: Amiga Hardware Reference Manual โ Serial Port chapter
- ADCD 2.1: serial.device autodocs