
/*
 * boot_hms_evb_h8s2633f.S - a bootloader for use via ufpb
 *
 * Copyright (C) 2002 Magnus Damm <damm@opensource.se>
 *
 * This code is released under the terms of GPL.
 * 
 * This is the boot code that is uploaded to the h8s/2633f-cpu
 * via the ufpb-board. Most of it is pretty generic, but it is
 * designed for the evb-h8s/2633f-board that has external ram.
 * We are initializing 128Kbytes external ram (CS1) in "board_init".
 * It is in the external ram at 0x00200000 we should load the RTOS.
 * We do have 256Kbytes external ram on the evb-board, but the
 * serial port-pins and the required address-bus pins are shared,
 * so we stick with 128Kbytes for now.
 *
 * We also enable RAM Emulation to be able to use interrupts. 
 *
 * We don't use any flash at all.
 * All this because maximum 100 programming cycles are supported...
 */
	
	
#include "../boot_cmds.h"	

#define STACK_TOP 0xffefac	
		
	.text
	.org 0
	.h8300s
	
	.globl start
start:
	mov.l #STACK_TOP, er7

	jsr pins_init
	jsr serial_init
	jsr board_init
	
main_loop:		
	mov.l #0x10000, er6

loop_delay:

	jsr serial_rx_check
	bne do_serial

dont_echo:	
	sub.l #1, er6
	bne loop_delay

	jsr pins_led_toggle
	bra main_loop


address:	
	.long 0x12345678

do_address_set:
	mov.b r0l, r5l

	jsr do_get_u32
	mov.l er0, @address
	
	mov.b r5l, r0l
	jsr serial_tx
	bra dont_echo
	
do_address_get:
	jsr serial_tx
	mov.l @address, er0
	jsr do_put_u32
		
	bra dont_echo

do_run:
	jsr serial_tx
	mov.l @address, er3
	jsr pins_led_off
	jmp @er3
	
do_bad:	
	mov.b #CMD_REPLY_BAD, r0l	
do_hello:		
	jsr serial_tx
	bra dont_echo		

do_serial:		
	
	jsr serial_rx

	mov.b r0l, r0h
	bset #7, r0l
	
	cmp #CMD_HELLO, r0h
	beq do_hello

	cmp #CMD_ADDRESS_GET, r0h
	beq do_address_get

	cmp #CMD_ADDRESS_SET, r0h
	beq do_address_set

	cmp #CMD_RUN, r0h
	beq do_run

	cmp #CMD_READ_8, r0h
	beq do_read_8

	cmp #CMD_READ_16, r0h
	beq do_read_16

	cmp #CMD_READ_32, r0h
	beq do_read_32

	cmp #CMD_WRITE_8, r0h
	beq do_write_8

	cmp #CMD_WRITE_16, r0h
	beq do_write_16

	cmp #CMD_WRITE_32, r0h
	beq do_write_32

	bra do_bad

do_read_8:
	jsr serial_tx
	mov.l @address, er3
	mov.b @er3, r0l
	jsr serial_tx

	bra do_inc_8

do_read_16:
	jsr serial_tx
	mov.l @address, er3
	mov.w @er3, r0
	jsr do_put_u16

	bra do_inc_16		

do_read_32:
	jsr serial_tx
	mov.l @address, er3
	mov.l @er3, er0
	jsr do_put_u32

	bra do_inc_32		

do_write_8:
	mov.b r0l, r5l

	jsr serial_rx
	mov.l @address, er3
	mov.b r0l, @er3

	mov.b r5l, r0l
	jsr serial_tx

do_inc_8:	
	mov.l #1, er0
	bra do_inc

do_write_16:
	mov.b r0l, r5l

	jsr do_get_u16
	mov.l @address, er3
	mov.w r0, @er3
	
	mov.b r5l, r0l
	jsr serial_tx

do_inc_16:	
	mov.l #2, er0
	bra do_inc

do_write_32:
	mov.b r0l, r5l

	jsr do_get_u32
	mov.l @address, er3
	mov.l er0, @er3
	
	mov.b r5l, r0l
	jsr serial_tx

do_inc_32:	
	mov.l #4, er0
	bra do_inc

do_inc:
	mov.l @address, er3
	add.l er0, er3
	mov.l er3, @address
	jmp dont_echo

/* 16-bit and 32-bit output functions */
	
do_get_u32:	
	jsr serial_rx
	mov.l #0, er3
	mov.b r0l, r3h

	shll.l #2, er3
	shll.l #2, er3
	shll.l #2, er3
	shll.l #2, er3

	jsr serial_rx
	mov.b r0l, r3h

	shll.l #2, er3
	shll.l #2, er3
	shll.l #2, er3
	shll.l #2, er3

	jsr serial_rx
	mov.b r0l, r3h

	jsr serial_rx
	mov.b r0l, r3l
	mov.l er3, er0
	rts	

