OSDN Git Service

Merge branch 'master' of https://framagit.org/Jean-Mi/FAST-FORTH
[fast-forth/master.git] / forthMSP430FR_SD_LowLvl.asm
index f02f57d..400fd52 100644 (file)
@@ -1,137 +1,6 @@
 ; -*- coding: utf-8 -*-
 ; forthMSP430FR_SD_lowLvl.asm
 
-; Copyright (C) <2017>  <J.M. THOORENS>
-;
-; This program is free software: you can redistribute it and/or modify
-; it under the terms of the GNU General Public License as published by
-; the Free Software Foundation, either version 3 of the License, or
-; (at your option) any later version.
-;
-; This program is distributed in the hope that it will be useful,
-; but WITHOUT ANY WARRANTY; without even the implied warranty of
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-; GNU General Public License for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-; =====================================================================
-; 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       
-; 446 |0x1CE    : partition table 2th record    ==> logical drive 1
-; 446 |0x1DE    : partition table 3th record    ==> logical drive 2
-; 446 |0x1EE    : partition table 4th record    ==> logical drive 3
-
-; partition record content :
-; ---------------------------------------------------
-; dec@|HEX@ =  HEX                                                           decimal
-; 0   |0x00 =  0x00     : not bootable
-; 1   |0x01 =  02 0C 00 : Org Cylinder/Head/Sector offset (CHS-addressing) = not used
-; 4   |0x04 =  0x0E     : type FAT16 using LBA addressing                  = 14 ==> FAT16
-; 5   |0x05 =  ED 3F EE : End Cylinder/Head/Sector offset (CHS-addressing) = not used
-; 8   |0x08 =  00 20 00 00 : sectors offset of logical drive               = 8192
-; 12  |0x0C =  00 40 74 00 : sectors size of logical drive                 = 7618560 sectors
-
-; 450 |0x04 =  0x0E     : type FAT16 using LBA addressing                  = 14 ==> set FATtype = FAT16 with byte CMD addressing
-; 454 |0x1C6 = 89 00    : FirstSector (of logical drive 0) BS_FirstSector  = 137
-
-
-; 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 block 0       
-; 446 |0x1CE    : partition table 2th record    ==> logical block 1
-; 446 |0x1DE    : partition table 3th record    ==> logical block 2
-; 446 |0x1EE    : partition table 4th record    ==> logical block 3
-
-; partition record content :
-; ---------------------------------------------------
-; dec@|HEX@ =  HEX                                                        decimal
-; 0   |0x00 =  0x00     : not bootable
-; 1   |0x01 =  82 03 00 : Org CHS offset (Cylinder/Head/Sector)         = not used
-; 4   |0x04 =  0x0C     : type FAT32 using LBA addressing               = 12 ==> set FATtype = FAT32 with sector CMD addressing
-; 5   |0x05 =  82 03 00 : End offset (Cylinder/Head/Sector offset)      = not used
-; 8   |0x08 =  00 20 00 00 : sectors offset of logical block            = 8192
-; 12  |0x0C =  00 40 74 00 : sectors size of logical block              = 7618560
-
-; 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
-
-
-
 BytsPerSec      .equ 512
 
 ; all sectors are computed as logical, then physically translated at last time by RW_Sector_CMD
@@ -140,13 +9,13 @@ BytsPerSec      .equ 512
 ; ==================================;
 RW_Sector_CMD                       ;WX <=== CMD17 or CMD24 (read or write Sector CMD)
 ; ==================================;
-    BIC.B   #SD_CS,&SD_CSOUT        ; set SD_CS low
-    BIT.B   #SD_CD,&SD_CDIN         ; test CD: memory card present ?
+    BIC.B   #CS_SD,&SD_CSOUT        ; set Chip Select low
+    BIT.B   #CD_SD,&SD_CDIN         ; test Card Detect: memory card present ?
     JZ      ComputePhysicalSector   ; yes
     MOV     #COLD,PC                ; no: force COLD
 ; ----------------------------------;
-ComputePhysicalSector               ;
-; ----------------------------------; input = logical sector...
+ComputePhysicalSector               ; input = logical sector...
+; ----------------------------------;
     ADD     &BS_FirstSectorL,W      ;3
     ADDC    &BS_FirstSectorH,X      ;3
 ; ----------------------------------; ...output = physical sector
@@ -156,10 +25,10 @@ ComputePhysicalSector               ;
     CMP     #2,&FATtype             ;3 FAT32 ?          
     JZ      FAT32_CMD               ;2 yes
 FAT16_CMD                           ;  FAT16 : CMD17/24 byte address = Sector * BPB_BytsPerSec
