This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC430 prone to hanging with marginal link quality

Other Parts Discussed in Thread: CC1101

Hello everyone,

We've been developing remote control appliance and use a bunch of EM430RF900 kits for prototyping CC430-based part.

The point-to-point data link involved uses variable-length packets at 38.4kbit/s. Logically, it is cookie-cutter link with device A listening periodically and device B sending out handshake packets and, once handshake is successful, short and (time-wise) dense sequence of packets.

 

The problem: when device A is in RX mode, and device B pours out continuous string of packets, rapid change in link quality sometimes leads device A to hang (with watchdog reset following).

To reproduce, I have two EM430 boards spaced approx 40cm on the table, both JTAG-powered and with short pieces of wire instead of antennas. Device B transmits packets continuously. Device A repeatedly calls receive routine that was mostly ripped from RF1A as used in G. Larmore's LED demo:

Initialize:

SetVCore(2); 

PMMCTL0_H = 0xA5;
SVSMHCTL = 0;
SVSMLCTL = 0;
PMMCTL0_H = 0x00;

1) Arm timer for timeout case (the delay is 2x times packet length). 

EnterCriticalSection();
TA1CCTL0 |= CCIE; 
TA1CCTL0 &= ~CCIFG;
TA1CTL &= ~TAIFG;

 TA1CCR0 = timeout_delay;
TA1CTL |= TASSEL_1 + MC_1; 

TA1CTL |= TACLR;
ExitCriticalSection();

 

2) ReceiveOn();

RF1AIES |= BIT9; // Falling edge of RFIFG9
RF1AIFG &= ~BIT9; // Clear a pending interrupt
RF1AIE |= BIT9; // Enable the interrupt

// Radio is in IDLE following a TX, so strobe SRX to enter Receive Mode
Strobe( RF_SRX );

  

3) Enter LPM3 (flagging is crude but was required)

GIS = _get_interrupt_state();
_disable_interrupts();

LPM3_IN_PROCESS = 1;

_set_interrupt_state(GIS);

__bis_SR_register( LPM3_bits + GIE );

 

4) Exit LPM3 either from CC1101 ISR, when RFIFG9 pops up:


TA1CCTL0 &= ~CCIE;
TA1CTL |= TASSEL_1 + MC_0;

TA1CTL &= ~TAIFG;
TA1CCTL0 &= ~CCIFG;

TA1CTL |= TACLR;

V_rxBufferLength = ReadSingleReg( RXBYTES );
ReadBurstReg(RF_RXFIFORD, (uint8_t*)V_rxBuffer, V_rxBufferLength);

if (1 == LPM3_IN_PROCESS )

{ LPM3_IN_PROCESS = 0;_bic_SR_register_on_exit(LPM3_bits); }

 

...or from within timer ISR:

TA1CCTL0 &= ~CCIE;
TA1CTL |= TASSEL_1 + MC_0;

TA1CTL &= ~TAIFG;
TA1CCTL0 &= ~CCIFG;

TA1CTL |= TACLR;

if (1 == LPM3_IN_PROCESS )

{ LPM3_IN_PROCESS = 0;_bic_SR_register_on_exit(LPM3_bits); }

5.  ReceiveOff():

RF1AIE &= ~BIT9; // Disable RX interrupts
RF1AIFG &= ~BIT9; // Clear pending IFG

// It is possible that ReceiveOff is called while radio is receiving a packet.
// Therefore, it is necessary to flush the RX FIFO after issuing IDLE strobe
// such that the RXFIFO is empty prior to receiving a packet.
Strobe( RF_SIDLE );
Strobe( RF_SFRX );

(sorry about formatting)

The above code works well when link quality is good and there are no screening objects, removed antennas. However, once e.g. I several times remove/place back piece of wire acting as antenna, the device A stops execution. 

It is quite possible that there is a misuse of LPM3 mode (the example is pretty dirty, I admit), but I can't see reason for a bug to manifest strictly when link quality changes and not just under random stream of packets. Please share any ideas.

