OpenCores
URL https://opencores.org/ocsvn/usb_device_core/usb_device_core/trunk

Subversion Repositories usb_device_core

[/] [usb_device_core/] [trunk/] [sw/] [usbf_hw.c] - Rev 5

Compare with Previous | Blame | View Log

//-----------------------------------------------------------------
//                         USB CDC Device SW
//                               V0.1
//                         Ultra-Embedded.com
//                          Copyright 2014
//
//                  Email: admin@ultra-embedded.com
//
//                          License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------
//
// This file is part of USB CDC Device SW.
//
// USB CDC Device SW is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// USB CDC Device SW is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with USB CDC Device SW; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
#include "usbf_hw.h"
#include "usb_log.h"
#include "timer.h"
 
//-----------------------------------------------------------------
// Peripheral registers:
//-----------------------------------------------------------------
#define USB_FUNC_CTRL     0x0
    #define USB_FUNC_CTRL_HS_CHIRP_EN            8
    #define USB_FUNC_CTRL_HS_CHIRP_EN_SHIFT      8
    #define USB_FUNC_CTRL_HS_CHIRP_EN_MASK       0x1
 
    #define USB_FUNC_CTRL_PHY_DMPULLDOWN         7
    #define USB_FUNC_CTRL_PHY_DMPULLDOWN_SHIFT   7
    #define USB_FUNC_CTRL_PHY_DMPULLDOWN_MASK    0x1
 
    #define USB_FUNC_CTRL_PHY_DPPULLDOWN         6
    #define USB_FUNC_CTRL_PHY_DPPULLDOWN_SHIFT   6
    #define USB_FUNC_CTRL_PHY_DPPULLDOWN_MASK    0x1
 
    #define USB_FUNC_CTRL_PHY_TERMSELECT         5
    #define USB_FUNC_CTRL_PHY_TERMSELECT_SHIFT   5
    #define USB_FUNC_CTRL_PHY_TERMSELECT_MASK    0x1
 
    #define USB_FUNC_CTRL_PHY_XCVRSELECT_SHIFT   3
    #define USB_FUNC_CTRL_PHY_XCVRSELECT_MASK    0x3
 
    #define USB_FUNC_CTRL_PHY_OPMODE_SHIFT       1
    #define USB_FUNC_CTRL_PHY_OPMODE_MASK        0x3
 
    #define USB_FUNC_CTRL_INT_EN_SOF             0
    #define USB_FUNC_CTRL_INT_EN_SOF_SHIFT       0
    #define USB_FUNC_CTRL_INT_EN_SOF_MASK        0x1
 
#define USB_FUNC_STAT     0x4
    #define USB_FUNC_STAT_RST                    13
    #define USB_FUNC_STAT_RST_SHIFT              13
    #define USB_FUNC_STAT_RST_MASK               0x1
 
    #define USB_FUNC_STAT_LINESTATE_SHIFT        11
    #define USB_FUNC_STAT_LINESTATE_MASK         0x3
 
    #define USB_FUNC_STAT_FRAME_SHIFT            0
    #define USB_FUNC_STAT_FRAME_MASK             0x7ff
 
#define USB_FUNC_ADDR     0x8
    #define USB_FUNC_ADDR_DEV_ADDR_SHIFT         0
    #define USB_FUNC_ADDR_DEV_ADDR_MASK          0x7f
 
#define USB_EP0_CFG       0xc
    #define USB_EP0_CFG_INT_RX                   3
    #define USB_EP0_CFG_INT_RX_SHIFT             3
    #define USB_EP0_CFG_INT_RX_MASK              0x1
 
    #define USB_EP0_CFG_INT_TX                   2
    #define USB_EP0_CFG_INT_TX_SHIFT             2
    #define USB_EP0_CFG_INT_TX_MASK              0x1
 
    #define USB_EP0_CFG_STALL_EP                 1
    #define USB_EP0_CFG_STALL_EP_SHIFT           1
    #define USB_EP0_CFG_STALL_EP_MASK            0x1
 
    #define USB_EP0_CFG_ISO                      0
    #define USB_EP0_CFG_ISO_SHIFT                0
    #define USB_EP0_CFG_ISO_MASK                 0x1
 
#define USB_EP0_TX_CTRL   0x10
    #define USB_EP0_TX_CTRL_TX_FLUSH             17
    #define USB_EP0_TX_CTRL_TX_FLUSH_SHIFT       17
    #define USB_EP0_TX_CTRL_TX_FLUSH_MASK        0x1
 
    #define USB_EP0_TX_CTRL_TX_START             16
    #define USB_EP0_TX_CTRL_TX_START_SHIFT       16
    #define USB_EP0_TX_CTRL_TX_START_MASK        0x1
 
    #define USB_EP0_TX_CTRL_TX_LEN_SHIFT         0
    #define USB_EP0_TX_CTRL_TX_LEN_MASK          0x7ff
 
