From 8c57277953e9d1b3f63ef55853f4ca1abee225a2 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Sun, 29 May 2011 21:05:28 -0300 Subject: [PATCH] atusb/fw/: added free-running 48 bit 8 MHz counter for clock measurements - atusb.c (main): poll the 16 bit timer for overflows - board.h (timer_poll, timer_read), (board.c (timer_h, timer_poll, timer_read, board_init): added support for a free-running 48 bit timer (16 bits in hardware, 32 bits in software) - include/atusb/ep0.h (ATUSB_TIMER), ep0.c (my_setup): new request ATUSB_TIMER to retrieve the value of the 8 MHz counter - include/atusb/ep0.h (enum atspi_requests): describe what the groups of requests do --- atusb/fw/atusb.c | 4 +++- atusb/fw/board.c | 38 ++++++++++++++++++++++++++++++++++++ atusb/fw/board.h | 3 +++ atusb/fw/ep0.c | 12 ++++++++++++ atusb/fw/include/atusb/ep0.h | 10 ++++++---- 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/atusb/fw/atusb.c b/atusb/fw/atusb.c index 831001e..8e9fed6 100644 --- a/atusb/fw/atusb.c +++ b/atusb/fw/atusb.c @@ -36,6 +36,8 @@ int main(void) usb_init(); ep0_init(); - while (1) + while (1) { usb_poll(); + timer_poll(); + } } diff --git a/atusb/fw/board.c b/atusb/fw/board.c index 4bd3e82..b4e06b4 100644 --- a/atusb/fw/board.c +++ b/atusb/fw/board.c @@ -29,6 +29,9 @@ uint8_t board_sernum[42] = { 42, USB_DT_STRING }; +static uint32_t timer_h = 0; /* 2^(16+32) / 8 MHz = ~1.1 years */ + + static void set_clkm(void) { /* switch CLKM to 8 MHz */ @@ -99,6 +102,36 @@ void panic(void) } +void timer_poll(void) +{ + if (!(TIFR1 & (1 << TOV1))) + return; + TIFR1 = 1 << TOV1; + timer_h++; +} + + +uint64_t timer_read(void) +{ + uint32_t high; + uint8_t low, mid; + + do { + timer_poll(); + high = timer_h; + low = TCNT1L; + mid = TCNT1H; + } + while (TIFR1 & (1 << TOV1)); + + /* + * We need all these casts because the intermediate results are handled + * as if they were signed and thus get sign-expanded. Sounds wrong-ish. + */ + return (uint64_t) high << 16 | (uint64_t) mid << 8 | (uint64_t) low; +} + + static char hex(uint8_t nibble) { return nibble < 10 ? '0'+nibble : 'a'+nibble-10; @@ -138,5 +171,10 @@ void board_init(void) OUT(nRST_RF); /* this also resets the transceiver */ OUT(SLP_TR); + /* configure timer 1 as a free-running CLK counter */ + + TCCR1A = 0; + TCCR1B = 1 << CS10; + get_sernum(); } diff --git a/atusb/fw/board.h b/atusb/fw/board.h index cecf7aa..f37b47f 100644 --- a/atusb/fw/board.h +++ b/atusb/fw/board.h @@ -74,6 +74,9 @@ uint8_t read_irq(void); void led(int on); void panic(void); +void timer_poll(void); +uint64_t timer_read(void); + void board_init(void); #endif /* !BOARD_H */ diff --git a/atusb/fw/ep0.c b/atusb/fw/ep0.c index e456be5..689e79b 100644 --- a/atusb/fw/ep0.c +++ b/atusb/fw/ep0.c @@ -12,6 +12,7 @@ #include +#include #include @@ -57,6 +58,7 @@ static int my_setup(const struct setup_request *setup) { unsigned tmp; uint8_t i; + uint64_t tmp64; switch (setup->bmRequestType | setup->bRequest << 8) { case ATUSB_FROM_DEV(ATUSB_ID): @@ -101,6 +103,16 @@ static int my_setup(const struct setup_request *setup) usb_send(&eps[0], buf, 1, NULL, NULL); return 1; + case ATUSB_FROM_DEV(ATUSB_TIMER): + debug("ATUSB_TIMER\n"); + size = setup->wLength; + if (size > sizeof(tmp64)) + size = sizeof(tmp64); + tmp64 = timer_read(); + memcpy(buf, &tmp64, sizeof(tmp64)); + usb_send(&eps[0], buf, size, NULL, NULL); + return 1; + case ATUSB_TO_DEV(ATUSB_REG_WRITE): debug("ATUSB_REG_WRITE\n"); spi_begin(); diff --git a/atusb/fw/include/atusb/ep0.h b/atusb/fw/include/atusb/ep0.h index 382aa92..e471454 100644 --- a/atusb/fw/include/atusb/ep0.h +++ b/atusb/fw/include/atusb/ep0.h @@ -24,6 +24,7 @@ * host-> ATUSB_RF_RESET - - 0 * ->host ATUSB_POLL_INT - - 1 * host-> ATUSB_TEST - - 0 + * ->host ATUSB_TIMER - - #bytes (6) * * host-> ATUSB_REG_WRITE value addr 0 * ->host ATUSB_REG_READ - addr 1 @@ -64,13 +65,14 @@ enum atspi_requests { - ATUSB_ID = 0x00, + ATUSB_ID = 0x00, /* system status/control grp */ ATUSB_BUILD, ATUSB_RESET, - ATUSB_RF_RESET = 0x10, + ATUSB_RF_RESET = 0x10, /* debug/test group */ ATUSB_POLL_INT, - ATUSB_TEST, - ATUSB_REG_WRITE = 0x20, + ATUSB_TEST, /* atusb-sil only */ + ATUSB_TIMER, + ATUSB_REG_WRITE = 0x20, /* transceiver group */ ATUSB_REG_READ, ATUSB_BUF_WRITE, ATUSB_BUF_READ,