1 ; -*- coding: utf-8 -*-
2 ; forthMSP430FR_SD_INIT.asm
4 ; http://patorjk.com/software/taag/#p=display&f=Banner&t=Fast Forth
6 ; Fast Forth For Texas Instrument MSP430FRxxxx FRAM devices
7 ; Copyright (C) <2017> <J.M. THOORENS>
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.
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.
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/>.
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 !
30 ; ===========================================================
31 ; 1- Init eUSCI dedicated to SD_Card SPI driver
32 ; ===========================================================
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
41 ; ===========================================================
42 ; 2- Init to 0 all SD_Card variables, handles and SDIB buffer
43 ; ===========================================================
53 ; ===========================================================
55 ; ===========================================================
58 MOV #8,X ; send 64 clk on SD_clk
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 ; ----------------------------------;
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
72 JZ INIT_CMD8 ; if idle state
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
92 ; ----------------------------------;
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
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
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
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 ; ----------------------------------;
141 ; ----------------------------------;
142 MOV #1,&FATtype ; preset FAT16
144 SUB.B #6,W ; ID=06h Partition FAT16 using CHS & LBA ?
145 JZ Read_MBR_FirstSector ; W = 0
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
152 ADD.B #2,W ; ID=0Ch Partition FAT32 using LBA ?
153 JZ Read_MBR_FirstSector ; W = 0
155 ADD.B #1,W ; ID=0Bh Partition FAT32 using CHS & LBA ?
156 JZ Read_MBR_FirstSector ; W = 0
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
175 MOV W,&FATSize ; limited to 16384 sectors....
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 ; ----------------------------------;