USB Works

This commit is contained in:
codetector 2020-11-29 15:20:58 -05:00
parent 2e9d04fb80
commit f065a3bb2e
No known key found for this signature in database
GPG Key ID: 7D42AB4D2C7B40A4
9 changed files with 1183 additions and 38 deletions

View File

@ -1,4 +1,3 @@
/****************************************************************************************************//**
* @file LPC11Uxx.h
*
@ -492,43 +491,55 @@ typedef struct { /*!< (@ 0x40048000) SYSCON Structure
#define SYSCON_SYSPLLCTRL_PSEL_POS (5U)
#define SYSCON_SYSPLLCTRL_PSEL_MASK (0x03U << SYSPLLCTRL_PSEL_POS)
// SYSCON_SYSPLLSTAT
#define SYSCON_SYSPLLSTAT_LOCK 0x1
#define SYSCON_SYSPLLSTAT_LOCK 0x1U
// SYSCON_SYSPLLCLKSEL
#define SYSCON_SYSPLLCLKSEL_IRC (0x00U << 0)
#define SYSCON_SYSPLLCLKSEL_SYSOSC (0x01U << 0)
#define SYSCON_SYSPLLCLKUEN_ENA 0x01
#define SYSCON_SYSPLLCLKUEN_ENA 0x01U
#define SYSCON_USBPLLCLKSEL_IRC (0U << 0U)
#define SYSCON_USBPLLCLKSEL_SYSOSC (1U << 0U)
#define SYSCON_USBPLLCLKUEN_ENA 0x01U
#define SYSCON_MAINCLKSEL_IRC (0x00U << 0)
#define SYSCON_MAINCLKSEL_PLLIN (0x01U << 0)
#define SYSCON_MAINCLKSEL_WATCHDOG (0x02U << 0)
#define SYSCON_MAINCLKSEL_PLLOUT (0x03U << 0)
#define SYSCON_MAINCLKUEN_ENA 0x01
#define SYSCON_MAINCLKUEN_ENA 0x01U
#define SYSAHBCLKCTRL_SYS (1U << 0)
#define SYSAHBCLKCTRL_ROM (1U << 1)
#define SYSAHBCLKCTRL_RAM0 (1U << 2)
#define SYSAHBCLKCTRL_FLASHREG (1U << 3)
#define SYSAHBCLKCTRL_FLASHARRAY (1U << 4)
#define SYSAHBCLKCTRL_I2C (1U << 5)
#define SYSAHBCLKCTRL_GPIO (1U << 6)
#define SYSAHBCLKCTRL_CT16B0 (1U << 7)
#define SYSAHBCLKCTRL_CT16B1 (1U << 8)
#define SYSAHBCLKCTRL_CT32B0 (1U << 9)
#define SYSAHBCLKCTRL_CT32B1 (1U << 10)
#define SYSAHBCLKCTRL_SSP0 (1U << 11)
#define SYSAHBCLKCTRL_USART (1U << 12)
#define SYSAHBCLKCTRL_ADC (1U << 13)
#define SYSAHBCLKCTRL_USB (1U << 14)
#define SYSAHBCLKCTRL_WWDT (1U << 15)
#define SYSAHBCLKCTRL_IOCON (1U << 16)
#define SYSAHBCLKCTRL_SSP1 (1U << 18)
#define SYSAHBCLKCTRL_PINT (1U << 19)
#define SYSAHBCLKCTRL_GROUP0INT (1U << 23)
#define SYSAHBCLKCTRL_GROUP1INT (1U << 24)
#define SYSAHBCLKCTRL_RAM1 (1U << 26)
#define SYSAHBCLKCTRL_USBRAM (1U << 27)
#define SYSCON_SYSAHBCLKCTRL_SYS (1U << 0)
#define SYSCON_SYSAHBCLKCTRL_ROM (1U << 1)
#define SYSCON_SYSAHBCLKCTRL_RAM0 (1U << 2)
#define SYSCON_SYSAHBCLKCTRL_FLASHREG (1U << 3)
#define SYSCON_SYSAHBCLKCTRL_FLASHARRAY (1U << 4)
#define SYSCON_SYSAHBCLKCTRL_I2C (1U << 5)
#define SYSCON_SYSAHBCLKCTRL_GPIO (1U << 6)
#define SYSCON_SYSAHBCLKCTRL_CT16B0 (1U << 7)
#define SYSCON_SYSAHBCLKCTRL_CT16B1 (1U << 8)
#define SYSCON_SYSAHBCLKCTRL_CT32B0 (1U << 9)
#define SYSCON_SYSAHBCLKCTRL_CT32B1 (1U << 10)
#define SYSCON_SYSAHBCLKCTRL_SSP0 (1U << 11)
#define SYSCON_SYSAHBCLKCTRL_USART (1U << 12)
#define SYSCON_SYSAHBCLKCTRL_ADC (1U << 13)
#define SYSCON_SYSAHBCLKCTRL_USB (1U << 14)
#define SYSCON_SYSAHBCLKCTRL_WWDT (1U << 15)
#define SYSCON_SYSAHBCLKCTRL_IOCON (1U << 16)
#define SYSCON_SYSAHBCLKCTRL_SSP1 (1U << 18)
#define SYSCON_SYSAHBCLKCTRL_PINT (1U << 19)
#define SYSCON_SYSAHBCLKCTRL_GROUP0INT (1U << 23)
#define SYSCON_SYSAHBCLKCTRL_GROUP1INT (1U << 24)
#define SYSCON_SYSAHBCLKCTRL_RAM1 (1U << 26)
#define SYSCON_SYSAHBCLKCTRL_USBRAM (1U << 27)
#define SYSCON_USBCLKSEL_USBPLLOUT (0U << 0U)
#define SYSCON_USBCLKSEL_MAINCLK (1U << 0U)
#define SYSCON_USBCLKUEN_ENA 0x01U
#define SYSCON_USBCLKDIV_MASK
#define SYSCON_PDRUNCFG_IRCOUT_PD (1U << 0U)
#define SYSCON_PDRUNCFG_IRC_PD (1U << 1U)
@ -608,6 +619,38 @@ typedef struct { /*!< (@ 0x40080000) USB Structure
__I uint32_t EPTOGGLE; /*!< (@ 0x40080034) USB Endpoint toggle register */
} LPC_USB_Type;
#define USB_DEVCMDSTAT_DEVADDR_POS 0U
#define USB_DEVCMDSTAT_DEVADDR_MASK (0x7FU << USB_DEVCMDSTAT_DEVADDR_POS)
#define USB_DEVCMDSTAT_DEV_EN (1U << 7U)
#define USB_DEVCMDSTAT_SETUP (1U << 8U)
#define USB_DEVCMDSTAT_PLL_ON (1U << 9U)
#define USB_DEVCMDSTAT_LPM_SUP (1U << 11U)
#define USB_DEVCMDSTAT_INTONNAK_AO (1U << 12U)
#define USB_DEVCMDSTAT_INTONNAK_AI (1U << 13U)
#define USB_DEVCMDSTAT_INTONNAK_CO (1U << 14U)
#define USB_DEVCMDSTAT_INTONNAK_CI (1U << 15U)
#define USB_DEVCMDSTAT_DCON (1U << 16U)
#define USB_DEVCMDSTAT_DSUP (1U << 17U)
#define USB_DEVCMDSTAT_LPM_SUS (1U << 19U)
#define USB_DEVCMDSTAT_LPM_REWP (1U << 20U)
#define USB_DEVCMDSTAT_DCON_C (1U << 24U)
#define USB_DEVCMDSTAT_DSUS_C (1U << 25U)
#define USB_DEVCMDSTAT_DRES_C (1U << 26U)
#define USB_INFO_FRAME_NR_POS 0U
#define USB_INFO_FRAME_NR_MASK (0x7FFU << USB_INFO_FRAME_NR_POS)
#define USB_EPLISTSTART_POS (8U)
#define USB_EPLISTSTART_MASK (0xFFFFFF << USB_EPLISTSTART_POS)
#define USB_DATABUFSTART_POS (22U)
#define USB_DATABUFSTART_MASK (0x3FF << USB_DATABUFSTART_POS)
#define USB_INT_EPn_INT (1U)
#define USB_INT_EP(ep) (1U << (ep))
#define USB_INT_EP_ALL_INT (0x3FF)
#define USB_INT_FRAME_INT (1U << 30U)
#define USB_INT_DEV_INT (1U << 31U)
// ------------------------------------------------------------------------------------------------
// ----- GPIO_PORT -----

