1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-11-26 12:45:21 +02:00

atusb/fw3/: adaptation of the f32xbase USB stack

This commit is contained in:
Werner Almesberger 2011-02-13 23:46:36 -03:00
parent f4d299d22b
commit da6677b3d9
9 changed files with 1044 additions and 0 deletions

108
atusb/fw3/Makefile Normal file
View File

@ -0,0 +1,108 @@
#
# Makefile - Makefile of the ATUSB firmware
#
# Written 2010-2011 by Werner Almesberger
# Copyright 2010-2011 by Werner Almesberger
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
SHELL = /bin/bash
NAME = atusb
CFLAGS = -g -Wall -Wextra -Wshadow -Werror -Wno-unused \
-Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes
CHIP=atmega32u2
AVR_PREFIX = $(BIN_PATH) avr-
CC = $(AVR_PREFIX)gcc
OBJCOPY = $(AVR_PREFIX)objcopy
#OBJDUMP = $(AVR_PREFIX)objdump
FreakUSB = usb
#USB_OBJS = usb.o ctrl.o usb_buf.o ep.o hw.o isr.o
USB_OBJS = usb.o
OBJS = atusb.o board.o spi.o descr.o ep0.o $(USB_OBJS)
#vpath %.c $(FreakUSB)/usb/
#vpath %.c $(FreakUSB)/hw/at90usbxx2/
vpath %.c usb2/
CFLAGS += -I../fw/include \
-Iusb2
-DNUM_EPS=1
# -I$(FreakUSB)/usb -I$(FreakUSB)/hw/at90usbxx2 \
# ----- Verbosity control -----------------------------------------------------
CC_normal := $(CC)
BUILD_normal :=
DEPEND_normal := $(CPP) $(CFLAGS) -MM -MG
CC_quiet = @echo " CC " $@ && $(CC_normal)
BUILD_quiet = @echo " BUILD " $@ && $(BUILD_normal)
DEPEND_quiet = @$(DEPEND_normal)
ifeq ($(V),1)
CC = $(CC_normal)
BUILD = $(BUILD_normal)
DEPEND = $(DEPEND_normal)
else
CC = $(CC_quiet)
BUILD = $(BUILD_quiet)
DEPEND = $(DEPEND_quiet)
endif
# ----- Rules -----------------------------------------------------------------
.PHONY: all clean upload prog
all: $(NAME).bin
$(NAME).elf: $(OBJS)
$(CC) $(CFLAGS) -mmcu=$(CHIP) -o $@ $(OBJS)
%.bin: %.elf
$(BUILD) $(OBJCOPY) -j .text -j .data -O binary $< $@
# ----- Cleanup ---------------------------------------------------------------
clean:
rm -f $(NAME).bin $(NAME).elf $(OBJS) $(OBJS:.o=.d)
# ----- Dependencies ----------------------------------------------------------
%.o: %.c
$(CC) $(CFLAGS) -mmcu=$(CHIP) -Os -c $<
$(DEPEND) $< | \
sed -e \
'/^\(.*:\)\? */{p;s///;s/ *\\\?$$/ /;s/ */:\n/g;H;}' \
-e '$${g;p;}' -e d >$*.d; \
[ "$${PIPESTATUS[*]}" = "0 0" ] || { rm -f $*.d; exit 1; }
-include $(OBJS:.o=.d)
# ----- Programming and device control ----------------------------------------
upload: $(NAME).bin
scp $(NAME).bin jlime:
prog:
ssh jlime avrdude -F -p $(CHIP) -c nanonote_atusb -e \
-U flash:w:$(NAME).bin:r \
-U lfuse:w:0x60:m # external clock, slow start-up
on:
ssh jlime poke 0x10010318 4
off:
ssh jlime poke 0x10010314 4
reset:
ssh jlime poke 0x10010318 2048
ssh jlime poke 0x10010314 2048

34
atusb/fw3/atusb.c Normal file
View File

