USB Works
This commit is contained in:
parent
4e5d4015b8
commit
9f194d72dc
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/****************************************************************************************************//**
|
/****************************************************************************************************//**
|
||||||
* @file LPC11Uxx.h
|
* @file LPC11Uxx.h
|
||||||
*
|
*
|
||||||
|
@ -492,43 +491,55 @@ typedef struct { /*!< (@ 0x40048000) SYSCON Structure
|
||||||
#define SYSCON_SYSPLLCTRL_PSEL_POS (5U)
|
#define SYSCON_SYSPLLCTRL_PSEL_POS (5U)
|
||||||
#define SYSCON_SYSPLLCTRL_PSEL_MASK (0x03U << SYSPLLCTRL_PSEL_POS)
|
#define SYSCON_SYSPLLCTRL_PSEL_MASK (0x03U << SYSPLLCTRL_PSEL_POS)
|
||||||
// SYSCON_SYSPLLSTAT
|
// SYSCON_SYSPLLSTAT
|
||||||
#define SYSCON_SYSPLLSTAT_LOCK 0x1
|
#define SYSCON_SYSPLLSTAT_LOCK 0x1U
|
||||||
// SYSCON_SYSPLLCLKSEL
|
// SYSCON_SYSPLLCLKSEL
|
||||||
#define SYSCON_SYSPLLCLKSEL_IRC (0x00U << 0)
|
#define SYSCON_SYSPLLCLKSEL_IRC (0x00U << 0)
|
||||||
#define SYSCON_SYSPLLCLKSEL_SYSOSC (0x01U << 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_IRC (0x00U << 0)
|
||||||
#define SYSCON_MAINCLKSEL_PLLIN (0x01U << 0)
|
#define SYSCON_MAINCLKSEL_PLLIN (0x01U << 0)
|
||||||
#define SYSCON_MAINCLKSEL_WATCHDOG (0x02U << 0)
|
#define SYSCON_MAINCLKSEL_WATCHDOG (0x02U << 0)
|
||||||
#define SYSCON_MAINCLKSEL_PLLOUT (0x03U << 0)
|
#define SYSCON_MAINCLKSEL_PLLOUT (0x03U << 0)
|
||||||
|
|
||||||
#define SYSCON_MAINCLKUEN_ENA 0x01
|
#define SYSCON_MAINCLKUEN_ENA 0x01U
|
||||||
|
|
||||||
#define SYSAHBCLKCTRL_SYS (1U << 0)
|
#define SYSCON_SYSAHBCLKCTRL_SYS (1U << 0)
|
||||||
#define SYSAHBCLKCTRL_ROM (1U << 1)
|
#define SYSCON_SYSAHBCLKCTRL_ROM (1U << 1)
|
||||||
#define SYSAHBCLKCTRL_RAM0 (1U << 2)
|
#define SYSCON_SYSAHBCLKCTRL_RAM0 (1U << 2)
|
||||||
#define SYSAHBCLKCTRL_FLASHREG (1U << 3)
|
#define SYSCON_SYSAHBCLKCTRL_FLASHREG (1U << 3)
|
||||||
#define SYSAHBCLKCTRL_FLASHARRAY (1U << 4)
|
#define SYSCON_SYSAHBCLKCTRL_FLASHARRAY (1U << 4)
|
||||||
#define SYSAHBCLKCTRL_I2C (1U << 5)
|
#define SYSCON_SYSAHBCLKCTRL_I2C (1U << 5)
|
||||||
#define SYSAHBCLKCTRL_GPIO (1U << 6)
|
#define SYSCON_SYSAHBCLKCTRL_GPIO (1U << 6)
|
||||||
#define SYSAHBCLKCTRL_CT16B0 (1U << 7)
|
#define SYSCON_SYSAHBCLKCTRL_CT16B0 (1U << 7)
|
||||||
#define SYSAHBCLKCTRL_CT16B1 (1U << 8)
|
#define SYSCON_SYSAHBCLKCTRL_CT16B1 (1U << 8)
|
||||||
#define SYSAHBCLKCTRL_CT32B0 (1U << 9)
|
#define SYSCON_SYSAHBCLKCTRL_CT32B0 (1U << 9)
|
||||||
#define SYSAHBCLKCTRL_CT32B1 (1U << 10)
|
#define SYSCON_SYSAHBCLKCTRL_CT32B1 (1U << 10)
|
||||||
#define SYSAHBCLKCTRL_SSP0 (1U << 11)
|
#define SYSCON_SYSAHBCLKCTRL_SSP0 (1U << 11)
|
||||||
#define SYSAHBCLKCTRL_USART (1U << 12)
|
#define SYSCON_SYSAHBCLKCTRL_USART (1U << 12)
|
||||||
#define SYSAHBCLKCTRL_ADC (1U << 13)
|
#define SYSCON_SYSAHBCLKCTRL_ADC (1U << 13)
|
||||||
#define SYSAHBCLKCTRL_USB (1U << 14)
|
#define SYSCON_SYSAHBCLKCTRL_USB (1U << 14)
|
||||||
#define SYSAHBCLKCTRL_WWDT (1U << 15)
|
#define SYSCON_SYSAHBCLKCTRL_WWDT (1U << 15)
|
||||||
#define SYSAHBCLKCTRL_IOCON (1U << 16)
|
#define SYSCON_SYSAHBCLKCTRL_IOCON (1U << 16)
|
||||||
#define SYSAHBCLKCTRL_SSP1 (1U << 18)
|
#define SYSCON_SYSAHBCLKCTRL_SSP1 (1U << 18)
|
||||||
#define SYSAHBCLKCTRL_PINT (1U << 19)
|
#define SYSCON_SYSAHBCLKCTRL_PINT (1U << 19)
|
||||||
#define SYSAHBCLKCTRL_GROUP0INT (1U << 23)
|
#define SYSCON_SYSAHBCLKCTRL_GROUP0INT (1U << 23)
|
||||||
#define SYSAHBCLKCTRL_GROUP1INT (1U << 24)
|
#define SYSCON_SYSAHBCLKCTRL_GROUP1INT (1U << 24)
|
||||||
#define SYSAHBCLKCTRL_RAM1 (1U << 26)
|
#define SYSCON_SYSAHBCLKCTRL_RAM1 (1U << 26)
|
||||||
#define SYSAHBCLKCTRL_USBRAM (1U << 27)
|
#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_IRCOUT_PD (1U << 0U)
|
||||||
#define SYSCON_PDRUNCFG_IRC_PD (1U << 1U)
|
#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 */
|
__I uint32_t EPTOGGLE; /*!< (@ 0x40080034) USB Endpoint toggle register */
|
||||||
} LPC_USB_Type;
|
} 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 -----
|
// ----- GPIO_PORT -----
|
||||||
|
|
|
@ -36,7 +36,7 @@ MEMORY {
|
||||||
flash5 : org = 0x00000000, len = 0
|
flash5 : org = 0x00000000, len = 0
|
||||||
flash6 : org = 0x00000000, len = 0
|
flash6 : org = 0x00000000, len = 0
|
||||||
flash7 : org = 0x00000000, len = 0
|
flash7 : org = 0x00000000, len = 0
|
||||||
ram0 : org = 0x10000000, len = 8k
|
ram0 : org = 0x10000200, len = 7680
|
||||||
ram1 : org = 0x00000000, len = 0
|
ram1 : org = 0x00000000, len = 0
|
||||||
ram2 : org = 0x00000000, len = 0
|
ram2 : org = 0x00000000, len = 0
|
||||||
ram3 : org = 0x00000000, len = 0
|
ram3 : org = 0x00000000, len = 0
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
*/
|
*/
|
||||||
void _pal_lld_init(void) {
|
void _pal_lld_init(void) {
|
||||||
// Enable GPIO / IOCON CLK
|
// 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
|
* @notapi
|
||||||
*/
|
*/
|
||||||
void _pal_lld_setpadmode(ioportid_t port, iopadid_t pad, iomode_t mode) {
|
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]
|
while (pad > 0x1F){}
|
||||||
= mode & MODE_IOCONF_MASK;
|
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) {
|
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 {
|
} else {
|
||||||
LPC_GPIO->DIR[LPC_IOPORT_NUM(port)] &= ~(1U << pad);
|
LPC_GPIO->DIR[LPC_IOPORT_NUM(port)] &= ~(((uint32_t)1U) << pad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,13 +71,13 @@
|
||||||
* @brief Decodes a port identifier from a line identifier.
|
* @brief Decodes a port identifier from a line identifier.
|
||||||
*/
|
*/
|
||||||
#define PAL_PORT(line) \
|
#define PAL_PORT(line) \
|
||||||
(((uint32_t)(line)) & 0xFFFFFFE0U)
|
(((uint32_t)(line)) & 0xFFFFFF00U)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Decodes a pad identifier from a line identifier.
|
* @brief Decodes a pad identifier from a line identifier.
|
||||||
*/
|
*/
|
||||||
#define PAL_PAD(line) \
|
#define PAL_PAD(line) \
|
||||||
(((uint32_t)(line) & 0x0000001FU))
|
(((uint32_t)(line) & 0x000000FFU))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Value identifying an invalid line.
|
* @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_PULL_UP (0x2U << MODE_MODE_POS)
|
||||||
#define MODE_MODE_REPEATER (0x3U << 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_POS 31U
|
||||||
#define MODE_DIR_MASK (0x1U << MODE_DIR_POS)
|
#define MODE_DIR_MASK (0x1U << MODE_DIR_POS)
|
||||||
#define MODE_DIR_IN (0U << MODE_DIR_POS)
|
#define MODE_DIR_IN (0U << MODE_DIR_POS)
|
||||||
#define MODE_DIR_OUT (1U << MODE_DIR_POS)
|
#define MODE_DIR_OUT (1U << MODE_DIR_POS)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Type of an I/O line.
|
* @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
|
* @details Low level drivers can define multiple ports, it is suggested to
|
||||||
* use this naming convention.
|
* use this naming convention.
|
||||||
*/
|
*/
|
||||||
#define LPC_IOPORT_ID(x) (x << 5U)
|
#define LPC_IOPORT_ID(x) ((x) << 8U)
|
||||||
#define LPC_IOPORT_NUM(x) (x >> 5U)
|
#define LPC_IOPORT_NUM(x) ((x) >> 8U)
|
||||||
#define IOPORT0 LPC_IOPORT_ID(0)
|
#define IOPORT0 LPC_IOPORT_ID(0)
|
||||||
#define IOPORT1 LPC_IOPORT_ID(1)
|
#define IOPORT1 LPC_IOPORT_ID(1)
|
||||||
|
|
||||||
|
@ -379,5 +385,4 @@ extern "C" {
|
||||||
#endif /* HAL_USE_PAL == TRUE */
|
#endif /* HAL_USE_PAL == TRUE */
|
||||||
|
|
||||||
#endif /* HAL_PAL_LLD_H */
|
#endif /* HAL_PAL_LLD_H */
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -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 */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -37,6 +37,9 @@ defined(__DOXYGEN__)
|
||||||
|
|
||||||
#if defined(LPC11Uxx) || defined(__DOXYGEN__)
|
#if defined(LPC11Uxx) || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
/* USB attributes.*/
|
||||||
|
#define LPC_HAS_USB TRUE
|
||||||
|
#define LPC_USB_IRQ_VECTOR Vector98
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -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/STM/driver.mk
|
||||||
include $(CHIBIOS_CONTRIB)/os/hal/ports/LPC/LLD/GPIO/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
|
# Shared variables
|
||||||
ALLCSRC += $(PLATFORMSRC)
|
ALLCSRC += $(PLATFORMSRC)
|
||||||
|
|
Loading…
Reference in New Issue