欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > LoRaWAN网关源码分析(集中器篇)

LoRaWAN网关源码分析(集中器篇)

2025/9/20 0:08:34 来源:https://blog.csdn.net/m0_65292176/article/details/139922297  浏览:    关键词:LoRaWAN网关源码分析(集中器篇)

目录

一、前言

二、主函数逻辑

三、lgw_start函数

四、lgw_connect函数

五、lgw_soft_reset函数


一、前言

        对于lora_pkt_fwd.c主函数实现功能的流程不熟悉的话,可以看上一篇文章。本篇文章就集中器开始进行整理。

二、主函数逻辑

    i = lgw_start();if (i == LGW_HAL_SUCCESS) {MSG("INFO: [main] concentrator started, packet can now be received\n");}else {MSG("ERROR: [main] failed to start the concentrator\n");exit(EXIT_FAILURE);}    

        首先,调用 lgw_start() 函数启动集中器,并将返回值赋给变量 i。然后检查 lgw_start() 的返回值,以确定集中器是否成功启动:

成功---调用 MSG 宏输出信息:“INFO: [main] concentrator started, packet can now be received”,通知用户集中器已经成功启动,并且可以接收数据包。

失败---调用 MSG 宏输出错误信息:“ERROR: [main] failed to start the concentrator”,通知用户启动集中器失败。然后调用 exit(EXIT_FAILURE) 退出程序,表示程序因错误退出。

三、lgw_start函数

        该函数用于初始化和启动一个 LoRa 集中器设备。接下来我们来看看该函数是如何实现功能的吧!

1、检查设备是否已经启动

if (lgw_is_started == true) 
{DEBUG_MSG("Note: LoRa concentrator already started, restarting it now\n");
}

2、连接到设备(lgw_connect函数下面已经整理了)

reg_stat = lgw_connect(false, rf_tx_notch_freq[rf_tx_enable[1]?1:0]);
if (reg_stat == LGW_REG_ERROR) 
{DEBUG_MSG("ERROR: FAIL TO CONNECT BOARD\n");return LGW_HAL_ERROR;
}

3、重置寄存器(lgw_soft_reset函数下面已经整理了)

lgw_soft_reset();
lgw_reg_w(LGW_GLOBAL_EN, 0);
lgw_reg_w(LGW_CLK32M_EN, 0);

4、启动和重置射频电台

lgw_reg_w(LGW_RADIO_A_EN,1);
lgw_reg_w(LGW_RADIO_B_EN,1);
wait_ms(500);
lgw_reg_w(LGW_RADIO_RST,1);
wait_ms(5);
lgw_reg_w(LGW_RADIO_RST,0);

5、配置射频电台

err = lgw_setup_sx125x(0, rf_clkout, rf_enable[0], rf_radio_type[0], rf_rx_freq[0]);
if (err != 0) 
{DEBUG_MSG("ERROR: Failed to setup sx125x radio for RF chain 0\n");return LGW_HAL_ERROR;
}
err = lgw_setup_sx125x(1, rf_clkout, rf_enable[1], rf_radio_type[1], rf_rx_freq[1]);
if (err != 0) 
{DEBUG_MSG("ERROR: Failed to setup sx125x radio for RF chain 0\n");return LGW_HAL_ERROR;
}

6、配置外部数字滤波器

lgw_reg_w(LGW_GPIO_MODE,31);
lgw_reg_w(LGW_GPIO_SELECT_OUTPUT,2);

7、配置LBT(Listen Before Talk)功能

if (lbt_is_enabled() == true) 
{lgw_reg_w(LGW_CLK32M_EN, 1);i = lbt_setup();if (i != LGW_LBT_SUCCESS) {DEBUG_MSG("ERROR: lbt_setup() did not return SUCCESS\n");return LGW_HAL_ERROR;}lgw_reg_w(LGW_CLK32M_EN, 0);i = lbt_start();if (i != LGW_LBT_SUCCESS) {DEBUG_MSG("ERROR: lbt_start() did not return SUCCESS\n");return LGW_HAL_ERROR;}
}

8、启用时钟

lgw_reg_w(LGW_GLOBAL_EN, 1);
lgw_reg_w(LGW_CLK32M_EN, 1);

9、选择和发送校准命令

cal_cmd = 0;
cal_cmd |= rf_enable[0] ? 0x01 : 0x00;
cal_cmd |= rf_enable[1] ? 0x02 : 0x00;
cal_cmd |= (rf_enable[0] && rf_tx_enable[0]) ? 0x04 : 0x00;
cal_cmd |= (rf_enable[1] && rf_tx_enable[1]) ? 0x08 : 0x00;
cal_cmd |= 0x10;switch (rf_radio_type[0]) {case LGW_RADIO_TYPE_SX1255:cal_cmd |= 0x20;break;case LGW_RADIO_TYPE_SX1257:cal_cmd |= 0x00;break;default:DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]);break;
}cal_time = 2300;

