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.