#define CMD55 (55) /* APP_CMD */
#define CMD58 (58) /* READ_OCR */
-/* Disk Status Bits (DSTATUS) */
+/* Disk Status Bits (masks) (DSTATUS) */
#define MMCST_NOINIT 0x01 /* Drive not initialized */
#define MMCST_NODISK 0x02 /* No medium in the drive */
#define MMCST_PROTECT 0x04 /* Write protected */
-/* Card type flags (CardType) */
+/* Card type flags (masks) (CardType) */
#define CT_MMC 0x01 /* MMC ver 3 */
#define CT_SD1 0x02 /* SD ver 1 */
#define CT_SD2 0x04 /* SD ver 2 */
#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
rjmp spi_rcvr_l
in temp,SPDR
.if MMC_DEBUG > 2
- push temp
printstring "<"
rcall printhex
printstring " "
- pop temp
.endif
ret
.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:
+; temp: 0 = ok, no error
+; z-flag 1 = ok, no error
+;
mmcCmd:
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:
- ldi temp,10
- mov _tmp1,temp
+ push temp2
+ ldi temp2,10
mmc_cmdrl:
rcall spi_rcvr
sbrs temp,7
rjmp mmc_cmdexit
- dec _tmp1
+ dec temp2
brne mmc_cmdrl
; Return with response value
mmc_cmdexit:
+ pop temp2
.if MMC_DEBUG
printstring " CMDRes: "
rcall printhex
.endif
tst temp ;set flags
ret
-
+
;------------------------------------------------
; Send command and receive ocr response
; temp2: Command, zl: expected cmd response
lds temp,delay_timer1
tst temp
brne mmc_ttex
- dec temp4
+ dec zh
breq mmc_ttex
ldi temp,100
sts delay_timer1,temp
; 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:
- ldi temp4,10 ;Initialization timeout of 1000 ms.
+mmci_1:
+ ldi zh,10 ;Initialization timeout of 1000 ms.
ldi temp,100
sts delay_timer1,temp
ldi temp2,CMD8
; 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
printstring " CT: "
push temp
lds temp,mmcCardType
- rcall printhex
+ lcall printhex
pop temp
printstring " InitRes: "
- rcall printhex
+ lcall printhex
printstring " "
.endif
spi_disable
ret
-
-
+
+;--------------------------------------------------------------
+
+ .equ MMC_RDOP = 0 ;Read Operation
+ .equ MMC_RDWORD = 1 ;Read Word (FAT entry)
+
;--------------------------------------------------------------
-; Read sector
-; z: Pointer to the data buffer to store read data
-; yh..xl: Start sector number (LBA)
mmcReadSect:
+
.if MMC_DEBUG > 1
printnewline
printstring "mmcRdSect "
.endif
- ldiw z,hostbuf ;for now
+ ldi temp,(1<<MMC_RDOP)
+ rjmp mmc_rw_common
+
+mmcReadWord:
+
+.if (MMC_DEBUG > 1) || (MMC_DEBUG_RDW > 0)
+ printnewline
+ printstring "mmcRdWord "
+.endif
+ ldi temp,(1<<MMC_RDOP) | (1<<MMC_RDWORD)
+ rjmp mmc_rw_common
+
+mmcWriteSect:
+
+.if MMC_DEBUG > 1
+ printnewline
+ printstring "mmcWrSect "
+.endif
+ ldi temp,0
+
+mmc_rw_common:
+ push temp3
+ mov temp3,temp
+ lds temp,mmcStat
+ ldi temp2,RES_NOTRDY
+ sbrc temp,log2(MMCST_NOINIT)
+ rjmp mmc_rwexit_2
- lds _tmp0,mmcStat
- ldi temp,RES_NOTRDY
- sbrc _tmp0,MMCST_NOINIT
- ret
-
spi_clkfast
lds temp,mmcCardType
sbrs temp,log2(CT_BLOCK)
rcall mul_yx_512 ;Convert to byte address (*512)
- ldi temp2,CMD17
+ sbrc temp3,MMC_RDOP
+ ldi temp2,CMD17
+ sbrs temp3,MMC_RDOP
+ ldi temp2,CMD24
rcall mmcCmd
- ldi temp2,RES_ERROR
- brne mmc_rdex
-
+ breq mmc_rw_1
+ rjmp mmc_rwexit_error
+
+mmc_rw_1:
+ ldiw y,512
+ sbrs temp3,MMC_RDOP
+ rjmp mmc_wroper
+
+;-------------------------------------------------------------------------------
; Receive a data packet from MMC
- ldiw y,512 ;Number of bytes to tranfer
ldi temp,200 ;Wait for data packet in timeout of 200ms.
sts delay_timer1,temp
mmc_rcv_wl:
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: "
- rcall printhex
+ lcall printhex
printstring " "
mmc_rcv_dbg1:
.endif
- cpi temp,0xFE ;If not valid data token,
- brne mmc_rdex
-
+ cpi temp,0xFE ;If not valid data token,
+ breq mmc_rw_2
+ rjmp mmc_rwexit_error
+mmc_rw_2:
+
rcall spi_rcvr ;Shift in first byte.
.if MMC_DEBUG > 3
printnewline
- rcall printhex
+ lcall printhex
printstring " "
.endif
out SPDR,_255 ;Start shift in next byte.
-mmc_rcv_rl:
- sbiw yl,1
- breq mmc_rcv_rle
- st z+,temp
- spi_waitm
- in temp,SPDR
-.if MMC_DEBUG > 3
- rcall printhex
- printstring " "
-.endif
- out SPDR,_255
- rjmp mmc_rcv_rl
-
-mmc_rcv_rle:
- st z+,temp ;Store last byte in buffer
-.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
-mmc_rdex:
- rcall mmcDeselect
- spi_disable
- mov temp,temp2
-.if MMC_DEBUG > 1
- printstring "RdSectRes: "
- rcall printhex
- printstring " "
-.endif
- ret
+ sbrs temp3,MMC_RDWORD
+ rjmp mmc_rcv_readloop
-;--------------------------------------------------------------
-; Read word
-; Read Word to ZL,ZH at given ZL/ZH Offset
-; Needed for reading a single FAT16 entry without killing the
-; entries in hostbuffer...
-;
-; in zh,zl: Pointer to word within the sector to read
-; in yh..xl: Start sector number (LBA)
-; out zh,zl: Word thats been read
+; discard x-1 bytes
-mmcReadWord:
-.if MMC_DEBUG > 1
- printnewline
- printstring "mmcRdWord "
-.endif
- lds _tmp0,mmcStat
- ldi temp,RES_NOTRDY
- sbrc _tmp0,MMCST_NOINIT
- ret
-
- spi_clkfast
- lds temp,mmcCardType
- sbrs temp,log2(CT_BLOCK)
- rcall mul_yx_512 ;Convert to byte address (*512)
-
- ldi temp2,CMD17
- rcall mmcCmd
- ldi temp2,RES_ERROR
- brne mmc_rdexw
-
-; Receive a data packet from MMC
-
- ldiw y,512 ;Number of bytes to tranfer
- ldi temp,200 ;Wait for data packet in timeout of 200ms.
- sts delay_timer1,temp
-mmc_rcvw_wl:
- rcall spi_rcvr
- cp temp,_255
- brne mmc_rcvw_start
- lds temp2,delay_timer1
- cpi temp2,0
- brne mmc_rcvw_wl
-mmc_rcvw_start:
- cpi temp,0xFE ;If not valid data token,
- ldi temp2,RES_ERROR
- brne mmc_rdexw
-
- rcall spi_rcvr ;Shift in first byte.
- out SPDR,_255 ;Start shift in next byte.
mmc_rcvw_rl:
sbiw yl,1
- breq mmc_rcvw_rle
+ breq mmc_rcv_rlend
cp zl,_0
cpc zh,_0
breq mmc_rcvw_sto
out SPDR,_255
rjmp mmc_rcvw_rl
+; read next two bytes
+
mmc_rcvw_sto:
mov zl,temp
spi_waitm
out SPDR,_255
mov zh,temp
+.if MMC_DEBUG_RDW > 0
+ movw temp,z
+ lcall printhexw
+ printstring " "
+.endif
+
+; discard the rest
+
mmc_rcvw_rl2:
sbiw yl,1
- breq mmc_rcvw_rle
+ breq mmc_rcv_rlend
spi_waitm
in temp,SPDR
out SPDR,_255
rjmp mmc_rcvw_rl2
-mmc_rcvw_rle:
- rcall spi_wait ; while SPI module shifts in crc part1.
- rcall spi_rcvr ;Read second crc.
-
- ldi temp2,RES_OK ;Return success
-mmc_rdexw:
- rcall mmcDeselect
- spi_disable
- mov temp,temp2
-.if MMC_DEBUG > 1
- printstring "RdWordRes: "
- rcall printhex
- printstring " "
-.endif
- ret
-;--------------------------------------------------------------
-; Write sector
-; z: Pointer to the data to be written
-; yh..xl: Sector number (LBA)
+; read sector, store in buffer
-mmcWriteSect:
-.if MMC_DEBUG > 1
+mmc_rcv_readloop:
+ sbiw yl,1
+ breq mmc_rcv_rle
+ st z+,temp
+ spi_waitm
+ in temp,SPDR
+.if MMC_DEBUG > 3
+ lcall printhex
+ printstring " "
+.endif
+ out SPDR,_255
+ rjmp mmc_rcv_readloop
+
+mmc_rcv_rle:
+ st z+,temp ;Store last byte in buffer
+mmc_rcv_rlend:
+.if MMC_DEBUG > 3
printnewline
- printstring "mmcWrSect "
.endif
- ldiw z,hostbuf ;for now
-
- lds _tmp0,mmcStat
- ldi temp,RES_NOTRDY
- sbrc _tmp0,MMCST_NOINIT
- ret
-
- spi_clkfast
- lds temp,mmcCardType
- sbrs temp,log2(CT_BLOCK)
- rcall mul_yx_512 ;Convert to byte address (*512)
+ rcall spi_wait ;while SPI module shifts in crc part1.
+ rcall spi_rcvr ;Read second crc.
- ldi temp2,CMD24
- rcall mmcCmd
- brne mmc_wrexer
-
+ ldi temp2,RES_OK ;Return success
+ rjmp mmc_rwexit
+
+
+;-------------------------------------------------------------------------------
; Send a data packet to MMC
+mmc_wroper:
+
.if MMC_DEBUG > 2
; printnewline
printstring "mmcXMIT "
.endif
rcall mmcWaitReady
- breq mmc_wrexer
+ breq mmc_rwexit_error
ldi temp,0xFE ;Data token
out SPDR,temp
- ldiw y,512
mmc_x_loop:
ld temp,z+
spi_waitm
out SPDR,temp
sbiw yl,1
brne mmc_x_loop
-
+
rcall spi_wait
ldi temp,0xFF ;dummy crc
rcall spi_xmit
rcall spi_rcvr
.if MMC_DEBUG > 2
printstring "XMITRes: "
- rcall printhex
+ lcall printhex
printstring " "
.endif
andi temp,0x1F ;If not accepted, return with error
cpi temp,0x05
ldi temp2,RES_OK ;Return success
- breq mmc_wrex
+ breq mmc_rwexit
-mmc_wrexer:
- ldi temp,RES_ERROR
-mmc_wrex:
+mmc_rwexit_error:
+ ldi temp2,RES_ERROR
+mmc_rwexit:
rcall mmcDeselect
spi_disable
+mmc_rwexit_2:
mov temp,temp2
+
.if MMC_DEBUG > 1
- printstring "WrSectRes: "
- rcall printhex
+ sbrc temp3,MMC_RDOP
+ rjmp mmc_dbg_rder
+
+ printstring "WrSectRes: "
+ rjmp mmc_dbg_rwerex
+
+mmc_dbg_rder:
+ sbrc temp3,MMC_RDWORD
+ rjmp mmc_dbg_rdwder
+ printstring "RdSectRes: "
+ rjmp mmc_dbg_rwerex
+
+mmc_dbg_rdwder:
+ printstring "RdWordRes: "
+mmc_dbg_rwerex:
+ lcall printhex
printstring " "
.endif
+ pop temp3
ret
;--------------------------------------------------------------
; vim:set ts=8 noet nowrap
-