Thanks.

  • Hi,

    If the device that is hanging is JTAG connected and you can reproduce the problem, why not disable the watchdog and see where it is hanging via the debugger?

    Regards,

    Barry

  • Hi,

    Did it, the result was unclear and hinted at problem with handling LPM. So I've cut everything (blessed be GIt designers!). Here is simpler code without any LPM functionality:

    Main:

    while(1)
    {
    ReceiveOn();

    while(0 == G_radioPacketReceived)
    {
    __no_operation();
    }
    ReceiveOff();

    EnterCriticalSection();
    G_radioPacketReceived = 0;
    ExitCriticalSection();

    P1OUT ^= BIT0;
    }


    CC1101 ISR:

    RF1AIE &= ~BIT9;
    G_radioPacketReceived = 1;

    V_rxBufferLength = ReadSingleReg( RXBYTES );
    ReadBurstReg(RF_RXFIFORD, (uint8_t*)V_rxBuffer, V_rxBufferLength); 

    It still hangs when receiving continuous stream of packets (no ISR, thus flag stays forever in 0). The worse the link quality, the easier it happens. I suspect that repeated strobing, along with irregular interrupts from radio core, may cause this.

    This being said, I've just started churning through CC1101 datasheet (I have no prior experience with the chip). It may just be that my predecessor overtaxed 1101 control interface.

     

  • Just an update: common CC1101 workarounds (setting packet len to 61, enabling autoflush etc.) does not exactly help. When device is put in and out of range several times, it hangs with radio core stuck. Of course one could reinit it, but it is way over top.

     

  • Oleg, 

    In the case of low signal strength you will get bad packets in the form of 

    • Short and Long packets, with BAD CRC
    • Short and Long packets, with Good CRC
    • Correct length packets with Good and bad CRC

    Depending on if you are using variable packet length these issues become more or less common. Your code will need to be able to accommodate for all three issues. If the CC1101 is expecting 50 bytes, but only sees 25 it can in some circumstances remain in RX and wait for the rest of the packet. This will to you look like "core stuck"
    I recommend using a timer to set a maximum expiration on the RX command. Lets say, your burst is 2ms long, you then set a timer to expire after 10ms. Then look at the FIFO, clean it up and re-arm the RX.
    Regards,
    Thomas
  • Hi,

    Thanks for reply. 

    I recommend using a timer to set a maximum expiration on the RX command. Lets say, your burst is 2ms long, you then set a timer to expire after 10ms. Then look at the FIFO, clean it up and re-arm the RX.

    The code in my first post is exactly how it was handed to me, and it appears to do just that. The timer is armed, the RX is strobed and whoever gets here first wins - either Timer1 runs out, or CC1101 interrupts (with LPM3_IN_PROCESS flag to prevent one of ISRs from "exiting LPM3" while CPU is active). The process is repeated then, until an application wants to cease reception. 

    Variable packet length is used. 

     

    As of now, I'm observing the following behavior:

    1) Everything works fine when both devices are stationary and RSSI could be considered good (we rotinely test them outdoors at ~150m, line-of-sight).

    2) The receiving device is especially prone to hanging while being moved in and out of good reception zone (I move it around on a rolling table, so possibly no bad contact etc. could cause this).

    Playing around with debugger revealed that it is not just CC1101 (ed: when device stucks). SR has CPU_OFF bit set, and several variables appear damaged when watched (e.g. flag variables should be 0/1,but appear to be large random positives). RTC works, though, and interrupts are called.

    To rule out possible LPM3 mishap (which might be the reason for CPU_OFF stucking set), I've also produced a version of code that replaces LPM3 with while() cycle. Unfortunately, the problem persists - move device in and out of range several times when incoming packets are flooding, and the device gets stuck with garbage in several variables and CPU_OFF set.

    One thing I have not investigated yet is device power settings. As of now, core setting is 2 (setting it to 3 does not solve the issue), and then SVSM is disabled entirely.

     Regards,

  • An update: case closed.

    The cause of bug was botched initialization of CC1101, which set everything right except from packet length, which (after faulty init) stuck as 80. Guess we've produced excellent demo of RX overflow issue described in CC1101's errata.