mac-floppy-emu/floppy_emu_bootloader/bootldr/asmfunc.S

213 lines
4.0 KiB
ArmAsm
Executable File

;---------------------------------------------------------------------------;
; MMC hardware controls and Flash controls (C)ChaN, 2010
;---------------------------------------------------------------------------;
; Hardware dependent macros to be modified
#define DDR_CS _SFR_IO_ADDR(DDRB), 4 // MMC CS pin (DDR, PORT)
#define PORT_CS _SFR_IO_ADDR(PORTB), 4
#define DDR_CK _SFR_IO_ADDR(DDRB), 7 // MMC SCLK pin (DDR, PORT)
#define PORT_CK _SFR_IO_ADDR(PORTB), 7
#define DDR_DI _SFR_IO_ADDR(DDRB), 5 // MMC DI pin (DDR, PORT)
#define PORT_DI _SFR_IO_ADDR(PORTB), 5
#define PIN_DO _SFR_IO_ADDR(PINB), 6 // MMC DO pin (PIN, PORT)
#define PORT_DO _SFR_IO_ADDR(PORTB), 6
;---------------------------------------------------------------------------;
.nolist
#include <avr/io.h>
.list
.text
;---------------------------------------------------------------------------;
; Initialize MMC port
;
; void init_spi (void);
.global init_spi
.func init_spi
init_spi:
sbi DDR_CS ; CS: output
sbi DDR_DI ; DI: output
sbi DDR_CK ; SCLK: output
sbi PORT_DO ; DO: pull-up
ret
.endfunc
;---------------------------------------------------------------------------;
; Delay 100 microseconds
;
; void dly_us (UINT n);
.global dly_100us
.func dly_100us
dly_100us:
ldi r24, lo8(F_CPU / 100000) /* Loop counter */
1: sbiw r30, 1 /* 10 clocks per loop */
sbiw r30, 1
sbiw r30, 1
nop
dec r24
brne 1b
ret
.endfunc
;---------------------------------------------------------------------------;
; Select MMC
;
; void select (void);
.global select
.func select
select:
rcall deselect
cbi PORT_CS
rjmp rcv_spi
.endfunc
;---------------------------------------------------------------------------;
; Deselect MMC
;
; void deselect (void);
.global deselect
.func deselect
deselect:
sbi PORT_CS
; Goto next function
.endfunc
;---------------------------------------------------------------------------;
; Receive a byte
;
; BYTE rcv_spi (void);
.global rcv_spi
.func rcv_spi
rcv_spi:
ldi r24, 0xFF ; Send 0xFF to receive data
; Goto next function
.endfunc
;---------------------------------------------------------------------------;
; Transmit a byte
;
; void xmit_spi (BYTE);
.global xmit_spi
.func xmit_spi
xmit_spi:
ldi r25, 8
1: sbrc r24, 7 ; DI = Bit to sent
sbi PORT_DI ;
sbrs r24, 7 ;
cbi PORT_DI ; /
lsl r24 ; Get DO from MMC
sbic PIN_DO ;
inc r24 ; /
sbi PORT_CK ; A positive pulse to SCLK
cbi PORT_CK ; /
dec r25 ; Repeat 8 times
brne 1b ; /
ret
.endfunc
;---------------------------------------------------------------------------
; Erase a flash page
;
; void flash_erase (DWORD flash_addr);
.global flash_erase
.func flash_erase
flash_erase:
movw ZL, r22
#if FLASHEND >= 0x10000
out _SFR_IO_ADDR(RAMPZ), r24
#endif
; Initiate erase operation
ldi r24, 0b00000011
sts _SFR_MEM_ADDR(SPMCSR), r24
spm
; Wait for end of erase operation
1: lds r24, _SFR_MEM_ADDR(SPMCSR)
sbrc r24, 0
rjmp 1b
; Re-enable read access to the flash
ldi r24, 0b00010001
sts _SFR_MEM_ADDR(SPMCSR), r24
spm
9: ret
.endfunc
;---------------------------------------------------------------------------
; Write a flash page
;
; void flash_write (DWORD flash_addr, const BYTE* data);
.global flash_write
.func flash_write
flash_write:
push r0
push r1
#if FLASHEND >= 0x10000
out _SFR_IO_ADDR(RAMPZ), r24
#endif
; Fill page buffer
movw ZL, r22
movw XL, r20
ldi r25, lo8(SPM_PAGESIZE/2)
1: ld r0, X+
ld r1, X+
ldi r24, 0b00000001
sts _SFR_MEM_ADDR(SPMCSR), r24
spm
adiw ZL, 2
dec r25
brne 1b
; Initiate write operation
movw ZL, r22
ldi r24, 0b00000101
sts _SFR_MEM_ADDR(SPMCSR), r24
spm
; Wait for end of write operation
2: lds r24, _SFR_MEM_ADDR(SPMCSR)
sbrc r24, 0
rjmp 2b
; Re-enable read access to the flash
ldi r24, 0b00010001
sts _SFR_MEM_ADDR(SPMCSR), r24
spm
9: pop r1
pop r0
ret
.endfunc