SAMA5/ECHI: Debug register access, add logic to determine transfer size, fix setting of control bit in token
This commit is contained in:
parent
db1b3c421b
commit
7c5f8c86ce
@ -75,6 +75,12 @@
|
||||
|
||||
#define HCOR ((volatile struct ehci_hcor_s *)(SAM_UHPEHCI_VSECTION + 0x10))
|
||||
|
||||
/* USB2 Debug Port Register Interface. These are not documented, but I was
|
||||
* able to find these by registers by peeking at EHCI memory.
|
||||
*/
|
||||
|
||||
#define HDEBUG ((volatile struct ehci_debug_s *)(SAM_UHPEHCI_VSECTION + 0x90))
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
@ -330,28 +330,7 @@ static inline void sam_selectplla(void)
|
||||
|
||||
static inline void sam_usbclockconfig(void)
|
||||
{
|
||||
#ifdef CONFIG_SAMA5_OHCI
|
||||
/* For OHCI Full-speed operations only, the user has to perform the
|
||||
* following:
|
||||
*
|
||||
* 1) Enable UHP peripheral clock, bit (1 << AT91C_ID_UHPHS) in PMC_PCER
|
||||
* register.
|
||||
* 2) Select PLLACK as Input clock of OHCI part, USBS bit in PMC_USB
|
||||
* register.
|
||||
* 3) Program the OHCI clocks (UHP48M and UHP12M) with USBDIV field in
|
||||
* PMC_USB register. USBDIV value is calculated regarding the PLLACK
|
||||
* value and USB Full-speed accuracy.
|
||||
* 4) Enable the OHCI clocks, UHP bit in PMC_SCER register.
|
||||
*
|
||||
* Steps 2 and 3 are done here. 1 and 2 are performed with the OHCI
|
||||
* driver is initialized.
|
||||
*/
|
||||
|
||||
putreg32(BOARD_OHCI_INPUT | BOARD_OHCI_DIVIDER << PMC_USB_USBDIV_SHIFT,
|
||||
SAM_PMC_USB);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAMA5_EHCI
|
||||
#if defined(CONFIG_SAMA5_EHCI)
|
||||
uint32_t regval;
|
||||
|
||||
/* The USB Host High Speed requires a 480 MHz clock (UPLLCK) for the
|
||||
@ -415,6 +394,27 @@ static inline void sam_usbclockconfig(void)
|
||||
|
||||
regval |= PMC_USB_USBDIV(9);
|
||||
putreg32(regval, SAM_PMC_USB);
|
||||
|
||||
#elif defined(CONFIG_SAMA5_OHCI)
|
||||
/* For OHCI Full-speed operations only, the user has to perform the
|
||||
* following:
|
||||
*
|
||||
* 1) Enable UHP peripheral clock, bit (1 << AT91C_ID_UHPHS) in PMC_PCER
|
||||
* register.
|
||||
* 2) Select PLLACK as Input clock of OHCI part, USBS bit in PMC_USB
|
||||
* register.
|
||||
* 3) Program the OHCI clocks (UHP48M and UHP12M) with USBDIV field in
|
||||
* PMC_USB register. USBDIV value is calculated regarding the PLLACK
|
||||
* value and USB Full-speed accuracy.
|
||||
* 4) Enable the OHCI clocks, UHP bit in PMC_SCER register.
|
||||
*
|
||||
* Steps 2 and 3 are done here. 1 and 2 are performed with the OHCI
|
||||
* driver is initialized.
|
||||
*/
|
||||
|
||||
putreg32(BOARD_OHCI_INPUT | BOARD_OHCI_DIVIDER << PMC_USB_USBDIV_SHIFT,
|
||||
SAM_PMC_USB);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -201,6 +201,7 @@ struct sam_epinfo_s
|
||||
uint16_t xfrtype:2; /* See USB_EP_ATTR_XFER_* definitions in usb.h */
|
||||
uint16_t speed:2; /* See USB_*_SPEED definitions in ehci.h */
|
||||
int result; /* The result of the transfer */
|
||||
uint32_t xfrd; /* On completion, will hold the number of bytes transferred */
|
||||
sem_t iocsem; /* Semaphore used to wait for transfer completion */
|
||||
};
|
||||
|
||||
@ -335,11 +336,12 @@ static void sam_qh_enqueue(struct sam_qh_s *qh);
|
||||
static struct sam_qh_s *sam_qh_create(struct sam_rhport_s *rhport,
|
||||
struct sam_epinfo_s *epinfo);
|
||||
static int sam_qtd_addbpl(struct sam_qtd_s *qtd, const void *buffer, size_t buflen);
|
||||
static struct sam_qtd_s *sam_qtd_setupphase(const struct usb_ctrlreq_s *req);
|
||||
static struct sam_qtd_s *sam_qtd_dataphase(void *buffer, int buflen,
|
||||
uint32_t tokenbits);
|
||||
static struct sam_qtd_s *sam_qtd_setupphase(struct sam_epinfo_s *epinfo,
|
||||
const struct usb_ctrlreq_s *req);
|
||||
static struct sam_qtd_s *sam_qtd_dataphase(struct sam_epinfo_s *epinfo,
|
||||
void *buffer, int buflen, uint32_t tokenbits);
|
||||
static struct sam_qtd_s *sam_qtd_statusphase(uint32_t tokenbits);
|
||||
static int sam_async_transfer(struct sam_rhport_s *rhport,
|
||||
static ssize_t sam_async_transfer(struct sam_rhport_s *rhport,
|
||||
struct sam_epinfo_s *epinfo, const struct usb_ctrlreq_s *req,
|
||||
uint8_t *buffer, size_t buflen);
|
||||
|
||||
@ -1337,10 +1339,11 @@ static int sam_ioc_setup(struct sam_rhport_s *rhport, struct sam_epinfo_s *epinf
|
||||
* completed.
|
||||
*/
|
||||
|
||||
epinfo->iocwait = true; /* We want to be awakened by IOC interrupt */
|
||||
epinfo->status = 0; /* No status yet */
|
||||
epinfo->iocwait = true; /* We want to be awakened by IOC interrupt */
|
||||
epinfo->status = 0; /* No status yet */
|
||||
epinfo->xfrd = 0; /* Nothing transferred yet */
|
||||
epinfo->result = -EBUSY; /* Transfer in progress */
|
||||
ret = OK; /* We are good to go */
|
||||
ret = OK; /* We are good to go */
|
||||
}
|
||||
|
||||
irqrestore(flags);
|
||||
@ -1459,11 +1462,20 @@ static struct sam_qh_s *sam_qh_create(struct sam_rhport_s *rhport,
|
||||
((uint32_t)epinfo->maxpacket << QH_EPCHAR_MAXPKT_SHIFT) |
|
||||
((uint32_t)8 << QH_EPCHAR_RL_SHIFT);
|
||||
|
||||
if (epinfo->speed != EHCI_FULL_SPEED && epinfo->epno == 0)
|
||||
/* Paragraph 3.6.3: "Control Endpoint Flag (C). If the QH.EPS field
|
||||
* indicates the endpoint is not a high-speed device, and the endpoint
|
||||
* is an control endpoint, then software must set this bit to a one.
|
||||
* Otherwise it should always set this bit to a zero."
|
||||
*/
|
||||
|
||||
if (epinfo->speed != EHCI_HIGH_SPEED &&
|
||||
epinfo->xfrtype == USB_EP_ATTR_XFER_CONTROL)
|
||||
{
|
||||
regval |= QH_EPCHAR_C;
|
||||
}
|
||||
|
||||
/* Save the endpoint characteristics word with the correct byte order */
|
||||
|
||||
qh->hw.epchar = sam_swap32(regval);
|
||||
|
||||
/* Write QH endpoint capabilities
|
||||
@ -1566,7 +1578,8 @@ static int sam_qtd_addbpl(struct sam_qtd_s *qtd, const void *buffer, size_t bufl
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static struct sam_qtd_s *sam_qtd_setupphase(const struct usb_ctrlreq_s *req)
|
||||
static struct sam_qtd_s *sam_qtd_setupphase(struct sam_epinfo_s *epinfo,
|
||||
const struct usb_ctrlreq_s *req)
|
||||
{
|
||||
struct sam_qtd_s *qtd;
|
||||
uint32_t regval;
|
||||
@ -1617,6 +1630,10 @@ static struct sam_qtd_s *sam_qtd_setupphase(const struct usb_ctrlreq_s *req)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add the data transfer size to the count in the epinfo structure */
|
||||
|
||||
epinfo->xfrd += USB_SIZEOF_CTRLREQ;
|
||||
|
||||
return qtd;
|
||||
}
|
||||
|
||||
@ -1628,7 +1645,8 @@ static struct sam_qtd_s *sam_qtd_setupphase(const struct usb_ctrlreq_s *req)
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static struct sam_qtd_s *sam_qtd_dataphase(void *buffer, int buflen,
|
||||
static struct sam_qtd_s *sam_qtd_dataphase(struct sam_epinfo_s *epinfo,
|
||||
void *buffer, int buflen,
|
||||
uint32_t tokenbits)
|
||||
{
|
||||
struct sam_qtd_s *qtd;
|
||||
@ -1680,6 +1698,10 @@ static struct sam_qtd_s *sam_qtd_dataphase(void *buffer, int buflen,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add the data transfer size to the count in the epinfo structure */
|
||||
|
||||
epinfo->xfrd += buflen;
|
||||
|
||||
return qtd;
|
||||
}
|
||||
|
||||
@ -1720,14 +1742,13 @@ static struct sam_qtd_s *sam_qtd_statusphase(uint32_t tokenbits)
|
||||
* PID PID Code Contained in tokenbits
|
||||
* CERR Error Counter 3
|
||||
* CPAGE Current Page 0
|
||||
* IOC Interrupt on complete QH_TOKEN_IOC
|
||||
* IOC Interrupt on complete QTD_TOKEN_IOC
|
||||
* NBYTES Total Bytes to Transfer 0
|
||||
* TOGGLE Data Toggle Contained in tokenbits
|
||||
*/
|
||||
|
||||
regval = tokenbits | QTD_TOKEN_ACTIVE |
|
||||
regval = tokenbits | QTD_TOKEN_ACTIVE | QTD_TOKEN_IOC |
|
||||
((uint32_t)3 << QTD_TOKEN_CERR_SHIFT) |
|
||||
QH_TOKEN_IOC |
|
||||
((uint32_t)USB_SIZEOF_CTRLREQ << QTD_TOKEN_NBYTES_SHIFT);
|
||||
|
||||
qtd->hw.token = sam_swap32(regval);
|
||||
@ -1751,12 +1772,18 @@ static struct sam_qtd_s *sam_qtd_statusphase(uint32_t tokenbits)
|
||||
* complete, but will be re-aquired when before returning. The state of
|
||||
* EHCI resources could be very different upon return.
|
||||
*
|
||||
* Returned value:
|
||||
* On success, this function returns the number of bytes actually transferred.
|
||||
* For control transfers, this size includes the size of the control request
|
||||
* plus the size of the data (which could be short); For bulk transfers, this
|
||||
* will be the number of data bytes transfers (which could be short).
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
static int sam_async_transfer(struct sam_rhport_s *rhport,
|
||||
struct sam_epinfo_s *epinfo,
|
||||
const struct usb_ctrlreq_s *req,
|
||||
uint8_t *buffer, size_t buflen)
|
||||
static ssize_t sam_async_transfer(struct sam_rhport_s *rhport,
|
||||
struct sam_epinfo_s *epinfo,
|
||||
const struct usb_ctrlreq_s *req,
|
||||
uint8_t *buffer, size_t buflen)
|
||||
{
|
||||
struct sam_qh_s *qh;
|
||||
struct sam_qtd_s *qtd;
|
||||
@ -1834,7 +1861,7 @@ static int sam_async_transfer(struct sam_rhport_s *rhport,
|
||||
* phase of the request sequence.
|
||||
*/
|
||||
|
||||
qtd = sam_qtd_setupphase(req);
|
||||
qtd = sam_qtd_setupphase(epinfo, req);
|
||||
if (qtd == NULL)
|
||||
{
|
||||
udbg("ERROR: sam_qtd_setupphase failed\n");
|
||||
@ -1878,7 +1905,7 @@ static int sam_async_transfer(struct sam_rhport_s *rhport,
|
||||
* buffer.
|
||||
*/
|
||||
|
||||
qtd = sam_qtd_dataphase(buffer, buflen, tokenbits);
|
||||
qtd = sam_qtd_dataphase(epinfo, buffer, buflen, tokenbits);
|
||||
if (qtd == NULL)
|
||||
{
|
||||
udbg("ERROR: sam_qtd_dataphase failed\n");
|
||||
@ -1950,9 +1977,9 @@ static int sam_async_transfer(struct sam_rhport_s *rhport,
|
||||
goto errout_with_iocwait;
|
||||
}
|
||||
|
||||
/* Transfer completed successfully */
|
||||
/* Transfer completed successfully. Return the number of bytes transferred */
|
||||
|
||||
return OK;
|
||||
return epinfo->xfrd;
|
||||
|
||||
/* Clean-up after an error */
|
||||
|
||||
@ -1960,7 +1987,7 @@ errout_with_qh:
|
||||
sam_qh_discard(qh);
|
||||
errout_with_iocwait:
|
||||
epinfo->iocwait = false;
|
||||
return ret;
|
||||
return (ssize_t)ret;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -1979,7 +2006,8 @@ errout_with_iocwait:
|
||||
|
||||
static int sam_qtd_ioccheck(struct sam_qtd_s *qtd, uint32_t **bp, void *arg)
|
||||
{
|
||||
DEBUGASSERT(qtd);
|
||||
struct sam_epinfo_s *epinfo = (struct sam_epinfo_s *)arg;
|
||||
DEBUGASSERT(qtd && epinfo);
|
||||
|
||||
/* Make sure we reload the QH from memory */
|
||||
|
||||
@ -1997,6 +2025,16 @@ static int sam_qtd_ioccheck(struct sam_qtd_s *qtd, uint32_t **bp, void *arg)
|
||||
|
||||
**bp = qtd->hw.nqp;
|
||||
|
||||
/* Subtract the number of bytes left untransferred. The epinfo->xfrd
|
||||
* field is initialized to the the total number of bytes to be transferred
|
||||
* (all qTDs in the list). We subtract out the number of untransferred
|
||||
* bytes on each transfer and the final result will be the number of bytes
|
||||
* actually transferred.
|
||||
*/
|
||||
|
||||
epinfo->xfrd -= (sam_swap32(qtd->hw.token) & QTD_TOKEN_NBYTES_MASK) >>
|
||||
QTD_TOKEN_NBYTES_SHIFT;
|
||||
|
||||
/* Release this QH by returning it to the free list */
|
||||
|
||||
sam_qtd_free(qtd);
|
||||
@ -2061,7 +2099,7 @@ static int sam_qh_ioccheck(struct sam_qh_s *qh, uint32_t **bp, void *arg)
|
||||
|
||||
/* Remove all active, attached qTD structures from the inactive QH */
|
||||
|
||||
ret = sam_qtd_foreach(qh, sam_qtd_ioccheck, NULL);
|
||||
ret = sam_qtd_foreach(qh, sam_qtd_ioccheck, (void *)qh->epinfo);
|
||||
if (ret < 0)
|
||||
{
|
||||
udbg("ERROR: sam_qh_forall failed: %d\n", ret);
|
||||
@ -3056,7 +3094,7 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr,
|
||||
{
|
||||
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
|
||||
uint16_t len;
|
||||
int ret;
|
||||
ssize_t nbytes;
|
||||
|
||||
DEBUGASSERT(rhport && req);
|
||||
|
||||
@ -3071,9 +3109,9 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr,
|
||||
|
||||
/* Now perform the transfer */
|
||||
|
||||
ret = sam_async_transfer(rhport, &rhport->ep0, req, buffer, len);
|
||||
nbytes = sam_async_transfer(rhport, &rhport->ep0, req, buffer, len);
|
||||
sam_givesem(&g_ehci.exclsem);
|
||||
return ret;
|
||||
return nbytes >=0 ? OK : (int)nbytes;
|
||||
}
|
||||
|
||||
static int sam_ctrlout(FAR struct usbhost_driver_s *drvr,
|
||||
@ -3125,11 +3163,11 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr,
|
||||
*******************************************************************************/
|
||||
|
||||
static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
FAR uint8_t *buffer, size_t buflen)
|
||||
FAR uint8_t *buffer, size_t buflen)
|
||||
{
|
||||
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
|
||||
struct sam_epinfo_s *epinfo = (struct sam_epinfo_s *)ep;
|
||||
int ret;
|
||||
ssize_t nbytes;
|
||||
|
||||
DEBUGASSERT(rhport && epinfo && buffer && buflen > 0);
|
||||
|
||||
@ -3142,7 +3180,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
switch (epinfo->xfrtype)
|
||||
{
|
||||
case USB_EP_ATTR_XFER_BULK:
|
||||
ret = sam_async_transfer(rhport, epinfo, NULL, buffer, buflen);
|
||||
nbytes = sam_async_transfer(rhport, epinfo, NULL, buffer, buflen);
|
||||
break;
|
||||
|
||||
#ifndef CONFIG_USBHOST_INT_DISABLE
|
||||
@ -3156,12 +3194,12 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
case USB_EP_ATTR_XFER_CONTROL:
|
||||
default:
|
||||
udbg("ERROR: Support for transfer type %d not implemented\n");
|
||||
ret = -ENOSYS;
|
||||
nbytes = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
sam_givesem(&g_ehci.exclsem);
|
||||
return ret;
|
||||
return nbytes >=0 ? OK : (int)nbytes;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -134,6 +134,15 @@
|
||||
#define EHCI_PORTSC14_OFFSET 0x0078 /* Port Status/Control, Port 14 */
|
||||
#define EHCI_PORTSC15_OFFSET 0x007c /* Port Status/Control, Port 15 */
|
||||
|
||||
/* Debug Register Offsets *******************************************************************/
|
||||
/* Paragraph C.3 */
|
||||
|
||||
#define ECHI_DEBUG_PCS_OFFSET 0x0000 /* Debug Port Control/Status Register */
|
||||
#define ECHI_DEBUG_USBPIDS_OFFSET 0x0004 /* Debug USB PIDs Register */
|
||||
#define ECHI_DEBUG_DATA0_OFFSET 0x0008 /* Debug Data Buffer 0 Register [31:0] */
|
||||
#define ECHI_DEBUG_DATA1_OFFSET 0x000c /* Debug Data Buffer 1 Register [63:32] */
|
||||
#define ECHI_DEBUG_DEVADDR_OFFSET 0x0010 /* Debug Device Address Register */
|
||||
|
||||
/* PCI Configuration Space Register Bit Definitions *****************************************/
|
||||
|
||||
/* 0x0009-0x000b: Class Code. Paragraph 2.1.2 */
|
||||
@ -355,6 +364,47 @@
|
||||
#define EHCI_PORTSC_ALLINTS (EHCI_PORTSC_CSC | EHCI_PORTSC_PEC | \
|
||||
EHCI_PORTSC_OCC | EHCI_PORTSC_RESUME)
|
||||
|
||||
/* Debug Register Bit Definitions ***********************************************************/
|
||||
|
||||
/* Debug Port Control/Status Register. Paragraph C.3.1 */
|
||||
|
||||
#define ECHI_DEBUG_PCS_LENGTH_SHIFT (0) /* Bits 0-3: Data Length */
|
||||
#define ECHI_DEBUG_PCS_LENGTH_MASK (15 << ECHI_DEBUG_PCS_LENGTH_SHIFT)
|
||||
#define ECHI_DEBUG_PCS_WRITE (1 << 4) /* Bit 6: Write/Read# */
|
||||
#define ECHI_DEBUG_PCS_GO (1 << 5) /* Bit 5: Go */
|
||||
#define ECHI_DEBUG_PCS_ERROR (1 << 6) /* Bit 6: Error/Good# */
|
||||
#define ECHI_DEBUG_PCS_EXCEPTION_SHIFT (17) /* Bits 7-9: Exception */
|
||||
#define ECHI_DEBUG_PCS_EXCEPTION_MASK (7 << ECHI_DEBUG_PCS_EXCEPTION_SHIFT)
|
||||
#define ECHI_DEBUG_PCS_INUSE (1 << 10) /* Bit 10: In Use */
|
||||
/* Bits 11-15: Reserved */
|
||||
#define ECHI_DEBUG_PCS_DONE (1 << 16) /* Bit 16: Done */
|
||||
/* Bits 17-27: Reserved */
|
||||
#define ECHI_DEBUG_PCS_ENABLED (1 << 28) /* Bit 28: Enabled */
|
||||
/* Bit 29: Reserved */
|
||||
#define ECHI_DEBUG_PCS_OWNER (1 << 30) /* Bit 30: Owner */
|
||||
/* Bit 31: Reserved */
|
||||
|
||||
/* Debug USB PIDs Register. Paragraph C.3.2 */
|
||||
|
||||
#define ECHI_DEBUG_USBPIDS_TKPID_SHIFT (0) /* Bits 0-7: Token PID */
|
||||
#define ECHI_DEBUG_USBPIDS_TKPID_MASK (0xff << ECHI_DEBUG_USBPIDS_TKPID_SHIFT)
|
||||
#define ECHI_DEBUG_USBPIDS_SPID_SHIFT (8) /* Bits 8-15: Sent PID */
|
||||
#define ECHI_DEBUG_USBPIDS_SPID_MASK (0xff << ECHI_DEBUG_USBPIDS_SPID_SHIFT)
|
||||
#define ECHI_DEBUG_USBPIDS_RPID_SHIFT (16) /* Bits 16-23: Received PID */
|
||||
#define ECHI_DEBUG_USBPIDS_RPID_MASK (0xff << ECHI_DEBUG_USBPIDS_RPID_SHIFT)
|
||||
/* Bits 24-31: Reserved */
|
||||
|
||||
/* Debug Data Buffer 0/1 Register [64:0]. Paragreph C.3.3. 64 bits of data. */
|
||||
|
||||
/* Debug Device Address Register. Paragraph C.3.4 */
|
||||
|
||||
#define ECHI_DEBUG_DEVADDR_ENDPT_SHIFT (0) /* Bit 0-3: USB Endpoint */
|
||||
#define ECHI_DEBUG_DEVADDR_ENDPT_MASK (15 << ECHI_DEBUG_DEVADDR_ENDPT_SHIFT)
|
||||
/* Bits 4-7: Reserved */
|
||||
#define ECHI_DEBUG_DEVADDR_ADDR_SHIFT (8) /* Bits 8-14: USB Address */
|
||||
#define ECHI_DEBUG_DEVADDR_ADDR_MASK (0x7f << ECHI_DEBUG_DEVADDR_ADDR_SHIFT)
|
||||
/* Bits 15-31: Reserved */
|
||||
|
||||
/* Data Structures **************************************************************************/
|
||||
/* Paragraph 3 */
|
||||
|
||||
@ -755,6 +805,19 @@ struct ehci_hcor_s
|
||||
uint32_t portsc[15]; /* 0x44: Port Status/Control */
|
||||
};
|
||||
|
||||
/* USB2 Debug Port Register Interface. This register block is normally found via the PCI
|
||||
* capabalities. In non-PCI implementions, you need apriori information about the location
|
||||
* of these registers.
|
||||
*/
|
||||
|
||||
struct ehci_debug_s
|
||||
{
|
||||
uint32_t psc; /* 0x00: Debug Port Control/Status Register */
|
||||
uint32_t pids; /* 0x04: Debug USB PIDs Register */
|
||||
uint32_t data[2]; /* 0x08: Debug Data buffer Registers */
|
||||
uint32_t addr; /* 0x10: Device Address Register */
|
||||
};
|
||||
|
||||
/* Data Structures **************************************************************************/
|
||||
/* Paragraph 3 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user