From 62284fb78e80ed515a9a51b81aa15a16a273f33f Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Thu, 24 Jan 2013 18:26:34 -0300 Subject: [PATCH] ubb-la/ubb-la.c: add command-line options, keyboard abort --- ubb-la/ubb-la.c | 119 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 103 insertions(+), 16 deletions(-) diff --git a/ubb-la/ubb-la.c b/ubb-la/ubb-la.c index 18331f7..28aef61 100644 --- a/ubb-la/ubb-la.c +++ b/ubb-la/ubb-la.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,8 @@ #define DMA 5 +#define KEY_MASK 0x5fc0000 + /* ----- Enable/disable interrupts ----------------------------------------- */ @@ -103,7 +106,8 @@ static void wait_dma_done(void) /* ----- MMC control ------------------------------------------------------- */ -static void xfer(unsigned long buf, int nibbles) +static int xfer(unsigned long buf, int nibbles, + uint32_t trigger, uint32_t mask) { dma_init(); dma_setup(buf, nibbles); @@ -127,9 +131,9 @@ static void xfer(unsigned long buf, int nibbles) disable_interrupts(); - while (!(PDPIN & UBB_DAT1)); - -// sleep(1); /* @@@ wait here for trigger */ + while ((PDPIN & mask) != trigger) + if ((PDPIN & KEY_MASK) != KEY_MASK) + goto quit; DCS(DMA) = DCS_NDES | /* no descriptor */ @@ -139,16 +143,23 @@ static void xfer(unsigned long buf, int nibbles) wait_dma_done(); -printf("MSC_STAT = %08x\n", MSC_STAT); +//printf("MSC_STAT = %08x\n", MSC_STAT); dma_cleanup(); + return 1; + +quit: + enable_interrupts(); + dma_cleanup(); + + return 0; } -static void do_buf(int nibbles) +static int do_buf(int nibbles, uint32_t trigger, uint32_t mask) { - uint8_t *buf = physmem_malloc(4095); + uint8_t *buf = physmem_malloc(4096); struct physmem_vec vec; int n, i; uint8_t v, last = 0xff; @@ -159,15 +170,16 @@ static void do_buf(int nibbles) exit(1); } - memset(buf, 0, 4095); - physmem_flush(buf, 4095); + memset(buf, 0, 4096); + physmem_flush(buf, 4096); n = physmem_xlat((void *) buf, nibbles >> 1, &vec, 1); if (n != 1) { fprintf(stderr, "physmem_xlat_vec: expected 1, got %d\n", n); exit(1); } - xfer(vec.addr, nibbles); + if (!xfer(vec.addr, nibbles, trigger, mask)) + return 0; for (i = 0; i != nibbles; i++) { v = (buf[i >> 1] >> (4*(~i & 1))) & 0xf; @@ -192,9 +204,18 @@ static void do_buf(int nibbles) printf("%X\n", last); else printf("%X{%d}\n", last, count); + return 1; } +/* ----- Command-line processing ------------------------------------------- */ + + +/* + * Among equal bus rates, pick the configuration with the fastest MMC clock. + * It'll save a few nanoseconds. + */ + static void frequency(struct mmcclk *clk, int hz) { struct mmcclk mmc; @@ -202,31 +223,97 @@ static void frequency(struct mmcclk *clk, int hz) mmcclk_first(&mmc, 0); *clk = mmc; while (mmcclk_next(&mmc)) - if (fabs(clk->bus_clk_hz-hz) > fabs(mmc.bus_clk_hz-hz)) + if (fabs(clk->bus_clk_hz-hz) > fabs(mmc.bus_clk_hz-hz) || + (fabs(clk->bus_clk_hz-hz) == fabs(mmc.bus_clk_hz-hz) && + clk->clkdiv > mmc.clkdiv)) *clk = mmc; } +static unsigned long xlat_pins(unsigned long pins) +{ + if (pins & ~0x1fUL) { + fprintf(stderr, "invalid trigger set/mask: 0x%lx\n", pins); + exit(1); + } + pins <<= 10; + if (pins & (0x10 << 10)) + pins = (pins ^ (0x10 << 10)) | UBB_CLK; + return pins; +} + + +static void usage(const char *name) +{ + fprintf(stderr, +"usage: %s [-C] [-t pattern/mask] [-f frequency_MHz]\n\n" +" -C output the MMC clock on CLK/TRIG (for debugging)\n" +" -f freq_MHz select the specified frequency (default; 1 MHz)\n" +" -t pattern/mask start capture at the specified pattern (DAT0 = 1, etc.,\n" +" CLK = 16). Default: any change on TRIG.\n" + , name); + exit(1); +} + + int main(int argc, char **argv) { + double freq_mhz = 1; + unsigned long trigger = 1, mask = 0; + int clkout = 0; struct mmcclk clk; + char *end; + int c, res; + + while ((c = getopt(argc, argv, "Cf:t:")) != EOF) + switch (c) { + case 'C': + clkout = 1; + break; + case 'f': + freq_mhz = strtod(optarg, &end); + if (*end) + usage(*argv); + break; + case 't': + trigger = strtoul(optarg, &end, 0); + if (*end != '/') + usage(*argv); + mask = strtoul(end+1, &end, 0); + if (*end) + usage(*argv); + trigger = xlat_pins(trigger); + mask = xlat_pins(mask); + break; + default: + usage(*argv); + } + + if (optind != argc) + usage(*argv); ubb_open(UBB_ALL); PDFUNS = UBB_DAT0 | UBB_DAT1 | UBB_DAT2 | UBB_DAT3; - PDFUNS = UBB_CLK; + if (clkout) + PDFUNS = UBB_CLK; OUT(UBB_CMD); CLR(UBB_CMD); PDFUNC = UBB_CMD; - frequency(&clk, atoi(argv[1])); - printf("bus %g MHz (MSC %g MHz)\n", clk.bus_clk_hz/1e6, + frequency(&clk, 1e6*freq_mhz); + fprintf(stderr, "bus %g MHz controller %g MHz\n", clk.bus_clk_hz/1e6, clk.sys_clk_hz/(clk.clkdiv+1.0)/1e6); mmcclk_start(&clk); - do_buf(6400); + if (trigger == 1) { + trigger = ~PDPIN & UBB_CLK; + mask = UBB_CLK; + } + + res = !do_buf(8128, trigger, mask); mmcclk_stop(); ubb_close(UBB_ALL); - return 0; + return res; }