uploaded 2 weeks ago
ESP-IDF component library for Semtech LoRa radios, currently targeting LR20xx/LR2021, with ESP platform integration and public RAC, RALF, and RAL layers; planned to expand with SX126x and LR11xx support.

readme

# ESP LoRa Driver

仓库地址:<https://github.com/lierda-iot/esp32_lora_driver.git>

`ESP LoRa Driver` 是一个面向 Semtech LoRa 无线芯片的 ESP-IDF 组件库,当前以 `LR20xx/LR2021` 为主要目标,集成了 ESP 平台适配,并对外公开 `RAC`、`RALF` 和 `RAL` 分层接口,后续将继续支持 `SX126x`、`LR11xx` 等芯片型号。

该组件基于 Semtech 上游 `smtc_rac_lib` 修改、裁剪并移植到 ESP-IDF 环境,保留了上游的分层抽象方式,并增加了适用于 ESP 平台的 HAL、GPIO、SPI、定时器和日志适配。

## 组件目标

这个组件不是单一的“裸驱动文件”,而是一套分层的无线接入组件库,目标包括:

- 为 `LR20xx/LR2021` 提供可在 ESP-IDF 下直接集成的射频驱动能力
- 保留 Semtech 上游 `RAC / RALF / RAL` 的分层抽象,便于后续维护和同步
- 同时支持“高层调度接入”和“低层驱动直连”两种使用方式
- 为后续扩展到其他 Semtech 无线芯片预留统一结构

## 分层结构

从组件库视角看,当前代码主要分为以下几层:

- `RAC API`:面向应用层的高层无线访问接口,适合需要统一调度、任务提交和事务管理的场景
- `RAC`:无线访问控制层,负责组织任务、调度、收发流程和无线事务上下文
- `Radio Planner`:调度与仲裁层,负责不同无线任务的排队、优先级和时序控制
- `RALF`:面向具体无线能力的功能层封装,构建在 `RAL` 之上
- `RAL`:射频抽象层,向上提供统一操作接口,向下对接具体芯片驱动
- `Radio Driver`:芯片寄存器与命令级驱动实现
- `Radio HAL / Modem HAL`:平台相关层,负责 SPI、GPIO、中断、时间和日志等底层能力

这意味着本组件既可以作为“完整的射频访问组件”使用,也可以只使用其中的某一层。

## 适用场景

这个组件适合以下几类场景:

- 在 ESP-IDF 工程中快速接入 `LR2021` 射频芯片
- 需要基于统一接口调度 LoRa、FSK、FLRC 或 LR-FHSS 等射频任务
- 需要在应用层直接调用 `RAC` 接口管理无线事务
- 需要在较低层直接访问 `RAL` 或 `RALF` 以实现更细粒度的射频控制

## 支持的利尔达产品

当前组件面向以下利尔达产品形态:

- `L-LRMAM36-FANN4`
- `L-LRMWP35-FANN4`,即基于 `ESP-IDF` 搭配 `LR2021 SPI` 模组的开发方案

## 对外接口

当前组件采用单入口对外方式,外部用户只需要包含一个头文件:

- [include/LiotLr2021.h](include/LiotLr2021.h)

也就是说,推荐的接入方式是:

```c
#include "LiotLr2021.h"
```

`LiotLr2021.h` 本身会聚合以下几层公共接口:

- `RAC API`
  - 来自 [smtc_rac_api.h](rac_api/smtc_rac_api.h)
  - 适合应用层直接发起无线事务、管理调度上下文和使用统一 API
- `RAC`
  - 来自 [smtc_rac.h](rac/smtc_rac.h)
  - 适合需要直接操作无线访问控制层的场景
- `RALF`
  - 来自 [ralf.h](ralf/ralf.h)
  - 适合需要使用射频功能层接口的场景
- `RAL`
  - 来自 [ral.h](ral/ral.h)
  - 适合需要最底层射频抽象接口的场景

因此,虽然用户只需要包含一个入口头文件,但仍然可以根据自己对组件分层的理解,直接调用不同层的接口类型和函数。

这种设计的目的有两个:

- 对外使用方式保持简单,只保留一个正式入口
- 内部仍保留上游风格的分层结构,便于维护、裁剪和继续同步

## 目录说明

当前目录结构大致如下:

- `include/`
  - 组件对外公开的单入口头
- `rac_api/`
  - 应用层使用的高层 API
- `rac/`
  - 无线访问控制核心逻辑
- `radio_planner/`
  - 无线任务调度器
- `ral/`
  - 射频抽象层
- `ralf/`
  - 射频功能层
