363 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			363 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /****************************************************************************
 | |
| 
 | |
| 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 "os_types.h"
 | |
| 
 | |
| /* plc public api includes */
 | |
| #include "plc_fr.h"
 | |
| #include "plc_const.h"
 | |
| #include "iot_io.h"
 | |
| 
 | |
| /* mac module internal includes */
 | |
| #include "mac.h"
 | |
| #include "mac_dsr.h"
 | |
| #include "mac_isr.h"
 | |
| #include "mac_pdev.h"
 | |
| #include "mac_sched.h"
 | |
| #include "mac_sched_hw.h"
 | |
| #include "mac_txq_hw.h"
 | |
| #include "mac_tx_hw.h"
 | |
| #include "plc_protocol.h"
 | |
| #if HW_PLATFORM == HW_PLATFORM_SIMU
 | |
| #include "simulator_txrx.h"
 | |
| #endif
 | |
| #include "mac_tx_power.h"
 | |
| #include "phy_nf.h"
 | |
| #include "mac_rx_buf_ring.h"
 | |
| #include "mac_cert_test.h"
 | |
| 
 | |
| #if HPLC_RF_DEV_SUPPORT
 | |
| #include "mac_rf_rx_buf_ring.h"
 | |
| #include "mac_rf_hwq_mgr.h"
 | |
| #include "mac_rf_txq_hw.h"
 | |
| #include "mac_rf_isr.h"
 | |
| #include "mac_rf_sched_hw.h"
 | |
| #endif
 | |
| 
 | |
| static void mac_dsr_bc_alert()
 | |