@ -0,0 +1,34 @@
#include <stdint.h>
#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#include "usb.h"
#include "board.h"
#include "spi.h"
#include "atusb/ep0.h"
int main(void)
{
board_init();
spi_init();
reset_rf();
/* now we should be at 8 MHz */
#if 0
led(1);
_delay_ms(100);
led(0);
#endif
usb_init();
ep0_init();
while (1)
usb_poll();
}

54
atusb/fw3/board.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef BOARD_H
#define BOARD_H
#include <stdint.h>
#define LED_PORT B
#define LED_BIT 6
#define nRST_RF_PORT C
#define nRST_RF_BIT 7
#define SLP_TR_PORT B
#define SLP_TR_BIT 4
#define SCLK_PORT D
#define SCLK_BIT 5
#define MOSI_PORT D
#define MOSI_BIT 3
#define MISO_PORT D
#define MISO_BIT 2
#define nSS_PORT D
#define nSS_BIT 1
#define IRQ_RF_PORT D
#define IRQ_RF_BIT 0
#define SET_2(p, b) PORT##p |= 1 << (b)
#define CLR_2(p, b) PORT##p &= ~(1 << (b))
#define IN_2(p, b) DDR##p &= ~(1 << (b))
#define OUT_2(p, b) DDR##p |= 1 << (b)
#define PIN_2(p, b) ((PIN##p >> (b)) & 1)
#define SET_1(p, b) SET_2(p, b)
#define CLR_1(p, b) CLR_2(p, b)
#define IN_1(p, b) IN_2(p, b)
#define OUT_1(p, b) OUT_2(p, b)
#define PIN_1(p, b) PIN_2(p, b)
#define SET(n) SET_1(n##_PORT, n##_BIT)
#define CLR(n) CLR_1(n##_PORT, n##_BIT)
#define IN(n) IN_1(n##_PORT, n##_BIT)
#define OUT(n) OUT_1(n##_PORT, n##_BIT)
#define PIN(n) PIN_1(n##_PORT, n##_BIT)
void reset_rf(void);
uint8_t read_irq(void);
void led(int on);
void panic(void);
void board_init(void);
void rf_init(void);
void rf_send(const char *s);
#endif /* !BOARD_H */

99
atusb/fw3/descr.c Normal file
View File

@ -0,0 +1,99 @@
/*
* atspi/descr.c - USB descriptors
*
* Written 2008-2011 by Werner Almesberger
* Copyright 2008-2011 Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "usb.h"
#define USB_VENDOR 0x20b7 /* Qi Hardware */
#define USB_PRODUCT 0x1540 /* ben-wpan atusb */
#define LE(x) ((uint16_t) (x) & 0xff), ((uint16_t) (x) >> 8)
/*
* Device descriptor
*/
const uint8_t device_descriptor[18] = {
18, /* bLength */
USB_DT_DEVICE, /* bDescriptorType */
LE(0x200), /* bcdUSB */
USB_CLASS_VENDOR_SPEC, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
EP0_SIZE, /* bMaxPacketSize */
LE(USB_VENDOR), /* idVendor */
LE(USB_PRODUCT), /* idProduct */
LE(0x0001), /* bcdDevice */
0, /* iManufacturer */
0, /* iProduct */
0, /* iSerialNumber */
1 /* bNumConfigurations */
};
/*
* Our configuration
*
* We're always bus-powered.
*/
const uint8_t config_descriptor[] = {
9, /* bLength */
USB_DT_CONFIG, /* bDescriptorType */
#if 0
LE(9+9+7+7), /* wTotalLength */
#else
LE(9+9), /* wTotalLength */
#endif
1, /* bNumInterfaces */
1, /* bConfigurationValue (> 0 !) */
0, /* iConfiguration */
USB_ATTR_BUS_POWERED, /* bmAttributes */
50/2, /* bMaxPower (50 mA) */
/* Interface #0 */
9, /* bLength */
USB_DT_INTERFACE, /* bDescriptorType */
0, /* bInterfaceNumber */
0, /* bAlternateSetting */
#if 0
2, /* bNumEndpoints */
#else
0,
#endif
USB_CLASS_VENDOR_SPEC, /* bInterfaceClass */
0, /* bInterfaceSubClass */
0, /* bInterfaceProtocol */
0, /* iInterface */
#if 0
/* EP OUT */
7, /* bLength */
USB_DT_ENDPOINT, /* bDescriptorType */
0x01, /* bEndPointAddress */
0x02, /* bmAttributes (bulk) */
LE(EP1_SIZE), /* wMaxPacketSize */
0, /* bInterval */
/* EP IN */
7, /* bLength */
USB_DT_ENDPOINT, /* bDescriptorType */
0x81, /* bEndPointAddress */
0x02, /* bmAttributes (bulk) */
LE(EP1_SIZE), /* wMaxPacketSize */
0, /* bInterval */
#endif
};