#define USB_EP0_RX_CTRL   0x14
    #define USB_EP0_RX_CTRL_RX_FLUSH             1
    #define USB_EP0_RX_CTRL_RX_FLUSH_SHIFT       1
    #define USB_EP0_RX_CTRL_RX_FLUSH_MASK        0x1
 
    #define USB_EP0_RX_CTRL_RX_ACCEPT            0
    #define USB_EP0_RX_CTRL_RX_ACCEPT_SHIFT      0
    #define USB_EP0_RX_CTRL_RX_ACCEPT_MASK       0x1
 
#define USB_EP0_STS       0x18
    #define USB_EP0_STS_TX_ERR                   20
    #define USB_EP0_STS_TX_ERR_SHIFT             20
    #define USB_EP0_STS_TX_ERR_MASK              0x1
 
    #define USB_EP0_STS_TX_BUSY                  19
    #define USB_EP0_STS_TX_BUSY_SHIFT            19
    #define USB_EP0_STS_TX_BUSY_MASK             0x1
 
    #define USB_EP0_STS_RX_ERR                   18
    #define USB_EP0_STS_RX_ERR_SHIFT             18
    #define USB_EP0_STS_RX_ERR_MASK              0x1
 
    #define USB_EP0_STS_RX_SETUP                 17
    #define USB_EP0_STS_RX_SETUP_SHIFT           17
    #define USB_EP0_STS_RX_SETUP_MASK            0x1
 
    #define USB_EP0_STS_RX_READY                 16
    #define USB_EP0_STS_RX_READY_SHIFT           16
    #define USB_EP0_STS_RX_READY_MASK            0x1
 
    #define USB_EP0_STS_RX_COUNT_SHIFT           0
    #define USB_EP0_STS_RX_COUNT_MASK            0x7ff
 
#define USB_EP0_DATA      0x1c
    #define USB_EP0_DATA_DATA_SHIFT              0
    #define USB_EP0_DATA_DATA_MASK               0xff
 
#define USB_EP1_CFG       0x20
    #define USB_EP1_CFG_INT_RX                   3
    #define USB_EP1_CFG_INT_RX_SHIFT             3
    #define USB_EP1_CFG_INT_RX_MASK              0x1
 
    #define USB_EP1_CFG_INT_TX                   2
    #define USB_EP1_CFG_INT_TX_SHIFT             2
    #define USB_EP1_CFG_INT_TX_MASK              0x1
 
    #define USB_EP1_CFG_STALL_EP                 1
    #define USB_EP1_CFG_STALL_EP_SHIFT           1
    #define USB_EP1_CFG_STALL_EP_MASK            0x1
 
    #define USB_EP1_CFG_ISO                      0
    #define USB_EP1_CFG_ISO_SHIFT                0
    #define USB_EP1_CFG_ISO_MASK                 0x1
 
#define USB_EP1_TX_CTRL   0x24
    #define USB_EP1_TX_CTRL_TX_FLUSH             17
    #define USB_EP1_TX_CTRL_TX_FLUSH_SHIFT       17
    #define USB_EP1_TX_CTRL_TX_FLUSH_MASK        0x1
 
    #define USB_EP1_TX_CTRL_TX_START             16
    #define USB_EP1_TX_CTRL_TX_START_SHIFT       16
    #define USB_EP1_TX_CTRL_TX_START_MASK        0x1
 
    #define USB_EP1_TX_CTRL_TX_LEN_SHIFT         0
    #define USB_EP1_TX_CTRL_TX_LEN_MASK          0x7ff
 
#define USB_EP1_RX_CTRL   0x28
    #define USB_EP1_RX_CTRL_RX_FLUSH             1
    #define USB_EP1_RX_CTRL_RX_FLUSH_SHIFT       1
    #define USB_EP1_RX_CTRL_RX_FLUSH_MASK        0x1
 
    #define USB_EP1_RX_CTRL_RX_ACCEPT            0
    #define USB_EP1_RX_CTRL_RX_ACCEPT_SHIFT      0
    #define USB_EP1_RX_CTRL_RX_ACCEPT_MASK       0x1
 
#define USB_EP1_STS       0x2c
    #define USB_EP1_STS_TX_ERR                   20
    #define USB_EP1_STS_TX_ERR_SHIFT             20
    #define USB_EP1_STS_TX_ERR_MASK              0x1
 
    #define USB_EP1_STS_TX_BUSY                  19
    #define USB_EP1_STS_TX_BUSY_SHIFT            19
    #define USB_EP1_STS_TX_BUSY_MASK             0x1
 
    #define USB_EP1_STS_RX_ERR                   18
    #define USB_EP1_STS_RX_ERR_SHIFT             18
    #define USB_EP1_STS_RX_ERR_MASK              0x1
 
    #define USB_EP1_STS_RX_SETUP                 17
    #define USB_EP1_STS_RX_SETUP_SHIFT           17
    #define USB_EP1_STS_RX_SETUP_MASK            0x1
 
    #define USB_EP1_STS_RX_READY                 16
    #define USB_EP1_STS_RX_READY_SHIFT           16
    #define USB_EP1_STS_RX_READY_MASK            0x1
 
    #define USB_EP1_STS_RX_COUNT_SHIFT           0
    #define USB_EP1_STS_RX_COUNT_MASK            0x7ff
 