| {
 | |
|     mac_pdev_t *pdev_ptr = g_mac_pdev[PLC_PDEV_ID];
 | |
|     mac_vdev_t *p_vdev = pdev_ptr->vdev[0];
 | |
| #if MAC_SCHED_HW_DEBUG
 | |
|     iot_printf("%s mac_ntb = %d,\n", __FUNCTION__,\
 | |
|         pdev_ptr->mac_isr_rx_fc_ts_ntb);
 | |
| #endif
 | |
|     if (mac_vdev_cfg_get_node_role(p_vdev) == PLC_DEV_ROLE_CCO) {
 | |
|         mac_sched_cco_bc_alert(p_vdev);
 | |
|     }
 | |
|     else {
 | |
|         mac_sched_sta_bc_alert(p_vdev);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void mac_dsr_bc_miss()
 | |
| {
 | |
|     return;
 | |
| }
 | |
| 
 | |
| #if HPLC_RF_DEV_SUPPORT
 | |
| 
 | |
| static void mac_rf_dsr_tx_comp()
 | |
| {
 | |
|     mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, RF_PDEV_ID);
 | |
|     uint32_t tx_comp_status;
 | |
|     uint32_t ret = 0;
 | |
|     /* get txq tx comp status bitmap
 | |
|      * and merge with saved one. Because INT
 | |
|      * may be generated during this dsr being
 | |
|      * handled.
 | |
|      */
 | |
|     tx_comp_status = mac_rf_txq_get_txcomp_status();
 | |
| 
 | |
|     /* call different hwq's tx comp handler */
 | |
|     /* TODO: use pri order */
 | |
|     /* TODO: use quota to make not take too much time */
 | |
|     do {
 | |
|         for (uint32_t i = 0; tx_comp_status && i < MAX_MAC_RF_TXQ_NUM; i++)
 | |
|         {
 | |
|             if ((0x1 << i) & tx_comp_status) {
 | |
|                 /* call hwq i's handler */
 | |
|                 if (rf_pdev->tx_comp) {
 | |
|                     ret = rf_pdev->tx_comp(i);
 | |
|                     if (0 == ret) {
 | |
|                         /* if done, clr pending int status */
 | |
|                         tx_comp_status &= ~(0x1 << i);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         /* to make sure all int handled */
 | |
|         tx_comp_status |= mac_rf_txq_get_txcomp_status();
 | |
|     } while (tx_comp_status);
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /* handle csma tx check */
 | |
| void mac_rf_dsr_csma_tx_check_handle()
 | |
| {
 | |
|     /* just schedule is enable need send interrupt to bbcpu */
 | |
|     if (mac_rf_sched_get_enable(NULL)) {
 | |
|         mac_rf_set_sw_irq_to_bbcpu(RF_MAC_SW_ISR_CSMA_TX_CHECK);
 | |
|     }
 | |
| }
 | |
| 
 | |
| #else /* HPLC_RF_DEV_SUPPORT */
 | |
| 
 | |
| static void mac_rf_dsr_tx_comp()
 | |
| {
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void mac_rf_dsr_csma_tx_check_handle()
 | |
| {
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| void mac_dsr_tx_comp()
 | |
| {
 | |
|     mac_pdev_t *pdev = g_mac_pdev[PLC_PDEV_ID];
 | |
|     uint32_t tx_comp_status;
 | |
|     uint32_t ret = 0;
 | |
|     /* get txq tx comp status bitmap
 | |
|      * and merge with saved one. Because INT
 | |
|      * may be generated during this dsr being
 | |
|      * handled.
 | |
|      */
 | |
|     tx_comp_status = \
 | |
|         mac_txq_get_txcomp_status();
 | |
| 
 | |
|     /* call different hwq's tx comp handler */
 | |
|     /* TODO: use pri order */
 | |
|     /* TODO: use quota to make not take too much time */
 | |
|     do {
 | |
|         for (uint32_t i = 0; tx_comp_status && i < MAX_MAC_TXQ_NUM; i++)
 | |
|         {
 | |
|             if ((0x1 << i) & tx_comp_status) {
 | |
|                 /* call hwq i's handler */
 | |
|                 if (pdev->tx_comp) {
 | |
|                     ret = pdev->tx_comp(i);
 | |
|                     if (0 == ret) {
 | |
|                         /* if done, clr pending int status */
 | |
|                         tx_comp_status &= ~(0x1 << i);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         /* to make sure all int handled */
 | |
|         tx_comp_status |= mac_txq_get_txcomp_status();
 | |
|     } while (tx_comp_status);
 | |
| 
 | |
|     /* rf dsr support */
 | |
|     mac_rf_dsr_tx_comp();
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void mac_dsr_rx()
 | |
| {
 | |
|     mac_pdev_t *pdev = g_mac_pdev[PLC_PDEV_ID];
 | |
|     uint32_t rx_int_status = 0;
 | |
|     uint32_t ret;
 | |
|     uint32_t i, ring_num;
 | |
| 
 | |
|     rx_int_status = rx_ring_get_mpdu_int_status();
 | |
| 
 | |
| #if HPLC_RF_DEV_SUPPORT
 | |
|     mac_rf_pdev_t *rf_pdev = pdev->mac_rf_pdev;
 | |
|     uint32_t rf_rx_int_status;
 | |
|     rf_rx_int_status = rf_rx_ring_get_mpdu_int_status();
 | |
|     ring_num = max(MAX_PLC_RX_RING_NUM, MAX_RF_RX_RING_NUM);
 | |
| #else
 | |
|     ring_num = MAX_PLC_RX_RING_NUM;
 | |
| #endif
 | |
| 
 | |
|     /* call different ring's callback handler */
 | |
|     /* TODO: use pri order */
 | |
|     for (i = 0; i < ring_num; i++)
 | |
|     {
 | |
|         if ((0x1 << i) & rx_int_status) {
 | |
|             if (pdev->rx) {
 | |
|                 ret = pdev->rx(pdev, i, 1000);
 | |
|                 if (ret == ERR_OK) {
 | |
|                     /* clear the RX ring INT if done
 | |
|                      * all the frames
 | |
|                      */
 | |
|                     rx_ring_clr_mpdu_int(i);
 | |
|                     rx_ring_clr_overflow_int(i);
 | |
|                     pdev->ring_hdl.ring[i].overflow = 0;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
| #if HPLC_RF_DEV_SUPPORT
 | |
|         if ((0x01 << i) & rf_rx_int_status) {
 | |
|             if (rf_pdev->rx) {
 | |
|                 ret = rf_pdev->rx(rf_pdev, i, 1000);
 | |
|                 if (ERR_OK == ret) {
 | |
|                     rf_rx_ring_clr_mpdu_int(i);
 | |
|                     rf_rx_ring_clr_overflow_int(i);
 | |
|                     rf_pdev->ring_hdl.ring[i].overflow = 0;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| #endif
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void mac_dsr_isr_sync()
 | |
| {
 | |
|     mac_isr_start();
 | |
|     mac_add_dsr_isr_sync_cnt();
 | |
| }
 | |
| 
 | |
| static void mac_rf_dsr_isr_sync()
 | |
| {
 | |
| #if HPLC_RF_DEV_SUPPORT
 | |
|     mac_rf_dsr_isr_start();
 | |
|     // TODO: increase rf isr sync cnt as needed.
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void mac_dsr_rx_overflow()
 | |
| {
 | |
|     mac_pdev_t *pdev = g_mac_pdev[PLC_PDEV_ID];
 | |
|     uint32_t rx_overflow_status = 0;
 | |
|     uint32_t ret;
 | |
|     rx_overflow_status = rx_ring_get_overflow_status();
 | |
| 
 | |
|     /* call different ring's callback handler */
 | |
|     /* TODO: use pri order */
 | |
|     for (uint32_t i = 0; i < MAX_PLC_RX_RING_NUM; i++)
 | |
|     {
 | |
|         if ((0x1 << i) & rx_overflow_status) {
 | |
|             if (pdev->rx) {
 | |
|                 pdev->ring_hdl.ring[i].overflow = 1;
 | |
|                 ret = pdev->rx(pdev, i, 2000);
 | |
|                 if (ret == ERR_OK) {
 | |
|                     /* clear the RX ring INT if done
 | |
|                     * all the frames
 | |
|                     */
 | |
|                     rx_ring_clr_overflow_int(i);
 | |
|                     rx_ring_clr_mpdu_int(i);
 | |
|                     pdev->ring_hdl.ring[i].overflow = 0;
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 iot_printf( \
 | |
|                     "ring%d enabled,but no rx handler\n", \
 | |
|                     i);
 | |
|                 IOT_ASSERT(0);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| void mac_dsr_init(mac_dsr_table_t *table)
 | |
| {
 | |
|     os_mem_set(table, 0, sizeof(*table));
 | |
| 
 | |
|     table->entry[MAC_DSR_BC_ALERT_ID].dsr = mac_dsr_bc_alert;
 | |
|     table->entry[MAC_DSR_BC_MISS_ID].dsr = mac_dsr_bc_miss;
 | |
|     table->entry[MAC_DSR_MPDU_TX_COMP_ID].dsr = mac_dsr_tx_comp;
 | |
|     table->entry[MAC_DSR_MPDU_RX_ID].dsr = mac_dsr_rx;
 | |
|     table->entry[MAC_DSR_ISR_SYNC_ID].dsr = mac_dsr_isr_sync;
 | |
|     table->entry[MAC_DSR_RX_DESC_OVERFLOW_ID].dsr = \
 | |
|         mac_dsr_rx_overflow;
 | |
|     table->entry[MAC_DSR_OVER_STRESS_ID].dsr = \
 | |
|         mac_over_stress_dsr_handle;
 | |
| #if PM_USE_DSR
 | |
|     table->entry[MAC_DSR_POWER_PM_ID].dsr = mac_pm_dsr_sleep_cfg;
 | |
| #endif
 | |
| #if WAR_TIMEOUT_TX_ABORT
 | |
|     table->entry[MAC_DSR_CHECK_TX_ABORT_ID].dsr = \
 | |
|         mac_handle_timeout_tx_abort;
 | |
| #endif
 | |
| #if DEBUG_INVAILD_ADDR
 | |
|     table->entry[MAC_DSR_INVAILD_ADDR_ID].dsr = \
 | |
|         mac_handle_invaild_addr;
 | |
| #endif
 | |
|     table->entry[MAC_DSR_PHY_TIMER_ID].dsr = \
 | |
|         phy_snr_cal_timer_handler;
 | |
|     table->entry[MAC_RF_DSR_CSMA_TX_CHECK_ID].dsr =
 | |
|         mac_rf_dsr_csma_tx_check_handle;
 | |
|     table->entry[MAC_RF_DSR_ISR_SYNC_ID].dsr = mac_rf_dsr_isr_sync;
 | |
| }
 | |
| 
 | |
| void mac_dsr_set_entry(mac_dsr_table_t *table, uint8_t dsr_id, \
 | |
|     mac_dsr_func_t entry)
 | |
| {
 | |
|     table->entry[dsr_id].dsr = entry;
 | |
| }
 | |
| 
 | |
| void mac_dsr_set(uint32_t dsr)
 | |
| {
 | |
|     if (dsr >= MAC_DSR_MAX_ID) {
 | |
|         IOT_ASSERT(0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     os_set_task_event_with_v(p_mac_glb->task_h, (1 << dsr));
 | |
| }
 | |
| 
 | |
| void IRAM_ATTR mac_dsr_set_from_isr(uint8_t *dsr, uint8_t cnt)
 | |
| {
 | |
|     uint32_t value = 0;
 | |
|     uint8_t i;
 | |
| 
 | |
|     for (i = 0; i < cnt; i++) {
 | |
|         if (dsr[i] < MAC_DSR_MAX_ID) {
 | |
|             value |= 1 << dsr[i];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (value) {
 | |
|         os_set_task_event_with_v_from_isr(p_mac_glb->task_h, value);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void mac_dsr_clear(uint32_t dsr)
 | |
| {
 | |
|     uint32_t dsr_event;
 | |
| 
 | |
|     if (dsr >= MAC_DSR_ISR_SYNC_ID) {
 | |
|         IOT_ASSERT(0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* get pending dsr event */
 | |
|     dsr_event = os_wait_task_event_with_v(0);
 | |
|     if (dsr_event) {
 | |
|         /* clear specific dsr */
 | |
|         dsr_event &= ~(1 << dsr);
 | |
|     }
 | |
|     /* restore pending dsr event even when dsr_event is 0 as we also need
 | |
|      * to restore the task notification status used by mac msg queue.
 | |
|      */
 | |
|     os_set_task_event_with_v(p_mac_glb->task_h, dsr_event);
 | |
| }
 | |
| 
 | |
| void mac_dsr_set_phy_timer()
 | |
| {
 | |
|     /* war for kl1 spike cert test on mengdong */
 | |
|     mac_cert_tt_spike_war_check();
 | |
| 
 | |
|     mac_dsr_set(MAC_DSR_PHY_TIMER_ID);
 | |
| }
 |