194
atusb/fw3/ep0.c Normal file
View File

@ -0,0 +1,194 @@
/*
* atspi/ep0.c - EP0 extension protocol
*
* Written 2008-2010 by Werner Almesberger
* Copyright 2008-2010 Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdint.h>
#include <avr/io.h>
#ifndef NULL
#define NULL 0
#endif
//#include "regs.h"
//#include "uart.h"
//#include "usb.h"
#include "usb.h"
#include "at86rf230.h"
#include "atusb/ep0.h"
//#include "version.h"
#include "board.h"
#include "spi.h"
#define HW_TYPE HW_TYPE_110131
static const char *build_date = "today";
static unsigned build_number = 42;
#define debug(...)
#define error(...)
static const uint8_t id[] = { EP0ATUSB_MAJOR, EP0ATUSB_MINOR, HW_TYPE };
static uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQI */
static uint8_t size;
static void do_buf_write(void *user)
{
uint8_t i;
spi_begin();
for (i = 0; i != size; i++)
spi_send(buf[i]);
spi_end();
}
#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */
static int my_setup(struct setup_request *setup)
{
unsigned tmp;
uint8_t i;
switch (setup->bmRequestType | setup->bRequest << 8) {
case ATUSB_FROM_DEV(ATUSB_ID):
debug("ATUSB_ID\n");
if (setup->wLength > 3)
return 0;
usb_send(&eps[0], id, setup->wLength, NULL, NULL);
return 1;
case ATUSB_FROM_DEV(ATUSB_BUILD):
debug("ATUSB_BUILD\n");
tmp = build_number;
for (i = BUILD_OFFSET-2; tmp; i--) {
buf[i] = (tmp % 10)+'0';
tmp /= 10;
}
buf[i] = '#';
buf[BUILD_OFFSET-1] = ' ';
for (size = 0; build_date[size]; size++)
buf[BUILD_OFFSET+size] = build_date[size];
size += BUILD_OFFSET-i;
if (size > setup->wLength)
return 0;
usb_send(&eps[0], buf+i, size, NULL, NULL);
return 1;
#ifdef NOTYET
case ATUSB_TO_DEV(ATUSB_RESET):
debug("ATUSB_RESET\n");
RSTSRC = SWRSF;
while (1);
#endif
case ATUSB_TO_DEV(ATUSB_RF_RESET):
debug("ATUSB_RF_RESET\n");
reset_rf();
//ep_send_zlp(EP_CTRL);
return 1;
case ATUSB_FROM_DEV(ATUSB_POLL_INT):
debug("ATUSB_POLL_INT\n");
if (setup->wLength < 1)
return 0;
*buf = read_irq();
usb_send(&eps[0], buf, 1, NULL, NULL);
return 1;
case ATUSB_TO_DEV(ATUSB_REG_WRITE):
debug("ATUSB_REG_WRITE\n");
spi_begin();
spi_send(AT86RF230_REG_WRITE | setup->wIndex);
spi_send(setup->wValue);
spi_end();
//ep_send_zlp(EP_CTRL);
return 1;
case ATUSB_FROM_DEV(ATUSB_REG_READ):
debug("ATUSB_REG_READ\n");
spi_begin();
spi_send(AT86RF230_REG_READ | setup->wIndex);
*buf = spi_recv();
spi_end();
usb_send(&eps[0], buf, 1, NULL, NULL);
return 1;
case ATUSB_TO_DEV(ATUSB_BUF_WRITE):
debug("ATUSB_BUF_WRITE\n");
if (setup->wLength < 1)
return 0;
if (setup->wLength > MAX_PSDU)
return 0;
buf[0] = AT86RF230_BUF_WRITE;
buf[1] = setup->wLength;
size = setup->wLength+2;
usb_recv(&eps[0], buf+2, setup->wLength, do_buf_write, NULL);
return 1;
case ATUSB_FROM_DEV(ATUSB_BUF_READ):
debug("ATUSB_BUF_READ\n");
if (setup->wLength < 2) /* PHR+LQI */
return 0;
if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQI */
return 0;
spi_begin();
spi_send(AT86RF230_BUF_READ);
size = spi_recv();
if (size >= setup->wLength)
size = setup->wLength-1;
for (i = 0; i != size+1; i++)
buf[i] = spi_recv();
spi_end();
usb_send(&eps[0], buf, size+1, NULL, NULL);
return 1;
case ATUSB_TO_DEV(ATUSB_SRAM_WRITE):
debug("ATUSB_SRAM_WRITE\n");
if (setup->wIndex > SRAM_SIZE)
return 0;
if (setup->wIndex+setup->wLength > SRAM_SIZE)
return 0;
buf[0] = AT86RF230_SRAM_WRITE;
buf[1] = setup->wIndex;
size = setup->wLength+2;
usb_recv(&eps[0], buf+2, setup->wLength, do_buf_write, NULL);
return 1;
case ATUSB_TO_DEV(ATUSB_SRAM_READ):
debug("ATUSB_SRAM_READ\n");
if (setup->wIndex > SRAM_SIZE)
return 0;
if (setup->wIndex+setup->wLength > SRAM_SIZE)
return 0;
spi_begin();
spi_send(AT86RF230_SRAM_READ);
spi_send(setup->wIndex);
for (i = 0; i != size; i++)
buf[i] = spi_recv();
spi_end();
usb_send(&eps[0], buf, size, NULL, NULL);
return 1;
default:
error("Unrecognized SETUP: 0x%02x 0x%02x ...\n",
setup->bmRequestType, setup->bRequest);
return 0;
}
}
void ep0_init(void)
{
user_setup = my_setup;
}

