Files
kunlun/plc/halmac/hw2/isr/mac_isr.c
2024-09-28 14:24:04 +08:00

507 lines
16 KiB
C

/****************************************************************************
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 "mpdu_header.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_stop()
{
}
void mac_isr_clear(uint32_t isr_evt)
{
(void)isr_evt;
}
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 if (isr_id == MAC_ISR_ZERO_CROSS_ID) {
dsr_id = MAC_DSR_ZERO_CROSS_ID;
} else if (isr_id == MAC_ISR_ZC_UPPER_BOUND_ID) {
dsr_id = MAC_DSR_ZC_UPPER_BOUND_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;
case MAC_ISR_ZERO_CROSS_ID:
dsr_id = MAC_DSR_ZERO_CROSS_ID;
break;
case MAC_ISR_ZC_UPPER_BOUND_ID:
dsr_id = MAC_DSR_ZC_UPPER_BOUND_ID;
break;
default:
break;
}
#endif
return dsr_id;
}
#if (ENABLE_CCA_ISR == 1 || ENA_TX_RAW_INT)
static uint32_t IRAM_ATTR mac_isr_raw_handler(uint32_t vector,
iot_addrword_t data)
{
(void)vector;
(void)data;
#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);
#if ENA_DBG_TX_PPM_PER_PKT
int32_t ppm_step = mac_get_clear_dbg_pkt_ppm_step(fc);
if (ppm_step) {
mac_modify_dbg_pkt_tx_ppm(ppm_step);
}
#endif
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
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<<MAC_INT_PCS_BUSY_TIMEOUT_OFFSET)) {
/*TODO: handle pcs busy interrupte*/
}
if(int_status & (1<<MAC_INT_PCS_IDLE_TIMEOUT_OFFSET)) {
/*TODO: handle pcs idle interrupte*/
}
mac_set_cca_pcs_busy_timeout_ms(1, MAC_PCS_BUSY_TIMEOUT);
mac_set_cca_pcs_idle_timeout_ms(1, MAC_PCS_IDLE_TIMEOUT);
#endif
return 0;
}
#endif
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);
prio_mask |= 1 << (MAC_ISR_ZERO_CROSS_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);
prio_mask |= 1 << (MAC_ISR_ZC_UPPER_BOUND_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_start()
{
/* enable soc irq */
#if (ENABLE_CCA_ISR == 1 || ENA_TX_RAW_INT)
iot_interrupt_unmask(p_mac_isr_ctx->isr_3_h);
#endif
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);
#if (ENABLE_CCA_ISR == 1 || ENA_TX_RAW_INT)
iot_interrupt_mask(p_mac_isr_ctx->isr_3_h);
#endif
}
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 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);
#if (ENABLE_CCA_ISR == 1 || ENA_TX_RAW_INT)
p_mac_isr_ctx->isr_3_h = iot_interrupt_create(HAL_VECTOR_MAC_3,
HAL_INTR_PRI_7, (iot_addrword_t)NULL, mac_isr_raw_handler);
#endif
/* 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);
#if (ENABLE_CCA_ISR == 1 || ENA_TX_RAW_INT)
iot_interrupt_attach(p_mac_isr_ctx->isr_3_h);
#endif
/* systic mac cb register */
#if HW_PLATFORM >= HW_PLATFORM_FPGA
os_task_set_systick_cb(mac_timer_ctxt);
#endif
}
void IRAM_ATTR mac_timer_ctxt()
{
#if PPM_NTB_CAL
mac_ntb_sync_ppm_from_isr();
#endif
mac_zc_systic_trig();
}
#endif /* HW_PLATFORM == HW_PLATFORM_SIMU */