diff --git a/drivers/at86rf2xx/at86rf2xx_internal.c b/drivers/at86rf2xx/at86rf2xx_internal.c index fe0e4b2dd9..6ab87878b5 100644 --- a/drivers/at86rf2xx/at86rf2xx_internal.c +++ b/drivers/at86rf2xx/at86rf2xx_internal.c @@ -86,16 +86,24 @@ void at86rf2xx_sram_write(const at86rf2xx_t *dev, spi_release(dev->spi); } -void at86rf2xx_fb_read(const at86rf2xx_t *dev, - uint8_t *data, - const size_t len) +void at86rf2xx_fb_start(const at86rf2xx_t *dev) { spi_acquire(dev->spi); gpio_clear(dev->cs_pin); spi_transfer_byte(dev->spi, AT86RF2XX_ACCESS_FB | AT86RF2XX_ACCESS_READ, NULL); +} + +void at86rf2xx_fb_read(const at86rf2xx_t *dev, + uint8_t *data, + const size_t len) +{ spi_transfer_bytes(dev->spi, NULL, (char *)data, len); +} + +void at86rf2xx_fb_stop(const at86rf2xx_t *dev) +{ gpio_set(dev->cs_pin); spi_release(dev->spi); } diff --git a/drivers/at86rf2xx/at86rf2xx_netdev.c b/drivers/at86rf2xx/at86rf2xx_netdev.c index 8e0baa9666..6909a2f3da 100644 --- a/drivers/at86rf2xx/at86rf2xx_netdev.c +++ b/drivers/at86rf2xx/at86rf2xx_netdev.c @@ -266,15 +266,24 @@ static int _send(gnrc_netdev_t *netdev, gnrc_pktsnip_t *pkt) static void _receive_data(at86rf2xx_t *dev) { uint8_t mhr[IEEE802154_MAX_HDR_LEN]; + uint8_t phr; size_t pkt_len, hdr_len; gnrc_pktsnip_t *hdr, *payload = NULL; gnrc_netif_hdr_t *netif; - /* get the size of the received packet (unlocks frame buffer protection) */ - pkt_len = at86rf2xx_rx_len(dev); + /* frame buffer protection will be unlocked as soon as at86rf2xx_fb_stop() + * is called*/ + at86rf2xx_fb_start(dev); + + /* get the size of the received packet */ + at86rf2xx_fb_read(dev, &phr, 1); + + /* Ignore FCS for packet length */ + pkt_len = phr - 2; /* abort here already if no event callback is registered */ if (!dev->event_cb) { + at86rf2xx_fb_stop(dev); return; } @@ -282,43 +291,63 @@ static void _receive_data(at86rf2xx_t *dev) if (dev->options & AT86RF2XX_OPT_RAWDUMP) { payload = gnrc_pktbuf_add(NULL, NULL, pkt_len, GNRC_NETTYPE_UNDEF); if (payload == NULL ) { + at86rf2xx_fb_stop(dev); DEBUG("[at86rf2xx] error: unable to allocate RAW data\n"); return; } - at86rf2xx_rx_read(dev, payload->data, pkt_len, 0); + at86rf2xx_fb_read(dev, payload->data, pkt_len); + at86rf2xx_fb_stop(dev); dev->event_cb(NETDEV_EVENT_RX_COMPLETE, payload); return; } /* get FCF field and compute 802.15.4 header length */ - at86rf2xx_rx_read(dev, mhr, 2, 0); + at86rf2xx_fb_read(dev, mhr, 2); + hdr_len = _get_frame_hdr_len(mhr); if (hdr_len == 0) { + at86rf2xx_fb_stop(dev); DEBUG("[at86rf2xx] error: unable parse incoming frame header\n"); return; } + /* read the rest of the header and parse the netif header from it */ - at86rf2xx_rx_read(dev, &(mhr[2]), hdr_len - 2, 2); + at86rf2xx_fb_read(dev, &(mhr[2]), hdr_len - 2); hdr = _make_netif_hdr(mhr); if (hdr == NULL) { + at86rf2xx_fb_stop(dev); DEBUG("[at86rf2xx] error: unable to allocate netif header\n"); return; } + /* fill missing fields in netif header */ netif = (gnrc_netif_hdr_t *)hdr->data; netif->if_pid = dev->mac_pid; - at86rf2xx_rx_read(dev, &(netif->lqi), 1, pkt_len); - netif->rssi = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_ED_LEVEL); /* allocate payload */ payload = gnrc_pktbuf_add(hdr, NULL, (pkt_len - hdr_len), dev->proto); if (payload == NULL) { + at86rf2xx_fb_stop(dev); DEBUG("[at86rf2xx] error: unable to allocate incoming payload\n"); gnrc_pktbuf_release(hdr); return; } /* copy payload */ - at86rf2xx_rx_read(dev, payload->data, payload->size, hdr_len); + at86rf2xx_fb_read(dev, payload->data, payload->size); + + /* Ignore FCS but advance fb read */ + at86rf2xx_fb_read(dev, NULL, 2); + + at86rf2xx_fb_read(dev, &(netif->lqi), 1); + +#ifndef MODULE_AT86RF231 + at86rf2xx_fb_read(dev, &(netif->rssi), 1); + at86rf2xx_fb_stop(dev); +#else + at86rf2xx_fb_stop(dev); + netif->rssi = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_ED_LEVEL); +#endif + /* finish up and send data to upper layers */ dev->event_cb(NETDEV_EVENT_RX_COMPLETE, payload); } diff --git a/drivers/at86rf2xx/include/at86rf2xx_internal.h b/drivers/at86rf2xx/include/at86rf2xx_internal.h index 21f5ba6783..d7285469d7 100644 --- a/drivers/at86rf2xx/include/at86rf2xx_internal.h +++ b/drivers/at86rf2xx/include/at86rf2xx_internal.h @@ -95,10 +95,19 @@ void at86rf2xx_sram_write(const at86rf2xx_t *dev, const size_t len); /** - * @brief Read the internal frame buffer of the given device + * @brief Start a read transcation internal frame buffer of the given device * * Reading the frame buffer returns some extra bytes that are not accessible - * through reading the RAM directly. + * through reading the RAM directly. This locks the used SPI. + * + * @param[in] dev device to start read + */ +void at86rf2xx_fb_start(const at86rf2xx_t *dev); + +/** + * @brief Read the internal frame buffer of the given device + * + * Each read advances the position in the buffer by @p len. * * @param[in] dev device to read from * @param[out] data buffer to copy the data to @@ -107,6 +116,15 @@ void at86rf2xx_sram_write(const at86rf2xx_t *dev, void at86rf2xx_fb_read(const at86rf2xx_t *dev, uint8_t *data, const size_t len); +/** + * @brief Stop a read transcation internal frame buffer of the given device + * + * Release the SPI device and unlock frame buffer protection. + * + * @param[in] dev device to stop read + */ +void at86rf2xx_fb_stop(const at86rf2xx_t *dev); + /** * @brief Cancel ongoing transactions and switch to TRX_OFF state *