os.asm (6560B)
1 ;;; Copyright 2021 Gerd Beuster (gerd@frombelow.net). This is free 2 ;;; software under the GNU GPL v3 license or any later version. See 3 ;;; COPYING in the root directory for details. 4 5 DEBUG = false 6 ;; DEBUG = true 7 8 CLOCK_SPEED = 4 ;4 Mhz Clock 9 10 ;;; An NMI may either dump the ROM (default behavior) or jump into Wozmon (in case 11 ;;; WOZMON_ON_NMI is set to true). The default behavior compiles a ROM 12 ;;; fully compliant with the GPL v3. Since Wozmon is not officially 13 ;;; free software, compiling the kernel into Wozmon does not comply to 14 ;;; the GPL v3. However I, Gerd Beuster, the author of the kernel, 15 ;;; grant you the right to compile Wozmon into the kernel. 16 WOZMON_ON_NMI = false 17 ; WOZMON_ON_NMI = true 18 19 .if SYMON 20 rom_start = $c000 21 .else 22 rom_start = $e000 23 .endif 24 25 .include "os.inc" 26 27 * = $00 28 .dsection zero_page 29 .cerror * > $ff, "Zero page exhausted" 30 * = rom_start 31 .dsection rom 32 .cerror * > $ffff, "ROM exhausted" 33 34 os .namespace 35 ram_end = $7fff 36 .endn 37 38 ;;; System jumps into memdump on NMIs. Since we want to be 39 ;;; able to handle IRQs in RAM, the ROM isr routine jump to the 40 ;;; address given here. After a reset, this RAM address is set to 41 ;;; default_irq_handler. 42 .namespace os 43 irq_vector = os.ram_end - $1 44 .endn 45 46 .section rom 47 ;;; ---------------------------------------------------------- 48 ;;; RESET 49 ;;; 50 ;;; Initialize serial interface, read code from serial 51 ;;; interface into RAM, execute it. 52 ;;; ---------------------------------------------------------- 53 54 boot: .block 55 sei 56 cld 57 ;; Reset interrupt vector 58 #mem.STORE_WORD os.default_irq_handler, os.irq_vector 59 jsr via.init 60 #io.SETUP 61 cli 62 ldx #$ff ; Reset return stack 63 txs 64 #ds.INIT_STACK os.ram_end-$206+$1 ;Minimal stack size to access SD card 65 #io.PRINTSNL "***** Eris 2010 8-Bit System (" .. VERSION .. ") *****" 66 jsr check_for_program_download 67 bcs no_program_download 68 jmp download_program 69 no_program_download: 70 ;; No program download? 71 ;; Start embedded program. 72 jmp default_program 73 .bend 74 75 ;;; If we receive a byte right after a reset, this 76 ;;; triggers a program download via serial line. 77 ;;; The value of the byte is the number of $100 byte 78 ;;; blocks to receive. 79 check_for_program_download: .block 80 #io.PRINTSNL "Kallisti!" 81 #io.PRINTNL 82 ldy #$20 ; Outer loop counter 83 ldx #$00 ; Inner counter 84 loop: 85 ;; Download sequence is initiated by sending $ff. 86 jsr io.getc_nonblocking 87 bcc got_byte 88 dex 89 bne loop 90 dey 91 bne loop 92 sec 93 rts 94 got_byte: 95 cmp #$ff 96 beq initiate_download 97 sec 98 rts 99 initiate_download: 100 clc 101 rts 102 .bend 103 104 download_program: .block 105 ;; Program is loaded to this memory address 106 start_addr = $0200 107 ;; Location of temporary variables 108 addr_pointer = $12 ; addr_pointer+1 stores MSB 109 msb_last_addr = $14 110 add_checksum = $15 111 xor_checksum = $16 112 ;; Get number of $100 blocks to be downloaded. 113 jsr io.getc 114 ;; The msb of the last block to be written is the msb 115 ;; of the start address plus the number of blocks. 116 clc 117 adc #>start_addr 118 sta msb_last_addr 119 ;; Read n * 0x100 bytes from acia 120 lda #<start_addr 121 sta addr_pointer 122 lda #>start_addr 123 sta addr_pointer+1 124 ;; We calculate a two checksums over the data: 125 ;; The first byte is the addition of all bytes 126 ;; received. The second byte is the xor of all 127 ;; bytes received. 128 lda #$00 129 sta add_checksum 130 sta xor_checksum 131 transmit_block: 132 jsr io.getc 133 ;; Store data 134 ldy #$00 135 sta (addr_pointer), y 136 ;; Update checksums 137 pha 138 clc 139 adc add_checksum 140 sta add_checksum 141 pla 142 eor xor_checksum 143 sta xor_checksum 144 ;; Update LSB of target address and check if 145 ;; transmission of block is completed. 146 inc addr_pointer 147 bne transmit_block 148 ;; Transmission of one block completed. 149 ;; If we are not done, increase 150 ;; MSB of target address and continue 151 inc addr_pointer+1 152 lda addr_pointer+1 153 cmp msb_last_addr 154 bne transmit_block 155 ;; Transmission completed. 156 ;; Transmit result of checksum calculation 157 lda add_checksum 158 jsr io.putc 159 lda xor_checksum 160 jsr io.putc 161 ;; Application number is passed to program 162 ;; in A. Since uploaded programs do not have 163 ;; an application number, we load A with $ff 164 lda #$ff 165 ;; Start program 166 jmp $0200 167 .bend 168 169 memdump: 170 .block 171 ldx #$00 ; Delay loop loop 172 ldy #$00 ; to make sure that 173 delay: ; we do not mess up 174 dey ; serial transfer. 175 bne delay 176 dex 177 bne delay 178 #io.PRINTSNL x"0d" .. x"0a" .. "-- BEGIN MEMORY DUMP --" 179 #io.PRINTS "Stack Pointer: " 180 tsx 181 txa 182 jsr io.puth 183 #mem.STORE_WORD $0000, os.memdump_ptr ; Start address of memory dump 184 next_line: 185 jsr print_nl_and_address 186 ldy #$00 187 next_byte: 188 lda (os.memdump_ptr),y ; Print next memory address. 189 phy 190 jsr io.puth 191 lda #' ' 192 jsr io.putc 193 ply 194 iny ; Advance byte counter. 195 cpy #16 ; 16 entries 196 bne next_byte ; per line. 197 lda os.memdump_ptr ; Check 198 cmp #<(os.ram_end-15) ; if 199 bne not_finished ; we 200 lda os.memdump_ptr+1 ; are 201 cmp #>(os.ram_end-15) ; done. 202 bne not_finished 203 #io.PRINTSNL x"0d" .. x"0a" .. "-- END MEMORY DUMP --" 204 rti 205 not_finished: 206 #mem.ADD_WORD os.memdump_ptr, 16 ; Advance memory pointer 207 jmp next_line 208 print_nl_and_address: 209 #io.PRINTNL 210 lda os.memdump_ptr+1 211 jsr io.puth 212 lda os.memdump_ptr 213 jsr io.puth 214 #io.PRINTS ": " 215 rts 216 .bend 217 218 219 .include "io.asm" 220 .include "ds.asm" 221 .include "lfsr.asm" 222 .include "via.asm" 223 .include "sd.asm" 224 .include "term.asm" 225 226 .namespace os 227 .section zero_page 228 memdump_ptr: .word ? 229 rom_zero_page_end: 230 .send zero_page 231 .endn 232 233 ;;; Default IRQ handler. Unless the user program changes 234 ;;; the irq_vector, IRQs are handled here. 235 .namespace os 236 default_irq_handler: 237 .endn 238 rti 239 240 derefer_ram_irq: 241 ;; Jump to the address given in the IRQ vector 242 ;; in RAM 243 jmp (os.irq_vector) 244 245 default_program: 246 LOAD_FROM_CARD_EMBEDDED = true 247 .include "../../sw/asm/load_from_card/load_from_card.asm" 248 249 .if WOZMON_ON_NMI 250 wozmon: 251 WOZMON_EMBEDDED = true 252 .include "../../contrib/asm/wozmon/wozmon.asm" 253 .endif 254 255 ;;; Vectors 256 .fill $fffa-*, $ff 257 .if WOZMON_ON_NMI 258 .word wozmon ; nmi 259 .else 260 .word memdump ; nmi 261 .fi 262 .word boot ; reset 263 .word derefer_ram_irq ; irq 264 265 .send rom