-
Notifications
You must be signed in to change notification settings - Fork 0
/
forthMSP430FR_SD_INIT.asm
282 lines (259 loc) · 15 KB
/
forthMSP430FR_SD_INIT.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
; -*- coding: utf-8 -*-
; forthMSP430FR_SD_INIT.asm
.save
.listing off
; ===========================================================
; ABOUT INIT SD_CARD AND HOW TO SELECT FAT16/FAT32 FORMAT
; ===========================================================
; FAT16/FAT32 selection is made via the ID of partition in EBP
; because SD must be always FAT16 and SDHC must be always FAT32
; this is automatically done when we format the SD_Card !
; =====================================================================
; goal : accept 64 MB up to 64 GB SD_CARD
; =====================================================================
; thus FAT and RootClus logical sectors are word addressable.
; FAT is a little endian structure.
; CMD frame is sent as big endian.
; we assume that SDSC Card (up to 2GB) is FAT16 with a byte addressing
; and that SDHC Card (4GB up to 64GB) is FAT32 with a sector addressing (sector = 512 bytes)
; for SDHC Card = 64 GB, cluster = 64 sectors ==> max clusters = 20 0000h ==> FAT size = 16384 sectors
; ==> FAT1 and FAT2 can be addressed with a single word.
; ref. https://en.wikipedia.org/wiki/Extended_boot_record
; ref. https://en.wikipedia.org/wiki/Partition_type
; Formatage FA16 d'une SDSC Card 2GB
; First sector of physical drive (sector 0) content :
; ---------------------------------------------------
; dec@| HEX@
; 446 |0x1BE : partition table first record ==> logical drive 0
; 462 |0x1CE : partition table 2th record ==> logical drive 1
; 478 |0x1DE : partition table 3th record ==> logical drive 2
; 494 |0x1EE : partition table 4th record ==> logical drive 3
; partition of first record content :
; ---------------------------------------------------
; 450 |0x1C2 = 0x0E : type FAT16 using LBA addressing
; 454 |0x1C6 = 89 00 00 00 : FirstSector (of logical drive 0) BS_FirstSector = 137
; Partition type Description
; 0 empty / unused
; 1 FAT12
; 4 FAT16 for partitions <= 32 MiB
; 5 extended partition
; 6 FAT16 for partitions > 32 MiB
; 11 FAT32 for partitions <= 2 GiB
; 12 Same as type 11 (FAT32), but using LBA addressing, which removes size constraints
; 14 Same as type 6 (FAT16), but using LBA addressing
; 15 Same as type 5, but using LBA addressing
; ref. https://www.compuphase.com/mbr_fat.htm#BOOTSECTOR
; FirstSector of logical drive (sector 0) content :
; -------------------------------------------------
; dec@| HEX@ = HEX decimal
; 11 | 0x0B = 00 02 : 512 bytes/sector BPB_BytsPerSec = 512
; 13 | 0x0D = 40 : 64 sectors/cluster BPB_SecPerClus = 64
; 14 | 0x0E = 01 00 : 2 reserved sectors BPB_RsvdSecCnt = 1
; 16 | 0x10 = 02 : 2 FATs BPB_NumFATs = 2 (always 2)
; 17 | 0x11 = 00 02 : 512 entries/directory BPB_RootEntCnt = 512
; 19 | 0x13 = 00 00 : BPB_TotSec16 (if < 65535) BPB_TotSec16 = 0
; 22 | 0x16 = EB 00 : 235 sectors/FAT (FAT16) BPB_FATSize = 235
; 32 | 0x20 = 77 9F 3A 00 : 3841911 total sectors BPB_TotSec32 = 3841911
; 54 | 0x36 = "FAT16" BS_FilSysType (not used)
; all values below are evaluated in logical sectors
; FAT1 = BPB_RsvdSecCnt = 1
; FAT2 = BPB_RsvdSecCnt + BPB_FATSz32 = 1 + 235 = 236
; OrgRootDirL = BPB_RsvdSecCnt + (BPB_FATSize * BPB_NumFATs) = 471
; RootDirSize = BPB_RootEntCnt * 32 / BPB_BytsPerSec = 32 sectors
; OrgDatas = OrgRootDir + RootDirSize = 503
; OrgCluster = OrgRootDir - 2*BPB_SecPerClus = 375 (virtual value)
; FirstSectorOfCluster(n) = OrgCluster + n*BPB_SecPerClus ==> cluster(3) = 705
; ====================================================================================
; Formatage FA32 d'une SDSC Card 8GB
; First sector of physical drive (sector 0) content :
; ---------------------------------------------------
; dec@| HEX@
; 446 |0x1BE : partition table first record ==> logical drive 0
; 462 |0x1CE : partition table 2th record ==> logical drive 1
; 478 |0x1DE : partition table 3th record ==> logical drive 2
; 494 |0x1EE : partition table 4th record ==> logical drive 3
; partition record content :
; ---------------------------------------------------
; 450 |0x1C2 = 0x0C : type FAT32 using LBA addressing
; 454 |0x1C6 = 00 20 00 00 : FirstSector (of logical drive 0) = BS_FirstSector = 8192
;
; FirstSector of logical block (sector 0) content :
; -------------------------------------------------
; dec@| HEX@ = HEX decimal
; 11 | 0x0B = 00 02 : 512 bytes/sector BPB_BytsPerSec = 512
; 13 | 0x0D = 08 : 8 sectors/cluster BPB_SecPerClus = 8
; 14 | 0x0E = 20 00 : 32 reserved sectors BPB_RsvdSecCnt = 32
; 16 | 0x10 = 02 : 2 FATs BPB_NumFATs = 2 (always 2)
; 17 | 0x11 = 00 00 : 0 BPB_RootEntCnt = 0 (always 0 for FAT32)
; 32 | 0x20 = 00 C0 EC 00 : BPB_TotSec32 BPB_TotSec32 = 15515648
; 36 | 0x24 = 30 3B 00 00 : BPB_FATSz32 BPB_FATSz32 = 15152
; 40 | 0x28 = 00 00 : BPB_ExtFlags BPB_ExtFlags
; 44 | 0x2C = 02 00 00 00 : BPB_RootClus BPB_RootClus = 2
; 48 | 0x30 = 01 00 : BPB_FSInfo BPB_FSInfo = 1
; 50 | 0x33 = 06 00 : BPB_BkBootSec BPB_BkBootSec = 6
; 82 | 0x52 = "FAT32" : BS_FilSysType BS_FilSysType (not used)
;
; all values below are evaluated in logical sectors
; FAT1 = BPB_RsvdSecCnt = 32
; FAT2 = BPB_RsvdSecCnt + BPB_FATSz32 = 32 + 15152 = 15184
; OrgRootDirL = BPB_RsvdSecCnt + BPB_FATSz32 * BPB_NumFATs = 32 + 15152*2 = 30336
; OrgCluster = OrgRootDir - 2*BPB_SecPerClus = 30320
; RootDirSize = BPB_RootEntCnt * 32 / BPB_BytsPerSec = 0
; OrgDatas = OrgRootDir + RootDirSize = 30336
; FirstSectorOfCluster(n) = OrgCluster + n*BPB_SecPerClus ==> cluster(6) = 30368
.restore
; ===========================================================
; WARNING! SD_INIT DRAW BIG CURRENT; IF THE SUPPLY IS TOO WEAK
; THE SD_CARD LOW VOLTAGE THRESHOLD MAY BE REACHED ==> SD_ERROR 4FF !
; ===========================================================
; ===========================================================
; Init SD_Card software, called by INIT_FORTH(SOFT_APP)
; ===========================================================
;-----------------------------------;
INIT_SOFT_SD ; called by INI_FORTH common part of ?ABORT|RST
;-----------------------------------;
; MOV #HandlesLen,X ; clear all handles
;ClearHandle SUB #2,X ; 1
; MOV #0,FirstHandle(X) ; 3
; JNZ ClearHandle ; 2
MOV #0,&CurrentHdl ;
MOV #INIT_SOFT,PC ; link to previous INI_SOFT_APP then RET
;-----------------------------------;
; ===========================================================
; Init hardware SD_Card, called by WARM(HARD_APP)
; ===========================================================
; web search: "SDA simplified specifications"
;-----------------------------------;
INIT_HARD_SD CALL @PC+ ; link to previous HARD_APP first, because used by ERROR outputs
.word INIT_TERM ; which activates all previous I/O settings.
;-----------------------------------;
BIT.B #CD_SD,&SD_CDIN ; SD_memory in SD_Card module ?
JNZ INIT_HSD_END ; no
;-----------------------------------;
MOV #0A981h,&SD_CTLW0 ; UCxxCTL1 = CKPH, MSB, MST, SPI_3, SMCLK + UCSWRST
MOV #FREQUENCY*3,&SD_BRW; UCxxBRW init SPI CLK = 333 kHz ( <= 400 kHz) for SD_Card initialisation
BIS.B #CS_SD,&SD_CSDIR ; SD Chip Select as output high
BIS #BUS_SD,&SD_SEL ; Configure pins as SIMO, SOMI & SCK (PxDIR.y are controlled by eUSCI module)
BIC #1,&SD_CTLW0 ; release eUSCI from reset
;-----------------------------------;
MOV #SD_LEN,X ; clear all SD datas
ClearSDdata SUB #2,X ; 1
MOV #0,SD_ORG(X) ; 3
JNZ ClearSDdata ; 2
;-----------------------------------;
BIC.B #CS_SD,&SD_CSOUT ; preset Chip Select output low to switch in SPI mode
; ----------------------------------;
INIT_CMD0 ; SD_CMD_FRM is zero fullfilled...
; ----------------------------------;
MOV #4,S ; preset error 4R1 for CMD0
MOV #0095h,&SD_CMD_FRM ; $(95 00 00 00 00 00)
MOV #0,&SD_CMD_FRM+2 ;
MOV #4000h,&SD_CMD_FRM+4 ; $(95 00 00 00 00 40) = CMD0
MOV #8,Y ; CMD0 necessary loop, not documented in "SDA simplified specifications"
; ----------------------------------;
SEND_CMD0 ; GO_IDLE_STATE (software reset), expected SPI_R1 response = 1 = idle state
; ----------------------------------;
CALL #sendCommandIdleRet ;X send command (does little to big endian conversion), see forthMSP430FR_SD_lowLvl.asm
JZ INIT_CMD8 ; if idle state reached (W=1)
SUB #1,Y ;
JNZ SEND_CMD0 ; else loop back 8 times, because init time of SD_Card can be long...
SD_INIT_ERROR ;
JMP SD_CARD_ERROR ; ReturnError = $04R1, case of defectuous card (or insufficient SD_POWER_ON clk)
; ----------------------------------; see forthMSP430FR_SD_lowLvl.asm
INIT_CMD8 ; mandatory if SD_Card >= V2.x [11:8]supply voltage(VHS)
; ----------------------------------;
MOV #0AA87h,&SD_CMD_FRM ; $(87 AA ...) (CRC:CHECK PATTERN)
MOV #1,&SD_CMD_FRM+2 ; $(87 AA 01 00 ...) (CRC:CHECK PATTERN:VHS set as 2.7to3.6V:0)
MOV #4800h,&SD_CMD_FRM+4 ; $(87 AA 01 00 00 48)
; ----------------------------------;
SEND_CMD8 ; SEND_IF_COND; expected R1 response (first byte of SPI R7) = 01h : idle state
; ----------------------------------;
CALL #sendCommandIdleRet ;X time out occurs with SD_Card V1.x (and all MMC_card)
; ----------------------------------;
MOV #4,X ; skip end of SD_Card V2.x type R7 response (4 bytes), because useless
CALL #SPI_X_GET ;WX
; ----------------------------------;
INIT_ACMD41 ; no more CRC needed from here
; ----------------------------------;
MOV #1,&SD_CMD_FRM ; $(01 00 ... set stop bit
MOV #0,&SD_CMD_FRM+2 ; $(01 00 00 00 ...
MOV.B #-1,Y ; init 255 * ACMD41 repeats ==> ~3 s time out
MOV #8,S ; preset error 8R1 for ACMD41
; ----------------------------------;
SEND_ACMD41 ; send CMD55+CMD41
; ----------------------------------;
INIT_CMD55 ;
MOV #7700h,&SD_CMD_FRM+4 ; $(01 00 00 00 00 77)
SEND_CMD55 ; CMD55 = APP_CMD; expected SPI_R1 response = 1 : idle
CALL #sendCommandIdleRet ;X
SEND_CMD41 ; CMD41 = APP OPERATING CONDITION
MOV #6940h,&SD_CMD_FRM+4 ; $(01 00 00 00 40 69) (30th bit = HCS = High Capacity Support request)
CALL #WaitIdleBeforeSendCMD ; wait until idle (needed to pass SanDisk ultra 8GB "HC I") then send Command CMD41
JZ SwitchSPIhighSpeed ; if SD_Card ready (R1=0)
SUB.B #1,Y ; else decr time out delay
JNZ INIT_CMD55 ; then loop back while count of repeat not reached
JMP SD_CARD_ERROR ; ReturnError on time out : unusable card (or insufficient Vdd SD)
; ----------------------------------; W = R1 = 0
SwitchSPIhighSpeed ; end of SD init ==> SD_CLK = SMCLK
; ----------------------------------;
BIS #1,&SD_CTLW0 ; UC Software reset
MOV #0,&SD_BRW ; UCxxBRW = 0 ==> SPI_CLK = MCLK
BIC #1,&SD_CTLW0 ; release from reset
; ----------------------------------;
Read_EBP_FirstSector ; BS_FirstSectorHL=0
; ----------------------------------;
MOV #0,W ;
MOV #0,X ;
CALL #ReadSectorWX ; read physical first sector, W=0
MOV #SD_BUF,Y ;
; ----------------------------------;
CMP #0AA55h,1FEh(Y) ; valid boot sector ?
JZ SetMBR ;
MOV #1000h,S ; error Boot Sector
JMP SD_CARD_INIT_ERROR ;
; ----------------------------------;
SetMBR ;
; ----------------------------------;
MOV 1C6h(Y),&BS_FirstSectorL; logical sector = physical sector + BS_FirstSector
MOV 1C8h(Y),&BS_FirstSectorH;
; ----------------------------------;
TestPartitionID ;
; ----------------------------------;
MOV.B 1C2h(Y),S ; S = partition ID
SUB.B #0Ch,S ; ID=0Ch Partition FAT32 using LBA ?
JZ Read_MBR_FirstSector ;
ADD.B #1,S ; ID=0Bh Partition FAT32 using CHS & LBA ?
JZ Read_MBR_FirstSector ;
ADD.B #4,S ; ID=07h assigned to FAT32 by MiniTools Partition Wizard....
JZ Read_MBR_FirstSector ;
ADD #01007h,S ; set ReturnError = $10 & restore ID value
JMP SD_CARD_INIT_ERROR ; see: https://en.wikipedia.org/wiki/Partition_type
; ----------------------------------;
Read_MBR_FirstSector ; read first logical sector
; ----------------------------------;
MOV #0,X ; W = 0
CALL #ReadSectorWX ;
; ----------------------------------;
FAT32_SetFileSystem ;
; ----------------------------------;
MOV 0Eh(Y),X ;3 X = BPB_RsvdSecCnt (05FEh=1534)
MOV X,&OrgFAT1 ;3 set OrgFAT1
; ----------------------------------;
MOV 24h(Y),W ; no set W = BPB_FATSz32 (1D01h=7425)
MOV W,&FATSize ; limited to 32767 sectors....
; ----------------------------------;
ADD W,X ;
MOV X,&OrgFAT2 ; X = OrgFAT1 + FATsize = OrgFAT32 (8959)
; ----------------------------------;
ADD W,X ; X = OrgFAT2 + FATsize = FAT32 OrgDatas (16384)
FATxx_SetFileSystemNext ;
MOV.B 0Dh(Y),Y ; Logical sectors per cluster (8)
MOV Y,&SecPerClus ;
SUB Y,X ; OrgDatas - SecPerClus*2 = OrgClusters
SUB Y,X ; no borrow expected
MOV X,&OrgClusters ; X = virtual cluster 0 address (clusters 0 and 1 don't exist)
MOV #2,&DIRClusterL ; init DIRcluster as FAT32 RootDIR
MOV #0,&DIRClusterH ;
INIT_HSD_END ;
MOV @RSP+,PC ; RET
;-----------------------------------;