Look for sample code for CC2430

Help
2009-04-08
2013-03-12
  • Jeremy Thiriet
    Jeremy Thiriet
    2009-04-08

    Hello,

    I'm currently using the 30-day Evaluation IAR to program the 8051 on the CC2430 card. It works fine, but the licence is very expansive.

    I'm looking for a solution to develop with SDCC, but I need a sample code which works on the 2430. In fact my code works only on Keil, Code Composer and IAR. Anyone have a little sample about "How to turn on a LED" please ?

     
    • afgncaap
      afgncaap
      2009-04-08

      I have had mixed feelings about sdcc in this regard, there dosen't seem to be a lot of support out there.  Here is some example code I hacked together out of the keil examples, blinks LED(P1.0) and sends a radio packet:

      Hello_world.c
      -------------------------------------------------------------------------------------------
      #include <mcs51\cc2430.h>
      #include "simpleRF.h"

      int t;
      char str[] = "Hi!\0";

      void timer_isr() __interrupt(T1_VECTOR)
      {
          t++;
          if((t % 4) == 0)
          {
              //Toggle LED
              P1 ^= 0x01;
             
              basicRfSendPacket(0x0001,str,4);
          }
          T1CTL = 0x0D;
      }

      /* A simple program to blink an LED and send a packet*/
      void main()
      {
          basicRfCfg_t config;
         
          /*set port 1 to output, no functions*/
         
          P1SEL = 0x00;
          P1DIR = 0x03;
          P1 = 0x03;
         
         
          /*Setup radio*/
          config.myAddr = 0x0000;
          config.panId = 0xA0A0;
          config.channel = 11;
          config.ackRequest = 0;
         
          rfInit(&config);
          rfReceiveOff();

         
          /*start timer1*/
          t = 0;
          T1CTL = 0x0D;
          T1CCTL0 &= 0x00;
          T1CCTL1 &= 0x00;
          T1CCTL2 &= 0x00;
          TIMIF = 0x40;

          IEN1 = 0x02;
          IEN0 = 0x80;

          while(1)
          {
          }
      }

      simpleRF.h
      -------------------------------------------------------------------------------------------
      /*  This code is based on the basic_RF header files from the TI cc2430 example code
        *
        */
      #ifndef _SIMPLERF
      #define _SIMPLERF 
       
      #include <mcs51\cc2430.h>

      #define st(x)      do { x } while (__LINE__ == -1)

      #ifdef BIG_ENDIAN
      #error "Big Endian is defined"
      #define UINT16_HTON(x)  st( utilReverseBuf((uint8*)&x, sizeof(uint16)); )
      #define UINT16_NTOH(x)  st( utilReverseBuf((uint8*)&x, sizeof(uint16)); )

      #define UINT32_HTON(x)  st( utilReverseBuf((uint8*)&x, sizeof(uint32)); )
      #define UINT32_NTOH(x)  st( utilReverseBuf((uint8*)&x, sizeof(uint32)); )      
      #else
      #define UINT16_HTON(x)
      #define UINT16_NTOH(x) 

      #define UINT32_HTON(x) 
      #define UINT32_NTOH(x) 
      #endif

      #ifndef TRUE
      #define TRUE 1
      #endif

      #ifndef FALSE
      #define FALSE 0
      #endif

      #ifndef SUCCESS
      #define SUCCESS 0
      #endif

      #ifndef FAILED
      #define FAILED  1
      #endif

      #ifndef NULL
      #define NULL (void *)0
      #endif

      #ifndef BV
      #define BV(n)      (1 << (n))
      #endif

      #ifndef BM
      #define BM(n)      (1 << (n))
      #endif

      #ifndef BF
      #define BF(x,b,s)  (((x) & (b)) >> (s))
      #endif

      #ifndef MIN
      #define MIN(n,m)   (((n) < (m)) ? (n) : (m))
      #endif

      #ifndef MAX
      #define MAX(n,m)   (((n) < (m)) ? (m) : (n))
      #endif

      #ifndef ABS
      #define ABS(n)     (((n) < 0) ? -(n) : (n))
      #endif

      #ifndef WIN32
      #define UPPER_WORD(a) ((int) (((long)(a)) >> 16))
      #define HIWORD(a)     UPPER_WORD(a)

      #define LOWER_WORD(a) ((int) ((long)(a)))
      #define LOWORD(a)     LOWER_WORD(a)

      #define UPPER_BYTE(a) ((char) (((int)(a)) >> 8))
      #define HIBYTE(a)     UPPER_BYTE(a)

      #define LOWER_BYTE(a) ((char) ( (int)(a))      )
      #define LOBYTE(a)     LOWER_BYTE(a)
      #endif

      // Chip revision
      #define REV_A                   0x01
      #define REV_B                   0x02
      #define REV_C                   0x03
      #define REV_D                   0x04
      #define REV_E                   0x05
      #define REV_F                   0x06

      #define CHIPREVISION            REV_E

      // Security
      #define PKT_LEN_MAX              127

      // CC2430 RSSI Offset
      #define RSSI_OFFSET               45
      #define RSSI_OFFSET_LNA_HIGHGAIN  RSSI_OFFSET + 12
      #define RSSI_OFFSET_LNA_LOWGAIN   RSSI_OFFSET + 6

      // Output power programming (TXCTRLL)
      #define PA_LEVEL_MASK           0x1F

      // RF status flags
      #define TX_ACTIVE_FLAG          0x10
      #define FIFO_FLAG               0x08
      #define FIFOP_FLAG              0x04
      #define SFD_FLAG                0x02
      #define CCA_FLAG                0x01

      // Radio status states
      #define TX_ACTIVE()             (RFSTATUS & TX_ACTIVE_FLAG)
      #define FIFO()                  (RFSTATUS & FIFO_FLAG)
      #define FIFOP()                 (RFSTATUS & FIFOP_FLAG)
      #define SFD()                   (RFSTATUS & SFD_FLAG)
      #define CCA()                   (RFSTATUS & CCA_FLAG)

      // Various radio settings
      #define ADR_DECODE              0x08
      #define AUTO_CRC                0x20
      #define AUTO_ACK                0x10
      #define AUTO_TX2RX_OFF          0x08
      #define RX2RX_TIME_OFF          0x04
      #define ACCEPT_ACKPKT           0x01

      // RF interrupt flags
      #define IRQ_RREG_ON             0x80
      #define IRQ_TXDONE              0x40
      #define IRQ_FIFOP               0x20
      #define IRQ_SFD                 0x10
      #define IRQ_CCA                 0x08
      #define IRQ_CSP_WT              0x04
      #define IRQ_CSP_STOP            0x02
      #define IRQ_CSP_INT             0x01

      // RF status flags

      // Selected strobes
      #define ISRXON()                st(RFST = 0xE2;)
      #define ISTXON()                st(RFST = 0xE3;)
      #define ISTXONCCA()             st(RFST = 0xE4;)
      #define ISRFOFF()               st(RFST = 0xE5;)
      #define ISFLUSHRX()             st(RFST = 0xE6;)
      #define ISFLUSHTX()             st(RFST = 0xE7;)
      #define FLUSH_RX_FIFO()         st( ISFLUSHRX(); ISFLUSHRX(); )

      // Packet and packet part lengths
      #define PKT_LEN_MIC                         8
      #define PKT_LEN_SEC                         PKT_LEN_UNSEC + PKT_LEN_MIC
      #define PKT_LEN_AUTH                        8
      #define PKT_LEN_ENCR                        24

      // Packet overhead ((frame control field, sequence number, PAN ID,
      // destination and source) + (footer))
      // Note that the length byte itself is not included included in the packet length
      #define BASIC_RF_PACKET_OVERHEAD_SIZE       ((2 + 1 + 2 + 2 + 2) + (2))
      #define BASIC_RF_MAX_PAYLOAD_SIZE            (127 - BASIC_RF_PACKET_OVERHEAD_SIZE - \     BASIC_RF_AUX_HDR_LENGTH - BASIC_RF_LEN_MIC)
      #define BASIC_RF_ACK_PACKET_SIZE            5
      #define BASIC_RF_FOOTER_SIZE                2

      // The time it takes for the acknowledgment packet to be received after the
      // data packet has been transmitted.
      #define BASIC_RF_ACK_DURATION                (0.5 * 32 * 2 * ((4 + 1) + (1) + (2 + 1) + (2)))
      #define BASIC_RF_SYMBOL_DURATION            (32 * 0.5)

      // The length byte
      #define BASIC_RF_PLD_LEN_MASK               0x7F

      // Frame control field
      #define BASIC_RF_FCF_NOACK                  0x8841
      #define BASIC_RF_FCF_ACK                    0x8861
      #define BASIC_RF_FCF_ACK_BM                 0x0020
      #define BASIC_RF_FCF_BM                     (~BASIC_RF_FCF_ACK_BM)
      #define BASIC_RF_ACK_FCF                    0x0002
      #define BASIC_RF_SEC_ENABLED_FCF_BM         0x0008

      // Auxiliary Security header
      #define BASIC_RF_AUX_HDR_LENGTH             5
      #define BASIC_RF_LEN_AUTH                   BASIC_RF_PACKET_OVERHEAD_SIZE + \     BASIC_RF_AUX_HDR_LENGTH - BASIC_RF_FOOTER_SIZE
      #define BASIC_RF_SECURITY_M                 2
      #define BASIC_RF_LEN_MIC                    8

      // Footer
      #define BASIC_RF_CRC_OK_BM                  0x80

      // IEEE 802.15.4 defined constants (2.4 GHz logical channels)
      #define MIN_CHANNEL                         11    // 2405 MHz
      #define MAX_CHANNEL                         26    // 2480 MHz
      #define CHANNEL_SPACING                     5     // MHz

      #define uint16 unsigned int
      #define uint8 unsigned char
      #define int8 char
      #define uint32 unsigned long

      typedef struct {
          uint16 myAddr;
          uint16 panId;
          uint8 channel;
          uint8 ackRequest;
      } basicRfCfg_t;

      // The receive struct
      typedef struct {
          uint8 seqNumber;
          uint16 srcAddr;
          uint16 srcPanId;
          int8 length;
          uint8* pPayload;
          uint8 ackRequest;
          int8 rssi;
          volatile uint8 isReady;
          uint8 status;
      } basicRfRxInfo_t;

      // Tx state
      typedef struct {
          uint8 txSeqNumber;
          volatile uint8 ackReceived;
          uint8 receiveOn;
          uint32 frameCounter;
      } basicRfTxState_t;

      typedef struct {
          uint8   packetLength;
          uint16  frameControlField;
          uint8   seqNumber;
          uint16  panId;
          uint16  destAddr;
          uint16  srcAddr;
      } basicRfPktHdr_t;

      void intOn();
      void intOff();
      void halRfSetChannel(uint8);
      void halRfSetShortAddr(uint16);
      void halRfSetPanId(uint16);
      void boardInit();
      uint8 halRfInit();
      uint8 rfInit(basicRfCfg_t*);
      void halRfWriteTxBuf(uint8*, uint8);
      void halRfReadRxBuf(uint8*, uint8);
      uint8 halRfTransmit();
      void halRfReceiveOn();
      void rfReceiveOff();
      void halRfDisableRxInterrupt();
      void halRfEnableRxInterrupt();
      void halRfWaitTransceiverReady();
      static uint8 basicRfBuildMpdu(uint16, uint8*, uint8);
      static uint8 basicRfBuildHeader(uint8*, uint16, uint8);
      uint8 basicRfSendPacket(uint16, uint8*, uint8);
      int packetReceived();
      void wait(uint16);
      #endif

      simpleRF.c
      -------------------------------------------------------------------------------------------
      /*  This code is based on the basic_RF header files from the TI cc2430 example code
        *
        */
      #include "simpleRF.h"

      static basicRfRxInfo_t  rxi=      { 0xFF }; // Make sure sequence numbers are
      static basicRfTxState_t txState=  { 0x00 }; // initialised and distinct.
      static basicRfCfg_t* pConfig;

      far static uint8 txMpdu[BASIC_RF_MAX_PAYLOAD_SIZE+BASIC_RF_PACKET_OVERHEAD_SIZE+1];
      far static uint8 rxMpdu[BASIC_RF_MAX_PAYLOAD_SIZE+BASIC_RF_PACKET_OVERHEAD_SIZE+1];

      void basicRfRxFrmDoneIsr() __interrupt(RF_VECTOR)
      {
          basicRfPktHdr_t *pHdr;
          uint8 *pStatusWord;

          // Map header to packet buffer
          pHdr= (basicRfPktHdr_t*)rxMpdu;

          // Clear interrupt and disable new RX frame done interrupt
          halRfDisableRxInterrupt();

          // Enable all other interrupt sources (enables interrupt nesting)
          intOn();

          // Read payload length.
          halRfReadRxBuf(&pHdr->packetLength,1);
          pHdr->packetLength &= BASIC_RF_PLD_LEN_MASK; // Ignore MSB

          // Is this an acknowledgment packet?
          // Only ack packets may be 5 bytes in total.
          if (pHdr->packetLength == BASIC_RF_ACK_PACKET_SIZE) {

              // Read the packet
              halRfReadRxBuf(&rxMpdu[1], pHdr->packetLength);

              // Make sure byte fields are changed from network to host byte order
              UINT16_NTOH(pHdr->frameControlField);
              UINT16_NTOH(pHdr->panId);
              UINT16_NTOH(pHdr->destAddr);
              UINT16_NTOH(pHdr->srcAddr);

              rxi.ackRequest = !!(pHdr->frameControlField & BASIC_RF_FCF_ACK_BM);

              // Read the status word and check for CRC OK
              pStatusWord= rxMpdu + 4;

              // Indicate the successful ACK reception if CRC and sequence number OK
              if ((pStatusWord[1] & BASIC_RF_CRC_OK_BM) && (pHdr->seqNumber == txState.txSeqNumber)) {
                  txState.ackReceived = TRUE;
              }

              // No, it is data
          } else {

              // It is assumed that the radio rejects packets with invalid length.
              // Subtract the number of bytes in the frame overhead to get actual payload.

              rxi.length = pHdr->packetLength - BASIC_RF_PACKET_OVERHEAD_SIZE;

              halRfReadRxBuf(&rxMpdu[1], pHdr->packetLength);

              // Make sure byte fields are changed from network to host byte order
              UINT16_NTOH(pHdr->frameControlField);
              UINT16_NTOH(pHdr->panId);
              UINT16_NTOH(pHdr->destAddr);
              UINT16_NTOH(pHdr->srcAddr);

              rxi.ackRequest = !!(pHdr->frameControlField & BASIC_RF_FCF_ACK_BM);

              // Read the source address
              rxi.srcAddr= pHdr->srcAddr;

              // Read the packet payload
              rxi.pPayload = rxMpdu+sizeof(basicRfPktHdr_t);

              // Read the FCS to get the RSSI and CRC
              pStatusWord= rxi.pPayload+rxi.length;
              rxi.rssi = pStatusWord[0];

              // Notify the application about the received data packet if the CRC is OK
              // Throw packet if the previous packet had the same sequence number
              if( (pStatusWord[1] & BASIC_RF_CRC_OK_BM) && (rxi.seqNumber != pHdr->seqNumber) ) {
                  // If security is used check also that authentication passed
                  if ( ((pHdr->frameControlField & (BASIC_RF_FCF_BM)) == BASIC_RF_FCF_NOACK) ) {
                      rxi.isReady = TRUE;
                  }
              }

              rxi.seqNumber = pHdr->seqNumber;
          }

          // Enable RX frame done interrupt again
          intOff();
          halRfEnableRxInterrupt();
      }

      void intOn()
      {
          IEN0 |= 0x80;   
      }

      void intOff()
      {
          IEN0 &= 0x7F;
      }

      void halRfSetChannel(uint8 channel)
      {
          uint16 freqMHz;

          freqMHz= 2405 + ((channel - MIN_CHANNEL) * CHANNEL_SPACING); // Calculate frequency
          freqMHz -= (uint32)2048;              // Subtract; datasheet sect 14.16

          FSCTRLL = LOBYTE(freqMHz);
          FSCTRLH &= ~0x03;
          FSCTRLH |= (HIBYTE(freqMHz) & 0x03);
      }

      void halRfSetShortAddr(uint16 shortAddr)
      {
          SHORTADDRL= LOBYTE(shortAddr);
          SHORTADDRH= HIBYTE(shortAddr);
      }

      void halRfSetPanId(uint16 panId)
      {
          PANIDL= LOBYTE(panId);
          PANIDH= HIBYTE(panId);
      }

      void boardInit()
      {
           /*Set clock to XOSC */
          SLEEP &= 0xFB;
          while (!(SLEEP & 0x40)) {}
          wait(64);
         
          CLKCON &= 0xBF;
          while (CLKCON != 0xBF);
          SLEEP |= 0x04;
         
          intOn();
      }

      uint8 halRfInit(void)
      {
          uint8 i;

          // turning on power to analog part of radio and waiting for voltage regulator.
          RFPWR = 0x04;
          while( RFPWR & 0x10 );

          // Setting for AUTO CRC and AUTOACK
          MDMCTRL0L |= (AUTO_CRC | AUTO_ACK);

          // Turning on AUTO_TX2RX
          FSMTC1 = ((FSMTC1 & (~AUTO_TX2RX_OFF & ~RX2RX_TIME_OFF))  | ACCEPT_ACKPKT);

          // Turning off abortRxOnSrxon.
          FSMTC1 &= ~0x20;

          // Set FIFOP threshold to maximum
          IOCFG0 = 0x7F;
          // tuning adjustments for optimal radio performance; details available in datasheet */
          RXCTRL0H = 0x32;
          RXCTRL0L = 0xF5;

          // Turning on receiver to get output from IF-ADC
          ISRXON();
          for(i = 0; i < 10; i++){}//halMcuWaitUs(1);

          // Enable random generator
          ADCCON1 &= ~0x0C;

          for(i = 0 ; i < 32 ; i++)
          {
              RNDH = ADCTSTH;
              // Clock random generator
              ADCCON1 |= 0x04;
          }
          ISRFOFF();

          // enable RX_FIFOP interrupt
          RFIM |= BV(5);
          // enable general RF interrupts
          IEN2 |= BV(0);

          return SUCCESS;
      }

      uint8 rfInit(basicRfCfg_t* pRfConfig)
      {
          if (halRfInit()==FAILED)
              return FAILED;

          intOff();

          pConfig = pRfConfig;
          // Set the protocol configuration
          rxi.pPayload   = NULL;

          txState.receiveOn = TRUE;
          txState.frameCounter = 0;

          // Set channel
          halRfSetChannel(pConfig->channel);

          // Write the short address and the PAN ID to the CC2520 RAM
          halRfSetShortAddr(pConfig->myAddr);
          halRfSetPanId(pConfig->panId);

          intOn();

          return SUCCESS;
      }

      void halRfWriteTxBuf(uint8* pData, uint8 length)
      {
          uint8 i;

          ISFLUSHTX();          // Making sure that the TX FIFO is empty.

          RFIF = ~IRQ_TXDONE;   // Clear TX done interrupt

          // Insert data
          for(i=0;i<length;i++){
              RFD = pData[i];
          }

      }

      void halRfReadRxBuf(uint8* pData, uint8 length)
      {
          while (length>0) {
              *pData++= RFD;
              length--;
          }
      }

      uint8 halRfTransmit(void)
      {
          uint8 status;

          ISTXON(); // Sending

          // Waiting for transmission to finish
          while(!(RFIF & IRQ_TXDONE) );

          RFIF = ~IRQ_TXDONE;
          status= SUCCESS;

          // TBD: use CCA
          return status;
      }

      void halRfReceiveOn(void)
      {
          FLUSH_RX_FIFO();
          ISRXON();
      }

      void rfReceiveOff(void)
      {
          txState.receiveOn = FALSE;
          ISRFOFF();
          FLUSH_RX_FIFO();
      }

      void halRfDisableRxInterrupt(void)
      {
        // disable RX_FIFOP interrupt
        RFIM &= ~BV(5);
        // disable general RF interrupts
        IEN2 &= ~BV(0);
      }

      void halRfEnableRxInterrupt(void)
      {
        // enable RX_FIFOP interrupt
        RFIM |= BV(5);
        // enable general RF interrupts
        IEN2 |= BV(0);
      }

      void halRfWaitTransceiverReady(void)
      {
          while (RFSTATUS & (BV(1) | BV(4) ));
      }

      static uint8 basicRfBuildMpdu(uint16 destAddr, uint8* pPayload, uint8 payloadLength)
      {
          uint8 hdrLength, n;

          hdrLength = basicRfBuildHeader(txMpdu, destAddr, payloadLength);

          for(n=0;n<payloadLength;n++)
          {
              txMpdu[hdrLength+n] = pPayload[n];
          }
          return hdrLength + payloadLength; // total mpdu length
      }

      static uint8 basicRfBuildHeader(uint8* buffer, uint16 destAddr, uint8 payloadLength)
      {
          basicRfPktHdr_t *pHdr;

          pHdr= (basicRfPktHdr_t*)buffer;

          // Populate packet header
          pHdr->packetLength = payloadLength + BASIC_RF_PACKET_OVERHEAD_SIZE;
          pHdr->frameControlField = pConfig->ackRequest ? BASIC_RF_FCF_ACK : BASIC_RF_FCF_NOACK;
          pHdr->seqNumber= txState.txSeqNumber;
          pHdr->panId= pConfig->panId;
          pHdr->destAddr= destAddr;
          pHdr->srcAddr= pConfig->myAddr;

          // Make sure bytefields are network byte order
          UINT16_HTON(pHdr->frameControlField);
          UINT16_HTON(pHdr->panId);
          UINT16_HTON(pHdr->destAddr);
          UINT16_HTON(pHdr->srcAddr);

          return sizeof(basicRfPktHdr_t);
      }

      uint8 basicRfSendPacket(uint16 destAddr, uint8* pPayload, uint8 length)
      {
          uint8 mpduLength;
          uint8 status;

          // Turn on receiver if its not on
          if(!txState.receiveOn) {
              halRfReceiveOn();
          }

          // Check packet length
          length = MIN(length, BASIC_RF_MAX_PAYLOAD_SIZE);

          // Wait until the transceiver is idle
          halRfWaitTransceiverReady();

          // Turn off RX frame done interrupt to avoid interference on the SPI interface
          halRfDisableRxInterrupt();

          mpduLength = basicRfBuildMpdu(destAddr, pPayload, length);

          halRfWriteTxBuf((uint8*)txMpdu, mpduLength);

          // Turn on RX frame done interrupt for ACK reception
          halRfEnableRxInterrupt();

          // Send frame with CCA. return FAILED if not successful
          if(halRfTransmit() != SUCCESS) {
              status = FAILED;
          }

          // Wait for the acknowledge to be received, if any
          if (pConfig->ackRequest) {
              txState.ackReceived = FALSE;

              // We'll enter RX automatically, so just wait until we can be sure that the ack reception should have finished
              // The timeout consists of a 12-symbol turnaround time, the ack packet duration, and a small margin
              wait((12 * BASIC_RF_SYMBOL_DURATION) + (BASIC_RF_ACK_DURATION) + (2 * BASIC_RF_SYMBOL_DURATION) + 10);

              // If an acknowledgment has been received (by RxFrmDoneIsr), the ackReceived flag should be set
              status = txState.ackReceived ? SUCCESS : FAILED;

          } else {
              status = SUCCESS;
          }

          // Turn off the receiver if it should not continue to be enabled
          if (!txState.receiveOn) {
              rfReceiveOff();
          }

          if(status == SUCCESS) {
              txState.txSeqNumber++;
          }
          return status;

      }

      int packetReceived()
      {
          return rxi.isReady;
      }   

      void wait(uint16 usec)
      {
          while(usec--)
          {
              _asm
              nop
              nop
              nop
              nop
              nop
              nop
              nop
              nop
              nop
              nop
              _endasm;
          }
      }

       
  • milin
    milin
    2012-02-28

    i am looking for help in programming TI's cc2530 and cc2531. please help.