3 ; Copyright (C) 2010 Leo C.
5 ; This file is part of avrcpm.
7 ; avrcpm is free software: you can redistribute it and/or modify it
8 ; under the terms of the GNU General Public License as published by
9 ; the Free Software Foundation, either version 3 of the License, or
10 ; (at your option) any later version.
12 ; avrcpm is distributed in the hope that it will be useful,
13 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ; GNU General Public License for more details.
17 ; You should have received a copy of the GNU General Public License
18 ; along with avrcpm. If not, see <http://www.gnu.org/licenses/>.
23 /* Definitions for MMC/SDC command */
24 #define CMD0 (0) /* GO_IDLE_STATE */
25 #define CMD1 (1) /* SEND_OP_COND (MMC) */
26 #define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
27 #define CMD8 (8) /* SEND_IF_COND */
28 #define CMD9 (9) /* SEND_CSD */
29 #define CMD10 (10) /* SEND_CID */
30 #define CMD12 (12) /* STOP_TRANSMISSION */
31 #define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
32 #define CMD16 (16) /* SET_BLOCKLEN */
33 #define CMD17 (17) /* READ_SINGLE_BLOCK */
34 #define CMD18 (18) /* READ_MULTIPLE_BLOCK */
35 #define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
36 #define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
37 #define CMD24 (24) /* WRITE_BLOCK */
38 #define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
39 #define CMD55 (55) /* APP_CMD */
40 #define CMD58 (58) /* READ_OCR */
42 /* Disk Status Bits (masks) (DSTATUS) */
43 #define MMCST_NOINIT 0x01 /* Drive not initialized */
44 #define MMCST_NODISK 0x02 /* No medium in the drive */
45 #define MMCST_PROTECT 0x04 /* Write protected */
47 /* Card type flags (masks) (CardType) */
48 #define CT_MMC 0x01 /* MMC ver 3 */
49 #define CT_SD1 0x02 /* SD ver 1 */
50 #define CT_SD2 0x04 /* SD ver 2 */
51 #define CT_SDC (CT_SD1|CT_SD2) /* SD */
52 #define CT_BLOCK 0x08 /* Block addressing */
54 #define RES_OK 0 /* 0: Successful */
55 #define RES_ERROR 1 /* 1: R/W Error */
56 #define RES_WRPRT 2 /* 2: Write Protected */
57 #define RES_NOTRDY 3 /* 3: Not Ready */
58 #define RES_PARERR 4 /* 4: Invalid Parameter */
61 #define SPI_MODE_0 (0<<CPOL)|(0<<CPHA)
62 #define SPI_MODE_1 (0<<CPOL)|(1<<CPHA)
63 #define SPI_MODE_2 (1<<CPOL)|(0<<CPHA)
64 #define SPI_MODE_3 (1<<CPOL)|(1<<CPHA)
65 #define SPI_MODE SPI_MODE_0
67 ;------------------------------------------------
71 printstring "SPI_CLK_SLOW "
73 ldi temp,SPI_MODE|(1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0) ;clk/128
78 ;------------------------------------------------
82 printstring "SPI_CLK_FAST "
84 ldi temp,SPI_MODE|(1<<SPE)|(1<<MSTR) ;clk/4
94 ;------------------------------------------------
98 printstring "SPI_DISABLE "
104 ;------------------------------------------------
112 ;------------------------------------------------
124 ;------------------------------------------------
125 ; Multiply 32 bit value in yh,yl,xh,xl by 512
137 ;------------------------------------------------
151 ;------------------------------------------------
165 ;------------------------------------------------
166 ; Wait for card ready
167 ; return 1:OK, 0:Timeout
171 ldi temp2,2 ;Wait for ready in timeout of 500ms.
174 sts delay_timer2,_255
183 lds temp,delay_timer2
187 brne mmc_wrl ;tmp is 0 here
195 ;------------------------------------------------
196 ; Deselect the card and release SPI bus
200 sbi P_MMC_CS,mmc_cs ; CS high
205 ;------------------------------------------------
206 ; Select the card and wait for ready
207 ; return 255:Successful, 0:Timeout
210 cbi P_MMC_CS,mmc_cs ; CS low
212 breq mmcDeselect ;return via Deselect
217 ;------------------------------------------------
218 ; Send a command packet to MMC
222 ; temp: 0 = ok, no error
223 ; z-flag 1 = ok, no error
230 ; ACMD<n> is the command sequence of CMD55-CMD<n>
248 brlo mmc_cmddo ; fall thru, if (retval <= 1)
251 ret ; else return error
253 ; Select the card and wait for ready
262 printstring "mmcCMD: "
282 ; Send command packet
298 ldi temp,0x95 ;CRC for CMD0(0)
301 ldi temp,0x87 ;CRC for CMD8(0x1AA)
304 ldi temp,0x01 ;Dummy CRC + Stop
312 ; Receive command response
314 cpi temp2,CMD12 ; Skip a stuff byte when stop reading
318 ; Wait for a valid response in timeout of 10 attempts
330 ; Return with response value
335 printstring " CMDRes: "
338 rcall uart_wait_empty
343 ;------------------------------------------------
344 ; Send command and receive ocr response
345 ; temp2: Command, zl: expected cmd response
347 ; return: yh..xl: ocr, z flag == 1, if return from mmcCmd was ok.
356 ; Get trailing return value of R7 response
359 ldiw z,0x1a ;memory address of xl
369 ;------------------------------------------------
370 ; Check if 1 sec timeout
371 ; return Z-Flag set, if timeout
374 lds temp,delay_timer1
380 sts delay_timer1,temp
385 ;------------------------------------------------
387 ;------------------------------------------------
389 ;------------------------------------------------
390 ; Initialize MMC/SD card
395 printstring "mmcInit "
397 lds temp,mmcStat ;Set 'NO INIT' status
398 sbr temp,MMCST_NOINIT
405 dec temp2 ;80 dummy clocks
408 ldi temp3,0 ;Card type
412 rcall mmcCmd ;Enter Idle state
417 ldi zh,10 ;Initialization timeout of 1000 ms.
419 sts delay_timer1,temp
426 brne mmci_sdv1 ;SDv2?
433 ; The card can work at vdd range of 2.7-3.6V.
434 ; Wait for leaving idle state (ACMD41 with HCS bit).
448 ; Check CCS bit in the OCR
473 sbr temp3,CT_SD1 ;SDv1
477 sbr temp3,CT_MMC ;MMCv3
480 ; Wait for leaving idle state
486 rjmp mmci_lend ;Timeout
488 ; Set R/W block length to 512
497 sts mmcCardType,temp3
500 ; Initialization succeded?
505 cbr temp,MMCST_NOINIT ;Yes, clear 'NO INIT' status
516 printstring " InitRes: "
524 ;--------------------------------------------------------------
526 .equ MMC_RDOP = 0 ;Read Operation
527 .equ MMC_RDWORD = 1 ;Read Word (FAT entry)
529 ;--------------------------------------------------------------
535 printstring "mmcRdSect "
537 ldi temp3,(1<<MMC_RDOP)
544 printstring "mmcRdWord "
546 ldi temp3,(1<<MMC_RDOP) | (1<<MMC_RDWORD)
553 printstring "mmcWrSect "
560 sbrc temp,log2(MMCST_NOINIT)
565 sbrs temp,log2(CT_BLOCK)
566 rcall mul_yx_512 ;Convert to byte address (*512)
574 rjmp mmc_rwexit_error
577 ldiw y,hostbuf ;aarrrgh
578 sbrs temp3,MMC_RDWORD
584 ;-------------------------------------------------------------------------------
585 ; Receive a data packet from MMC
587 ldi temp,200 ;Wait for data packet in timeout of 200ms.
588 sts delay_timer1,temp
593 lds _tmp0,delay_timer1
597 printstring "TIMEOUT "
603 cpi temp,0xFE ;If not valid data token,
605 printstring "Token: "
610 cpi temp,0xFE ;If not valid data token,
612 rjmp mmc_rwexit_error
615 rcall spi_rcvr ;Shift in first byte.
621 out SPDR,_255 ;Start shift in next byte.
623 sbrs temp3,MMC_RDWORD
624 rjmp mmc_rcv_readloop
641 ; read next two bytes
660 ; read sector, store in buffer
673 rjmp mmc_rcv_readloop
676 st z+,temp ;Store last byte in buffer
681 rcall spi_wait ;while SPI module shifts in crc part1.
682 rcall spi_rcvr ;Read second crc.
684 ldi temp2,RES_OK ;Return success
688 ;-------------------------------------------------------------------------------
689 ; Send a data packet to MMC
695 printstring "mmcXMIT "
698 breq mmc_rwexit_error
700 ldi temp,0xFE ;Data token
710 ldi temp,0xFF ;dummy crc
715 printstring "XMITRes: "
719 andi temp,0x1F ;If not accepted, return with error
721 ldi temp2,RES_OK ;Return success
736 printstring "WrSectRes: "
740 sbrc temp3,MMC_RDWORD
742 printstring "RdSectRes: "
746 printstring "RdWordRes: "
753 ;--------------------------------------------------------------
754 ; vim:set ts=8 noet nowrap