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 (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 (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 ;------------------------------------------------
127 ;------------------------------------------------
128 ; Multiply 32 bit value in yh,yl,xh,xl by 512
140 ;------------------------------------------------
156 ;------------------------------------------------
170 ;------------------------------------------------
171 ; Wait for card ready
172 ; return 1:OK, 0:Timeout
176 ldi temp2,2 ;Wait for ready in timeout of 500ms.
179 sts delay_timer2,_255
188 lds temp,delay_timer2
192 brne mmc_wrl ;tmp is 0 here
200 ;------------------------------------------------
201 ; Deselect the card and release SPI bus
205 sbi P_MMC_CS,mmc_cs ; CS high
210 ;------------------------------------------------
211 ; Select the card and wait for ready
212 ; return 255:Successful, 0:Timeout
215 cbi P_MMC_CS,mmc_cs ; CS low
217 breq mmcDeselect ;return via Deselect
222 ;------------------------------------------------
223 ; Send a command packet to MMC
231 ; ACMD<n> is the command sequence of CMD55-CMD<n>
249 brlo mmc_cmddo ; fall thru, if (retval <= 1)
252 ret ; else return error
254 ; Select the card and wait for ready
263 printstring "mmcCMD: "
283 ; Send command packet
299 ldi temp,0x95 ;CRC for CMD0(0)
302 ldi temp,0x87 ;CRC for CMD8(0x1AA)
305 ldi temp,0x01 ;Dummy CRC + Stop
313 ; Receive command response
315 cpi temp2,CMD12 ; Skip a stuff byte when stop reading
319 ; Wait for a valid response in timeout of 10 attempts
331 ; Return with response value
335 printstring " CMDRes: "
338 rcall uart_wait_empty
343 ;------------------------------------------------
344 ; Check if 1 sec timeout
345 ; return Z-Flag set, if timeout
348 lds temp,delay_timer1
354 sts delay_timer1,temp
359 ;------------------------------------------------
361 ;------------------------------------------------
363 ;------------------------------------------------
364 ; Initialize MMC/SD card
369 printstring "mmcInit "
371 lds temp,mmcStat ;Set 'NO INIT' status
372 sbr temp,MMCST_NOINIT
379 dec temp2 ;80 dummy clocks
382 ldi temp3,0 ;Card type
386 rcall mmcCmd ;Enter Idle state
391 ldi temp4,10 ;Initialization timeout of 1000 ms.
393 sts delay_timer1,temp
402 ; Get trailing return value of R7 response
415 cpc temp,xl ;Reuse 0xAA value in xl
418 ; The card can work at vdd range of 2.7-3.6V.
419 ; Wait for leaving idle state (ACMD41 with HCS bit).
433 ; Check CCS bit in the OCR
465 sbr temp3,CT_SD1 ;SDv1
469 sbr temp3,CT_MMC ;MMCv3
472 ; Wait for leaving idle state
478 rjmp mmci_lend ;Timeout
480 ; Set R/W block length to 512
489 sts mmcCardType,temp3
492 ; Initialization succeded?
497 cbr temp,MMCST_NOINIT ;Yes, clear 'NO INIT' status
508 printstring " InitRes: "
517 ;--------------------------------------------------------------
519 ; z: Pointer to the data buffer to store read data
520 ; yh..xl: Start sector number (LBA)
525 printstring "mmcRdSect "
527 ldiw z,hostbuf ;for now
531 sbrc _tmp0,MMCST_NOINIT
536 sbrs temp,log2(CT_BLOCK)
537 rcall mul_yx_512 ;Convert to byte address (*512)
544 ; Receive a data packet from MMC
546 ldiw y,512 ;Number of bytes to tranfer
547 ldi temp,200 ;Wait for data packet in timeout of 200ms.
548 sts delay_timer1,temp
553 lds _tmp0,delay_timer1
557 printstring "TIMEOUT "
563 cpi temp,0xFE ;If not valid data token,
565 printstring "Token: "
570 cpi temp,0xFE ;If not valid data token,
573 rcall spi_rcvr ;Shift in first byte.
579 out SPDR,_255 ;Start shift in next byte.
594 st z+,temp ;Store last byte in buffer
598 rcall spi_wait ; while SPI module shifts in crc part1.
599 rcall spi_rcvr ;Read second crc.
601 ldi temp2,RES_OK ;Return success
607 printstring "RdSectRes: "
614 ;--------------------------------------------------------------
616 ; TODO: Read Word to ZL,ZH at given ZL/ZH Offset
617 ; Need for reading of single FAT16 Entrys without killing the
618 ; Entrys in hostbuffer...
620 ; in zh,zl: Pointer to Word within the Sector to read
621 ; in yh..xl: Start sector number (LBA)
622 ; out zh,zl : word thats been read
627 printstring "mmcRdWord "
631 sbrc _tmp0,MMCST_NOINIT
636 sbrs temp,log2(CT_BLOCK)
637 rcall mul_yx_512 ;Convert to byte address (*512)
644 ; Receive a data packet from MMC
646 ldiw y,512 ;Number of bytes to tranfer
647 ldi temp,200 ;Wait for data packet in timeout of 200ms.
648 sts delay_timer1,temp
653 lds temp2,delay_timer1
657 cpi temp,0xFE ;If not valid data token,
661 rcall spi_rcvr ;Shift in first byte.
662 out SPDR,_255 ;Start shift in next byte.
691 rcall spi_wait ; while SPI module shifts in crc part1.
692 rcall spi_rcvr ;Read second crc.
694 ldi temp2,RES_OK ;Return success
700 printstring "RdWordRes: "
706 ;--------------------------------------------------------------
708 ; z: Pointer to the data to be written
709 ; yh..xl: Sector number (LBA)
714 printstring "mmcWrSect "
716 ldiw z,hostbuf ;for now
720 sbrc _tmp0,MMCST_NOINIT
725 sbrs temp,log2(CT_BLOCK)
726 rcall mul_yx_512 ;Convert to byte address (*512)
732 ; Send a data packet to MMC
736 printstring "mmcXMIT "
741 ldi temp,0xFE ;Data token
752 ldi temp,0xFF ;dummy crc
757 printstring "XMITRes: "
761 andi temp,0x1F ;If not accepted, return with error
763 ldi temp2,RES_OK ;Return success
773 printstring "WrSectRes: "
779 ;--------------------------------------------------------------
780 ; vim:set ts=8 noet nowrap