diff --git a/features/nanostack/targets/TARGET_Freescale/TARGET_KW41Z/NanostackRfPhyKw41z.cpp b/features/nanostack/nanostack-interface/targets/TARGET_Freescale/TARGET_KW41Z/NanostackRfPhyKw41z.cpp similarity index 100% rename from features/nanostack/targets/TARGET_Freescale/TARGET_KW41Z/NanostackRfPhyKw41z.cpp rename to features/nanostack/nanostack-interface/targets/TARGET_Freescale/TARGET_KW41Z/NanostackRfPhyKw41z.cpp diff --git a/features/nanostack/nanostack-interface/targets/TARGET_NXP/TARGET_KW41Z/NanostackRfPhyKw41z.h b/features/nanostack/nanostack-interface/targets/TARGET_Freescale/TARGET_KW41Z/NanostackRfPhyKw41z.h similarity index 100% rename from features/nanostack/nanostack-interface/targets/TARGET_NXP/TARGET_KW41Z/NanostackRfPhyKw41z.h rename to features/nanostack/nanostack-interface/targets/TARGET_Freescale/TARGET_KW41Z/NanostackRfPhyKw41z.h diff --git a/features/nanostack/nanostack-interface/targets/TARGET_NXP/TARGET_KW41Z/NanostackRfPhyKw41z.cpp b/features/nanostack/nanostack-interface/targets/TARGET_NXP/TARGET_KW41Z/NanostackRfPhyKw41z.cpp deleted file mode 100644 index 9ddc9cdbad..0000000000 --- a/features/nanostack/nanostack-interface/targets/TARGET_NXP/TARGET_KW41Z/NanostackRfPhyKw41z.cpp +++ /dev/null @@ -1,1124 +0,0 @@ -/* -* Copyright (c) 2016-2018 ARM Limited. All rights reserved. -* SPDX-License-Identifier: Apache-2.0 -* Licensed under the Apache License, Version 2.0 (the License); you may -* not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an AS IS BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include "mbed_power_mgmt.h" -#include "common_functions.h" -#include "platform/arm_hal_interrupt.h" -#include "platform/arm_hal_phy.h" -#include "NanostackRfPhyKw41z.h" - -#include "fsl_xcvr.h" - -#define RF_THREAD_STACK_SIZE 1024 - -static void rf_thread_loop(); -Thread rf_thread(osPriorityRealtime, RF_THREAD_STACK_SIZE); - -#define PHY_MTU_SIZE 127 -#define CRC_LENGTH 0 -#define PHY_HEADER_LENGTH 0 - -#define BM_ZLL_IRQSTS_TMRxMSK (ZLL_IRQSTS_TMR1MSK_MASK | \ - ZLL_IRQSTS_TMR2MSK_MASK | \ - ZLL_IRQSTS_TMR3MSK_MASK | \ - ZLL_IRQSTS_TMR4MSK_MASK) - -#define RF_CCA_THRESHOLD 75 /* -75 dBm */ - -#define gPhyDefaultTxPowerLevel_d (22) -#define gPhyMaxTxPowerLevel_d (32) -#define gCcaED_c (0) -#define gCcaCCA_MODE1_c (1) - -#define gPhyTimeMask_c (0x00FFFFFF) - -#define KW41Z_SHR_PHY_TIME 12 -#define KW41Z_PER_BYTE_TIME 2 -#define KW41Z_ACK_WAIT_TIME 54 - -static int8_t rf_radio_driver_id = -1; -static uint8_t need_ack = 0; - -/* PHY states */ -typedef enum xcvrState_tag { - gIdle_c, - gRX_c, - gTX_c, - gCCA_c, - gTR_c, - gCCCA_c, -} xcvrState_t; - -static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel); -static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol); -static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr); -static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr); -static void rf_mac_hw_init(void); -static void rf_mac_ed_state_enable(void); -static void rf_mac_set_pending(uint8_t status); -static void rf_mac_set_shortAddress(uint8_t *valueAddress); -static void rf_mac_set_panId(uint8_t *valueAddress); -static void rf_mac_set_mac64(const uint8_t *valueAddress); -static uint8_t rf_convert_energy_level(uint8_t energyLevel); -static void rf_abort(void); -static void rf_ack_wait_timer_start(uint16_t time); -static void rf_get_timestamp(uint32_t *pRetClk); -static uint32_t rf_get_timeout(void); -static void rf_set_timeout(uint32_t timeout); -static void rf_promiscuous(uint8_t state); -static void handle_IRQ_events(void); -static uint8_t PhyPlmeSetCurrentChannelRequest(uint8_t channel, uint8_t pan); -static void rf_receive(void); -static void rf_handle_rx_end(void); - -static uint8_t MAC64_addr_default[8] = {1, 2, 3, 4, 5, 6, 7, 8}; -static uint8_t MAC64_addr[8]; - -static xcvrState_t mPhySeqState; -static uint8_t rf_mac_handle; -static volatile uint8_t rf_ed_value = 0; -static volatile bool rf_ack_pending_state = false; -static volatile bool sleep_blocked = false; - -static NanostackRfPhyKw41z *rf = NULL; - -#define MAC_PACKET_SIZE 127 //MAX MAC payload is 127 bytes -static uint8_t PHYPAYLOAD[MAC_PACKET_SIZE]; - -const phy_rf_channel_configuration_s phy_2_4ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK}; - -const phy_device_channel_page_s phy_channel_pages[] = { - {CHANNEL_PAGE_0, &phy_2_4ghz}, - {CHANNEL_PAGE_0, NULL} -}; - -static phy_device_driver_s device_driver = { - PHY_LINK_15_4_2_4GHZ_TYPE, - PHY_LAYER_PAYLOAD_DATA_FLOW, - MAC64_addr, - PHY_MTU_SIZE, - (char *)"NXP kw41z", - CRC_LENGTH, - PHY_HEADER_LENGTH, - &rf_interface_state_control, - &rf_start_cca, - &rf_address_write, - &rf_extension, - phy_channel_pages, - NULL, - NULL, - NULL, - NULL -}; - -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); - } -} - -static int8_t rf_device_register(void) -{ - if (rf_radio_driver_id < 0) { - rf_mac_hw_init(); - /** - * Read factory stored Mac address to RAM - */ - common_write_32_bit(ZLL->MACLONGADDRS0_MSB, MAC64_addr); - common_write_32_bit(ZLL->MACLONGADDRS0_LSB, MAC64_addr + 4); - - rf_radio_driver_id = arm_net_phy_register(&device_driver); - } - - return rf_radio_driver_id; -} - -static void rf_device_unregister(void) -{ - arm_net_phy_unregister(rf_radio_driver_id); - - if (sleep_blocked) { - sleep_manager_unlock_deep_sleep(); - sleep_blocked = false; - } -} - -/* - * \brief Function enables/disables Rx promiscuous mode. - * - * \param state of XCVR promiscuous mode - * - * \return none - */ -static void rf_promiscuous(uint8_t state) -{ - if (state) { - ZLL->PHY_CTRL |= ZLL_PHY_CTRL_PROMISCUOUS_MASK; - /* FRM_VER[11:8] = b1111. Any FrameVersion accepted */ - ZLL->RX_FRAME_FILTER |= (ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK | - ZLL_RX_FRAME_FILTER_ACK_FT_MASK | - ZLL_RX_FRAME_FILTER_NS_FT_MASK); - } else { - ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_PROMISCUOUS_MASK; - /* FRM_VER[11:8] = b0011. Accept FrameVersion 0 and 1 packets, reject all others */ - /* Beacon, Data and MAC command frame types accepted */ - ZLL->RX_FRAME_FILTER &= ~(ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK | - ZLL_RX_FRAME_FILTER_ACK_FT_MASK | - ZLL_RX_FRAME_FILTER_NS_FT_MASK | - ZLL_RX_FRAME_FILTER_ACTIVE_PROMISCUOUS_MASK); - ZLL->RX_FRAME_FILTER |= ZLL_RX_FRAME_FILTER_FRM_VER_FILTER(3); - } -} - -static void rf_mac_set_pending(uint8_t status) -{ - uint32_t reg = ZLL->SAM_TABLE; - - /* Disable the Source Address Matching feature and set FP manually */ - reg |= ZLL_SAM_TABLE_ACK_FRM_PND_CTRL_MASK; - if (status) { - reg |= ZLL_SAM_TABLE_ACK_FRM_PND_MASK; - rf_ack_pending_state = true; - } else { - reg &= ~ZLL_SAM_TABLE_ACK_FRM_PND_MASK; - rf_ack_pending_state = false; - } - ZLL->SAM_TABLE = reg; -} - -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(); - if (sleep_blocked) { - sleep_manager_unlock_deep_sleep(); - sleep_blocked = false; - } - break; - /*Disable PHY Interface driver*/ - case PHY_INTERFACE_DOWN: - rf_abort(); - if (sleep_blocked) { - sleep_manager_unlock_deep_sleep(); - sleep_blocked = false; - } - break; - /*Enable PHY Interface driver*/ - case PHY_INTERFACE_UP: - if (PhyPlmeSetCurrentChannelRequest(rf_channel, 0)) { - return 1; - } - if (!sleep_blocked) { - /* Disable enter to deep sleep when transfer active */ - sleep_manager_lock_deep_sleep(); - sleep_blocked = true; - } - rf_receive(); - break; - /*Enable wireless interface ED scan mode*/ - case PHY_INTERFACE_RX_ENERGY_STATE: - if (PhyPlmeSetCurrentChannelRequest(rf_channel, 0)) { - return 1; - } - if (!sleep_blocked) { - /* Disable enter to deep sleep when transfer active */ - sleep_manager_lock_deep_sleep(); - sleep_blocked = true; - } - 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; - } - if (!sleep_blocked) { - /* Disable enter to deep sleep when transfer active */ - sleep_manager_lock_deep_sleep(); - sleep_blocked = true; - } - rf_receive(); - break; - } - - platform_exit_critical(); - - return 0; -} - -/* - * \brief Function forces the XCVR to Idle state. - * - * \param none - * - * \return none - */ -static void rf_abort(void) -{ - /* Mask XCVR irq */ - NVIC_DisableIRQ(Radio_1_IRQn); - - mPhySeqState = gIdle_c; - - /* Mask SEQ interrupt */ - ZLL->PHY_CTRL |= ZLL_PHY_CTRL_SEQMSK_MASK; - - /* Disable timer trigger (for scheduled XCVSEQ) */ - if (ZLL->PHY_CTRL & ZLL_PHY_CTRL_TMRTRIGEN_MASK) { - ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMRTRIGEN_MASK; - /* give the FSM enough time to start if it was triggered */ - while ((XCVR_MISC->XCVR_CTRL & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) == 0) {} - } - - /* If XCVR is not idle, abort current SEQ */ - if (ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK) { - /* Abort current SEQ */ - ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK; - - /* Wait for Sequence Idle (if not already) */ - while (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) {} - } - - /* Stop timers */ - ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR1CMP_EN_MASK | - ZLL_PHY_CTRL_TMR2CMP_EN_MASK | - ZLL_PHY_CTRL_TMR3CMP_EN_MASK | - ZLL_PHY_CTRL_TC3TMOUT_MASK); - - /* clear all IRQ bits to avoid unexpected interrupts */ - ZLL->IRQSTS = ZLL->IRQSTS; - - /* Unmask XCVR irq */ - NVIC_EnableIRQ(Radio_1_IRQn); -} - -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 { - tx_warmup_time = tx_warmup_time >> 4; - } - - if (need_ack) { - rf_ack_wait_timer_start(tx_warmup_time + KW41Z_SHR_PHY_TIME + - tx_len * KW41Z_PER_BYTE_TIME + 10 + KW41Z_ACK_WAIT_TIME); - } - - /* Unmask SEQ interrupt */ - ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_SEQMSK_MASK); - - /* Start the TX / TRX */ - reg = ZLL->PHY_CTRL; - reg &= ~(ZLL_PHY_CTRL_XCVSEQ_MASK); - reg |= mPhySeqState; - ZLL->PHY_CTRL = reg; - - platform_exit_critical(); - - /*Return success*/ - return 0; -} - -static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr) -{ - int8_t ret_val = 0; - - platform_enter_critical(); - - switch (address_type) { - case PHY_MAC_64BIT: - rf_mac_set_mac64(address_ptr); - break; - /*Set 16-bit address*/ - case PHY_MAC_16BIT: - rf_mac_set_shortAddress(address_ptr); - break; - /*Set PAN Id*/ - case PHY_MAC_PANID: - rf_mac_set_panId(address_ptr); - break; - default: - ret_val = -1; - } - - platform_exit_critical(); - - return ret_val; -} - -static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr) -{ - int ret_value = 0; - - platform_enter_critical(); - - switch (extension_type) { - case PHY_EXTENSION_CTRL_PENDING_BIT: /**< Control MAC pending bit for indirect data. */ - rf_mac_set_pending(*data_ptr); - break; - /* Return frame Auto Ack frame pending status */ - case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS: { - *data_ptr = rf_ack_pending_state; - break; - } - case PHY_EXTENSION_SET_CHANNEL: /**< Net library channel set. */ - break; - case PHY_EXTENSION_READ_CHANNEL_ENERGY: /**< RF interface ED scan energy read. */ - *data_ptr = rf_ed_value; - break; - case PHY_EXTENSION_READ_LINK_STATUS: /**< Net library could read link status. */ - case PHY_EXTENSION_CONVERT_SIGNAL_INFO: /**< Convert signal info. */ - default: - ret_value = -1; - } - - platform_exit_critical(); - - return ret_value; -} - -/* - * \brief Function converts the energy level from dBm to a 0-255 value. - * - * \param energyLevel in dBm - * - * \return energy level (0-255) - */ -static uint8_t rf_convert_energy_level(uint8_t energyLevel) -{ - int32_t temp = (int8_t)energyLevel; - - if (temp <= -82) { - temp = 0x00; - } else if (temp >= -3) { - temp = 0xFF; - } else { - /* Convert energy level from dbm into a 0x00-0xFF value */ - temp = (255 * temp + 20910) / 79; - } - - return (uint8_t)temp; -} - -/** - * SET MAC 16 address to Register - */ -static void rf_mac_set_shortAddress(uint8_t *valueAddress) -{ - ZLL->MACSHORTADDRS0 &= ~ZLL_MACSHORTADDRS0_MACSHORTADDRS0_MASK; - ZLL->MACSHORTADDRS0 |= ZLL_MACSHORTADDRS0_MACSHORTADDRS0(common_read_16_bit(valueAddress)); -} - -/** - * SET PAN-ID to Register - */ -static void rf_mac_set_panId(uint8_t *valueAddress) -{ - ZLL->MACSHORTADDRS0 &= ~ZLL_MACSHORTADDRS0_MACPANID0_MASK; - ZLL->MACSHORTADDRS0 |= ZLL_MACSHORTADDRS0_MACPANID0(common_read_16_bit(valueAddress)); -} - -/** - * SET MAC64 address to register - */ -static void rf_mac_set_mac64(const uint8_t *valueAddress) -{ - ZLL->MACLONGADDRS0_MSB = common_read_32_bit(valueAddress); - valueAddress += 4; - ZLL->MACLONGADDRS0_LSB = common_read_32_bit(valueAddress); -} - -static void PhyPlmeSetPwrLevelRequest(uint8_t pwrStep) -{ - /* Do not exceed the Tx power limit for the current channel */ - if (pwrStep > gPhyMaxTxPowerLevel_d) { - pwrStep = gPhyMaxTxPowerLevel_d; - } - - if (pwrStep > 2) { - pwrStep = (pwrStep << 1) - 2; - } - - ZLL->PA_PWR = pwrStep; -} - -static uint8_t PhyPlmeGetPwrLevelRequest(void) -{ - uint8_t pwrStep = (uint8_t)ZLL->PA_PWR; - - if (pwrStep > 2) { - pwrStep = (pwrStep + 2) >> 1; - } - - return pwrStep; -} - -static uint8_t PhyPlmeSetCurrentChannelRequest(uint8_t channel, uint8_t pan) -{ - if ((channel < 11) || (channel > 26)) { - return 1; - } - - if (!pan) { - ZLL->CHANNEL_NUM0 = channel; - } else { - ZLL->CHANNEL_NUM1 = channel; - } - - /* Make sure the current Tx power doesn't exceed the Tx power limit for the new channel */ - if (PhyPlmeGetPwrLevelRequest() > gPhyMaxTxPowerLevel_d) { - PhyPlmeSetPwrLevelRequest(gPhyMaxTxPowerLevel_d); - } - - return 0; -} - -/* - * Function is a RF interrupt vector. - */ -static void PHY_InterruptHandler(void) -{ - /* Disable and clear transceiver(IRQ_B) interrupt */ - NVIC_DisableIRQ(Radio_1_IRQn); - rf_thread.flags_set(1); -} - -static void PhyIsrSeqCleanup(void) -{ - uint32_t irqStatus; - - /* Set the PHY sequencer back to IDLE */ - ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK; - /* Mask SEQ, RX, TX and CCA interrupts */ - ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCAMSK_MASK | - ZLL_PHY_CTRL_RXMSK_MASK | - ZLL_PHY_CTRL_TXMSK_MASK | - ZLL_PHY_CTRL_SEQMSK_MASK; - - while (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) {} - - irqStatus = ZLL->IRQSTS; - /* Mask TMR3 interrupt */ - irqStatus |= ZLL_IRQSTS_TMR3MSK_MASK; - /* Clear transceiver interrupts except TMRxIRQ */ - irqStatus &= ~(ZLL_IRQSTS_TMR1IRQ_MASK | - ZLL_IRQSTS_TMR2IRQ_MASK | - ZLL_IRQSTS_TMR3IRQ_MASK | - ZLL_IRQSTS_TMR4IRQ_MASK); - ZLL->IRQSTS = irqStatus; -} - -static void PhyIsrTimeoutCleanup(void) -{ - uint32_t irqStatus; - - /* Set the PHY sequencer back to IDLE and disable TMR3 comparator and timeout */ - ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR3CMP_EN_MASK | - ZLL_PHY_CTRL_TC3TMOUT_MASK | - ZLL_PHY_CTRL_XCVSEQ_MASK); - /* Mask SEQ, RX, TX and CCA interrupts */ - ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCAMSK_MASK | - ZLL_PHY_CTRL_RXMSK_MASK | - ZLL_PHY_CTRL_TXMSK_MASK | - ZLL_PHY_CTRL_SEQMSK_MASK; - - while (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK) {} - - irqStatus = ZLL->IRQSTS; - /* Mask TMR3 interrupt */ - irqStatus |= ZLL_IRQSTS_TMR3MSK_MASK; - /* Clear transceiver interrupts except TMR1IRQ and TMR4IRQ. */ - irqStatus &= ~(ZLL_IRQSTS_TMR1IRQ_MASK | - ZLL_IRQSTS_TMR4IRQ_MASK); - ZLL->IRQSTS = irqStatus; - - /* The packet was transmitted successfully, but no ACK was received */ - if (device_driver.phy_tx_done_cb) { - device_driver.phy_tx_done_cb(rf_radio_driver_id, rf_mac_handle, PHY_LINK_TX_SUCCESS, 1, 1); - } -} - -/* - * \brief Function get the time-out for the current sequence. - * - * \return sequence time-out value - */ -static uint32_t rf_get_timeout(void) -{ - return ZLL->T3CMP; -} - -/* - * \brief Function set a time-out to an XCVR sequence. - * - * \param pEndTime sequence time-out value [symbols] - * - * \return none - */ -static void rf_set_timeout(uint32_t pEndTime) -{ - uint32_t irqsts; - - platform_enter_critical(); - - /* disable TMR3 compare */ - ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMR3CMP_EN_MASK; - ZLL->T3CMP = pEndTime & ZLL_T3CMP_T3CMP_MASK; - - /* acknowledge TMR3 IRQ */ - irqsts = ZLL->IRQSTS & BM_ZLL_IRQSTS_TMRxMSK; - irqsts |= ZLL_IRQSTS_TMR3IRQ_MASK; - ZLL->IRQSTS = irqsts; - /* enable TMR3 compare */ - ZLL->PHY_CTRL |= ZLL_PHY_CTRL_TMR3CMP_EN_MASK; - /* enable autosequence stop by TC3 match */ - ZLL->PHY_CTRL |= ZLL_PHY_CTRL_TC3TMOUT_MASK; - - platform_exit_critical(); - -} - -/** - * Call this only One time - */ -static void rf_mac_hw_init(void) -{ - xcvrStatus_t xcvrStatus; - uint32_t phyReg; - - /* The data rate argument only matters when GFSK/MSK protocol is selected */ - xcvrStatus = XCVR_Init(ZIGBEE_MODE, DR_500KBPS); - if (xcvrStatus != gXcvrSuccess_c) { - return; - } - - mPhySeqState = gIdle_c; - - /* Enable 16 bit mode for TC2 - TC2 prime EN, disable all timers, - enable AUTOACK, mask all interrupts */ - ZLL->PHY_CTRL = (gCcaCCA_MODE1_c << ZLL_PHY_CTRL_CCATYPE_SHIFT) | - ZLL_PHY_CTRL_TC2PRIME_EN_MASK | - ZLL_PHY_CTRL_TSM_MSK_MASK | - ZLL_PHY_CTRL_WAKE_MSK_MASK | - ZLL_PHY_CTRL_CRC_MSK_MASK | - ZLL_PHY_CTRL_PLL_UNLOCK_MSK_MASK | - ZLL_PHY_CTRL_FILTERFAIL_MSK_MASK | - ZLL_PHY_CTRL_RX_WMRK_MSK_MASK | - ZLL_PHY_CTRL_CCAMSK_MASK | - ZLL_PHY_CTRL_RXMSK_MASK | - ZLL_PHY_CTRL_TXMSK_MASK | - ZLL_PHY_CTRL_SEQMSK_MASK | - ZLL_PHY_CTRL_AUTOACK_MASK | - ZLL_PHY_CTRL_TRCV_MSK_MASK; - - /* Clear all PP IRQ bits to avoid unexpected interrupts immediately after init - disable all timer interrupts */ - ZLL->IRQSTS = ZLL->IRQSTS; - - /* Clear HW indirect queue */ - ZLL->SAM_TABLE |= ZLL_SAM_TABLE_INVALIDATE_ALL_MASK; - - /* Frame Filtering - FRM_VER[7:6] = b11. Accept FrameVersion 0 and 1 packets, reject all others */ - ZLL->RX_FRAME_FILTER &= ~ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK; - ZLL->RX_FRAME_FILTER = ZLL_RX_FRAME_FILTER_FRM_VER_FILTER(3) | - ZLL_RX_FRAME_FILTER_CMD_FT_MASK | - ZLL_RX_FRAME_FILTER_DATA_FT_MASK | - ZLL_RX_FRAME_FILTER_BEACON_FT_MASK; - - /* Set prescaller to obtain 1 symbol (16us) timebase */ - ZLL->TMR_PRESCALE = 0x05; - - /* Set CCA threshold to -75 dBm */ - ZLL->CCA_LQI_CTRL &= ~ZLL_CCA_LQI_CTRL_CCA1_THRESH_MASK; - ZLL->CCA_LQI_CTRL |= ZLL_CCA_LQI_CTRL_CCA1_THRESH(RF_CCA_THRESHOLD); - - /* Set the default power level */ - PhyPlmeSetPwrLevelRequest(gPhyDefaultTxPowerLevel_d); - - /* Adjust ACK delay to fulfill the 802.15.4 turnaround requirements */ - ZLL->ACKDELAY &= ~ZLL_ACKDELAY_ACKDELAY_MASK; - ZLL->ACKDELAY |= ZLL_ACKDELAY_ACKDELAY(-8); - - /* Adjust LQI compensation */ - ZLL->CCA_LQI_CTRL &= ~ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP_MASK; - ZLL->CCA_LQI_CTRL |= ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP(96); - - /* Enable the RxWatermark IRQ */ - ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_RX_WMRK_MSK_MASK; - /* Set Rx watermark level */ - ZLL->RX_WTR_MARK = 0; - - /* Set default channels */ - PhyPlmeSetCurrentChannelRequest(0x0B, 0); /* 2405 MHz */ - PhyPlmeSetCurrentChannelRequest(0x0B, 1); /* 2405 MHz */ - - /* DSM settings */ - phyReg = (RSIM->RF_OSC_CTRL & RSIM_RF_OSC_CTRL_BB_XTAL_READY_COUNT_SEL_MASK) >> - RSIM_RF_OSC_CTRL_BB_XTAL_READY_COUNT_SEL_SHIFT; - phyReg = (1024U << phyReg) / (SystemCoreClock / 32768) + 1; - RSIM->DSM_OSC_OFFSET = phyReg; - - osStatus status = rf_thread.start(mbed::callback(rf_thread_loop)); - MBED_ASSERT(status == osOK); - - /** Clear and enable MAC IRQ at task level, when scheduler is on. */ - InstallIRQHandler((IRQn_Type)Radio_1_IRQn, (uint32_t)PHY_InterruptHandler); - - /* Unmask Transceiver Global Interrupts */ - ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TRCV_MSK_MASK; - - NVIC_ClearPendingIRQ(Radio_1_IRQn); - NVIC_EnableIRQ(Radio_1_IRQn); -} - -/* - * \brief Function reads a time-stamp value from XCVR [symbols] - * - * \param pEndTime pointer to location where time-stamp will be stored - * - * \return none - */ -static void rf_get_timestamp(uint32_t *pRetClk) -{ - if (NULL == pRetClk) { - return; - } - - platform_enter_critical(); - - *pRetClk = 0; - *pRetClk = ZLL->EVENT_TMR >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT; - - platform_exit_critical(); -} - -/* - * \brief Function starts the ACK wait time-out. - * - * \param slots The ACK wait time-out in [symbols] - * - * \return none - */ -static void rf_ack_wait_timer_start(uint16_t time) -{ - uint32_t timestamp, t; - - rf_get_timestamp(×tamp); - - t = (rf_get_timeout() - timestamp) & gPhyTimeMask_c; - - if (t > 1) { - timestamp += time; - rf_set_timeout(timestamp); - } -} - -/* - * \brief Function sets the RF in RX state. - * - * \param none - * - * \return none - */ -static void rf_receive(void) -{ - uint32_t irqSts; - - /* RX can start only from Idle state */ - if (mPhySeqState != gIdle_c) { - rf_abort(); - } - - mPhySeqState = gRX_c; - - /* Ensure that no spurious interrupts are raised, but do not change TMR1 and TMR4 IRQ status */ - irqSts = ZLL->IRQSTS; - irqSts &= ~(ZLL_IRQSTS_TMR1IRQ_MASK | ZLL_IRQSTS_TMR4IRQ_MASK); - irqSts |= ZLL_IRQSTS_TMR3MSK_MASK; - ZLL->IRQSTS = irqSts; - - /* unmask SEQ interrupt */ - ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_SEQMSK_MASK; - - /* Start the RX sequence */ - ZLL->PHY_CTRL |= gRX_c; -} - -static void rf_mac_ed_state_enable(void) -{ - uint32_t ccaMode, irqSts; - - mPhySeqState = gCCA_c; - - /* Switch to ED mode */ - ccaMode = (ZLL->PHY_CTRL & ZLL_PHY_CTRL_CCATYPE_MASK) >> ZLL_PHY_CTRL_CCATYPE_SHIFT; - if (ccaMode != gCcaED_c) { - ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_CCATYPE_MASK); - } - - /* Ensure that no spurious interrupts are raised(do not change TMR1 and TMR4 IRQ status) */ - irqSts = ZLL->IRQSTS; - irqSts &= ~(ZLL_IRQSTS_TMR1IRQ_MASK | ZLL_IRQSTS_TMR4IRQ_MASK); - irqSts |= ZLL_IRQSTS_TMR3MSK_MASK; - ZLL->IRQSTS = irqSts; - - /* Unmask SEQ interrupt */ - ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_SEQMSK_MASK; - - /* start ED sequence */ - ZLL->PHY_CTRL |= gCCA_c; -} - -/* - * \brief Function is a call back for TX end interrupt. - * - * \param none - * - * \return none - */ -static void rf_handle_tx_end(bool framePending) -{ - /*Start receiver*/ - rf_receive(); - - if (!device_driver.phy_tx_done_cb) { - return; - } - - /*Call PHY TX Done API*/ - if (need_ack) { - if (framePending) { - device_driver.phy_tx_done_cb(rf_radio_driver_id, rf_mac_handle, PHY_LINK_TX_DONE_PENDING, 1, 1); - } else { - device_driver.phy_tx_done_cb(rf_radio_driver_id, rf_mac_handle, PHY_LINK_TX_DONE, 1, 1); - } - } else { - device_driver.phy_tx_done_cb(rf_radio_driver_id, rf_mac_handle, PHY_LINK_TX_SUCCESS, 1, 1); - } -} - -/* - * \brief Function converts LQI into RSSI. - * - * \param LQI - * - * \return RSSI - */ -static int8_t rf_convert_LQI_to_RSSI(uint8_t lqi) -{ - int32_t rssi = (36 * lqi - 9836) / 109; - - return (int8_t)rssi; -} - -/* - * \brief Function scale the LQI value reported by RF into a 0-255 value. - * - * \param hwLqi - the LQI value reported by RF - * - * \return scaled LQI - */ -static uint8_t rf_convert_LQI(uint8_t hwLqi) -{ - if (hwLqi >= 220) { - return 255; - } else { - return (51 * hwLqi) / 44; - } -} - -/* - * \brief Function is a call back for RX end interrupt. - * - * \param none - * - * \return none - */ -static void rf_handle_rx_end(void) -{ - uint8_t rf_lqi = (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_LQI_VALUE_MASK) >> - ZLL_LQI_AND_RSSI_LQI_VALUE_SHIFT; - int8_t rf_rssi = 0; - uint8_t len; - uint8_t i; - volatile uint8_t *pPB; - - len = (ZLL->IRQSTS & ZLL_IRQSTS_RX_FRAME_LENGTH_MASK) >> ZLL_IRQSTS_RX_FRAME_LENGTH_SHIFT; /* Including FCS (2 bytes) */ - - /* Excluding FCS (2 bytes) */ - len -= 2; - - /*Check the length is valid*/ - if (len > 1 && len < MAC_PACKET_SIZE) { - rf_lqi = rf_convert_LQI(rf_lqi); - rf_rssi = rf_convert_LQI_to_RSSI(rf_lqi); - - /* Load data from Packet Buffer */ - pPB = (uint8_t *)ZLL->PKT_BUFFER_RX; - - for (i = 0; i < len; i++) { - PHYPAYLOAD[i] = *pPB++; - } - - /* Start receiver */ - rf_receive(); - - if (device_driver.phy_rx_cb) { - device_driver.phy_rx_cb(PHYPAYLOAD, len, rf_lqi, rf_rssi, rf_radio_driver_id); - } - } else { - /* Start receiver */ - rf_receive(); - } -} - -static void handle_IRQ_events(void) -{ - uint8_t xcvseqCopy; - uint32_t irqStatus; - - /* Read current XCVRSEQ and interrupt status */ - xcvseqCopy = ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK; - irqStatus = ZLL->IRQSTS; - /* Clear all xcvr interrupts */ - ZLL->IRQSTS = irqStatus; - - /* Filter Fail IRQ */ - if (irqStatus & ZLL_IRQSTS_FILTERFAIL_IRQ_MASK) { - - } else { - /* Rx Watermark IRQ */ - if ((!(ZLL->PHY_CTRL & ZLL_PHY_CTRL_RX_WMRK_MSK_MASK)) && - (irqStatus & ZLL_IRQSTS_RXWTRMRKIRQ_MASK)) { - uint32_t rx_len = (irqStatus & ZLL_IRQSTS_RX_FRAME_LENGTH_MASK) >> ZLL_IRQSTS_RX_FRAME_LENGTH_SHIFT; - - /* Convert to symbols and add IFS and ACK duration */ - rx_len = rx_len * 2 + 12 + 22 + 2; - rf_ack_wait_timer_start(rx_len); - } - } - - /* Sequencer interrupt, the autosequence has completed */ - if (irqStatus & ZLL_IRQSTS_SEQIRQ_MASK) { - - /* XCVR will be set to Idle */ - mPhySeqState = gIdle_c; - - /* PLL unlock, the autosequence has been aborted due to PLL unlock */ - if (irqStatus & ZLL_IRQSTS_PLL_UNLOCK_IRQ_MASK) { - PhyIsrSeqCleanup(); - /* Start receiver */ - rf_receive(); - } - /* TMR3 timeout, the autosequence has been aborted due to TMR3 timeout */ - else if ((irqStatus & ZLL_IRQSTS_TMR3IRQ_MASK) && - (!(irqStatus & ZLL_IRQSTS_RXIRQ_MASK)) && - (xcvseqCopy != gTX_c)) { - PhyIsrTimeoutCleanup(); - /* Start receiver */ - rf_receive(); - } else { - PhyIsrSeqCleanup(); - switch (xcvseqCopy) { - case gTX_c: - if ((ZLL->PHY_CTRL & ZLL_PHY_CTRL_CCABFRTX_MASK) && - (irqStatus & ZLL_IRQSTS_CCA_MASK)) { - device_driver.phy_tx_done_cb(rf_radio_driver_id, rf_mac_handle, - PHY_LINK_CCA_FAIL, 1, 1); - } else { - rf_handle_tx_end(false); - } - break; - - case gTR_c: - if ((ZLL->PHY_CTRL & ZLL_PHY_CTRL_CCABFRTX_MASK) && - (irqStatus & ZLL_IRQSTS_CCA_MASK)) { - device_driver.phy_tx_done_cb(rf_radio_driver_id, rf_mac_handle, - PHY_LINK_CCA_FAIL, 1, 1); - } else { - rf_handle_tx_end((irqStatus & ZLL_IRQSTS_RX_FRM_PEND_MASK) > 0); - } - break; - - case gRX_c: - rf_handle_rx_end(); - break; - - case gCCA_c: - rf_ed_value = rf_convert_energy_level((ZLL->LQI_AND_RSSI & - ZLL_LQI_AND_RSSI_CCA1_ED_FNL_MASK) >> - ZLL_LQI_AND_RSSI_CCA1_ED_FNL_SHIFT); - break; - - default: - break; - } - } - } -} - -NanostackRfPhyKw41z::NanostackRfPhyKw41z() -{ - memcpy(MAC64_addr, MAC64_addr_default, sizeof(MAC64_addr)); -} - -NanostackRfPhyKw41z::~NanostackRfPhyKw41z() -{ - // Do nothing -} - -int8_t NanostackRfPhyKw41z::rf_register() -{ - platform_enter_critical(); - - if (rf != NULL) { - platform_exit_critical(); - error("Multiple registrations of NanostackRfPhyKw41z not supported"); - return -1; - } - - rf = this; - int8_t radio_id = rf_device_register(); - if (radio_id < 0) { - rf = NULL; - } - - platform_exit_critical(); - return radio_id; -} - -void NanostackRfPhyKw41z::rf_unregister() -{ - platform_enter_critical(); - - if (rf != this) { - platform_exit_critical(); - return; - } - - rf_device_unregister(); - rf = NULL; - - platform_exit_critical(); -} - -void NanostackRfPhyKw41z::get_mac_address(uint8_t *mac) -{ - platform_enter_critical(); - - memcpy((void *)mac, (void *)MAC64_addr, sizeof(MAC64_addr)); - - platform_exit_critical(); -} - -void NanostackRfPhyKw41z::set_mac_address(uint8_t *mac) -{ - platform_enter_critical(); - - if (NULL != rf) { - error("NanostackRfPhyKw41z cannot change mac address when running"); - platform_exit_critical(); - return; - } - memcpy((void *)MAC64_addr, (void *)mac, sizeof(MAC64_addr)); - - platform_exit_critical(); -} - -NanostackRfPhy &NanostackRfPhy::get_default_instance() -{ - static NanostackRfPhyKw41z rf_phy; - return rf_phy; -} diff --git a/features/nanostack/targets/TARGET_Freescale/TARGET_KW41Z/NanostackRfPhyKw41z.h b/features/nanostack/targets/TARGET_Freescale/TARGET_KW41Z/NanostackRfPhyKw41z.h deleted file mode 100644 index c85f6bdca3..0000000000 --- a/features/nanostack/targets/TARGET_Freescale/TARGET_KW41Z/NanostackRfPhyKw41z.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2018 ARM Limited. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NANOSTACK_PHY_KW41Z_H_ -#define NANOSTACK_PHY_KW41Z_H_ - -#if MBED_CONF_RTOS_PRESENT -#include "rtos/rtos.h" -#endif -#include "NanostackRfPhy.h" -#include "fsl_common.h" - -class NanostackRfPhyKw41z : public NanostackRfPhy { -public: - NanostackRfPhyKw41z(); - ~NanostackRfPhyKw41z(); - int8_t rf_register(); - void rf_unregister(); - void get_mac_address(uint8_t *mac); - void set_mac_address(uint8_t *mac); -}; - -#endif /* NANOSTACK_PHY_KW41Z_H_ */