Example #1
0
/*---------------------------------------------------------------------------*/
static int
prepare(const void *payload, unsigned short payload_len)
{
  uint8_t i;

  PRINTF("RF: Prepare 0x%02x bytes\n", payload_len + CHECKSUM_LEN);

  /*
   * When we transmit in very quick bursts, make sure previous transmission
   * is not still in progress before re-writing to the TX FIFO
   */
  while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);

  if((rf_flags & RX_ACTIVE) == 0) {
    on();
  }

  CC2538_RF_CSP_ISFLUSHTX();

  PRINTF("RF: data = ");
  /* Send the phy length byte first */
  REG(RFCORE_SFR_RFDATA) = payload_len + CHECKSUM_LEN;

  if(CC2538_RF_CONF_TX_USE_DMA) {
    PRINTF("<uDMA payload>");

    /* Set the transfer source's end address */
    udma_set_channel_src(CC2538_RF_CONF_TX_DMA_CHAN,
                         (uint32_t)(payload) + payload_len - 1);

    /* Configure the control word */
    udma_set_channel_control_word(CC2538_RF_CONF_TX_DMA_CHAN,
                                  UDMA_TX_FLAGS | udma_xfer_size(payload_len));

    /* Enabled the RF TX uDMA channel */
    udma_channel_enable(CC2538_RF_CONF_TX_DMA_CHAN);

    /* Trigger the uDMA transfer */
    udma_channel_sw_request(CC2538_RF_CONF_TX_DMA_CHAN);

    /*
     * No need to wait for this to end. Even if transmit() gets called
     * immediately, the uDMA controller will stream the frame to the TX FIFO
     * faster than transmit() can empty it
     */
  } else {
    for(i = 0; i < payload_len; i++) {
      REG(RFCORE_SFR_RFDATA) = ((unsigned char *)(payload))[i];
      PRINTF("%02x", ((unsigned char *)(payload))[i]);
    }
  }
  PRINTF("\n");

  return 0;
}
Example #2
0
/*---------------------------------------------------------------------------*/
static int
read(void *buf, unsigned short bufsize)
{
  uint8_t i;
  uint8_t len;
  uint8_t crc_corr;
  int8_t rssi;

  PRINTF("RF: Read\n");

  if((REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) == 0) {
    return 0;
  }

  /* Check the length */
  len = REG(RFCORE_SFR_RFDATA);

  /* Check for validity */
  if(len > CC2538_RF_MAX_PACKET_LEN) {
    /* Oops, we must be out of sync. */
    PRINTF("RF: bad sync\n");

    RIMESTATS_ADD(badsynch);
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

  if(len <= CC2538_RF_MIN_PACKET_LEN) {
    PRINTF("RF: too short\n");

    RIMESTATS_ADD(tooshort);
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

  if(len - CHECKSUM_LEN > bufsize) {
    PRINTF("RF: too long\n");

    RIMESTATS_ADD(toolong);
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

  /* If we reach here, chances are the FIFO is holding a valid frame */
  PRINTF("RF: read (0x%02x bytes) = ", len);
  len -= CHECKSUM_LEN;

  /* Don't bother with uDMA for short frames (e.g. ACKs) */
  if(CC2538_RF_CONF_RX_USE_DMA && len > UDMA_RX_SIZE_THRESHOLD) {
    PRINTF("<uDMA payload>");

    /* Set the transfer destination's end address */
    udma_set_channel_dst(CC2538_RF_CONF_RX_DMA_CHAN,
                         (uint32_t)(buf) + len - 1);

    /* Configure the control word */
    udma_set_channel_control_word(CC2538_RF_CONF_RX_DMA_CHAN,
                                  UDMA_RX_FLAGS | udma_xfer_size(len));

    /* Enabled the RF RX uDMA channel */
    udma_channel_enable(CC2538_RF_CONF_RX_DMA_CHAN);

    /* Trigger the uDMA transfer */
    udma_channel_sw_request(CC2538_RF_CONF_RX_DMA_CHAN);

    /* Wait for the transfer to complete. */
    while(udma_channel_get_mode(CC2538_RF_CONF_RX_DMA_CHAN));
  } else {
    for(i = 0; i < len; ++i) {
      ((unsigned char *)(buf))[i] = REG(RFCORE_SFR_RFDATA);
      PRINTF("%02x", ((unsigned char *)(buf))[i]);
    }
  }

  /* Read the RSSI and CRC/Corr bytes */
  rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET;
  crc_corr = REG(RFCORE_SFR_RFDATA);

  PRINTF("%02x%02x\n", (uint8_t)rssi, crc_corr);

  /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */
  if(crc_corr & CRC_BIT_MASK) {
    packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
    packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK);
    RIMESTATS_ADD(llrx);
  } else {
    RIMESTATS_ADD(badcrc);
    PRINTF("RF: Bad CRC\n");
    CC2538_RF_CSP_ISFLUSHRX();
    return 0;
  }

#if CC2538_RF_CONF_SNIFFER
  write_byte(magic[0]);
  write_byte(magic[1]);
  write_byte(magic[2]);
  write_byte(magic[3]);
  write_byte(len + 2);
  for(i = 0; i < len; ++i) {
    write_byte(((unsigned char *)(buf))[i]);
  }
  write_byte(rssi);
  write_byte(crc_corr);
  flush();
#endif

  /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
  if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) {
    if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) {
      process_poll(&cc2538_rf_process);
    } else {
      CC2538_RF_CSP_ISFLUSHRX();
    }
  }

  return (len);
}
Example #3
0
PROCESS_THREAD(spiProcess, ev, data) {
    PROCESS_BEGIN();
    uint8_t spi_data_fifo[SPIFIFOSIZE];
    uint8_t packetLen;
    spi_packet_t spi_rx_pkt;
    uint8_t* dma_src_end_addr;
    static uint8_t spi_data_ptr = 0;
    uint8_t proc_idx;


    while (1){
        PROCESS_YIELD();
        switch (spiState){
            case SPI_RESET:
                spi_cs_int = 0;
                spi_rxfifo_halffull = 0; 
                spiInUse = 0;
                spi_data_ptr = 0;
                spix_interrupt_enable(SPIDEV, SSI_IM_RXIM_M);
                spiState = SPI_WAIT;
                process_poll(&mainProcess);
                #ifdef LED_DEBUG
                leds_off(LEDS_RED);
                leds_on(LEDS_GREEN);
                leds_on(LEDS_BLUE);
                #endif
            break;

            /* Wait SPI from Edison*/
            case SPI_WAIT:
                #ifdef LED_DEBUG
                leds_on(LEDS_BLUE);
                #endif
                if (spi_rxfifo_halffull==1){
                    spi_rxfifo_halffull = 0; 
                    spi_data_ptr += spix_get_data(SPIDEV, spi_data_fifo+spi_data_ptr);
                    spix_interrupt_enable(SPIDEV, SSI_IM_RXIM_M);
                    spiInUse = 1;
                }
                if (spi_cs_int==1){
                    spi_data_ptr += spix_get_data(SPIDEV, spi_data_fifo+spi_data_ptr);
                    spi_cs_int = 0;
                    spiInUse = 1;
                    proc_idx = 0;
                    while (proc_idx < spi_data_ptr){
                        proc_idx += spi_packet_parse(&spi_rx_pkt, spi_data_fifo+proc_idx);
                        switch (spi_rx_pkt.cmd){
                            // write length and data into tx fifo
                            case SPI_MASTER_REQ_DATA:
                                packetLen = triumviRXPackets[triumviFullIDX].length;
                                spix_put_data_single(SPIDEV, packetLen);
                                dma_src_end_addr = triumviRXPackets[triumviFullIDX].payload + packetLen - 1;
                                udma_set_channel_src(CC2538_SPI0_TX_DMA_CHAN, (uint32_t)(dma_src_end_addr));
                                udma_set_channel_control_word(CC2538_SPI0_TX_DMA_CHAN, 
                                    (SPI0TX_DMA_FLAG | udma_xfer_size(packetLen)));
                                udma_channel_enable(CC2538_SPI0_TX_DMA_CHAN);
                                GPIO_CLR_PIN(TRIUMVI_DATA_READY_PORT_BASE, TRIUMVI_DATA_READY_MASK);
                            break;

                            // do nothing...
                            case SPI_MASTER_DUMMY:
                            break;

                            // spi transmission is completed, advances pointer
                            case SPI_MASTER_GET_DATA:
                                if ((triumviAvailIDX!=triumviFullIDX) || (triumviRXBufFull==1)){
                                    triumviRXBufFull = 0;
                                    if (triumviFullIDX == TRIUMVI_PACKET_BUF_LEN-1)
                                        triumviFullIDX = 0;
                                    else
                                        triumviFullIDX += 1;
                                    #ifndef LED_DEBUG
                                    leds_off(LEDS_GREEN);
                                    #endif
                                }
                                resetCnt  = 0;
                                spiInUse = 0;
                            break;

                            case SPI_MASTER_RADIO_ON:
                                NETSTACK_RADIO.on();
                                spiInUse = 0;
                            break;

                            case SPI_MASTER_RADIO_OFF:
                                NETSTACK_RADIO.off();
                                spiInUse = 0;
                            break;

                            default:
                                spiInUse = 0;
                            break;
                        }
                    }
                    spi_data_ptr = 0;
                    #ifndef LED_DEBUG
                    leds_off(LEDS_BLUE);
                    #else
                    leds_on(LEDS_RED);
                    leds_off(LEDS_GREEN);
                    leds_on(LEDS_BLUE);
                    #endif
                }
                process_poll(&mainProcess);
            break;
            
            default:
            break;
        }
    }
    PROCESS_END();
}