int16_t ns_dyn_mem_longest_free_sector(void) { int *ptr; int size, h_size; int scanned = 0; int16_t longest_sector = 0; if (heap_main) { h_size = heap_size / 4; ptr = heap_main; platform_enter_critical(); while (scanned < h_size) { size = *ptr; if (size < 0) { size = -size; if (size > longest_sector) { longest_sector = size; } } if (size == 0) { heap_failure(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED); platform_exit_critical(); return 0; } ptr += size + 2; scanned += (size + 2); } platform_exit_critical(); } return longest_sector; }
void ns_dyn_mem_free(void *block) { #ifndef STANDARD_MALLOC int *ptr = block; int size; if (!block) { return; } if (!heap_main) { heap_failure(NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED); return; } platform_enter_critical(); ptr --; //Read Current Size size = *ptr; if (size < 0) { heap_failure(NS_DYN_MEM_DOUBLE_FREE); } else if (ptr < heap_main || ptr >= heap_main_end) { heap_failure(NS_DYN_MEM_POINTER_NOT_VALID); } else if ((size < 0) || ((ptr + size) >= heap_main_end)) { heap_failure(NS_DYN_MEM_POINTER_NOT_VALID); } else { // Validate Sector if (ns_sector_validate(ptr, 1) != 0) { heap_failure(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED); } else { //Set Pointer to sector end len //Link always prev sector //Sub sequency Free //Check prev sector //Try Link Next between cur ns_free_and_merge_next_sector(ptr, size); //Try Merge Prev with cur ns_merge_prev_sector(ptr); if (mem_stat_info_ptr) { //Update Free Counter size = (size * sizeof(int)); dev_stat_update(DEV_HEAP_FREE, size); } } } platform_exit_critical(); #else platform_enter_critical(); free(block); platform_exit_critical(); #endif }
void fhss_receive_frame_cb(const fhss_api_t *api, uint16_t pan_id, uint8_t *source_address, uint32_t timestamp, uint8_t *synch_info, int frame_type) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); if (!fhss_structure) { return; } if (FHSS_SYNCH_FRAME == frame_type) { if ((fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) || fhss_structure->synch_panid != pan_id) { fhss_add_beacon_info(fhss_structure, pan_id, source_address, timestamp, synch_info); } else { if (!fhss_compare_with_synch_parent_address(fhss_structure, source_address)) { // Synch parent address needs to be updated in case parent has changed fhss_update_synch_parent_address(fhss_structure); platform_enter_critical(); // Calculate time since the Beacon was received uint32_t elapsed_time = api->read_timestamp(api) - timestamp; // Synchronize to given PAN fhss_beacon_received(fhss_structure, synch_info, elapsed_time); platform_exit_critical(); } } } else if (FHSS_SYNCH_REQUEST_FRAME == frame_type) { // If current channel is broadcast, we don't need to send another synch info on next broadcast channel. // Only send number of MAX_SYNCH_INFOS_PER_CHANNEL_LIST synch infos per one channel list cycle if ((fhss_structure->fhss_state == FHSS_SYNCHRONIZED) && (fhss_is_current_channel_broadcast(fhss_structure) == false) && (fhss_structure->synch_infos_sent_counter < MAX_SYNCH_INFOS_PER_CHANNEL_LIST)) { fhss_structure->send_synch_info_on_next_broadcast_channel = true; } } }
void flash_eeprom_erase_uint32(uint32_t offset) { // Check offset if (offset >= FLASH_SIZE_EEPROM) { return; } // Disable interrupts during write platform_enter_critical(); // Unlock PECR // Write the keys to PEKEYR *flash_get_PEKEYR() = PEKEY1; *flash_get_PEKEYR() = PEKEY2; // Erase word *mem_get_reg32(EEPROM_ADDRESS + offset) = 0; // Wait end of operation while (*flash_get_SR() & FLASH_SR__BSY) { } // Lock PECR // Set PELOCK bit in PECR *flash_get_PECR() |= FLASH_PECR__PELOCK; // Enable interrupts after write platform_exit_critical(); }
/* * \brief Function starts the CCA process before starting data transmission and copies the data to RF TX FIFO. * * \param data_ptr Pointer to TX data * \param data_length Length of the TX data * \param tx_handle Handle to transmission * \return 0 Success * \return -1 Busy */ int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol ) { (void)data_protocol; /*Check if transmitter is busy*/ if(rf_if_read_trx_state() == BUSY_RX_AACK) { /*Return busy*/ return -1; } else { platform_enter_critical(); /*Check if transmitted data needs to be acked*/ if(*data_ptr & 0x20) need_ack = 1; else need_ack = 0; /*Store the sequence number for ACK handling*/ tx_sequence = *(data_ptr + 2); /*Write TX FIFO*/ rf_if_write_frame_buffer(data_ptr, (uint8_t)data_length); rf_flags_set(RFF_CCA); /*Start CCA timeout*/ rf_cca_timer_start(RF_CCA_TIMEOUT); /*Store TX handle*/ mac_tx_handle = tx_handle; platform_exit_critical(); } /*Return success*/ return 0; }
/* * \brief Function sets the RF channel. * * \param ch New channel * * \return none */ void rf_channel_set(uint8_t ch) { platform_enter_critical(); rf_phy_channel = ch; if(ch < 0x1f) rf_if_set_channel_register(ch); platform_exit_critical(); }
/* * \brief Function writes various RF settings in startup. * * \param none * * \return none */ void rf_write_settings(void) { platform_enter_critical(); rf_if_write_rf_settings(); /*Set output power*/ rf_if_write_set_tx_power_register(radio_tx_power); /*Initialise Antenna Diversity*/ if(rf_use_antenna_diversity) rf_if_write_antenna_diversity_settings(); platform_exit_critical(); }
/* * \brief Function is a call back for ACK wait timeout. * * \param none * * \return none */ void rf_ack_wait_timer_interrupt(void) { platform_enter_critical(); /*Force PLL state*/ rf_if_change_trx_state(FORCE_PLL_ON); rf_poll_trx_state_change(PLL_ON); /*Start receiver in RX_AACK_ON state*/ rf_rx_mode = 0; rf_flags_clear(RFF_RX); rf_receive(); platform_exit_critical(); }
uint8_t heap_cor_scan(void) { #ifndef STANDARD_MALLOC #ifdef HEAP_CORRUPT_CHECK if (heap_main) { int *ptr; int size, tail_size, h_size; int jump_size; int scanned = 0; h_size = heap_size / 4; ptr = heap_main; platform_enter_critical(); while (scanned < h_size) { size = *ptr++; if (size < 0) { jump_size = -size; } else { jump_size = size; } if (jump_size == 0) { platform_exit_critical(); return 0; } ptr += jump_size; tail_size = *ptr++; if (size != tail_size) { platform_exit_critical(); return 0; } scanned += (jump_size + 2); } platform_exit_critical(); } #endif #endif return 0; }
static void rf_thread_loop() { for (;;) { ThisThread::flags_wait_all(1); platform_enter_critical(); handle_IRQ_events(); platform_exit_critical(); NVIC_ClearPendingIRQ(Radio_1_IRQn); NVIC_EnableIRQ(Radio_1_IRQn); } }
void fhss_synch_state_set_cb(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); if (!fhss_structure) { return; } // State is already set if (fhss_structure->fhss_state == fhss_state) { tr_debug("Synch same state %u", fhss_state); return; } if (fhss_state == FHSS_UNSYNCHRONIZED) { tr_debug("FHSS down"); fhss_down(fhss_structure); } else { // Do not synchronize to current pan if (fhss_structure->synch_panid == pan_id) { tr_debug("Synch same panid %u", pan_id); return; } uint32_t datarate = fhss_structure->callbacks.read_datarate(api); fhss_set_datarate(fhss_structure, datarate); uint8_t mac_address[8]; fhss_structure->callbacks.read_mac_address(fhss_structure->fhss_api, mac_address); fhss_structure->uc_channel_index = fhss_get_offset(fhss_structure, mac_address); // Get Beacon info from storage fhss_beacon_info_t *beacon_info = fhss_get_beacon_info(fhss_structure, pan_id); if (beacon_info) { memcpy(fhss_structure->synch_parent, beacon_info->source_address, 8); platform_enter_critical(); // Calculate time since the Beacon was received uint32_t elapsed_time = api->read_timestamp(api) - beacon_info->timestamp; // Synchronize to given PAN fhss_beacon_received(fhss_structure, beacon_info->synch_info, elapsed_time); platform_exit_critical(); // Delete stored Beacon infos fhss_flush_beacon_info_storage(fhss_structure); fhss_structure->synch_panid = pan_id; } else if (fhss_is_synch_root(fhss_structure) == true) { // Synch root will start new network fhss_start_timer(fhss_structure, fhss_structure->synch_configuration.fhss_superframe_length, fhss_superframe_handler); } else { tr_error("Synch info not find"); } } fhss_structure->fhss_state = fhss_state; }
void flash_memory_copy_upper_to_lower() { // Disable interrupts during write platform_enter_critical(); // Set high power mode pwr_main_mode(PWR_VRANGE_1); // Unlock program memory unlock_program_memory(); // Clear PECR *flash_get_PECR() = 0; // Set the ERASE bit in PECR *flash_get_PECR() |= FLASH_PECR__ERASE; // Set the PROG bit in PECR *flash_get_PECR() |= FLASH_PECR__PROG; // Wait for BSY to be cleared while (*flash_get_SR() & FLASH_SR__BSY) { } #define RAM_CODE_LENGTH ((uint32_t) flash_ram_copy_all_end - (uint32_t) flash_ram_copy_all) uint8_t ram_code[RAM_CODE_LENGTH + 3]; void (*ram_func)() = (void( *)())(((uint32_t) ram_code + 3) & ~0x3); uint32_t func_i, copy_i; func_i = ((uint32_t) ram_func) & ~0x3; copy_i = ((uint32_t) flash_ram_copy_all) & ~0x3; // Copy memcpy((void *) func_i, (void *) copy_i, RAM_CODE_LENGTH); // Set pointer ram_func = (void( *)())(func_i | 0x1); // Call ram_func(); // Enable interrupts after write platform_exit_critical(); }
/* * \brief Function writes 16-bit address in RF address filter. * * \param short_address Given short address * * \return none */ void rf_set_short_adr(uint8_t * short_address) { uint8_t rf_off_flag = 0; platform_enter_critical(); /*Wake up RF if sleeping*/ if(rf_if_read_trx_state() == 0x00 || rf_if_read_trx_state() == 0x1F) { rf_if_disable_slptr(); rf_off_flag = 1; rf_poll_trx_state_change(TRX_OFF); } /*Write address filter registers*/ rf_if_write_short_addr_registers(short_address); /*RF back to sleep*/ if(rf_off_flag) rf_if_enable_slptr(); platform_exit_critical(); }
/* * \brief Function handles the received ACK frame. * * \param seq_number Sequence number of received ACK * \param data_pending Pending bit state in received ACK * * \return none */ void rf_handle_ack(uint8_t seq_number, uint8_t data_pending) { phy_link_tx_status_e phy_status; platform_enter_critical(); /*Received ACK sequence must be equal with transmitted packet sequence*/ if(tx_sequence == seq_number) { rf_ack_wait_timer_stop(); /*When data pending bit in ACK frame is set, inform NET library*/ if(data_pending) phy_status = PHY_LINK_TX_DONE_PENDING; else phy_status = PHY_LINK_TX_DONE; /*Call PHY TX Done API*/ arm_net_phy_tx_done(rf_radio_driver_id, mac_tx_handle,phy_status, 1, 1); } platform_exit_critical(); }
static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel) { platform_enter_critical(); switch (new_state) { /*Reset PHY driver and set to idle*/ case PHY_INTERFACE_RESET: rf_abort(); break; /*Disable PHY Interface driver*/ case PHY_INTERFACE_DOWN: rf_abort(); break; /*Enable PHY Interface driver*/ case PHY_INTERFACE_UP: if (PhyPlmeSetCurrentChannelRequest(rf_channel, 0)) { return 1; } rf_receive(); break; /*Enable wireless interface ED scan mode*/ case PHY_INTERFACE_RX_ENERGY_STATE: if (PhyPlmeSetCurrentChannelRequest(rf_channel, 0)) { return 1; } rf_abort(); rf_mac_ed_state_enable(); break; case PHY_INTERFACE_SNIFFER_STATE: /**< Enable Sniffer state */ rf_promiscuous(1); if (PhyPlmeSetCurrentChannelRequest(rf_channel, 0)) { return 1; } rf_receive(); break; } platform_exit_critical(); return 0; }
flash_status_t flash_memory_erase_page(uint32_t address) { // Check the address is a page border if (address % FLASH_SIZE_PAGE) { return FLASH_ERR_INVALID_ADDRESS; } // Disable interrupts during write platform_enter_critical(); // Unlock program memory unlock_program_memory(); // Set the ERASE bit in PECR *flash_get_PECR() |= FLASH_PECR__ERASE; // Set the PROG bit in PECR *flash_get_PECR() |= FLASH_PECR__PROG; // Wait for BSY to be cleared while (*flash_get_SR() & FLASH_SR__BSY) { } // Write 0x0 to start erasing *mem_get_reg32(address) = 0x0; // Wait for end of operation while (*flash_get_SR() & FLASH_SR__BSY) { } // Lock program memory lock_program_memory(); // Enable interrupts after write platform_exit_critical(); return FLASH_OK; }
/* * \brief Function polls the RF state until it has changed to desired state. * * \param trx_state RF state * * \return none */ void rf_poll_trx_state_change(rf_trx_states_t trx_state) { uint16_t while_counter = 0; platform_enter_critical(); if(trx_state != RF_TX_START) { if(trx_state == FORCE_PLL_ON) trx_state = PLL_ON; else if(trx_state == FORCE_TRX_OFF) trx_state = TRX_OFF; while(rf_if_read_trx_state() != trx_state) { while_counter++; if(while_counter == 0x1ff) break; } } platform_exit_critical(); }
/* * \brief Function calibrates the radio. * * \param none * * \return none */ void rf_calibration_cb(void) { /*clear tuned flag to start tuning in rf_receive*/ rf_tuned = 0; /*If RF is in default receive state, start calibration*/ if(rf_if_read_trx_state() == RX_AACK_ON) { platform_enter_critical(); /*Set RF in PLL_ON state*/ rf_if_change_trx_state(PLL_ON); /*Set RF in TRX_OFF state to start PLL tuning*/ rf_if_change_trx_state(TRX_OFF); /*Set RF in RX_ON state to calibrate*/ rf_if_change_trx_state(RX_ON); /*Calibrate FTN*/ rf_if_calibration(); /*RF is tuned now*/ rf_tuned = 1; /*Back to default receive state*/ rf_flags_clear(RFF_RX); rf_receive(); platform_exit_critical(); } }
flash_status_t flash_memory_write_word(uint32_t address, uint32_t word) { // Disable interrupts during write asm volatile("cpsid i\n"); // Unlock program memory unlock_program_memory(); // Write the word to the address *mem_get_reg32(address) = word; // Wait for end of operation while (*flash_get_SR() & FLASH_SR__BSY) { } // Lock program memory lock_program_memory(); // Enable interrupts after write platform_exit_critical(); return FLASH_OK; }
static void rf_thread_loop(const void *arg) { SL_DEBUG_PRINT("rf_thread_loop: starting (id: %d)\n", (int)rf_thread_id); for (;;) { osEvent event = osSignalWait(0, osWaitForever); if (event.status != osEventSignal) { continue; } platform_enter_critical(); if (event.value.signals & SL_RX_DONE) { while(rx_queue_tail != rx_queue_head) { uint8_t* packet = (uint8_t*) rx_queue[rx_queue_tail]; SL_DEBUG_PRINT("rPKT %d\n", packet[MAC_PACKET_INFO_LENGTH] - 2); device_driver.phy_rx_cb( &packet[MAC_PACKET_INFO_LENGTH + 1], /* Data payload for Nanostack starts at FCS */ packet[MAC_PACKET_INFO_LENGTH] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */ packet[MAC_PACKET_OFFSET_LQI], /* LQI in second byte */ packet[MAC_PACKET_OFFSET_RSSI], /* RSSI in first byte */ rf_radio_driver_id); rx_queue_tail = (rx_queue_tail + 1) % RF_QUEUE_SIZE; } } else if (event.value.signals & SL_TX_DONE) { device_driver.phy_tx_done_cb(rf_radio_driver_id, current_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1); } else if (event.value.signals & SL_ACK_RECV) { device_driver.phy_tx_done_cb( rf_radio_driver_id, current_tx_handle, (event.value.signals & SL_ACK_PEND) ? PHY_LINK_TX_DONE_PENDING : PHY_LINK_TX_DONE, 1, 1); } else if (event.value.signals & SL_ACK_TIMEOUT) { waiting_for_ack = false; device_driver.phy_tx_done_cb(rf_radio_driver_id, current_tx_handle, PHY_LINK_TX_FAIL, 1, 1); } else if(event.value.signals & SL_TX_ERR) { device_driver.phy_tx_done_cb( rf_radio_driver_id, current_tx_handle, PHY_LINK_CCA_FAIL, 8, 1); } else if(event.value.signals & SL_TX_TIMEOUT) { device_driver.phy_tx_done_cb( rf_radio_driver_id, current_tx_handle, PHY_LINK_CCA_FAIL, 8, 1); } else if(event.value.signals & SL_CAL_REQ) { SL_DEBUG_PRINT("rf_thread_loop: SL_CAL_REQ signal received (unhandled)\n"); } else if(event.value.signals & SL_RXFIFO_ERR) { SL_DEBUG_PRINT("rf_thread_loop: SL_RXFIFO_ERR signal received (unhandled)\n"); } else if(event.value.signals & SL_TXFIFO_ERR) { SL_DEBUG_PRINT("rf_thread_loop: SL_TXFIFO_ERR signal received (unhandled)\n"); } else if(event.value.signals & SL_QUEUE_FULL) { SL_DEBUG_PRINT("rf_thread_loop: SL_QUEUE_FULL signal received (packet dropped)\n"); } else { SL_DEBUG_PRINT("rf_thread_loop unhandled event status: %d value: %d\n", event.status, (int)event.value.signals); } platform_exit_critical(); } }
/* * \brief Function sets the RF in RX state. * * \param none * * \return none */ void rf_receive(void) { uint16_t while_counter = 0; if(rf_flags_check(RFF_ON) == 0) { rf_on(); } /*If not yet in RX state set it*/ if(rf_flags_check(RFF_RX) == 0) { platform_enter_critical(); /*Wait while receiving data*/ while(rf_if_read_trx_state() == BUSY_RX_AACK) { while_counter++; if(while_counter == 0xffff) { break; } } //TODO: rf_if_delay_function(50); /*Wake up from sleep state*/ if(rf_if_read_trx_state() == 0x00 || rf_if_read_trx_state() == 0x1f) { rf_if_disable_slptr(); rf_poll_trx_state_change(TRX_OFF); } rf_if_change_trx_state(PLL_ON); if(rf_mode == RF_MODE_SNIFFER) { rf_if_change_trx_state(RX_ON); } else { /*ACK is always received in promiscuous mode to bypass address filters*/ if(rf_rx_mode) { rf_rx_mode = 0; rf_if_enable_promiscuous_mode(); } else { rf_if_disable_promiscuous_mode(); } rf_if_change_trx_state(RX_AACK_ON); } /*If calibration timer was unable to calibrate the RF, run calibration now*/ if(!rf_tuned) { /*Start calibration. This can be done in states TRX_OFF, PLL_ON or in any receive state*/ rf_if_calibration(); /*RF is tuned now*/ rf_tuned = 1; } rf_channel_set(rf_phy_channel); rf_flags_set(RFF_RX); rf_if_enable_rx_end_interrupt(); platform_exit_critical(); } /*Stop the running CCA process*/ if(rf_flags_check(RFF_CCA)) rf_cca_abort(); }
flash_status_t flash_memory_write_half_pages(uint32_t address, const uint32_t *words, uint32_t words_number) { // Check the address is a half page border if (address % (FLASH_SIZE_PAGE / 2)) { return FLASH_ERR_INVALID_ADDRESS; } // Check if length has a correct words number 32 words per half page if (words_number % 32) { return FLASH_ERR_INVALID_LENGTH; } // Disable interrupts during write platform_enter_critical(); // Unlock program memory unlock_program_memory(); // Set the FPRG bit in PECR *flash_get_PECR() |= FLASH_PECR__FPRG; // Set the PROG bit in PECR *flash_get_PECR() |= FLASH_PECR__PROG; // Wait for BSY to be cleared while (*flash_get_SR() & FLASH_SR__BSY) { } #define RAM_COPY_CODE_LENGTH ((uint32_t) flash_ram_copy_end - (uint32_t) flash_ram_copy) uint8_t ram_code[RAM_COPY_CODE_LENGTH + 3]; void (*ram_func)(uint32_t * dst, const uint32_t * src, uint32_t length) = (void( *)(uint32_t * dst, const uint32_t * src, uint32_t length))(((uint32_t) ram_code + 3) & ~0x3); uint32_t func_i, copy_i; func_i = ((uint32_t) ram_func) & ~0x3; copy_i = ((uint32_t) flash_ram_copy) & ~0x3; // Copy memcpy((void *) func_i, (void *) copy_i, RAM_COPY_CODE_LENGTH); // Set pointer ram_func = (void( *)(uint32_t * dst, const uint32_t * src, uint32_t length))(func_i | 0x1); // Call ram_func((uint32_t *) address, words, words_number); // Lock the program memory lock_program_memory(); // Enable interrupts after write platform_exit_critical(); return FLASH_OK; }
void *ns_dyn_mem_temporary_alloc(int16_t alloc_size) { #ifndef STANDARD_MALLOC int *ptr = heap_main; void *retval = 0; int h_size, alloc_sector, s_size; int moved = 0; //int16_t -->int alloc_sector = heap_alloc_internal_check(alloc_size); if (alloc_sector) { h_size = (heap_size / sizeof(int)); platform_enter_critical(); while (moved < h_size) { if (ns_sector_validate(ptr, 1) == 0) { s_size = *ptr; if (s_size == 0) { heap_failure(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED); retval = 0; break; } else if (s_size < 0) { //Free if (((-s_size) >= alloc_sector)) { /*found block*/ //Convert Current size s_size = -s_size; if (s_size > (alloc_sector + 4)) { //debug("Bigger\r\n"); //Set sectror start len & Move pointer to Allocated data sector *ptr++ = alloc_sector; //Set return Pointer retval = (void *) ptr; ptr += alloc_sector; *ptr++ = alloc_sector; //Now set new slice start & End len fields //Move pointer to New Free Sector //Calculate new sector size alloc_sector += 2; // s_size = (s_size - alloc_sector); *ptr++ = -(s_size); ptr += s_size; *ptr = -(s_size); if (mem_stat_info_ptr) { alloc_sector -= 2; } } else { //debug("USE Same\r\n"); //Move pointer to Allocated data sector *ptr++ = s_size; //Set return Pointer retval = (void *) ptr; ptr += s_size;//Move Pointer to next free place *ptr = s_size; } break; } else { //Set Number from negative to Positive s_size = -s_size; } } //Allocated sector //Move //Set Move field moved += (s_size + 2); ptr += 2; //Skip Both of length fileds ptr += s_size; //Move Pointer to next free place if (heap_main_end == ptr) { break; } } else { heap_failure(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED); retval = 0; break; } } if (mem_stat_info_ptr) { alloc_size = (alloc_sector * sizeof(int)); if (retval) { //Update Allocate OK dev_stat_update(DEV_HEAP_ALLOC_OK, alloc_size); } else { //Update Allocate Fail dev_stat_update(DEV_HEAP_ALLOC_FAIL, alloc_size); } } platform_exit_critical(); } return retval; #else void *retval = 0; if (alloc_size) { platform_enter_critical(); retval = malloc(alloc_size); platform_exit_critical(); } return retval; #endif }
static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol) { uint32_t reg, tx_len; uint32_t irqSts; volatile uint8_t *pPB; uint8_t i; uint32_t tx_warmup_time; platform_enter_critical(); if (mPhySeqState == gRX_c) { rf_abort(); } /* Check if transmitter is busy*/ if (mPhySeqState != gIdle_c) { platform_exit_critical(); /*Return busy*/ return -1; } /*Store TX handle*/ rf_mac_handle = tx_handle; /* Check if transmitted data needs to be acked */ need_ack = (*data_ptr & 0x20) == 0x20; /* Load data into Packet Buffer */ pPB = (uint8_t*)ZLL->PKT_BUFFER_TX; tx_len = data_length + 2; *pPB++ = tx_len; /* including 2 bytes of FCS */ for (i = 0; i < data_length; i++) { *pPB++ = *data_ptr++; } reg = ZLL->PHY_CTRL; /* Perform CCA before TX */ reg |= ZLL_PHY_CTRL_CCABFRTX_MASK; /* Set CCA mode 1 */ reg &= ~(ZLL_PHY_CTRL_CCATYPE_MASK); reg |= ZLL_PHY_CTRL_CCATYPE(gCcaCCA_MODE1_c); ZLL->PHY_CTRL = reg; /* Perform TxRxAck sequence if required by phyTxMode */ if (need_ack) { ZLL->PHY_CTRL |= ZLL_PHY_CTRL_RXACKRQD_MASK; mPhySeqState = gTR_c; } else { ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_RXACKRQD_MASK; mPhySeqState = gTX_c; } /* Ensure that no spurious interrupts are raised */ irqSts = ZLL->IRQSTS; irqSts &= ~(ZLL_IRQSTS_TMR1IRQ_MASK | ZLL_IRQSTS_TMR4IRQ_MASK); irqSts |= ZLL_IRQSTS_TMR3MSK_MASK; ZLL->IRQSTS = irqSts; tx_warmup_time = (XCVR_TSM->END_OF_SEQ & XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_MASK) >> XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_SHIFT; /* Compute warmup times (scaled to 16us) */ if (tx_warmup_time & 0x0F) { tx_warmup_time = 1 + (tx_warmup_time >> 4); } else {
/* * \brief Function starts the CCA process before starting data transmission and copies the data to RF TX FIFO. * * \param data_ptr Pointer to TX data * \param data_length Length of the TX data * \param tx_handle Handle to transmission * \return 0 Success * \return -1 Busy */ static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol ) { switch(radio_state) { case RADIO_UNINIT: SL_DEBUG_PRINT("rf_start_cca: Radio uninit\n"); return -1; case RADIO_INITING: SL_DEBUG_PRINT("rf_start_cca: Radio initing\n"); return -1; case RADIO_CALIBRATION: SL_DEBUG_PRINT("rf_start_cca: Radio calibrating\n"); return -1; case RADIO_TX: SL_DEBUG_PRINT("rf_start_cca: Radio in TX mode\n"); return -1; case RADIO_IDLE: case RADIO_RX: // If we're still waiting for an ACK, don't mess up the internal state if(waiting_for_ack || RAIL_GetRadioState(gRailHandle) == RAIL_RF_STATE_TX) { if((RAIL_GetTime() - last_tx) < 30000) { SL_DEBUG_PRINT("rf_start_cca: Still waiting on previous ACK\n"); return -1; } else { SL_DEBUG_PRINT("rf_start_cca: TXerr\n"); } } platform_enter_critical(); /* Since we set up Nanostack to give us a 1-byte PHY header, we get the one extra byte at the start of data_ptr * and need to populate it with the MAC-frame length byte (including the 2-byte hardware-inserted CRC) */ data_ptr[0] = data_length + 2; RAIL_Idle(gRailHandle, RAIL_IDLE_ABORT, true); RAIL_WriteTxFifo(gRailHandle, data_ptr, data_length + 1, true); radio_state = RADIO_TX; RAIL_TxOptions_t txOpt = RAIL_TX_OPTIONS_DEFAULT; //Check to see whether we'll be waiting for an ACK if(data_ptr[1] & (1 << 5)) { txOpt |= RAIL_TX_OPTION_WAIT_FOR_ACK; waiting_for_ack = true; } else { waiting_for_ack = false; } SL_DEBUG_PRINT("rf_start_cca: Called TX, len %d, chan %d, ack %d\n", data_length, channel, waiting_for_ack ? 1 : 0); if(RAIL_StartCcaCsmaTx(gRailHandle, channel, txOpt, &csma_config, NULL) == 0) { //Save packet number and sequence current_tx_handle = tx_handle; current_tx_sequence = data_ptr[3]; platform_exit_critical(); return 0; } else { RAIL_Idle(gRailHandle, RAIL_IDLE_ABORT, true); RAIL_StartRx(gRailHandle, channel, NULL); radio_state = RADIO_RX; platform_exit_critical(); return -1; } } //Should never get here... return -1; }
static void rf_if_unlock(void) { platform_exit_critical(); }
/* * \brief Function starts the CCA process before starting data transmission and copies the data to RF TX FIFO. * * \param data_ptr Pointer to TX data * \param data_length Length of the TX data * \param tx_handle Handle to transmission * \return 0 Success * \return -1 Busy */ static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol ) { RAIL_TxData_t txData = { data_ptr, data_length + 3 }; switch(radio_state) { case RADIO_UNINIT: SL_DEBUG_PRINT("rf_start_cca: Radio uninit\n"); return -1; case RADIO_INITING: SL_DEBUG_PRINT("rf_start_cca: Radio initing\n"); return -1; case RADIO_CALIBRATION: SL_DEBUG_PRINT("rf_start_cca: Radio calibrating\n"); return -1; case RADIO_TX: SL_DEBUG_PRINT("rf_start_cca: Radio in TX mode\n"); return -1; case RADIO_IDLE: case RADIO_RX: // If we're still waiting for an ACK, don't mess up the internal state if(waiting_for_ack || RAIL_RfStateGet() == RAIL_RF_STATE_TX) { if((RAIL_GetTime() - last_tx) < 30000) { SL_DEBUG_PRINT("rf_start_cca: Still waiting on previous ACK\n"); return -1; } else { SL_DEBUG_PRINT("rf_start_cca: TXerr\n"); } } platform_enter_critical(); data_ptr[0] = data_length + 2; RAIL_RfIdleExt(RAIL_IDLE_ABORT , true); RAIL_TxDataLoad(&txData); radio_state = RADIO_TX; RAIL_TxOptions_t txOpt; //Check to see whether we'll be waiting for an ACK if(data_ptr[1] & (1 << 5)) { txOpt.waitForAck = true; waiting_for_ack = true; } else { txOpt.waitForAck = false; } SL_DEBUG_PRINT("rf_start_cca: Called TX, len %d, chan %d, ack %d\n", data_length, channel, waiting_for_ack ? 1 : 0); if(RAIL_TxStartWithOptions(channel, &txOpt, &RAIL_CcaCsma, (RAIL_CsmaConfig_t*) &csma_config) == 0) { //Save packet number and sequence current_tx_handle = tx_handle; current_tx_sequence = data_ptr[3]; platform_exit_critical(); return 0; } else { RAIL_RfIdle(); RAIL_RxStart(channel); radio_state = RADIO_RX; platform_exit_critical(); return -1; } } //Should never get here... platform_exit_critical(); return -1; }
static void rf_thread_loop(const void *arg) { SL_DEBUG_PRINT("rf_thread_loop: starting (id: %d)\n", rf_thread_id); for (;;) { osEvent event = osSignalWait(0, osWaitForever); if (event.status != osEventSignal) { continue; } platform_enter_critical(); if (event.value.signals & SL_RX_DONE) { while(rx_queue_tail != rx_queue_head) { void* handle = (void*) rx_queue[rx_queue_tail]; RAIL_RxPacketInfo_t* info = (RAIL_RxPacketInfo_t*) memoryPtrFromHandle(handle); device_driver.phy_rx_cb( info->dataPtr + 1, info->dataLength - 1, info->appendedInfo.lqi, info->appendedInfo.rssiLatch, rf_radio_driver_id); memoryFree(handle); rx_queue[rx_queue_tail] = NULL; rx_queue_tail = (rx_queue_tail + 1) % RF_QUEUE_SIZE; } } else if (event.value.signals & SL_TX_DONE) { device_driver.phy_tx_done_cb(rf_radio_driver_id, current_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1); } else if (event.value.signals & SL_ACK_RECV) { device_driver.phy_tx_done_cb( rf_radio_driver_id, current_tx_handle, (event.value.signals & SL_ACK_PEND) ? PHY_LINK_TX_DONE_PENDING : PHY_LINK_TX_DONE, 1, 1); } else if (event.value.signals & SL_ACK_TIMEOUT) { waiting_for_ack = false; device_driver.phy_tx_done_cb(rf_radio_driver_id, current_tx_handle, PHY_LINK_TX_FAIL, 1, 1); } else if(event.value.signals & SL_TX_ERR) { device_driver.phy_tx_done_cb( rf_radio_driver_id, current_tx_handle, PHY_LINK_CCA_FAIL, 8, 1); } else if(event.value.signals & SL_CAL_REQ) { SL_DEBUG_PRINT("rf_thread_loop: SL_CAL_REQ signal received (unhandled)\n"); } else if(event.value.signals & SL_RXFIFO_ERR) { SL_DEBUG_PRINT("rf_thread_loop: SL_RXFIFO_ERR signal received (unhandled)\n"); } else if(event.value.signals & SL_TXFIFO_ERR) { SL_DEBUG_PRINT("rf_thread_loop: SL_TXFIFO_ERR signal received (unhandled)\n"); } else if(event.value.signals & SL_QUEUE_FULL) { SL_DEBUG_PRINT("rf_thread_loop: SL_QUEUE_FULL signal received (packet dropped)\n"); } else { SL_DEBUG_PRINT("rf_thread_loop unhandled event status: %d value: %d\n", event.status, event.value.signals); } platform_exit_critical(); } }