#define USB_EP1_DATA      0x30
    #define USB_EP1_DATA_DATA_SHIFT              0
    #define USB_EP1_DATA_DATA_MASK               0xff
 
#define USB_EP2_CFG       0x34
    #define USB_EP2_CFG_INT_RX                   3
    #define USB_EP2_CFG_INT_RX_SHIFT             3
    #define USB_EP2_CFG_INT_RX_MASK              0x1
 
    #define USB_EP2_CFG_INT_TX                   2
    #define USB_EP2_CFG_INT_TX_SHIFT             2
    #define USB_EP2_CFG_INT_TX_MASK              0x1
 
    #define USB_EP2_CFG_STALL_EP                 1
    #define USB_EP2_CFG_STALL_EP_SHIFT           1
    #define USB_EP2_CFG_STALL_EP_MASK            0x1
 
    #define USB_EP2_CFG_ISO                      0
    #define USB_EP2_CFG_ISO_SHIFT                0
    #define USB_EP2_CFG_ISO_MASK                 0x1
 
#define USB_EP2_TX_CTRL   0x38
    #define USB_EP2_TX_CTRL_TX_FLUSH             17
    #define USB_EP2_TX_CTRL_TX_FLUSH_SHIFT       17
    #define USB_EP2_TX_CTRL_TX_FLUSH_MASK        0x1
 
    #define USB_EP2_TX_CTRL_TX_START             16
    #define USB_EP2_TX_CTRL_TX_START_SHIFT       16
    #define USB_EP2_TX_CTRL_TX_START_MASK        0x1
 
    #define USB_EP2_TX_CTRL_TX_LEN_SHIFT         0
    #define USB_EP2_TX_CTRL_TX_LEN_MASK          0x7ff
 
#define USB_EP2_RX_CTRL   0x3c
    #define USB_EP2_RX_CTRL_RX_FLUSH             1
    #define USB_EP2_RX_CTRL_RX_FLUSH_SHIFT       1
    #define USB_EP2_RX_CTRL_RX_FLUSH_MASK        0x1
 
    #define USB_EP2_RX_CTRL_RX_ACCEPT            0
    #define USB_EP2_RX_CTRL_RX_ACCEPT_SHIFT      0
    #define USB_EP2_RX_CTRL_RX_ACCEPT_MASK       0x1
 
#define USB_EP2_STS       0x40
    #define USB_EP2_STS_TX_ERR                   20
    #define USB_EP2_STS_TX_ERR_SHIFT             20
    #define USB_EP2_STS_TX_ERR_MASK              0x1
 
    #define USB_EP2_STS_TX_BUSY                  19
    #define USB_EP2_STS_TX_BUSY_SHIFT            19
    #define USB_EP2_STS_TX_BUSY_MASK             0x1
 
    #define USB_EP2_STS_RX_ERR                   18
    #define USB_EP2_STS_RX_ERR_SHIFT             18
    #define USB_EP2_STS_RX_ERR_MASK              0x1
 
    #define USB_EP2_STS_RX_SETUP                 17
    #define USB_EP2_STS_RX_SETUP_SHIFT           17
    #define USB_EP2_STS_RX_SETUP_MASK            0x1
 
    #define USB_EP2_STS_RX_READY                 16
    #define USB_EP2_STS_RX_READY_SHIFT           16
    #define USB_EP2_STS_RX_READY_MASK            0x1
 
    #define USB_EP2_STS_RX_COUNT_SHIFT           0
    #define USB_EP2_STS_RX_COUNT_MASK            0x7ff
 
#define USB_EP2_DATA      0x44
    #define USB_EP2_DATA_DATA_SHIFT              0
    #define USB_EP2_DATA_DATA_MASK               0xff
 
#define USB_EP3_CFG       0x48
    #define USB_EP3_CFG_INT_RX                   3
    #define USB_EP3_CFG_INT_RX_SHIFT             3
    #define USB_EP3_CFG_INT_RX_MASK              0x1
 
    #define USB_EP3_CFG_INT_TX                   2
    #define USB_EP3_CFG_INT_TX_SHIFT             2
    #define USB_EP3_CFG_INT_TX_MASK              0x1
 
    #define USB_EP3_CFG_STALL_EP                 1
    #define USB_EP3_CFG_STALL_EP_SHIFT           1
    #define USB_EP3_CFG_STALL_EP_MASK            0x1
 
    #define USB_EP3_CFG_ISO                      0
    #define USB_EP3_CFG_ISO_SHIFT                0
    #define USB_EP3_CFG_ISO_MASK                 0x1
 
