/**************************************************************************** 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. ****************************************************************************/ #include "chip_reg_base.h" #include "hw_reg_api.h" #include "hw_tonemask.h" #include "tx_mpdu_start.h" #include "tx_mpdu_end.h" #include "tx_pb_start.h" #include "plc_utils.h" #include "mac_reset.h" #include "mac_hwq_reg.h" #include "mac_sys_reg.h" #include "mac_rx_reg.h" #include "mac_tmr_reg.h" #include "ada_reg.h" #include "hw_phy_init.h" #include "phy_ana.h" #include "phy_reg.h" #include "phy_bb.h" #include "mpdu_frame.h" #include "ahb_rf.h" #include "iot_irq.h" //#include "iot_mem.h" #include "mac_tx_main.h" #include "intc_reg.h" #include "apb_glb_reg.h" #include "command_list.h" #include "dbg_io.h" #include "iot_config.h" #include "iot_io.h" #include "plc_protocol.h" #define IPC_CONTROL #ifdef IPC_CONTROL #include "iot_errno.h" #include "iot_mc_ipc.h" #endif extern void tx_common_init(); extern uint32_t mac_tx_mpdu_test(void *pdev, tx_mpdu_start *mpdu); extern void mac_glb_map(uint32_t mac_type, uint32_t pkt_type, uint32_t test_type); extern tx_mpdu_start mpdu_start; extern iot_tx_cfg_info_t glb_cfg; extern iot_mac_intr_info_t mac_info; extern volatile bool_t mac_beacon_alert_flag; extern volatile bool_t mac_tx_complete_flag; extern uint32_t bcn_period_ms; extern uint32_t print_tx_period_ms; extern void phy_sts_get(iot_phy_sts_info_t *pkt_sts); #ifdef IPC_CONTROL #define IPC_MSG_ID_RAWDATA_START_REQ 1 #define REQ_TYPE_NEW 1 typedef struct _ipc_msg_rawdata_start_req { uint8_t req_type; }ipc_msg_rawdata_start_req_t; #define IPC_MSG_ID_RAWDATA_START_CNF 2 #define CNF_STATUS_OK 1 #define CNF_STATUS_FAIL 2 typedef struct _ipc_msg_rawdata_start_cnf { uint8_t status; }ipc_msg_rawdata_cnf_t; ipc_msg_rawdata_start_req_t start_msg; ipc_msg_rawdata_cnf_t cnf_msg; volatile uint32_t rawdata_cnf_received = 0; volatile uint32_t rawdata_start_received = 0; void scpu_recv_ipc_msg(uint32_t msg_id, void* msg_arg); void acpu_recv_ipc_msg(uint32_t msg_id, void* msg_arg); uint32_t iot_rawdata_init_ipc(uint8_t cpuid) { if(cpuid == IOT_SECCPU_ID){ iot_mc_ipc_init(scpu_recv_ipc_msg, IOT_SECCPU_ID, INTC_MODE); }else{ iot_mc_ipc_init(acpu_recv_ipc_msg, IOT_APPCPU_ID, INTC_MODE); } return ERR_OK; } volatile uint32_t rawdata_start_send = 0; uint32_t acpu_start_rawdata(void) { uint32_t j = 0; start_msg.req_type = REQ_TYPE_NEW; while(!rawdata_cnf_received){ if(!rawdata_start_send){ if(iot_mc_ipc_query_mailbox_freecredit() >0){ iot_mc_ipc_send_msg(IPC_MSG_ID_RAWDATA_START_REQ, (void*)&start_msg); rawdata_start_send = 1; } } //iot_printf("rawdata_cnf_received=%d rawdata_start_send=%d\n", rawdata_cnf_received, rawdata_start_send); for(j=0;jstatus); if(pmsg->status == CNF_STATUS_OK){ rawdata_cnf_received = 1; } break; default: iot_printf("unhandled msgid:0x%x\n", msg_id); break; } } void scpu_recv_ipc_msg(uint32_t msg_id, void* msg_arg) { ipc_msg_rawdata_start_req_t* pmsg = NULL; iot_printf("secpu[rec] msg_id:%x arg:%x status:%x\n", msg_id, msg_arg, iot_mc_ipc_get_hw_stauts()); switch(msg_id) { case IPC_MSG_ID_RAWDATA_START_REQ: pmsg = (ipc_msg_rawdata_start_req_t*)msg_arg; iot_printf("IPC_MSG_ID_RAWDATA_START_REQ : %d\n", pmsg->req_type); cnf_msg.status = CNF_STATUS_OK; if(iot_mc_ipc_query_mailbox_freecredit() >0){ iot_mc_ipc_send_msg(IPC_MSG_ID_RAWDATA_START_CNF, (void*)&cnf_msg); rawdata_start_received = 1; } break; default: iot_printf("unhandled msgid:0x%x\n", msg_id); break; } } /* acpu will send ipc request to scpu to start rawmode */ #endif #if 0 #define IPC_MSG_ID_RAWDATA_START_REQ 1 #define REQ_TYPE_NEW 1 typedef struct _ipc_msg_rawdata_start_req { uint8_t req_type; }ipc_msg_rawdata_start_req_t; #define IPC_MSG_ID_RAWDATA_START_CNF 2 #define CNF_STATUS_OK 1 #define CNF_STATUS_FAIL 2 typedef struct _ipc_msg_rawdata_start_cnf { uint8_t status; }ipc_msg_rawdata_cnf_t; ipc_msg_rawdata_start_req_t start_msg; ipc_msg_rawdata_cnf_t cnf_msg; uint32_t rawdata_cnf_received = 0; uint32_t rawdata_start_received = 0; void scpu_recv_ipc_msg(uint32_t msg_id, void* msg_arg); void acpu_recv_ipc_msg(uint32_t msg_id, void* msg_arg); uint32_t iot_rawdata_init_ipc(uint8_t cpuid) { if(cpuid == IOT_SECCPU_ID){ iot_mc_ipc_init(scpu_recv_ipc_msg, IOT_SECCPU_ID, INTC_MODE); }else{ iot_mc_ipc_init(acpu_recv_ipc_msg, IOT_APPCPU_ID, INTC_MODE); } return ERR_OK; } uint32_t acpu_start_rawdata(void) { uint32_t j = 0; start_msg.req_type = REQ_TYPE_NEW; while(!rawdata_cnf_received){ if(iot_mc_ipc_query_mailbox_freecredit() >0){ iot_mc_ipc_send_msg(IPC_MSG_ID_RAWDATA_START_REQ, (void*)&start_msg); } for(j=0;jstatus); if(pmsg->status == CNF_STATUS_OK){ rawdata_cnf_received = 1; } break; default: iot_printf("unhandled msgid:0x%x\n", msg_id); break; } } void scpu_recv_ipc_msg(uint32_t msg_id, void* msg_arg) { ipc_msg_rawdata_start_req_t* pmsg = NULL; iot_printf("secpu[rec] msg_id:%x arg:%x status:%x\n", msg_id, msg_arg, iot_mc_ipc_get_hw_stauts()); switch(msg_id) { case IPC_MSG_ID_RAWDATA_START_REQ: pmsg = (ipc_msg_rawdata_start_req_t*)msg_arg; iot_printf("IPC_MSG_ID_RAWDATA_START_REQ : %d\n", pmsg->req_type); cnf_msg.status = CNF_STATUS_OK; if(iot_mc_ipc_query_mailbox_freecredit() >0){ iot_mc_ipc_send_msg(IPC_MSG_ID_RAWDATA_START_CNF, (void*)&cnf_msg); rawdata_start_received = 1; } break; default: iot_printf("unhandled msgid:0x%x\n", msg_id); break; } } /* acpu will send ipc request to scpu to start rawmode */ #endif uint32_t mac_tx_single_mode() { uint32_t tx_done = 0; uint32_t enq_time = 0, cur_time = 0; int64_t time_span = 0; uint32_t start_time = 0, end_time = 0; iot_phy_sts_info_t total_sts = {0}; start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);/*for cnt*/ /* beacon or sof transmit */ do { enq_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);/*for tx*/ /* send the beacon */ mac_tx_mpdu_test(NULL, &mpdu_start); do { // wait for tx done and hwq disable cur_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); time_span = cur_time - enq_time; if (time_span < 0) { // wrap around time_span = (0x100000000LL) - enq_time + cur_time; } tx_done = mpdu_start.tx_status->tx_done; } while (!tx_done \ || ((uint64_t)time_span < bcn_period_ms * TICKS_MS)); /* tx cnt print */ end_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); time_span = end_time - start_time; if (time_span < 0) { // wrap around time_span = (0x100000000LL) - start_time + end_time; } if((uint64_t)time_span > print_tx_period_ms*TICKS_MS){ phy_sts_get(&total_sts); iot_printf("mac tx ok:%d/4s, fc_ok:%d/4s, fc_err:%d/4s,", \ total_sts.mac_tx_ok_cnt,total_sts.fc_crc_ok_cnt,total_sts.fc_crc_fail_cnt); iot_printf("pld_ok:%d/4s, pld fail:%d/4s, sync ok:%d/4s\r\n", \ total_sts.pld_crc_ok_cnt,total_sts.pld_crc_fail_cnt,total_sts.sync_ok_cnt); start_time = end_time; } } while (true); return 0; } extern tonemap_table_entry spg_tonemap_table[]; extern tonemap_table_entry sg_tonemap_table[]; extern tonemap_table_entry sg_ext_tonemap_table[]; extern tonemap_table_entry gp_tonemap_table[]; uint32_t mac_tx_tmi_scan() { uint32_t tx_done = 0; uint32_t enq_time = 0, cur_time = 0; int64_t time_span = 0; iot_phy_sts_info_t total_sts = {0}; uint32_t tmi_retry_cnt = 0; /* pb num for each tmi */ for(uint32_t j=1; j<5; j++) { for(uint32_t i=0; i sg_tonemap_table[i].max_pb_num){ continue; } /* mask unused TMI in ext table */ if(i >= 15){ if(sg_ext_tonemap_table[i].pb_size == 0 || \ j > sg_ext_tonemap_table[i].max_pb_num){ continue; } } /* not support,delete in the future */ if(i == 16 || i == 17) continue; #if IOT_PLC_PHY_BAND_DFT == IOT_SUPPORT_TONE_100_230 /* total symb num >= 512*/ if((i == 7 && j >= 2) || (i == 8 && j >= 2) || \ (i == 3 && j >= 3) || (i == 9 && j >= 3) || \ (i == 12 && j >= 3) || (i == 0 && j == 4) || \ (i == 10 && j == 4)) continue; #endif } #if SUPPORT_SOUTHERN_POWER_GRID else if(PHY_PROTO_TYPE_GET() == PLC_PROTO_TYPE_SPG) { /* mask some unused TMI */ if(spg_tonemap_table[i].pb_size == 0 || j > spg_tonemap_table[i].max_pb_num) continue; /* TMIExt not done now */ if(i > 10) continue; } #endif else if(PHY_PROTO_TYPE_GET() == PLC_PROTO_TYPE_GP){ /* mask some unused TMI */ if(gp_tonemap_table[i].pb_size == 0 || j > gp_tonemap_table[i].max_pb_num) continue; /* max tmi */ if(i >= GP_TMI_MAX) continue; } glb_cfg.tmi = i; glb_cfg.pb_num = j; tmi_retry_cnt = MAC_TMI_SCAN_CNT; while(tmi_retry_cnt--) { enq_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);/*for tx*/ /* send the beacon */ mac_tx_mpdu_test(NULL, &mpdu_start); do { // wait for tx done and hwq disable cur_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); time_span = cur_time - enq_time; if (time_span < 0) { // wrap around time_span = (0x100000000LL) - enq_time + cur_time; } tx_done = mpdu_start.tx_status->tx_done; } while (!tx_done \ || ((uint64_t)time_span < bcn_period_ms * TICKS_MS)); } phy_sts_get(&total_sts); iot_printf("[TMI-%d][PB-%d]:\r\nmac tx ok:%d/4s, fc_ok:%d/4s, fc_err:%d/4s,", \ glb_cfg.tmi,glb_cfg.pb_num,total_sts.mac_tx_ok_cnt,total_sts.fc_crc_ok_cnt, \ total_sts.fc_crc_fail_cnt); iot_printf("pld_ok:%d/4s, pld fail:%d/4s, sync ok:%d/4s\r\n", \ total_sts.pld_crc_ok_cnt,total_sts.pld_crc_fail_cnt,total_sts.sync_ok_cnt); } } return 0; } uint32_t mac_tx_bcn_alert() { uint32_t tmp1 = 0; /* beacon alert */ do { /* beacon period */ RGF_MAC_WRITE_REG(CFG_BEACON_PERIOD_ADDR, 0xffff0000);//1000ms /* beacon alert ahead */ RGF_MAC_WRITE_REG(CFG_BEACON_ADDR,1); /* scedule */ tmp1 = RGF_HWQ_READ_REG(CFG_SCHEDULE_ADDR); REG_FIELD_SET(CFG_SCH_EN,tmp1,1); REG_FIELD_SET(CFG_SCH_CMD_NUM,tmp1,0); REG_FIELD_SET(CFG_SCH_WR_TRIG,tmp1,1); REG_FIELD_SET(CFG_SCH_SELF_RECUR_EN,tmp1,1); REG_FIELD_SET(SCH_WR_TRIG_ENABLE,tmp1,0); REG_FIELD_SET(SCH_CUR_NUM,tmp1,0); RGF_HWQ_WRITE_REG(CFG_SCHEDULE_ADDR,tmp1); while(!mac_beacon_alert_flag); mac_beacon_alert_flag = false; } while (true); return 0; } uint32_t mac_tx_complete() { int64_t time_span = 0; uint32_t start_time = 0, end_time = 0; iot_phy_sts_info_t total_sts = {0}; uint32_t start1_time = 0, end1_time = 0; /* tx complete */ start1_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);/*for print*/ do { /* send the beacon/sof */ mac_tx_mpdu_test(NULL, &mpdu_start); while(!mac_tx_complete_flag); mac_tx_complete_flag = false; start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);/*for tx*/ do { // wait for tx done and hwq disable end_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); time_span = end_time - start_time; if (time_span < 0) { // wrap around time_span = (0x100000000LL) - start_time + end_time; } } while (0&& (uint64_t)time_span < (bcn_period_ms-5) * TICKS_MS); /* tx cnt print */ end1_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); time_span = end1_time - start1_time; if (time_span < 0) { // wrap around time_span = (0x100000000LL) - start1_time + end1_time; } if((uint64_t)time_span > print_tx_period_ms*TICKS_MS){ phy_sts_get(&total_sts); iot_printf("mac tx ok:%d/4s, fc_ok:%d/4s, fc_err:%d/4s,", \ total_sts.mac_tx_ok_cnt,total_sts.fc_crc_ok_cnt,total_sts.fc_crc_fail_cnt); iot_printf("pld_ok:%d/4s, pld fail:%d/4s, sync ok:%d/4s\r\n", \ total_sts.pld_crc_ok_cnt,total_sts.pld_crc_fail_cnt,total_sts.sync_ok_cnt); start1_time = end1_time; } } while (true); return 0; } uint32_t mac_tx_sched() { uint32_t tmp1 = 0; uint32_t cur_time; hw_sched_cmd_t cmd[HW_SCHED_CMD_MAX_CNT]; /* schedule: beacon ahead alert interrupt */ do { /* send the beacon */ mac_tx_mpdu_test(NULL, &mpdu_start); /* q0 ptr */ RGF_HWQ_WRITE_REG(CFG_Q0_PTR_ADDR,(uint32_t)(&mpdu_start)); /* q0 ena */ RGF_HWQ_WRITE_REG(CFG_Q_ENA_ADDR,0x1); #if MAC_DTEST_PLATFORM == MAC_DTEST_EDA /* beacon period */ RGF_MAC_WRITE_REG(CFG_BEACON_PERIOD_ADDR, 0x320000);//50ms /* beacon alert ahead */ RGF_MAC_WRITE_REG(CFG_BEACON_ADDR,5);//5ms #define END_TIME_UNIT 10 #elif MAC_DTEST_PLATFORM == MAC_DTEST_FPGA /* beacon period */ RGF_MAC_WRITE_REG(CFG_BEACON_PERIOD_ADDR, 0x3E80000);//1s /* beacon alert ahead */ RGF_MAC_WRITE_REG(CFG_BEACON_ADDR,100);//100ms #define END_TIME_UNIT 10 #endif cmd[0].t_info.se.end_t=END_TIME_UNIT;//1ms cmd[0].t_info.se.start_t=0x0; cmd[0].t_info.se.r_flag=0x0; cmd[0].t_info.se.s_flag=0x0; cmd[0].phase=0x1; cmd[0].nb_flag=0x0; cmd[0].idle_bit=0x0; cmd[0].req_int=0x0; cmd[0].rx_rate_mode=RX_MODE_SR; cmd[0].tx_q_en_bm=0x1; for(uint32_t i=1;i HW_PLATFORM_SIMU #if EDA_SIMU_SUPPORT != 1 /* serial init */ dbg_uart_init(); iot_printf("mac_tx_test begin...\n"); #endif #endif /* glb cfg mapping */ glb_cfg.m_type = PHY_PROTO_TYPE_GET(); /* mac tx common init interface */ tx_common_init(); #if defined(MODULE_EN) if(glb_cfg.t_type == MAC_TX_SCHED_BCN_AHEAD_ALERT) iot_printf("[Error]: Must debug mode...\n"); /* send the beacon/sof */ mac_tx_mpdu_test(NULL, &mpdu_start); while(!mac_tx_complete_flag); mac_tx_complete_flag = false; return; #endif #ifdef IPC_CONTROL iot_rawdata_init_ipc(IOT_APPCPU_ID); acpu_start_rawdata(); #endif switch(MAC_TX_TEST_ID) { case MAC_TX_BEACON: case MAC_TX_SOF: mac_tx_single_mode(); break; case MAC_TX_TMI: mac_tx_tmi_scan(); break; case MAC_TX_INTR_BCN_ALT: mac_tx_bcn_alert(); break; case MAC_TX_INTR_MPDU_COMPLETE: mac_tx_complete(); break; case MAC_TX_SCHED_BCN_AHEAD_ALERT: mac_tx_sched(); break; default: while(true); } return; } #if !MODULE_EN int main(void) { mac_tx_start(); return 0; } #endif