/** * @brief Reset transceiver * * @return MAC_SUCCESS if the transceiver state is changed to TRX_OFF * FAILURE otherwise */ static retval_t trx_reset(void) { tal_trx_status_t trx_status; uint8_t poll_counter = 0; #if (EXTERN_EEPROM_AVAILABLE == 1) uint8_t xtal_trim_value; #endif /* Get trim value for 16 MHz xtal; needs to be done before reset */ #if (EXTERN_EEPROM_AVAILABLE == 1) pal_ps_get(EXTERN_EEPROM, EE_XTAL_TRIM_ADDR, 1, &xtal_trim_value); #endif /* trx might sleep, so wake it up */ PAL_SLP_TR_LOW(); pal_timer_delay(SLEEP_TO_TRX_OFF_TYP_US); /* Apply reset pulse */ PAL_RST_LOW(); pal_timer_delay(RST_PULSE_WIDTH_US); PAL_RST_HIGH(); /* verify that trx has reached TRX_OFF */ do { /* Wait a short time interval. */ pal_timer_delay(TRX_POLL_WAIT_TIME_US); trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS); /* Wait not more than max. value of TR2. */ if (poll_counter == SLEEP_TO_TRX_OFF_ATTEMPTS) { #if (DEBUG > 0) pal_alert(); #endif return FAILURE; } poll_counter++; } while (trx_status != TRX_OFF); tal_trx_status = TRX_OFF; // Write 16MHz xtal trim value to trx. // It's only necessary if it differs from the reset value. #if (EXTERN_EEPROM_AVAILABLE == 1) if (xtal_trim_value != 0x00) { pal_trx_bit_write(SR_XTAL_TRIM, xtal_trim_value); } #endif return MAC_SUCCESS; }
/** * \brief Reset transceiver */ static retval_t trx_reset(void) { tal_trx_status_t trx_status; uint8_t poll_counter = 0; #if (EXTERN_EEPROM_AVAILABLE == 1) uint8_t xtal_trim_value; #endif /* Get trim value for 16 MHz xtal; needs to be done before reset */ #if (EXTERN_EEPROM_AVAILABLE == 1) pal_ps_get(EXTERN_EEPROM, EE_XTAL_TRIM_ADDR, 1, &xtal_trim_value); #endif /* trx might sleep, so wake it up */ PAL_SLP_TR_LOW(); pal_timer_delay(SLEEP_TO_TRX_OFF_US); PAL_RST_LOW(); pal_timer_delay(RST_PULSE_WIDTH_US); PAL_RST_HIGH(); /* verify that trx has reached TRX_OFF */ do { trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS); poll_counter++; if (poll_counter > 250) { #if (_DEBUG_ > 0) Assert( "MAX Attempts to switch to TRX_OFF state reached" == 0); #endif return FAILURE; } } while (trx_status != TRX_OFF); tal_trx_status = TRX_OFF; /* Write 16MHz xtal trim value to trx. */ /* It's only necessary if it differs from the reset value. */ #if (EXTERN_EEPROM_AVAILABLE == 1) if (xtal_trim_value != 0x00) { pal_trx_bit_write(SR_XTAL_TRIM, xtal_trim_value); } #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; } 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() */
/* * \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() */