Files
kunlun/plc/halmac/task/mac_dsr.c
2024-09-28 14:24:04 +08:00

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);
}