1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2024-11-16 18:45:54 +02:00

ubb-la/ubb-la.c: add command-line options, keyboard abort

This commit is contained in:
Werner Almesberger 2013-01-24 18:26:34 -03:00
parent bac21bf8cb
commit 62284fb78e

View File

@ -13,6 +13,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <assert.h> #include <assert.h>
@ -26,6 +27,8 @@
#define DMA 5 #define DMA 5
#define KEY_MASK 0x5fc0000
/* ----- Enable/disable interrupts ----------------------------------------- */ /* ----- Enable/disable interrupts ----------------------------------------- */
@ -103,7 +106,8 @@ static void wait_dma_done(void)
/* ----- MMC control ------------------------------------------------------- */ /* ----- 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_init();
dma_setup(buf, nibbles); dma_setup(buf, nibbles);
@ -127,9 +131,9 @@ static void xfer(unsigned long buf, int nibbles)
disable_interrupts(); disable_interrupts();
while (!(PDPIN & UBB_DAT1)); while ((PDPIN & mask) != trigger)
if ((PDPIN & KEY_MASK) != KEY_MASK)
// sleep(1); /* @@@ wait here for trigger */ goto quit;
DCS(DMA) = DCS(DMA) =
DCS_NDES | /* no descriptor */ DCS_NDES | /* no descriptor */
@ -139,16 +143,23 @@ static void xfer(unsigned long buf, int nibbles)
wait_dma_done(); wait_dma_done();
printf("MSC_STAT = %08x\n", MSC_STAT); //printf("MSC_STAT = %08x\n", MSC_STAT);
dma_cleanup(); 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; struct physmem_vec vec;
int n, i; int n, i;
uint8_t v, last = 0xff; uint8_t v, last = 0xff;
@ -159,15 +170,16 @@ static void do_buf(int nibbles)
exit(1); exit(1);
} }
memset(buf, 0, 4095); memset(buf, 0, 4096);
physmem_flush(buf, 4095); physmem_flush(buf, 4096);
n = physmem_xlat((void *) buf, nibbles >> 1, &vec, 1); n = physmem_xlat((void *) buf, nibbles >> 1, &vec, 1);
if (n != 1) { if (n != 1) {
fprintf(stderr, "physmem_xlat_vec: expected 1, got %d\n", n); fprintf(stderr, "physmem_xlat_vec: expected 1, got %d\n", n);
exit(1); exit(1);
} }
xfer(vec.addr, nibbles); if (!xfer(vec.addr, nibbles, trigger, mask))
return 0;
for (i = 0; i != nibbles; i++) { for (i = 0; i != nibbles; i++) {
v = (buf[i >> 1] >> (4*(~i & 1))) & 0xf; v = (buf[i >> 1] >> (4*(~i & 1))) & 0xf;
@ -192,9 +204,18 @@ static void do_buf(int nibbles)
printf("%X\n", last); printf("%X\n", last);
else else
printf("%X{%d}\n", last, count); 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) static void frequency(struct mmcclk *clk, int hz)
{ {
struct mmcclk mmc; struct mmcclk mmc;
@ -202,31 +223,97 @@ static void frequency(struct mmcclk *clk, int hz)
mmcclk_first(&mmc, 0); mmcclk_first(&mmc, 0);
*clk = mmc; *clk = mmc;
while (mmcclk_next(&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; *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) int main(int argc, char **argv)
{ {
double freq_mhz = 1;
unsigned long trigger = 1, mask = 0;
int clkout = 0;
struct mmcclk clk; 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); ubb_open(UBB_ALL);
PDFUNS = UBB_DAT0 | UBB_DAT1 | UBB_DAT2 | UBB_DAT3; PDFUNS = UBB_DAT0 | UBB_DAT1 | UBB_DAT2 | UBB_DAT3;
PDFUNS = UBB_CLK; if (clkout)
PDFUNS = UBB_CLK;
OUT(UBB_CMD); OUT(UBB_CMD);
CLR(UBB_CMD); CLR(UBB_CMD);
PDFUNC = UBB_CMD; PDFUNC = UBB_CMD;
frequency(&clk, atoi(argv[1])); frequency(&clk, 1e6*freq_mhz);
printf("bus %g MHz (MSC %g MHz)\n", clk.bus_clk_hz/1e6, fprintf(stderr, "bus %g MHz controller %g MHz\n", clk.bus_clk_hz/1e6,
clk.sys_clk_hz/(clk.clkdiv+1.0)/1e6); clk.sys_clk_hz/(clk.clkdiv+1.0)/1e6);
mmcclk_start(&clk); mmcclk_start(&clk);
do_buf(6400); if (trigger == 1) {
trigger = ~PDPIN & UBB_CLK;
mask = UBB_CLK;
}
res = !do_buf(8128, trigger, mask);
mmcclk_stop(); mmcclk_stop();
ubb_close(UBB_ALL); ubb_close(UBB_ALL);
return 0; return res;
} }