10、加载校准固件并启动MCU

load_firmware(MCU_AGC, cal_firmware, MCU_AGC_FW_BYTE);
lgw_reg_w(LGW_FORCE_HOST_RADIO_CTRL, 0);
lgw_reg_w(LGW_RADIO_SELECT, cal_cmd);
lgw_reg_w(LGW_MCU_RST_1, 0);

11、检查固件版本

lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR, FW_VERSION_ADDR);
lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val);
fw_version = (uint8_t)read_val;
if (fw_version != FW_VERSION_CAL) 
{printf("ERROR: Version of calibration firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_CAL);return -1;
}

12、启动校准并检查校准状态

lgw_reg_w(LGW_PAGE_REG, 3);
lgw_reg_w(LGW_EMERGENCY_FORCE_HOST_CTRL, 0);
DEBUG_PRINTF("Note: calibration started (time: %u ms)\n", cal_time);
wait_ms(cal_time);
lgw_reg_w(LGW_EMERGENCY_FORCE_HOST_CTRL, 1);lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val);
cal_status = (uint8_t)read_val;
if ((cal_status & 0x81) != 0x81) 
{DEBUG_PRINTF("ERROR: CALIBRATION FAILURE (STATUS = %u)\n", cal_status);return LGW_HAL_ERROR;
}

13、获取和检查校准偏移值

for(i=0; i<=7; ++i) 
{lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR, 0xA0+i);lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val);cal_offset_a_i[i] = (int8_t)read_val;lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR, 0xA8+i);lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val);cal_offset_a_q[i] = (int8_t)read_val;lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR, 0xB0+i);lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val);cal_offset_b_i[i] = (int8_t)read_val;lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR, 0xB8+i);lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val);cal_offset_b_q[i] = (int8_t)read_val;
}

14、调整常数并配置频率漂移

lgw_constant_adjust();
x = 4096000000 / (rf_rx_freq[0] >> 1);
x = ( x > 63 ) ? 63 : x;
lgw_reg_w(LGW_FREQ_TO_TIME_DRIFT, x);x = 4096000000 / (rf_rx_freq[0] >> 3);
x = ( x > 63 ) ? 63 : x;
lgw_reg_w(LGW_MBWSSF_FREQ_TO_TIME_DRIFT, x);

15、配置LoRa多通道解调器

radio_select = 0;
for(i=0; i<LGW_MULTI_NB; ++i) 
{radio_select += (if_rf_chain[i] == 1 ? 1 << i : 0);
}

16、配置LoRa单独解调器

lgw_reg_w(LGW_IF_FREQ_8, IF_HZ_TO_REG(if_freq[8]));
if (if_enable[8] == true) {lgw_reg_w(LGW_MBWSSF_RADIO_SELECT, if_rf_chain[8]);switch(lora_rx_bw) {case BW_125KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW, 0); break;case BW_250KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW, 1); break;case BW_500KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW, 2); break;default:DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw);return LGW_HAL_ERROR;}switch(lora_rx_sf) {case DR_LORA_SF7: lgw_reg_w(LGW_MBWSSF_RATE_SF, 7); break;case DR_LORA_SF8: lgw_reg_w(LGW_MBWSSF_RATE_SF, 8); break;case DR_LORA_SF9: lgw_reg_w(LGW_MBWSSF_RATE_SF, 9); break;

四、lgw_connect函数

        这段代码主要用于连接 LoRa 集中器,并且在连接成功后进行一些初始化操作。以下是代码的详细解释:

代码主干部分

int lgw_connect(bool spi_only, uint32_t tx_notch_freq) 
{int spi_stat = LGW_SPI_SUCCESS;uint8_t u = 0;int x;/* check SPI link status */if (lgw_spi_target != NULL) {DEBUG_MSG("WARNING: concentrator was already connected\n");lgw_spi_close(lgw_spi_target);}/* open the SPI link */spi_stat = lgw_spi_open(&lgw_spi_target);if (spi_stat != LGW_SPI_SUCCESS) {DEBUG_MSG("ERROR CONNECTING CONCENTRATOR\n");return LGW_REG_ERROR;}
  • lgw_connect 函数接受两个参数:spi_only 表示是否仅使用 SPI,tx_notch_freq 是传输时的不可用频率。
  • 首先,代码检查当前的 SPI 链接状态,如果已经连接了集中器,则关闭当前连接。
  • 然后,尝试打开 SPI 链接,如果打开失败,则输出错误信息并返回错误代码 LGW_REG_ERROR
    if (spi_only == false ) {/* Detect if the gateway has an FPGA with SPI mux header support *//* First, we assume there is an FPGA, and try to read its version */spi_stat = lgw_spi_r(lgw_spi_target, LGW_SPI_MUX_MODE1, LGW_SPI_MUX_TARGET_FPGA, loregs[LGW_VERSION].addr, &u);if (spi_stat != LGW_SPI_SUCCESS) {DEBUG_MSG("ERROR READING VERSION REGISTER\n");return LGW_REG_ERROR;}if (check_fpga_version(u) != true) {/* We failed to read expected FPGA version, so let's assume there is no FPGA */DEBUG_PRINTF("INFO: no FPGA detected or version not supported (v%u)\n", u);lgw_spi_mux_mode = LGW_SPI_MUX_MODE0;} else {DEBUG_PRINTF("INFO: detected FPGA with SPI mux header (v%u)\n", u);lgw_spi_mux_mode = LGW_SPI_MUX_MODE1;/* FPGA Soft Reset */lgw_spi_w(lgw_spi_target, lgw_spi_mux_mode, LGW_SPI_MUX_TARGET_FPGA, 0, 1);lgw_spi_w(lgw_spi_target, lgw_spi_mux_mode, LGW_SPI_MUX_TARGET_FPGA, 0, 0);/* FPGA configure */x = lgw_fpga_configure(tx_notch_freq);if (x != LGW_REG_SUCCESS) {DEBUG_MSG("ERROR CONFIGURING FPGA\n");return LGW_REG_ERROR;}}/* check SX1301 version */spi_stat = lgw_spi_r(lgw_spi_target, lgw_spi_mux_mode, LGW_SPI_MUX_TARGET_SX1301, loregs[LGW_VERSION].addr, &u);if (spi_stat != LGW_SPI_SUCCESS) {DEBUG_MSG("ERROR READING CHIP VERSION REGISTER\n");return LGW_REG_ERROR;}if (u != loregs[LGW_VERSION].dflt) {DEBUG_PRINTF("ERROR: NOT EXPECTED CHIP VERSION (v%u)\n", u);return LGW_REG_ERROR;}/* write 0 to the page/reset register */spi_stat = lgw_spi_w(lgw_spi_target, lgw_spi_mux_mode, LGW_SPI_MUX_TARGET_SX1301, loregs[LGW_PAGE_REG].addr, 0);if (spi_stat != LGW_SPI_SUCCESS) {DEBUG_MSG("ERROR WRITING PAGE REGISTER\n");return LGW_REG_ERROR;} else {lgw_regpage = 0;}}

 如果 spi_only 参数为 false,则执行以下操作:

  • 检测网关是否具有带有 SPI 复用器头的 FPGA 支持。
  • 尝试读取 FPGA 版本,如果成功读取到版本号则进行 FPGA 的软复位和配置。
  • 检查 SX1301 芯片的版本号,并且确保版本号与期望的版本号相符。
  • 将值 0 写入页/复位寄存器,以重置寄存器页为默认页。
    DEBUG_MSG("Note: success connecting the concentrator\n");return LGW_REG_SUCCESS;
}

        最后,在成功连接集中器后输出成功信息,并返回 LGW_REG_SUCCESS 表示连接成功。

五、lgw_soft_reset函数

        这个函数实现了软重置功能,用于重置集中器模块。

1、检查SPI连接

if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) 
{DEBUG_MSG("ERROR: CONCENTRATOR UNCONNECTED\n");return LGW_REG_ERROR;
}

        这里首先检查了是否已经初始化了 SPI 连接,并且检查了是否已经设置了正确的寄存器页(lgw_regpage)。如果 SPI 连接未初始化或者寄存器页设置不正确,就会打印错误消息并返回 LGW_REG_ERROR

2、发送软重置命令

lgw_spi_w(lgw_spi_target, lgw_spi_mux_mode, LGW_SPI_MUX_TARGET_SX1301, 0, 0x80); /* 1 -> SOFT_RESET bit */

这行代码向 SX1301 芯片的指定目标(LGW_SPI_MUX_TARGET_SX1301)发送一个特定的命令字节,其中第 7 位被设置为 1,表示软重置(SOFT_RESET)。这个命令将触发 SX1301 芯片执行软重置操作。

3、重置寄存器页

lgw_regpage = 0; /* reset the paging static variable */

4、返回执行结果

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词