USB 2.0 Stack for Bulk Transfer written pascal. Two years ago, I wrote the USB Driver for Stellaris. Stack is now open source. :)
Fig 1. StarterWare USB ref. http://processors.wiki.ti.com/index.php/StarterWare_USB
//------------------------------------------------------------------------------
//
// USB Bulk Library for LM3S9B95,LMS9B96
//
// #1. Environment
// -------------------------------------------------------------------------
// Eval Board : MikroMedia for Stellaris (LM3S9B95)
// Compiler : MikroPascal PRO for ARM v.2.0.0
//
// #2. Author
// -------------------------------------------------------------------------
// simon,choi / south korea (최원식옹의 스텔라리스 USB 라이브러리)
// Blog : http://blog.naver.com/simonsayz
// E-Mail : simonsayz@naver.com
//
// #3. History
// ---------------------------------------------------------------------------
// 2012.03.01 : Start
// 2012.03.02 : Convert USBLib in StellarisWare
// 2012.03.05 : RX FIFO Read
// 2012.03.10 : PLL Setting Bug Fixed
// 2012.03.11 : Rewrite Lib
// 2012.03.12 : Enumeration (EP0)
// 2012.03.14 : Data Xfer (EP1)
//
// #4. Maximum Speed Test (Full Speed : 12Mhz)
// ---------------------------------------------------------------------------
// 19 x 64 x 1000 1216000 [Bytes/s]
// Example. /wo Rcv 1066667 [Bytes/s] 88% [64000KB Block]
// /w Rcv 565771 [Bytes/s] 47%
// /w Rcv 1064007 [Bytes/s]
// /w Rcv 1066667 [Bytes/s]
//
// Snd 941592 [Bytes/s]
//
// #5. Enumeration List
// Env. C:\StellarisWare\boards\dk-lm3s9b96\usb_dev_bulk & XP
// ---------------------------------------------------------------------------
// Ty Rq Value Index Length
// PC->Dev (GetDesc, Devic ) 80 06 00 01 00 00 40 00
// Dev->PC (Answer ) 12 01 10 01 FF 00 00 40 BE 1C 03 00 00 01 01 02 03 01
// PC->Dev (Set Addr ) 00 05 01 00 00 00 00 00 // ZL Ack by Client
// PC->Dev (GetDesc, Device ) 80 06 00 01 00 00 12 00 // Dev Desc (Ver,PktSize...)
// Dev->PC (Answser ) 12 01 10 01 FF 00 00 40 BE 1C 03 00 00 01 01 02 03 01
// PC->Dev (GetDesc, Config ) 80 06 00 02 00 00 09 00
// Dev->PC (Config Answer ) 09 02 20 00 01 01 05 C0 FA // Cfg.Desc
// PC->Dev (GetDesc, String ) 80 06 00 03 00 00 FF 00
// Dev->PC (Lang: EN ) 04 03 09 04 // Lang Desc.
// PC->Dev (GetDesc,Str Inx3 ) 80 06 03 03 09 04 FF 00 // "12345678"
// Dev->PC ( Str Inx3 ) 12 03 31 00 32 00 33 00 34 00 35 00 36 00 37 00 38 00
// PC->Dev (GetDesc. Cfg Full ) 80 06 00 02 00 00 FF 00 // Cfg. All
// Dev->PC (Config Answer ) 09 02 20 00 01 01 05 C0 FA // Cfg Desc(Self Pwr,500mA)
// 09 04 00 00 02 FF 00 00 04 // I/F Desc (Ep#:2,IF:4)
// 07 05 81 02 40 00 00 // Ep Desc (Ep,81,I,Bulk,64,0)
// 07 05 01 02 40 00 00 // Ep Desc (Ep,01,O,Bulk,64,0)
// PC->Dev (GetDesc,String ) 80 06 00 03 00 00 FF 00
// Dev->PC (Lang: EN ) 04 03 09 04
// PC->Dev (GetDesc,Str Inx2 ) 80 06 02 03 09 04 FF 00 // "Genera..."
// Dev->PC ( Str Inx2 ) 28 03 47 00 65 00 6E 00 65 00 72 00 69 00
// PC->Dev (GetDesc,String ) 80 06 00 03 00 00 FF 00
// Dev->PC (Lang: EN ) 04 03 09 04
// PC->Dev (GetDesc,Str Inx2 ) 80 06 02 03 09 04 FF 00 // "General..."
// Dev->PC ( Str Inx2 ) 28 03 47 00 65 00 6E 00 65 00 72 00 69 00
// PC->Dev (GetDesc, Device ) 80 06 00 01 00 00 12 00 //
// Dev->PC ( Device ) 12 01 10 01 FF 00 00 40 BE 1C 03 00 00 01
// PC->Dev (GetDesc, Config ) 80 06 00 02 00 00 09 00
// Dev->PC ( Config ) 09 02 20 00 01 01 05 C0 FA
// PC->Dev (GetDesc, ) 80 06 00 02 00 00 20 00
// 09 02 20 00 01 01 05 C0 FA
// Dev->PC (Config Answer ) 09 04 00 00 02 FF 00 00 04
// 07 05 81 02 40 00 00
// 07 05 01 00 40 00 00
// PC->Dev (Get.Status ) 80 00 00 00 00 00 02 00
// Dev->PC (Self Power OK ) 01 00
// PC->Dev (SetConfig ) 00 09 01 00 00 00 00 00 // All Enum Done.
//
//
// bmRequestType bRequest
// ---------------------------------------------------
// Std Std Std
// Device Interface EndPoint
// ---------------------------------------------------
// 0x80 0x81 0x82 0 #USBDGetStatus
// 0x00 0x01 0x02 1 USBDClearFeature,
// -
// 0x00 0x01 0x02 3 USBDSetFeature,
// -
// 0x00 5 #USBDSetAddress,
// 0x80 6 #USBDGetDescriptor,
// 0x00 7 USBDSetDescriptor,
// 0x80 8 USBDGetConfiguration,
// 0x00 9 #USBDSetConfiguration,
// 0x81 A USBDGetInterface,
// 0x01 B USBDSetInterface,
// 0x82 C USBDSyncFrame
//
// bmRequest
// 0 00 0:0000
// x : 0 : Host To Device
// 1 : Device to Host
// xx : 00 : Standard
// 01 : Class
// 10 : Vendor
// 11 : Reserved
// 1 01 0:0000
//
//
//
// Command List
// ---------------------------------------------------------------------------
// Cmd_SetMode( Mode,Address : DWord) ReadMode Address
// WriteMode Addesss
// DialogMode Address
// Execute -
// PC->Dev : SetUpPkt : $60 $D8 $0000 $0000 $0040
// PC->Dev : Data[64] ( Mode4, Address4 )
//
// Cmd_GetMode(Var Mode,Address : DWord);
// PC->Dev : SetupPkt : $E0 $D8 $0000 $0000 $0040
// Dev->PC : Data[64]
//
// Pin Layout
// USBDM : USB0DM p70
// USBDP : USB0DP p71
// USB-DET : USB0VBUS PB1 p67
// USB-ID : USB0ID PB0 p66
//
unit Drv_USB;
//
// USB Bulk Library for LM3S9B95,LMS9B96
//
// #1. Environment
// -------------------------------------------------------------------------
// Eval Board : MikroMedia for Stellaris (LM3S9B95)
// Compiler : MikroPascal PRO for ARM v.2.0.0
//
// #2. Author
// -------------------------------------------------------------------------
// simon,choi / south korea (최원식옹의 스텔라리스 USB 라이브러리)
// Blog : http://blog.naver.com/simonsayz
// E-Mail : simonsayz@naver.com
//
// #3. History
// ---------------------------------------------------------------------------
// 2012.03.01 : Start
// 2012.03.02 : Convert USBLib in StellarisWare
// 2012.03.05 : RX FIFO Read
// 2012.03.10 : PLL Setting Bug Fixed
// 2012.03.11 : Rewrite Lib
// 2012.03.12 : Enumeration (EP0)
// 2012.03.14 : Data Xfer (EP1)
//
// #4. Maximum Speed Test (Full Speed : 12Mhz)
// ---------------------------------------------------------------------------
// 19 x 64 x 1000 1216000 [Bytes/s]
// Example. /wo Rcv 1066667 [Bytes/s] 88% [64000KB Block]
// /w Rcv 565771 [Bytes/s] 47%
// /w Rcv 1064007 [Bytes/s]
// /w Rcv 1066667 [Bytes/s]
//
// Snd 941592 [Bytes/s]
//
// #5. Enumeration List
// Env. C:\StellarisWare\boards\dk-lm3s9b96\usb_dev_bulk & XP
// ---------------------------------------------------------------------------
// Ty Rq Value Index Length
// PC->Dev (GetDesc, Devic ) 80 06 00 01 00 00 40 00
// Dev->PC (Answer ) 12 01 10 01 FF 00 00 40 BE 1C 03 00 00 01 01 02 03 01
// PC->Dev (Set Addr ) 00 05 01 00 00 00 00 00 // ZL Ack by Client
// PC->Dev (GetDesc, Device ) 80 06 00 01 00 00 12 00 // Dev Desc (Ver,PktSize...)
// Dev->PC (Answser ) 12 01 10 01 FF 00 00 40 BE 1C 03 00 00 01 01 02 03 01
// PC->Dev (GetDesc, Config ) 80 06 00 02 00 00 09 00
// Dev->PC (Config Answer ) 09 02 20 00 01 01 05 C0 FA // Cfg.Desc
// PC->Dev (GetDesc, String ) 80 06 00 03 00 00 FF 00
// Dev->PC (Lang: EN ) 04 03 09 04 // Lang Desc.
// PC->Dev (GetDesc,Str Inx3 ) 80 06 03 03 09 04 FF 00 // "12345678"
// Dev->PC ( Str Inx3 ) 12 03 31 00 32 00 33 00 34 00 35 00 36 00 37 00 38 00
// PC->Dev (GetDesc. Cfg Full ) 80 06 00 02 00 00 FF 00 // Cfg. All
// Dev->PC (Config Answer ) 09 02 20 00 01 01 05 C0 FA // Cfg Desc(Self Pwr,500mA)
// 09 04 00 00 02 FF 00 00 04 // I/F Desc (Ep#:2,IF:4)
// 07 05 81 02 40 00 00 // Ep Desc (Ep,81,I,Bulk,64,0)
// 07 05 01 02 40 00 00 // Ep Desc (Ep,01,O,Bulk,64,0)
// PC->Dev (GetDesc,String ) 80 06 00 03 00 00 FF 00
// Dev->PC (Lang: EN ) 04 03 09 04
// PC->Dev (GetDesc,Str Inx2 ) 80 06 02 03 09 04 FF 00 // "Genera..."
// Dev->PC ( Str Inx2 ) 28 03 47 00 65 00 6E 00 65 00 72 00 69 00
// PC->Dev (GetDesc,String ) 80 06 00 03 00 00 FF 00
// Dev->PC (Lang: EN ) 04 03 09 04
// PC->Dev (GetDesc,Str Inx2 ) 80 06 02 03 09 04 FF 00 // "General..."
// Dev->PC ( Str Inx2 ) 28 03 47 00 65 00 6E 00 65 00 72 00 69 00
// PC->Dev (GetDesc, Device ) 80 06 00 01 00 00 12 00 //
// Dev->PC ( Device ) 12 01 10 01 FF 00 00 40 BE 1C 03 00 00 01
// PC->Dev (GetDesc, Config ) 80 06 00 02 00 00 09 00
// Dev->PC ( Config ) 09 02 20 00 01 01 05 C0 FA
// PC->Dev (GetDesc, ) 80 06 00 02 00 00 20 00
// 09 02 20 00 01 01 05 C0 FA
// Dev->PC (Config Answer ) 09 04 00 00 02 FF 00 00 04
// 07 05 81 02 40 00 00
// 07 05 01 00 40 00 00
// PC->Dev (Get.Status ) 80 00 00 00 00 00 02 00
// Dev->PC (Self Power OK ) 01 00
// PC->Dev (SetConfig ) 00 09 01 00 00 00 00 00 // All Enum Done.
//
//
// bmRequestType bRequest
// ---------------------------------------------------
// Std Std Std
// Device Interface EndPoint
// ---------------------------------------------------
// 0x80 0x81 0x82 0 #USBDGetStatus
// 0x00 0x01 0x02 1 USBDClearFeature,
// -
// 0x00 0x01 0x02 3 USBDSetFeature,
// -
// 0x00 5 #USBDSetAddress,
// 0x80 6 #USBDGetDescriptor,
// 0x00 7 USBDSetDescriptor,
// 0x80 8 USBDGetConfiguration,
// 0x00 9 #USBDSetConfiguration,
// 0x81 A USBDGetInterface,
// 0x01 B USBDSetInterface,
// 0x82 C USBDSyncFrame
//
// bmRequest
// 0 00 0:0000
// x : 0 : Host To Device
// 1 : Device to Host
// xx : 00 : Standard
// 01 : Class
// 10 : Vendor
// 11 : Reserved
// 1 01 0:0000
//
//
//
// Command List
// ---------------------------------------------------------------------------
// Cmd_SetMode( Mode,Address : DWord) ReadMode Address
// WriteMode Addesss
// DialogMode Address
// Execute -
// PC->Dev : SetUpPkt : $60 $D8 $0000 $0000 $0040
// PC->Dev : Data[64] ( Mode4, Address4 )
//
// Cmd_GetMode(Var Mode,Address : DWord);
// PC->Dev : SetupPkt : $E0 $D8 $0000 $0000 $0040
// Dev->PC : Data[64]
//
// Pin Layout
// USBDM : USB0DM p70
// USBDP : USB0DP p71
// USB-DET : USB0VBUS PB1 p67
// USB-ID : USB0ID PB0 p66
//
unit Drv_USB;
Uses
Drv_PasBase,Drv_LM3S9B95,Drv_TFT,Drv_SD;
Drv_PasBase,Drv_LM3S9B95,Drv_TFT,Drv_SD;
Const
//
_cUSB_Polling = $1234;
_cUSB_Interrupt = $2345;
// TUSBStatus
_tusNone = $0000;
_tusReset = $0001;
_tusSuspend = $0002;
_tusResume = $0003;
_tusDisconnect = $0004;
_tusSOF = $0005;
_tusReady = $0006;
// TUSBPktPhase
_pSetup = $0001;
_pData = $0002;
// TUSBModeState
_tmsNone = $00;
_tmsXferStart = $01;
_tmsStop = $02;
_tmsPictShow = $03;
_tmsMovShow = $04;
_tmsSDTest = $05;
//
_CmdReqGet = $80 or $60; // bmRequestType Get+UserFunc
_CmdReqSet = $00 or $60; // bmRequestType Set+UserFunc
_CmdReqFunc = $D8; // bRequest
//
_cUSB_Polling = $1234;
_cUSB_Interrupt = $2345;
// TUSBStatus
_tusNone = $0000;
_tusReset = $0001;
_tusSuspend = $0002;
_tusResume = $0003;
_tusDisconnect = $0004;
_tusSOF = $0005;
_tusReady = $0006;
// TUSBPktPhase
_pSetup = $0001;
_pData = $0002;
// TUSBModeState
_tmsNone = $00;
_tmsXferStart = $01;
_tmsStop = $02;
_tmsPictShow = $03;
_tmsMovShow = $04;
_tmsSDTest = $05;
//
_CmdReqGet = $80 or $60; // bmRequestType Get+UserFunc
_CmdReqSet = $00 or $60; // bmRequestType Set+UserFunc
_CmdReqFunc = $D8; // bRequest
_DirIn = $01; // PC <- dev="" nbsp="" span="">
_DirOut = $02; // PC -> Dev
_DirInOut = $03; // PC <-> Dev->
// RT Req Val Inx Len Data
_CmdNone = $00;
_CmdSetStatus = $01; // PC -> Dev 60 D8 0001 0000 0040 : dir addr cnt
_CmdGetStatus = $02; // PC <- 0000="" 0002="" :="" addr="" cnt="" d8="" dev="" dir="" e0="" nbsp="" span="">
_CmdSetAction = $03; // PC -> Dev 80 D8 0003 0000 0040 : modeState->->
_DirOut = $02; // PC -> Dev
_DirInOut = $03; // PC <-> Dev->
// RT Req Val Inx Len Data
_CmdNone = $00;
_CmdSetStatus = $01; // PC -> Dev 60 D8 0001 0000 0040 : dir addr cnt
_CmdGetStatus = $02; // PC <- 0000="" 0002="" :="" addr="" cnt="" d8="" dev="" dir="" e0="" nbsp="" span="">
_CmdSetAction = $03; // PC -> Dev 80 D8 0003 0000 0040 : modeState->->
//
Type
TUSBOperation = DWord;
Pointer = ^Byte;
TUSBBufDW = Array[16] of DWord;
pUSBBufDW = ^TUSBBufDW;
TUSBBuf = Array[64] of Char;
TUSBStatus = DWord;
TUSBPktPhase = DWord;
TUSBState = DWord;
TUSBModeState = DWord;
TUSB = Record
Operation : TUSBOperation;
Ready : Boolean;
Status : TUSBStatus;
PktPhase : TUSBPktPhase;
CtlReqType : DWord;
CtlReq : DWord;
CtlValue : DWord;
CtlLength : DWord;
ModeDir : DWord; // Internal Operation
ModeAddr : DWord;
ModeCnt : DWord;
ModeState : TUSBModeState;
Addr : Dword;
AddrSet : Boolean;
BufR : TUSBBuf;
BufW : TUSBBuf;
End;
Var
_gUSB : TUSB;
//
Procedure USB_Init(Operation : TUSBOperation);
Procedure USB_Handler;
//
Function USB_PutSD (Var USB : TUSB) : Boolean;
Function USB_GetSD (Var USB : TUSB) : Boolean;
Type
TUSBOperation = DWord;
Pointer = ^Byte;
TUSBBufDW = Array[16] of DWord;
pUSBBufDW = ^TUSBBufDW;
TUSBBuf = Array[64] of Char;
TUSBStatus = DWord;
TUSBPktPhase = DWord;
TUSBState = DWord;
TUSBModeState = DWord;
TUSB = Record
Operation : TUSBOperation;
Ready : Boolean;
Status : TUSBStatus;
PktPhase : TUSBPktPhase;
CtlReqType : DWord;
CtlReq : DWord;
CtlValue : DWord;
CtlLength : DWord;
ModeDir : DWord; // Internal Operation
ModeAddr : DWord;
ModeCnt : DWord;
ModeState : TUSBModeState;
Addr : Dword;
AddrSet : Boolean;
BufR : TUSBBuf;
BufW : TUSBBuf;
End;
Var
_gUSB : TUSB;
//
Procedure USB_Init(Operation : TUSBOperation);
Procedure USB_Handler;
//
Function USB_PutSD (Var USB : TUSB) : Boolean;
Function USB_GetSD (Var USB : TUSB) : Boolean;
Implementation
Const
//
cDescDev = 1; // Device Descriptor
cDescCfg = 2; // Config Descriptor
cDescStr = 3; // String Descriptor
cDescIF = 4; // Interface Descriptor
cDescEP = 5; // EndPoint Descriptor
//
cEpBulk = 1; // Ref. EndPoint Descriptor [In,Out];
// Device Description -------------------------------------------------------
cDevDesc : Array[18] of Byte =
($12, // bLength [Always]
$01, // bDescriptorType [Device Description:$01]
$10,$01, // bcdUSB [USB Version] // $10,$01 $00,$02
$FF, // DeviceClass [Vendor Specific]
$00, // bDeviceSubClass [User Defined]
$00, // bDeviceProtocol [User Defined]
64, // bMaxPacketSize [8,16,32,64]
$BE,$1C, // idVendor [*Stellaris]
$03,$00, // idProduct [*User Define]
$00,$01, // bcdDevice [*Prod Version]
$01, // iManufacturer [Manufacturer Str Inx]
$02, // iProduct [Product Str Inx]
$03, // iSerialNumber [Serial Number Inx]
$01); // bNumConfigurations [# of Config]
// Config Description -------------------------------------------------------
cCfgDesc : Array[32] of Byte = (
// Configuration Descriptor ------------------------------------
$09, // bLength [Always $09]
$02, // bDescriptorType [Configuration Description:$02]
$20,$00, // wTotalLength [Total Size = Cfg + Sub ...]
$01, // bNumInterfaces [Interface #]
$01, // bConfigurationValue [1]
$05, // iConfiguration [Config Str Inx]
$C0, // bmAttributes [11.. = Reserved, Self Powered]
$FA, // bMaxPower [$FA x 2mA = 500 mA ]
// Inteface Descriptor -----------------------------------------
$09, // bLength [Always $09]
$04, // bDescriptorType [Interface Description:$04]
$00, // bInterfaceNumber [Interface ID]
$00, // bAlternateSetting [Alternated Service #]
$02, // bNumEndpoint [2 EP Point(1,81)]
$FF, // bInterfaceClass [*User Define]
$00, // bInterfaceSubclass [Subclass code]
$00, // bInterfaceProtocol [Protocol code]
$04, // iInterface [Interface Str Inx]
// EndPoint Descriptor (IN) ------------------------------------
$07, // bLength [Always $07]
$05, // bDescriptorType [EndPoint : $05]
$80 or cEpBulk,// bEndpointAddress [Addr : 81] <------------------ span="">
$02, // bmAttributes [Bulk]
$40,$00, // wMaxPacketSize [Pkt 64bytes, Ref. Device Desc]
$00, // bInterval [Svc Interval , NAK rate]
// EndPoint Descriptor (OUT) -----------------------------------
$07, // bLength [Always $07]
$05, // bDescriptorType [EndPoint : $05]
$00 or cEpBulk,// bEndpointAddress [Addr : 01] <------------------ span="">
$02, // bmAttributes [Bulk]
$40,$00, // wMaxPacketSize [Pkt 64bytes, Ref. Device Desc]
$00); // bInterval [Svc Interval , NAK rate]
// String Description -------------------------------------------------------
cStrLang : Array[2] of byte = ($09,$04); // $0409 US
cStrDescs : Array[5] of String[64] =
('Texas Instruments', // Str Inx 1, Manu Dev Desc
'Generic Bulk Device', // Str Inx 2, Prod Dev Desc
'12345678', // Str Inx 3, Serial Dev Desc
'Bulk Data Interface', // Str Inx 4, I/F I/F Desc
'Bulk Data Configuration'); // Str Inx 5, Cfg Cfg Desc------------------>------------------>
//
cDescDev = 1; // Device Descriptor
cDescCfg = 2; // Config Descriptor
cDescStr = 3; // String Descriptor
cDescIF = 4; // Interface Descriptor
cDescEP = 5; // EndPoint Descriptor
//
cEpBulk = 1; // Ref. EndPoint Descriptor [In,Out];
// Device Description -------------------------------------------------------
cDevDesc : Array[18] of Byte =
($12, // bLength [Always]
$01, // bDescriptorType [Device Description:$01]
$10,$01, // bcdUSB [USB Version] // $10,$01 $00,$02
$FF, // DeviceClass [Vendor Specific]
$00, // bDeviceSubClass [User Defined]
$00, // bDeviceProtocol [User Defined]
64, // bMaxPacketSize [8,16,32,64]
$BE,$1C, // idVendor [*Stellaris]
$03,$00, // idProduct [*User Define]
$00,$01, // bcdDevice [*Prod Version]
$01, // iManufacturer [Manufacturer Str Inx]
$02, // iProduct [Product Str Inx]
$03, // iSerialNumber [Serial Number Inx]
$01); // bNumConfigurations [# of Config]
// Config Description -------------------------------------------------------
cCfgDesc : Array[32] of Byte = (
// Configuration Descriptor ------------------------------------
$09, // bLength [Always $09]
$02, // bDescriptorType [Configuration Description:$02]
$20,$00, // wTotalLength [Total Size = Cfg + Sub ...]
$01, // bNumInterfaces [Interface #]
$01, // bConfigurationValue [1]
$05, // iConfiguration [Config Str Inx]
$C0, // bmAttributes [11.. = Reserved, Self Powered]
$FA, // bMaxPower [$FA x 2mA = 500 mA ]
// Inteface Descriptor -----------------------------------------
$09, // bLength [Always $09]
$04, // bDescriptorType [Interface Description:$04]
$00, // bInterfaceNumber [Interface ID]
$00, // bAlternateSetting [Alternated Service #]
$02, // bNumEndpoint [2 EP Point(1,81)]
$FF, // bInterfaceClass [*User Define]
$00, // bInterfaceSubclass [Subclass code]
$00, // bInterfaceProtocol [Protocol code]
$04, // iInterface [Interface Str Inx]
// EndPoint Descriptor (IN) ------------------------------------
$07, // bLength [Always $07]
$05, // bDescriptorType [EndPoint : $05]
$80 or cEpBulk,// bEndpointAddress [Addr : 81] <------------------ span="">
$02, // bmAttributes [Bulk]
$40,$00, // wMaxPacketSize [Pkt 64bytes, Ref. Device Desc]
$00, // bInterval [Svc Interval , NAK rate]
// EndPoint Descriptor (OUT) -----------------------------------
$07, // bLength [Always $07]
$05, // bDescriptorType [EndPoint : $05]
$00 or cEpBulk,// bEndpointAddress [Addr : 01] <------------------ span="">
$02, // bmAttributes [Bulk]
$40,$00, // wMaxPacketSize [Pkt 64bytes, Ref. Device Desc]
$00); // bInterval [Svc Interval , NAK rate]
// String Description -------------------------------------------------------
cStrLang : Array[2] of byte = ($09,$04); // $0409 US
cStrDescs : Array[5] of String[64] =
('Texas Instruments', // Str Inx 1, Manu Dev Desc
'Generic Bulk Device', // Str Inx 2, Prod Dev Desc
'12345678', // Str Inx 3, Serial Dev Desc
'Bulk Data Interface', // Str Inx 4, I/F I/F Desc
'Bulk Data Configuration'); // Str Inx 5, Cfg Cfg Desc------------------>------------------>
//------------------------------------------------------------------------------
//
// H/W Driver Function
//
//------------------------------------------------------------------------------
Const
_EP0_MAX_PACKET_SIZE = 64;
_USB_DEV_EP0_IN_PKTPEND = $00000002; // Transmit data packet pending
_USB_DEV_EP0_OUT_PKTRDY = $00000001; // Receive data packet ready
_USB_DEV_EP0_SENT_STALL = $00000004; // Stall was sent on this endpoint
_USB_DEV_EP0_SETUP_END = $00000010; // Control transaction ended before
_USB_DEV_RX_DATA_ERROR = $00080000; // CRC error on the data
_USB_DEV_RX_FIFO_FULL = $00020000; // RX FIFO full
_USB_DEV_RX_OVERRUN = $00040000; // OUT packet was not loaded due to
_USB_DEV_RX_PKT_RDY = $00010000; // Data packet ready
_USB_DEV_RX_SENT_STALL = $00400000; // Stall was sent on this endpoint
_USB_DEV_TX_SENT_STALL = $00000020; // Stall was sent on this endpoint
_USB_DEV_TX_UNDERRUN = $00000004; // IN received with no data ready
_USB_EP_0 = $00000000; // Endpoint 0
_USB_EP_1 = $00000010; // Endpoint 1
_USB_EP_AUTO_CLEAR = $00000004; // Auto clear feature enabled
_USB_EP_AUTO_SET = $00000001; // Auto set feature enabled
_USB_EP_DEV_IN = $00002000; // Device IN endpoint
_USB_EP_DEV_OUT = $00000000; // Device OUT endpoint
_USB_EP_DMA_MODE_0 = $00000008; // Enable DMA access using mode 0
_USB_EP_DMA_MODE_1 = $00000010; // Enable DMA access using mode 1
_USB_EP_HOST_OUT = $00002000; // Host OUT endpoint
_USB_EP_MODE_BULK = $00000100; // Bulk endpoint
_USB_EP_MODE_INT = $00000200; // Interrupt endpoint
_USB_EP_MODE_ISOC = $00000000; // Isochronous endpoint
_USB_EP_MODE_MASK = $00000300; // Mode Mask
_USB_FIFO_SZ_64 = $00000003; // 64 byte FIFO
_USB_INTCTRL_ALL = $000003FF; // All control interrupt sources
_USB_INTCTRL_DISCONNECT = $00000020; // Disconnect Detected
_USB_INTCTRL_MODE_DETECT = $00000200; // Mode value valid
_USB_INTCTRL_POWER_FAULT = $00000100; // Power Fault detected
_USB_INTCTRL_RESET = $00000004; // Reset signaled
_USB_INTCTRL_RESUME = $00000002; // Resume detected
_USB_INTCTRL_SOF = $00000008; // Start of Frame Detected
_USB_INTCTRL_STATUS = $000000FF; // Status Interrupts
_USB_INTCTRL_SUSPEND = $00000001; // Suspend detected
_USB_INTEP_0 = $00000001; // Endpoint 0 Interrupt
_USB_INTEP_ALL = $FFFFFFFF; // Host IN Interrupts
_USB_INTEP_DEV_IN = $0000FFFE; // Device IN Interrupts
_USB_INTEP_DEV_OUT = $FFFE0000; // Device OUT Interrupts
_USB_INTEP_HOST_IN = $FFFE0000; // Host IN Interrupts
_USB_INTEP_HOST_OUT = $0000FFFE; // Host OUT Interrupts
_USB_INTEP_RX_SHIFT = 16; // usb.c
_USB_O_FADDR = $00000000; // USB Device Functional Address
_USB_RX_EPSTATUS_SHIFT = 16;
_USB_STATE_IDLE = 0; // usbdevicepriv.h TEP0State
_USB_STATE_RX = 3;
_USB_STATE_STALL = 5;
_USB_STATE_STATUS = 4;
_USB_STATE_TX = 1;
_USB_STATE_TX_CONFIG = 2;
_USB_TRANS_IN = $00000102; // Normal IN transaction
_USB_TRANS_IN_LAST = $0000010a; // Final IN transaction (for endpoint 0 in device mode)
_USB_TXCSRH1_DMAEN = $00000010; // DMA Request Enable
_USB_TXCSRH1_DMAMOD = $00000004; // DMA Request Mode
_USB_RTYPE_TYPE_M = $60;
// Direct Access [Fast Act]
_USB0_BASE_TXIS = $40050002;
_USB0_BASE_FIFO0 = $40050020; // USB FIFO Endpoint 0
_USB0_BASE_CSRL0 = $40050102; // USB Control and Status Endpoint 0 Low
_USB0_BASE_COUNT0 = $40050108; // USB Receive Byte Count Endpoint
_USB0_BASE_TXCSRL1 = $40050112;
_USB0_BASE_RXCSRL1 = $40050116;
//
_urGetStat = 0;
_urSetAddr = 5;
_urGetDesc = 6;
_urSetConf = 9;
//
_cStrDesc = 3;
_udHost2Dev = $00;
_udDev2Host = $80;
Type
TUSBRequest = Record // usblib.h
bmRequestType : Byte; // 80
bRequest : Byte; // 00
wValue : Word; // 80
wIndex : Word; // 80
wLength : Word; // 80
End;
pUSBRequest = ^TUSBRequest;
TStrDesc = Record
Len : Byte;
StrDesc : Byte;
Dat : Array[64] of Byte;
End;
pStrDesc = ^TStrDesc;
//
// H/W Driver Function
//
//------------------------------------------------------------------------------
Const
_EP0_MAX_PACKET_SIZE = 64;
_USB_DEV_EP0_IN_PKTPEND = $00000002; // Transmit data packet pending
_USB_DEV_EP0_OUT_PKTRDY = $00000001; // Receive data packet ready
_USB_DEV_EP0_SENT_STALL = $00000004; // Stall was sent on this endpoint
_USB_DEV_EP0_SETUP_END = $00000010; // Control transaction ended before
_USB_DEV_RX_DATA_ERROR = $00080000; // CRC error on the data
_USB_DEV_RX_FIFO_FULL = $00020000; // RX FIFO full
_USB_DEV_RX_OVERRUN = $00040000; // OUT packet was not loaded due to
_USB_DEV_RX_PKT_RDY = $00010000; // Data packet ready
_USB_DEV_RX_SENT_STALL = $00400000; // Stall was sent on this endpoint
_USB_DEV_TX_SENT_STALL = $00000020; // Stall was sent on this endpoint
_USB_DEV_TX_UNDERRUN = $00000004; // IN received with no data ready
_USB_EP_0 = $00000000; // Endpoint 0
_USB_EP_1 = $00000010; // Endpoint 1
_USB_EP_AUTO_CLEAR = $00000004; // Auto clear feature enabled
_USB_EP_AUTO_SET = $00000001; // Auto set feature enabled
_USB_EP_DEV_IN = $00002000; // Device IN endpoint
_USB_EP_DEV_OUT = $00000000; // Device OUT endpoint
_USB_EP_DMA_MODE_0 = $00000008; // Enable DMA access using mode 0
_USB_EP_DMA_MODE_1 = $00000010; // Enable DMA access using mode 1
_USB_EP_HOST_OUT = $00002000; // Host OUT endpoint
_USB_EP_MODE_BULK = $00000100; // Bulk endpoint
_USB_EP_MODE_INT = $00000200; // Interrupt endpoint
_USB_EP_MODE_ISOC = $00000000; // Isochronous endpoint
_USB_EP_MODE_MASK = $00000300; // Mode Mask
_USB_FIFO_SZ_64 = $00000003; // 64 byte FIFO
_USB_INTCTRL_ALL = $000003FF; // All control interrupt sources
_USB_INTCTRL_DISCONNECT = $00000020; // Disconnect Detected
_USB_INTCTRL_MODE_DETECT = $00000200; // Mode value valid
_USB_INTCTRL_POWER_FAULT = $00000100; // Power Fault detected
_USB_INTCTRL_RESET = $00000004; // Reset signaled
_USB_INTCTRL_RESUME = $00000002; // Resume detected
_USB_INTCTRL_SOF = $00000008; // Start of Frame Detected
_USB_INTCTRL_STATUS = $000000FF; // Status Interrupts
_USB_INTCTRL_SUSPEND = $00000001; // Suspend detected
_USB_INTEP_0 = $00000001; // Endpoint 0 Interrupt
_USB_INTEP_ALL = $FFFFFFFF; // Host IN Interrupts
_USB_INTEP_DEV_IN = $0000FFFE; // Device IN Interrupts
_USB_INTEP_DEV_OUT = $FFFE0000; // Device OUT Interrupts
_USB_INTEP_HOST_IN = $FFFE0000; // Host IN Interrupts
_USB_INTEP_HOST_OUT = $0000FFFE; // Host OUT Interrupts
_USB_INTEP_RX_SHIFT = 16; // usb.c
_USB_O_FADDR = $00000000; // USB Device Functional Address
_USB_RX_EPSTATUS_SHIFT = 16;
_USB_STATE_IDLE = 0; // usbdevicepriv.h TEP0State
_USB_STATE_RX = 3;
_USB_STATE_STALL = 5;
_USB_STATE_STATUS = 4;
_USB_STATE_TX = 1;
_USB_STATE_TX_CONFIG = 2;
_USB_TRANS_IN = $00000102; // Normal IN transaction
_USB_TRANS_IN_LAST = $0000010a; // Final IN transaction (for endpoint 0 in device mode)
_USB_TXCSRH1_DMAEN = $00000010; // DMA Request Enable
_USB_TXCSRH1_DMAMOD = $00000004; // DMA Request Mode
_USB_RTYPE_TYPE_M = $60;
// Direct Access [Fast Act]
_USB0_BASE_TXIS = $40050002;
_USB0_BASE_FIFO0 = $40050020; // USB FIFO Endpoint 0
_USB0_BASE_CSRL0 = $40050102; // USB Control and Status Endpoint 0 Low
_USB0_BASE_COUNT0 = $40050108; // USB Receive Byte Count Endpoint
_USB0_BASE_TXCSRL1 = $40050112;
_USB0_BASE_RXCSRL1 = $40050116;
//
_urGetStat = 0;
_urSetAddr = 5;
_urGetDesc = 6;
_urSetConf = 9;
//
_cStrDesc = 3;
_udHost2Dev = $00;
_udDev2Host = $80;
Type
TUSBRequest = Record // usblib.h
bmRequestType : Byte; // 80
bRequest : Byte; // 00
wValue : Word; // 80
wIndex : Word; // 80
wLength : Word; // 80
End;
pUSBRequest = ^TUSBRequest;
TStrDesc = Record
Len : Byte;
StrDesc : Byte;
Dat : Array[64] of Byte;
End;
pStrDesc = ^TStrDesc;
Var
_lStrDesc : TStrDesc;
_lStrDesc : TStrDesc;
//-----------------------------------------------------------------------------
//
// Original Code : C:\StellarisWare\driverlib\usb.c
//
// Function USB_EP_TO_Index(x : DWord) : DWord;//
// Function EP_OFFSET(Endpoint : DWord) : DWord;
// Procedure USBIndexWrite(ulBase, ulEndpoint,ulIndexedReg,ulValue,ulSize : DWord);
// Procedure USBIntEnableControl(ulBase,ulFlags : DWord);
// Function USBIntStatusControl(ulBase : DWord) : DWord;
// Procedure USBIntEnableEndpoint(ulBase,ulFlags : DWord);
// Function USBIntStatusEndpoint(ulBase : DWord) : DWord;
// Function USBEndpointStatus(ulBase, ulEndpoint : DWord) : DWord;
// Procedure USBDevEndpointStatusClear(ulBase,ulEndpoint,ulFlags : DWord);
// Procedure USBDevConnect( ulBase : DWord);
// Procedure USBDevDisconnect(ulBase : DWord);
// Procedure USBDevAddrSet(ulBase, ulAddress : DWord);
// Procedure USBDevEndpointConfigSet(ulBase,ulEndpoint,ulMaxPacketSize,ulFlags : DWord);
// Procedure USBFIFOConfigSet(ulBase,ulEndpoint,ulFIFOAddress,ulFIFOSize,ulFlags : DWord);
// Function USBEndpointDataAvail(ulBase,ulEndpoint : DWord) : DWord;
// Function USBEndpointDataGet(ulBase, ulEndpoint : DWord; pucData : Pointer; Var pulSize : DWord) : LongInt;
// Procedure USBDevEndpointDataAck(ulBase, ulEndpoint : DWord; bIsLastPacket : Boolean);
// Function USBEndpointDataPut(ulBase, ulEndpoint : DWord; pucData : Pointer; ulSize : DWord) : LongInt;
// Function USBEndpointDataSend(ulBase, ulEndpoint,ulTransType : DWord) : LongInt;
// Procedure USBOTGMode(ulBase : DWord);
//
//-----------------------------------------------------------------------------
//
// Original Code : C:\StellarisWare\driverlib\usb.c
//
// Function USB_EP_TO_Index(x : DWord) : DWord;//
// Function EP_OFFSET(Endpoint : DWord) : DWord;
// Procedure USBIndexWrite(ulBase, ulEndpoint,ulIndexedReg,ulValue,ulSize : DWord);
// Procedure USBIntEnableControl(ulBase,ulFlags : DWord);
// Function USBIntStatusControl(ulBase : DWord) : DWord;
// Procedure USBIntEnableEndpoint(ulBase,ulFlags : DWord);
// Function USBIntStatusEndpoint(ulBase : DWord) : DWord;
// Function USBEndpointStatus(ulBase, ulEndpoint : DWord) : DWord;
// Procedure USBDevEndpointStatusClear(ulBase,ulEndpoint,ulFlags : DWord);
// Procedure USBDevConnect( ulBase : DWord);
// Procedure USBDevDisconnect(ulBase : DWord);
// Procedure USBDevAddrSet(ulBase, ulAddress : DWord);
// Procedure USBDevEndpointConfigSet(ulBase,ulEndpoint,ulMaxPacketSize,ulFlags : DWord);
// Procedure USBFIFOConfigSet(ulBase,ulEndpoint,ulFIFOAddress,ulFIFOSize,ulFlags : DWord);
// Function USBEndpointDataAvail(ulBase,ulEndpoint : DWord) : DWord;
// Function USBEndpointDataGet(ulBase, ulEndpoint : DWord; pucData : Pointer; Var pulSize : DWord) : LongInt;
// Procedure USBDevEndpointDataAck(ulBase, ulEndpoint : DWord; bIsLastPacket : Boolean);
// Function USBEndpointDataPut(ulBase, ulEndpoint : DWord; pucData : Pointer; ulSize : DWord) : LongInt;
// Function USBEndpointDataSend(ulBase, ulEndpoint,ulTransType : DWord) : LongInt;
// Procedure USBOTGMode(ulBase : DWord);
//
//-----------------------------------------------------------------------------
// Utility 함수
// usb.c
// Function EP_OFFSET(Endpoint : DWord) : DWord;
// usb.c
// Function EP_OFFSET(Endpoint : DWord) : DWord;
//
Procedure USBIndexWrite(ulBase, ulEndpoint,ulIndexedReg,ulValue,ulSize : DWord);
Var
ulIndex : DWord;
Begin
// Save the old index in case it was in use.
HWRegBR(ulBase + _USB_O_EPIDX,ulIndex);
// Set the index.
HWRegBW(ulBase + _USB_O_EPIDX,ulEndpoint);
// Determine the size of the register value.
Case (ulSize = 1) of
True : HWRegBW(ulBase + ulIndexedReg,ulValue);
False : HWRegHW(ulBase + ulIndexedReg,ulValue);
End;
// Restore the old index in case it was in use.
HWRegBW(ulBase + _USB_O_EPIDX, ulIndex);
End;
Procedure USBIndexWrite(ulBase, ulEndpoint,ulIndexedReg,ulValue,ulSize : DWord);
Var
ulIndex : DWord;
Begin
// Save the old index in case it was in use.
HWRegBR(ulBase + _USB_O_EPIDX,ulIndex);
// Set the index.
HWRegBW(ulBase + _USB_O_EPIDX,ulEndpoint);
// Determine the size of the register value.
Case (ulSize = 1) of
True : HWRegBW(ulBase + ulIndexedReg,ulValue);
False : HWRegHW(ulBase + ulIndexedReg,ulValue);
End;
// Restore the old index in case it was in use.
HWRegBW(ulBase + _USB_O_EPIDX, ulIndex);
End;
// usb.c
Procedure USBIntEnableControl(ulBase,ulFlags : DWord);
Var
ulVal : DWord;
begin
If(ulFlags and _USB_INTCTRL_STATUS) then
begin
HWRegBR(ulBase + _USB_O_IE,ulVal);
HWRegBW(ulBase + _USB_O_IE,ulVal or ulFlags);
end;
// Enable the power fault interrupt.
If(ulFlags and _USB_INTCTRL_POWER_FAULT) then
HWRegW(ulBase + _USB_O_EPCIM,USB_EPCIM_PF);
// Enable the ID pin detect interrupt.
If(ulFlags and _USB_INTCTRL_MODE_DETECT) then
HWRegW(_USB0_BASE + _USB_O_IDVIM,USB_IDVIM_ID);
end;
Procedure USBIntEnableControl(ulBase,ulFlags : DWord);
Var
ulVal : DWord;
begin
If(ulFlags and _USB_INTCTRL_STATUS) then
begin
HWRegBR(ulBase + _USB_O_IE,ulVal);
HWRegBW(ulBase + _USB_O_IE,ulVal or ulFlags);
end;
// Enable the power fault interrupt.
If(ulFlags and _USB_INTCTRL_POWER_FAULT) then
HWRegW(ulBase + _USB_O_EPCIM,USB_EPCIM_PF);
// Enable the ID pin detect interrupt.
If(ulFlags and _USB_INTCTRL_MODE_DETECT) then
HWRegW(_USB0_BASE + _USB_O_IDVIM,USB_IDVIM_ID);
end;
// usb.c
Function USBIntStatusControl(ulBase : DWord) : DWord;
Var
ulStatus : DWord;
_USB0_IS : Byte ; absolute 0x4005000A; volatile; sfr;
_USB0_EPCISC : Dword; absolute 0x4005040C; volatile; sfr;
_USB0_IDVISC : Dword; absolute 0x4005044C; volatile; sfr;
begin
ulStatus := _USB0_IS;
If(_USB0_EPCISC and _USB_EPCISC_PF) then
begin
ulStatus := ulStatus or _USB_INTCTRL_POWER_FAULT;
_USB0_EPCISC := _USB0_EPCISC or _USB_EPCISC_PF; // Clear power fault int
end;
Function USBIntStatusControl(ulBase : DWord) : DWord;
Var
ulStatus : DWord;
_USB0_IS : Byte ; absolute 0x4005000A; volatile; sfr;
_USB0_EPCISC : Dword; absolute 0x4005040C; volatile; sfr;
_USB0_IDVISC : Dword; absolute 0x4005044C; volatile; sfr;
begin
ulStatus := _USB0_IS;
If(_USB0_EPCISC and _USB_EPCISC_PF) then
begin
ulStatus := ulStatus or _USB_INTCTRL_POWER_FAULT;
_USB0_EPCISC := _USB0_EPCISC or _USB_EPCISC_PF; // Clear power fault int
end;
If(_USB0_IDVISC and _USB_IDVRIS_ID) then
begin
ulStatus := ulStatus or _USB_INTCTRL_MODE_DETECT;
_USB0_IDVISC := _USB0_IDVISC or _USB_IDVRIS_ID; // Clear id detection int
end;
Result := ulStatus;
end;
begin
ulStatus := ulStatus or _USB_INTCTRL_MODE_DETECT;
_USB0_IDVISC := _USB0_IDVISC or _USB_IDVRIS_ID; // Clear id detection int
end;
Result := ulStatus;
end;
// usb.
Procedure USBIntEnableEndpoint(ulBase,ulFlags : DWord);
begin
// Enable any transmit endpoint interrupts.
HWRegHW(ulBase + _USB_O_TXIE, HWRegHR(ulBase + _USB_O_TXIE) or
ulFlags and ( _USB_INTEP_HOST_OUT or _USB_INTEP_DEV_IN or _USB_INTEP_0));
// Enable any receive endpoint interrupts.
HWRegHW(ulBase + _USB_O_RXIE, HWRegHR(ulBase + _USB_O_RXIE) or
((ulFlags and (_USB_INTEP_HOST_IN or _USB_INTEP_DEV_OUT)) shr
_USB_INTEP_RX_SHIFT));
end;
// usb.c , Pascal Compiler Bug -> hand coding SIMON
Function USBIntStatusEndpoint(ulBase : DWord) : DWord;
Var
TXIS : ^DWord;
begin
TXIS := _USB0_BASE_TXIS;
Result := TXIS^; // TXIS[16] + RXIS[16]
end;
Procedure USBIntEnableEndpoint(ulBase,ulFlags : DWord);
begin
// Enable any transmit endpoint interrupts.
HWRegHW(ulBase + _USB_O_TXIE, HWRegHR(ulBase + _USB_O_TXIE) or
ulFlags and ( _USB_INTEP_HOST_OUT or _USB_INTEP_DEV_IN or _USB_INTEP_0));
// Enable any receive endpoint interrupts.
HWRegHW(ulBase + _USB_O_RXIE, HWRegHR(ulBase + _USB_O_RXIE) or
((ulFlags and (_USB_INTEP_HOST_IN or _USB_INTEP_DEV_OUT)) shr
_USB_INTEP_RX_SHIFT));
end;
// usb.c , Pascal Compiler Bug -> hand coding SIMON
Function USBIntStatusEndpoint(ulBase : DWord) : DWord;
Var
TXIS : ^DWord;
begin
TXIS := _USB0_BASE_TXIS;
Result := TXIS^; // TXIS[16] + RXIS[16]
end;
// usb.c/ Device Mode Result
Function USBEndpointStatus(ulBase, ulEndpoint : DWord) : DWord;
Var
TXCSRL : ^DWord;
RXCSRL : ^DWord;
begin
//
TXCSRL := _USB0_BASE_TXCSRL1 + (ulEndPoint-$10);
RXCSRL := _USB0_BASE_RXCSRL1 + (ulEndPoint-$10);
//
Result := (TXCSRL^ and $0000FFFF) or
(RXCSRL^ shl 16)
end;
// usb.c
Procedure USBDevEndpointStatusClear(ulBase,ulEndpoint,ulFlags : DWord);
Var
ulVal : DWord;
begin
// If this is endpoint 0, then the bits have different meaning and map
// into the TX memory location.
Case (ulEndpoint = _USB_EP_0) of
True : begin // EP0
HWRegBR( _USB0_Base_CSRL0, ulVal);
// Set the Serviced RxPktRdy bit to clear the RxPktRdy.
if(ulFlags and _USB_DEV_EP0_OUT_PKTRDY) then
HWRegBW(_USB0_Base_CSRL0, ulVal or _USB_CSRL0_RXRDYC);
// Set the serviced Setup End bit to clear the SetupEnd status.
if(ulFlags and _USB_DEV_EP0_SETUP_END) then
HWRegBW(_USB0_Base_CSRL0, ulVal or _USB_CSRL0_SETENDC);
// Clear the Sent Stall status flag.
if(ulFlags and _USB_DEV_EP0_SENT_STALL) then
HWRegBW(_USB0_Base_CSRL0, ulVal and Not(_USB_DEV_EP0_SENT_STALL));
end;
False : begin // EP1 ~
ulEndpoint := ulEndpoint - $10;
HWRegBR(_USB0_Base_TXCSRL1 + ulEndpoint,ulVal);
HWRegBW(_USB0_Base_TXCSRL1 + ulEndpoint,
ulVal and Not(ulFlags and $00000020)); // _USB_DEV_TX_SENT_STALL or _USB_DEV_TX_UNDERRUN
HWRegBR(_USB0_Base_RXCSRL1 + ulEndpoint,ulVal);
HWRegBW(_USB0_Base_RXCSRL1 + ulEndpoint,
ulVal and Not((ulFlags and $004C0000) shr 16));
// Not((ulFlags and (_USB_DEV_RX_SENT_STALL or _USB_DEV_RX_DATA_ERROR or
// _USB_DEV_RX_OVERRUN)) shr _USB_RX_EPSTATUS_SHIFT));
end;
end;
end;
Function USBEndpointStatus(ulBase, ulEndpoint : DWord) : DWord;
Var
TXCSRL : ^DWord;
RXCSRL : ^DWord;
begin
//
TXCSRL := _USB0_BASE_TXCSRL1 + (ulEndPoint-$10);
RXCSRL := _USB0_BASE_RXCSRL1 + (ulEndPoint-$10);
//
Result := (TXCSRL^ and $0000FFFF) or
(RXCSRL^ shl 16)
end;
// usb.c
Procedure USBDevEndpointStatusClear(ulBase,ulEndpoint,ulFlags : DWord);
Var
ulVal : DWord;
begin
// If this is endpoint 0, then the bits have different meaning and map
// into the TX memory location.
Case (ulEndpoint = _USB_EP_0) of
True : begin // EP0
HWRegBR( _USB0_Base_CSRL0, ulVal);
// Set the Serviced RxPktRdy bit to clear the RxPktRdy.
if(ulFlags and _USB_DEV_EP0_OUT_PKTRDY) then
HWRegBW(_USB0_Base_CSRL0, ulVal or _USB_CSRL0_RXRDYC);
// Set the serviced Setup End bit to clear the SetupEnd status.
if(ulFlags and _USB_DEV_EP0_SETUP_END) then
HWRegBW(_USB0_Base_CSRL0, ulVal or _USB_CSRL0_SETENDC);
// Clear the Sent Stall status flag.
if(ulFlags and _USB_DEV_EP0_SENT_STALL) then
HWRegBW(_USB0_Base_CSRL0, ulVal and Not(_USB_DEV_EP0_SENT_STALL));
end;
False : begin // EP1 ~
ulEndpoint := ulEndpoint - $10;
HWRegBR(_USB0_Base_TXCSRL1 + ulEndpoint,ulVal);
HWRegBW(_USB0_Base_TXCSRL1 + ulEndpoint,
ulVal and Not(ulFlags and $00000020)); // _USB_DEV_TX_SENT_STALL or _USB_DEV_TX_UNDERRUN
HWRegBR(_USB0_Base_RXCSRL1 + ulEndpoint,ulVal);
HWRegBW(_USB0_Base_RXCSRL1 + ulEndpoint,
ulVal and Not((ulFlags and $004C0000) shr 16));
// Not((ulFlags and (_USB_DEV_RX_SENT_STALL or _USB_DEV_RX_DATA_ERROR or
// _USB_DEV_RX_OVERRUN)) shr _USB_RX_EPSTATUS_SHIFT));
end;
end;
end;
// usb.c
Procedure USBDevConnect( ulBase : DWord);
Var
ulVal : DWord;
begin
// Enable connection to the USB bus.
HWRegBR(ulBase + _USB_O_POWER,ulVal);
HWRegBW(ulBase + _USB_O_POWER,ulVal or _USB_POWER_SOFTCONN);
end;
Procedure USBDevConnect( ulBase : DWord);
Var
ulVal : DWord;
begin
// Enable connection to the USB bus.
HWRegBR(ulBase + _USB_O_POWER,ulVal);
HWRegBW(ulBase + _USB_O_POWER,ulVal or _USB_POWER_SOFTCONN);
end;
// usb.c
Procedure USBDevDisconnect(ulBase : DWord);
Var
ulVal : DWord;
begin
// Disable connection to the USB bus.
HWRegBR(ulBase + _USB_O_POWER,ulVal);
HWRegBW(ulBase + _USB_O_POWER,ulVal and Not(_USB_POWER_SOFTCONN));
end;
Procedure USBDevDisconnect(ulBase : DWord);
Var
ulVal : DWord;
begin
// Disable connection to the USB bus.
HWRegBR(ulBase + _USB_O_POWER,ulVal);
HWRegBW(ulBase + _USB_O_POWER,ulVal and Not(_USB_POWER_SOFTCONN));
end;
// usb.c
Procedure USBDevAddrSet(ulBase, ulAddress : DWord);
begin
// Set the function address in the correct location.
HWRegBW(ulBase + _USB_O_FADDR, byte(ulAddress));
end;
Procedure USBDevAddrSet(ulBase, ulAddress : DWord);
begin
// Set the function address in the correct location.
HWRegBW(ulBase + _USB_O_FADDR, byte(ulAddress));
end;
// usb.c
Procedure USBDevEndpointConfigSet(ulBase,ulEndpoint,ulMaxPacketSize,ulFlags : DWord);
Var
ulRegister : DWord;
begin
Case (ulFlags and _USB_EP_DEV_IN) of
True : begin
// Set the maximum packet size.
HWRegHW(ulBase + (ulEndpoint- $10) + _USB_O_TXMAXP1, ulMaxPacketSize);
ulRegister := 0;
If (ulFlags and _USB_EP_AUTO_SET) then
ulRegister := ulRegister or _USB_TXCSRH1_AUTOSET;
// Configure the DMA mode.
Case (ulFlags and _USB_EP_DMA_MODE_1) of
True : ulRegister := ulRegister or _USB_TXCSRH1_DMAEN or _USB_TXCSRH1_DMAMOD;
False: If(ulFlags and _USB_EP_DMA_MODE_0) then
ulRegister := ulRegister or USB_TXCSRH1_DMAEN;
End;
// Enable isochronous mode if requested.
if((ulFlags and _USB_EP_MODE_MASK) = _USB_EP_MODE_ISOC) then
ulRegister := ulRegister or USB_TXCSRH1_ISO;
// Write the transmit control value.
HWRegBW(ulBase + (ulEndpoint-$10) + _USB_O_TXCSRH1,ulRegister);
// Reset the Data toggle to zero.
HWRegBW(ulBase + (ulEndpoint-$10) + _USB_O_TXCSRL1,_USB_TXCSRL1_CLRDT);
end;
False:begin
// Set the MaxPacketSize.
HWRegHW(ulBase + (ulEndpoint-$10) + _USB_O_RXMAXP1,ulMaxPacketSize);
ulRegister := 0;
if(ulFlags and _USB_EP_AUTO_CLEAR) then
ulRegister := _USB_RXCSRH1_AUTOCL;
// Configure the DMA mode.
Case (ulFlags and _USB_EP_DMA_MODE_1) of
True : ulRegister := ulRegister or _USB_RXCSRH1_DMAEN or _USB_RXCSRH1_DMAMOD;
False: If (ulFlags and _USB_EP_DMA_MODE_0) then
ulRegister := ulRegister or _USB_RXCSRH1_DMAEN;
End;
// Enable isochronous mode if requested.
if((ulFlags and _USB_EP_MODE_MASK) = _USB_EP_MODE_ISOC) then
ulRegister := ulRegister or _USB_RXCSRH1_ISO;
// Write the receive control value.
HWRegBW(ulBase + (ulEndpoint-$10) + _USB_O_RXCSRH1,ulRegister);
// Reset the Data toggle to zero.
HWRegBW(ulBase + (ulEndpoint-$10) + _USB_O_RXCSRL1,_USB_RXCSRL1_CLRDT);
end;
end;
end;
Procedure USBDevEndpointConfigSet(ulBase,ulEndpoint,ulMaxPacketSize,ulFlags : DWord);
Var
ulRegister : DWord;
begin
Case (ulFlags and _USB_EP_DEV_IN) of
True : begin
// Set the maximum packet size.
HWRegHW(ulBase + (ulEndpoint- $10) + _USB_O_TXMAXP1, ulMaxPacketSize);
ulRegister := 0;
If (ulFlags and _USB_EP_AUTO_SET) then
ulRegister := ulRegister or _USB_TXCSRH1_AUTOSET;
// Configure the DMA mode.
Case (ulFlags and _USB_EP_DMA_MODE_1) of
True : ulRegister := ulRegister or _USB_TXCSRH1_DMAEN or _USB_TXCSRH1_DMAMOD;
False: If(ulFlags and _USB_EP_DMA_MODE_0) then
ulRegister := ulRegister or USB_TXCSRH1_DMAEN;
End;
// Enable isochronous mode if requested.
if((ulFlags and _USB_EP_MODE_MASK) = _USB_EP_MODE_ISOC) then
ulRegister := ulRegister or USB_TXCSRH1_ISO;
// Write the transmit control value.
HWRegBW(ulBase + (ulEndpoint-$10) + _USB_O_TXCSRH1,ulRegister);
// Reset the Data toggle to zero.
HWRegBW(ulBase + (ulEndpoint-$10) + _USB_O_TXCSRL1,_USB_TXCSRL1_CLRDT);
end;
False:begin
// Set the MaxPacketSize.
HWRegHW(ulBase + (ulEndpoint-$10) + _USB_O_RXMAXP1,ulMaxPacketSize);
ulRegister := 0;
if(ulFlags and _USB_EP_AUTO_CLEAR) then
ulRegister := _USB_RXCSRH1_AUTOCL;
// Configure the DMA mode.
Case (ulFlags and _USB_EP_DMA_MODE_1) of
True : ulRegister := ulRegister or _USB_RXCSRH1_DMAEN or _USB_RXCSRH1_DMAMOD;
False: If (ulFlags and _USB_EP_DMA_MODE_0) then
ulRegister := ulRegister or _USB_RXCSRH1_DMAEN;
End;
// Enable isochronous mode if requested.
if((ulFlags and _USB_EP_MODE_MASK) = _USB_EP_MODE_ISOC) then
ulRegister := ulRegister or _USB_RXCSRH1_ISO;
// Write the receive control value.
HWRegBW(ulBase + (ulEndpoint-$10) + _USB_O_RXCSRH1,ulRegister);
// Reset the Data toggle to zero.
HWRegBW(ulBase + (ulEndpoint-$10) + _USB_O_RXCSRL1,_USB_RXCSRL1_CLRDT);
end;
end;
end;
// usb.c
Procedure USBFIFOConfigSet(ulBase,ulEndpoint,ulFIFOAddress,ulFIFOSize,ulFlags : DWord);
begin
// See if the transmit or receive FIFO is being configured.
Case (ulFlags and (_USB_EP_HOST_OUT or _USB_EP_DEV_IN)) of
True : // Set the transmit FIFO location and size for this endpoint.
begin
USBIndexWrite(ulBase, ulEndpoint shr 4, _USB_O_TXFIFOSZ, ulFIFOSize, 1);
USBIndexWrite(ulBase, ulEndpoint shr 4, _USB_O_TXFIFOADD,ulFIFOAddress shr 3, 2);
end;
False: // Set the receive FIFO location and size for this endpoint.
begin
USBIndexWrite(ulBase, ulEndpoint shr 4, _USB_O_RXFIFOSZ, ulFIFOSize, 1);
USBIndexWrite(ulBase, ulEndpoint shr 4, _USB_O_RXFIFOADD,ulFIFOAddress shr 3, 2);
end;
end;
end;
Procedure USBFIFOConfigSet(ulBase,ulEndpoint,ulFIFOAddress,ulFIFOSize,ulFlags : DWord);
begin
// See if the transmit or receive FIFO is being configured.
Case (ulFlags and (_USB_EP_HOST_OUT or _USB_EP_DEV_IN)) of
True : // Set the transmit FIFO location and size for this endpoint.
begin
USBIndexWrite(ulBase, ulEndpoint shr 4, _USB_O_TXFIFOSZ, ulFIFOSize, 1);
USBIndexWrite(ulBase, ulEndpoint shr 4, _USB_O_TXFIFOADD,ulFIFOAddress shr 3, 2);
end;
False: // Set the receive FIFO location and size for this endpoint.
begin
USBIndexWrite(ulBase, ulEndpoint shr 4, _USB_O_RXFIFOSZ, ulFIFOSize, 1);
USBIndexWrite(ulBase, ulEndpoint shr 4, _USB_O_RXFIFOADD,ulFIFOAddress shr 3, 2);
end;
end;
end;
// usb.c
Function USBEndpointDataAvail(ulBase,ulEndpoint : DWord) : DWord;
Var
ulRegister : DWord;
ulFIFO : ^DWord;
begin
// Get the address of the receive status register to use, based on the endpoint.
Case (ulEndpoint = _USB_EP_0) of
True : ulRegister := _USB0_BASE_CSRL0;
False : ulRegister := _USB0_BASE_RXCSRL1 + (ulEndpoint-$10);
End;
// Is there a packet ready in the FIFO?
ulFIFO := ulRegister;
If (ulFIFO^ and _USB_CSRL0_RXRDY) = 0 then
begin
Result := 0;
Exit;
end;
// Return the byte count in the FIFO.
ulFIFO := _USB0_BASE_COUNT0 + ulEndpoint;
Result := ulFIFO^;
end;
Function USBEndpointDataAvail(ulBase,ulEndpoint : DWord) : DWord;
Var
ulRegister : DWord;
ulFIFO : ^DWord;
begin
// Get the address of the receive status register to use, based on the endpoint.
Case (ulEndpoint = _USB_EP_0) of
True : ulRegister := _USB0_BASE_CSRL0;
False : ulRegister := _USB0_BASE_RXCSRL1 + (ulEndpoint-$10);
End;
// Is there a packet ready in the FIFO?
ulFIFO := ulRegister;
If (ulFIFO^ and _USB_CSRL0_RXRDY) = 0 then
begin
Result := 0;
Exit;
end;
// Return the byte count in the FIFO.
ulFIFO := _USB0_BASE_COUNT0 + ulEndpoint;
Result := ulFIFO^;
end;
//
Procedure USBDevEndpointDataAck(ulBase, ulEndpoint : DWord; bIsLastPacket : Boolean);
Var
ulVal : DWord;
begin
// Determine which endpoint is being acked.
Case (ulEndpoint = _USB_EP_0) of
True : // Clear RxPktRdy, and optionally DataEnd, on endpoint zero.
Case bIsLastPacket of
True : HWRegBW(ulBase + _USB_O_CSRL0,_USB_CSRL0_RXRDYC or _USB_CSRL0_DataEnd);
False: HWRegBW(ulBase + _USB_O_CSRL0,_USB_CSRL0_RXRDYC );
End;
False: // Clear RxPktRdy on all other endpoints.
Begin
HWRegBR(ulBase + _USB_O_RXCSRL1 + (ulEndpoint-$10),ulVal);
HWRegBW(ulBase + _USB_O_RXCSRL1 + (ulEndpoint-$10),
ulVal and Not(Dword(_USB_RXCSRL1_RXRDY)));
End;
End;
End;
// R0 R1 R2
Procedure USBGetData(ulFIFO :DWord; Var Buf : Array[1] of Byte; Lp : DWord);
begin
asm
Loop:
LDR R3,[R0,#0]; // Load Data
STR R3,[R1,#0]; // Save Data to Buf
SUBS R2, R2, #4; // Dec Lp
ADD R1, R1, #4; // Pointer Move +1
BNE Loop; //
end;
end;
Procedure USBDevEndpointDataAck(ulBase, ulEndpoint : DWord; bIsLastPacket : Boolean);
Var
ulVal : DWord;
begin
// Determine which endpoint is being acked.
Case (ulEndpoint = _USB_EP_0) of
True : // Clear RxPktRdy, and optionally DataEnd, on endpoint zero.
Case bIsLastPacket of
True : HWRegBW(ulBase + _USB_O_CSRL0,_USB_CSRL0_RXRDYC or _USB_CSRL0_DataEnd);
False: HWRegBW(ulBase + _USB_O_CSRL0,_USB_CSRL0_RXRDYC );
End;
False: // Clear RxPktRdy on all other endpoints.
Begin
HWRegBR(ulBase + _USB_O_RXCSRL1 + (ulEndpoint-$10),ulVal);
HWRegBW(ulBase + _USB_O_RXCSRL1 + (ulEndpoint-$10),
ulVal and Not(Dword(_USB_RXCSRL1_RXRDY)));
End;
End;
End;
// R0 R1 R2
Procedure USBGetData(ulFIFO :DWord; Var Buf : Array[1] of Byte; Lp : DWord);
begin
asm
Loop:
LDR R3,[R0,#0]; // Load Data
STR R3,[R1,#0]; // Save Data to Buf
SUBS R2, R2, #4; // Dec Lp
ADD R1, R1, #4; // Pointer Move +1
BNE Loop; //
end;
end;
// 추후 Word단위 수정 요망
// R0 R1 R2
Procedure USBPutData(ulFIFO :DWord; Var Buf : Array[1] of Byte; Lp : DWord);
begin
asm
Loop:
LDRB R3,[R1,#0]; // Save Data to Buf
STRB R3,[R0,#0]; // Load Data
SUBS R2, R2, #1; // Dec Lp
ADD R1, R1, #1; // Pointer Move +1
BNE Loop; //
end;
end;
// usb.c
Function USBEndpointDataGet (ulBase, ulEndpoint : DWord;
pucData : Pointer; Var pulSize : DWord) : LongInt;
Var
ulRegister : DWord;
ulByteCount : DWord;
ulFIFO : DWord;
ulVal : ^DWord;
Bv : Byte;
Lp : Byte;
begin
// Get the address of the receive status register to use, based on the endpoint.
Case (ulEndpoint = _USB_EP_0) of
True : ulRegister := _USB0_BASE_CSRL0;
False : ulRegister := _USB0_BASE_RXCSRL1 + (ulEndpoint-$10);
End;
// Don't allow reading of data if the RxPktRdy bit is not set.
ulVal := ulRegister;
If (ulVal^ and _USB_CSRL0_RXRDY) = 0 then
begin
pulSize := 0;
Result := -1;
Exit;
end;
// Get the byte count in the FIFO.
ulVal := _USB0_BASE_COUNT0 + ulEndPoint;
ulByteCount := ulVal^;
If (ulByteCount >= pulSize) then
ulByteCount := pulSize;
// Return the number of bytes we are going to read.
pulSize := ulByteCount;
// Calculate the FIFO address.
ulFIFO := _USB0_BASE_FIFO0 + (ulEndpoint shr 2);
//
{
Lp := 0;
While (ulByteCount > 0) do
begin
HWRegBR(ulFIFO,Bv);
_gUSB.BufR[lp] := Bv;
Inc(lp);
Dec(ulByteCount);
end;
}
//USBGetData(ulFIFO,_gUSB.BufR,ulByteCount);
USBGetData(ulFIFO,pucData,ulByteCount);
// Success.
Result := 0;
end;
// R0 R1 R2
Procedure USBPutData(ulFIFO :DWord; Var Buf : Array[1] of Byte; Lp : DWord);
begin
asm
Loop:
LDRB R3,[R1,#0]; // Save Data to Buf
STRB R3,[R0,#0]; // Load Data
SUBS R2, R2, #1; // Dec Lp
ADD R1, R1, #1; // Pointer Move +1
BNE Loop; //
end;
end;
// usb.c
Function USBEndpointDataGet (ulBase, ulEndpoint : DWord;
pucData : Pointer; Var pulSize : DWord) : LongInt;
Var
ulRegister : DWord;
ulByteCount : DWord;
ulFIFO : DWord;
ulVal : ^DWord;
Bv : Byte;
Lp : Byte;
begin
// Get the address of the receive status register to use, based on the endpoint.
Case (ulEndpoint = _USB_EP_0) of
True : ulRegister := _USB0_BASE_CSRL0;
False : ulRegister := _USB0_BASE_RXCSRL1 + (ulEndpoint-$10);
End;
// Don't allow reading of data if the RxPktRdy bit is not set.
ulVal := ulRegister;
If (ulVal^ and _USB_CSRL0_RXRDY) = 0 then
begin
pulSize := 0;
Result := -1;
Exit;
end;
// Get the byte count in the FIFO.
ulVal := _USB0_BASE_COUNT0 + ulEndPoint;
ulByteCount := ulVal^;
If (ulByteCount >= pulSize) then
ulByteCount := pulSize;
// Return the number of bytes we are going to read.
pulSize := ulByteCount;
// Calculate the FIFO address.
ulFIFO := _USB0_BASE_FIFO0 + (ulEndpoint shr 2);
//
{
Lp := 0;
While (ulByteCount > 0) do
begin
HWRegBR(ulFIFO,Bv);
_gUSB.BufR[lp] := Bv;
Inc(lp);
Dec(ulByteCount);
end;
}
//USBGetData(ulFIFO,_gUSB.BufR,ulByteCount);
USBGetData(ulFIFO,pucData,ulByteCount);
// Success.
Result := 0;
end;
// usb.c
Function USBEndpointDataPut( ulBase, ulEndpoint : DWord;
pucData : Pointer; ulSize : DWord) : LongInt;
Var
ulFIFO : DWord;
ucTxPktRdy : Byte;
ulVal : DWord;
begin
// Get the bit position of TxPktRdy based on the endpoint.
Case (ulEndpoint = _USB_EP_0) of
True : ucTxPktRdy := _USB_CSRL0_TXRDY;
False : ucTxPktRdy := _USB_TXCSRL1_TXRDY;
End;
// Don't allow transmit of data if the TxPktRdy bit is already set.
HWRegBR(ulBase + _USB_O_CSRL0 + ulEndpoint,ulVal);
If (ulVal and ucTxPktRdy) then
begin
Result := -1;
Exit;
end;
// Calculate the FIFO address.
ulFIFO := ulBase + _USB_O_FIFO0 + (ulEndpoint shr 2);
// Write the data to the FIFO.
{
While (ulSize > 0) do
begin
HWRegBW(ulFIFO,pucData^); // SIMON / 최적화 필요
Inc(pucData);
Dec(ulSize);
end;
}
Function USBEndpointDataPut( ulBase, ulEndpoint : DWord;
pucData : Pointer; ulSize : DWord) : LongInt;
Var
ulFIFO : DWord;
ucTxPktRdy : Byte;
ulVal : DWord;
begin
// Get the bit position of TxPktRdy based on the endpoint.
Case (ulEndpoint = _USB_EP_0) of
True : ucTxPktRdy := _USB_CSRL0_TXRDY;
False : ucTxPktRdy := _USB_TXCSRL1_TXRDY;
End;
// Don't allow transmit of data if the TxPktRdy bit is already set.
HWRegBR(ulBase + _USB_O_CSRL0 + ulEndpoint,ulVal);
If (ulVal and ucTxPktRdy) then
begin
Result := -1;
Exit;
end;
// Calculate the FIFO address.
ulFIFO := ulBase + _USB_O_FIFO0 + (ulEndpoint shr 2);
// Write the data to the FIFO.
{
While (ulSize > 0) do
begin
HWRegBW(ulFIFO,pucData^); // SIMON / 최적화 필요
Inc(pucData);
Dec(ulSize);
end;
}
USBPutData(ulFIFO,pucData,ulSize);
// Success.
Result := 0;
end;
// Success.
Result := 0;
end;
//
Function USBEndpointDataSend(ulBase, ulEndpoint,ulTransType : DWord) : LongInt;
Var
ulTxPktRdy : DWord;
ulVal : DWord;
begin
// Get the bit position of TxPktRdy based on the endpoint.
if(ulEndpoint = _USB_EP_0) then
ulTxPktRdy := ulTransType and $ff
else
ulTxPktRdy := (ulTransType shr 8) and $ff;
// Don't allow transmit of data if the TxPktRdy bit is already set.
HWRegBR(ulBase + _USB_O_CSRL0 + ulEndpoint,ulVal);
If (ulVal and _USB_CSRL0_TXRDY) then
begin
Result := -1;
Exit;
end;
// Set TxPktRdy in order to send the data.
HWRegBW(ulBase + _USB_O_CSRL0 + ulEndpoint, ulTxPktRdy);
// Success.
Result := 0;
end;
Function USBEndpointDataSend(ulBase, ulEndpoint,ulTransType : DWord) : LongInt;
Var
ulTxPktRdy : DWord;
ulVal : DWord;
begin
// Get the bit position of TxPktRdy based on the endpoint.
if(ulEndpoint = _USB_EP_0) then
ulTxPktRdy := ulTransType and $ff
else
ulTxPktRdy := (ulTransType shr 8) and $ff;
// Don't allow transmit of data if the TxPktRdy bit is already set.
HWRegBR(ulBase + _USB_O_CSRL0 + ulEndpoint,ulVal);
If (ulVal and _USB_CSRL0_TXRDY) then
begin
Result := -1;
Exit;
end;
// Set TxPktRdy in order to send the data.
HWRegBW(ulBase + _USB_O_CSRL0 + ulEndpoint, ulTxPktRdy);
// Success.
Result := 0;
end;
// usb.c
Procedure USBOTGMode(ulBase : DWord);
begin
// Disable the override of the USB controller mode when running on an OTG device.
HWRegBW(ulBase + _USB_O_GPCS,0);
end;
Procedure USBOTGMode(ulBase : DWord);
begin
// Disable the override of the USB controller mode when running on an OTG device.
HWRegBW(ulBase + _USB_O_GPCS,0);
end;
//------------------------------------------------------------------------------
// Utility Function
//------------------------------------------------------------------------------
// Utility Function
//------------------------------------------------------------------------------
//
Procedure utGetStrDesc(inx : DWord; Var ugDesc : TStrDesc);
Var
uLp : DWord;
uLen : DWord;
Begin
//
If Inx > 5 then Inx := 2; // Str Product
//
ugDesc.StrDesc := _cStrDesc;
//
Case inx of
0 : Begin
ugDesc.Len := 4;
ugDesc.Dat[0] := cStrlang[0];
ugDesc.Dat[1] := cStrlang[1];
End
else Begin
Dec(inx); // Set Inx
uLen := Length(cStrDescs[inx]);
ugDesc.Len := uLen*2 + 2; // Size + StrDesc + Str
For uLp := 0 to uLen-1 do
begin
ugDesc.Dat[uLp*2+0] := cStrDescs[inx][uLp];
ugDesc.Dat[uLp*2+1] := 0;
end;
End;
End;
End;
Procedure utGetStrDesc(inx : DWord; Var ugDesc : TStrDesc);
Var
uLp : DWord;
uLen : DWord;
Begin
//
If Inx > 5 then Inx := 2; // Str Product
//
ugDesc.StrDesc := _cStrDesc;
//
Case inx of
0 : Begin
ugDesc.Len := 4;
ugDesc.Dat[0] := cStrlang[0];
ugDesc.Dat[1] := cStrlang[1];
End
else Begin
Dec(inx); // Set Inx
uLen := Length(cStrDescs[inx]);
ugDesc.Len := uLen*2 + 2; // Size + StrDesc + Str
For uLp := 0 to uLen-1 do
begin
ugDesc.Dat[uLp*2+0] := cStrDescs[inx][uLp];
ugDesc.Dat[uLp*2+1] := 0;
end;
End;
End;
End;
//------------------------------------------------------------------------------
//
// S/W Driver Function
//
//------------------------------------------------------------------------------
//
// S/W Driver Function
//
//------------------------------------------------------------------------------
//
Procedure User_Reply(Var USB : TUSB);
Var
lRetCode : Integer;
begin
USB.BufW[0] := $10;
USB.BufW[1] := $20;
lRetcode := USBEndpointDataPut(_USB0_BASE,$10,@USB.BufR,64);
If lRetcode = -1 then Exit;
USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In_Last);
end;
Procedure User_Reply(Var USB : TUSB);
Var
lRetCode : Integer;
begin
USB.BufW[0] := $10;
USB.BufW[1] := $20;
lRetcode := USBEndpointDataPut(_USB0_BASE,$10,@USB.BufR,64);
If lRetcode = -1 then Exit;
USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In_Last);
end;
// 단 USB.ModeCnt > 0 이상
Procedure Bulk_DevToPc_Start(Var USB : TUSB);
Var
lRetCode : Integer;
begin
// 첫 번째 패킷 전송
lRetcode := USBEndpointDataPut(_USB0_BASE,$10,@USB.BufW,64);
If lRetcode = -1 then Exit;
//
Case (USB.ModeCnt = 1) of
True : USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In_Last);
False : USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In );
End;
end;
Procedure Bulk_DevToPc_Start(Var USB : TUSB);
Var
lRetCode : Integer;
begin
// 첫 번째 패킷 전송
lRetcode := USBEndpointDataPut(_USB0_BASE,$10,@USB.BufW,64);
If lRetcode = -1 then Exit;
//
Case (USB.ModeCnt = 1) of
True : USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In_Last);
False : USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In );
End;
end;
//
Procedure Bulk_DevToPC_Send(Var USB : TUSB; ulEPStatus : DWord);
Var
lRetCode : Integer;
ulLength : DWord;
begin
USBDevEndpointStatusClear(_USB0_BASE,$10 {cEpBulk},ulEPStatus);
//If _gUSB.UserCmd <>
Dec(USB.ModeCnt);
//
Case (USB.ModeCnt = 0) of
True : // 종료
begin
LCD_Log(clWhite,'Bulk End');
Exit;
end;
False: // 다음 블럭
begin
ulLength := 64;
lRetcode := USBEndpointDataPut(_USB0_BASE,$10,@USB.BufW,ulLength);
If lRetcode = -1 then Exit;
Case (USB.ModeCnt = 1) of
True : USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In_Last);
False : USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In );
End;
end;
End;
end;
Procedure Bulk_DevToPC_Send(Var USB : TUSB; ulEPStatus : DWord);
Var
lRetCode : Integer;
ulLength : DWord;
begin
USBDevEndpointStatusClear(_USB0_BASE,$10 {cEpBulk},ulEPStatus);
//If _gUSB.UserCmd <>
Dec(USB.ModeCnt);
//
Case (USB.ModeCnt = 0) of
True : // 종료
begin
LCD_Log(clWhite,'Bulk End');
Exit;
end;
False: // 다음 블럭
begin
ulLength := 64;
lRetcode := USBEndpointDataPut(_USB0_BASE,$10,@USB.BufW,ulLength);
If lRetcode = -1 then Exit;
Case (USB.ModeCnt = 1) of
True : USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In_Last);
False : USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In );
End;
end;
End;
end;
// HandleEndpoints ( usbdbulk.c )
// ProcessDataFromHost ( usbdbulk.c )
// USBDBulkPacketRead
// ProcessDataToHost ( usbdbulk.c )
// USBDBulkPacketWrite
Procedure Process_EP1(Var USB :TUSB; ulStatus :DWord); // Ep[1~x]
Var
ulEPStatus : DWord;
ulSize : DWord;
lRetCode : Integer;
begin
// Host -> Dev : Bulk Out // Process_DataFromHost, USBDBulkPacketRead -------
If (ulStatus and $00020000) then // Hard Coding , Simon 추후 변경
begin
ulEPStatus := USBEndpointStatus (_USB0_BASE, $10 {cEpBulk} );
// $0003:0000 -> RX_FIFO_FULL & RX_PKT_RDY
If (ulEPStatus and _USB_DEV_RX_PKT_RDY) then
begin
ulSize := USBEndpointDataAvail (_USB0_Base, $10 {cEpBulk} );
USBEndPointDataGet (_USB0_Base, $10,@_gUSB.BufR,ulSize );
//
USBDevEndpointStatusClear (_USB0_BASE, $10 {cEpBulk} , ulEPStatus);
USBDevEndpointDataAck (_USB0_Base, $10 {cEpBulk} , True);
If USB.ModeDir = _DirInOut then
User_Reply(USB);
end;
end;
// Dev -> Host : Bulk In ( Process_DataToHost(ulStatus) )-------------------
If (ulStatus and $00000002) then // Hard Coding, Simon 추후 변경
begin
If USB.ModeDir <> _DirIn then Exit; // DirIn [PC<-dev span="">
ulEPStatus := USBEndpointStatus (_USB0_BASE, $10 {cEpBulk} );
Bulk_DevToPC_Send(USB,ulEPStatus);
end;
end;-dev>
// Process User Command :
Procedure Process_EP0_User(Var USB : TUSB);
Var
pUSBBuf : pUSBBufDW;
begin
//
Case USB.PktPhase of
_pSetup : // Check Get Set Request
If USB.CtlReq = _CmdReqFunc then
Case (USB.CtlReqType and _udDev2Host) > 0 of
True : // Get Request ( No Data Phase )
begin
USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,false);
Case USB.CtlValue of
_CmdGetStatus : // 적당한 응답 (Dir + Addr + Cnt)
begin
USBEndpointDataPut (_USB0_BASE,_USB_EP_0,@USB.ModeDir,12);
USBEndpointDataSend(_USB0_BASE,_USB_EP_0,_USB_TRANS_IN_LAST);
end;
End;
end;
False: // Set Request -> Read Data
Case USB.CtlLength = 0 of
True : USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,True);
False: Begin
USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,false);
USB.PktPhase := _pData;
End;
end;
end;
_pData : // Data Phase for User Command
begin
USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,True);
If (USB.CtlReq = _CmdReqFunc) then
Case USB.CtlValue of
_CmdSetStatus : begin
pUSBBuf := Pointer(@USB.BufR);
USB.ModeDir := pUSBBuf^[0];
USB.ModeAddr := pUSBBuf^[1];
USB.ModeCnt := pUSBBuf^[2];
end;
_CmdSetAction : begin
pUSBBuf := Pointer(@USB.BufR);
USB.ModeState := pUSBBuf^[0];
// Simon : Future Works...
If USB.ModeState = _tmsStop then
SD_MovStop := True;
// Bulk_DevToPc_Start(USB);
end;
end;
end;
End;
end;
Procedure Process_EP0_User(Var USB : TUSB);
Var
pUSBBuf : pUSBBufDW;
begin
//
Case USB.PktPhase of
_pSetup : // Check Get Set Request
If USB.CtlReq = _CmdReqFunc then
Case (USB.CtlReqType and _udDev2Host) > 0 of
True : // Get Request ( No Data Phase )
begin
USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,false);
Case USB.CtlValue of
_CmdGetStatus : // 적당한 응답 (Dir + Addr + Cnt)
begin
USBEndpointDataPut (_USB0_BASE,_USB_EP_0,@USB.ModeDir,12);
USBEndpointDataSend(_USB0_BASE,_USB_EP_0,_USB_TRANS_IN_LAST);
end;
End;
end;
False: // Set Request -> Read Data
Case USB.CtlLength = 0 of
True : USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,True);
False: Begin
USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,false);
USB.PktPhase := _pData;
End;
end;
end;
_pData : // Data Phase for User Command
begin
USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,True);
If (USB.CtlReq = _CmdReqFunc) then
Case USB.CtlValue of
_CmdSetStatus : begin
pUSBBuf := Pointer(@USB.BufR);
USB.ModeDir := pUSBBuf^[0];
USB.ModeAddr := pUSBBuf^[1];
USB.ModeCnt := pUSBBuf^[2];
end;
_CmdSetAction : begin
pUSBBuf := Pointer(@USB.BufR);
USB.ModeState := pUSBBuf^[0];
// Simon : Future Works...
If USB.ModeState = _tmsStop then
SD_MovStop := True;
// Bulk_DevToPc_Start(USB);
end;
end;
end;
End;
end;
// Ref. USBDeviceEnumHandler (usbdenum.c)
Procedure Process_EP0(Var USB : TUSB);
Var
EP0Stat : DWord;
pDat : Pointer;
dSize : DWord;
wData : Word;
pRequest : pUSBRequest;
pUSBBuf : pUSBBufDW;
begin
Ep0Stat := USBEndpointStatus(_USB0_BASE, _USB_EP_0); // -값 발생 (Simon)
Procedure Process_EP0(Var USB : TUSB);
Var
EP0Stat : DWord;
pDat : Pointer;
dSize : DWord;
wData : Word;
pRequest : pUSBRequest;
pUSBBuf : pUSBBufDW;
begin
Ep0Stat := USBEndpointStatus(_USB0_BASE, _USB_EP_0); // -값 발생 (Simon)
If USB.AddrSet then
begin
USBDevAddrSet(_USB0_Base,USB.Addr);
USB.AddrSet := False;
end;
If (Ep0Stat and _USB_DEV_EP0_SENT_STALL) then
USBDevEndpointStatusClear(_USB0_BASE, _USB_EP_0,_USB_DEV_EP0_SENT_STALL);
begin
USBDevAddrSet(_USB0_Base,USB.Addr);
USB.AddrSet := False;
end;
If (Ep0Stat and _USB_DEV_EP0_SENT_STALL) then
USBDevEndpointStatusClear(_USB0_BASE, _USB_EP_0,_USB_DEV_EP0_SENT_STALL);
If (Ep0Stat and _USB_DEV_EP0_OUT_PKTRDY) = 0 then Exit;
// Receive Data & Process ---------------------------------------------------
dSize := _EP0_MAX_PACKET_SIZE;
USBEndpointDataGet(_USB0_BASE,_USB_EP_0,@USB.BufR,dSize);
If dSize = 0 then Exit;
//
Case USB.PktPhase of
_pSetup : begin
pRequest := Pointer(@USB.BufR);
USB.CtlReqType := pRequest^.bmRequestType;
USB.CtlReq := pRequest^.bRequest;
USB.CtlValue := pRequest^.wValue;
USB.CtlLength := pRequest^.wLength;
Case (pRequest^.bmRequestType and _USB_RTYPE_TYPE_M) = 0 of
True : // Standard
Case pRequest^.bRequest of
_urGetStat : // 0
begin
wData := $0001;
USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,false);
USBEndpointDataPut (_USB0_BASE,_USB_EP_0,@wData,SizeOf(wData));
USBEndpointDataSend (_USB0_BASE,_USB_EP_0,_USB_TRANS_IN_LAST);
//LCD_Log(clLime,'GetStat');
end;
_urSetConf : // 9
begin
USBDevEndpointDataAck(_USB0_BASE, _USB_EP_0,True);
USB.Status := _tusReady;
// LCD_Log(clLime,'SetConf');
USB.Ready := True;
//
USBDevEndpointConfigSet(_USB0_BASE,_USB_EP_1, 64,_USB_EP_DEV_IN or _USB_EP_MODE_BULK);
USBDevEndpointConfigSet(_USB0_BASE,_USB_EP_1, 64,_USB_EP_DEV_OUT or _USB_EP_MODE_BULK);
USBFIFOConfigSet (_USB0_BASE,_USB_EP_1, 64,_USB_FIFO_SZ_64, _USB_EP_DEV_IN );
USBFIFOConfigSet (_USB0_BASE,_USB_EP_1,128,_USB_FIFO_SZ_64, _USB_EP_DEV_OUT);
end;
_urSetAddr : // 5
begin
USBDevEndpointDataAck(_USB0_BASE, _USB_EP_0,True);
USB.Addr := pRequest^.wValue;
USB.AddrSet := True;
//LCD_Log(clLime,'SetAddr');
end;
_urGetDesc : // 6
Begin
Case Hi(pRequest^.wValue) of
$01 : // Device
begin
pDat := @cDevDesc;
dSize := SizeOf(cDevDesc);
//LCD_Log(clLime,'gd Device');
end;
$02 : // Configuration
begin
pDat := @cCfgDesc;
Case pRequest^.wLength of
$09 : dSize := $09 // Cfg Desc Only
else dSize := SizeOf(cCfgDesc); // Cfg + Device + EP (Full)
end;
//Case pRequest^.wLength of
// $09 : LCD_Log(clLime,'Cfg mini')
// else LCD_Log(clLime,'Cfg full');
//End;
end;
$03 : // String
begin
utGetStrDesc(Lo(pRequest^.wValue),_lStrDesc);
pDat := @_lStrDesc;
dSize := _lStrDesc.Len;
IntToStr(Lo(pRequest^.wValue),Str);
//LCD_Log(clLime,'sd'+Str);
end
else begin
//LCD_Log(clLime,'Exit');
Exit;
end;
End;
// Send Ack + Data (Asumption : Always DataLen < 64 )
USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,false);
USBEndpointDataPut (_USB0_BASE,_USB_EP_0,pDat,dSize);
USBEndpointDataSend (_USB0_BASE,_USB_EP_0,_USB_TRANS_IN_LAST);
End;
end;
False: // Non-Standard
Process_EP0_User(USB);
end;
End;
_pData : begin
Case (USB.CtlReqType and _USB_RTYPE_TYPE_M) = 0 of
True : // Standard
USBDevEndpointDataAck(_USB0_BASE, _USB_EP_0,True);
False: // Non Standard
Case USB.CtlReq = _CmdReqFunc of
True : Process_EP0_User(USB);
False : USBDevEndpointDataAck(_USB0_BASE, _USB_EP_0,True);
End;
End;
USB.PktPhase := _pSetup;
end;
end;
end;
dSize := _EP0_MAX_PACKET_SIZE;
USBEndpointDataGet(_USB0_BASE,_USB_EP_0,@USB.BufR,dSize);
If dSize = 0 then Exit;
//
Case USB.PktPhase of
_pSetup : begin
pRequest := Pointer(@USB.BufR);
USB.CtlReqType := pRequest^.bmRequestType;
USB.CtlReq := pRequest^.bRequest;
USB.CtlValue := pRequest^.wValue;
USB.CtlLength := pRequest^.wLength;
Case (pRequest^.bmRequestType and _USB_RTYPE_TYPE_M) = 0 of
True : // Standard
Case pRequest^.bRequest of
_urGetStat : // 0
begin
wData := $0001;
USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,false);
USBEndpointDataPut (_USB0_BASE,_USB_EP_0,@wData,SizeOf(wData));
USBEndpointDataSend (_USB0_BASE,_USB_EP_0,_USB_TRANS_IN_LAST);
//LCD_Log(clLime,'GetStat');
end;
_urSetConf : // 9
begin
USBDevEndpointDataAck(_USB0_BASE, _USB_EP_0,True);
USB.Status := _tusReady;
// LCD_Log(clLime,'SetConf');
USB.Ready := True;
//
USBDevEndpointConfigSet(_USB0_BASE,_USB_EP_1, 64,_USB_EP_DEV_IN or _USB_EP_MODE_BULK);
USBDevEndpointConfigSet(_USB0_BASE,_USB_EP_1, 64,_USB_EP_DEV_OUT or _USB_EP_MODE_BULK);
USBFIFOConfigSet (_USB0_BASE,_USB_EP_1, 64,_USB_FIFO_SZ_64, _USB_EP_DEV_IN );
USBFIFOConfigSet (_USB0_BASE,_USB_EP_1,128,_USB_FIFO_SZ_64, _USB_EP_DEV_OUT);
end;
_urSetAddr : // 5
begin
USBDevEndpointDataAck(_USB0_BASE, _USB_EP_0,True);
USB.Addr := pRequest^.wValue;
USB.AddrSet := True;
//LCD_Log(clLime,'SetAddr');
end;
_urGetDesc : // 6
Begin
Case Hi(pRequest^.wValue) of
$01 : // Device
begin
pDat := @cDevDesc;
dSize := SizeOf(cDevDesc);
//LCD_Log(clLime,'gd Device');
end;
$02 : // Configuration
begin
pDat := @cCfgDesc;
Case pRequest^.wLength of
$09 : dSize := $09 // Cfg Desc Only
else dSize := SizeOf(cCfgDesc); // Cfg + Device + EP (Full)
end;
//Case pRequest^.wLength of
// $09 : LCD_Log(clLime,'Cfg mini')
// else LCD_Log(clLime,'Cfg full');
//End;
end;
$03 : // String
begin
utGetStrDesc(Lo(pRequest^.wValue),_lStrDesc);
pDat := @_lStrDesc;
dSize := _lStrDesc.Len;
IntToStr(Lo(pRequest^.wValue),Str);
//LCD_Log(clLime,'sd'+Str);
end
else begin
//LCD_Log(clLime,'Exit');
Exit;
end;
End;
// Send Ack + Data (Asumption : Always DataLen < 64 )
USBDevEndpointDataAck(_USB0_BASE,_USB_EP_0,false);
USBEndpointDataPut (_USB0_BASE,_USB_EP_0,pDat,dSize);
USBEndpointDataSend (_USB0_BASE,_USB_EP_0,_USB_TRANS_IN_LAST);
End;
end;
False: // Non-Standard
Process_EP0_User(USB);
end;
End;
_pData : begin
Case (USB.CtlReqType and _USB_RTYPE_TYPE_M) = 0 of
True : // Standard
USBDevEndpointDataAck(_USB0_BASE, _USB_EP_0,True);
False: // Non Standard
Case USB.CtlReq = _CmdReqFunc of
True : Process_EP0_User(USB);
False : USBDevEndpointDataAck(_USB0_BASE, _USB_EP_0,True);
End;
End;
USB.PktPhase := _pSetup;
end;
end;
end;
//
Procedure USB_Handler;
Var
ulStatus : DWord;
begin
// System Event
ulStatus := USBIntStatusControl(_USB0_Base);
If (ulStatus and $2F) then
begin
If (ulStatus and _USB_INTCTRL_RESET ) then _gUSB.Status := _tusReset;
If (ulStatus and _USB_INTCTRL_SUSPEND ) then _gUSB.Status := _tusSuspend;
If (ulStatus and _USB_INTCTRL_RESUME ) then _gUSB.Status := _tusResume;
If (ulStatus and _USB_INTCTRL_DISCONNECT) then _gUSB.Status := _tusDisconnect;
If (ulStatus and _USB_INTCTRL_SOF ) then _gUSB.Status := _tusSOF;
end;
Procedure USB_Handler;
Var
ulStatus : DWord;
begin
// System Event
ulStatus := USBIntStatusControl(_USB0_Base);
If (ulStatus and $2F) then
begin
If (ulStatus and _USB_INTCTRL_RESET ) then _gUSB.Status := _tusReset;
If (ulStatus and _USB_INTCTRL_SUSPEND ) then _gUSB.Status := _tusSuspend;
If (ulStatus and _USB_INTCTRL_RESUME ) then _gUSB.Status := _tusResume;
If (ulStatus and _USB_INTCTRL_DISCONNECT) then _gUSB.Status := _tusDisconnect;
If (ulStatus and _USB_INTCTRL_SOF ) then _gUSB.Status := _tusSOF;
end;
// Ep0 Event
ulStatus := USBIntStatusEndpoint(_USB0_Base);
If (ulStatus and _USB_INTEP_0 ) then Process_EP0(_gUSB);
// Ep1~15 Event
If _gUSB.Ready then Process_EP1(_gUSB,ulStatus);
end;
ulStatus := USBIntStatusEndpoint(_USB0_Base);
If (ulStatus and _USB_INTEP_0 ) then Process_EP0(_gUSB);
// Ep1~15 Event
If _gUSB.Ready then Process_EP1(_gUSB,ulStatus);
end;
// USBDeviceIntHandlerInternal (usbdenum.c)
Procedure USB0Int(); iv IVT_INT_USB0; ics ICS_AUTO; //ics ICS_OFF; // ics ICS_AUTO;
begin
USB_Handler;
end;
Procedure USB0Int(); iv IVT_INT_USB0; ics ICS_AUTO; //ics ICS_OFF; // ics ICS_AUTO;
begin
USB_Handler;
end;
//
Procedure USB_Init(Operation : TUSBOperation);
Var
Lp : DWord;
begin
// S/W Init ----------------------------------------------------------------
_gUSB.Operation := Operation;
_gUSB.Ready := False;
_gUSB.Status := _tusNone;
_gUSB.PktPhase := _pSetup;
_gUSB.CtlReqType := 0;
_gUSB.CtlReq := 0;
_gUSB.CtlValue := 0;
_gUSB.CtlLength := 0;
_gUSB.ModeDir := _DirInOut;
_gUSB.ModeAddr := 0;
_gUSB.ModeCnt := 0;
_gUSB.ModeState := _tmsNone;
_gUSB.Addr := 0;
_gUSB.AddrSet := False;
Procedure USB_Init(Operation : TUSBOperation);
Var
Lp : DWord;
begin
// S/W Init ----------------------------------------------------------------
_gUSB.Operation := Operation;
_gUSB.Ready := False;
_gUSB.Status := _tusNone;
_gUSB.PktPhase := _pSetup;
_gUSB.CtlReqType := 0;
_gUSB.CtlReq := 0;
_gUSB.CtlValue := 0;
_gUSB.CtlLength := 0;
_gUSB.ModeDir := _DirInOut;
_gUSB.ModeAddr := 0;
_gUSB.ModeCnt := 0;
_gUSB.ModeState := _tmsNone;
_gUSB.Addr := 0;
_gUSB.AddrSet := False;
// H/W Init ----------------------------------------------------------------
SysCtlPeripheralReset (_SYSCTL_PERIPH_USB0); // Reset the USB controller.
SysCtlPeripheralEnable(_SYSCTL_PERIPH_USB0); // Enable Clocking to the USB controller.
SysCtlUSBPLLEnable(); // Turn on USB Phy clock.
USBOTGMode(_USB0_BASE);
//--------------------------------------------------------------------------
USBIntStatusControl (_USB0_BASE); // 모든 상태 초기화
USBIntStatusEndpoint (_USB0_BASE);
// Enable USB Interrupts.
USBIntEnableControl (_USB0_BASE,
_USB_INTCTRL_SUSPEND or //$01
_USB_INTCTRL_RESUME or //$02
_USB_INTCTRL_RESET or //$04
_USB_INTCTRL_SOF or //$08
_USB_INTCTRL_DISCONNECT); //$20
USBIntEnableEndpoint(_USB0_BASE, _USB_INTEP_ALL);
USBDevDisconnect(_USB0_BASE);
Delay_ms(100);
USBDevConnect (_USB0_BASE); // Attach the device using the soft connect.
//
Case Operation = _cUSB_Interrupt of
True : IntEnable (_INT_USB0 ); // Enable the USB interrupt.
False : For Lp := 0 to 2000 do
begin
Delay_ms(1);
USB_Handler;
If _gUSB.Ready then Exit;
end;
End;
end;
SysCtlPeripheralReset (_SYSCTL_PERIPH_USB0); // Reset the USB controller.
SysCtlPeripheralEnable(_SYSCTL_PERIPH_USB0); // Enable Clocking to the USB controller.
SysCtlUSBPLLEnable(); // Turn on USB Phy clock.
USBOTGMode(_USB0_BASE);
//--------------------------------------------------------------------------
USBIntStatusControl (_USB0_BASE); // 모든 상태 초기화
USBIntStatusEndpoint (_USB0_BASE);
// Enable USB Interrupts.
USBIntEnableControl (_USB0_BASE,
_USB_INTCTRL_SUSPEND or //$01
_USB_INTCTRL_RESUME or //$02
_USB_INTCTRL_RESET or //$04
_USB_INTCTRL_SOF or //$08
_USB_INTCTRL_DISCONNECT); //$20
USBIntEnableEndpoint(_USB0_BASE, _USB_INTEP_ALL);
USBDevDisconnect(_USB0_BASE);
Delay_ms(100);
USBDevConnect (_USB0_BASE); // Attach the device using the soft connect.
//
Case Operation = _cUSB_Interrupt of
True : IntEnable (_INT_USB0 ); // Enable the USB interrupt.
False : For Lp := 0 to 2000 do
begin
Delay_ms(1);
USB_Handler;
If _gUSB.Ready then Exit;
end;
End;
end;
//------------------------------------------------------------------------------
//
//
//
//------------------------------------------------------------------------------
//
//
//
//------------------------------------------------------------------------------
// Result : USB.ModeState
Procedure USB_ReadBuf(Var USB : TUSB; Var Buf : Array[1] of Byte; MaxCnt : DWord);
Var
ulStatus : DWord;
ulEPStatus : DWord;
ulSize : DWord;
ulLp : Integer;
begin
USB.ModeState := _tmsNone;
ulLp := 0; // 64 x 8 = 512
Repeat
// Ep0 Event
ulStatus := USBIntStatusEndpoint(_USB0_Base);
If (ulStatus and _USB_INTEP_0 ) then Process_EP0(_gUSB);
If Not(_gUSB.Ready) then Exit;
If USB.ModeState = _tmsStop then Exit;
Procedure USB_ReadBuf(Var USB : TUSB; Var Buf : Array[1] of Byte; MaxCnt : DWord);
Var
ulStatus : DWord;
ulEPStatus : DWord;
ulSize : DWord;
ulLp : Integer;
begin
USB.ModeState := _tmsNone;
ulLp := 0; // 64 x 8 = 512
Repeat
// Ep0 Event
ulStatus := USBIntStatusEndpoint(_USB0_Base);
If (ulStatus and _USB_INTEP_0 ) then Process_EP0(_gUSB);
If Not(_gUSB.Ready) then Exit;
If USB.ModeState = _tmsStop then Exit;
// Host -> Dev : Bulk Out // Process_DataFromHost, USBDBulkPacketRead -------
If (ulStatus and $00020000) then // Hard Coding , Simon 추후 변경
begin
ulEPStatus := USBEndpointStatus (_USB0_BASE, $10 {cEpBulk} );
// $0003:0000 -> RX_FIFO_FULL & RX_PKT_RDY
If (ulEPStatus and _USB_DEV_RX_PKT_RDY) then
begin
ulSize := USBEndpointDataAvail (_USB0_Base, $10 {cEpBulk} );
USBEndPointDataGet (_USB0_Base, $10, @Buf[ulLp*64],ulSize);
USBDevEndpointStatusClear (_USB0_BASE, $10 {cEpBulk} , ulEPStatus);
USBDevEndpointDataAck (_USB0_Base, $10 {cEpBulk} , True);
Inc(ulLp);
end
end;
//
Until ( ulLp >= MaxCnt );
end;
If (ulStatus and $00020000) then // Hard Coding , Simon 추후 변경
begin
ulEPStatus := USBEndpointStatus (_USB0_BASE, $10 {cEpBulk} );
// $0003:0000 -> RX_FIFO_FULL & RX_PKT_RDY
If (ulEPStatus and _USB_DEV_RX_PKT_RDY) then
begin
ulSize := USBEndpointDataAvail (_USB0_Base, $10 {cEpBulk} );
USBEndPointDataGet (_USB0_Base, $10, @Buf[ulLp*64],ulSize);
USBDevEndpointStatusClear (_USB0_BASE, $10 {cEpBulk} , ulEPStatus);
USBDevEndpointDataAck (_USB0_Base, $10 {cEpBulk} , True);
Inc(ulLp);
end
end;
//
Until ( ulLp >= MaxCnt );
end;
// Result : USB.ModeState
Procedure USB_WriteBuf(Var USB : TUSB; Var Buf : Array[1] of Byte; MaxCnt : DWord);
Var
ulStatus : DWord;
ulEPStatus : DWord;
ulSize : DWord;
ulLp : Integer;
begin
USB.ModeState := _tmsNone;
ulLp := 0; // 64 x 8 = 512
//
USBEndpointDataPut (_USB0_BASE,$10,@Buf[ulLp*64],64);
USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In );
Inc(ulLp);
//
Repeat
// Ep0 Event
ulStatus := USBIntStatusEndpoint(_USB0_Base);
If (ulStatus and _USB_INTEP_0 ) then Process_EP0(_gUSB);
If Not(_gUSB.Ready) then Exit;
If USB.ModeState = _tmsStop then Exit;
Procedure USB_WriteBuf(Var USB : TUSB; Var Buf : Array[1] of Byte; MaxCnt : DWord);
Var
ulStatus : DWord;
ulEPStatus : DWord;
ulSize : DWord;
ulLp : Integer;
begin
USB.ModeState := _tmsNone;
ulLp := 0; // 64 x 8 = 512
//
USBEndpointDataPut (_USB0_BASE,$10,@Buf[ulLp*64],64);
USBEndpointDataSend(_USB0_BASE,$10,_USB_TRANS_In );
Inc(ulLp);
//
Repeat
// Ep0 Event
ulStatus := USBIntStatusEndpoint(_USB0_Base);
If (ulStatus and _USB_INTEP_0 ) then Process_EP0(_gUSB);
If Not(_gUSB.Ready) then Exit;
If USB.ModeState = _tmsStop then Exit;
// Host -> Dev : Bulk Out // Process_DataFromHost, USBDBulkPacketRead -------
If (ulStatus and $00000002) then // Hard Coding , Simon 추후 변경
begin
ulEPStatus := USBEndpointStatus (_USB0_BASE, $10 {cEpBulk} );
//
USBDevEndpointStatusClear(_USB0_BASE,$10 {cEpBulk},ulEPStatus);
USBEndpointDataPut (_USB0_BASE,$10,@Buf[ulLp*64],64);
// SIMON
Case (ulLp = (MaxCnt-1))of
True : USBEndpointDataSend (_USB0_BASE,$10,_USB_TRANS_In_Last);
False : USBEndpointDataSend (_USB0_BASE,$10,_USB_TRANS_In );
End;
Inc(ulLp);
end;
Until ( ulLp >= MaxCnt );
//
While (true) do
begin
// Ep0 Event
ulStatus := USBIntStatusEndpoint(_USB0_Base);
//If _gUSB.Ready then Process_EP1(_gUSB,ulStatus);
If Not(_gUSB.Ready) then Exit;
If USB.ModeState = _tmsStop then Exit;
// Host -> Dev : Bulk Out // Process_DataFromHost, USBDBulkPacketRead -------
If (ulStatus and $00000002) then // Hard Coding , Simon 추후 변경
begin
ulEPStatus := USBEndpointStatus (_USB0_BASE, $10 {cEpBulk} );
USBDevEndpointStatusClear(_USB0_BASE,$10 {cEpBulk},ulEPStatus);
Exit;
end;
end;
If (ulStatus and $00000002) then // Hard Coding , Simon 추후 변경
begin
ulEPStatus := USBEndpointStatus (_USB0_BASE, $10 {cEpBulk} );
//
USBDevEndpointStatusClear(_USB0_BASE,$10 {cEpBulk},ulEPStatus);
USBEndpointDataPut (_USB0_BASE,$10,@Buf[ulLp*64],64);
// SIMON
Case (ulLp = (MaxCnt-1))of
True : USBEndpointDataSend (_USB0_BASE,$10,_USB_TRANS_In_Last);
False : USBEndpointDataSend (_USB0_BASE,$10,_USB_TRANS_In );
End;
Inc(ulLp);
end;
Until ( ulLp >= MaxCnt );
//
While (true) do
begin
// Ep0 Event
ulStatus := USBIntStatusEndpoint(_USB0_Base);
//If _gUSB.Ready then Process_EP1(_gUSB,ulStatus);
If Not(_gUSB.Ready) then Exit;
If USB.ModeState = _tmsStop then Exit;
// Host -> Dev : Bulk Out // Process_DataFromHost, USBDBulkPacketRead -------
If (ulStatus and $00000002) then // Hard Coding , Simon 추후 변경
begin
ulEPStatus := USBEndpointStatus (_USB0_BASE, $10 {cEpBulk} );
USBDevEndpointStatusClear(_USB0_BASE,$10 {cEpBulk},ulEPStatus);
Exit;
end;
end;
end;
// PC -> Read USB Read -> Write
Function USB_PutSD(Var USB : TUSB) : Boolean;
Var
Lp : DWord;
Inx : DWord;
Rst : Boolean;
Label
JumpEnd;
begin
//
Result := True;
//
Rst := SD_Write_MultiBlock_Start (USB.ModeAddr);
If Not(Rst) then Result := False;
For Lp := 0 to USB.ModeCnt-1 do
begin
USB_ReadBuf(_gUSB,Buf512,8);
If _gUSB.ModeState = _tmsStop then
begin
LCD_log(clRed,'Stop');
Goto JumpEnd;
end;
Rst := SD_Write_MultiBlock(Buf512);
If Not(Rst) then Result := False;
end;
//
JumpEnd:
_gUSB.ModeState := _tmsNone;
SD_Write_MultiBlock_Stop;
end;
//
Function USB_GetSD (Var USB : TUSB) : Boolean;
Var
Lp : DWord;
Inx : DWord;
Rst : Boolean;
Label
JumpEnd;
begin
//
Result := True;
//
Rst := SD_Read_MultiBlock_Start (USB.ModeAddr);
If Not(Rst) then Result := False;
//
For Lp := 0 to USB.ModeCnt-1 do
begin
Rst := SD_Read_MultiBlock(Buf512);
If Not(Rst) then Result := False;
USB_WriteBuf(_gUSB,Buf512,8);
If _gUSB.ModeState = _tmsStop then
begin
LCD_log(clRed,'Stop');
Goto JumpEnd;
end;
end;
//
JumpEnd:
_gUSB.ModeState := _tmsNone;
SD_Read_MultiBlock_Stop;
end;
Function USB_PutSD(Var USB : TUSB) : Boolean;
Var
Lp : DWord;
Inx : DWord;
Rst : Boolean;
Label
JumpEnd;
begin
//
Result := True;
//
Rst := SD_Write_MultiBlock_Start (USB.ModeAddr);
If Not(Rst) then Result := False;
For Lp := 0 to USB.ModeCnt-1 do
begin
USB_ReadBuf(_gUSB,Buf512,8);
If _gUSB.ModeState = _tmsStop then
begin
LCD_log(clRed,'Stop');
Goto JumpEnd;
end;
Rst := SD_Write_MultiBlock(Buf512);
If Not(Rst) then Result := False;
end;
//
JumpEnd:
_gUSB.ModeState := _tmsNone;
SD_Write_MultiBlock_Stop;
end;
//
Function USB_GetSD (Var USB : TUSB) : Boolean;
Var
Lp : DWord;
Inx : DWord;
Rst : Boolean;
Label
JumpEnd;
begin
//
Result := True;
//
Rst := SD_Read_MultiBlock_Start (USB.ModeAddr);
If Not(Rst) then Result := False;
//
For Lp := 0 to USB.ModeCnt-1 do
begin
Rst := SD_Read_MultiBlock(Buf512);
If Not(Rst) then Result := False;
USB_WriteBuf(_gUSB,Buf512,8);
If _gUSB.ModeState = _tmsStop then
begin
LCD_log(clRed,'Stop');
Goto JumpEnd;
end;
end;
//
JumpEnd:
_gUSB.ModeState := _tmsNone;
SD_Read_MultiBlock_Stop;
end;
end.