From 1ec8f14f03322e3fe1f56f4abcbc85f5c2934dfc Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Tue, 2 May 2017 16:14:41 +0200 Subject: fix for sdcc makefile fix for the old makefile, because it could't compile more than one source file. new libc directory with mem.c to start implementing the standard C library (or at least the part we need). --- sw/z80/kernel/include/types.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sw/z80/kernel') diff --git a/sw/z80/kernel/include/types.h b/sw/z80/kernel/include/types.h index adde214..c24b311 100644 --- a/sw/z80/kernel/include/types.h +++ b/sw/z80/kernel/include/types.h @@ -6,4 +6,6 @@ #define int16_t int #define uint16_t unsigned int +#define size_t uint16_t + #endif -- cgit v1.2.1 From 8a461a14c3ceaf42f1483abe51cda47ac785bfc9 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Tue, 2 May 2017 22:09:40 +0200 Subject: add serial device struct other changes: - change from main() to kmain() in crt0.s and kernel.c - new file devices.h to define all address locations for devices - new data type - register_t as volatile uint8_t for registers in devices - size_t from libc --- sw/z80/kernel/include/devices.h | 13 +++++++ sw/z80/kernel/include/serial.h | 85 +++++++++++++++++++++++++++++++++++++++++ sw/z80/kernel/include/types.h | 2 + sw/z80/kernel/kernel.c | 7 +--- 4 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 sw/z80/kernel/include/devices.h create mode 100644 sw/z80/kernel/include/serial.h (limited to 'sw/z80/kernel') diff --git a/sw/z80/kernel/include/devices.h b/sw/z80/kernel/include/devices.h new file mode 100644 index 0000000..ea29065 --- /dev/null +++ b/sw/z80/kernel/include/devices.h @@ -0,0 +1,13 @@ +#ifndef __DEVICES_H__ +#define __DEVICES_H__ + +#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_RAM 0x8000 + +#endif diff --git a/sw/z80/kernel/include/serial.h b/sw/z80/kernel/include/serial.h new file mode 100644 index 0000000..03e2448 --- /dev/null +++ b/sw/z80/kernel/include/serial.h @@ -0,0 +1,85 @@ +#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/types.h b/sw/z80/kernel/include/types.h index c24b311..552b7e9 100644 --- a/sw/z80/kernel/include/types.h +++ b/sw/z80/kernel/include/types.h @@ -1,6 +1,8 @@ #ifndef __TYPES_H__ #define __TYPES_H__ +#define register_t volatile unsigned char + #define int8_t char #define uint8_t unsigned char #define int16_t int diff --git a/sw/z80/kernel/kernel.c b/sw/z80/kernel/kernel.c index fe87c3d..3db6579 100644 --- a/sw/z80/kernel/kernel.c +++ b/sw/z80/kernel/kernel.c @@ -1,10 +1,7 @@ #include "types.h" -void main(void) +void kmain(void) { - int i, j = 20; - for (i = 0; i < 10; i++) { - j--; - } + } -- cgit v1.2.1 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 ++++++++++++++++++++++++ 7 files changed, 292 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 (limited to 'sw/z80/kernel') 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; +} -- cgit v1.2.1 From b96b0d6c00ea72895582ec14f9c7dccd3fe7062a Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Sat, 10 Jun 2017 17:47:36 +0200 Subject: add port interface header, api still to implement fix for bug in usart.c, in function usart_write() that checked the trasmission_empty register at the wrong time causing it to overwrite the buffer. --- sw/z80/kernel/include/pio.h | 27 ++++++++++++++++++++++----- sw/z80/kernel/pio.c | 25 +++++++------------------ sw/z80/kernel/usart.c | 4 ++-- 3 files changed, 31 insertions(+), 25 deletions(-) (limited to 'sw/z80/kernel') diff --git a/sw/z80/kernel/include/pio.h b/sw/z80/kernel/include/pio.h index 8d72ab0..5d289ca 100644 --- a/sw/z80/kernel/include/pio.h +++ b/sw/z80/kernel/include/pio.h @@ -1,14 +1,31 @@ #ifndef __PIO_H__ #define __PIO_H__ -#define PIO_A 0 -#define PIO_B 1 +#include "devices.h" +#include "types.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); +#define PIO_MODE_0 0 +#define PIO_MODE_1 1 +#define PIO_MODE_2 2 +#define PIO_MODE_3 3 -uint8_t pio_read_data(int port); +#define PIO_INT_ACTIVE_HIGH (1<<5) +#define PIO_INT_AND_MODE (1<<6) +#define PIO_INT_ENABLE (1<<7) + + +void _pio_data(int port, uint8_t data); +void _pio_command(int port, uint8_t cmd); + +void pio_set_mode(int port, int mode); +void pio_set_interrupts(int port, int control); +void pio_set_interrupts_mask(int port, uint8_t mask); +void pio_set_io(int port, uint8_t io); + +// 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); diff --git a/sw/z80/kernel/pio.c b/sw/z80/kernel/pio.c index e8c7e24..4b9caee 100644 --- a/sw/z80/kernel/pio.c +++ b/sw/z80/kernel/pio.c @@ -1,29 +1,18 @@ #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; +static uint8_t *pio_port = (uint8_t *) ADDR_DEV_PIO; +static uint8_t *pio_ctrl = (uint8_t *) (ADDR_DEV_PIO + 2); -void pio_data(int port, uint8_t data) +void _pio_data(int port, uint8_t data) { - if (port == PIO_A) - *pio_port_a = cmd; - else - *pio_port_b = cmd; + *(pio_port + port) = data; } -void pio_command(int port, uint8_t cmd) +void _pio_command(int port, uint8_t cmd) { - if (port == PIO_A) - *pio_ctrl_a = cmd; - else - *pio_ctrl_b = cmd; + *(pio_ctrl + port) = cmd; } - - -inline int pio_read_pin(int port, uint8_t pin) +void pio_set_mode(int port, int mode) { - } diff --git a/sw/z80/kernel/usart.c b/sw/z80/kernel/usart.c index 4c2fdaf..9ec6dbd 100644 --- a/sw/z80/kernel/usart.c +++ b/sw/z80/kernel/usart.c @@ -65,8 +65,8 @@ int usart_write(uint8_t *data, size_t size) while (size--) { _usart->buffer = *(dp++); + while (_usart->LSR.transmitter_empty); } - while (_usart->LSR.transmitter_empty); // TODO: do something that actually counts for sent bytes return size; @@ -83,7 +83,7 @@ int usart_read(uint8_t *buffer, size_t count) if (_usart->LSR.framing_error || _usart->LSR.parity_error) { bp--; // delete last byte (?) } else { - read_count++; + read_count++; } } -- cgit v1.2.1 From 436e259b4c3d687bab51cc8ca35fe61103b430a2 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 16 Jun 2017 13:51:06 +0200 Subject: fixed typo in usart.h and in doc --- sw/z80/kernel/include/usart.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sw/z80/kernel') diff --git a/sw/z80/kernel/include/usart.h b/sw/z80/kernel/include/usart.h index f1f428e..3e5c070 100644 --- a/sw/z80/kernel/include/usart.h +++ b/sw/z80/kernel/include/usart.h @@ -134,7 +134,7 @@ struct _usart_device // 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_stop_bits(int count); void usart_set_word_length(int length); void usart_set_autoflow(int mode); -- cgit v1.2.1