uracoli-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[uracoli-devel] SPI speed issues when transmitting a frame with radio_se


From: Joerg Wunsch
Subject: [uracoli-devel] SPI speed issues when transmitting a frame with radio_send_frame()
Date: Thu, 24 Jun 2010 15:58:08 +0200
User-agent: Mutt/1.5.20 (2009-06-14)

After porting an older project where I've already been using µracoli
in from 868 MHz to 2.4 GHz, I've been stumbling across strange frame
corruption issues:

In a particular sequence of events, the very first frame always ended
up being corrupted (as seen on the sniffer) somewhere in the middle of
the source address field, down to the payload.  The FCS was correct,
and as the destination address was not corrupted, the receiver
responded with an ACK frame, leaving the sender in the assumption the
transmission has been fine.  (The receiver just didn't respond to the
payload subsequently.)

Much to my surprise, when no receiver was present so the TX_ARET
procedure had to retry the transmissions, all retried frames came out
correctly (again, with a correct FCS as well).

After some discussion with Axel, we came to the conclusion that this
must be a case of TX underrun.  My transmitting node was only clocked
with a CPU frequency of 1 MHz, and as the controller is an ATtiny84
with a USI-based SPI only, the resulting SPI clock is 250 kHz.  This
is the same as the over-the-air bitrate on 2.4 GHz radios, so together
with the overhead for obtaining the next byte, the transmitter
eventually starvated on lack of actual data.  As the auto-CRC feature
was turned on, the FCS was correctly calculated by the transmitter
anyway.  When being force to retry the transaction, however, all the
correct data have been there meanwhile.

The slow CPU frequency has been chosen in order to reduce the power
consumption of the node, as otherwise the resulting computing power
was still enough.  The node falls asleep after being inactive for 10 s
anyway, so it seemed appropriate not to attempt any further power
reduction while it is active, and just keep the CPU frequency low.  In
my previous setup with the 868 MHz radio, the over-the-air rate was
sufficiently low so this did not become an issue.

As the sequence of actions inside radio_send_frame() is opaque to the
user, the user has no chance to switch it into a different mode, where
the frame is loaded into the transceiver first, before starting the
transmission (which would otherwise have been appropriate here).

There are several possible ways out of this dilemma:

. We just document that the minimum SPI speed required is about twice
  the over-the-air rate when calling radio_send_frame(), and the user
  has to take care for that.  I'm now modifying the clock prescaler so
  the CPU runs with 2 MHz before calling radio_send_frame(), and
  revert it to 1 MHz afterwards.  This potentially wastes a bit of
  energy though as radio_send_frame() only returns upon finishing the
  TX_ARET transaction, so the CPU remains at the elevated clock
  frequency during the entire transaction (while it would only be
  required for the actual SPI transfer).

. We try to decide whether to use an early start (SLP_TR pulse before
  downloading the frame) vs. late start (download first, SLP_TR to
  start transmission afterward) based on the F_CPU value.  While this
  automatism sounds appealing at first, it's tricky: it requires
  knowledge of the project's F_CPU setting, so it can only happen
  within a header file that is compiled together with the project.  It
  makes assumptions about the SPI speed used and its relationship to
  the CPU speed, although this can be deduced from the "spirate"
  parameter to SPI_INIT().  Different situations have to be considered
  on 868/910 MHz, depending on the PHY modulation scheme used (BPSK
  20/40 vs. OQPSK 100/250).

. We provide an external "knob" to make the decision about early or
  late start.  This requires extending the API, either in a backwards
  compatible manner (adding a new function or variable for the
  "knob"), or by changing the API for one of the existing functions,
  breaking older applications.  The code for both, early and late
  start has to be present in the library, but the overhead is probably
  tolerable.

. We add code to increase the CPU frequency dynamically just for the
  SPI transfer.  This has the best power consumption vs. efficiency
  ratio, but goes deep into the hardware, causing further potential
  issue whenever µracoli might be in a situation to port to something
  else than an AVR (say, an ARM7 or AVR32 UC3 or Cortex-M3 ARM).  It
  might also bloat the API.

As a placeholder, I opened bug #30246 for this.

-- 
cheers, J"org               .-.-.   --... ...--   -.. .  DL8DTL

http://www.sax.de/~joerg/                        NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]