-    ADD     W,W                     ;  shift left one Sector
-    ADDC.B  X,X                     ;
-    MOV     W,&SD_CMD_FRM+2         ;  $(01 00 ll LL xx CMD)
-    MOV.B   X,&SD_CMD_FRM+4         ;  $(01 00 ll LL hh CMD) 
+    ADD     W,W                     ;1 shift left one Sector
+    ADDC.B  X,X                     ;1
+    MOV     W,&SD_CMD_FRM+2         ;3 $(01 00 ll LL xx CMD)
+    MOV.B   X,&SD_CMD_FRM+4         ;3 $(01 00 ll LL hh CMD) 
     JMP     WaitIdleBeforeSendCMD   ;
 FAT32_CMD                           ;  FAT32 : CMD17/24 sector address
     MOV.B   W,&SD_CMD_FRM+1         ;3 $(01 ll xx xx xx CMD)
@@ -172,11 +41,10 @@ FAT32_CMD                           ;  FAT32 : CMD17/24 sector address
 WaitIdleBeforeSendCMD               ; <=== CMD41, CMD1, CMD16 (forthMSP430FR_SD_INIT.asm)
 ; ==================================;
     CALL #SPI_GET                   ;
-    CMP.B   #-1,W                   ; FFh = expected value <==> MISO = 1 = not busy = idle state
-    JNE WaitIdleBeforeSendCMD       ; loop back until idle state
-    MOV     #0,W                    ; W = expected R1 response = ready, for CMD41,CMD16, CMD17, CMD24
-; ==================================;
-sendCommand                         ;X <=== CMD0, CMD8, CMD55: W = R1 expected response = idle (forthMSP430FR_SD_INIT.asm)
+    ADD.B   #1,W                    ; expected value = FFh <==> MISO = 1 = SPI idle state
+    JNZ WaitIdleBeforeSendCMD       ; loop back if <> FFh
+; ==================================; W = 0 = expected R1 response = ready, for CMD41,CMD16, CMD17, CMD24
+sendCommand                         ;  
 ; ==================================;
                                     ; input : SD_CMD_FRM : {CRC,byte_l,byte_L,byte_h,byte_H,CMD} 
                                     ;         W = expected return value
@@ -189,14 +57,14 @@ Send_CMD_PUT                        ; performs little endian --> big endian conv
     MOV.B   SD_CMD_FRM(X),&SD_TXBUF ;5 
     CMP     #0,&SD_BRW              ;3 full speed ?
     JZ      FullSpeedSend           ;2 yes
-Send_CMD_Loop                       ;
-    BIT     #UCRXIFG,&SD_IFG        ;3 no: case of low speed during memCardInit
+Send_CMD_Loop                       ;  case of low speed during memCardInit
+    BIT     #RX_SD,&SD_IFG          ;3
     JZ      Send_CMD_Loop           ;2
     CMP.B   #0,&SD_RXBUF            ;3 to clear UCRXIFG
 FullSpeedSend                       ;
 ;   NOP                             ;0 NOPx adjusted to avoid SD error
     SUB.B   #1,X                    ;1
-    JHS     Send_CMD_PUT            ;2 U>= : don't skip SD_CMD_FRM(0) !
+    J     Send_CMD_PUT            ;2 U>= : don't skip SD_CMD_FRM(0) !
 
                                     ; host must provide height clock cycles to complete operation
                                     ; here X=255, so wait for CMD return expected value with PUT FFh 256 times
@@ -213,15 +81,22 @@ Wait_Command_Response               ; expect W = return value during X = 255 tim
     MOV.B   #-1,&SD_TXBUF           ;3 PUT FFh
     CMP     #0,&SD_BRW              ;3 full speed ?
     JZ      FullSpeedGET            ;2 yes
-cardResp_Getloop                    ;  no: case of low speed during memCardInit (CMD0,CMD8,ACMD41,CMD16)
-    BIT     #UCRXIFG,&SD_IFG        ;3
+cardResp_Getloop                    ;  case of low speed during memCardInit (CMD0,CMD8,ACMD41,CMD16)
+    BIT     #RX_SD,&SD_IFG          ;3
     JZ      cardResp_Getloop        ;2
 FullSpeedGET                        ;
 ;    NOP                            ;  NOPx adjusted to avoid SD_error
     CMP.B   &SD_RXBUF,W             ;3 return value = ExpectedValue ?
     JNZ     Wait_Command_Response   ;2 16~ full speed loop
 SPI_WAIT_RET                        ; flag Z = 1 <==> Returned value = expected value
-    RET                             ; W = expected value, unchanged
+    MOV @RSP+,PC                    ; W = expected value, unchanged
+; ----------------------------------;
+
+; ----------------------------------;
+sendCommandIdleRet                  ; <=== CMD0, CMD8, CMD55: W = 1 = R1 expected response = idle (forthMSP430FR_SD_INIT.asm)
+; ----------------------------------;
+    MOV     #1,W                    ; expected R1 response (first byte of SPI R7) = 01h : idle state
+    JMP     sendCommand             ;
 ; ----------------------------------;
 
 
