Date:2010-09-09 22:23:47 (13 years 6 months ago)
Author:Werner Almesberger
Commit:9162689d3e913fc105dca7e04288e2f8f52e7a95
Message:Cleaned up interrupt handling in atspi-txrx. Report ED. Shut down at end.

- tools/atspi-txrx/atspi-txrx.c (receive, wait_for_interrupt): moved wait
for interrupt logic to separate function and made it more versatile
- tools/atspi-txrx/atspi-txrx.c (init_txrx, receive): clear interrupts in
init_txrx now, so that also transmit has a clear interrupt register
- tools/atspi-txrx/atspi-txrx.c (set_channel): since we're in TRX_OFF,
don't wait for PLL lock
- tools/atspi-txrx/atspi-txrx.c (receive): wait for PLL lock interrupt
after activating receiver
- tools/atspi-txrx/atspi-txrx.c (transmit): wait for PLL lock interrupt
after activating the PLL
- tools/atspi-txrx/atspi-txrx.c (transmit): wait for TRX_END interrupt
after sending a frame
- tools/atspi-txrx/atspi-txrx.c (receive): report the Energy Density (ED)
after receiving a frame
- tools/atspi-txrx/atspi-txrx.c (main): shut down the board with
atspi_close, so that we can hot-swap safely
Files: tools/atspi-txrx/atspi-txrx.c (6 diffs)

Change Details

tools/atspi-txrx/atspi-txrx.c
6363#endif
6464    atspi_reg_write(dsc, REG_TRX_CTRL_0, 0); /* disable CLKM */
6565
66    (void) atspi_reg_read(dsc, REG_IRQ_STATUS);
67
6668    return dsc;
6769}
6870
6971
72static uint8_t wait_for_interrupt(struct atspi_dsc *dsc, uint8_t wait_for,
73    uint8_t ignore, int sleep_us, int timeout)
74{
75    uint8_t irq, show;
76
77    while (1) {
78        while (!atspi_interrupt(dsc)) {
79            usleep(sleep_us);
80            if (timeout && !--timeout)
81                return 0;
82        }
83        irq = atspi_reg_read(dsc, REG_IRQ_STATUS);
84        if (atspi_error(dsc))
85            exit(1);
86        if (!irq)
87            continue;
88        show = irq & ~ignore;
89        if ((irq & wait_for) && !show)
90            break;
91        fprintf(stderr, "IRQ (0x%02x):", irq);
92        if (irq & IRQ_PLL_LOCK)
93            fprintf(stderr, " PLL_LOCK");
94        if (irq & IRQ_PLL_UNLOCK)
95            fprintf(stderr, " PLL_UNLOCK");
96        if (irq & IRQ_RX_START)
97            fprintf(stderr, " RX_START");
98        if (irq & IRQ_TRX_END)
99            fprintf(stderr, " TRX_END");
100        if (irq & IRQ_TRX_UR)
101            fprintf(stderr, " TRX_UR");
102        if (irq & IRQ_BAT_LOW)
103            fprintf(stderr, " BAT_LOW");
104        fprintf(stderr, "\n");
105        if (irq & wait_for)
106            break;
107    }
108    return irq;
109}
110
111
70112static void set_channel(struct atspi_dsc *dsc, int channel)
71113{
72114    atspi_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
73    /*
74     * 150 us, according to AVR2001 section 3.5. Note that we should just
75     * wait for the PPL_LOCK interrupt.
76     */
77    usleep(1000);
78115}
79116
80117
...... 
91128
92129static void receive(struct atspi_dsc *dsc)
93130{
94    uint8_t irq;
95131    uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */
96132    int n, ok, i;
97    uint8_t lq;
133    uint8_t ed, lqi;
98134
99135    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
100
101    (void) atspi_reg_read(dsc, REG_IRQ_STATUS);
136    /*
137     * 180 us, according to AVR2001 section 4.2. We time out after
138     * nominally 200 us.
139     */
140    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 10, 20);
102141
103142    fprintf(stderr, "Ready.\n");
104    while (1) {
105        while (!atspi_interrupt(dsc))
106            usleep(10);
107        irq = atspi_reg_read(dsc, REG_IRQ_STATUS);
108        if (atspi_error(dsc))
109            exit(1);
110        if (!irq)
111            continue;
112        if (irq == IRQ_TRX_END)
113            break;
114        fprintf(stderr, "IRQ (0x%02x):", irq);
115        if (irq & IRQ_PLL_LOCK)
116            fprintf(stderr, " PLL_LOCK");
117        if (irq & IRQ_PLL_UNLOCK)
118            fprintf(stderr, " PLL_UNLOCK");
119        if (irq & IRQ_RX_START)
120            fprintf(stderr, " RX_START");
121        if (irq & IRQ_TRX_UR)
122            fprintf(stderr, " TRX_UR");
123        if (irq & IRQ_BAT_LOW)
124            fprintf(stderr, " BAT_LOW");
125        fprintf(stderr, "\n");
126        if (irq & IRQ_TRX_END)
127            break;
128    }
143    wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START,
144        10, 0);
129145
130146    n = atspi_buf_read(dsc, buf, sizeof(buf));
131147    if (n < 0)
...... 
134150        fprintf(stderr, "%d bytes received\n", n);
135151        exit(1);
136152    }
153    ed = atspi_reg_read(dsc, REG_PHY_ED_LEVEL);
137154    ok = !!(atspi_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID);
138    lq = buf[n-1];
139    fprintf(stderr, "%d bytes payload, CRC %s, LQI %u\n",
140        n-3, ok ? "OK" : "BAD", lq);
155    lqi = buf[n-1];
156    fprintf(stderr, "%d bytes payload, CRC %s, LQI %u, ED %d dBm\n",
157        n-3, ok ? "OK" : "BAD", lqi, -91+ed);
141158    for (i = 0; i != n-3; i++)
142159        putchar(buf[i] < ' ' || buf[i] > '~' ? '?' : buf[i]);
143160    putchar('\n');
...... 
149166    uint8_t buf[MAX_PSDU];
150167
151168    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
169    /*
170     * 180 us, according to AVR2001 section 4.3. We time out after
171     * nominally 200 us.
172     */
173    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 10, 20);
152174
153175    /*
154176     * We need to copy the message to append the CRC placeholders.
...... 
158180
159181    /* @@@ should wait for clear channel */
160182    atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
161    /* @@@ should wait for TX done */
183
184    /* wait up to 10 ms (nominally) */
185    wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_PLL_LOCK,
186      10, 1000);
162187}
163188
164189
...... 
224249        usage(*argv);
225250    }
226251
252    atspi_close(dsc);
253
227254    return 0;
228255}

Archive Download the corresponding diff file



interactive