回复
<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Star</font></font> </a> yun
发帖数: 4
注册日期: ‎09-10-2017
已接受解答

EFR32FG12实现变长包通信中遇到的问题

我使用两块BRD4253A开发套件做变长包通信实验时,通过Simiplicity IDE生成了“simple_trx_with_fifo”项目,然后修改其配置为915MHz, Bitrate为500kbps,Maximum Length为512bytes,Variable Length Bit Size为9bits,其余配置均不变,生成代码后对其进行必要的修改,发送1000个数据包,每个数据包长度为34B或52B(加上Header所占空间),当发送数据包长为34B,调试时发现程序直接跳转到RAILCb_TxPacketSent()函数;而当发送包长度为52B时,调试时发现程序却跳转到RAILCb_TxFifoAlmostEmpty()函数。然而RAILCb_TxFifoAlmostEmpty()函数的注解是这样些的“Callback that fires when the transmit fifo falls under the configured threshold value.”,我的发送FIFO配置的是40,但现在却得到相反的结果,即发送包长度大于配置的发送FIFO时,回调RAILCb_TxFifoAlmostEmpty(),发送包小于配置的发送FIFO时,却不回调,这怎么解释呢?

代码如下:

/***************************************************************************//**
 * @file main.c
 * @brief This application demonstrates the simplest exchange of transmit and receive operation in FIFO mode between two nodes.
 * @copyright Copyright 2017 Silicon Laboratories, Inc. http://www.silabs.com
 ******************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include "rail.h"
#include "hal_common.h"
#include "rail_config.h"
#include "em_chip.h"
#include "bsp.h"
#include "retargetserial.h"
#include "gpiointerrupt.h"

#include "graphics.h"

#include <string.h>

#define MAX_FRAME_LENGTH (512)
#define PACKET_HEADER_LEN (2)

#define LED_TX (0)
#define LED_RX  (1)
#define TX_FIFO_THRESHOLD (40)
#define RX_FIFO_THRESHOLD (100)

const uint8_t channel = 0;
int currentConfig = 0; //default is first in list
uint8_t txPtr[TX_FIFO_THRESHOLD];
uint8_t rxPtr[TX_FIFO_THRESHOLD];

uint16_t txLength;
uint16_t txWritten;
volatile uint16_t rxReceived;
volatile uint16_t rxExpected;
volatile uint8_t fifoReads;
volatile bool packetTx = false; //go into transfer mode
volatile bool packetRx = true;  //go into receive mode

typedef struct ButtonArray{
  GPIO_Port_TypeDef   port;
  unsigned int        pin;
} ButtonArray_t;

static const ButtonArray_t buttonArray[BSP_NO_OF_BUTTONS] = BSP_GPIO_BUTTONARRAY_INIT;

static const RAIL_Init_t railInitParams = {
  256,
  RADIO_CONFIG_XTAL_FREQUENCY,
  RAIL_CAL_ALL,
};

static const RAIL_CalInit_t calInitParams = {
  RAIL_CAL_ALL,
  irCalConfig,
};

struct statistics_s {
  uint32_t txLen;
  uint32_t txPktCnt;
  uint32_t rxPktCnt;

  uint32_t txStartTime;
  uint32_t rxStartTime;
  uint32_t txEndTime;
  uint32_t rxEndTime;
  double txTime;
  double rxTime;

  uint16_t txPktRate;
  uint16_t rxPktRate;

  uint32_t errNo;
} Statistics;

#define PKT_LEN   (50 + PACKET_HEADER_LEN)
#define SEND_CNT  1000

// Prototypes
void changeRadioConfig(int newConfig);
void radioInit();
void gpioCallback(uint8_t pin);
void printBuffer(uint8_t * buffer, const uint16_t bufferLength);
void buttonInit();
void sendPacket(uint16_t packetLength);
void startReceive();

static void displayStatics(void);

int main(void)
{
  // Initialize the chip
  CHIP_Init();

  // Initialize the system clocks and other HAL components
  halInit();

  // Initialize the BSP
  BSP_Init(BSP_INIT_BCC);

  // Initialize the LEDs on the board
  BSP_LedsInit();

//  RETARGET_SerialInit();
//  RETARGET_SerialCrLf(1);

  // Initialize gpio for buttons
  buttonInit();

  // Initialize Radio
  radioInit();

  //enable buffer error callbacks
  RAIL_TxConfig(RAIL_TX_CONFIG_BUFFER_UNDERFLOW);
  RAIL_RxConfig((RAIL_RX_CONFIG_BUFFER_OVERFLOW
                 | RAIL_RX_CONFIG_INVALID_CRC
                 | RAIL_RX_CONFIG_SYNC1_DETECT),
                false);

  //enable fifo mode
  RAIL_DataConfig_t dataConfig = { TX_PACKET_DATA, RX_PACKET_DATA, FIFO_MODE, FIFO_MODE };
  RAIL_DataConfig(&dataConfig);

  //fill the buffer with dummy data
  for (int i = PACKET_HEADER_LEN; i < TX_FIFO_THRESHOLD - PACKET_HEADER_LEN; i++) {
    txPtr[i] = i - PACKET_HEADER_LEN;
  }

  memset(&Statistics, 0, sizeof(Statistics));
  GRAPHICS_Init();
  displayStatics();

//  printf("BOOTING....\n");

  while (1) {
    if (packetTx) {
      packetTx = false;
      //txLength = (rand() + 1) % (MAX_FRAME_LENGTH);
      //printf("TX(%d): ", txLength - PACKET_HEADER_LEN);
      //printBuffer(txPtr + PACKET_HEADER_LEN, txLength - PACKET_HEADER_LEN);
      //printf("\n");
      sendPacket(txLength);
    }
    if (packetRx) {
      packetRx = false;
      startReceive();
    }
  }
}

static void displayStatics(void)
{
  char buf[32];

  Statistics.txTime += (Statistics.txEndTime-Statistics.txStartTime)/1000000.0;
  Statistics.rxTime += (Statistics.rxEndTime-Statistics.rxStartTime)/1000000.0;

  Statistics.txPktRate = (uint16_t)(Statistics.txPktCnt/Statistics.txTime);
  Statistics.rxPktRate = (uint16_t)(Statistics.rxPktCnt/Statistics.rxTime);

  GRAPHICS_Clear();
  GRAPHICS_AppendString("  VarLen Test \n");
  GRAPHICS_AppendString(" ");
  snprintf(buf, 32, "Tx Pkt: %07lu", Statistics.txPktCnt);
  GRAPHICS_AppendString(buf);
  if (Statistics.txTime < 10.0)
    snprintf(buf, 32, "Tx Tmr: %01.4fs", Statistics.txTime);
  else if (Statistics.txTime < 100.0)
    snprintf(buf, 32, "Tx Tmr: %02.3fs", Statistics.txTime);
  else if (Statistics.txTime < 1000.0)
    snprintf(buf, 32, "Tx Tmr: %03.2f s", Statistics.txTime);
  GRAPHICS_AppendString(buf);
  snprintf(buf, 32, "Tx Rate:%05d/s", Statistics.txPktRate);
  GRAPHICS_AppendString(buf);
  GRAPHICS_AppendString("\n");

  snprintf(buf, 32, "Rx Pkt: %07lu", Statistics.rxPktCnt);
  GRAPHICS_AppendString(buf);
  if (Statistics.rxTime < 10.0)
    snprintf(buf, 32, "Rx Tmr: %01.4fs", Statistics.rxTime);
  else if (Statistics.rxTime < 100.0)
    snprintf(buf, 32, "Rx Tmr: %02.3fs", Statistics.rxTime);
  else if (Statistics.rxTime < 1000.0)
    snprintf(buf, 32, "Rx Tmr: %03.2fs", Statistics.rxTime);
  GRAPHICS_AppendString(buf);
  snprintf(buf, 32, "Rx Rate:%05d/s", Statistics.rxPktRate);
  GRAPHICS_AppendString(buf);

  GRAPHICS_AppendString("\n");
  snprintf(buf, 32, "Bit Rate: %04lu", RAIL_BitRateGet()/1000);
  GRAPHICS_AppendString(buf);

//  snprintf(buf, 32, "ErrNo: 0x%04x", (unsigned int)Statistics.errNo);
//  GRAPHICS_AppendString(buf);
//  snprintf(buf, 32, "trxErrNbr: %04lu", Statistics.trxErrNbr);
//  GRAPHICS_AppendString(buf);
  GRAPHICS_Update();
}

//uint16_t fifo;
/******************************************************************************
 * Configuration Utility Functions
 *****************************************************************************/
void sendPacket(uint16_t packetLength)
{
  RAIL_RfIdleExt(RAIL_IDLE_ABORT, true);
  RAIL_ResetFifo(true, false);
  txPtr[0] = (packetLength - PACKET_HEADER_LEN) >> 8;
  txPtr[1] = (packetLength - PACKET_HEADER_LEN) & 0xff;
//  txPtr[0] = (packetLength - PACKET_HEADER_LEN);

  RAIL_SetTxFifoThreshold(TX_FIFO_THRESHOLD);
  txWritten = RAIL_WriteTxFifo(txPtr, packetLength);
//  fifo = RAIL_GetTxFifoSpaceAvailable();
  RAIL_TxStart(channel, NULL, NULL);
}

void startReceive()
{
  RAIL_RfIdleExt(RAIL_IDLE, true);
  RAIL_ResetFifo(false, true);
  RAIL_SetRxFifoThreshold(RX_FIFO_THRESHOLD); //FIFO size is 512B
  RAIL_EnableRxFifoThreshold();
  rxReceived = 0;
  fifoReads = 0;
  rxExpected = 0;
  RAIL_RxStart(channel);
}

void changeRadioConfig(int newConfig)
{
  // Turn off the radio before reconfiguring it
  RAIL_RfIdleExt(RAIL_IDLE, true);

  // Reconfigure the radio parameters
  RAIL_PacketLengthConfigFrameType(frameTypeConfigList[newConfig]);
  if (RAIL_RadioConfig((void*)configList[newConfig])) {
    while (1) ;
  }

  // Set us to a valid channel for this config and force an update in the main
  // loop to restart whatever action was going on
  RAIL_ChannelConfig(channelConfigs[newConfig]);
  currentConfig = newConfig;
}

void buttonInit()
{
  // Enable the buttons on the board
  for (int i = 0; i < BSP_NO_OF_BUTTONS; i++) {
    GPIO_PinModeSet(buttonArray[i].port, buttonArray[i].pin, gpioModeInputPull, 1);
  }

  // Button Interrupt Config
  GPIOINT_Init();
  GPIOINT_CallbackRegister(buttonArray[0].pin, gpioCallback);
  GPIOINT_CallbackRegister(buttonArray[1].pin, gpioCallback);
  GPIO_IntConfig(buttonArray[0].port, buttonArray[0].pin, false, true, true);
  GPIO_IntConfig(buttonArray[1].port, buttonArray[1].pin, false, true, true);
}

void radioInit()
{
  RAIL_RfInit(&railInitParams);
  RAIL_RfIdleExt(RAIL_IDLE, true);
  RAIL_CalInit(&calInitParams);
  changeRadioConfig(currentConfig);
}

void gpioCallback(uint8_t pin)
{
  BSP_LedToggle(LED_TX);
  if (!packetTx && Statistics.txPktCnt % SEND_CNT == 0) {
    packetTx = true;
    txLength = PKT_LEN;
    Statistics.txStartTime = RAIL_GetTime();
  }
}

void printBuffer(uint8_t * buffer, const uint16_t bufferLength)
{
  for (uint16_t i = 0; i < bufferLength; ++i) {
    printf("0x%X, ", buffer[i]);
  }
}

/******************************************************************************
 * RAIL Callback Implementation
 *****************************************************************************/
