12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237 |
- MODULE Sd;
- (**
- AUTHOR Timothée Martiel, 2015
- PURPOSE SD Card Host Controller Driver
- *)
- IMPORT
- SYSTEM,
- SdEnvironment;
- CONST
- BlockSize * = 512;
- InitialClockFrequency * = 400000; (* Hz *)
- (* Commands *) (*! Do not change values *)
- CMD_GO_IDLE_STATE * = 0; (** CMD0 bc [31:0] stuff bits - *)
- CMD_ALL_SEND_CID * = 2; (** CMD2 bcr [31:0] stuff bits R2 *)
- CMD_SEND_RELATIVE_ADDR * = 3; (** CMD3 bcr [31:0] stuff bits R6 *)
- CMD_SET_DSR * = 4; (** CMD4 bc [31:16] DSR [15:0] stuff bits - *)
- CMD_IO_SEND_OP_COND * = 5; (** CMD5 ?? [31:25] stuff bits [24] switch 1.8V request [23:0] I/O OCR R4 *)
- CMD_SWITCH_FUNC * = 6; (** CMD6 adtc [31] Mode 0:Check function 1:Switch function [30:24] reserved (All '0') [23:20] reserved for function group 6 (0h or Fh) [19:16] reserved for function group 5 (0h or Fh) [15:12] function group 4 for current limit [11:8] funciton group 3 for drive strength [7:4] function group 2 for command system [3:0] function group 1 for access mode R1 *)
- CMD_SELECT_DESELECT_CARD * = 7; (** CMD7 ac [31:16] RCA [15:0] stuff bits R1b (only from the selected card) *)
- CMD_SEND_IF_COND * = 8; (** CMD8 bcr [31:12] reserved bits [11:8] supply voltage(VHS) [7:0]check pattern R7 *)
- CMD_SEND_CSD * = 9; (** CMD9 ac [31:16] RCA [15:0] stuff bits R2 *)
- CMD_SEND_CID * = 10; (** CMD10 ac [31:16] RCA [15:0] stuff bits R2 *)
- CMD_VOLTAGE_SWITCH * = 11; (** CMD11 ac [31:0] reserved bits (all 0) R1 *)
- CMD_STOP_TRANSMISSION * = 12; (** CMD12 ac [31:0] stuff bits R1b *)
- CMD_SEND_STATUS * = 13; (** CMD13 ac [31:16] RCA [15:0] stuff bits R1 *)
- CMD_GO_INACTIVE_STATE * = 15; (** CMD15 ac [31:16] RCA [15:0] reserved bits - *)
- CMD_SET_BLOCKLEN * = 16; (** CMD16 ac [31:0] block length R1 *)
- CMD_READ_SINGLE_BLOCK * = 17; (** CMD17 adtc [31:0] data address2 R1 *)
- CMD_READ_MULTIPLE_BLOCK * = 18; (** CMD18 adtc [31:0] data address2 R1 *)
- CMD_SEND_TUNING_BLOCK * = 19; (** CMD19 adtc [31:0] reserved bits (all 0) R1 *)
- CMD_SPEED_CLASS_CONTROL * = 20; (** CMD20 ac [31:28]Speed Class Control [27:0] Reserved (all-0) R1b *)
- CMD_SET_BLOCK_COUNT * = 23; (** CMD23 ac [31:0] Block Count R1 *)
- CMD_WRITE_BLOCK * = 24; (** CMD24 adtc [31:0] data address2 R1 *)
- CMD_WRITE_MULTIPLE_BLOCK * = 25; (** CMD25 adtc [31:0] data address2 R1 *)
- CMD_PROGRAM_CSD * = 27; (** CMD27 adtc [31:0] stuff bits R1 *)
- CMD_SET_WRITE_PROT * = 28; (** CMD28 ac [31:0] data address2 R1b *)
- CMD_CLR_WRITE_PROT * = 29; (** CMD29 ac [31:0] data address2 R1b *)
- CMD_SEND_WRITE_PROT * = 30; (** CMD30 adtc [31:0] write protect data address2 R1 *)
- CMD_ERASE_WR_BLK_START * = 32; (** CMD32 ac [31:0] data address1 R1 *)
- CMD_ERASE_WR_BLK_END * = 33; (** CMD33 ac [31:0] data address1 R1 *)
- CMD_ERASE * = 38; (** CMD38 ac [31:0] stuff bits R1b *)
- CMD_LOCK_UNLOCK * = 42; (** CMD42 adtc [31:0] Reserved bits (Set all 0) R1 *)
- CMD_APP_CMD * = 55; (** CMD55 ac [31:16] RCA [15:0] stuff bits R1 *)
- CMD_GEN_CMD * = 56; (** CMD56 adtc [31:1] stuff bits. [0] RD/WR R1 *)
- (** Application Commands *) (*! Do Not Change Values *)
- ACMD_SET_BUS_WIDTH * = 6; (** ACMD6 ac [31:2] stuff bits [1:0] bus width R1 *)
- ACMD_SD_STATUS * = 13; (** ACMD13 adtc [31:0] stuff bits R1 *)
- ACMD_SEND_NUM_WR_BLOCKS * = 22; (** ACMD22 adtc [31:0] stuff bits R1 *)
- ACMD_SET_WR_BLK_ERASE_COUNT * = 23; (** ACMD23 ac [31:23] stuff bits [22:0] Number of blocks R1 *)
- ACMD_SD_SEND_OP_COND * = 41; (** ACMD41 bcr [31]reserved bit [30] HCS(OCR[30]) [29] reserved for eSD [28] XPC [27:25] reserved bits [24] S18R [23:0] VDD Voltage Window(OCR[23:0]) R3 *)
- ACMD_SET_CLR_CARD_DETECT * = 42; (** ACMD42 ac [31:1] stuff bits [0] set_cd R1 *)
- ACMD_SEND_SCR * = 51; (** ACMD51 adtc [31:0] stuff bits R1 *)
- (** Errors *)
- ErrorNone * = 0;
- ErrorCmdTimeout * = 1;
- ErrorCmdCrc * = 2;
- ErrorDatTimeout * = 3;
- ErrorDatCrc * = 4;
- ErrorNoCard * = 5;
- ErrorCard * = 6;
- ErrorUnrecoverable * = 7;
- ErrorInvalidParameters * = 8;
- (** Card Versions *)
- Version1 * = 0; (** v1.00 or v1.01 *)
- Version1p1 * = 1; (** v1.10 *)
- Version2 * = 2; (** v2.00 *)
- Version3 * = 3; (** v3.00 *)
- (** Card Type *)
- TypeNone * = 0;
- TypeSDSC * = 1;
- TypeSDHC * = 2;
- TypeSDXC * = 3;
- (** Card Events *)
- OnInitialization * = 0;
- OnRemoval * = 1;
- OnReadComplete * = 2;
- OnWriteComplete * = 3;
- (** Command Record Flags *)
- FlagData * = 0;
- FlagRead * = 1;
- FlagAutoCmd12 * = 2;
- FlagAutoCmd23 * = 3;
- FlagMultipleBlockTx * = 4;
- FlagCountBlocks * = 5;
- FlagUseDma * = 6;
- FlagAbort * = 7;
- FlagApplicationCmd * = 8;
- FlagIgnoreIllegalCmd * = 9;
- (** Response Types *) (*! Do not change values *)
- ResponseNone * = -1;
- ResponseR1 * = 0;
- ResponseR1b * = 1;
- ResponseR2 * = 2;
- ResponseR3 * = 3;
- ResponseR4 * = 4;
- ResponseR5 * = 5;
- ResponseR5b * = 6;
- ResponseR6 * = 7;
- ResponseR7 * = 8;
- (** Card States *)
- CardIdle = 0;
- CardReady = 1;
- CardIdentification = 2;
- CardStandby = 3;
- CardTransfer = 4;
- CardData = 5;
- CardReceive = 6;
- CardProgram = 7;
- CardDisabled = 8;
- (** Operation modes *)
- OpCpu = 0;
- OpSdma = 1;
- OpAdma = 2;
- (* Present State bits *)
- PresentState_CommandInhibitCmd = 0;
- PresentState_CommandInhibitDat = 1;
- PresentState_DatLineActive = 2;
- PresentState_RetuningRequest = 3;
- PresentState_WriteTransferActive = 8;
- PresentState_ReadTransferActive = 9;
- PresentState_BufferWriteEnable = 10;
- PresentState_BufferReadEnable = 11;
- PresentState_CardInserted = 16;
- PresentState_CardStateStable = 17;
- PresentState_CardDetectPinLevel = 18;
- PresentState_WriteProtectSwitchPinLevel = 19;
- PresentState_CmdLineSignalLevel = 24;
- PresentState_DatLineSignalLevelOfs = 20;
- PresentState_DatLineSignalLevelMask = {20 .. 23};
- (* Interrupt Status, Status Enable, Signal Enable bits *)
- Interrupt_Normal_CommandComplete = 0;
- Interrupt_Normal_TransferComplete = 1;
- Interrupt_Normal_BlockGapEvent = 2;
- Interrupt_Normal_DmaInterrupt = 3;
- Interrupt_Normal_BufferWriteReady = 4;
- Interrupt_Normal_BufferReadReady = 5;
- Interrupt_Normal_CardInsertion = 6;
- Interrupt_Normal_CardRemoval = 7;
- Interrupt_Normal_CardInterrupt = 8;
- Interrupt_Normal_IntA = 9;
- Interrupt_Normal_IntB = 10;
- Interrupt_Normal_IntC = 11;
- Interrupt_Normal_RetuningEvent = 12;
- Interrupt_Normal_ErrorInterrupt = 15;
- Interrupt_Error_CommandTimeout = 16;
- Interrupt_Error_CommandCrc = 17;
- Interrupt_Error_CommandEndBit = 18;
- Interrupt_Error_CommandIndex = 19;
- Interrupt_Error_DataTimeout = 20;
- Interrupt_Error_DataCrc = 21;
- Interrupt_Error_DataEndBit = 22;
- Interrupt_Error_CurrentLimit = 23;
- Interrupt_Error_AutoCmd12 = 24;
- Interrupt_Error_Adma = 25;
- Interrupt_Error_Tuning = 26;
- Interrupt_Normal_All = {Interrupt_Normal_CommandComplete, Interrupt_Normal_TransferComplete, Interrupt_Normal_BlockGapEvent, Interrupt_Normal_DmaInterrupt,
- Interrupt_Normal_BufferWriteReady, Interrupt_Normal_BufferReadReady, Interrupt_Normal_CardInsertion, Interrupt_Normal_CardRemoval,
- Interrupt_Normal_CardInterrupt, Interrupt_Normal_IntA, Interrupt_Normal_IntB, Interrupt_Normal_IntC, Interrupt_Normal_RetuningEvent,
- Interrupt_Normal_ErrorInterrupt};
- Interrupt_Error_All = {Interrupt_Error_CommandTimeout, Interrupt_Error_CommandCrc, Interrupt_Error_CommandEndBit,
- Interrupt_Error_CommandIndex, Interrupt_Error_DataTimeout, Interrupt_Error_DataCrc, Interrupt_Error_DataEndBit, Interrupt_Error_CurrentLimit,
- Interrupt_Error_AutoCmd12, Interrupt_Error_Adma, Interrupt_Error_Tuning};
- Interrupt_All = Interrupt_Normal_All + Interrupt_Error_All;
- (* Transfer Mode Register bits *)
- TransferMode_DmaEnable = 0;
- TransferMode_BlockCountEnable = 1;
- TransferMode_AutoCmdOfs = 2;
- TransferMode_AutoCmdMask = {2 .. 3};
- TransferMode_DataTxDirection = 4;
- TransferMode_MultipleBlocks = 5;
- TransferMode_AutoCmd_None = {};
- TransferMode_AutoCmd_Cmd12 = {2};
- TransferMode_AutoCmd_Cmd23 = {3};
- (* Command Register bits *)
- Command_ResponseTypeOffset = 0;
- Command_CrcCheckEnable = 3;
- Command_IndexCheckEnable = 4;
- Command_DataPresent = 5;
- Command_CommandTypeOffset = 6;
- Command_CommandTypeMask = {6 .. 7};
- Command_CommandIndexOffset = 8;
- Command_CommandIndexMask = {8 .. 13};
- Command_ResponseType_None = 0;
- Command_ResponseType_136b = 1;
- Command_ResponseType_48b = 2;
- Command_ResponseType_48bBusy = 3;
- (* Capabilities Register *)
- (* Low Word *)
- Capabilities_TimeoutClockFrequencyOfs = 0;
- Capabilities_TimeoutClockFrequencyMask = {0 .. 5};
- Capabilities_TimeoutClockUnit = 7;
- Capabilities_BaseClockFreqSdOfs = 8;
- Capabilities_BaseClockFreqSdMask = {8 .. 15};
- Capabilities_MaxBlockLenOfs = 16;
- Capabilities_MaxBlockLenMask = {16 .. 17};
- Capabilities_8BitEmbedded = 18;
- Capabilities_ADMA2 = 19;
- Capabilities_HighSpeed = 21;
- Capabilities_SDMA = 22;
- Capabilities_SuspendResume = 23;
- Capabilities_Voltage33 = 24;
- Capabilities_Voltage30 = 25;
- Capabilities_Voltage18 = 26;
- Capabilities_64BitBus = 28;
- Capabilities_AsyncInterrupt = 29;
- Capabilities_SlotTypeOfs = 30;
- Capabilities_SlotTypeMask = {30 .. 31};
- (* High Word *)
- Capabilities_SDR50 = 0;
- Capabilities_SDR104 = 1;
- Capabilities_DDR50 = 2;
- Capabilities_DriverTypeA = 4;
- Capabilities_DriverTypeC = 5;
- Capabilities_DriverTypeD = 6;
- Capabilities_TimerCountRetuningOfs = 8;
- Capabilities_TimerCountRetuningMask = {8 .. 11};
- Capabilities_TuningSDR50 = 13;
- Capabilities_RetuningModesOfs = 14;
- Capabilities_RetuningModesMask = {14 .. 15};
- Capabilities_ClockMultiplierOfs = 16;
- Capabilities_ClockMultiplierMask = {16 .. 23};
- (* Patterns *)
- Capabilities_SlotType_Removable = {};
- Capabilities_SlotType_Embedded = {30};
- Capabilities_SlotType_SharedBus = {31};
- (* Host Control 1 register values *)
- HostControl1_LedControl = 0;
- HostControl1_DataWidthTransfer = 1;
- HostControl1_HighSpeedEnable = 2;
- HostControl1_DmaSelectOfs = 3;
- HostControl1_DmaSelectMask = {3 .. 4};
- HostControl1_ExtendedDataTxWidth = 5;
- HostControl1_CardDetectTestLevel = 6;
- HostControl1_CardDetectSignalSelection = 7;
- HostControl1_DmaSelect_Sdma = {};
- HostControl1_DmaSelect_32Adma = {4};
- (* SoftwareReset register values *)
- SoftwareResetAll = 1;
- SoftwareResetCmd = 2;
- SoftwareResetDat = 4;
- (* Clock Control register values *)
- ClockControl_InternalClockEnable = 0;
- ClockControl_InternalClockState = 1;
- ClockControl_SdClockEnable = 2;
- ClockControl_ClockGeneratorSelect = 5;
- ClockControl_SdClockFreqUpperOfs = 6;
- ClockControl_SdClockFreqUpperMask = {6, 7};
- ClockControl_SdClockFreqOfs = 8;
- ClockControl_SdClockFreqMask = {8 .. 15};
- (* Power Control register values *)
- PowerControl_SDBusPower = 0;
- PowerControl_SDBusVoltageOfs = 1;
- PowerControl_SDBusVoltageMask = {1 .. 3};
- PowerControl_SDBusVoltage_18 = {1, 3};
- PowerControl_SDBusVoltage_30 = {2, 3};
- PowerControl_SDBusVoltage_33 = {1, 2, 3};
- (* Host Controller Version *)
- HostControllerVersion_SpecificationMask = {0 .. 7};
- HostControllerVersion_VendorOfs = 8;
- HostControllerVersion_VendorMask = {8 .. 15};
- (* Card Status register -- R1 *)
- CardStatus_AkeSpecError = 3;
- CardStatus_AppCmd = 5;
- CardStatus_ReadyForData = 8;
- CardStatus_CurrentStateOffset = 9;
- CardStatus_CurrentStateMask = {9 .. 12};
- CardStatus_EraseReset = 13;
- CardStatus_CardEccDisable = 14;
- CardStatus_WpEraseSkip = 15;
- CardStatus_CsdOverwrite = 16;
- CardStatus_Error = 19;
- CardStatus_CcError = 20;
- CardStatus_CardEccFailed = 21;
- CardStatus_IllegalCommand = 22;
- CardStatus_ComCrcError = 23;
- CardStatus_LockUnlockFailed = 24;
- CardStatus_CardIsLocked = 25;
- CardStatus_WpViolation = 26;
- CardStatus_EraseParam = 27;
- CardStatus_EraseSeqError = 28;
- CardStatus_BlockLenError = 29;
- CardStatus_AddressError = 30;
- CardStatus_OutOfRange = 31;
- (* OCR Registers *)
- CardOcr_Vdd27_28 = 15;
- CardOcr_Vdd28_29 = 16;
- CardOcr_Vdd29_30 = 17;
- CardOcr_Vdd30_31 = 18;
- CardOcr_Vdd31_32 = 19;
- CardOcr_Vdd32_33 = 20;
- CardOcr_Vdd33_34 = 21;
- CardOcr_Vdd34_35 = 22;
- CardOcr_Vdd35_36 = 23;
- CardOcr_S18A = 24;
- CardOcr_CardCapacityStatus = 30;
- CardOcr_PowerUpStatus = 31;
- (* CSD Register. This excludes the CRC7 of the specifications. *)
- CardCsd_FileFormatOfs = 2;
- CardCsd_FileFormatWidth = 2;
- CardCsd_TmpWriteProtect = 4;
- CardCsd_PermWriteProtect = 5;
- CardCsd_Copy = 6;
- CardCsd_FileFormatGrp = 7;
- CardCsd_WriteBlPartial = 13;
- CardCsd_WriteBlLenOfs = 14;
- CardCsd_WriteBlLenWidth = 4;
- CardCsd_R2wFactorOfs = 18;
- CardCsd_R2wFactorWidth = 3;
- CardCsd_WpGrpEnable = 23;
- CardCsd_WpGrpSizeOfs = 24;
- CardCsd_WpGrpSizeWidth = 7;
- CardCsd_SectorSizeOfs = 31;
- CardCsd_SectorSizeWidth = 7;
- CardCsd_EraseBlkEn = 38;
- CardCsd_CSizeMultOfs1 = 39; (** V1 *)
- CardCsd_CSizeMultWidth1 = 3; (** V1 *)
- CardCsd_VddWCurrMaxOfs1 = 42; (** V1 *)
- CardCsd_VddWCurrMaxWidth1 = 3; (** V1 *)
- CardCsd_VddWCurrMinOfs1 = 45; (** V1 *)
- CardCsd_VddWCurrMinWidth1 = 3; (** V1 *)
- CardCsd_VddRCurrMaxOfs1 = 48; (** V1 *)
- CardCsd_VddRCurrMaxWidth1 = 3; (** V1 *)
- CardCsd_VddRCurrMinOfs1 = 51; (** V1 *)
- CardCsd_VdddRCurrMaxWidth1 = 3; (** V1 *)
- CardCsd_CSizeOfs1 = 54; (** V1 *)
- CardCsd_CSizeWidth1 = 12; (** V1 *)
- CardCsd_CSizeOfs2 = 40; (** V2 *)
- CardCsd_CSizeWidth2 = 22; (** V2 *)
- CardCsd_DsrImp = 68;
- CardCsd_ReadBlkMisalign = 69;
- CardCsd_WriteBlkMisalign = 70;
- CardCsd_ReadBlPartial = 71;
- CardCsd_ReadBlLenOfs = 72;
- CardCsd_ReadBlLenWidth = 4;
- CardCsd_CccOfs = 76;
- CardCsd_CccWidth = 12;
- CardCsd_TranSpeedOfs = 88;
- CardCsd_TranSpeedWidth = 8;
- CardCsd_NsacOfs = 96;
- CardCsd_NsacWidth = 8;
- CardCsd_TaacOfs = 104;
- CardCsd_TaacWidth = 8;
- CardCsd_CsdStructureOfs = 118;
- CardCsd_CsdStructureWidth = 2;
- (* SCR Register *)
- CardScr_CommandSupportOfs = 32;
- CardScr_CommandSupportWidth = 2;
- CardScr_ExtendedSecurityOfs = 43;
- CardScr_ExtendedSecurityWidth = 4;
- CardScr_SpecV3 = 47;
- CardScr_SdBusWidthsOfs = 48;
- CardScr_SdBusWidthsWidth = 4;
- CardScr_SecurityOfs = 52;
- CardScr_SecurityWidth = 3;
- CardScr_DataStateAfterErase = 55;
- CardScr_SdSpecVersionOfs = 56;
- CardScr_SdSpecVersionWidth = 4;
- CardScr_StructureOfs = 60;
- CardScr_StructureWidth = 4;
- (* SCR register fields values *)
- CardScr_SdBusWidths_1 = 0;
- CardScr_SdBusWidths_4 = 2;
- (* Transfer options *)
- TxDma = TRUE; (** Use DMA for transfers on all hosts that support it *)
- TxBufferSize = 4096; (** Buffer size used for DMA transfers *)
- TxBufferAlign = 32; (** Alignment requirement on DMA buffer: here cache line size of ARM *)
- (* Multi-threading *)
- Synchronize * = FALSE; (** Do we need to take care of concurrency? *)
- (* Tracing options for debugging *)
- TraceCmd = FALSE;
- Trace = FALSE;
- TYPE
- (** Interface for data command execute method of host controller *)
- CommandExecuter * = PROCEDURE (CONST command: Command; VAR data: ARRAY OF CHAR; ofs, len: LONGINT; VAR result: LONGINT): BOOLEAN;
- (**
- SD Host controller descriptor.
- *)
- HostController * = POINTER TO HostControllerDesc;
- HostControllerDesc * = RECORD
- baseFrequency -, (** Base hc clock frequency *)
- frequency -, (** Bus frequency *)
- timeoutFreq, (** Timeout clock frequency *)
- state -, (** HC state *)
- version -: LONGINT; (** Specifications version *)
- execute -: CommandExecuter; (** Method to execute command with data transmission *)
- opmode, (** Host controller operation mode for data transfers *)
- lastRca: LONGINT; (** Last RCA selected by the controller. *)
- acquire *, release *: PROCEDURE {DELEGATE};
- handle: EventHandler; (** Card event handler *)
- handlerParam: ANY; (** Parameter of the eventHandler *)
- regs: HcRegisters; (** Memory-mapped I/O registers *)
- cards: Card; (** List of cards on this HC *)
- next: HostController; (** Linked list of controllers for interrupt handling *)
- dmaBuf: POINTER TO ARRAY OF CHAR;
- dmaBufAdr: ADDRESS;
- desc: ARRAY 5 OF HUGEINT; (** DMA descriptor *)
- descOfs: LONGINT;
- END;
- (**
- Command record.
- This record type is used to describe a command and its result.
- To execute a command, fill in the fields 'hc', 'command', 'argument', 'responseType'.
- If the command uses the DAT line or is an application command, setup then necessary flags.
- If the command is an application command, you also need to specify the RCA for CMD55.
- After command execution, you can read the command response in the 'response' field. Use the
- 'GetR*' procedures to extract all information from this field in a convenient way.
- *)
- Command * = RECORD
- hc *: HostController; (** Host controller on which the command is executed *)
- rca *, (** Optional RCA parameter. Required only for ACMDs *)
- command *, (** Command number *)
- argument *, (** Command argument *)
- responseType *: LONGINT; (** Response type *)
- flags *: SET; (** Command flags *)
- response *: ARRAY 4 OF LONGINT; (** Response *)
- END;
- (** Card descriptor *)
- Card * = POINTER TO CardDesc;
- CardDesc * = RECORD
- state -, (** Card state. Currently not used *)
- (*type -, (** Type of card. One of 'Type*' constants *)*)
- rca -: LONGINT; (** Card RCA *)
- cid: ARRAY 4 OF LONGINT; (** Raw CID *)
- csd -: Csd; (** CSD *)
- scr -: Scr; (** SCR *)
- ocr: SET; (** Raw OCR *)
- hc -: HostController; (** Host controller on which the card is attached *)
- next: Card; (** Internal linked list of cards attached to the same HC *)
- acquire *, release *: PROCEDURE {DELEGATE};
- END;
- (* Card Registers *)
- Csd * = RECORD
- (* Card properties *)
- capacity *: HUGEINT; (** Card capacity in bytes *)
- sectorSize *: LONGINT; (** Size of a sector in bytes *)
- commandClasses *: SET; (** Command classes supported by the card *)
- (* Timing info *)
- r2w *: LONGINT; (** Read to write time factor = read time / write time *)
- taac *: REAL; (** Asynchronous access time, in s *)
- nsac *: LONGINT; (** Worst-case clock dependent access time, in clock cycles *)
- txSpeed *: LONGINT; (** Max transfer speed in bit/s *)
- END;
- (** SCR register *)
- Scr * = RECORD
- version *, (** Card physical spec. version: one of Version* *)
- security *: LONGINT; (** Card security type: one of Type* *)
- busWidth *: SET; (** Bus widths supported by the card *)
- END;
- (** SWITCH_FUNC returned status *)
- SwitchFuncStatus * = RECORD
- current *: LONGINT; (** Current for specified config *)
- functionGroups *: ARRAY 6 OF SET; (** Supported function in each group *)
- functionStatus *: ARRAY 6 OF LONGINT; (** Function status *)
- END;
- (** Card event handler. 'card' is the card for which an event is reported (can be a new card object) and 'event' is one of 'On*' constants *)
- EventHandler * = PROCEDURE {DELEGATE} (card: Card; event: LONGINT; param: ANY);
- (** Host controller registers *)
- HcRegisters = POINTER {UNSAFE,UNTRACED} TO RECORD
- SDMASystemAddress {ALIGNED(1)}: LONGINT; (** offset = 0H *)
- BlockSize {ALIGNED(1)}, (** offset = 4H *)
- BlockCount {ALIGNED(1)}: INTEGER; (** offset = 6H *)
- Argument1 {ALIGNED(1)}: LONGINT; (** offset = 8H *)
- TransferMode {ALIGNED(1)}, (** offset = 0CH *)
- Command {ALIGNED(1)}: INTEGER; (** offset = 0EH *)
- Response {ALIGNED(1)}: ARRAY 4 OF LONGINT; (** offset = 10H *)
- BufferData {ALIGNED(1)}: LONGINT;
- PresentState {ALIGNED(1)}: SET;
- HostControl1 {ALIGNED(1)},
- PowerControl {ALIGNED(1)},
- BlockGapControl {ALIGNED(1)},
- WakeupControl {ALIGNED(1)}: SHORTINT;
- ClockControl {ALIGNED(1)}: INTEGER;
- TimeoutControl {ALIGNED(1)},
- SoftwareReset {ALIGNED(1)}: SHORTINT;
- InterruptStatus {ALIGNED(1)},
- InterruptStatusEnable {ALIGNED(1)},
- InterruptSignalEnable {ALIGNED(1)}: SET;
- AutoCmdErrorStatus {ALIGNED(1)},
- HostControl2 {ALIGNED(1)}: INTEGER;
- Capabilities {ALIGNED(1)}: ARRAY 2 OF SET;
- MaximumCurrentCapabilities {ALIGNED(1)}: HUGEINT;
- ForceEventAutoCmdErrorStatus {ALIGNED(1)},
- ForceEventErrorInterruptStatus {ALIGNED(1)}: INTEGER;
- AdmaErrorStatus {ALIGNED(1)}: SHORTINT;
- padding0 {ALIGNED(1)}: ARRAY 3 OF SHORTINT;
- AdmaSystemAddress {ALIGNED(1)}: HUGEINT;
- PresetValues {ALIGNED(1)}: ARRAY 8 OF INTEGER;
- padding1 {ALIGNED(1)}: ARRAY 28 OF LONGINT;
- SharedBusControl {ALIGNED(1)}: LONGINT;
- padding2 {ALIGNED(1)}: ARRAY 6 OF LONGINT;
- SlotInterruptStatus {ALIGNED(1)},
- HostControllerVersion {ALIGNED(1)}: INTEGER;
- END;
- VAR
- (** List of all host controllers *)
- hcs: HostController;
- (* ==================== Host Controller (Low-Level) Interface ==================== *)
- (**
- Create an host controller descriptor and initializes it with the given info.
- 'baseAddress' is the base address of the IO registers.
- 'extClockFreq' is an optional external clock frequency. It is used iff the host controller has no information about its clock frequency.
- 'handler' is the event handler and 'param' is user parameter.
- *)
- PROCEDURE New * (baseAddress: ADDRESS; extClockFreq: LONGINT; handler: EventHandler; param: ANY): HostController;
- VAR
- hc: HostController;
- val, result: LONGINT;
- BEGIN
- NEW(hc);
- hc.regs := baseAddress;
- hc.handle := handler;
- IF ~Reset(hc, TRUE, TRUE) THEN RETURN NIL END;
- hc.baseFrequency := LSH(SYSTEM.VAL(LONGINT, hc.regs.Capabilities[0] * Capabilities_BaseClockFreqSdMask), -Capabilities_BaseClockFreqSdOfs);
- IF hc.baseFrequency = 0 THEN
- hc.baseFrequency := extClockFreq
- END;
- hc.timeoutFreq := LSH(SYSTEM.VAL(LONGINT, hc.regs.Capabilities[0] * Capabilities_TimeoutClockFrequencyMask), -Capabilities_TimeoutClockFrequencyOfs) * 1000;
- IF Capabilities_TimeoutClockUnit IN hc.regs.Capabilities[0] THEN hc.timeoutFreq := hc.timeoutFreq * 1000 END;
- IF hc.timeoutFreq = 0 THEN hc.timeoutFreq := extClockFreq END;
- SetBusClock(hc, InitialClockFrequency);
- SetTimeout(hc, 10);
- (* Power select 3.3V bus voltage *)
- hc.regs.PowerControl := SYSTEM.VAL(SHORTINT, PowerControl_SDBusVoltage_33 + {PowerControl_SDBusPower});
- (* Enable All Interrupts *)
- hc.regs.InterruptStatusEnable := Interrupt_All;
- hc.regs.InterruptSignalEnable := {Interrupt_Normal_CardInsertion, Interrupt_Normal_CardRemoval};
- hc.regs.BlockGapControl := 0;
- val := LONGINT(hc.regs.HostControllerVersion);
- hc.version := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, val) * HostControllerVersion_SpecificationMask) + 1;
- IF Trace THEN
- SdEnvironment.String("[SD] New Host Controller v");
- SdEnvironment.Int(hc.version, 0);
- SdEnvironment.String(" at ");
- SdEnvironment.Address(baseAddress);
- SdEnvironment.Ln;
- END;
- IF Synchronize THEN SdEnvironment.GetLock(hc.acquire, hc.release) END;
- (* Select method according to DMA support *)
- IF TxDma THEN
- IF (Capabilities_ADMA2 IN hc.regs.Capabilities[0]) THEN
- hc.execute := ExecuteAdmaCommand;
- hc.opmode := OpAdma;
- INC(hc.regs.HostControl1, 10H);
- NEW(hc.dmaBuf, TxBufferSize + TxBufferAlign);
- hc.dmaBufAdr := ADDRESSOF(hc.dmaBuf[0]) + (TxBufferAlign) - ADDRESSOF(hc.dmaBuf[0]) MOD (TxBufferAlign);
- hc.descOfs := (TxBufferAlign - ADDRESSOF(hc.desc[0]) MOD TxBufferAlign) DIV SIZEOF(HUGEINT);
- ASSERT(hc.dmaBufAdr MOD TxBufferAlign = 0);
- (*! NOT IMPLEMENTED YET *)(*ELSIF (Capabilities_SDMA IN hc.regs.Capabilities[0]) THEN
- SdEnvironment.String("[SD] Host Controller uses SDMA");
- SdEnvironment.Ln;
- hc.execute := ExecuteAdmaCommand;
- hc.opmode := OpSdma*)
- ELSE
- hc.execute := ExecuteDataCommand;
- hc.opmode := OpCpu
- END
- ELSE
- hc.execute := ExecuteDataCommand;
- hc.opmode := OpCpu
- END;
- (* If there is a card already, initialize it *)
- IF (PresentState_CardInserted IN hc.regs.PresentState) & (PresentState_CardStateStable IN hc.regs.PresentState) THEN
- NEW(hc.cards);
- IF InitCard(hc, hc.cards, result) & (hc.handle # NIL) THEN
- hc.handle(hc.cards, OnInitialization, hc.handlerParam)
- ELSIF hc.handle # NIL THEN
- SdEnvironment.String("[SD] Could not initialize inserted card: error ");
- SdEnvironment.Int(result, 0);
- SdEnvironment.Ln
- END
- END;
- hc.next := hcs;
- hcs := hc;
- RETURN hc
- END New;
- (**
- Execute the command 'command', without data transfer. If you need data transfer, use 'ExecuteDataCommand'.
- Performs all necessary steps for executing a command:
- o Runs CMD55 if command is an application command
- o Execute the command
- o Wait for response
- *)
- PROCEDURE ExecuteCommand * (VAR command: Command; VAR result: LONGINT): BOOLEAN;
- VAR
- status, r1: SET;
- BEGIN
- IF Synchronize THEN command.hc.acquire END;
- result := ErrorNone;
- (* Check Parameters *)
- IF {FlagData, FlagRead, FlagAutoCmd12, FlagAutoCmd23, FlagMultipleBlockTx, FlagCountBlocks, FlagUseDma} * command.flags # {} THEN
- result := ErrorInvalidParameters;
- IF Synchronize THEN command.hc.release END;
- RETURN FALSE
- END;
- (*IF ~Reset(command.hc, TRUE, FALSE) THEN
- result := ErrorCard;
- IF Synchronize THEN command.hc.release END;
- RETURN FALSE
- END;*)
- IF (FlagApplicationCmd IN command.flags) THEN
- IF ~StartCommand(command.hc, CMD_APP_CMD, LSH(command.rca, 16), ResponseR1, FlagRead IN command.flags, FALSE, FALSE, FALSE, status, result) THEN
- IF Synchronize THEN command.hc.release END;
- RETURN FALSE
- END;
- r1 := GetR1(command);
- IF Trace THEN PrintCardStatus(r1) END;
- IF ~(FlagIgnoreIllegalCmd IN command.flags) & (CardStatus_Error IN r1) THEN
- result := ErrorCard;
- IF Synchronize THEN command.hc.release END;
- RETURN FALSE
- END
- END;
- IF ~StartCommand(
- command.hc, command.command, command.argument, command.responseType, FlagRead IN command.flags, FALSE,
- FALSE (*command.responseType = ResponseR1b*), FlagAbort IN command.flags, status, result) THEN
- IF Synchronize THEN command.hc.release END;
- RETURN FALSE
- END;
- GetResponse(command.hc, command.responseType, command.response);
- IF command.command = CMD_SELECT_DESELECT_CARD THEN
- command.hc.lastRca := LSH(command.argument, -16)
- ELSIF command.command = CMD_GO_IDLE_STATE THEN
- command.hc.lastRca := 0
- END;
- IF Synchronize THEN command.hc.release END;
- RETURN TRUE
- END ExecuteCommand;
- (**
- Execute command with data transfer using CPU.
- Data is read from/written to [data[ofs], data[ofs + len]).
- *)
- PROCEDURE ExecuteDataCommand (CONST command: Command; VAR data: ARRAY OF CHAR; ofs, len: LONGINT; VAR result: LONGINT): BOOLEAN;
- TYPE
- DataBytes = ARRAY 4 OF CHAR;
- VAR
- tmp: DataBytes;
- i, stepLen: LONGINT;
- hc: HostController;
- r1, status: SET;
- BEGIN
- ASSERT(ofs + len <= LEN(data), 7);
- result := ErrorNone;
- IF ~(FlagData IN command.flags) THEN
- result := ErrorInvalidParameters;
- RETURN FALSE
- END;
- hc := command.hc;
- IF Synchronize THEN hc.acquire END;
- (* Set timeout *)
- (*SetTimeout(hc, 2);*)
- (*IF (*~Reset(hc, TRUE, FALSE) OR*) ~Reset(hc, FALSE, TRUE) THEN
- result := ErrorCard;
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END;*)
- IF (FlagApplicationCmd IN command.flags) THEN
- IF ~StartCommand(hc, CMD_APP_CMD, LSH(command.rca, 16), ResponseR1, FlagRead IN command.flags, FALSE, FALSE, FALSE, status, result) THEN
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END;
- r1 := SYSTEM.VAL(SET, command.response[0]);
- IF CardStatus_Error IN r1 THEN
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END;
- IF Trace THEN
- SdEnvironment.String("[SD] CMD55 Status:");
- SdEnvironment.Ln;
- PrintCardStatus(r1)
- END
- END;
- (* 1 *)
- IF ~(FlagApplicationCmd IN command.flags) &
- ((command.command = CMD_READ_SINGLE_BLOCK) OR (command.command = CMD_READ_MULTIPLE_BLOCK) OR
- (command.command = CMD_WRITE_BLOCK) OR (command.command = CMD_WRITE_MULTIPLE_BLOCK) OR
- (command.command = 53)(* SDIO Command *)) THEN
- IF len <= BlockSize THEN
- hc.regs.BlockSize := INTEGER(len);
- hc.regs.BlockCount := 1
- ELSE
- hc.regs.BlockSize := BlockSize;
- hc.regs.BlockCount := INTEGER(len DIV BlockSize)
- END;
- IF Trace THEN
- SdEnvironment.String("[SD] ");
- IF FlagRead IN command.flags THEN SdEnvironment.String("Read")
- ELSE SdEnvironment.String("Write") END;
- SdEnvironment.String(" parameters:"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Block Size = "); SdEnvironment.Int(hc.regs.BlockSize, 0); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Block Count = "); SdEnvironment.Int(hc.regs.BlockCount, 0); SdEnvironment.Ln;
- SdEnvironment.String("[SD] CMD"); SdEnvironment.Int(command.command, 0); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Argument = "); SdEnvironment.Address(command.argument); SdEnvironment.Ln
- END
- END;
- (* 3 - 8 *)
- (*IF (hc.regs.BlockSize < BlockSize) THEN
- IF ~StartCommand(hc, CMD_SET_BLOCKLEN, hc.regs.BlockSize, ResponseR1, FALSE, FALSE, result) THEN
- RETURN FALSE
- END
- END;*)
- IF ~StartCommand(hc, command.command, command.argument, ResponseR1, FlagRead IN command.flags, FALSE, TRUE, FALSE, status, result) THEN RETURN FALSE END;
- r1 := SYSTEM.VAL(SET, command.response[0]);
- IF CardStatus_Error IN r1 THEN
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END;
- IF Trace THEN PrintCardStatus(r1) END;
- WHILE len > 0 DO
- (* 14 *)
- IF FlagRead IN command.flags THEN
- REPEAT UNTIL (Interrupt_Normal_BufferReadReady IN hc.regs.InterruptStatus) OR (Interrupt_Normal_ErrorInterrupt IN hc.regs.InterruptStatus)
- ELSE
- REPEAT UNTIL (Interrupt_Normal_BufferWriteReady IN hc.regs.InterruptStatus) OR (Interrupt_Normal_ErrorInterrupt IN hc.regs.InterruptStatus)
- END;
- IF Interrupt_Normal_ErrorInterrupt IN hc.regs.InterruptStatus THEN
- IF ErrorRecovery(hc, result, status) THEN END;
- IF Interrupt_Error_DataTimeout IN status THEN
- result := ErrorDatTimeout
- ELSIF Interrupt_Error_DataCrc IN status THEN
- result := ErrorDatCrc
- ELSIF Interrupt_Error_DataEndBit IN status THEN
- result := ErrorCard
- END;
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END;
- (* 15 *)
- INCL(hc.regs.InterruptStatus, Interrupt_Normal_BufferReadReady);
- (* 16 *)
- stepLen := MIN(BlockSize, len);
- IF FlagRead IN command.flags THEN
- FOR i := 0 TO stepLen - 1 BY 4 DO
- SYSTEM.PUT32(ADDRESSOF(data[ofs + i]), hc.regs.BufferData);
- (*SYSTEM.VAL(LONGINT, tmp) := hc.regs.BufferData;
- SYSTEM.VAL(DataBytes, data[ofs + i]) := tmp*)
- END
- ELSE
- FOR i := 0 TO stepLen - 1 BY 4 DO
- tmp := SYSTEM.VAL(DataBytes, data[ofs + i]);
- hc.regs.BufferData := SYSTEM.VAL(LONGINT, tmp);
- END
- END;
- (* 17 *)
- INC(ofs, stepLen);
- DEC(len, stepLen)
- END;
- (* 18 -> Not infinite block *)
- REPEAT UNTIL Interrupt_Normal_TransferComplete IN hc.regs.InterruptStatus;
- (* 19 *)
- INCL(hc.regs.InterruptStatus, Interrupt_Normal_TransferComplete);
- (*DEC(hc.regs.ClockControl, LSH(1, ClockControl_SdClockEnable));
- hc.regs.SoftwareReset := SYSTEM.VAL(SHORTINT, {SoftwareResetCmd, SoftwareResetDat});
- REPEAT UNTIL hc.regs.SoftwareReset = 0;
- INC(hc.regs.ClockControl, LSH(1, ClockControl_SdClockEnable));*)
- IF Synchronize THEN hc.release END;
- RETURN Reset(hc, TRUE, FALSE) & Reset(hc, FALSE, TRUE)
- END ExecuteDataCommand;
- (**
- Execute Command with data transfers using ADMA
- *)
- PROCEDURE ExecuteAdmaCommand (CONST command: Command; VAR data: ARRAY OF CHAR; ofs, len: LONGINT; VAR result: LONGINT): BOOLEAN;
- TYPE
- QWord = ARRAY 2 OF ADDRESS;
- VAR
- (*!DBG*)t: HUGEINT;
- hc: HostController;
- desc: HUGEINT;
- r1, status: SET;
- address: ADDRESS;
- BEGIN
- hc := command.hc;
- (* Setup descriptor *)
- address := (*command.hc.dmaBufAdr*)ADDRESSOF(data[ofs]);
- SYSTEM.VAL(QWord, desc)[1] := address;
- SYSTEM.VAL(QWord, desc)[0] := LSH(len, 16) + 27H;
- hc.desc[hc.descOfs] := desc;
- SdEnvironment.FlushDCacheRange(ADDRESSOF(hc.desc[hc.descOfs]), 8);
- (*IF ~(FlagRead IN command.flags) THEN
- SYSTEM.MOVE(ADDRESSOF(data[ofs]), address, len);
- END;*)
- SdEnvironment.FlushDCacheRange(address, len);
- IF Synchronize THEN hc.acquire END;
- SetTimeout(hc, 10);
- IF ~Reset(hc, TRUE, FALSE) OR ~Reset(hc, FALSE, TRUE) THEN
- result := ErrorCard;
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END;
- (* 1 *)
- hc.regs.AdmaSystemAddress := ADDRESSOF(hc.desc[hc.descOfs]);
- IF (FlagApplicationCmd IN command.flags) THEN
- IF ~StartCommand(command.hc, CMD_APP_CMD, LSH(command.rca, 16), ResponseR1, FlagRead IN command.flags, FALSE, FALSE, FALSE, status, result) THEN
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END;
- r1 := SYSTEM.VAL(SET, command.response[0]);
- IF Trace THEN
- SdEnvironment.String("[SD] CMD55 Status:");
- SdEnvironment.Ln;
- PrintCardStatus(r1)
- END;
- IF CardStatus_Error IN r1 THEN
- result := ErrorCard;
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END
- END;
- (* 2-3 *)
- IF FlagData IN command.flags(*((command.command = CMD_READ_SINGLE_BLOCK) OR (command.command = CMD_READ_MULTIPLE_BLOCK) OR
- (command.command = CMD_WRITE_BLOCK) OR (command.command = CMD_WRITE_MULTIPLE_BLOCK) OR
- (command.command = 53)(* SDIO Command *))*) THEN
- IF len <= BlockSize THEN
- hc.regs.BlockSize := INTEGER(len);
- hc.regs.BlockCount := 1
- ELSE
- hc.regs.BlockSize := BlockSize;
- hc.regs.BlockCount := INTEGER(len DIV BlockSize)
- END;
- IF Trace THEN
- SdEnvironment.String("[SD] ");
- IF FlagRead IN command.flags THEN SdEnvironment.String("Read")
- ELSE SdEnvironment.String("Write") END;
- SdEnvironment.String(" parameters:"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Block Size = "); SdEnvironment.Int(hc.regs.BlockSize, 0); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Block Count = "); SdEnvironment.Int(hc.regs.BlockCount, 0); SdEnvironment.Ln;
- SdEnvironment.String("[SD] CMD"); SdEnvironment.Int(command.command, 0); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Argument = "); SdEnvironment.Address(command.argument); SdEnvironment.Ln
- END
- END;
- IF ~StartCommand(command.hc, command.command, command.argument, command.responseType, FlagRead IN command.flags, TRUE, TRUE, FALSE, status, result) THEN
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END;
- r1 := SYSTEM.VAL(SET, command.response[0]);
- IF CardStatus_Error IN r1 THEN
- result := ErrorCard;
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END;
- IF Trace THEN PrintCardStatus(r1) END;
- WHILE ~((Interrupt_Normal_TransferComplete IN status) OR (Interrupt_Normal_ErrorInterrupt IN status)) DO
- status := hc.regs.InterruptStatus
- END;
- IF Interrupt_Normal_ErrorInterrupt IN status THEN
- IF ErrorRecovery(hc, result, status) THEN END;
- IF Interrupt_Error_DataTimeout IN status THEN
- result := ErrorDatTimeout
- ELSIF Interrupt_Error_DataCrc IN status THEN
- result := ErrorDatCrc
- ELSIF Interrupt_Error_DataEndBit IN status THEN
- result := ErrorCard
- END;
- IF Synchronize THEN hc.release END;
- RETURN FALSE
- END;
- hc.regs.InterruptStatus := status;
- IF FlagRead IN command.flags THEN
- SdEnvironment.InvalidateDCacheRange(address, len);
- (*SYSTEM.MOVE(address, ADDRESSOF(data[ofs]), len)*)
- END;
- IF Synchronize THEN hc.release END;
- RETURN TRUE
- END ExecuteAdmaCommand;
- (** Read response R1 or R1b from command record *)
- PROCEDURE GetR1 * (CONST command: Command): SET;
- VAR
- idx: LONGINT;
- BEGIN
- idx := 0;
- (*IF (FlagAutoCmd12 IN command.flags) OR (FlagAutoCmd23 IN command.flags) THEN
- idx := 3
- END;*)
- RETURN SYSTEM.VAL(SET, command.response[idx])
- END GetR1;
- (** Read response R2 from command record *)
- PROCEDURE GetR2 * (CONST command: Command; VAR response: ARRAY OF LONGINT);
- VAR
- i: LONGINT;
- BEGIN
- FOR i := 0 TO 3 DO
- response[i] := command.response[i]
- END
- END GetR2;
- (** Read response R3 from command record *)
- PROCEDURE GetR3 * (CONST command: Command): LONGINT;
- BEGIN
- RETURN command.response[0]
- END GetR3;
- (** Read response R4 from command record *)
- PROCEDURE GetR4 * (CONST command: Command): LONGINT;
- BEGIN
- RETURN command.response[0]
- END GetR4;
- (** Read response R5 from command record *)
- PROCEDURE GetR5 * (CONST command: Command): LONGINT;
- BEGIN
- RETURN command.response[0]
- END GetR5;
- (** Read response R6 from command record *)
- PROCEDURE GetR6 * (CONST command: Command): LONGINT;
- BEGIN
- RETURN command.response[0]
- END GetR6;
- (** Read response R7 from command record *)
- PROCEDURE GetR7 * (CONST command: Command): LONGINT;
- BEGIN
- RETURN command.response[0]
- END GetR7;
- PROCEDURE SetEventHandler * (hc: HostController; handler: EventHandler; param: ANY);
- BEGIN
- hc.handle := handler;
- hc.handlerParam := param
- END SetEventHandler;
- (* ==================== Card (High-Level) Interface ==================== *)
- (** Write 'data[ofs, ofs + len)' to 'card', starting at block 'firstBlock'. *)
- PROCEDURE Write * (card: Card; firstBlock, len: LONGINT; VAR data: ARRAY OF CHAR; ofs: LONGINT; VAR result: LONGINT): BOOLEAN;
- VAR
- command: Command;
- ret: BOOLEAN;
- r1: SET;
- BEGIN
- IF Synchronize THEN card.acquire END;
- IF ~SelectCard(card, result) THEN
- IF Synchronize THEN card.release END;
- RETURN FALSE
- END;
- command.hc := card.hc;
- command.argument := firstBlock;
- command.responseType := ResponseR1;
- command.flags := {FlagData};
- command.rca := card.rca;
- IF len > BlockSize THEN
- INCL(command.flags, FlagMultipleBlockTx);
- INCL(command.flags, FlagCountBlocks);
- INCL(command.flags, FlagAutoCmd12);
- command.command := CMD_WRITE_MULTIPLE_BLOCK
- ELSE
- command.command := CMD_WRITE_BLOCK
- END;
- ret := command.hc.execute(command, data, ofs, len, result);
- IF Synchronize THEN card.release END;
- RETURN ret
- (*IF command.hc.execute(command, data, ofs, len, result) & ~(CardStatus_Error IN GetR1(command)) THEN
- command.flags := {};
- command.argument := 0;
- command.command := CMD_SEND_STATUS;
- command.responseType := ResponseR1;
- REPEAT
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- r1 := GetR1(command);
- IF CardStatus_Error IN r1 THEN RETURN FALSE END
- UNTIL CardStatus_ReadyForData IN r1;
- RETURN TRUE
- ELSE
- RETURN FALSE
- END*)
- END Write;
- (** Read 'len' bytes starting from 'firstBlock' of 'card' to 'data[ofs, ofs + len)' *)
- PROCEDURE Read * (card: Card; firstBlock, len: LONGINT; VAR data: ARRAY OF CHAR; ofs: LONGINT; VAR result: LONGINT): BOOLEAN;
- VAR
- command: Command;
- ret: BOOLEAN;
- BEGIN
- IF Synchronize THEN card.acquire END;
- IF ~SelectCard(card, result) THEN
- IF Synchronize THEN card.release END;
- RETURN FALSE
- END;
- command.hc := card.hc;
- command.argument := firstBlock;
- command.responseType := ResponseR1;
- command.flags := {FlagData, FlagRead};
- command.rca := card.rca;
- IF len > BlockSize THEN
- INCL(command.flags, FlagMultipleBlockTx);
- INCL(command.flags, FlagCountBlocks);
- INCL(command.flags, FlagAutoCmd12);
- command.command := CMD_READ_MULTIPLE_BLOCK
- ELSE
- command.command := CMD_READ_SINGLE_BLOCK
- END;
- ret := command.hc.execute(command, data, ofs, len, result) & ~(CardStatus_Error IN GetR1(command));
- IF Synchronize THEN card.release END;
- RETURN ret
- END Read;
- PROCEDURE Erase * (card: Card; block, num: LONGINT; VAR result: LONGINT): BOOLEAN;
- VAR
- command: Command;
- r1: SET;
- BEGIN
- command.hc := card.hc;
- command.flags := {};
- command.rca := card.rca;
- command.responseType := ResponseR1;
- command.argument := block;
- command.command := CMD_ERASE_WR_BLK_START;
- IF ~ExecuteCommand(command, result) & (CardStatus_Error IN GetR1(command)) THEN RETURN FALSE END;
- command.argument := block + num - 1;
- command.command := CMD_ERASE_WR_BLK_END;
- IF ~ExecuteCommand(command, result) & (CardStatus_Error IN GetR1(command)) THEN RETURN FALSE END;
- command.argument := 0;
- command.command := CMD_ERASE;
- command.responseType := ResponseR1b;
- IF ~ExecuteCommand(command, result) & (CardStatus_Error IN GetR1(command)) THEN RETURN FALSE END;
- (*WHILE 20 IN card.hc.regs.PresentState DO END;*)
- command.command := CMD_SEND_STATUS;
- command.responseType := ResponseR1;
- REPEAT
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- r1 := GetR1(command);
- IF CardStatus_Error IN r1 THEN RETURN FALSE END
- UNTIL CardStatus_ReadyForData IN r1;
- RETURN TRUE
- END Erase;
- PROCEDURE Reset (hc: HostController; cmd, dat: BOOLEAN): BOOLEAN;
- VAR
- val: SHORTINT;
- BEGIN
- IF cmd & dat THEN
- val := SoftwareResetAll
- ELSIF cmd THEN
- val := SoftwareResetCmd
- ELSIF dat THEN
- val := SoftwareResetDat
- ELSE
- RETURN FALSE
- END;
- hc.regs.SoftwareReset := val;
- REPEAT
- UNTIL hc.regs.SoftwareReset # val;
- RETURN TRUE
- END Reset;
- PROCEDURE SetBusClock (hc: HostController; freq: LONGINT);
- VAR
- divisor, d, val: LONGINT;
- BEGIN
- hc.regs.ClockControl := 0;
- divisor := hc.baseFrequency DIV freq;
- IF divisor = 0 THEN
- (* requested freq is higher that base freq *)
- divisor := 1
- END;
- IF hc.baseFrequency DIV divisor > freq THEN INC(divisor) END;
- val := 0;
- ASSERT(divisor > 0);
- d := divisor;
- WHILE d # 1 DO
- d := d DIV 2;
- INC(val)
- END;
- IF val >= 8 THEN val := 7 END;
- ASSERT(val < 8);
- (*val := divisor * 2;*)
- hc.regs.ClockControl := INTEGER(LSH(LSH(LONGINT(1), val), 8) + SYSTEM.VAL(INTEGER, {ClockControl_InternalClockEnable}));
- hc.frequency := hc.baseFrequency DIV (LSH(LONGINT(1), val));
- REPEAT val := hc.regs.ClockControl UNTIL ClockControl_InternalClockState IN SYSTEM.VAL(SET, val);
- val := hc.regs.ClockControl;
- hc.regs.ClockControl := SYSTEM.VAL(INTEGER, SYSTEM.VAL(SET, val) + {ClockControl_SdClockEnable});
- IF Trace THEN
- SdEnvironment.String("[SD] Selecting Bus Clock Frequency: ");
- SdEnvironment.Int(hc.frequency, 0);
- SdEnvironment.Ln
- END;
- (*SetTimeout(hc, 10); (* 100ms *)*)
- END SetBusClock;
- PROCEDURE SetTimeout (hc: HostController; timeoutFreq: LONGINT);
- VAR
- ratio, val: LONGINT;
- BEGIN
- ratio := hc.frequency DIV timeoutFreq DIV 8192;
- val := 0;
- REPEAT
- INC(val);
- ratio := ratio DIV 2
- UNTIL ratio = 0;
- hc.regs.TimeoutControl := SYSTEM.VAL(SHORTINT, val);
- END SetTimeout;
- PROCEDURE SetBusWidth (hc: HostController; rca, width: LONGINT; VAR result: LONGINT): BOOLEAN;
- VAR
- command: Command;
- val: LONGINT;
- BEGIN
- (* 1 *)
- (*EXCL(hc.regs.InterruptStatusEnable, Interrupt_Normal_CardInterrupt);*)
- (* 2: driver supports SD cards only *)
- (* 3: not implemented *)
- (* 4 *)
- command.command := ACMD_SET_BUS_WIDTH;
- CASE width OF
- 1: command.argument := 0
- |4: command.argument := 2
- END;
- command.hc := hc;
- command.rca := rca;
- command.flags := {FlagApplicationCmd};
- command.responseType := ResponseR1;
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- (* 5 *)
- val := hc.regs.HostControl1;
- CASE width OF
- 1: EXCL(SYSTEM.VAL(SET, val), HostControl1_DataWidthTransfer)
- |4: INCL(SYSTEM.VAL(SET, val), HostControl1_DataWidthTransfer)
- END;
- hc.regs.HostControl1 := SHORTINT(val);
- (* 6: SD card only *)
- (* 8 *)
- (*INCL(hc.regs.InterruptStatusEnable, Interrupt_Normal_CardInterrupt);*)
- RETURN TRUE
- END SetBusWidth;
- PROCEDURE HandleInterrupt * (hc: HostController);
- VAR
- card: Card;
- result: LONGINT;
- BEGIN
- IF Trace THEN SdEnvironment.String("[SD] Interrupt: "); SdEnvironment.Set(hc.regs.InterruptStatus); SdEnvironment.Ln END;
- IF Interrupt_Normal_CardInsertion IN hc.regs.InterruptStatus THEN
- IF Trace THEN SdEnvironment.String("[SD] Card Insertion"); SdEnvironment.Ln END;
- NEW(card);
- IF InitCard(hc, card, result) & (hc.handle # NIL) THEN
- hc.handle(card, OnInitialization, hc.handlerParam)
- ELSIF Trace THEN
- SdEnvironment.String("[SD] Could not initialize card");
- SdEnvironment.Ln
- END
- ELSIF Interrupt_Normal_CardRemoval IN hc.regs.InterruptStatus THEN
- IF Trace THEN SdEnvironment.String("[SD] Card Removal"); SdEnvironment.Ln END;
- card := hc.cards;
- IF hc.handle #NIL THEN hc.handle(card, OnRemoval, hc.handlerParam) END;
- hc.cards := hc.cards.next
- END;
- hc.regs.InterruptStatus := hc.regs.InterruptStatus
- END HandleInterrupt;
- PROCEDURE InitCard * (hc: HostController; card: Card; VAR result: LONGINT): BOOLEAN;
- VAR
- csd: ARRAY 4 OF LONGINT;
- response: LONGINT;
- status: SET;
- f8, sdio: BOOLEAN;
- command: Command;
- i: LONGINT;
- BEGIN
- SetBusClock(hc, 400000);
- FOR response := 0 TO 10000000 DO END;
- command.hc := hc;
- (* 1 *)
- command.command := CMD_GO_IDLE_STATE;
- command.argument := 0;
- command.responseType := ResponseNone;
- command.flags := {};
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- (* 2 *)
- command.command := CMD_SEND_IF_COND;
- command.argument := 1AAH;
- command.responseType := ResponseR7;
- command.flags := {};
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- (* 3 *)
- response := GetR7(command);
- IF response # 1AAH THEN
- result := ErrorCard;
- RETURN FALSE
- END;
- f8 := TRUE;
- (* 5 *)
- command.command := CMD_IO_SEND_OP_COND;
- command.argument := 0;
- command.responseType := ResponseR4;
- command.flags := {};
- IF ~ExecuteCommand(command, result) & (result = ErrorCmdTimeout) THEN
- sdio := FALSE;
- result := ErrorNone;
- ELSIF result # ErrorNone THEN
- RETURN FALSE
- ELSE
- sdio := TRUE;
- END;
- IF Trace THEN SdEnvironment.String("[SD] Card is SDIO: "); SdEnvironment.Boolean(sdio); SdEnvironment.Ln END;
- (* 6 *)
- IF sdio THEN
- (*! NOT IMPLEMENTED YET *)
- HALT(100);
- (* 7 *)
- (*IF ~StartCommand(hc, CMD_IO_SEND_OP_COND, 800H, ResponseR4, FALSE, FALSE, res) THEN
- RETURN FALSE
- END;
- RETURN TRUE*)
- END;
- (* A *)
- (* 12 & 19 *)
- command.command := ACMD_SD_SEND_OP_COND;
- command.argument := 0;
- command.responseType := ResponseR3;
- command.flags := {FlagApplicationCmd, FlagIgnoreIllegalCmd};
- (*IF ~StartCommand(hc, CMD_APP_CMD, 0, ResponseR1, FALSE, FALSE, res) THEN
- RETURN FALSE
- END;
- IF CardStatus_Error IN Response1(hc) THEN RETURN FALSE END;*)
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- response := GetR3(command);
- IF Trace THEN
- SdEnvironment.String("[SD] VDD: Ranges Supported by Card:"); SdEnvironment.Ln;
- IF CardOcr_Vdd27_28 IN SYSTEM.VAL(SET, response) THEN SdEnvironment.String("[SD] 2.7 - 2.8 V"); SdEnvironment.Ln END;
- IF CardOcr_Vdd28_29 IN SYSTEM.VAL(SET, response) THEN SdEnvironment.String("[SD] 2.8 - 2.9 V"); SdEnvironment.Ln END;
- IF CardOcr_Vdd29_30 IN SYSTEM.VAL(SET, response) THEN SdEnvironment.String("[SD] 2.9 - 3.0 V"); SdEnvironment.Ln END;
- IF CardOcr_Vdd30_31 IN SYSTEM.VAL(SET, response) THEN SdEnvironment.String("[SD] 3.0 - 3.1 V"); SdEnvironment.Ln END;
- IF CardOcr_Vdd31_32 IN SYSTEM.VAL(SET, response) THEN SdEnvironment.String("[SD] 3.1 - 3.2 V"); SdEnvironment.Ln END;
- IF CardOcr_Vdd32_33 IN SYSTEM.VAL(SET, response) THEN SdEnvironment.String("[SD] 3.2 - 3.3 V"); SdEnvironment.Ln END;
- IF CardOcr_Vdd33_34 IN SYSTEM.VAL(SET, response) THEN SdEnvironment.String("[SD] 3.3 - 3.4 V"); SdEnvironment.Ln END;
- IF CardOcr_Vdd34_35 IN SYSTEM.VAL(SET, response) THEN SdEnvironment.String("[SD] 3.4 - 3.5 V"); SdEnvironment.Ln END;
- IF CardOcr_Vdd35_36 IN SYSTEM.VAL(SET, response) THEN SdEnvironment.String("[SD] 3.5 - 3.6 V"); SdEnvironment.Ln END
- END;
- status := {30};
- IF Capabilities_Voltage30 IN hc.regs.Capabilities[0] THEN
- IF Trace THEN SdEnvironment.String("[SD] Selecting 3.0 V"); SdEnvironment.Ln END;
- INCL(status, CardOcr_Vdd30_31)
- ELSIF Capabilities_Voltage33 IN hc.regs.Capabilities[0] THEN
- IF Trace THEN SdEnvironment.String("[SD] Selecting 3.3 V"); SdEnvironment.Ln END;
- INCL(status, CardOcr_Vdd32_33)
- END;
- command.command := ACMD_SD_SEND_OP_COND;
- command.argument := SYSTEM.VAL(LONGINT, status);
- command.responseType := ResponseR3;
- command.flags := {FlagApplicationCmd, FlagIgnoreIllegalCmd};
- REPEAT
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- status := SYSTEM.VAL(SET, GetR3(command));
- UNTIL (CardOcr_PowerUpStatus IN status);
- IF Trace & (CardOcr_S18A IN status) THEN
- SdEnvironment.String("[SD] Card supports 1.8V");
- SdEnvironment.Ln
- END;
- IF f8 & (CardOcr_CardCapacityStatus IN status) THEN
- IF Trace THEN SdEnvironment.String("[SD] Card: SDHC or SDXC") END;
- card.scr.security := TypeSDHC
- ELSIF f8 THEN
- IF Trace THEN SdEnvironment.String("[SD] Card: SDSC v2 or v3") END;
- card.scr.security := TypeSDSC
- ELSE
- IF Trace THEN SdEnvironment.String("[SD] Card: SDSC v1.0 or v1.1") END;
- card.scr.security := TypeSDSC
- END;
- IF Trace THEN SdEnvironment.Ln END;
- (* 32 *)
- command.command := CMD_ALL_SEND_CID;
- command.argument := 0;
- command.responseType := ResponseR2;
- command.flags := {};
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- GetR2(command, card.cid);
- (* 33 *)
- command.command := CMD_SEND_RELATIVE_ADDR;
- command.argument := 0;
- command.responseType := ResponseR6;
- command.flags := {};
- REPEAT
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- card.rca := LSH(GetR6(command), -16)
- UNTIL card.rca # 0;
- IF Trace THEN SdEnvironment.String("[SD] New Card with RCA: "); SdEnvironment.Hex(card.rca, -4); SdEnvironment.Ln END;
- status := SYSTEM.VAL(SET, GetR6(command));
- status := status * {0 .. 15};
- (* status is a modified CardStatus: reform corresponding card status *)
- IF 15 IN status THEN EXCL(status, 15); INCL(status, 23) END;
- IF 14 IN status THEN EXCL(status, 14); INCL(status, 22) END;
- IF 13 IN status THEN EXCL(status, 13); INCL(status, 19) END;
- IF Trace THEN PrintCardStatus(status) END;
- card.hc := hc;
- card.next := hc.cards;
- hc.cards := card;
- IF Synchronize THEN SdEnvironment.GetLock(card.acquire, card.release) END;
- (* Get Additional card registers: CSD *)
- command.command := CMD_SEND_CSD;
- command.argument := LSH(card.rca, 16);
- command.responseType := ResponseR2;
- command.flags := {};
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- GetR2(command, csd);
- GetCsd(csd, card.csd);
- IF Trace THEN
- SdEnvironment.String("[SD] Card Capacity: "); SdEnvironment.Int(card.csd.capacity, 0); SdEnvironment.String(" B"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Bus frequency: "); SdEnvironment.Int(card.csd.txSpeed, 0); SdEnvironment.String(" Hz"); SdEnvironment.Ln
- END;
- SetBusClock(hc, card.csd.txSpeed);
- IF ~ReadScr(card, result) THEN RETURN FALSE END;
- IF CardScr_SdBusWidths_4 IN card.scr.busWidth THEN
- IF Trace THEN
- SdEnvironment.String("[SD] Changing bus width to 4 bits");
- SdEnvironment.Ln
- END;
- IF ~SetBusWidth(card.hc, card.rca, 4, result) THEN RETURN FALSE END;
- IF Trace THEN
- SdEnvironment.String("[SD] Bus width changed");
- SdEnvironment.Ln
- END
- END;
- IF (card.scr.version >= Version1p1) & SelectSpeedMode(card, TRUE, result) THEN
- (*! Assume card supports 50 MHz clock rate *)
- SetBusClock(hc, 50000000)
- END;
- (*FOR i := 0 TO 10000000H DO END;*)
- (*IF ~Reset(card.hc, TRUE, FALSE) THEN RETURN FALSE END;*)
- (*TRACE('RESET done');*)
- (*FOR i := 0 TO 10000000H DO END;*)
- (* Get Additional card registers: CSD *)
- (*command.command := CMD_SEND_CSD;
- command.argument := LSH(card.rca, 16);
- command.responseType := ResponseR2;
- command.flags := {};
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- TRACE('command succeeded');
- GetR2(command, csd);
- GetCsd(csd, card.csd);
- IF Trace THEN
- SdEnvironment.String("[SD] Card Capacity: "); SdEnvironment.Int(card.csd.capacity, 0); SdEnvironment.String(" B"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Bus frequency: "); SdEnvironment.Int(card.csd.txSpeed, 0); SdEnvironment.String(" Hz"); SdEnvironment.Ln
- END;
- TRACE(card.csd.txSpeed);
- SetBusClock(hc, card.csd.txSpeed);*)
- RETURN TRUE
- END InitCard;
- PROCEDURE ReadScr (card: Card; VAR result: LONGINT): BOOLEAN;
- VAR
- command: Command;
- scr: ARRAY 8 OF CHAR;
- BEGIN
- IF ~SelectCard(card, result) THEN RETURN FALSE END;
- (* Get Card Register: SCR *)
- command.hc := card.hc;
- command.command := ACMD_SEND_SCR;
- command.argument := 0;
- command.responseType := ResponseR1;
- command.flags := {FlagApplicationCmd, FlagData, FlagRead};
- command.rca := card.rca;
- IF ~card.hc.execute(command, scr, 0, 8, result) THEN RETURN FALSE END;
- IF CardStatus_Error IN GetR1(command) THEN result := ErrorCard; RETURN FALSE END;
- GetScr(scr, card.scr);
- RETURN TRUE
- END ReadScr;
- PROCEDURE SwitchFunc (card: Card; switch: BOOLEAN; funcs: ARRAY 6 OF LONGINT; VAR sts: SwitchFuncStatus; VAR res: LONGINT): BOOLEAN;
- VAR
- status: ARRAY 64 OF CHAR;
- command: Command;
- PROCEDURE GetStatus (CONST status: ARRAY OF CHAR; VAR sts: SwitchFuncStatus);
- VAR
- i: LONGINT;
- BEGIN
- sts.current := LONGINT(ORD(status[0])) * 100H + LONGINT(ORD(status[1]));
- FOR i := 0 TO 5 DO
- sts.functionGroups[i] := SYSTEM.VAL(SET, LONGINT(ORD(status[2 + 2 * (5 - i)])) * 100H + LONGINT(ORD(status[1 + 2 + 2 * (5 - i)])))
- END;
- FOR i := 0 TO 5 BY 2 DO
- sts.functionStatus[i] := ORD(status[14 + 2 - i DIV 2]) MOD 10H;
- sts.functionStatus[i + 1] := ORD(status[14 + 2 - i DIV 2]) DIV 10H
- END;
- END GetStatus;
- BEGIN
- IF ~SelectCard(card, res) THEN RETURN FALSE END;
- command.hc := card.hc;
- command.command := CMD_SWITCH_FUNC;
- command.responseType := ResponseR1;
- command.argument := (funcs[0] MOD 10H) + 10H * (funcs[1] MOD 10H) + 100H * (funcs[2] MOD 10H) + 1000H * (funcs[3] MOD 10H) + 10000H * (funcs[4] MOD 10H) + 100000H * (funcs[5] MOD 10H);
- IF switch THEN INCL(SYSTEM.VAL(SET, command.argument), 31) END;
- command.flags := {FlagRead, FlagData};
- IF ~card.hc.execute(command, status, 0, 64, res) THEN RETURN FALSE END;
- GetStatus(status, sts);
- RETURN TRUE
- END SwitchFunc;
- PROCEDURE PrintSwitchFuncStatus(CONST status: SwitchFuncStatus);
- VAR
- i: LONGINT;
- BEGIN
- IF Trace THEN
- SdEnvironment.String("Switch Func Status");
- SdEnvironment.Ln;
- SdEnvironment.String("Current = ");
- IF status.current = 0 THEN
- SdEnvironment.String("ERROR")
- ELSE
- SdEnvironment.Int(status.current, 0);
- SdEnvironment.String(" mA");
- SdEnvironment.Ln
- END;
- FOR i := 0 TO 5 DO
- SdEnvironment.String("Function Group #");
- SdEnvironment.Int(i, 0);
- SdEnvironment.String(": functions = ");
- SdEnvironment.Set(status.functionGroups[i]);
- SdEnvironment.String(", status = ");
- CASE status.functionStatus[i] OF
- 0: SdEnvironment.String("switchable")
- |1: SdEnvironment.String("switched")
- |0FH: SdEnvironment.String("ERROR")
- END;
- SdEnvironment.Ln
- END
- END
- END PrintSwitchFuncStatus;
- PROCEDURE SelectSpeedMode(card: Card; high: BOOLEAN; VAR res: LONGINT): BOOLEAN;
- VAR
- funcs: ARRAY 6 OF LONGINT;
- status: SwitchFuncStatus;
- BEGIN
- funcs[0] := 1;
- IF ~SwitchFunc(card, FALSE, funcs, status, res) THEN RETURN FALSE END;
- PrintSwitchFuncStatus(status);
- IF ~(1 IN status.functionGroups[0]) THEN
- SdEnvironment.String("[SD] HIGH-SPEED MODE NOT SUPPORTED");
- SdEnvironment.Ln;
- RETURN TRUE
- END;
- IF ~SwitchFunc(card, TRUE, funcs, status, res) THEN RETURN FALSE END;
- PrintSwitchFuncStatus(status);
- RETURN TRUE
- END SelectSpeedMode;
- (** Sends CMD7 if necessary to select the given card *)
- PROCEDURE SelectCard (card: Card; VAR result: LONGINT): BOOLEAN;
- VAR
- command: Command;
- status: SET;
- BEGIN
- IF card.hc.lastRca = card.rca THEN
- IF Trace THEN
- SdEnvironment.String("[SD] Card Already Selected");
- SdEnvironment.Ln
- END;
- RETURN TRUE
- END;
- IF Trace THEN SdEnvironment.String("[SD] Selecting Card "); SdEnvironment.Int(card.rca, 0); SdEnvironment.Ln END;
- command.hc := card.hc;
- command.command := CMD_SELECT_DESELECT_CARD;
- command.argument := LSH(card.rca, 16);
- command.responseType := ResponseR1b;
- IF ~ExecuteCommand(command, result) THEN RETURN FALSE END;
- status := GetR1(command);
- IF CardStatus_Error IN status THEN result := ErrorCard; RETURN FALSE END;
- RETURN TRUE
- END SelectCard;
- (** Get the response registers in 'response' *)
- PROCEDURE GetResponse (hc: HostController; responseType: LONGINT; VAR response: ARRAY 4 OF LONGINT);
- BEGIN
- response := hc.regs.Response
- END GetResponse;
- (** Issue an SD Card Transaction. [Simplified specs. 3.7.1.1 pp. 106-108] *)
- PROCEDURE StartCommand (hc: HostController; cmd, argument, responseType: LONGINT; read, dma, busy, abort: BOOLEAN; VAR status: SET; VAR result: LONGINT): BOOLEAN;
- VAR
- reg: LONGINT;
- flags, txFlags: SET;
- BEGIN
- IF TraceCmd THEN
- SdEnvironment.String("[SD] Sending Command CMD"); SdEnvironment.Int(cmd, 0); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Argument: "); SdEnvironment.Hex(argument, -8); SdEnvironment.Ln
- END;
- (* 1 *)
- WHILE PresentState_CommandInhibitCmd IN hc.regs.PresentState DO END;
- (* 2 *)
- IF busy THEN
- (* 3 *)
- IF ~abort THEN
- (* 4 *)
- WHILE PresentState_CommandInhibitDat IN hc.regs.PresentState DO END
- END
- END;
- (* 5 *)
- hc.regs.Argument1 := argument;
- (* 6 *)
- (* The response type determines the response-type and CRC/Index checks enabling *)
- CASE responseType OF
- ResponseNone:
- reg := Command_ResponseType_None;
- IF TraceCmd THEN
- SdEnvironment.String("[SD] No Response Expected");
- SdEnvironment.Ln
- END
- |ResponseR1, ResponseR5, ResponseR6, ResponseR7:
- reg := Command_ResponseType_48b;
- flags := {Command_CrcCheckEnable, Command_IndexCheckEnable};
- IF TraceCmd THEN
- SdEnvironment.String("[SD] 48 Bit Response"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Enabling CRC Check and Index Check"); SdEnvironment.Ln
- END
- |ResponseR3, ResponseR4:
- reg := Command_ResponseType_48b;
- IF TraceCmd THEN SdEnvironment.String("[SD] 48 Bit Response"); SdEnvironment.Ln END
- |ResponseR1b, ResponseR5b:
- reg := Command_ResponseType_48bBusy;
- flags := {Command_CrcCheckEnable, Command_IndexCheckEnable};
- IF TraceCmd THEN
- SdEnvironment.String("[SD] 48 Bit Response"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Enabling Index Check"); SdEnvironment.Ln
- END
- |ResponseR2:
- reg := Command_ResponseType_136b;
- flags := {Command_CrcCheckEnable};
- IF TraceCmd THEN
- SdEnvironment.String("[SD] 136 Bit Response"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Enabling Command CRC Check"); SdEnvironment.Ln
- END
- END;
- (* Command determines data-enable *)
- IF busy THEN
- INCL(flags, Command_DataPresent);
- IF TraceCmd THEN SdEnvironment.String("[SD] Using DAT Line"); SdEnvironment.Ln END;
- txFlags := {};
- IF (*(cmd = CMD_READ_SINGLE_BLOCK) OR (cmd = CMD_READ_MULTIPLE_BLOCK) OR (cmd = ACMD_SEND_SCR)*) read THEN
- IF TraceCmd THEN SdEnvironment.String("[SD] Data Read"); SdEnvironment.Ln END;
- INCL(txFlags, TransferMode_DataTxDirection)
- ELSIF TraceCmd THEN
- SdEnvironment.String("[SD] Data Write");
- SdEnvironment.Ln
- END;
- IF (cmd = CMD_READ_MULTIPLE_BLOCK) OR (cmd = CMD_WRITE_MULTIPLE_BLOCK) THEN
- IF TraceCmd THEN SdEnvironment.String("[SD] Multiple blocks: using Auto CMD12 & activating block count"); SdEnvironment.Ln END;
- txFlags := txFlags + TransferMode_AutoCmd_Cmd12 + {TransferMode_MultipleBlocks, TransferMode_BlockCountEnable}
- ELSIF TraceCmd THEN
- SdEnvironment.String("[SD] Single Block");
- SdEnvironment.Ln
- END;
- IF dma THEN INCL(txFlags, TransferMode_DmaEnable) END;
- hc.regs.TransferMode := SYSTEM.VAL(INTEGER, txFlags)
- END;
- hc.regs.Command := SYSTEM.VAL(INTEGER, SYSTEM.VAL(SET, reg + LSH(cmd, Command_CommandIndexOffset)) + flags);
- (* 7 *)
- RETURN WaitForCompletion(hc, ~abort, status, result)
- (* Steps 7, 8 and 9 of WaitForCompletion have to be done by caller *)
- END StartCommand;
- PROCEDURE ErrorRecovery (hc: HostController; VAR result: LONGINT; VAR status: SET): BOOLEAN;
- BEGIN
- (* 1 is done *)
- status := hc.regs.InterruptStatus;
- hc.regs.InterruptStatusEnable := {0 .. 14};
- EXCL(hc.regs.InterruptStatusEnable, Interrupt_Normal_ErrorInterrupt);
- EXCL(hc.regs.InterruptStatusEnable, Interrupt_Normal_ErrorInterrupt);
- EXCL(hc.regs.InterruptStatusEnable, Interrupt_Normal_ErrorInterrupt);
- (* 2 *)
- IF (Interrupt_Error_CommandTimeout IN status) OR (Interrupt_Error_CommandCrc IN status) OR (Interrupt_Error_CommandEndBit IN status)
- OR (Interrupt_Error_CommandIndex IN status) THEN
- (* 3 & 4 *)
- IF ~Reset(hc, TRUE, FALSE) THEN
- result := ErrorUnrecoverable;
- RETURN FALSE
- END
- END;
- (* 5 *)
- IF (Interrupt_Error_DataTimeout IN status) OR (Interrupt_Error_DataCrc IN status) OR (Interrupt_Error_DataEndBit IN status) THEN
- (* 6 & 7 *)
- IF ~Reset(hc, FALSE, TRUE) THEN
- result := ErrorUnrecoverable;
- RETURN FALSE
- END
- END;
- (* 8 & 9 *)
- hc.regs.InterruptStatus := status;
- (* 10 & 11 *)
- (*IF ~Command(hc, CMD_STOP_TRANSMISSION, 0, ResponseR1b, FALSE, TRUE, result) THEN
- (* 12 *)
- IF (Interrupt_Error_CommandTimeout IN status) OR (Interrupt_Error_CommandCrc IN status) OR (Interrupt_Error_CommandEndBit IN status)
- OR (Interrupt_Error_CommandIndex IN status) THEN
- TRACE('CMD12 CMD LINE ERROR');
- result := ErrorUnrecoverable;
- RETURN FALSE
- END;
- (* 13 *)
- IF ~WaitForTransfer(hc, result) THEN
- result := ErrorUnrecoverable;
- RETURN FALSE
- END;
- TRACE(hc.regs.BufferData);
- END;
- (* 15 *)
- IF hc.regs.PresentState * PresentState_DatLineSignalLevelMask # PresentState_DatLineSignalLevelMask THEN
- TRACE('CMD12 DAT LINE ERROR');
- result := ErrorUnrecoverable;
- RETURN FALSE
- END;*)
- hc.regs.InterruptStatusEnable := {0 .. 31};
- INCL(hc.regs.InterruptStatusEnable, Interrupt_Normal_ErrorInterrupt);
- result := ErrorNone;
- RETURN TRUE
- END ErrorRecovery;
- (** Wait for completion of an SD command [Simplified specs. 3.7.1.2 pp. 109-110 *)
- PROCEDURE WaitForCompletion (hc: HostController; tryRecover: BOOLEAN; VAR status: SET; VAR result: LONGINT): BOOLEAN;
- BEGIN
- result := ErrorNone;
- (* 1 *)
- REPEAT
- status := hc.regs.InterruptStatus;
- UNTIL (Interrupt_Normal_CommandComplete IN status)
- OR (Interrupt_Normal_ErrorInterrupt IN status);
- IF Interrupt_Normal_ErrorInterrupt IN status THEN
- IF ~tryRecover THEN
- hc.regs.InterruptStatus := status;
- result := ErrorUnrecoverable;
- RETURN FALSE
- END;
- IF ~ErrorRecovery(hc, result, status) THEN RETURN FALSE END;
- IF Interrupt_Error_CommandTimeout IN status THEN
- IF TraceCmd THEN SdEnvironment.String("[SD] Timeout in command"); SdEnvironment.Ln END;
- result := ErrorCmdTimeout;
- RETURN FALSE
- ELSIF Interrupt_Error_CommandCrc IN status THEN
- result := ErrorCmdCrc;
- RETURN FALSE
- ELSE
- result := ErrorCard;
- RETURN FALSE
- END
- END;
- (* 2 *)
- IF TraceCmd THEN SdEnvironment.String("[SD] Command successful"); SdEnvironment.Ln END;
- INCL(hc.regs.InterruptStatus, Interrupt_Normal_CommandComplete);
- RETURN TRUE
- END WaitForCompletion;
- PROCEDURE WaitForTransfer (hc: HostController; VAR result: LONGINT): BOOLEAN;
- VAR
- status: SET;
- BEGIN
- (* 5 *)
- REPEAT UNTIL (Interrupt_Normal_TransferComplete IN hc.regs.InterruptStatus) OR (Interrupt_Normal_ErrorInterrupt IN hc.regs.InterruptStatus);
- IF Interrupt_Normal_ErrorInterrupt IN hc.regs.InterruptStatus THEN
- IF ~ErrorRecovery(hc, result, status) THEN RETURN FALSE END;
- result := ErrorCard;
- RETURN FALSE
- END;
- (* 6 *)
- INCL(hc.regs.InterruptStatus, Interrupt_Normal_TransferComplete)
- END WaitForTransfer;
- (** Fills a Csd record from the raw csd bytes *)
- PROCEDURE GetCsd (CONST raw: ARRAY OF LONGINT; VAR csd: Csd);
- VAR
- sizeMult, val, version: LONGINT;
- real: REAL;
- BEGIN
- version := ReadBitfield(raw, CardCsd_CsdStructureOfs, CardCsd_CsdStructureWidth) + 1;
-
- IF version = 1 THEN
- sizeMult := LSH(LONGINT(2), ReadBitfield(raw, CardCsd_CSizeMultOfs1, CardCsd_CSizeMultWidth1));
- csd.capacity := sizeMult * (1 + ReadBitfield(raw, CardCsd_CSizeOfs1, CardCsd_CSizeWidth1)) * 512;
- ELSE
- csd.capacity := 1024 * (HUGEINT(ReadBitfield(raw, CardCsd_CSizeOfs2, CardCsd_CSizeWidth2)) + 1);
- END;
- csd.commandClasses := SYSTEM.VAL(SET, ReadBitfield(raw, CardCsd_CccOfs, CardCsd_CccWidth));
- csd.nsac := ReadBitfield(raw, CardCsd_NsacOfs, CardCsd_NsacWidth) * 100;
- val := ReadBitfield(raw, CardCsd_R2wFactorOfs, CardCsd_R2wFactorWidth);
- IF val >= 6 THEN
- csd.r2w := 0
- ELSE
- csd.r2w := LSH(LONGINT(1), val);
- END;
- val := ReadBitfield(raw, CardCsd_TranSpeedOfs, CardCsd_TranSpeedWidth);
- CASE val DIV 8 OF
- 1: csd.txSpeed := 10
- |2: csd.txSpeed := 12
- |3: csd.txSpeed := 13
- |4: csd.txSpeed := 15
- |5: csd.txSpeed := 20
- |6: csd.txSpeed := 25
- |7: csd.txSpeed := 30
- |8: csd.txSpeed := 35
- |9: csd.txSpeed := 40
- |10: csd.txSpeed := 45
- |11: csd.txSpeed := 50
- |12: csd.txSpeed := 55
- |13: csd.txSpeed := 60
- |14: csd.txSpeed := 70
- |15: csd.txSpeed := 80
- ELSE
- csd.txSpeed := 00
- END;
- csd.txSpeed := csd.txSpeed * 100;
- CASE val MOD 8 OF
- 0: csd.txSpeed := csd.txSpeed * 100
- |1: csd.txSpeed := csd.txSpeed * 1000
- |2: csd.txSpeed := csd.txSpeed * 10000
- |3: csd.txSpeed := csd.txSpeed * 100000
- END;
- val := ReadBitfield(raw, CardCsd_TaacOfs, CardCsd_TaacWidth);
- CASE val DIV 8 OF
- 1: real := 1.0
- |2: real := 1.2
- |3: real := 1.3
- |4: real := 1.5
- |5: real := 2.0
- |6: real := 2.5
- |7: real := 3.0
- |8: real := 3.5
- |9: real := 4.0
- |10: real := 4.5
- |11: real := 5.0
- |12: real := 5.5
- |13: real := 6.0
- |14: real := 7.0
- |15: real := 8.0
- ELSE
- real := 0.0
- END;
- CASE val MOD 8 OF
- 0: real := real * 1.0E-9
- |1: real := real * 1.0E-8
- |2: real := real * 1.0E-7
- |3: real := real * 1.0E-6
- |4: real := real * 1.0E-5
- |5: real := real * 1.0E-4
- |6: real := real * 1.0E-3
- |7: real := real * 1.0E-2
- END;
- csd.taac := real
- END GetCsd;
- PROCEDURE GetScr (CONST raw: ARRAY OF CHAR; VAR scr: Scr);
- TYPE
- Array = ARRAY 8 OF CHAR;
- VAR
- bfield: ARRAY 2 OF LONGINT;
- i: LONGINT;
- BEGIN
- FOR i := 0 TO 7 DO SYSTEM.VAL(Array, bfield)[7-i] := raw[i] END;
- IF ReadBitfield(bfield, CardScr_StructureOfs, CardScr_StructureWidth) # 0 THEN RETURN END;
- scr.version := ReadBitfield(bfield, CardScr_SdSpecVersionOfs, CardScr_SdSpecVersionWidth);
- IF (scr.version = Version2) & (ReadBitfield(bfield, CardScr_SpecV3, 1) # 0) THEN
- scr.version := Version3
- END;
- CASE ReadBitfield(bfield, CardScr_SecurityOfs, CardScr_SecurityWidth) OF
- 0: scr.security := TypeNone
- |2: scr.security := TypeSDSC
- |3: scr.security := TypeSDHC
- |4: scr.security := TypeSDXC
- END;
- scr.busWidth := SYSTEM.VAL(SET, ReadBitfield(bfield, CardScr_SdBusWidthsOfs, CardScr_SdBusWidthsWidth))
- END GetScr;
- PROCEDURE PrintCapabilities * (hc: HostController);
- VAR
- c0, c1: SET;
- BEGIN
- IF Trace THEN
- c0 := hc.regs.Capabilities[0];
- c1 := hc.regs.Capabilities[1];
- SdEnvironment.String("[SD] "); SdEnvironment.String("Host Capabilities:"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Timeout Clock Frequency: ");
- IF c0 * Capabilities_TimeoutClockFrequencyMask = {} THEN
- SdEnvironment.String("Unknown")
- ELSE
- SdEnvironment.Int(SYSTEM.VAL(LONGINT, c0 * Capabilities_TimeoutClockFrequencyMask), 0);
- IF Capabilities_TimeoutClockUnit IN c0 THEN
- SdEnvironment.String(" MHz")
- ELSE
- SdEnvironment.String(" kHz")
- END
- END;
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Base Clock Frequency: ");
- IF c0 * Capabilities_BaseClockFreqSdMask = {} THEN
- SdEnvironment.String("Unknown")
- ELSE
- SdEnvironment.Int(LSH(SYSTEM.VAL(LONGINT, c0 * Capabilities_BaseClockFreqSdMask), -Capabilities_BaseClockFreqSdOfs), 0)
- END;
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Max Block Length: ");
- SdEnvironment.Int(512 * (1 + LSH(SYSTEM.VAL(LONGINT, c0 * Capabilities_MaxBlockLenMask), -Capabilities_MaxBlockLenOfs)), 0);
- SdEnvironment.String(" B");
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" 8 Bit Support for Embedded Device: ");
- SdEnvironment.Boolean(Capabilities_8BitEmbedded IN c0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for ADMA2: ");
- SdEnvironment.Boolean(Capabilities_ADMA2 IN c0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for High Speed: ");
- SdEnvironment.Boolean(Capabilities_HighSpeed IN c0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for SDMA: ");
- SdEnvironment.Boolean(Capabilities_SDMA IN c0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for Suspend/Resume: ");
- SdEnvironment.Boolean(Capabilities_SuspendResume IN c0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Voltage Support for 3.3 V: ");
- SdEnvironment.Boolean(Capabilities_Voltage33 IN c0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Voltage Support for 3.0 V: ");
- SdEnvironment.Boolean(Capabilities_Voltage30 IN c0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Voltage Support for 1.8 V: ");
- SdEnvironment.Boolean(Capabilities_Voltage18 IN c0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for 64 Bit Bus: ");
- SdEnvironment.Boolean(Capabilities_64BitBus IN c0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for Asynchronous Interrupts: ");
- SdEnvironment.Boolean(Capabilities_AsyncInterrupt IN c0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Slot Type: ");
- IF c0 * Capabilities_SlotTypeMask = Capabilities_SlotType_Removable THEN
- SdEnvironment.String("Removable Card Slot")
- ELSIF c0 * Capabilities_SlotTypeMask = Capabilities_SlotType_Embedded THEN
- SdEnvironment.String("Embedded Slot for One Device")
- ELSIF c0 * Capabilities_SlotTypeMask = Capabilities_SlotType_SharedBus THEN
- SdEnvironment.String("Shared Bus Slot")
- END;
- SdEnvironment.Ln;
- IF hc.version = 3 THEN
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for SDR50: ");
- SdEnvironment.Boolean(Capabilities_SDR50 IN c1);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for SDR104: ");
- SdEnvironment.Boolean(Capabilities_SDR104 IN c1);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for DDR50: ");
- SdEnvironment.Boolean(Capabilities_DDR50 IN c1);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for Driver Type A: ");
- SdEnvironment.Boolean(Capabilities_DriverTypeA IN c1);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for Driver Type C: ");
- SdEnvironment.Boolean(Capabilities_DriverTypeC IN c1);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Support for Driver Type D: ");
- SdEnvironment.Boolean(Capabilities_DriverTypeD IN c1);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Timer Count for Retuning: ");
- IF c1 * Capabilities_TimerCountRetuningMask = Capabilities_TimerCountRetuningMask THEN
- SdEnvironment.String("Unknown")
- ELSIF c1 * Capabilities_TimerCountRetuningMask = {} THEN
- SdEnvironment.String("Disabled")
- ELSE
- SdEnvironment.Int(LSH(LONGINT(1), LSH(SYSTEM.VAL(LONGINT, c1 * Capabilities_TimerCountRetuningMask), -Capabilities_TimerCountRetuningOfs)), 0);
- SdEnvironment.String(" s")
- END;
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" SDR50 Requires Retuning: ");
- SdEnvironment.Boolean(Capabilities_TuningSDR50 IN c1);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Retuning Mode: ");
- SdEnvironment.Int(LSH(SYSTEM.VAL(LONGINT, c1 * Capabilities_RetuningModesMask), -Capabilities_RetuningModesOfs), 0);
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Clock Multiplier: ");
- IF c1 * Capabilities_ClockMultiplierMask = {} THEN
- SdEnvironment.String("Not Supported")
- ELSE
- SdEnvironment.Int(LSH(SYSTEM.VAL(LONGINT, c1 * Capabilities_ClockMultiplierMask), -Capabilities_ClockMultiplierOfs) + 1, 0)
- END;
- SdEnvironment.Ln
- END
- END
- END PrintCapabilities;
- PROCEDURE PrintCardStatus * (status: SET);
- BEGIN
- IF TRUE OR Trace THEN
- SdEnvironment.String("[SD] Card Status:"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] AKE Error: "); SdEnvironment.Boolean(CardStatus_AkeSpecError IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] App Command: "); SdEnvironment.Boolean(CardStatus_AppCmd IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Ready For Data: "); SdEnvironment.Boolean(CardStatus_ReadyForData IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Card State: ");
- CASE LSH(SYSTEM.VAL(LONGINT, status * CardStatus_CurrentStateMask), -CardStatus_CurrentStateOffset) OF
- CardIdle: SdEnvironment.String("Idle")
- |CardReady: SdEnvironment.String("Ready")
- |CardIdentification: SdEnvironment.String("Identification")
- |CardStandby: SdEnvironment.String("Standby")
- |CardTransfer: SdEnvironment.String("Transfer")
- |CardData: SdEnvironment.String("Sending Data")
- |CardReceive: SdEnvironment.String("Receiving Data")
- |CardProgram: SdEnvironment.String("Programming")
- |CardDisabled: SdEnvironment.String("Disabled")
- END;
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] Erase Reset: "); SdEnvironment.Boolean(CardStatus_EraseReset IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Internal ECC Enable: "); SdEnvironment.Boolean(CardStatus_CardEccDisable IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Write_Protection Erase Skip: "); SdEnvironment.Boolean(CardStatus_WpEraseSkip IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] CSD Overwrite: "); SdEnvironment.Boolean(CardStatus_CsdOverwrite IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Error: "); SdEnvironment.Boolean(CardStatus_Error IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Card Controller Error: "); SdEnvironment.Boolean(CardStatus_CcError IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Card ECC Failed: "); SdEnvironment.Boolean(CardStatus_CardEccFailed IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Illegal Command: "); SdEnvironment.Boolean(CardStatus_IllegalCommand IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Command CRC Error: "); SdEnvironment.Boolean(CardStatus_ComCrcError IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Lock/Unlock Failed: "); SdEnvironment.Boolean(CardStatus_LockUnlockFailed IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Card is Locked: "); SdEnvironment.Boolean(CardStatus_CardIsLocked IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Write-Protection Violation: "); SdEnvironment.Boolean(CardStatus_WpViolation IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Invalid Erase Parameters: "); SdEnvironment.Boolean(CardStatus_EraseParam IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Erase Sequence Error: "); SdEnvironment.Boolean(CardStatus_EraseSeqError IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Block Length Error: "); SdEnvironment.Boolean(CardStatus_BlockLenError IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Address Error: "); SdEnvironment.Boolean(CardStatus_AddressError IN status); SdEnvironment.Ln;
- SdEnvironment.String("[SD] Argument Out of Range: "); SdEnvironment.Boolean(CardStatus_OutOfRange IN status); SdEnvironment.Ln
- END
- END PrintCardStatus;
- PROCEDURE PrintCardCsd * (CONST csd: ARRAY OF LONGINT);
- VAR
- cap: HUGEINT;
- val, version, sizeMult: LONGINT;
- BEGIN
- IF Trace THEN
- version := ReadBitfield(csd, CardCsd_CsdStructureOfs, CardCsd_CsdStructureWidth) + 1;
- SdEnvironment.String("[SD] "); SdEnvironment.String("Card CSD:"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Version: "); SdEnvironment.Int(version, 0); SdEnvironment.Ln;
- (* Common Fields *)
- SdEnvironment.String("[SD] "); SdEnvironment.String(" File Format: ");
- val := ReadBitfield(csd, CardCsd_FileFormatOfs, CardCsd_FileFormatWidth);
- IF ReadBitfield(csd, CardCsd_FileFormatGrp, 1) = 1 THEN
- SdEnvironment.String("Unknown Value (");
- SdEnvironment.Int(val, 0);
- SdEnvironment.String(")")
- ELSIF val = 0 THEN
- SdEnvironment.String("Hard-disk file system with partition table")
- ELSIF val = 1 THEN
- SdEnvironment.String("FAT")
- ELSIF val = 2 THEN
- SdEnvironment.String("Universal File Format")
- ELSE
- SdEnvironment.String("Other")
- END;
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Temporary Write Protection: "); SdEnvironment.Boolean(ReadBitfield(csd, CardCsd_TmpWriteProtect, 1) = 1); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Permanent Write Protection: "); SdEnvironment.Boolean(ReadBitfield(csd, CardCsd_PermWriteProtect, 1) = 1); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Copy: "); SdEnvironment.Boolean(ReadBitfield(csd, CardCsd_Copy, 1) = 1); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Partial Block Write: "); SdEnvironment.Boolean(ReadBitfield(csd, CardCsd_WriteBlPartial, 1) = 1); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Maximum Write Block Length: ");
- val := ReadBitfield(csd, CardCsd_WriteBlLenOfs, CardCsd_WriteBlLenWidth);
- IF (val <= 8) OR (val >= 12) THEN
- SdEnvironment.String("Unknown Value (");
- SdEnvironment.Int(val, 0);
- SdEnvironment.String(")")
- ELSE
- SdEnvironment.Int(LSH(LONGINT(1), val), 0);
- END;
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Block Program Time / Block Read Time: ");
- val := ReadBitfield(csd, CardCsd_R2wFactorOfs, CardCsd_R2wFactorWidth);
- IF val >= 6 THEN
- SdEnvironment.String("Unknown Value (");
- SdEnvironment.Int(val, 0);
- SdEnvironment.String(")")
- ELSE
- SdEnvironment.Int(LSH(LONGINT(1), val), 0);
- END;
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Group Write Protection: "); SdEnvironment.Boolean(ReadBitfield(csd, CardCsd_WpGrpEnable, 1) = 1); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" WpGrpSize: "); SdEnvironment.Int(ReadBitfield(csd, CardCsd_WpGrpSizeOfs, CardCsd_WpGrpSizeWidth) + 1, 0); SdEnvironment.String(" sectors"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Sector Size: "); SdEnvironment.Int(ReadBitfield(csd, CardCsd_SectorSizeOfs, CardCsd_SectorSizeWidth) + 1, 0); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Erase Block Enable: "); SdEnvironment.Boolean(ReadBitfield(csd, CardCsd_EraseBlkEn, 1) = 1); SdEnvironment.Ln;
- IF version = 1 THEN
- sizeMult := LSH(LONGINT(2), ReadBitfield(csd, CardCsd_CSizeMultOfs1, CardCsd_CSizeMultWidth1));
- cap := sizeMult * (1 + ReadBitfield(csd, CardCsd_CSizeOfs1, CardCsd_CSizeWidth1)) * 512;
- ELSE
- cap := 1024 * (HUGEINT(ReadBitfield(csd, CardCsd_CSizeOfs2, CardCsd_CSizeWidth2)) + 1);
- END;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Card Capacity: "); SdEnvironment.Int(cap, 0); SdEnvironment.String(" B"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" DSR Implemented: "); SdEnvironment.Boolean(ReadBitfield(csd, CardCsd_DsrImp, 1) = 1); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Misaligned Block Read: "); SdEnvironment.Boolean(ReadBitfield(csd, CardCsd_ReadBlkMisalign, 1) = 1); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Misaligned Block Write: "); SdEnvironment.Boolean(ReadBitfield(csd, CardCsd_WriteBlkMisalign, 1) = 1); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Partial Block Read: "); SdEnvironment.Boolean(ReadBitfield(csd, CardCsd_ReadBlPartial, 1) = 1); SdEnvironment.Ln;
- (*ASSERT(ReadBitfield(csd, CardCsd_ReadBlPartial, 1) = 1);*)
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Maximal Block Read Length: ");
- val := ReadBitfield(csd, CardCsd_ReadBlLenOfs, CardCsd_ReadBlLenWidth);
- IF (val <= 8) OR (val >= 12) THEN
- SdEnvironment.String("Unknown Value (");
- SdEnvironment.Int(val, 0);
- SdEnvironment.String(")")
- ELSE
- SdEnvironment.Int(LSH(LONGINT(1), val), 0); SdEnvironment.String(" B")
- END;
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Supported Command Classes: "); SdEnvironment.Set(SYSTEM.VAL(SET, ReadBitfield(csd, CardCsd_CccOfs, CardCsd_CccWidth))); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Transfer Speed: ");
- val := ReadBitfield(csd, CardCsd_TranSpeedOfs, CardCsd_TranSpeedWidth);
- CASE val DIV 8 OF
- 1: SdEnvironment.String("1.0")
- |2: SdEnvironment.String("1.2")
- |3: SdEnvironment.String("1.3")
- |4: SdEnvironment.String("1.5")
- |5: SdEnvironment.String("2.0")
- |6: SdEnvironment.String("2.0")
- |7: SdEnvironment.String("2.5")
- |8: SdEnvironment.String("3.5")
- |9: SdEnvironment.String("4.0")
- |10: SdEnvironment.String("4.5")
- |11: SdEnvironment.String("5.0")
- |12: SdEnvironment.String("5.5")
- |13: SdEnvironment.String("6.0")
- |14: SdEnvironment.String("7.0")
- |15: SdEnvironment.String("8.0")
- ELSE
- SdEnvironment.String("Unknown Value (");
- SdEnvironment.Int(val, 0);
- SdEnvironment.String(")")
- END;
- SdEnvironment.String(" * 1");
- CASE val MOD 8 OF
- 0: SdEnvironment.String("00 k")
- |1: SdEnvironment.String(" M")
- |2: SdEnvironment.String("0 M")
- |3: SdEnvironment.String("00 M")
- END;
- SdEnvironment.String("Bit/s");
- SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Clock-Dependent Access Time: "); SdEnvironment.Int(ReadBitfield(csd, CardCsd_NsacOfs, CardCsd_NsacWidth) * 100, 0); SdEnvironment.String("000 clock cycles"); SdEnvironment.Ln;
- SdEnvironment.String("[SD] "); SdEnvironment.String(" Asynchronous Access Time: ");
- val := ReadBitfield(csd, CardCsd_TaacOfs, CardCsd_TaacWidth);
- CASE val DIV 8 OF
- 1: SdEnvironment.String("1.0")
- |2: SdEnvironment.String("1.2")
- |3: SdEnvironment.String("1.3")
- |4: SdEnvironment.String("1.5")
- |5: SdEnvironment.String("2.0")
- |6: SdEnvironment.String("2.5")
- |7: SdEnvironment.String("3.0")
- |8: SdEnvironment.String("3.5")
- |9: SdEnvironment.String("4.0")
- |10: SdEnvironment.String("4.5")
- |11: SdEnvironment.String("5.0")
- |12: SdEnvironment.String("5.5")
- |13: SdEnvironment.String("6.0")
- |14: SdEnvironment.String("7.0")
- |15: SdEnvironment.String("8.0")
- ELSE
- SdEnvironment.String("Unknown Value (");
- SdEnvironment.Int(val, 0);
- SdEnvironment.String(")")
- END;
- SdEnvironment.String(" * 1");
- CASE val MOD 8 OF
- 0: SdEnvironment.String(" ns")
- |1: SdEnvironment.String("0 ns")
- |2: SdEnvironment.String("00 ns")
- |3: SdEnvironment.String(" microsecond")
- |4: SdEnvironment.String("0 microsecond")
- |5: SdEnvironment.String("00 microsecond")
- |6: SdEnvironment.String(" ms")
- |7: SdEnvironment.String("0 ms")
- END;
- SdEnvironment.Ln;
- END
- END PrintCardCsd;
- PROCEDURE ReadBitfield (CONST field: ARRAY OF LONGINT; ofs, width: LONGINT): LONGINT;
- VAR
- bits: ADDRESS;
- BEGIN
- ASSERT(ofs MOD 8 + width <= 32);
- bits := SYSTEM.GET8(ADDRESSOF(field[0]) + ofs DIV 8);
- IF ofs MOD 8 + width > 8 THEN
- bits := bits + SYSTEM.GET8(ADDRESSOF(field[0]) + ofs DIV 8 + 1) * 100H
- END;
- IF ofs MOD 8 + width > 16 THEN
- bits := bits + SYSTEM.GET8(ADDRESSOF(field[0]) + ofs DIV 8 + 2) * 10000H
- END;
- IF ofs MOD 8 + width > 24 THEN
- bits := bits + SYSTEM.GET8(ADDRESSOF(field[0]) + ofs DIV 8 + 3) * 1000000H
- END;
- RETURN SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LSH(bits, -(ofs MOD 8))) * {0 .. width - 1})
- END ReadBitfield;
- END Sd.
|