@@ -229,21 +104,21 @@ SPI_WAIT_RET                        ; flag Z = 1 <==> Returned value = expected
 ; PUT value must be a word or  byte:byte because little endian to big endian conversion
 
 ; ==================================;
-SPI_GET                             ; PUT(FFh)
-; ==================================; output : W = received byte, X = 0 always
-    MOV #1,X                        ;1
+SPI_GET                             ; PUT(FFh) one time, output : W = received byte, X = 0
+; ==================================;
+    MOV #1,X                        ;
+; ==================================;
+SPI_X_GET                           ; PUT(FFh) X times, output : W = last received byte, X = 0
 ; ==================================;
-SPI_X_GET                           ; PUT(FFh) X times
-; ==================================; output : W = last received byte, X = 0
-    MOV #-1,W                       ;1
+    MOV #-1,W                       ;
 ; ==================================;
-SPI_PUT                             ; PUT(W) X time
-; ==================================; output : W = last received byte, X = 0
-            SWPB W                  ;1
+SPI_PUT                             ; PUT(W) X times, output : W = last received byte, X = 0
+; ==================================;
+            SWPB W                  ;1 
             MOV.B W,&SD_TXBUF       ;3 put W high byte then W low byte and so forth, that performs little to big endian conversion
             CMP #0,&SD_BRW          ;3 full speed ?
             JZ FullSpeedPut         ;2 
-SPI_PUTWAIT BIT #UCRXIFG,&SD_IFG    ;3
+SPI_PUTWAIT BIT #RX_SD,&SD_IFG      ;3
             JZ SPI_PUTWAIT          ;2
             CMP.B #0,&SD_RXBUF      ;3 reset RX flag
 FullSpeedPut
@@ -251,19 +126,12 @@ FullSpeedPut
             SUB #1,X                ;1
             JNZ SPI_PUT             ;2 12~ loop
 SPI_PUT_END MOV.B &SD_RXBUF,W       ;3
-            RET                     ;4
+            MOV @RSP+,PC            ;4
 ; ----------------------------------;
 
+        ASMWORD "READ_SWX"
 ; ==================================;
-readFAT1SectorW                     ; read a FAT1 sector
-; ==================================;
-    ADD     &OrgFAT1,W              ;
-; ==================================;
-readSectorW                         ; read a logical sector up to 65535 (case of FAT1,FAT2)
-; ==================================;
-    MOV     #0,X                    ;
-; ==================================;
-readSectorWX                        ; read a logical sector
+ReadSectorWX                        ; SWX read a logical sector
 ; ==================================;
     BIS     #1,S                    ; preset sd_read error
     MOV.B   #51h,&SD_CMD_FRM+5      ; CMD17 = READ_SINGLE_BLOCK
@@ -273,35 +141,32 @@ readSectorWX                        ; read a logical sector
 WaitFEhResponse                     ; wait SD_Card response FEh
 ; ----------------------------------;
     CALL #SPI_GET                   ;
-    CMP.B   #-2,W                   ; FEh expected value
-    JZ  ReadSectorfirst             ; 2
-    JNZ WaitFEhResponse             ;
+    ADD.B   #2,W                    ;1 FEh expected value
+    JZ  ReadSectorFirstByte         ; 2
+    JNZ WaitFEhResponse             ;2
 ; ----------------------------------;
-ReadSectorLoop                      ; get 512+1 bytes, write 512 bytes
+ReadSectorLoop                      ; get 512+1 bytes, write 512 bytes in SD_BUF
 ; ----------------------------------;
     MOV.B   &SD_RXBUF,SD_BUF-1(X)   ; 5
-ReadSectorfirst                     ;
+ReadSectorFirstByte                 ; 
     MOV.B   #-1,&SD_TXBUF           ; 3 put FF
     NOP                             ; 1 NOPx adjusted to avoid read SD_error
     ADD     #1,X                    ; 1
     CMP     #BytsPerSec+1,X         ; 2
     JNZ     ReadSectorLoop          ; 2 14 cycles loop read byte
 ; ----------------------------------;
-    MOV.B   #-1,&SD_TXBUF           ; 3 put only one FF because first CRC byte is already received...
+    MOV.B #-1,&SD_TXBUF             ; 3 put only one FF because first CRC byte is already received...
 ; ----------------------------------;
 ReadWriteHappyEnd                   ; <==== WriteSector
 ; ----------------------------------;
