/**************************************************************************** Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT be copied by any method or incorporated into another program without the express written consent of Aerospace C.Power. This Information or any portion thereof remains the property of Aerospace C.Power. The Information contained herein is believed to be accurate and Aerospace C.Power assumes no responsibility or liability for its use in any way and conveys no license or title under any patent or copyright and makes no representation or warranty that this Information is free from patent or copyright infringement. ****************************************************************************/ /* os shim includes */ #include "iot_config.h" #include "os_types.h" /* plc public api includes */ #include "plc_fr.h" #include "plc_const.h" #include "iot_bitops.h" /* mac module internal includes */ #include "mac.h" #include "mac_dsr.h" #include "mac_isr.h" #include "hw_reg_api.h" #include "mac_sys_reg.h" /* driver includes */ #include "iot_irq.h" #include "mac_ppm_scan.h" /* WAR */ #include "mac_rx_buf_ring.h" #if HW_PLATFORM >= HW_PLATFORM_FPGA #include "mac_raw_reg.h" #include "mac_rawdata_hw.h" #include "plc_protocol.h" #include "phy_bb.h" #include "phy_phase.h" #endif #include "mac_pdev.h" #include "mac_tx_power.h" #if WAR_TIMEOUT_TX_ABORT #include "mac_tx_hw.h" #endif #include "mac_int.h" #include "mac_cmn_hw.h" #include "mac_rf_isr.h" #if HW_PLATFORM == HW_PLATFORM_SIMU void mac_isr_enable(uint8_t id) { (void)id; } void mac_isr_disable(uint8_t id) { (void)id; } void mac_isr_start() { } void mac_isr_clear(uint32_t isr_evt) { (void)isr_evt; } void mac_isr_stop() { } void mac_isr_init(dsr_notification_func_t callback) { (void)callback; } #else /* HW_PLATFORM == HW_PLATFORM_SIMU */ /* global mac isr context */ mac_isr_ctx_t g_mac_isr_ctx; mac_isr_ctx_t *p_mac_isr_ctx = &g_mac_isr_ctx; uint8_t IRAM_ATTR mac_isr_get_dsr_id(uint32_t isr_id) { uint32_t dsr_id = MAC_DSR_MAX_ID; #if 1 if (isr_id == MAC_ISR_BC_ALERT_ID) { dsr_id = MAC_DSR_BC_ALERT_ID; } else if (isr_id == MAC_ISR_BC_MISS_ID) { dsr_id = MAC_DSR_BC_MISS_ID; } else if (isr_id == MAC_ISR_BC_RX_ID) { dsr_id = MAC_DSR_BC_RX_ID; } else if (isr_id == MAC_ISR_SCH_STOP_ID) { dsr_id = MAC_DSR_SCH_STOP_ID; } else if (isr_id == MAC_ISR_HWQ_STOP_ID) { dsr_id = MAC_DSR_HWQ_STOP_ID; } else if (isr_id == MAC_ISR_MPDU_TX_COMP_ID) { dsr_id = MAC_DSR_MPDU_TX_COMP_ID; } else if (isr_id == MAC_ISR_MPDU_LIST_TX_COMP_ID) { dsr_id = MAC_DSR_MPDU_LIST_TX_COMP_ID; } else if (isr_id == MAC_ISR_START_DESC_ERR_ID) { dsr_id = MAC_DSR_START_DESC_ERR_ID; } else if (isr_id == MAC_ISR_END_DESC_ERR_ID) { dsr_id = MAC_DSR_END_DESC_ERR_ID; } else if (isr_id == MAC_ISR_TX_UNDERRUN_ID) { dsr_id = MAC_DSR_TX_UNDERRUN_ID; } else if (isr_id == MAC_ISR_MPDU_RX_ID) { dsr_id = MAC_DSR_MPDU_RX_ID; } else if (isr_id == MAC_ISR_PB_RX_ID) { dsr_id = MAC_DSR_PB_RX_ID; } else if (isr_id == MAC_ISR_FC_RX_ID) { dsr_id = MAC_DSR_FC_RX_ID; } else if (isr_id == MAC_ISR_RX_DESC_OVERFLOW_ID) { dsr_id = MAC_DSR_RX_DESC_OVERFLOW_ID; } else if (isr_id == MAC_ISR_RX_LOAD_OVERFLOW_ID) { dsr_id = MAC_DSR_RX_LOAD_OVERFLOW_ID; } else if (isr_id == MAC_ISR_RX_LOW_WATERMARK_ID) { dsr_id = MAC_DSR_RX_LOW_WATERMARK_ID; } #else switch (isr_id) { case MAC_ISR_BC_ALERT_ID: dsr_id = MAC_DSR_BC_ALERT_ID; break; case MAC_ISR_BC_MISS_ID: dsr_id = MAC_DSR_BC_MISS_ID; break; case MAC_ISR_BC_RX_ID: dsr_id = MAC_DSR_BC_RX_ID; break; case MAC_ISR_SCH_STOP_ID: dsr_id = MAC_DSR_SCH_STOP_ID; break; case MAC_ISR_HWQ_STOP_ID: dsr_id = MAC_DSR_HWQ_STOP_ID; break; case MAC_ISR_MPDU_TX_COMP_ID: dsr_id = MAC_DSR_MPDU_TX_COMP_ID; break; case MAC_ISR_MPDU_LIST_TX_COMP_ID: dsr_id = MAC_DSR_MPDU_LIST_TX_COMP_ID; break; case MAC_ISR_START_DESC_ERR_ID: dsr_id = MAC_DSR_START_DESC_ERR_ID; break; case MAC_ISR_END_DESC_ERR_ID: dsr_id = MAC_DSR_END_DESC_ERR_ID; break; case MAC_ISR_TX_UNDERRUN_ID: dsr_id = MAC_DSR_TX_UNDERRUN_ID; break; case MAC_ISR_MPDU_RX_ID: dsr_id = MAC_DSR_MPDU_RX_ID; break; case MAC_ISR_PB_RX_ID: dsr_id = MAC_DSR_PB_RX_ID; break; case MAC_ISR_FC_RX_ID: dsr_id = MAC_DSR_FC_RX_ID; break; case MAC_ISR_RX_DESC_OVERFLOW_ID: dsr_id = MAC_DSR_RX_DESC_OVERFLOW_ID; break; case MAC_ISR_RX_LOAD_OVERFLOW_ID: dsr_id = MAC_DSR_RX_LOAD_OVERFLOW_ID; break; case MAC_ISR_RX_LOW_WATERMARK_ID: dsr_id = MAC_DSR_RX_LOW_WATERMARK_ID; break; default: break; } #endif return dsr_id; } static uint32_t IRAM_ATTR mac_isr_ext1_handler(uint32_t vector, iot_addrword_t data) { uint32_t int_status; uint8_t dsr[32], cnt; (void)vector; (void)data; /* read pending interrupt status */ int_status = RGF_MAC_READ_REG(CFG_MAC_INT_EXT_3_STS_ADDR); /* clear pending interrupt status */ RGF_MAC_WRITE_REG(CFG_MAC_INT_EXT_3_CLR_ADDR, int_status); cnt = 0; if (int_status & ((1 << MAC_INT_ZC0_CAP_OFFSET) | (1 << MAC_INT_ZC1_CAP_OFFSET) | (1 << MAC_INT_ZC2_CAP_OFFSET) | (1 << MAC_INT_ZC3_CAP_OFFSET) | (1 << MAC_INT_ZC4_CAP_OFFSET) | (1 << MAC_INT_ZC5_CAP_OFFSET))) { dsr[cnt++] = MAC_DSR_ZERO_CROSS_ID; } //TODO: add code #if ENA_TX_RAW_INT uint32_t raw_sts = RGF_RAW_READ_REG(CFG_RAW_INT_STATUS_ADDR); if (MAC_TX_START_INT_STATUS & raw_sts) { uint32_t fc[4]; /* tx fc need update */ iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_NEED_UPD_ADDR, 0x1); /* get original tx fc */ fc[0] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_RAW_FC_0_ADDR); fc[1] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_RAW_FC_1_ADDR); fc[2] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_RAW_FC_2_ADDR); fc[3] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_RAW_FC_3_ADDR); iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_0_ADDR, fc[0]); iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_1_ADDR, fc[1]); iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_2_ADDR, fc[2]); iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_SW_FC_3_ADDR, fc[3]); iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA0_ADDR, fc[0]); iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA1_ADDR, fc[1]); iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA2_ADDR, fc[2]); iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA3_ADDR, fc[3]); /* set sw fc valid */ iot_raw_write_reg(RAW_REG_TYPE_MAC, CFG_SW_FC_VALID_ADDR, 0x1); /* clear interrupt status */ mac_rawdata_tx_start_isr_clr(); } #endif #if ENABLE_CCA_ISR == 1 /* TODO: for kl3, need move to proi 0/1 */ mac_set_cca_pcs_busy_timeout_ms(0, 0); mac_set_cca_pcs_idle_timeout_ms(0, 0); mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID); uint32_t int_status; int_status = mac_cca_get_int_sts(pdev->cca_isr_pri); mac_cca_int_clear(pdev->cca_isr_pri, int_status); if(int_status & (1<dsr_callback(dsr, cnt); mac_isr_stop(); } /* if entry cert mode, * use os_task_switch_context sw can immediately entry dsr * to save time */ mac_pdev_t *pdev_t = g_mac_pdev[PLC_PDEV_ID]; if (1 == pdev_t->switch_ctxt_in_mac_isr) { os_task_switch_context(); } return 0; } static uint32_t IRAM_ATTR mac_isr_handler(uint32_t vector, iot_addrword_t data) { uint8_t i, j, tmp; uint32_t int_status; uint8_t dsr[32], cnt; (void)vector; (void)data; /* read pending interrupt status */ int_status = RGF_MAC_READ_REG(CFG_MAC_INT_STS_ADDR); int_status >>= MAC_INT_STATUS_OFFSET; /* clear pending interrupt status */ RGF_MAC_WRITE_REG(CFG_MAC_INT_CLR_ADDR, (int_status << MAC_INT_CLR_0_OFFSET)); i = 0; cnt = 0; while (int_status) { tmp = int_status & 0xFF; while (tmp) { #if WAR_TIMEOUT_TX_ABORT /*check phy tx abort*/ mac_check_timeout_tx_abort(); #endif j = iot_bitops_fls(tmp) - 1; tmp &= ~(0x1 << j); dsr[cnt] = mac_isr_get_dsr_id(i + j); cnt++; #if MAC_SCHED_HW_DEBUG if (MAC_ISR_BC_ALERT_ID == (i + j)) { //reorder beacon alert time g_mac_pdev[PLC_PDEV_ID]->mac_isr_rx_fc_ts_ntb = \ RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); } #endif /*count mac underrun_cnt */ if (MAC_ISR_TX_UNDERRUN_ID == (i + j)) { g_mac_pdev[PLC_PDEV_ID]->mac_underrun_cnt++; } /* isr callback */ if (MAC_ISR_MPDU_RX_ID == (i + j)) { #if ENA_HW_SYNC_PPM_WAR mac_hw_sync_ppm_clr(PLC_PDEV_ID); #endif #if DEBUG_INVAILD_ADDR mac_judge_ring_buf_validation(); #endif /* WAR for bug id 244, save sof fc info * TODO:remember a cnt, and check at * the top of SACK handler */ #if MAC_TIMESTAMPING mac_pdev_t *pdev_t = g_mac_pdev[PLC_PDEV_ID]; pdev_t->mac_isr_ntb = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); #endif } if (MAC_ISR_MPDU_TX_COMP_ID == (i + j)) { /* tx comp isr */ mac_pdev_t *pdev = g_mac_pdev[PLC_PDEV_ID]; pdev->fc_hw[0] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA0_ADDR); pdev->fc_hw[1] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA1_ADDR); pdev->fc_hw[2] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA2_ADDR); pdev->fc_hw[3] = iot_raw_read_reg(RAW_REG_TYPE_MAC, CFG_TX_FC_DATA3_ADDR); } } int_status >>= 8; i += 8; } if (cnt) { dsr[cnt] = MAC_DSR_ISR_SYNC_ID; cnt++; p_mac_isr_ctx->dsr_callback(dsr, cnt); mac_isr_stop(); } /* if entry cert mode, * use os_task_switch_context sw can immediately entry dsr * to save time */ mac_pdev_t *pdev_t = g_mac_pdev[PLC_PDEV_ID]; if(1 == pdev_t->switch_ctxt_in_mac_isr) { os_task_switch_context(); } return 0; } static void mac_isr_reset() { uint32_t prio_mask; /* disable all mac interrupt and clean up any pending interrupt */ p_mac_isr_ctx->isr_mask = 0; RGF_MAC_WRITE_REG(CFG_INT_ENA_MASK_ADDR, p_mac_isr_ctx->isr_mask); /* clean up all pending interrupt */ RGF_MAC_WRITE_REG(CFG_MAC_INT_CLR_ADDR, CFG_INT_ENABLE_MASK_MASK); /* assign priority 0 interrupts, CPU0 & CPU1 use the interrupt */ prio_mask = 1 << (MAC_ISR_MPDU_RX_ID + CFG_INT_PRI0_MASK_OFFSET); RGF_MAC_WRITE_REG(CFG_INT_PRI0_MASK_ADDR, prio_mask); /* assign priority 1 interrupts */ prio_mask = 1 << (MAC_ISR_BC_MISS_ID + CFG_INT_PRI1_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_SCH_STOP_ID + CFG_INT_PRI1_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_HWQ_STOP_ID + CFG_INT_PRI1_MASK_OFFSET); /* move from priority 0 */ prio_mask |= 1 << (MAC_ISR_RX_LOW_WATERMARK_ID + CFG_INT_PRI0_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_MPDU_TX_COMP_ID + CFG_INT_PRI0_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_MPDU_LIST_TX_COMP_ID + CFG_INT_PRI0_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_PB_RX_ID + CFG_INT_PRI0_MASK_OFFSET); RGF_MAC_WRITE_REG(CFG_INT_PRI1_MASK_ADDR, prio_mask); /* assign priority 2 interrupts */ prio_mask = 1 << (MAC_ISR_BC_ALERT_ID + CFG_INT_PRI2_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_BC_RX_ID + CFG_INT_PRI2_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_START_DESC_ERR_ID + CFG_INT_PRI2_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_END_DESC_ERR_ID + CFG_INT_PRI2_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_TX_UNDERRUN_ID + CFG_INT_PRI2_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_FC_RX_ID + CFG_INT_PRI2_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_RX_DESC_OVERFLOW_ID + CFG_INT_PRI2_MASK_OFFSET); prio_mask |= 1 << (MAC_ISR_RX_LOAD_OVERFLOW_ID + CFG_INT_PRI2_MASK_OFFSET); RGF_MAC_WRITE_REG(CFG_INT_PRI2_MASK_ADDR, prio_mask); /* assign priority 3 interrupts, only cpu1 use the interrupt*/ prio_mask = 0; RGF_MAC_WRITE_REG(CFG_INT_PRI3_MASK_ADDR, prio_mask); } void mac_isr_enable(uint8_t id) { uint32_t int_mask; if (id <= MAC_ISR_MAX_ID) { int_mask = 1 << (CFG_INT_ENABLE_MASK_OFFSET + id); if (!(p_mac_isr_ctx->isr_mask & int_mask)) { p_mac_isr_ctx->isr_mask |= int_mask; RGF_MAC_WRITE_REG(CFG_INT_ENA_MASK_ADDR, p_mac_isr_ctx->isr_mask); } } } void mac_isr_disable(uint8_t id) { uint32_t int_mask; if (id <= MAC_ISR_MAX_ID) { int_mask = 1 << (CFG_INT_ENABLE_MASK_OFFSET + id); if (p_mac_isr_ctx->isr_mask & int_mask) { p_mac_isr_ctx->isr_mask &= ~int_mask; RGF_MAC_WRITE_REG(CFG_INT_ENA_MASK_ADDR, p_mac_isr_ctx->isr_mask); } } } void mac_isr_ext1_enable(uint8_t id) { uint32_t int_mask; if (id <= MAC_ISR_EXT1_MAX_ID) { int_mask = RGF_MAC_READ_REG(CFG_MAC_INT_EXT_3_ENA_ADDR); int_mask |= 1 << id; RGF_MAC_WRITE_REG(CFG_MAC_INT_EXT_3_ENA_ADDR, int_mask); } } void mac_isr_ext1_disable(uint8_t id) { uint32_t int_mask; if (id <= MAC_ISR_EXT1_MAX_ID) { int_mask = RGF_MAC_READ_REG(CFG_MAC_INT_EXT_3_ENA_ADDR); int_mask &= ~(1 << id); RGF_MAC_WRITE_REG(CFG_MAC_INT_EXT_3_ENA_ADDR, int_mask); } } void mac_isr_start() { /* enable soc irq */ iot_interrupt_unmask(p_mac_isr_ctx->isr_3_h); iot_interrupt_unmask(p_mac_isr_ctx->isr_2_h); iot_interrupt_unmask(p_mac_isr_ctx->isr_1_h); iot_interrupt_unmask(p_mac_isr_ctx->isr_0_h); } void IRAM_ATTR mac_isr_stop() { /* disable soc irq */ iot_interrupt_mask(p_mac_isr_ctx->isr_0_h); iot_interrupt_mask(p_mac_isr_ctx->isr_1_h); iot_interrupt_mask(p_mac_isr_ctx->isr_2_h); iot_interrupt_mask(p_mac_isr_ctx->isr_3_h); } void mac_isr_init(dsr_notification_func_t callback) { os_mem_set(p_mac_isr_ctx, 0, sizeof(*p_mac_isr_ctx)); p_mac_isr_ctx->dsr_callback = callback; mac_isr_reset(); /* allocate soc irq resource */ p_mac_isr_ctx->isr_0_h = iot_interrupt_create(HAL_VECTOR_MAC_0, HAL_INTR_PRI_7, (iot_addrword_t)NULL, mac_isr_handler); p_mac_isr_ctx->isr_1_h = iot_interrupt_create(HAL_VECTOR_MAC_1, HAL_INTR_PRI_7, (iot_addrword_t)NULL, mac_isr_handler); p_mac_isr_ctx->isr_2_h = iot_interrupt_create(HAL_VECTOR_MAC_2, HAL_INTR_PRI_7, (iot_addrword_t)NULL, mac_isr_handler); p_mac_isr_ctx->isr_3_h = iot_interrupt_create(HAL_VECTOR_MAC_3, HAL_INTR_PRI_7, (iot_addrword_t)NULL, mac_isr_ext1_handler); /* attach soc irq resource */ iot_interrupt_attach(p_mac_isr_ctx->isr_0_h); iot_interrupt_attach(p_mac_isr_ctx->isr_1_h); iot_interrupt_attach(p_mac_isr_ctx->isr_2_h); iot_interrupt_attach(p_mac_isr_ctx->isr_3_h); /* systic mac cb register */ #if HW_PLATFORM >= HW_PLATFORM_FPGA os_task_set_systick_cb(mac_timer_ctxt); #endif /* init rf isr */ mac_rf_isr_init(callback); } void mac_isr_clear(uint32_t isr_evt) { if (isr_evt > MAC_ISR_MAX_ID) { IOT_ASSERT(0); return; } /* clear isr */ RGF_MAC_WRITE_REG(CFG_MAC_INT_CLR_ADDR, 1 << isr_evt); } void IRAM_ATTR mac_check_nncco_fc() { uint32_t bb_fc[4] = {0}; /* if nncco , need fill back desc */ bb_fc[0] = RGF_RAW_READ_REG(CFG_TX_FC_DATA0_ADDR); bb_fc[1] = RGF_RAW_READ_REG(CFG_TX_FC_DATA1_ADDR); bb_fc[2] = RGF_RAW_READ_REG(CFG_TX_FC_DATA2_ADDR); bb_fc[3] = RGF_RAW_READ_REG(CFG_TX_FC_DATA3_ADDR); /* judge delimeter type */ if (FC_DELIM_NNCCO == (bb_fc[0] & 0x3)) { g_phy_ctxt.indep.nn_cco_fc[0] = bb_fc[0]; g_phy_ctxt.indep.nn_cco_fc[1] = bb_fc[1]; g_phy_ctxt.indep.nn_cco_fc[2] = bb_fc[2]; g_phy_ctxt.indep.nn_cco_fc[3] = bb_fc[3]; } } void IRAM_ATTR mac_timer_ctxt() { #if PPM_NTB_CAL mac_ntb_sync_ppm_from_isr(); #endif mac_zc_systic_trig(); /* check fc */ mac_check_nncco_fc(); } #endif /* HW_PLATFORM == HW_PLATFORM_SIMU */