45
atusb/fw3/spi.c Normal file
View File

@ -0,0 +1,45 @@
#include <stdint.h>
#include <avr/io.h>
#include "board.h"
#include "spi.h"
void spi_begin(void)
{
CLR(nSS);
}
uint8_t spi_io(uint8_t v)
{
// while (!(UCSR1A & 1 << UDRE1));
UDR1 = v;
while (!(UCSR1A & 1 << RXC1));
return UDR1;
}
void spi_end(void)
{
// while (!(UCSR1A & 1 << TXC1));
SET(nSS);
}
void spi_init(void)
{
SET(nSS);
OUT(SCLK);
OUT(MOSI);
OUT(nSS);
IN(MISO);
UBRR1 = 0; /* set bit rate to zero to begin */
UCSR1C = 1 << UMSEL11 | 1 << UMSEL10;
/* set MSPI, MSB first, SPI data mode 0 */
UCSR1B = 1 << RXEN1 | 1 << TXEN1;
/* enable receiver and transmitter */
UBRR1 = 0; /* reconfirm the bit rate */
}

15
atusb/fw3/spi.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef SPI_H
#define SPI_H
#include <stdint.h>
void spi_begin(void);
uint8_t spi_io(uint8_t v);
void spi_end(void);
void spi_init(void);
#define spi_send(v) (void) spi_io(v)
#define spi_recv(v) spi_io(0)
#endif /* !SPI_H */

349
atusb/fw3/usb2/usb.c Normal file
View File

