OSDN Git Service

aa5f8e9207d4f177aad7ec99df4daff8683302d5
[fast-forth/master.git] / forthMSP430FR_SD_INIT.asm
1 ; -*- coding: utf-8 -*-
2 ; forthMSP430FR_SD_INIT.asm
3
4 ; http://patorjk.com/software/taag/#p=display&f=Banner&t=Fast Forth
5
6 ; Fast Forth For Texas Instrument MSP430FRxxxx FRAM devices
7 ; Copyright (C) <2017>  <J.M. THOORENS>
8 ;
9 ; This program is free software: you can redistribute it and/or modify
10 ; it under the terms of the GNU General Public License as published by
11 ; the Free Software Foundation, either version 3 of the License, or
12 ; (at your option) any later version.
13 ;
14 ; This program is distributed in the hope that it will be useful,
15 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ; GNU General Public License for more details.
18 ;
19 ; You should have received a copy of the GNU General Public License
20 ; along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 ; ===========================================================
23 ; ABOUT INIT SD_CARD AND HOW TO SELECT FAT16/FAT32 FORMAT
24 ; ===========================================================
25 ; FAT16/FAT32 selection is made via the ID of partition in EBP
26 ; because SD must be always FAT16 and SDHC must be always FAT32
27 ; this is automatically done when we format the SD_Card !
28
29
30 ; ===========================================================
31 ; 1- Init eUSCI dedicated to SD_Card SPI driver
32 ; ===========================================================
33
34     MOV #0A981h,&SD_CTLW0           ; UCxxCTL1  = CKPH, MSB, MST, SPI_3, SMCLK  + UCSWRST
35     MOV #FREQUENCY*3,&SD_BRW        ; UCxxBRW init SPI CLK = 333 kHz ( < 400 kHz) for SD_Card init
36     BIS.B #SD_CS,&SD_CSDIR          ; SD_CS as output high
37     BIS     #SD_BUS,&SD_SEL         ; Configure pins as SIMO, SOMI & SCK (PxDIR.y are controlled by eUSCI module)
38 ;    BIC     #SD_BUS,&SD_REN         ; disable pullup resistors for SIMO/SOMI/SCK pins
39     BIC     #1,&SD_CTLW0            ; release eUSCI from reset
40
41 ; ===========================================================
42 ; 2- Init to 0 all SD_Card variables, handles and SDIB buffer
43 ; ===========================================================
44
45 InitSDdata
46     MOV     #SD_ORG_DATA,X          ;
47 InitSDdataLoop                      ;
48     MOV     #0,0(X)                 ;
49     ADD     #2,X                    ;
50     CMP     #SD_END_DATA,X          ;
51     JNE     InitSDdataLoop          ;
52
53 ; ===========================================================
54 ; 3- Init SD_Card
55 ; ===========================================================
56
57 SD_POWER_ON
58     MOV     #8,X                    ; send 64 clk on SD_clk
59     CALL    #SPI_X_GET              ;
60     BIC.B   #SD_CS,&SD_CSOUT        ; preset SD_CS output low to switch in SPI mode
61     MOV     #4,S                    ; preset error 4R1
62 ; ----------------------------------;
63 INIT_CMD0                           ;
64 ; ----------------------------------;
65     MOV     #95h,&SD_CMD_FRM        ; $(95 00 00 00 00 00)
66     MOV     #4000h,&SD_CMD_FRM+4    ; $(95 00 00 00 00 40); send CMD0 
67 ; ----------------------------------;
68 SEND_CMD0                           ; CMD0 : GO_IDLE_STATE
69 ; ----------------------------------;
70     MOV     #1,W                    ; expected SPI_R1 response = 1 = idle state
71     CALL    #sendCommand            ;X
72     JZ      INIT_CMD8               ; if idle state
73 SD_INIT_ERROR                       ;
74     MOV     #SD_CARD_ERROR,PC       ; ReturnError = $04R1, case of defectuous card (or insufficient SD_POWER_ON clk)
75 ; ----------------------------------;
76 INIT_CMD8                           ; mandatory if SD_Card >= V2.x [11:8]supply voltage(VHS)
77 ; ----------------------------------;
78     CALL    #SPI_GET                ; (needed to pass SanDisk ultra 8GB "HC I")
79     CMP.B   #-1,W                   ; FFh expected value <==> MISO = high level
80     JNE     INIT_CMD8               ; loop back while yet busy
81     MOV     #0AA87h,&SD_CMD_FRM     ; $(87 AA ...)  (CRC:CHECK PATTERN)
82     MOV     #1,&SD_CMD_FRM+2        ; $(87 AA 01 00 ...)  (CRC:CHECK PATTERN:VHS set as 2.7to3.6V:0)
83     MOV     #4800h,&SD_CMD_FRM+4    ; $(87 AA 01 00 00 48)
84 ; ----------------------------------;
85 SEND_CMD8                           ; CMD8 = SEND_IF_COND
86 ; ----------------------------------;
87     MOV     #1,W                    ; expected R1 response (first byte of SPI R7) = 01h : idle state
88     CALL    #sendCommand            ; time out occurs with SD_Card V1.x (and all MMC_card) 
89 ; ----------------------------------;
90     MOV     #4,X                    ; skip end of SD_Card V2.x type R7 response (4 bytes), because useless
91     CALL    #SPI_X_GET              ;WX
92 ; ----------------------------------;
93 INIT_ACMD41                         ;
94 ; ----------------------------------;
95     MOV     #1,&SD_CMD_FRM          ; $(01 00 ...   set stop bit
96     MOV     #0,&SD_CMD_FRM+2        ; $(01 00 00 00 ...
97 ;    MOV.B   #16,Y                   ; init 16 * ACMD41 repeats (power on fails with SanDisk ultra 8GB "HC I" and Transcend 2GB)
98 ;    MOV.B   #32,Y                   ; init 32 * ACMD41 repeats ==> ~400ms time out
99     MOV.B   #-1,Y                   ; init 255 * ACMD41 repeats ==> ~3 s time out
100 ; ----------------------------------;
101 SEND_ACMD41                         ; send CMD55+CMD41
102 ; ----------------------------------;
103     MOV     #8,S                    ; preset error 8R1 for ACMD41
104 INIT_CMD55                          ;
105     MOV     #7700h,&SD_CMD_FRM+4    ; $(01 00 00 00 00 77)
106 SEND_CMD55                          ; CMD55 = APP_CMD
107     MOV     #1,W                    ; expected R1 response = 1 : idle
108     CALL    #sendCommand            ;
109 SEND_CMD41                          ; CMD41 = APP OPERATING CONDITION
110     MOV     #6940h,&SD_CMD_FRM+4    ; $(01 00 00 00 40 69) (30th bit = HCS = High Capacity Support request)
111     CALL    #WaitIdleBeforeSendCMD  ; wait until idle (needed to pass SanDisk ultra 8GB "HC I") then send Command CMD41
112     JZ      SetBLockLength          ; if SD_Card ready (R1=0)
113     SUB.B   #1,Y                    ; else decr time out delay
114     JNZ     INIT_CMD55              ; then loop back while count of repeat not reached
115     JMP     SD_INIT_ERROR           ; ReturnError on time out : unusable card
116 ; ----------------------------------;
117 setBLockLength                      ; set block = 512 bytes (buffer size), usefull only for FAT16 SD Cards
118 ; ----------------------------------;
119     ADD     S,S                     ; preset error $10 for CMD16
120 SEND_CMD16                          ; CMD16 = SET_BLOCKLEN
121     MOV     #02h,&SD_CMD_FRM+2      ; $(01 00 02 00 ...)
122     MOV     #5000h,&SD_CMD_FRM+4    ; $(01 00 02 00 00 50) 
123     CALL    #WaitIdleBeforeSendCMD  ; wait until idle then send CMD16
124     JNZ     SD_INIT_ERROR           ; if W = R1 <> 0, ReturnError = $20R1 ; send command ko
125 ; ----------------------------------;
126 SetHighSpeed                        ; end of SD init ==> SD_CLK = SMCLK
127 ; ----------------------------------;
128     BIS     #1,&SD_CTLW0            ; Software reset
129     MOV     #0,&SD_BRW              ; UCxxBRW = 0 ==> SPI_CLK = MCLK
130     BIC     #1,&SD_CTLW0            ; release from reset
131 ; ----------------------------------;
132 Read_EBP_FirstSector                ; W=0, BS_FirstSectorHL=0
133 ; ----------------------------------;
134     CALL    #readSectorW            ; read physical first sector
135     MOV     #SD_BUF,Y               ;
136     MOV     454(Y),&BS_FirstSectorL ; so, sectors become logical
137     MOV     456(Y),&BS_FirstSectorH ; 
138     MOV.B   450(Y),W                ; W = partition ID 
139 ; ----------------------------------;
140 TestPartitionID                     ;
141 ; ----------------------------------;
142     MOV     #1,&FATtype             ; preset FAT16
143 FAT16_CHS_LBA_Test                  ;
144     SUB.B   #6,W                    ; ID=06h Partition FAT16 using CHS & LBA ?
145     JZ      Read_MBR_FirstSector    ; W = 0
146 FAT16_LBA_Test                      ;
147     SUB.B   #8,W                    ; ID=0Eh Partition FAT16 using LBA ?
148     JZ      Read_MBR_FirstSector    ; W = 0
149 ; ----------------------------------;
150     MOV     #2,&FATtype             ; set FAT32
151 FAT32_LBA_Test                      ;
152     ADD.B   #2,W                    ; ID=0Ch Partition FAT32 using LBA ?
153     JZ      Read_MBR_FirstSector    ; W = 0
154 FAT32_CHS_LBA_Test                  ;
155     ADD.B   #1,W                    ; ID=0Bh Partition FAT32 using CHS & LBA ?
156     JZ      Read_MBR_FirstSector    ; W = 0
157     ADD     #0200Bh,W               ;
158     MOV     W,S                     ;
159     MOV     #SD_CARD_ID_ERROR,PC    ; S = ReturnError = $20xx with xx = partition ID 
160 ; ----------------------------------; see: https://en.wikipedia.org/wiki/Partition_type
161 Read_MBR_FirstSector                ; read first logical sector
162 ; ----------------------------------;
163     CALL    #readSectorW            ; ...with the good CMD17 bytes/sectors frame ! (good switch FAT16/FAT32)
164 ; ----------------------------------;
165 FATxx_SetFileSystem                 ;
166 ; ----------------------------------;
167     MOV.B   13(Y),&SecPerClus       ;
168     MOV     14(Y),X                 ;3 X = BPB_RsvdSecCnt
169     MOV     X,&OrgFAT1              ;3 set OrgFAT1
170     MOV     22(Y),W                 ; W = BPB_FATsize
171     CMP     #0,W                    ; BPB_FATsize <> 0 ?
172     JNZ     Set_FATsize             ; yes
173     MOV     36(Y),W                 ; W = BPB_FATSz32
174 Set_FATsize                         ;
175     MOV     W,&FATSize              ; limited to 16384 sectors....
176     ADD     W,X                     ;
177     MOV     X,&OrgFAT2              ; X = OrgFAT1 + FATsize = OrgFAT2
178     ADD     W,X                     ; X = OrgFAT2 + FATsize = FAT16 OrgRootDir | FAT32 OrgDatas
179     CMP     #2,&FATtype             ; FAT32?
180     JZ      FATxx_SetFileSystemNext ; yes
181 FAT16_SetRootCluster                ;
182     MOV     X,&OrgRootDIR           ; only FAT16 use, is a sector used by ComputeClusFrstSect
183     ADD     #32,X                   ; OrgRootDir + RootDirSize = OrgDatas
184 FATxx_SetFileSystemNext             ;
185     SUB     &SecPerClus,X           ; OrgDatas - SecPerClus*2 = OrgClusters
186     SUB     &SecPerClus,X           ; no borrow expected
187     MOV     X,&OrgClusters          ; X = virtual cluster 0 address (clusters 0 and 1 don't exist)
188     MOV     &FATtype,&DIRClusterL   ; init DIRcluster as RootDIR
189 ; ----------------------------------;
190
191