OSDN Git Service

V205
[fast-forth/master.git] / forthMSP430FR_SD_LowLvl.asm
1 ; -*- coding: utf-8 -*-
2 ; forthMSP430FR_SD_lowLvl.asm
3
4 ; Copyright (C) <2017>  <J.M. THOORENS>
5 ;
6 ; This program is free software: you can redistribute it and/or modify
7 ; it under the terms of the GNU General Public License as published by
8 ; the Free Software Foundation, either version 3 of the License, or
9 ; (at your option) any later version.
10 ;
11 ; This program is distributed in the hope that it will be useful,
12 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ; GNU General Public License for more details.
15 ;
16 ; You should have received a copy of the GNU General Public License
17 ; along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19
20
21 BytsPerSec      .equ 512
22
23 ; all sectors are computed as logical, then physically translated at last time by RW_Sector_CMD
24
25 sendCommandIdleRet                  ; <=== CMD0, CMD8, CMD55: W = 1 = R1 expected response = idle (forthMSP430FR_SD_INIT.asm)
26     MOV     #1,W                    ; expected R1 response (first byte of SPI R7) = 01h : idle state
27     JMP     sendCommand             ;
28
29 ; in SPI mode CRC is not required, but CMD frame must be ended with a stop bit
30 ; ==================================;
31 RW_Sector_CMD                       ;WX <=== CMD17 or CMD24 (read or write Sector CMD)
32 ; ==================================;
33     BIC.B   #SD_CS,&SD_CSOUT        ; set SD_CS low
34     BIT.B   #SD_CD,&SD_CDIN         ; test CD: memory card present ?
35     JZ      ComputePhysicalSector   ; yes
36     MOV     #COLD,PC                ; no: force COLD
37 ; ----------------------------------;
38 ComputePhysicalSector               ;
39 ; ----------------------------------; input = logical sector...
40     ADD     &BS_FirstSectorL,W      ;3
41     ADDC    &BS_FirstSectorH,X      ;3
42 ; ----------------------------------; ...output = physical sector
43 ;Compute CMD                        ;
44 ; ----------------------------------;
45     MOV     #1,&SD_CMD_FRM          ;3 $(01 00 xx xx xx CMD) set stop bit in CMD frame
46     CMP     #2,&FATtype             ;3 FAT32 ?          
47     JZ      FAT32_CMD               ;2 yes
48 FAT16_CMD                           ;  FAT16 : CMD17/24 byte address = Sector * BPB_BytsPerSec
49     ADD     W,W                     ;1 shift left one Sector
50     ADDC.B  X,X                     ;1
51     MOV     W,&SD_CMD_FRM+2         ;3 $(01 00 ll LL xx CMD)
52     MOV.B   X,&SD_CMD_FRM+4         ;3 $(01 00 ll LL hh CMD) 
53     JMP     WaitIdleBeforeSendCMD   ;
54 FAT32_CMD                           ;  FAT32 : CMD17/24 sector address
55     MOV.B   W,&SD_CMD_FRM+1         ;3 $(01 ll xx xx xx CMD)
56     SWPB    W                       ;1
57     MOV.B   W,&SD_CMD_FRM+2         ;3 $(01 ll LL xx xx CMD)
58     MOV.B   X,&SD_CMD_FRM+3         ;3 $(01 ll LL hh xx CMD)
59     SWPB    X                       ;1
60     MOV.B   X,&SD_CMD_FRM+4         ;3 $(01 ll LL hh HH CMD)
61 ; ==================================;
62 WaitIdleBeforeSendCMD               ; <=== CMD41, CMD1, CMD16 (forthMSP430FR_SD_INIT.asm)
63 ; ==================================;
64     CALL #SPI_GET                   ;
65     ADD.B   #1,W                    ; expected value = FFh <==> MISO = 1 = not busy = idle state
66     JNE WaitIdleBeforeSendCMD       ; loop back if <> FFh
67 ; ==================================;   W = 0 = expected R1 response = ready, for CMD41,CMD16, CMD17, CMD24
68 sendCommand                         ;X  
69 ; ==================================;
70                                     ; input : SD_CMD_FRM : {CRC,byte_l,byte_L,byte_h,byte_H,CMD} 
71                                     ;         W = expected return value
72                                     ; output  W is unchanged, flag Z is positionned
73                                     ; reverts CMD bytes before send : $(CMD hh LL ll 00 CRC)
74     MOV     #5,X                    ; X = SD_CMD_FRM ptr AND countdown
75 ; ----------------------------------;
76 Send_CMD_PUT                        ; performs little endian --> big endian conversion
77 ; ----------------------------------;
78     MOV.B   SD_CMD_FRM(X),&SD_TXBUF ;5 
79     CMP     #0,&SD_BRW              ;3 full speed ?
80     JZ      FullSpeedSend           ;2 yes
81 Send_CMD_Loop                       ;
82     BIT     #UCRXIFG,&SD_IFG        ;3 no: case of low speed during memCardInit
83     JZ      Send_CMD_Loop           ;2
84     CMP.B   #0,&SD_RXBUF            ;3 to clear UCRXIFG
85 FullSpeedSend                       ;
86 ;   NOP                             ;0 NOPx adjusted to avoid SD error
87     SUB.B   #1,X                    ;1
88     JHS     Send_CMD_PUT            ;2 U>= : don't skip SD_CMD_FRM(0) !
89
90                                     ; host must provide height clock cycles to complete operation
91                                     ; here X=255, so wait for CMD return expected value with PUT FFh 256 times
92
93 ;    MOV     #4,X                    ; to pass made in PRC SD_Card init 
94 ;    MOV     #16,X                   ; to pass Transcend SD_Card init
95 ;    MOV     #32,X                   ; to pass Panasonic SD_Card init
96 ;    MOV     #64,X                   ; to pass SanDisk SD_Card init
97 ; ----------------------------------;
98 Wait_Command_Response               ; expect W = return value during X = 255 times
99 ; ----------------------------------;
100     SUB     #1,X                    ;1
101     JN      SPI_WAIT_RET            ;2 error on time out with flag Z = 0
102     MOV.B   #-1,&SD_TXBUF           ;3 PUT FFh
103     CMP     #0,&SD_BRW              ;3 full speed ?
104     JZ      FullSpeedGET            ;2 yes
105 cardResp_Getloop                    ;  no: case of low speed during memCardInit (CMD0,CMD8,ACMD41,CMD16)
106     BIT     #UCRXIFG,&SD_IFG        ;3
107     JZ      cardResp_Getloop        ;2
108 FullSpeedGET                        ;
109 ;    NOP                            ;  NOPx adjusted to avoid SD_error
110     CMP.B   &SD_RXBUF,W             ;3 return value = ExpectedValue ?
111     JNZ     Wait_Command_Response   ;2 16~ full speed loop
112 SPI_WAIT_RET                        ; flag Z = 1 <==> Returned value = expected value
113     RET                             ; W = expected value, unchanged
114 ; ----------------------------------;
115
116
117 ; SPI_GET and SPI_PUT are adjusted for SD_CLK = MCLK
118 ; PUT value must be a word or  byte:byte because little endian to big endian conversion
119
120 ; ==================================;
121 SPI_GET                             ; PUT(FFh), output : W = received byte, X = 0
122 ; ==================================;
123     MOV #1,X                        ;1
124 ; ==================================;
125 SPI_X_GET                           ; PUT(FFh) X times, output : W = last received byte, X = 0
126 ; ==================================;
127     MOV #-1,W                       ;1 W = FFFFh
128 ; ==================================;
129 SPI_PUT                             ; PUT(W) X time, output : W = last received byte, X = 0
130 ; ==================================;
131             SWPB W                  ;1
132             MOV.B W,&SD_TXBUF       ;3 put W high byte then W low byte and so forth, that performs little to big endian conversion
133             CMP #0,&SD_BRW          ;3 full speed ?
134             JZ FullSpeedPut         ;2 
135 SPI_PUTWAIT BIT #UCRXIFG,&SD_IFG    ;3
136             JZ SPI_PUTWAIT          ;2
137             CMP.B #0,&SD_RXBUF      ;3 reset RX flag
138 FullSpeedPut
139 ;           NOP                     ;  NOPx adjusted to avoid SD error
140             SUB #1,X                ;1
141             JNZ SPI_PUT             ;2 12~ loop
142 SPI_PUT_END MOV.B &SD_RXBUF,W       ;3
143             RET                     ;4
144 ; ----------------------------------;
145
146 ; ==================================;
147 readFAT1SectorW                     ; read a FAT1 sector
148 ; ==================================;
149     ADD     &OrgFAT1,W              ;
150 ; ==================================;
151 readSectorW                         ; read a logical sector < 65536
152 ; ==================================;
153     MOV     #0,X                    ;
154 ; ==================================;
155 readSectorWX                        ; read a logical sector
156 ; ==================================;
157     BIS     #1,S                    ; preset sd_read error
158     MOV.B   #51h,&SD_CMD_FRM+5      ; CMD17 = READ_SINGLE_BLOCK
159     CALL    #RW_Sector_CMD          ; which performs logical sector to physical sector then little endian to big endian conversion
160     JNE     SD_CARD_ERROR           ; time out error if R1 <> 0 
161 ; ----------------------------------;
162 WaitFEhResponse                     ; wait SD_Card response FEh
163 ; ----------------------------------;
164     CALL #SPI_GET                   ;
165     ADD.B   #2,W                    ;1 FEh expected value
166     JZ  ReadSectorfirst             ; 2
167     JNZ WaitFEhResponse             ;
168 ; ----------------------------------;
169 ReadSectorLoop                      ; get 512+1 bytes, write 512 bytes in SD_BUF
170 ; ----------------------------------;
171     MOV.B   &SD_RXBUF,SD_BUF-1(X)   ; 5
172 ReadSectorfirst                     ; 
173     MOV.B   #-1,&SD_TXBUF           ; 3 put FF
174     NOP                             ; 1 NOPx adjusted to avoid read SD_error
175     ADD     #1,X                    ; 1
176     CMP     #BytsPerSec+1,X         ; 2
177     JNZ     ReadSectorLoop          ; 2 14 cycles loop read byte
178 ; ----------------------------------;
179     MOV.B   #-1,&SD_TXBUF           ; 3 put only one FF because first CRC byte is already received...
180 ; ----------------------------------;
181 ReadWriteHappyEnd                   ; <==== WriteSector
182 ; ----------------------------------;
183     BIC     #3,S                    ; reset read and write errors
184     BIS.B   #SD_CS,&SD_CSOUT        ; SD_CS = high  
185     RET                             ; 
186 ; ----------------------------------;
187
188     .IFDEF SD_CARD_READ_WRITE
189
190 ; ==================================;
191 WriteSectorW                        ; write a logical sector up to 65535 (FAT1,FAT2)
192 ; ==================================;
193     MOV     #0,X                    ;
194 ; ==================================;
195 WriteSectorWX                       ; write a logical sector
196 ; ==================================;
197     BIS     #2,S                    ; preset sd_write error
198     MOV.B   #058h,SD_CMD_FRM+5      ; CMD24 = WRITE_SINGLE_BLOCK
199     CALL    #RW_Sector_CMD          ; which performs logical sector to physical sector then little endian to big endian conversions
200     JNE     SD_CARD_ERROR           ; ReturnError = 2
201     MOV     #0FFFEh,W               ; PUT FFFEh as preamble requested for sector write
202     MOV     #2,X                    ; to put 16 bits value
203     CALL    #SPI_PUT                ; which performs little endian to big endian conversion
204 ; ----------------------------------;
205 WriteSectorLoop                     ; 11 cycles loop write, starts with X = 0
206 ; ----------------------------------;
207     MOV.B   SD_BUF(X),&SD_TXBUF     ; 5
208     NOP                             ; 1 NOPx adjusted to avoid write SD_error
209     ADD     #1,X                    ; 1
210     CMP     #BytsPerSec,X           ; 2
211     JNZ     WriteSectorLoop         ; 2
212 ; ----------------------------------;
213 WriteSkipCRC16                      ; CRC not used in SPI mode
214 ; ----------------------------------;
215     MOV     #3,X                    ; PUT 2 bytes to skip CRC16
216     CALL    #SPI_X_GET              ; + 1 byte to get data token in W
217 ; ----------------------------------;
218 CheckWriteState                     ;
219 ; ----------------------------------;
220     BIC.B   #0E1h,W                 ; apply mask for Data response
221     CMP.B   #4,W                    ; data accepted
222     JZ      ReadWriteHappyEnd       ;
223 ; ----------------------------------;
224
225     .ENDIF ; SD_CARD_READ_WRITE
226
227 ; SD Error n°
228 ; High byte
229 ; 1  = CMD17    read error
230 ; 2  = CMD24    write error 
231 ; 4  = CMD0     time out (GO_IDLE_STATE)
232 ; 8  = ACMD41   time out (APP_SEND_OP_COND)
233 ; 10 = CMD16    time out (SET_BLOCKLEN)
234 ; 20 = not FAT16/FAT32 media, low byte = partition ID
235
236 ; low byte, if CMD R1 response : |0|7|6|5|4|3|2|1|
237 ; 1th bit = In Idle state
238 ; 2th bit = Erase reset
239 ; 3th bit = Illegal command
240 ; 4th bit = Command CRC error
241 ; 5th bit = erase sequence error
242 ; 6th bit = address error
243 ; 7th bit = parameter error
244
245 ; Data Response Token
246 ; Every data block written to the card will be acknowledged by a data response token. 
247 ; It is one byte long and has the following format:
248 ; 7 6 5 4 3 2  1  0
249 ; x x x 0 Status  1
250 ;The meaning of the status bits is defined as follows:
251 ;'010' - Data accepted.
252 ;'101' - Data rejected due to a CRC error.
253 ;'110' - Data Rejected due to a Write Error
254
255 ; ----------------------------------;
256 SD_CARD_ERROR                       ; <=== SD_INIT errors 4,8,$10
257 ; ----------------------------------;
258     SWPB S                          ; High Level error in High byte
259     ADD &SD_RXBUF,S                 ; add SPI(GET) return value as low byte error
260 SD_CARD_ID_ERROR                    ; <=== SD_INIT error $20 from forthMSP430FR_SD_LowLvl.asm
261     BIS.B #SD_CS,&SD_CSOUT          ; SD_CS = high
262     mDOCOL                          ;
263     .word   XSQUOTE                 ;
264     .byte   11,"< SD Error!"        ;
265 ; ----------------------------------;
266 SD_QABORTYES                        ; <=== OPEN file errors from forthMSP430FR_SD_LOAD.asm
267 ; ----------------------------------;
268     FORTHtoASM                      ;
269     SUB #2,PSP                      ; to avoid stack underflow crash
270     MOV #10h,&BASE                  ; select hex
271     MOV S,TOS                       ;
272     ASMtoFORTH                      ;
273     .word   UDOT                    ;
274     .word   QABORTYES               ; no return...
275 ; ----------------------------------;
276