#define SPI_MODE SPI_MODE_0
;------------------------------------------------
-;
+;
.macro spi_clkslow
.if MMC_DEBUG > 1
printstring "SPI_CLK_SLOW "
.endm
;------------------------------------------------
-;
+;
.macro spi_clkfast
.if MMC_DEBUG > 1
printstring "SPI_CLK_FAST "
.endm
;------------------------------------------------
-;
+;
.macro spi_disable
.if MMC_DEBUG > 1
printstring "SPI_DISABLE "
rol yl
rol yh
ret
-
+
;------------------------------------------------
spi_rcvr:
out SPDR,_255
.endif
out SPDR,temp
;fall thru
-spi_wait:
+spi_wait:
sbism8 SPSR,SPIF
rjmp spi_wait
ret
-
+
;------------------------------------------------
-; Wait for card ready
-; return 1:OK, 0:Timeout
+; Wait for card ready
+; return 1:OK, 0:Timeout
mmcWaitReady:
push temp2
brne mmc_wrl ;tmp is 0 here
mmc_wrbreak:
- pop temp2
+ pop temp2
tst temp ;set flags
ret
ret
;------------------------------------------------
-; Select the card and wait for ready
+; Select the card and wait for ready
; return 255:Successful, 0:Timeout
mmcSelect:
breq mmcDeselect ;return via Deselect
sbr temp,255
ret
-
+
;------------------------------------------------
-; Send a command packet to MMC
+; Send a command packet to MMC
; temp2: Command
; yh..xl: Argument
; return:
sbrs temp2,7
rjmp mmc_cmddo
-; ACMD<n> is the command sequence of CMD55-CMD<n>
-
+; ACMD<n> is the command sequence of CMD55-CMD<n>
+
push yh
push yl
push xh
cpi temp,2
brlo mmc_cmddo ; fall thru, if (retval <= 1)
-
+
tst temp
ret ; else return error
ldi temp,0xFF
rjmp mmc_cmdexit
-
+
; Send command packet
mmc_cmd_p:
rcall spi_wait
out SPDR,xl
rcall spi_wait
-
+
ldi temp,0x95 ;CRC for CMD0(0)
cpi temp2,CMD0
breq mmc_cmdxcrc
- ldi temp,0x87 ;CRC for CMD8(0x1AA)
+ ldi temp,0x87 ;CRC for CMD8(0x1AA)
cpi temp2,CMD8
breq mmc_cmdxcrc
ldi temp,0x01 ;Dummy CRC + Stop
cpi temp2,CMD12 ; Skip a stuff byte when stop reading
brne mmc_cmdres
rcall spi_rcvr
-
+
; Wait for a valid response in timeout of 10 attempts
mmc_cmdres:
.endif
tst temp ;set flags
ret
-
+
;------------------------------------------------
; Send command and receive ocr response
; temp2: Command, zl: expected cmd response
; Initialize MMC/SD card
mmcInit:
-.if MMC_DEBUG
+.if MMC_DEBUG
printnewline
printstring "mmcInit "
.endif
cpi temp,1
breq mmci_1
rjmp mmci_lend
-mmci_1:
+mmci_1:
ldi zh,10 ;Initialization timeout of 1000 ms.
ldi temp,100
sts delay_timer1,temp
; The card can work at vdd range of 2.7-3.6V.
; Wait for leaving idle state (ACMD41 with HCS bit).
-
+
ldi temp2,ACMD41
ldi yh,0x40
ldi yl,0
rcall mmc_timeout_1s
brne mmci_v2l2
rjmp mmci_sdv2end
-
+
; Check CCS bit in the OCR
mmci_ccc:
ldi temp2,CMD58
mmci_sdv2end:
rjmp mmci_lend
-
+
; SDv1 or MMCv3
mmci_sdv1:
ldi temp2,ACMD41
ldiw y,0
movw x,y
- rcall mmcCmd
+ rcall mmcCmd
cpi temp,2
brsh mmci_mmcv3
sbr temp3,CT_SD1 ;SDv1
rcall mmc_timeout_1s
brne mmci_v1_l
rjmp mmci_lend ;Timeout
-
+
; Set R/W block length to 512
mmci_v1_2:
- ldi temp2,CMD16
+ ldi temp2,CMD16
ldiw x,512
rcall mmcCmd
breq mmci_lend
ldi temp3,0
-
+
mmci_lend:
sts mmcCardType,temp3
rcall mmcDeselect
-
+
; Initialization succeded?
lds temp,mmcStat
spi_disable
ret
-
+
;--------------------------------------------------------------
.equ MMC_RDOP = 0 ;Read Operation
printnewline
printstring "mmcRdWord "
.endif
- ldi temp,(1<<MMC_RDOP) | (1<<MMC_RDWORD)
+ ldi temp,(1<<MMC_RDOP) | (1<<MMC_RDWORD)
rjmp mmc_rw_common
mmcWriteSect:
ldi temp2,RES_NOTRDY
sbrc temp,log2(MMCST_NOINIT)
rjmp mmc_rwexit_2
-
+
spi_clkfast
lds temp,mmcCardType
sbrs temp,log2(CT_BLOCK)
rcall mul_yx_512 ;Convert to byte address (*512)
-
+
sbrc temp3,MMC_RDOP
ldi temp2,CMD17
sbrs temp3,MMC_RDOP
mmc_rcv_start:
.if MMC_DEBUG > 1
- cpi temp,0xFE ;If not valid data token,
+ cpi temp,0xFE ;If not valid data token,
breq mmc_rcv_dbg1
printstring "Token: "
lcall printhex
printstring " "
mmc_rcv_dbg1:
.endif
- cpi temp,0xFE ;If not valid data token,
+ cpi temp,0xFE ;If not valid data token,
breq mmc_rw_2
rjmp mmc_rwexit_error
mmc_rw_2:
rjmp mmc_rcv_readloop
mmc_rcv_rle:
- st z+,temp ;Store last byte in buffer
+ st z+,temp ;Store last byte in buffer
mmc_rcv_rlend:
.if MMC_DEBUG > 3
printnewline
.endif
rcall spi_wait ;while SPI module shifts in crc part1.
rcall spi_rcvr ;Read second crc.
-
+
ldi temp2,RES_OK ;Return success
rjmp mmc_rwexit
-
+
;-------------------------------------------------------------------------------
; Send a data packet to MMC
out SPDR,temp
sbiw yl,1
brne mmc_x_loop
-
+
rcall spi_wait
ldi temp,0xFF ;dummy crc
rcall spi_xmit
;--------------------------------------------------------------
; vim:set ts=8 noet nowrap
-