mirror of
https://github.com/elua/elua.git
synced 2025-01-08 20:56:17 +08:00
Merge branch 'master' of git://github.com/elua/elua into lpc2368
This commit is contained in:
commit
081082508c
@ -91,4 +91,4 @@ Dado Sutter: dadosutter -at- eluaproject -dot- net
|
||||
James Snyder: jbsnyder -at- eluaproject -dot- net
|
||||
|
||||
You are also welcomed to share your questions and suggestions on our
|
||||
link:http://www.eluaproject.net/en_comunity.html#lists[Mail Discussion List]
|
||||
link:http://www.eluaproject.net/get-involved/community-resources[Mail Discussion List]
|
33
boards/known/lpcxpresso.lua
Normal file
33
boards/known/lpcxpresso.lua
Normal file
@ -0,0 +1,33 @@
|
||||
-- LPCXpresso LPC1769 build configuration
|
||||
|
||||
return {
|
||||
cpu = 'lpc1769',
|
||||
components = {
|
||||
sercon = { uart = "cdc", speed = 115200 },
|
||||
romfs = true,
|
||||
shell = true,
|
||||
cdc = true,
|
||||
term = { lines = 25, cols = 80 },
|
||||
linenoise = { shell_lines = 10, lua_lines = 50 },
|
||||
rpc = { uart = 0, speed = 115200 },
|
||||
adc = { buf_size = 4 },
|
||||
xmodem = true
|
||||
},
|
||||
config = {
|
||||
egc = { mode = "alloc" },
|
||||
ram = { internal_rams = 2 },
|
||||
clocks = { external = 12000000, cpu = 120000000 },
|
||||
-- P0.0 UART3 TX, P0.1 UART3 RX, P0.29 USB D+, P0.30 USB D-, P1.18 USB_UP_LED, P2.9 USB CONNECT
|
||||
map_pins = {
|
||||
port = { 0, 0, 0, 0, 1, 2 },
|
||||
pin = { 0, 1, 29, 30, 18, 9 },
|
||||
pinfunction = { 2, 2, 1, 1, 1, 1 }
|
||||
}
|
||||
},
|
||||
modules = {
|
||||
generic = { 'all', "-spi", "-i2c", "-net" },
|
||||
platform = 'all',
|
||||
platform_name = 'lpcxpresso'
|
||||
},
|
||||
}
|
||||
|
@ -15,7 +15,13 @@ return {
|
||||
},
|
||||
config = {
|
||||
egc = { mode = "alloc" },
|
||||
ram = { internal_rams = 2 }
|
||||
ram = { internal_rams = 2 },
|
||||
clocks = { external = 12000000, cpu = 100000000 },
|
||||
map_pins = {
|
||||
port = { 0, 0 },
|
||||
pin = { 2, 3 },
|
||||
pinfunction = { 1, 1 }
|
||||
}
|
||||
},
|
||||
modules = {
|
||||
generic = { 'all', "-spi", "-i2c", "-net" },
|
||||
|
31
boards/known/nucleo-f411re.lua
Normal file
31
boards/known/nucleo-f411re.lua
Normal file
@ -0,0 +1,31 @@
|
||||
-- STM32F4-NUCLEO build configuration
|
||||
|
||||
return {
|
||||
cpu = 'stm32f411re',
|
||||
components = {
|
||||
sercon = { uart = "1", speed = 115200 },
|
||||
romfs = true,
|
||||
cdc = false,
|
||||
advanced_shell = true,
|
||||
term = { lines = 25, cols = 80 },
|
||||
linenoise = { shell_lines = 10, lua_lines = 50 },
|
||||
stm32f4_enc = true,
|
||||
rpc = { uart = "0", speed = 115200 },
|
||||
adc = { buf_size = 2 },
|
||||
xmodem = true,
|
||||
cints = true,
|
||||
luaints = true
|
||||
},
|
||||
config = {
|
||||
egc = { mode = "alloc" },
|
||||
vtmr = { num = 4, freq = 10 },
|
||||
ram = { internal_rams = 1 },
|
||||
clocks = { internal = 16000000, cpu = 100000000 },
|
||||
stm32f4_uart_pins = { con_rx_port = 0, con_rx_pin = 3, con_tx_port = 0, con_tx_pin = 2 }
|
||||
},
|
||||
modules = {
|
||||
generic = { 'all', "-i2c", "-net", "-can" },
|
||||
platform = 'all',
|
||||
},
|
||||
}
|
||||
|
@ -111,10 +111,10 @@ local platform_list =
|
||||
str7 = { cpus = { 'STR711FR2' }, arch = 'arm' },
|
||||
stm32f2 = { cpus = { 'STM32F205RF' }, arch = 'cortexm' },
|
||||
stm32 = { cpus = { 'STM32F103ZE', 'STM32F103RE' }, arch = 'cortexm' },
|
||||
stm32f4 = { cpus = { 'STM32F401RE', 'STM32F407VG', 'STM32F407ZG' }, arch = 'cortexm' },
|
||||
stm32f4 = { cpus = { 'STM32F411RE', 'STM32F401RE', 'STM32F407VG', 'STM32F407ZG' }, arch = 'cortexm' },
|
||||
avr32 = { cpus = { 'AT32UC3A0128', 'AT32UC3A0256', 'AT32UC3A0512', 'AT32UC3B0256' }, arch = 'avr32' },
|
||||
lpc24xx = { cpus = { 'LPC2468' }, arch = 'arm' },
|
||||
lpc17xx = { cpus = { 'LPC1768' }, arch = 'cortexm' }
|
||||
lpc17xx = { cpus = { 'LPC1768', 'LPC1769' }, arch = 'cortexm' }
|
||||
}
|
||||
|
||||
-- Returns the platform of a given CPU
|
||||
|
30
src/common.c
30
src/common.c
@ -24,6 +24,8 @@ extern const elua_int_descriptor elua_int_table[ INT_ELUA_LAST ];
|
||||
#define CON_BUF_SIZE 0
|
||||
#endif // #ifndef CON_BUF_SIZE
|
||||
|
||||
static unsigned int skip_0A = 0;
|
||||
|
||||
// ****************************************************************************
|
||||
// XMODEM support code
|
||||
|
||||
@ -55,10 +57,23 @@ static void term_out( u8 data )
|
||||
|
||||
static int term_in( int mode )
|
||||
{
|
||||
if( mode == TERM_INPUT_DONT_WAIT )
|
||||
return platform_uart_recv( CON_UART_ID, CON_TIMER_ID, 0 );
|
||||
else
|
||||
return platform_uart_recv( CON_UART_ID, CON_TIMER_ID, PLATFORM_TIMER_INF_TIMEOUT );
|
||||
int c;
|
||||
do{
|
||||
if( mode == TERM_INPUT_DONT_WAIT )
|
||||
c = platform_uart_recv( CON_UART_ID, CON_TIMER_ID, 0 );
|
||||
else
|
||||
c = platform_uart_recv( CON_UART_ID, CON_TIMER_ID, PLATFORM_TIMER_INF_TIMEOUT );
|
||||
// CR/LF sequence, skip the second char (LF) if applicable
|
||||
if( skip_0A > 0 )
|
||||
{
|
||||
skip_0A=0;
|
||||
if( c == 0x0A )
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}while( TRUE );
|
||||
return c;
|
||||
}
|
||||
|
||||
static int term_translate( int data )
|
||||
@ -107,8 +122,11 @@ static int term_translate( int data )
|
||||
}
|
||||
else if( data == 0x0D )
|
||||
{
|
||||
// CR/LF sequence, read the second char (LF) if applicable
|
||||
platform_uart_recv( CON_UART_ID, CON_TIMER_ID, TERM_TIMEOUT );
|
||||
skip_0A=1;
|
||||
return KC_ENTER;
|
||||
}
|
||||
else if( data == 0x0A )
|
||||
{
|
||||
return KC_ENTER;
|
||||
}
|
||||
else
|
||||
|
@ -131,7 +131,7 @@ static void refreshLine(const char *prompt, char *buf, size_t len, size_t pos, s
|
||||
}
|
||||
|
||||
/* Cursor to left edge */
|
||||
snprintf(seq,MAX_SEQ_LEN,"\x1b[0G");
|
||||
snprintf(seq,MAX_SEQ_LEN,"\r");
|
||||
term_putstr( seq, strlen( seq ) );
|
||||
/* Write the prompt and the current buffer content */
|
||||
term_putstr( prompt, strlen( prompt ) );
|
||||
@ -140,7 +140,7 @@ static void refreshLine(const char *prompt, char *buf, size_t len, size_t pos, s
|
||||
snprintf(seq,MAX_SEQ_LEN,"\x1b[0K");
|
||||
term_putstr( seq, strlen( seq ) );
|
||||
/* Move cursor to original position. */
|
||||
snprintf(seq,MAX_SEQ_LEN,"\x1b[0G\x1b[%dC", (int)(pos+plen));
|
||||
snprintf(seq,MAX_SEQ_LEN,"\r\x1b[%dC", (int)(pos+plen));
|
||||
term_putstr( seq, strlen( seq ) );
|
||||
}
|
||||
|
||||
|
@ -2,20 +2,33 @@
|
||||
-- It is used by the generic board configuration system (config/)
|
||||
|
||||
module( ..., package.seeall )
|
||||
local at = require "attributes"
|
||||
local comps = require "components"
|
||||
|
||||
-- Add specific components to the 'components' table
|
||||
function add_platform_components( t )
|
||||
function add_platform_components( t, board, cpu )
|
||||
t.lpc17xx_semifs = { macro = "BUILD_SEMIFS" }
|
||||
t.cdc = comps.cdc_uart()
|
||||
end
|
||||
|
||||
-- Add specific configuration to the 'configs' table
|
||||
function add_platform_configs( t )
|
||||
end
|
||||
|
||||
-- Return an array of all the available platform modules for the given cpu
|
||||
function get_platform_modules( cpu )
|
||||
return {
|
||||
pio = { map = "mbed_pio_map", open = "luaopen_mbed_pio" }
|
||||
function add_platform_configs( t, board, cpu )
|
||||
t.map_pins = {
|
||||
attrs = {
|
||||
port = at.array_of( at.int_attr( 'LPC17XX_MAP_PORT' )),
|
||||
pin = at.array_of( at.int_attr( 'LPC17XX_MAP_PIN' )),
|
||||
pinfunction = at.array_of( at.int_attr( 'LPC17XX_MAP_PINFUNCTION' ))
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
-- Return an array of all the available platform modules for the given cpu
|
||||
function get_platform_modules( board, cpu )
|
||||
local m = { pio = { map = "lpc17xx_pio_map", open = "luaopen_lpc17xx_pio" } }
|
||||
board = board:upper()
|
||||
if board == 'MBED' then
|
||||
m.pio = { map = "mbed_pio_map", open = "luaopen_mbed_pio" }
|
||||
end
|
||||
return m
|
||||
end
|
||||
|
||||
|
@ -1,12 +1,22 @@
|
||||
-- Configuration file for the LPC17xx backend
|
||||
|
||||
addi( sf( 'src/platform/%s/drivers/inc', platform ) )
|
||||
addi( sf( 'src/platform/%s/usbstack/inc', platform ) )
|
||||
|
||||
local fwlib_files = utils.get_files( sf( "src/platform/%s/drivers/src", platform ), ".*%.c$" )
|
||||
specific_files = "startup_LPC17xx.c system_LPC17xx.c core_cm3.c platform.c mbed_pio.c"
|
||||
fwlib_files = fwlib_files .. " " .. utils.get_files( sf( "src/platform/%s/usbstack/src", platform ), ".*%.c$" )
|
||||
specific_files = "startup_LPC17xx.c system_LPC17xx.c core_cm3.c platform.c"
|
||||
|
||||
local board = comp.board:upper()
|
||||
|
||||
if board == "MBED" then
|
||||
specific_files = specific_files .. " mbed_pio.c"
|
||||
else
|
||||
specific_files = specific_files .. " lpc17xx_pio.c"
|
||||
end
|
||||
|
||||
local ldscript = "LPC17xx.ld"
|
||||
|
||||
|
||||
-- Prepend with path
|
||||
specific_files = fwlib_files .. " " .. utils.prepend_path( specific_files, sf( "src/platform/%s", platform ) )
|
||||
specific_files = specific_files .. " src/platform/cortex_utils.s src/platform/arm_cortex_interrupts.c"
|
||||
|
@ -17,8 +17,8 @@
|
||||
#define ADC_BIT_RESOLUTION 12
|
||||
|
||||
// CPU frequency (needed by the CPU module, 0 if not used)
|
||||
u32 mbed_get_cpu_frequency();
|
||||
#define CPU_FREQUENCY mbed_get_cpu_frequency()
|
||||
u32 lpc17xx_get_cpu_frequency();
|
||||
#define CPU_FREQUENCY lpc17xx_get_cpu_frequency()
|
||||
|
||||
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
|
||||
#define PIO_PREFIX '0'
|
||||
|
43
src/platform/lpc17xx/cpu_lpc1769.h
Normal file
43
src/platform/lpc17xx/cpu_lpc1769.h
Normal file
@ -0,0 +1,43 @@
|
||||
// eLua platform configuration
|
||||
|
||||
#ifndef __CPU_LPC1769_H__
|
||||
#define __CPU_LPC1769_H__
|
||||
|
||||
#include "stacks.h"
|
||||
|
||||
// Number of resources (0 if not available/not implemented)
|
||||
#define NUM_PIO 5
|
||||
#define NUM_SPI 0
|
||||
#define NUM_UART 4
|
||||
#define NUM_PWM 6
|
||||
#define NUM_ADC 8
|
||||
#define NUM_CAN 2
|
||||
#define NUM_TIMER 4
|
||||
|
||||
#define ADC_BIT_RESOLUTION 12
|
||||
|
||||
// CPU frequency (needed by the CPU module, 0 if not used)
|
||||
u32 lpc17xx_get_cpu_frequency();
|
||||
#define CPU_FREQUENCY lpc17xx_get_cpu_frequency()
|
||||
|
||||
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
|
||||
#define PIO_PREFIX '0'
|
||||
// Pins per port configuration:
|
||||
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
|
||||
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
|
||||
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
|
||||
#define PIO_PINS_PER_PORT 32
|
||||
|
||||
// Allocator data: define your free memory zones here in two arrays
|
||||
// (start address and end address)
|
||||
#define SRAM_ORIGIN 0x10000000
|
||||
#define SRAM_SIZE 0x8000
|
||||
#define SRAM2_ORIGIN 0x2007C000
|
||||
#define SRAM2_SIZE 0x8000
|
||||
#define INTERNAL_RAM1_FIRST_FREE end
|
||||
#define INTERNAL_RAM1_LAST_FREE ( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 )
|
||||
#define INTERNAL_RAM2_FIRST_FREE SRAM2_ORIGIN
|
||||
#define INTERNAL_RAM2_LAST_FREE ( SRAM2_ORIGIN + SRAM2_SIZE - 1 )
|
||||
|
||||
#endif // #ifndef __CPU_LPC1769_H__
|
||||
|
22
src/platform/lpc17xx/drivers/inc/lpc17xx_usb_cdc.h
Normal file
22
src/platform/lpc17xx/drivers/inc/lpc17xx_usb_cdc.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef __LPC17XX_USB_CDC_H
|
||||
#define __LPC17XX_USB_CDC_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int VCOM_putchar(int c);
|
||||
int VCOM_getchar(void);
|
||||
void platform_setup_usb_cdc(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __LPC17XX_USB_CDC_H */
|
@ -32,18 +32,13 @@
|
||||
|
||||
/* Includes ------------------------------------------------------------------- */
|
||||
#include <stdint.h>
|
||||
|
||||
#include <type.h>
|
||||
|
||||
/* Public Types --------------------------------------------------------------- */
|
||||
/** @defgroup LPC_Types_Public_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Boolean Type definition
|
||||
*/
|
||||
typedef enum {FALSE = 0, TRUE = !FALSE} Bool;
|
||||
|
||||
/**
|
||||
* @brief Flag Status and Interrupt Flag Status type definition
|
||||
*/
|
||||
|
462
src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c
Normal file
462
src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c
Normal file
@ -0,0 +1,462 @@
|
||||
/*
|
||||
LPCUSB, an USB device driver for LPC microcontrollers
|
||||
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform_conf.h"
|
||||
|
||||
#ifdef BUILD_USB_CDC
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h> // memcpy
|
||||
|
||||
#include "LPC17xx.h"
|
||||
#include "type.h"
|
||||
|
||||
#include "usbapi.h"
|
||||
#include "usbdebug.h"
|
||||
|
||||
#ifdef CDC_BUF_SIZE
|
||||
#define VCOM_FIFO_SIZE (1<<CDC_BUF_SIZE)
|
||||
#else
|
||||
#define VCOM_FIFO_SIZE 128
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int head;
|
||||
int tail;
|
||||
u8 *buf;
|
||||
} fifo_t;
|
||||
|
||||
void fifo_init(fifo_t *fifo, u8 *buf)
|
||||
{
|
||||
fifo->head = 0;
|
||||
fifo->tail = 0;
|
||||
fifo->buf = buf;
|
||||
}
|
||||
|
||||
|
||||
BOOL fifo_put(fifo_t *fifo, u8 c)
|
||||
{
|
||||
int next;
|
||||
|
||||
// check if FIFO has room
|
||||
next = (fifo->head + 1) % VCOM_FIFO_SIZE;
|
||||
if (next == fifo->tail) {
|
||||
// full
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fifo->buf[fifo->head] = c;
|
||||
fifo->head = next;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL fifo_get(fifo_t *fifo, u8 *pc)
|
||||
{
|
||||
int next;
|
||||
|
||||
// check if FIFO has data
|
||||
if (fifo->head == fifo->tail) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
next = (fifo->tail + 1) % VCOM_FIFO_SIZE;
|
||||
|
||||
*pc = fifo->buf[fifo->tail];
|
||||
fifo->tail = next;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int fifo_avail(fifo_t *fifo)
|
||||
{
|
||||
return (VCOM_FIFO_SIZE + fifo->head - fifo->tail) % VCOM_FIFO_SIZE;
|
||||
}
|
||||
|
||||
|
||||
int fifo_free(fifo_t *fifo)
|
||||
{
|
||||
return (VCOM_FIFO_SIZE - 1 - fifo_avail(fifo));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define BAUD_RATE 115200
|
||||
|
||||
#define INT_IN_EP 0x81
|
||||
#define BULK_OUT_EP 0x05
|
||||
#define BULK_IN_EP 0x82
|
||||
|
||||
#define MAX_PACKET_SIZE 64
|
||||
|
||||
#define LE_WORD(x) ((x)&0xFF),((x)>>8)
|
||||
|
||||
// CDC definitions
|
||||
#define CS_INTERFACE 0x24
|
||||
#define CS_ENDPOINT 0x25
|
||||
|
||||
#define SET_LINE_CODING 0x20
|
||||
#define GET_LINE_CODING 0x21
|
||||
#define SET_CONTROL_LINE_STATE 0x22
|
||||
|
||||
// data structure for GET_LINE_CODING / SET_LINE_CODING class requests
|
||||
typedef struct {
|
||||
u32 dwDTERate;
|
||||
u8 bCharFormat;
|
||||
u8 bParityType;
|
||||
u8 bDataBits;
|
||||
} TLineCoding;
|
||||
|
||||
static TLineCoding LineCoding = {115200, 0, 0, 8};
|
||||
static u8 abBulkBuf[64];
|
||||
static u8 abClassReqData[8];
|
||||
|
||||
static u8 txdata[VCOM_FIFO_SIZE];
|
||||
static u8 rxdata[VCOM_FIFO_SIZE];
|
||||
|
||||
static fifo_t txfifo;
|
||||
static fifo_t rxfifo;
|
||||
|
||||
// forward declaration of interrupt handler
|
||||
void USBIntHandler(void);
|
||||
|
||||
static const u8 abDescriptors[] = {
|
||||
|
||||
// device descriptor
|
||||
0x12,
|
||||
DESC_DEVICE,
|
||||
LE_WORD(0x0101), // bcdUSB
|
||||
0x02, // bDeviceClass
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
MAX_PACKET_SIZE0, // bMaxPacketSize
|
||||
LE_WORD(0x1fc9), // idVendor
|
||||
LE_WORD(0x2047), // idProduct
|
||||
LE_WORD(0x0100), // bcdDevice
|
||||
0x01, // iManufacturer
|
||||
0x02, // iProduct
|
||||
0x03, // iSerialNumber
|
||||
0x01, // bNumConfigurations
|
||||
|
||||
// configuration descriptor
|
||||
0x09,
|
||||
DESC_CONFIGURATION,
|
||||
LE_WORD(67), // wTotalLength
|
||||
0x02, // bNumInterfaces
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration
|
||||
0xC0, // bmAttributes
|
||||
0x32, // bMaxPower
|
||||
// control class interface
|
||||
0x09,
|
||||
DESC_INTERFACE,
|
||||
0x00, // bInterfaceNumber
|
||||
0x00, // bAlternateSetting
|
||||
0x01, // bNumEndPoints
|
||||
0x02, // bInterfaceClass
|
||||
0x02, // bInterfaceSubClass
|
||||
0x01, // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module
|
||||
0x00, // iInterface
|
||||
// header functional descriptor
|
||||
0x05,
|
||||
CS_INTERFACE,
|
||||
0x00,
|
||||
LE_WORD(0x0110),
|
||||
// call management functional descriptor
|
||||
0x05,
|
||||
CS_INTERFACE,
|
||||
0x01,
|
||||
0x01, // bmCapabilities = device handles call management
|
||||
0x01, // bDataInterface
|
||||
// ACM functional descriptor
|
||||
0x04,
|
||||
CS_INTERFACE,
|
||||
0x02,
|
||||
0x02, // bmCapabilities
|
||||
// union functional descriptor
|
||||
0x05,
|
||||
CS_INTERFACE,
|
||||
0x06,
|
||||
0x00, // bMasterInterface
|
||||
0x01, // bSlaveInterface0
|
||||
// notification EP
|
||||
0x07,
|
||||
DESC_ENDPOINT,
|
||||
INT_IN_EP, // bEndpointAddress
|
||||
0x03, // bmAttributes = intr
|
||||
LE_WORD(8), // wMaxPacketSize
|
||||
0x0A, // bInterval
|
||||
// data class interface descriptor
|
||||
0x09,
|
||||
DESC_INTERFACE,
|
||||
0x01, // bInterfaceNumber
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndPoints
|
||||
0x0A, // bInterfaceClass = data
|
||||
0x00, // bInterfaceSubClass
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface
|
||||
// data EP OUT
|
||||
0x07,
|
||||
DESC_ENDPOINT,
|
||||
BULK_OUT_EP, // bEndpointAddress
|
||||
0x02, // bmAttributes = bulk
|
||||
LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
|
||||
0x00, // bInterval
|
||||
// data EP in
|
||||
0x07,
|
||||
DESC_ENDPOINT,
|
||||
BULK_IN_EP, // bEndpointAddress
|
||||
0x02, // bmAttributes = bulk
|
||||
LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
|
||||
0x00, // bInterval
|
||||
|
||||
// string descriptors
|
||||
0x04,
|
||||
DESC_STRING,
|
||||
LE_WORD(0x0409),
|
||||
|
||||
0x0E,
|
||||
DESC_STRING,
|
||||
'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,
|
||||
|
||||
0x14,
|
||||
DESC_STRING,
|
||||
'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,
|
||||
|
||||
0x12,
|
||||
DESC_STRING,
|
||||
'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0,
|
||||
|
||||
// terminating zero
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Local function to handle incoming bulk data
|
||||
|
||||
@param [in] bEP
|
||||
@param [in] bEPStatus
|
||||
*/
|
||||
static void BulkOut(u8 bEP, u8 bEPStatus)
|
||||
{
|
||||
int i, iLen;
|
||||
|
||||
if (fifo_free(&rxfifo) < MAX_PACKET_SIZE) {
|
||||
// may not fit into fifo
|
||||
return;
|
||||
}
|
||||
|
||||
// get data from USB into intermediate buffer
|
||||
iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));
|
||||
for (i = 0; i < iLen; i++) {
|
||||
// put into FIFO
|
||||
if (!fifo_put(&rxfifo, abBulkBuf[i])) {
|
||||
// overflow... :(
|
||||
ASSERT(FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Local function to handle outgoing bulk data
|
||||
|
||||
@param [in] bEP
|
||||
@param [in] bEPStatus
|
||||
*/
|
||||
static void BulkIn(u8 bEP, u8 bEPStatus)
|
||||
{
|
||||
int i, iLen;
|
||||
|
||||
if (fifo_avail(&txfifo) == 0) {
|
||||
// no more data, disable further NAK interrupts until next USB frame
|
||||
USBHwNakIntEnable(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// get bytes from transmit FIFO into intermediate buffer
|
||||
for (i = 0; i < MAX_PACKET_SIZE; i++) {
|
||||
if (!fifo_get(&txfifo, &abBulkBuf[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
iLen = i;
|
||||
|
||||
// send over USB
|
||||
if (iLen > 0) {
|
||||
USBHwEPWrite(bEP, abBulkBuf, iLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Local function to handle the USB-CDC class requests
|
||||
|
||||
@param [in] pSetup
|
||||
@param [out] piLen
|
||||
@param [out] ppbData
|
||||
*/
|
||||
static BOOL HandleClassRequest(TSetupPacket *pSetup, int *piLen, u8 **ppbData)
|
||||
{
|
||||
switch (pSetup->bRequest) {
|
||||
|
||||
// set line coding
|
||||
case SET_LINE_CODING:
|
||||
DBG("SET_LINE_CODING\n");
|
||||
memcpy((u8 *)&LineCoding, *ppbData, 7);
|
||||
*piLen = 7;
|
||||
DBG("dwDTERate=%u, bCharFormat=%u, bParityType=%u, bDataBits=%u\n",
|
||||
LineCoding.dwDTERate,
|
||||
LineCoding.bCharFormat,
|
||||
LineCoding.bParityType,
|
||||
LineCoding.bDataBits);
|
||||
break;
|
||||
|
||||
// get line coding
|
||||
case GET_LINE_CODING:
|
||||
DBG("GET_LINE_CODING\n");
|
||||
*ppbData = (u8 *)&LineCoding;
|
||||
*piLen = 7;
|
||||
break;
|
||||
|
||||
// set control line state
|
||||
case SET_CONTROL_LINE_STATE:
|
||||
// bit0 = DTR, bit = RTS
|
||||
DBG("SET_CONTROL_LINE_STATE %X\n", pSetup->wValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialises the VCOM port.
|
||||
Call this function before using VCOM_putchar or VCOM_getchar
|
||||
*/
|
||||
void VCOM_init(void)
|
||||
{
|
||||
fifo_init(&txfifo, txdata);
|
||||
fifo_init(&rxfifo, rxdata);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Writes one character to VCOM port
|
||||
|
||||
@param [in] c character to write
|
||||
@returns character written, or EOF if character could not be written
|
||||
*/
|
||||
int VCOM_putchar(int c)
|
||||
{
|
||||
return fifo_put(&txfifo, c) ? c : EOF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reads one character from VCOM port
|
||||
|
||||
@returns character read, or EOF if character could not be read
|
||||
*/
|
||||
int VCOM_getchar(void)
|
||||
{
|
||||
u8 c;
|
||||
|
||||
return fifo_get(&rxfifo, &c) ? c : EOF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Interrupt handler
|
||||
|
||||
Simply calls the USB ISR
|
||||
|
||||
This gets installed by overriding a WEAK linker symbol
|
||||
|
||||
*/
|
||||
void USB_IRQHandler(void)
|
||||
{
|
||||
USBHwISR();
|
||||
}
|
||||
|
||||
|
||||
static void USBFrameHandler(u16 wFrame)
|
||||
{
|
||||
if (fifo_avail(&txfifo) > 0) {
|
||||
// data available, enable NAK interrupt on bulk in
|
||||
USBHwNakIntEnable(INACK_BI);
|
||||
}
|
||||
}
|
||||
|
||||
void platform_setup_usb_cdc(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
printf("Initialising USB stack\n");
|
||||
|
||||
// initialise stack
|
||||
USBInit();
|
||||
|
||||
// register descriptors
|
||||
USBRegisterDescriptors(abDescriptors);
|
||||
|
||||
// register class request handler
|
||||
USBRegisterRequestHandler(REQTYPE_TYPE_CLASS, HandleClassRequest, abClassReqData);
|
||||
|
||||
// register endpoint handlers
|
||||
USBHwRegisterEPIntHandler(INT_IN_EP, NULL);
|
||||
USBHwRegisterEPIntHandler(BULK_IN_EP, BulkIn);
|
||||
USBHwRegisterEPIntHandler(BULK_OUT_EP, BulkOut);
|
||||
|
||||
// register frame handler
|
||||
USBHwRegisterFrameHandler(USBFrameHandler);
|
||||
|
||||
// enable bulk-in interrupts on NAKs
|
||||
USBHwNakIntEnable(INACK_BI);
|
||||
|
||||
// initialise VCOM
|
||||
VCOM_init();
|
||||
printf("Starting USB communication\n");
|
||||
|
||||
// enable IRQ
|
||||
NVIC_EnableIRQ(USB_IRQn);
|
||||
|
||||
// connect to bus
|
||||
|
||||
printf("Connecting to USB bus\n");
|
||||
USBHwConnect(TRUE);
|
||||
}
|
||||
|
||||
#endif
|
79
src/platform/lpc17xx/lpc17xx_pio.c
Normal file
79
src/platform/lpc17xx/lpc17xx_pio.c
Normal file
@ -0,0 +1,79 @@
|
||||
// LPC17xx specific PIO support
|
||||
#include <string.h>
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include "platform.h"
|
||||
#include "lrotable.h"
|
||||
#include "platform_conf.h"
|
||||
#include "auxmods.h"
|
||||
#include "lpc17xx_pinsel.h"
|
||||
|
||||
static int configpin( lua_State* L )
|
||||
{
|
||||
pio_type v = ( pio_type )luaL_checkinteger( L, 1 );
|
||||
int funcnum = luaL_checkinteger( L, 2 );
|
||||
int opendrain = luaL_checkinteger( L, 3 );
|
||||
int pinmode = luaL_checkinteger( L, 4 );
|
||||
PINSEL_CFG_Type PinCfg;
|
||||
int port, pin;
|
||||
|
||||
port = PLATFORM_IO_GET_PORT( v );
|
||||
pin = PLATFORM_IO_GET_PIN( v );
|
||||
if( PLATFORM_IO_IS_PORT( v ) || !platform_pio_has_port( port ) || !platform_pio_has_pin( port, pin ) )
|
||||
return luaL_error( L, "invalid pin" );
|
||||
|
||||
PinCfg.Funcnum = funcnum;
|
||||
PinCfg.OpenDrain = opendrain;
|
||||
PinCfg.Pinmode = pinmode;
|
||||
PinCfg.Portnum = port;
|
||||
PinCfg.Pinnum = pin;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Module function map
|
||||
#define MIN_OPT_LEVEL 2
|
||||
#include "lrodefs.h"
|
||||
const LUA_REG_TYPE lpc17xx_pio_map[] =
|
||||
{
|
||||
#if LUA_OPTIMIZE_MEMORY > 0
|
||||
{ LSTRKEY( "__metatable" ), LROVAL( lpc17xx_pio_map ) },
|
||||
{ LSTRKEY( "RES_PULLUP" ), LNUMVAL( PINSEL_PINMODE_PULLUP )},
|
||||
{ LSTRKEY( "RES_TRISTATE" ), LNUMVAL( PINSEL_PINMODE_TRISTATE )},
|
||||
{ LSTRKEY( "RES_PULLDOWN" ), LNUMVAL( PINSEL_PINMODE_PULLDOWN )},
|
||||
{ LSTRKEY( "FUNCTION_0" ), LNUMVAL( PINSEL_FUNC_0 )},
|
||||
{ LSTRKEY( "FUNCTION_1" ), LNUMVAL( PINSEL_FUNC_1 )},
|
||||
{ LSTRKEY( "FUNCTION_2" ), LNUMVAL( PINSEL_FUNC_2 )},
|
||||
{ LSTRKEY( "FUNCTION_3" ), LNUMVAL( PINSEL_FUNC_3 )},
|
||||
{ LSTRKEY( "MODE_DEFAULT" ), LNUMVAL( PINSEL_PINMODE_NORMAL )},
|
||||
{ LSTRKEY( "MODE_OD" ), LNUMVAL( PINSEL_PINMODE_OPENDRAIN )},
|
||||
#endif
|
||||
{ LSTRKEY( "configpin" ), LFUNCVAL( configpin ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
LUALIB_API int luaopen_lpc17xx_pio( lua_State *L )
|
||||
{
|
||||
#if LUA_OPTIMIZE_MEMORY > 0
|
||||
return 0;
|
||||
#else
|
||||
luaL_register( L, PS_LIB_TABLE_NAME, lpc17xx_pio_map );
|
||||
MOD_REG_NUMBER( L, "RES_PULLUP", PINSEL_PINMODE_PULLUP );
|
||||
MOD_REG_NUMBER( L, "RES_TRISTATE", PINSEL_PINMODE_TRISTATE );
|
||||
MOD_REG_NUMBER( L, "RES_PULLDOWN", PINSEL_PINMODE_PULLDOWN );
|
||||
MOD_REG_NUMBER( L, "FUNCTION_0", PINSEL_FUNC_0 );
|
||||
MOD_REG_NUMBER( L, "FUNCTION_1", PINSEL_FUNC_1 );
|
||||
MOD_REG_NUMBER( L, "FUNCTION_2", PINSEL_FUNC_2 );
|
||||
MOD_REG_NUMBER( L, "FUNCTION_3", PINSEL_FUNC_3 );
|
||||
MOD_REG_NUMBER( L, "MODE_DEFAULT", PINSEL_PINMODE_NORMAL );
|
||||
MOD_REG_NUMBER( L, "MODE_OD", PINSEL_PINMODE_OPENDRAIN );
|
||||
|
||||
// Set it as its own metatable
|
||||
lua_pushvalue( L, -1 );
|
||||
lua_setmetatable( L, -2 );
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
@ -28,6 +28,7 @@
|
||||
#include "lpc17xx_pwm.h"
|
||||
#include "lpc17xx_adc.h"
|
||||
#include "lpc17xx_can.h"
|
||||
#include "lpc17xx_usb_cdc.h"
|
||||
|
||||
#define SYSTICKHZ 10
|
||||
|
||||
@ -38,12 +39,13 @@ static void platform_setup_timers();
|
||||
static void platform_setup_pwm();
|
||||
static void platform_setup_adcs();
|
||||
static void cans_init( void );
|
||||
static void platform_setup_pins();
|
||||
|
||||
int platform_init()
|
||||
{
|
||||
// Set up microcontroller system and SystemCoreClock variable
|
||||
SystemInit();
|
||||
|
||||
|
||||
// DeInit NVIC and SCBNVIC
|
||||
NVIC_DeInit();
|
||||
NVIC_SCBDeInit();
|
||||
@ -73,21 +75,29 @@ int platform_init()
|
||||
// Setup CANs
|
||||
cans_init();
|
||||
|
||||
// Setup pin routing
|
||||
platform_setup_pins();
|
||||
|
||||
// System timer setup
|
||||
cmn_systimer_set_base_freq( mbed_get_cpu_frequency() );
|
||||
cmn_systimer_set_base_freq( lpc17xx_get_cpu_frequency() );
|
||||
cmn_systimer_set_interrupt_freq( SYSTICKHZ );
|
||||
|
||||
// Enable SysTick
|
||||
SysTick_Config( mbed_get_cpu_frequency() / SYSTICKHZ );
|
||||
SysTick_Config( lpc17xx_get_cpu_frequency() / SYSTICKHZ );
|
||||
|
||||
#ifdef BUILD_USB_CDC
|
||||
// Setup USB CDC
|
||||
platform_setup_usb_cdc();
|
||||
#endif
|
||||
|
||||
// Common platform initialization code
|
||||
cmn_platform_init();
|
||||
|
||||
return PLATFORM_OK;
|
||||
}
|
||||
}
|
||||
|
||||
extern u32 SystemCoreClock;
|
||||
u32 mbed_get_cpu_frequency()
|
||||
u32 lpc17xx_get_cpu_frequency()
|
||||
{
|
||||
return SystemCoreClock;
|
||||
}
|
||||
@ -104,50 +114,71 @@ void SysTick_Handler()
|
||||
|
||||
// ****************************************************************************
|
||||
// PIO section
|
||||
|
||||
|
||||
static const u8 map_ports[] = LPC17XX_MAP_PORT;
|
||||
static const u8 map_pins [] = LPC17XX_MAP_PIN;
|
||||
static const u8 map_funcs[] = LPC17XX_MAP_PINFUNCTION;
|
||||
|
||||
static void platform_setup_pins(void)
|
||||
{
|
||||
PINSEL_CFG_Type PinCfg;
|
||||
u8 i;
|
||||
|
||||
PinCfg.OpenDrain = PINSEL_PINMODE_NORMAL;
|
||||
PinCfg.Pinmode = PINSEL_PINMODE_PULLUP;
|
||||
|
||||
for(i=0; i<sizeof(map_ports); i++)
|
||||
{
|
||||
PinCfg.Portnum = map_ports[i];
|
||||
PinCfg.Pinnum = map_pins [i];
|
||||
PinCfg.Funcnum = map_funcs[i];
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
}
|
||||
}
|
||||
|
||||
// The platform I/O functions
|
||||
pio_type platform_pio_op( unsigned port, pio_type pinmask, int op )
|
||||
{
|
||||
pio_type retval = 1;
|
||||
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_IO_PORT_SET_VALUE:
|
||||
case PLATFORM_IO_PORT_SET_VALUE:
|
||||
GPIO_SetValue(port, pinmask);
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_IO_PIN_SET:
|
||||
GPIO_SetValue(port, pinmask);
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_IO_PIN_CLEAR:
|
||||
GPIO_ClearValue(port, pinmask);
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_IO_PORT_DIR_OUTPUT:
|
||||
GPIO_SetDir(port, 0xFFFFFFFF, 1);
|
||||
break;
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PIN_DIR_OUTPUT:
|
||||
GPIO_SetDir(port, pinmask, 1);
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_IO_PORT_DIR_INPUT:
|
||||
GPIO_SetDir(port, 0xFFFFFFFF, 0);
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PIN_DIR_INPUT:
|
||||
GPIO_SetDir(port, pinmask, 0);
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PORT_GET_VALUE:
|
||||
retval = GPIO_ReadValue(port);
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_IO_PIN_GET:
|
||||
retval = ( GPIO_ReadValue(port) & pinmask ) ? 1 : 0;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
retval = 0;
|
||||
break;
|
||||
@ -159,9 +190,8 @@ pio_type platform_pio_op( unsigned port, pio_type pinmask, int op )
|
||||
// ****************************************************************************
|
||||
// UART section
|
||||
|
||||
// UART0: Rx = P0.3, Tx = P0.2
|
||||
// The other UARTs have assignable Rx/Tx pins and thus have to be configured
|
||||
// by the user
|
||||
// If you want to use an UART, make sure it is routed to your desired output
|
||||
// pin. See section 8.5 of the LPC17xx User Manual.
|
||||
|
||||
static LPC_UART_TypeDef* const uart[] = { LPC_UART0, LPC_UART1, LPC_UART2, LPC_UART3 };
|
||||
|
||||
@ -171,27 +201,20 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st
|
||||
UART_CFG_Type UARTConfigStruct;
|
||||
// UART FIFO configuration Struct variable
|
||||
UART_FIFO_CFG_Type UARTFIFOConfigStruct;
|
||||
// Pin configuration for UART0
|
||||
PINSEL_CFG_Type PinCfg;
|
||||
|
||||
// UART0 Pin Config
|
||||
PinCfg.Funcnum = 1;
|
||||
PinCfg.OpenDrain = 0;
|
||||
PinCfg.Pinmode = 0;
|
||||
PinCfg.Pinnum = 2;
|
||||
PinCfg.Portnum = 0;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
PinCfg.Pinnum = 3;
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
|
||||
UARTConfigStruct.Baud_rate = ( uint32_t )baud;
|
||||
|
||||
|
||||
#ifdef BUILD_USB_CDC
|
||||
if( id == CDC_UART_ID )
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
switch( databits )
|
||||
{
|
||||
case 5:
|
||||
UARTConfigStruct.Databits = UART_DATABIT_5;
|
||||
break;
|
||||
|
||||
|
||||
case 6:
|
||||
UARTConfigStruct.Databits = UART_DATABIT_6;
|
||||
break;
|
||||
@ -204,33 +227,33 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st
|
||||
UARTConfigStruct.Databits = UART_DATABIT_8;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( stopbits == PLATFORM_UART_STOPBITS_2 )
|
||||
UARTConfigStruct.Stopbits = UART_STOPBIT_2;
|
||||
else
|
||||
UARTConfigStruct.Stopbits = UART_STOPBIT_1;
|
||||
|
||||
|
||||
switch( parity )
|
||||
{
|
||||
case PLATFORM_UART_PARITY_NONE:
|
||||
UARTConfigStruct.Parity = UART_PARITY_NONE;
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_UART_PARITY_ODD:
|
||||
UARTConfigStruct.Parity = UART_PARITY_ODD;
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_UART_PARITY_EVEN:
|
||||
UARTConfigStruct.Parity = UART_PARITY_EVEN;
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_UART_PARITY_MARK:
|
||||
UARTConfigStruct.Parity = UART_PARITY_SP_1;
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_UART_PARITY_SPACE:
|
||||
UARTConfigStruct.Parity = UART_PARITY_SP_0;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
UART_Init(uart[ id ], &UARTConfigStruct);
|
||||
@ -238,22 +261,44 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st
|
||||
// Get default FIFO config and initialize
|
||||
UART_FIFOConfigStructInit(&UARTFIFOConfigStruct);
|
||||
UART_FIFOConfig(uart[ id ], &UARTFIFOConfigStruct);
|
||||
|
||||
|
||||
// Enable Transmit
|
||||
UART_TxCmd(uart[ id ], ENABLE);
|
||||
|
||||
|
||||
return baud; // FIXME: find a way to actually get baud
|
||||
}
|
||||
|
||||
void platform_s_uart_send( unsigned id, u8 data )
|
||||
{
|
||||
UART_Send(uart[ id ], &data, 1, BLOCKING);
|
||||
#ifdef BUILD_USB_CDC
|
||||
if( id == CDC_UART_ID )
|
||||
VCOM_putchar( data );
|
||||
else
|
||||
#endif
|
||||
{
|
||||
UART_Send(uart[ id ], &data, 1, BLOCKING);
|
||||
}
|
||||
}
|
||||
|
||||
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
|
||||
{
|
||||
u8 buffer;
|
||||
|
||||
int rc;
|
||||
|
||||
/* Polling is bad style. Replace me with something interrupt-driven. */
|
||||
#ifdef BUILD_USB_CDC
|
||||
if( id == CDC_UART_ID )
|
||||
{
|
||||
do
|
||||
{
|
||||
rc = VCOM_getchar();
|
||||
if( (timeout == 0) && (rc == EOF) )
|
||||
return -1;
|
||||
} while( rc == EOF );
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( timeout == 0 )
|
||||
{
|
||||
if ( UART_Receive(uart[ id ], &buffer, 1, NONE_BLOCKING) == 0 )
|
||||
@ -261,7 +306,7 @@ int platform_s_uart_recv( unsigned id, timer_data_type timeout )
|
||||
else
|
||||
return ( int )buffer;
|
||||
}
|
||||
|
||||
|
||||
UART_Receive(uart[ id ], &buffer, 1, BLOCKING);
|
||||
return ( int )buffer;
|
||||
}
|
||||
@ -297,7 +342,7 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock )
|
||||
TIM_Init( tmr[ id ], TIM_TIMER_MODE, &TIM_ConfigStruct );
|
||||
TIM_Cmd( tmr[ id ], ENABLE );
|
||||
TIM_ResetCounter( tmr[ id ] );
|
||||
|
||||
|
||||
return clock;
|
||||
}
|
||||
|
||||
@ -305,11 +350,11 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock )
|
||||
static void platform_setup_timers()
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
|
||||
// Power on clocks on APB1
|
||||
CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM2, ENABLE);
|
||||
CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM3, ENABLE);
|
||||
|
||||
|
||||
// Set base frequency to 1MHz, as we can't use a better resolution anyway
|
||||
for( i = 0; i < 4; i ++ )
|
||||
platform_timer_set_clock( i, 1000000ULL );
|
||||
@ -324,7 +369,7 @@ void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
|
||||
TIM_ResetCounter( tmr[ id ] );
|
||||
while( tmr[ id ]->TC < last );
|
||||
}
|
||||
|
||||
|
||||
timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data )
|
||||
{
|
||||
u32 res = 0;
|
||||
@ -335,7 +380,7 @@ timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data )
|
||||
TIM_Cmd( tmr[ id ], ENABLE );
|
||||
TIM_ResetCounter( tmr[ id ] );
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_TIMER_OP_READ:
|
||||
res = tmr[ id ]->TC;
|
||||
break;
|
||||
@ -343,7 +388,7 @@ timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data )
|
||||
case PLATFORM_TIMER_OP_SET_CLOCK:
|
||||
res = platform_timer_set_clock( id, data );
|
||||
break;
|
||||
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_CLOCK:
|
||||
res = platform_timer_get_clock( id );
|
||||
break;
|
||||
@ -390,13 +435,13 @@ int platform_adc_check_timer_id( unsigned id, unsigned timer_id )
|
||||
}
|
||||
|
||||
void platform_adc_stop( unsigned id )
|
||||
{
|
||||
{
|
||||
elua_adc_ch_state *s = adc_get_ch_state( id );
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
|
||||
|
||||
s->op_pending = 0;
|
||||
INACTIVATE_CHANNEL( d, id );
|
||||
|
||||
|
||||
// If there are no more active channels, stop the sequencer
|
||||
if( d->ch_active == 0 && d->running == 1 )
|
||||
{
|
||||
@ -412,17 +457,17 @@ void ADC_IRQHandler(void)
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
elua_adc_ch_state *s = d->ch_state[ d->seq_ctr ];
|
||||
//int i;
|
||||
|
||||
|
||||
// Disable sampling & current sequence channel
|
||||
ADC_StartCmd( LPC_ADC, 0 );
|
||||
ADC_ChannelCmd( LPC_ADC, s->id, DISABLE );
|
||||
ADC_IntConfig( LPC_ADC, s->id, DISABLE );
|
||||
|
||||
if ( ADC_ChannelGetStatus( LPC_ADC, s->id, ADC_DATA_DONE ) )
|
||||
{
|
||||
{
|
||||
d->sample_buf[ d->seq_ctr ] = ( u16 )ADC_ChannelGetData( LPC_ADC, s->id );
|
||||
s->value_fresh = 1;
|
||||
|
||||
|
||||
if ( s->logsmoothlen > 0 && s->smooth_ready == 0)
|
||||
adc_smooth_data( s->id );
|
||||
#if defined( BUF_ENABLE_ADC )
|
||||
@ -432,11 +477,11 @@ void ADC_IRQHandler(void)
|
||||
s->value_fresh = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if ( adc_samples_available( s->id ) >= s->reqsamples && s->freerunning == 0 )
|
||||
platform_adc_stop( s->id );
|
||||
platform_adc_stop( s->id );
|
||||
}
|
||||
|
||||
|
||||
// Set up for next channel acquisition if we're still running
|
||||
if( d->running == 1 )
|
||||
{
|
||||
@ -444,14 +489,14 @@ void ADC_IRQHandler(void)
|
||||
if( d->seq_ctr < ( d->seq_len - 1 ) )
|
||||
d->seq_ctr++;
|
||||
else if( d->seq_ctr == ( d->seq_len - 1 ) )
|
||||
{
|
||||
{
|
||||
adc_update_dev_sequence( 0 );
|
||||
d->seq_ctr = 0; // reset sequence counter if on last sequence entry
|
||||
}
|
||||
|
||||
|
||||
ADC_ChannelCmd( LPC_ADC, d->ch_state[ d->seq_ctr ]->id, ENABLE );
|
||||
ADC_IntConfig( LPC_ADC, d->ch_state[ d->seq_ctr ]->id, ENABLE );
|
||||
|
||||
|
||||
if( d->clocked == 1 && d->seq_ctr == 0 ) // always use clock for first in clocked sequence
|
||||
ADC_StartCmd( LPC_ADC, adc_trig[ d->timer_id ] );
|
||||
|
||||
@ -465,20 +510,20 @@ void ADC_IRQHandler(void)
|
||||
static void platform_setup_adcs()
|
||||
{
|
||||
unsigned id;
|
||||
|
||||
|
||||
for( id = 0; id < NUM_ADC; id ++ )
|
||||
adc_init_ch_state( id );
|
||||
|
||||
|
||||
NVIC_SetPriority(ADC_IRQn, ((0x01<<3)|0x01));
|
||||
|
||||
ADC_Init(LPC_ADC, 13000000);
|
||||
|
||||
|
||||
// Default enables CH0, disable channel
|
||||
ADC_ChannelCmd( LPC_ADC, 0, DISABLE );
|
||||
|
||||
|
||||
// Default enables ADC interrupt only on global, switch to per-channel
|
||||
ADC_IntConfig( LPC_ADC, ADC_ADGINTEN, DISABLE );
|
||||
|
||||
|
||||
platform_adc_set_clock( 0, 0 );
|
||||
}
|
||||
|
||||
@ -493,15 +538,15 @@ u32 platform_adc_set_clock( unsigned id, u32 frequency )
|
||||
if ( frequency > 0 )
|
||||
{
|
||||
d->clocked = 1;
|
||||
|
||||
|
||||
// Max Sampling Rate on LPC1768 is 200 kS/s
|
||||
if ( frequency > 200000 )
|
||||
frequency = 200000;
|
||||
|
||||
|
||||
// Run timer at 1MHz
|
||||
TIM_ConfigStruct.PrescaleOption = TIM_PRESCALE_USVAL;
|
||||
TIM_ConfigStruct.PrescaleValue = 1;
|
||||
|
||||
|
||||
TIM_MatchConfigStruct.MatchChannel = 1;
|
||||
TIM_MatchConfigStruct.IntOnMatch = FALSE;
|
||||
TIM_MatchConfigStruct.ResetOnMatch = TRUE;
|
||||
@ -509,9 +554,9 @@ u32 platform_adc_set_clock( unsigned id, u32 frequency )
|
||||
TIM_MatchConfigStruct.ExtMatchOutputType = TIM_EXTMATCH_TOGGLE;
|
||||
// Set match value to period (in uS) associated with frequency
|
||||
TIM_MatchConfigStruct.MatchValue = ( 1000000ULL / ( frequency * 2 ) ) - 1;
|
||||
|
||||
|
||||
frequency = 1000000ULL / (TIM_MatchConfigStruct.MatchValue + 1);
|
||||
|
||||
|
||||
// Set configuration for Tim_config and Tim_MatchConfig
|
||||
TIM_Init( tmr[ d->timer_id ], TIM_TIMER_MODE, &TIM_ConfigStruct );
|
||||
TIM_ConfigMatch( tmr[ d->timer_id ], &TIM_MatchConfigStruct );
|
||||
@ -519,48 +564,48 @@ u32 platform_adc_set_clock( unsigned id, u32 frequency )
|
||||
}
|
||||
else
|
||||
d->clocked = 0;
|
||||
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
static const u8 adc_ports[] = { 0, 0, 0, 0, 1, 1, 0, 0 };
|
||||
static const u8 adc_pins[] = { 23, 24, 25, 26, 30, 31, 3, 2 };
|
||||
static const u8 adc_pins[] = { 23, 24, 25, 26, 30, 31, 3, 2 };
|
||||
static const u8 adc_funcs[] = { 1, 1, 1, 1, 3, 3, 2, 2 };
|
||||
|
||||
// Prepare Hardware Channel
|
||||
int platform_adc_update_sequence( )
|
||||
{
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
{
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
PINSEL_CFG_Type PinCfg;
|
||||
u8 seq_tmp;
|
||||
unsigned id;
|
||||
|
||||
|
||||
// Enable Needed Pins
|
||||
PinCfg.OpenDrain = 0;
|
||||
PinCfg.Pinmode = 0;
|
||||
|
||||
|
||||
for( seq_tmp = 0; seq_tmp < d->seq_len; seq_tmp++ )
|
||||
{
|
||||
id = d->ch_state[ seq_tmp ]->id;
|
||||
|
||||
|
||||
PinCfg.Funcnum = adc_funcs[ id ];
|
||||
PinCfg.Pinnum = adc_pins[ id ];
|
||||
PinCfg.Pinnum = adc_pins[ id ];
|
||||
PinCfg.Portnum = adc_ports[ id ];
|
||||
PINSEL_ConfigPin(&PinCfg);
|
||||
}
|
||||
|
||||
|
||||
return PLATFORM_OK;
|
||||
}
|
||||
|
||||
|
||||
int platform_adc_start_sequence()
|
||||
{
|
||||
{
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
|
||||
|
||||
if( d->running != 1 )
|
||||
{
|
||||
adc_update_dev_sequence( 0 );
|
||||
|
||||
|
||||
// Start sampling on first channel
|
||||
d->seq_ctr = 0;
|
||||
ADC_ChannelCmd( LPC_ADC, d->ch_state[ d->seq_ctr ]->id, ENABLE );
|
||||
@ -568,7 +613,7 @@ int platform_adc_start_sequence()
|
||||
|
||||
d->running = 1;
|
||||
NVIC_EnableIRQ( ADC_IRQn );
|
||||
|
||||
|
||||
if( d->clocked == 1 )
|
||||
{
|
||||
ADC_StartCmd( LPC_ADC, adc_trig[ d->timer_id ] );
|
||||
@ -578,7 +623,7 @@ int platform_adc_start_sequence()
|
||||
else
|
||||
ADC_StartCmd( LPC_ADC, ADC_START_NOW );
|
||||
}
|
||||
|
||||
|
||||
return PLATFORM_OK;
|
||||
}
|
||||
|
||||
@ -599,7 +644,7 @@ u32 platform_pwm_get_clock( unsigned id )
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
PWM_TIMERCFG_Type PWMCfgDat;
|
||||
|
||||
|
||||
PWMCfgDat.PrescaleOption = PWM_TIMER_PRESCALE_USVAL;
|
||||
PWMCfgDat.PrescaleValue = 1000000ULL / clock;
|
||||
PWM_Init( LPC_PWM1, PWM_MODE_TIMER, &PWMCfgDat );
|
||||
@ -611,10 +656,10 @@ u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
static void platform_setup_pwm()
|
||||
{
|
||||
PWM_MATCHCFG_Type PWMMatchCfgDat;
|
||||
|
||||
|
||||
// Keep clock in reset, set PWM code
|
||||
PWM_ResetCounter( LPC_PWM1 );
|
||||
|
||||
|
||||
// Set match mode (reset on MR0 match)
|
||||
PWMMatchCfgDat.IntOnMatch = DISABLE;
|
||||
PWMMatchCfgDat.MatchChannel = 0;
|
||||
@ -630,13 +675,13 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
{
|
||||
PWM_MATCHCFG_Type PWMMatchCfgDat;
|
||||
u32 divisor = platform_pwm_get_clock( id ) / frequency - 1;
|
||||
|
||||
|
||||
PWM_MatchUpdate( LPC_PWM1, 0, divisor, PWM_MATCH_UPDATE_NOW ); // PWM1 cycle rate
|
||||
PWM_MatchUpdate( LPC_PWM1, id, ( divisor * duty ) / 100, PWM_MATCH_UPDATE_NOW ); // PWM1 channel edge position
|
||||
|
||||
|
||||
if ( id > 1 ) // Channel one is permanently single-edge
|
||||
PWM_ChannelConfig( LPC_PWM1, id, PWM_CHANNEL_SINGLE_EDGE );
|
||||
|
||||
|
||||
PWMMatchCfgDat.IntOnMatch = DISABLE;
|
||||
PWMMatchCfgDat.MatchChannel = id;
|
||||
PWMMatchCfgDat.ResetOnMatch = DISABLE;
|
||||
@ -673,7 +718,7 @@ void CAN_IRQHandler(void)
|
||||
// CAN1 Error (bits 1~10 cleared when read)
|
||||
if (LPC_CAN1->ICR & (1<<2 | 1<<5 | 1<<7))
|
||||
can_err_flag[0] = 1;
|
||||
|
||||
|
||||
// CAN1 Receive
|
||||
if (LPC_CAN1->ICR & (1<<0))
|
||||
{
|
||||
@ -701,7 +746,7 @@ void cans_init( void )
|
||||
|
||||
|
||||
u32 platform_can_setup( unsigned id, u32 clock )
|
||||
{
|
||||
{
|
||||
LPC_CAN_TypeDef * canx;
|
||||
uint32_t div;
|
||||
|
||||
@ -712,13 +757,13 @@ u32 platform_can_setup( unsigned id, u32 clock )
|
||||
default: return 0;
|
||||
}
|
||||
|
||||
CAN_DeInit(canx);
|
||||
CAN_DeInit(canx);
|
||||
CAN_Init(canx, clock);
|
||||
CAN_ModeConfig(canx, CAN_OPERATING_MODE, ENABLE);
|
||||
CAN_IRQCmd(canx, CANINT_RIE, ENABLE); // Receive IRQ
|
||||
CAN_IRQCmd(canx, CANINT_EIE, ENABLE); // Error IRQ
|
||||
CAN_IRQCmd(canx, CANINT_BEIE, ENABLE); // Bus error IRQ
|
||||
LPC_CANAF->AFMR = 2; // Filter bypass (receive all messages)
|
||||
CAN_ModeConfig(canx, CAN_OPERATING_MODE, ENABLE);
|
||||
CAN_IRQCmd(canx, CANINT_RIE, ENABLE); // Receive IRQ
|
||||
CAN_IRQCmd(canx, CANINT_EIE, ENABLE); // Error IRQ
|
||||
CAN_IRQCmd(canx, CANINT_BEIE, ENABLE); // Bus error IRQ
|
||||
LPC_CANAF->AFMR = 2; // Filter bypass (receive all messages)
|
||||
NVIC_EnableIRQ(CAN_IRQn); // Enable IRQs
|
||||
|
||||
// Fix clock
|
||||
@ -800,7 +845,7 @@ int platform_can_recv( unsigned id, u32 *canid, u8 *idtype, u8 *len, u8 *data )
|
||||
if( can_rx_flag[id] != 0 )
|
||||
{
|
||||
memcpy(data, &(can_msg_rx[id].dataA), 4);
|
||||
memcpy(data+4, &(can_msg_rx[id].dataB), 4);
|
||||
memcpy(data+4, &(can_msg_rx[id].dataB), 4);
|
||||
|
||||
can_rx_flag[id] = 0;
|
||||
|
||||
@ -813,4 +858,3 @@ int platform_can_recv( unsigned id, u32 *canid, u8 *idtype, u8 *len, u8 *data )
|
||||
else
|
||||
return PLATFORM_UNDERFLOW;
|
||||
}
|
||||
|
||||
|
@ -20,15 +20,15 @@
|
||||
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
|
||||
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
||||
*
|
||||
* @par
|
||||
* Modified for usage in eLua.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include "LPC17xx.h"
|
||||
|
||||
/*
|
||||
//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
|
||||
*/
|
||||
#include <platform_conf.h>
|
||||
|
||||
/*--------------------- Clock Configuration ----------------------------------
|
||||
//
|
||||
@ -279,23 +279,6 @@
|
||||
// </h>
|
||||
//
|
||||
// </e>
|
||||
*/
|
||||
#define CLOCK_SETUP 1
|
||||
#define SCS_Val 0x00000020
|
||||
#define CLKSRCSEL_Val 0x00000001
|
||||
#define PLL0_SETUP 1
|
||||
#define PLL0CFG_Val 0x00050063
|
||||
#define PLL1_SETUP 1
|
||||
#define PLL1CFG_Val 0x00000023
|
||||
#define CCLKCFG_Val 0x00000003
|
||||
#define USBCLKCFG_Val 0x00000000
|
||||
#define PCLKSEL0_Val 0x00000000
|
||||
#define PCLKSEL1_Val 0x00000000
|
||||
#define PCONP_Val 0x042887DE
|
||||
#define CLKOUTCFG_Val 0x00000000
|
||||
|
||||
|
||||
/*--------------------- Flash Accelerator Configuration ----------------------
|
||||
//
|
||||
// <e> Flash Accelerator Configuration
|
||||
// <o1.0..11> Reserved
|
||||
@ -304,12 +287,43 @@
|
||||
// <1=> 2 CPU clocks (for CPU clock up to 40 MHz)
|
||||
// <2=> 3 CPU clocks (for CPU clock up to 60 MHz)
|
||||
// <3=> 4 CPU clocks (for CPU clock up to 80 MHz)
|
||||
// <4=> 5 CPU clocks (for CPU clock up to 100 MHz)
|
||||
// <4=> 5 CPU clocks (for CPU clock up to 100 MHz, or 1769 up to 120MHz)
|
||||
// <5=> 6 CPU clocks (for any CPU clock)
|
||||
// </e>
|
||||
*/
|
||||
/*----------------------------------------------------------------------------
|
||||
Define clocks
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define XTAL ((DWORD)(ELUA_BOARD_EXTERNAL_CLOCK_HZ)) /* Oscillator frequency */
|
||||
#define OSC_CLK ((DWORD)( XTAL)) /* Main oscillator frequency */
|
||||
#define RTC_CLK ((DWORD)( 32768UL)) /* RTC oscillator frequency */
|
||||
#define IRC_OSC ((DWORD)( 4000000UL)) /* Internal RC oscillator frequency */
|
||||
#define CPU_CLK ( ELUA_BOARD_CPU_CLOCK_HZ) /* Desired CPU clock */
|
||||
|
||||
#define CLOCK_SETUP 1
|
||||
#define SCS_Val 0x00000020
|
||||
#define CLKSRCSEL_Val 0x00000001
|
||||
#define PLL0_SETUP 1
|
||||
/* In a perfect world, we'd calculate the PLL configuration from the information above.
|
||||
* For now, just handle the two cases we actually know about. */
|
||||
#if CPU_CLK==100000000
|
||||
#define PLL0CFG_Val 0x00050063
|
||||
#elif CPU_CLK==120000000
|
||||
#define PLL0CFG_Val 0x00050077
|
||||
#else
|
||||
#error "Unsupported CPU clock, please provide PLL configuration"
|
||||
#endif
|
||||
#define PLL1_SETUP 1
|
||||
#define PLL1CFG_Val 0x00000023
|
||||
#define CCLKCFG_Val 0x00000003
|
||||
#define USBCLKCFG_Val 0x00000000
|
||||
#define PCLKSEL0_Val 0x00000000
|
||||
#define PCLKSEL1_Val 0x00000000
|
||||
#define PCONP_Val 0x042887DE
|
||||
#define CLKOUTCFG_Val 0x00000000
|
||||
#define FLASH_SETUP 1
|
||||
#define FLASHCFG_Val 0x0000303A
|
||||
#define FLASHCFG_Val 0x0000403A
|
||||
|
||||
|
||||
/*
|
||||
//-------- <<< end of configuration section >>> ------------------------------
|
||||
@ -372,15 +386,6 @@
|
||||
DEFINES
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Define clocks
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define XTAL (12000000UL) /* Oscillator frequency */
|
||||
#define OSC_CLK ( XTAL) /* Main oscillator frequency */
|
||||
#define RTC_CLK ( 32000UL) /* RTC oscillator frequency */
|
||||
#define IRC_OSC ( 4000000UL) /* Internal RC oscillator frequency */
|
||||
|
||||
|
||||
/* F_cco0 = (2 * M * F_in) / N */
|
||||
#define __M (((PLL0CFG_Val ) & 0x7FFF) + 1)
|
||||
#define __N (((PLL0CFG_Val >> 16) & 0x00FF) + 1)
|
||||
|
@ -1,6 +1,19 @@
|
||||
#ifndef __TYPE_H__
|
||||
#define __TYPE_H__
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#endif
|
||||
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef signed char s8;
|
||||
typedef unsigned short u16;
|
||||
@ -16,6 +29,7 @@ typedef unsigned char BYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned int BOOL;
|
||||
typedef unsigned int Bool;
|
||||
|
||||
typedef volatile unsigned long* PREG;
|
||||
|
||||
|
120
src/platform/lpc17xx/usbstack/inc/usbapi.h
Normal file
120
src/platform/lpc17xx/usbstack/inc/usbapi.h
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
LPCUSB, an USB device driver for LPC microcontrollers
|
||||
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
@file
|
||||
*/
|
||||
|
||||
#include "type.h"
|
||||
|
||||
#include "usbstruct.h" // for TSetupPacket
|
||||
|
||||
/*************************************************************************
|
||||
USB configuration
|
||||
**************************************************************************/
|
||||
|
||||
#define MAX_PACKET_SIZE0 64 /**< maximum packet size for EP 0 */
|
||||
|
||||
/*************************************************************************
|
||||
USB hardware interface
|
||||
**************************************************************************/
|
||||
|
||||
// endpoint status sent through callback
|
||||
#define EP_STATUS_DATA (1<<0) /**< EP has data */
|
||||
#define EP_STATUS_STALLED (1<<1) /**< EP is stalled */
|
||||
#define EP_STATUS_SETUP (1<<2) /**< EP received setup packet */
|
||||
#define EP_STATUS_ERROR (1<<3) /**< EP data was overwritten by setup packet */
|
||||
#define EP_STATUS_NACKED (1<<4) /**< EP sent NAK */
|
||||
|
||||
// device status sent through callback
|
||||
#define DEV_STATUS_CONNECT (1<<0) /**< device just got connected */
|
||||
#define DEV_STATUS_SUSPEND (1<<2) /**< device entered suspend state */
|
||||
#define DEV_STATUS_RESET (1<<4) /**< device just got reset */
|
||||
|
||||
// interrupt bits for NACK events in USBHwNakIntEnable
|
||||
// (these bits conveniently coincide with the LPC176x USB controller bit)
|
||||
#define INACK_CI (1<<1) /**< interrupt on NACK for control in */
|
||||
#define INACK_CO (1<<2) /**< interrupt on NACK for control out */
|
||||
#define INACK_II (1<<3) /**< interrupt on NACK for interrupt in */
|
||||
#define INACK_IO (1<<4) /**< interrupt on NACK for interrupt out */
|
||||
#define INACK_BI (1<<5) /**< interrupt on NACK for bulk in */
|
||||
#define INACK_BO (1<<6) /**< interrupt on NACK for bulk out */
|
||||
|
||||
BOOL USBHwInit (void);
|
||||
void USBHwISR (void);
|
||||
|
||||
void USBHwNakIntEnable (u8 bIntBits);
|
||||
|
||||
void USBHwConnect (BOOL fConnect);
|
||||
|
||||
void USBHwSetAddress (u8 bAddr);
|
||||
void USBHwConfigDevice (BOOL fConfigured);
|
||||
|
||||
// endpoint operations
|
||||
void USBHwEPConfig (u8 bEP, u16 wMaxPacketSize);
|
||||
int USBHwEPRead (u8 bEP, u8 *pbBuf, int iMaxLen);
|
||||
int USBHwEPWrite (u8 bEP, u8 *pbBuf, int iLen);
|
||||
void USBHwEPStall (u8 bEP, BOOL fStall);
|
||||
u8 USBHwEPGetStatus (u8 bEP);
|
||||
|
||||
/** Endpoint interrupt handler callback */
|
||||
typedef void (TFnEPIntHandler) (u8 bEP, u8 bEPStatus);
|
||||
void USBHwRegisterEPIntHandler (u8 bEP, TFnEPIntHandler *pfnHandler);
|
||||
|
||||
/** Device status handler callback */
|
||||
typedef void (TFnDevIntHandler) (u8 bDevStatus);
|
||||
void USBHwRegisterDevIntHandler (TFnDevIntHandler *pfnHandler);
|
||||
|
||||
/** Frame event handler callback */
|
||||
typedef void (TFnFrameHandler)(u16 wFrame);
|
||||
void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler);
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
USB application interface
|
||||
**************************************************************************/
|
||||
|
||||
// initialise the complete stack, including HW
|
||||
BOOL USBInit(void);
|
||||
|
||||
/** Request handler callback (standard, vendor, class) */
|
||||
typedef BOOL (TFnHandleRequest)(TSetupPacket *pSetup, int *piLen, u8 **ppbData);
|
||||
void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, u8 *pbDataStore);
|
||||
void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler);
|
||||
|
||||
/** Descriptor handler callback */
|
||||
typedef BOOL (TFnGetDescriptor)(u16 wTypeIndex, u16 wLangID, int *piLen, u8 **ppbData);
|
||||
|
||||
/** Default standard request handler */
|
||||
BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, u8 **ppbData);
|
||||
|
||||
/** Default EP0 handler */
|
||||
void USBHandleControlTransfer(u8 bEP, u8 bEPStat);
|
||||
|
||||
/** Descriptor handling */
|
||||
void USBRegisterDescriptors(const u8 *pabDescriptors);
|
||||
BOOL USBGetDescriptor(u16 wTypeIndex, u16 wLangID, int *piLen, u8 **ppbData);
|
36
src/platform/lpc17xx/usbstack/inc/usbdebug.h
Normal file
36
src/platform/lpc17xx/usbstack/inc/usbdebug.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
LPCUSB, an USB device driver for LPC microcontrollers
|
||||
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
#ifdef DEBUG_MESSAGES
|
||||
#define DBG printf
|
||||
#define ASSERT(x) if(!(x)){DBG("\nAssertion '%s' failed in %s:%s#%d!\n",#x,__FILE__,__FUNCTION__,__LINE__);while(1);}
|
||||
#else
|
||||
#define DBG(x ...)
|
||||
#define ASSERT(x)
|
||||
#endif
|
140
src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h
Normal file
140
src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
LPCUSB, an USB device driver for LPC microcontrollers
|
||||
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
Hardware definitions for the LPC176x USB controller
|
||||
|
||||
These are private to the usbhw module
|
||||
*/
|
||||
|
||||
// CodeRed - pull in defines from NXP header file
|
||||
#include "LPC17xx.h"
|
||||
|
||||
|
||||
// CodeRed - these registers have been renamed on LPC176x
|
||||
#define USBReEP USBReEp
|
||||
#define OTG_CLK_CTRL USBClkCtrl
|
||||
#define OTG_CLK_STAT USBClkSt
|
||||
|
||||
/* USBIntSt bits */
|
||||
#define USB_INT_REQ_LP (1<<0)
|
||||
#define USB_INT_REQ_HP (1<<1)
|
||||
#define USB_INT_REQ_DMA (1<<2)
|
||||
#define USB_need_clock (1<<8)
|
||||
#define EN_USB_BITS (1<<31)
|
||||
|
||||
/* USBDevInt... bits */
|
||||
#define FRAME (1<<0)
|
||||
#define EP_FAST (1<<1)
|
||||
#define EP_SLOW (1<<2)
|
||||
#define DEV_STAT (1<<3)
|
||||
#define CCEMTY (1<<4)
|
||||
#define CDFULL (1<<5)
|
||||
#define RxENDPKT (1<<6)
|
||||
#define TxENDPKT (1<<7)
|
||||
#define EP_RLZED (1<<8)
|
||||
#define ERR_INT (1<<9)
|
||||
|
||||
/* USBRxPLen bits */
|
||||
#define PKT_LNGTH (1<<0)
|
||||
#define PKT_LNGTH_MASK 0x3FF
|
||||
#define DV (1<<10)
|
||||
#define PKT_RDY (1<<11)
|
||||
|
||||
/* USBCtrl bits */
|
||||
#define RD_EN (1<<0)
|
||||
#define WR_EN (1<<1)
|
||||
#define LOG_ENDPOINT (1<<2)
|
||||
|
||||
/* protocol engine command codes */
|
||||
/* device commands */
|
||||
#define CMD_DEV_SET_ADDRESS 0xD0
|
||||
#define CMD_DEV_CONFIG 0xD8
|
||||
#define CMD_DEV_SET_MODE 0xF3
|
||||
#define CMD_DEV_READ_CUR_FRAME_NR 0xF5
|
||||
#define CMD_DEV_READ_TEST_REG 0xFD
|
||||
#define CMD_DEV_STATUS 0xFE /* read/write */
|
||||
#define CMD_DEV_GET_ERROR_CODE 0xFF
|
||||
#define CMD_DEV_READ_ERROR_STATUS 0xFB
|
||||
/* endpoint commands */
|
||||
#define CMD_EP_SELECT 0x00
|
||||
#define CMD_EP_SELECT_CLEAR 0x40
|
||||
#define CMD_EP_SET_STATUS 0x40
|
||||
#define CMD_EP_CLEAR_BUFFER 0xF2
|
||||
#define CMD_EP_VALIDATE_BUFFER 0xFA
|
||||
|
||||
/* set address command */
|
||||
#define DEV_ADDR (1<<0)
|
||||
#define DEV_EN (1<<7)
|
||||
|
||||
/* configure device command */
|
||||
#define CONF_DEVICE (1<<0)
|
||||
|
||||
/* set mode command */
|
||||
#define AP_CLK (1<<0)
|
||||
#define INAK_CI (1<<1)
|
||||
#define INAK_CO (1<<2)
|
||||
#define INAK_II (1<<3)
|
||||
#define INAK_IO (1<<4)
|
||||
#define INAK_BI (1<<5)
|
||||
#define INAK_BO (1<<6)
|
||||
|
||||
/* set get device status command */
|
||||
#define CON (1<<0)
|
||||
#define CON_CH (1<<1)
|
||||
#define SUS (1<<2)
|
||||
#define SUS_CH (1<<3)
|
||||
#define RST (1<<4)
|
||||
|
||||
/* get error code command */
|
||||
// ...
|
||||
|
||||
/* Select Endpoint command read bits */
|
||||
#define EPSTAT_FE (1<<0)
|
||||
#define EPSTAT_ST (1<<1)
|
||||
#define EPSTAT_STP (1<<2)
|
||||
#define EPSTAT_PO (1<<3)
|
||||
#define EPSTAT_EPN (1<<4)
|
||||
#define EPSTAT_B1FULL (1<<5)
|
||||
#define EPSTAT_B2FULL (1<<6)
|
||||
|
||||
/* CMD_EP_SET_STATUS command */
|
||||
#define EP_ST (1<<0)
|
||||
#define EP_DA (1<<5)
|
||||
#define EP_RF_MO (1<<6)
|
||||
#define EP_CND_ST (1<<7)
|
||||
|
||||
/* read error status command */
|
||||
#define PID_ERR (1<<0)
|
||||
#define UEPKT (1<<1)
|
||||
#define DCRC (1<<2)
|
||||
#define TIMEOUT (1<<3)
|
||||
#define EOP (1<<4)
|
||||
#define B_OVRN (1<<5)
|
||||
#define BTSTF (1<<6)
|
||||
#define TGL_ERR (1<<7)
|
117
src/platform/lpc17xx/usbstack/inc/usbstruct.h
Normal file
117
src/platform/lpc17xx/usbstack/inc/usbstruct.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
LPCUSB, an USB device driver for LPC microcontrollers
|
||||
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
Definitions of structures of standard USB packets
|
||||
*/
|
||||
|
||||
#ifndef _USBSTRUCT_H_
|
||||
#define _USBSTRUCT_H_
|
||||
|
||||
#include "type.h"
|
||||
|
||||
/** setup packet definitions */
|
||||
typedef struct {
|
||||
u8 bmRequestType; /**< characteristics of the specific request */
|
||||
u8 bRequest; /**< specific request */
|
||||
u16 wValue; /**< request specific parameter */
|
||||
u16 wIndex; /**< request specific parameter */
|
||||
u16 wLength; /**< length of data transfered in data phase */
|
||||
} TSetupPacket;
|
||||
|
||||
|
||||
#define REQTYPE_GET_DIR(x) (((x)>>7)&0x01)
|
||||
#define REQTYPE_GET_TYPE(x) (((x)>>5)&0x03)
|
||||
#define REQTYPE_GET_RECIP(x) ((x)&0x1F)
|
||||
|
||||
#define REQTYPE_DIR_TO_DEVICE 0
|
||||
#define REQTYPE_DIR_TO_HOST 1
|
||||
|
||||
#define REQTYPE_TYPE_STANDARD 0
|
||||
#define REQTYPE_TYPE_CLASS 1
|
||||
#define REQTYPE_TYPE_VENDOR 2
|
||||
#define REQTYPE_TYPE_RESERVED 3
|
||||
|
||||
#define REQTYPE_RECIP_DEVICE 0
|
||||
#define REQTYPE_RECIP_INTERFACE 1
|
||||
#define REQTYPE_RECIP_ENDPOINT 2
|
||||
#define REQTYPE_RECIP_OTHER 3
|
||||
|
||||
/* standard requests */
|
||||
#define REQ_GET_STATUS 0x00
|
||||
#define REQ_CLEAR_FEATURE 0x01
|
||||
#define REQ_SET_FEATURE 0x03
|
||||
#define REQ_SET_ADDRESS 0x05
|
||||
#define REQ_GET_DESCRIPTOR 0x06
|
||||
#define REQ_SET_DESCRIPTOR 0x07
|
||||
#define REQ_GET_CONFIGURATION 0x08
|
||||
#define REQ_SET_CONFIGURATION 0x09
|
||||
#define REQ_GET_INTERFACE 0x0A
|
||||
#define REQ_SET_INTERFACE 0x0B
|
||||
#define REQ_SYNCH_FRAME 0x0C
|
||||
|
||||
/* class requests HID */
|
||||
#define HID_GET_REPORT 0x01
|
||||
#define HID_GET_IDLE 0x02
|
||||
#define HID_GET_PROTOCOL 0x03
|
||||
#define HID_SET_REPORT 0x09
|
||||
#define HID_SET_IDLE 0x0A
|
||||
#define HID_SET_PROTOCOL 0x0B
|
||||
|
||||
/* feature selectors */
|
||||
#define FEA_ENDPOINT_HALT 0x00
|
||||
#define FEA_REMOTE_WAKEUP 0x01
|
||||
#define FEA_TEST_MODE 0x02
|
||||
|
||||
/*
|
||||
USB descriptors
|
||||
*/
|
||||
|
||||
/** USB descriptor header */
|
||||
typedef struct {
|
||||
u8 bLength; /**< descriptor length */
|
||||
u8 bDescriptorType; /**< descriptor type */
|
||||
} TUSBDescHeader;
|
||||
|
||||
#define DESC_DEVICE 1
|
||||
#define DESC_CONFIGURATION 2
|
||||
#define DESC_STRING 3
|
||||
#define DESC_INTERFACE 4
|
||||
#define DESC_ENDPOINT 5
|
||||
#define DESC_DEVICE_QUALIFIER 6
|
||||
#define DESC_OTHER_SPEED 7
|
||||
#define DESC_INTERFACE_POWER 8
|
||||
|
||||
#define DESC_HID_HID 0x21
|
||||
#define DESC_HID_REPORT 0x22
|
||||
#define DESC_HID_PHYSICAL 0x23
|
||||
|
||||
#define GET_DESC_TYPE(x) (((x)>>8)&0xFF)
|
||||
#define GET_DESC_INDEX(x) ((x)&0xFF)
|
||||
|
||||
#endif /* _USBSTRUCT_H_ */
|
47
src/platform/lpc17xx/usbstack/readme.txt
Normal file
47
src/platform/lpc17xx/usbstack/readme.txt
Normal file
@ -0,0 +1,47 @@
|
||||
USB stack for LPC17xx. Based on the library distributed by Code Red
|
||||
Technologies, which in turn is based on the LPCUSB project for the
|
||||
LPC2148, originally written by Bertrik Sikken.
|
||||
|
||||
I'm taking the liberty to just edit the code without annotating
|
||||
edits, even removing Code Red annotations, as git will preserve
|
||||
all this history for us.
|
||||
|
||||
Original README follows.
|
||||
|
||||
|
||||
|
||||
Code Red Technologies RDB1768 Board - USB Stack Example
|
||||
=======================================================
|
||||
|
||||
The USB stack and associated examples provided with RDB1768 board are
|
||||
based on the open source LPCUSB stack, originally written for the NXP
|
||||
LPC214x microcontrollers. The original sources for the USB stack and
|
||||
and examples can be found at:
|
||||
|
||||
http://sourceforge.net/projects/lpcusb/
|
||||
|
||||
with additional information at:
|
||||
|
||||
http://wiki.sikken.nl/index.php?title=LPCUSB
|
||||
|
||||
We have tried to keep the changes to the codebase down to a minimum, and
|
||||
have commented where changes have been made as much as possible
|
||||
|
||||
Support
|
||||
-------
|
||||
This example project is based on the open source LPCUSB stack.
|
||||
Code Red can provide support on using this project as supplied to
|
||||
users with a valid support contract with us. But if you require
|
||||
assistance on the general use of the stack or on extending the
|
||||
example, then we would recommend that you raise your questions
|
||||
to an appropriate community forum, such as....
|
||||
|
||||
http://tech.groups.yahoo.com/group/lpc2000/messages
|
||||
|
||||
USBstack
|
||||
--------
|
||||
This is the main project which builds the LPCUSB stack as a library.
|
||||
This is then used in building the various RDB1768 USB examples projects.
|
||||
|
||||
|
||||
|
236
src/platform/lpc17xx/usbstack/src/usbcontrol.c
Normal file
236
src/platform/lpc17xx/usbstack/src/usbcontrol.c
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
LPCUSB, an USB device driver for LPC microcontrollers
|
||||
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform_conf.h"
|
||||
|
||||
#ifdef BUILD_USB_CDC
|
||||
|
||||
/** @file
|
||||
Control transfer handler.
|
||||
|
||||
This module handles control transfers and is normally installed on the
|
||||
endpoint 0 callback.
|
||||
|
||||
Control transfers can be of the following type:
|
||||
0 Standard;
|
||||
1 Class;
|
||||
2 Vendor;
|
||||
3 Reserved.
|
||||
|
||||
A callback can be installed for each of these control transfers using
|
||||
USBRegisterRequestHandler.
|
||||
When an OUT request arrives, data is collected in the data store provided
|
||||
with the USBRegisterRequestHandler call. When the transfer is done, the
|
||||
callback is called.
|
||||
When an IN request arrives, the callback is called immediately to either
|
||||
put the control transfer data in the data store, or to get a pointer to
|
||||
control transfer data. The data is then packetised and sent to the host.
|
||||
*/
|
||||
|
||||
#include "type.h"
|
||||
|
||||
#include "usbdebug.h"
|
||||
|
||||
#include "usbstruct.h"
|
||||
#include "usbapi.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define MAX_CONTROL_SIZE 128 /**< maximum total size of control transfer data */
|
||||
#define MAX_REQ_HANDLERS 4 /**< standard, class, vendor, reserved */
|
||||
|
||||
static TSetupPacket Setup; /**< setup packet */
|
||||
|
||||
static u8 *pbData; /**< pointer to data buffer */
|
||||
static int iResidue; /**< remaining bytes in buffer */
|
||||
static int iLen; /**< total length of control transfer */
|
||||
|
||||
/** Array of installed request handler callbacks */
|
||||
static TFnHandleRequest *apfnReqHandlers[4] = {NULL, NULL, NULL, NULL};
|
||||
/** Array of installed request data pointers */
|
||||
static u8 *apbDataStore[4] = {NULL, NULL, NULL, NULL};
|
||||
|
||||
/**
|
||||
Local function to handle a request by calling one of the installed
|
||||
request handlers.
|
||||
|
||||
In case of data going from host to device, the data is at *ppbData.
|
||||
In case of data going from device to host, the handler can either
|
||||
choose to write its data at *ppbData or update the data pointer.
|
||||
|
||||
@param [in] pSetup The setup packet
|
||||
@param [in,out] *piLen Pointer to data length
|
||||
@param [in,out] ppbData Data buffer.
|
||||
|
||||
@return TRUE if the request was handles successfully
|
||||
*/
|
||||
static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, u8 **ppbData)
|
||||
{
|
||||
TFnHandleRequest *pfnHandler;
|
||||
int iType;
|
||||
|
||||
iType = REQTYPE_GET_TYPE(pSetup->bmRequestType);
|
||||
pfnHandler = apfnReqHandlers[iType];
|
||||
if (pfnHandler == NULL) {
|
||||
DBG("No handler for reqtype %d\n", iType);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pfnHandler(pSetup, piLen, ppbData);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Local function to stall the control endpoint
|
||||
|
||||
@param [in] bEPStat Endpoint status
|
||||
*/
|
||||
static void StallControlPipe(u8 bEPStat)
|
||||
{
|
||||
u8 *pb;
|
||||
int i;
|
||||
|
||||
USBHwEPStall(0x80, TRUE);
|
||||
|
||||
// dump setup packet
|
||||
DBG("STALL on [");
|
||||
pb = (u8 *)&Setup;
|
||||
for (i = 0; i < 8; i++) {
|
||||
DBG(" %02x", *pb++);
|
||||
}
|
||||
DBG("] stat=%x\n", bEPStat);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sends next chunk of data (possibly 0 bytes) to host
|
||||
*/
|
||||
static void DataIn(void)
|
||||
{
|
||||
int iChunk;
|
||||
|
||||
iChunk = UMIN(MAX_PACKET_SIZE0, iResidue);
|
||||
USBHwEPWrite(0x80, pbData, iChunk);
|
||||
pbData += iChunk;
|
||||
iResidue -= iChunk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles IN/OUT transfers on EP0
|
||||
*
|
||||
* @param [in] bEP Endpoint address
|
||||
* @param [in] bEPStat Endpoint status
|
||||
*/
|
||||
void USBHandleControlTransfer(u8 bEP, u8 bEPStat)
|
||||
{
|
||||
int iChunk, iType;
|
||||
|
||||
if (bEP == 0x00) {
|
||||
// OUT transfer
|
||||
if (bEPStat & EP_STATUS_SETUP) {
|
||||
// setup packet, reset request message state machine
|
||||
USBHwEPRead(0x00, (u8 *)&Setup, sizeof(Setup));
|
||||
DBG("S%x", Setup.bRequest);
|
||||
|
||||
// defaults for data pointer and residue
|
||||
iType = REQTYPE_GET_TYPE(Setup.bmRequestType);
|
||||
pbData = apbDataStore[iType];
|
||||
iResidue = Setup.wLength;
|
||||
iLen = Setup.wLength;
|
||||
|
||||
if ((Setup.wLength == 0) ||
|
||||
(REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST)) {
|
||||
// ask installed handler to process request
|
||||
if (!_HandleRequest(&Setup, &iLen, &pbData)) {
|
||||
DBG("_HandleRequest1 failed\n");
|
||||
StallControlPipe(bEPStat);
|
||||
return;
|
||||
}
|
||||
// send smallest of requested and offered length
|
||||
iResidue = UMIN(iLen, Setup.wLength);
|
||||
// send first part (possibly a zero-length status message)
|
||||
DataIn();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (iResidue > 0) {
|
||||
// store data
|
||||
iChunk = USBHwEPRead(0x00, pbData, iResidue);
|
||||
if (iChunk < 0) {
|
||||
StallControlPipe(bEPStat);
|
||||
return;
|
||||
}
|
||||
pbData += iChunk;
|
||||
iResidue -= iChunk;
|
||||
if (iResidue == 0) {
|
||||
// received all, send data to handler
|
||||
iType = REQTYPE_GET_TYPE(Setup.bmRequestType);
|
||||
pbData = apbDataStore[iType];
|
||||
if (!_HandleRequest(&Setup, &iLen, &pbData)) {
|
||||
DBG("_HandleRequest2 failed\n");
|
||||
StallControlPipe(bEPStat);
|
||||
return;
|
||||
}
|
||||
// send status to host
|
||||
DataIn();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// absorb zero-length status message
|
||||
iChunk = USBHwEPRead(0x00, NULL, 0);
|
||||
DBG(iChunk > 0 ? "?" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bEP == 0x80) {
|
||||
// IN transfer
|
||||
// send more data if available (possibly a 0-length packet)
|
||||
DataIn();
|
||||
}
|
||||
else {
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Registers a callback for handling requests
|
||||
|
||||
@param [in] iType Type of request, e.g. REQTYPE_TYPE_STANDARD
|
||||
@param [in] *pfnHandler Callback function pointer
|
||||
@param [in] *pbDataStore Data storage area for this type of request
|
||||
*/
|
||||
void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, u8 *pbDataStore)
|
||||
{
|
||||
ASSERT(iType >= 0);
|
||||
ASSERT(iType < 4);
|
||||
apfnReqHandlers[iType] = pfnHandler;
|
||||
apbDataStore[iType] = pbDataStore;
|
||||
}
|
||||
|
||||
#endif
|
532
src/platform/lpc17xx/usbstack/src/usbhw_lpc.c
Normal file
532
src/platform/lpc17xx/usbstack/src/usbhw_lpc.c
Normal file
@ -0,0 +1,532 @@
|
||||
/*
|
||||
LPCUSB, an USB device driver for LPC microcontrollers
|
||||
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform_conf.h"
|
||||
|
||||
#ifdef BUILD_USB_CDC
|
||||
|
||||
/** @file
|
||||
USB hardware layer
|
||||
*/
|
||||
|
||||
#include "type.h"
|
||||
|
||||
#include "usbdebug.h"
|
||||
#include "usbhw_lpc.h"
|
||||
#include "usbapi.h"
|
||||
|
||||
/** Installed device interrupt handler */
|
||||
static TFnDevIntHandler *_pfnDevIntHandler = NULL;
|
||||
/** Installed endpoint interrupt handlers */
|
||||
static TFnEPIntHandler *_apfnEPIntHandlers[16];
|
||||
/** Installed frame interrupt handlers */
|
||||
static TFnFrameHandler *_pfnFrameHandler = NULL;
|
||||
|
||||
/** convert from endpoint address to endpoint index */
|
||||
#define EP2IDX(bEP) ((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7))
|
||||
/** convert from endpoint index to endpoint address */
|
||||
#define IDX2EP(idx) ((((idx)<<7)&0x80)|(((idx)>>1)&0xF))
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Local function to wait for a device interrupt (and clear it)
|
||||
|
||||
@param [in] dwIntr Bitmask of interrupts to wait for
|
||||
*/
|
||||
static void Wait4DevInt(u32 dwIntr)
|
||||
{
|
||||
// wait for specific interrupt
|
||||
while ((LPC_USB->USBDevIntSt & dwIntr) != dwIntr);
|
||||
// clear the interrupt bits
|
||||
LPC_USB->USBDevIntClr = dwIntr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Local function to send a command to the USB protocol engine
|
||||
|
||||
@param [in] bCmd Command to send
|
||||
*/
|
||||
static void USBHwCmd(u8 bCmd)
|
||||
{
|
||||
// clear CDFULL/CCEMTY
|
||||
LPC_USB->USBDevIntClr = CDFULL | CCEMTY;
|
||||
// write command code
|
||||
LPC_USB->USBCmdCode = 0x00000500 | (bCmd << 16);
|
||||
Wait4DevInt(CCEMTY);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Local function to send a command + data to the USB protocol engine
|
||||
|
||||
@param [in] bCmd Command to send
|
||||
@param [in] bData Data to send
|
||||
*/
|
||||
static void USBHwCmdWrite(u8 bCmd, u16 bData)
|
||||
{
|
||||
// write command code
|
||||
USBHwCmd(bCmd);
|
||||
|
||||
// write command data
|
||||
LPC_USB->USBCmdCode = 0x00000100 | (bData << 16);
|
||||
Wait4DevInt(CCEMTY);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Local function to send a command to the USB protocol engine and read data
|
||||
|
||||
@param [in] bCmd Command to send
|
||||
|
||||
@return the data
|
||||
*/
|
||||
static u8 USBHwCmdRead(u8 bCmd)
|
||||
{
|
||||
// write command code
|
||||
USBHwCmd(bCmd);
|
||||
|
||||
// get data
|
||||
LPC_USB->USBCmdCode = 0x00000200 | (bCmd << 16);
|
||||
Wait4DevInt(CDFULL);
|
||||
return LPC_USB->USBCmdData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
'Realizes' an endpoint, meaning that buffer space is reserved for
|
||||
it. An endpoint needs to be realised before it can be used.
|
||||
|
||||
From experiments, it appears that a USB reset causes USBReEP to
|
||||
re-initialise to 3 (= just the control endpoints).
|
||||
However, a USB bus reset does not disturb the USBMaxPSize settings.
|
||||
|
||||
@param [in] idx Endpoint index
|
||||
@param [in] wMaxPSize Maximum packet size for this endpoint
|
||||
*/
|
||||
static void USBHwEPRealize(int idx, u16 wMaxPSize)
|
||||
{
|
||||
LPC_USB->USBReEP |= (1 << idx);
|
||||
LPC_USB->USBEpInd = idx;
|
||||
LPC_USB->USBMaxPSize = wMaxPSize;
|
||||
Wait4DevInt(EP_RLZED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Enables or disables an endpoint
|
||||
|
||||
@param [in] idx Endpoint index
|
||||
@param [in] fEnable TRUE to enable, FALSE to disable
|
||||
*/
|
||||
static void USBHwEPEnable(int idx, BOOL fEnable)
|
||||
{
|
||||
USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configures an endpoint and enables it
|
||||
|
||||
@param [in] bEP Endpoint number
|
||||
@param [in] wMaxPacketSize Maximum packet size for this EP
|
||||
*/
|
||||
void USBHwEPConfig(u8 bEP, u16 wMaxPacketSize)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = EP2IDX(bEP);
|
||||
|
||||
// realise EP
|
||||
USBHwEPRealize(idx, wMaxPacketSize);
|
||||
|
||||
// enable EP
|
||||
USBHwEPEnable(idx, TRUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Registers an endpoint event callback
|
||||
|
||||
@param [in] bEP Endpoint number
|
||||
@param [in] pfnHandler Callback function
|
||||
*/
|
||||
void USBHwRegisterEPIntHandler(u8 bEP, TFnEPIntHandler *pfnHandler)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = EP2IDX(bEP);
|
||||
|
||||
ASSERT(idx<32);
|
||||
|
||||
/* add handler to list of EP handlers */
|
||||
_apfnEPIntHandlers[idx / 2] = pfnHandler;
|
||||
|
||||
/* enable EP interrupt */
|
||||
LPC_USB->USBEpIntEn |= (1 << idx);
|
||||
LPC_USB->USBDevIntEn |= EP_SLOW;
|
||||
|
||||
DBG("Registered handler for EP 0x%x\n", bEP);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Registers an device status callback
|
||||
|
||||
@param [in] pfnHandler Callback function
|
||||
*/
|
||||
void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler)
|
||||
{
|
||||
_pfnDevIntHandler = pfnHandler;
|
||||
|
||||
// enable device interrupt
|
||||
LPC_USB->USBDevIntEn |= DEV_STAT;
|
||||
|
||||
DBG("Registered handler for device status\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Registers the frame callback
|
||||
|
||||
@param [in] pfnHandler Callback function
|
||||
*/
|
||||
void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler)
|
||||
{
|
||||
_pfnFrameHandler = pfnHandler;
|
||||
|
||||
// enable device interrupt
|
||||
LPC_USB->USBDevIntEn |= FRAME;
|
||||
|
||||
DBG("Registered handler for frame\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sets the USB address.
|
||||
|
||||
@param [in] bAddr Device address to set
|
||||
*/
|
||||
void USBHwSetAddress(u8 bAddr)
|
||||
{
|
||||
USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Connects or disconnects from the USB bus
|
||||
|
||||
@param [in] fConnect If TRUE, connect, otherwise disconnect
|
||||
*/
|
||||
void USBHwConnect(BOOL fConnect)
|
||||
{
|
||||
USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Enables interrupt on NAK condition
|
||||
|
||||
For IN endpoints a NAK is generated when the host wants to read data
|
||||
from the device, but none is available in the endpoint buffer.
|
||||
For OUT endpoints a NAK is generated when the host wants to write data
|
||||
to the device, but the endpoint buffer is still full.
|
||||
|
||||
The endpoint interrupt handlers can distinguish regular (ACK) interrupts
|
||||
from NAK interrupt by checking the bits in their bEPStatus argument.
|
||||
|
||||
@param [in] bIntBits Bitmap indicating which NAK interrupts to enable
|
||||
*/
|
||||
void USBHwNakIntEnable(u8 bIntBits)
|
||||
{
|
||||
USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Gets the status from a specific endpoint.
|
||||
|
||||
@param [in] bEP Endpoint number
|
||||
@return Endpoint status byte (containing EP_STATUS_xxx bits)
|
||||
*/
|
||||
u8 USBHwEPGetStatus(u8 bEP)
|
||||
{
|
||||
int idx = EP2IDX(bEP);
|
||||
|
||||
return USBHwCmdRead(CMD_EP_SELECT | idx);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sets the stalled property of an endpoint
|
||||
|
||||
@param [in] bEP Endpoint number
|
||||
@param [in] fStall TRUE to stall, FALSE to unstall
|
||||
*/
|
||||
void USBHwEPStall(u8 bEP, BOOL fStall)
|
||||
{
|
||||
int idx = EP2IDX(bEP);
|
||||
|
||||
USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Writes data to an endpoint buffer
|
||||
|
||||
@param [in] bEP Endpoint number
|
||||
@param [in] pbBuf Endpoint data
|
||||
@param [in] iLen Number of bytes to write
|
||||
|
||||
@return TRUE if the data was successfully written or <0 in case of error.
|
||||
*/
|
||||
int USBHwEPWrite(u8 bEP, u8 *pbBuf, int iLen)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = EP2IDX(bEP);
|
||||
|
||||
// set write enable for specific endpoint
|
||||
LPC_USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2);
|
||||
|
||||
// set packet length
|
||||
LPC_USB->USBTxPLen = iLen;
|
||||
|
||||
// write data
|
||||
while (LPC_USB->USBCtrl & WR_EN) {
|
||||
LPC_USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0];
|
||||
pbBuf += 4;
|
||||
}
|
||||
|
||||
// select endpoint and validate buffer
|
||||
USBHwCmd(CMD_EP_SELECT | idx);
|
||||
USBHwCmd(CMD_EP_VALIDATE_BUFFER);
|
||||
|
||||
return iLen;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reads data from an endpoint buffer
|
||||
|
||||
@param [in] bEP Endpoint number
|
||||
@param [in] pbBuf Endpoint data
|
||||
@param [in] iMaxLen Maximum number of bytes to read
|
||||
|
||||
@return the number of bytes available in the EP (possibly more than iMaxLen),
|
||||
or <0 in case of error.
|
||||
*/
|
||||
int USBHwEPRead(u8 bEP, u8 *pbBuf, int iMaxLen)
|
||||
{
|
||||
int i, idx;
|
||||
u32 dwData, dwLen;
|
||||
|
||||
idx = EP2IDX(bEP);
|
||||
|
||||
// set read enable bit for specific endpoint
|
||||
LPC_USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2);
|
||||
|
||||
// wait for PKT_RDY
|
||||
do {
|
||||
dwLen = LPC_USB->USBRxPLen;
|
||||
} while ((dwLen & PKT_RDY) == 0);
|
||||
|
||||
// packet valid?
|
||||
if ((dwLen & DV) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get length
|
||||
dwLen &= PKT_LNGTH_MASK;
|
||||
|
||||
// get data
|
||||
dwData = 0;
|
||||
for (i = 0; i < dwLen; i++) {
|
||||
if ((i % 4) == 0) {
|
||||
dwData = LPC_USB->USBRxData;
|
||||
}
|
||||
if ((pbBuf != NULL) && (i < iMaxLen)) {
|
||||
pbBuf[i] = dwData & 0xFF;
|
||||
}
|
||||
dwData >>= 8;
|
||||
}
|
||||
|
||||
// make sure RD_EN is clear
|
||||
LPC_USB->USBCtrl = 0;
|
||||
|
||||
// select endpoint and clear buffer
|
||||
USBHwCmd(CMD_EP_SELECT | idx);
|
||||
USBHwCmd(CMD_EP_CLEAR_BUFFER);
|
||||
|
||||
return dwLen;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sets the 'configured' state.
|
||||
|
||||
All registered endpoints are 'realised' and enabled, and the
|
||||
'configured' bit is set in the device status register.
|
||||
|
||||
@param [in] fConfigured If TRUE, configure device, else unconfigure
|
||||
*/
|
||||
void USBHwConfigDevice(BOOL fConfigured)
|
||||
{
|
||||
// set configured bit
|
||||
USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
USB interrupt handler
|
||||
|
||||
@todo Get all 11 bits of frame number instead of just 8
|
||||
|
||||
Endpoint interrupts are mapped to the slow interrupt
|
||||
*/
|
||||
void USBHwISR(void)
|
||||
{
|
||||
u32 dwStatus;
|
||||
u32 dwIntBit;
|
||||
u8 bEPStat, bDevStat, bStat;
|
||||
int i;
|
||||
u16 wFrame;
|
||||
|
||||
// handle device interrupts
|
||||
dwStatus = LPC_USB->USBDevIntSt;
|
||||
|
||||
// frame interrupt
|
||||
if (dwStatus & FRAME) {
|
||||
// clear int
|
||||
LPC_USB->USBDevIntClr = FRAME;
|
||||
// call handler
|
||||
if (_pfnFrameHandler != NULL) {
|
||||
wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR);
|
||||
_pfnFrameHandler(wFrame);
|
||||
}
|
||||
}
|
||||
|
||||
// device status interrupt
|
||||
if (dwStatus & DEV_STAT) {
|
||||
/* Clear DEV_STAT interrupt before reading DEV_STAT register.
|
||||
This prevents corrupted device status reads, see
|
||||
LPC2148 User manual revision 2, 25 july 2006.
|
||||
*/
|
||||
LPC_USB->USBDevIntClr = DEV_STAT;
|
||||
bDevStat = USBHwCmdRead(CMD_DEV_STATUS);
|
||||
if (bDevStat & (CON_CH | SUS_CH | RST)) {
|
||||
// convert device status into something HW independent
|
||||
bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) |
|
||||
((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) |
|
||||
((bDevStat & RST) ? DEV_STATUS_RESET : 0);
|
||||
// call handler
|
||||
if (_pfnDevIntHandler != NULL) {
|
||||
_pfnDevIntHandler(bStat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endpoint interrupt
|
||||
if (dwStatus & EP_SLOW) {
|
||||
// clear EP_SLOW
|
||||
LPC_USB->USBDevIntClr = EP_SLOW;
|
||||
// check all endpoints
|
||||
for (i = 0; i < 32; i++) {
|
||||
dwIntBit = (1 << i);
|
||||
if (LPC_USB->USBEpIntSt & dwIntBit) {
|
||||
// clear int (and retrieve status)
|
||||
LPC_USB->USBEpIntClr = dwIntBit;
|
||||
Wait4DevInt(CDFULL);
|
||||
bEPStat = LPC_USB->USBCmdData;
|
||||
// convert EP pipe stat into something HW independent
|
||||
bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) |
|
||||
((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) |
|
||||
((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) |
|
||||
((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) |
|
||||
((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0);
|
||||
// call handler
|
||||
if (_apfnEPIntHandlers[i / 2] != NULL) {
|
||||
_apfnEPIntHandlers[i / 2](IDX2EP(i), bStat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Initialises the USB hardware
|
||||
|
||||
To make sure this works, I/O pin functions need to be mapped inside
|
||||
the board description as follows:
|
||||
|
||||
* P0.29 USB D+
|
||||
* P0.30 USB D-
|
||||
* P1.18 USB_UP_LED
|
||||
* P2.9 USB CONNECT
|
||||
|
||||
To do this, use a map_pins clause inside the configuration section
|
||||
as follows:
|
||||
|
||||
map_pins = {
|
||||
port = { 0, 0, 1, 2 },
|
||||
pin = { 29, 30, 18, 9 },
|
||||
pinfunction = { 1, 1, 1, 1 }
|
||||
}
|
||||
|
||||
|
||||
@return TRUE if the hardware was successfully initialised
|
||||
*/
|
||||
BOOL USBHwInit(void)
|
||||
{
|
||||
|
||||
|
||||
// enable PUSB
|
||||
LPC_SC->PCONP |= (1 << 31);
|
||||
|
||||
LPC_USB->USBClkCtrl = 0x1A; /* Dev clock, AHB clock enable */
|
||||
while ((LPC_USB->USBClkSt & 0x1A) != 0x1A);
|
||||
|
||||
|
||||
// disable/clear all interrupts for now
|
||||
LPC_USB->USBDevIntEn = 0;
|
||||
LPC_USB->USBDevIntClr = 0xFFFFFFFF;
|
||||
LPC_USB->USBDevIntPri = 0;
|
||||
|
||||
LPC_USB->USBEpIntEn = 0;
|
||||
LPC_USB->USBEpIntClr = 0xFFFFFFFF;
|
||||
LPC_USB->USBEpIntPri = 0;
|
||||
|
||||
// by default, only ACKs generate interrupts
|
||||
USBHwNakIntEnable(0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
87
src/platform/lpc17xx/usbstack/src/usbinit.c
Normal file
87
src/platform/lpc17xx/usbstack/src/usbinit.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
LPCUSB, an USB device driver for LPC microcontrollers
|
||||
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform_conf.h"
|
||||
|
||||
#ifdef BUILD_USB_CDC
|
||||
|
||||
/** @file
|
||||
USB stack initialisation
|
||||
*/
|
||||
|
||||
#include "type.h"
|
||||
|
||||
#include "usbdebug.h"
|
||||
#include "usbapi.h"
|
||||
|
||||
|
||||
/** data storage area for standard requests */
|
||||
static u8 abStdReqData[8];
|
||||
|
||||
|
||||
/**
|
||||
USB reset handler
|
||||
|
||||
@param [in] bDevStatus Device status
|
||||
*/
|
||||
static void HandleUsbReset(u8 bDevStatus)
|
||||
{
|
||||
if (bDevStatus & DEV_STATUS_RESET) {
|
||||
DBG("\n!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialises the USB hardware and sets up the USB stack by
|
||||
installing default callbacks.
|
||||
|
||||
@return TRUE if initialisation was successful
|
||||
*/
|
||||
BOOL USBInit(void)
|
||||
{
|
||||
// init hardware
|
||||
USBHwInit();
|
||||
|
||||
// register bus reset handler
|
||||
USBHwRegisterDevIntHandler(HandleUsbReset);
|
||||
|
||||
// register control transfer handler on EP0
|
||||
USBHwRegisterEPIntHandler(0x00, USBHandleControlTransfer);
|
||||
USBHwRegisterEPIntHandler(0x80, USBHandleControlTransfer);
|
||||
|
||||
// setup control endpoints
|
||||
USBHwEPConfig(0x00, MAX_PACKET_SIZE0);
|
||||
USBHwEPConfig(0x80, MAX_PACKET_SIZE0);
|
||||
|
||||
// register standard request handler
|
||||
USBRegisterRequestHandler(REQTYPE_TYPE_STANDARD, USBHandleStandardRequest, abStdReqData);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
436
src/platform/lpc17xx/usbstack/src/usbstdreq.c
Normal file
436
src/platform/lpc17xx/usbstack/src/usbstdreq.c
Normal file
@ -0,0 +1,436 @@
|
||||
/*
|
||||
LPCUSB, an USB device driver for LPC microcontrollers
|
||||
Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform_conf.h"
|
||||
|
||||
#ifdef BUILD_USB_CDC
|
||||
|
||||
/** @file
|
||||
Standard request handler.
|
||||
|
||||
This modules handles the 'chapter 9' processing, specifically the
|
||||
standard device requests in table 9-3 from the universal serial bus
|
||||
specification revision 2.0
|
||||
|
||||
Specific types of devices may specify additional requests (for example
|
||||
HID devices add a GET_DESCRIPTOR request for interfaces), but they
|
||||
will not be part of this module.
|
||||
|
||||
@todo some requests have to return a request error if device not configured:
|
||||
@todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME
|
||||
@todo this applies to the following if endpoint != 0:
|
||||
@todo SET_FEATURE, GET_FEATURE
|
||||
*/
|
||||
|
||||
#include "type.h"
|
||||
|
||||
#include "usbdebug.h"
|
||||
#include "usbstruct.h"
|
||||
#include "usbapi.h"
|
||||
|
||||
#define MAX_DESC_HANDLERS 4 /**< device, interface, endpoint, other */
|
||||
|
||||
|
||||
/* general descriptor field offsets */
|
||||
#define DESC_bLength 0 /**< length offset */
|
||||
#define DESC_bDescriptorType 1 /**< descriptor type offset */
|
||||
|
||||
/* config descriptor field offsets */
|
||||
#define CONF_DESC_wTotalLength 2 /**< total length offset */
|
||||
#define CONF_DESC_bConfigurationValue 5 /**< configuration value offset */
|
||||
#define CONF_DESC_bmAttributes 7 /**< configuration characteristics */
|
||||
|
||||
/* interface descriptor field offsets */
|
||||
#define INTF_DESC_bAlternateSetting 3 /**< alternate setting offset */
|
||||
|
||||
/* endpoint descriptor field offsets */
|
||||
#define ENDP_DESC_bEndpointAddress 2 /**< endpoint address offset */
|
||||
#define ENDP_DESC_wMaxPacketSize 4 /**< maximum packet size offset */
|
||||
|
||||
|
||||
/** Currently selected configuration */
|
||||
static u8 bConfiguration = 0;
|
||||
/** Installed custom request handler */
|
||||
static TFnHandleRequest *pfnHandleCustomReq = NULL;
|
||||
/** Pointer to registered descriptors */
|
||||
static const u8 *pabDescrip = NULL;
|
||||
|
||||
|
||||
/**
|
||||
Registers a pointer to a descriptor block containing all descriptors
|
||||
for the device.
|
||||
|
||||
@param [in] pabDescriptors The descriptor byte array
|
||||
*/
|
||||
void USBRegisterDescriptors(const u8 *pabDescriptors)
|
||||
{
|
||||
pabDescrip = pabDescriptors;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parses the list of installed USB descriptors and attempts to find
|
||||
the specified USB descriptor.
|
||||
|
||||
@param [in] wTypeIndex Type and index of the descriptor
|
||||
@param [in] wLangID Language ID of the descriptor (currently unused)
|
||||
@param [out] *piLen Descriptor length
|
||||
@param [out] *ppbData Descriptor data
|
||||
|
||||
@return TRUE if the descriptor was found, FALSE otherwise
|
||||
*/
|
||||
BOOL USBGetDescriptor(u16 wTypeIndex, u16 wLangID, int *piLen, u8 **ppbData)
|
||||
{
|
||||
u8 bType, bIndex;
|
||||
u8 *pab;
|
||||
int iCurIndex;
|
||||
|
||||
ASSERT(pabDescrip != NULL);
|
||||
|
||||
bType = GET_DESC_TYPE(wTypeIndex);
|
||||
bIndex = GET_DESC_INDEX(wTypeIndex);
|
||||
|
||||
pab = (u8 *)pabDescrip;
|
||||
iCurIndex = 0;
|
||||
|
||||
while (pab[DESC_bLength] != 0) {
|
||||
if (pab[DESC_bDescriptorType] == bType) {
|
||||
if (iCurIndex == bIndex) {
|
||||
// set data pointer
|
||||
*ppbData = pab;
|
||||
// get length from structure
|
||||
if (bType == DESC_CONFIGURATION) {
|
||||
// configuration descriptor is an exception, length is at offset 2 and 3
|
||||
*piLen = (pab[CONF_DESC_wTotalLength]) |
|
||||
(pab[CONF_DESC_wTotalLength + 1] << 8);
|
||||
}
|
||||
else {
|
||||
// normally length is at offset 0
|
||||
*piLen = pab[DESC_bLength];
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
iCurIndex++;
|
||||
}
|
||||
// skip to next descriptor
|
||||
pab += pab[DESC_bLength];
|
||||
}
|
||||
// nothing found
|
||||
DBG("Desc %x not found!\n", wTypeIndex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configures the device according to the specified configuration index and
|
||||
alternate setting by parsing the installed USB descriptor list.
|
||||
A configuration index of 0 unconfigures the device.
|
||||
|
||||
@param [in] bConfigIndex Configuration index
|
||||
@param [in] bAltSetting Alternate setting number
|
||||
|
||||
@todo function always returns TRUE, add stricter checking?
|
||||
|
||||
@return TRUE if successfully configured, FALSE otherwise
|
||||
*/
|
||||
static BOOL USBSetConfiguration(u8 bConfigIndex, u8 bAltSetting)
|
||||
{
|
||||
u8 *pab;
|
||||
u8 bCurConfig, bCurAltSetting;
|
||||
u8 bEP;
|
||||
u16 wMaxPktSize;
|
||||
|
||||
ASSERT(pabDescrip != NULL);
|
||||
|
||||
if (bConfigIndex == 0) {
|
||||
// unconfigure device
|
||||
USBHwConfigDevice(FALSE);
|
||||
}
|
||||
else {
|
||||
// configure endpoints for this configuration/altsetting
|
||||
pab = (u8 *)pabDescrip;
|
||||
bCurConfig = 0xFF;
|
||||
bCurAltSetting = 0xFF;
|
||||
|
||||
while (pab[DESC_bLength] != 0) {
|
||||
|
||||
switch (pab[DESC_bDescriptorType]) {
|
||||
|
||||
case DESC_CONFIGURATION:
|
||||
// remember current configuration index
|
||||
bCurConfig = pab[CONF_DESC_bConfigurationValue];
|
||||
break;
|
||||
|
||||
case DESC_INTERFACE:
|
||||
// remember current alternate setting
|
||||
bCurAltSetting = pab[INTF_DESC_bAlternateSetting];
|
||||
break;
|
||||
|
||||
case DESC_ENDPOINT:
|
||||
if ((bCurConfig == bConfigIndex) &&
|
||||
(bCurAltSetting == bAltSetting)) {
|
||||
// endpoint found for desired config and alternate setting
|
||||
bEP = pab[ENDP_DESC_bEndpointAddress];
|
||||
wMaxPktSize = (pab[ENDP_DESC_wMaxPacketSize]) |
|
||||
(pab[ENDP_DESC_wMaxPacketSize + 1] << 8);
|
||||
// configure endpoint
|
||||
USBHwEPConfig(bEP, wMaxPktSize);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// skip to next descriptor
|
||||
pab += pab[DESC_bLength];
|
||||
}
|
||||
|
||||
// configure device
|
||||
USBHwConfigDevice(TRUE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Local function to handle a standard device request
|
||||
|
||||
@param [in] pSetup The setup packet
|
||||
@param [in,out] *piLen Pointer to data length
|
||||
@param [in,out] ppbData Data buffer.
|
||||
|
||||
@return TRUE if the request was handled successfully
|
||||
*/
|
||||
static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, u8 **ppbData)
|
||||
{
|
||||
u8 *pbData = *ppbData;
|
||||
|
||||
switch (pSetup->bRequest) {
|
||||
|
||||
case REQ_GET_STATUS:
|
||||
// bit 0: self-powered
|
||||
// bit 1: remote wakeup = not supported
|
||||
pbData[0] = 0;
|
||||
pbData[1] = 0;
|
||||
*piLen = 2;
|
||||
break;
|
||||
|
||||
case REQ_SET_ADDRESS:
|
||||
USBHwSetAddress(pSetup->wValue);
|
||||
break;
|
||||
|
||||
case REQ_GET_DESCRIPTOR:
|
||||
DBG("D%x", pSetup->wValue);
|
||||
return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData);
|
||||
|
||||
case REQ_GET_CONFIGURATION:
|
||||
// indicate if we are configured
|
||||
pbData[0] = bConfiguration;
|
||||
*piLen = 1;
|
||||
break;
|
||||
|
||||
case REQ_SET_CONFIGURATION:
|
||||
if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) {
|
||||
DBG("USBSetConfiguration failed!\n");
|
||||
return FALSE;
|
||||
}
|
||||
// configuration successful, update current configuration
|
||||
bConfiguration = pSetup->wValue & 0xFF;
|
||||
break;
|
||||
|
||||
case REQ_CLEAR_FEATURE:
|
||||
case REQ_SET_FEATURE:
|
||||
if (pSetup->wValue == FEA_REMOTE_WAKEUP) {
|
||||
// put DEVICE_REMOTE_WAKEUP code here
|
||||
}
|
||||
if (pSetup->wValue == FEA_TEST_MODE) {
|
||||
// put TEST_MODE code here
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
case REQ_SET_DESCRIPTOR:
|
||||
DBG("Device req %d not implemented\n", pSetup->bRequest);
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
DBG("Illegal device req %d\n", pSetup->bRequest);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Local function to handle a standard interface request
|
||||
|
||||
@param [in] pSetup The setup packet
|
||||
@param [in,out] *piLen Pointer to data length
|
||||
@param [in] ppbData Data buffer.
|
||||
|
||||
@return TRUE if the request was handled successfully
|
||||
*/
|
||||
static BOOL HandleStdInterfaceReq(TSetupPacket *pSetup, int *piLen, u8 **ppbData)
|
||||
{
|
||||
u8 *pbData = *ppbData;
|
||||
|
||||
switch (pSetup->bRequest) {
|
||||
|
||||
case REQ_GET_STATUS:
|
||||
// no bits specified
|
||||
pbData[0] = 0;
|
||||
pbData[1] = 0;
|
||||
*piLen = 2;
|
||||
break;
|
||||
|
||||
case REQ_CLEAR_FEATURE:
|
||||
case REQ_SET_FEATURE:
|
||||
// not defined for interface
|
||||
return FALSE;
|
||||
|
||||
case REQ_GET_INTERFACE: // TODO use bNumInterfaces
|
||||
// there is only one interface, return n-1 (= 0)
|
||||
pbData[0] = 0;
|
||||
*piLen = 1;
|
||||
break;
|
||||
|
||||
case REQ_SET_INTERFACE: // TODO use bNumInterfaces
|
||||
// there is only one interface (= 0)
|
||||
if (pSetup->wValue != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
*piLen = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
DBG("Illegal interface req %d\n", pSetup->bRequest);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Local function to handle a standard endpoint request
|
||||
|
||||
@param [in] pSetup The setup packet
|
||||
@param [in,out] *piLen Pointer to data length
|
||||
@param [in] ppbData Data buffer.
|
||||
|
||||
@return TRUE if the request was handled successfully
|
||||
*/
|
||||
static BOOL HandleStdEndPointReq(TSetupPacket *pSetup, int *piLen, u8 **ppbData)
|
||||
{
|
||||
u8 *pbData = *ppbData;
|
||||
|
||||
switch (pSetup->bRequest) {
|
||||
case REQ_GET_STATUS:
|
||||
// bit 0 = endpointed halted or not
|
||||
pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0;
|
||||
pbData[1] = 0;
|
||||
*piLen = 2;
|
||||
break;
|
||||
|
||||
case REQ_CLEAR_FEATURE:
|
||||
if (pSetup->wValue == FEA_ENDPOINT_HALT) {
|
||||
// clear HALT by unstalling
|
||||
USBHwEPStall(pSetup->wIndex, FALSE);
|
||||
break;
|
||||
}
|
||||
// only ENDPOINT_HALT defined for endpoints
|
||||
return FALSE;
|
||||
|
||||
case REQ_SET_FEATURE:
|
||||
if (pSetup->wValue == FEA_ENDPOINT_HALT) {
|
||||
// set HALT by stalling
|
||||
USBHwEPStall(pSetup->wIndex, TRUE);
|
||||
break;
|
||||
}
|
||||
// only ENDPOINT_HALT defined for endpoints
|
||||
return FALSE;
|
||||
|
||||
case REQ_SYNCH_FRAME:
|
||||
DBG("EP req %d not implemented\n", pSetup->bRequest);
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
DBG("Illegal EP req %d\n", pSetup->bRequest);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Default handler for standard ('chapter 9') requests
|
||||
|
||||
If a custom request handler was installed, this handler is called first.
|
||||
|
||||
@param [in] pSetup The setup packet
|
||||
@param [in,out] *piLen Pointer to data length
|
||||
@param [in] ppbData Data buffer.
|
||||
|
||||
@return TRUE if the request was handled successfully
|
||||
*/
|
||||
BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, u8 **ppbData)
|
||||
{
|
||||
// try the custom request handler first
|
||||
if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) {
|
||||
case REQTYPE_RECIP_DEVICE: return HandleStdDeviceReq(pSetup, piLen, ppbData);
|
||||
case REQTYPE_RECIP_INTERFACE: return HandleStdInterfaceReq(pSetup, piLen, ppbData);
|
||||
case REQTYPE_RECIP_ENDPOINT: return HandleStdEndPointReq(pSetup, piLen, ppbData);
|
||||
default: return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Registers a callback for custom device requests
|
||||
|
||||
In USBHandleStandardRequest, the custom request handler gets a first
|
||||
chance at handling the request before it is handed over to the 'chapter 9'
|
||||
request handler.
|
||||
|
||||
This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR
|
||||
request is sent to an interface, which is not covered by the 'chapter 9'
|
||||
specification.
|
||||
|
||||
@param [in] pfnHandler Callback function pointer
|
||||
*/
|
||||
void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler)
|
||||
{
|
||||
pfnHandleCustomReq = pfnHandler;
|
||||
}
|
||||
|
||||
#endif
|
52
src/platform/stm32f4/cpu_stm32f411re.h
Normal file
52
src/platform/stm32f4/cpu_stm32f411re.h
Normal file
@ -0,0 +1,52 @@
|
||||
// CPU definition file for STM32F411RE
|
||||
|
||||
#ifndef __CPU_STM32F411RE_H__
|
||||
#define __CPU_STM32F411RE_H__
|
||||
|
||||
#include "type.h"
|
||||
#include "stacks.h"
|
||||
#include "platform_ints.h"
|
||||
|
||||
// Number of resources (0 if not available/not implemented)
|
||||
#define NUM_PIO 5
|
||||
#define NUM_SPI 3
|
||||
#define NUM_UART 3
|
||||
#define NUM_TIMER 12
|
||||
#define NUM_PHYS_TIMER 12
|
||||
#define NUM_PWM 4
|
||||
#define NUM_ADC 18
|
||||
#define NUM_CAN 0
|
||||
|
||||
#define ADC_BIT_RESOLUTION 12
|
||||
|
||||
u32 platform_s_cpu_get_frequency();
|
||||
#define CPU_FREQUENCY platform_s_cpu_get_frequency()
|
||||
|
||||
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
|
||||
#define PIO_PREFIX 'A'
|
||||
// Pins per port configuration:
|
||||
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
|
||||
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
|
||||
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
|
||||
#define PIO_PINS_PER_PORT 16
|
||||
|
||||
// Internal memory data
|
||||
#define INTERNAL_SRAM_BASE 0x20000000
|
||||
#define INTERNAL_SRAM_SIZE ( 128 * 1024 )
|
||||
#define INTERNAL_RAM1_FIRST_FREE end
|
||||
#define INTERNAL_RAM1_LAST_FREE ( INTERNAL_SRAM_BASE + INTERNAL_SRAM_SIZE - STACK_SIZE_TOTAL -1 )
|
||||
|
||||
// Internal Flash data
|
||||
#define INTERNAL_FLASH_SIZE ( 512 * 1024 )
|
||||
#define INTERNAL_FLASH_SECTOR_ARRAY { 16384, 16384, 16384, 16384, 65536, 131072, 131072, 131072 }
|
||||
#define INTERNAL_FLASH_START_ADDRESS 0x08000000
|
||||
|
||||
// Interrupt list for this CPU
|
||||
#define PLATFORM_CPU_CONSTANTS_INTS\
|
||||
_C( INT_GPIO_POSEDGE ), \
|
||||
_C( INT_GPIO_NEGEDGE ), \
|
||||
_C( INT_TMR_MATCH ), \
|
||||
_C( INT_UART_RX ),
|
||||
|
||||
#endif // #ifndef __CPU_STM32F411RE_H__
|
||||
|
Loading…
x
Reference in New Issue
Block a user