/** * @brief todo * */ retval_t tal_rampup(void) { pal_trx_init(); if (trx_init() != MAC_SUCCESS) { return FAILURE; } /* * Do the reset stuff. * Set the default PIBs. * Generate random seed. */ if (internal_tal_reset(true) != MAC_SUCCESS) { return FAILURE; } /* * Activate interrupt handling. */ pal_trx_irq_en(); /* Enable transceiver main interrupt. */ #if ((defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)) && (DISABLE_TSTAMP_IRQ == 0) /* Configure time stamp interrupt. */ pal_trx_irq_en_tstamp(); /* Enable timestamp interrupt. */ #endif return MAC_SUCCESS; } /* tal_rampup() */
trx_retval_t tal_init(void) { if (trx_init() != TRX_SUCCESS) { return TRX_FAILURE; } /* * Do the reset stuff. * Generate random seed. */ if (internal_tal_reset() != TRX_SUCCESS) { return TRX_FAILURE; } /* Set the default CCA mode. */ pal_trx_bit_write(SR_CCA_MODE, CCA_MODE_DEFAULT); /* Default configuration to perform auto CSMA-CA */ pal_trx_reg_write(RG_CSMA_BE, ((MAXBE_DEFAULT << 4) | MINBE_DEFAULT)); pal_trx_bit_write(SR_MAX_CSMA_RETRIES, MAX_CSMA_BACKOFFS_DEFAULT); /* Set the trx in promiscuous mode to receive all frame with CRC OK */ pal_trx_bit_write(SR_AACK_PROM_MODE, PROM_MODE_ENABLE); /* Configuration to perform auto CRC for transmission */ pal_trx_bit_write(SR_TX_AUTO_CRC_ON, TX_AUTO_CRC_ENABLE); return TRX_SUCCESS; }
/** * @brief Initializes the TAL * * This function is called to initialize the TAL. The transceiver is * initialized, the TAL PIBs are set to their default values, and the TAL state * machine is set to TAL_IDLE state. * * @return MAC_SUCCESS if the transceiver state is changed to TRX_OFF and the * current device part number and version number are correct; * FAILURE otherwise */ retval_t tal_init(void) { /* Init the PAL and by this means also the transceiver interface */ if (pal_init() != MAC_SUCCESS) { return FAILURE; } if (trx_init() != MAC_SUCCESS) { return FAILURE; } #if (EXTERN_EEPROM_AVAILABLE == 1) pal_ps_get(EXTERN_EEPROM, EE_IEEE_ADDR, 8, &tal_pib.IeeeAddress); #else pal_ps_get(INTERN_EEPROM, EE_IEEE_ADDR, 8, &tal_pib.IeeeAddress); #endif /* * Do the reset stuff. * Set the default PIBs. * Generate random seed. */ if (internal_tal_reset(true) != MAC_SUCCESS) { return FAILURE; } #ifndef DISABLE_IEEE_ADDR_CHECK /* Check if a valid IEEE address is available. */ /* * This while loop is on purpose, since just in the * rare case that such an address is randomly * generated again, we must repeat this. */ while ((tal_pib.IeeeAddress == 0x0000000000000000) || (tal_pib.IeeeAddress == 0xFFFFFFFFFFFFFFFF) ) { /* * In case no valid IEEE address is available, a random * IEEE address will be generated to be able to run the * applications for demonstration purposes. * In production code this can be omitted. */ /* * The proper seed for function rand() has already been generated * in function tal_generate_rand_seed(). */ uint8_t *ptr_pib = (uint8_t *)&tal_pib.IeeeAddress; for (uint8_t i = 0; i < 8; i++) { *ptr_pib++ = (uint8_t)rand(); /* * Note: * Even if casting the 16 bit rand value back to 8 bit, * and running the loop 8 timers (instead of only 4 times) * may look cumbersome, it turns out that the code gets * smaller using 8-bit here. * And timing is not an issue at this place... */ } } #endif /* #ifndef DISABLE_IEEE_ADDR_CHECK */ /* * Configure interrupt handling. * Install handlers for the transceiver interrupts. */ pal_trx_irq_init_rx_end((FUNC_PTR)trx_rx_end_handler_cb); pal_trx_irq_init_tx_end((FUNC_PTR)trx_tx_end_handler_cb); pal_trx_irq_init_awake((FUNC_PTR)trx_awake_handler_cb); #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) /* Configure time stamp interrupt. */ pal_trx_irq_init_tstamp((FUNC_PTR)trx_irq_timestamp_handler_cb); #endif /* (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ /* Initialize the buffer management module and get a buffer to store reveived frames. */ bmm_buffer_init(); tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE); /* Init incoming frame queue */ #ifdef ENABLE_QUEUE_CAPACITY qmm_queue_init(&tal_incoming_frame_queue, TAL_INCOMING_FRAME_QUEUE_CAPACITY); #else qmm_queue_init(&tal_incoming_frame_queue); #endif /* ENABLE_QUEUE_CAPACITY */ #ifdef ENABLE_TFA tfa_init(); #endif return MAC_SUCCESS; } /* tal_init() */
/** * @brief Initializes the TAL * * This function is called to initialize the TAL. The transceiver is * initialized, the TAL PIBs are set to their default values, and the TAL state * machine is set to TAL_IDLE state. * * @return MAC_SUCCESS if the transceiver state is changed to TRX_OFF and the * current device part number and version number are correct; * FAILURE otherwise */ retval_t tal_init(void) { /* Init the PAL and by this means also the transceiver interface */ #ifdef ENABLE_RP /* * The ranging processor (RP) only performs a minimalistic * initialization here. */ pal_basic_init(); #else /* !ENABLE_RP */ if (pal_init() != MAC_SUCCESS) { return FAILURE; } if (trx_init() != MAC_SUCCESS) { return FAILURE; } #if (EXTERN_EEPROM_AVAILABLE == 1) pal_ps_get(EXTERN_EEPROM, EE_IEEE_ADDR, 8, &tal_pib.IeeeAddress); #else #if (USER_SIGN_AVAILABLE == 1) pal_ps_get(USER_SIGNATURE, USER_SIGNATURES_START + 2, 8, &tal_pib.IeeeAddress); //http://www.atmel.com/Images/Atmel-42172-Wireless-ZigBit-ATZB-X0-256-3-0-C_Datasheet.pdf #else pal_ps_get(INTERN_EEPROM, EE_IEEE_ADDR, 8, &tal_pib.IeeeAddress); #endif #endif /* * Do the reset stuff. * Set the default PIBs. * Generate random seed. */ if (internal_tal_reset(true) != MAC_SUCCESS) { return FAILURE; } #ifndef DISABLE_IEEE_ADDR_CHECK /* Check if a valid IEEE address is available. */ /* * This while loop is on purpose, since just in the * rare case that such an address is randomly * generated again, we must repeat this. */ while ((tal_pib.IeeeAddress == 0x0000000000000000) || (tal_pib.IeeeAddress == 0xFFFFFFFFFFFFFFFF)) { /* * In case no valid IEEE address is available, a random * IEEE address will be generated to be able to run the * applications for demonstration purposes. * In production code this can be omitted. */ /* * The proper seed for function rand() has already been generated * in function tal_generate_rand_seed(). */ uint8_t *ptr_pib = (uint8_t *)&tal_pib.IeeeAddress; for (uint8_t i = 0; i < 8; i++) { *ptr_pib++ = (uint8_t)rand(); /* * Note: * Even if casting the 16 bit rand value back to 8 bit, * and running the loop 8 timers (instead of only 4 times) * may look cumbersome, it turns out that the code gets * smaller using 8-bit here. * And timing is not an issue at this place... */ } } #endif /* #ifndef DISABLE_IEEE_ADDR_CHECK */ #endif /* ENABLE_RP */ /* * Configure interrupt handling. * Install a handler for the transceiver interrupt. */ pal_trx_irq_init(trx_irq_handler_cb); #ifndef ENABLE_RP pal_trx_irq_en(); /* Enable transceiver main interrupt. */ #endif #if ((defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)) && (DISABLE_TSTAMP_IRQ == 0) /* Configure time stamp interrupt. */ pal_trx_irq_init_tstamp(trx_irq_timestamp_handler_cb); #ifndef ENABLE_RP pal_trx_irq_en_tstamp(); /* Enable timestamp interrupt. */ #endif #endif /* Initialize the buffer management module and get a buffer to store received frames. */ bmm_buffer_init(); tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE); #if DEBUG > 0 if (tal_rx_buffer == NULL) { return FAILURE; } #endif /* Init incoming frame queue */ #ifdef ENABLE_QUEUE_CAPACITY qmm_queue_init(&tal_incoming_frame_queue, TAL_INCOMING_FRAME_QUEUE_CAPACITY); #else qmm_queue_init(&tal_incoming_frame_queue); #endif /* ENABLE_QUEUE_CAPACITY */ #ifdef ENABLE_TFA tfa_init(); #endif return MAC_SUCCESS; } /* tal_init() */
int main(int argc, char **argv) { char dev_if[16]; int opt; int err = 0; int daemonize = 0; int log_level = LOG_WARN; char *log_file = NULL; memset(dev_if, '\0', sizeof(dev_if)); strncpy(dev_if, PHOST_DEFAULT_TAP_DEVICE, sizeof(dev_if) - 1); phost_set_program_name(basename(argv[0])); /* parse options */ while(1){ opt = getopt(argc, argv, "Dd:i:p:l:n:v"); if(opt < 0){ break; } switch(opt){ case 'D': daemonize = 1; break; case 'd': if(optarg){ if(atoi(optarg) < LOG_LEVEL_MAX){ log_level = atoi(optarg); } else{ phost_print_usage(); exit(1); } } else{ err |= 1; } break; case 'i': if(optarg){ memset(dev_if, '\0', sizeof(dev_if)); strncpy(dev_if, optarg, sizeof(dev_if) - 1); } else{ err |= 1; } break; case 'p': if(optarg){ memset(pid_dir, '\0', sizeof(pid_dir)); strncpy(pid_dir, optarg, sizeof(pid_dir) - 1); } else{ err |= 1; } break; case 'l': if(optarg){ memset(log_dir, '\0', sizeof(log_dir)); strncpy(log_dir, optarg, sizeof(log_dir) - 1); } else{ err |= 1; } break; case 'n': if(optarg){ memset(host_name, '\0', sizeof(host_name)); strncpy(host_name, optarg, sizeof(host_name) - 1); } else{ err |= 1; } break; case 'v': log_file = LOG_OUT_STDOUT; log_level = LOG_DEBUG; break; default: err |= 1; } } if(err){ phost_print_usage(); exit(1); } if(log_file == NULL){ log_file = (char*)malloc(sizeof(char)*(strlen(log_dir)+strlen(PHOST_LOG_FILE)+strlen(dev_if)+3)); sprintf(log_file, "%s/%s.%s", log_dir, PHOST_LOG_FILE, dev_if); } /* check if this process is run with root privilege */ if(getuid() != 0){ fprintf(stderr, "[ERROR] `%s' must be run with root privilege.\n", program_name); exit(1); } /* register signal handler */ signal(SIGINT, phost_handle_signals); signal(SIGTERM, phost_handle_signals); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); /* initializations */ if(log_init(log_level, log_file) < 0){ fprintf(stderr, "[ERROR] cannot initialize logger.\n"); exit(1); } if(daemonize && (phost_daemonize() < 0)){ fprintf(stderr, "[ERROR] cannot daemonize.\n"); exit(1); } if(strncmp(dev_if, "tap", 3) != 0){ if(ethdev_init(dev_if) < 0){ fprintf(stderr, "[ERROR] cannot initialize Ethernet device (%s).\n", dev_if); exit(1); } trx_init(ethdev_read, ethdev_send); } else{ if(tap_init(dev_if) < 0){ fprintf(stderr, "[ERROR] cannot create tap device (%s).\n", dev_if); exit(1); } trx_init(tap_read, tap_send); } phost_set_global_params(); phost_create_pid_file(host_name); cmdif_init(dev_if, stats_udp_send_update); arp_init(host_mac_addr, host_ip_addr); ipv4_init(host_ip_addr, host_ip_mask); udp_init(stats_udp_recv_update); pkt_dump = (char*)malloc(sizeof(char)*PKT_BUF_SIZE*2); while(run){ phost_run(); cmdif_run(); arp_age_entries(); } free(pkt_dump); cmdif_close(); tap_close(); phost_delete_pid_file(host_name); phost_unset_global_params(); log_close(); return 0; }
/* * \brief Initializes the TAL * * This function is called to initialize the TAL. The transceiver is * initialized, the TAL PIBs are set to their default values, and the TAL state * machine is set to TAL_IDLE state. * * \return MAC_SUCCESS if the transceiver state is changed to TRX_OFF and the * current device part number and version number are correct; * FAILURE otherwise */ retval_t tal_init(void) { /* Init the PAL and by this means also the transceiver interface */ if (pal_init() != MAC_SUCCESS) { return FAILURE; } if (trx_init() != MAC_SUCCESS) { return FAILURE; } if (tal_timer_init() != MAC_SUCCESS) { return FAILURE; } #ifdef ENABLE_STACK_NVM pal_ps_get(INTERN_EEPROM, EE_IEEE_ADDR, 8, &tal_pib.IeeeAddress); #endif /* * For systems including the AT86RF230B the random seed generation * cannot be done using a dedicated hardware feature. * Therefore all random seed generation needs to be done by special * means (e.g. utilization of ADC) that generate a random value only * within a certain range. * * In case the node already has a valid IEEE address (i.e. an IEEE * address which is different from 0x0000000000000000 or * 0xFFFFFFFFFFFFFFFF), this IEEE address (the lower 16 bit) * shall be used as seed for srand(), since each node should have a *unique * IEEE address. * In this case srand() is called directly and function *tal_generate_rand_seed() * is not called. * * Note: This behaviour is different in all other TALs, since in these * cases the seed for srand() is always generated based on transceiver * hardware support. */ #ifndef DISABLE_IEEE_ADDR_CHECK if ((tal_pib.IeeeAddress == 0x0000000000000000) || (tal_pib.IeeeAddress == 0xFFFFFFFFFFFFFFFF) ) { /* * Generate a seed for the random number generator in function *rand(). * This is required (for example) as seed for the CSMA-CA *algorithm. */ tal_generate_rand_seed(); /* * Now that we have generated a random seed, we can generate a *random * IEEE address for this node. */ do { /* * In case no valid IEEE address is available, a random * IEEE address will be generated to be able to run the * applications for demonstration purposes. * In production code this can be omitted. */ /* * The proper seed for function rand() has already been *generated * in function tal_generate_rand_seed(). */ uint8_t *ptr_pib = (uint8_t *)&tal_pib.IeeeAddress; for (uint8_t i = 0; i < 8; i++) { *ptr_pib++ = (uint8_t)rand(); /* * Note: * Even if casting the 16 bit rand value back to *8 bit, * and running the loop 8 timers (instead of *only 4 times) * may look cumbersome, it turns out that the *code gets * smaller using 8-bit here. * And timing is not an issue at this place... */ } } /* Check if a valid IEEE address is available. */ while ((tal_pib.IeeeAddress == 0x0000000000000000) || (tal_pib.IeeeAddress == 0xFFFFFFFFFFFFFFFF) ); } else { /* Valid IEEE address, so no need to generate a new random seed. **/ uint16_t cur_rand_seed = (uint16_t)tal_pib.IeeeAddress; srand(cur_rand_seed); } #else /* * No check for a valid IEEE address done, so directly create a seed * for srand(). */ tal_generate_rand_seed(); #endif /* * Do the reset stuff. * Set the default PIBs. */ if (internal_tal_reset(true) != MAC_SUCCESS) { return FAILURE; } pal_trx_reg_read(RG_IRQ_STATUS); /* clear pending irqs, dummy read */ /* * Configure interrupt handling. * Install a handler for the transceiver interrupt. */ pal_trx_irq_init((FUNC_PTR)trx_irq_handler_cb); pal_trx_irq_en(); /* Enable transceiver main interrupt. */ /* Initialize the buffer management module and get a buffer to store *reveived frames. */ bmm_buffer_init(); tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE); /* Init incoming frame queue */ #ifdef ENABLE_QUEUE_CAPACITY qmm_queue_init(&tal_incoming_frame_queue, TAL_INCOMING_FRAME_QUEUE_CAPACITY); #else qmm_queue_init(&tal_incoming_frame_queue); #endif /* ENABLE_QUEUE_CAPACITY */ return MAC_SUCCESS; } /* tal_init() */
/** * @brief Resets TAL state machine and sets the default PIB values if requested * * @param trx_id Transceiver identifier * @param set_default_pib Defines whether PIB values need to be set * to its default values * * @return * - @ref MAC_SUCCESS if the transceiver state is changed to TRX_OFF * - @ref FAILURE otherwise * @ingroup apiTalApi */ retval_t tal_reset(trx_id_t trx_id, bool set_default_pib) { rf_cmd_state_t previous_trx_state[NUM_TRX]; previous_trx_state[RF09] = trx_state[RF09]; previous_trx_state[RF24] = trx_state[RF24]; /* Reset the actual device or part of the device */ if (trx_reset(trx_id) != MAC_SUCCESS) { return FAILURE; } /* Init Trx if necessary, e.g. trx was in deep sleep */ if (((previous_trx_state[RF09] == RF_SLEEP) && (previous_trx_state[RF24] == RF_SLEEP)) || (trx_id == RFBOTH)) { trx_init(); /* Initialize generic trx functionality */ } if (trx_id == RFBOTH) { for (uint8_t i = 0; i < NUM_TRX; i++) { /* Clean TAL and removed any pending tasks */ cleanup_tal((trx_id_t)i); /* Configure the transceiver register values. */ trx_config((trx_id_t)i); if (set_default_pib) { /* Set the default PIB values */ init_tal_pib((trx_id_t)i); /* see 'tal_pib.c' */ calculate_pib_values(trx_id); } else { /* nothing to do - the current TAL PIB attribute *values are used */ } write_all_tal_pib_to_trx((trx_id_t)i); /* see *'tal_pib.c' */ config_phy((trx_id_t)i); /* Reset TAL variables. */ tal_state[(trx_id_t)i] = TAL_IDLE; tx_state[(trx_id_t)i] = TX_IDLE; #ifdef ENABLE_FTN_PLL_CALIBRATION /* Stop FTN timer */ stop_ftn_timer((trx_id_t)i); #endif /* ENABLE_FTN_PLL_CALIBRATION */ } } else { /* Maintain other trx */ trx_id_t other_trx_id; if (trx_id == RF09) { other_trx_id = RF24; } else { other_trx_id = RF09; } if (tal_state[other_trx_id] == TAL_SLEEP) { /* Switch other trx back to sleep again */ uint16_t reg_offset = RF_BASE_ADDR_OFFSET * other_trx_id; #ifdef IQ_RADIO pal_dev_reg_write(RF215_BB, reg_offset + RG_RF09_CMD, RF_SLEEP); pal_dev_reg_write(RF215_RF, reg_offset + RG_RF09_CMD, RF_SLEEP); #else trx_reg_write(reg_offset + RG_RF09_CMD, RF_SLEEP); #endif TAL_RF_IRQ_CLR_ALL(trx_id); } /* Clean TAL and removed any pending tasks */ cleanup_tal(trx_id); /* Configure the transceiver register values. */ trx_config(trx_id); if (set_default_pib) { /* Set the default PIB values */ init_tal_pib(trx_id); /* see 'tal_pib.c' */ calculate_pib_values(trx_id); } else { /* nothing to do - the current TAL PIB attribute values *are used */ } write_all_tal_pib_to_trx(trx_id); /* see 'tal_pib.c' */ config_phy(trx_id); /* Reset TAL variables. */ tal_state[trx_id] = TAL_IDLE; tx_state[trx_id] = TX_IDLE; #ifdef ENABLE_FTN_PLL_CALIBRATION /* Stop FTN timer */ stop_ftn_timer(trx_id); #endif /* ENABLE_FTN_PLL_CALIBRATION */ } /* * Configure interrupt handling. * Install a handler for the transceiver interrupt. */ #ifdef IQ_RADIO trx_irq_init(RF215_BB, bb_irq_handler_cb); trx_irq_init(RF215_RF, rf_irq_handler_cb); pal_trx_irq_en(RF215_BB); /* Enable transceiver main interrupt. */ pal_trx_irq_en(RF215_RF); /* Enable transceiver main interrupt. */ #else trx_irq_init((FUNC_PTR)trx_irq_handler_cb); pal_trx_irq_en(); /* Enable transceiver main interrupt. */ #endif return MAC_SUCCESS; }
/** * @brief Initializes the TAL * * This function is called to initialize the TAL. The transceiver is * initialized, the TAL PIBs are set to their default values, and the TAL state * machine is set to TAL_IDLE state. * * @return MAC_SUCCESS if the transceiver state is changed to TRX_OFF and the * current device part number and version number are correct; * FAILURE otherwise */ retval_t tal_init(void) { /* Init the PAL and by this means also the transceiver interface */ if (pal_init() != MAC_SUCCESS) { return FAILURE; } /* Reset trx */ if (trx_reset(RFBOTH) != MAC_SUCCESS) { return FAILURE; } /* Check if RF215 is connected */ if ((trx_reg_read( RG_RF_PN) != 0x34) || (trx_reg_read( RG_RF_VN) != 0x01)) { return FAILURE; } /* Initialize trx */ trx_init(); if (tal_timer_init() != MAC_SUCCESS) { return FAILURE; } /* Initialize the buffer management */ bmm_buffer_init(); /* Configure both trx and set default PIB values */ for (uint8_t trx_id = 0; trx_id < NUM_TRX; trx_id++) { /* Configure transceiver */ trx_config((trx_id_t)trx_id); #ifdef RF215V1 /* Calibrate LO */ calibrate_LO((trx_id_t)trx_id); #endif /* Set the default PIB values */ init_tal_pib((trx_id_t)trx_id); /* see 'tal_pib.c' */ calculate_pib_values((trx_id_t)trx_id); /* * Write all PIB values to the transceiver * that are needed by the transceiver itself. */ write_all_tal_pib_to_trx((trx_id_t)trx_id); /* see 'tal_pib.c' **/ config_phy((trx_id_t)trx_id); tal_rx_buffer[trx_id] = bmm_buffer_alloc(LARGE_BUFFER_SIZE); if (tal_rx_buffer[trx_id] == NULL) { return FAILURE; } /* Init incoming frame queue */ qmm_queue_init(&tal_incoming_frame_queue[trx_id]); tal_state[trx_id] = TAL_IDLE; tx_state[trx_id] = TX_IDLE; } /* Init seed of rand() */ tal_generate_rand_seed(); #ifndef DISABLE_IEEE_ADDR_CHECK for (uint8_t trx_id = 0; trx_id < 2; trx_id++) { /* Check if a valid IEEE address is available. */ /* * This while loop is on purpose, since just in the * rare case that such an address is randomly * generated again, we must repeat this. */ while ((tal_pib[trx_id].IeeeAddress == 0x0000000000000000) || (tal_pib[trx_id].IeeeAddress == ((uint64_t)-1))) { /* * In case no valid IEEE address is available, a random * IEEE address will be generated to be able to run the * applications for demonstration purposes. * In production code this can be omitted. */ /* * The proper seed for function rand() has already been *generated * in function tal_generate_rand_seed(). */ uint8_t *ptr_pib = (uint8_t *)&tal_pib[trx_id].IeeeAddress; for (uint8_t i = 0; i < 8; i++) { *ptr_pib++ = (uint8_t)rand(); /* * Note: * Even if casting the 16 bit rand value back to *8 bit, * and running the loop 8 timers (instead of *only 4 times) * may look cumbersome, it turns out that the *code gets * smaller using 8-bit here. * And timing is not an issue at this place... */ } } } #endif #ifdef IQ_RADIO /* Init BB IRQ handler */ pal_trx_irq_flag_clr(RF215_BB); trx_irq_init(RF215_BB, bb_irq_handler_cb); pal_trx_irq_en(RF215_BB); /* Init RF IRQ handler */ pal_trx_irq_flag_clr(RF215_RF); trx_irq_init(RF215_RF, rf_irq_handler_cb); pal_trx_irq_en(RF215_RF); #else /* * Configure interrupt handling. * Install a handler for the radio and the baseband interrupt. */ pal_trx_irq_flag_clr(); trx_irq_init((FUNC_PTR)trx_irq_handler_cb); pal_trx_irq_en(); /* Enable transceiver main interrupt. */ #endif #if ((defined SUPPORT_FSK) && (defined SUPPORT_MODE_SWITCH)) init_mode_switch(); #endif return MAC_SUCCESS; } /* tal_init() */