From 5514c336a503d1b7febfaeec78b71d956c75d928 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Mon, 23 Aug 2010 19:56:02 -0300 Subject: [PATCH] Completed the basic counter firmware. Now it just has to work ... - cntr/fw/cntr/Makefile, cntr/fw/cntr/descr.c, cntr/fw/cntr/ep0.c: enabled the usual USB stack - cntr/fw/cntr/cntr.c: initialize and poll USB - cntr/fw/cntr/cntr.c, cntr/fw/cntr/ep0.c: added counter application - cntr/fw/common/config.h (PLATFORM_SETUP): enable the crossbar --- cntr/fw/cntr/Makefile | 2 +- cntr/fw/cntr/cntr.c | 51 ++++++++++++++++- cntr/fw/cntr/descr.c | 68 +++++++++++++++++++++++ cntr/fw/cntr/ep0.c | 119 ++++++++++++++++++++++++++++++++++++++++ cntr/fw/common/config.h | 5 +- 5 files changed, 239 insertions(+), 6 deletions(-) create mode 100644 cntr/fw/cntr/descr.c create mode 100644 cntr/fw/cntr/ep0.c diff --git a/cntr/fw/cntr/Makefile b/cntr/fw/cntr/Makefile index 1ad1b53..e75c096 100644 --- a/cntr/fw/cntr/Makefile +++ b/cntr/fw/cntr/Makefile @@ -12,7 +12,7 @@ MAIN = cntr -OBJS = $(MAIN) # usb descr version ep0 +OBJS = $(MAIN) usb descr version ep0 F32XBASE = ../../../../f32xbase diff --git a/cntr/fw/cntr/cntr.c b/cntr/fw/cntr/cntr.c index bbbe529..9bd8ead 100644 --- a/cntr/fw/cntr/cntr.c +++ b/cntr/fw/cntr/cntr.c @@ -11,6 +11,8 @@ */ +#include + #include "regs.h" #include "io.h" #include "usb.h" @@ -18,6 +20,16 @@ #include "version.h" +/* + * Free-running 32 bit counter. The lower two bytes are from hardware Timer 0. + * The upper two bytes are maintained by software. At the maximum input clock + * frequency of 6 MHz, it wraps around every 11.9 minutes, leaving the host + * plenty of time to read it. + */ + +uint8_t cntr[4]; + + static void init_io(void) { /* @@ -46,14 +58,47 @@ static void init_io(void) } +static void setup_counter(void) +{ + TCON = TR0; /* enable Timer 0 */ + TMOD = C_T0 | T0M0; /* clock from T0, mode 1: 16 bit counter */ + + XBR1 |= T0E; /* route T0 to port */ + + P0SKIP = 0x7f; /* assign T0 to P0_7 */ +} + + +static void read_counter(void) +{ + uint8_t th; + + th = TH0; + while (1) { + cntr[0] = TL0; + if (th == TH0) + break; + th = TH0; + } + if (th < cntr[1]) { + cntr[2]++; + if (!cntr[2]) + cntr[3]++; + } + cntr[1] = th; +} + + void main(void) { init_io(); + setup_counter(); -// usb_init(); -// ep0_init(); + usb_init(); + ep0_init(); while (1) { -// usb_poll(); + read_counter(); + usb_poll(); } } diff --git a/cntr/fw/cntr/descr.c b/cntr/fw/cntr/descr.c new file mode 100644 index 0000000..2646add --- /dev/null +++ b/cntr/fw/cntr/descr.c @@ -0,0 +1,68 @@ +/* + * atspi/descr.c - USB descriptors + * + * 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 "usb.h" + +#include "config.h" + + +/* + * 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 */ + LE(9+9), /* wTotalLength */ + 1, /* bNumInterfaces */ + 1, /* bConfigurationValue (> 0 !) */ + 0, /* iConfiguration */ + USB_ATTR_BUS_POWERED, /* bmAttributes */ + 15, /* bMaxPower */ + + /* Interface #0 */ + + 9, /* bLength */ + USB_DT_INTERFACE, /* bDescriptorType */ + 0, /* bInterfaceNumber */ + 0, /* bAlternateSetting */ + 0, /* bNumEndpoints */ + USB_CLASS_VENDOR_SPEC, /* bInterfaceClass */ + 0, /* bInterfaceSubClass */ + 0, /* bInterfaceProtocol */ + 0, /* iInterface */ +}; diff --git a/cntr/fw/cntr/ep0.c b/cntr/fw/cntr/ep0.c new file mode 100644 index 0000000..098b305 --- /dev/null +++ b/cntr/fw/cntr/ep0.c @@ -0,0 +1,119 @@ +/* + * cntr/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 + +#ifndef NULL +#define NULL 0 +#endif + +#include "regs.h" +#include "usb.h" +#include "cntr/ep0.h" +#include "version.h" + + +#define debug(...) +#define error(...) + + +/* + * SDCC 2.8.0 had a number of code generation bugs that appeared in the big + * switch statement of my_setup. SDCC_FORCE_UPDATE forced the value of the + * "size" variable to be written to memory. This work-around doesn't seem + * to be necessary with 2.9.0, but we keep it around, just in case. + * + * Unfortunately, the setup->bRequest garbling bug is still with us. Without + * the evaluation forced with SDCC_FORCE_EVAL, sdcc gets confused about the + * value of setup->bRequest and then rejects all SETUP requests. + */ + +#define SDCC_FORCE_EVAL(type, value) \ + do { \ + static volatile type foo; \ + foo = value; \ + } while (0) + +#define SDCC_FORCE_UPDATE(type, var) \ + do { \ + volatile type foo; \ + foo = var; \ + var = foo; \ + } while (0) + + +extern uint8_t cntr[8]; + +static const uint8_t id[] = { EP0CNTR_MAJOR, EP0CNTR_MINOR, HW_TYPE }; +static __xdata uint8_t buf[128]; + + +#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */ + + +static __bit my_setup(struct setup_request *setup) __reentrant +{ + unsigned tmp; + uint8_t size, i; + + switch (setup->bmRequestType | setup->bRequest << 8) { + case CNTR_FROM_DEV(CNTR_ID): + debug("CNTR_ID\n"); + if (setup->wLength > 3) + return 0; + usb_send(&ep0, id, setup->wLength, NULL, NULL); + return 1; + case CNTR_FROM_DEV(CNTR_BUILD): + debug("CNTR_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+1; + SDCC_FORCE_EVAL(uint8_t, setup->bRequest); + if (size > setup->wLength) + return 0; + usb_send(&ep0, buf+i, size, NULL, NULL); + return 1; + + case CNTR_TO_DEV(CNTR_RESET): + debug("CNTR_RESET\n"); + RSTSRC = SWRSF; + while (1); + + case CNTR_FROM_DEV(CNTR_READ): + debug("CNTR_READ\n"); + buf[0] = cntr[0]; + buf[1] = cntr[1]; + buf[2] = cntr[2]; + buf[3] = cntr[3]; + usb_send(&ep0, buf, 4, 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; +} diff --git a/cntr/fw/common/config.h b/cntr/fw/common/config.h index 4e3c280..2f6850e 100644 --- a/cntr/fw/common/config.h +++ b/cntr/fw/common/config.h @@ -25,8 +25,9 @@ * This turns on the LED, to indicate that we're in the boot loader. */ -#define PLATFORM_SETUP \ - LED_MODE |= 1 << LED_BIT; +#define PLATFORM_SETUP \ + LED_MODE |= 1 << LED_BIT; \ + XBR1 = XBARE; /*