-    BIC     #3,S                    ; reset read and write errors
-    BIS.B   #SD_CS,&SD_CSOUT        ; SD_CS = high  
-    RET                             ; 
+    BIC #3,S                        ; reset read and write errors
+    BIS.B #CS_SD,&SD_CSOUT          ; Chip Select high
+    MOV @RSP+,PC                    ; 
 ; ----------------------------------;
 
     .IFDEF SD_CARD_READ_WRITE
 
-; ==================================;
-WriteSectorW                        ; write a logical sector up to 65535 (FAT1,FAT2)
-; ==================================;
-    MOV     #0,X                    ;
+        ASMWORD "WRITE_SWX"
 ; ==================================;
 WriteSectorWX                       ; write a logical sector
 ; ==================================;
@@ -321,7 +186,7 @@ WriteSectorLoop                     ; 11 cycles loop write, starts with X = 0
     CMP     #BytsPerSec,X           ; 2
     JNZ     WriteSectorLoop         ; 2
 ; ----------------------------------;
-WriteSkipCRC16                      ; CRC not used in SPI mode
+WriteSkipCRC16                      ; CRC16 not used in SPI mode
 ; ----------------------------------;
     MOV     #3,X                    ; PUT 2 bytes to skip CRC16
     CALL    #SPI_X_GET              ; + 1 byte to get data token in W
@@ -337,14 +202,14 @@ CheckWriteState                     ;
 
 ; SD Error n°
 ; High byte
-; 1  = CMD17    read error
-; 2  = CMD24    write error 
-; 4  = CMD0     time out (GO_IDLE_STATE)
-; 8  = ACMD41   time out (APP_SEND_OP_COND)
-; 10 = CMD16    time out (SET_BLOCKLEN)
-; 20 = not FAT16/FAT32 media, low byte = partition ID
-
-; low byte, if CMD R1 response : |0|7|6|5|4|3|2|1|
+; 1   = CMD17    read error
+; 2   = CMD24    write error 
+; 4   = CMD0     time out (GO_IDLE_STATE)
+; 8   = ACMD41   time out (APP_SEND_OP_COND)
+; $10 = CMD16    time out (SET_BLOCKLEN)
+; $20 = not FAT16/FAT32 media, low byte = partition ID
+
+; low byte, if CMD R1 response : %0xxx_xxxx
 ; 1th bit = In Idle state
 ; 2th bit = Erase reset
 ; 3th bit = Illegal command
@@ -353,28 +218,35 @@ CheckWriteState                     ;
 ; 6th bit = address error
 ; 7th bit = parameter error
 
+; Data Response Token
+; Every data block written to the card will be acknowledged by a data response token. 
+; It is one byte long and has the following format:
+; %xxxx_sss0 with bits(3-1) = Status
+;The meaning of the status bits is defined as follows:
+;'010' - Data accepted.
+;'101' - Data rejected due to a CRC error.
+;'110' - Data Rejected due to a Write Error
+
 ; ----------------------------------;
-SD_CARD_ERROR                       ; <=== SD_INIT errors 4,8,$10
+SD_CARD_ERROR                       ; <=== SD_INIT errors 4,8,$10 from forthMSP430FR_SD_INIT.asm
 ; ----------------------------------;
     SWPB S                          ; High Level error in High byte
-    ADD &SD_RXBUF,S                 ; add SPI(GET) return value to high level error
-SD_CARD_ID_ERROR                    ; <=== SD_INIT error $20
-    BIS.B #SD_CS,&SD_CSOUT          ; SD_CS = high
+    ADD &SD_RXBUF,S                 ; add SPI(GET) return value as low byte error
+SD_CARD_ID_ERROR                    ; <=== SD_INIT error $20 from forthMSP430FR_SD_INIT.asm
+    BIS.B #CS_SD,&SD_CSOUT          ; Chip Select high
     mDOCOL                          ;
-    .word   XSQUOTE                 ;
+    .word   ECHO
+    .word   XSQUOTE                 ; don't use S register
     .byte   11,"< SD Error!"        ;
 ; ----------------------------------;
-SD_QABORTYES                        ; <=== OPEN/READ and WRITE errors
+ABORT_SD                            ; <=== OPEN file errors from forthMSP430FR_SD_LOAD.asm
 ; ----------------------------------;
-    FORTHtoASM                      ;
-    SUB #4,PSP                      ;
-    MOV TOS,2(PSP)                  ;
-    MOV &BASE,0(PSP)                ;
+    .word   $+2                     ;
+    SUB #2,PSP                      ;
+    MOV TOS,0(PSP)                  ;
     MOV #10h,&BASE                  ; select hex
     MOV S,TOS                       ;
     ASMtoFORTH                      ;
-    .word   UDOT                    ;
-    .word   FBASE,STORE             ; restore base
-    .word   QABORTYES               ;
+    .word UDOT,ABORT_TERM           ; no return...
 ; ----------------------------------;