View File

@ -36,7 +36,7 @@ MEMORY {
flash5 : org = 0x00000000, len = 0
flash6 : org = 0x00000000, len = 0
flash7 : org = 0x00000000, len = 0
ram0 : org = 0x10000000, len = 8k
ram0 : org = 0x10000200, len = 7680
ram1 : org = 0x00000000, len = 0
ram2 : org = 0x00000000, len = 0
ram3 : org = 0x00000000, len = 0

View File

@ -57,7 +57,7 @@
*/
void _pal_lld_init(void) {
// Enable GPIO / IOCON CLK
LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_GPIO | SYSAHBCLKCTRL_IOCON;
LPC_SYSCON->SYSAHBCLKCTRL |= SYSCON_SYSAHBCLKCTRL_GPIO | SYSCON_SYSAHBCLKCTRL_IOCON;
}
/**
@ -94,12 +94,16 @@ void _pal_lld_setgroupmode(ioportid_t port,
* @notapi
*/
void _pal_lld_setpadmode(ioportid_t port, iopadid_t pad, iomode_t mode) {
((uint32_t *)LPC_IOCON)[(PAL_IOPORTS_WIDTH * LPC_IOPORT_NUM(port)) + pad]
= mode & MODE_IOCONF_MASK;
while (pad > 0x1F){}
uint32_t* base = (uint32_t*)0x40044000;
if (LPC_IOPORT_NUM(port) == 1) {
base = (uint32_t*)0x40044060;
}
base[pad & 0x1F] = (mode & MODE_IOCONF_MASK);
if (mode & MODE_DIR_MASK) {
LPC_GPIO->DIR[LPC_IOPORT_NUM(port)] |= 1U << pad;
LPC_GPIO->DIR[LPC_IOPORT_NUM(port)] |= (uint32_t) 1U << pad;
} else {
LPC_GPIO->DIR[LPC_IOPORT_NUM(port)] &= ~(1U << pad);
LPC_GPIO->DIR[LPC_IOPORT_NUM(port)] &= ~(((uint32_t)1U) << pad);
}
}

View File

@ -71,13 +71,13 @@
* @brief Decodes a port identifier from a line identifier.
*/
#define PAL_PORT(line) \
(((uint32_t)(line)) & 0xFFFFFFE0U)
(((uint32_t)(line)) & 0xFFFFFF00U)
/**
* @brief Decodes a pad identifier from a line identifier.
*/
#define PAL_PAD(line) \
(((uint32_t)(line) & 0x0000001FU))
(((uint32_t)(line) & 0x000000FFU))
/**
* @brief Value identifying an invalid line.
@ -128,11 +128,17 @@ typedef uint32_t iomode_t;
#define MODE_MODE_PULL_UP (0x2U << MODE_MODE_POS)
#define MODE_MODE_REPEATER (0x3U << MODE_MODE_POS)
#define MODE_AD_POS (7U)
#define MODE_AD_MASK (1U << MODE_AD_POS)
#define MODE_AD_ANALOG (0U << MODE_AD_POS)
#define MODE_AD_DIGITAL (1U << MODE_AD_POS)
#define MODE_DIR_POS 31U
#define MODE_DIR_MASK (0x1U << MODE_DIR_POS)
#define MODE_DIR_IN (0U << MODE_DIR_POS)
#define MODE_DIR_OUT (1U << MODE_DIR_POS)
/**
* @brief Type of an I/O line.
*/
@ -160,8 +166,8 @@ typedef uint32_t iopadid_t;
* @details Low level drivers can define multiple ports, it is suggested to
* use this naming convention.
*/
#define LPC_IOPORT_ID(x) (x << 5U)
#define LPC_IOPORT_NUM(x) (x >> 5U)
#define LPC_IOPORT_ID(x) ((x) << 8U)
#define LPC_IOPORT_NUM(x) ((x) >> 8U)
#define IOPORT0 LPC_IOPORT_ID(0)
#define IOPORT1 LPC_IOPORT_ID(1)
@ -379,5 +385,4 @@ extern "C" {
#endif /* HAL_USE_PAL == TRUE */
#endif /* HAL_PAL_LLD_H */
/** @} */

View File

@ -0,0 +1,5 @@
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/USB/hal_usb_lld.c
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/USB

View File

@ -0,0 +1,676 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_usb_lld.c
* @brief LPC11Uxx USB subsystem low level driver source.
*
* @addtogroup USB
* @{
*/
#include "hal.h"
#include <string.h>
#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#define roundup2(x, m) (((x) + (m) - 1) & ~((m) - 1))
#define LPC_USB_SRAM_START 0x20004000
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief USB- driver identifier.
*/
#if (LPC_USB_USE_USB1 == TRUE) || defined(__DOXYGEN__)
USBDriver USBD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief EP0 state.
* @note It is an union because IN and OUT endpoints are never used at the
* same time for EP0.
*/
static union {
/**
* @brief IN EP0 state.
*/
USBInEndpointState in;
/**
* @brief OUT EP0 state.
*/
USBOutEndpointState out;
} ep0_state;
/**
* @brief EP0 initialization structure.
*/
static const USBEndpointConfig ep0config = {
USB_EP_MODE_TYPE_CTRL,
_usb_ep0setup,
_usb_ep0in,
_usb_ep0out,
0x40,
0x40,
&ep0_state.in,
&ep0_state.out,
0,
NULL,
};
static struct {
uint32_t entry[20];
} *USB_EPLIST = (void*)LPC_USB_SRAM_START;
#define EPLIST_ENTRY_BUFFER_RSHIFT 6U
#define EPLIST_ENTRY_BUFFER_POS 0U
#define EPLIST_ENTRY_BUFFER_MASK (0xFFFF << EPLIST_ENTRY_BUFFER_POS)
#define EPLIST_ADDR(ADDR) \
((((uint32_t)(ADDR)) >> EPLIST_ENTRY_BUFFER_RSHIFT) & EPLIST_ENTRY_BUFFER_MASK)
#define EPLIST_ENTRY_NBYTES_POS 16U
#define EPLIST_ENTRY_NBYTES_MASK (0x3FF << EPLIST_ENTRY_NBYTES_POS)
#define EPLIST_ENTRY_NBYTES(BYTES) \
(((BYTES) << EPLIST_ENTRY_NBYTES_POS) & EPLIST_ENTRY_NBYTES_MASK)
#define EPLIST_ENTRY_ACTIVE (1U << 31U)
#define EPLIST_ENTRY_DISABLE (1U << 30U)
#define EPLIST_ENTRY_STALL (1U << 29U)
#define EPLIST_ENTRY_TOGGLE_RESET (1U << 28U)
#define EPLIST_ENTRY_RFTV (1U << 27U)
#define EPLIST_ENTRY_EPTYPE (1U << 26U)
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static size_t usb_ep_malloc(USBDriver *usbp, size_t size, size_t alignment) {
size_t current = usbp->epmem_next;
if ((current & (alignment - 1)) != 0) { // Alignment issue
current = (current + alignment) & (~(alignment - 1));
}
const size_t epmo = current;
usbp->epmem_next = current + size;
osalDbgAssert(usbp->epmem_next <= (LPC_USB_SRAM_START + 0x800), "UBSSRAM exhausted");
return epmo;
}
static void usb_packet_transmit(USBDriver *usbp, usbep_t ep, size_t n)
{
const USBEndpointConfig * const epc = usbp->epc[ep];
USBInEndpointState * const isp = epc->in_state;
if (n > epc->in_maxsize) {
n = epc->in_maxsize;
}
if (ep == 0) {
// When EP0 IN is received, set ACTIVE bit on both EP0 IN
// and OUT.
USB_EPLIST->entry[0] |= EPLIST_ENTRY_ACTIVE;
}
/* Get EP command/status List, update the length field and data pointer. */
USB_EPLIST->entry[ep * 4 + 2] &= ~0x3FFFFFF;
USB_EPLIST->entry[ep * 4 + 2] |= EPLIST_ENTRY_NBYTES(n) |
EPLIST_ADDR(usbp->epn_buffer[ep * 2 + 1]);
if (n > 0)
memcpy(usbp->epn_buffer[ep*2 + 1], isp->txbuf, n);
isp->txlastpktlen = n;
USB_EPLIST->entry[ep * 4 + 2] |= EPLIST_ENTRY_ACTIVE;
}
static size_t usb_packet_receive(USBDriver *usbp, usbep_t ep) {
const USBEndpointConfig *epcp = usbp->epc[ep];
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
uint32_t n = (USB_EPLIST->entry[4 * ep] & EPLIST_ENTRY_NBYTES_MASK) >> EPLIST_ENTRY_NBYTES_POS;
n = epcp->out_maxsize - n;
if (osp->rxbuf != NULL && n > 0) {
memcpy(osp->rxbuf, usbp->epn_buffer[ep * 2], n);
osp->rxbuf += n;
}
// ReSetup for recieve
USB_EPLIST->entry[4 * ep] &= ~0x3FFFFFF;
USB_EPLIST->entry[4 * ep] |= EPLIST_ENTRY_NBYTES(epcp->out_maxsize) |
EPLIST_ADDR(usbp->epn_buffer[ep * 2]);
if (osp->rxpkts > 0)
osp->rxpkts -= 1;
osp->rxcnt += n;
osp->rxsize -= n;
return n;
}
/*===========================================================================*/
/* Driver interrupt handlers and threads. */
/*===========================================================================*/
#ifndef LPC_USB_IRQ_VECTOR
#error "LPC_USB_IRQ_VECTOR not defined"
#endif
OSAL_IRQ_HANDLER(LPC_USB_IRQ_VECTOR) {
OSAL_IRQ_PROLOGUE();
USBDriver *usbp = &USBD1;
uint32_t isr = LPC_USB->INTSTAT;
#define devstat (LPC_USB->DEVCMDSTAT)
LPC_USB->INTSTAT &= 0xFFFFFFFF; // Clear Flags
// SOF
if (isr & USB_INT_FRAME_INT) {
_usb_isr_invoke_sof_cb(usbp);
}
if (isr & USB_INT_DEV_INT) {
if (devstat & USB_DEVCMDSTAT_DSUS_C) {
if (devstat & USB_DEVCMDSTAT_DCON) {
if (devstat & USB_DEVCMDSTAT_DSUP) {
// Suspend
_usb_suspend(usbp);
} else {
// Wakeup
_usb_wakeup(usbp);
}
}
}
if (devstat & USB_DEVCMDSTAT_DRES_C) {
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_DRES_C;
_usb_reset(usbp);
}
} // USB_INT_DEV_INT
for (int ep = 0; ep < 5; ++ep)
{
// EP0 OUT (Setup)
if (isr & (USB_INT_EPn_INT << (2 * ep))) {
if (devstat & USB_DEVCMDSTAT_SETUP) {
_usb_isr_invoke_setup_cb(usbp, ep);
} else {
// OUT endpoint, receive
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
osalSysLockFromISR();
size_t n = usb_packet_receive(usbp, ep);
osalSysUnlockFromISR();
if ((n < usbp->epc[0]->out_maxsize) || (osp->rxpkts == 0)) {
_usb_isr_invoke_out_cb(usbp, ep);
} else {
USB_EPLIST->entry[4 * ep] |= EPLIST_ENTRY_ACTIVE;
}
}
}
// EP0 IN
if (isr & (USB_INT_EPn_INT << (2 * ep + 1))) {
USBInEndpointState *isp = usbp->epc[ep]->in_state;
size_t n = isp->txlastpktlen;
isp->txcnt += n;
if (isp->txcnt < isp->txsize) {
isp->txbuf += n;
osalSysLockFromISR();
usb_packet_transmit(usbp, ep, isp->txsize - isp->txcnt);
osalSysUnlockFromISR();
} else {
// IN callback
_usb_isr_invoke_in_cb(usbp, ep);
}
}
}
OSAL_IRQ_EPILOGUE();
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level USB driver initialization.
*
* @notapi
*/
void usb_lld_init(void) {
#if LPC_USB_USE_USB1 == TRUE
/* Driver initialization.*/
usbObjectInit(&USBD1);
// Enable Clock
LPC_SYSCON->SYSAHBCLKCTRL |=
(
SYSCON_SYSAHBCLKCTRL_USB | SYSCON_SYSAHBCLKCTRL_USBRAM |
SYSCON_SYSAHBCLKCTRL_RAM0
);
USBD1.epmem_next = (0x50 + LPC_USB_SRAM_START);
#if defined(LPC_MAINCLK_FREQUENCY) && LPC_MAINCLK_FREQUENCY == 48000000U
// TODO: Implement proper PLL support
LPC_SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_USBPLL_PD;
LPC_SYSCON->USBPLLCLKSEL = SYSCON_USBPLLCLKSEL_SYSOSC;
LPC_SYSCON->USBPLLCLKUEN = 0;
LPC_SYSCON->USBPLLCLKUEN = SYSCON_USBPLLCLKUEN_ENA;
LPC_SYSCON->USBPLLCTRL = LPC_SYSCON->SYSPLLCTRL; // BIG HACK. Steal Main PLL CFG
while(LPC_SYSCON->USBPLLSTAT == 0){}
LPC_SYSCON->USBCLKSEL = SYSCON_USBCLKSEL_USBPLLOUT;
LPC_SYSCON->USBCLKDIV = 1; // Divide By 1
#else // LPC_MAINCLK_FREQUENCY
#error "USB Currently requires LPC_MAINCLK_FREQUENCY = 48MHz"
#endif // LPC_MAINCLK_FREQUENCY
#endif // LPC_USB_USE_USB1 == TRUE
}
/**
* @brief Configures and activates the USB peripheral.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_start(USBDriver *usbp) {
if (usbp->state == USB_STOP) {
/* Enables the peripheral.*/
#if LPC_USB_USE_USB1 == TRUE
if (&USBD1 == usbp) {
// USB Transiver Powerup
LPC_SYSCON->PDRUNCFG &= ~SYSCON_PDRUNCFG_USBPAD_PD;
// Enable Vector
#if !defined(LPC_USB_USB1_IRQ_PRIORITY)
#error "LPC_USB_USB1_IRQ_PRIORITY is not defined"
#endif
nvicEnableVector(USB_IRQn, LPC_USB_USB1_IRQ_PRIORITY);
}
#endif
usb_lld_reset(usbp);
}
/* Configures the peripheral.*/
}
/**
* @brief Deactivates the USB peripheral.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_stop(USBDriver *usbp) {
if (usbp->state == USB_READY) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if LPC_USB_USE_USB1 == TRUE
if (&USBD1 == usbp) {
nvicDisableVector(USB_IRQn);
LPC_USB->INTEN = 0;
LPC_SYSCON->PDRUNCFG |= SYSCON_PDRUNCFG_USBPAD_PD;
LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_DEV_EN;
}
#endif
}
}
/**
* @brief USB low level reset routine.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_reset(USBDriver *usbp) {
/* Post reset initialization.*/
// cfg Interrupt routing to IRQ
LPC_USB->INTROUTING = 0;
LPC_USB->EPINUSE = 0;
LPC_USB->EPSKIP = 0;
LPC_USB->EPBUFCFG = 0;
// Points USB Buffers to correct places
LPC_USB->EPLISTSTART = LPC_USB_SRAM_START & USB_EPLISTSTART_MASK;
LPC_USB->DATABUFSTART = LPC_USB_SRAM_START & USB_DATABUFSTART_MASK;
// Clear Existing Interrupts
LPC_USB->INTSTAT = USB_INT_DEV_INT | USB_INT_FRAME_INT | USB_INT_EP_ALL_INT;
// Setup Interrupt Masks
LPC_USB->INTEN = USB_INT_DEV_INT | USB_INT_EP_ALL_INT;
// SOF only if there is a handler registered.
if ((usbp)->config->sof_cb != NULL) {
LPC_USB->INTEN |= USB_INT_FRAME_INT;
}
// Reset Allocator
usbp->epmem_next = (0x50 + LPC_USB_SRAM_START);
usbp->setup_buffer = NULL;
for (int i = 0; i < 10; ++i)
{
usbp->epn_buffer[i] = NULL;
}
// Disable all endpoints
for (int i = 0; i < 16; ++i)
{
USB_EPLIST->entry[i + 4] = EPLIST_ENTRY_DISABLE;
}
/* EP0 initialization.*/
usbp->epc[0] = &ep0config;
usb_lld_init_endpoint(usbp, 0);
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_DEV_EN; // USB Start Running
}
/**
* @brief Sets the USB address.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_set_address(USBDriver *usbp) {
LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_DEVADDR_MASK;
LPC_USB->DEVCMDSTAT |= (USB_DEVCMDSTAT_DEV_EN |
(usbp->address & USB_DEVCMDSTAT_DEVADDR_MASK));
}
/**
* @brief Enables an endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
if(ep > USB_MAX_ENDPOINTS)
return;
const USBEndpointConfig *epcp = usbp->epc[ep];
uint32_t usbep_cfg = 0;
switch(epcp->ep_mode & USB_EP_MODE_TYPE) {
case USB_EP_MODE_TYPE_CTRL:
break;
case USB_EP_MODE_TYPE_ISOC:
usbep_cfg |= EPLIST_ENTRY_EPTYPE;
break;
case USB_EP_MODE_TYPE_BULK:
break;
case USB_EP_MODE_TYPE_INTR:
break;
default:
while(1) {}
}
if (epcp->out_state != NULL) {
while(epcp->out_maxsize > 1023);
uint32_t ep_mem = usb_ep_malloc(usbp, epcp->out_maxsize, 64);
usbp->epn_buffer[(2 * ep)] = (void *)ep_mem;
USB_EPLIST->entry[(4 * ep)] = usbep_cfg | EPLIST_ADDR(ep_mem)
| EPLIST_ENTRY_NBYTES(epcp->out_maxsize);
}
if (ep == 0) {
while(usbp->setup_buffer != NULL){}
// Allocate Setup Bytes
uint32_t ep_mem = usb_ep_malloc(usbp, 8, 64);
usbp->setup_buffer = (void *)ep_mem;
USB_EPLIST->entry[1] = EPLIST_ADDR(ep_mem);
LPC_USB->INTEN |= USB_INT_EP(ep * 2);
}
if (epcp->in_state != NULL) {
while(epcp->in_maxsize > 1023);
uint32_t ep_mem = usb_ep_malloc(usbp, epcp->in_maxsize, 64);
usbp->epn_buffer[(2 * ep) + 1] = (void *)ep_mem;
USB_EPLIST->entry[(4 * ep) + 2] = usbep_cfg | EPLIST_ADDR(ep_mem)
| EPLIST_ENTRY_NBYTES(epcp->in_maxsize);
LPC_USB->INTEN |= USB_INT_EP((ep * 2) + 1);
}
}
/**
* @brief Disables all the active endpoints except the endpoint zero.
*
* @param[in] usbp pointer to the @p USBDriver object
*
* @notapi
*/
void usb_lld_disable_endpoints(USBDriver *usbp) {
if (usbp != &USBD1)
return;
LPC_USB->EPSKIP = 0xFFFFFFFF;
LPC_USB->INTEN &= (~USB_INT_EP_ALL_INT) | USB_INT_EP(0) | USB_INT_EP(1);
while (LPC_USB->EPSKIP) {}
for (int i = 1; i < 5; ++i) // 4 EPs needs to be disabled, EP0 can't
{
USB_EPLIST->entry[i * 2] &= ~EP_STATUS_ACTIVE;
USB_EPLIST->entry[i * 2] |= EP_STATUS_DISABLED;
USB_EPLIST->entry[i * 2 + 2] &= ~EP_STATUS_ACTIVE;
USB_EPLIST->entry[i * 2 + 2] |= EP_STATUS_DISABLED;
}
}
/**
* @brief Returns the status of an OUT endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @return The endpoint status.
* @retval EP_STATUS_DISABLED The endpoint is not active.
* @retval EP_STATUS_STALLED The endpoint is stalled.
* @retval EP_STATUS_ACTIVE The endpoint is active.
*
* @notapi
*/
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return EP_STATUS_DISABLED;
if (USB_EPLIST->entry[ep * 2] & EPLIST_ENTRY_DISABLE) {
return EP_STATUS_DISABLED;
} else if (USB_EPLIST->entry[ep * 2] & EPLIST_ENTRY_STALL) {
return EP_STATUS_STALLED;
} else {
return EP_STATUS_ACTIVE;
}
}
/**
* @brief Returns the status of an IN endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @return The endpoint status.
* @retval EP_STATUS_DISABLED The endpoint is not active.
* @retval EP_STATUS_STALLED The endpoint is stalled.
* @retval EP_STATUS_ACTIVE The endpoint is active.
*
* @notapi
*/
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return EP_STATUS_DISABLED;
if (USB_EPLIST->entry[ep * 2 + 2] & EPLIST_ENTRY_DISABLE) {
return EP_STATUS_DISABLED;
} else if (USB_EPLIST->entry[ep * 2 + 2] & EPLIST_ENTRY_STALL) {
return EP_STATUS_STALLED;
} else {
return EP_STATUS_ACTIVE;
}
}
/**
* @brief Reads a setup packet from the dedicated packet buffer.
* @details This function must be invoked in the context of the @p setup_cb
* callback in order to read the received setup packet.
* @pre In order to use this function the endpoint must have been
* initialized as a control endpoint.
* @post The endpoint is ready to accept another packet.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @param[out] buf buffer where to copy the packet data
*
* @notapi
*/
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
if (usbp == &USBD1) {
if (ep == 0) {
while(usbp->setup_buffer == 0){}
/* Check/Clear STALL on both EP0 IN and OUT when SETUP is received. */
USB_EPLIST->entry[0] &= ~(EPLIST_ENTRY_STALL | EPLIST_ENTRY_ACTIVE); // EP0OUT
USB_EPLIST->entry[2] &= ~(EPLIST_ENTRY_STALL | EPLIST_ENTRY_ACTIVE); // EP0IN
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_SETUP; // Clear SETUP
LPC_USB->DEVCMDSTAT &= ~(USB_DEVCMDSTAT_INTONNAK_CO | USB_DEVCMDSTAT_INTONNAK_CI);
memcpy(buf, usbp->setup_buffer, 8);
USB_EPLIST->entry[1] = EPLIST_ADDR(usbp->setup_buffer);
} else {
while(1){}
}
}
}
/**
* @brief Starts a receive operation on an OUT endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
const USBEndpointConfig *epcp = usbp->epc[ep];
if (osp->rxsize == 0) /* Special case for zero sized packets.*/
osp->rxpkts = 1;
else
osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
usbp->epc[ep]->out_maxsize);
USB_EPLIST->entry[ep * 4] &= ~0x3FFFFFF;
USB_EPLIST->entry[ep * 4] |= EPLIST_ENTRY_ACTIVE |
EPLIST_ENTRY_NBYTES(epcp->out_maxsize) |
EPLIST_ADDR(usbp->epn_buffer[ep * 2]);
LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_INTONNAK_CO;
LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_INTONNAK_CI;
}
/**
* @brief Starts a transmit operation on an IN endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
USBInEndpointState * const isp = usbp->epc[ep]->in_state;
usb_packet_transmit(usbp, ep, isp->txsize);
}
/**
* @brief Brings an OUT endpoint in the stalled state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return;
const uint32_t skip_flag = 1U << (ep * 2);
if (USB_EPLIST->entry[ep * 4] & EPLIST_ENTRY_ACTIVE) {
LPC_USB->EPSKIP = skip_flag;
}
while(LPC_USB->EPSKIP & skip_flag) {} // Wait for not active
USB_EPLIST->entry[ep*4] |= EPLIST_ENTRY_STALL;
}
/**
* @brief Brings an IN endpoint in the stalled state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return;
const uint32_t skip_flag = 1U << (ep * 2 + 1);
if (USB_EPLIST->entry[ep * 4 + 2] & EPLIST_ENTRY_ACTIVE) {
LPC_USB->EPSKIP = skip_flag;
}
while(LPC_USB->EPSKIP & skip_flag) {} // Wait for not active
USB_EPLIST->entry[ep * 4 + 2] |= EPLIST_ENTRY_STALL;
}
/**
* @brief Brings an OUT endpoint in the active state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return;
const uint32_t skip_flag = 1U << (ep * 2);
if (USB_EPLIST->entry[ep * 4] & EPLIST_ENTRY_ACTIVE) {
LPC_USB->EPSKIP = skip_flag;
}
while(LPC_USB->EPSKIP & skip_flag) {} // Wait for not active
USB_EPLIST->entry[ep*4] &= ~EPLIST_ENTRY_STALL;
}
/**
* @brief Brings an IN endpoint in the active state.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) {
if (usbp != &USBD1)
return;
const uint32_t skip_flag = 1U << (ep * 2 + 1);
if (USB_EPLIST->entry[ep * 4 + 2] & EPLIST_ENTRY_ACTIVE) {
LPC_USB->EPSKIP = skip_flag;
}
while(LPC_USB->EPSKIP & skip_flag) {} // Wait for not active
USB_EPLIST->entry[ep * 4 + 2] &= ~EPLIST_ENTRY_STALL;
}
#endif /* HAL_USE_USB == TRUE */
/** @} */

