From c57a8a9bf49fa7a3231ce8d6e435603e8ab016eb Mon Sep 17 00:00:00 2001 From: Dominic Radermacher Date: Wed, 19 Jul 2017 14:08:49 +0200 Subject: initial import --- .gitignore | 5 + Makefile | 47 +++++++ fw_src/eepr_read.s | 32 +++++ fw_src/eepr_write.s | 100 ++++++++++++++ fw_src/obsolete.c | 29 ++++ fw_src/talker.s | 100 ++++++++++++++ fw_src/test.s | 13 ++ include/hc11tools.h | 36 +++++ include/s19stuff.h | 12 ++ include/serial.h | 8 ++ include/talker.h | 19 +++ include/tty.h | 73 ++++++++++ include/ui.h | 6 + src/hc11debug.c | 379 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/hc11eepr.c | 222 ++++++++++++++++++++++++++++++ src/hc11loader.c | 120 +++++++++++++++++ src/s19stuff.c | 148 ++++++++++++++++++++ src/serial.c | 153 +++++++++++++++++++++ src/talker.c | 182 +++++++++++++++++++++++++ src/tty.c | 232 ++++++++++++++++++++++++++++++++ src/ui.c | 179 +++++++++++++++++++++++++ 21 files changed, 2095 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 fw_src/eepr_read.s create mode 100644 fw_src/eepr_write.s create mode 100644 fw_src/obsolete.c create mode 100644 fw_src/talker.s create mode 100644 fw_src/test.s create mode 100644 include/hc11tools.h create mode 100644 include/s19stuff.h create mode 100644 include/serial.h create mode 100644 include/talker.h create mode 100644 include/tty.h create mode 100644 include/ui.h create mode 100644 src/hc11debug.c create mode 100644 src/hc11eepr.c create mode 100644 src/hc11loader.c create mode 100644 src/s19stuff.c create mode 100644 src/serial.c create mode 100644 src/talker.c create mode 100644 src/tty.c create mode 100644 src/ui.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2a25522 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# C-Objects +*.o + +# S19 binaries +/*.s19 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3129477 --- /dev/null +++ b/Makefile @@ -0,0 +1,47 @@ +# New Makefile 2006-01-23 +# $@ = output file, $< = first input, $+ = all input files + +ECHO = /bin/echo -e +RM = /bin/rm -f +CC = gcc +STRIP = strip +CFLAGS = -g -Os -I./include -Wall -Wstrict-prototypes -Wmissing-prototypes +CFLAGS += -Wshadow -Wextra -Wunused # -Wconversion + +PROGS = hc11loader hc11debug hc11eepr + +all: $(PROGS) + +clean: + $(RM) src/*.o +tidy: + $(RM) src/*.o $(PROGS) +install: $(PROGS) + @$(ECHO) "\t==> Installing nothing" +pack: + @$(ECHO) "Cleaning up ..." ; \ + $(RM) src/*.o lib/* $(PROGS) + @$(ECHO) "Creating package ..." ; \ + VERSION=`cat include/hc11tools.h |grep VERSION |cut -d"\"" -f2`;\ + tar Jcvf hc11tools-$$VERSION.txz --directory=.. --exclude=fw_src --exclude=*.s19 hc11tools + +# Generic instructions. Don't change. +src/%.o: src/%.c + @printf "\t--> Compiling `basename $<`\n" + @$(CC) $(CFLAGS) -c $< -o $@ + +# Specific programs +hc11loader: src/hc11loader.o src/serial.o src/s19stuff.o + @printf "\t==> Linking objects to output file $@\n" + @$(CC) $(CFLAGS) $(LDFLAGS) $+ -o $@ + @$(STRIP) $@ + +hc11eepr: src/hc11eepr.o src/serial.o src/s19stuff.o + @printf "\t==> Linking objects to output file $@\n" + @$(CC) $(CFLAGS) $(LDFLAGS) $+ -o $@ + @$(STRIP) $@ + +hc11debug: src/hc11debug.o src/serial.o src/s19stuff.o src/talker.o src/tty.o src/ui.o + @printf "\t==> Linking objects to output file $@\n" + @$(CC) $(CFLAGS) $(LDFLAGS) $+ -o $@ + @$(STRIP) $@ diff --git a/fw_src/eepr_read.s b/fw_src/eepr_read.s new file mode 100644 index 0000000..818208f --- /dev/null +++ b/fw_src/eepr_read.s @@ -0,0 +1,32 @@ + +RAM equ $0000 +EEPROM equ $b600 + +REGBASE equ $1000 +BAUD equ $2b ; SCI Baud Rate Control +SCCR2 equ $2d ; SCI Control Register 2 +SCSR equ $2e ; SCI Status Register +SCDR equ $2f ; SCI Data Register + + org RAM +init: + lds #$00ff ; init stack pointer + ldd #$300c ; A=SCP1|SCP0, B=TE|RE + staa REGBASE+BAUD ; 9600 bps + stab REGBASE+SCCR2 +main: + ldx #EEPROM +loop1: + ldaa 0,X ; read byte + jsr sci_txd ; acknowledge byte + inx + cpx #EEPROM+512 + bne loop1 +end: + wai + bra end +sci_txd: + tst REGBASE+SCSR + bpl sci_txd ; wait until TDRE bit set + staa REGBASE+SCDR + rts diff --git a/fw_src/eepr_write.s b/fw_src/eepr_write.s new file mode 100644 index 0000000..f2c0509 --- /dev/null +++ b/fw_src/eepr_write.s @@ -0,0 +1,100 @@ + +RAM equ $0000 +EEPROM equ $b600 +EEPSIZE equ 256 + +REGBASE equ $1000 +BAUD equ $2b ; SCI Baud Rate Control +SCCR2 equ $2d ; SCI Control Register 2 +SCSR equ $2e ; SCI Status Register +SCDR equ $2f ; SCI Data Register +BPROT equ $35 ; EEPROM block protect +PPROG equ $3b + + org RAM +init: + lds #$00ff ; init stack pointer + ldd #$330c ; A=SCP1|SCP0, B=TE|RE + staa REGBASE+BAUD ; 1200 bps + stab REGBASE+SCCR2 +main: + clr REGBASE+BPROT + ldx #EEPROM +loop1: + bsr sci_rxd ; receive byte + jsr eepr_write ; write accu A to address X + bsr sci_txd ; acknowledge byte + inx + cpx #EEPROM+EEPSIZE + beq done +; ldy #$ffff +loop2: +; dey +; beq done ; timeout -> end of code +; jsr sci_rx_tst ; byte received? +; beq loop2 + bra loop1 +done: + ldaa #$1f + staa REGBASE+BPROT + jmp EEPROM ; execute the program +sci_rx_tst: + ldaa REGBASE+SCSR + anda #$20 ; receive buf full? + rts ; return 0 if not +sci_rxd: + ldaa REGBASE+SCSR + bita #%00001010 ; OV or FE bits set ? + bne init + anda #%00100000 ; RDRF bit set ? + beq sci_rxd + ldaa REGBASE+SCDR + rts +sci_txd: + tst REGBASE+SCSR + bpl sci_txd ; wait until TDRE bit set + staa REGBASE+SCDR + rts + +eepr_write: + tab + comb + orab 0,X + bne _eepr_erase_ok + ldaa #0e + rts + ldab #%00010110 ; BYTE=1, ERASE=1, EELAT=1 +; stab PPROG + stab 0,X + ldab #%00010111 ; BYTE=1, ERASE=1, EELAT=1, EEPGM=1 +; stab PPROG + bsr delay10ms +; clr PPROG +_eepr_erase_ok: + cmpa 0,X + beq _eepr_write_ok +_xx0: + ldaa #$01 + rts + + ldab #%00000010 ; EELAT=1 + stab REGBASE+PPROG + staa 0,X + ldab #%00000011 ; EELAT=1, EEPGM=1 + stab REGBASE+PPROG + bsr delay10ms + clr REGBASE+PPROG + ldaa 0,X ; read back for verifying + rts +_eepr_write_ok: + ldaa #0 ; read back for verifying + rts + +delay10ms: ; 20000 cycles to eat at Eclk=2MHz + pshx + ldx #3330 ; 3330*6 = 19980 cycles +_delay_10ms_l0: + dex + bne _delay_10ms_l0 + pulx + rts diff --git a/fw_src/obsolete.c b/fw_src/obsolete.c new file mode 100644 index 0000000..640f514 --- /dev/null +++ b/fw_src/obsolete.c @@ -0,0 +1,29 @@ +void dump_obj(struct obj *bo) +{ + int i; + + for(i=0; i<(bo->end_addr-bo->start_addr); i++) { + printf("%02x ", bo->code[i]); + if((i+1)%16 == 0) printf("\n"); + } + printf("\n"); + return; +} + +byte TalkPgm[256] = { +0x8e,0x01,0xff,0xce,0x10,0x00,0x6f,0x2c,0xcc,0x30,0x0c,0xa7,0x2b,0xe7,0x2d,0x86, +0x10,0x06,0x7e,0x00,0x12,0xb6,0x10,0x2e,0x84,0x20,0x27,0xf9,0xb6,0x10,0x2f,0x43, +0x8d,0x46,0x2a,0x51,0x8d,0x33,0x8f,0x8d,0x30,0x17,0x8d,0x2d,0x8f,0x81,0xfe,0x26, +0x0d,0xa6,0x00,0x8d,0x33,0x17,0x8d,0x21,0x16,0x08,0x5a,0x26,0xf4,0x3b,0x81,0xbe, +0x26,0x16,0x17,0x8d,0x14,0xe7,0x00,0x18,0xce,0x00,0x01,0x18,0x09,0x26,0xfc,0xe6, +0x00,0xf7,0x10,0x2f,0x08,0x4a,0x26,0xeb,0x3b,0xf6,0x10,0x2e,0xc5,0x0a,0x26,0xa0, +0xc4,0x20,0x27,0xf5,0xf6,0x10,0x2f,0x39,0x18,0x8f,0xb6,0x10,0x2e,0x2a,0xfb,0x18, +0x8f,0xb7,0x10,0x2f,0x39,0x81,0x7e,0x26,0x0c,0x30,0x8f,0x8d,0xeb,0x17,0x8d,0xe8, +0x30,0xc6,0x09,0x20,0xac,0x81,0x3e,0x26,0x12,0x8d,0xce,0x17,0x8d,0xcb,0x8f,0x35, +0x86,0x09,0x20,0xaf,0x86,0x4a,0x8d,0xd0,0x0f,0x20,0xfd,0x81,0x4a,0x26,0xb9,0x30, +0xc6,0x09,0x3a,0x35,0xec,0x07,0x8d,0xc0,0x17,0x8d,0xbd,0xcc,0x00,0x98,0xed,0x07, +0x20,0xc7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x7e,0x00,0x15,0x7e,0x00,0x58,0x7e,0x00,0x58,0x7e,0x00,0x58, +0x7e,0x00,0x58,0x7e,0x00,0x58,0x7e,0x00,0x58,0x7e,0x00,0x58,0x7e,0x00,0x58,0x7e, +0x00,0x58,0x7e,0x00,0x58,0x7e,0x00,0x58,0x7e,0x00,0x58,0x7e,0x00,0x58,0x7e,0x00, +0x58,0x7e,0x00,0x58,0x7e,0x00,0x58,0x7e,0x00,0x00,0x7e,0x00,0x58,0x7e,0x00,0x58}; diff --git a/fw_src/talker.s b/fw_src/talker.s new file mode 100644 index 0000000..0b9b612 --- /dev/null +++ b/fw_src/talker.s @@ -0,0 +1,100 @@ + +****************************************************************************** +****************************************************************************** + +BAUD equ $102b ; SCI Baud Rate Control +SCCR2 equ $102d ; SCI Control Register 2 +SCSR equ $102e ; SCI Status Register +SCDR equ $102f ; SCI Data Register + + org $0000 ; program start +init: + lds #$01ff ; init stack pointer + ldd #$330c ; A=SCP1|SCP0, B=TE|RE + staa BAUD ; => XX00 bps + stab SCCR2 + ldaa #%10010000 + tap +idleloop: + bra idleloop +sci_srv: + bsr sci_rxd + coma + bsr sci_txd + bpl hi_command + psha + bsr sci_rxd + tab + pula + xgdx + bsr sci_rxd + tab + bsr sci_rxd + xgdx + cmpa #$be + bne read_mcu_mem +write_mcu_mem: + bsr sci_rxd + staa 0,X + inx + decb + bne write_mcu_mem + rti +hi_command: + cmpa #$3e + beq write_mcu_regs +read_mcu_regs: + tsx ; SP -> X + xgdx ; X <-> D + bsr sci_txd + tba + bsr sci_txd + tsx + ldab #9 + bra read_mcu_mem +write_mcu_regs: + bsr sci_rxd + tab + bsr sci_rxd + xgdx +; txs + ldab #9 + bra write_mcu_mem +sci_rxd: + ldaa SCSR + bita #%00001010 ; OV or FE bits set ? + bne init + anda #%00100000 ; RDRF bit set ? + beq sci_rxd + ldaa SCDR + rts +sci_txd: + tst SCSR + bpl sci_txd ; wait until TDRE bit set + staa SCDR + rts +swi_srv: + ldaa #$4a + bsr sci_txd + tsx + ldd 7,X + bsr sci_txd + tba + bsr sci_txd + ldd #idleloop + std 7,X + ldab #7 +read_mcu_mem: + ldaa 0,X + bsr sci_txd + inx + decb + bne read_mcu_mem + rti + + org $00f1 + jmp sci_srv ; /XIRQ ** NEEDED ** + jmp swi_srv ; SWI ** NEEDED ** + jmp init ; Illegal opcode ** NEEDED ** + jmp init ; COP-Fail + jmp init ; Clock Monitor Fail diff --git a/fw_src/test.s b/fw_src/test.s new file mode 100644 index 0000000..524aebc --- /dev/null +++ b/fw_src/test.s @@ -0,0 +1,13 @@ + org $0100 +blink: + ldx #REGBASE + bclr PORTA,X #%00010000 ; clear bit 5 of port A -> LED off +loop_1: + inx + bne loop_1 + ldx #REGBASE + bset PORTA,X #%00010000 ; set bit 5 of port A -> LED on +loop_2: + dex + bne loop_2 + bra blink diff --git a/include/hc11tools.h b/include/hc11tools.h new file mode 100644 index 0000000..34b05c0 --- /dev/null +++ b/include/hc11tools.h @@ -0,0 +1,36 @@ + +#include + +#ifndef _HC11TOOLS_H + #define _HC11TOOLS_H + + #define VERSION "0.9" + +// #define MAX_CODE_SIZE 1024 /* 68HC11F1 has 1 KByte RAM */ + #define MAX_CODE_SIZE 65536 + + /* ----------------------------------------------------------------- + Type defs + ----------------------------------------------------------------- */ + + typedef enum BOOL {false, true} boolean; + + struct mcu { + uint16_t devid; + uint16_t maskid; + }; + struct mcu_regs { + uint8_t a; + uint8_t b; + uint16_t ix; + uint16_t iy; + uint16_t sp; + uint16_t pc; + uint8_t ccr; + }; + struct obj { + uint8_t code[MAX_CODE_SIZE]; + int start_addr; + int end_addr; + }; +#endif diff --git a/include/s19stuff.h b/include/s19stuff.h new file mode 100644 index 0000000..ac7df0b --- /dev/null +++ b/include/s19stuff.h @@ -0,0 +1,12 @@ + +#include "hc11tools.h" + +uint8_t hex2chr(char *s); + +void s19_chksum_init(void); +void s19_chksum_add(uint8_t val); +uint8_t s19_chksum_get(void); + +int f_readline(FILE *f, char *buf, int size); +int parse_s19_line(struct obj *bo, char *buf); +int load_s19file(struct obj *bo, char *file); diff --git a/include/serial.h b/include/serial.h new file mode 100644 index 0000000..1bd8815 --- /dev/null +++ b/include/serial.h @@ -0,0 +1,8 @@ + +#include "hc11tools.h" + +int serial_open(char *device, int speed, int c_flags); +int serial_setspeed(int fd, int speed); +int serial_waitrxdata(int fd); +int serial_rx_empty(int fd); +int upload_firmware(int fd, struct obj *bo); diff --git a/include/talker.h b/include/talker.h new file mode 100644 index 0000000..e84f666 --- /dev/null +++ b/include/talker.h @@ -0,0 +1,19 @@ + +#include +#include /* read(), write() */ + +#include "hc11tools.h" +#include "serial.h" + +int read_byte(int fd, uint8_t *d); +int read_word(int fd, uint16_t *d); + +int send_command(int fd, uint8_t cmd); + +int read_mcu_mem(int fd, uint16_t addr, uint8_t *mem, int len); +int write_mcu_mem(int fd, uint16_t addr, uint8_t *mem, int len); + +int read_mcu_regs(int fd, struct mcu_regs *regs); +int write_mcu_regs(int fd, struct mcu_regs *regs); + +int swi_handler(int fd, struct mcu_regs *regs); diff --git a/include/tty.h b/include/tty.h new file mode 100644 index 0000000..6ac924f --- /dev/null +++ b/include/tty.h @@ -0,0 +1,73 @@ + +/* -------------------------------------------------------------------- + -------------------------------------------------------------------- */ + +struct Screen { + int width; + int height; +} my_scr; + +/* keycodes possibly returned by tty_getkey() */ +#define KEY_ENTER 0x000a +#define KEY_ESC 0x001b +#define KEY_BS 0x007f +#define KEY_DEL 0x0233 +#define KEY_INS 0x0232 +#define KEY_HOME 0x0231 +#define KEY_END 0x0234 +#define KEY_PG_UP 0x0235 +#define KEY_PG_DOWN 0x0236 +#define KEY_C_UP 0x0241 +#define KEY_C_DOWN 0x0242 +#define KEY_C_RIGHT 0x0243 +#define KEY_C_LEFT 0x0244 +#define KEY_BREAK 0x0250 +#define KEY_F1 0x0201 +#define KEY_F2 0x0202 +#define KEY_F3 0x0203 +#define KEY_F4 0x0204 +#define KEY_F5 0x0205 +#define KEY_F6 0x0206 +#define KEY_F7 0x0207 +#define KEY_F8 0x0208 +#define KEY_F9 0x0209 +#define KEY_F10 0x0210 +#define KEY_F11 0x0211 +#define KEY_F12 0x0212 +#define KEY_F13 0x0213 +#define KEY_UNKNOWN 0xff00 +#define KEY_TIMEOUT 0xffff + +/* modes for tty_setmode() */ +#define MODE_NORMAL 0 +#define MODE_BOLD 1 +#define MODE_UNDERLINE 4 +#define MODE_BLINK 5 +#define MODE_REVERSE 7 + +/* colors for use with tty_setcolor() */ +#define COLOR_BLACK 0 +#define COLOR_RED 1 +#define COLOR_GREEN 2 +#define COLOR_YELLOW (COLOR_RED+COLOR_GREEN) +#define COLOR_BLUE 4 +#define COLOR_VIOLETT (COLOR_RED+COLOR_BLUE) +#define COLOR_CYAN (COLOR_GREEN+COLOR_BLUE) +#define COLOR_WHITE (COLOR_RED+COLOR_GREEN+COLOR_BLUE) + +int tty_init(void); +int tty_width(void); +int tty_height(void); +int tty_setechomode(int mode); +int tty_getkey(void); +void tty_cls(void); +void tty_clreol(void); +void tty_savecursorpos(void); +void tty_restorecursorpos(void); +void tty_gotoxy(int x, int y); +int tty_setscrollregion(int from, int to); +void tty_setmode(int mode); +void tty_setcolor(int bg, int fg); +void tty_reset(void); + +int _tty_getkeycode(int t); diff --git a/include/ui.h b/include/ui.h new file mode 100644 index 0000000..55c53c2 --- /dev/null +++ b/include/ui.h @@ -0,0 +1,6 @@ + +char *ccr_to_string(uint8_t ccr); +char *ui_enter_cmd(char *str); +void ui_show_mcu_regs(struct mcu_regs *regs); +void ui_show_mem(uint16_t addr, uint8_t *mem, int len); +void ui_show_mcu_type(struct mcu *mymcu); diff --git a/src/hc11debug.c b/src/hc11debug.c new file mode 100644 index 0000000..ddb886e --- /dev/null +++ b/src/hc11debug.c @@ -0,0 +1,379 @@ + +/* -------------------------------------------------------------------- + hc11debug - Debugger for the Motorola 68HC11 + Copyright (C) 2004 Dominic Radermacher + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + -------------------------------------------------------------------- */ + +#include +#include +#include /* exit() */ +#include /* strcmp() */ +#include /* isdigit() */ +#include /* read(), write(), sleep(), tcgetattr() */ +#include /* tcgetattr() */ +#include /* open() */ +#include /* open() */ +#include /* open() */ + +#include "hc11tools.h" +#include "s19stuff.h" +#include "serial.h" +#include "talker.h" +#include "tty.h" +#include "ui.h" + +#define DEFAULT_SERDEV "/dev/ttyUSB0" + +/* -------------------------------------------------------------------- + Function prototypes + -------------------------------------------------------------------- */ + +int f_readline(FILE *f, char *buf, int size); +void usage(char *progname); +int is_chardev(char *file); +int parse_args(int argc, char **argv); +int load_talker(struct obj *bo); + +int parse_cmd(int fd, char *cmd); + +boolean any(char *str, char c); +int arg_val(char *arg); + +/* -------------------------------------------------------------------- + Global variables + -------------------------------------------------------------------- */ + +char *device; /* device where the board is connected to */ +boolean skipload, extmem; + +int is_chardev(char *file) +{ + struct stat stbuf; + + if(stat(file, &stbuf) == -1) { + return -1; + } + if((stbuf.st_mode & S_IFMT) != S_IFCHR) { + return -1; + } + return 0; +} + +int parse_args(int argc, char **argv) +{ + int i; + char *p; + + for(i=1; istart_addr=0xffff; + bo->end_addr=0x0000; + for(i=0; i<(int)sizeof(bo->code); bo->code[i++]=0); + printf("Loading talker code...\n"); + for(i=0; xx_talk[i] != 0; ) { + for(k=i; xx_talk[k] != '\n'; k++); + xx_talk[k++]=0; + parse_s19_line(bo, &xx_talk[i]); + i=k; + } + printf("Loading IRQ vectors...\n"); + for(i=0; talk_irqvec[i] != 0; ) { + for(k=i; talk_irqvec[k] != '\n'; k++); + talk_irqvec[k++]=0; + parse_s19_line(bo, &talk_irqvec[i]); + i=k; + } + return 0; +} + +void usage(char *progname) +{ + printf("usage: %s [options] \n", progname); + printf("\toptions:\n"); + printf("\t-d \tserial device to use (default: %s)\n", DEFAULT_SERDEV); + printf("\t--skipload\tskip bootload process (talker already running)\n"); + printf("\t--extmem\tenable external bus\n"); + exit(5); +} + +/* + * any --- does str contain c? + */ +boolean any(char *str, char c) +{ + while(*str != 0) { + if(*str++ == c) { + return true; + } + } + return false; +} + +/* -------------------------------------------------------------------- + evaluate the decimal value of the argument. + input can be binary %01010011, hexadecimal $0f or decimal 45 + values + -------------------------------------------------------------------- */ + +int arg_val(char *arg) +{ + int val=0; + + if(*arg == '%') { /* binary constant */ + arg++; + while(any("01", *arg) == true) { + printf("%s -> %i\n", arg, val); + val = (val * 2) + ((*arg++)-'0'); + } + } else if(*arg == '@') { /* octal constant */ + arg++; + while(any("01234567", *arg) == true) { + val = (val * 8) + ((*arg++)-'0'); + } + } else if(*arg == '$') { /* hex constant */ + arg++; + while(any("0123456789abcdefABCDEF", *arg) == true) { + if(*arg > '9') { + val = (val * 16) + 10 + (tolower(*arg++)-'a'); + } else { + val = (val * 16) + ((*arg++)-'0'); + } + } + } else if(any("0123456789", *arg) == true) { /* decimal constant */ + while(*arg >= '0' && *arg <= '9') { + val = (val * 10) + ((*arg++)-'0'); + } + } else { + printf("error while parsing argument '%s'\n", arg); + return 0; + } + return val; +} + +int parse_cmd(int fd, char *cmd) +{ + char *p; + uint8_t buf[256]; + int addr=0, len=0, val=0; + struct obj code; + struct mcu_regs myregs; + + if(strncmp(cmd, "md ", 3) == 0) { + if((p=strchr(cmd+3, ' ')) != NULL) { /* we've got 2 args */ + *p++=0; + len=arg_val(p); + if(len > 256) { + printf("I would not do that if I where you (hint: md [len])\n"); + return 0; + } + } else { + len=16; + } + addr=arg_val(cmd+3); + printf("memory dump from addr $%04x (len = %i)\n", addr, len); + read_mcu_mem(fd, addr, buf, len); + ui_show_mem(addr, buf, len); + } else if(strncmp(cmd, "ms ", 3) == 0) { + if((p=strchr(cmd+3, ' ')) != NULL) { + *p++=0; + val=arg_val(p); + if(val > 255) { + printf("value must be 0 .. 255\n"); + return 0; + } + } else { + printf("hint: ms \n"); + return 0; + } + addr=arg_val(cmd+3); + printf("setting value at addr $%04x to $%02x\n", addr, val); + buf[0]=val; + write_mcu_mem(fd, addr, buf, 1); + } else if(strncmp(cmd, "go ", 3) == 0) { + addr=arg_val(cmd+3); + printf("Starting program at 0x%04x\n", addr); + read_mcu_regs(fd, &myregs); + myregs.pc=addr; + write_mcu_regs(fd, &myregs); + ui_show_mcu_regs(&myregs); + } else if(strncmp(cmd, "load ", 5) == 0) { + load_s19file(&code, cmd+5); /* load s19 source file */ + addr=code.start_addr; + len=code.end_addr - code.start_addr; + if(len > 255) { + printf("sorry, currently we can load a maximum of 256 bytes\n"); + return -1; + } + printf("Writing %i byte starting from addr $%04x (this may take a while)\n", len, addr); + write_mcu_mem(fd, addr, &code.code[addr], len); + printf("Done\n"); + } + return 0; +} + +int main(int argc, char **argv) +{ + int fd, i, k; + struct obj bootcode; + struct mcu mymcu; + struct mcu_regs myregs; + char *cmd; + uint8_t b; + uint8_t buf[16]; + + if(argc < 2) { + usage(argv[0]); + } + device=DEFAULT_SERDEV; + skipload=false; + extmem=false; /* we do not use external bus per default */ + i=parse_args(argc, argv); + if((fd=serial_open(device, B1200, CS8+CLOCAL)) < 0) { + fprintf(stderr, "error: can not open '%s'\n", device); + return 5; + } + if(skipload == false) { + if(i < argc) { + load_s19file(&bootcode, argv[i]); /* load s19 source file */ + } else { + load_talker(&bootcode); + } + if(bootcode.start_addr != 0) { + fprintf(stderr, "error: program must start at address $0000\n"); + return 1; + } + if(upload_firmware(fd, &bootcode) != 0) { + return 5; /* makes no sense to continue then */ + } + sleep(1); + } +/* if(serial_setspeed(fd, B9600) != 0) { + printf("failed to switch switching baudrate\n"); + exit(5); + } */ + mymcu.devid=0; + mymcu.maskid=0; + /* try to detect mcu type */ + read_mcu_mem(fd, 0x103c, buf, 1); + /* either 0x0c or 0x0d seems bootstrap mode */ + b=(buf[0]>>4); + if((b & 4) == 4) { /* SMOD=1 - special mode */ + if((b & 8) == 8) { + read_mcu_mem(fd, 0xbfd4, buf, 2); + mymcu.devid=(buf[0]<<8)+buf[1]; + read_mcu_mem(fd, 0xbfd2, buf, 2); + mymcu.maskid=(buf[0]<<8)+buf[1]; + } + if((b & 2) == 2) { + printf("=> Special Test mode\n"); + } else { + // printf("=> Special Bootstrap mode\n"); + if(extmem == true) { + // printf("enabling external bus\n"); + buf[0] |= 0x20; + // write_mcu_mem(fd, 0x103c, buf, 1); + } + } + } + tcflush(fd, TCIOFLUSH); + i=0; + tty_init(); + tty_setscrollregion(1, tty_height()-4); + tty_gotoxy(1, 1); + tty_cls(); + while((k=tty_getkey()) != KEY_ESC) { + ui_show_mcu_type(&mymcu); + if(serial_rx_empty(fd) != 0) { /* when NOT empty */ + read_byte(fd, &b); + if(b == 0x4a) { /* SWI */ + swi_handler(fd, &myregs); + } else { + printf("trap code %02x\n", b); + } + } + if(k == 's') { /* 's' */ + printf("Stopping MCU (setting to idle loop)\n"); + read_mcu_regs(fd, &myregs); + myregs.pc=0x000f; + write_mcu_regs(fd, &myregs); + ui_show_mcu_regs(&myregs); + i=0; + } else if(k == 'r') { /* r */ + if(read_mcu_regs(fd, &myregs) == 0) { + ui_show_mcu_regs(&myregs); + } + } else if(k == KEY_ENTER) { + cmd=ui_enter_cmd(NULL); + parse_cmd(fd, cmd); + } else if(k == KEY_TIMEOUT) { + if(read_mcu_regs(fd, &myregs) == 0) { + ui_show_mcu_regs(&myregs); + } + } else { + printf("keycode %04x counter %i\n", k, i); + } + i++; + } + tty_reset(); + close(fd); + return 0; +} diff --git a/src/hc11eepr.c b/src/hc11eepr.c new file mode 100644 index 0000000..411e583 --- /dev/null +++ b/src/hc11eepr.c @@ -0,0 +1,222 @@ + +/* -------------------------------------------------------------------- + hc11eepr - Read and write S19 binaries from/to the EEPROM of the 68HC11 + + Copyright (C) 2004 Dominic Radermacher + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + -------------------------------------------------------------------- */ + +#include +#include /* exit() */ +#include +#include /* strcmp() */ +#include /* isdigit() */ +#include /* read(), write(), sleep(), tcgetattr() */ +#include /* tcgetattr() */ +#include /* open() */ +#include /* open() */ +#include /* open() */ + +#include "hc11tools.h" +#include "s19stuff.h" +#include "serial.h" + +#define DEFAULT_SERDEV "/dev/ttyUSB0" +#define MODE_UNDEF 0 +#define MODE_READ 1 +#define MODE_WRITE 2 + +/* -------------------------------------------------------------------- + Global variables + -------------------------------------------------------------------- */ + +char *device; /* device where the board is connected to */ +char mode; + +char fw_code_read[] = +"S12300008E00FFCC300CB7102BF7102DCEB600A600BD001D088CB80026F53E20FD7D102EA0\n" +"S10900202AFBB7102F3982\n"; + +char fw_code_write[] = +"S11300008E00FFCC330CB7102BF7102D7F1035CE9C\n" +"S1130010B6008D278D3D8D32088CB700270F18CE82\n" +"S1130020FFFF18092707BD003527F720E5861FB70E\n" +"S113003010357EB600B6102E842039B6102E850AEF\n" +"S113004026BE842027F5B6102F397D102E2AFBB743\n" +"S1130050102F39371653EA002608C616E700C617CC\n" +"S11300608D12A100270AC602A700C6038D06A600AA\n" +"S1100070A60033393CCE0D020926FD3839B7\n"; + +/* -------------------------------------------------------------------- + Function prototypes + -------------------------------------------------------------------- */ + +void usage(char *progname); +int is_chardev(char *file); +int parse_args(int argc, char **argv); +int load_talker(struct obj *bo, char *code); + +int is_chardev(char *file) +{ + struct stat stbuf; + + if(stat(file, &stbuf) == -1) { + return -1; + } + if((stbuf.st_mode & S_IFMT) != S_IFCHR) { + return -1; + } + return 0; +} + +int parse_args(int argc, char **argv) +{ + int i; + char *p; + + for(i=1; i \n", progname); + printf("\toptions:\n"); + printf("\t-d \tserial device to use (default: %s)\n", DEFAULT_SERDEV); + exit(5); +} + +int load_talker(struct obj *bo, char *code) +{ + int i, k; + + bo->start_addr=0xffff; + bo->end_addr=0x0000; + for(i=0; i<(int)sizeof(bo->code); bo->code[i++]=0); + for(i=0; code[i] != 0; ) { + for(k=i; code[k] != '\n'; k++); + code[k++]=0; + parse_s19_line(bo, &code[i]); + i=k; + } + return 0; +} + +int main(int argc, char **argv) +{ + int d, i; + struct obj bootcode, eeprdata; + uint8_t b; + + if(argc < 2) { + usage(argv[0]); + } + mode=MODE_UNDEF; + device=DEFAULT_SERDEV; + i=parse_args(argc, argv); + if(mode == MODE_READ) { + load_talker(&bootcode, fw_code_read); + } else if(mode == MODE_WRITE) { + load_s19file(&bootcode, "eepr_write.s19"); + load_s19file(&eeprdata, argv[i]); /* load s19 source file */ + //if(eeprdata.start_addr != 0xb600) { + // printf("this s19 was not intended for EEPROM\n"); + // exit(5); + //} + } else { + usage(argv[0]); + } + if(bootcode.start_addr != 0) { + fprintf(stderr, "error: program must start at address $0000\n"); + return 1; + } + if((d=serial_open(device, B1200, CS8+CLOCAL)) < 0) { + fprintf(stderr, "error: can not open '%s'\n", device); + return 5; + } + upload_firmware(d, &bootcode); + tcflush(d, TCIOFLUSH); + if(mode == MODE_READ) { + serial_setspeed(d, B9600); + for(i=0xb600; i<=0xb7ff; ) { + if((i % 32) == 0) { + printf("S123%04X", i); + s19_chksum_init(); + s19_chksum_add(35); + s19_chksum_add(i>>8); + s19_chksum_add(i&0xff); + } + if(serial_waitrxdata(d) == 0) { + fprintf(stderr, "timeout\n"); + return 5; + } + if(read(d, &b, 1) != 1) { + fprintf(stderr, "read error\n"); + return 5; + } + printf("%02X", b); + s19_chksum_add(b); + i++; + if((i % 32) == 0) { + printf("%02X\n", s19_chksum_get()); + } + } + + } else if(mode == MODE_WRITE) { + for(i=eeprdata.start_addr; i<=eeprdata.end_addr; ) { + tcflush(d, TCIOFLUSH); + write(d, &eeprdata.code[i], 1); + if(serial_waitrxdata(d) == 0) { + fprintf(stderr, "timeout\n"); + return 5; + } + if(read(d, &b, 1) != 1) { + fprintf(stderr, "read error\n"); + return 5; + } + if(eeprdata.code[i] != b) { + fprintf(stderr, "error on addr $%04X (wrote: %02X, read: %02X). EEPROM defect?\n", + i, eeprdata.code[i], b); + exit(5); + } + i++; + } + printf("Successfully programmed %i bytes to EEPROM\n", + eeprdata.end_addr-eeprdata.start_addr); + } + close(d); + return 0; +} diff --git a/src/hc11loader.c b/src/hc11loader.c new file mode 100644 index 0000000..ebb975c --- /dev/null +++ b/src/hc11loader.c @@ -0,0 +1,120 @@ + +/* -------------------------------------------------------------------- + hc11loader - Bootloader for the Motorola 68HC11 + + Copyright (C) 2004 Dominic Radermacher + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + -------------------------------------------------------------------- */ + +#include +#include /* exit() */ +#include /* strcmp() */ +#include /* isdigit() */ +#include /* read(), write(), sleep(), tcgetattr() */ +#include /* tcgetattr() */ +#include /* open() */ +#include /* open() */ +#include /* open() */ + +#include "hc11tools.h" +#include "s19stuff.h" +#include "serial.h" + +#define DEFAULT_SERDEV "/dev/ttyUSB0" + +/* -------------------------------------------------------------------- + Global variables + -------------------------------------------------------------------- */ + +char *device; /* device where the board is connected to */ + +/* -------------------------------------------------------------------- + Function prototypes + -------------------------------------------------------------------- */ + +void usage(char *progname); +int is_chardev(char *file); +int parse_args(int argc, char **argv); + +int is_chardev(char *file) +{ + struct stat stbuf; + + if(stat(file, &stbuf) == -1) { + return -1; + } + if((stbuf.st_mode & S_IFMT) != S_IFCHR) { + return -1; + } + return 0; +} + +int parse_args(int argc, char **argv) +{ + int i; + char *p; + + for(i=1; i\n", progname); + printf("\toptions:\n"); + printf("\t-d \tserial device to use (default: %s)\n", DEFAULT_SERDEV); + exit(5); +} + +int main(int argc, char **argv) +{ + int d, i; + struct obj bootcode; + + if(argc < 2) { + usage(argv[0]); + } + device=DEFAULT_SERDEV; + i=parse_args(argc, argv); + load_s19file(&bootcode, argv[i]); /* load s19 source file */ + if(bootcode.start_addr != 0) { + fprintf(stderr, "error: program must start at address $0000\n"); + return 1; + } + if((d=serial_open(device, B1200, CS8+CLOCAL)) < 0) { + fprintf(stderr, "error: can not open '%s'\n", device); + return 5; + } + upload_firmware(d, &bootcode); + close(d); + return 0; +} diff --git a/src/s19stuff.c b/src/s19stuff.c new file mode 100644 index 0000000..59b39fb --- /dev/null +++ b/src/s19stuff.c @@ -0,0 +1,148 @@ + +/* -------------------------------------------------------------------- + Copyright (C) 2004 Dominic Radermacher + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + -------------------------------------------------------------------- */ + +#include +#include /* isdigit(), tolower() */ + +#include "s19stuff.h" + +static uint8_t _s19_chksum_val=0; + +uint8_t hex2chr(char *s) +{ + return( ((isdigit(s[0])?s[0]-'0':tolower(s[0])-'a'+10)<<4) + + (isdigit(s[1])?s[1]-'0':tolower(s[1])-'a'+10)); +} + +void s19_chksum_init(void) +{ + _s19_chksum_val=0; +} + +void s19_chksum_add(uint8_t val) +{ + _s19_chksum_val += val; +} + +uint8_t s19_chksum_get(void) +{ + return ~_s19_chksum_val; +} + +int parse_s19_line(struct obj *bo, char *buf) +{ + int i, len, addr, val; + + if(*buf++ != 'S') { + return -1; + } + s19_chksum_init(); + val=0; + if(*buf == '0') { + printf("ignoring S0 record\n"); + return 0; + } else if(*buf == '1') { + len=hex2chr(++buf); + s19_chksum_add(len); + buf+=2; + addr=hex2chr(buf); + s19_chksum_add(addr); + buf+=2; + addr=addr<<8; + val=hex2chr(buf); + s19_chksum_add(val); + addr+=val; + buf+=2; + for(i=0; icode[addr+i]=val; + s19_chksum_add(val); + buf+=2; + } + val=hex2chr(buf); + if(val != s19_chksum_get()) { /* checksum does not match */ + printf("Invalid checksum for S1 Record: len=%d bytes addr=%04x chk=%02x calc=%02x\n", len, addr, val, s19_chksum_get()); + } + if(bo->start_addr > addr) { + bo->start_addr = addr; + } + if(bo->end_addr < (addr+len-3)) { + bo->end_addr = addr+len-3; + } + } else if((*buf == '2') || (*buf == '3') || (*buf == '7') || (*buf == '8')) { + printf("S%c records cant be loaded to the 68HC11 (16 bit adress only)\n", *buf); + return -1; + } else if(*buf == '5') { + printf("S5 record count ignored\n"); + return 0; + } else if(*buf == '9') { + printf("S9 record ignored yet\n"); + return 0; + } + if(val != s19_chksum_get()) { + printf("checksum error (found: %02x, expected: %02x)\n", val, s19_chksum_get()); + } + return 0; +} + +/* -------------------------------------------------------------------- + Description read from file 'f' to buffer 'd' of size 'size' + until either the buffer is full, or \n or EOF is + found. return the number of read octets or -1 + if no octets could be read (EOF) + -------------------------------------------------------------------- */ + +int f_readline(FILE *f, char *buf, int size) +{ + int n, c; + char *p; + + for(n=0, p=buf; n stop and terminate */ + *p++=c; + n++; + } else { + if(n != 0) break; /* line NOT empty -> terminate */ + return -1; /* else return -1 */ + } + } + if(n < size) { /* we have left space to terminate string */ + *p=0; + } + return n; +} + +int load_s19file(struct obj *bo, char *file) +{ + int i; + char buf[515]; /* 'S1' + len (2 chars) + 255*2 + '\0' */ + FILE *f; + + bo->start_addr=0xffff; + bo->end_addr=0x0000; + for(i=0; i<(int)sizeof(bo->code); bo->code[i++]=0); + if((f=fopen(file, "r")) == NULL) { + fprintf(stderr, "cant open file '%s'\n", file); + return -1; + } + while((i=f_readline(f, buf, 515)) != -1) { + parse_s19_line(bo, buf); + } + return 0; +} diff --git a/src/serial.c b/src/serial.c new file mode 100644 index 0000000..53a90a6 --- /dev/null +++ b/src/serial.c @@ -0,0 +1,153 @@ + +/* -------------------------------------------------------------------- + Copyright (C) 2004 Dominic Radermacher + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + -------------------------------------------------------------------- */ + +#include +#include /* tcgetattr, read(), write() */ +#include /* tcgetattr, tcflush() */ +#include /* open */ +#include /* open */ +#include /* open */ + +#include "hc11tools.h" +#include "serial.h" + +#define SERBUFSIZE 16 + +/* -------------------------------------------------------------------- + Function: serial_open + Revision: 20040801 (use this version !) + -------------------------------------------------------------------- */ + +int serial_open(char *device, int speed, int c_flags) +{ + int fd; + struct termios term; + + if((fd = open(device, O_RDWR)) < 0) { + return -1; + } + if(tcgetattr(fd, &term) < 0) { /* Get current characteristics */ + return -1; + } + cfsetispeed(&term, speed); + cfsetospeed(&term, speed); + cfmakeraw(&term); /* makeraw sets default CS8 */ + term.c_cflag |= c_flags; /* apply c_flags */ + if(tcsetattr(fd, TCSANOW, &term) < 0) { /* Now set everything */ + return -1; + } + return fd; +} + +int serial_setspeed(int fd, int speed) +{ + struct termios term; + + if(tcgetattr(fd, &term) < 0) { + perror("tcgetattr"); + return -1; + } + if(cfsetispeed(&term, speed) < 0) { + perror("cfsetispeed"); + return -1; + } + if(cfsetospeed(&term, speed) < 0) { + perror("cfsetospeed"); + return -1; + } + if(tcsetattr(fd, TCSANOW, &term) < 0) { + perror("tcsetattr"); + return -1; + } + return 0; +} + +int serial_waitrxdata(int fd) +{ + fd_set fds; + struct timeval tv; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + tv.tv_sec = 2; + tv.tv_usec = 0; + return select(fd+1, &fds, NULL, NULL, &tv); +} + +int serial_rx_empty(int fd) +{ + fd_set fds; + struct timeval tv; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + tv.tv_sec = 0; + tv.tv_usec = 10; + return select(fd+1, &fds, NULL, NULL, &tv); +} + +int upload_firmware(int fd, struct obj *bo) +{ + int i, size, len, trig; + uint8_t buf[1]; + + trig=SERBUFSIZE/2; + + tcflush(fd, TCIOFLUSH); + printf("Press reset on the HC11 board ... "); + fflush(stdout); + while(serial_waitrxdata(fd) == 0); + printf("ok, got BRK\n"); + if(read(fd, buf, 1) != 1) { + return -1; + } + sleep(1); + printf("Sending upload request code (0xff)\n"); + buf[0]=0xff; + if(write(fd, buf, 1) != 1) { /* send upload code */ + return -1; + } + size=bo->end_addr-bo->start_addr; + printf("Uploading firmware (%i bytes) ... ", size); + fflush(stdout); + tcflush(fd, TCIOFLUSH); + write(fd, &bo->code[0], SERBUFSIZE); + for(i=0; i 0) && ((i+trig)%trig == 0)) { + len=size-(i+trig); + if(len > trig) { + len=trig; + } + write(fd, &bo->code[i+trig], len); + } + if(serial_waitrxdata(fd) == 0) { + fprintf(stderr, "serial.c:138: reply timeout - board not ready ?\n"); + return -1; + } + if(read(fd, buf, 1) != 1) { + fprintf(stderr, "serial.c:142: read error\n"); + return -1; + } + if(buf[0] != bo->code[i]) { + fprintf(stderr, "serial.c:146: byte #%i: %02x != %02x\n", i, buf[0], bo->code[i]); + return -1; + } + fflush(stdout); + } + printf("ok\n"); + return 0; +} diff --git a/src/talker.c b/src/talker.c new file mode 100644 index 0000000..7f8b93f --- /dev/null +++ b/src/talker.c @@ -0,0 +1,182 @@ + +/* -------------------------------------------------------------------- + Copyright (C) 2004 Dominic Radermacher + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + -------------------------------------------------------------------- */ + +#include +#include /* uint8_t, uint16_t */ +#include /* read(), write() */ +#include /* tcflush() */ + +#include "hc11tools.h" +#include "serial.h" +#include "talker.h" + +int read_byte(int fd, uint8_t *d) +{ + if(serial_waitrxdata(fd) == 0) { + return -1; + } + if(read(fd, d, 1) != 1) { + return -1; + } + return 0; +} + +int read_word(int fd, uint16_t *d) +{ + uint8_t a; + + if(read_byte(fd, &a) < 0) { + return -1; + } + *d=(a<<8); /* MSB comes first */ + if(read_byte(fd, &a) < 0) { + return -1; + } + *d|=a; /* then LSB */ + return 0; +} + +int send_command(int fd, uint8_t cmd) +{ + uint8_t buf[1]; + + buf[0]=cmd; + if(write(fd, buf, 1) != 1) { /* send command */ + return -1; + } + if(serial_waitrxdata(fd) != 0) { + if(read(fd, buf, 1) != 1) { + return -1; + } + if(buf[0] != ~(cmd)) { /* reply is complement ? */ + printf("ERR[%02x!=%02x]\n", buf[0], ~cmd); + return -1; + } + return 0; + } + fprintf(stderr, "reply timeout\n"); + return -1; +} + +int read_mcu_mem(int fd, uint16_t addr, uint8_t *data, int len) +{ + int i; + uint8_t buf[2]; + + if((len < 1) || (len > 256)) { + return -1; + } + if(send_command(fd, 0x01) != 0) { /* complement = 0xfe */ + printf("read_mcu_mem (0x01) failed\n"); + tcflush(fd, TCIOFLUSH); + return -1; + } + buf[0]=len; + write(fd, buf, 1); + buf[0]=(addr & 0xff); /* LSB */ + buf[1]=(addr >> 8); /* MSB */ + write(fd, buf, 2); + for(i=0; i 256)) { + return -1; + } + if(send_command(fd, 0x41) != 0) { /* complement = 0xbe */ + printf("write_mcu_mem (0x41) failed\n"); + tcflush(fd, TCIOFLUSH); + return -1; + } + buf[0]=len; + write(fd, buf, 1); + buf[0]=(addr & 0xff); /* LSB */ + buf[1]=(addr >> 8); /* MSB */ + write(fd, buf, 2); + for(i=0; isp); + read_byte(fd, ®s->ccr); + read_byte(fd, ®s->b); + read_byte(fd, ®s->a); + read_word(fd, ®s->ix); + read_word(fd, ®s->iy); + read_word(fd, ®s->pc); + return 0; +} + +int write_mcu_regs(int fd, struct mcu_regs *regs) +{ + uint8_t buf[10]; + + if(send_command(fd, 0xc1) != 0) { /* complement = 0x3e */ + printf("write_mcu_regs (0xc1) failed\n"); + tcflush(fd, TCIOFLUSH); + return -1; + } + /* buf[0] = LSB, buf[1] = MSB */ + buf[0]=(regs->sp & 0xff); + buf[1]=(regs->sp >> 8); + write(fd, buf, 2); /* Set SP */ + buf[0]=regs->ccr; + buf[1]=regs->b; + buf[2]=regs->a; + buf[3]=(regs->ix >> 8); + buf[4]=(regs->ix & 0xff); + buf[5]=(regs->iy >> 8); + buf[6]=(regs->iy & 0xff); + buf[7]=(regs->pc >> 8); + buf[8]=(regs->pc & 0xff); + write(fd, buf, 9); + return 0; +} + +int swi_handler(int fd, struct mcu_regs *regs) +{ + uint16_t pc; + + read_word(fd, &pc); + printf("SWI on $%04x\n", pc-1); /* stored PC points to next */ + regs->pc=pc-1; /* well, will be set to idleloop */ + read_word(fd, ®s->sp); + read_byte(fd, ®s->ccr); + read_byte(fd, ®s->b); + read_byte(fd, ®s->a); + read_word(fd, ®s->ix); + read_word(fd, ®s->iy); + return 0; +} diff --git a/src/tty.c b/src/tty.c new file mode 100644 index 0000000..0a7b7fc --- /dev/null +++ b/src/tty.c @@ -0,0 +1,232 @@ + +/* -------------------------------------------------------------------- + tty code for my 68HC11 devtools project + + Copyright (C) 2004 Dominic Radermacher + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + -------------------------------------------------------------------- */ + +#include +#include +#include +#include /* strncpy() */ +#include +#include +#include +#include + +#include "tty.h" + +struct _tty_keyseq_struct { + char *seq; + int code; +} tty_keyseqs[] = { + {"[[A", KEY_F1}, {"OP ", KEY_F1}, + {"[[B", KEY_F2}, {"OQ", KEY_F2}, + {"[[C", KEY_F3}, {"OR", KEY_F3}, + {"[[D", KEY_F4}, {"OS", KEY_F4}, + {"[[E", KEY_F5}, {"[15~", KEY_F5}, + {"[17~", KEY_F6}, + {"[18~", KEY_F7}, + {"[19~", KEY_F8}, + {"[20~", KEY_F9}, + {"[21~", KEY_F10}, + {"[23~", KEY_F11}, + {"[24~", KEY_F12}, + {"[25~", KEY_F13}, + {"[A", KEY_C_UP}, + {"[B", KEY_C_DOWN}, + {"[C", KEY_C_RIGHT}, + {"[D", KEY_C_LEFT}, + {"[2~", KEY_INS}, + {"[3~", KEY_DEL}, + {"[1~", KEY_HOME}, {"[H", KEY_HOME}, + {"[5~", KEY_PG_UP}, + {"[6~", KEY_PG_DOWN}, + {"[4~", KEY_END}, {"[F", KEY_END}, + {"[P", KEY_BREAK}, + {0, 0} +}; + +/* -------------------------------------------------------------------- + Function : Initialisation of the tty. + Input value : Structure of screen. + Output value : Structure of screen with height and width + -------------------------------------------------------------------- */ + +int tty_init(void) +{ + struct termios tios; + + if(tcgetattr(0, &tios) == 0) { + tios.c_lflag &= ~ICANON; /* Turn char buffering off */ + tios.c_lflag &= ~ECHO; /* Turn char displaying off */ + tios.c_cflag |= CRTSCTS; + if(tcsetattr(0, 0, &tios) != 0) { + fprintf(stderr, "TTY Error\n"); + } + } + printf("\033[r\033[999;999f\033[6n"); + scanf("\033[%i;%i", &(my_scr.height), &(my_scr.width)); + return 0; +} + +int _tty_getkeycode(int t) +{ + fd_set fds; + struct timeval TimeOut; + unsigned char b[1]; + TimeOut.tv_sec = t; + TimeOut.tv_usec = 1000; /* Mikrosekunden !! */ + + FD_ZERO(&fds); + FD_SET(0, &fds); /* 0 means socket stdin */ + if(select(1, &fds, NULL, NULL, &TimeOut) != 0) { + read(0, b, 1); + return 0x0000+b[0]; + } /* else ... */ + return KEY_TIMEOUT; +} + +/* --------------------------------------------------------------------- + Function : Wait for key until timeout, if a key is pressed + return its code. + Input value : Timeout in seconds. + Output value : 0x00xx, xx=keycode, if normal keycode + 0x01xx xx=keycode with ALT modifier + 0x02xx xx=special ESC sequence code + 0xffff if timeout occurs. + --------------------------------------------------------------------- */ + +int tty_getkey(void) +{ + int count, k; + char b[8]; + + if((k=_tty_getkeycode(1)) == KEY_TIMEOUT) { + return KEY_TIMEOUT; + } else if(k != 0x1b) { + return k; + } else { + for(count=0; ((k=_tty_getkeycode(0)) != KEY_TIMEOUT); count++) { + if(count < 7) { + b[count]=(k & 0xff); + } + } + if(count == 0) { + return 0x001b; + } else if(count == 1) { /* ESC = Alt + */ + return 0x0100 + b[0]; + } /* all others must be looked up */ + for(k=0; tty_keyseqs[k].seq != NULL; k++) { + if(strncmp(tty_keyseqs[k].seq, b, count) == 0) { + return tty_keyseqs[k].code; + } + } +// printf("%i ESC %02x %02x %02x %02x\n", count, b[0], b[1], b[2], b[3]); + return KEY_UNKNOWN; + } +} + +/* -------------------------------------------------------------------- + Function : Turns display of chars on or off. + Input value : Mode, can be 0 (off) or 1 (on) + Output value : None. + -------------------------------------------------------------------- */ + +int tty_setechomode(int mode) +{ + struct termios tios; + + if(tcgetattr(0, &tios) != 0) { + return -1; + } + if(mode == 0) { + tios.c_lflag &= ~ECHO; /* Char displaying off */ + } else { + tios.c_lflag |= ECHO; /* Char displaying on */ + } + if(tcsetattr(0, 0, &tios) != 0) { + return -1; + } + return 0; +} + +inline int tty_width() +{ + return my_scr.width; +} + +inline int tty_height() +{ + return my_scr.height; +} + +inline void tty_cls(void) +{ + printf("\033[2J"); +} + +inline void tty_clreol(void) +{ + printf("\033[0K"); /* clear from cursor to end of line */ +} + +void tty_gotoxy(int x, int y) +{ + if(x < 1) x=1; + if(x > my_scr.width) x=my_scr.width; + if(y < 1) y=1; + if(y > my_scr.height) y=my_scr.height; + printf("\033[%i;%if", y, x); +} + +int tty_setscrollregion(int from, int to) +{ + if((from < 1) || (from >= my_scr.height) || (to < from) || (to > my_scr.height)) { + return -1; + } + printf("\033[%i;%ir", from, to); /* Set scrolling region */ + return 0; +} + +void tty_setmode(int mode) +{ + printf("\033[%im", mode); +} + +void tty_setcolor(int bg, int fg) +{ + if((bg < 0) || (bg > 7) || (fg < 0) || (fg > 7)) { + return; + } + printf("\033[%i;%im", 40+bg, 30+fg); +} + +inline void tty_savecursorpos(void) +{ + printf("\0337"); /* Save cursor position */ +} + +inline void tty_restorecursorpos(void) +{ + printf("\0338"); /* Restore cursor */ +} + +void tty_reset(void) +{ +// tty_setscrollregion(1, my_scr.height); + tty_setechomode(1); /* is NOT included in full reset */ + printf("\033c"); /* Full reset */ +} diff --git a/src/ui.c b/src/ui.c new file mode 100644 index 0000000..54b0fbc --- /dev/null +++ b/src/ui.c @@ -0,0 +1,179 @@ + +/* -------------------------------------------------------------------- + Copyright (C) 2004 Dominic Radermacher + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + -------------------------------------------------------------------- */ + +#include +#include /* memset() */ + +#include "hc11tools.h" +#include "tty.h" +#include "ui.h" + +void show_linebuf(char *s, int offs, int scr_x); + +char *ccr_to_string(uint8_t ccr) +{ + int i; + static char ret[9]; + + for(i=0; i<8; i++) { + ret[7-i]=((ccr&(1< "); + for(i=0; i 0) { + OffsetX--; + } + } else if(i == KEY_DEL) { + if(OffsetX < len) { + for(k=OffsetX; k 0) { + for(k=OffsetX; k31) && (i<127)) { + if(OffsetX < (int)(sizeof(LineBuf)-1)) { + LineBuf[OffsetX]=i; + OffsetX++; + len++; + } + } else if((i==0xfc)||(i==0xf6)||(i==0xe4)||(i==0xdc)||(i==0xd6)||(i==0xc4)||(i==0xdf)) { + if(OffsetX < (int)(sizeof(LineBuf)-1)) { + LineBuf[OffsetX]=i; + OffsetX++; + len++; + } + } + if(OffsetX < tty_width()) { /* Now calculate LineX and CursorX */ + if(OffsetX < (tty_width()/2)) { + LineX=0; + } + CursorX=OffsetX-LineX; + } else { + k = (tty_width() / 2); + LineX=((OffsetX / k)-1)*k; + CursorX=OffsetX-LineX; + } + } + return NULL; +} + +void ui_show_mcu_regs(struct mcu_regs *regs) +{ + int i; + + tty_savecursorpos(); + tty_gotoxy(1, tty_height()-3); + printf("\033[7m"); /* Set cursor and inverse */ + printf("PC A B IX IY CCR (SXHINZVC) SP"); + for(i=48; ipc, regs->a, regs->b, regs->ix, regs->iy, + regs->ccr, ccr_to_string(regs->ccr), regs->sp); + tty_restorecursorpos(); + fflush(stdout); + return; +} + +void ui_show_mcu_type(struct mcu *mymcu) +{ + tty_savecursorpos(); + tty_gotoxy(tty_width()-10, tty_height()-3); + printf("\033[7m"); /* Set cursor and inverse */ + printf("MCU = $%04X", mymcu->devid); + printf("\033[0m"); /* Set normal */ + tty_restorecursorpos(); + fflush(stdout); + return; +} + +void ui_show_mem(uint16_t addr, uint8_t *mem, int len) +{ + int i; + + for(i=0; i