Files
kunlun/bb_cpu/fsm/bb_cpu_fsm.c

3093 lines
106 KiB
C
Raw Normal View History

2024-09-28 14:24:04 +08:00
/****************************************************************************
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 "iot_config.h"
#include "os_types.h"
#include "iot_bitops.h"
#include "bb_cpu_utils.h"
#include "bb_cpu_fsm.h"
#include "bb_cpu_config.h"
#include "bb_init.h"
#include "bb_rf_cfg.h"
#include "bb_cpu_mac_isr.h"
#include "bb_cpu_mac_init.h"
#include "bb_rf_cfg.h"
#include "bb_rf_hw_tbl.h"
#include "mac_sched_hw.h"
#include "plc_mpdu_header.h"
#include "mpdu_frame.h"
#include "phy_rf_chn.h"
#include "rf_tx_mpdu_desc.h"
#include "rf_rx_mpdu_desc.h"
#include "mac_cmn_hw.h"
#include "rfplc_reg_base.h"
#include "plc_const.h"
#include "rf_spi_api.h"
#include "iot_clock.h"
#include "bb_cpu_timer.h"
#include "gp_timer.h"
#include "mac_rf_hwq_mgr.h"
#include "mac_rf_txq_hw.h"
#include "bb_cpu_hw_ring.h"
#include "rf_mac_int.h"
#include "mac_rf_common_hw.h"
#include "plc_mac_cfg.h"
#include "bb_cpu_utils.h"
#include "hw_war.h"
#include "mac_reset.h"
#include "plc_protocol.h"
#include "plc_beacon.h"
void bb_cpu_rx_sm(uint32_t event_id);
void bb_cpu_global_sm(uint32_t event_id);
#if ENA_RF_MULTI_CSMA_HWQ_WAR
/* NOTE: currently csma txq just support 4 hwq */
rf_tx_mpdu_start simu_mpdu_tbl[MAX_ENABLE_CSMA_HWQ] = { 0 };
#endif
typedef struct _bb_cpu_fsm {
/* bb cpu event signal */
uint32_t bb_cpu_event;
/* bb cpu global finite state machine */
uint32_t bb_cpu_glb_fsm;
/* bb cpu tx finite state machine */
uint32_t bb_cpu_tx_fsm;
/* bb cpu rx finite state machine */
uint32_t bb_cpu_rx_fsm;
/* bb cpu reset finite state machine */
uint32_t bb_cpu_rst_fsm;
/* bb cpu record previous fsm */
uint32_t bb_cpu_prev_glb_fsm;
/* bb cpu record more previous fsm */
uint32_t bb_cpu_more_prev_glb_fsm;
/* record tx dtei, used by rx sack */
uint16_t wait_sack_tei;
/* the flag to indecate reset reason.
* 0: invaild reason. 1: stop schedule. 2: rx abort.
*/
uint8_t rst_reason;
/* bb cpu record hwqid */
uint8_t bb_cpu_hwqid;
/* bb cpu record event signal */
uint32_t bb_cpu_evt_tmp;
/* point to current tx mpdu desc */
uint32_t bb_cpu_tx_mpdu_t;
/* indicate bb cpu isr is vaild */
uint8_t bb_cpu_isr_vaild;
/* record bb cpu option */
uint8_t bb_cpu_option;
/* record bbcpu tobe set channel id */
uint8_t bb_cpu_channel_id;
/* record bb cpu vcs timer working */
uint8_t bb_cpu_vcs_working;
/* record bbcpu tobe set channel frequecy unit hz */
uint32_t bb_cpu_channel_freq;
/* record bb cpu rx buf */
uint8_t *bb_cpu_rx_buf;
/* record bb cpu vcs timer start local ntb */
uint32_t bb_cpu_vcs_ntb;
/* record bb cpu vcs timer length, unit us */
uint32_t bb_cpu_vcs_len;
/* record bb cpu enter rx flag */
uint8_t bb_cpu_rx_flag;
/* record current wphy tx power, unit: dBm */
int8_t bb_cpu_tx_pwr;
/* record bb cpu set tx cfg step1 */
uint8_t bb_cpu_txcfg1_vld;
/* record bb cpu set proto */
uint8_t bb_cpu_proto;
} bb_cpu_fsm_t;
bb_cpu_fsm_t glb_fsm_ctxt = { 0 };
/* get parameter */
#define BB_CPU_GET(_STR, _ITEM) _STR._ITEM
/* set parameter */
#define BB_CPU_SET(_STR, _ITEM, VALUE) (_STR._ITEM = VALUE)
/* bb cpu get globle fsm */
#define BB_CPU_GET_GLB_FSM() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_glb_fsm)
/* bb cpu get the previous glb state */
#define BB_CPU_GET_PREV_STATE() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_prev_glb_fsm)
/* bb cpu get the previous glb state */
#define BB_CPU_GET_MORE_PREV_STATE() \
BB_CPU_GET(glb_fsm_ctxt, bb_cpu_more_prev_glb_fsm)
/* bb cpu set globle fsm */
#define BB_CPU_SET_GLB_FSM(X) \
do { \
BB_CPU_SET(glb_fsm_ctxt, bb_cpu_more_prev_glb_fsm, \
(BB_CPU_GET_PREV_STATE())); \
BB_CPU_SET(glb_fsm_ctxt, bb_cpu_prev_glb_fsm, (BB_CPU_GET_GLB_FSM())); \
BB_CPU_SET(glb_fsm_ctxt, bb_cpu_glb_fsm, X); \
} while (0);
/* bb cpu get tx fsm */
#define BB_CPU_GET_TX_FSM() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_tx_fsm)
/* bb cpu set tx fsm */
#define BB_CPU_SET_TX_FSM(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_tx_fsm, X)
/* bb cpu get rx fsm */
#define BB_CPU_GET_RX_FSM() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_rx_fsm)
/* bb cpu set rx fsm */
#define BB_CPU_SET_RX_FSM(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_rx_fsm, X)
/* bb cpu get reset fsm */
#define BB_CPU_GET_RST_FSM() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_rst_fsm)
/* bb cpu set reset fsm */
#define BB_CPU_SET_RST_FSM(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_rst_fsm, X)
/* bb cpu get tx dtei, used by rx sack */
#define BB_CPU_GET_TXDTEI() BB_CPU_GET(glb_fsm_ctxt, wait_sack_tei)
/* bb cpu set need tx sack, used by rx sack */
#define BB_CPU_SET_TXDTEI(X) BB_CPU_SET(glb_fsm_ctxt, wait_sack_tei, X)
/* bb cpu get reset reason */
#define BB_CPU_GET_RST_RS() BB_CPU_GET(glb_fsm_ctxt, rst_reason)
/* bb cpu set reset reason */
#define BB_CPU_SET_RST_RS(X) BB_CPU_SET(glb_fsm_ctxt, rst_reason, X)
/* bb cpu get tx mpdu */
#define BB_CPU_GET_TX_MPDU() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_tx_mpdu_t)
/* bb cpu set tx mpdu */
#define BB_CPU_SET_TX_MPDU(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_tx_mpdu_t, X)
/* bb cpu get hwqid */
#define BB_CPU_GET_HWQID() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_hwqid)
/* bb cpu set hwqid */
#define BB_CPU_SET_HWQID(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_hwqid, X)
/* bb cpu get isr vaild */
#define BB_CPU_GET_ISR_VAILD() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_isr_vaild)
/* bb cpu set isr vaild */
#define BB_CPU_SET_ISR_VAILD(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_isr_vaild, X)
/* bb cpu get tobe channel frequecy */
#define BB_CPU_GET_CHANNEL_FREQ() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_channel_freq)
/* bb cpu get tobe channel id */
#define BB_CPU_GET_CHANNEL_ID() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_channel_id)
/* bb cpu set tobe channel frequecy */
#define BB_CPU_SET_CHANNEL(id, freq) \
do { \
BB_CPU_SET(glb_fsm_ctxt, bb_cpu_channel_id, id); \
BB_CPU_SET(glb_fsm_ctxt, bb_cpu_channel_freq, freq); \
} while (0);
/* bb cpu get option */
#define BB_CPU_GET_OPTION() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_option)
/* bb cpu set option */
#define BB_CPU_SET_OPTION(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_option, X)
/* bb cpu get rx buf */
#define BB_CPU_GET_RX_BUF() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_rx_buf)
/* bb cpu set rx buf */
#define BB_CPU_SET_RX_BUF(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_rx_buf, X)
/* bb cpu get VCS timer working */
#define BB_CPU_GET_VCS_WORKING() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_vcs_working)
/* bb cpu set vCS timer working */
#define BB_CPU_SET_VCS_WORKING(X) \
BB_CPU_SET(glb_fsm_ctxt, bb_cpu_vcs_working, X)
/* bb cpu get VCS timer start ntb */
#define BB_CPU_GET_VCS_NTB() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_vcs_ntb)
/* bb cpu set vCS timer start ntb */
#define BB_CPU_SET_VCS_NTB(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_vcs_ntb, X)
/* bb cpu get VCS timer length */
#define BB_CPU_GET_VCS_LEN() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_vcs_len)
/* bb cpu set vCS timer length */
#define BB_CPU_SET_VCS_LEN(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_vcs_len, X)
/* bb cpu get rx flag */
#define BB_CPU_GET_RX_FLAG() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_rx_flag)
/* bb cpu set rx flag */
#define BB_CPU_SET_RX_FLAG(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_rx_flag, X)
/* bb cpu get current wphy tx power */
#define BB_CPU_GET_CUR_TX_PWR() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_tx_pwr)
/* bb cpu set current wphy tx power */
#define BB_CPU_SET_CUR_TX_PWR(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_tx_pwr, (X))
/* bb cpu get txcfg step1 vaild or not */
#define BB_CPU_GET_TXCFG1_VLD() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_txcfg1_vld)
/* bb cpu set txcfg step1 vaild */
#define BB_CPU_SET_TXCFG1_VLD(X) \
BB_CPU_SET(glb_fsm_ctxt, bb_cpu_txcfg1_vld, (X))
/* bb cpu get proto */
#define BB_CPU_GET_PROTO() BB_CPU_GET(glb_fsm_ctxt, bb_cpu_proto)
/* bb cpu set proto */
#define BB_CPU_SET_PROTO(X) BB_CPU_SET(glb_fsm_ctxt, bb_cpu_proto, (X))
static void bb_cpu_csma_check_txq()
{
#if ENA_RF_MULTI_CSMA_HWQ_WAR
uint32_t hwq_id;
uint8_t dummy_hwq_map = 0;
rf_tx_mpdu_start *mpdu = NULL;
rf_tx_mpdu_start *next = NULL;
/* debug mode do not need this war */
if (mac_rf_txq_is_dbg_mode()) {
return;
}
/* judge csma hwq is all enable or not */
for (hwq_id = MAC_RF_QUE_CSMA_0; hwq_id < MAX_ENABLE_CSMA_HWQ; hwq_id++) {
if (!mac_rf_txq_is_enable(hwq_id)) {
bb_cpu_printf("need 4 csma hwq enable!\n");
return;
}
}
uint8_t vaild_mpdu = 0;
/* if hwq pointer all dummy */
for (hwq_id = MAC_RF_QUE_CSMA_0; hwq_id < MAX_ENABLE_CSMA_HWQ; hwq_id++) {
mpdu = (rf_tx_mpdu_start *)bb_cpu_mac_get_hwq_cur_ptr(hwq_id);
IOT_ASSERT(mpdu);
/* is mpdu */
if (mpdu->desc_type == DESC_TYPE_TX_MPDU_START) {
/* is simulater mpdu */
if (mpdu->tx_status == NULL) {
next = mpdu->next;
IOT_ASSERT(next);
/* is dummy */
if (next->desc_type != DESC_TYPE_TX_MPDU_START) {
next = next->next;
/* vaild mpdu exist or not */
if (next && next->desc_type == DESC_TYPE_TX_MPDU_START) {
mac_rf_txq_force_disable(hwq_id);
/* recover csma configuration */
mac_rf_txq_cfg_by_hwqid(hwq_id);
/* enable hwq */
mac_rf_txq_enable(hwq_id, mpdu->next);
vaild_mpdu++;
}
}
} else {
/* recover csma configuration */
mac_rf_txq_cfg_by_hwqid(hwq_id);
vaild_mpdu++;
}
} else {
/* current pointer is dummy and next is vaild mpdu */
next = mpdu->next;
if (next && next->desc_type == DESC_TYPE_TX_MPDU_START &&
next->tx_status != NULL) {
/* recover csma configuration */
mac_rf_txq_cfg_by_hwqid(hwq_id);
vaild_mpdu++;
} else {
dummy_hwq_map |= 1 << hwq_id;
}
}
}
if (vaild_mpdu) {
for (hwq_id = MAC_RF_QUE_CSMA_0;
dummy_hwq_map && hwq_id < MAX_ENABLE_CSMA_HWQ; hwq_id++) {
if (dummy_hwq_map & (1 << hwq_id)) {
mpdu = (rf_tx_mpdu_start *)bb_cpu_mac_get_hwq_cur_ptr(hwq_id);
mac_rf_txq_force_disable(hwq_id);
rf_tx_mpdu_start *simu_mpdu = &simu_mpdu_tbl[hwq_id];
IOT_ASSERT(simu_mpdu);
simu_mpdu->next = mpdu;
mac_rf_txq_cfg_block_by_hwqid(hwq_id);
mac_rf_txq_enable(hwq_id, simu_mpdu);
dummy_hwq_map &= ~(0x1 << hwq_id);
}
}
}
#endif
}
static void bb_cpu_csma_check_next_mpdu()
{
#if ENA_RF_MULTI_CSMA_HWQ_WAR
uint8_t allhwq_is_simu = 1;
rf_tx_mpdu_start *mpdu = NULL;
rf_tx_mpdu_start *tmp_mpdu = NULL;
rf_tx_mpdu_start *next = NULL;
/* debug mode do not need this war */
if (mac_rf_txq_is_dbg_mode()) {
return;
}
uint32_t hwq_id = BB_CPU_GET_HWQID();
if (hwq_id >= MAC_RF_QUE_CSMA_0 && hwq_id < MAX_ENABLE_CSMA_HWQ) {
mpdu = (rf_tx_mpdu_start *)bb_cpu_mac_get_hwq_cur_ptr(hwq_id);
IOT_ASSERT(mpdu->desc_type == DESC_TYPE_TX_MPDU_START);
next = mpdu->next;
IOT_ASSERT(next->desc_type != DESC_TYPE_TX_MPDU_START);
next = next->next;
if (next == NULL) {
for (uint8_t i = MAC_RF_QUE_CSMA_0; i < MAX_ENABLE_CSMA_HWQ; i++) {
if (i == hwq_id) {
continue;
}
tmp_mpdu = (rf_tx_mpdu_start *)bb_cpu_mac_get_hwq_cur_ptr(i);
if (!(tmp_mpdu->desc_type == DESC_TYPE_TX_MPDU_START &&
tmp_mpdu->tx_status == NULL)) {
allhwq_is_simu = 0;
break;
}
}
/* at least one of them is not simu mpdu */
if (!allhwq_is_simu) {
mac_rf_txq_force_disable(hwq_id);
rf_tx_mpdu_start *simu_mpdu = &simu_mpdu_tbl[hwq_id];
simu_mpdu->next = mpdu->next;
mac_rf_txq_cfg_block_by_hwqid(hwq_id);
mac_rf_txq_enable(hwq_id, simu_mpdu);
}
}
}
#endif
}
static void bb_cpu_rx_reset()
{
/* reset rx need stop rx timer */
bb_rf_rx_timer_en(0);
bb_cpu_mac_rx_timer_en(0);
bb_rf_rx_reset();
//bb_rf_jesd_reset();
/* set rx flag = 0 */
BB_CPU_SET_RX_FLAG(0);
}
static void bb_cpu_tx_reset()
{
/* reset rx need stop rx timer */
bb_rf_tx_timer_en(0);
bb_cpu_mac_tx_timer_en(0);
bb_rf_tx_reset();
//bb_rf_jesd_reset();
}
static void bb_cpu_rf_reset()
{
bb_cpu_rx_reset();
bb_cpu_tx_reset();
}
static void bb_cpu_set_isr_vaild(uint8_t is_vaild)
{
/* disable irq */
bb_cpu_mac_isr_stop();
/* config isr is vaild */
BB_CPU_SET_ISR_VAILD(is_vaild);
/* enable irq */
bb_cpu_mac_isr_start();
}
void bb_cpu_set_isr_vaild_from_isr(uint8_t is_vaild)
{
/* config isr is vaild */
BB_CPU_SET_ISR_VAILD(is_vaild);
}
static void bb_cpu_judge_goto_next_ptr()
{
#define GOTO_NEXT_PTR_TIMEOUT 2500 // 100us
uint32_t hwq_id, judge, start_ntb, cur_ntb, time_span;
/* notify main cpu tx done */
hwq_id = BB_CPU_GET_HWQID();
/* wait vld change */
start_ntb = mac_sched_get_lts();
do {
cur_ntb = mac_sched_get_lts();
time_span = cur_ntb - start_ntb;
judge = (bb_cpu_mac_get_hwq_cur_ptr(hwq_id) == BB_CPU_GET_TX_MPDU());
} while (judge && time_span < GOTO_NEXT_PTR_TIMEOUT);
/* judge again */
judge = (bb_cpu_mac_get_hwq_cur_ptr(hwq_id) == BB_CPU_GET_TX_MPDU());
if (judge) {
bb_cpu_printf("forcestophwq:%d, mpdu:0x%x\n",
hwq_id, BB_CPU_GET_TX_MPDU());
#if ENA_RF_FORCE_RESET_HWQ
rf_tx_mpdu_start *mpdu = (rf_tx_mpdu_start *)BB_CPU_GET_TX_MPDU();
rf_tx_mpdu_start *next = mpdu->next;
IOT_ASSERT(next);
mac_rf_txq_force_disable(hwq_id);
mac_rf_txq_enable(hwq_id, next);
#else
IOT_ASSERT(0);
#endif
}
}
static void bb_cpu_notify_sw_tx_done()
{
uint32_t hwq_id;
/* notify main cpu tx done */
hwq_id = BB_CPU_GET_HWQID();
/* clear record hwqid */
BB_CPU_SET_HWQID(MAX_MAC_RF_TXQ_NUM);
IOT_ASSERT(hwq_id < MAX_MAC_RF_TXQ_NUM);
bb_cpu_mac_set_share_irq_to_maincpu(hwq_id + RF_MAC_INT_HWQ_BIT_OFFSET);
bb_cpu_mac_set_sw_irq_to_maincpu(RF_MAC_SW_ISR_TX_MPDU_COMPLETE);
}
#if HPLC_RF_ASYNC_TX
#if HPLC_RF_ASYNC_TX == 1
/* return 1: early stop occor */
uint32_t bb_cpu_set_hplc_pcs_sts(uint32_t is_busy)
{
#define BB_CPU_SET_HPLC_PCS_TIMEOUT 25000 // 1ms
uint32_t start_ntb, cur_ntb, time_span, early_stop_judge;
if (mac_rf_get_hplc_pcs_reg() == is_busy) {
return 0;
}
/* notify hplc to set pcs busy */
mac_rf_set_hplc_pcs_reg(is_busy);
if (is_busy) {
/* set hplc pcs status */
mac_rf_set_hplc_pcs_sts_reg(0);
}
bb_cpu_mac_set_sw_irq_to_maincpu(RF_MAC_SW_ISR_SET_HPLC_PCS);
if (is_busy) {
/* wait vld change */
start_ntb = mac_sched_get_lts();
do {
cur_ntb = mac_sched_get_lts();
time_span = cur_ntb - start_ntb;
early_stop_judge = !!(glb_fsm_ctxt.bb_cpu_event &
(1 << BB_CPU_EVENT_RST_ID));
} while (!early_stop_judge && !mac_rf_get_hplc_pcs_sts_reg() &&
time_span < BB_CPU_SET_HPLC_PCS_TIMEOUT);
/* early stop occor */
if (early_stop_judge) {
bb_cpu_printf("early stop occor!\n");
return 1;
}
/* judge again */
if (!mac_rf_get_hplc_pcs_sts_reg()) {
bb_cpu_printf("set hplc pcs fail:0x%x\n",
glb_fsm_ctxt.bb_cpu_event);
IOT_ASSERT(0);
}
}
return 0;
}
#elif HPLC_RF_ASYNC_TX == 2
uint32_t bb_cpu_set_hplc_pcs_sts(uint32_t is_busy)
{
uint32_t ret;
if (is_busy) {
ret = mac_set_pcs_busy_from_isr(1, 1);
} else {
ret = mac_set_pcs_busy_from_isr(0, 0);
}
return ret;
}
#else
#error "config HPLC_RF_ASYNC_TX error"
#endif
uint32_t bb_cpu_async_tx_check()
{
uint32_t ret = 0;
if (!mac_rf_get_hplc_rf_async_tx()) {
return 0;
}
/* if current cmd is csma and is not cert mode,
* need judge hplc is tx or not
*/
if (bb_cpu_mac_judge_cur_cmd_need_tx_csma() &&
!mac_rf_get_cert_flag()) {
/* if hplc is tx status, wmac return.
* if hplc is not tx status, wmac tx rf pkt.
*/
if (mac_get_phy_txrx_sts() == MAC_PHY_TX_STS) {
/* set rf mac tx done */
bb_cpu_mac_set_tx_done();
ret = 1;
} else {
/* notify hplc set pcs busy */
ret = bb_cpu_set_hplc_pcs_sts(1);
if (ret || mac_get_phy_txrx_sts() == MAC_PHY_TX_STS) {
bb_cpu_printf("set hplc pcs status fail\n");
/* set rf mac tx done */
bb_cpu_mac_set_tx_done();
/* free hplc pcs */
bb_cpu_set_hplc_pcs_sts(0);
ret = 1;
}
}
}
return ret;
}
#else /* HPLC_RF_ASYNC_TX */
uint32_t bb_cpu_set_hplc_pcs_sts(uint32_t is_busy)
{
(void)is_busy;
return 0;
}
uint32_t bb_cpu_async_tx_check()
{
return 0;
}
#endif /* HPLC_RF_ASYNC_TX */
/* bb_cpu trigger mac to handle */
static void bb_cpu_trigger_mac(uint32_t reason)
{
switch (reason) {
case BB_CPU_TRIGGER_MAC_TX_DONE:
{
/* inter-packet interval cifs */
bb_cpu_mac_inter_pkt_interval(RF_MAC_CIFS_US);
/* check next mpdu is vaild or not */
bb_cpu_csma_check_next_mpdu();
/* set rf mac tx done */
bb_cpu_mac_set_tx_done();
/* notify hplc pcs busy free */
bb_cpu_set_hplc_pcs_sts(0);
/* judge next mpdu */
bb_cpu_judge_goto_next_ptr();
/* notify main cpu tx done */
bb_cpu_notify_sw_tx_done();
break;
}
case BB_CPU_TRIGGER_MAC_RX_SACK_DONE:
{
/* notify main cpu tx done */
bb_cpu_notify_sw_tx_done();
break;
}
case BB_CPU_TRIGGER_MAC_RX_DONE:
{
/* set rf mac rx done */
bb_cpu_mac_set_rx_done();
BB_CPU_SET_RX_FLAG(0);
break;
}
case BB_CPU_TRIGGER_MAC_NEED_RX_SACK:
{
uint32_t interval = RF_MAC_RX_RIFS_US +
phy_rf_get_g_stf_ltf_fl() + phy_rf_get_g_sig_fl() +
phy_rf_get_g_phr_fl(phy_rf_get_g_tx_sack_mcs()) + RF_MAC_CIFS_US;
if (mac_rf_get_cert_flag()) {
/* for certification mode, add 1ms as margin */
interval += RF_MAC_RX_SACK_CERT_MARGIN;
}
/* inter-packet interval rx sack */
bb_cpu_mac_inter_pkt_interval(interval);
/* check next mpdu is vaild or not */
bb_cpu_csma_check_next_mpdu();
/* set rf mac tx done */
bb_cpu_mac_set_tx_done();
/* notify hplc pcs busy free */
bb_cpu_set_hplc_pcs_sts(0);
break;
}
case BB_CPU_TRIGGER_MAC_STOP_SCHE_COMPLETE:
{
/* set rf mac sched stop done */
uint32_t ret_fsm = bb_cpu_mac_set_sched_stop_done(1);
if (ret_fsm) {
/* try again */
bb_cpu_mac_set_sched_stop_done(2);
}
/* notify plc cpu stop sched success */
mac_rf_set_stop_sched_sts_success();
break;
}
case BB_CPU_TRIGGER_MAC_RX_ABORT_COMPLETE:
{
/* set rf mac rx abort done */
bb_cpu_mac_set_rx_abort_done();
break;
}
case BB_CPU_TRIGGER_MAC_TX_ABORT_COMPLETE:
{
/* set rf mac tx abort done */
bb_cpu_mac_set_tx_abort_done();
break;
}
case BB_CPU_TRIGGER_MAC_BBCPU_IS_READY:
{
/* set rf mac csma is ready */
bb_cpu_mac_set_csma_is_ready();
break;
}
case BB_CPU_TRIGGER_MAC_CMSLIST_DONE:
{
bb_cpu_set_isr_vaild_from_isr(1);
/* set rf mac cmdlist don complete */
bb_cpu_mac_set_cmdlist_done();
/* some case. cmdlist done come before early stop.
* no more early stop processing, but we need set early stop success.
*/
mac_rf_set_stop_sched_sts_success();
/* notify plc cpu cmdlist done */
bb_cpu_mac_set_sw_irq_to_maincpu(RF_MAC_SW_ISR_CMDLIST_BBCPU_DONE);
break;
}
default:
bb_cpu_printf("trg mac rsn:%d\n", reason);
IOT_ASSERT(0);
break;
}
return;
}
static void bb_cpu_backfill_txntb_to_desc(uint32_t *phr, uint32_t tx_ntb)
{
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_BEACON ||
fc_msg.delimiter == FC_DELIM_SOF) {
rf_tx_mpdu_start *mpdu = (rf_tx_mpdu_start *)BB_CPU_GET_TX_MPDU();
rf_tx_mpdu_end *tx_end = mpdu->tx_status;
tx_end->first_try_ts = tx_ntb;
} else if (fc_msg.delimiter == FC_DELIM_SACK) {
// TODO: maybe add sack tx ntb in rx desc.
}
}
/* bb_cpu trigger bb to handle */
void bb_cpu_trigger_bb(uint32_t reason)
{
if (BB_CPU_TRIGGER_BB_TX == reason) {
uint32_t tx_ntb;
uint32_t phr[4] = { 0 };
bb_rf_get_tx_phr(phr);
tx_ntb = bb_cpu_mac_trigger_tx(phr);
bb_cpu_backfill_txntb_to_desc(phr, tx_ntb);
} else if (BB_CPU_TRIGGER_BB_RX == reason) {
bb_cpu_mac_trigger_rx();
} else {
bb_cpu_printf("trg bb rsn:%d\n", reason);
IOT_ASSERT(0);
}
}
void bb_cpu_set_event(uint32_t event_id)
{
/* disable irq */
bb_cpu_mac_isr_stop();
/* config event id */
glb_fsm_ctxt.bb_cpu_event |= 1 << event_id;
/* enable irq */
bb_cpu_mac_isr_start();
}
static void bb_cpu_clr_evt(uint32_t event_id)
{
/* disable irq */
bb_cpu_mac_isr_stop();
/* config event id */
glb_fsm_ctxt.bb_cpu_event &= ~(0x1 << event_id);
glb_fsm_ctxt.bb_cpu_evt_tmp &= ~(0x1 << event_id);
/* enable irq */
bb_cpu_mac_isr_start();
}
static void bb_cpu_clr_multi_evt(uint32_t event_ids)
{
/* disable irq */
bb_cpu_mac_isr_stop();
/* config event id */
glb_fsm_ctxt.bb_cpu_event &= ~event_ids;
glb_fsm_ctxt.bb_cpu_evt_tmp &= ~event_ids;
/* enable irq */
bb_cpu_mac_isr_start();
}
void bb_cpu_set_event_from_isr(uint32_t event_id)
{
/* config event id */
if (BB_CPU_GET_ISR_VAILD() ||
// TODO: need check the necessity of these events.
BB_CPU_EVENT_TX_COMP_ID == event_id ||
BB_CPU_EVENT_RX_PLD_START_ID == event_id ||
BB_CPU_EVENT_TX_TIMEOUT_ID == event_id ||
BB_CPU_EVENT_RX_TIMEOUT_ID == event_id ||
BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID == event_id ||
BB_CPU_EVENT_RST_TIMEOUT_ID == event_id ||
BB_CPU_EVENT_SYNC_SPI_ID == event_id ||
BB_CPU_EVENT_TX_TONE_ID == event_id ||
BB_CPU_EVENT_TX_CAL_UPDATE_ID == event_id) {
glb_fsm_ctxt.bb_cpu_event |= 1 << event_id;
}
if (BB_CPU_GET_ISR_VAILD() && (BB_CPU_EVENT_RST_ID == event_id ||
BB_CPU_EVENT_CMDLIST_DONE_ID == event_id)) {
bb_cpu_set_isr_vaild_from_isr(0);
}
}
static uint32_t bb_cpu_get_event()
{
uint32_t event_id;
/* disable irq */
bb_cpu_mac_isr_stop();
/* get event id */
event_id = glb_fsm_ctxt.bb_cpu_event;
/* clear event id */
glb_fsm_ctxt.bb_cpu_event = 0;
/* enable irq */
bb_cpu_mac_isr_start();
return event_id;
}
static uint32_t bb_cpu_wait_event(uint32_t time_to_wait_us)
{
uint32_t cur_time;
int64_t time_span = 0;
uint32_t start_ts = gp_timer_get_current_val(0);
do {
cur_time = gp_timer_get_current_val(0);
time_span = cur_time - start_ts;
/* wrap around */
if (time_span < 0) {
time_span = (0x100000000LL) - start_ts + cur_time;
}
} while ((time_span < time_to_wait_us) && !glb_fsm_ctxt.bb_cpu_event);
return bb_cpu_get_event();
}
/* bb cpu set timer to wait timeout */
static void bb_cpu_timer_restart(uint32_t timer_id, uint32_t time_us)
{
bb_cpu_timer_stop(timer_id);
bb_cpu_timer_set(timer_id, time_us);
bb_cpu_timer_start(timer_id);
}
static void bb_cpu_set_vcs_timer(uint32_t time_us)
{
/* disable irq */
bb_cpu_mac_isr_stop();
/* record vcs timer length */
BB_CPU_SET_VCS_LEN(time_us);
bb_cpu_timer_restart(TIMER_OF_VCS, time_us);
/* record vcs timer start ntb */
BB_CPU_SET_VCS_NTB(mac_sched_get_lts());
/* record vcs timer working */
BB_CPU_SET_VCS_WORKING(1);
/* enable irq */
bb_cpu_mac_isr_start();
}
void bb_cpu_set_vcs_timer_from_isr(uint32_t time_us, uint32_t is_force)
{
uint32_t cur_ntb, dlt_us, time_remain;
if (BB_CPU_GET_VCS_WORKING() && !is_force) {
cur_ntb = mac_sched_get_lts();
dlt_us = (cur_ntb - BB_CPU_GET_VCS_NTB())/25000;
if (dlt_us > BB_CPU_GET_VCS_LEN()) {
IOT_ASSERT(0);
}
time_remain = BB_CPU_GET_VCS_LEN() - dlt_us;
if (time_us > time_remain) {
BB_CPU_SET_VCS_LEN(time_us);
bb_cpu_timer_restart(TIMER_OF_VCS, time_us);
/* record vcs timer start ntb */
BB_CPU_SET_VCS_NTB(mac_sched_get_lts());
BB_CPU_SET_VCS_WORKING(1);
}
} else {
BB_CPU_SET_VCS_LEN(time_us);
bb_cpu_timer_restart(TIMER_OF_VCS, time_us);
/* record vcs timer start ntb */
BB_CPU_SET_VCS_NTB(mac_sched_get_lts());
BB_CPU_SET_VCS_WORKING(1);
}
}
void bb_cpu_stop_vcs_working_from_isr()
{
/* pull vcs down */
bb_cpu_mac_set_vcs_sts_from_isr(0);
BB_CPU_SET_VCS_WORKING(0);
}
static void bb_cpu_rxabort_cmdlistdone_set_vcs(uint32_t time_us)
{
uint32_t cur_ntb, dlt_us, time_remain;
/* disable irq */
bb_cpu_mac_isr_stop();
if (BB_CPU_GET_VCS_WORKING()) {
cur_ntb = mac_sched_get_lts();
dlt_us = (cur_ntb - BB_CPU_GET_VCS_NTB())/25000;
if (dlt_us > BB_CPU_GET_VCS_LEN() &&
BB_CPU_VCS_MARGIN > BB_CPU_GET_VCS_LEN()) {
bb_cpu_printf("special set vcs err dltus:%lu, vcslen:%lu\n",
dlt_us, BB_CPU_GET_VCS_LEN());
IOT_ASSERT(0);
}
if (dlt_us < (BB_CPU_GET_VCS_LEN() - BB_CPU_VCS_MARGIN)) {
time_remain = BB_CPU_GET_VCS_LEN() - dlt_us - BB_CPU_VCS_MARGIN;
BB_CPU_SET_VCS_LEN(time_remain);
bb_cpu_timer_restart(TIMER_OF_VCS, time_remain);
} else {
/* record vcs timer length */
BB_CPU_SET_VCS_LEN(time_us);
bb_cpu_timer_restart(TIMER_OF_VCS, time_us);
}
/* record vcs timer start ntb */
BB_CPU_SET_VCS_NTB(mac_sched_get_lts());
BB_CPU_SET_VCS_WORKING(1);
} else {
/* vcs has already timeout */
}
/* enable irq */
bb_cpu_mac_isr_start();
}
static void bb_cpu_stop_and_clr_tx_timer()
{
bb_cpu_timer_stop(TIMER_OF_TX);
bb_cpu_clr_evt(BB_CPU_EVENT_TX_TIMEOUT_ID);
}
static void bb_cpu_stop_and_clr_rx_timer()
{
bb_cpu_timer_stop(TIMER_OF_RX);
bb_cpu_clr_evt(BB_CPU_EVENT_RX_TIMEOUT_ID);
}
static void bb_cpu_stop_and_clr_rst_timer()
{
bb_cpu_timer_stop(TIMER_OF_RST);
bb_cpu_clr_evt(BB_CPU_EVENT_RST_TIMEOUT_ID);
}
static void bb_cpu_set_rst_reason_by_evt(uint32_t event_id)
{
if (BB_CPU_EVENT_RX_ABORT_ID == event_id) {
BB_CPU_SET_RST_RS(BB_CPU_TO_RST_IS_RX_ABORT);
} else if (BB_CPU_EVENT_TX_ABORT_ID == event_id) {
BB_CPU_SET_RST_RS(BB_CPU_TO_RST_IS_TX_ABORT);
} else if (BB_CPU_EVENT_RST_ID == event_id) {
BB_CPU_SET_RST_RS(BB_CPU_TO_RST_IS_STOP_SCHE);
} else if (BB_CPU_EVENT_CMDLIST_DONE_ID == event_id) {
BB_CPU_SET_RST_RS(BB_CPU_TO_RST_IS_CMDLIST_DONE);
} else {
BB_CPU_SET_RST_RS(BB_CPU_TO_RST_IS_INVALID);
}
}
static void bb_cpu_update_tx_pwr(void)
{
int8_t target_pwr;
if (ERR_OK != mac_rf_get_target_tx_power(&target_pwr)) {
return;
}
if (target_pwr != BB_CPU_GET_CUR_TX_PWR()) {
if (0 == bb_rf_set_pa(1, (int32_t)target_pwr)) {
bb_cpu_printf("set tx pwr %d to %d\n",
BB_CPU_GET_CUR_TX_PWR(), target_pwr);
BB_CPU_SET_CUR_TX_PWR(target_pwr);
}
}
}
static void bb_cpu_set_tx_fsm(uint32_t tx_state, uint32_t reason)
{
uint32_t bb_evt = 0;
if (BB_CPU_TX_STATE_IDLE == tx_state) {
bb_evt = glb_fsm_ctxt.bb_cpu_evt_tmp;
if (BB_CPU_ENTER_IDLE_NOR == reason) {
/* tx abort cannot be cleared
* because a tx abort done reply is required.
*/
if (bb_evt & (~(1 << BB_CPU_EVENT_TX_ABORT_ID))) {
bb_cpu_printf("tx fsm:%d, evt:0x%x\n",
BB_CPU_GET_TX_FSM(), bb_evt);
IOT_ASSERT(0);
}
} else if (BB_CPU_ENTER_IDLE_RST == reason) {
if (bb_evt & (~(1 << BB_CPU_EVENT_TX_COMP_ID))) {
bb_cpu_printf("tx rst fsm:%d, tmpevt:0x%x\n",
BB_CPU_GET_TX_FSM(), bb_evt);
IOT_ASSERT(0);
}
bb_cpu_timer_stop(TIMER_OF_WAIT_SACK);
/* check event id, tx complete id can not clear */
glb_fsm_ctxt.bb_cpu_evt_tmp &= (1 << BB_CPU_EVENT_TX_COMP_ID);
} else {
IOT_ASSERT(0);
}
bb_cpu_stop_and_clr_tx_timer();
}
BB_CPU_SET_TX_FSM(tx_state);
}
static void bb_cpu_set_rx_fsm(uint32_t rx_state, uint32_t reason)
{
uint32_t bb_evt = 0;
if (BB_CPU_RX_STATE_IDLE == rx_state) {
bb_evt = glb_fsm_ctxt.bb_cpu_evt_tmp;
if (BB_CPU_ENTER_IDLE_NOR == reason) {
if (bb_evt) {
if ((BB_CPU_GET_RX_FSM() == BB_CPU_RX_STATE_LISTENING ||
BB_CPU_GET_RX_FSM() == BB_CPU_RX_STATE_WAIT_PHR ||
/* rx sack and enter rx complete state directly */
BB_CPU_GET_RX_FSM() == BB_CPU_RX_STATE_RX_COMPLETE) &&
!(bb_evt & (~(1 << BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID)))) {
/* listening status and
* wait sack timeout happened,
* do not care
*/
} else {
bb_cpu_printf("rx fsm:%d, evt:0x%x\n",
BB_CPU_GET_RX_FSM(), bb_evt);
IOT_ASSERT(0);
}
}
} else if (BB_CPU_ENTER_IDLE_RST == reason) {
if (bb_evt) {
if (BB_CPU_GET_RX_FSM() == BB_CPU_RX_STATE_WAIT_SACK_TX_COMPLETE
&& !(bb_evt & (~(1 << BB_CPU_EVENT_TX_COMP_ID)))) {
/* wait sack tx complete and
* tx complete happen,
* do not care
*/
} else {
if (bb_evt & (~(1 << BB_CPU_EVENT_RX_PLD_START_ID))) {
bb_cpu_printf("rx rst fsm:%d, tmpevt:0x%x\n",
BB_CPU_GET_RX_FSM(), bb_evt);
IOT_ASSERT(0);
}
}
}
bb_cpu_timer_stop(TIMER_OF_WAIT_SACK);
} else {
IOT_ASSERT(0);
}
bb_cpu_stop_and_clr_rx_timer();
}
BB_CPU_SET_RX_FSM(rx_state);
}
static uint32_t bb_cpu_get_option()
{
if (BB_CPU_GET_OPTION() >= PHY_RF_OPTION_MAX) {
/* not init */
IOT_ASSERT(0);
}
return BB_CPU_GET_OPTION();
}
extern uint8_t bb_cpu_buf[520];
static void bb_cpu_send_data_to_bb(rf_tx_mpdu_start *mpdu)
{
uint32_t pb_size;
uint32_t proto = BB_CPU_GET_PROTO();
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), &mpdu->phr0, &fc_msg);
pb_size = phy_rf_get_pbsz(mpdu->blkz);
if (fc_msg.delimiter == FC_DELIM_BEACON) {
/* cpu write data */
bb_rf_write_data_to_bb(pb_size, (uint8_t *)mpdu->pb->pb_buf_addr);
} else if (fc_msg.delimiter == FC_DELIM_SOF) {
#if SUPPORT_SMART_GRID
if (PLC_PROTO_TYPE_SG == proto) {
bb_cpu_buf[0] = mpdu->pb->sof_pb_header;
os_mem_cpy((uint8_t *)&bb_cpu_buf[1],
(uint8_t *)mpdu->pb->pb_buf_addr,
pb_size - SG_SOF_PB_HDR_CRC_LEN);
} else
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
if (PLC_PROTO_TYPE_SPG == proto) {
spg_sof_pb_hdr_t *pb_hdr = (spg_sof_pb_hdr_t *)bb_cpu_buf;
pb_hdr->seq = mpdu->pb->sof_pb_header;
pb_hdr->resv = 0;
os_mem_cpy((uint8_t *)&bb_cpu_buf[4],
(uint8_t *)mpdu->pb->pb_buf_addr,
pb_size - SPG_SOF_PB_HDR_LEN);
}
#endif
{
}
/* cpu write data */
bb_rf_write_data_to_bb(pb_size, (uint8_t *)bb_cpu_buf);
}
}
/* align startand beacon header channel and option info */
static void bb_cpu_align_bcn_hdr_ch_op_info(uint32_t delimiter,
uint32_t pb_buf_addr)
{
if (delimiter != FC_DELIM_BEACON || mac_rf_get_cert_mode()) {
return;
}
switch (BB_CPU_GET_PROTO()) {
#if SUPPORT_SMART_GRID
case PLC_PROTO_TYPE_SG:
{
beacon_payload_fixed_header_t *fix_header =
(beacon_payload_fixed_header_t *)pb_buf_addr;
if (!fix_header->simple_beacon) {
beacon_payload_std_header_t *std_header =
(beacon_payload_std_header_t *)pb_buf_addr;
std_header->rf_channel = BB_CPU_GET_CHANNEL_ID();
std_header->rf_option = BB_CPU_GET_OPTION();
}
break;
}
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
case PLC_PROTO_TYPE_SPG:
{
spg_beacon_payload_fixed_header_t *fix_header =
(spg_beacon_payload_fixed_header_t *)pb_buf_addr;
if (!fix_header->simple_beacon) {
spg_beacon_payload_std_header_t *std_header =
(spg_beacon_payload_std_header_t *)pb_buf_addr;
std_header->rf_channel = BB_CPU_GET_CHANNEL_ID();
std_header->rf_option = BB_CPU_GET_OPTION();
}
break;
}
#endif
default:
break;
}
}
/* config bb to tx */
static void bb_cpu_config_bb_tx(bb_rf_hw_info_t *phr_info,
bb_rf_hw_info_t *pld_info, void *phr, uint32_t pb_buf,
uint32_t pb_size, uint32_t pb_num, uint32_t need_sack, uint32_t crc32_en)
{
uint32_t set_if = 0;
uint8_t tx_i_p, tx_q_p;
if (!BB_CPU_GET_TXCFG1_VLD()) {
/* reset tx before each tx configuration */
bb_cpu_tx_reset();
bb_rf_jesd_reset();
/* bb rf tx switch1 */
bb_rf_tx_switch_step1();
}
/* bb rf tx switch2 */
bb_rf_tx_switch_step2();
/* clear txcfg1 vaild */
BB_CPU_SET_TXCFG1_VLD(0);
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
/* channel id changed and tx sof and beacon.
* if tx sack not update current channel
*/
if (BB_CPU_GET_CHANNEL_FREQ() != mac_rf_get_cur_channel_freq() &&
(fc_msg.delimiter == FC_DELIM_BEACON ||
fc_msg.delimiter == FC_DELIM_SOF)) {
mac_rf_set_cur_channel_freq(BB_CPU_GET_CHANNEL_FREQ());
mac_rf_set_cur_channel_id(BB_CPU_GET_CHANNEL_ID());
}
int64_t ppmhz = ((int64_t)mac_rf_get_wphy_ppm() *
BB_CPU_GET_CHANNEL_FREQ()) >> 26;
set_if = mac_rf_get_cur_channel_freq() - (int32_t)ppmhz;
IOT_ASSERT(set_if);
bb_cpu_update_tx_pwr();
/* update tx iq phase */
mac_rf_get_tx_iqp_cali(&tx_i_p, &tx_q_p);
bb_rf_set_tx_iq_phase(tx_i_p, tx_q_p);
/* tx config */
bb_rf_tx_set_freq_and_filter(BB_CPU_GET_OPTION(), set_if);
/* clear tx info */
bb_rf_clear_tx_info();
/* make sure that the channel in beacon header is
* the same as the real channel
*/
bb_cpu_align_bcn_hdr_ch_op_info(fc_msg.delimiter, pb_buf);
if (pb_num && BB_CPU_TXRX_USE_DMA) {
/* start dma */
bb_cpu_dma_start(RF_PHY_TX_DMA_BASEADDR, pb_buf, pb_size * pb_num);
}
/* just beacon need calcualte crc32 */
if (crc32_en && fc_msg.delimiter == FC_DELIM_BEACON &&
BB_CPU_GET_PROTO() == PLC_PROTO_TYPE_SG) {
bb_rf_set_crc32_en(1);
} else {
bb_rf_set_crc32_en(0);
}
/* set need sack dtei.
* dtei = 0 : do not need sack;
* dtei != 0 : need wait dtei tx sack.
*/
if (fc_msg.delimiter == FC_DELIM_SOF && need_sack) {
BB_CPU_SET_TXDTEI(fc_msg.dst_tei);
} else {
BB_CPU_SET_TXDTEI(PLC_TEI_INVAL);
}
/* set tx phy header */
bb_rf_set_tx_phr((uint32_t *)phr);
/* config tx phy header info */
bb_rf_cfg_tx_phr_info(phr_info);
/* config tx payload info */
bb_rf_cfg_tx_pld_info(pld_info, pb_num);
return;
}
static void bb_cpu_tx_mpdu_start(rf_tx_mpdu_start *mpdu)
{
bb_rf_hw_info_t *phr_info = NULL;
bb_rf_hw_info_t *pld_info = NULL;
rf_tx_pb_start *pb = NULL;
uint32_t pbaddr = 0;
uint32_t pb_size = 0;
uint32_t pb_mum = 0;
uint32_t need_ack = 0;
uint32_t crc32_en = 0;
phr_info = bb_rf_get_phr_hw_info(mpdu->option, mpdu->phr_mcs);
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), &mpdu->phr0, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_BEACON ||
fc_msg.delimiter == FC_DELIM_SOF) {
pld_info = bb_rf_get_pld_hw_info(mpdu->option,
mpdu->blkz, mpdu->pld_mcs);
pb_size = phy_rf_get_pbsz(mpdu->blkz);
/* mabey multi pb */
// pb_mum = mpdu->pb_num;
pb_mum = 1;
pb = mpdu->pb;
pbaddr = pb->pb_buf_addr;
need_ack = mpdu->need_ack;
crc32_en = mpdu->crc32_en;
}
bb_cpu_config_bb_tx(phr_info, pld_info, (void *)&mpdu->phr0,
pbaddr, pb_size, pb_mum, need_ack, crc32_en);
}
static void bb_cpu_tx_phr_start(uint32_t *phr, uint32_t phr_mcs)
{
bb_rf_hw_info_t *phr_info;
phr_info = bb_rf_get_phr_hw_info(bb_cpu_get_option(), phr_mcs);
bb_cpu_config_bb_tx(phr_info, NULL, (void *)phr,
0, 0, 0, 0, 0);
}
static void bb_cpu_backfill_tx_desc(uint32_t timeout)
{
rf_tx_mpdu_start *mpdu = (rf_tx_mpdu_start *)BB_CPU_GET_TX_MPDU();
rf_tx_mpdu_end *tx_end = mpdu->tx_status;
/* notify hw tx done */
mpdu->notify_hw_tx_done = 1;
/* notify sw tx done */
tx_end->tx_done = 1;
// TODO: need backfill tx desc
if (timeout) {
bb_cpu_backfill_txntb_to_desc(&mpdu->phr0, 0);
} else {
}
return;
}
static void bb_cpu_backfill_tx_desc_sack(uint32_t timeout)
{
rf_tx_mpdu_start *mpdu = (rf_tx_mpdu_start *)BB_CPU_GET_TX_MPDU();
rf_tx_mpdu_end *tx_end = mpdu->tx_status;
tx_end->rx_sack_ok = 0;
if (timeout) {
/* notify sw tx ok */
tx_end->tx_ok = 0;
} else {
/* notify sw tx ok */
tx_end->tx_ok = 1;
uint32_t phr[4] = { 0 };
/* get phy header */
bb_rf_get_rx_phr(phr);
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_SACK) {
tx_end->rx_sack_ok = !fc_msg.result_in_sack;
}
}
return;
}
static void bb_cpu_prepare_tx_sack(uint32_t phr_mcs, uint32_t rx_snr)
{
uint32_t sack_phr_tbl[4] = { 0 };
uint32_t phr[4] = { 0 };
bb_rf_get_rx_phr(phr);
switch (BB_CPU_GET_PROTO()) {
#if SUPPORT_SMART_GRID
case PLC_PROTO_TYPE_SG:
{
frame_control_t *sack_phr = (frame_control_t *)sack_phr_tbl;
frame_control_t *phr_t = (frame_control_t *)phr;
IOT_ASSERT(FC_DELIM_SOF == phr_t->delimiter_type);
sack_phr->delimiter_type = FC_DELIM_SACK;
sack_phr->network_type = 0;
sack_phr->nid = phr_t->nid;
sack_phr->vf.rf_sack.rx_result = !!bb_rf_get_pld_crc24_err();
sack_phr->vf.rf_sack.resv0 = 0;
sack_phr->vf.rf_sack.stei = phr_t->vf.rf_sof.dst_tei;
sack_phr->vf.rf_sack.dtei = phr_t->vf.rf_sof.src_tei;
sack_phr->vf.rf_sack.resv1 = 0;
sack_phr->vf.rf_sack.snr = rx_snr;
sack_phr->vf.rf_sack.load = 0;
sack_phr->vf.rf_sack.resv2 = 0;
sack_phr->vf.rf_sack.ext_deli = 0;
sack_phr->vf.rf_sack.version = SG_STANDARD_VERSION;
break;
}
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
case PLC_PROTO_TYPE_SPG:
{
spg_frame_control_t *sack_phr = (spg_frame_control_t *)sack_phr_tbl;
spg_frame_control_t *phr_t = (spg_frame_control_t *)phr;
IOT_ASSERT(FC_DELIM_SOF == phr_t->delimiter_type);
sack_phr->delimiter_type = FC_DELIM_SACK;
sack_phr->access_ind = phr_t->access_ind;
sack_phr->snid = phr_t->snid;
sack_phr->vf.rf_sack.rx_result = !!bb_rf_get_pld_crc24_err();
sack_phr->vf.rf_sack.resv0 = 0;
sack_phr->vf.rf_sack.dtei = phr_t->vf.rf_sof.src_tei;
sack_phr->vf.rf_sack.resv1 = 0;
sack_phr->vf.rf_sack.resv2 = 0;
sack_phr->vf.rf_sack.resv3 = 0;
sack_phr->vf.rf_sack.ext_deli = 0;
sack_phr->vf.rf_sack.version = SPG_STANDARD_VERSION;
break;
}
#endif
default:
IOT_ASSERT(0);
}
/* config bb */
bb_cpu_tx_phr_start(sack_phr_tbl, phr_mcs);
}
static uint32_t bb_cpu_get_sig_and_cfg_bb()
{
uint32_t ret = 1;
/* TODO: maybe add timeout */
while (!bb_rf_get_rx_sig_is_ready());
if (!bb_rf_get_rx_sig_is_err()) {
bb_rf_hw_info_t *phr_info = NULL;
uint32_t option = bb_cpu_get_option();
uint32_t phr_mcs_id = bb_rf_get_rx_sig_info();
if (phr_mcs_id >= PHY_MCS_MAX) {
bb_cpu_printf("rx phrmcs err:%d\n", phr_mcs_id);
phr_mcs_id = PHY_MCS_MAX - 1;
}
phr_info = bb_rf_get_phr_hw_info(option, phr_mcs_id);
/* config phy header info */
bb_rf_cfg_rx_phr_info(phr_info);
/* set rx state continue */
bb_rf_set_rx_state_cont(1);
ret = 0;
}
return ret;
}
static uint32_t bb_cpu_calu_tx_fl(void *phr, uint32_t phr_mcs)
{
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
uint32_t frame_len = 0;
if (fc_msg.delimiter == FC_DELIM_BEACON ||
fc_msg.delimiter == FC_DELIM_SOF) {
frame_len = phy_rf_get_g_stf_ltf_fl() + phy_rf_get_g_sig_fl() +
phy_rf_get_g_phr_fl(phr_mcs) +
phy_rf_get_g_psdu_fl(fc_msg.rf_mcs, fc_msg.rf_pb_sz_idx);
} else if (fc_msg.delimiter == FC_DELIM_SACK) {
/* tx sack use fixed phr mcs */
frame_len = phy_rf_get_g_stf_ltf_fl() + phy_rf_get_g_sig_fl() +
phy_rf_get_g_phr_fl(phy_rf_get_g_tx_sack_mcs());
} else if (fc_msg.delimiter == FC_DELIM_RF_TEST) {
frame_len = phy_rf_get_g_stf_ltf_fl() + phy_rf_get_g_sig_fl() +
phy_rf_get_g_phr_fl(phr_mcs);
} else {
IOT_ASSERT(0);
}
/* the actual sending time is longer than the fl.
* so add 1ms margin, prevents timeout interrupts and
* tx done interrupt from occurring simultaneously.
*/
return frame_len + BB_CPU_TX_TIMEOUT_MARGIN;
}
static uint32_t bb_cpu_calu_rx_fl_from_phr(uint32_t *phr)
{
uint32_t frame_len = 0;
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_BEACON) {
frame_len = phy_rf_get_g_psdu_fl(fc_msg.rf_mcs, fc_msg.rf_pb_sz_idx) +
RF_MAC_BIFS_US;
} else if (fc_msg.delimiter == FC_DELIM_SOF) {
frame_len = phy_rf_get_g_psdu_fl(fc_msg.rf_mcs, fc_msg.rf_pb_sz_idx);
/* calculate fl */
if (fc_msg.nid != 0 &&
fc_msg.dst_tei != 0 &&
fc_msg.dst_tei != 0xFFF) {
/* TODO: some rule to select phr mcs */
uint32_t sack_len = phy_rf_get_g_stf_ltf_fl() +
phy_rf_get_g_sig_fl() +
phy_rf_get_g_phr_fl(phy_rf_get_g_tx_sack_mcs());
frame_len += sack_len + RF_MAC_CIFS_US + RF_MAC_RX_RIFS_US;
} else {
frame_len += RF_MAC_CIFS_US;
}
}
return frame_len;
}
static bb_rf_hw_info_t * bb_cpu_get_hw_info(void *phr)
{
bb_rf_hw_info_t *pld_info = NULL;
uint32_t option = bb_cpu_get_option();
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_BEACON ||
fc_msg.delimiter == FC_DELIM_SOF) {
pld_info = bb_rf_get_pld_hw_info(option, fc_msg.rf_pb_sz_idx,
fc_msg.rf_mcs);
}
return pld_info;
}
static uint32_t bb_cpu_get_pb_size(void *phr)
{
uint32_t pb_size = 0;
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_BEACON ||
fc_msg.delimiter == FC_DELIM_SOF) {
pb_size = phy_rf_get_pbsz(fc_msg.rf_pb_sz_idx);
}
return pb_size;
}
static uint32_t bb_cpu_cfg_rx_pld_info_to_bb(uint32_t *phr, uint8_t *rx_buf)
{
uint32_t need_rx_pld = 0;
bb_rf_hw_info_t *pld_info = NULL;
uint32_t pb_size = 0, pb_num = 1;
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_BEACON ||
fc_msg.delimiter == FC_DELIM_SOF) {
pld_info = bb_cpu_get_hw_info(phr);
IOT_ASSERT(pld_info != NULL);
need_rx_pld = 1;
pb_size = bb_cpu_get_pb_size(phr);
IOT_ASSERT(pb_size);
/* clear rx info */
bb_rf_clear_rx_info();
IOT_ASSERT(rx_buf);
if (BB_CPU_TXRX_USE_DMA) {
/* start dma */
bb_cpu_dma_start(RF_PHY_RX_DMA_BASEADDR, (uint32_t)rx_buf,
pb_size * pb_num);
} else {
IOT_ASSERT(BB_CPU_GET_RX_BUF() == NULL);
/* use copy */
BB_CPU_SET_RX_BUF(rx_buf);
}
/* need to check crc32 or not */
if (bb_cpu_mac_get_rx_crc32_check() &&
fc_msg.delimiter == FC_DELIM_BEACON &&
BB_CPU_GET_PROTO() == PLC_PROTO_TYPE_SG) {
bb_rf_set_crc32_en(1);
} else {
bb_rf_set_crc32_en(0);
}
/* config rx payload info */
bb_rf_cfg_rx_pld_info(pld_info, pb_num);
/* set rx state continue */
bb_rf_set_rx_state_cont(1);
/* set rx dec continue */
bb_rf_set_dec_cont(1);
}
return need_rx_pld;
}
static void bb_cpu_tx_hdl_idle_sm(uint32_t event_id)
{
uint32_t frame_len = 0, hwqid;
if (BB_CPU_EVENT_MAC_TX_FILL_INFO_ID == event_id) {
if (BB_CPU_GET_TXDTEI()) {
IOT_ASSERT(0);
}
/* record hwqid */
hwqid = bb_cpu_mac_get_cur_hwqid();
BB_CPU_SET_HWQID(hwqid);
rf_tx_mpdu_start *mpdu = (rf_tx_mpdu_start *)bb_cpu_mac_get_txq_ptr();
if (mpdu->desc_type) {
bb_cpu_printf("rftxdummy err, hwq:%d, csma:%d, tdma:%d\n",
hwqid, bb_cpu_mac_judge_cur_cmd_need_tx_csma(),
bb_cpu_mac_judge_cur_cmd_need_tx_tdma());
IOT_ASSERT(0);
}
/* store tx mpdu addr */
BB_CPU_SET_TX_MPDU(bb_cpu_mac_get_txq_ptr());
/* config bb */
bb_cpu_tx_mpdu_start(mpdu);
/* bb cpu set tx to wait ok state */
bb_cpu_set_tx_fsm(BB_CPU_TX_STATE_WAIT_COMPLETE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu trigger bb to tx */
bb_cpu_trigger_bb(BB_CPU_TRIGGER_BB_TX);
/* frame form mpdu */
frame_len = bb_cpu_calu_tx_fl((void *)&mpdu->phr0, mpdu->phr_mcs);
/* config timer and wait timeout */
bb_cpu_timer_restart(TIMER_OF_TX, frame_len);
if (!BB_CPU_TXRX_USE_DMA) {
/* send data to bb replace dma */
bb_cpu_send_data_to_bb(mpdu);
}
} else {
bb_cpu_printf("txdile fsm:%d, evt:%d\n",
BB_CPU_GET_RST_FSM(), event_id);
/* BB_CPU_EVENT_RX_ABORT_ID will not appear in tx state */
IOT_ASSERT(0);
}
}
static void bb_cpu_tx_hdl_wait_complete_sm(uint32_t event_id)
{
uint32_t time = 0;
/* stop tx timer */
bb_cpu_stop_and_clr_tx_timer();
if (event_id == BB_CPU_EVENT_TX_TIMEOUT_ID) {
bb_cpu_backfill_tx_desc(1);
if (BB_CPU_GET_TXDTEI()) {
BB_CPU_SET_TXDTEI(PLC_TEI_INVAL);
bb_cpu_backfill_tx_desc_sack(1);
}
/* timeout reset bb/rf */
bb_cpu_tx_reset();
/* clera tx complete event */
bb_cpu_clr_evt(BB_CPU_EVENT_TX_COMP_ID);
/* bb cpu set tx to idle state */
bb_cpu_set_tx_fsm(BB_CPU_TX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* bb cpu trigger mac tx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_TX_DONE);
} else if (event_id == BB_CPU_EVENT_TX_COMP_ID) {
/* tx ok whit pld cnt increase */
mac_rf_tx_ok_with_pld_cnt_inc();
if (BB_CPU_GET_TXDTEI()) {
// need wait sack
/* backfill tx desc */
bb_cpu_backfill_tx_desc(0);
/* bb cpu set tx to idle state */
bb_cpu_set_tx_fsm(BB_CPU_TX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* bb cpu trigger mac need rx sack */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_NEED_RX_SACK);
/* config timer and wait timeout, time = wait sig + wait phr */
time = RF_MAC_RX_RIFS_US + phy_rf_get_g_stf_ltf_fl() +
phy_rf_get_g_sig_fl() +
phy_rf_get_g_phr_fl(phy_rf_get_g_tx_sack_mcs());
if (mac_rf_get_cert_flag()) {
/* for certification mode, add 1ms as margin */
time += RF_MAC_RX_SACK_CERT_MARGIN;
}
bb_cpu_timer_restart(TIMER_OF_WAIT_SACK, time);
} else {
/* backfill tx desc */
bb_cpu_backfill_tx_desc(0);
/* bb cpu set tx to idle state */
bb_cpu_set_tx_fsm(BB_CPU_TX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* bb cpu trigger mac tx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_TX_DONE);
}
} else if (event_id == BB_CPU_EVENT_RST_ID ||
BB_CPU_EVENT_CMDLIST_DONE_ID == event_id ||
BB_CPU_EVENT_TX_ABORT_ID == event_id) {
if (BB_CPU_EVENT_CMDLIST_DONE_ID == event_id &&
bb_cpu_mac_judge_next_cmd_is_vld()) {
/* next cmd is invaild if cmdlist done,
* otherwise something is error.
*/
IOT_ASSERT(0);
}
/* bb cpu set tx to idle state */
bb_cpu_set_tx_fsm(BB_CPU_TX_STATE_IDLE, BB_CPU_ENTER_IDLE_RST);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(event_id);
/* send event to global sm, enter wait sack tx done */
bb_cpu_global_sm(BB_CPU_EVENT_RST_WAIT_TX_DONE_ID);
} else {
bb_cpu_printf("txwaitcomp fsm:%d, evt:%d\n",
BB_CPU_GET_RST_FSM(), event_id);
/* BB_CPU_EVENT_RX_ABORT_ID will not appear in tx state */
IOT_ASSERT(0);
}
}
static void bb_cpu_tx_sm(uint32_t event_id)
{
#if BB_CPU_DEBUG_PRINT
if (event_id != BB_CPU_EVENT_MAC_TX_FILL_INFO_ID) {
bb_cpu_printf("tx fsm:%d, evt:%d\n", BB_CPU_GET_TX_FSM(), event_id);
}
#endif
switch (BB_CPU_GET_TX_FSM()) {
case BB_CPU_TX_STATE_IDLE:
{
bb_cpu_tx_hdl_idle_sm(event_id);
break;
}
case BB_CPU_TX_STATE_WAIT_COMPLETE:
{
bb_cpu_tx_hdl_wait_complete_sm(event_id);
break;
}
default:
break;
}
}
static void bb_cpu_rx_config_start()
{
/* if bb is rx state, do not init rx again */
if (BB_CPU_GET_RX_FLAG()) {
return;
}
/* need handle sleep or not */
if (mac_rf_is_pa_disable()) {
mac_rf_disable_pa(0);
/* ip request delay 1ms */
iot_delay_us(1000);
bb_rf_jesd_reset();
bb_rf_init(BB_CPU_GET_OPTION(), 1);
} else {
bb_rf_jesd_reset();
}
/* clear tx iq phase */
bb_rf_set_tx_iq_phase(0, 0);
/* reset rx before each rx configuration */
bb_cpu_rx_reset();
/* clear sig */
bb_cpu_clr_evt(BB_CPU_EVENT_RX_SIG_ID);
uint32_t set_if = 0;
/* channel id changed and not in tx sack status.
* if in tx sack status, not update current channel.
*/
if (BB_CPU_GET_CHANNEL_FREQ() != mac_rf_get_cur_channel_freq() &&
BB_CPU_GET_TXDTEI() == PLC_TEI_INVAL) {
mac_rf_set_cur_channel_freq(BB_CPU_GET_CHANNEL_FREQ());
mac_rf_set_cur_channel_id(BB_CPU_GET_CHANNEL_ID());
}
int64_t ppmhz = ((int64_t)mac_rf_get_wphy_ppm() *
BB_CPU_GET_CHANNEL_FREQ()) >> 26;
set_if = mac_rf_get_cur_channel_freq() - (int32_t)ppmhz;
IOT_ASSERT(set_if);
/* rx config */
bb_rf_rx_cfg(BB_CPU_GET_OPTION(), set_if);
/* bb cpu trigger bb to tx */
bb_cpu_trigger_bb(BB_CPU_TRIGGER_BB_RX);
BB_CPU_SET_RX_FLAG(1);
/* clear txcfg1 vaild */
BB_CPU_SET_TXCFG1_VLD(0);
}
static void bb_cpu_get_data_from_bb(uint32_t *phr)
{
uint32_t pb_size;
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_BEACON ||
fc_msg.delimiter == FC_DELIM_SOF) {
pb_size = bb_cpu_get_pb_size(phr);
/* cpu read data */
bb_rf_read_data_from_bb(pb_size, BB_CPU_GET_RX_BUF());
BB_CPU_SET_RX_BUF(NULL);
while (!bb_rf_get_pld_crc_rdy());
}
}
static uint32_t bb_cpu_rx_judge_need_tx_sack()
{
uint32_t need_sack = 0;
uint32_t phr[4] = { 0 };
if (BB_CPU_GET_TXDTEI()) {
return need_sack;
}
/* get phy header */
bb_rf_get_rx_phr(phr);
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_SOF) {
if (fc_msg.nid != 0 &&
fc_msg.dst_tei != 0 &&
fc_msg.dst_tei != 0xFFF &&
mac_get_hw_nid() == fc_msg.nid &&
mac_get_hw_tei() == fc_msg.dst_tei) {
need_sack = 1;
}
}
return need_sack;
}
static uint32_t bb_cpu_rx_judge_is_mine_sack()
{
uint32_t is_mine_sack = 0;
uint32_t phr[4] = { 0 };
if (BB_CPU_GET_TXDTEI() == PLC_TEI_INVAL) {
return is_mine_sack;
}
/* get phy header */
bb_rf_get_rx_phr(phr);
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_SACK) {
if (mac_get_hw_nid() == fc_msg.nid &&
mac_get_hw_tei() == fc_msg.dst_tei &&
((BB_CPU_GET_PROTO() == PLC_PROTO_TYPE_SG) ?
(BB_CPU_GET_TXDTEI() == fc_msg.src_tei) : 1)) {
is_mine_sack = 1;
}
}
return is_mine_sack;
}
static void bb_cpu_rx_hdl_self_sack(uint32_t timeout)
{
/* there must have a sign need sack = 1 */
IOT_ASSERT(BB_CPU_GET_TXDTEI());
/* stop wait sack timer */
bb_cpu_timer_stop(TIMER_OF_WAIT_SACK);
bb_cpu_clr_evt(BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID);
/* clear tx need sack flag */
BB_CPU_SET_TXDTEI(PLC_TEI_INVAL);
bb_cpu_backfill_tx_desc_sack(timeout);
/* bb cpu trigger mac rx sack done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_SACK_DONE);
}
static uint32_t bb_rf_get_vaild_rx_phr(uint32_t *phr)
{
uint32_t ret = 1;
while (!bb_rf_get_phr_crc_rdy());
bb_rf_get_rx_phr(phr);
if (!bb_rf_get_phr_crc24_err()) {
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_BEACON ||
fc_msg.delimiter == FC_DELIM_SOF) {
if (fc_msg.rf_mcs < PHY_MCS_MAX &&
fc_msg.rf_pb_sz_idx < BLOCK_SIZE_MAX) {
ret = 0;
}
} else {
ret = 0;
}
}
return ret;
}
static void bb_cpu_rx_hdl_listening_sm(uint32_t event_id)
{
uint32_t ret = 0;
if (BB_CPU_EVENT_RX_SIG_ID == event_id) {
/* get sig info and config bb to rx phy header */
ret = bb_cpu_get_sig_and_cfg_bb();
if (!ret) {
/* sig ok cnt increase */
mac_rf_rx_sig_ok_cnt_inc();
bb_cpu_clr_evt(BB_CPU_EVENT_PS_IDLE_ID);
/* bb cpu rx enter wait phy header state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_WAIT_PHR, BB_CPU_ENTER_IDLE_NOR);
/* config timer and wait timeout, rx timeout */
bb_cpu_timer_restart(TIMER_OF_RX, RF_MAC_EIFS_US);
} else {
#if BB_CPU_RX_EXCEPTION_NOTIFY_PLC_CPU
/* sig err, get ring id */
bb_cpu_hw_ring_select(NULL);
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_SIG_ERR);
/* set rx ring complete, fill desc */
bb_cpu_hw_ring_rx_complete_cfg_desc();
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
#endif
/* sig error cnt increase */
mac_rf_rx_sig_err_cnt_inc();
/* timeout reset bb/rf */
bb_cpu_rx_reset();
/* clear out specific unhandled interrupts */
bb_cpu_clr_multi_evt((1 << BB_CPU_EVENT_RX_PHR_ID) |
(1 << BB_CPU_EVENT_PS_IDLE_ID));
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* bb cpu trigger mac rx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_DONE);
}
} else if (BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID == event_id) {
bb_cpu_rx_hdl_self_sack(1);
} else if (BB_CPU_EVENT_RST_ID == event_id ||
BB_CPU_EVENT_RX_ABORT_ID == event_id ||
BB_CPU_EVENT_CMDLIST_DONE_ID == event_id) {
if (BB_CPU_EVENT_CMDLIST_DONE_ID == event_id &&
bb_cpu_mac_judge_next_cmd_is_vld()) {
bb_cpu_printf("rxlisten cmdlist done err\n");
/* next cmd is invaild if cmdlist done,
* otherwise something is error.
*/
IOT_ASSERT(0);
}
if (BB_CPU_EVENT_RX_ABORT_ID == event_id &&
bb_cpu_mac_judge_cur_cmd_need_tx_csma()) {
bb_cpu_printf("rxlisten rx abort but tx csma\n");
/* csma should not appear rx abort event */
IOT_ASSERT(0);
}
/* some case, early stop and rx sig trigger together,
* and rx sig must be cleard after early stop is processed
*/
bb_cpu_clr_multi_evt((1 << BB_CPU_EVENT_RX_SIG_ID) |
/* some case, early stop and rx abort trigger together,
* and rx abort must be cleard after early stop is processed
*/
(1 << BB_CPU_EVENT_RX_ABORT_ID) |
/* some case, early stop and backoff timeout trigger together,
* and backoff timeout must be cleard after early stop is processed
*/
(1 << BB_CPU_EVENT_BACKOFF_TIMEOUT_ID) |
/* some case, early stop and wait rx sack timeout trigger together,
* and wait rx sack timeout must be cleard after early stop is processed
*/
(1 << BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID) |
/* some case, early stop and set power save idle trigger together,
* and set power save idle must be cleard after early stop is processed
*/
(1 << BB_CPU_EVENT_PS_IDLE_ID));
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_RST);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(event_id);
/* send event to global sm, enter reset */
bb_cpu_global_sm(BB_CPU_EVENT_RST_ID);
} else if (BB_CPU_EVENT_BACKOFF_TIMEOUT_ID == event_id) {
/* timeout reset bb/rf */
bb_cpu_rf_reset();
/* config tx cfg in advance on csma */
bb_rf_jesd_reset();
/* bb rf tx switch1 */
bb_rf_tx_switch_step1();
BB_CPU_SET_TXCFG1_VLD(1);
/* clear out specific unhandled interrupts */
bb_cpu_clr_evt(BB_CPU_EVENT_RX_SIG_ID);
bb_cpu_clr_evt(BB_CPU_EVENT_RX_PHR_ID);
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* bb cpu trigger mac backoff complete, cpu2 is ready */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_BBCPU_IS_READY);
} else if (BB_CPU_EVENT_CSMA_TX_CHECK_ID == event_id) {
/* update hwq mpdu pointer */
bb_cpu_csma_check_txq();
} else if (BB_CPU_EVENT_SET_CHANNEL_ID == event_id) {
/* if rx listening state, restart rx with new config */
uint32_t bb_evt = glb_fsm_ctxt.bb_cpu_evt_tmp;
if (!(bb_evt & ((1 << BB_CPU_EVENT_RST_ID) |
(1 << BB_CPU_EVENT_CMDLIST_DONE_ID) |
(1 << BB_CPU_EVENT_RX_ABORT_ID) |
(1 << BB_CPU_EVENT_RX_SIG_ID) |
(1 << BB_CPU_EVENT_BACKOFF_TIMEOUT_ID)))) {
if (!mac_rf_is_pa_disable()) {
/* trigger bb to rx */
bb_cpu_rx_config_start();
}
}
} else if (BB_CPU_EVENT_PS_IDLE_ID == event_id) {
if (mac_rf_get_bb_ps_idle()) {
/* if rx listening state, restart rx with new config */
uint32_t bb_evt = glb_fsm_ctxt.bb_cpu_evt_tmp;
if (!(bb_evt & ((1 << BB_CPU_EVENT_RST_ID) |
(1 << BB_CPU_EVENT_CMDLIST_DONE_ID) |
(1 << BB_CPU_EVENT_RX_ABORT_ID) |
(1 << BB_CPU_EVENT_RX_SIG_ID) |
(1 << BB_CPU_EVENT_BACKOFF_TIMEOUT_ID)))) {
/* reset rf */
bb_cpu_rf_reset();
mac_rf_disable_pa(1);
/* clear sig */
bb_cpu_clr_evt(BB_CPU_EVENT_RX_SIG_ID);
}
} else {
/* trigger bb to rx */
bb_cpu_rx_config_start();
}
} else {
bb_cpu_printf("rxlisten fsm:%d, evt:%d\n",
BB_CPU_GET_RST_FSM(), event_id);
IOT_ASSERT(0);
}
}
static void bb_cpu_rx_update_snr_rssi_info()
{
#if HPLC_BBCPU_CALC_SNR_RSSI
int8_t snr, rssi;
uint8_t rx_gain;
uint16_t raw_snr;
bb_rf_get_snr_rssi(BB_CPU_GET_OPTION(), &snr, &rssi, &rx_gain, &raw_snr);
/* update rx snr */
bb_cpu_hw_ring_snr_set(snr);
bb_cpu_hw_ring_raw_snr_set(raw_snr);
/* update rx rssi */
bb_cpu_hw_ring_rssi_set(rssi);
/* update rx gain */
bb_cpu_hw_ring_rx_gain_set(rx_gain);
#else /* HPLC_BBCPU_CALC_SNR_RSSI */
bb_cpu_hw_ring_raw_snr_rssi_set(bb_rf_get_raw_snr_rssi_reg1(),
bb_rf_get_raw_snr_rssi_reg2(), bb_rf_get_raw_snr_rssi_reg3());
#endif /* HPLC_BBCPU_CALC_SNR_RSSI */
/* update rx ppmhz */
bb_cpu_hw_ring_rx_ppmhz_set(bb_rf_get_evaluate_ppm_hz());
}
static void bb_cpu_rx_hdl_wait_phr_sm(uint32_t event_id)
{
uint32_t ret = 0;
uint32_t phr[4] = { 0 };
uint32_t rx_fl = 0;
uint8_t *rx_buf;
/* BB_CPU_EVENT_RX_PLD_START_ID is regarded as
* BB_CPU_EVENT_RX_TIMEOUT_ID in wait_phr state.
*/
if ((event_id == BB_CPU_EVENT_RX_TIMEOUT_ID) ||
(BB_CPU_EVENT_RX_PLD_START_ID == event_id)) {
#if BB_CPU_RX_EXCEPTION_NOTIFY_PLC_CPU
/* phy header err, get ring id */
bb_cpu_hw_ring_select(NULL);
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_PHR_TIMEOUT);
/* set rx ring complete, fill desc */
bb_cpu_hw_ring_rx_complete_cfg_desc();
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
#endif
/* timeout reset bb/rf */
bb_cpu_rx_reset();
/* clear out specific unhandled interrupts */
bb_cpu_clr_evt(BB_CPU_EVENT_RX_PHR_ID);
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* bb cpu trigger mac rx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_DONE);
} else if (BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID == event_id) {
bb_cpu_rx_hdl_self_sack(1);
} else if (event_id == BB_CPU_EVENT_RX_PHR_ID) {
/* get phy header */
ret = bb_rf_get_vaild_rx_phr(phr);
if (!ret) {
/* update rx phr to hw rx ring */
rx_buf = bb_cpu_hw_ring_select(phr);
/* get phy header info and config bb to rx pld */
if (bb_cpu_cfg_rx_pld_info_to_bb(phr, rx_buf)) {
/* phr ok with pld cnt increase */
mac_rf_rx_phr_ok_with_pld_cnt_inc();
/* calulate fl len */
rx_fl = bb_cpu_calu_rx_fl_from_phr(phr);
IOT_ASSERT(rx_fl != 0);
/* set frame length */
bb_cpu_set_vcs_timer(rx_fl + BB_CPU_VCS_MARGIN);
/* config timer and wait timeout, rx timeout */
bb_cpu_timer_restart(TIMER_OF_RX, rx_fl);
/* need wait pld, bb cpu tx enter wait payload state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_WAIT_PLD,
BB_CPU_ENTER_IDLE_NOR);
/* update rx snr/rssi/rx_gain/ppm */
bb_cpu_rx_update_snr_rssi_info();
} else {
/* update rx snr/rssi/rx_gain/ppm */
bb_cpu_rx_update_snr_rssi_info();
/* timeout reset bb/rf */
bb_cpu_rx_reset();
/* phr ok without pld cnt increase */
mac_rf_rx_phr_ok_without_pld_cnt_inc();
/* only have a phy header ,set cifs */
bb_cpu_set_vcs_timer(RF_MAC_CIFS_US);
bb_cpu_stop_and_clr_rx_timer();
/* bb cpu tx enter rx complete state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_RX_COMPLETE,
BB_CPU_ENTER_IDLE_NOR);
/* set event to rx backfill desc */
bb_cpu_rx_sm(BB_CPU_EVENT_RX_BACKFILL_DESC_ID);
}
} else {
#if BB_CPU_RX_EXCEPTION_NOTIFY_PLC_CPU
/* phy header err, get ring id */
bb_cpu_hw_ring_select(NULL);
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_PHR_ERR);
/* update rx snr/rssi/rx_gain/ppm */
bb_cpu_rx_update_snr_rssi_info();
/* set rx ring complete, fill desc */
bb_cpu_hw_ring_rx_complete_cfg_desc();
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
#endif
/* phr error cnt increase */
mac_rf_rx_phr_err_cnt_inc();
/* timeout reset bb/rf */
bb_cpu_rx_reset();
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* bb cpu trigger mac rx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_DONE);
}
} else if (BB_CPU_EVENT_RST_ID == event_id ||
BB_CPU_EVENT_CMDLIST_DONE_ID == event_id) {
if ((BB_CPU_EVENT_CMDLIST_DONE_ID == event_id) &&
bb_cpu_mac_judge_next_cmd_is_vld()) {
bb_cpu_printf("rxwaitphr cmdlist done err\n");
/* next cmd is invaild if cmdlist done,
* otherwise something is error.
*/
IOT_ASSERT(0);
}
#if BB_CPU_RX_EXCEPTION_NOTIFY_PLC_CPU
/* phy header err, get ring id */
bb_cpu_hw_ring_select(NULL);
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_WAIT_PHR_RESET);
/* set rx ring complete, fill desc */
bb_cpu_hw_ring_rx_complete_cfg_desc();
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
#endif
/* some case, early stop and rx phr trigger together,
* and rx phr must be cleard after early stop is processed
*/
bb_cpu_clr_evt(BB_CPU_EVENT_RX_PHR_ID);
/* some case, early stop and wait sack timeout trigger together,
* and wait sack timeout must be cleard after early stop is processed
*/
bb_cpu_clr_evt(BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID);
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_RST);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(event_id);
/* send event to global sm, enter reset */
bb_cpu_global_sm(BB_CPU_EVENT_RST_ID);
} else if (BB_CPU_EVENT_RX_ABORT_ID == event_id) {
if (bb_cpu_mac_judge_cur_cmd_need_tx_tdma()) {
#if BB_CPU_RX_EXCEPTION_NOTIFY_PLC_CPU
/* phy header err, get ring id */
bb_cpu_hw_ring_select(NULL);
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_WAIT_PHR_RX_ABORT);
/* set rx ring complete, fill desc */
bb_cpu_hw_ring_rx_complete_cfg_desc();
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
#endif
/* some case, rx abort and rx phr trigger together,
* and rx sig must be cleard after rx abort is processed
*/
bb_cpu_clr_evt(BB_CPU_EVENT_RX_PHR_ID);
/* some case, rx abort and wait sack timeout trigger together,
* and wait sack timeout must be cleard after rx abort is processed
*/
bb_cpu_clr_evt(BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID);
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_RST);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(event_id);
/* send event to global sm, enter reset */
bb_cpu_global_sm(BB_CPU_EVENT_RST_ID);
} else {
bb_cpu_printf("rxwaitphr rx abort but tx csma\n");
/* csma should not appear rx abort event */
IOT_ASSERT(0);
}
} else {
bb_cpu_printf("rxwaitphr fsm:%d, evt:%d, vcs:%d\n",
BB_CPU_GET_RST_FSM(), event_id, bb_cpu_mac_get_vcs_sts());
IOT_ASSERT(0);
}
}
static void bb_cpu_add_pld_cnt()
{
if (bb_rf_get_pld_crc24_err()) {
mac_rf_rx_pld_err_cnt_inc();
} else {
mac_rf_rx_pld_ok_cnt_inc();
}
}
static void bb_cpu_rx_hdl_wait_pld_sm(uint32_t event_id)
{
/* stop rx timer */
bb_cpu_stop_and_clr_rx_timer();
if (event_id == BB_CPU_EVENT_RX_TIMEOUT_ID) {
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_WAIT_PLD_TIMEOUT);
/* set rx ring complete, fill desc */
bb_cpu_hw_ring_rx_complete_cfg_desc();
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
/* timeout reset bb/rf */
bb_cpu_rx_reset();
BB_CPU_SET_RX_BUF(NULL);
/* clear out specific unhandled interrupts */
bb_cpu_clr_evt(BB_CPU_EVENT_RX_PLD_START_ID);
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* bb cpu trigger mac rx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_DONE);
/* rx done set vcs timer BB_CPU_VCS_INTERVAL */
bb_cpu_set_vcs_timer(BB_CPU_VCS_INTERVAL);
} else if (event_id == BB_CPU_EVENT_RX_PLD_START_ID) {
if (!BB_CPU_TXRX_USE_DMA) {
uint32_t phr[4] = { 0 };
/* get phy header */
bb_rf_get_rx_phr(phr);
/* start move data */
bb_cpu_get_data_from_bb(phr);
}
/* add pld cnt */
bb_cpu_add_pld_cnt();
/* bb cpu tx enter rx complete state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_RX_COMPLETE, BB_CPU_ENTER_IDLE_NOR);
/* set event to rx backfill desc */
bb_cpu_rx_sm(BB_CPU_EVENT_RX_BACKFILL_DESC_ID);
} else if (BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID == event_id) {
bb_cpu_rx_hdl_self_sack(1);
} else if (BB_CPU_EVENT_RST_ID == event_id ||
BB_CPU_EVENT_CMDLIST_DONE_ID == event_id) {
if ((BB_CPU_EVENT_CMDLIST_DONE_ID == event_id) &&
bb_cpu_mac_judge_next_cmd_is_vld()) {
bb_cpu_printf("rxwaitpld cmdlist done err\n");
/* next cmd is invaild if cmdlist done,
* otherwise something is error.
*/
IOT_ASSERT(0);
}
/* some case, reset/cmdlist done and wait sack timeout trigger together,
* and wait sack timeout must be cleard after rx abort is processed
*/
bb_cpu_clr_evt(BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID);
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_WAIT_PLD_RESET);
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_RST);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(event_id);
/* send event to global sm, enter wait rx complete
* this state need wait BB_CPU_EVENT_RX_PLD_START_ID.
*/
bb_cpu_global_sm(BB_CPU_EVENT_RST_WAIT_RX_COMPLETE_ID);
} else if (BB_CPU_EVENT_RX_ABORT_ID == event_id) {
if (bb_cpu_mac_judge_cur_cmd_need_tx_tdma()) {
/* some case, rx abort and wait sack timeout trigger together,
* and wait sack timeout must be cleard after rx abort is processed
*/
bb_cpu_clr_evt(BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID);
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_WAIT_PLD_RX_ABORT);
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_RST);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(event_id);
/* send event to global sm, enter wait rx complete
* this state need wait BB_CPU_EVENT_RX_PLD_START_ID.
*/
bb_cpu_global_sm(BB_CPU_EVENT_RST_WAIT_RX_COMPLETE_ID);
} else {
bb_cpu_printf("rxwaitpld rx abort but tx csma\n");
/* csma should not appear rx abort event */
IOT_ASSERT(0);
}
} else {
bb_cpu_printf("rxwaitpld fsm:%d, evt:%d\n",
BB_CPU_GET_RST_FSM(), event_id);
IOT_ASSERT(0);
}
}
static void bb_cpu_rx_hdl_rx_complete_sm(uint32_t event_id)
{
if (event_id == BB_CPU_EVENT_RX_BACKFILL_DESC_ID) {
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_RX_SUCCESS);
/* set rx ring complete, fill desc */
bb_cpu_hw_ring_rx_complete_cfg_desc();
/* if here need to wait for rx sack in tx state, do not tx sack */
if (bb_cpu_rx_judge_need_tx_sack()) {
// need tx sack
/* prepare tx sack */
bb_cpu_prepare_tx_sack(phy_rf_get_g_tx_sack_mcs(), INVALID_SNR);
uint32_t span_us = (mac_sched_get_lts() -
bb_cpu_mac_get_rx_pld_start_local_ntb()) / 25;
if (span_us < RF_MAC_TX_RIFS_US) {
iot_delay_us(RF_MAC_TX_RIFS_US - span_us);
}
/* bb cpu trigger bb tx */
bb_cpu_trigger_bb(BB_CPU_TRIGGER_BB_TX);
/* bb cpu set tx to wait sack tx state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_WAIT_SACK_TX_COMPLETE,
BB_CPU_ENTER_IDLE_NOR);
} else {
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
/* bb cpu trigger mac rx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_DONE);
/* rx done set vcs timer BB_CPU_VCS_INTERVAL */
bb_cpu_set_vcs_timer(BB_CPU_VCS_INTERVAL);
if (bb_cpu_rx_judge_is_mine_sack()) {
bb_cpu_rx_hdl_self_sack(0);
}
}
} else if (BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID == event_id) {
bb_cpu_rx_hdl_self_sack(1);
} else if (BB_CPU_EVENT_RST_ID == event_id ||
BB_CPU_EVENT_CMDLIST_DONE_ID == event_id) {
if (BB_CPU_EVENT_CMDLIST_DONE_ID == event_id &&
bb_cpu_mac_judge_next_cmd_is_vld()) {
bb_cpu_printf("rxcomp cmdlist done err\n");
/* next cmd is invaild if cmdlist done,
* otherwise something is error.
*/
IOT_ASSERT(0);
}
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_WAIT_COMPLETE_RESET);
/* set rx ring complete, fill desc */
bb_cpu_hw_ring_rx_complete_cfg_desc();
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_RST);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(event_id);
/* send event to global sm, enter reset */
bb_cpu_global_sm(BB_CPU_EVENT_RST_ID);
} else if (BB_CPU_EVENT_RX_ABORT_ID == event_id) {
if (bb_cpu_mac_judge_cur_cmd_need_tx_tdma()) {
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_WAIT_COMPLETE_RX_ABORT);
/* set rx ring complete, fill desc */
bb_cpu_hw_ring_rx_complete_cfg_desc();
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
/* bb cpu set rx to end state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_RST);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(event_id);
/* send event to global sm, enter reset */
bb_cpu_global_sm(BB_CPU_EVENT_RST_ID);
} else {
bb_cpu_printf("rxcomp rx abort but tx csma\n");
/* csma should not appear rx abort event */
IOT_ASSERT(0);
}
} else {
bb_cpu_printf("rxcomp fsm:%d, evt:%d\n",
BB_CPU_GET_RST_FSM(), event_id);
IOT_ASSERT(0);
}
}
static void bb_cpu_rx_hdl_wait_sack_tx_complete_sm(uint32_t event_id)
{
/* stop rx timer */
bb_cpu_stop_and_clr_rx_timer();
if (event_id == BB_CPU_EVENT_RX_TIMEOUT_ID) {
/* set rx ring status */
bb_cpu_hw_ring_set_tx_sack_status(BB_CPU_RX_RING_TX_SACK_TIMEOUT);
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
/* timeout reset bb/rf */
bb_cpu_rx_reset();
/* clear out specific unhandled interrupts */
bb_cpu_clr_evt(BB_CPU_EVENT_TX_COMP_ID);
/* bb cpu set tx to idle state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* bb cpu trigger mac rx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_DONE);
/* rx done set vcs timer BB_CPU_VCS_INTERVAL */
bb_cpu_set_vcs_timer(BB_CPU_VCS_INTERVAL);
} else if (event_id == BB_CPU_EVENT_TX_COMP_ID) {
/* tx ok cnt increase */
mac_rf_get_tx_ok_without_pld_cnt();
/* set rx ring status */
bb_cpu_hw_ring_set_tx_sack_status(BB_CPU_RX_RING_TX_SACK_SUCCESS);
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
/* bb cpu set tx to idle state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* bb cpu trigger mac rx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_DONE);
/* rx done set vcs timer BB_CPU_VCS_INTERVAL */
bb_cpu_set_vcs_timer(BB_CPU_VCS_INTERVAL);
} else if (BB_CPU_EVENT_RST_ID == event_id ||
BB_CPU_EVENT_CMDLIST_DONE_ID == event_id) {
if (BB_CPU_EVENT_CMDLIST_DONE_ID == event_id &&
bb_cpu_mac_judge_next_cmd_is_vld()) {
bb_cpu_printf("rxwaitsack cmdlist done err\n");
/* next cmd is invaild if cmdlist done,
* otherwise something is error.
*/
IOT_ASSERT(0);
}
/* set rx ring status */
bb_cpu_hw_ring_set_tx_sack_status(BB_CPU_RX_RING_TX_SACK_RESET);
/* bb cpu set rx to idle state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_RST);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(event_id);
/* send event to global sm, enter wait sack tx done */
bb_cpu_global_sm(BB_CPU_EVENT_RST_WAIT_TX_DONE_ID);
} else if (BB_CPU_EVENT_RX_ABORT_ID == event_id) {
if (bb_cpu_mac_judge_cur_cmd_need_tx_tdma()) {
/* set rx ring status */
bb_cpu_hw_ring_set_tx_sack_status(BB_CPU_RX_RING_TX_SACK_RX_ABORT);
/* bb cpu set rx to idle state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_RST);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(event_id);
/* send event to global sm, enter wait sack tx done */
bb_cpu_global_sm(BB_CPU_EVENT_RST_WAIT_TX_DONE_ID);
} else {
bb_cpu_printf("rxwaitsack rx abort but tx csma\n");
/* csma should not appear rx abort event */
IOT_ASSERT(0);
}
} else {
bb_cpu_printf("rxwaitsack fsm:%d, evt:%d\n",
BB_CPU_GET_RST_FSM(), event_id);
IOT_ASSERT(0);
}
}
void bb_cpu_rx_sm(uint32_t event_id)
{
#if BB_CPU_DEBUG_PRINT
if (BB_CPU_EVENT_BACKOFF_TIMEOUT_ID != event_id &&
BB_CPU_EVENT_RX_ABORT_ID != event_id) {
bb_cpu_printf("rx fsm:%d, evt:%d\n",
BB_CPU_GET_RX_FSM(), event_id);
}
#endif
switch (BB_CPU_GET_RX_FSM()) {
case BB_CPU_RX_STATE_LISTENING:
{
bb_cpu_rx_hdl_listening_sm(event_id);
break;
}
case BB_CPU_RX_STATE_WAIT_PHR:
{
bb_cpu_rx_hdl_wait_phr_sm(event_id);
break;
}
case BB_CPU_RX_STATE_WAIT_PLD:
{
bb_cpu_rx_hdl_wait_pld_sm(event_id);
break;
}
case BB_CPU_RX_STATE_RX_COMPLETE:
{
bb_cpu_rx_hdl_rx_complete_sm(event_id);
break;
}
case BB_CPU_RX_STATE_WAIT_SACK_TX_COMPLETE:
{
bb_cpu_rx_hdl_wait_sack_tx_complete_sm(event_id);
break;
}
default:
break;
}
}
static void bb_cpu_rst_trigger_mac(uint32_t rst_reason)
{
if (BB_CPU_TO_RST_IS_RX_ABORT == rst_reason) {
/* clear the reason */
BB_CPU_SET_RST_RS(BB_CPU_TO_RST_IS_INVALID);
/* bb cpu trigger mac rx abort complete */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_ABORT_COMPLETE);
} else if (BB_CPU_TO_RST_IS_TX_ABORT == rst_reason) {
/* clear the reason */
BB_CPU_SET_RST_RS(BB_CPU_TO_RST_IS_INVALID);
/* bb cpu trigger mac to tx abort complete */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_TX_ABORT_COMPLETE);
} else if (BB_CPU_TO_RST_IS_STOP_SCHE == rst_reason) {
/* clear the reason */
BB_CPU_SET_RST_RS(BB_CPU_TO_RST_IS_INVALID);
/* bb cpu trigger mac to reset complete */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_STOP_SCHE_COMPLETE);
} else if (BB_CPU_TO_RST_IS_CMDLIST_DONE == rst_reason) {
/* clear the reason */
BB_CPU_SET_RST_RS(BB_CPU_TO_RST_IS_INVALID);
/* bb cpu trigger mac cmdlist done complete */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_CMSLIST_DONE);
} else {
bb_cpu_printf("rst trg mac fsm:%d, rsn:%d\n",
BB_CPU_GET_RST_FSM(), rst_reason);
IOT_ASSERT(0);
}
}
static void bb_cpu_rst_hdl_idle_sm(uint32_t event_id)
{
uint32_t phr[4] = { 0 };
uint32_t frame_len = 0, prev_state = 0;
if (BB_CPU_EVENT_RST_ID == event_id) {
bb_cpu_rf_reset();
/* some case, early stop and rx start trigger together,
* and rx start must be cleard after early stop is processed
*/
bb_cpu_clr_multi_evt((1 << BB_CPU_EVENT_MAC_RX_START_ID) |
/* some case, rx abort and rx sig trigger together,
* and rx sig must be cleard after rx abort is processed
*/
(1 << BB_CPU_EVENT_RX_SIG_ID) |
/* some case, rx abort and rx phr trigger together,
* and rx sig must be cleard after rx abort is processed
*/
(1 << BB_CPU_EVENT_RX_PHR_ID) |
/* some case, early stop and tx start trigger together,
* and tx start must be cleard after early stop is processed
*/
(1 << BB_CPU_EVENT_MAC_TX_START_ID) |
/* some case, early stop and rx abort trigger together,
* and rx abort must be cleard after early stop is processed
*/
(1 << BB_CPU_EVENT_RX_ABORT_ID) |
/* some case, early stop and set power save idle trigger together,
* and set power save idle must be cleard after early stop is processed
*/
(1 << BB_CPU_EVENT_PS_IDLE_ID));
if (glb_fsm_ctxt.bb_cpu_evt_tmp) {
bb_cpu_printf("rstidle evt:0x%x\n",
glb_fsm_ctxt.bb_cpu_evt_tmp);
IOT_ASSERT(0);
}
/* check need sack or not.
* mabey backfill desc tx ok = 0 and trigger mac
*/
if (BB_CPU_GET_TXDTEI()) {
bb_cpu_rx_hdl_self_sack(1);
}
/* bb cpu set reset to idle state */
BB_CPU_SET_RST_FSM(BB_CPU_RST_STATE_IDLE);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
bb_cpu_rst_trigger_mac(BB_CPU_GET_RST_RS());
} else if (BB_CPU_EVENT_RST_WAIT_TX_DONE_ID == event_id) {
BB_CPU_SET_RST_FSM(BB_CPU_RST_STATE_WAIT_TX_COMPLETE);
bb_rf_get_tx_phr(phr);
bb_cpu_rf_fc_t fc_msg = {0};
bb_cpu_mac_get_msg_from_phr(BB_CPU_GET_PROTO(), phr, &fc_msg);
if (fc_msg.delimiter == FC_DELIM_SACK) {
frame_len = phy_rf_get_g_stf_ltf_fl() + phy_rf_get_g_sig_fl() +
phy_rf_get_g_phr_fl(phy_rf_get_g_tx_sack_mcs());
} else {
rf_tx_mpdu_start *mpdu = (rf_tx_mpdu_start *)BB_CPU_GET_TX_MPDU();
/* come from phr */
frame_len = bb_cpu_calu_tx_fl(phr, mpdu->phr_mcs);
}
/* if cco early stop/cmdlist done/rx abort need reset immediately */
if (mac_get_hw_role() || (BB_CPU_GET_RST_RS() ==
BB_CPU_TO_RST_IS_STOP_SCHE)) {
if (BB_CPU_GET_PREV_STATE() == BB_CPU_STATE_IDLE) {
prev_state = BB_CPU_GET_MORE_PREV_STATE();
} else{
prev_state = BB_CPU_GET_PREV_STATE();
}
if (prev_state == BB_CPU_STATE_RX) {
frame_len = BB_CPU_RESET_RX_IMME;
}
}
/* config timer and wait timeout */
bb_cpu_timer_restart(TIMER_OF_RST, frame_len);
} else if (BB_CPU_EVENT_RST_WAIT_RX_COMPLETE_ID == event_id) {
BB_CPU_SET_RST_FSM(BB_CPU_RST_STATE_WAIT_RX_PLD_START);
bb_rf_get_rx_phr(phr);
/* come form phr */
frame_len = bb_cpu_calu_rx_fl_from_phr(phr);
/* if cco early stop/cmdlist done/rx abort need reset immediately */
if (mac_get_hw_role() || (BB_CPU_GET_RST_RS() ==
BB_CPU_TO_RST_IS_STOP_SCHE)) {
frame_len = BB_CPU_RESET_RX_IMME;
}
/* config timer and wait timeout */
bb_cpu_timer_restart(TIMER_OF_RST, frame_len);
} else {
bb_cpu_printf("rstidle fsm:%d, evt:%d\n",
BB_CPU_GET_RST_FSM(), event_id);
IOT_ASSERT(0);
}
}
static void bb_cpu_rst_hdl_wait_tx_complete_sm(uint32_t event_id)
{
uint32_t prev_state = 0;
if (BB_CPU_EVENT_TX_COMP_ID == event_id ||
BB_CPU_EVENT_RST_TIMEOUT_ID == event_id) {
/* stop reset timer */
bb_cpu_stop_and_clr_rst_timer();
if (BB_CPU_GET_PREV_STATE() == BB_CPU_STATE_IDLE) {
prev_state = BB_CPU_GET_MORE_PREV_STATE();
} else{
prev_state = BB_CPU_GET_PREV_STATE();
}
if (prev_state == BB_CPU_STATE_RX) {
if (BB_CPU_EVENT_TX_COMP_ID == event_id) {
/* tx ok without pld cnt increase */
mac_rf_tx_ok_without_pld_cnt_inc();
/* set rx ring status */
bb_cpu_hw_ring_set_tx_sack_status(BB_CPU_RX_RING_TX_SACK_SUCCESS);
} else {
/* set rx ring status */
bb_cpu_hw_ring_set_tx_sack_status(
BB_CPU_RX_RING_TX_SACK_RESET_TIMEOUT);
}
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
/* bb cpu trigger mac rx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_DONE);
/* rx done set vcs timer BB_CPU_VCS_INTERVAL */
bb_cpu_rxabort_cmdlistdone_set_vcs(BB_CPU_VCS_INTERVAL);
} else if (prev_state == BB_CPU_STATE_TX) {
if (BB_CPU_EVENT_TX_COMP_ID == event_id) {
/* tx ok with pld cnt increase */
mac_rf_tx_ok_with_pld_cnt_inc();
}
/* check need sack or not.
* mabey backfill desc tx ok = 0 and trigger mac
*/
if (BB_CPU_GET_TXDTEI()) {
BB_CPU_SET_TXDTEI(PLC_TEI_INVAL);
bb_cpu_backfill_tx_desc_sack(1);
}
bb_cpu_backfill_tx_desc(0);
/* bb cpu trigger mac tx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_TX_DONE);
} else {
bb_cpu_printf("rstwaittxcomp err, prev fsm:%d\n",
BB_CPU_GET_PREV_STATE());
IOT_ASSERT(0);
}
/* bb cpu set reset to idle state */
BB_CPU_SET_RST_FSM(BB_CPU_RST_STATE_IDLE);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
/* reset bb rf */
bb_cpu_tx_reset();
/* clear tx complete evt */
bb_cpu_clr_evt(BB_CPU_EVENT_TX_COMP_ID);
bb_cpu_rst_trigger_mac(BB_CPU_GET_RST_RS());
} else if (BB_CPU_EVENT_RST_ID == event_id) {
/* this position can only be BB_CPU_TO_RST_IS_TX_ABORT and
* BB_CPU_TO_RST_IS_CMDLIST_DONE, otherwise sometion wrong.
*/
/* set reset reason is early stop */
if (BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_TX_ABORT ||
BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_CMDLIST_DONE) {
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(BB_CPU_EVENT_RST_ID);
} else {
bb_cpu_printf("rstwaittxcomp earlystop err rsn:%d\n",
BB_CPU_GET_RST_RS());
IOT_ASSERT(0);
}
} else if (BB_CPU_EVENT_CMDLIST_DONE_ID == event_id) {
/* this position can only be BB_CPU_TO_RST_IS_TX_ABORT and
* BB_CPU_TO_RST_IS_STOP_SCHE, otherwise sometion wrong.
*/
/* set reset reason is early stop */
if (BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_TX_ABORT) {
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(BB_CPU_EVENT_CMDLIST_DONE_ID);
} else if (BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_STOP_SCHE) {
/* stop schedule, keep reason */
} else {
bb_cpu_printf("rstwaittxcomp cmdlistdone err rsn:%d\n",
BB_CPU_GET_RST_RS());
IOT_ASSERT(0);
}
} else {
bb_cpu_printf("rstwaittxcomp fsm:%d, evt:%d\n",
BB_CPU_GET_RST_FSM(), event_id);
IOT_ASSERT(0);
}
}
static void bb_cpu_rst_hdl_wait_rx_pld_start_sm(uint32_t event_id)
{
if (BB_CPU_EVENT_RX_PLD_START_ID == event_id ||
BB_CPU_EVENT_RST_TIMEOUT_ID == event_id) {
if (BB_CPU_EVENT_RX_PLD_START_ID == event_id) {
if (!BB_CPU_TXRX_USE_DMA) {
uint32_t phr[4] = { 0 };
/* get phy header */
bb_rf_get_rx_phr(phr);
/* start move data */
bb_cpu_get_data_from_bb(phr);
}
/* add pld cnt */
bb_cpu_add_pld_cnt();
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_RX_SUCCESS);
} else {
BB_CPU_SET_RX_BUF(NULL);
/* set rx ring status */
bb_cpu_hw_ring_set_rx_status(BB_CPU_RX_RING_WAIT_PLD_RESET_TIMEOUT);
}
/* check need sack or not.
* mabey backfill desc tx ok = 0 and trigger mac
*/
if (BB_CPU_GET_TXDTEI()) {
bb_cpu_rx_hdl_self_sack(1);
}
/* stop reset timer */
bb_cpu_stop_and_clr_rst_timer();
/* set rx ring complete, fill desc */
bb_cpu_hw_ring_rx_complete_cfg_desc();
/* set ring rx done */
bb_cpu_hw_ring_rx_done_set();
/* bb cpu trigger mac rx done */
bb_cpu_trigger_mac(BB_CPU_TRIGGER_MAC_RX_DONE);
/* rx done set vcs timer BB_CPU_VCS_INTERVAL */
bb_cpu_rxabort_cmdlistdone_set_vcs(BB_CPU_VCS_INTERVAL);
/* reset bb rf */
bb_cpu_rf_reset();
/* clear rx pld start evt */
bb_cpu_clr_evt(BB_CPU_EVENT_RX_PLD_START_ID);
/* bb cpu set reset to idle state */
BB_CPU_SET_RST_FSM(BB_CPU_RST_STATE_IDLE);
/* bb cpu set to idle state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
bb_cpu_rst_trigger_mac(BB_CPU_GET_RST_RS());
} else if (BB_CPU_EVENT_RST_ID == event_id) {
/* this position can only be BB_CPU_TO_RST_IS_RX_ABORT and
* BB_CPU_TO_RST_IS_CMDLIST_DONE, otherwise sometion wrong.
*/
/* set reset reason is early stop */
if (BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_RX_ABORT ||
BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_CMDLIST_DONE) {
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(BB_CPU_EVENT_RST_ID);
} else {
bb_cpu_printf("waitrxpld earlystop err rsn:%d\n",
BB_CPU_GET_RST_RS());
IOT_ASSERT(0);
}
} else if (BB_CPU_EVENT_CMDLIST_DONE_ID == event_id) {
/* this position can only be BB_CPU_TO_RST_IS_RX_ABORT and
* BB_CPU_TO_RST_IS_STOP_SCHE, otherwise sometion wrong.
*/
/* set reset reason is early stop */
if (BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_RX_ABORT) {
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(BB_CPU_EVENT_CMDLIST_DONE_ID);
} else if (BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_STOP_SCHE) {
/* stop schedule, keep reason */
} else {
bb_cpu_printf("waitrxpld cmdlistdone err rsn:%d\n",
BB_CPU_GET_RST_RS());
IOT_ASSERT(0);
}
} else {
bb_cpu_printf("waitrxpld fsm:%d, evt:%d\n",
BB_CPU_GET_RST_FSM(), event_id);
IOT_ASSERT(0);
}
}
static void bb_cpu_reset_sm(uint32_t event_id)
{
#if BB_CPU_DEBUG_PRINT
bb_cpu_printf("rst fsm:%d, evt:%d\n", BB_CPU_GET_RST_FSM(), event_id);
#endif
switch (BB_CPU_GET_RST_FSM()) {
case BB_CPU_RST_STATE_IDLE:
{
bb_cpu_rst_hdl_idle_sm(event_id);
break;
}
case BB_CPU_RST_STATE_WAIT_TX_COMPLETE:
{
bb_cpu_rst_hdl_wait_tx_complete_sm(event_id);
break;
}
case BB_CPU_RST_STATE_WAIT_RX_PLD_START:
{
bb_cpu_rst_hdl_wait_rx_pld_start_sm(event_id);
break;
}
default:
break;
}
}
static void bb_cpu_set_channel()
{
uint32_t channel_id = mac_rf_get_tobe_set_channel_id();
uint32_t channel_freq = phy_rf_get_channel_freq_by_id(
BB_CPU_GET_OPTION(), channel_id);
BB_CPU_SET_CHANNEL(channel_id, channel_freq);
mac_rf_set_channel_success();
}
static void bb_cpu_idle_sm(uint32_t event_id)
{
uint32_t option, proto;
#if BB_CPU_DEBUG_PRINT
if (event_id != BB_CPU_EVENT_MAC_TX_START_ID) {
bb_cpu_printf("idle evt:%d\n", event_id);
}
#endif
switch (event_id) {
case BB_CPU_EVENT_MAC_TX_START_ID:
{
#if ENA_RF_MULTI_CSMA_HWQ_WAR
/* if mpdu is simu, end tx process.
* this usually happens with cmd start.
*/
uint32_t hwqid = bb_cpu_mac_get_cur_hwqid();
if (hwqid >= MAC_RF_QUE_CSMA_0 && hwqid < MAX_ENABLE_CSMA_HWQ) {
if ((uint32_t)&simu_mpdu_tbl[hwqid] == bb_cpu_mac_get_txq_ptr()) {
/* set rf mac tx done */
bb_cpu_mac_set_tx_done();
return;
}
}
#endif
/* hplc and rf asynchronous tx */
if (bb_cpu_async_tx_check()) {
return;
}
/* tx start increase */
mac_rf_tx_start_cnt_inc();
/* bb cpu enter tx state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_TX);
/* set event to fill tx info */
bb_cpu_tx_sm(BB_CPU_EVENT_MAC_TX_FILL_INFO_ID);
break;
}
case BB_CPU_EVENT_MAC_RX_START_ID:
{
/* update txq before rx */
bb_cpu_csma_check_txq();
/* bb cpu enter rx state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_RX);
/* bb cpu tx enter rx listening state */
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_LISTENING, BB_CPU_ENTER_IDLE_NOR);
if (!mac_rf_get_bb_ps_idle()) {
/* trigger bb to rx */
bb_cpu_rx_config_start();
}
break;
}
case BB_CPU_EVENT_WAIT_SACK_TIMEOUT_ID:
{
bb_cpu_rx_hdl_self_sack(1);
break;
}
case BB_CPU_EVENT_CMDLIST_DONE_ID:
{
if (BB_CPU_GET_RST_RS() != BB_CPU_TO_RST_IS_INVALID) {
bb_cpu_printf("idle cmdlistdone err rsn:%d\n", BB_CPU_GET_RST_RS());
IOT_ASSERT(0);
}
/* NOTE: cmdlist done happened, wmac can not trigger rx start interrupt.
* so it is possible to be idle status when cmdList occurs.
* we need haddle cmdlist done event.
*/
bb_cpu_set_rst_reason_by_evt(BB_CPU_EVENT_CMDLIST_DONE_ID);
/* bb cpu enter reset state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_RST);
/* set event to eventid */
bb_cpu_reset_sm(BB_CPU_EVENT_RST_ID);
break;
}
case BB_CPU_EVENT_RST_ID:
case BB_CPU_EVENT_RST_WAIT_TX_DONE_ID:
case BB_CPU_EVENT_RST_WAIT_RX_COMPLETE_ID:
{
/* set reset reason when trigger reset event on idle state */
if (BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_INVALID) {
IOT_ASSERT(BB_CPU_EVENT_RST_ID == event_id);
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(BB_CPU_EVENT_RST_ID);
}
/* bb cpu enter reset state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_RST);
/* set event to eventid */
bb_cpu_reset_sm(event_id);
break;
}
case BB_CPU_EVENT_BB_INIT_ID:
{
option = mac_rf_get_option();
IOT_ASSERT(option < PHY_RF_OPTION_MAX);
bb_rf_jesd_reset();
bb_rf_init(option, 0);
BB_CPU_SET_OPTION(option);
/* init proto */
proto = mac_rf_get_proto();
IOT_ASSERT(proto <= PLC_PROTO_TYPE_RAWDATA);
BB_CPU_SET_PROTO(proto);
/* fl init */
phy_rf_fl_init(option);
/* set channel */
bb_cpu_set_channel();
mac_rf_set_cur_channel_id(BB_CPU_GET_CHANNEL_ID());
mac_rf_set_cur_channel_freq(BB_CPU_GET_CHANNEL_FREQ());
/* set option success */
mac_rf_set_option_success();
break;
}
case BB_CPU_EVENT_TX_ABORT_ID:
{
/* while processing tx complete, tx abort be triggered.
* it is already in idle state, when processing tx abort.
* so need to be added.
*/
if (BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_INVALID) {
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(BB_CPU_EVENT_TX_ABORT_ID);
} else {
bb_cpu_printf("idle tx abort, rsn:%d\n", BB_CPU_GET_RST_RS());
IOT_ASSERT(0);
}
/* bb cpu enter reset state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_RST);
/* set event to eventid */
bb_cpu_reset_sm(BB_CPU_EVENT_RST_ID);
break;
}
case BB_CPU_EVENT_RX_ABORT_ID:
{
/* while processing rx err(sig err/phr err), rx abort be triggered.
* it is already in idle state, when processing rx abort.
* so need to be added.
*/
if (BB_CPU_GET_RST_RS() == BB_CPU_TO_RST_IS_INVALID) {
/* set reset reason */
bb_cpu_set_rst_reason_by_evt(BB_CPU_EVENT_RX_ABORT_ID);
} else {
bb_cpu_printf("idle rx abort, rsn:%d\n", BB_CPU_GET_RST_RS());
IOT_ASSERT(0);
}
/* bb cpu enter reset state */
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_RST);
/* set event to eventid */
bb_cpu_reset_sm(BB_CPU_EVENT_RST_ID);
break;
}
case BB_CPU_EVENT_BACKOFF_TIMEOUT_ID:
{
/* rf mac backoff timer can not stop by sw */
break;
}
default:
bb_cpu_printf("idle err evt:%d\n", event_id);
IOT_ASSERT(0);
break;
}
}
void bb_cpu_global_sm(uint32_t event_id)
{
/* MP mode handle something */
uint32_t on_off, rf_option, freq, tone_num, tone_att;
if (BB_CPU_EVENT_SYNC_SPI_ID == event_id) {
uint16_t spi_addr, spi_value;
mac_rf_get_rf_spi(&spi_addr, &spi_value);
if (mac_rf_get_rf_spi_rw_cfg()) {
/* write */
rf_spi_write(spi_addr, spi_value);
} else {
/* read */
uint16_t value = rf_spi_read(spi_addr);
mac_rf_set_rf_spi(spi_addr, value);
}
mac_rf_set_rf_spi_status(1);
return;
}
/* MP mode handle something */
if (BB_CPU_EVENT_TX_CAL_UPDATE_ID == event_id) {
mac_rf_get_tx_tone_para(&on_off, &rf_option, &tone_num, &tone_att);
bb_rf_update_cali(rf_option);
mac_rf_set_tx_cal_update_status(1);
return;
}
if (BB_CPU_EVENT_TX_TONE_ID == event_id) {
mac_rf_get_tx_tone_para(&on_off, &rf_option, &tone_num, &tone_att);
freq = mac_rf_get_tx_tone_freq();
bb_cpu_printf("txtone of:%d, opt:%d, tnum:%d, frq:%lu\n",
on_off, rf_option, tone_num, freq);
bb_cpu_rf_reset();
bb_rf_jesd_reset();
/* cfg data unsigned */
rf_spi_write(30, 0x101);
/* tx config */
bb_rf_tx_cfg(rf_option, freq);
bb_cpu_update_tx_pwr();
mac_rf_tx_tone(on_off, tone_num, tone_att);
mac_rf_set_tx_tone_status(1);
return;
}
if (BB_CPU_EVENT_SET_CHANNEL_ID == event_id) {
bb_cpu_printf("glb fsm:%d, evt:%d\n", BB_CPU_GET_GLB_FSM(), event_id);
bb_cpu_set_channel();
/* if current fsm is rx listening, need restart rx with new config */
if (!(BB_CPU_GET_GLB_FSM() == BB_CPU_STATE_RX &&
BB_CPU_GET_RX_FSM() == BB_CPU_RX_STATE_LISTENING)) {
return;
}
}
/* process BB_CPU_EVENT_CSMA_TX_CHECK_ID just on rx listening fsm,
* else ignore this event.
*/
if (BB_CPU_EVENT_CSMA_TX_CHECK_ID == event_id &&
!(BB_CPU_GET_GLB_FSM() == BB_CPU_STATE_RX &&
BB_CPU_GET_RX_FSM() == BB_CPU_RX_STATE_LISTENING)) {
bb_cpu_printf("glb fsm:%d, rxfsm:%d, evt:%d\n", BB_CPU_GET_GLB_FSM(),
BB_CPU_GET_RX_FSM(), event_id);
return;
}
/* just need to respond in rx listening state */
if (BB_CPU_EVENT_PS_IDLE_ID == event_id &&
!(BB_CPU_GET_GLB_FSM() == BB_CPU_STATE_RX &&
BB_CPU_GET_RX_FSM() == BB_CPU_RX_STATE_LISTENING)) {
bb_cpu_printf("glb fsm:%d, evt:%d\n", BB_CPU_GET_GLB_FSM(), event_id);
return;
}
switch (BB_CPU_GET_GLB_FSM()) {
case BB_CPU_STATE_IDLE:
{
bb_cpu_idle_sm(event_id);
break;
}
case BB_CPU_STATE_TX:
{
bb_cpu_tx_sm(event_id);
break;
}
case BB_CPU_STATE_RX:
{
bb_cpu_rx_sm(event_id);
break;
}
case BB_CPU_STATE_RST:
{
bb_cpu_reset_sm(event_id);
break;
}
default:
IOT_ASSERT(0);
break;
}
}
void bb_cpu_fsm_main()
{
uint8_t i, j;
uint8_t *bb_cpu_evt;
for(;;) {
/* waitting a valid event */
glb_fsm_ctxt.bb_cpu_evt_tmp = bb_cpu_wait_event(BB_MAX_TIME);
bb_cpu_evt = (uint8_t *)&glb_fsm_ctxt.bb_cpu_evt_tmp;
i = 0;
while (glb_fsm_ctxt.bb_cpu_evt_tmp) {
while (*bb_cpu_evt) {
j = iot_bitops_ffs(*bb_cpu_evt) - 1;
glb_fsm_ctxt.bb_cpu_evt_tmp &= ~(0x1 << (i+ j));
bb_cpu_global_sm(i + j);
}
bb_cpu_evt++;
i += 8;
}
}
}
static void bb_cpu_simu_mpdu_init()
{
#if ENA_RF_MULTI_CSMA_HWQ_WAR
for (uint8_t i = 0; i < MAX_ENABLE_CSMA_HWQ; i++) {
simu_mpdu_tbl[i].notify_hw_tx_done = 0;
simu_mpdu_tbl[i].desc_type = DESC_TYPE_TX_MPDU_START;
simu_mpdu_tbl[i].tx_fl = 0xffffff;
simu_mpdu_tbl[i].next = NULL;
/* simulate mpdu flag */
simu_mpdu_tbl[i].tx_status = NULL;
}
#endif
}
void bb_cpu_fsm_init()
{
int8_t default_power;
BB_CPU_SET_GLB_FSM(BB_CPU_STATE_IDLE);
bb_cpu_set_tx_fsm(BB_CPU_TX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
bb_cpu_set_rx_fsm(BB_CPU_RX_STATE_IDLE, BB_CPU_ENTER_IDLE_NOR);
BB_CPU_SET_RST_FSM(BB_CPU_RST_STATE_IDLE);
BB_CPU_SET_RST_RS(BB_CPU_TO_RST_IS_INVALID);
BB_CPU_SET_TXDTEI(PLC_TEI_INVAL);
BB_CPU_SET_HWQID(MAX_MAC_RF_TXQ_NUM);
BB_CPU_SET_RX_BUF(NULL);
/* set vcs is idle */
bb_cpu_mac_set_vcs_sts_from_isr(0);
/* set isr is vaild */
bb_cpu_set_isr_vaild(1);
/* set option is vaild */
BB_CPU_SET_OPTION(PHY_RF_OPTION_MAX);
bb_cpu_simu_mpdu_init();
phy_rf_get_power(NULL, NULL, &default_power, NULL);
BB_CPU_SET_CUR_TX_PWR(default_power);
/* set txcfg1 vaild */
BB_CPU_SET_TXCFG1_VLD(0);
}
int8_t bb_cpu_get_tx_pwr()
{
return BB_CPU_GET_CUR_TX_PWR();
}
uint32_t bb_cpu_get_proto()
{
return BB_CPU_GET_PROTO();
}