You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
4.6 KiB
ArmAsm
272 lines
4.6 KiB
ArmAsm
;---------------------------------------------------------------------------;
|
|
; MMC hardware controls and Flash controls (C)ChaN, 2010
|
|
;---------------------------------------------------------------------------;
|
|
; Hardware dependent macros to be modified //do this in Makefile
|
|
#include "spi_pins.h"
|
|
|
|
; ALL Pins given as Port (A,B,C,...) plus number
|
|
|
|
; LED Pins
|
|
;#define DDR_SS _SFR_IO_ADDR(DDRD), 5 // SS pin (PIN, PORT)
|
|
;#define PORT_SS _SFR_IO_ADDR(PORTD), 5
|
|
#define DDR_SS _SFR_IO_ADDR(DDRC), 3 // SS pin (PIN, PORT)
|
|
#define PORT_SS _SFR_IO_ADDR(PORTC), 3
|
|
|
|
;#define DDR_PW _SFR_IO_ADDR(DDRD), 6 // Power pin (PIN, PORT)
|
|
;#define PORT_PW _SFR_IO_ADDR(PORTD), 6
|
|
|
|
;SD CARD PINS
|
|
#define DDR_CS _SFR_IO_ADDR(SD_CS_DDR), SD_CS_BIT
|
|
#define PORT_CS _SFR_IO_ADDR(SD_CS_PORT), SD_CS_BIT
|
|
|
|
;---------------------------------------------------------------------------;
|
|
.nolist
|
|
#include <avr/io.h>
|
|
.list
|
|
.text
|
|
|
|
.global init_leds
|
|
.func init_leds
|
|
init_leds:
|
|
sbi DDR_SS
|
|
; sbi DDR_PW
|
|
ret
|
|
.endfunc
|
|
|
|
|
|
.global led_write_on
|
|
.func led_write_on
|
|
led_write_on:
|
|
sbi PORT_SS
|
|
ret
|
|
.endfunc
|
|
|
|
.global led_write_off
|
|
.func led_write_off
|
|
led_write_off:
|
|
cbi PORT_SS
|
|
ret
|
|
.endfunc
|
|
|
|
;.global led_power_on
|
|
;.func led_power_on
|
|
;led_power_on:
|
|
; sbi PORT_PW
|
|
; ret
|
|
;.endfunc
|
|
|
|
;.;global led_power_off
|
|
;.;func led_power_off
|
|
;led_power_off:
|
|
; cbi PORT_PW
|
|
; ret
|
|
;.endfunc
|
|
|
|
;.;global led_power_toggle
|
|
;.func led_power_toggle
|
|
;led_power_toggle:
|
|
; sbis PORT_PW
|
|
; jmp led_power_on
|
|
; jmp led_power_off
|
|
;.endfunc
|
|
|
|
.global led_write_toggle
|
|
.func led_write_toggle
|
|
led_write_toggle:
|
|
sbis PORT_SS
|
|
jmp led_write_on
|
|
jmp led_write_off
|
|
.endfunc
|
|
|
|
;---------------------------------------------------------------------------;
|
|
; 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);
|
|
|
|
#ifndef SPMCSR
|
|
#define SPMCSR SPMCR
|
|
#endif
|
|
|
|
.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
|