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 */
60 ;------------------------------------------------
64 printstring "SPI_CLK_SLOW "
66 ldi temp,(1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0) ;clk/128
71 ;------------------------------------------------
75 printstring "SPI_CLK_FAST "
77 ldi temp,(1<<SPE)|(1<<MSTR) ;clk/4
87 ;------------------------------------------------
91 printstring "SPI_DISABLE "
97 ;------------------------------------------------
105 ;------------------------------------------------
120 ;------------------------------------------------
121 ; Multiply 32 bit value in yh,yl,xh,xl by 512
133 ;------------------------------------------------
149 ;------------------------------------------------
163 ;------------------------------------------------
164 ; Wait for card ready
165 ; return 1:OK, 0:Timeout
169 ldi temp2,2 ;Wait for ready in timeout of 500ms.
172 sts delay_timer2,_255
181 lds temp,delay_timer2
185 brne mmc_wrl ;tmp is 0 here
193 ;------------------------------------------------
194 ; Deselect the card and release SPI bus
198 sbi P_MMC_CS,mmc_cs ; CS high
203 ;------------------------------------------------
204 ; Select the card and wait for ready
205 ; return 255:Successful, 0:Timeout
208 cbi P_MMC_CS,mmc_cs ; CS low
210 breq mmcDeselect ;return via Deselect
215 ;------------------------------------------------
216 ; Send a command packet to MMC
224 ; ACMD<n> is the command sequence of CMD55-CMD<n>
242 brlo mmc_cmddo ; fall thru, if (retval <= 1)
245 ret ; else return error
247 ; Select the card and wait for ready
256 printstring "mmcCMD: "
276 ; Send command packet
292 ldi temp,0x95 ;CRC for CMD0(0)
295 ldi temp,0x87 ;CRC for CMD8(0x1AA)
298 ldi temp,0x01 ;Dummy CRC + Stop
306 ; Receive command response
308 cpi temp2,CMD12 ; Skip a stuff byte when stop reading
312 ; Wait for a valid response in timeout of 10 attempts
324 ; Return with response value
328 printstring " CMDRes: "
331 rcall uart_wait_empty
336 ;------------------------------------------------
337 ; Check if 1 sec timeout
338 ; return Z-Flag set, if timeout
341 lds temp,delay_timer1
347 sts delay_timer1,temp
352 ;------------------------------------------------
354 ;------------------------------------------------
356 ;------------------------------------------------
357 ; Initialize MMC/SD card
362 printstring "mmcInit "
364 lds temp,mmcStat ;Set 'NO INIT' status
365 sbr temp,MMCST_NOINIT
372 dec temp2 ;80 dummy clocks
375 ldi temp3,0 ;Card type
379 rcall mmcCmd ;Enter Idle state
384 ldi temp4,10 ;Initialization timeout of 1000 ms.
386 sts delay_timer1,temp
395 ; Get trailing return value of R7 response
408 cpc temp,xl ;Reuse 0xAA value in xl
411 ; The card can work at vdd range of 2.7-3.6V.
412 ; Wait for leaving idle state (ACMD41 with HCS bit).
426 ; Check CCS bit in the OCR
458 sbr temp3,CT_SD1 ;SDv1
462 sbr temp3,CT_MMC ;MMCv3
465 ; Wait for leaving idle state
471 rjmp mmci_lend ;Timeout
473 ; Set R/W block length to 512
482 sts mmcCardType,temp3
485 ; Initialization succeded?
490 cbr temp,MMCST_NOINIT ;Yes, clear 'NO INIT' status
501 printstring " InitRes: "
510 ;--------------------------------------------------------------
512 ; z: Pointer to the data buffer to store read data
513 ; yh..xl: Start sector number (LBA)
518 printstring "mmcRdSect "
520 ldiw z,hostbuf ;for now
524 sbrc _tmp0,MMCST_NOINIT
529 sbrs temp,log2(CT_BLOCK)
530 rcall mul_yx_512 ;Convert to byte address (*512)
537 ; Receive a data packet from MMC
539 ldiw y,512 ;Number of bytes to tranfer
540 ldi temp,200 ;Wait for data packet in timeout of 200ms.
541 sts delay_timer1,temp
546 lds _tmp0,delay_timer1
550 printstring "TIMEOUT "
556 cpi temp,0xFE ;If not valid data token,
558 printstring "Token: "
563 cpi temp,0xFE ;If not valid data token,
566 rcall spi_rcvr ;Shift in first byte.
567 out SPDR,_255 ;Start shift in next byte.
578 st z+,temp ;Store last byte in buffer
579 rcall spi_wait ; while SPI module shifts in crc part1.
580 rcall spi_rcvr ;Read second crc.
582 ldi temp2,RES_OK ;Return success
588 printstring "RdSectRes: "
595 ;--------------------------------------------------------------
597 ; TODO: Read Word to ZL,ZH at given ZL/ZH Offset
598 ; Need for reading of single FAT16 Entrys without killing the
599 ; Entrys in hostbuffer...
601 ; in zh,zl: Pointer to Word within the Sector to read
602 ; in yh..xl: Start sector number (LBA)
603 ; out xh,xl : word thats been read
608 printstring "mmcRdWord "
612 sbrc _tmp0,MMCST_NOINIT
617 sbrs temp,log2(CT_BLOCK)
618 rcall mul_yx_512 ;Convert to byte address (*512)
625 ; Receive a data packet from MMC
627 ldiw y,512 ;Number of bytes to tranfer
628 ldi temp,200 ;Wait for data packet in timeout of 200ms.
629 sts delay_timer1,temp
634 lds temp2,delay_timer1
638 cpi temp,0xFE ;If not valid data token,
642 rcall spi_rcvr ;Shift in first byte.
643 out SPDR,_255 ;Start shift in next byte.
654 //st z+,temp ;Store last byte in buffer
655 rcall spi_wait ; while SPI module shifts in crc part1.
656 rcall spi_rcvr ;Read second crc.
658 ldi temp2,RES_OK ;Return success
664 printstring "RdWordRes: "
670 ;--------------------------------------------------------------
672 ; z: Pointer to the data to be written
673 ; yh..xl: Sector number (LBA)
678 printstring "mmcWrSect "
680 ldiw z,hostbuf ;for now
684 sbrc _tmp0,MMCST_NOINIT
689 sbrs temp,log2(CT_BLOCK)
690 rcall mul_yx_512 ;Convert to byte address (*512)
696 ; Send a data packet to MMC
700 printstring "mmcXMIT "
705 ldi temp,0xFE ;Data token
716 ldi temp,0xFF ;dummy crc
721 printstring "XMITRes: "
725 andi temp,0x1F ;If not accepted, return with error
727 ldi temp2,RES_OK ;Return success
737 printstring "WrSectRes: "
743 ;--------------------------------------------------------------
744 ; vim:set ts=8 noet nowrap