- `radio_drivers/`
  - 各芯片驱动实现
- `radio_hal/`
  - 芯片相关平台适配层
- `modem_hal/`
  - ESP-IDF 平台底层 HAL 和调试支持
- `Kconfig`
  - 组件配置项
- `idf_component.yml`
  - 组件元数据

## 配置方式

组件通过 [Kconfig](Kconfig) 暴露配置项,主要包括:

- 射频芯片家族选择
  - `SX126x`
  - `LR11xx`
  - `LR20xx`
- `LR2021` 的 SPI Host 选择
- `L-LRMWP35-FANN4` 或 `Generic / Custom LR2021 SPI board` 下的 `NRST`、`BUSY`、`NSS`、`MOSI`、`MISO`、`SCLK` 等 GPIO 分配
- `L-LRMWP35-FANN4` 或 `Generic / Custom LR2021 SPI board` 下的 `LR20xx` 相关 `DIO` 配置

当前默认目标为 `LR20xx`,适合作为 `LR2021` 的默认配置基础。

## 日志输出说明

当前组件内的日志主要分为三类:

- `RAC Core` 日志
  - 位于 [smtc_rac.c](rac/smtc_rac.c)
  - 主要用于 `RAC` 初始化、上下文设置、调度流程和接口调用跟踪
- `RAC 业务日志`
  - 主要位于 `LoRa`、`FLRC`、`LR-FHSS` 等 `RAC` 业务文件
  - 使用统一的 [smtc_rac_log.h](rac_api/smtc_rac_log.h) 宏输出
- `ESP_LOG` 日志
  - 主要位于 `LR20xx RAL / RALF` 和 `modem_hal`
  - 使用 `ESP_LOGI`、`ESP_LOGD`、`ESP_LOGE` 输出

### 1. RAC Core 日志

`RAC Core` 使用以下宏:

- `RAC_CORE_LOG_ERROR`
- `RAC_CORE_LOG_CONFIG`
- `RAC_CORE_LOG_INFO`
- `RAC_CORE_LOG_WARN`
- `RAC_CORE_LOG_DEBUG`
- `RAC_CORE_LOG_API`
- `RAC_CORE_LOG_RADIO`

