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 FORMATTING
24 ; ===========================================================
25 ; FAT16/FAT32 selection is done via the ID of partition in EBP, because SD must be always FAT16 and SDHC must be always FAT32
26 ; So we assume that the SD_Card FAT16/FAT32 formatting was done well !
29 ; ===========================================================
30 ; 1- Init eUSCI dedicated to SD_Card SPI driver
31 ; ===========================================================
33 MOV #0A981h,&SD_CTLW0 ; UCxxCTL1 = CKPH, MSB, MST, SPI_3, SMCLK + UCSWRST
34 MOV #FREQUENCY*3,&SD_BRW ; UCxxBRW init SPI CLK = 333 kHz ( < 400 kHz) for SD_Card init
37 .IFDEF MSP_EXP430FR5739
39 ; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
41 ; P2.2 - RF.16 <--- CD SD_CardAdapter (Card Detect)
44 ; P2.3 - RF.10 ---> CS SD_CardAdapter (Card Select)
47 BIS.B #SD_CS,&P2DIR ; SD_CS output high
49 ; P2.4 - RF.14 UCA1 CLK ---> CLK SD_CardAdapter (SCK)
50 ; P2.5 - RF.7 UCA1 TXD/SIMO ---> SDI SD_CardAdapter (MOSI)
51 ; P2.6 - RF.5 UCA1 RXD/SOMI <--- SDO SD_CardAdapter (MISO)
52 BIS.B #070h,&P2SEL1 ; Configure UCA1 pins P2.4 as UCA1CLK, P2.5 as UCA1SIMO & P2.6 as UCA1SOMI
53 ; P2DIR.x is controlled by eUSCI_A0 module
54 BIC.B #070h,&P2REN ; disable pullup resistors for SIMO/SOMI/SCK pins
57 .IFDEF MSP_EXP430FR5969
59 ; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
61 ; P4.2 <--- SD_CD (Card Detect)
64 ; P4.3 ---> SD_CS (Card Select)
67 BIS.B #SD_CS,&P4DIR ; SD_CS output high
69 ; P2.4 UCA1 CLK ---> SD_CLK
70 ; P2.5 UCA1 TX/SIMO ---> SD_SDI
71 ; P2.6 UCA1 RX/SOMI <--- SD_SDO
72 BIS.B #070h, &P2SEL1 ; Configure UCA1 pins P2.4 as UCA1CLK, P2.5 as UCA1SIMO & P2.6 as UCA1SOMI
73 ; P2DIR.x is controlled by eUSCI_A0 module
74 BIC.B #070h, &P2REN ; disable pullup resistors for SIMO/SOMI/SCK pins
77 .IFDEF MSP_EXP430FR5994
79 ; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
81 ; P7.2/UCB2CLK - SD_CD (Card Detect)
84 ; P4.0/A8 - SD_CS (Card Select)
87 BIS.B #SD_CS,&P4DIR ; SD_CS output high
89 ; P2.2/TB0.2/UCB0CLK - SD_CLK
90 ; P1.6/TB0.3/UCB0SIMO/UCB0SDA/TA0.0 - SD_SDI
91 ; P1.7/TB0.4/UCB0SOMI/UCB0SCL/TA1.0 - SD_SDO
92 BIS #04C0h,&PASEL1 ; Configure UCB0 pins P1.6 as UCB0SIMO, P1.7 as UCB0SOMI& UCB0 pins P2.2 as UCB0CLK
93 ; PxDIR.x is controlled by eUSCI_A0 module
94 BIC #04C0h,&PAREN ; disable pullup resistors for SIMO/SOMI/SCK pins
97 .IFDEF MSP_EXP430FR6989
99 ; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
101 ; P2.7 <--- SD_CD (Card Detect)
104 ; P2.6 ---> SD_CS (Card Select)
107 BIS.B #SD_CS,&P2DIR ; SD_CS output high
109 ; P2.2 UCA0 CLK ---> SD_CLK
110 ; P2.0 UCA0 TX/SIMO ---> SD_SDI
111 ; P2.2 UCA0 RX/SOMI <--- SD_SDO
112 BIS.B #007h,&P2SEL0 ; Configure UCA1 pins P2.2 as UCA0CLK, P2.0 as UCA0SIMO & P2.1 as UCA0SOMI
113 ; P2DIR.x is controlled by eUSCI_A0 module
114 BIC.B #007h,&P2REN ; disable pullup resistors for SIMO/SOMI/SCK pins
117 ; .IFDEF MSP_EXP430FR4133
119 ;; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
121 ;; P8.0 <--- SD_CD (Card Detect)
124 ;; P8.1 ---> SD_CS (Card Select)
127 ; BIS.B #SD_CS,&P8DIR ; SD_CS output high
129 ;; P5.1 UCB0 CLK ---> SD_CLK
130 ;; P5.2 UCB0 TX/SIMO ---> SD_SDI
131 ;; P5.3 UCB0 RX/SOMI <--- SD_SDO
132 ; BIS.B #00Eh,&P5SEL1 ; Configure UCB0 pins P5.1 as CLK, P5.2 as SIMO & P5.3 as SOMI
133 ; ; P2DIR.x is controlled by eUSCI_A0 module
134 ; BIC.B #00Eh,&P5REN ; disable pullup resistors for SIMO/SOMI/SCK pins
137 .IFDEF CHIPSTICK_FR2433
139 ; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
141 ; P2.3 <--- SD_CD (Card Detect)
144 ; P2.2 ---> SD_CS (Card Select)
147 BIS.B #SD_CS,&P2DIR ; SD_CS output high
149 ; P1.1 UCB0 CLK ---> SD_CLK
150 ; P1.2 UCB0 TX/SIMO ---> SD_SDI
151 ; P1.3 UCB0 RX/SOMI <--- SD_SDO
152 BIS.B #00Eh,&P1SEL0 ; Configure UCB0 pins P1.1 as CLK, P1.2 as SIMO & P1.3 as SOMI
153 ; P1DIR.x is controlled by eUSCI_B0 module
154 BIC.B #00Eh,&P1REN ; disable pullup resistors for SIMO/SOMI/SCK pins
157 .IFDEF MY_MSP430FR5738
159 ; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
167 BIS.B #SD_CS,&P2DIR ; SD_CS output high
169 ; P2.2/UCB0CLK ---> SD_CardAdapter CLK (SCK) default value
170 ; P1.6/UCB0SIMO/UCB0SDA/TA0.0 ---> SD_CardAdapter SDI (MOSI) default value
171 ; P1.7/UCB0SOMI/UCB0SCL/TA1.0 <--- SD_CardAdapter SDO (MISO) default value
172 BIS #04C0h,&PASEL1 ; Configure UCB0 pins P2.2 as UCB0CLK, P1.6 as UCB0SIMO & P1.7 as UCB0SOMI
173 ; P2DIR.x is controlled by eUSCI_B0 module
174 BIC #04C0h,&PAREN ; disable pullup resistors for SIMO/SOMI/CLK pins
177 .IFDEF MY_MSP430FR5738_1
179 ; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
187 BIS.B #SD_CS,&P2DIR ; SD_CS output high
189 ; P2.2/UCB0CLK ---> SD_CardAdapter CLK (SCK) default value
190 ; P1.6/UCB0SIMO/UCB0SDA/TA0.0 ---> SD_CardAdapter SDI (MOSI) default value
191 ; P1.7/UCB0SOMI/UCB0SCL/TA1.0 <--- SD_CardAdapter SDO (MISO) default value
192 BIS #04C0h,&PASEL1 ; Configure UCB0 pins P2.2 as UCB0CLK, P1.6 as UCB0SIMO & P1.7 as UCB0SOMI
193 ; P2DIR.x is controlled by eUSCI_B0 module
194 BIC #04C0h,&PAREN ; disable pullup resistors for SIMO/SOMI/CLK pins
197 .IFDEF MY_MSP430FR5948
199 ; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
201 ; P2.3 <--- SD_CD (Card Detect)
204 ; P2.7 ---> SD_CS (Card Select)
207 BIS.B #SD_CS,&P2DIR ; SD_CS output high
209 ; P2.4 UCA1 CLK ---> SD_CLK
210 ; P2.5 UCA1 TX/SIMO ---> SD_SDI
211 ; P2.6 UCA1 RX/SOMI <--- SD_SDO
212 BIS.B #070h,&P2SEL1 ; Configure UCA1 pins P2.4 as UCA1CLK, P2.5 as UCA1SIMO & P2.6 as UCA1SOMI
213 ; P2DIR.x is controlled by eUSCI_A0 module
214 BIC.B #070h,&P2REN ; disable pullup resistors for SIMO/SOMI/SCK pins
217 .IFDEF MY_MSP430FR5948_1 ; = new version of MY_MSP430FR5948
219 ; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
221 ; P2.7 ---> SD_CD (Card Detect)
224 ; P2.3 <--- SD_CS (Card Select)
227 BIS.B #SD_CS,&P2DIR ; SD_CS output high
229 ; P2.4 UCA1 CLK ---> SD_CLK
230 ; P2.5 UCA1 TX/SIMO ---> SD_SDI
231 ; P2.6 UCA1 RX/SOMI <--- SD_SDO
232 BIS.B #070h,&P2SEL1 ; Configure UCA1 pins P2.4 as UCA1CLK, P2.5 as UCA1SIMO & P2.6 as UCA1SOMI
233 ; P2DIR.x is controlled by eUSCI_A0 module
234 BIC.B #070h,&P2REN ; disable pullup resistors for SIMO/SOMI/SCK pins
238 BIC #1,&SD_CTLW0 ; release eUSCI from reset
240 ; ===========================================================
241 ; 2- Init all SD_Card variables, handles and SDIB buffer to 0
242 ; ===========================================================
253 ; ===========================================================
255 ; ===========================================================
258 MOV #8,X ; send 64 clk on SD_clk
260 BIC.B #SD_CS,&SD_CSOUT ; set SD_CS output low to switch in SPI mode
261 MOV #4,S ; preset error 4R1
262 SEND_CMD0 ; CMD0 : GO_IDLE_STATE
263 MOV #95h,&SD_CMD_FRM ; $(95 00 00 00 00 00)
264 MOV #4000h,&SD_CMD_FRM+4 ; $(95 00 00 00 00 40); send CMD0
265 MOV #1,W ; expected SPI_R1 response = 1 = idle state
267 JZ INIT_CMD8 ; if idle state
269 MOV #SD_CARD_ERROR,PC ; ReturnError = $04R1, case of defectuous card (or insufficient SD_POWER_ON clk)
270 ; ----------------------------------;
271 INIT_CMD8 ; mandatory if SD_Card >= V2.x [11:8]supply voltage(VHS)
272 ; ----------------------------------;
273 CALL #SPI_GET ; (needed to pass SanDisk ultra 8GB "HC I")
274 CMP.B #-1,W ; FFh expected value <==> MISO = high level
275 JNE INIT_CMD8 ; loop back while yet busy
276 ; ----------------------------------;
277 MOV #8,S ; preset error 8R1 for CMD1
278 MOV #0AA87h,&SD_CMD_FRM ; $(87 AA ...) (CRC:CHECK PATTERN)
279 MOV #1,&SD_CMD_FRM+2 ; $(87 AA 01 00 ...) (CRC:CHECK PATTERN:VHS set as 2.7to3.6V:0)
280 MOV #4800h,&SD_CMD_FRM+4 ; $(87 AA 01 00 00 48)
281 SEND_CMD8 ; CMD8 = SEND_IF_COND
282 MOV #1,W ; expected R1 response (first byte of SPI R7) = 01h : idle state
284 ; ----------------------------------;
285 CMD8_NEXT ; time out occured with SD_Card V1.x and all MMC_card
287 CALL #SPI_X_GET ;WX skip end of SD_Card V2.x type R7 response (4 bytes)
288 ; ----------------------------------;
289 MOV #1,&SD_CMD_FRM ; $(01 00 ... set stop bit
290 MOV #0,&SD_CMD_FRM+2 ; $(01 00 00 00 ...
291 ; MOV.B #16,Y ; init 16 * ACMD41 repeats (power on fails with SanDisk ultra 8GB "HC I" and Transcend 2GB)
292 ; MOV.B #32,Y ; init 32 * ACMD41 repeats ==> ~400ms
293 MOV.B #-1,Y ; init 255 * ACMD41 repeats ==> 3 s
294 ; ----------------------------------;
295 SEND_ACMD41 ; (CMD55+CMD41)
296 ; ----------------------------------;
297 ADD S,S ; preset error 10R1 for ACMD41
298 SEND_CMD55 ; CMD55 = APP_CMD
299 MOV #7700h,&SD_CMD_FRM+4 ; $(01 00 00 00 00 77)
300 MOV #1,W ; expected R1 response = 1 : idle
302 SEND_CMD41 ; CMD41 = APP OPERATING CONDITION
303 MOV #6940h,&SD_CMD_FRM+4 ; $(01 00 00 00 40 69) (30th bit = HCS = High Capacity Support request)
304 CALL #SDbusyLoop ; wait until busy (needed to pass SanDisk ultra 8GB "HC I") then send Command CMD41
305 JZ SetBLockLength ; if SD_Card ready (R1=0)
306 SUB.B #1,Y ; else decr time out delay
307 JNZ SEND_CMD55 ; then loop back while count of repeat not reached
308 JMP SD_INIT_ERROR ; ReturnError on time out : unusable card
309 ; ----------------------------------;
310 setBLockLength ; set block = 512 bytes (buffer size), usefull for FAT16 SD Cards
311 ; ----------------------------------;
312 ADD S,S ; preset error $20 for CMD16
313 SEND_CMD16 ; CMD16 = SET_BLOCKLEN
314 MOV #02h,&SD_CMD_FRM+2 ; $(01 00 02 00 ...)
315 MOV #5000h,&SD_CMD_FRM+4 ; $(01 00 02 00 00 50)
316 CALL #SDbusyLoop ; wait until busy then send CMD16
317 JNZ SD_INIT_ERROR ; if W = R1 <> 0, ReturnError = $20R1 ; send command ko
318 ; ----------------------------------;
319 SetHighSpeed ; end of SD init ==> SD_CLK = SMCLK
320 ; ----------------------------------;
321 BIS #1,&SD_CTLW0 ; Software reset
322 MOV #0,&SD_BRW ; UCxxBRW = 0 ==> SPI_CLK = MCLK
323 BIC #1,&SD_CTLW0 ; release from reset
324 ; ----------------------------------;
325 Read_EBP_FirstSector ; W=0, BS_FirstSectorHL=0
326 ; ----------------------------------;
327 ADD S,S ; preset error $40 ; SD card not FAT16/FAT32
328 CALL #readSectorW ; read physical first sector
330 MOV 454(Y),&BS_FirstSectorL ;
331 MOV 456(Y),&BS_FirstSectorH ;
332 MOV.B 450(Y),W ; W = partition ID
333 ; ----------------------------------;
335 ; ----------------------------------;
336 MOV #1,&FATtype ; preset FAT16
338 SUB.B #6,W ; ID=06h Partition FAT16 using CHS & LBA ?
339 JZ Read_MBR_FirstSector ;
341 SUB.B #8,W ; ID=0Eh Partition FAT16 using LBA ?
342 JZ Read_MBR_FirstSector ;
343 ; ----------------------------------;
344 MOV #2,&FATtype ; set FAT32
346 ADD.B #2,W ; ID=0Ch Partition FAT32 using LBA ?
347 JZ Read_MBR_FirstSector ;
349 ADD.B #1,W ; ID=0Bh Partition FAT32 using CHS & LBA ?
350 JZ Read_MBR_FirstSector ;
352 JNZ SD_INIT_ERROR ; ReturnError = $40xx with xx = partition ID
353 ; ----------------------------------;
354 Read_MBR_FirstSector ; W=0
355 ; ----------------------------------;
356 CALL #readSectorW ; ...with the good bytes/sectors (FAT16/FAT32) CMD17 frame !
357 ; ----------------------------------;
358 FATxx_SetFileSystem ;
359 ; ----------------------------------;
360 MOV.B 13(Y),&SecPerClus ;
361 MOV 14(Y),X ;3 X = BPB_RsvdSecCnt
362 MOV X,&OrgFAT1 ;3 set OrgFAT1
363 MOV 22(Y),W ; W = BPB_FATsize
364 CMP #0,W ; BPB_FATsize = 0 ?
366 MOV 36(Y),W ; W = BPB_FATSz32
368 MOV W,&FATSize ; limited to 16384 sectors....
370 MOV X,&OrgFAT2 ; X = OrgFAT1 + FATsize = OrgFAT2
371 ADD W,X ; X = OrgFAT2 + FATsize = FAT16 OrgRootDir | FAT32 OrgDatas
372 CMP #2,&FATtype ; FAT32?
373 JZ FATxx_SetFileSystemNext ; yes
374 FAT16_SetRootCluster ;
375 MOV X,&OrgRootDIR ; only FAT16 use, is a sector used by ComputeClusFrstSect
376 ADD #32,X ; OrgRootDir + RootDirSize = OrgDatas
377 FATxx_SetFileSystemNext ;
378 SUB &SecPerClus,X ; OrgDatas - SecPerClus*2 = OrgClusters
379 SUB &SecPerClus,X ; no borrow expected
380 MOV X,&OrgClusters ; X = virtual cluster 0 address (clusters 0 and 1 don't exist)
381 MOV &FATtype,&DIRClusterL ; init DIRcluster as RootDIR
382 ; ----------------------------------;