2887 lines
89 KiB
C
2887 lines
89 KiB
C
/****************************************************************************
|
|
|
|
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 "os_types.h"
|
|
#include "os_mem.h"
|
|
#include "os_utils.h"
|
|
#include "os_timer.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_io_api.h"
|
|
#include "iot_system.h"
|
|
#include "iot_oem.h"
|
|
|
|
#include "plc_protocol.h"
|
|
#include "mac_pdev.h"
|
|
#include "mac_vdev.h"
|
|
#include "mac_msg.h"
|
|
#include "mac.h"
|
|
#include "mac_sched_hw.h"
|
|
#include "mac_isr.h"
|
|
#include "mac_status.h"
|
|
#include "iot_bitops_api.h"
|
|
#include "iot_bitmap_api.h"
|
|
#include "iot_board_api.h"
|
|
#include "gpio_mtx.h"
|
|
#include "mac_zc_hw.h"
|
|
#include "mac_zc.h"
|
|
#include "iot_dbglog_parser.h"
|
|
#include "iot_dbglog_api.h"
|
|
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
#include "mac_rf_common_hw.h"
|
|
#endif
|
|
|
|
/* mac zc system debug log level, 0 - disable, others: enable */
|
|
#define MAC_ZC_DBG_LOG_LEVEL 1
|
|
|
|
/* mac zc system self map signal and gpio */
|
|
#define MAC_ZC_SELF_MAP_GPIO_ENA 1
|
|
|
|
/* report repeat collect/phase ntb */
|
|
#define MAC_ZC_GET_RPT_REPEAT_ENA 0
|
|
|
|
/* each capture sw fifo buffer size, unit: 4byte */
|
|
#define MAC_ZC_CAP_SW_FIFO_SIZE 100
|
|
|
|
#define MAC_ZC_COLLECT_BUF_SIZE MAC_ZC_CAP_SW_FIFO_SIZE
|
|
|
|
/* the max gap between two period allowed, unit: ntb */
|
|
#define MAC_ZC_PERIOD_JITTER_GAP_NTB 12500
|
|
|
|
/* default period goldon gap ntb = 20ms */
|
|
#define MAC_ZC_PERIOD_DEF_GOLDON_GAP_NTB 500000
|
|
|
|
/* systick interval period count */
|
|
#define MAC_ZC_SYSTICK_PERIOD_CNT 1
|
|
|
|
/* success collect count */
|
|
#define MAC_ZC_COLLECT_SUCCESS_CNT 32
|
|
|
|
/* success collect margin count */
|
|
#define MAC_ZC_COLLECT_SUCCESS_MARGIN 8
|
|
|
|
/* loss collect margin count */
|
|
#define MAC_ZC_COLLECT_LOSS_MARGIN 4
|
|
|
|
/* get ntb search max count base on reference index */
|
|
#define MAC_ZC_SEARCH_MAX_CNT 7
|
|
|
|
/* in order to ensure that the first effective phase line is always used
|
|
* as the reference phase line, some adjustment may be required for the
|
|
* starting reporting position of the non reference phase line, so as
|
|
* to ensure that the first NTB sample is always after the first sample
|
|
* of the reference phase line.
|
|
* here, the maximum allowable adjustment distance of the starting position
|
|
* of the non reference phase line is defined
|
|
*/
|
|
#define MAC_ZC_NO_REF_PHASE_START_MAX_ADJ_CNT 2
|
|
|
|
/* update ntb and local ts convert info period (ring write count) */
|
|
#define MAC_ZC_NTB_LTS_RECORD_W_CNT_SHITF (7)
|
|
#define MAC_ZC_NTB_LTS_RECORD_W_CNT \
|
|
(1 << MAC_ZC_NTB_LTS_RECORD_W_CNT_SHITF)
|
|
|
|
/* convert local timestamp to ntb timestamp max ppm */
|
|
#define MAC_ZC_CONVERT_TS_PPM_MAX 50
|
|
|
|
/* lts to ntb write flashlog count max */
|
|
#define MAC_ZC_LTS_TO_NTB_LOG_CNT_MAX 3
|
|
|
|
/* mac zc system state machine running tirger event id */
|
|
typedef enum _mac_zc_trigger_id {
|
|
/* trigger id for start zc system request */
|
|
MAC_ZC_TRIG_SYS_START_REQ = 0,
|
|
/* trigger id for stop zc system request */
|
|
MAC_ZC_TRIG_SYS_STOP_REQ = 1,
|
|
/* trigger id for systick interrupt */
|
|
MAC_ZC_TRIG_SYSTICK_INT = 2,
|
|
/* trigger id max */
|
|
MAC_ZC_TRIG_MAX = 3,
|
|
} mac_zc_trigger_id_t;
|
|
|
|
/* mac zc system state machine id */
|
|
typedef enum _mac_zc_state_id {
|
|
/* state for system idle state */
|
|
MAC_ZC_STATE_IDLE = 0,
|
|
/* state for training and wait for system to stabilize */
|
|
MAC_ZC_STATE_TRAINING = 1,
|
|
/* state for train successful */
|
|
MAC_ZC_STATE_TRAINED = 2,
|
|
/* state for collecting */
|
|
MAC_ZC_STATE_COLLECT = 3,
|
|
/* state id max */
|
|
MAC_ZC_STATE_MAX = 4,
|
|
} mac_zc_state_id_t;
|
|
|
|
/* mac zc state machine info */
|
|
typedef struct _mac_zc_sm_info {
|
|
/* mac zc prev state id */
|
|
mac_zc_state_id_t prev_state;
|
|
/* mac zc current state id */
|
|
mac_zc_state_id_t cur_state;
|
|
} mac_zc_sm_info_t;
|
|
|
|
typedef struct _mac_zc_map_info {
|
|
/* capture id */
|
|
uint8_t cap_id;
|
|
/* plc phase id */
|
|
uint8_t phase_id;
|
|
/* hw gpio id */
|
|
uint8_t gpio;
|
|
/* is extern phase gpio */
|
|
uint8_t is_ext;
|
|
} mac_zc_map_info_t;
|
|
|
|
typedef struct _mac_zc_pre_update_info {
|
|
/* current period */
|
|
uint32_t period : 24,
|
|
/* int8_t */
|
|
collect_cnt : 8;
|
|
/* last collect ts before upate */
|
|
uint32_t last_ts;
|
|
/* current update write last ts */
|
|
uint32_t cur_last_ts;
|
|
/* current ring write index */
|
|
uint16_t ring_wr_idx;
|
|
/* indicate collect valid */
|
|
uint16_t is_collect : 1,
|
|
/* reserved */
|
|
rsvd : 15;
|
|
} mac_zc_pre_update_info_t;
|
|
|
|
typedef struct _mac_zc_daemon_info {
|
|
/* all of active collect last timestamp */
|
|
uint32_t last_collect_ts;
|
|
/* enter collect update timestamp */
|
|
uint32_t enter_collect_ts;
|
|
/* exit collect update timestamp */
|
|
uint32_t exit_collect_ts;
|
|
/* collect updata reload count */
|
|
uint8_t collect_reload_cnt;
|
|
/* lts to ntb write flash log count */
|
|
uint8_t lts_to_ntb_log_cnt;
|
|
/* reserved */
|
|
uint16_t rsvd;
|
|
/* daemon pre update collect information */
|
|
mac_zc_pre_update_info_t pre_info[MAC_ZC_HW_CAP_CNT];
|
|
} mac_zc_daemon_info_t;
|
|
|
|
typedef struct _mac_zc_hook_ctxt {
|
|
/* save mac zc system run on os task handle */
|
|
os_task_h *hdl;
|
|
/* save mac zc dsr table address */
|
|
void *dsr_tbl;
|
|
/* save dsr set entry function address */
|
|
mac_zc_dsr_set_entry_fn_t dsr_set_entry;
|
|
/* save dsr event clear function address */
|
|
mac_zc_dsr_clr_fn_t dsr_clr;
|
|
} mac_zc_hook_ctxt_t;
|
|
|
|
typedef struct _mac_zc_nv_info {
|
|
/* indicate support capture bitmap */
|
|
uint16_t ena_cap_bitmap : 6,
|
|
/* indicate input chip hw capture edge, the board hardware will convert all
|
|
* the signals input to the chip to the same edge.
|
|
*/
|
|
cap_edge : 1,
|
|
/* indicate use 2 hw capture collect 1 phase double edge */
|
|
is_double_collect : 1,
|
|
/* indicate collect base on ntb fifo or local fifo */
|
|
is_ntb_collect : 1,
|
|
/* reserved */
|
|
rsvd : 7;
|
|
/* collect buffer size, unit: 4byte */
|
|
uint16_t buf_sz;
|
|
/* save collect data */
|
|
uint32_t *buffer;
|
|
/* mac zc system mapping */
|
|
mac_zc_map_info_t map[MAC_ZC_HW_CAP_CNT];
|
|
} mac_zc_nv_info_t;
|
|
|
|
typedef struct _mac_zc_ring_ctxt {
|
|
/* ring buffer address */
|
|
uint32_t *buf;
|
|
/* ring buffer write index */
|
|
uint16_t wr_idx;
|
|
/* ring buffer size, unit: 4byte */
|
|
uint16_t size : 15,
|
|
/* indicate the ring buffer is full wrap */
|
|
is_full : 1;
|
|
/* wirte bitmap byte size */
|
|
uint16_t wr_bm_sz;
|
|
/* zc ring id */
|
|
uint16_t ring_id : 3,
|
|
/* reserved */
|
|
rsvd : 13;
|
|
/* write buffer valid data bitmap */
|
|
uint8_t *wr_bitmap;
|
|
} mac_zc_ring_ctxt_t;
|
|
|
|
typedef struct _mac_zc_sw_fifo_ctxt {
|
|
/* fifo buffer */
|
|
uint32_t *buf;
|
|
/* fifo size */
|
|
uint8_t size;
|
|
/* fifo write index */
|
|
uint8_t wr_idx;
|
|
/* fifo read index */
|
|
uint8_t rd_idx;
|
|
/* indicate write overflow */
|
|
uint8_t is_overflow : 1,
|
|
/* reserved */
|
|
rsvd : 7;
|
|
} mac_zc_sw_fifo_ctxt_t;
|
|
|
|
typedef struct _mac_zc_collect_info {
|
|
/* collect period, unit: 1ntb */
|
|
uint32_t period : 24,
|
|
/* indicate the phase collect status */
|
|
is_collect : 1,
|
|
/* reuse for collect count */
|
|
collect_cnt : 7;
|
|
/* indicate repeat cap id, if value is self cap id, indicate no repeat
|
|
* connect.
|
|
*/
|
|
uint32_t repeat_id : 3,
|
|
/* reserved */
|
|
rsvd : 29;
|
|
/* last collect timestamp */
|
|
uint32_t last_ts;
|
|
/* ring context */
|
|
mac_zc_ring_ctxt_t ring;
|
|
/* capture sw fifo */
|
|
mac_zc_sw_fifo_ctxt_t ntb_fifo;
|
|
} mac_zc_collect_info_t;
|
|
|
|
typedef struct _mac_zc_systick_info {
|
|
/* systick check period, unit: 1ntb */
|
|
uint32_t check_period : 24,
|
|
/* indicate systick check enable or disable */
|
|
is_ena : 1,
|
|
/* reserved */
|
|
rsvd : 7;
|
|
/* systick last entry ts, unit: 1ntb */
|
|
uint32_t ts;
|
|
/* systick isr collect temp buffer */
|
|
uint32_t isr_buf[MAC_ZC_HW_CAP_BUF_DEPTH];
|
|
} mac_zc_systick_info_t;
|
|
|
|
typedef struct _mac_zc_ntb_lts_record_info {
|
|
/* beacon rx local timestamp */
|
|
uint32_t bcn_rx_lts;
|
|
/* beacon remote tx ntb */
|
|
uint32_t bcn_tx_ntb;
|
|
/* ntb ppm, unit: 1/(1 << PLC_NTB_PPM_SHIFT) */
|
|
int16_t ntb_ppm;
|
|
/* current record plc ppm is valid or not */
|
|
uint16_t is_plc_valid : 1,
|
|
/* current record rf ppm is valid or not */
|
|
is_rf_valid : 1,
|
|
/* reserved */
|
|
rsvd : 14;
|
|
} mac_zc_ntb_lts_record_t;
|
|
|
|
typedef struct _mac_zc_ntb_lts_sync_info {
|
|
/* record info number */
|
|
uint16_t num : 15,
|
|
/* indicate ntb lts sync start or stop */
|
|
is_start : 1;
|
|
/* current record index */
|
|
uint16_t cur_idx;
|
|
/* ntb and local ts convert infomation */
|
|
mac_zc_ntb_lts_record_t *record;
|
|
} mac_zc_ntb_lts_sync_info_t;
|
|
|
|
typedef struct _mac_zc_ctxt {
|
|
/* indicate pdev id */
|
|
uint8_t ref_pdev_id : 2,
|
|
/* indicate mac zc power state */
|
|
is_power_collapsed : 1,
|
|
/* reserved */
|
|
rsvd0 : 5;
|
|
/* reserved */
|
|
uint8_t rsvd1;
|
|
/* reserved */
|
|
uint16_t rsvd2;
|
|
/* collect temp buffer */
|
|
uint32_t collect_buf[MAC_ZC_COLLECT_BUF_SIZE];
|
|
/* systick callback ctxt info */
|
|
mac_zc_systick_info_t systick;
|
|
/* mac zc system hook context */
|
|
mac_zc_hook_ctxt_t hook;
|
|
/* mac zc system nv info */
|
|
mac_zc_nv_info_t nv;
|
|
/* mac zc state information context */
|
|
mac_zc_sm_info_t sm;
|
|
/* mac zc system daemon context */
|
|
mac_zc_daemon_info_t daemon;
|
|
/* mac zc collect ntb and local ts sync information */
|
|
mac_zc_ntb_lts_sync_info_t ntb_lts_sync;
|
|
/* mac zc capture collect conetext */
|
|
mac_zc_collect_info_t collect[MAC_ZC_HW_CAP_CNT];
|
|
} mac_zc_ctxt_t;
|
|
|
|
/* macro define function */
|
|
/**
|
|
* @brief get mac zc ctxt ptr by pdev_id(mac_zc_id)
|
|
* @param id: mac pdev id or mac zc id
|
|
* @retval: mac zc ctxt ptr
|
|
*/
|
|
#define mac_zc_ctxt_get(id) (((id) >= MAC_ZC_NUM_MAX) ? NULL : \
|
|
&g_mac_zc_ctxt[id])
|
|
|
|
/**
|
|
* @brief get mac ctxt collecting status
|
|
* @param ctxt: mac zc ctxt ptr
|
|
* @retval: 1 - collecting, 0 - not collecting
|
|
*/
|
|
#define mac_zc_is_collecting(ctxt) \
|
|
(((mac_zc_ctxt_t *)(ctxt))->sm.cur_state == MAC_ZC_STATE_COLLECT)
|
|
|
|
/* get hw capture support bitmap */
|
|
#define mac_zc_cap_support_bm_get(ctxt) \
|
|
(((mac_zc_ctxt_t *)(ctxt))->nv.ena_cap_bitmap)
|
|
|
|
/* get cap_id is support */
|
|
#define mac_zc_cap_is_support(ctxt, cap_id) \
|
|
(0 != (mac_zc_cap_support_bm_get(ctxt) & (1 << (cap_id))))
|
|
|
|
/* update collect average period */
|
|
#define mac_zc_period_update(src, update) \
|
|
((src) - ((src) >> 3) + ((update) >> 3))
|
|
|
|
#define mac_zc_phase_cap_to_ext(cap_id) \
|
|
((cap_id) + MAC_ZC_PHASE_CNT)
|
|
|
|
#define mac_zc_phase_cap_is_ext(cap_id) \
|
|
(((cap_id) >= MAC_ZC_PHASE_CNT))
|
|
|
|
#define mac_zc_phase_ext_to_cap(cap_ext_id) \
|
|
((cap_ext_id) - MAC_ZC_PHASE_CNT)
|
|
|
|
#define mac_zc_cap_id_to_phase(ctxt, cap_id) \
|
|
(((mac_zc_ctxt_t *)(ctxt))->nv.map[cap_id].phase_id)
|
|
|
|
#define mac_zc_cap_is_repeat(ctxt, cap_id) \
|
|
((((mac_zc_ctxt_t *)(ctxt))->collect[cap_id].repeat_id) != (cap_id))
|
|
|
|
#define mac_zc_phase_id_zc_to_plc(id) \
|
|
((id) - MAC_ZC_PHASE_A + PLC_PHASE_A)
|
|
|
|
#if MAC_ZC_ENABLE
|
|
|
|
static mac_zc_ctxt_t g_mac_zc_ctxt[MAC_ZC_NUM_MAX] = {0};
|
|
|
|
static void mac_zc_state_machine(mac_zc_ctxt_t *ctxt,
|
|
mac_zc_trigger_id_t trig_id);
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
|
|
void mac_zc_dbg_collect_print(uint8_t cap_id, uint8_t num, uint32_t *buf)
|
|
{
|
|
uint8_t i;
|
|
|
|
if ((0 == num) || !buf) {
|
|
return;
|
|
}
|
|
|
|
iot_printf("[zc]cap-%d,num-%d,lts=%u,ntb=%u,buf: ",
|
|
cap_id, num, mac_sched_get_lts(), mac_sched_get_ntb(NULL));
|
|
for (i = 0; i < num; i++) {
|
|
iot_printf("%u, ", buf[i]);
|
|
if (i > 0) {
|
|
uint32_t delta = (uint32_t)(buf[i] - buf[i - 1]);
|
|
if (delta > (MAC_ZC_PERIOD_DEF_GOLDON_GAP_NTB
|
|
+ MAC_ZC_PERIOD_JITTER_GAP_NTB)) {
|
|
iot_printf("\n!!!!error, %u\n", delta);
|
|
}
|
|
}
|
|
}
|
|
iot_printf("\n");
|
|
}
|
|
|
|
#else
|
|
|
|
#define mac_zc_dbg_collect_print(cap_id, num, buf)
|
|
|
|
#endif
|
|
|
|
/* return ntb is larger than base_ntb.
|
|
* 1 - ntb > base_ntb, 0 - ntb <= base_ntb
|
|
*/
|
|
static uint8_t mac_zc_ntb_is_larger_base(uint32_t base_ntb, uint32_t ntb)
|
|
{
|
|
int32_t delta;
|
|
|
|
delta = (int32_t)(ntb - base_ntb);
|
|
|
|
return ((delta > 0) ^ (IOT_ABS(delta) > 0x7FFFFFFF));
|
|
}
|
|
|
|
static int32_t mac_zc_ntb_get_degree(int32_t ntb_d, uint32_t ntb_period)
|
|
{
|
|
int32_t degree;
|
|
|
|
degree = ntb_d * 360;
|
|
degree += (degree >= 0) ? (ntb_period >> 1) : -(ntb_period >> 1);
|
|
degree /= (int32_t)ntb_period;
|
|
|
|
return degree % 360;
|
|
}
|
|
|
|
static uint8_t IRAM_ATTR mac_zc_sw_fifo_elements(mac_zc_sw_fifo_ctxt_t *fifo)
|
|
{
|
|
uint8_t wr_idx = fifo->wr_idx;
|
|
uint8_t rd_idx = fifo->rd_idx;
|
|
|
|
return (uint8_t)((rd_idx > wr_idx) ? (fifo->size + wr_idx - rd_idx)
|
|
: (wr_idx - rd_idx));
|
|
}
|
|
|
|
uint8_t IRAM_ATTR mac_zc_sw_fifo_puts(mac_zc_sw_fifo_ctxt_t *fifo,
|
|
uint32_t *buf, uint8_t num)
|
|
{
|
|
uint8_t cnt, i;
|
|
|
|
cnt = (uint8_t)min(fifo->size - mac_zc_sw_fifo_elements(fifo) - 1, num);
|
|
|
|
for (i = 0; i < cnt; i++) {
|
|
fifo->buf[fifo->wr_idx++] = buf[i];
|
|
if (fifo->wr_idx >= fifo->size) {
|
|
fifo->wr_idx = 0;
|
|
}
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
uint8_t mac_zc_sw_fifo_gets(mac_zc_sw_fifo_ctxt_t *fifo, uint32_t *buf,
|
|
uint8_t num)
|
|
{
|
|
uint8_t cnt, i;
|
|
|
|
cnt = min(mac_zc_sw_fifo_elements(fifo), num);
|
|
|
|
for (i = 0; i < cnt; i++) {
|
|
buf[i] = fifo->buf[fifo->rd_idx++];
|
|
if (fifo->rd_idx >= fifo->size) {
|
|
fifo->rd_idx = 0;
|
|
}
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
void mac_zc_collect_sw_fifo_clr(mac_zc_ctxt_t *ctxt, uint8_t collect_bm)
|
|
{
|
|
uint8_t id;
|
|
|
|
while (collect_bm) {
|
|
id = iot_bitops_ffs(collect_bm) - 1;
|
|
collect_bm &= ~(1 << id);
|
|
|
|
mac_zc_sw_fifo_gets(&ctxt->collect[id].ntb_fifo,
|
|
ctxt->collect_buf, MAC_ZC_COLLECT_BUF_SIZE);
|
|
ctxt->collect[id].ntb_fifo.is_overflow = 0;
|
|
}
|
|
}
|
|
|
|
static uint8_t mac_zc_phase_id_to_cap(mac_zc_ctxt_t *ctxt, uint8_t phase_id,
|
|
uint8_t is_ext)
|
|
{
|
|
uint8_t cap_id;
|
|
mac_zc_map_info_t *map;
|
|
for (cap_id = MAC_ZC_HW_CAP0; cap_id < MAC_ZC_HW_CAP_CNT; cap_id++) {
|
|
map = &ctxt->nv.map[cap_id];
|
|
if ((map->phase_id == phase_id) && (map->is_ext == !!is_ext)) {
|
|
return cap_id;
|
|
}
|
|
}
|
|
|
|
IOT_ASSERT(0);
|
|
return MAC_ZC_HW_CAP_CNT;
|
|
}
|
|
|
|
static void mac_zc_collect_info_reset(mac_zc_ctxt_t *ctxt, uint8_t collect_bm)
|
|
{
|
|
uint8_t id;
|
|
|
|
while (collect_bm) {
|
|
id = iot_bitops_ffs(collect_bm) - 1;
|
|
collect_bm &= ~(1 << id);
|
|
|
|
ctxt->collect[id].period = 0;
|
|
ctxt->collect[id].is_collect = 0;
|
|
ctxt->collect[id].collect_cnt = 0;
|
|
ctxt->collect[id].last_ts = 0;
|
|
ctxt->collect[id].repeat_id = id;
|
|
}
|
|
}
|
|
|
|
static void mac_zc_collect_ring_reset(mac_zc_ctxt_t *ctxt, uint8_t collect_bm)
|
|
{
|
|
uint8_t id;
|
|
|
|
while (collect_bm) {
|
|
id = iot_bitops_ffs(collect_bm) - 1;
|
|
collect_bm &= ~(1 << id);
|
|
|
|
ctxt->collect[id].ring.wr_idx = 0;
|
|
ctxt->collect[id].ring.is_full = 0;
|
|
if (ctxt->collect[id].ring.wr_bitmap) {
|
|
os_mem_set(ctxt->collect[id].ring.wr_bitmap, 0,
|
|
ctxt->collect[id].ring.wr_bm_sz);
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint32_t mac_zc_collect_ring_elements(mac_zc_ring_ctxt_t *ring)
|
|
{
|
|
return iot_bitmap_cbs(ring->wr_bitmap, ring->wr_bm_sz);
|
|
}
|
|
|
|
static uint32_t mac_zc_collect_ring_legal_idx_get(mac_zc_ring_ctxt_t *ring,
|
|
int32_t idx)
|
|
{
|
|
if (idx < 0) {
|
|
idx += ring->size;
|
|
IOT_ASSERT(idx >= 0);
|
|
}
|
|
|
|
if (idx < ring->size) {
|
|
return idx;
|
|
} else {
|
|
return (idx - ring->size);
|
|
}
|
|
}
|
|
|
|
static uint8_t mac_zc_collect_ring_idx_is_valid(mac_zc_ring_ctxt_t *ring,
|
|
uint32_t idx)
|
|
{
|
|
return iot_bitmap_is_set(ring->wr_bitmap, ring->wr_bm_sz, idx + 1);
|
|
}
|
|
|
|
static uint32_t mac_zc_collect_ring_last_idx_get(mac_zc_ring_ctxt_t *ring)
|
|
{
|
|
uint32_t last_idx;
|
|
|
|
if (ring->wr_idx) {
|
|
last_idx = ring->wr_idx - 1;
|
|
} else {
|
|
last_idx = ring->size - 1;
|
|
}
|
|
|
|
IOT_ASSERT(ring->wr_bitmap[last_idx >> 3] & (1 << (last_idx & 0x07)));
|
|
|
|
return last_idx;
|
|
}
|
|
|
|
static uint32_t mac_zc_collect_ring_idx2widx_interval(mac_zc_ring_ctxt_t *ring,
|
|
uint32_t idx)
|
|
{
|
|
if (idx <= ring->wr_idx) {
|
|
return ring->wr_idx - idx;
|
|
} else {
|
|
return ring->size + ring->wr_idx - idx;
|
|
}
|
|
}
|
|
|
|
static void mac_zc_collect_ring_write(mac_zc_ring_ctxt_t *ring, uint32_t wdata)
|
|
{
|
|
uint16_t widx;
|
|
|
|
widx = ring->wr_idx;
|
|
ring->buf[widx] = wdata;
|
|
ring->wr_bitmap[widx >> 3] |= 1 << (widx & 0x07);
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]cap_id:%lu.bm[%d]=0x%02x,wr[%d]=%u\n", ring->ring_id,
|
|
widx >> 3, ring->wr_bitmap[widx >> 3], widx, wdata);
|
|
#endif
|
|
widx++;
|
|
if (widx >= ring->size) {
|
|
ring->is_full = 1;
|
|
widx = 0;
|
|
}
|
|
ring->wr_idx = widx;
|
|
}
|
|
|
|
static uint32_t mac_zc_collect_ref_period_get(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint8_t cap_bm, id;
|
|
|
|
cap_bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
|
|
if (ctxt->collect[id].is_collect) {
|
|
return ctxt->collect[id].period;
|
|
}
|
|
cap_bm &= ~(1 << id);
|
|
}
|
|
|
|
/* at least one of collect is active when this function is called */
|
|
IOT_ASSERT_DUMP(0, (uint32_t *)ctxt, iot_ceil(sizeof(*ctxt), 4));
|
|
return 0;
|
|
}
|
|
|
|
static uint8_t mac_zc_collect_record_is_valid(mac_zc_ctxt_t *ctxt,
|
|
uint32_t ring_idx)
|
|
{
|
|
uint32_t record_idx;
|
|
mac_zc_ntb_lts_record_t *record;
|
|
|
|
if (NULL == ctxt->ntb_lts_sync.record) {
|
|
return 0;
|
|
}
|
|
|
|
record_idx = ring_idx >> MAC_ZC_NTB_LTS_RECORD_W_CNT_SHITF;
|
|
IOT_ASSERT(record_idx < ctxt->ntb_lts_sync.num);
|
|
record = &ctxt->ntb_lts_sync.record[record_idx];
|
|
|
|
return !!(record->is_plc_valid || record->is_rf_valid);
|
|
}
|
|
|
|
static void mac_zc_collect_ntb_lts_record(mac_zc_ctxt_t *ctxt,
|
|
uint32_t ring_idx)
|
|
{
|
|
uint8_t idx, is_rf_valid = 0, is_plc_valid = 0;
|
|
uint64_t cur_ntb64;
|
|
int64_t delta;
|
|
uint32_t chk_period;
|
|
mac_vdev_t *plc_vdev;
|
|
|
|
if (NULL == ctxt->ntb_lts_sync.record) {
|
|
return;
|
|
}
|
|
|
|
/* ring write index to record index */
|
|
idx = (uint8_t)(ring_idx >> MAC_ZC_NTB_LTS_RECORD_W_CNT_SHITF);
|
|
if (idx != ctxt->ntb_lts_sync.cur_idx) {
|
|
cur_ntb64 = mac_sched_get_ntb64(NULL);
|
|
plc_vdev = get_vdev_ptr(ctxt->ref_pdev_id, PLC_DEFAULT_VDEV);
|
|
chk_period = MAC_MS_TO_NTB(vdev_get_bc_period_ms(plc_vdev,
|
|
PHY_PROTO_TYPE_GET()) * 6);
|
|
if (plc_vdev->mac_ppm.ntb_record.last_saved_ntb) {
|
|
delta = cur_ntb64 - plc_vdev->mac_ppm.ntb_record.last_saved_ntb;
|
|
if ((delta > 0) && (delta < chk_period)) {
|
|
is_plc_valid = 1;
|
|
}
|
|
}
|
|
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
mac_rf_vdev_t *rf_vdev;
|
|
|
|
rf_vdev = get_rf_vdev_ptr(ctxt->ref_pdev_id, RF_PDEV_ID,
|
|
plc_vdev->rf_vdev_id);
|
|
|
|
if (!is_plc_valid && rf_vdev->mac_rf_ppm.last_saved_ntb) {
|
|
delta = cur_ntb64 - rf_vdev->mac_rf_ppm.last_saved_ntb;
|
|
if ((delta > 0) && (delta < chk_period)) {
|
|
is_rf_valid = 1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (is_plc_valid) {
|
|
ctxt->ntb_lts_sync.record[idx].ntb_ppm =
|
|
-plc_vdev->mac_ppm.ntb_ppm;
|
|
ctxt->ntb_lts_sync.record[idx].bcn_rx_lts =
|
|
plc_vdev->mac_ppm.ntb_record.last_bcn_local_ts
|
|
- MAC_SCHED_GOLDEN_GAP;
|
|
ctxt->ntb_lts_sync.record[idx].bcn_tx_ntb =
|
|
plc_vdev->mac_ppm.ntb_record.last_bcn_remote_tx_ntb;
|
|
}
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
else if (is_rf_valid) {
|
|
ctxt->ntb_lts_sync.record[idx].ntb_ppm = -rf_vdev->rf_ntb_ppm;
|
|
ctxt->ntb_lts_sync.record[idx].bcn_rx_lts =
|
|
rf_vdev->mac_rf_ppm.last_bcn_local_ts;
|
|
ctxt->ntb_lts_sync.record[idx].bcn_tx_ntb =
|
|
rf_vdev->mac_rf_ppm.last_bcn_remote_tx_ntb;
|
|
}
|
|
#endif
|
|
else {
|
|
ctxt->ntb_lts_sync.record[idx].ntb_ppm =
|
|
-phy_get_cal_ppm_in_pib() << PLC_NTB_PPM_SHIFT;
|
|
os_disable_irq();
|
|
ctxt->ntb_lts_sync.record[idx].bcn_rx_lts = mac_sched_get_lts();
|
|
ctxt->ntb_lts_sync.record[idx].bcn_tx_ntb =
|
|
mac_sched_get_ntb(NULL);
|
|
os_enable_irq();
|
|
}
|
|
ctxt->ntb_lts_sync.cur_idx = idx;
|
|
ctxt->ntb_lts_sync.record[idx].is_plc_valid = is_plc_valid;
|
|
ctxt->ntb_lts_sync.record[idx].is_rf_valid = is_rf_valid;
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 1)
|
|
iot_printf("[zc]ntb_lts_sync. idx:%d,lts:%u,ntb:%u,ppm:%d,"
|
|
"vaild:%d-%d\n",
|
|
ctxt->ntb_lts_sync.cur_idx,
|
|
ctxt->ntb_lts_sync.record[idx].bcn_rx_lts,
|
|
ctxt->ntb_lts_sync.record[idx].bcn_tx_ntb,
|
|
ctxt->ntb_lts_sync.record[idx].ntb_ppm, is_plc_valid, is_rf_valid);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void mac_zc_collect_lts_to_ntb(mac_zc_ctxt_t *ctxt, uint32_t ring_idx,
|
|
uint32_t *lts_buf, uint32_t len, uint32_t *ntb_buf)
|
|
{
|
|
uint32_t i, record_idx;
|
|
int64_t delta, ntb_ppm;
|
|
mac_zc_ntb_lts_record_t *record;
|
|
|
|
if ((0 == len) || !lts_buf || !ntb_buf) {
|
|
return;
|
|
}
|
|
|
|
record_idx = ring_idx >> MAC_ZC_NTB_LTS_RECORD_W_CNT_SHITF;
|
|
IOT_ASSERT(record_idx < ctxt->ntb_lts_sync.num);
|
|
record = &ctxt->ntb_lts_sync.record[record_idx];
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]lts_to_ntb. remote_ntb:%u, local_ts:%u, ppm:%d\n",
|
|
record->bcn_tx_ntb, record->bcn_rx_lts, record->ntb_ppm);
|
|
iot_printf("[zc]lts_to_ntb. lts: ");
|
|
for (i = 0; i < len; i++) {
|
|
iot_printf("%u, ", lts_buf[i]);
|
|
}
|
|
iot_printf("\n");
|
|
#endif
|
|
|
|
record_idx = lts_buf[0]; /* reuse record_idx save start lts */
|
|
ntb_ppm = record->ntb_ppm;
|
|
if (IOT_ABS(ntb_ppm) > (MAC_ZC_CONVERT_TS_PPM_MAX
|
|
<< PLC_NTB_PPM_SHIFT)) {
|
|
ntb_ppm = (ntb_ppm < 0) ? -(MAC_ZC_CONVERT_TS_PPM_MAX
|
|
<< PLC_NTB_PPM_SHIFT) : (MAC_ZC_CONVERT_TS_PPM_MAX
|
|
<< PLC_NTB_PPM_SHIFT);
|
|
}
|
|
|
|
/* ntb1 = (lts1 - lts0)/(ppm/2^20 + 1) + ntb0 */
|
|
if (ntb_ppm) {
|
|
ntb_ppm += (1 << (PPM_CALC_MILLION_SHIFT + PLC_NTB_PPM_SHIFT));
|
|
for (i = 0; i < len; i++) {
|
|
delta = (int64_t)(lts_buf[i] - record->bcn_rx_lts)
|
|
<< (PPM_CALC_MILLION_SHIFT + PLC_NTB_PPM_SHIFT);
|
|
ntb_buf[i] = delta / ntb_ppm + record->bcn_tx_ntb;
|
|
}
|
|
} else {
|
|
delta = record->bcn_tx_ntb - record->bcn_rx_lts;
|
|
for (i = 0; i < len; i++) {
|
|
ntb_buf[i] = lts_buf[i] + delta;
|
|
}
|
|
}
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]lts_to_ntb. ntb: ");
|
|
for (i = 0; i < len; i++) {
|
|
iot_printf("%u, ", ntb_buf[i]);
|
|
}
|
|
iot_printf("\n");
|
|
#endif
|
|
|
|
if (ctxt->daemon.lts_to_ntb_log_cnt < MAC_ZC_LTS_TO_NTB_LOG_CNT_MAX) {
|
|
ring_idx = (ring_idx & 0xFFFF) | ((uint32_t)record->is_plc_valid << 16)
|
|
| ((uint32_t)record->is_rf_valid << 17);
|
|
iot_dbglog_input(PLC_MAC_ZC_MID, DBGLOG_ERR, IOT_MAC_ZC_LTS_TO_NTB_ID,
|
|
6, ring_idx, record->bcn_rx_lts, record->bcn_tx_ntb,
|
|
record->ntb_ppm, record_idx, ntb_buf[0]);
|
|
ctxt->daemon.lts_to_ntb_log_cnt++;
|
|
}
|
|
}
|
|
|
|
static void mac_zc_collect_ntb_to_lts(mac_zc_ctxt_t *ctxt, uint32_t ring_idx,
|
|
uint32_t *ntb_buf, uint32_t len, uint32_t *lts_buf)
|
|
{
|
|
uint32_t i, record_idx;
|
|
int32_t delta, fix_delta;
|
|
int16_t ntb_ppm;
|
|
mac_zc_ntb_lts_record_t *record;
|
|
|
|
if ((0 == len) || !lts_buf || !ntb_buf) {
|
|
return;
|
|
}
|
|
|
|
record_idx = ring_idx >> MAC_ZC_NTB_LTS_RECORD_W_CNT_SHITF;
|
|
IOT_ASSERT(record_idx < ctxt->ntb_lts_sync.num);
|
|
record = &ctxt->ntb_lts_sync.record[record_idx];
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]ntb_to_lts. remote_ntb:%u, local_ts:%u, ppm:%d\n",
|
|
record->bcn_tx_ntb, record->bcn_rx_lts, record->ntb_ppm);
|
|
iot_printf("[zc]ntb_to_lts. ntb: ");
|
|
for (i = 0; i < len; i++) {
|
|
iot_printf("%u, ", ntb_buf[i]);
|
|
}
|
|
iot_printf("\n");
|
|
#endif
|
|
|
|
ntb_ppm = record->ntb_ppm;
|
|
if (IOT_ABS(ntb_ppm) > (MAC_ZC_CONVERT_TS_PPM_MAX
|
|
<< PLC_NTB_PPM_SHIFT)) {
|
|
ntb_ppm = (ntb_ppm < 0) ? -(MAC_ZC_CONVERT_TS_PPM_MAX
|
|
<< PLC_NTB_PPM_SHIFT) : (MAC_ZC_CONVERT_TS_PPM_MAX
|
|
<< PLC_NTB_PPM_SHIFT);
|
|
}
|
|
|
|
/* lts1 = delta_ntb + delta_ntb * ppm + lts0 */
|
|
if (ntb_ppm) {
|
|
for (i = 0; i < len; i++) {
|
|
delta = ntb_buf[i] - record->bcn_tx_ntb;
|
|
fix_delta = (int32_t)(((int64_t)delta * ntb_ppm)
|
|
>> (PPM_CALC_MILLION_SHIFT + PLC_NTB_PPM_SHIFT));
|
|
lts_buf[i] = delta + fix_delta + record->bcn_rx_lts;
|
|
}
|
|
} else {
|
|
delta = record->bcn_rx_lts - record->bcn_tx_ntb;
|
|
for (i = 0; i < len; i++) {
|
|
lts_buf[i] = ntb_buf[i] + delta;
|
|
}
|
|
}
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]ntb_to_lts. lts: ");
|
|
for (i = 0; i < len; i++) {
|
|
iot_printf("%u, ", lts_buf[i]);
|
|
}
|
|
iot_printf("\n");
|
|
#endif
|
|
}
|
|
|
|
static void mac_zc_dsr_hw(void)
|
|
{
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("%s. %u.\n",
|
|
__FUNCTION__, mac_sched_get_lts());
|
|
#endif
|
|
}
|
|
|
|
static uint8_t mac_zc_phase_is_active(mac_zc_ctxt_t *ctxt, uint8_t phase_id)
|
|
{
|
|
uint8_t id, ext_id;
|
|
|
|
id = mac_zc_phase_id_to_cap(ctxt, phase_id, 0);
|
|
|
|
if (ctxt->nv.is_double_collect) {
|
|
ext_id = mac_zc_phase_cap_to_ext(id);
|
|
return (ctxt->collect[id].is_collect
|
|
&& ctxt->collect[ext_id].is_collect);
|
|
} else {
|
|
return mac_zc_cap_is_support(ctxt, id)
|
|
? ctxt->collect[id].is_collect : 0;
|
|
}
|
|
}
|
|
|
|
static uint32_t mac_zc_phase_period_get(mac_zc_ctxt_t *ctxt, uint8_t phase_id)
|
|
{
|
|
uint8_t id;
|
|
|
|
if (mac_zc_phase_is_active(ctxt, phase_id)) {
|
|
id = mac_zc_phase_id_to_cap(ctxt, phase_id, 0);
|
|
|
|
return ctxt->collect[id].period;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static void mac_zc_set_event(mac_zc_ctxt_t * ctxt)
|
|
{
|
|
uint8_t id;
|
|
uint32_t status;
|
|
mac_vdev_t *vdev;
|
|
|
|
if (!mac_zc_is_collecting(ctxt)) {
|
|
return;
|
|
}
|
|
|
|
vdev = get_vdev_ptr(ctxt->ref_pdev_id, PLC_DEFAULT_VDEV);
|
|
|
|
if (vdev && vdev->start_cfg.mac_zc_status_rpt_func) {
|
|
status = 0;
|
|
for (id = MAC_ZC_PHASE_A; id < MAC_ZC_PHASE_CNT; id++) {
|
|
status |= mac_zc_phase_is_active(ctxt, id) << id;
|
|
}
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]status_rpt_event: 0x%02x\n", status);
|
|
#endif
|
|
vdev->start_cfg.mac_zc_status_rpt_func(
|
|
vdev->start_cfg.mac_callback_arg, status);
|
|
}
|
|
|
|
mac_status_add_zc_event_cnt();
|
|
}
|
|
|
|
static void mac_zc_dsr_systick(void)
|
|
{
|
|
uint8_t id;
|
|
mac_zc_ctxt_t *ctxt;
|
|
|
|
for (id = 0; id < MAC_ZC_NUM_MAX; id++) {
|
|
ctxt = mac_zc_ctxt_get(id);
|
|
if (ctxt) {
|
|
mac_zc_state_machine(ctxt, MAC_ZC_TRIG_SYSTICK_INT);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void mac_zc_set_hook(mac_zc_ctxt_t *ctxt, void *task_hdl, void *dsr_tbl,
|
|
void *dsr_set_fn, void *dsr_clr_fn)
|
|
{
|
|
IOT_ASSERT(ctxt);
|
|
|
|
ctxt->hook.hdl = task_hdl;
|
|
ctxt->hook.dsr_tbl = dsr_tbl;
|
|
ctxt->hook.dsr_set_entry = (mac_zc_dsr_set_entry_fn_t)dsr_set_fn;
|
|
ctxt->hook.dsr_clr = (mac_zc_dsr_clr_fn_t)dsr_clr_fn;
|
|
}
|
|
|
|
static uint32_t mac_zc_collect_info_init(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint8_t id, offset, cap_bm;
|
|
uint32_t ring_sz, wr_bm_sz;
|
|
mac_zc_collect_info_t *collect;
|
|
|
|
cap_bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
if (0 == cap_bm) {
|
|
//IOT_ASSERT(cap_bm);
|
|
return ERR_NOSUPP;
|
|
}
|
|
|
|
ring_sz = ctxt->nv.buf_sz / iot_bitops_cbs(cap_bm);
|
|
wr_bm_sz = iot_ceil(ring_sz, 8);
|
|
offset = 0;
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id - MAC_ZC_HW_CAP0];
|
|
os_mem_set(collect, 0, sizeof(*collect));
|
|
|
|
/* init sw fifo info */
|
|
collect->ntb_fifo.buf = os_mem_malloc(PLC_MAC_ZC_MID,
|
|
MAC_ZC_CAP_SW_FIFO_SIZE * sizeof(uint32_t));
|
|
if (NULL == collect->ntb_fifo.buf) {
|
|
IOT_ASSERT(0);
|
|
return ERR_NOMEM;
|
|
}
|
|
collect->ntb_fifo.size = MAC_ZC_CAP_SW_FIFO_SIZE;
|
|
|
|
collect->ring.ring_id = id;
|
|
collect->ring.buf = ctxt->nv.buffer + (offset * ring_sz);
|
|
collect->ring.size = ring_sz;
|
|
collect->ring.wr_bitmap = os_mem_malloc(PLC_MAC_ZC_MID, wr_bm_sz);
|
|
if (NULL == collect->ring.wr_bitmap) {
|
|
IOT_ASSERT(0);
|
|
return ERR_NOMEM;
|
|
}
|
|
collect->ring.wr_bm_sz = wr_bm_sz;
|
|
offset++;
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]id:%d,ring:0x%08x,size:%u\n",
|
|
id, (uint32_t)collect->ring.buf, collect->ring.size);
|
|
#endif
|
|
}
|
|
|
|
if (ctxt->nv.is_ntb_collect) {
|
|
ctxt->ntb_lts_sync.num = 0;
|
|
ctxt->ntb_lts_sync.record = NULL;
|
|
} else {
|
|
ctxt->ntb_lts_sync.num = iot_ceil(ring_sz,
|
|
MAC_ZC_NTB_LTS_RECORD_W_CNT);
|
|
ctxt->ntb_lts_sync.record = os_mem_malloc(PLC_MAC_ZC_MID,
|
|
ctxt->ntb_lts_sync.num * sizeof(*ctxt->ntb_lts_sync.record));
|
|
if (NULL == ctxt->ntb_lts_sync.record) {
|
|
IOT_ASSERT(0);
|
|
return ERR_NOMEM;
|
|
}
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
static void mac_zc_system_status_log(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint8_t id;
|
|
uint16_t offset, size;
|
|
char *str_buf;
|
|
|
|
str_buf = (char *)ctxt->collect_buf;
|
|
size = sizeof(ctxt->collect_buf);
|
|
|
|
offset = iot_snprintf(str_buf, size, "zc:sts-%d-ena:0x%x-",
|
|
ctxt->sm.cur_state, ctxt->nv.ena_cap_bitmap);
|
|
|
|
for (id = MAC_ZC_HW_CAP0; id < MAC_ZC_HW_CAP_CNT; id++) {
|
|
offset += iot_snprintf(str_buf + offset, size - offset,
|
|
"[%d:%d:%d:%d-%d]",
|
|
id,
|
|
ctxt->nv.map[id].phase_id,
|
|
ctxt->nv.map[id].gpio,
|
|
ctxt->nv.map[id].is_ext,
|
|
ctxt->collect[id].is_collect);
|
|
}
|
|
|
|
offset += iot_snprintf(str_buf + offset, size - offset,
|
|
"-%d", ctxt->is_power_collapsed);
|
|
|
|
iot_printf("%s\n", str_buf);
|
|
}
|
|
|
|
static void mac_zc_system_start(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint32_t id;
|
|
|
|
iot_printf("zc:sys_start-0x%x\n", (uint32_t)ctxt);
|
|
|
|
/* clear dsr event */
|
|
|
|
/* re-config mac zc hw */
|
|
mac_zc_hw_init(0, (uint8_t)ctxt->nv.cap_edge);
|
|
|
|
/* enable mac zc dsr */
|
|
ctxt->hook.dsr_set_entry(ctxt->hook.dsr_tbl, MAC_DSR_ZERO_CROSS_ID,
|
|
mac_zc_dsr_hw);
|
|
/* clear dsr event */
|
|
ctxt->hook.dsr_clr(MAC_DSR_ZERO_CROSS_ID);
|
|
|
|
/* enable mac zc systick dsr */
|
|
ctxt->hook.dsr_set_entry(ctxt->hook.dsr_tbl, MAC_DSR_ZC_SYSTIC_TRIG_CB_ID,
|
|
mac_zc_dsr_systick);
|
|
/* clear dsr event */
|
|
ctxt->hook.dsr_clr(MAC_DSR_ZC_SYSTIC_TRIG_CB_ID);
|
|
|
|
for (id = MAC_ZC_HW_CAP0; id < MAC_ZC_HW_CAP_CNT; id++) {
|
|
if (mac_zc_cap_is_support(ctxt, id)) {
|
|
/* clear hw capture data buffer */
|
|
mac_zc_hw_cap_data_clr(id);
|
|
/* enable mac zc hw capture */
|
|
mac_zc_hw_cap_enable_set(id + MAC_ZC_HW_CAP0, 1);
|
|
/* clear collect sw fifo buffer */
|
|
mac_zc_collect_sw_fifo_clr(ctxt, 1 << id);
|
|
/* reset collect ring buffer */
|
|
mac_zc_collect_ring_reset(ctxt, 1 << id);
|
|
/* reset collect context info */
|
|
mac_zc_collect_info_reset(ctxt, 1 << id);
|
|
}
|
|
}
|
|
|
|
ctxt->ntb_lts_sync.cur_idx = (uint16_t)(-1);
|
|
#if MAC_ZC_START_FOLLOW_VDEV
|
|
ctxt->ntb_lts_sync.is_start = ctxt->nv.is_ntb_collect ? 1 : 0;
|
|
#else
|
|
ctxt->ntb_lts_sync.is_start = 1;
|
|
#endif
|
|
|
|
/* enable systick */
|
|
ctxt->systick.is_ena = 1;
|
|
/* set systick check period */
|
|
ctxt->systick.check_period = (MAC_ZC_PERIOD_DEF_GOLDON_GAP_NTB
|
|
* MAC_ZC_SYSTICK_PERIOD_CNT) + MAC_ZC_PERIOD_JITTER_GAP_NTB;
|
|
|
|
ctxt->daemon.lts_to_ntb_log_cnt = 0;
|
|
}
|
|
|
|
static void mac_zc_system_stop(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint32_t id;
|
|
|
|
iot_printf("zc:sys_stop-0x%x\n", (uint32_t)ctxt);
|
|
|
|
/* stop daemon */
|
|
|
|
ctxt->systick.is_ena = 0;
|
|
/* disable isr */
|
|
for (id = MAC_ZC_HW_CAP0; id < MAC_ZC_HW_CAP_CNT; id++) {
|
|
/* disable mac zc hw capture */
|
|
mac_zc_hw_cap_enable_set(id + MAC_ZC_HW_CAP0, 0);
|
|
/* disable isr */
|
|
mac_isr_ext1_disable(id + MAC_ISR_EXT1_ZC0_CAP_ID);
|
|
}
|
|
|
|
/* clear dsr event */
|
|
ctxt->hook.dsr_clr(MAC_DSR_ZERO_CROSS_ID);
|
|
ctxt->hook.dsr_clr(MAC_DSR_ZC_SYSTIC_TRIG_CB_ID);
|
|
/* disable dsr */
|
|
ctxt->hook.dsr_set_entry(ctxt->hook.dsr_tbl, MAC_DSR_ZERO_CROSS_ID, NULL);
|
|
ctxt->hook.dsr_set_entry(ctxt->hook.dsr_tbl, MAC_DSR_ZC_SYSTIC_TRIG_CB_ID,
|
|
NULL);
|
|
}
|
|
|
|
/* 0 - fail, 1 - success */
|
|
static uint8_t mac_zc_collect_ring_widx_check(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint8_t id, cap_bm;
|
|
uint32_t min_idx, max_idx, delta;
|
|
mac_zc_collect_info_t *collect;
|
|
|
|
min_idx = 0xFFFFFFFF;
|
|
max_idx = 0;
|
|
cap_bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
|
|
if (!collect->is_collect) {
|
|
continue;
|
|
}
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]status_chk-%d,is_collect:%d,idx:%u\n",
|
|
id, collect->is_collect, collect->ring.wr_idx);
|
|
#endif
|
|
if (max_idx < collect->ring.wr_idx) {
|
|
max_idx = collect->ring.wr_idx;
|
|
}
|
|
|
|
if (min_idx > collect->ring.wr_idx) {
|
|
min_idx = collect->ring.wr_idx;
|
|
}
|
|
|
|
delta = (uint32_t)(max_idx - min_idx);
|
|
if (delta > (collect->ring.size >> 1)) {
|
|
delta = min_idx + collect->ring.size - max_idx;
|
|
}
|
|
|
|
if (delta > 1) {
|
|
IOT_ASSERT_DUMP(0, (uint32_t *)ctxt, iot_ceil(sizeof(*ctxt), 4));
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* update ntb lts convert sync info */
|
|
mac_zc_collect_ntb_lts_record(ctxt, min_idx);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static uint8_t mac_zc_phase_repeat_get(mac_zc_ctxt_t *ctxt, uint8_t phase_id)
|
|
{
|
|
uint8_t cap_id;
|
|
|
|
cap_id = mac_zc_phase_id_to_cap(ctxt, phase_id, 0);
|
|
|
|
if (!mac_zc_cap_is_support(ctxt, cap_id)) {
|
|
return phase_id;
|
|
}
|
|
|
|
if (!ctxt->collect[cap_id].is_collect) {
|
|
if (ctxt->nv.is_double_collect) {
|
|
/* check ext cap id */
|
|
cap_id = mac_zc_phase_cap_to_ext(cap_id);
|
|
if (!ctxt->collect[cap_id].is_collect) {
|
|
cap_id = MAC_ZC_HW_CAP_CNT;
|
|
}
|
|
} else {
|
|
cap_id = MAC_ZC_HW_CAP_CNT;
|
|
}
|
|
}
|
|
|
|
return (MAC_ZC_HW_CAP_CNT == cap_id) ? phase_id
|
|
: mac_zc_cap_id_to_phase(ctxt, ctxt->collect[cap_id].repeat_id);
|
|
}
|
|
|
|
static void mac_zc_collect_repeat_set(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint8_t chk_id, chk_bm, tmp_id, tmp_bm;
|
|
int16_t ntb_jitter_degree, chk_degree;
|
|
mac_zc_collect_info_t *chk_collect, *base_collect;
|
|
|
|
chk_bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
if (ctxt->nv.is_double_collect) {
|
|
chk_bm &= (1 << MAC_ZC_PHASE_CNT) - 1;
|
|
}
|
|
|
|
/* get all active collect */
|
|
tmp_bm = chk_bm;
|
|
while (tmp_bm) {
|
|
tmp_id = iot_bitops_ffs(tmp_bm) - 1;
|
|
tmp_bm &= ~(1 << tmp_id);
|
|
if (!ctxt->collect[tmp_id].is_collect) {
|
|
chk_bm &= ~(1 << tmp_id);
|
|
}
|
|
}
|
|
if (0 == chk_bm) {
|
|
return;
|
|
}
|
|
|
|
base_collect = &ctxt->collect[iot_bitops_ffs(chk_bm) - 1];
|
|
ntb_jitter_degree = mac_zc_ntb_get_degree(MAC_ZC_PERIOD_JITTER_GAP_NTB,
|
|
base_collect->period);
|
|
|
|
while (chk_bm) {
|
|
chk_id = iot_bitops_fls(chk_bm) - 1;
|
|
chk_bm &= ~(1 << chk_id);
|
|
chk_collect = &ctxt->collect[chk_id];
|
|
|
|
tmp_bm = chk_bm;
|
|
while (tmp_bm) {
|
|
tmp_id = iot_bitops_ffs(tmp_bm) - 1;
|
|
tmp_bm &= ~(1 << tmp_id);
|
|
base_collect = &ctxt->collect[tmp_id];
|
|
|
|
chk_degree = mac_zc_ntb_get_degree((int32_t)(base_collect->last_ts
|
|
- chk_collect->last_ts), chk_collect->period);
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]repeat. chk[%d]-%u, base[%d]-%u, period:%d, "
|
|
"degree:%d-%d\n",
|
|
chk_id, chk_collect->last_ts,
|
|
tmp_id, base_collect->last_ts, chk_collect->period,
|
|
ntb_jitter_degree, chk_degree);
|
|
#endif
|
|
if (IOT_ABS(chk_degree) <= IOT_ABS(ntb_jitter_degree)) {
|
|
chk_collect->repeat_id = tmp_id;
|
|
} else {
|
|
/* set to self collect id */
|
|
chk_collect->repeat_id = chk_id;
|
|
}
|
|
|
|
iot_printf("zc:repeat. cap %d-%d. ",
|
|
chk_id, chk_collect->repeat_id);
|
|
if (ctxt->nv.is_double_collect) {
|
|
tmp_id = mac_zc_phase_cap_to_ext(chk_id);
|
|
ctxt->collect[tmp_id].repeat_id =
|
|
mac_zc_phase_cap_to_ext(chk_collect->repeat_id);
|
|
iot_printf("%d-%d", tmp_id, ctxt->collect[tmp_id].repeat_id);
|
|
}
|
|
iot_printf("\n");
|
|
|
|
if (chk_collect->repeat_id != chk_id) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* set collect status to active or inactive */
|
|
static uint8_t mac_zc_collect_status_set(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint8_t id, bm, collect_bm, loss_bm, restore_bm;
|
|
uint16_t base_idx;
|
|
int32_t delta;
|
|
uint32_t max_ts, min_ts;
|
|
mac_zc_collect_info_t *collect;
|
|
|
|
collect_bm = 0;
|
|
loss_bm = 0;
|
|
restore_bm = 0;
|
|
bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
while (bm) {
|
|
id = iot_bitops_ffs(bm) - 1;
|
|
bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
if (collect->is_collect) {
|
|
if (collect->collect_cnt <= MAC_ZC_COLLECT_LOSS_MARGIN) {
|
|
loss_bm |= 1 << id;
|
|
} else {
|
|
collect_bm |= 1 << id;
|
|
}
|
|
} else {
|
|
if (collect->collect_cnt >= (MAC_ZC_COLLECT_SUCCESS_CNT
|
|
- MAC_ZC_COLLECT_SUCCESS_MARGIN)) {
|
|
restore_bm |= 1 << id;
|
|
}
|
|
}
|
|
}
|
|
|
|
iot_printf("zc:sts_set. collect:0x%02x, loss:0x%02x, restore:0x%02x\n",
|
|
collect_bm, loss_bm, restore_bm);
|
|
|
|
mac_zc_collect_info_reset(ctxt, loss_bm);
|
|
|
|
if (restore_bm) {
|
|
mac_zc_collect_ring_reset(ctxt, restore_bm);
|
|
|
|
if (collect_bm) {
|
|
/* find collect min write index as as the reference base index */
|
|
base_idx = 0;
|
|
bm = collect_bm;
|
|
while (bm) {
|
|
id = iot_bitops_ffs(bm) - 1;
|
|
bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
iot_printf("zc:sts_set.collect:%d,widx:%d,ts:%u\n",
|
|
id, collect->ring.wr_idx, collect->last_ts);
|
|
|
|
if (id == (iot_bitops_ffs(collect_bm) - 1)) {
|
|
base_idx = mac_zc_collect_ring_last_idx_get(
|
|
&ctxt->collect[id].ring);
|
|
continue;
|
|
}
|
|
|
|
delta = base_idx - mac_zc_collect_ring_last_idx_get(
|
|
&collect->ring);
|
|
if (0 == delta) {
|
|
continue;
|
|
}
|
|
|
|
if ((IOT_ABS(delta) > (collect->ring.size >> 1))
|
|
^ (delta > 0)) {
|
|
base_idx = mac_zc_collect_ring_last_idx_get(
|
|
&ctxt->collect[id].ring);
|
|
}
|
|
}
|
|
iot_printf("zc:sts_set.collect_base_idx=%d\n", base_idx);
|
|
|
|
/* find collect base index max/min ts */
|
|
max_ts = 0;
|
|
min_ts = (uint32_t)(-1);
|
|
bm = collect_bm;
|
|
while (bm) {
|
|
id = iot_bitops_ffs(bm) - 1;
|
|
bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
|
|
if (id == (iot_bitops_ffs(collect_bm) - 1)) {
|
|
max_ts = ctxt->collect[id].ring.buf[base_idx];
|
|
min_ts = max_ts;
|
|
continue;
|
|
}
|
|
|
|
if (mac_zc_ntb_is_larger_base(max_ts,
|
|
collect->ring.buf[base_idx])) {
|
|
max_ts = collect->ring.buf[base_idx];
|
|
}
|
|
if (mac_zc_ntb_is_larger_base(collect->ring.buf[base_idx],
|
|
min_ts)) {
|
|
min_ts = collect->ring.buf[base_idx];
|
|
}
|
|
}
|
|
iot_printf("zc:sts_set.collect.max:%u,min:%u\n", max_ts, min_ts);
|
|
|
|
/* base on collect max/min ts update restore min ts */
|
|
bm = restore_bm;
|
|
while (bm) {
|
|
id = iot_bitops_ffs(bm) - 1;
|
|
bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
|
|
if (mac_zc_ntb_is_larger_base(max_ts, collect->last_ts)) {
|
|
continue;
|
|
}
|
|
|
|
do {
|
|
delta = (uint32_t)(max_ts - collect->last_ts);
|
|
if (delta < (collect->period
|
|
- MAC_ZC_PERIOD_JITTER_GAP_NTB)) {
|
|
if (mac_zc_ntb_is_larger_base(collect->last_ts,
|
|
min_ts)) {
|
|
min_ts = collect->last_ts;
|
|
iot_printf("zc:sts_set.restore min_ts[%d]=%u\n",
|
|
id, min_ts);
|
|
}
|
|
break;
|
|
}
|
|
collect->last_ts += collect->period;
|
|
} while(1);
|
|
}
|
|
|
|
/* base on min ts update restore ts to ring buffer */
|
|
bm = restore_bm;
|
|
while (bm) {
|
|
id = iot_bitops_ffs(bm) - 1;
|
|
bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
|
|
delta = collect->last_ts - min_ts;
|
|
IOT_ASSERT_DUMP(delta >= 0, (uint32_t *)ctxt,
|
|
iot_ceil(sizeof(*ctxt), 4));
|
|
if (delta > (collect->period + MAC_ZC_PERIOD_JITTER_GAP_NTB)) {
|
|
collect->ring.wr_idx = base_idx + 1;
|
|
if (collect->ring.wr_idx >= collect->ring.size) {
|
|
collect->ring.wr_idx = collect->ring.wr_idx
|
|
- collect->ring.size;
|
|
}
|
|
} else {
|
|
collect->ring.wr_idx = base_idx;
|
|
}
|
|
|
|
iot_printf("zc:sts_set.restore:%d,widx:%u,ts:%u,d:%d\n",
|
|
id, collect->ring.wr_idx, collect->last_ts, delta);
|
|
collect->is_collect = 1;
|
|
mac_zc_collect_ring_write(&collect->ring, collect->last_ts);
|
|
}
|
|
} else {
|
|
/* find restore max last_ts as the reference */
|
|
max_ts = 0;
|
|
bm = restore_bm;
|
|
while (bm) {
|
|
id = iot_bitops_ffs(bm) - 1;
|
|
bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
|
|
iot_printf("zc:sts_set.restore:%d,ts:%u,max:%u\n",
|
|
id, collect->last_ts, max_ts);
|
|
|
|
if ((id == (iot_bitops_ffs(restore_bm) - 1))
|
|
|| mac_zc_ntb_is_larger_base(max_ts, collect->last_ts)) {
|
|
max_ts = collect->last_ts;
|
|
}
|
|
}
|
|
|
|
/* base on max ts update restore ts to ring buffer */
|
|
bm = restore_bm;
|
|
while (bm) {
|
|
id = iot_bitops_ffs(bm) - 1;
|
|
bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
|
|
do {
|
|
delta = max_ts - collect->last_ts;
|
|
if (delta < (collect->period
|
|
- MAC_ZC_PERIOD_JITTER_GAP_NTB)) {
|
|
break;
|
|
}
|
|
collect->last_ts += collect->period;
|
|
} while (1);
|
|
|
|
collect->ring.wr_idx = 0;
|
|
iot_printf("zc:sts_set.restore:%d,widx:%u,ts:%u\n",
|
|
id, collect->ring.wr_idx, collect->last_ts);
|
|
collect->is_collect = 1;
|
|
mac_zc_collect_ring_write(&collect->ring, collect->last_ts);
|
|
}
|
|
}
|
|
}
|
|
|
|
ctxt->is_power_collapsed = (collect_bm | restore_bm) ? 0 : 1;
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]power_collapsed:%d\n", ctxt->is_power_collapsed);
|
|
#endif
|
|
|
|
mac_zc_collect_repeat_set(ctxt);
|
|
|
|
mac_zc_set_event(ctxt);
|
|
|
|
bm = restore_bm | loss_bm;
|
|
for (id = MAC_ZC_PHASE_A; id < MAC_ZC_PHASE_CNT; id++) {
|
|
/* update mac status */
|
|
mac_status_zc_status_para_update(mac_zc_phase_is_active(ctxt, id), id);
|
|
if ((1 <<mac_zc_phase_id_to_cap(ctxt, id, 0)) & bm) {
|
|
mac_status_add_zc_phase_chg_cnt(id);
|
|
}
|
|
}
|
|
|
|
mac_zc_system_status_log(ctxt);
|
|
|
|
return (collect_bm | restore_bm);
|
|
}
|
|
|
|
/* return is need check collect status */
|
|
static uint8_t mac_zc_collect_cnt_set(mac_zc_collect_info_t *collect,
|
|
int8_t set_cnt)
|
|
{
|
|
uint8_t is_need_chk = 0;
|
|
|
|
set_cnt += (uint8_t)collect->collect_cnt;
|
|
if (set_cnt >= MAC_ZC_COLLECT_SUCCESS_CNT) {
|
|
collect->collect_cnt = MAC_ZC_COLLECT_SUCCESS_CNT;
|
|
if (!collect->is_collect) {
|
|
is_need_chk = 1;
|
|
}
|
|
} else if (set_cnt <= 0) {
|
|
collect->collect_cnt = 0;
|
|
if (collect->is_collect) {
|
|
is_need_chk = 1;
|
|
}
|
|
} else {
|
|
collect->collect_cnt = set_cnt;
|
|
}
|
|
|
|
return is_need_chk;
|
|
}
|
|
|
|
static uint8_t mac_zc_train_period(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint8_t id, cap_bm, num;
|
|
uint8_t pos, collect_cnt;
|
|
uint8_t trained_bm;
|
|
int32_t delta;
|
|
uint32_t period;
|
|
uint32_t *buf = ctxt->collect_buf;
|
|
mac_zc_collect_info_t *collect;
|
|
|
|
mac_zc_collect_info_reset(ctxt, (1 << MAC_ZC_HW_CAP_CNT) - 1);
|
|
|
|
trained_bm = 0;
|
|
cap_bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << (id - MAC_ZC_HW_CAP0));
|
|
|
|
collect = &ctxt->collect[id];
|
|
num = mac_zc_sw_fifo_elements(&collect->ntb_fifo);
|
|
|
|
/* min of 4 data, then 3 period to check valid */
|
|
if (num < 4) {
|
|
continue;
|
|
}
|
|
|
|
num = mac_zc_sw_fifo_gets(&collect->ntb_fifo, buf,
|
|
MAC_ZC_COLLECT_BUF_SIZE);
|
|
|
|
mac_zc_dbg_collect_print(id, num, buf);
|
|
|
|
collect_cnt = 0;
|
|
/* calculate period */
|
|
for (pos = 1; pos < num; pos++) {
|
|
period = (uint32_t)(buf[pos] - buf[pos - 1]);
|
|
delta = (int32_t)(collect->period - period);
|
|
|
|
if (period > MAC_ZC_PERIOD_JITTER_GAP_NTB) {
|
|
if (0 == collect_cnt) {
|
|
/* first period */
|
|
collect->period = period;
|
|
collect_cnt++;
|
|
} else {
|
|
if (IOT_ABS(delta) > MAC_ZC_PERIOD_JITTER_GAP_NTB) {
|
|
break;
|
|
} else {
|
|
collect->period = mac_zc_period_update(collect->period,
|
|
period);
|
|
collect_cnt++;
|
|
/* all of collect period valid */
|
|
if (collect_cnt >= (num - 1)) {
|
|
collect->last_ts = buf[pos];
|
|
collect->collect_cnt = num;
|
|
trained_bm |= 1 << id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]train_period.%d, period:%u,ts:%u,bm:0x%x\n",
|
|
id, collect->period, collect->last_ts, trained_bm);
|
|
#endif
|
|
}
|
|
|
|
return trained_bm;
|
|
}
|
|
|
|
static void mac_zc_collect_pre_update(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint8_t cap_bm, id;
|
|
mac_zc_collect_info_t *collect;
|
|
mac_zc_pre_update_info_t *pre_info;
|
|
|
|
cap_bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
pre_info = &ctxt->daemon.pre_info[id];
|
|
|
|
pre_info->is_collect = collect->is_collect;
|
|
pre_info->period = collect->period;
|
|
pre_info->collect_cnt = collect->collect_cnt;
|
|
pre_info->last_ts = collect->last_ts;
|
|
pre_info->ring_wr_idx = collect->ring.wr_idx;
|
|
}
|
|
}
|
|
|
|
/* return need check current capture is active or not */
|
|
static uint8_t mac_zc_collect_update(mac_zc_ctxt_t *ctxt, uint8_t is_update)
|
|
{
|
|
uint8_t id, cap_bm, num, pos, is_valid_last, is_reload;
|
|
uint8_t need_chk_bm;
|
|
int8_t cnt;
|
|
int32_t delta;
|
|
uint32_t period, last_collect_ts;
|
|
uint32_t *buf = ctxt->collect_buf;
|
|
mac_zc_collect_info_t *collect;
|
|
|
|
if (ctxt->nv.is_ntb_collect) {
|
|
ctxt->daemon.enter_collect_ts = mac_sched_get_ntb(NULL);
|
|
} else {
|
|
ctxt->daemon.enter_collect_ts = mac_sched_get_lts();
|
|
}
|
|
|
|
need_chk_bm = 0;
|
|
is_valid_last = 0;
|
|
last_collect_ts = 0;
|
|
ctxt->daemon.collect_reload_cnt = 0;
|
|
|
|
collect_reload:
|
|
is_reload = 0;
|
|
cap_bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
|
|
collect = &ctxt->collect[id];
|
|
num = mac_zc_sw_fifo_gets(&collect->ntb_fifo, buf,
|
|
MAC_ZC_COLLECT_BUF_SIZE);
|
|
|
|
mac_zc_dbg_collect_print(id, num, buf);
|
|
|
|
if (0 == num) {
|
|
continue;
|
|
}
|
|
|
|
/* only called once */
|
|
if (0 == ctxt->daemon.collect_reload_cnt) {
|
|
mac_zc_collect_pre_update(ctxt);
|
|
}
|
|
|
|
is_reload = 1;
|
|
|
|
/* train period done or restore collect */
|
|
if (0 == collect->collect_cnt) {
|
|
if (0 == collect->period) {
|
|
/* restore collect */
|
|
collect->period = mac_zc_collect_ref_period_get(ctxt);
|
|
}
|
|
collect->last_ts = buf[0];
|
|
collect->collect_cnt = 1;
|
|
pos = 1;
|
|
} else {
|
|
pos = 0;
|
|
}
|
|
|
|
cnt = 0;
|
|
while (pos < num) {
|
|
period = buf[pos] - collect->last_ts;
|
|
delta = (int32_t)(collect->period - period);
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]%d.data[%d]=%u,last_ts=%u,period=%u-%u,"
|
|
"delta=%d,cnt=%d-%d,is_collect=%d\n",
|
|
id, pos, buf[pos], collect->last_ts, period,
|
|
collect->period, delta, collect->collect_cnt, cnt,
|
|
collect->is_collect);
|
|
#endif
|
|
if (IOT_ABS(delta) > MAC_ZC_PERIOD_JITTER_GAP_NTB) {
|
|
if (delta > 0) {
|
|
/* delta of the interval between 2 colloct data too
|
|
* short, this data is noise.
|
|
*/
|
|
pos++;
|
|
continue;
|
|
} else {
|
|
/* miss collect, not update check position */
|
|
cnt--;
|
|
collect->last_ts += collect->period;
|
|
IOT_ASSERT(mac_zc_ntb_is_larger_base(collect->last_ts,
|
|
ctxt->nv.is_ntb_collect ? mac_sched_get_ntb(NULL)
|
|
: mac_sched_get_lts()));
|
|
}
|
|
} else {
|
|
collect->last_ts = buf[pos];
|
|
collect->period = mac_zc_period_update(collect->period,
|
|
period);
|
|
pos++;
|
|
cnt++;
|
|
}
|
|
|
|
if (is_update && collect->is_collect) {
|
|
mac_zc_collect_ring_write(&collect->ring, collect->last_ts);
|
|
}
|
|
}
|
|
|
|
need_chk_bm |= mac_zc_collect_cnt_set(collect, cnt) << id;
|
|
|
|
if (collect->is_collect) {
|
|
if (!is_valid_last) {
|
|
last_collect_ts = collect->last_ts;
|
|
is_valid_last = 1;
|
|
} else if (mac_zc_ntb_is_larger_base(last_collect_ts,
|
|
collect->last_ts)) {
|
|
last_collect_ts = collect->last_ts;
|
|
}
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]last_collect_ts:%u\n", last_collect_ts);
|
|
#endif
|
|
}
|
|
|
|
ctxt->daemon.pre_info[id].cur_last_ts = collect->last_ts;
|
|
}
|
|
|
|
if (ctxt->nv.is_ntb_collect) {
|
|
ctxt->daemon.exit_collect_ts = mac_sched_get_ntb(NULL);
|
|
} else {
|
|
ctxt->daemon.exit_collect_ts = mac_sched_get_lts();
|
|
}
|
|
|
|
if (is_reload) {
|
|
IOT_ASSERT_DUMP(ctxt->daemon.collect_reload_cnt < 3,
|
|
(uint32_t *)ctxt, iot_ceil(sizeof(*ctxt), 4));
|
|
ctxt->daemon.collect_reload_cnt++;
|
|
goto collect_reload;
|
|
}
|
|
|
|
if (is_valid_last) {
|
|
ctxt->daemon.last_collect_ts = last_collect_ts;
|
|
cap_bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
|
|
if (!collect->is_collect) {
|
|
continue;
|
|
}
|
|
|
|
period = (uint32_t)(last_collect_ts - collect->last_ts);
|
|
cnt = period / collect->period;
|
|
|
|
if (0 == cnt) {
|
|
continue;
|
|
}
|
|
|
|
if (is_update) {
|
|
for (pos = 0; pos < cnt; pos++) {
|
|
collect->last_ts += collect->period;
|
|
mac_zc_collect_ring_write(&collect->ring, collect->last_ts);
|
|
}
|
|
} else {
|
|
collect->last_ts += cnt * collect->period;
|
|
}
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]comp:%d,ts:%u,period:%u, cnt:%d-%d\n",
|
|
id, collect->last_ts, collect->period,
|
|
collect->collect_cnt, cnt);
|
|
#endif
|
|
cnt = -cnt;
|
|
need_chk_bm |= mac_zc_collect_cnt_set(collect, cnt) << id;
|
|
}
|
|
|
|
if (is_update) {
|
|
mac_zc_collect_ring_widx_check(ctxt);
|
|
}
|
|
} else {
|
|
last_collect_ts = mac_sched_get_ntb(NULL);
|
|
period = (uint32_t)(last_collect_ts
|
|
- ctxt->daemon.last_collect_ts);
|
|
cnt = period / MAC_ZC_PERIOD_DEF_GOLDON_GAP_NTB;
|
|
/* not data collect for long time, set all active collect as inactive */
|
|
if (cnt > MAC_ZC_COLLECT_SUCCESS_CNT) {
|
|
cnt = -MAC_ZC_COLLECT_SUCCESS_CNT;
|
|
cap_bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
|
|
if (!collect->is_collect) {
|
|
continue;
|
|
}
|
|
|
|
need_chk_bm |= mac_zc_collect_cnt_set(collect, cnt) << id;
|
|
}
|
|
}
|
|
}
|
|
|
|
return need_chk_bm;
|
|
}
|
|
|
|
static uint8_t mac_zc_get_ntb_valid_collect(mac_zc_ctxt_t *ctxt,
|
|
uint8_t is_get_full)
|
|
{
|
|
uint8_t cap_bm, collect_bm, id, tmp_id, is_chk_ext;
|
|
|
|
collect_bm = 0;
|
|
cap_bm = (uint8_t)mac_zc_cap_support_bm_get(ctxt);
|
|
|
|
if (is_get_full || (!is_get_full && !ctxt->nv.is_double_collect)) {
|
|
/* only check is_ext = 0 collect */
|
|
cap_bm &= (1 << MAC_ZC_PHASE_CNT) - 1;
|
|
is_chk_ext = 0;
|
|
} else {
|
|
is_chk_ext = 1;
|
|
}
|
|
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
|
|
if (is_chk_ext) {
|
|
IOT_ASSERT(!ctxt->nv.map[id].is_ext);
|
|
tmp_id = mac_zc_phase_cap_to_ext(id);
|
|
if (ctxt->collect[id].is_collect
|
|
&& ctxt->collect[tmp_id].is_collect) {
|
|
#if !MAC_ZC_GET_RPT_REPEAT_ENA
|
|
if (!mac_zc_cap_is_repeat(ctxt, id))
|
|
#endif
|
|
{
|
|
collect_bm |= (1 << id) | (1 << tmp_id);
|
|
}
|
|
}
|
|
cap_bm &= ~((1 << id) | (1 << tmp_id));
|
|
} else {
|
|
if (ctxt->collect[id].is_collect) {
|
|
#if !MAC_ZC_GET_RPT_REPEAT_ENA
|
|
if (!mac_zc_cap_is_repeat(ctxt, id))
|
|
#endif
|
|
{
|
|
collect_bm |= (1 << id);
|
|
}
|
|
}
|
|
cap_bm &= ~(1 << id);
|
|
}
|
|
}
|
|
|
|
return collect_bm;
|
|
}
|
|
|
|
static void mac_zc_get_ntb_fill_rpt_buf(mac_zc_ctxt_t *ctxt, uint32_t *buf,
|
|
uint32_t count, uint32_t *start_idx, uint8_t collect_bm,
|
|
uint8_t is_sw_fill_reverse)
|
|
{
|
|
uint8_t cap_bm, id, collect_cnt;
|
|
uint32_t idx[MAC_ZC_HW_CAP_CNT], pos, next_idx, reverse_pos;
|
|
|
|
collect_cnt = iot_bitops_cbs(collect_bm);
|
|
os_mem_cpy(idx, start_idx, sizeof(idx));
|
|
id = 0;
|
|
pos = 0; /* report buffer position */
|
|
while (1) {
|
|
cap_bm = collect_bm;
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
|
|
if (pos >= count) {
|
|
goto out; /* fill count */
|
|
}
|
|
|
|
buf[pos] = ctxt->collect[id].ring.buf[idx[id]];
|
|
|
|
if (is_sw_fill_reverse) {
|
|
/* sw fill report reverse edge index */
|
|
reverse_pos = pos + collect_cnt;
|
|
if (reverse_pos < count) {
|
|
/* next ring buffer index */
|
|
next_idx = mac_zc_collect_ring_legal_idx_get(
|
|
&ctxt->collect[id].ring, idx[id] + 1);
|
|
buf[reverse_pos] = ((ctxt->collect[id].ring.buf[next_idx]
|
|
- ctxt->collect[id].ring.buf[idx[id]]) >> 1) +
|
|
ctxt->collect[id].ring.buf[idx[id]];
|
|
}
|
|
}
|
|
pos++;
|
|
idx[id] = mac_zc_collect_ring_legal_idx_get(&ctxt->collect[id].ring,
|
|
(int32_t)(idx[id] + 1));
|
|
}
|
|
|
|
if (is_sw_fill_reverse) {
|
|
pos += collect_cnt;
|
|
}
|
|
}
|
|
|
|
out:
|
|
if (!ctxt->nv.is_ntb_collect) {
|
|
id = iot_bitops_ffs(collect_bm) - 1;
|
|
mac_zc_collect_lts_to_ntb(ctxt, start_idx[id], buf, count, buf);
|
|
}
|
|
}
|
|
|
|
/* return fill buffer count */
|
|
static uint32_t mac_zc_get_ntb_history(mac_zc_ctxt_t *ctxt, uint32_t *buf,
|
|
uint32_t count, uint32_t target_ntb, uint8_t is_full_period)
|
|
{
|
|
uint8_t cap_bm, collect_bm, ext_ref_ts_valid = 0;;
|
|
uint8_t id, ref_id, is_sw_fill_reverse, find = 0;
|
|
uint32_t idx, last_idx, ref_idx;
|
|
uint32_t tmp, cnt;
|
|
uint32_t target_ts, ref_ts, ext_ref_ts = 0, std_ts = 0;
|
|
uint32_t cnt_per_line = 0, cnt_per_line_fix = 0;
|
|
uint32_t start_idx[MAC_ZC_HW_CAP_CNT] = { 0 };
|
|
mac_zc_collect_info_t *collect;
|
|
int32_t search_of = 0;
|
|
|
|
/* get valid collect bitmap */
|
|
collect_bm = mac_zc_get_ntb_valid_collect(ctxt, is_full_period);
|
|
if (0 == collect_bm) {
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]his. not found:%d\n", __LINE__);
|
|
#endif
|
|
return 0; /* not found */
|
|
}
|
|
|
|
cap_bm = collect_bm;
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
cnt = mac_zc_collect_ring_elements(&collect->ring);
|
|
if (!cnt_per_line || cnt < cnt_per_line) {
|
|
cnt_per_line = cnt;
|
|
}
|
|
}
|
|
|
|
/* always take the first active phase line as the reference phase line */
|
|
cap_bm = collect_bm;
|
|
ref_id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << ref_id);
|
|
collect = &ctxt->collect[ref_id];
|
|
last_idx = mac_zc_collect_ring_last_idx_get(&collect->ring);
|
|
|
|
if (!ctxt->nv.is_ntb_collect) {
|
|
mac_zc_collect_ntb_to_lts(ctxt, last_idx, &target_ntb, 1, &target_ts);
|
|
} else {
|
|
target_ts = target_ntb;
|
|
}
|
|
iot_printf("zc:his. cnt:%d, start_ts:%u-%u, cur_ts:%u-%u\n",
|
|
cnt_per_line, target_ntb, target_ts,
|
|
mac_sched_get_ntb(NULL), mac_sched_get_lts());
|
|
cnt = (uint32_t)(collect->ring.buf[last_idx] - target_ts) / collect->period;
|
|
|
|
/* the ref collect ring buffer has enough data to search */
|
|
if (cnt < cnt_per_line) {
|
|
idx = mac_zc_collect_ring_legal_idx_get(&collect->ring,
|
|
(int32_t)(last_idx - cnt + 1));
|
|
/* adjust the left boundary of the lookup range */
|
|
if (mac_zc_ntb_is_larger_base(target_ts, collect->ring.buf[idx])) {
|
|
tmp = cnt_per_line - cnt;
|
|
tmp = min(tmp, MAC_ZC_SEARCH_MAX_CNT);
|
|
cnt_per_line = cnt + tmp;
|
|
idx = mac_zc_collect_ring_legal_idx_get(&collect->ring,
|
|
(int32_t)(last_idx - cnt_per_line + 1));
|
|
}
|
|
} else {
|
|
idx = mac_zc_collect_ring_legal_idx_get(&collect->ring,
|
|
(int32_t)(last_idx - cnt_per_line + 1));
|
|
}
|
|
|
|
/* get search start index and count */
|
|
find = 0;
|
|
for (cnt = MAC_ZC_SEARCH_MAX_CNT; cnt > 0 && cnt_per_line > 0;
|
|
cnt--) {
|
|
tmp = IOT_ABS((int32_t)(target_ts - collect->ring.buf[idx]));
|
|
if (tmp < (collect->period + MAC_ZC_PERIOD_JITTER_GAP_NTB)) {
|
|
find = 1;
|
|
ref_ts = collect->ring.buf[idx];
|
|
ref_idx = idx;
|
|
iot_printf("zc:his. get_bm:0x%x, ref_id:%d, cnt:%d, start[%d]:%u\n",
|
|
collect_bm, ref_id, cnt_per_line, idx, ref_ts);
|
|
break;
|
|
}
|
|
cnt_per_line--;
|
|
idx = mac_zc_collect_ring_legal_idx_get(&collect->ring, idx + 1);
|
|
}
|
|
|
|
if (!find) {
|
|
iot_printf("zc:his. not found:%d\n", __LINE__);
|
|
return 0; /* not found */
|
|
}
|
|
|
|
if (!ctxt->nv.is_ntb_collect
|
|
&& !mac_zc_collect_record_is_valid(ctxt, idx)) {
|
|
iot_printf("zc:his. record invalid\n");
|
|
return 0;
|
|
}
|
|
|
|
start_idx[ref_id] = idx;
|
|
cnt_per_line_fix = cnt_per_line;
|
|
|
|
/* always take the first active phase line as the reference phase line */
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
|
|
/* adjust the index of the first reported sample of the non reference
|
|
* phase line to ensure that after the reference time.
|
|
*/
|
|
cnt = cnt_per_line;
|
|
if (mac_zc_phase_cap_is_ext(id) && ext_ref_ts_valid) {
|
|
std_ts = ext_ref_ts;
|
|
} else {
|
|
std_ts = ref_ts;
|
|
}
|
|
find = 0;
|
|
for (search_of = -MAC_ZC_NO_REF_PHASE_START_MAX_ADJ_CNT;
|
|
search_of <= MAC_ZC_NO_REF_PHASE_START_MAX_ADJ_CNT &&
|
|
search_of < (int32_t)cnt_per_line; search_of++) {
|
|
idx = mac_zc_collect_ring_legal_idx_get(&collect->ring,
|
|
(int32_t)(ref_idx + search_of));
|
|
if (!mac_zc_collect_ring_idx_is_valid(&collect->ring, idx)) {
|
|
continue;
|
|
}
|
|
if (mac_zc_ntb_is_larger_base(std_ts, collect->ring.buf[idx])) {
|
|
find = 1;
|
|
start_idx[id] = idx;
|
|
cnt = mac_zc_collect_ring_idx2widx_interval(&collect->ring,
|
|
idx);
|
|
if (mac_zc_phase_cap_is_ext(id) && !ext_ref_ts_valid) {
|
|
ext_ref_ts = collect->ring.buf[idx];
|
|
ext_ref_ts_valid = 1;
|
|
if (mac_zc_phase_ext_to_cap(id) != ref_id) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
}
|
|
iot_printf("zc:his. id:%d, cnt:%d, start[%d]:%u\n",
|
|
id, cnt, idx, collect->ring.buf[idx]);
|
|
break;
|
|
}
|
|
}
|
|
if (!find) {
|
|
IOT_ASSERT(0);
|
|
collect_bm &= ~(1 << id);
|
|
} else if (cnt < cnt_per_line_fix) {
|
|
cnt_per_line_fix = cnt;
|
|
}
|
|
}
|
|
|
|
/* calculate the maximum number of samples supported after adjustment */
|
|
is_sw_fill_reverse = !ctxt->nv.is_double_collect && !is_full_period;
|
|
cnt = cnt_per_line_fix * iot_bitops_cbs(collect_bm);
|
|
if (is_sw_fill_reverse) {
|
|
cnt += (cnt_per_line_fix - 1) * collect_bm;
|
|
}
|
|
if (count > cnt) {
|
|
count = cnt;
|
|
}
|
|
mac_zc_get_ntb_fill_rpt_buf(ctxt, buf, count, start_idx, collect_bm,
|
|
is_sw_fill_reverse);
|
|
|
|
return count;
|
|
}
|
|
|
|
static uint32_t mac_zc_get_ntb_real(mac_zc_ctxt_t *ctxt, uint32_t *buf,
|
|
uint32_t count, uint8_t is_full_period)
|
|
{
|
|
uint8_t cap_bm, collect_bm, ext_ref_ts_valid = 0;
|
|
uint8_t id, ref_id, collect_cnt, is_sw_fill_reverse, find = 0;
|
|
uint32_t idx, ref_idx;
|
|
uint32_t cnt, tmp;
|
|
uint32_t ref_ts = 0, ext_ref_ts = 0, std_ts = 0;
|
|
mac_zc_collect_info_t *collect;
|
|
uint32_t start_idx[MAC_ZC_HW_CAP_CNT] = { 0 };
|
|
uint32_t cnt_per_line = 0, cnt_per_line_fix = 0;
|
|
int32_t search_of = 0;
|
|
|
|
/* get valid collect bitmap */
|
|
collect_bm = mac_zc_get_ntb_valid_collect(ctxt, is_full_period);
|
|
cap_bm = collect_bm;
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
cnt = mac_zc_collect_ring_elements(&ctxt->collect[id].ring);
|
|
if (cnt <= (MAC_ZC_NO_REF_PHASE_START_MAX_ADJ_CNT * 2)) {
|
|
tmp = 1 << id;
|
|
if (ctxt->nv.is_double_collect) {
|
|
if (mac_zc_phase_cap_is_ext(id)) {
|
|
tmp |= 1 << mac_zc_phase_ext_to_cap(id);
|
|
} else {
|
|
tmp |= 1 << mac_zc_phase_cap_to_ext(id);
|
|
}
|
|
}
|
|
iot_printf("zc:real. bm:0x%08x-0x%08x, id:%d, cnt:%d too small\n",
|
|
collect_bm, tmp, id, cnt);
|
|
tmp = ~tmp;
|
|
collect_bm &= (uint8_t)tmp;
|
|
cap_bm &= (uint8_t)tmp;
|
|
}
|
|
}
|
|
|
|
if (0 == collect_bm) {
|
|
iot_printf("zc:real. not found:%d\n", __LINE__);
|
|
return 0; /* not found */
|
|
}
|
|
|
|
cap_bm = collect_bm;
|
|
collect_cnt = iot_bitops_cbs(collect_bm);
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
cnt = mac_zc_collect_ring_elements(&collect->ring);
|
|
if (!cnt_per_line || cnt < cnt_per_line) {
|
|
cnt_per_line = cnt;
|
|
}
|
|
}
|
|
|
|
/* get source support max report data count */
|
|
is_sw_fill_reverse = !ctxt->nv.is_double_collect && !is_full_period;
|
|
cnt = cnt_per_line * collect_cnt;
|
|
if (is_sw_fill_reverse) {
|
|
cnt += (cnt_per_line - 1) * collect_cnt;
|
|
}
|
|
if (count > cnt) {
|
|
count = cnt;
|
|
} else {
|
|
if (is_sw_fill_reverse) {
|
|
tmp = iot_ceil(count - collect_cnt, collect_cnt << 1);
|
|
} else {
|
|
tmp = iot_ceil(count, collect_cnt);
|
|
}
|
|
if ((cnt_per_line - tmp) > MAC_ZC_NO_REF_PHASE_START_MAX_ADJ_CNT * 2) {
|
|
cnt_per_line = tmp + MAC_ZC_NO_REF_PHASE_START_MAX_ADJ_CNT * 2;
|
|
}
|
|
}
|
|
|
|
/* always take the first active phase line as the reference phase line */
|
|
cap_bm = collect_bm;
|
|
ref_id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << ref_id);
|
|
collect = &ctxt->collect[ref_id];
|
|
idx = mac_zc_collect_ring_last_idx_get(&collect->ring);
|
|
ref_idx = mac_zc_collect_ring_legal_idx_get(&collect->ring,
|
|
(int32_t)(idx - cnt_per_line + 1));
|
|
if (!ctxt->nv.is_ntb_collect
|
|
&& !mac_zc_collect_record_is_valid(ctxt, ref_idx)) {
|
|
iot_printf("zc:real. record invalid\n");
|
|
return 0;
|
|
}
|
|
ref_ts = collect->ring.buf[ref_idx];
|
|
start_idx[ref_id] = ref_idx;
|
|
cnt_per_line_fix = cnt_per_line;
|
|
iot_printf("zc:real. get_bm:0x%x, ref_id:%d, cnt:%d, start[%d]:%u\n",
|
|
collect_bm, ref_id, cnt_per_line, ref_idx, ref_ts);
|
|
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
collect = &ctxt->collect[id];
|
|
/* adjust the index of the first reported sample of the non reference
|
|
* phase line to ensure that after the reference time.
|
|
*/
|
|
cnt = cnt_per_line;
|
|
if (mac_zc_phase_cap_is_ext(id) && ext_ref_ts_valid) {
|
|
std_ts = ext_ref_ts;
|
|
} else {
|
|
std_ts = ref_ts;
|
|
}
|
|
find = 0;
|
|
for (search_of = -MAC_ZC_NO_REF_PHASE_START_MAX_ADJ_CNT;
|
|
search_of <= MAC_ZC_NO_REF_PHASE_START_MAX_ADJ_CNT &&
|
|
search_of < (int32_t)cnt_per_line; search_of++) {
|
|
idx = mac_zc_collect_ring_legal_idx_get(&collect->ring,
|
|
(int32_t)(ref_idx + search_of));
|
|
if (!mac_zc_collect_ring_idx_is_valid(&collect->ring, idx)) {
|
|
continue;
|
|
}
|
|
if (mac_zc_ntb_is_larger_base(std_ts, collect->ring.buf[idx])) {
|
|
find = 1;
|
|
start_idx[id] = idx;
|
|
cnt = mac_zc_collect_ring_idx2widx_interval(&collect->ring,
|
|
idx);
|
|
if (mac_zc_phase_cap_is_ext(id) && !ext_ref_ts_valid) {
|
|
ext_ref_ts = collect->ring.buf[idx];
|
|
ext_ref_ts_valid = 1;
|
|
if (mac_zc_phase_ext_to_cap(id) != ref_id) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
}
|
|
iot_printf("zc:real. id:%d, cnt:%d, start[%d]:%u\n",
|
|
id, cnt, idx, collect->ring.buf[idx]);
|
|
break;
|
|
}
|
|
}
|
|
if (!find) {
|
|
IOT_ASSERT(0);
|
|
collect_bm &= ~(1 << id);
|
|
} else if (cnt < cnt_per_line_fix) {
|
|
cnt_per_line_fix = cnt;
|
|
}
|
|
}
|
|
/* calculate the maximum number of samples supported after adjustment */
|
|
cnt = cnt_per_line_fix * iot_bitops_cbs(collect_bm);
|
|
if (is_sw_fill_reverse) {
|
|
cnt += (cnt_per_line_fix - 1) * collect_bm;
|
|
}
|
|
if (count > cnt) {
|
|
count = cnt;
|
|
}
|
|
mac_zc_get_ntb_fill_rpt_buf(ctxt, buf, count, start_idx, collect_bm,
|
|
is_sw_fill_reverse);
|
|
return count;
|
|
}
|
|
|
|
#if MAC_ZC_DBG_LOG_LEVEL >= 2
|
|
|
|
static void mac_zc_rpt_info_dump(mac_zc_ntb_rpt_t *rpt)
|
|
{
|
|
uint32_t collec_cnt;
|
|
uint32_t pos, idx;
|
|
uint8_t line_conn_ind = 0, temp;
|
|
uint8_t phase_of, phase = 0;
|
|
line_conn_ind |= (rpt->phase_a_valid ? (1 << 0) : 0);
|
|
line_conn_ind |= (rpt->phase_b_valid ? (1 << 1) : 0);
|
|
line_conn_ind |= (rpt->phase_c_valid ? (1 << 2) : 0);
|
|
|
|
if (rpt->is_full_period) {
|
|
collec_cnt = rpt->phase_cnt;
|
|
} else {
|
|
collec_cnt = rpt->phase_cnt << 1;
|
|
}
|
|
for (idx = 0; idx < collec_cnt; idx++) {
|
|
phase_of = idx % rpt->phase_cnt;
|
|
phase_of += 1;
|
|
temp = line_conn_ind;
|
|
while (phase_of-- > 0) {
|
|
phase = iot_bitops_ffs(temp) - 1;
|
|
temp &= ~ (1 << phase);
|
|
}
|
|
iot_printf("[zc]phase%lu%s_ntb: ", phase, idx >= rpt->phase_cnt ?
|
|
"-" : "+");
|
|
for (pos = idx; pos < rpt->ntb_cnt; pos += collec_cnt) {
|
|
iot_printf("%lu,", rpt->ntb[pos]);
|
|
}
|
|
iot_printf("\n");
|
|
iot_printf("[zc]phase%lu%s_period: ", phase, idx >= rpt->phase_cnt ?
|
|
"-" : "+");
|
|
for (pos = idx + collec_cnt; pos < rpt->ntb_cnt;
|
|
pos += collec_cnt) {
|
|
iot_printf("%lu,", (uint32_t)(rpt->ntb[pos] -
|
|
rpt->ntb[pos - collec_cnt]));
|
|
}
|
|
iot_printf("\n");
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
#define mac_zc_rpt_info_dump(rpt)
|
|
|
|
#endif
|
|
|
|
/* mac_zc copy real time ntb or history ntb to upper layer rpt buffer */
|
|
uint32_t mac_zc_get_ntb(uint8_t id, mac_zc_ntb_rpt_t *rpt,
|
|
uint16_t count, uint8_t is_full_period, uint8_t is_history_ntb,
|
|
uint32_t nid, uint32_t ntb)
|
|
{
|
|
uint8_t idx;
|
|
uint32_t tar_ntb;
|
|
uint32_t err_no, ret = ERR_OK;
|
|
uint32_t fill_cnt;
|
|
mac_zc_ctxt_t *ctxt = mac_zc_ctxt_get(id);
|
|
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 1)
|
|
iot_printf("[zc]get_para-cnt:%d,is_full:%d,is_his:%d,tar_nid:0x%x,"
|
|
"tar_ntb:%u,cur_ts:%u-%u\n",
|
|
count, is_full_period, is_history_ntb, nid, ntb,
|
|
mac_sched_get_lts(), mac_sched_get_ntb(NULL));
|
|
#endif
|
|
|
|
err_no = 0;
|
|
fill_cnt = 0;
|
|
do {
|
|
if (!ctxt || !rpt) {
|
|
IOT_ASSERT(0);
|
|
err_no = __LINE__;
|
|
ret = ERR_INVAL;
|
|
break;
|
|
}
|
|
|
|
if (!mac_zc_is_collecting(ctxt)) {
|
|
err_no = __LINE__;
|
|
ret = ERR_NOT_READY;
|
|
break;
|
|
}
|
|
|
|
if (0 == count) {
|
|
break;
|
|
}
|
|
|
|
tar_ntb = ntb;
|
|
if (PLC_NID_INVALID != nid) {
|
|
if (is_history_ntb) {
|
|
/* convert neighbor nid history ntb to current nid ntb.
|
|
* neighbor nid -> my nid ntb */
|
|
if (ERR_OK != mac_other_ntb_to_myntb(id, (nid_t)nid,
|
|
&tar_ntb, 1)) {
|
|
err_no = __LINE__;
|
|
ret = ERR_NOT_EXIST;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (is_history_ntb) {
|
|
fill_cnt = mac_zc_get_ntb_history(ctxt, rpt->ntb, count, tar_ntb,
|
|
is_full_period);
|
|
} else {
|
|
fill_cnt = mac_zc_get_ntb_real(ctxt, rpt->ntb, count,
|
|
is_full_period);
|
|
}
|
|
|
|
if (PLC_NID_INVALID != nid) {
|
|
if (ERR_OK != mac_myntb_to_other_ntb(id, nid, rpt->ntb, fill_cnt)) {
|
|
ret = ERR_NOT_EXIST;
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
}
|
|
} while(0);
|
|
|
|
if ((ERR_INVAL != ret) && (ERR_NOT_READY != ret)) {
|
|
rpt->is_full_period = !!is_full_period;
|
|
rpt->ntb_cnt = fill_cnt;
|
|
rpt->phase_a_repeat = mac_zc_phase_id_zc_to_plc(
|
|
mac_zc_phase_repeat_get(ctxt, MAC_ZC_PHASE_A));
|
|
rpt->phase_b_repeat = mac_zc_phase_id_zc_to_plc(
|
|
mac_zc_phase_repeat_get(ctxt, MAC_ZC_PHASE_B));
|
|
rpt->phase_c_repeat = mac_zc_phase_id_zc_to_plc(
|
|
mac_zc_phase_repeat_get(ctxt, MAC_ZC_PHASE_C));
|
|
rpt->is_repeat_phase = (rpt->phase_a_repeat != PLC_PHASE_A)
|
|
|| (rpt->phase_b_repeat != PLC_PHASE_B)
|
|
|| (rpt->phase_c_repeat != PLC_PHASE_C);
|
|
#if MAC_ZC_GET_RPT_REPEAT_ENA
|
|
rpt->phase_a_valid = mac_zc_phase_is_active(ctxt, MAC_ZC_PHASE_A);
|
|
rpt->phase_b_valid = mac_zc_phase_is_active(ctxt, MAC_ZC_PHASE_B);
|
|
rpt->phase_c_valid = mac_zc_phase_is_active(ctxt, MAC_ZC_PHASE_C);
|
|
#else
|
|
rpt->phase_a_valid = mac_zc_phase_is_active(ctxt, MAC_ZC_PHASE_A)
|
|
&& (rpt->phase_a_repeat == PLC_PHASE_A);
|
|
rpt->phase_b_valid = mac_zc_phase_is_active(ctxt, MAC_ZC_PHASE_B)
|
|
&& (rpt->phase_b_repeat == PLC_PHASE_B);
|
|
rpt->phase_c_valid = mac_zc_phase_is_active(ctxt, MAC_ZC_PHASE_C)
|
|
&& (rpt->phase_c_repeat == PLC_PHASE_C);
|
|
#endif
|
|
rpt->phase_cnt = rpt->phase_a_valid + rpt->phase_b_valid
|
|
+ rpt->phase_c_valid;
|
|
for (idx = MAC_ZC_PHASE_A; idx < MAC_ZC_PHASE_CNT; idx++) {
|
|
rpt->avg_period[idx] = mac_zc_phase_period_get(ctxt, idx);
|
|
}
|
|
}
|
|
|
|
iot_printf("zc:rpt-%d:%u.cnt-%d:%d,v-%d:%d:%d,full=%d,repeat:%d-%d:%d:%d,"
|
|
"cur:%u\n",
|
|
ret, err_no, rpt->phase_cnt, rpt->ntb_cnt,
|
|
rpt->phase_a_valid, rpt->phase_b_valid, rpt->phase_c_valid,
|
|
rpt->is_full_period, rpt->is_repeat_phase, rpt->phase_a_repeat,
|
|
rpt->phase_b_repeat, rpt->phase_c_repeat, mac_sched_get_ntb(NULL));
|
|
if (rpt->ntb_cnt) {
|
|
iot_printf("ntb=%u:%u\n",
|
|
rpt->ntb[0], rpt->ntb[rpt->ntb_cnt - 1]);
|
|
mac_zc_rpt_info_dump(rpt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static mac_zc_state_id_t mac_zc_sm_idle(mac_zc_ctxt_t *ctxt,
|
|
mac_zc_trigger_id_t trig_id)
|
|
{
|
|
uint8_t bm, id, ref_id;
|
|
mac_zc_collect_info_t *collect;
|
|
mac_zc_state_id_t next_state = MAC_ZC_STATE_IDLE;
|
|
|
|
IOT_ASSERT(ctxt);
|
|
|
|
switch (trig_id) {
|
|
case MAC_ZC_TRIG_SYS_START_REQ:
|
|
mac_zc_system_start(ctxt);
|
|
//TODO: add daemon code
|
|
break;
|
|
|
|
case MAC_ZC_TRIG_SYSTICK_INT:
|
|
bm = mac_zc_train_period(ctxt);
|
|
if (bm) {
|
|
ref_id = iot_bitops_ffs(bm) - 1;
|
|
ctxt->systick.check_period = (ctxt->collect[ref_id].period
|
|
* MAC_ZC_SYSTICK_PERIOD_CNT) + MAC_ZC_PERIOD_JITTER_GAP_NTB;
|
|
|
|
for (id = MAC_ZC_HW_CAP0; id < MAC_ZC_HW_CAP_CNT; id++) {
|
|
if (!mac_zc_cap_is_support(ctxt, id)) {
|
|
continue;
|
|
}
|
|
collect = &ctxt->collect[id];
|
|
if (0 == collect->collect_cnt) {
|
|
collect->last_ts = ctxt->collect[ref_id].last_ts;
|
|
//TODO: all of capture periods are the same
|
|
collect->period = ctxt->collect[ref_id].period;
|
|
}
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]state:%d,cap:%d,last_ts:%u,period:%d\n",
|
|
MAC_ZC_STATE_IDLE, id, ctxt->collect[id].last_ts,
|
|
ctxt->collect[id].period);
|
|
#endif
|
|
}
|
|
|
|
next_state = MAC_ZC_STATE_TRAINING;
|
|
}
|
|
break;
|
|
|
|
case MAC_ZC_TRIG_SYS_STOP_REQ:
|
|
mac_zc_system_stop(ctxt);
|
|
break;
|
|
|
|
default:
|
|
IOT_ASSERT_DUMP(0, (uint32_t *)ctxt, iot_ceil(sizeof(*ctxt), 4));
|
|
break;
|
|
}
|
|
|
|
return next_state;
|
|
}
|
|
|
|
static mac_zc_state_id_t mac_zc_sm_training(mac_zc_ctxt_t *ctxt,
|
|
mac_zc_trigger_id_t trig_id)
|
|
{
|
|
mac_zc_state_id_t next_state = MAC_ZC_STATE_TRAINING;
|
|
|
|
IOT_ASSERT(ctxt);
|
|
|
|
switch (trig_id) {
|
|
case MAC_ZC_TRIG_SYSTICK_INT:
|
|
if (mac_zc_collect_update(ctxt, 0)) {
|
|
if (mac_zc_collect_status_set(ctxt)) {
|
|
if (!ctxt->ntb_lts_sync.is_start) {
|
|
IOT_ASSERT_DUMP(!ctxt->nv.is_ntb_collect, (uint32_t *)ctxt,
|
|
iot_ceil(sizeof(*ctxt), 4));
|
|
next_state = MAC_ZC_STATE_TRAINED;
|
|
} else {
|
|
ctxt->daemon.last_collect_ts = mac_sched_get_ntb(NULL);
|
|
ctxt->ntb_lts_sync.cur_idx = (uint16_t)(-1);
|
|
next_state = MAC_ZC_STATE_COLLECT;
|
|
}
|
|
} else {
|
|
mac_zc_set_func_cmd(ctxt->ref_pdev_id,
|
|
MAC_ZC_FUNC_CMD_DELAY_RESET_HW, NULL);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MAC_ZC_TRIG_SYS_STOP_REQ:
|
|
mac_zc_system_stop(ctxt);
|
|
next_state = MAC_ZC_STATE_IDLE;
|
|
break;
|
|
|
|
default:
|
|
IOT_ASSERT_DUMP(0, (uint32_t *)ctxt, iot_ceil(sizeof(*ctxt), 4));
|
|
break;
|
|
}
|
|
|
|
return next_state;
|
|
}
|
|
|
|
static mac_zc_state_id_t mac_zc_sm_trained(mac_zc_ctxt_t *ctxt,
|
|
mac_zc_trigger_id_t trig_id)
|
|
{
|
|
mac_zc_state_id_t next_state = MAC_ZC_STATE_TRAINED;
|
|
|
|
switch (trig_id) {
|
|
case MAC_ZC_TRIG_SYSTICK_INT:
|
|
if (mac_zc_collect_update(ctxt, 0)) {
|
|
if (mac_zc_collect_status_set(ctxt)) {
|
|
if (ctxt->ntb_lts_sync.is_start) {
|
|
next_state = MAC_ZC_STATE_COLLECT;
|
|
}
|
|
} else {
|
|
mac_zc_set_func_cmd(ctxt->ref_pdev_id,
|
|
MAC_ZC_FUNC_CMD_DELAY_RESET_HW, NULL);
|
|
}
|
|
} else {
|
|
if (ctxt->ntb_lts_sync.is_start) {
|
|
next_state = MAC_ZC_STATE_COLLECT;
|
|
}
|
|
}
|
|
|
|
if (next_state != MAC_ZC_STATE_TRAINED) {
|
|
ctxt->daemon.last_collect_ts = mac_sched_get_ntb(NULL);
|
|
ctxt->ntb_lts_sync.cur_idx = (uint16_t)(-1);
|
|
}
|
|
break;
|
|
|
|
case MAC_ZC_TRIG_SYS_STOP_REQ:
|
|
mac_zc_system_stop(ctxt);
|
|
next_state = MAC_ZC_STATE_IDLE;
|
|
break;
|
|
|
|
default:
|
|
IOT_ASSERT_DUMP(0, (uint32_t *)ctxt, iot_ceil(sizeof(*ctxt), 4));
|
|
break;
|
|
}
|
|
|
|
return next_state;
|
|
}
|
|
|
|
static mac_zc_state_id_t mac_zc_sm_collect(mac_zc_ctxt_t *ctxt,
|
|
mac_zc_trigger_id_t trig_id)
|
|
{
|
|
mac_zc_state_id_t next_state = MAC_ZC_STATE_COLLECT;
|
|
|
|
IOT_ASSERT(ctxt);
|
|
|
|
switch (trig_id) {
|
|
case MAC_ZC_TRIG_SYSTICK_INT:
|
|
if (mac_zc_collect_update(ctxt, 1)) {
|
|
if (0 == mac_zc_collect_status_set(ctxt)) {
|
|
mac_zc_set_func_cmd(ctxt->ref_pdev_id,
|
|
MAC_ZC_FUNC_CMD_DELAY_RESET_HW, NULL);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MAC_ZC_TRIG_SYS_STOP_REQ:
|
|
mac_zc_system_stop(ctxt);
|
|
next_state = MAC_ZC_STATE_IDLE;
|
|
break;
|
|
|
|
default:
|
|
IOT_ASSERT_DUMP(0, (uint32_t *)ctxt, iot_ceil(sizeof(*ctxt), 4));
|
|
break;
|
|
}
|
|
|
|
return next_state;
|
|
}
|
|
|
|
static void mac_zc_state_machine(mac_zc_ctxt_t *ctxt,
|
|
mac_zc_trigger_id_t trig_id)
|
|
{
|
|
mac_zc_state_id_t cur_state, next_state;
|
|
|
|
IOT_ASSERT(ctxt);
|
|
|
|
cur_state = ctxt->sm.cur_state;
|
|
#if (MAC_ZC_DBG_LOG_LEVEL >= 2)
|
|
iot_printf("[zc]sm:%d,trig:%d\n", cur_state, trig_id);
|
|
#endif
|
|
switch (cur_state) {
|
|
case MAC_ZC_STATE_IDLE:
|
|
next_state = mac_zc_sm_idle(ctxt, trig_id);
|
|
break;
|
|
case MAC_ZC_STATE_TRAINING:
|
|
next_state = mac_zc_sm_training(ctxt, trig_id);
|
|
break;
|
|
case MAC_ZC_STATE_TRAINED:
|
|
next_state = mac_zc_sm_trained(ctxt, trig_id);
|
|
break;
|
|
case MAC_ZC_STATE_COLLECT:
|
|
next_state = mac_zc_sm_collect(ctxt, trig_id);
|
|
break;
|
|
default:
|
|
IOT_ASSERT_DUMP(0, (uint32_t *)ctxt, iot_ceil(sizeof(*ctxt), 4));
|
|
next_state = MAC_ZC_STATE_IDLE;
|
|
break;
|
|
}
|
|
if (next_state != cur_state)
|
|
{
|
|
iot_printf("zc:state %d to %d. trig:%d, is_power_collapsed=%d\n",
|
|
(uint8_t)cur_state, (uint8_t)next_state, trig_id,
|
|
mac_zc_is_power_collapsed((uint8_t)ctxt->ref_pdev_id));
|
|
ctxt->sm.prev_state = cur_state;
|
|
ctxt->sm.cur_state = next_state;
|
|
}
|
|
}
|
|
|
|
static uint32_t mac_zc_load_nv_info(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
uint8_t idx, offset;
|
|
uint32_t size, mtype;
|
|
mac_zc_map_info_t *map;
|
|
|
|
mtype = iot_oem_get_module_type();
|
|
/* alloc total collect buffer. start { */
|
|
switch (mtype) {
|
|
case MODULE_TYPE_CCO:
|
|
BUILD_BUG_ON(MAC_ZC_NTB_SUPPORT_CNT_CCO <= MAC_ZC_BUF_SIZE_MAX_CCO);
|
|
size = MAC_ZC_NTB_SUPPORT_CNT_CCO;
|
|
break;
|
|
|
|
case MODULE_TYPE_3_PHASE_STA:
|
|
BUILD_BUG_ON(MAC_ZC_NTB_SUPPORT_CNT_STA_3P
|
|
<= MAC_ZC_BUF_SIZE_MAX_STA_3P);
|
|
size = MAC_ZC_NTB_SUPPORT_CNT_STA_3P;
|
|
break;
|
|
|
|
default:
|
|
BUILD_BUG_ON(MAC_ZC_NTB_SUPPORT_CNT_STA <= MAC_ZC_BUF_SIZE_MAX_STA);
|
|
size = MAC_ZC_NTB_SUPPORT_CNT_STA;
|
|
break;
|
|
}
|
|
|
|
/* alloc zc ring buffer */
|
|
ctxt->nv.buffer = os_mem_malloc(PLC_MAC_ZC_MID,
|
|
size * sizeof(uint32_t));
|
|
if (NULL == ctxt->nv.buffer) {
|
|
/* memory must be allocated successfully */
|
|
IOT_ASSERT(0);
|
|
return ERR_NOMEM;
|
|
}
|
|
ctxt->nv.buf_sz = size;
|
|
/* alloc total collect buffer. end } */
|
|
|
|
#if (HW_PLATFORM == HW_PLATFORM_SILICON)
|
|
ctxt->nv.is_double_collect = (GPIO_NO_VALID
|
|
== iot_board_get_gpio(GPIO_PA_ZC_EXT)) ? 0 : 1;
|
|
#else
|
|
ctxt->nv.is_double_collect = (MODULE_TYPE_CCO == mtype) ? 1 : 0;
|
|
#endif
|
|
|
|
ctxt->nv.is_ntb_collect = (MODULE_TYPE_CCO == mtype) ? 1 : 0;
|
|
|
|
/* get phase gpio map. start { */
|
|
ctxt->nv.ena_cap_bitmap = 0;
|
|
for (idx = 0; idx < MAC_ZC_HW_CAP_CNT; idx++) {
|
|
map = &ctxt->nv.map[idx];
|
|
map->cap_id = idx;
|
|
map->is_ext = !(idx < MAC_ZC_PHASE_CNT);
|
|
if (map->is_ext) {
|
|
offset = idx - MAC_ZC_PHASE_CNT;
|
|
map->gpio = iot_board_get_gpio(GPIO_PA_ZC_EXT + offset);
|
|
} else {
|
|
offset = idx;
|
|
map->gpio = iot_board_get_gpio(GPIO_PA_ZC + offset);
|
|
}
|
|
map->phase_id = offset + MAC_ZC_PHASE_A;
|
|
|
|
#if (HW_PLATFORM == HW_PLATFORM_SILICON)
|
|
if (GPIO_NO_VALID != map->gpio) {
|
|
#if MAC_ZC_SELF_MAP_GPIO_ENA
|
|
gpio_sig_info_t info = {0};
|
|
info.sig_type = 1;
|
|
info.CFG[0].type = IO_TYPE_IN;
|
|
info.CFG[0].func = 0;
|
|
info.CFG[0].gpio = map->gpio;
|
|
info.CFG[0].inid = MAC_ZC_HW_SIG0_ID + idx;
|
|
info.CFG[0].outid = 0xFF;
|
|
gpio_module_pin_select(&info);
|
|
gpio_module_sig_select(&info, GPIO_MTX_MODE_MATRIX);
|
|
#endif
|
|
ctxt->nv.ena_cap_bitmap |= 1 << idx;
|
|
}
|
|
#else /* HW_PLATFORM == HW_PLATFORM_SILICON */
|
|
/* Note: for FPGA, mac zc capture signal connected to
|
|
* the mac zc signal is directly connected with the plc sub board,
|
|
* without passing through the kl3 chip GPIO.
|
|
*/
|
|
if (ctxt->nv.is_double_collect) {
|
|
ctxt->nv.ena_cap_bitmap |= 1 << idx;
|
|
} else {
|
|
ctxt->nv.ena_cap_bitmap |= 1 << offset;
|
|
}
|
|
#endif /* HW_PLATFORM == HW_PLATFORM_SILICON */
|
|
|
|
iot_printf("zc:cap%d,phase%d,gpio%d,ext:%d\n",
|
|
map->cap_id, map->phase_id, map->gpio, map->is_ext);
|
|
}
|
|
/* get phase gpio map. end } */
|
|
|
|
//TODO: fix base on hw version
|
|
ctxt->nv.cap_edge = MAC_ZC_HW_CAP_EDGE_RISE;
|
|
|
|
/* save nv info into flash */
|
|
mac_status_zc_nv_para_update(0, (uint8_t)ctxt->nv.cap_edge,
|
|
(uint8_t)ctxt->nv.ena_cap_bitmap, (uint8_t)ctxt->nv.is_double_collect);
|
|
|
|
iot_printf("zc:cap_ena-0x%x,edge:%d,double_collect:%d,ntb_collect:%d,"
|
|
"buf_size:%u\n",
|
|
ctxt->nv.ena_cap_bitmap, ctxt->nv.cap_edge, ctxt->nv.is_double_collect,
|
|
ctxt->nv.is_ntb_collect, ctxt->nv.buf_sz);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
static uint32_t mac_zc_daemon_init(mac_zc_ctxt_t *ctxt)
|
|
{
|
|
ctxt->daemon.last_collect_ts = mac_sched_get_ntb(NULL);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
void IRAM_ATTR mac_zc_systic_trig(void)
|
|
{
|
|
uint8_t cap_bm, id, num;
|
|
uint32_t cur_ts;
|
|
mac_zc_ctxt_t *ctxt;
|
|
|
|
ctxt = mac_zc_ctxt_get(PLC_PDEV_ID);
|
|
|
|
if (!ctxt->systick.is_ena || !ctxt->systick.check_period) {
|
|
return;
|
|
}
|
|
|
|
cur_ts = mac_sched_get_lts();
|
|
if ((uint32_t)(cur_ts - ctxt->systick.ts) > ctxt->systick.check_period) {
|
|
cap_bm = mac_zc_cap_support_bm_get(ctxt);
|
|
while (cap_bm) {
|
|
id = iot_bitops_ffs(cap_bm) - 1;
|
|
cap_bm &= ~(1 << id);
|
|
if (ctxt->nv.is_ntb_collect) {
|
|
num = mac_zc_hw_cap_ntb_read(id,
|
|
IOT_ARRAY_CNT(ctxt->systick.isr_buf),
|
|
ctxt->systick.isr_buf);
|
|
} else {
|
|
num = mac_zc_hw_cap_lts_read(id,
|
|
IOT_ARRAY_CNT(ctxt->systick.isr_buf),
|
|
ctxt->systick.isr_buf);
|
|
}
|
|
if (num) {
|
|
if (mac_zc_sw_fifo_puts(&ctxt->collect[id].ntb_fifo,
|
|
ctxt->systick.isr_buf, num) < num) {
|
|
ctxt->collect[id].ntb_fifo.is_overflow = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
os_set_task_event_with_v_from_isr(ctxt->hook.hdl,
|
|
(uint32_t)(0x1 << MAC_DSR_ZC_SYSTIC_TRIG_CB_ID));
|
|
ctxt->systick.ts = cur_ts;
|
|
}
|
|
}
|
|
|
|
void mac_zc_train_hw_timeout_internal(uint32_t id, void *arg)
|
|
{
|
|
(void)id;
|
|
(void)arg;
|
|
}
|
|
|
|
void mac_zc_set_func_cmd_internal(uint8_t zc_id, uint8_t cmd, void *arg)
|
|
{
|
|
mac_zc_ctxt_t *ctxt;
|
|
|
|
(void)arg;
|
|
ctxt = mac_zc_ctxt_get(zc_id);
|
|
|
|
switch ((mac_zc_func_cmd_id_t)cmd) {
|
|
case MAC_ZC_FUNC_CMD_DELAY_RESET_HW:
|
|
/* stop mac zc system */
|
|
mac_zc_state_machine(ctxt, MAC_ZC_TRIG_SYS_STOP_REQ);
|
|
/* start mac zc system */
|
|
mac_zc_state_machine(ctxt, MAC_ZC_TRIG_SYS_START_REQ);
|
|
mac_status_add_zc_reset_hw_cnt();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void mac_zc_set_func_cmd(uint8_t zc_id, mac_zc_func_cmd_id_t cmd, void *arg)
|
|
{
|
|
#if (HW_PLATFORM >= HW_PLATFORM_FPGA)
|
|
mac_zc_ctxt_t *ctxt;
|
|
mac_msg_t *msg;
|
|
|
|
(void)arg;
|
|
ctxt = mac_zc_ctxt_get(zc_id);
|
|
IOT_ASSERT(ctxt);
|
|
|
|
iot_printf("zc:set_cmd-%u\n", cmd);
|
|
|
|
switch (cmd) {
|
|
case MAC_ZC_FUNC_CMD_RESET_HW:
|
|
/* stop mac zc system */
|
|
mac_zc_state_machine(ctxt, MAC_ZC_TRIG_SYS_STOP_REQ);
|
|
/* start mac zc system */
|
|
mac_zc_state_machine(ctxt, MAC_ZC_TRIG_SYS_START_REQ);
|
|
mac_status_add_zc_reset_hw_cnt();
|
|
break;
|
|
|
|
case MAC_ZC_FUNC_CMD_COLLECT_STOP:
|
|
/* stop mac zc system */
|
|
mac_zc_state_machine(ctxt, MAC_ZC_TRIG_SYS_STOP_REQ);
|
|
break;
|
|
|
|
case MAC_ZC_FUNC_CMD_DELAY_RESET_HW:
|
|
msg = mac_alloc_msg();
|
|
IOT_ASSERT(msg);
|
|
msg->type = MAC_MSG_TYPE_MAC;
|
|
msg->id = MAC_MSG_ID_MAC_ZC_SET_FUNC_CMD;
|
|
msg->data1 = zc_id | (cmd << 8);
|
|
msg->data2 = arg;
|
|
mac_queue_msg(msg, MAC_MSG_QUEUE_HP);
|
|
break;
|
|
|
|
case MAC_ZC_FUNC_CMD_NTB_STABLE_NOTIF:
|
|
ctxt->ntb_lts_sync.is_start = 1;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
#else
|
|
(void)zc_id;
|
|
(void)cmd;
|
|
(void)arg;
|
|
#endif
|
|
}
|
|
|
|
uint8_t mac_zc_is_power_collapsed(uint8_t pdev_id)
|
|
{
|
|
mac_zc_ctxt_t *ctxt = mac_zc_ctxt_get(pdev_id);
|
|
|
|
return (uint8_t)ctxt->is_power_collapsed;
|
|
}
|
|
|
|
uint32_t mac_zc_system_init(uint8_t id, void *task_hdl, void *dsr_tbl,
|
|
void *dsr_set_fn, void *dsr_clr_fn)
|
|
{
|
|
uint32_t err_no = 0;
|
|
mac_zc_ctxt_t *ctxt;
|
|
|
|
if (id >= MAC_ZC_NUM_MAX) {
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
do {
|
|
ctxt = mac_zc_ctxt_get(id);
|
|
if (NULL == ctxt) {
|
|
err_no = __LINE__;
|
|
IOT_ASSERT(ctxt);
|
|
break;
|
|
}
|
|
/* clean zc ctxt data */
|
|
os_mem_set(ctxt, 0, sizeof(*ctxt));
|
|
|
|
ctxt->ref_pdev_id = id;
|
|
|
|
mac_zc_set_hook(ctxt, task_hdl, dsr_tbl, dsr_set_fn, dsr_clr_fn);
|
|
|
|
if (ERR_OK != mac_zc_load_nv_info(ctxt)) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
if (ERR_OK != mac_zc_daemon_init(ctxt)) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
if (ERR_OK != mac_zc_collect_info_init(ctxt)) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
} while (0);
|
|
|
|
if (0 == err_no) {
|
|
mac_zc_system_stop(ctxt);
|
|
|
|
ctxt->sm.cur_state = MAC_ZC_STATE_IDLE;
|
|
ctxt->sm.prev_state = MAC_ZC_STATE_IDLE;
|
|
|
|
ctxt->is_power_collapsed = 0;
|
|
}
|
|
|
|
iot_printf("zc:sys_init-%d.ena:%d,%u\n",
|
|
id, MAC_ZC_ENABLE, mac_sched_get_ntb(NULL));
|
|
|
|
return (err_no ? ERR_FAIL : ERR_OK);
|
|
}
|
|
|
|
#else /* MAC_ZC_ENABLE */
|
|
|
|
uint32_t mac_zc_system_init(uint8_t id, void *task_hdl, void *dsr_tbl,
|
|
void *dsr_set_fn, void *dsr_clr_fn)
|
|
{
|
|
(void)id;
|
|
(void)task_hdl;
|
|
(void)dsr_tbl;
|
|
(void)dsr_set_fn;
|
|
(void)dsr_clr_fn;
|
|
|
|
iot_printf("zc:sys_init-%d.ena:%d,%u\n",
|
|
id, MAC_ZC_ENABLE, mac_sched_get_ntb(NULL));
|
|
|
|
return ERR_NOSUPP;
|
|
}
|
|
|
|
#endif /* MAC_ZC_ENABLE */
|