[Solved] Raven rf230 checksum bad after jtag reset

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have this puzzling problem that just started with the rf230 radio on one of my ravens.

I routinely use a jtag signature read to reboot contiki to see the startup traffic, and the other day I noticed it occasionally started up in a mode that added bad checksums to all tx packets. Some experimentation showed that reboots done by power cycling always gave the correct CRC (shown by 15dot4 sniffer and wireshark).

Since I was powering the Raven through the ext voltage input using an STK500 at 3v3 which is below specs, I thought maybe cranking that up to 5 volts would fix it. But just the opposite! Now it is completely consistent, checksum errors after signature read reboot, no errors when power is cycled.

It's as if the radio doesn't get initialized properly if the 1284p starts up too fast. But adding waitidle calls before all the register writes (especially the hal_subregister_write(SR_TX_AUTO_CRC_ON, 1) had no effect.

The packets are otherwise correct as shown by wireshark. How can the Dragon JTAG reset be affecting the radio? How can the *hardware* be computing the wrong checksum? I can see how possible dragon/stk500 rs232 ground loops might get worse with higher voltage, but affecting the hardware checksum? The 1284p boot does

[/* Do full rf230 Reset */
  hal_set_rst_low();
  hal_set_slptr_low();
  delay_us(TIME_RESET);
  hal_set_rst_high();

Interrups are disabled as part of the boot process but timer or radio interrupts can conceivably occur if the jtag signature read does not disable interrupts, but how can any of that affect the radio hardware checksum????

Last Edited: Fri. Oct 16, 2015 - 02:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well I found a workaround. A jtag reset tristates the 1284p interface pins which apparently can cause the rf230 to enter the bad CRC state when it is later initialized. (Oddly, more probable at higher voltages)

I don't see CRC errors any more when the pins are initialized as soon as possible after a reset. For good measure I hold the radio in reset as well:

void initialize(void)
{
/* A jtag or brownout reset of the mcu tristates the RF230 control pins while
 * it is in operation, which can result in a mulfunctioning condition when the
 * radio is later re-initialized.
 * This manifests as an incorrectly computed hardware FCS checksum.
 * Setting up the pins as soon as possible after mcu reset seems to fix this.
 * Additionally, hold the radio in reset to prevent premature rx interrupts.
 */
#include "radio/rf230bb/hal.h"
  hal_init();
  hal_set_rst_low();

I have to verify this, but I think it is a result of the radio being in sleep mode (SLP_PTR high) when the pins are tristated. The odds of starting properly seem about the same as the radio on time:

Uptime     : 00:26:50
CPU time   (ENERGEST): 00:02:36 (9.68%)
Radio      (ENERGEST): Tx 00:00:01 (0.06%)  Rx 00:00:51 (3.16%)
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> using an STK500 at 3v3 which is below specs
No, 3v3 is exactly right, with 5V the radio transceiver
is out of spec, lucky you that the radio survived this torture
(I don't know exactly if there is a protection diode on the raven).

> I have to verify this, but I think it is a result of the
> radio being in sleep mode (SLP_PTR high) when the pins are
> tristated.

Especially for the SPI setup it is a good practice is to set up
at first the PORT register followed by the DDR register, because
glitches on the SPI can bring the transceiver in a strange mood ;-)

void spi_init (void)
{
    /* To avoid a SPI glitch, the port register shall be set before the DDR register */
    PORT_SPI |= _BV(SPI_SCK) | _BV(SPI_SS); /* SCK high  */
    DDR_SPI  |= _BV(SPI_MOSI) | _BV(SPI_SCK) | _BV(SPI_SS); /* SCK, MOSI, SS output */
    DDR_SPI  &=~ _BV(SPI_MISO); /* MISO input */
    SPCR = SPI_CFG_0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do set the DDR before PORT, so I'll try the reverse.

The Raven ext input power goes through a LDO regulator with reverse diode protection, so that is bulletproof to 18 volts. However I did run an atmega128rfa1 at 4 volts for about an hour, only noticing when it stopped replying to pings. I had put a fully charged lithium battery into the holder, instead of the one that gets the 3v6 maximum voltage.

Didn't seem to hurt the chip any...well maybe it caused a problem with CRC calculation after jtag reset :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Either way gives the FCS error on jtag reset 5 times out of 6. But doing the hal_init before the 510us warmup delay fixes it:

#if 1  //this works
  /* Initialize Hardware Abstraction Layer */
  hal_init();
  /* Wait in case VCC just applied */
  delay_us(TIME_TO_ENTER_P_ON);
#else  //this gives FCS errors 5 out of 6 times
  /* Wait in case VCC just applied */
  delay_us(TIME_TO_ENTER_P_ON);
  /* Initialize Hardware Abstraction Layer */
  hal_init();
#endif

  /* Do full rf230 Reset */
  hal_set_rst_low();
  hal_set_slptr_low();
  delay_us(TIME_RESET);
  hal_set_rst_high();

Here is the full initialize

void
hal_init(void)
{
    /*IO Specific Initialization - sleep and reset pins. */
#if 0 //set pins low before enabling as output - makes no difference
  hal_set_rst_low();
  hal_set_slptr_low();
#endif
    DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */
    DDR_RST    |= (1 << RST);    /* Enable RST as output. */

    /*SPI Specific Initialization.*/
    /* Set SS, CLK and MOSI as output. */
#if 0
    HAL_DDR_SPI  |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK) | (1 << HAL_DD_MOSI);
    HAL_PORT_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK); /* Set SS and CLK high */
#else
    HAL_PORT_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK); /* Set SS and CLK high */
	HAL_DDR_SPI  |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK) | (1 << HAL_DD_MOSI);
    HAL_DDR_SPI  &=~ (1<< HAL_DD_MISO);                      /* MISO input */ 
#endif
    /* Run SPI at max speed */
    SPCR         = (1 << SPE) | (1 << MSTR); /* Enable SPI module and master operation. */
    SPSR         = (1 << SPI2X); /* Enable doubled SPI speed in master mode. */

    /*TIMER1 Specific Initialization.*/
    TCCR1B = HAL_TCCR1B_CONFIG;       /* Set clock prescaler */
    TIFR1 |= (1 << ICF1);             /* Clear Input Capture Flag. */
    HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer1 overflow interrupt. */
    hal_enable_trx_interrupt();    /* Enable interrupts from the radio transceiver. */
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> But doing the hal_init before the 510us warmup delay fixes it.

Quite possible that, if your SLP_TR pin is floating, it causes the
radio to partially go to sleep, or to produce glitches in the xtal
oscillator that is starting up during that time.

The difference to a power cycle is, that after a power cycle, the
AT86RF230 enters state "P_ON" which explicitly activates pull-up/down
resistors on the pins to give the microcontroller time to reach a
stable state on the SPI pins before starting up the radio. (Actually,
that is the *only* purpose of state P_ON, and thus also the reason why
the ATmega128RFA1 doesn't have P_ON: there's no SPI interface that has
to be configured before.)

The pulling resistors are then turned off in order to not cause any
permanent unwanted current flow, eventually leaking out battery
capacity. Consequently, upon a microcontroller-induced (as opposed to
power-on) reset (JTAG, watchdog), pins left floating by the controller
can trigger any kind of illegal behaviour.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Doing the hal_init before the warmup delay, it was very odd that extra 500 usec should have any effect since the mcu already spent 65 msec on the RC clock startup delay. However it also increased the delay between hal_init and the full reset, and that pointed to the answer.

If the radio is in sleep mode from before the reset, it continues to be in sleep mode until SLP_TR is pulled low. So the needed delay is not the reset time, but the longer wake time:

  /* Do full rf230 Reset */
  hal_set_rst_low();
  hal_set_slptr_low();
#if 1
/* On powerup a TIME_RESET delay is needed here, however on some other MCU reset
 * (JTAG, WDT, Brownout) the radio may be sleeping. It can enter an uncertain
 * state (sending wrong hardware FCS for example) unless the full wakeup delay
 * is done.
 * Wake time depends on board capacitance; use 2x the nominal delay for safety.
 * See www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=78725
 */
  delay_us(2*TIME_SLEEP_TO_TRX_OFF);
#else
  delay_us(TIME_RESET);
#endif
  hal_set_rst_high();