#define USB_EP3_TX_CTRL   0x4c
    #define USB_EP3_TX_CTRL_TX_FLUSH             17
    #define USB_EP3_TX_CTRL_TX_FLUSH_SHIFT       17
    #define USB_EP3_TX_CTRL_TX_FLUSH_MASK        0x1
 
    #define USB_EP3_TX_CTRL_TX_START             16
    #define USB_EP3_TX_CTRL_TX_START_SHIFT       16
    #define USB_EP3_TX_CTRL_TX_START_MASK        0x1
 
    #define USB_EP3_TX_CTRL_TX_LEN_SHIFT         0
    #define USB_EP3_TX_CTRL_TX_LEN_MASK          0x7ff
 
#define USB_EP3_RX_CTRL   0x50
    #define USB_EP3_RX_CTRL_RX_FLUSH             1
    #define USB_EP3_RX_CTRL_RX_FLUSH_SHIFT       1
    #define USB_EP3_RX_CTRL_RX_FLUSH_MASK        0x1
 
    #define USB_EP3_RX_CTRL_RX_ACCEPT            0
    #define USB_EP3_RX_CTRL_RX_ACCEPT_SHIFT      0
    #define USB_EP3_RX_CTRL_RX_ACCEPT_MASK       0x1
 
#define USB_EP3_STS       0x54
    #define USB_EP3_STS_TX_ERR                   20
    #define USB_EP3_STS_TX_ERR_SHIFT             20
    #define USB_EP3_STS_TX_ERR_MASK              0x1
 
    #define USB_EP3_STS_TX_BUSY                  19
    #define USB_EP3_STS_TX_BUSY_SHIFT            19
    #define USB_EP3_STS_TX_BUSY_MASK             0x1
 
    #define USB_EP3_STS_RX_ERR                   18
    #define USB_EP3_STS_RX_ERR_SHIFT             18
    #define USB_EP3_STS_RX_ERR_MASK              0x1
 
    #define USB_EP3_STS_RX_SETUP                 17
    #define USB_EP3_STS_RX_SETUP_SHIFT           17
    #define USB_EP3_STS_RX_SETUP_MASK            0x1
 
    #define USB_EP3_STS_RX_READY                 16
    #define USB_EP3_STS_RX_READY_SHIFT           16
    #define USB_EP3_STS_RX_READY_MASK            0x1
 
    #define USB_EP3_STS_RX_COUNT_SHIFT           0
    #define USB_EP3_STS_RX_COUNT_MASK            0x7ff
 
#define USB_EP3_DATA      0x58
    #define USB_EP3_DATA_DATA_SHIFT              0
    #define USB_EP3_DATA_DATA_MASK               0xff
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
#define EP_STRIDE           0x14
 
#define USB_FUNC_CTRL_MODE_MASK   (0xFF << USB_FUNC_CTRL_PHY_OPMODE_SHIFT)
 
#define USB_FUNC_CTRL_MODE_HS    ((0 << USB_FUNC_CTRL_PHY_OPMODE_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_XCVRSELECT_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_TERMSELECT_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_DPPULLDOWN_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_DMPULLDOWN_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_HS_CHIRP_EN_SHIFT))
#define USB_FUNC_CTRL_MODE_PERIP_CHIRP ((2 << USB_FUNC_CTRL_PHY_OPMODE_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_XCVRSELECT_SHIFT) | \
                                 (1 << USB_FUNC_CTRL_PHY_TERMSELECT_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_DPPULLDOWN_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_DMPULLDOWN_SHIFT) | \
                                 (1 << USB_FUNC_CTRL_HS_CHIRP_EN_SHIFT))
#define USB_FUNC_CTRL_MODE_HOST_CHIRP ((2 << USB_FUNC_CTRL_PHY_OPMODE_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_XCVRSELECT_SHIFT) | \
                                 (1 << USB_FUNC_CTRL_PHY_TERMSELECT_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_DPPULLDOWN_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_DMPULLDOWN_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_HS_CHIRP_EN_SHIFT))
#define USB_FUNC_CTRL_PULLUP_EN ((0 << USB_FUNC_CTRL_PHY_OPMODE_SHIFT) | \
                                 (1 << USB_FUNC_CTRL_PHY_XCVRSELECT_SHIFT) | \
                                 (1 << USB_FUNC_CTRL_PHY_TERMSELECT_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_DPPULLDOWN_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_DMPULLDOWN_SHIFT))
#define USB_FUNC_CTRL_PULLUP_DIS ((1 << USB_FUNC_CTRL_PHY_OPMODE_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_XCVRSELECT_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_TERMSELECT_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_DPPULLDOWN_SHIFT) | \
                                 (0 << USB_FUNC_CTRL_PHY_DMPULLDOWN_SHIFT))
 
