From 37a219b0b953591b6b9b603bc04611360f2677ef Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Sat, 26 Jan 2013 23:25:17 -0300 Subject: [PATCH] ubb-la/ubb-la.c: option -n N to enter experimental multi-buffer mode (WIP) --- ubb-la/ubb-la.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/ubb-la/ubb-la.c b/ubb-la/ubb-la.c index 6dffde4..de62d4b 100644 --- a/ubb-la/ubb-la.c +++ b/ubb-la/ubb-la.c @@ -99,6 +99,7 @@ static void dma_setup(unsigned long buf, int nibbles) { assert(!(nibbles & 63)); +/* need to reset DSA, DTA, DTC when done. uncertain about DCS */ DCS(DMA) = DCS_NDES; /* no-descriptor transfer */ DSA(DMA) = REG_PADDR(MSC_RXFIFO); /* source */ DTA(DMA) = buf; /* destination */ @@ -166,6 +167,61 @@ quit: } +static void xfers(unsigned long *bufs, int n_bufs, int nibbles) +{ + int i = 0; + + dma_init(); + + MSC_STRPCL = MSC_STRPCRL_START_CLOCK; /* start the bus clock */ + MSC_RESTO = MSC_RESTO_MASK; /* maximum response time-out */ + MSC_RDTO = MSC_RDTO_MASK; + MSC_BLKLEN = nibbles >> 1; + + MSC_CMDAT = + MSC_CMDAT_BUS_WIDTH_4 << MSC_CMDAT_BUS_WIDTH_SHIFT | + MSC_CMDAT_DMA_EN | /* DMA */ + MSC_CMDAT_DATA_EN | /* with data transfer */ + MSC_CMDAT_RESPONSE_FORMAT_NONE; /* no response required */ + + disable_interrupts(); + + OUT(UBB_CMD); + dma_setup(bufs[0], nibbles); + + while (1) { + MSC_STRPCL = MSC_STRPCRL_START_OP; + + while (MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY); + + IN(UBB_CMD); + + DCS(DMA) = + DCS_NDES | /* no descriptor */ + DCS_CTE; /* enable channel */ + + /* + * @@@ We could enable interrupts while waiting, particularly + * at low sample rates, as long as the probability of missing + * the end of the DMA transfer is acceptably low. + */ + wait_dma_done(); + + if (++i == n_bufs) + break; + + OUT(UBB_CMD); + dma_setup(bufs[i], nibbles); + + while (!(MSC_STAT & MSC_STAT_DATA_TRAN_DONE)); + } + + enable_interrupts(); + + dma_cleanup(); +} + + static void print_samples(FILE *file, uint8_t *buf, int skip, int nibbles) { uint8_t v, last = 0xff; @@ -225,6 +281,38 @@ static int do_buf(int nibbles, uint32_t trigger, uint32_t mask) } +static void do_bufs(int n_bufs, int nibbles) +{ + uint8_t *bufs[n_bufs]; + struct physmem_vec vecs[n_bufs]; + unsigned long addrs[n_bufs]; + int i,n; + + if (mlockall(MCL_CURRENT | MCL_FUTURE)) { + perror("mlockall"); + exit(1); + } + + for (i = 0; i != n_bufs; i++) { + bufs[i] = physmem_malloc(4096); + memset(bufs[i], 0, 4096); + physmem_flush(bufs[i], 4096); + + n = physmem_xlat(bufs[i], nibbles >> 1, vecs+i, 1); + if (n != 1) { + fprintf(stderr, + "physmem_xlat_vec: expected 1, got %d\n", n); + exit(1); + } + addrs[i] = vecs[i].addr; + } + xfers(addrs, n_bufs, nibbles); + + for (i = 0; i != n_bufs; i++) + print_samples(stdout, bufs[i], INITIAL_SKIP, nibbles); +} + + /* ----- Command-line processing ------------------------------------------- */ @@ -263,9 +351,11 @@ static unsigned long xlat_pins(unsigned long pins) static void usage(const char *name) { fprintf(stderr, -"usage: %s [-C] [-t pattern/mask] [-f frequency_MHz]\n\n" +"usage: %s [-C] [-t pattern/mask] [-f frequency_MHz] [-n N]\n\n" " -C output the MMC clock on CLK/TRIG (for debugging)\n" " -f freq_MHz select the specified frequency (default; 1 MHz)\n" +" -n N capture N buffers worth of samples without waiting for a\n" +" trigger\n" " -t pattern/mask start capture at the specified pattern (DAT0 = 1, etc.,\n" " CLK = 16). Default: any change on TRIG.\n" , name); @@ -277,12 +367,13 @@ int main(int argc, char **argv) { double freq_mhz = 1; unsigned long trigger = 1, mask = 0; + unsigned long multi = 0; int clkout = 0; struct mmcclk clk; char *end; int c, res; - while ((c = getopt(argc, argv, "Cf:t:")) != EOF) + while ((c = getopt(argc, argv, "Cf:n:t:")) != EOF) switch (c) { case 'C': clkout = 1; @@ -292,6 +383,11 @@ int main(int argc, char **argv) if (*end) usage(*argv); break; + case 'n': + multi = strtoul(optarg, &end, 0); + if (*end) + usage(*argv); + break; case 't': trigger = strtoul(optarg, &end, 0); if (*end != '/') @@ -327,7 +423,12 @@ int main(int argc, char **argv) mask = UBB_CLK; } - res = !do_buf(8128, trigger, mask); + if (!multi) { + res = !do_buf(8128, trigger, mask); + } else { + do_bufs(multi, 8128); + res = 0; + } mmcclk_stop(); ubb_close(UBB_ALL);