do_get_u16:	
	jsr serial_rx
	mov.l #0, er3
	mov.b r0l, r3h

	jsr serial_rx
	mov.b r0l, r3l
	mov.l er3, er0
	rts	

do_put_u32:	
	mov.l er0, @-er7

	mov.b @er7, r0l 
	jsr serial_tx
	add.l #1, er7

	mov.b @er7, r0l 
	jsr serial_tx
	add.l #1, er7

	mov.b @er7, r0l 
	jsr serial_tx
	add.l #1, er7

	mov.b @er7, r0l 
	jsr serial_tx
	add.l #1, er7
	rts
	
do_put_u16:	
	mov.w r0, @-er7

	mov.b @er7, r0l 
	jsr serial_tx
	add.l #1, er7

	mov.b @er7, r0l 
	jsr serial_tx
	add.l #1, er7
	rts
	

#define P1DDR  0xfe30:16
#define P1DR   0x00:8 /* same as 0xff00:16 */
#define P1DATA 0xb0:8 /* same as 0xffb0:16 */

#define P1_PIN_PMODE   0x80
#define P1_PIN_USERLED 0x20

pins_init:	
	mov.b #(P1_PIN_PMODE + P1_PIN_USERLED), r0l   /* pins are outputs */
	mov.b #P1_PIN_USERLED, r1l   
	mov.b r0l, @P1DDR
	mov.b r1l, @P1DR
	rts			
	
pins_led_toggle:	
	mov.b @P1DATA, r0l
	xor.b #P1_PIN_USERLED, r0l
	mov.b r0l, @P1DR
	rts
	
pins_led_off:	
	mov.b @P1DATA, r0l
	or.b #P1_PIN_USERLED, r0l
	mov.b r0l, @P1DR
	rts
	
			
#define SMR2  0x88:8
#define BRR2  0x89:8
#define SCR2  0x8a:8
#define TDR2  0x8b:8
#define SSR2  0x8c:8
#define RDR2  0x8d:8
#define SCMR2 0x8e:8

#define SMR  SMR2
#define BRR  BRR2
#define SCR  SCR2
#define TDR  TDR2
#define SSR  SSR2
#define RDR  RDR2
#define SCMR SCMR2

#define BOARD_XIN 18432000	
#define BOARD_BRR_9600 58
#define BOARD_BRR BOARD_BRR_9600
	
serial_init:	
	
	/* setup the serial controller to n81 and clock/1 */
	
	mov.b #0, r0l      
	mov.b r0l, @SMR

#ifdef BOARD_BRR
	/* setup the clock generator to the desired bps */
	
	mov.b #BOARD_BRR, r0l      
	mov.b r0l, @BRR
#endif	
	/* enable transmit and receive, no interrupts */
	
	mov.b #0x30, r0l
	mov.b r0l, @SCR

	rts

serial_tx:			
	/* send a character passed in r0l*/
	
serial_tx_drain:	
	btst #7, @SSR
	beq serial_tx_drain
	
	mov.b r0l, @TDR
	bclr #7, @SSR

serial_tx_finish:	
	btst #2, @SSR
	beq serial_tx_finish

	rts	

serial_rx:
	/* receive a character and return in r0l */

serial_rx_wait:	
	btst #6, @SSR
	beq serial_rx_wait

	mov.b @RDR, r0l
	bclr #6, @SSR
	
	rts

serial_rx_check:
	/* check if data is available - z-flag is cleared if available */
	btst #6, @SSR
	rts

#define RAMER  0xfedb:16

#define ABWCR  0xfed0:16
#define WRCL   0xfed3:16
#define PFCR   0xfdeb:16
	
#define PADDR  0xfe39:16
#define PBDDR  0xfe3a:16
#define PCDDR  0xfe3b:16
#define PGDDR  0xfe3f:16

board_init:

	/* RAMER: enable RAM emulation for interrupt vectors */
	
	mov.b #8, r0l
	mov.b r0l, @RAMER

	/* ABWCR: CS1 should be 16-bit */

	mov.b #0xfd, r0l
	mov.b r0l, @ABWCR

	/* WRCL: CS1 should have 0 waitstates */

	mov.b #0xf9, r0l
	mov.b r0l, @WRCL

	/* PFCR: 128k adresses */

	mov.b #0x9, r0l
	mov.b r0l, @PFCR

	/* PGDDR: The CS1 pin should be configured as CS1 */

	mov.b #0x8, r0l
	mov.b r0l, @PGDDR

	/* PADDR, PBDDR, PCDDR: Configure the address-pins */

	mov.b #0xff, r0l
	mov.b r0l, @PCDDR
	mov.b r0l, @PBDDR
	mov.b #0x3, r0l
	mov.b r0l, @PADDR

	rts
