Hi, I try to use a CC430F5137 as a receiver which forwards the received data to a PC via a UART connection.
The CC430 is permanently in Rx-state waiting for incoming packets (up to 5 bytes). When a valid packet is detected (RFIFG9 + CRC_OK) the received data is written to a ringbuffer. To forward the data to the PC a Matlab-script is polling every two seconds by sending an'a' to the CC430.
My code works fine for some time (minutes to hours) till it fails.
Then either the CC430 stops receiving data, but the UART connection still works or the UART connection fails, so in Matlab there always occurs a timeout when data should be received.
For debugging I implemented the blinking of a led in the main() function. When I tried to debug the code (in the condition where the CC430 stopped receiving) I asserted that the direction of the led port was changed form output to input, which I can't explain.
I also implemented a watchdog timer (source XT2 interval 83 sec) which is reset when data is received either via the RF link or the UART connection. But the watchdog doesn't reset the CC430 when the UART connection fails. In this condition the led also stops blinking, so I the the watchdog timer isn't reset in the CC1101_ISR either. I also put a breakepoint in the main()-while loop when the failure of the UART connection occured which was never reached.
Can anybody tell me what's my problem?
Why does the reception of data via the Radio module or the UART connection fail at all?
And why does the CC430 behave like it does in the case of a faliure?
Thanks in advance.
#include <msp430.h> #include <RF1A.h> #define MAX_TX_PACKET_LEN (500) #define MAX_RX_PACKET_LEN (55) #define RINGBUF_SIZE (252) #define CRC_OK (BIT7) #define SUCCESS (0) #define EVENT (1) #define MIN(n,m) (((n) < (m)) ? (n) : (m)) void ReadData(void); void SendData(void); void InitTimer(void); void InitRadio(void); void InitUart(void); unsigned char ringbufferIn(unsigned char byte); unsigned char ringbufferOut(unsigned char *buffer); extern RF_SETTINGS rfSettings; unsigned char read_data = 0; unsigned char senddata = 0; unsigned char ringbuffer[RINGBUF_SIZE]; unsigned int write = 0; unsigned int read = 0; unsigned char ringbuffull = 0; unsigned long count = 0; int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer PMMCTL0 = PMMPW + PMMCOREV_3; P1OUT &= BIT0; P1DIR |= BIT0; InitRadio(); InitTimer(); InitUart(); // Select ACLK as WDT clock, clear WDT counter and set WDT interval to 2^31/clock source ~ 83s WDTCTL = WDTPW | WDTSSEL__ACLK | WDTCNTCL | WDTIS_0; RF1AIES |= BIT9; // select negative edge for end of packet interrupt RF1AIFG = 0; // Clear pending RFIFG interrupts RF1AIE |= BIT9; // Enable end of packet interrupt Strobe(RF_SIDLE); Strobe(RF_SRX); __enable_interrupt(); while(1) { count++; if(count > 400000) { P1OUT ^= BIT0; count = 0; } if(read_data) { ReadData(); } if(senddata) { SendData(); } } } void ReadData(void) { unsigned char RxBuffer[MAX_RX_PACKET_LEN+2] = {0}; // +2 for status bytes unsigned char RxBufferLength; unsigned char i; RF1AIFG &= 0; // Clear pending IFG RxBufferLength = ReadSingleReg( RXBYTES ); ReadBurstReg(RF_RXFIFORD, RxBuffer, RxBufferLength); // RSSI_index = RxBufferLength-2; if(RxBuffer[RxBufferLength - 1] & CRC_OK) { for (i=1; i < RxBufferLength-2; i++) { ringbufferIn(RxBuffer[i]); if((i % 5) == 0) { ringbufferIn(0xFF); } } } read_data = 0; Strobe( RF_SIDLE ); Strobe( RF_SFRX ); Strobe( RF_SRX ); } void SendData(void) { unsigned int bytes_in_ring_buffer = 0; unsigned char tx_count = 0; unsigned char txBuffer; if(read != write || (read == write && ringbuffull)) { if(read < write) { bytes_in_ring_buffer = write - read; } else { bytes_in_ring_buffer = RINGBUF_SIZE + write - read; } tx_count = MIN(bytes_in_ring_buffer, MAX_TX_PACKET_LEN); while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = tx_count; while(tx_count) { while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready? __delay_cycles(5000); ringbufferOut(&txBuffer); tx_count--; UCA0TXBUF = txBuffer; } } else { while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = 0x01; __delay_cycles(5000); while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = 0x00; } senddata = 0; } void InitTimer(void) { UCSCTL6 &= ~XT2OFF; UCSCTL3 |= SELREF_2; UCSCTL4 = SELA__REFOCLK + SELS__DCOCLKDIV + SELM__DCOCLKDIV; do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); SFRIFG1 &= ~OFIFG; }while (SFRIFG1&OFIFG); UCSCTL4 |= SELA__XT2CLK + SELS__XT2CLK + SELM__XT2CLK; UCSCTL5 |= DIVS_1; } void InitRadio(void) { WriteRfSettings(&rfSettings); } void InitUart(void) { PMAPPWD = 0x02D52; // Get write-access to port mapping regs P1MAP5 = PM_UCA0RXD; // Map UCA0RXD output to P1.5 P1MAP6 = PM_UCA0TXD; // Map UCA0TXD output to P1.6 PMAPPWD = 0; // Lock port mapping registers P1DIR |= BIT6; // Set P1.6 as TX output P1SEL |= BIT5 + BIT6; // Select P1.5 & P1.6 to UART function UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL1 |= UCSSEL_2; // SMCLK UCA0BR0 = 112; // 26MHz 115200 UCA0BR1 = 0; // 26MHz 115200 UCA0MCTL |= UCBRS_7 + UCBRF_0; // Modulation UCBRSx=7, UCBRFx=0 UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt } unsigned char ringbufferIn(unsigned char byte) { unsigned char retval = SUCCESS; if (ringbuffull) { read++; if(read >= RINGBUF_SIZE) { read = 0; } retval = EVENT; } ringbuffer[write] = byte; write++; if (write >= RINGBUF_SIZE) { write = 0; } if(write == read) { ringbuffull = 1; } return retval; } unsigned char ringbufferOut(unsigned char *buffer) { if (((read == write) && !ringbuffull)) return EVENT; *buffer = ringbuffer[read]; read++; if (read >= RINGBUF_SIZE) { read = 0; } if(read == write) { ringbuffull = 0; P1OUT &= ~BIT0; } return SUCCESS; } #pragma vector=CC1101_VECTOR __interrupt void CC1101_ISR(void) { switch(__even_in_range(RF1AIV,32)) // Prioritizing Radio Core Interrupt { case 0: break; // No RF core interrupt pending case 2: break; // RFIFG0 case 4: break; // RFIFG1 case 6: break; // RFIFG2 case 8: break; // RFIFG3 case 10: break; // RFIFG4 case 12: break; // RFIFG5 case 14: break; // RFIFG6 case 16: break; // RFIFG7 case 18: break; // RFIFG8 case 20: // RFIFG9 read_data = 1; WDTCTL = WDTPW | WDTCNTCL; break; case 22: break; // RFIFG10 case 24: break; // RFIFG11 case 26: break; // RFIFG12 case 28: break; // RFIFG13 case 30: break; // RFIFG14 case 32: break; // RFIFG15 } } #pragma vector=USCI_A0_VECTOR __interrupt void USCI_A0_ISR(void) { switch(__even_in_range(UCA0IV,4)) { case 0:break; case 2: if (UCA0RXBUF == 0x61) { senddata = 1; WDTCTL = WDTPW | WDTCNTCL; } break; case 4:break; default: break; } }