View File

@ -0,0 +1,408 @@
/*
ChibiOS - Copyright (C) 2020 Yaotian Feng / Codetector
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_usb_lld.h
* @brief LPC11Uxx USB subsystem low level driver header.
*
* @addtogroup USB
* @{
*/
#ifndef HAL_USB_LLD_H
#define HAL_USB_LLD_H
#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Maximum endpoint address.
*/
#define USB_MAX_ENDPOINTS 5
/**
* @brief Status stage handling method.
*/
#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW
/**
* @brief The address can be changed immediately upon packet reception.
*/
#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS
/**
* @brief Method for set address acknowledge.
*/
#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name PLC11Uxx configuration options
* @{
*/
/**
* @brief USB driver enable switch.
* @details If set to @p TRUE the support for USB0 is included.
* @note The default is @p FALSE.
*/
#if !defined(LPC_USB_USE_USB1) || defined(__DOXYGEN__)
#define LPC_USB_USE_USB1 FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type of an IN endpoint state structure.
*/
typedef struct {
/**
* @brief Requested transmit transfer size.
*/
size_t txsize;
/**
* @brief Transmitted bytes so far.
*/
size_t txcnt;
/**
* @brief Pointer to the transmission linear buffer.
*/
const uint8_t *txbuf;
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Waiting thread.
*/
thread_reference_t thread;
#endif
/* End of the mandatory fields.*/
uint16_t txlastpktlen;
} USBInEndpointState;
/**
* @brief Type of an OUT endpoint state structure.
*/
typedef struct {
/**
* @brief Requested receive transfer size.
*/
size_t rxsize;
/**
* @brief Received bytes so far.
*/
size_t rxcnt;
/**
* @brief Pointer to the receive linear buffer.
*/
uint8_t *rxbuf;
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Waiting thread.
*/
thread_reference_t thread;
#endif
/* End of the mandatory fields.*/
uint16_t rxpkts;
} USBOutEndpointState;
/**
* @brief Type of an USB endpoint configuration structure.
* @note Platform specific restrictions may apply to endpoints.
*/
typedef struct {
/**
* @brief Type and mode of the endpoint.
*/
uint32_t ep_mode;
/**
* @brief Setup packet notification callback.
* @details This callback is invoked when a setup packet has been
* received.
* @post The application must immediately call @p usbReadPacket() in
* order to access the received packet.
* @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL
* endpoints, it should be set to @p NULL for other endpoint
* types.
*/
usbepcallback_t setup_cb;
/**
* @brief IN endpoint notification callback.
* @details This field must be set to @p NULL if the IN endpoint is not
* used.
*/
usbepcallback_t in_cb;
/**
* @brief OUT endpoint notification callback.
* @details This field must be set to @p NULL if the OUT endpoint is not
* used.
*/
usbepcallback_t out_cb;
/**
* @brief IN endpoint maximum packet size.
* @details This field must be set to zero if the IN endpoint is not
* used.
*/
uint16_t in_maxsize;
/**
* @brief OUT endpoint maximum packet size.
* @details This field must be set to zero if the OUT endpoint is not
* used.
*/
uint16_t out_maxsize;
/**
* @brief @p USBEndpointState associated to the IN endpoint.
* @details This structure maintains the state of the IN endpoint.
*/
USBInEndpointState *in_state;
/**
* @brief @p USBEndpointState associated to the OUT endpoint.
* @details This structure maintains the state of the OUT endpoint.
*/
USBOutEndpointState *out_state;
/* End of the mandatory fields.*/
/**
* @brief Reserved field, not currently used.
* @note Initialize this field to 1 in order to be forward compatible.
*/
uint16_t ep_buffers;
/**
* @brief Pointer to a buffer for setup packets.
* @details Setup packets require a dedicated 8-bytes buffer, set this
* field to @p NULL for non-control endpoints.
*/
uint8_t *setup_buf;
} USBEndpointConfig;
/**
* @brief Type of an USB driver configuration structure.
*/
typedef struct {
/**
* @brief USB events callback.
* @details This callback is invoked when an USB driver event is registered.
*/
usbeventcb_t event_cb;
/**
* @brief Device GET_DESCRIPTOR request callback.
* @note This callback is mandatory and cannot be set to @p NULL.
*/
usbgetdescriptor_t get_descriptor_cb;
/**
* @brief Requests hook callback.
* @details This hook allows to be notified of standard requests or to
* handle non standard requests.
*/
usbreqhandler_t requests_hook_cb;
/**
* @brief Start Of Frame callback.
*/
usbcallback_t sof_cb;
/* End of the mandatory fields.*/
} USBConfig;
/**
* @brief Structure representing an USB driver.
*/
struct USBDriver {
/**
* @brief Driver state.
*/
usbstate_t state;
/**
* @brief Current configuration data.
*/
const USBConfig *config;
/**
* @brief Bit map of the transmitting IN endpoints.
*/
uint16_t transmitting;
/**
* @brief Bit map of the receiving OUT endpoints.
*/
uint16_t receiving;
/**
* @brief Active endpoints configurations.
*/
const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1];
/**
* @brief Fields available to user, it can be used to associate an
* application-defined handler to an IN endpoint.
* @note The base index is one, the endpoint zero does not have a
* reserved element in this array.
*/
void *in_params[USB_MAX_ENDPOINTS];
/**
* @brief Fields available to user, it can be used to associate an
* application-defined handler to an OUT endpoint.
* @note The base index is one, the endpoint zero does not have a
* reserved element in this array.
*/
void *out_params[USB_MAX_ENDPOINTS];
/**
* @brief Endpoint 0 state.
*/
usbep0state_t ep0state;
/**
* @brief Next position in the buffer to be transferred through endpoint 0.
*/
uint8_t *ep0next;
/**
* @brief Number of bytes yet to be transferred through endpoint 0.
*/
size_t ep0n;
/**
* @brief Endpoint 0 end transaction callback.
*/
usbcallback_t ep0endcb;
/**
* @brief Setup packet buffer.
*/
uint8_t setup[8];
/**
* @brief Current USB device status.
*/
uint16_t status;
/**
* @brief Assigned USB address.
*/
uint8_t address;
/**
* @brief Current USB device configuration.
*/
uint8_t configuration;
/**
* @brief State of the driver when a suspend happened.
*/
usbstate_t saved_state;
#if defined(USB_DRIVER_EXT_FIELDS)
USB_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
/**
* @brief Offset of the next chunk of usb_ep_malloc
*/
size_t epmem_next;
void* setup_buffer;
void* epn_buffer[10]; // OUT = 2n, IN = 2n +1
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Returns the current frame number.
*
* @param[in] usbp pointer to the @p USBDriver object
* @return The current frame number.
*
* @notapi
*/
#define usb_lld_get_frame_number(usbp) \
((LPC_USB->INFO & USB_INFO_FRAME_NR_MASK) >> USB_INFO_FRAME_NR_POS)
/**
* @brief Returns the exact size of a receive transaction.
* @details The received size can be different from the size specified in
* @p usbStartReceiveI() because the last packet could have a size
* different from the expected one.
* @pre The OUT endpoint must have been configured in transaction mode
* in order to use this function.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @return Received data size.
*
* @notapi
*/
#define usb_lld_get_transaction_size(usbp, ep) \
((usbp)->epc[ep]->out_state->rxcnt)
/**
* @brief Connects the USB device.
*
* @api
*/
#define usb_lld_connect_bus(usbp) \
(LPC_USB->DEVCMDSTAT |= USB_DEVCMDSTAT_DCON)
/**
* @brief Disconnect the USB device.
*
* @api
*/
#define usb_lld_disconnect_bus(usbp) \
(LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_DCON)
/**
* @brief Start of host wake-up procedure.
*
* @notapi
*/
#define usb_lld_wakeup_host(usbp) \
(LPC_USB->DEVCMDSTAT &= ~USB_DEVCMDSTAT_DSUP)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (LPC_USB_USE_USB1 == TRUE) && !defined(__DOXYGEN__)
extern USBDriver USBD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void usb_lld_init(void);
void usb_lld_start(USBDriver *usbp);
void usb_lld_stop(USBDriver *usbp);
void usb_lld_reset(USBDriver *usbp);
void usb_lld_set_address(USBDriver *usbp);
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep);
void usb_lld_disable_endpoints(USBDriver *usbp);
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep);
void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep);
void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep);
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_USB == TRUE */
#endif /* HAL_USB_LLD_H */
/** @} */

View File

@ -37,6 +37,9 @@ defined(__DOXYGEN__)
#if defined(LPC11Uxx) || defined(__DOXYGEN__)
/* USB attributes.*/
#define LPC_HAS_USB TRUE
#define LPC_USB_IRQ_VECTOR Vector98
#endif

View File

@ -8,6 +8,7 @@ PLATFORMINC = ${CHIBIOS}/os/hal/ports/common/ARMCMx \
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/STM/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/GPIO/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/USB/driver.mk
# Shared variables
ALLCSRC += $(PLATFORMSRC)