⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 at91的一个bootloader
💻 C
📖 第 1 页 / 共 2 页
字号:
    }
}

//-----------------------------------------------------------------------------
// Send a zero-length packet on EP0. This blocks until the packet has been
// transmitted and an ACK from the host has been received.
//-----------------------------------------------------------------------------
static void UsbSendZeroLength(void)
{
    UDP_ENDPOINT_CSR(0) |= UDP_CSR_TX_PACKET;

    while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED))
        ;

    UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;

    while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)
        ;
}

//-----------------------------------------------------------------------------
// Handle a received SETUP DATA packet. These are the packets used to
// configure the link (e.g. request various descriptors, and assign our
// address).
//-----------------------------------------------------------------------------
static void HandleRxdSetupData(void)
{
    int i;
    UsbSetupData usd;

    for(i = 0; i < sizeof(usd); i++) {
        ((BYTE *)&usd)[i] = UDP_ENDPOINT_FIFO(0);
    }

    if(usd.bmRequestType & 0x80) {
        UDP_ENDPOINT_CSR(0) |= UDP_CSR_CONTROL_DATA_DIR;
        while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_CONTROL_DATA_DIR))
            ;
    }

    UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_RX_HAVE_READ_SETUP_DATA;
    while(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_HAVE_READ_SETUP_DATA)
        ;

    switch(usd.bRequest) {
        case USB_REQUEST_GET_DESCRIPTOR:
            if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_DEVICE) {
                UsbSendEp0((BYTE *)&DeviceDescriptor,
                    min(sizeof(DeviceDescriptor), usd.wLength));
            } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_CONFIGURATION) {
                UsbSendEp0((BYTE *)&ConfigurationDescriptor,
                    min(sizeof(ConfigurationDescriptor), usd.wLength));
            } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_STRING) {
                const BYTE *s = StringDescriptors[usd.wValue & 0xff];
                UsbSendEp0(s, min(s[0], usd.wLength));
            } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_HID_REPORT) {
                UsbSendEp0((BYTE *)&HidReportDescriptor,
                    min(sizeof(HidReportDescriptor), usd.wLength));
            }
            break;

        case USB_REQUEST_SET_ADDRESS:
            UsbSendZeroLength();
            UDP_FUNCTION_ADDR = UDP_FUNCTION_ADDR_ENABLED | usd.wValue ;
            if(usd.wValue != 0) {
                UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_ADDRESSED;
            } else {
                UDP_GLOBAL_STATE = 0;
            }
            break;

        case USB_REQUEST_GET_CONFIGURATION:
            UsbSendEp0(&CurrentConfiguration, sizeof(CurrentConfiguration));
            break;

        case USB_REQUEST_GET_STATUS: {
            if(usd.bmRequestType & 0x80) {
                WORD w = 0;
                UsbSendEp0((BYTE *)&w, sizeof(w));
            }
            break;
        }
        case USB_REQUEST_SET_CONFIGURATION:
            CurrentConfiguration = usd.wValue;
            if(CurrentConfiguration) {
                UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_CONFIGURED;
                UDP_ENDPOINT_CSR(1) = UDP_CSR_ENABLE_EP |
                    UDP_CSR_EPTYPE_INTERRUPT_OUT;
                UDP_ENDPOINT_CSR(2) = UDP_CSR_ENABLE_EP |
                    UDP_CSR_EPTYPE_INTERRUPT_IN;
            } else {
                UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_ADDRESSED;
                UDP_ENDPOINT_CSR(1) = 0;
                UDP_ENDPOINT_CSR(2) = 0;
            }
            UsbSendZeroLength();
            break;

        case USB_REQUEST_GET_INTERFACE: {
            BYTE b = 0;
            UsbSendEp0(&b, sizeof(b));
            break;
        }

        case USB_REQUEST_SET_INTERFACE:
            UsbSendZeroLength();
            break;
            
        case USB_REQUEST_CLEAR_FEATURE:
        case USB_REQUEST_SET_FEATURE:
        case USB_REQUEST_SET_DESCRIPTOR:
        case USB_REQUEST_SYNC_FRAME:
        default:
            break;
    }
}

