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