#define USB_FUNC_ENDPOINTS      4
 
#define MIN(a,b)                ((a)<=(b)?(a):(b))
 
//-----------------------------------------------------------------
// Locals:
//-----------------------------------------------------------------
static unsigned int _tx_count[USB_FUNC_ENDPOINTS];
static int _addressed;
static int _configured;
static int _attached;
static int _endpoint_stalled[USB_FUNC_ENDPOINTS];
static FUNC_PTR _func_bus_reset;
static FUNC_PTR _func_setup;
static FUNC_PTR _func_ctrl_out;
static unsigned int _ctrl_reg;
static unsigned int _usb_base;
 
//-----------------------------------------------------------------
// usbhw_reg_write:
//-----------------------------------------------------------------
static void usbhw_reg_write(unsigned int addr, unsigned data)
{
    *((volatile unsigned int*)(_usb_base + addr)) = data;
}
//-----------------------------------------------------------------
// usbhw_reg_read:
//-----------------------------------------------------------------
static unsigned int usbhw_reg_read(unsigned int addr)
{
    return *((volatile unsigned int*)(_usb_base + addr));
}
//-----------------------------------------------------------------
// usbhw_init:
//-----------------------------------------------------------------
void usbhw_init(unsigned int base, FUNC_PTR bus_reset, FUNC_PTR on_setup, FUNC_PTR on_out)
{
    int i;
 
    _usb_base = base;
 
    log_printf(USBLOG_HW_RESET, "Init\n");
 
    for (i=0;i<USB_FUNC_ENDPOINTS;i++)
    {
        _tx_count[i] = 0;
        _endpoint_stalled[i] = 0;
    }
 
    _addressed  = 0;
    _configured = 0;
    _attached   = 0;
 
    _ctrl_reg = USB_FUNC_CTRL_PULLUP_DIS;
 
    _func_bus_reset = bus_reset;
    _func_setup = on_setup;
    _func_ctrl_out = on_out;
 
    usbhw_reg_write(USB_EP0_TX_CTRL, (1 << USB_EP0_TX_CTRL_TX_FLUSH_SHIFT));
    usbhw_reg_write(USB_EP1_TX_CTRL, (1 << USB_EP1_TX_CTRL_TX_FLUSH_SHIFT));
    usbhw_reg_write(USB_EP2_TX_CTRL, (1 << USB_EP2_TX_CTRL_TX_FLUSH_SHIFT));
    usbhw_reg_write(USB_EP3_TX_CTRL, (1 << USB_EP3_TX_CTRL_TX_FLUSH_SHIFT));
 
    usbhw_reg_write(USB_EP0_RX_CTRL, (1 << USB_EP0_RX_CTRL_RX_FLUSH_SHIFT));
    usbhw_reg_write(USB_EP1_RX_CTRL, (1 << USB_EP1_RX_CTRL_RX_FLUSH_SHIFT));
    usbhw_reg_write(USB_EP2_RX_CTRL, (1 << USB_EP2_RX_CTRL_RX_FLUSH_SHIFT));
    usbhw_reg_write(USB_EP3_RX_CTRL, (1 << USB_EP3_RX_CTRL_RX_FLUSH_SHIFT));
}
//-----------------------------------------------------------------
// usbhw_service:
//-----------------------------------------------------------------
void usbhw_service(void)
{
    unsigned int status = usbhw_reg_read(USB_FUNC_STAT);
    static int _initial  = 1;
    static int _reset_count = 0;
    int i;
 
    // Acknowledge fake USB reset after attach..
    if (_initial)
    {
        usbhw_reg_write(USB_FUNC_CTRL, _ctrl_reg);
 
        _initial = 0;
        return ; 
    }
 
#ifdef USB_SPEED_HS
    // Bus reset event
    if (status & (1 << USB_FUNC_STAT_RST))
    {
        // Ack bus reset by writing to CTRL register
        usbhw_reg_write(USB_FUNC_STAT, (1 << USB_FUNC_STAT_RST));
 
        usbhw_reg_write(USB_EP0_TX_CTRL, (1 << USB_EP0_TX_CTRL_TX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP0_RX_CTRL, (1 << USB_EP0_RX_CTRL_RX_FLUSH_SHIFT));
 
        usbhw_reg_write(USB_EP1_TX_CTRL, (1 << USB_EP1_TX_CTRL_TX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP2_TX_CTRL, (1 << USB_EP2_TX_CTRL_TX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP3_TX_CTRL, (1 << USB_EP3_TX_CTRL_TX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP1_RX_CTRL, (1 << USB_EP1_RX_CTRL_RX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP2_RX_CTRL, (1 << USB_EP2_RX_CTRL_RX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP3_RX_CTRL, (1 << USB_EP3_RX_CTRL_RX_FLUSH_SHIFT));        
 
        // Fail ... 
        if (_reset_count > 4)
        {
            log_printf(USBLOG_HW_RESET, " DEVICE: Another Reset Detected %d\n", timer_now());
 
            // Force detach
            usbhw_attach(0);
            timer_sleep(100);
            usbhw_attach(1);
 
            _reset_count = 0;
            return ;
        }
 
        _configured = 0;
        _addressed  = 0;
 
        for (i=0;i<USB_FUNC_ENDPOINTS;i++)
        {
            _tx_count[i] = 0;
            _endpoint_stalled[i] = 0;
        }
 
        log_printf(USBLOG_HW_RESET, " DEVICE: Reset Detected %d\n", timer_now());
 
        // Detected SE0 for at least 2.5us, now drive HS CHIRP for at least 1ms
        usbhw_reg_write(USB_FUNC_CTRL, USB_FUNC_CTRL_MODE_PERIP_CHIRP);
        timer_sleep(3);
 
        // Stop driving the chirp pattern
        log_printf(USBLOG_HW_RESET, " DEVICE: Peripheral Chirp De-assert %d\n", timer_now());
        usbhw_reg_write(USB_FUNC_CTRL, USB_FUNC_CTRL_MODE_HOST_CHIRP);
 
        int chirps = 0;
        while (chirps < 5)
        {
            static unsigned old_ls = ~0;
            unsigned new_ls = (usbhw_reg_read(USB_FUNC_STAT) >> USB_FUNC_STAT_LINESTATE_SHIFT) & 0x3;
            if ((old_ls != new_ls) && (new_ls == 1 || new_ls == 2))
                chirps++;
            old_ls = new_ls;
        }        
 
        log_printf(USBLOG_HW_RESET, " DEVICE: Host Chirp Detected %d\n", timer_now());
        usbhw_reg_write(USB_FUNC_CTRL, USB_FUNC_CTRL_MODE_HS);
 
 
        log_printf(USBLOG_HW_RESET, " DEVICE: BUS RESET %d\n", timer_now());
 
 
        if (_func_bus_reset)
            _func_bus_reset();
 
        // Ack bus reset by writing to CTRL register
        usbhw_reg_write(USB_FUNC_STAT, (1 << USB_FUNC_STAT_RST));
        _reset_count += 1;
    }
#else
    // Bus reset event
    if (status & (1 << USB_FUNC_STAT_RST))
    {
        // Ack bus reset by writing to CTRL register
        usbhw_reg_write(USB_FUNC_STAT, (1 << USB_FUNC_STAT_RST));
 
        _configured = 0;
        _addressed  = 0;
 
        for (i=0;i<USB_FUNC_ENDPOINTS;i++)
        {
            _tx_count[i] = 0;
            _endpoint_stalled[i] = 0;
        }
 
        log_printf(USBLOG_HW_RESET, " DEVICE: BUS RESET %d\n", timer_now());
 
        usbhw_reg_write(USB_EP0_TX_CTRL, (1 << USB_EP0_TX_CTRL_TX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP1_TX_CTRL, (1 << USB_EP1_TX_CTRL_TX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP2_TX_CTRL, (1 << USB_EP2_TX_CTRL_TX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP3_TX_CTRL, (1 << USB_EP3_TX_CTRL_TX_FLUSH_SHIFT));
 
        usbhw_reg_write(USB_EP0_RX_CTRL, (1 << USB_EP0_RX_CTRL_RX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP1_RX_CTRL, (1 << USB_EP1_RX_CTRL_RX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP2_RX_CTRL, (1 << USB_EP2_RX_CTRL_RX_FLUSH_SHIFT));
        usbhw_reg_write(USB_EP3_RX_CTRL, (1 << USB_EP3_RX_CTRL_RX_FLUSH_SHIFT));
 
        if (_func_bus_reset)
            _func_bus_reset();
    }
#endif
 
    status = usbhw_reg_read(USB_EP0_STS);
 
    // Tx underflow error 
    if (status & (1 << USB_EP0_STS_TX_ERR))
    {
        log_printf(USBLOG_ERR, "Tx underflow error!\n");
        while (1) 
            ;
    }
    // CRC error 
    else if (status & (1 << USB_EP0_STS_RX_ERR))
    {
        log_printf(USBLOG_ERR, "Rx CRC error!\n");
        while (1)
            ;
    }    
    // SETUP packet received (EP0)
    else if ((status & (1 << USB_EP0_STS_RX_READY)) && (status & (1 << USB_EP0_STS_RX_SETUP)))
    {
        log_printf(USBLOG_HW_CTRL, "SETUP packet received\n");
 
        if (_func_setup)
            _func_setup();
 
        log_printf(USBLOG_HW_CTRL, "SETUP packet processed\n");
    }
    // OUT data received on EP0
    else if (status & (1 << USB_EP0_STS_RX_READY))
    {
        log_printf(USBLOG_HW_CTRL, "OUT packet received on EP0\n");
 
        if (_func_ctrl_out)
            _func_ctrl_out();
    }
}
//-----------------------------------------------------------------
// usbhw_attach:
//-----------------------------------------------------------------
void usbhw_attach(int state)
{
    // Pull up D+ to Vdd
    if ( state )
    {
        _attached = 1;
        _ctrl_reg &= ~USB_FUNC_CTRL_MODE_MASK;
        _ctrl_reg |= USB_FUNC_CTRL_PULLUP_EN;
        usbhw_reg_write(USB_FUNC_CTRL, _ctrl_reg);
        log_printf(USBLOG_HW_CTRL, "ATTACH\n");
 
        // Reset any previous reset detection
        usbhw_reg_write(USB_FUNC_STAT, (1 << USB_FUNC_STAT_RST));
    }
    // Disconnect pull-up to disconnect from bus
    else
    {
        _attached = 0;
        _ctrl_reg &= ~USB_FUNC_CTRL_MODE_MASK;
        _ctrl_reg |= USB_FUNC_CTRL_PULLUP_DIS;
        usbhw_reg_write(USB_FUNC_CTRL, _ctrl_reg);
        log_printf(USBLOG_HW_CTRL, "DETACH\n");          
    }
}
//-----------------------------------------------------------------
// usbhw_is_configured:
//-----------------------------------------------------------------
int usbhw_is_configured(void)
{
    return _configured;
}
//-----------------------------------------------------------------
// usbhw_is_addressed:
//-----------------------------------------------------------------
int usbhw_is_addressed(void)
{
    return _addressed;
}
//-----------------------------------------------------------------
// usbhw_is_attached:
//-----------------------------------------------------------------
int usbhw_is_attached(void)
{
    return _attached;
}
//-----------------------------------------------------------------
// usbhw_set_configured:
//-----------------------------------------------------------------
void usbhw_set_configured(int configured)
{
    _configured = configured;
}
//-----------------------------------------------------------------
// usbhw_set_address:
//-----------------------------------------------------------------
void usbhw_set_address(unsigned char addr)
{    
    usbhw_reg_write(USB_FUNC_ADDR, addr);
    _addressed = 1;
}
//-----------------------------------------------------------------
// usbhw_is_endpoint_stalled:
//-----------------------------------------------------------------
int usbhw_is_endpoint_stalled(unsigned char endpoint)
{
    return _endpoint_stalled[endpoint];
}
//-----------------------------------------------------------------
// usbhw_clear_endpoint_stall:
//-----------------------------------------------------------------
void usbhw_clear_endpoint_stall(unsigned char endpoint)
{
    unsigned int data = usbhw_reg_read(USB_EP0_CFG + (endpoint * EP_STRIDE));
    data &= ~(1 << USB_EP0_CFG_STALL_EP);
    usbhw_reg_write(USB_EP0_CFG + (endpoint * EP_STRIDE), data);
 
    _endpoint_stalled[endpoint] = 0;
}
//-----------------------------------------------------------------
// usbhw_set_endpoint_stall:
//-----------------------------------------------------------------
void usbhw_set_endpoint_stall(unsigned char endpoint)
{
    unsigned int data = usbhw_reg_read(USB_EP0_CFG + (endpoint * EP_STRIDE));
    data |= (1 << USB_EP0_CFG_STALL_EP);
    usbhw_reg_write(USB_EP0_CFG + (endpoint * EP_STRIDE), data);
 
    _endpoint_stalled[endpoint] = 1;
}
//-----------------------------------------------------------------
// usbhw_is_rx_ready: Is some receive data ready on an endpoint?
//-----------------------------------------------------------------
int usbhw_is_rx_ready(unsigned char endpoint)
{
    return (usbhw_reg_read(USB_EP0_STS + (endpoint * EP_STRIDE)) & (1 << USB_EP0_STS_RX_READY_SHIFT)) ? 1 : 0;
}
//-----------------------------------------------------------------
// usbhw_get_rx_count: Get amount of data waiting in endpoint
//-----------------------------------------------------------------
int usbhw_get_rx_count(unsigned char endpoint)
{
    return (usbhw_reg_read(USB_EP0_STS + (endpoint * EP_STRIDE)) >> USB_EP0_STS_RX_COUNT_SHIFT) & USB_EP0_STS_RX_COUNT_MASK;
}
//-----------------------------------------------------------------
// usbhw_get_rx_data: Read data from endpoint
//-----------------------------------------------------------------
int usbhw_get_rx_data(unsigned char endpoint, unsigned char *data, int max_len)
{
    int i;
    int bytes_ready;
    int bytes_read = 0;
 
    // Received data count includes CRC
    bytes_ready = usbhw_get_rx_count(endpoint);
 
    // Limit data read to buffer size
    bytes_read = MIN(bytes_ready, max_len);
 
    for (i=0;i<bytes_read;i++)
        *data++ = usbhw_reg_read(USB_EP0_DATA + (endpoint * EP_STRIDE));
 
    // Return number of bytes read
    return bytes_read;
}
//-----------------------------------------------------------------
// usbhw_get_rx_byte: Read byte from endpoint
//-----------------------------------------------------------------
unsigned char usbhw_get_rx_byte(unsigned char endpoint)
{
    return usbhw_reg_read(USB_EP0_DATA + (endpoint * EP_STRIDE));
}
//-----------------------------------------------------------------
// usbhw_clear_rx_ready: Clear Rx data ready flag
//-----------------------------------------------------------------
void usbhw_clear_rx_ready(unsigned char endpoint)
{
    log_printf(USBLOG_HW_DATA, "Clear endpoint buffer\n");
    usbhw_reg_write(USB_EP0_RX_CTRL + (endpoint * EP_STRIDE), 1 << USB_EP1_RX_CTRL_RX_ACCEPT_SHIFT);
}
//-----------------------------------------------------------------
// usbhw_has_tx_space: Is there space in the tx buffer
//-----------------------------------------------------------------
int usbhw_has_tx_space(unsigned char endpoint)
{
    return (usbhw_reg_read(USB_EP0_STS + (endpoint * EP_STRIDE)) & (1 << USB_EP1_STS_TX_BUSY_SHIFT)) ? 0 : 1;
}
//-----------------------------------------------------------------
// usbhw_load_tx_buffer: Load tx buffer & start transfer (non-blocking) 
//-----------------------------------------------------------------
int usbhw_load_tx_buffer(unsigned char endpoint, unsigned char *data, int count)
{
    int i;
    unsigned int word_data = 0;
 
    for (i=0;i<count;i++)
        usbhw_reg_write(USB_EP0_DATA + (endpoint * EP_STRIDE), *data++);
 
    // Start transmit
    word_data = (1 << USB_EP0_TX_CTRL_TX_START_SHIFT) | count;
    usbhw_reg_write(USB_EP0_TX_CTRL + (endpoint * EP_STRIDE), word_data);
 
    log_printf(USBLOG_HW_DATA, "Tx %d bytes\n", count);
 
    return count;
}
//-----------------------------------------------------------------
// usbhw_write_tx_byte: Write a byte to Tx buffer (don't send yet)
//-----------------------------------------------------------------
void usbhw_write_tx_byte(unsigned char endpoint, unsigned char data)
{
    usbhw_reg_write(USB_EP0_DATA + (endpoint * EP_STRIDE), data);
    _tx_count[endpoint]++;
}
//-----------------------------------------------------------------
// usbhw_start_tx: Start a tx packet with data loaded into endpoint
//-----------------------------------------------------------------
void usbhw_start_tx(unsigned char endpoint)
{
    // Start transmit
    unsigned int word_data = (1 << USB_EP0_TX_CTRL_TX_START_SHIFT) | _tx_count[endpoint];
    usbhw_reg_write(USB_EP0_TX_CTRL + (endpoint * EP_STRIDE), word_data);
 
    log_printf(USBLOG_HW_DATA, "Tx %d bytes\n", _tx_count[endpoint]);
 
    _tx_count[endpoint] = 0;  
}
//-----------------------------------------------------------------
// usbhw_control_endpoint_stall:
//-----------------------------------------------------------------
void usbhw_control_endpoint_stall(void)
{
    log_printf(USBLOG_ERR, "Error, send EP stall!\n");
    usbhw_set_endpoint_stall(0);
 
    // Control endpoint stalls are self clearing
    _endpoint_stalled[0] = 0;
}
//-----------------------------------------------------------------
// usbhw_control_endpoint_ack:
//-----------------------------------------------------------------
void usbhw_control_endpoint_ack(void)
{
    // Send ZLP on EP0
    log_printf(USBLOG_HW_DATA, "Send ZLP\n");
    usbhw_reg_write(USB_EP0_TX_CTRL, (1 << USB_EP0_TX_CTRL_TX_START_SHIFT));
 
    log_printf(USBLOG_HW_DATA, "Tx [ZLP/ACK]\n");
 
    while (!usbhw_has_tx_space(0))
        ;
 
    log_printf(USBLOG_HW_DATA, "Tx complete\n");
}
//-----------------------------------------------------------------
// usbhw_get_frame_number:
//-----------------------------------------------------------------
unsigned short usbhw_get_frame_number(void)
{
    return (usbhw_reg_read(USB_FUNC_STAT) >> USB_FUNC_STAT_FRAME_SHIFT) & USB_FUNC_STAT_FRAME_MASK;
}
 
//-----------------------------------------------------------------
// usbhw_timer_now:
//-----------------------------------------------------------------
t_time usbhw_timer_now(void)
{
    return timer_now();
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.