1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-10-01 15:12:34 +03:00

Updated atusd driver for new hardware. Make use of the interrupt line.

- tools/lib/atusd.c (spi_send_partial, spi_send): removed the old spi_send
  and renamed spi_send_partial to spi_send
- tools/lib/atusd.c (atusd_cycle, spi_send, spi_recv, atusd_open): updated
  for removal of SLP_TR and split of MxSx into MOSI and MISO
- tools/lib/atusd.c (atusd_reset_rf, atusd_open): added delays to precharge
  the capacitors
- tools/lib/atusd.c (atusd_reset, spi_data_in, spi_data_out, spi_finish):
  removed functions for obsolete hardware features
- tools/lib/atusd.c (atusd_reg_read): removed calls to removed functions
- tools/lib/atusd.c (atusd_buf_write, atusd_buf_read, atusd_driver): new
  buffer read/write functions
- tools/atspi-txrx/atspi-txrx.c (init_txrx): set the internal osciallator
  trim only in the USB version. Switch to the external oscillator in the
  uSD version.
- tools/atspi-rssi/atspi-rssi.c (sweep), tools/atspi-txrx/atspi-txrx.c
  (set_channel): wait for the PLL to settle after setting the channel
- tools/include/atspi.h, tools/lib/atspi.c (atspi_interrupt),
  tools/lib/driver.h (struct atspi_driver), tools/lib/atusd.c
  (atusd_interrupt): new function to poll the interrupt line
- tools/atspi-txrx/atspi-txrx.c (receive): only read REG_IRQ_STATUS if
  there is a pending interrupt
- tools/atspi-id/atspi-id.c (usage): print "usage:" as well
- tools/Makefile (upload): upload the atspi tools to the Ben
This commit is contained in:
Werner Almesberger 2010-09-09 09:19:06 -03:00
parent 284b557434
commit 18eec557d0
8 changed files with 98 additions and 80 deletions

View File

@ -15,3 +15,8 @@ DIRS=atspi-id atspi-reset atspi-rssi atspi-trim atspi-txrx
TARGET_ONLY_DIRS=lib
include ../Makefile.recurse
.PHONY: upload
upload:
scp `for n in $(DIRS); do echo $$n/$$n; done` ben:

View File

@ -127,7 +127,7 @@ static void show_info(struct atspi_dsc *dsc)
static void usage(const char *name)
{
fprintf(stderr, "%s\n", name);
fprintf(stderr, "usage: %s\n", name);
exit(1);
}

View File