//-----------------------------------------------------------------------------
// Send a data packet. This packet should be exactly USB_REPORT_PACKET_SIZE
// long. This function blocks until the packet has been transmitted, and
// an ACK has been received from the host.
//-----------------------------------------------------------------------------
void UsbSendPacket(BYTE *packet, int len)
{
    int i, thisTime;

    while(len > 0) {
        thisTime = min(len, 8);
       
        for(i = 0; i < thisTime; i++) {
            UDP_ENDPOINT_FIFO(2) = packet[i];
        }
        UDP_ENDPOINT_CSR(2) |= UDP_CSR_TX_PACKET;

        while(!(UDP_ENDPOINT_CSR(2) & UDP_CSR_TX_PACKET_ACKED))
            ;
        UDP_ENDPOINT_CSR(2) &= ~UDP_CSR_TX_PACKET_ACKED;

        while(UDP_ENDPOINT_CSR(2) & UDP_CSR_TX_PACKET_ACKED)
            ;

        len -= thisTime;
        packet += thisTime;
    }
}

//-----------------------------------------------------------------------------
// Handle a received packet. This handles only those packets received on
// EP1 (i.e. the HID reports that we use as our data packets).
//-----------------------------------------------------------------------------
static void HandleRxdData(void)
{
    int i, len;

    if(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0) {
        len = UDP_CSR_BYTES_RECEIVED(UDP_ENDPOINT_CSR(1));

        for(i = 0; i < len; i++) {
            UsbBuffer[UsbSoFarCount] = UDP_ENDPOINT_FIFO(1);
            UsbSoFarCount++;
        }

        UDP_ENDPOINT_CSR(1) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_0;
        while(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0)
            ;

        if(UsbSoFarCount >= 64) {
            UsbPacketReceived(UsbBuffer, UsbSoFarCount);
            UsbSoFarCount = 0;
        }
    }

    if(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_1) {
        len = UDP_CSR_BYTES_RECEIVED(UDP_ENDPOINT_CSR(1));

        for(i = 0; i < len; i++) {
            UsbBuffer[UsbSoFarCount] = UDP_ENDPOINT_FIFO(1);
            UsbSoFarCount++;
        }

        UDP_ENDPOINT_CSR(1) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_1;
        while(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_1)
            ;

        if(UsbSoFarCount >= 64) {
            UsbPacketReceived(UsbBuffer, UsbSoFarCount);
            UsbSoFarCount = 0;
        }
    }
}

//-----------------------------------------------------------------------------
// Initialize the USB driver. To be thorough, disconnect the pull-up on
// D+ (to make the host think that we have been unplugged, resetting all
// of its state) before reconnecting it and resetting the AT91's USB
// peripheral.
//-----------------------------------------------------------------------------
void UsbStart(void)
{
    volatile int i;

    UsbSoFarCount = 0;

    USB_D_PLUS_PULLUP_OFF();

    for(i = 0; i < 1000000; i++)
        ;

    USB_D_PLUS_PULLUP_ON();

    if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_END_OF_BUS_RESET) {
        UDP_INTERRUPT_CLEAR = UDP_INTERRUPT_END_OF_BUS_RESET;
    }
}

//-----------------------------------------------------------------------------
// This must be called periodically in order for USB to work. UsbPoll may
// call UsbPacketReceived if a non-control packet has been received, and
// UsbPoll should not be called from UsbPacketReceived.
//
// Returns TRUE if we `did something' (received either a control or data
// packet, or a piece of one at least), FALSE otherwise.
//-----------------------------------------------------------------------------
BOOL UsbPoll(void)
{
    BOOL ret = FALSE;

    if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_END_OF_BUS_RESET) {
        UDP_INTERRUPT_CLEAR = UDP_INTERRUPT_END_OF_BUS_RESET;

        // following a reset we should be ready to receive a setup packet
        UDP_RESET_ENDPOINT = 0xf;
        UDP_RESET_ENDPOINT = 0;

        UDP_FUNCTION_ADDR = UDP_FUNCTION_ADDR_ENABLED;

        UDP_ENDPOINT_CSR(0) = UDP_CSR_EPTYPE_CONTROL | UDP_CSR_ENABLE_EP;

        CurrentConfiguration = 0;

        ret = TRUE;
    }

    if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_ENDPOINT(0)) {
        if(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_HAVE_READ_SETUP_DATA) {
            HandleRxdSetupData();
            ret = TRUE;
        }
    }

    if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_ENDPOINT(1)) {
        HandleRxdData();
        ret = TRUE;
    }

    return ret;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -