574 lines
17 KiB
C
574 lines
17 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 "mac_rf_rx_buf_ring.h"
|
|
#include "iot_errno.h"
|
|
#include "iot_utils.h"
|
|
#include "iot_io.h"
|
|
#include "plc_utils.h"
|
|
#include "plc_mac_cfg.h"
|
|
#include "mac.h"
|
|
#include "plc_fr.h"
|
|
#include "plc_const.h"
|
|
#include "mac_rf_pdev.h"
|
|
#include "mac_rx_buf_ring.h"
|
|
#include "mac_rf_isr.h"
|
|
#include "mac_rf_rx_hw.h"
|
|
#include "math_log10.h"
|
|
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
|
|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
|
|
|
|
#include "hw_reg_api.h"
|
|
#include "rf_mac_rx_reg.h"
|
|
#include "rf_mac_int.h"
|
|
|
|
/* get rf ring buffer read index */
|
|
#define RF_RX_RING_GET_RD_IDX(ring_id) \
|
|
REG_FIELD_GET(CFG_RF_RING##ring_id##_RD_IDX, \
|
|
RGF_RF_RX_READ_REG(RF_BUFFER_RING##ring_id##_2_ADDR))
|
|
|
|
/* set rf ring buffer read index */
|
|
#define RF_RX_RING_SET_RD_IDX(ring_id, value) \
|
|
do { \
|
|
uint32_t __tmp = RGF_RF_RX_READ_REG( \
|
|
RF_BUFFER_RING##ring_id##_2_ADDR); \
|
|
REG_FIELD_SET(CFG_RF_RING##ring_id##_RD_IDX, \
|
|
__tmp, value); \
|
|
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING##ring_id##_2_ADDR, __tmp); \
|
|
} while (0)
|
|
|
|
/* get rf ring buffer write index */
|
|
#define RF_RX_RING_GET_WR_IDX(ring_id, reg_idx) \
|
|
REG_FIELD_GET(RO_RF_RING##ring_id##_MPDU_BUF_WR_IDX, \
|
|
RGF_RF_RX_READ_REG(RX_BUF_RING_WR_IDX_##reg_idx##_ADDR))
|
|
|
|
#define RF_RX_RING_SET_FILTER(ring_id, value) \
|
|
do { \
|
|
uint32_t __tmp = RGF_RF_RX_READ_REG( \
|
|
RF_BUFFER_RING##ring_id##_1_ADDR); \
|
|
REG_FIELD_SET(CFG_RF_RING##ring_id##_FILTER, \
|
|
__tmp, value); \
|
|
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING##ring_id##_1_ADDR, __tmp); \
|
|
} while (0)
|
|
|
|
void rf_rx_ring_clr_overflow_int(uint32_t rid)
|
|
{
|
|
//TODO: add code
|
|
(void)rid;
|
|
}
|
|
|
|
uint32_t rf_rx_ring_get_mpdu_int_status(void)
|
|
{
|
|
uint32_t tmp;
|
|
tmp = mac_rf_get_share_interrupt_sts();
|
|
/* clear interrupt status */
|
|
mac_rf_clear_share_interrupt(RF_MAC_INT_RX_RING_BIT_MASK & tmp);
|
|
return ((tmp & RF_MAC_INT_RX_RING_BIT_MASK)
|
|
>> RF_MAC_INT_RX_RING_BIT_OFFSET);
|
|
}
|
|
|
|
void rf_rx_ring_clr_mpdu_int(uint32_t rid)
|
|
{
|
|
if (rid > MAX_RF_RX_RING_NUM) {
|
|
return;
|
|
}
|
|
mac_rf_clear_share_interrupt(1 << (rid + RF_MAC_INT_RX_RING_BIT_OFFSET));
|
|
}
|
|
|
|
/* get ring rd idx */
|
|
uint32_t rf_rx_ring_get_rd_idx(rx_buf_ring_t *rf_rx_ring)
|
|
{
|
|
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_RF_RX_RING_NUM));
|
|
switch (rf_rx_ring->ring_id) {
|
|
case 0:
|
|
return RF_RX_RING_GET_RD_IDX(0);
|
|
case 1:
|
|
return RF_RX_RING_GET_RD_IDX(1);
|
|
case 2:
|
|
return RF_RX_RING_GET_RD_IDX(2);
|
|
case 3:
|
|
return RF_RX_RING_GET_RD_IDX(3);
|
|
case 4:
|
|
return RF_RX_RING_GET_RD_IDX(4);
|
|
case 5:
|
|
return RF_RX_RING_GET_RD_IDX(5);
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* set ring rd idx */
|
|
void rf_rx_ring_set_rd_idx(rx_buf_ring_t *rf_rx_ring, uint32_t value)
|
|
{
|
|
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_RF_RX_RING_NUM));
|
|
switch (rf_rx_ring->ring_id) {
|
|
case 0:
|
|
RF_RX_RING_SET_RD_IDX(0, value);
|
|
break;
|
|
case 1:
|
|
RF_RX_RING_SET_RD_IDX(1, value);
|
|
break;
|
|
case 2:
|
|
RF_RX_RING_SET_RD_IDX(2, value);
|
|
break;
|
|
case 3:
|
|
RF_RX_RING_SET_RD_IDX(3, value);
|
|
break;
|
|
case 4:
|
|
RF_RX_RING_SET_RD_IDX(4, value);
|
|
break;
|
|
case 5:
|
|
RF_RX_RING_SET_RD_IDX(5, value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* get ring rd idx */
|
|
uint32_t rf_rx_ring_get_wr_idx(rx_buf_ring_t *rf_rx_ring)
|
|
{
|
|
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_RF_RX_RING_NUM));
|
|
switch (rf_rx_ring->ring_id) {
|
|
case 0:
|
|
return RF_RX_RING_GET_WR_IDX(0, 0);
|
|
case 1:
|
|
return RF_RX_RING_GET_WR_IDX(1, 0);
|
|
case 2:
|
|
return RF_RX_RING_GET_WR_IDX(2, 0);
|
|
case 3:
|
|
return RF_RX_RING_GET_WR_IDX(3, 1);
|
|
case 4:
|
|
return RF_RX_RING_GET_WR_IDX(4, 1);
|
|
case 5:
|
|
return RF_RX_RING_GET_WR_IDX(5, 1);
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint8_t rf_rx_ring_set_filter(rx_buf_ring_t *rf_rx_ring)
|
|
{
|
|
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_RF_RX_RING_NUM));
|
|
switch(rf_rx_ring->ring_id) {
|
|
case 0:
|
|
RF_RX_RING_SET_FILTER(0, rf_rx_ring->filter);
|
|
break;
|
|
case 1:
|
|
RF_RX_RING_SET_FILTER(1, rf_rx_ring->filter);
|
|
break;
|
|
case 2:
|
|
RF_RX_RING_SET_FILTER(2, rf_rx_ring->filter);
|
|
break;
|
|
case 3:
|
|
RF_RX_RING_SET_FILTER(3, rf_rx_ring->filter);
|
|
break;
|
|
case 4:
|
|
RF_RX_RING_SET_FILTER(4, rf_rx_ring->filter);
|
|
break;
|
|
case 5:
|
|
RF_RX_RING_SET_FILTER(5, rf_rx_ring->filter);
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* enable rx ring */
|
|
void mac_rf_rx_ring_enable(rx_buf_ring_t *rf_rx_ring, uint32_t enable)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_RF_RX_RING_NUM));
|
|
switch (rf_rx_ring->ring_id) {
|
|
case 0:
|
|
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING0_2_ADDR);
|
|
REG_FIELD_SET(CFG_RF_RING0_EN, tmp, enable);
|
|
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING0_2_ADDR, tmp);
|
|
break;
|
|
case 1:
|
|
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING1_2_ADDR);
|
|
REG_FIELD_SET(CFG_RF_RING1_EN, tmp, enable);
|
|
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING1_2_ADDR, tmp);
|
|
break;
|
|
case 2:
|
|
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING2_2_ADDR);
|
|
REG_FIELD_SET(CFG_RF_RING2_EN, tmp, enable);
|
|
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING2_2_ADDR, tmp);
|
|
break;
|
|
case 3:
|
|
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING3_2_ADDR);
|
|
REG_FIELD_SET(CFG_RF_RING3_EN, tmp, enable);
|
|
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING3_2_ADDR, tmp);
|
|
break;
|
|
case 4:
|
|
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING4_2_ADDR);
|
|
REG_FIELD_SET(CFG_RF_RING4_EN, tmp, enable);
|
|
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING4_2_ADDR, tmp);
|
|
break;
|
|
case 5:
|
|
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING5_2_ADDR);
|
|
REG_FIELD_SET(CFG_RF_RING5_EN, tmp, enable);
|
|
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING5_2_ADDR, tmp);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* fill in the ring cfg */
|
|
void rf_rx_ring_fill_hw_cfg(rx_buf_ring_t *rf_rx_ring)
|
|
{
|
|
uint32_t tmp;
|
|
uint32_t ring_addr0, ring_addr1, ring_addr3;
|
|
|
|
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_PLC_RX_RING_NUM));
|
|
switch (rf_rx_ring->ring_id) {
|
|
case 0:
|
|
ring_addr0 = RF_BUFFER_RING0_0_ADDR;
|
|
ring_addr1 = RF_BUFFER_RING0_1_ADDR;
|
|
ring_addr3 = RF_BUFFER_RING0_3_ADDR;
|
|
break;
|
|
case 1:
|
|
ring_addr0 = RF_BUFFER_RING1_0_ADDR;
|
|
ring_addr1 = RF_BUFFER_RING1_1_ADDR;
|
|
ring_addr3 = RF_BUFFER_RING1_3_ADDR;
|
|
break;
|
|
case 2:
|
|
ring_addr0 = RF_BUFFER_RING2_0_ADDR;
|
|
ring_addr1 = RF_BUFFER_RING2_1_ADDR;
|
|
ring_addr3 = RF_BUFFER_RING2_3_ADDR;
|
|
break;
|
|
case 3:
|
|
ring_addr0 = RF_BUFFER_RING3_0_ADDR;
|
|
ring_addr1 = RF_BUFFER_RING3_1_ADDR;
|
|
ring_addr3 = RF_BUFFER_RING3_3_ADDR;
|
|
break;
|
|
case 4:
|
|
ring_addr0 = RF_BUFFER_RING4_0_ADDR;
|
|
ring_addr1 = RF_BUFFER_RING4_1_ADDR;
|
|
ring_addr3 = RF_BUFFER_RING4_3_ADDR;
|
|
break;
|
|
case 5:
|
|
default:
|
|
ring_addr0 = RF_BUFFER_RING5_0_ADDR;
|
|
ring_addr1 = RF_BUFFER_RING5_1_ADDR;
|
|
ring_addr3 = RF_BUFFER_RING5_3_ADDR;
|
|
break;
|
|
}
|
|
/* set ring buf array ptr */
|
|
RGF_RF_RX_WRITE_REG(ring_addr0, (uint32_t)rf_rx_ring->buf_list);
|
|
|
|
/* set ring size and buf length */
|
|
tmp = RGF_RF_RX_READ_REG(ring_addr1);
|
|
REG_FIELD_SET(CFG_RF_RING0_BUF_SIZE, tmp, iot_ceil(rf_rx_ring->buf_sz, 4));
|
|
REG_FIELD_SET(CFG_RF_RING0_BUF_NUM, tmp, rf_rx_ring->ring_sz);
|
|
/* re-enable ring, disable clr wr idx */
|
|
REG_FIELD_SET(CFG_RF_RING0_BUF_REENA_CLR_EN, tmp, 0);
|
|
RGF_RF_RX_WRITE_REG(ring_addr1, tmp);
|
|
|
|
rf_rx_ring_set_filter(rf_rx_ring);
|
|
|
|
/* set rd idx = 0 as default */
|
|
rf_rx_ring_set_rd_idx(rf_rx_ring, 0);
|
|
|
|
/* set desc and payload offset */
|
|
tmp = RGF_RF_RX_READ_REG(ring_addr3);
|
|
REG_FIELD_SET(CFG_RF_RING0_DESC_EN, tmp,
|
|
rf_rx_ring->config[CONFIG_RX_DESC].enable);
|
|
REG_FIELD_SET(CFG_RF_RING0_PAYLOAD_EN, tmp,
|
|
rf_rx_ring->config[CONFIG_PAYLOAD].enable);
|
|
REG_FIELD_SET(CFG_RF_RING0_DESC_OFFSET, tmp,
|
|
iot_ceil(rf_rx_ring->config[CONFIG_RX_DESC].offset, 4));
|
|
REG_FIELD_SET(CFG_RF_RING0_PAYLOAD_OFFSET, tmp,
|
|
iot_ceil(rf_rx_ring->config[CONFIG_PAYLOAD].offset, 4));
|
|
RGF_RF_RX_WRITE_REG(ring_addr3, tmp);
|
|
}
|
|
|
|
rx_buf_ring_t *mac_rf_rx_get_ring(void *rf_pdev, uint32_t index)
|
|
{
|
|
if (index >= MAX_RF_RX_RING_NUM) {
|
|
IOT_ASSERT(0);
|
|
return NULL;
|
|
}
|
|
mac_rf_pdev_t *rf_pdev_ptr = (mac_rf_pdev_t *)rf_pdev;
|
|
IOT_ASSERT(rf_pdev_ptr);
|
|
return &rf_pdev_ptr->ring_hdl.ring[index];
|
|
}
|
|
|
|
#endif /* HW_PLATFORM >= HW_PLATFORM_FPGA */
|
|
|
|
#if ((HW_PLATFORM >= HW_PLATFORM_FPGA) && (HPLC_BBCPU_CALC_SNR_RSSI == 0))
|
|
|
|
static float mac_rf_get_snr(uint32_t option, uint32_t raw_reg1,
|
|
uint16_t *raw_snr)
|
|
{
|
|
float snr;
|
|
float rdata = (float)raw_reg1;
|
|
float rawdata = (1<<16)*1.0/(rdata*1.0/((option==3) ? 36 : 96));
|
|
float tmp = rawdata * 10 + 0.5;
|
|
*raw_snr = (uint16_t)(min(0xFFFF, (uint32_t)tmp));
|
|
if (rawdata >= 1) {
|
|
snr = 10*mlog10(rawdata);
|
|
} else {
|
|
snr = 10*na_mlog10(rawdata);
|
|
}
|
|
|
|
return snr;
|
|
}
|
|
|
|
static void mac_rf_get_snr_rssi(uint32_t option, uint32_t raw_reg1,
|
|
uint32_t raw_reg2, uint32_t raw_reg3, int8_t *snr, int8_t *rssi,
|
|
uint8_t *gain, uint16_t *raw_snr)
|
|
{
|
|
/* X can be got by calibration */
|
|
#define X_CALIBRATION 60
|
|
float snr_tmp = mac_rf_get_snr(option, raw_reg1, raw_snr);
|
|
float rdata1 = (float)raw_reg2;
|
|
uint32_t rdata2 = raw_reg3;
|
|
float rssi_tmp = 10*mlog10(rdata1*1.0) - X_CALIBRATION - (rdata2 & 0xFF) -
|
|
((rdata2 >> 8) & 0xFF) + ((snr_tmp < 0) ? snr_tmp: 0);
|
|
/* 13 - 74 */
|
|
*gain = (uint8_t)((rdata2 & 0xFF) + ((rdata2 >> 8) & 0xFF));
|
|
*snr = (int8_t)snr_tmp;
|
|
*rssi = (int8_t)rssi_tmp;
|
|
}
|
|
|
|
static void mac_rf_cal_snr_rssi_gain(rf_rx_attention *att,
|
|
rf_rx_mpdu_start *mpdu_st)
|
|
{
|
|
IOT_ASSERT(att && mpdu_st);
|
|
/* get record raw register */
|
|
uint32_t rawreg1 = mpdu_st->raw_snr_rssi_reg1;
|
|
uint32_t rawreg2 = mpdu_st->raw_snr_rssi_reg2;
|
|
uint32_t rawreg3 = mpdu_st->raw_snr_rssi_reg3;
|
|
/* clear record raw register */
|
|
mpdu_st->raw_snr_rssi_reg1 = 0;
|
|
mpdu_st->raw_snr_rssi_reg2 = 0;
|
|
mpdu_st->raw_snr_rssi_reg3 = 0;
|
|
|
|
int8_t snr, rssi;
|
|
uint8_t rx_gain;
|
|
uint16_t raw_snr;
|
|
/* calculate snr, rssi rx gain, raw snr */
|
|
mac_rf_get_snr_rssi(att->option, rawreg1, rawreg2, rawreg3,
|
|
&snr, &rssi, &rx_gain, &raw_snr);
|
|
|
|
/* record snr */
|
|
mac_rf_rx_mpdu_st_set_avg_snr(mpdu_st, snr);
|
|
/* record raw snr */
|
|
mac_rf_rx_mpdu_st_set_raw_snr(mpdu_st, raw_snr);
|
|
/* record rssi */
|
|
mac_rf_rx_mpdu_st_set_rssi(mpdu_st, rssi);
|
|
/* record rx gain */
|
|
mac_rf_rx_mpdu_st_set_rx_gain(mpdu_st, rx_gain);
|
|
}
|
|
|
|
#else /* (HW_PLATFORM >= HW_PLATFORM_FPGA) && (HPLC_BBCPU_CALC_SNR_RSSI == 0) */
|
|
|
|
static void mac_rf_cal_snr_rssi_gain(rf_rx_attention *att,
|
|
rf_rx_mpdu_start *mpdu_st)
|
|
{
|
|
(void)att;
|
|
(void)mpdu_st;
|
|
}
|
|
|
|
#endif /* (HW_PLATFORM >= HW_PLATFORM_FPGA) && (HPLC_BBCPU_CALC_SNR_RSSI == 0) */
|
|
|
|
void mac_rf_rx_all_ring_enable(void *rf_pdev)
|
|
{
|
|
rx_buf_ring_t *rf_ring;
|
|
mac_rf_pdev_t *rf_pdev_ptr = (mac_rf_pdev_t *)rf_pdev;
|
|
IOT_ASSERT(rf_pdev_ptr);
|
|
for (uint32_t i = 0; i < MAX_RF_RX_RING_NUM; i++){
|
|
/* get ring pointer */
|
|
rf_ring = mac_rf_rx_get_ring(rf_pdev, i);
|
|
/* enable ring */
|
|
if(rf_ring->cfg_enabled == 1) {
|
|
mac_rf_rx_ring_enable(rf_ring, 1);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void mac_rf_rx_all_ring_disable(void *rf_pdev)
|
|
{
|
|
rx_buf_ring_t *rf_ring;
|
|
mac_rf_pdev_t *rf_pdev_ptr = (mac_rf_pdev_t *)rf_pdev;
|
|
IOT_ASSERT(rf_pdev_ptr);
|
|
for (uint32_t i = 0; i < MAX_RF_RX_RING_NUM; i++){
|
|
/* get ring pointer */
|
|
rf_ring = mac_rf_rx_get_ring(rf_pdev, i);
|
|
if(rf_ring->cfg_enabled == 1){
|
|
mac_rf_rx_ring_enable(rf_ring, 0);
|
|
if (rf_pdev_ptr->rx) {
|
|
mac_rf_rx_hw_mpdu_internal(rf_pdev_ptr, i, MAX_RX_QUOTA_MS);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
uint32_t mac_rf_rx_ring_ctxt_init(mac_rx_ring_ctxt_t *rf_ring_ctxt)
|
|
{
|
|
uint32_t ret;
|
|
/* init only one rx ring temply */
|
|
ring_config config_sof[] =
|
|
{
|
|
{ CONFIG_RX_DESC, RF_RX_ATTENTION_OFFSET, 1 },
|
|
{ CONFIG_RX_MPDU_START, 0, 0 },
|
|
{ CONFIG_RX_MPDU_END, 0, 0 },
|
|
{ CONFIG_RX_PB_START, 0, 0 },
|
|
{ CONFIG_RX_PB_END, 0, 0 },
|
|
{ CONFIG_FC, 0, 0 },
|
|
{ CONFIG_PAYLOAD, RF_RX_PB_PAYLOAD_OFFSET, 1 }
|
|
};
|
|
rf_ring_ctxt->mpdu_pb_cb = NULL;
|
|
ret = rf_rx_buf_ring_init(&rf_ring_ctxt->ring[RF_RING_0], RF_RING_0,
|
|
(uint32_t)RF_SHORT_RX_BUF_COUNT, PLC_SHORT_BUF_SIZE, NULL,
|
|
config_sof, 0, 0);
|
|
if (ERR_OK != ret) {
|
|
/* return error */
|
|
goto out;
|
|
}
|
|
|
|
/*init ring1 bufsize = 136*/
|
|
ret = rf_rx_buf_ring_init(&rf_ring_ctxt->ring[RF_RING_1], RF_RING_1,
|
|
(uint32_t)RF_SMALL_RX_BUF_COUNT, PLC_SMALL_BUF_SIZE, NULL,
|
|
config_sof, 0, 0);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
/* init and put on the buf_list */
|
|
uint32_t rf_rx_buf_ring_init(rx_buf_ring_t *rf_rx_ring, uint32_t ring_id,
|
|
uint32_t ring_sz, uint32_t buf_sz, rx_low_watermark_callback cb,
|
|
ring_config *cfg, uint8_t bufsz_filter_sel, uint8_t filter)
|
|
{
|
|
iot_pkt_t *iot_pkt;
|
|
uint8_t *data_ptr;
|
|
|
|
if(!rf_rx_ring->buf_list){
|
|
rf_rx_ring->buf_list =
|
|
(uint8_t**)os_mem_malloc(PLC_MAC_RX_RING_MID,
|
|
ring_sz * mac_rx_get_ring_buf_desc_size());
|
|
|
|
if (!rf_rx_ring->buf_list) {
|
|
return ERR_NOMEM;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < ring_sz; i++) {
|
|
iot_pkt = iot_pkt_alloc(buf_sz, PLC_MAC_RX_HW_MID);
|
|
if (!iot_pkt) {
|
|
/* alloc failed */
|
|
IOT_ASSERT(0);
|
|
return ERR_NOMEM;
|
|
}
|
|
else {
|
|
/* alloc successful */
|
|
/* set and check data field len */
|
|
data_ptr = iot_pkt_put(iot_pkt, buf_sz);
|
|
IOT_ASSERT(data_ptr);
|
|
|
|
mac_rx_set_ring_buf_list(rf_rx_ring->buf_list, ring_sz,
|
|
i, iot_pkt);
|
|
}
|
|
}
|
|
}
|
|
rf_rx_ring->read_idx = 0;
|
|
rf_rx_ring->write_idx = 0;
|
|
rf_rx_ring->ring_id = ring_id;
|
|
rf_rx_ring->water_mark_buf_num = ring_sz << 2; // 1/4 of ring_sz
|
|
rf_rx_ring->overflow = 0;
|
|
rf_rx_ring->bufsz_filter_sel = bufsz_filter_sel;
|
|
rf_rx_ring->filter = filter;
|
|
rf_rx_ring->buf_sz = buf_sz;
|
|
rf_rx_ring->ring_sz = ring_sz;
|
|
rf_rx_ring->config[CONFIG_RX_DESC] = cfg[CONFIG_RX_DESC];
|
|
rf_rx_ring->config[CONFIG_PAYLOAD] = cfg[CONFIG_PAYLOAD];
|
|
rf_rx_ring->cb = cb;
|
|
rf_rx_ring->cfg_enabled = 1;
|
|
rf_rx_ring_fill_hw_cfg(rf_rx_ring);
|
|
return ERR_OK;
|
|
}
|
|
|
|
/* FW call this to reap data down and repurnish the buf */
|
|
uint32_t rf_pop_buf_from_ring(rx_buf_ring_t *rf_rx_ring, uint32_t num,
|
|
iot_pkt_t **buf_array)
|
|
{
|
|
uint32_t aval_num = 0;
|
|
uint32_t read_num = 0;
|
|
iot_pkt_t *p_buf = NULL;
|
|
uint8_t *rx_buf_addr;
|
|
|
|
if (!rf_rx_ring)
|
|
{
|
|
return read_num;
|
|
}
|
|
|
|
/* read rd and wr idx */
|
|
rf_rx_ring->write_idx = rf_rx_ring_get_wr_idx(rf_rx_ring);
|
|
rf_rx_ring->read_idx = rf_rx_ring_get_rd_idx(rf_rx_ring);
|
|
|
|
(aval_num = (rf_rx_ring->write_idx - rf_rx_ring->read_idx)) < 0 ? \
|
|
aval_num += (rf_rx_ring->ring_sz) : aval_num;
|
|
read_num = min(aval_num, num);
|
|
|
|
for (uint32_t i = 0; i < read_num; i++)
|
|
{
|
|
/* get the iot_pkt_t ptr and reap the buf */
|
|
buf_array[i] = mac_rx_get_ring_buf_list(rf_rx_ring);
|
|
|
|
/* repurnish another buf */
|
|
p_buf = iot_pkt_alloc(rf_rx_ring->buf_sz, PLC_MAC_RF_MID);
|
|
if (!p_buf) {
|
|
//IOT_ASSERT(0);
|
|
return i;
|
|
}
|
|
|
|
rf_rx_buf_hdr_t *rf_rx_buf =
|
|
(rf_rx_buf_hdr_t *)iot_pkt_data(buf_array[i]);
|
|
/* calculate snr/rssi/rx gain */
|
|
mac_rf_cal_snr_rssi_gain(&rf_rx_buf->att, &rf_rx_buf->mpdu_st);
|
|
|
|
rx_buf_addr = iot_pkt_put(p_buf, rf_rx_ring->buf_sz);
|
|
|
|
IOT_ASSERT(rx_buf_addr);
|
|
/* clear the mpdu_done bit, sometimes HW move the
|
|
* wr idx without write to the rx buf when rx abort
|
|
* happen
|
|
*/
|
|
((rf_rx_attention*)(iot_pkt_data(p_buf)))->rx_mpdu_done = 0;
|
|
|
|
mac_rx_set_ring_buf_list(rf_rx_ring->buf_list, rf_rx_ring->ring_sz,
|
|
rf_rx_ring->read_idx, p_buf);
|
|
|
|
if (++rf_rx_ring->read_idx == rf_rx_ring->ring_sz) {
|
|
rf_rx_ring->read_idx = 0;
|
|
}
|
|
rf_rx_ring_set_rd_idx(rf_rx_ring, rf_rx_ring->read_idx);
|
|
}
|
|
return read_num;
|
|
}
|
|
|
|
#endif /* HPLC_RF_DEV_SUPPORT */
|