📄 u08usb.c
字号:
//============================================================================
// File: U08USB.C
// Func: USB Implementation Module for USB08 Demo Application
// Ver.: 1.01
// Auth: (C)2000,2001 by Oliver Thamm, MCT Elektronikladen GbR
// http://hc08web.de/usb08
// Rem.: View/Edit this File with TAB-Size=4
//============================================================================
#include "u08usb.h" // Definitions for USB Data Types & Constants
#include "u08desc.c" // const USB Descriptor Data
//-- Source Code Option - set as required by Hardware! -----------------------
//
#define USB_IPUE 1 // Internal Pull-up Enable
// 1=Enable (use build-in Pull-up Resistor)
// 0=Disable (external Pull-up required)
//-- Variables ---------------------------------------------------------------
#pragma DATA_SEG SHORT MY_ZEROPAGE
volatile uchar USB_State;
#define MAX_TXBUF_SIZE 16 // must be 2^x!
volatile uchar TxBuffer[MAX_TXBUF_SIZE];
volatile uchar TxBuf_RdIdx;
volatile uchar TxBuf_WrIdx;
#define MAX_RXBUF_SIZE 16 // must be 2^x!
volatile uchar RxBuffer[MAX_RXBUF_SIZE];
volatile uchar RxBuf_RdIdx;
volatile uchar RxBuf_WrIdx;
volatile uchar SuspendCounter;
setup_buffer SetupBuffer;
uchar SetupSize;
const uchar * SetupDataPtr;
uchar R0Sequence; // DATA0/1 Flag for EP0 Rx
uchar R2Sequence; // DATA0/1 Flag for EP2 Rx
#pragma DATA_SEG DEFAULT
//----------------------------------------------------------------------------
// Force STALL Condition for EP0 (both IN and OUT)
// as a Response to an invalid SETUP Request
// Flags will be auto-cleared by the next SETUP Token
//
void forceSTALL() {
UCR3 |= BM_OSTALL0 + BM_ISTALL0;
}
//----------------------------------------------------------------------------
#define ENDPOINT_HALT 0x00
#define RT_ENDPOINT 0x02
// CLEAR_FEATURE Standard Device Request Handler
// called by handleSETUP();
//
void clearFeature() {
if( SetupBuffer.wValue.hi ||
SetupBuffer.wIndex.hi ||
SetupBuffer.wLength.hi ||
SetupBuffer.wLength.lo) // check 0-fields
forceSTALL();
else if((SetupBuffer.bmRequestType == RT_ENDPOINT) &&
(SetupBuffer.wValue.lo == ENDPOINT_HALT) &&
((SetupBuffer.wIndex.lo==0x81) || (SetupBuffer.wIndex.lo==0x02))) {
// clear EP1/2 Force STALL Bit
if(SetupBuffer.wIndex.lo == 0x81) { // EP1
UCR1 &= ~(BM_T1SEQ+BM_STALL1); // clear STALL, Sequence = DATA0
}
else { // EP2
UCR2 &= ~BM_STALL2; // clear STALL
R2Sequence = 0; // Sequence = DATA0
}
// prepare to send empty DATA1 at next IN Transaction
UCR0 = BM_T0SEQ + BM_TX0E + 0;
}
else forceSTALL();
}
//----------------------------------------------------------------------------
// SET_ADDRESS Standard Device Request Handler
// called by handleSETUP();
//
void setAddress() {
if( SetupBuffer.wIndex.hi ||
SetupBuffer.wIndex.lo ||
SetupBuffer.wLength.hi ||
SetupBuffer.wLength.lo ||
SetupBuffer.wValue.hi ||
(SetupBuffer.wValue.lo & 0x80))
forceSTALL();
else {
// prepare to send empty DATA1 at next IN Transaction
UCR0 = BM_T0SEQ + BM_TX0E + 0;
}
}
//----------------------------------------------------------------------------
// SET_CONFIGURATION Standard Device Request Handler
// called by handleSETUP();
//
void setConfiguration() {
if( SetupBuffer.wIndex.hi ||
SetupBuffer.wIndex.lo ||
SetupBuffer.wLength.hi ||
SetupBuffer.wLength.lo ||
SetupBuffer.wValue.hi ||
(SetupBuffer.wValue.lo > 1) ||
(USB_State == US_DEFAULT)) {
forceSTALL();
}
else {
if(SetupBuffer.wValue.lo > 0) {
// no need to remember the Configuration Value
// since we support only one Configuration anyway
USB_State = US_CONFIGURED;
// Activate Interrupt Endpoints, reset STALL and DATA-Toggle
UCR1 = BM_TX1E + 0; // EP1 Tx Enable, Data Size is 0
UCR2 = BM_RX2E; // EP2 Rx Enable
}
else {
// Zero means: go back to Adressed State
USB_State = US_ADDRESSED;
UCR1 = 0; // deactivate EP1
UCR2 = 0; // deactivate EP2
}
// prepare to send empty DATA1 at next IN Transaction
UCR0 = BM_T0SEQ + BM_TX0E + 0;
}
}
//----------------------------------------------------------------------------
// GET_DESCRIPTOR Standard Device Request Handler
// called by handleSETUP();
//
void getDescriptor() {
uchar n;
uchar *dest;
switch(SetupBuffer.wValue.hi) {
case DT_DEVICE: // Get Device Descriptor
SetupDataPtr = (uchar *)&DeviceDesc;
SetupSize = DeviceDesc.bLength;
break;
case DT_CONFIGURATION: // Get Configuration Descriptor
SetupDataPtr = (uchar *)&ConfigDesc;
SetupSize = ConfigDesc.wTotalLength.lo;
break;
case DT_STRING: // Get String Descriptor
// ### Table Index Boundary should be checked
SetupDataPtr = StringDescTable[SetupBuffer.wValue.lo];
SetupSize = *SetupDataPtr;
break;
default:
forceSTALL();
break;
}
if( SetupBuffer.wValue.hi == DT_DEVICE ||
SetupBuffer.wValue.hi == DT_CONFIGURATION ||
SetupBuffer.wValue.hi == DT_STRING) {
// check if requested Length is less than Descriptor Length
if((SetupBuffer.wLength.lo < SetupSize) && (SetupBuffer.wLength.hi == 0))
SetupSize = SetupBuffer.wLength.lo;
// copy (up to) 8 Bytes to EP0 Data Registers
n = 0;
dest = (uchar *)&UE0D0;
while(SetupSize!=0 && n<8) {
*dest = *SetupDataPtr;
dest++;
SetupDataPtr++;
SetupSize--;
n++;
}
// prepare to send n Bytes as DATA1 at next IN Transaction
// Rem: RX0E (currently disabled) will be re-enabled at end of handleSETUP()
UCR0 = BM_T0SEQ + BM_TX0E + n;
// check if this is the last DATA packet to send
if(n < 8) SetupBuffer.bRequest = REQUEST_COMPLETE;
}
}
//----------------------------------------------------------------------------
void handleSETUP() {
UCR0 &= ~BM_RX0E; // Deactivate EP0 Receiver
UIR2 = BM_RXD0FR; // Reset EP0 Receive Flag
SetupBuffer = *(setup_buffer *)(&UE0D0);
if(USR0 != 0x48) { // SETUP Transaction must be DATA0 with Size=8
forceSTALL(); // otherwise we have an Error Condition
}
else { // now we will check the Request Type
if((SetupBuffer.bmRequestType & 0x60) != 0) {
forceSTALL(); // Non-Standard Requests will not be handled!
}
else { // Standard Request Decoder:
switch(SetupBuffer.bRequest) {
case CLEAR_FEATURE: // 1
clearFeature();
break;
case SET_ADDRESS: // 5
setAddress();
break;
case GET_DESCRIPTOR: // 6
getDescriptor();
break;
case SET_CONFIGURATION: // 9
setConfiguration();
break;
default:
forceSTALL();
break;
}
}
}
UCR0 |= BM_RX0E; // Activate EP0 Receiver
}
//----------------------------------------------------------------------------
void handleOUT() {
UCR0 &= ~(BM_RX0E+BM_TX0E); // Deactivate EP0 Receiver + Transmitter
UIR2 = BM_RXD0FR; // Reset EP0 Receive Flag
// OUT Transactions over EP0 appear as Status Stage
// of a Standard Device Request only
UCR0 |= BM_RX0E; // Activate EP0 Receiver
}
//----------------------------------------------------------------------------
void handleIN() {
uchar n;
uchar *dest;
UCR0 &= ~BM_TX0E; // Deactivate EP0 Transmitter
UIR2 = BM_TXD0FR; // Reset EP0 Transmit complete Flag
switch(SetupBuffer.bRequest) {
case SET_ADDRESS:
UADDR = SetupBuffer.wValue.lo | BM_USBEN;
if(SetupBuffer.wValue.lo != 0) USB_State = US_ADDRESSED;
else USB_State = US_DEFAULT;
SetupBuffer.bRequest = REQUEST_COMPLETE;
break;
case GET_DESCRIPTOR:
// copy (up to) 8 Bytes to EP0 Data Registers
n = 0;
dest = (uchar *)&UE0D0;
while(SetupSize!=0 && n<8) {
*dest = *SetupDataPtr;
dest++;
SetupDataPtr++;
SetupSize--;
n++;
}
// prepare to send n Bytes at next IN Transaction
// toggle DATA0/1
UCR0 = ((UCR0^BM_T0SEQ) & BM_T0SEQ) + BM_TX0E + BM_RX0E + n;
// check if this is the last DATA packet to send
if(n < 8) SetupBuffer.bRequest = REQUEST_COMPLETE;
break;
case CLEAR_FEATURE:
case SET_CONFIGURATION:
// nothing to do - handshake finished
SetupBuffer.bRequest = REQUEST_COMPLETE;
break;
case REQUEST_COMPLETE:
// Request is finished - just clear the TXD0F Flag (see above)
// and do not re-enable EP0 Transmitter, since there is no more
// data to send
break;
default:
forceSTALL();
break;
}
}
//----------------------------------------------------------------------------
// handle IN Packet Transmit complete over EP1
//
void handleIN1() {
uchar n;
uchar volatile *dest;
UCR1 &= ~BM_TX1E; // Deactivate EP1 Transmitter
UIR2 = BM_TXD1FR; // Reset EP1 Transmit complete Flag
// refill EP1 Tx Data Buffer
n = 0;
dest = &UE1D0;
while((TxBuf_RdIdx != TxBuf_WrIdx) && n<8) {
*dest = TxBuffer[TxBuf_RdIdx];
TxBuf_RdIdx = (TxBuf_RdIdx+1) & (MAX_TXBUF_SIZE-1);
dest++;
n++;
}
// Activate EP1 Transmitter to send n Bytes
UCR1 = ((UCR1^BM_T1SEQ) & BM_T1SEQ) + BM_TX1E + n;
}
//----------------------------------------------------------------------------
// handle OUT Packet received over EP2
//
void handleOUT2() {
uchar n;
uchar newIdx;
uchar volatile *src;
UCR2 &= ~BM_RX2E; // Deactivate EP2 Receiver
UIR2 = BM_RXD2FR; // Reset EP2 Receive Flag
// ### Sender's DATA Toggle should be checked!
// read out EP2 Rx Data Buffer
src = &UE2D0;
n = USR1 & BM_RP2SIZ; // Check Transfer Size
while(n) {
newIdx = (RxBuf_WrIdx+1) & (MAX_RXBUF_SIZE-1);
while(newIdx == RxBuf_RdIdx)
; // wait if TxBuffer is full
RxBuffer[RxBuf_WrIdx] = *src;
RxBuf_WrIdx = newIdx;
src++;
n--;
}
UCR2 = BM_RX2E; // Activate EP2 Receiver
}
//----------------------------------------------------------------------------
void initUSB() {
UADDR = BM_USBEN + 0; // USB enable, default address
UCR0 = 0; // reset EP0
UCR1 = 0; // reset EP1
UCR2 = 0; // reset EP2
UCR3 = BM_TX1STR + // clear TX1ST Flag
USB_IPUE*BM_PULLEN; // enable/disable internal Pull-up
UCR4 = 0; // USB normal operation
UIR0 = 0; // disable Interrupts
UIR2 = 0xff; // clear all Flags in UIR1
R0Sequence = 0; // EP0 Rx starts with DATA0
R2Sequence = 0; // EP2 Rx starts with DATA0
USB_State = US_POWERED; // powered, but not yet reset
TxBuf_RdIdx = 0; // reset Buffer Indexes
TxBuf_WrIdx = 0;
RxBuf_RdIdx = 0;
RxBuf_WrIdx = 0;
}
//----------------------------------------------------------------------------
uchar getUSB() {
uchar c;
while(RxBuf_RdIdx == RxBuf_WrIdx)
; // wait if RxBuffer is empty
c = RxBuffer[RxBuf_RdIdx];
RxBuf_RdIdx = (RxBuf_RdIdx+1) & (MAX_RXBUF_SIZE-1);
return c;
}
//----------------------------------------------------------------------------
void putUSB(uchar c) {
uchar newIdx;
newIdx = (TxBuf_WrIdx+1) & (MAX_TXBUF_SIZE-1);
while(newIdx == TxBuf_RdIdx)
; // wait if TxBuffer is full
TxBuffer[TxBuf_WrIdx] = c;
TxBuf_WrIdx = newIdx;
}
//----------------------------------------------------------------------------
// USB Interrupt Handler
// All Interrupt Sources of the JB8's integrated USB peripheral
// will be treated by this ISR
//
interrupt void isrUSB() {
if(UIR1 & BM_EOPF) { // End of Packet detected?
SuspendCounter = 0; // reset 3ms-Suspend Counter
UIR2 = BM_EOPFR; // reset EOP Intr Flag
}
else if(UIR1 & BM_RXD0F) { // has EP0 received some data?
if(USR0 & BM_SETUP) // was it a SETUP Packet?
handleSETUP();
else // or a normal OUT Packet
handleOUT();
}
else if(UIR1 & BM_TXD0F) { // has EP0 sent Data?
handleIN();
}
else if(UIR1 & BM_TXD1F) { // has EP1 sent Data?
handleIN1();
}
else if(UIR1 & BM_RXD2F) { // has EP2 received Data?
handleOUT2();
}
else if(UIR1 & BM_RSTF) { // USB Reset Signal State detected?
initUSB(); // Soft Reset of USB Systems
UCR3 |= BM_ENABLE1+BM_ENABLE2; // Enable EP1 and EP2
UIR0 = BM_TXD0IE + BM_RXD0IE + // EP0 Rx/Tx Intr Enable and
BM_TXD1IE + BM_RXD2IE + // EP1 Tx and EP2 Rx Intr Enable
BM_EOPIE; // and End-of-Packet Intr Enable
UCR0 |= BM_RX0E; // EP0 Receive Enable
USB_State = US_DEFAULT; // Device is powered and reset
}
}
//============================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -