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

1013 lines
28 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"
#include "os_mem.h"
#include "os_task.h"
#include "os_event.h"
/* common includes */
#include "iot_module.h"
#include "iot_queue.h"
#include "iot_errno.h"
#include "iot_bitops.h"
#include "iot_io.h"
#include "iot_plc_pm_api.h"
#include "iot_task_api.h"
/* mac module internal includes */
#include "mac.h"
#include "mac_msg.h"
#include "beacon.h"
#include "mac_vdev.h"
#include "mac_pdev.h"
#include "sw_sched.h"
#include "mac_data.h"
#include "mac_rx_hw.h"
#include "mac_cert_test.h"
#include "mac_sched.h"
#include "mac_zc.h"
#include "mac_ppm_scan.h"
#include "mac_reset.h"
#include "mac_pm.h"
#include "mac_channel.h"
#include "mac_check_spur_cco.h"
#include "mac_check_spur_sta.h"
/* public api includes */
#include "plc_fr.h"
#include "mac_pdev.h"
#include "mac_dbg_pkt_mode.h"
#include "mac_hplc_ext.h"
#include "mac_channel_tools.h"
#include "mac_hw_tsfm.h"
#include "mac_rf_cert_test.h"
#include "mac_rf_scan.h"
#if HPLC_RF_DEV_SUPPORT
#include "mac_rf_rx_hw.h"
#include "mac_rf_rx_buf_ring.h"
#endif
/* define the quota of each mac message queue. 0 means disable quota.
* quota rule:
* 1. quota disabled queues first
* 2. then quota available queues
* 3. quota exhausted queues last
*/
static uint8_t g_mac_msg_q_quota[MAC_MSG_QUEUE_MAX_PRIO] =
{
/* MAC_MSG_QUEUE_HP */
0,
/* MAC_MSG_QUEUE_MP */
2,
/* MAC_MSG_QUEUE_LP */
1
};
static void mac_handle_msg_mac(mac_global_t * glb,mac_msg_t * msg)
{
(void)glb;
switch (msg->id) {
case MAC_MSG_ID_MAC_WARM_RESET_WAR:
{
mac_warm_reset_war(msg->data1);
break;
}
case MAC_MSG_ID_MAC_DEBUG_TX_HANG:
{
mac_tx_hang_handle();
break;
}
case MAC_MSG_ID_MAC_ZC_SET_FUNC_CMD:
{
mac_zc_set_func_cmd_internal(msg->data1 & 0xFF,
(msg->data1 >> 8) & 0xFF, msg->data2);
break;
}
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_cvg(mac_global_t *glb, mac_msg_t *msg)
{
uint8_t pdev_id, vdev_id, tmp, sn;
uint8_t stop_band_scan_flag = 0;
(void)glb;
switch (msg->id) {
case MAC_MSG_ID_CVG_START_BC:
{
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
mac_start_beacon_internal(pdev_id, vdev_id);
break;
}
case MAC_MSG_ID_CVG_STOP_BC:
{
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
mac_stop_beacon_internal(pdev_id, vdev_id);
break;
}
case MAC_MSG_ID_CVG_UPDATE_BC:
{
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
msg->data1 = mac_update_beacon_internal(pdev_id, vdev_id, msg->data2,
&tmp);
msg->data2 = (void *)((uint32_t)tmp);
break;
}
case MAC_MSG_ID_CVG_CREATE_VDEV:
{
pdev_id = (uint8_t)(msg->data1 & 0xFF);
vdev_id = msg->data1 & 0xFF;
msg->data1 = mac_create_vdev_internal(pdev_id, &vdev_id, msg->data2);
#if PLC_SUPPORT_DBG_PKT_MODE
/* since the PLC_DEFAULT_VDEV == 0, then it must create cvg call
* vdev first.
*/
//TODO: will fix create dbg pkt vdev in create vdev function
mac_create_dbg_pkt_vdev(pdev_id, msg->data2);
#endif
msg->data2 = (void *)((uint32_t)vdev_id);
break;
}
case MAC_MSG_ID_CVG_START_VDEV:
{
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
msg->data1 = mac_start_vdev_internal(pdev_id, vdev_id, msg->data2);
break;
}
case MAC_MSG_ID_CVG_SET_VDEV_CFG:
{
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
msg->data1 = mac_set_vdev_cfg_internal(pdev_id, vdev_id, msg->data2);
break;
}
case MAC_MSG_ID_CVG_STOP_VDEV:
{
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
msg->data1 = mac_stop_vdev_internal(pdev_id, vdev_id);
break;
}
case MAC_MSG_ID_CVG_MSDU_SEND:
{
iot_pkt_t* msdu_buf;
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
msdu_buf = msg->data2;
mac_tx_info *tx_info = msg->data3;
if (tx_info->is_rf_data) {
msg->data1 = mac_send_rf_msdu_ex_internal(pdev_id, vdev_id,
msdu_buf, msg->data3);
} else {
msg->data1 = mac_send_msdu_ex_internal(pdev_id, vdev_id,
msdu_buf, msg->data3);
}
/* if no memery,then free buf */
if (ERR_OK != msg->data1) {
iot_pkt_free_tx_done(msdu_buf, IOT_PKT_STATE_TX_FAIL);
msg->data2 = NULL;
}
break;
}
case MAC_MSG_ID_CVG_CERT_MODE_SEL:
{
uint8_t mt_mode_sel = msg->data1 & 0xFF;
mac_cert_test_g_set(mt_mode_sel);
stop_band_scan_flag = 1;
break;
}
case MAC_MSG_ID_CVG_CERT_BAND:
{
uint8_t band_id;
band_id = msg->data1 & 0xFF;
mac_cert_test_band_cfg(band_id);
stop_band_scan_flag = 1;
break;
}
case MAC_MSG_ID_CVG_CERT_TONEMASK:
{
uint8_t tonemask_id;
tonemask_id = msg->data1 & 0xFF;
mac_cert_test_tonemast_cfg(tonemask_id);
stop_band_scan_flag = 1;
break;
}
case MAC_MSG_ID_CVG_SET_PDEV_CFG:
{
cfg_data_tlv *tlv = (cfg_data_tlv *)msg->data2;
pdev_id = msg->data1 & 0xFF;
msg->data1 = mac_set_pdev_cfg_internal(pdev_id, msg->data2);
if (tlv->type == PLC_PDEV_CFG_SET_BAND && msg->data1 == ERR_OK) {
stop_band_scan_flag = 1;
}
break;
}
case MAC_MSG_ID_CVG_START_ZC_NTB:
{
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
msg->data1 = mac_start_zc_ntb_collect_internal(pdev_id, vdev_id,
(iot_pkt_t *)msg->data2);
break;
}
case MAC_MSG_ID_CVG_EXT_FRAME_SEND:
{
uint8_t ext_type;
pdev_id = (msg->data1 >> 24) & 0xFF;
sn = (msg->data1 >> 16) & 0xFF;
vdev_id = (msg->data1 >> 8) & 0xff;
ext_type = msg->data1 & 0xFF;
mac_send_ext_frame_internal(ext_type, pdev_id, vdev_id, msg->data2,
msg->data3, sn);
break;
}
case MAC_MSG_ID_CVG_GET_PDEV_CFG:
{
pdev_id = msg->data1 & 0xFF;
msg->data1 = mac_get_pdev_cfg_internal(pdev_id, msg->data2);
break;
}
case MAC_MSG_ID_CVG_HW_TSFM_SEND:
{
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
msg->data1 = mac_hw_tsfm_send_internal(pdev_id, vdev_id, msg->data2);
break;
}
case MAC_MSG_ID_CVG_CERT_HPLC2RF:
{
uint8_t phr_mcs = (msg->data1 >> 16) & 0xFF;
uint8_t pld_mcs = (msg->data1 >> 8) & 0xFF ;
uint8_t pb_idx = msg->data1 & 0xFF;
mac_rf_cert_test_set_phy_hplc2rf_lp(phr_mcs, pld_mcs, pb_idx);
stop_band_scan_flag = 1;
break;
}
case MAC_MSG_ID_CVG_CERT_SEC_MODE:
{
mac_cert_test_sec_mode_set((uint8_t)msg->data1);
stop_band_scan_flag = 1;
break;
}
case MAC_MSG_ID_CVG_CERT_RF_CFG:
{
uint8_t rf_option, rf_channel;
rf_channel = msg->data1 & 0xFF;
rf_option = (msg->data1 >> 8) & 0xFF;
mac_rf_cert_test_option_channel_cfg(rf_option, rf_channel);
stop_band_scan_flag = 1;
break;
}
case MAC_MSG_ID_CVG_GET_VDEV_CFG:
{
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
msg->data1 = mac_get_vdev_cfg_internal(pdev_id, vdev_id, msg->data2);
break;
}
default:
IOT_ASSERT(0);
break;
}
mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID);
/* NOTE: if need stop band scan after some msg from cvg */
if (stop_band_scan_flag == 1 &&
!mac_scan_get_band_selected(&pdev->scan)) {
#if STATIC_POWER_SAVE
/* stop power save */
mac_pm_stop(pdev);
#endif
/* stop the scan to sync the bcn */
mac_scan_stop(&pdev->scan);
mac_scan_set_band_selected(&pdev->scan, true);
/* stop rf scan timer */
mac_rf_scan_stop();
/* set channel selected */
mac_rf_scan_set_channel_selected(1);
}
}
static void mac_handle_msg_dsr(mac_global_t *glb, mac_msg_t *msg)
{
(void)glb;
switch (msg->id) {
case MAC_MSG_ID_DSR_RX_TO_MSG:
{
void *pdev = msg->data2;
uint32_t ring_id = msg->data1 & 0xFFFF;
#if HPLC_RF_DEV_SUPPORT
if (msg->data1 & (1 << 16)) {
/* rf ring */
msg->data1 = mac_rf_rx_hw_mpdu_internal(pdev, ring_id,
(uint32_t)msg->data3);
rx_buf_ring_t *rf_ring; //TODO: fix to rf rx ring context
#if HW_PLATFORM == HW_PLATFORM_SIMU
rf_ring = &((mac_rf_pdev_t*)pdev)->simu.rx_ring[ring_id];
#else
rf_ring = &((mac_rf_pdev_t*)pdev)->ring_hdl.ring[ring_id];
#endif
if (ERR_OK == msg->data1) {
/* TODO: this is assume in the same task of MAC */
rf_ring->msg_delivered = 0;
}
} else
#endif /* HPLC_RF_DEV_SUPPORT */
{
/* plc ring */
msg->data1 = mac_rx_hw_mpdu_internal(pdev, ring_id,
(uint32_t)msg->data3);
rx_buf_ring_t *plc_ring;
#if HW_PLATFORM == HW_PLATFORM_SIMU
plc_ring = &((mac_pdev_t*)pdev)->simu.rx_ring[ring_id];
#else
plc_ring = &((mac_pdev_t*)pdev)->ring_hdl.ring[ring_id];
#endif
if (ERR_OK == msg->data1) {
/* TODO: this is assume in the same task of MAC */
plc_ring->msg_delivered = 0;
}
}
break;
}
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_timer(mac_global_t *glb, mac_msg_t *msg)
{
(void)glb;
mac_vdev_t *vdev;
uint8_t pdev_id, vdev_id;
switch (msg->id) {
case MAC_MSG_ID_SCHED_TX:
{
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
vdev = get_vdev_ptr(pdev_id, vdev_id);
if (vdev)
mac_sched_nn_tx(vdev);
break;
}
case MAC_MSG_ID_ZC_TRAIN_HW_TIMER:
{
mac_zc_train_hw_timeout_internal(msg->data1, msg->data2);
break;
}
#if !PM_USE_DSR
case MAC_MSG_ID_SYSTEM_SLEEP:
{
sleep_cfg_internal(msg->data2);
break;
}
#endif
#if K48_STA_MULTI_CHANNEL_SELECT_ENABLE
case MAC_MSG_ID_CHANNEL_SCAN_TIMER:
{
iot_mac_k48sta_switch_next_channel(msg->data2);
break;
}
#endif
case MAC_MSG_ID_CCO_CHECK_SPUR_TIMER:
{
/* msg->data2 point to pdev */
mac_cco_check_spur_start(msg->data2);
break;
}
case MAC_MSG_ID_STA_CHECK_SPUR_TIMER:
{
mac_sta_check_spur(msg->data2);
break;
}
case MAC_MSG_ID_STA_PERIOD_CHECK_SPUR:
{
mac_sta_period_check_spur();
break;
}
case MAC_MSG_ID_DEL_STREAM_TIMER:
{
mac_vdev_del_timeout_stream_internal(msg->data2, msg->data1);
break;
}
case MAC_MSG_ID_RF_SCAN_TIMER:
{
mac_rf_scan_next_target(msg->data2);
break;
}
case MAC_MSG_ID_PPM_RECORD_TIMER:
{
mac_ppm_record_refresh_handle(msg->data2);
break;
}
case MAC_MSG_ID_MAC_CERT_WAR_TIMER:
{
mac_cert_war_trans_handle();
break;
}
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_sch(mac_global_t *glb, mac_msg_t *msg)
{
(void)glb;
uint8_t pdev_id, vdev_id;
switch (msg->id) {
case MAC_MSG_ID_SCH_TX:
/* call frame selection handler */
/* TODO: place call here ... */
pdev_id = (msg->data1 >> 8) & 0xFF;
vdev_id = msg->data1 & 0xFF;
mac_swsch_post_msdu(pdev_id,vdev_id);
break;
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_pm(mac_global_t *glb, mac_msg_t *msg)
{
(void)glb;
uint8_t pdev_id, vdev_id;
switch (msg->id) {
case MAC_MSG_ID_PM_OFF:
{
if (msg->data1 == IOT_PLC_PM_MSG_POWER_COLLAPSED) {
for(pdev_id = 0; pdev_id < MAX_PDEV_NUM; pdev_id++) {
for(vdev_id = 0; vdev_id < MAX_VDEV_NUM; vdev_id++) {
mac_pdev_t *pdev = get_pdev_ptr(pdev_id);
if(pdev->vdev[vdev_id]) {
mac_pm_rx_power_off_internal(pdev_id, vdev_id);
}
}
}
} else if (msg->data1 == IOT_PLC_PM_MSG_POWER_RECOVERED) {
for (pdev_id = 0; pdev_id < MAX_PDEV_NUM; pdev_id++) {
for (vdev_id = 0; vdev_id < MAX_VDEV_NUM; vdev_id++) {
mac_pdev_t *pdev = get_pdev_ptr(pdev_id);
if (pdev->vdev[vdev_id]) {
mac_pm_power_recover_internal(pdev_id, vdev_id);
}
}
}
}
break;
}
case MAC_MSG_ID_PWR_CHANGE:
{
low_pwr_for_powroff_cfg_internal(msg->data1, msg->data2);
break;
}
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_phy(mac_global_t *glb, mac_msg_t *msg)
{
(void)glb;
switch (msg->id) {
#if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_STA)
case MAC_MSG_ID_CHANNEL_TEST_STOP:
mac_channel_test_end_internal();
break;
#endif
case MAC_MSG_ID_CHANNEL_ESTIMATED:
mac_check_spur_cert(msg->data1);
break;
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_cli(mac_global_t *glb, mac_msg_t *msg)
{
(void)glb;
switch (msg->id) {
#if (IOT_STA_CONTROL_MODE == IOT_STA_CONTROL_TYPE_STA)
case MAC_MSG_ID_CHANNEL_DUMP_TEST:
mac_channel_dump_start_internal(msg->data2);
break;
#endif
default:
IOT_ASSERT(0);
break;
}
}
/* mac msg handling function */
static inline void mac_handle_msg(mac_global_t *glb, mac_msg_t *msg)
{
switch (msg->type) {
case MAC_MSG_TYPE_CVG:
mac_handle_msg_cvg(glb, msg);
break;
case MAC_MSG_TYPE_DSR:
mac_handle_msg_dsr(glb, msg);
break;
case MAC_MSG_TYPE_TIMER:
mac_handle_msg_timer(glb, msg);
break;
case MAC_MSG_TYPE_SCH:
mac_handle_msg_sch(glb, msg);
break;
case MAC_MSG_TYPE_MAC:
mac_handle_msg_mac(glb, msg);
break;
case MAC_MSG_TYPE_PM:
mac_handle_msg_pm(glb, msg);
break;
case MAC_MSG_TYPE_PHY:
mac_handle_msg_phy(glb, msg);
break;
case MAC_MSG_TYPE_CLI:
mac_handle_msg_cli(glb, msg);
break;
default:
IOT_ASSERT(0);
break;
}
if (msg->sync) {
/* notify message sender that message handling is done. */
mac_msg_sync_t *msg_sync = (mac_msg_sync_t *)msg;
os_set_event(msg_sync->event);
} else {
/* free non-sync message. for sync message, message sender will
* free it.
*/
mac_free_msg(msg);
}
}
static void mac_handle_msg_cvg_cancel(mac_global_t *glb, mac_msg_t *msg)
{
iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
switch (msg->id) {
case MAC_MSG_ID_CVG_START_BC:
case MAC_MSG_ID_CVG_STOP_BC:
case MAC_MSG_ID_CVG_UPDATE_BC:
case MAC_MSG_ID_CVG_CREATE_VDEV:
case MAC_MSG_ID_CVG_START_VDEV:
case MAC_MSG_ID_CVG_SET_VDEV_CFG:
case MAC_MSG_ID_CVG_STOP_VDEV:
case MAC_MSG_ID_CVG_MSDU_SEND:
case MAC_MSG_ID_CVG_CERT_MODE_SEL:
case MAC_MSG_ID_CVG_CERT_BAND:
case MAC_MSG_ID_CVG_CERT_TONEMASK:
case MAC_MSG_ID_CVG_SET_PDEV_CFG:
case MAC_MSG_ID_CVG_START_ZC_NTB:
case MAC_MSG_ID_CVG_EXT_FRAME_SEND:
case MAC_MSG_ID_CVG_GET_PDEV_CFG:
case MAC_MSG_ID_CVG_HW_TSFM_SEND:
case MAC_MSG_ID_CVG_CERT_HPLC2RF:
case MAC_MSG_ID_CVG_CERT_SEC_MODE:
case MAC_MSG_ID_CVG_CERT_RF_CFG:
case MAC_MSG_ID_CVG_GET_VDEV_CFG:
{
break;
}
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_mac_cancel(mac_global_t *glb, mac_msg_t *msg)
{
iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
switch (msg->id) {
case MAC_MSG_ID_MAC_WARM_RESET_WAR:
case MAC_MSG_ID_MAC_DEBUG_TX_HANG:
case MAC_MSG_ID_MAC_ZC_SET_FUNC_CMD:
break;
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_dsr_cancel(mac_global_t *glb, mac_msg_t *msg)
{
iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
switch (msg->id) {
case MAC_MSG_ID_DSR_RX_TO_MSG:
break;
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_timer_cancel(mac_global_t *glb,
mac_msg_t *msg)
{
iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
switch (msg->id) {
case MAC_MSG_ID_SCHED_TX:
break;
#if !PM_USE_DSR
case MAC_MSG_ID_SYSTEM_SLEEP:
break;
#endif
case MAC_MSG_ID_ZC_TRAIN_HW_TIMER:
break;
#if K48_STA_MULTI_CHANNEL_SELECT_ENABLE
case MAC_MSG_ID_CHANNEL_SCAN_TIMER:
break;
#endif
case MAC_MSG_ID_CCO_CHECK_SPUR_TIMER:
break;
case MAC_MSG_ID_STA_CHECK_SPUR_TIMER:
break;
case MAC_MSG_ID_STA_PERIOD_CHECK_SPUR:
break;
case MAC_MSG_ID_DEL_STREAM_TIMER:
break;
case MAC_MSG_ID_RF_SCAN_TIMER:
break;
case MAC_MSG_ID_PPM_RECORD_TIMER:
break;
case MAC_MSG_ID_MAC_CERT_WAR_TIMER:
break;
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_sch_cancel(mac_global_t *glb,
mac_msg_t *msg)
{
iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
switch (msg->id) {
case MAC_MSG_ID_SCH_TX:
break;
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_pm_cancel(mac_global_t *glb, mac_msg_t *msg)
{
iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
switch (msg->id) {
case MAC_MSG_ID_PM_OFF:
case MAC_MSG_ID_PWR_CHANGE:
break;
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_phy_cancel(mac_global_t *glb, mac_msg_t *msg)
{
iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
switch (msg->id) {
case MAC_MSG_ID_CHANNEL_TEST_STOP:
break;
case MAC_MSG_ID_CHANNEL_ESTIMATED:
break;
default:
IOT_ASSERT(0);
break;
}
}
static void mac_handle_msg_cli_cancel(mac_global_t *glb, mac_msg_t *msg)
{
iot_printf("%s glb %p msg %lu\n", __FUNCTION__, glb, msg->id);
switch (msg->id) {
case MAC_MSG_ID_CHANNEL_DUMP_TEST:
break;
default:
IOT_ASSERT(0);
break;
}
}
/* handle msg canceled case. message can be canceled due to various reasons.
* each message may have different cancelation operation required.
*/
void mac_handle_msg_cancel(mac_global_t *glb, mac_msg_t *msg)
{
switch (msg->type) {
case MAC_MSG_TYPE_CVG:
mac_handle_msg_cvg_cancel(glb, msg);
break;
case MAC_MSG_TYPE_MAC:
mac_handle_msg_mac_cancel(glb, msg);
break;
case MAC_MSG_TYPE_DSR:
mac_handle_msg_dsr_cancel(glb, msg);
break;
case MAC_MSG_TYPE_TIMER:
mac_handle_msg_timer_cancel(glb, msg);
break;
case MAC_MSG_TYPE_SCH:
mac_handle_msg_sch_cancel(glb, msg);
break;
case MAC_MSG_TYPE_PM:
mac_handle_msg_pm_cancel(glb, msg);
break;
case MAC_MSG_TYPE_PHY:
mac_handle_msg_phy_cancel(glb, msg);
break;
case MAC_MSG_TYPE_CLI:
mac_handle_msg_cli_cancel(glb, msg);
break;
default:
IOT_ASSERT(0);
break;
}
mac_free_msg(msg);
}
extern uint8_t mac_log_print_en;
extern void mac_tx_csma_dump();
static void mac_main_task(void* arg)
{
uint8_t i, j, tmp;
uint32_t dsr_event;
mac_global_t *glb = arg;
iot_msg_entry_t *entry;
mac_msg_t *msg;
mac_dsr_func_t dsr;
mac_msg_queue_t *pq;
uint8_t quota_disbled_q_cnt = 0;
uint8_t quota_enabled_q_cnt = 0;
uint8_t quota_exhausted_q_cnt = 0;
mac_msg_queue_t *quota_disbled_q[MAC_MSG_QUEUE_MAX_PRIO];
mac_msg_queue_t *quota_enabled_q[MAC_MSG_QUEUE_MAX_PRIO];
mac_msg_queue_t *quota_exhausted_q[MAC_MSG_QUEUE_MAX_PRIO];
iot_printf("%s glb %p\n", __FUNCTION__, glb);
/* check if quota enabled and disabled queue exist */
for (i = 0; i < MAC_MSG_QUEUE_MAX_PRIO; i++) {
pq = &glb->msg_q[i];
if (pq->quota_en) {
quota_enabled_q[quota_enabled_q_cnt] = pq;
quota_enabled_q_cnt++;
} else {
quota_disbled_q[quota_disbled_q_cnt] = pq;
quota_disbled_q_cnt++;
}
}
for (;;) {
/* waiting for messages from various modules and dsr events from isr.
* always handle dsr event firstly.
*/
dsr_event = os_wait_task_event_with_v(MAX_TIME);
handle_dsr:
i = 0;
while (dsr_event) {
tmp = dsr_event & 0xFF;
while (tmp) {
j = iot_bitops_fls(tmp) - 1;
tmp &= ~(0x1 << j);
dsr = glb->dsr_table.entry[i + j].dsr;
if (dsr) {
dsr();
}
}
dsr_event >>= 8;
i += 8;
}
handle_msg:
/* check quota disabled queue */
if (quota_disbled_q_cnt) {
/* check message queues based on priority */
for (i = 0; i < quota_disbled_q_cnt; i++) {
pq = quota_disbled_q[i];
entry = iot_msg_queue_get(&pq->q);
if (entry) {
/* get message and handle it */
msg = container_of(entry, mac_msg_t, link);
mac_handle_msg(glb, msg);
/* check if any dsr event pending */
dsr_event = os_wait_task_event_with_v(0);
if (dsr_event)
goto handle_dsr;
/* always search from highest priority queue with quota
* disabled.
*/
goto handle_msg;
}
}
}
/* check quota enabled queue */
if (quota_enabled_q_cnt) {
quota_exhausted_q_cnt = 0;
/* check message queues based on priority */
for (i = 0; i < quota_enabled_q_cnt; i++) {
pq = quota_enabled_q[i];
/* check if quota available for this queue */
if (pq->curr_quota == 0) {
quota_exhausted_q[quota_exhausted_q_cnt] = pq;
quota_exhausted_q_cnt++;
continue;
}
entry = iot_msg_queue_get(&pq->q);
if (entry) {
/* get message and handle it */
msg = container_of(entry, mac_msg_t, link);
mac_handle_msg(glb, msg);
pq->curr_quota--;
/* check if any dsr event pending */
dsr_event = os_wait_task_event_with_v(0);
if (dsr_event)
goto handle_dsr;
/* always search from highest priority queue with quota
* disabled.
*/
goto handle_msg;
}
}
if (quota_exhausted_q_cnt == quota_enabled_q_cnt) {
/* no quota available queue exist, re-assign quota */
for (i = 0; i < quota_enabled_q_cnt; i++) {
pq = quota_enabled_q[i];
pq->curr_quota = pq->quota;
}
/* always search from highest priority queue with quota
* disabled.
*/
goto handle_msg;
} else {
/* check if any quota exhausted queue exist */
for (i = 0; i < quota_exhausted_q_cnt; i++) {
pq = quota_exhausted_q[i];
entry = iot_msg_queue_get(&pq->q);
if (entry) {
/* get message and handle it */
msg = container_of(entry, mac_msg_t, link);
mac_handle_msg(glb, msg);
/* check if any dsr event pending */
dsr_event = os_wait_task_event_with_v(0);
if (dsr_event)
goto handle_dsr;
/* always search from highest priority queue with
* quota disabled.
*/
goto handle_msg;
}
}
}
}
if (mac_log_print_en) {
mac_tx_csma_dump();
mac_log_print_en = 0;
}
}
}
uint32_t mac_start_task(mac_global_t *glb)
{
uint8_t i;
uint32_t ret = 0;
os_task_h handle;
/* initialize mac message queue */
for (i = 0; i < MAC_MSG_QUEUE_MAX_PRIO; i++) {
ret = iot_msg_queue_init(&glb->msg_q[i].q);
if (g_mac_msg_q_quota[i]) {
/* enable quota for this queue */
glb->msg_q[i].quota_en = 1;
glb->msg_q[i].quota = g_mac_msg_q_quota[i];
glb->msg_q[i].curr_quota = glb->msg_q[i].quota;
} else {
/* disable quota for this queue */
glb->msg_q[i].quota_en = 0;
glb->msg_q[i].quota = 0;
glb->msg_q[i].curr_quota = 0;
}
if (ret) {
for (; i > 0; i--) {
iot_msg_queue_deinit(&glb->msg_q[i - 1].q);
}
goto out;
}
}
/* start mac main task */
handle = os_create_task_ext(mac_main_task, glb, PLC_MAC_TASK_PRIO,
PLC_MAC_STACK_SIZE, __FUNCTION__);
iot_printf("%s glb %p\n", __FUNCTION__, glb);
if (handle == NULL) {
ret = ERR_NOMEM;
goto err_task;
} else {
glb->task_h = handle;
}
goto out;
err_task:
for (i = 0; i < MAC_MSG_QUEUE_MAX_PRIO; i++)
iot_msg_queue_deinit(&glb->msg_q[i].q);
out:
return ret;
}
void mac_stop_task(mac_global_t *glb)
{
iot_msg_entry_t *entry;
mac_msg_t *msg;
iot_msg_queue_t *pq;
uint8_t i;
if (glb->task_h) {
/* delete mac main task */
os_delete_task(glb->task_h);
glb->task_h = NULL;
for (i = 0; i < MAC_MSG_QUEUE_MAX_PRIO; i++) {
pq = &glb->msg_q[i].q;
entry = iot_msg_queue_get(pq);
while (entry) {
/* get messages */
msg = container_of(entry, mac_msg_t, link);
mac_handle_msg_cancel(glb, msg);
entry = iot_msg_queue_get(pq);
}
/* deinit the mac message queue */
iot_msg_queue_deinit(pq);
}
}
iot_printf("%s glb %p\n", __FUNCTION__, glb);
}
void mac_boost_task_prio()
{
os_set_task_prio_ext(p_mac_glb->task_h, PLC_TASK_HIGHEST_PRIO);
}
void mac_restore_task_prio()
{
os_set_task_prio_ext(p_mac_glb->task_h, PLC_MAC_TASK_PRIO);
}