@ -0,0 +1,349 @@
/*
* u/usb.c - USB hardware setup and standard device requests
*
* Written 2008-2011 by Werner Almesberger
* Copyright 2008-2011 Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
/*
* Known issues:
* - no suspend/resume
* - EP0-sized packets cause an (otherwise harmless) SUEND at the end of the
* packet
* - #ifdef hell
*/
/*
* This code follows the register read/write sequences from the examples in
* SiLabs/MCU/Examples/C8051F326_7/USB_Interrupt/Firmware/F326_USB_Main.c and
* SiLabs/MCU/Examples/C8051F326_7/USB_Interrupt/Firmware/F326_USB_ISR.c
*
* More resources:
* http://www.beyondlogic.org/usbnutshell/usb1.htm
*/
#include <stdint.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/io.h>
#include "usb.h"
#include "../board.h"
#ifndef NULL
#define NULL 0
#endif
#define NUM_EPS 1
#if 1
extern void panic(void);
#define BUG_ON(cond) do { if (cond) panic(); } while (0)
#else
#define BUG_ON(cond)
#endif
struct ep_descr eps[5];
int (*user_setup)(struct setup_request *setup);
int (*user_get_descriptor)(uint8_t type, uint8_t index,
const uint8_t * const *reply, uint8_t *size);
void (*user_reset)(void);
static uint8_t addr;
void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf,
uint8_t size, void (*callback)(void *user), void *user)
{
BUG_ON(ep->state);
ep->state = state;
ep->buf = buf;
ep->end = buf+size;
ep->callback = callback;
ep->user = user;
}
static uint16_t usb_read_word(void)
{
uint8_t low;
low = UEDATX;
return low | UEDATX << 8;
}
static int get_descriptor(uint8_t type, uint8_t index, uint16_t length)
{
const uint8_t *reply;
uint8_t size;
switch (type) {
case USB_DT_DEVICE:
reply = device_descriptor;
size = reply[0];
break;
case USB_DT_CONFIG:
if (index)
return 0;
reply = config_descriptor;
size = reply[2];
break;
default:
if (!user_get_descriptor)
return 0;
if (!user_get_descriptor(type, index, &reply, &size))
return 0;
}
if (length < size)
size = length;
usb_send(&eps[0], reply, size, NULL, NULL);
return 1;
}
static void enable_addr(void *user)
{
while (!(UEINTX & (1 << TXINI)));
UDADDR = addr | 1 << ADDEN;
}
/*
* Process a SETUP packet. Hardware ensures that length is 8 bytes.
*/
static int handle_setup(void)
{
struct setup_request setup;
BUG_ON(UEBCLX < 8);
setup.bmRequestType = UEDATX;
setup.bRequest = UEDATX;
setup.wValue = usb_read_word();
setup.wIndex = usb_read_word();
setup.wLength = usb_read_word();
// UEINTX &= ~(1 << RXSTPI);
switch (setup.bmRequestType | setup.bRequest << 8) {
/*
* Device request
*
* See http://www.beyondlogic.org/usbnutshell/usb6.htm
*/
case FROM_DEVICE(GET_STATUS):
if (setup.wLength != 2)
return 0;
usb_send(&eps[0], "\000", 2, NULL, NULL);
break;
case TO_DEVICE(CLEAR_FEATURE):
break;
case TO_DEVICE(SET_FEATURE):
return 0;
case TO_DEVICE(SET_ADDRESS):
addr = setup.wValue;
UDADDR = addr;
usb_send(&eps[0], NULL, 0, enable_addr, NULL);
break;
case FROM_DEVICE(GET_DESCRIPTOR):
if (!get_descriptor(setup.wValue >> 8, setup.wValue,
setup.wLength))
return 0;
break;
case TO_DEVICE(SET_DESCRIPTOR):
return 0;
case FROM_DEVICE(GET_CONFIGURATION):
usb_send(&eps[0], "", 1, NULL, NULL);
break;
case TO_DEVICE(SET_CONFIGURATION):
if (setup.wValue != config_descriptor[5])
return 0;
break;
/*
* Interface request
*/
case FROM_INTERFACE(GET_STATUS):
return 0;
case TO_INTERFACE(CLEAR_FEATURE):
return 0;
case TO_INTERFACE(SET_FEATURE):
return 0;
case FROM_INTERFACE(GET_INTERFACE):
return 0;
case TO_INTERFACE(SET_INTERFACE):
{
const uint8_t *interface_descriptor =
config_descriptor+9;
if (setup.wIndex != interface_descriptor[2] ||
setup.wValue != interface_descriptor[3])
return 0;
}
break;
/*
* Endpoint request
*/
case FROM_ENDPOINT(GET_STATUS):
return 0;
case TO_ENDPOINT(CLEAR_FEATURE):
return 0;
case TO_ENDPOINT(SET_FEATURE):
return 0;
case FROM_ENDPOINT(SYNCH_FRAME):
return 0;
default:
if (!user_setup)
return 0;
if (!user_setup(&setup))
return 0;
}
if (!(setup.bmRequestType & 0x80) && eps[0].state == EP_IDLE)
usb_send(&eps[0], NULL, 0, NULL, NULL);
return 1;
}
static int ep_rx(struct ep_descr *ep)
{
uint8_t size;
size = UEBCLX;
if (size > ep->end-ep->buf)
return 0;
while (size--)
*ep->buf++ = UEDATX;
if (ep->buf == ep->end) {
ep->state = EP_IDLE;
if (ep->callback)
ep->callback(ep->user);
if (ep == &eps[0])
usb_send(ep, NULL, 0, NULL, NULL);
}
return 1;
}
static void ep_tx(struct ep_descr *ep)
{
uint8_t size = ep->end-ep->buf;
uint8_t left;
if (size > ep->size)
size = ep->size;
for (left = size; left; left--)
UEDATX = *ep->buf++;
if (size == ep->size)
return;
ep->state = EP_IDLE;
}
static void handle_ep(int n)
{
struct ep_descr *ep = eps+n;
int res;
UENUM = n;
if (UEINTX & (1 << RXSTPI)) {
/* @@@ EP_RX. EP_TX: cancel */
if (!handle_setup())
goto stall;
UEINTX &= ~(1 << RXSTPI);
}
if (UEINTX & (1 << RXOUTI)) {
/* @@ EP_TX: cancel */
if (ep->state != EP_RX)
goto stall;
if (!ep_rx(ep))
goto stall;
// UEINTX &= ~(1 << RXOUTI);
UEINTX &= ~(1 << RXOUTI | 1 << FIFOCON);
}
if (UEINTX & (1 << STALLEDI)) {
ep->state = EP_IDLE;
UEINTX &= ~(1 << STALLEDI);
}
if (UEINTX & (1 << TXINI)) {
/* @@ EP_RX: cancel */
if (ep->state == EP_TX) {
ep_tx(ep);
UEINTX &= ~(1 << TXINI);
if (ep->state == EP_IDLE && ep->callback)
ep->callback(ep->user);
}
}
return;
stall:
UEINTX &= ~(1 << RXSTPI | 1 << RXOUTI | 1 << STALLEDI);
ep->state = EP_IDLE;
UECONX |= 1 << STALLRQ;
}
void usb_poll(void)
{
uint8_t flags, i;
flags = UEINT;
for (i = 0; i != NUM_EPS; i++)
if (1 || flags & (1 << i))
handle_ep(i);
/* @@@ USB bus reset */
}
static void ep_init(void)
{
UENUM = 0;
UECONX = (1 << RSTDT) | (1 << EPEN); /* enable */
UECFG0X = 0; /* control, direction is ignored */
UECFG1X = 3 << EPSIZE0; /* 64 bytes */
UECFG1X |= 1 << ALLOC;
while (!(UESTA0X & (1 << CFGOK)));
eps[0].state = EP_IDLE;
eps[0].size = 64;
}
void usb_init(void)
{
USBCON |= 1 << FRZCLK; /* freeze the clock */
/* enable the PLL and wait for it to lock */
PLLCSR &= ~(1 << PLLP2 | 1 << PLLP1 | 1 << PLLP0);
PLLCSR |= 1 << PLLE;
while (!(PLLCSR & (1 << PLOCK)));
USBCON &= ~(1 << USBE); /* reset the controller */
USBCON |= 1 << USBE;
USBCON &= ~(1 << FRZCLK); /* thaw the clock */
UDCON &= ~(1 << DETACH); /* attach the pull-up */
UDCON |= 1 << RSTCPU; /* reset CPU on bus reset */
ep_init();
}