当前默认行为见 [smtc_rac.c](rac/smtc_rac.c#L82):

- 默认开启:`ERROR`、`CONFIG`
- 默认关闭:`INFO`、`WARN`、`DEBUG`、`API`、`RADIO`

如果只是临时调试,最直接的方式是修改 [smtc_rac.c](rac/smtc_rac.c#L82) 中这些默认宏值,例如:

```c
#define RAC_CORE_LOG_INFO_ENABLE 1
#define RAC_CORE_LOG_WARN_ENABLE 1
#define RAC_CORE_LOG_DEBUG_ENABLE 1
#define RAC_CORE_LOG_API_ENABLE 1
#define RAC_CORE_LOG_RADIO_ENABLE 1
```

这种方式适合本地快速打开或关闭 `RAC Core` 日志。

如果希望在不改源码的情况下控制日志,也可以通过编译宏覆盖,例如:

```cmake
target_compile_definitions(${COMPONENT_LIB} PRIVATE
    RAC_CORE_LOG_INFO_ENABLE=1
    RAC_CORE_LOG_WARN_ENABLE=1
    RAC_CORE_LOG_DEBUG_ENABLE=1
    RAC_CORE_LOG_API_ENABLE=1
    RAC_CORE_LOG_RADIO_ENABLE=1
)
```

如果想关闭某一类日志,可将对应宏设为 `0`。编译宏会覆盖源码里的默认值。

### 2. RAC 业务日志

`LoRa`、`FLRC`、`LR-FHSS` 路径使用 [smtc_rac_log.h](rac_api/smtc_rac_log.h) 中的统一日志宏:

- `RAC_LOG_ERROR`
- `RAC_LOG_WARN`
- `RAC_LOG_INFO`
- `RAC_LOG_DEBUG`
- `RAC_LOG_CONFIG`
- `RAC_LOG_TX`
- `RAC_LOG_RX`
- `RAC_LOG_STATS`
- `RAC_LOG_HEX_DUMP`
- `RAC_LOG_BANNER`
- `RAC_LOG_SIMPLE_BANNER`

日志输出格式大致如下:

```text
[RAC-LORA-INFO ] [    1234 ms] setup ok
```

其中:

- 前缀如 `RAC-LORA`、`RAC-FLRC`、`RAC-LRFHSS` 用于区分业务模块
- 时间戳来自 `smtc_modem_hal_get_time_in_ms()`
- 最终输出通过 `SMTC_MODEM_HAL_TRACE_PRINTF(...)` 进入 `smtc_modem_hal_print_trace(...)`

当前组件在 [CMakeLists.txt](CMakeLists.txt#L222) 中预留了以下日志 profile:

- `OFF`
  - 关闭 `FSK`、`LoRa`、`LR-FHSS` 业务日志
- `MINIMAL`
  - 仅开启 `LoRa` 业务日志
- `VERBOSE`
  - 开启 `FSK`、`LoRa`、`LR-FHSS` 业务日志
- `ALL`
  - 当前实现与 `VERBOSE` 等效

这些 profile 现在已经通过 `Kconfig` 暴露,可直接在 `menuconfig` 中选择:

```text
Liot LR2021 (IDF)
  -> Logging
    -> RAC business log profile
```

如果你希望手动控制这几类日志,可通过编译宏覆盖,例如:

```cmake
target_compile_definitions(${COMPONENT_LIB} PRIVATE
    RAC_FSK_LOG_ENABLE=1
    RAC_LORA_LOG_ENABLE=1
    RAC_LRFHSS_LOG_ENABLE=1
)
```

### 3. Trace 后端开关

`RAC` 日志最终依赖 [smtc_modem_hal_dbg_trace.h](modem_hal/smtc_modem_hal_dbg_trace.h) 中的 trace 宏。

当前默认值为:

- `MODEM_HAL_DBG_TRACE=ON`
- `MODEM_HAL_DBG_TRACE_COLOR=ON`
- `MODEM_HAL_DBG_TRACE_RP=OFF`
- `MODEM_HAL_DEEP_DBG_TRACE=OFF`

如需关闭 `RAC` 类 trace 输出,可在编译时设置:

```cmake
target_compile_definitions(${COMPONENT_LIB} PRIVATE
    MODEM_HAL_DBG_TRACE=0
)
```

如需关闭颜色输出,可设置:

```cmake
target_compile_definitions(${COMPONENT_LIB} PRIVATE
    MODEM_HAL_DBG_TRACE_COLOR=0
)
```

### 4. ESP_LOG 日志

组件中还有一部分日志直接使用 `ESP-IDF` 的 `ESP_LOGx`:

- [ralf_lr20xx.c](ralf/lr20xx_ralf/ralf_lr20xx.c)
  - 主要输出 `LR20xx` 的 `setup GFSK / LoRa / FLRC / CAD` 信息
- [ral_lr20xx.c](ral/lr20xx_ral/ral_lr20xx.c)
  - 主要输出部分 `PA` 和发射配置调试信息
- [smtc_modem_hal.c](modem_hal/smtc_modem_hal.c)
  - 主要输出 `panic` 和部分 `HAL` 运行信息

这部分日志不受 `RAC_LOG_*` 宏控制,而是受 `ESP-IDF` 自身日志等级控制。

常见控制方式包括:

1. 在 `menuconfig` 中调整默认日志等级
2. 在运行时调用 `esp_log_level_set("*", ESP_LOG_INFO);`
3. 针对特定 tag 调用 `esp_log_level_set("SMTC_MODEM", ESP_LOG_DEBUG);`

### 5. 应用层如何使用

如果你的应用希望直接复用组件自带的 `RAC` 风格日志,可显式包含:

- [smtc_rac_log.h](rac_api/smtc_rac_log.h)

示例:

```c
#include "smtc_rac_log.h"

void app_main(void)
{
    RAC_LOG_SIMPLE_BANNER("LR2021 demo");
    RAC_LOG_INFO("radio init start");
    RAC_LOG_CONFIG("freq=%u", 470300000U);
    RAC_LOG_TX("tx len=%u", 16U);
}
```

如果你的应用只想使用 `ESP-IDF` 原生日志,则直接使用 `ESP_LOGI`、`ESP_LOGW`、`ESP_LOGE` 即可,不必依赖 `RAC_LOG_*` 宏。

## 默认硬件配置

当前 `Kconfig` 中提供的默认 `SPI` 与 `GPIO` 参数,已经按照 `L-LRMAM36-FANN4` 模组的典型连接方式进行预设。

因此,在使用 `L-LRMAM36-FANN4` 进行开发时,通常可以直接使用组件默认配置作为起点,无需在初始阶段手动调整 `SPI Host`、`NRST`、`BUSY`、`NSS`、`MOSI`、`MISO`、`SCLK` 以及 `DIO7` 等参数。

对于 `LR20XX / LR2021` 路径,组件当前支持在 `menuconfig` 中选择利尔达板型:

- `L-LRMAM36-FANN4`
- `L-LRMWP35-FANN4`

其中:

- 选择 `L-LRMAM36-FANN4` 时,引脚参数默认按该模组预设,不需要额外配置
- 选择 `L-LRMWP35-FANN4` 时,可在 `menuconfig` 中继续配置 `SPI` 与 `GPIO` 参数

当前第一版实现中,`L-LRMAM36-FANN4` 与 `L-LRMWP35-FANN4` 已分别对应独立的 `LR20XX BSP` 源文件,便于后续继续按板型细化晶振、功耗表、PA 和射频前端相关参数。

当前板型与 BSP 对应关系如下:

- `L-LRMAM36-FANN4` -> [ral_lr20xx_bsp_lrmam36_fann4.c](ral/lr20xx_ral/ral_lr20xx_bsp_lrmam36_fann4.c)
- `L-LRMWP35-FANN4` -> [ral_lr20xx_bsp_lrmwp35_fann4.c](ral/lr20xx_ral/ral_lr20xx_bsp_lrmwp35_fann4.c)
- `Generic / Custom LR2021 SPI board` -> [ral_lr20xx_bsp.c](ral/lr20xx_ral/ral_lr20xx_bsp.c)

## 自定义硬件适配说明

如果使用的是 `L-LRMAM36-FANN4`,可以直接沿用组件默认配置。  
如果使用的是其他硬件方案,则需要按实际情况调整相关配置。

### 1. 晶振配置

当前 `LR20XX` 路径下的晶振相关配置由板型 BSP 决定:

- `L-LRMAM36-FANN4`:见 [ral_lr20xx_bsp_lrmam36_fann4.c](ral/lr20xx_ral/ral_lr20xx_bsp_lrmam36_fann4.c#L484)
- `L-LRMWP35-FANN4`:见 [ral_lr20xx_bsp_lrmwp35_fann4.c](ral/lr20xx_ral/ral_lr20xx_bsp_lrmwp35_fann4.c#L484)
- `Generic / Custom LR2021 SPI board`:见 [ral_lr20xx_bsp.c](ral/lr20xx_ral/ral_lr20xx_bsp.c#L484)

对于自定义 `ESP-IDF + LR2021 SPI` 硬件,建议按实际射频模组和参考设计确认以下内容:

- 板上使用的是 `XTAL` 还是 `TCXO`
- 如果使用 `TCXO`,需要相应调整 `ral_lr20xx_bsp_get_xosc_cfg(...)` 中的 `xosc_cfg`、供电电压和启动时间
- 如果使用 `XTAL`,需要根据实际晶振及板级寄生参数,评估是否要调整默认的 `XOSC trim` 参数

如果这部分配置与硬件不匹配,可能导致射频初始化异常、时钟稳定性问题或收发行为异常。

### 2. 引脚配置

对于 `L-LRMWP35-FANN4` 和自定义 `ESP-IDF + LR2021 SPI` 硬件,通常还需要在 `menuconfig` 中根据实际连线修改以下参数:

- `LR2021_RADIO_SPI_ID`
- `LR2021_NRST_GPIO`
- `LR2021_BUSY_GPIO`
- `LR2021_NSS_GPIO`
- `LR2021_SPI_MOSI`
- `LR2021_SPI_MISO`
- `LR2021_SPI_CLK`
- `LR20XX_DIO7_GPIO`

这些配置项定义见 [Kconfig](Kconfig)。

如果你的硬件不是按 `L-LRMAM36-FANN4` 的默认连接方式设计,那么这里的参数应视为必须检查项,而不是可选项。

## 与 ESP-IDF 的集成方式

该组件按 ESP-IDF 组件方式组织,当前已经包含:

- [CMakeLists.txt](CMakeLists.txt)
- [idf_component.yml](idf_component.yml)
- [LICENSE](LICENSE)
- [NOTICE](NOTICE)

在工程中集成后,用户通常只需要:

1. 在 `menuconfig` 中选择目标射频芯片和 GPIO/SPI 参数
2. 在应用层包含所需头文件
3. 根据所选层级调用 `RAC`、`RALF` 或 `RAL` 接口

## 示例工程

如需参考该组件的使用方式、工程集成方法和基础调用示例,请使用以下例程仓库:

- [esp32_lora_samples](https://github.com/lierda-iot/esp32_lora_samples.git)

## 文档链接

如需查看该组件的补充说明文档,请参考以下链接:

- [钉钉文档](https://alidocs.dingtalk.com/i/nodes/dxXB52LJqnGE6GN4cQRNK0PX8qjMp697?utm_scene=team_space)
- [钉钉文档](https://alidocs.dingtalk.com/i/nodes/gpG2NdyVX32N52zwuAREozYpWMwvDqPk?utm_scene=team_space)

## 快速开始

下面给出一个推荐的最小接入流程。

### 1. 将组件加入工程

将当前组件作为本地组件加入 ESP-IDF 工程,并确保工程可以在构建系统中找到它。

### 2. 配置目标芯片和硬件参数

运行:

```bash
idf.py menuconfig
```

然后在 `Liot LR2021 (IDF)` 菜单中完成以下配置:

- 选择目标射频芯片家族
- 如果使用 `L-LRMAM36-FANN4`,可以直接使用默认参数
- 如果使用 `L-LRMWP35-FANN4`,先选择对应板型,再按需要调整 `SPI` 与 `GPIO` 参数
- 如果使用其他自定义 `ESP-IDF + LR2021 SPI` 硬件,按实际连接修改 `SPI` 与 `GPIO` 参数,并检查晶振配置是否与硬件一致

### 3. 在应用代码中包含组件入口头

```c
#include "LiotLr2021.h"
```

### 4. 按所需层级调用接口

你可以在单入口头基础上直接使用以下层级的接口:

- `RAC API`:适合应用层直接发起无线事务
- `RAC`:适合直接控制无线访问管理逻辑
- `RALF`:适合更细粒度的射频功能配置
- `RAL`:适合底层射频抽象控制

### 5. 编译工程

```bash
idf.py build
```

如果当前目标是 `LR20XX / LR2021` 路径,组件已经完成过最小工程构建验证,可作为当前主要集成路径使用。

## 推荐使用方式

从组件维护角度,推荐按以下优先级使用:

- 应用层优先使用 `RAC API` 或 `RAC`
- 需要更细粒度射频控制时使用 `RALF`
- 仅在需要最底层芯片操作抽象时使用 `RAL`

这样做的好处是:

- 上层代码与具体芯片解耦更好
- 后续适配其他 Semtech 芯片时复用性更高
- 组件内部实现调整时,对应用层影响更小

## 版本信息

当前 `RAC API` 版本定义见 [smtc_rac_version.h](rac_api/smtc_rac_version.h#L1):

- Major: `1`
- Minor: `0`
- Patch: `0`

## 许可证说明

本组件基于 Semtech 上游代码修改和移植,主许可证采用 `The Clear BSD License`,对应 SPDX 标识符为 `BSD-3-Clause-Clear`。

相关文件:

- [LICENSE](LICENSE)
- [NOTICE](NOTICE)

如果分发源码或二进制,请保留上游版权声明、许可证文本和免责声明。

## 发布说明

如果后续要将该组件发布到 ESP Component Registry,建议在发布前再确认以下事项:

- 更新 [idf_component.yml](idf_component.yml) 中的 `url`
- 补充使用例程链接
- 进行至少一次目标芯片配置下的编译验证
- 检查所有公开头文件是否确实属于稳定外部接口

当前验证状态:

- `L-LRMAM36-FANN4` 已完成最小 ESP-IDF 工程构建验证
- `L-LRMWP35-FANN4` 当前处于功能验证阶段,性能参数尚未完成调优
- `SX126X` / `LR11XX` 分支当前仍视为“未完成验证”

说明:

- 本轮审查中,最小工程已实际完成 `L-LRMAM36-FANN4` 对应路径编译
- `L-LRMWP35-FANN4` 已拆分为独立 BSP,并完成基础功能路径接入,但板级性能参数仍需后续细化
- 对 `SX126X` / `LR11XX` 的条件分支尚未完成独立有效的分支构建确认,因此发布时不应默认宣称这两个分支已验证可用

## 维护说明

这个组件当前保留了较强的上游结构痕迹,这是有意为之。这样做的主要目的是:

- 方便和 Semtech 上游代码进行差异比对
- 降低后续继续同步或回溯问题时的维护成本
- 在不破坏组件对外接口的前提下,逐步整理内部结构

因此,对外接口统一通过 `include/` 暴露,而内部实现目录保持原有分层布局。

Links

Supports all targets

To add this component to your project, run:

idf.py add-dependency "lierda-iot/esp_lora_driver^0.0.2"

download archive

Stats

  • Archive size
    Archive size ~ 10.66 MB
  • Downloaded in total
    Downloaded in total 3 times
  • Weekly Downloads Weekly Downloads (All Versions)
  • Downloaded this version
    This version: 2 times

Badge

lierda-iot/esp_lora_driver version: 0.0.2
|