diff options
Diffstat (limited to 'sw/z80')
-rw-r--r-- | sw/z80/coding_rules.txt | 120 | ||||
-rw-r--r-- | sw/z80/crt0.s | 4 | ||||
-rw-r--r-- | sw/z80/kernel/include/devices.h | 13 | ||||
-rw-r--r-- | sw/z80/kernel/include/pio.h | 35 | ||||
-rw-r--r-- | sw/z80/kernel/include/types.h | 2 | ||||
-rw-r--r-- | sw/z80/kernel/include/usart.h | 149 | ||||
-rw-r--r-- | sw/z80/kernel/kernel.c | 9 | ||||
-rw-r--r-- | sw/z80/kernel/pio.c | 18 | ||||
-rw-r--r-- | sw/z80/kernel/usart.c | 91 | ||||
-rw-r--r-- | sw/z80/libc/include/stdio.h | 11 | ||||
-rw-r--r-- | sw/z80/libc/include/string.h | 8 | ||||
-rw-r--r-- | sw/z80/libc/stdio.c | 12 | ||||
-rw-r--r-- | sw/z80/libc/string.c | 13 |
13 files changed, 477 insertions, 8 deletions
diff --git a/sw/z80/coding_rules.txt b/sw/z80/coding_rules.txt new file mode 100644 index 0000000..e5c11f0 --- /dev/null +++ b/sw/z80/coding_rules.txt @@ -0,0 +1,120 @@ +CODING STYLE FOR THIS PROJECT +============================= + +In order to have a consistent codebase, there are the following rules on +writing code in C (and assembly). For the most part they are similar to the +Linux kernel coding rules by Torvalds. + +PROGRAM LOGIC +------------- +I expect a certain level of common sense from people so I won't mention the +super-basic stuff. But I would like to point out a few thing I WON'T accept +(unless there is a valid reason and an explanation of why). First, I believe +that code has to be aesthetically pleasing to watch and with a clear logic +flow so: + + - Avoid deeply nested code and recursive black magic + + - No special cases: generally the code of a function should behave the + same with any argument. Avoid horrible exceptions for magic values + + - No extreme modularization: do not write code that is extremely + encapsulated with dozens of helper functions to control every signal + that runs through the damn motherboard + +EDITOR (SPACES > TABS) +---------------------- +You can use your favourite editor but spaces are better than tabs, no +discussion. For this project every source file must have an indent of 4 +spaces. Since 80 characters is the standard terminal width, the code has to be +hard wrapped at 80, 78 or 72 characters. Also there shouldn't be any markup on +the source code for your editor, not even in the comments; just the code. + + - use spaces, 1 indent - 4 spaces + - hard wrap at 80 / 78 / 72 characters + - no markup for folds or any other editor specific feature + + +C CODE INDENT AND BRACES +------------------------ +I personally prefer the K&R coding style because it was used in 'The C +Programming Language' book from Dennis Ritchie which is the 'standard' for +learning C. But I also like Linus' kernel coding rules, so sometimes I might +use some of his rules. Anyway, you can look them up if you want to or just +look at the following example that sums most of the important stuff. + + - K&R braces and function prototypes + - snake_case for variables and function names + - pointer asterisk in front of the variable ( ex: int *p; ) + +Here's a short example that uses most of the stuff: + + #include <stdio.h> + #include <stdlib.h> + + #define MY_DEVICE_MEMORY_ADDR 0x5020 + + #define MY_DEVICE_FLAG_RDY 1 + #define MY_DEVICE_FLAG_ERR 2 + + // same for unions + struct my_device + { + volatile uint8_t buffer; + volatile uint8_t flags; + } *_my_dev = (struct my_device *) MY_DEVICE_MEMORY_ADDR; + + + int my_device_write(uint8_t *data, size_t size); + + /* This is the main function + * and this is a multiline comment to explain something if needed + */ + int main(int argc, char *argv[]) + { + int i; + int j = 0; + uint8_t data[2] = { 0xFF, 0xAB }; + const char *string = "My magic string"; + + while (j < 100) { + j++; + } + + printf("%s\n", string); + + if (some_condition) { + // inline comment + } else { + my_device_write(data, 2); + } + + switch (i) { + case 0: + some_function(); + break; + + case 1: + // ... + break; + + default: + // ... + } + } + + int my_device_write(uint8_t *data, size_t size) + { + int i; + + for (i = 0; i < size; i++) { + _my_dev.buffer = data; + while (!(_my_dev.flags & (1<<MY_DEVICE_FLAG_RDY))); + + if (_my_dev.flags & (1<<MY_DEVICE_FLAG_ERR)) { + return -1; + } + } + + return i; + } diff --git a/sw/z80/crt0.s b/sw/z80/crt0.s index 7701ca6..00c7da1 100644 --- a/sw/z80/crt0.s +++ b/sw/z80/crt0.s @@ -27,7 +27,7 @@ ;-------------------------------------------------------------------------- .module crt0 - .globl _main + .globl _kmain .area _HEADER (ABS) ;; Reset vector @@ -56,7 +56,7 @@ init: ;; Initialise global variables call gsinit - call _main + call _kmain jp _exit ;; Ordering of segments for the linker. diff --git a/sw/z80/kernel/include/devices.h b/sw/z80/kernel/include/devices.h new file mode 100644 index 0000000..e8c183f --- /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 0x4100 +#define ADDR_DEV_PIO 0x4200 + +#define ADDR_DEV_RAM 0x8000 + +#endif diff --git a/sw/z80/kernel/include/pio.h b/sw/z80/kernel/include/pio.h new file mode 100644 index 0000000..5d289ca --- /dev/null +++ b/sw/z80/kernel/include/pio.h @@ -0,0 +1,35 @@ +#ifndef __PIO_H__ +#define __PIO_H__ + +#include "devices.h" +#include "types.h" + +#define PIO_A 0 +#define PIO_B 1 + +#define PIO_MODE_0 0 +#define PIO_MODE_1 1 +#define PIO_MODE_2 2 +#define PIO_MODE_3 3 + +#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); + +// TODO: implement mode (in/out/both) and interrupt vector + +#endif // __PIO_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/include/usart.h b/sw/z80/kernel/include/usart.h new file mode 100644 index 0000000..3e5c070 --- /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_stop_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 fe87c3d..3d5aeb6 100644 --- a/sw/z80/kernel/kernel.c +++ b/sw/z80/kernel/kernel.c @@ -1,10 +1,7 @@ #include "types.h" +#include "usart.h" - -void main(void) +void kmain(void) { - int i, j = 20; - for (i = 0; i < 10; i++) { - j--; - } + 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..4b9caee --- /dev/null +++ b/sw/z80/kernel/pio.c @@ -0,0 +1,18 @@ +#include "pio.h" + +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) +{ + *(pio_port + port) = data; +} + +void _pio_command(int port, uint8_t cmd) +{ + *(pio_ctrl + port) = cmd; +} + +void pio_set_mode(int port, int mode) +{ +} diff --git a/sw/z80/kernel/usart.c b/sw/z80/kernel/usart.c new file mode 100644 index 0000000..9ec6dbd --- /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; +} |