@ -30,6 +30,8 @@ static void sweep(struct atspi_dsc *dsc)
for (chan = 11; chan <= 26; chan++) {
atspi_reg_write(dsc, REG_PHY_CC_CCA, chan);
/* 150 us, according to AVR2001 section 3.5 */
usleep(1000);
/*
* No need to explicitly wait for the PPL lock - going USB-SPI
* is pretty slow, leaving the transceiver plenty of time.

View File

@ -55,8 +55,12 @@ static struct atspi_dsc *init_txrx(int trim)
atspi_reset_rf(dsc);
atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
#ifdef HAVE_USB /* @@@ yeah, ugly */
atspi_reg_write(dsc, REG_XOSC_CTRL,
(XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
#else
atspi_reg_write(dsc, REG_XOSC_CTRL, XTAL_MODE_EXT << XTAL_MODE_SHIFT);
#endif
atspi_reg_write(dsc, REG_TRX_CTRL_0, 0); /* disable CLKM */
return dsc;
@ -66,6 +70,11 @@ static struct atspi_dsc *init_txrx(int trim)
static void set_channel(struct atspi_dsc *dsc, int channel)
{
atspi_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
/*
* 150 us, according to AVR2001 section 3.5. Note that we should just
* wait for the PPL_LOCK interrupt.
*/
usleep(1000);
}
@ -93,6 +102,8 @@ static void receive(struct atspi_dsc *dsc)
fprintf(stderr, "Ready.\n");
while (1) {
while (!atspi_interrupt(dsc))
usleep(10);
irq = atspi_reg_read(dsc, REG_IRQ_STATUS);
if (atspi_error(dsc))
exit(1);

View File

@ -36,4 +36,6 @@ uint8_t atspi_reg_read(struct atspi_dsc *dsc, uint8_t reg);
void atspi_buf_write(struct atspi_dsc *dsc, const void *buf, int size);
int atspi_buf_read(struct atspi_dsc *dsc, void *buf, int size);
int atspi_interrupt(struct atspi_dsc *dsc);
#endif /* !ATSPI_H */

View File

@ -121,3 +121,10 @@ int atspi_buf_read(struct atspi_dsc *dsc, void *buf, int size)
{
return dsc->driver->buf_read(dsc->handle, buf, size);
}
int atspi_interrupt(struct atspi_dsc *dsc)
{
return
dsc->driver->interrupt ? dsc->driver->interrupt(dsc->handle) : 1;
}

View File

@ -23,11 +23,11 @@
enum {
VDD_OFF = 1 << 6, /* VDD disable, PD06 */
MxSx = 1 << 8, /* CMD, PD08 */
VDD_OFF = 1 << 2, /* VDD disable, PD02 */
MOSI = 1 << 8, /* CMD, PD08 */
CLK = 1 << 9, /* CLK, PD09 */
SCLK = 1 << 10, /* DAT0, PD10 */
SLP_TR = 1 << 11, /* DAT1, PD11 */
MISO = 1 << 10, /* DAT0, PD10 */
SCLK = 1 << 11, /* DAT1, PD11 */
IRQ = 1 << 12, /* DAT2, PD12 */
nSEL = 1 << 13, /* DAT3/CD, PD13 */
};
@ -72,7 +72,7 @@ static void wait_for_power(void)
{
/*
* Give power time to stabilize and the chip time to reset.
* Experiments show that even usleep(0) is long enough.
* Power takes about 2 ms to ramp up. We wait 10 ms to be sure.
*/
usleep(10*1000);
}
@ -84,7 +84,7 @@ static void atusd_cycle(struct atusd_dsc *dsc)
MSC_STRPCL = 1;
/* drive all outputs low (including the MMC bus clock) */
PDDATC = MxSx | CLK | SCLK | SLP_TR | nSEL;
PDDATC = MOSI | CLK | SCLK | nSEL;
/* make the MMC bus clock a regular output */
PDFUNC = CLK;
@ -95,11 +95,11 @@ static void atusd_cycle(struct atusd_dsc *dsc)
/* Power drains within about 20 ms. Wait 100 ms to be sure. */
usleep(100*1000);
/* drive nSS high */
PDDATS = nSEL;
/* drive MOSI and nSS high */
PDDATS = MOSI | nSEL;
/* supply power */
PDDATC = VDD_OFF;
/* precharge the capacitors to avoid current surge */
wait_for_power();
/* return the bus clock output to the MMC controller */
PDFUNS = CLK;
@ -107,30 +107,13 @@ static void atusd_cycle(struct atusd_dsc *dsc)
/* start MMC clock output */
MSC_STRPCL = 2;
/* supply power */
PDDATC = VDD_OFF;
wait_for_power();
}
#if 0 /* we probably won't need this anymore */
static void atusd_reset(struct atusd_dsc *dsc)
{
/* activate reset */
PDDATS = SLP_TR;
PDDATC = nSEL;
/*
* Data sheet says 625 ns, programmer's guide says 6 us. Whom do we
* trust ?
*/
usleep(6);
/* release reset */
PDDATS = nSEL;
PDDATC = SLP_TR;
}
#endif
/* ----- Low-level SPI operations ------------------------------------------ */
@ -146,35 +129,17 @@ static void spi_end(struct atusd_dsc *dsc)
}
static void spi_data_in(struct atusd_dsc *dsc)
{
PDDIRC = MxSx;
}
static void spi_data_out(struct atusd_dsc *dsc)
{
PDDIRS = MxSx;
}
/*
* Send a sequence of bytes but leave the clock high on the last bit, so that
* we can turn around the data line for reads.
*/
static void spi_send_partial(struct atusd_dsc *dsc, uint8_t v)
static void spi_send(struct atusd_dsc *dsc, uint8_t v)
{
uint8_t mask;
for (mask = 0x80; mask; mask >>= 1) {
PDDATC = SCLK;
if (v & mask)
PDDATS = MxSx;
PDDATS = MOSI;
else
PDDATC = MxSx;
PDDATC = MOSI;
PDDATS = SCLK;
PDDATC = SCLK;
}
}
@ -185,29 +150,15 @@ static uint8_t spi_recv(struct atusd_dsc *dsc)
uint8_t mask;
for (mask = 0x80; mask; mask >>= 1) {
PDDATC = SCLK;
if (PDPIN & MxSx)
if (PDPIN & MISO)
res |= mask;
PDDATS = SCLK;
PDDATC = SCLK;
}
PDDATC = SCLK;
return res;
}
static void spi_finish(struct atusd_dsc *dsc)
{
PDDATC = SCLK;
}
static void spi_send(struct atusd_dsc *dsc, uint8_t v)
{
spi_send_partial(dsc, v);
spi_finish(dsc);
}
/* ----- Driver operations ------------------------------------------------- */
@ -216,6 +167,7 @@ static void atusd_reset_rf(void *handle)
struct atusd_dsc *dsc = handle;
atusd_cycle(dsc);
wait_for_power();
}
@ -243,15 +195,18 @@ static void *atusd_open(void)
/* set the output levels */
PDDATS = nSEL | VDD_OFF;
PDDATC = SCLK | SLP_TR;
PDDATC = SCLK;
/* take the GPIOs away from the MMC controller */
PDFUNC = MxSx | SCLK | SLP_TR | IRQ | nSEL;
PDFUNC = MOSI | MISO | SCLK | IRQ | nSEL;
PDFUNS = CLK;
/* set the pin directions */
PDDIRC = IRQ;
PDDIRS = MxSx | CLK | SCLK | SLP_TR | nSEL;
PDDIRC = MISO | IRQ;
PDDIRS = MOSI | CLK | SCLK | nSEL;
/* let capacitors precharge */
wait_for_power();
/* enable power */
PDDATC = VDD_OFF;
@ -286,7 +241,7 @@ static void atusd_close(void *arg)
PDDATS = VDD_OFF;
/* make all MMC pins inputs */
PDDIRC = MxSx | CLK | SCLK | SLP_TR | IRQ | nSEL;
PDDIRC = MOSI | MISO | CLK | SCLK | IRQ | nSEL;
}
@ -307,16 +262,52 @@ static uint8_t atusd_reg_read(void *handle, uint8_t reg)
uint8_t res;
spi_begin(dsc);
spi_send_partial(dsc, AT86RF230_REG_READ| reg);
spi_data_in(dsc);
spi_send(dsc, AT86RF230_REG_READ | reg);
res = spi_recv(dsc);
spi_finish(dsc);
spi_data_out(dsc);
spi_end(dsc);
return res;
}
static void atusd_buf_write(void *handle, const void *buf, int size)
{
struct atusd_dsc *dsc = handle;
spi_begin(dsc);
spi_send(dsc, AT86RF230_BUF_WRITE);
spi_send(dsc, size);
while (size--)
spi_send(dsc, *(uint8_t *) buf++);
spi_end(dsc);
}
static int atusd_buf_read(void *handle, void *buf, int size)
{
struct atusd_dsc *dsc = handle;
uint8_t len, i;
spi_begin(dsc);
spi_send(dsc, AT86RF230_BUF_READ);
len = spi_recv(dsc);
len++; /* LQI */
if (len > size)
len = size;
for (i = 0; i != len; i++)
*(uint8_t *) buf++ = spi_recv(dsc);
spi_end(dsc);
return len;
}
static int atusd_interrupt(void *handle)
{
struct atusd_dsc *dsc = handle;
return !!(PDPIN & IRQ);
}
/* ----- Driver interface -------------------------------------------------- */
@ -328,8 +319,7 @@ struct atspi_driver atusd_driver = {
.reset_rf = atusd_reset_rf,
.reg_write = atusd_reg_write,
.reg_read = atusd_reg_read,
#if 0
.buf_write = atusd_buf_write,
.buf_read = atusd_buf_read,
#endif
.interrupt = atusd_interrupt,
};

View File

@ -29,6 +29,7 @@ struct atspi_driver {
uint8_t (*reg_read)(void *dsc, uint8_t reg);
void (*buf_write)(void *dsc, const void *buf, int size);
int (*buf_read)(void *dsc, void *buf, int size);
int (*interrupt)(void *dsc);
};
#endif /* !DRIVER_H */