void RAILCb_TxPacketSent(RAIL_TxPacketInfo_t *txPacketInfo)
{
  //packetRx = true;
  ++ Statistics.txPktCnt;
  if (Statistics.txPktCnt % SEND_CNT == 0) {   // 600 packet
    RAIL_RfIdleExt(RAIL_IDLE_ABORT, true);
    Statistics.txEndTime = txPacketInfo->timeUs;
    displayStatics();
    BSP_LedClear(LED_TX);
    packetTx = false;
  }
  else
    packetTx = true;
}

uint16_t rxAvai;
void storeReceivedPackets(uint16_t bytesAvailable)
{
  if (rxExpected == 0) {
    rxAvai = bytesAvailable;
    rxReceived = RAIL_ReadRxFifo(rxPtr, bytesAvailable);
    rxExpected = (rxPtr[0] << 8) + rxPtr[1] + PACKET_HEADER_LEN; //received length + length of header
    //rxExpected = rxPtr[0] + PACKET_HEADER_LEN;
  } else {
    rxReceived += RAIL_ReadRxFifo(rxPtr + rxReceived, rxExpected - rxReceived);
  }
}

void printReceivedPackets()
{
  printf("RX(%d): ", rxReceived - PACKET_HEADER_LEN);
  printBuffer(rxPtr + PACKET_HEADER_LEN, rxReceived - PACKET_HEADER_LEN);
  printf("\n");
}

void RAILCb_TxFifoAlmostEmpty(uint16_t spaceAvailable)
{
  if ( txLength - txWritten > 0) {
    txWritten += RAIL_WriteTxFifo(txPtr + txWritten, txLength - txWritten);
  }
}

void RAILCb_RxFifoAlmostFull(uint16_t bytesAvailable)
{
  storeReceivedPackets(bytesAvailable);
}

void RAILCb_RxPacketReceived(void *rxPacketHandle)
{
  BSP_LedToggle(LED_RX);

  storeReceivedPackets(RAIL_GetRxFifoBytesAvailable());
//  printReceivedPackets();

  // when receive data contain RAIL_RxPacketInfo_t structure, actual received data great than expected.
  if (rxReceived >= rxExpected) {
    Statistics.errNo &= ~RAIL_RX_CONFIG_SYNC1_DETECT;
    ++ Statistics.rxPktCnt;
    if (Statistics.rxPktCnt % SEND_CNT == 1)
      Statistics.rxStartTime = RAIL_GetTime();  //(((RAIL_RxPacketInfo_t *)(rxPacketHandle))->appendedInfo).timeUs;

    if (Statistics.rxPktCnt % SEND_CNT == 0) {
      Statistics.rxEndTime = RAIL_GetTime();
      displayStatics();
    }
  }

  packetRx = true;
}

void RAILCb_RxRadioStatus(uint8_t status)
{
  if (status & RAIL_RX_CONFIG_INVALID_CRC) {
    Statistics.errNo |= RAIL_RX_CONFIG_INVALID_CRC;
  }
  if (status & RAIL_RX_CONFIG_SYNC1_DETECT) {
    Statistics.errNo |= RAIL_RX_CONFIG_SYNC1_DETECT;
  }
  if (status & RAIL_RX_CONFIG_PREAMBLE_DETECT) {
  }
  if (status & RAIL_RX_CONFIG_BUFFER_OVERFLOW) {
    //printf("overflow\n");
    Statistics.errNo |= RAIL_RX_CONFIG_BUFFER_OVERFLOW;
  } else if (status & RAIL_RX_CONFIG_ADDRESS_FILTERED) {
  }
}

void RAILCb_TxRadioStatus(uint8_t status)
{
}

void RAILCb_TimerExpired()
{
}

 

Highlighted
发帖数: 101
注册日期: ‎12-02-2016

回复: EFR32FG12实现变长包通信中遇到的问题

Hi,

The threshold for tx is the current rest of data which are being transmitted out in the transmit fifo.
If the tx threshold is 40 and the packet length is more than 40, then when start to transmit and the current rest of data in transmit fifo is equal to 40, it will fire fire RAILCb_TxFifoAlmostEmpty() and fill in the next piece of packet if there's still the rest part.

So, for your case, it's very normal and correct.

Regards,
Yongsheng