146
atusb/fw3/usb2/usb.h Normal file
View File

@ -0,0 +1,146 @@
/*
* common/usb.h - USB hardware setup and standard device requests
*
* Written 2008, 2009 by Werner Almesberger
* Copyright 2008, 2009 Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef USB_H
#define USB_H
#include <stdint.h>
/*
* Descriptor types
*
* Reuse libusb naming scheme (/usr/include/usb.h)
*/
#define USB_DT_DEVICE 1
#define USB_DT_CONFIG 2
#define USB_DT_STRING 3
#define USB_DT_INTERFACE 4
#define USB_DT_ENDPOINT 5
/*
* Device classes
*
* Reuse libusb naming scheme (/usr/include/usb.h)
*/
#define USB_CLASS_PER_INTERFACE 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
/*
* Configuration attributes
*/
#define USB_ATTR_BUS_POWERED 0x80
#define USB_ATTR_SELF_POWERED 0x40
#define USB_ATTR_REMOTE_WAKEUP 0x20
/*
* Setup request types
*/
#define TO_DEVICE(req) (0x00 | (req) << 8)
#define FROM_DEVICE(req) (0x80 | (req) << 8)
#define TO_INTERFACE(req) (0x01 | (req) << 8)
#define FROM_INTERFACE(req) (0x81 | (req) << 8)
#define TO_ENDPOINT(req) (0x02 | (req) << 8)
#define FROM_ENDPOINT(req) (0x82 | (req) << 8)
/*
* Setup requests
*/
#define GET_STATUS 0x00
#define CLEAR_FEATURE 0x01
#define SET_FEATURE 0x03
#define SET_ADDRESS 0x05
#define GET_DESCRIPTOR 0x06
#define SET_DESCRIPTOR 0x07
#define GET_CONFIGURATION 0x08
#define SET_CONFIGURATION 0x09
#define GET_INTERFACE 0x0a
#define SET_INTERFACE 0x0b
#define SYNCH_FRAME 0x0c
/*
* Odd. sdcc seems to think "x" assumes the size of the destination, i.e.,
* uint8_t. Hence the cast.
*/
#define LE(x) ((uint16_t) (x) & 0xff), ((uint16_t) (x) >> 8)
#define LO(x) (((uint8_t *) &(x))[0])
#define HI(x) (((uint8_t *) &(x))[1])
#ifdef LOW_SPEED
#define EP0_SIZE 8
#else
#define EP0_SIZE 64
#endif
#define EP1_SIZE 64 /* simplify */
enum ep_state {
EP_IDLE,
EP_RX,
EP_TX,
EP_STALL,
};
struct ep_descr {
enum ep_state state;
uint8_t *buf;
uint8_t *end;
uint8_t size;
void (*callback)(void *user);
void *user;
};
struct setup_request {
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
};
extern const uint8_t device_descriptor[];
extern const uint8_t config_descriptor[];
extern struct ep_descr eps[];
extern int (*user_setup)(struct setup_request *setup);
extern int (*user_get_descriptor)(uint8_t type, uint8_t index,
const uint8_t * const *reply, uint8_t *size);
extern void (*user_reset)(void);
#define usb_left(ep) ((ep)->end-(ep)->buf)
#define usb_send(ep, buf, size, callback, user) \
usb_io(ep, EP_TX, (void *) buf, size, callback, user)
#define usb_recv(ep, buf, size, callback, user) \
usb_io(ep, EP_RX, buf, size, callback, user)
void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf,
uint8_t size, void (*callback)(void *user), void *user);
void usb_init(void);
void usb_poll(void);
#endif /* !USB_H */