/*---------------------------------------------------------------------------*/ static int init(void) { PRINTF("RF: Init\n"); if(rf_flags & RF_ON) { return 0; } /* Enable clock for the RF Core while Running, in Sleep and Deep Sleep */ REG(SYS_CTRL_RCGCRFC) = 1; REG(SYS_CTRL_SCGCRFC) = 1; REG(SYS_CTRL_DCGCRFC) = 1; REG(RFCORE_XREG_CCACTRL0) = CC2538_RF_CCA_THRES_USER_GUIDE; /* * Changes from default values * See User Guide, section "Register Settings Update" */ REG(RFCORE_XREG_TXFILTCFG) = 0x09; /** TX anti-aliasing filter bandwidth */ REG(RFCORE_XREG_AGCCTRL1) = 0x15; /** AGC target value */ REG(ANA_REGS_IVCTRL) = 0x0B; /** Bias currents */ /* * Defaults: * Auto CRC; Append RSSI, CRC-OK and Corr. Val.; CRC calculation; * RX and TX modes with FIFOs */ REG(RFCORE_XREG_FRMCTRL0) = RFCORE_XREG_FRMCTRL0_AUTOCRC; #if CC2538_RF_AUTOACK REG(RFCORE_XREG_FRMCTRL0) |= RFCORE_XREG_FRMCTRL0_AUTOACK; #endif /* If we are a sniffer, turn off frame filtering */ #if CC2538_RF_CONF_SNIFFER REG(RFCORE_XREG_FRMFILT0) &= ~RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN; #endif /* Disable source address matching and autopend */ REG(RFCORE_XREG_SRCMATCH) = 0; /* MAX FIFOP threshold */ REG(RFCORE_XREG_FIFOPCTRL) = CC2538_RF_MAX_PACKET_LEN; /* Set TX Power */ REG(RFCORE_XREG_TXPOWER) = CC2538_RF_TX_POWER; set_channel(rf_channel); /* Acknowledge RF interrupts, FIFOP only */ REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; nvic_interrupt_enable(NVIC_INT_RF_RXTX); /* Acknowledge all RF Error interrupts */ REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM; nvic_interrupt_enable(NVIC_INT_RF_ERR); if(CC2538_RF_CONF_TX_USE_DMA) { /* Disable peripheral triggers for the channel */ udma_channel_mask_set(CC2538_RF_CONF_TX_DMA_CHAN); /* * Set the channel's DST. SRC can not be set yet since it will change for * each transfer */ udma_set_channel_dst(CC2538_RF_CONF_TX_DMA_CHAN, RFCORE_SFR_RFDATA); } if(CC2538_RF_CONF_RX_USE_DMA) { /* Disable peripheral triggers for the channel */ udma_channel_mask_set(CC2538_RF_CONF_RX_DMA_CHAN); /* * Set the channel's SRC. DST can not be set yet since it will change for * each transfer */ udma_set_channel_src(CC2538_RF_CONF_RX_DMA_CHAN, RFCORE_SFR_RFDATA); } process_start(&cc2538_rf_process, NULL); rf_flags |= RF_ON; ENERGEST_ON(ENERGEST_TYPE_LISTEN); return 1; }
/*---------------------------------------------------------------------------*/ 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); }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(mainProcess, ev, data) { PROCESS_BEGIN(); GPIO_SET_OUTPUT(GPIO_A_BASE, 0xf8); GPIO_SET_OUTPUT(GPIO_B_BASE, 0x0f); GPIO_SET_OUTPUT(GPIO_C_BASE, 0x02); GPIO_CLR_PIN(GPIO_A_BASE, 0xf8); GPIO_CLR_PIN(GPIO_B_BASE, 0x07); GPIO_SET_PIN(EDISON_WAKEUP_BASE, EDISON_WAKEUP_PIN_MASK); // edison WAKEUP GPIO_SET_INPUT(RESET_PORT_BASE, RESET_PIN_MASK); // reset ioc_set_over(RESET_PORT, RESET_PIN, IOC_OVERRIDE_PUE); leds_off(LEDS_RED); leds_off(LEDS_GREEN); leds_off(LEDS_BLUE); // RESET interrupt, active low GPIO_DETECT_EDGE(RESET_PORT_BASE, RESET_PIN_MASK); GPIO_DETECT_FALLING(RESET_PORT_BASE, RESET_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(RESET_PORT_BASE, RESET_PIN_MASK); gpio_register_callback(resetcallBack, RESET_PORT, RESET_PIN); GPIO_ENABLE_INTERRUPT(RESET_PORT_BASE, RESET_PIN_MASK); nvic_interrupt_enable(RESET_NVIC_PORT); GPIO_CLR_PIN(TRIUMVI_DATA_READY_PORT_BASE, TRIUMVI_DATA_READY_MASK); // SPI CS interrupt GPIO_DETECT_EDGE(SPI0_CS_PORT_BASE, SPI0_CS_PIN_MASK); GPIO_DETECT_RISING(SPI0_CS_PORT_BASE, SPI0_CS_PIN_MASK); GPIO_TRIGGER_SINGLE_EDGE(SPI0_CS_PORT_BASE, SPI0_CS_PIN_MASK); gpio_register_callback(spiCScallBack, SPI0_CS_PORT, SPI0_CS_PIN); GPIO_ENABLE_INTERRUPT(SPI0_CS_PORT_BASE, SPI0_CS_PIN_MASK); // SPI interface spix_slave_init(SPIDEV); spix_txdma_enable(SPIDEV); spi_register_callback(spiFIFOcallBack); spix_interrupt_enable(SPIDEV, SSI_IM_RXIM_M); // RX FIFO half full nvic_interrupt_enable(NVIC_INT_SSI0); // uDMA SPI0 TX udma_channel_disable(CC2538_SPI0_TX_DMA_CHAN); udma_channel_prio_set_default(CC2538_SPI0_TX_DMA_CHAN); udma_channel_use_primary(CC2538_SPI0_TX_DMA_CHAN); udma_channel_use_single(CC2538_SPI0_TX_DMA_CHAN); udma_channel_mask_clr(CC2538_SPI0_TX_DMA_CHAN); udma_set_channel_dst(CC2538_SPI0_TX_DMA_CHAN, SPI0DR); udma_set_channel_assignment(CC2538_SPI0_TX_DMA_CHAN, UDMA_CH11_SSI0TX); simple_network_set_callback(&rf_rx_handler); //NETSTACK_RADIO.off(); process_start(&decryptProcess, NULL); process_start(&spiProcess, NULL); while (1){ PROCESS_YIELD(); // buffer is not empty, spi is not in use //if ((spiInUse==0) && (spix_busy(SPIDEV)==0) && ((triumviAvailIDX!=triumviFullIDX) || (triumviRXBufFull==1))){ if ((spiInUse==0) && ((triumviAvailIDX!=triumviFullIDX) || (triumviRXBufFull==1))){ GPIO_SET_PIN(TRIUMVI_DATA_READY_PORT_BASE, TRIUMVI_DATA_READY_MASK); if (triumviRXBufFull==1){ resetCnt += 1; if (resetCnt==RESET_THRESHOLD){ watchdog_reboot(); } } #ifdef LED_DEBUG leds_off(LEDS_RED); leds_off(LEDS_GREEN); leds_off(LEDS_BLUE); #endif } // Fail safe, CC2538 missing some SPI commands, reset spi state else if (triumviRXBufFull==1){ spiState = SPI_RESET; process_poll(&spiProcess); #ifdef LED_DEBUG leds_off(LEDS_RED); leds_off(LEDS_GREEN); leds_on(LEDS_BLUE); #endif } } PROCESS_END(); }