From 4a7f45ee28ac0799ba1ca93fd1683f7858efc54a Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 2 Jun 2017 16:22:26 +0200 Subject: add serial interface and a few std library functions changes in usart: - new functions to setup the serial comunication settings such as baudrate, parity and stop bits - init function with most common values - transmit and receive functions each with a wrapper to send data blocks changes in libc: - new file stdio.c with basic implementation of putch, printf still a prototype - new file string.c with memcpy() function --- sw/z80/kernel/include/devices.h | 6 +- sw/z80/kernel/include/pio.h | 18 +++++ sw/z80/kernel/include/serial.h | 85 ----------------------- sw/z80/kernel/include/usart.h | 149 ++++++++++++++++++++++++++++++++++++++++ sw/z80/kernel/kernel.c | 4 +- sw/z80/kernel/pio.c | 29 ++++++++ sw/z80/kernel/usart.c | 91 ++++++++++++++++++++++++ sw/z80/libc/include/stdio.h | 11 +++ sw/z80/libc/include/string.h | 8 +++ sw/z80/libc/stdio.c | 12 ++++ sw/z80/libc/string.c | 13 ++++ 11 files changed, 336 insertions(+), 90 deletions(-) create mode 100644 sw/z80/kernel/include/pio.h delete mode 100644 sw/z80/kernel/include/serial.h create mode 100644 sw/z80/kernel/include/usart.h create mode 100644 sw/z80/kernel/pio.c create mode 100644 sw/z80/kernel/usart.c create mode 100644 sw/z80/libc/include/stdio.h create mode 100644 sw/z80/libc/include/string.h create mode 100644 sw/z80/libc/stdio.c create mode 100644 sw/z80/libc/string.c diff --git a/sw/z80/kernel/include/devices.h b/sw/z80/kernel/include/devices.h index ea29065..e8c183f 100644 --- a/sw/z80/kernel/include/devices.h +++ b/sw/z80/kernel/include/devices.h @@ -4,9 +4,9 @@ #define ADDR_DEV_ROM_L 0x0000 #define ADDR_DEV_ROM_H 0x2000 -#define ADDR_DEV_USART 0x4000 -#define ADDR_DEV_CTC -#define ADDR_DEV_PIO +#define ADDR_DEV_USART 0x4000 +#define ADDR_DEV_CTC 0x4100 +#define ADDR_DEV_PIO 0x4200 #define ADDR_DEV_RAM 0x8000 diff --git a/sw/z80/kernel/include/pio.h b/sw/z80/kernel/include/pio.h new file mode 100644 index 0000000..8d72ab0 --- /dev/null +++ b/sw/z80/kernel/include/pio.h @@ -0,0 +1,18 @@ +#ifndef __PIO_H__ +#define __PIO_H__ + +#define PIO_A 0 +#define PIO_B 1 + + +void pio_data(int port, uint8_t data); +void pio_command(int port, uint8_t cmd); + +uint8_t pio_read_data(int port); + +inline int pio_read_pin(int port, uint8_t pin); +inline void pio_write_pin(int port, uint8_t pin); + +// TODO: implement mode (in/out/both) and interrupt vector + +#endif // __PIO_H__ diff --git a/sw/z80/kernel/include/serial.h b/sw/z80/kernel/include/serial.h deleted file mode 100644 index 03e2448..0000000 --- a/sw/z80/kernel/include/serial.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef __SERIAL_H__ -#define __SERIAL_H__ - -#include "types.h" -#include "devices.h" - -/* this structure is only for internal usage */ -struct _usart_device -{ - register_t buffer; // also used as LSB for divisor latch - - struct IER - { - volatile int received_data_interrupt :1; - volatile int transmitter_empty_interrupt :1; - volatile int receiver_line_status_interrupt :1; - volatile int modem_status_interrupt :1; - volatile int reserved :4; - } IER; - - struct IIR - { - volatile int interrupt_pending :1; - volatile int interrupt_id :3; - volatile int reserved :2; - volatile int fifos :2; - } IIR; - - struct FCR - { - volatile int fifo_enable :1; - volatile int receiver_fifo_rst :1; - } - - struct LCR - { - volatile int word_length :2; - volatile int stop_bits :1; - volatile int parity :1; - volatile int even_parity :1; - volatile int stick_parity :1; - volatile int break_control :1; - volatile int divisor_latch_access :1; - } LCR; - - struct MCR - { - volatile int data_terminal_ready :1; - volatile int request_to_send :1; - volatile int out1; - volatile int out2; - volatile int loop; - volatile int autoflow :1; - volatile int reserved :2; - } MCR; - - struct LSR - { - volatile int data_ready :1; - volatile int overrun_error :1; - volatile int parity_error :1; - volatile int framing_error :1; - volatile int break_interrupt :1; - volatile int transmitter_register :1; - volatile int transmitter_emtpy :1; - volatile int fifo_recv_error :1; - } LSR; - - struct MSR - { - volatile int delta_cts :1; - volatile int delta_data_set_ready :1; - volatile int trailing_edge_ring_indicator :1; - volatile int delta_data_carrier_detect :1; - volatile int clear_to_send :1; - volatile int data_set_ready :1; - volatile int ring_indicator :1; - volatile int data_carrier_detect :1; - } MSR; - - register_t scratch; -} *_usart = (_usart_device *) ADDR_DEV_USART; - - -#endif // __SERIAL__H__ diff --git a/sw/z80/kernel/include/usart.h b/sw/z80/kernel/include/usart.h new file mode 100644 index 0000000..f1f428e --- /dev/null +++ b/sw/z80/kernel/include/usart.h @@ -0,0 +1,149 @@ +#ifndef __USART_H__ +#define __USART_H__ + +#include "types.h" +#include "devices.h" + +#include "string.h" + +// baudrate clock divisors +// values from TL16C550C datasheet (table 9 for 1.8432 MHz crystal) +#define USART_BAUDRATE_50 2304 +#define USART_BAUDRATE_75 1536 +#define USART_BAUDRATE_110 1047 +#define USART_BAUDRATE_134_5 857 +#define USART_BAUDRATE_150 768 +#define USART_BAUDRATE_300 384 +#define USART_BAUDRATE_600 192 +#define USART_BAUDRATE_1200 96 +#define USART_BAUDRATE_1800 64 +#define USART_BAUDRATE_2000 58 +#define USART_BAUDRATE_2400 48 +#define USART_BAUDRATE_3600 32 +#define USART_BAUDRATE_4800 24 +#define USART_BAUDRATE_7200 16 +#define USART_BAUDRATE_9600 12 +#define USART_BAUDRATE_19200 6 +#define USART_BAUDRATE_38400 3 +#define USART_BAUDRATE_56000 3 + +// parity +#define USART_PARITY_NONE 0 +#define USART_PARITY_EVEN 1 +#define USART_PARITY_ODD 2 + +// stop bits +#define USART_STOP_BITS_1 10 +#define USART_STOP_BITS_15 15 +#define USART_STOP_BITS_2 20 + +// word lenght +#define USART_WORD_LENGTH_5 0 +#define USART_WORD_LENGTH_6 1 +#define USART_WORD_LENGTH_7 2 +#define USART_WORD_LENGTH_8 3 + +// autoflow +#define USART_AUTOFLOW_ALL 3 +#define USART_AUTOFLOW_CTS 2 +#define USART_AUTOFLOW_OFF 0 + + +/* this structure is only for internal usage */ +struct _usart_device +{ + register_t buffer; // also used as LSB for divisor latch + + struct IER + { + volatile int received_data_interrupt :1; + volatile int transmitter_empty_interrupt :1; + volatile int receiver_line_status_interrupt :1; + volatile int modem_status_interrupt :1; + volatile int reserved :4; + } IER; + + struct IIR + { + volatile int interrupt_pending :1; + volatile int interrupt_id :3; + volatile int reserved :2; + volatile int fifos :2; + } IIR; + + struct FCR + { + volatile int fifo_enable :1; + volatile int receiver_fifo_rst :1; + volatile int trasmitter_fifo_rst :1; + volatile int dma_mode_select :1; + volatile int reserved :1; + volatile int receiver_trigger :2; + } FCR; + + struct LCR + { + volatile int word_length :2; + volatile int stop_bits :1; + volatile int parity :1; + volatile int even_parity :1; + volatile int stick_parity :1; + volatile int break_control :1; + volatile int divisor_latch_access :1; + } LCR; + + struct MCR + { + volatile int data_terminal_ready :1; + volatile int request_to_send :1; + volatile int out1; + volatile int out2; + volatile int loop; + volatile int autoflow :1; + volatile int reserved :2; + } MCR; + + struct LSR + { + volatile int data_ready :1; + volatile int overrun_error :1; + volatile int parity_error :1; + volatile int framing_error :1; + volatile int break_interrupt :1; + volatile int transmitter_holder_empty :1; + volatile int transmitter_empty :1; + volatile int fifo_recv_error :1; + } LSR; + + struct MSR + { + volatile int delta_cts :1; + volatile int delta_data_set_ready :1; + volatile int trailing_edge_ring_indicator :1; + volatile int delta_data_carrier_detect :1; + volatile int clear_to_send :1; + volatile int data_set_ready :1; + volatile int ring_indicator :1; + volatile int data_carrier_detect :1; + } MSR; + + register_t scratch; +}; + + +// setup functions (wrappers) +void usart_set_baudrate(uint16_t baudrate); +void usart_set_parity(int mode); +void usart_set_stob_bits(int count); +void usart_set_word_length(int length); +void usart_set_autoflow(int mode); + +inline void usart_init(uint16_t baudrate, int parity, int stop_bits); + +void usart_transmit(uint8_t data); +uint8_t usart_receive(); + +int usart_write(uint8_t *data, size_t size); +int usart_read(uint8_t *buffer, size_t count); + +#endif // __USART__H__ diff --git a/sw/z80/kernel/kernel.c b/sw/z80/kernel/kernel.c index 3db6579..3d5aeb6 100644 --- a/sw/z80/kernel/kernel.c +++ b/sw/z80/kernel/kernel.c @@ -1,7 +1,7 @@ #include "types.h" - +#include "usart.h" void kmain(void) { - + usart_init(USART_BAUDRATE_9600, USART_PARITY_EVEN, USART_STOP_BITS_1); } diff --git a/sw/z80/kernel/pio.c b/sw/z80/kernel/pio.c new file mode 100644 index 0000000..e8c7e24 --- /dev/null +++ b/sw/z80/kernel/pio.c @@ -0,0 +1,29 @@ +#include "pio.h" + +static uint8_t *pio_port_a = (uint8_t *) ADDR_DEV_PIO; +static uint8_t *pio_port_b = (uint8_t *) ADDR_DEV_PIO + 1; +static uint8_t *pio_ctrl_a = (uint8_t *) ADDR_DEV_PIO + 2; +static uint8_t *pio_ctrl_b = (uint8_t *) ADDR_DEV_PIO + 3; + +void pio_data(int port, uint8_t data) +{ + if (port == PIO_A) + *pio_port_a = cmd; + else + *pio_port_b = cmd; +} + +void pio_command(int port, uint8_t cmd) +{ + if (port == PIO_A) + *pio_ctrl_a = cmd; + else + *pio_ctrl_b = cmd; +} + + + +inline int pio_read_pin(int port, uint8_t pin) +{ + +} diff --git a/sw/z80/kernel/usart.c b/sw/z80/kernel/usart.c new file mode 100644 index 0000000..4c2fdaf --- /dev/null +++ b/sw/z80/kernel/usart.c @@ -0,0 +1,91 @@ +#include "usart.h" + +static struct _usart_device *_usart = (struct _usart_device *) ADDR_DEV_USART; + +void usart_set_baudrate(uint16_t baudrate) +{ + // enable latch access + _usart->LCR.divisor_latch_access = 1; + _usart->buffer = 0x00FF & baudrate; // LSBs + memcpy(&_usart->IER, &(baudrate >>8), 1); + // _usart->IER = 0x00FF & (baudrate >> 8); // MSBs + _usart->LCR.divisor_latch_access = 0; +} + +void usart_set_parity(int mode) +{ + if (mode == USART_PARITY_EVEN) { + _usart->LCR.even_parity = 1; + } + else if (mode == USART_PARITY_ODD) { + _usart->LCR.even_parity = 0; + } + + _usart->LCR.parity = (mode == USART_PARITY_NONE) ? 0 : 1; +} + +void usart_set_stop_bits(int count) +{ + _usart->LCR.stop_bits = (count == USART_STOP_BITS_1) ? 0 : 1; +} + +void usart_word_length(int length) +{ + _usart->LCR.word_length = length; +} + +void usart_set_autoflow(int mode) +{ + _usart->MCR.autoflow = (mode == USART_AUTOFLOW_OFF) ? 0 : 1; + _usart->MCR.data_terminal_ready = (mode == USART_AUTOFLOW_ALL); +} + +inline void usart_init(uint16_t baudrate, int parity, int stop_bits) +{ + usart_set_baudrate(baudrate); + usart_set_parity(parity); + usart_set_stop_bits(stop_bits); + usart_set_autoflow(USART_AUTOFLOW_OFF); +} + +void usart_transmit(uint8_t data) +{ + _usart->buffer = data; + while (_usart->LSR.transmitter_holder_empty == 0); // wait +} + +uint8_t usart_receive() +{ + return _usart->buffer; +} + +int usart_write(uint8_t *data, size_t size) +{ + uint8_t *dp = data; + + while (size--) { + _usart->buffer = *(dp++); + } + while (_usart->LSR.transmitter_empty); + + // TODO: do something that actually counts for sent bytes + return size; +} + +int usart_read(uint8_t *buffer, size_t count) +{ + uint8_t *bp = buffer; + size_t read_count = 0; + + while (count--) { + *(bp++) = _usart->buffer; + // check for errors + if (_usart->LSR.framing_error || _usart->LSR.parity_error) { + bp--; // delete last byte (?) + } else { + read_count++; + } + } + + return read_count; +} diff --git a/sw/z80/libc/include/stdio.h b/sw/z80/libc/include/stdio.h new file mode 100644 index 0000000..b31cdfd --- /dev/null +++ b/sw/z80/libc/include/stdio.h @@ -0,0 +1,11 @@ +#ifndef __STDIO_H__ +#define __STDIO_H__ + +#include "types.h" + +extern uint8_t *stdout, stderr; + +void putc(char ch, uint8_t *buffer); +int printf(const char *fmt, ...); + +#endif diff --git a/sw/z80/libc/include/string.h b/sw/z80/libc/include/string.h new file mode 100644 index 0000000..f224c87 --- /dev/null +++ b/sw/z80/libc/include/string.h @@ -0,0 +1,8 @@ +#ifndef __STRING_H__ +#define __STRING_H__ + +#include "types.h" + +void *memcpy(void *dest, const void *src, size_t n); + +#endif diff --git a/sw/z80/libc/stdio.c b/sw/z80/libc/stdio.c new file mode 100644 index 0000000..c2548d6 --- /dev/null +++ b/sw/z80/libc/stdio.c @@ -0,0 +1,12 @@ +#include "stdio.h" + +void putc(char ch, uint8_t *buffer) +{ + *buffer = ch; + *(++buffer) = '\0'; +} + + +int printf(const char *fmt, ...) +{ +} diff --git a/sw/z80/libc/string.c b/sw/z80/libc/string.c new file mode 100644 index 0000000..fd6a7ff --- /dev/null +++ b/sw/z80/libc/string.c @@ -0,0 +1,13 @@ +#include "string.h" + +void *memcpy(void *dest, void *src, size_t n) +{ + char *dp = dest; + char *sp = src; + + while (n--) { + *dp++ = *sp++; + } + + return dest; +} -- cgit v1.2.1