17个版本
新版本 0.5.0 | 2024年8月9日 |
---|---|
0.4.3 | 2024年6月18日 |
0.4.1 | 2023年9月22日 |
0.3.2 | 2023年4月24日 |
0.1.1 | 2022年12月26日 |
#79 in 嵌入式开发
173 每月下载量
160KB
3.5K SLoC
nRF-Modem
这是一个库,为Nordic nRF91*系列芯片(系统封装)上的调制解调器提供高级异步API。支持的芯片包括以下
- nRF9160
- nRF9151
- nRF9161
它可以与任何执行器一起使用。
使用
在您的程序或库中,您可以像通常那样依赖此包
[dependencies]
nrf-modem = "0.5.0"
nrf9160
功能默认启用,以支持旧版本。要在其他支持的芯片(例如nrf9151
)上使用此库,请选择该功能并禁用默认功能。
[dependencies]
nrf-modem = { version = "0.5.0", default-featues = false, features = ["nrf9151"] }
错误和恢复
释放LteLink和Gnss(这还包括所有套接字和GnssStream)可能会导致调制解调器保持活动状态。有一个内部互斥锁可以锁定。恐慌是对此的唯一合理反应。如果您有更好的想法,请提出问题或PR!异步deactivate
函数出错的可能性要小得多,您将获得一个Result,这样您就知道出了什么问题。
如果发生任何问题,has_runtime_state_error()
将返回true。一切都应该正常工作,但调制解调器可能没有正确关闭。这可以通过在确保不再使用调制解调器的任何部分时调用reset_runtime_state()
函数来恢复。
设置
您必须做一些事情才能使用此库。
首先,确保已安装llvm-tools
。这可以通过使用rustup component add llvm-tools-preview
来完成。
库还需要一些libc
函数。最佳导入方式是使用tinyrlibc。截至编写时,最新版本是0.3.0
。此版本不包括所需的API,因此最好包含最新的master分支或任何更新的发布版本。
该库已与调制解调器固件版本 1.3.4
进行过测试,但可能与更早版本兼容。当该库开始要求更高版本时,这将被视为破坏性更改。但可能会遗漏某些内容,因此这仅提供“尽力而为”的保证。
非安全
Nordic 已经使调制解调器只能在非安全上下文中使用。请确保您处于该上下文,例如使用 SPM 或 TF-M。
中断
中断 EGU1
和 IPC
必须路由到调制解调器软件。
// Interrupt Handler for LTE related hardware. Defer straight to the library.
#[interrupt]
#[allow(non_snake_case)]
fn IPC() {
nrf_modem::ipc_irq_handler();
}
let mut cp = unwrap!(cortex_m::Peripherals::take());
// Enable the modem interrupts
unsafe {
NVIC::unmask(pac::Interrupt::IPC);
cp.NVIC.set_priority(pac::Interrupt::IPC, 0 << 5);
}
电源
当库初始化时,DC/DC 转换器会自动为您启用。这是调制解调器认证操作所必需的。
初始化
现在是对库进行初始化的时候了。在这里,您可以为主调解调器的连接性进行选择
nrf_modem::init(SystemMode {
lte_support: true,
lte_psm_support: true,
nbiot_support: true,
gnss_support: true,
preference: ConnectionPreference::None,
})
.await
.unwrap();
现在库已准备好使用。
AT 命令
let response = nrf_modem::send_at::<64>("AT+CGMI").await.unwrap();
assert_eq!(response, "AT+CGMI\n\rNordic Semiconductor ASA\n\rOK\n\r");
DNS 请求
let google_ip = nrf_modem::get_host_by_name("www.google.com").await.unwrap();
Tcp 连接
let stream = nrf_modem::TcpStream::connect(SocketAddr::from((google_ip, 80))).await.unwrap();
stream
.write("GET / HTTP/1.0\nHost: google.com\r\n\r\n".as_bytes())
.await
.unwrap();
let mut buffer = [0; 1024];
let received = stream.receive(&mut buffer).await.unwrap();
println!("Google response: {}", core::str::from_utf8(received).unwrap());
// Drop the stream async (normal Drop is ok too, but that's blocking)
stream.deactivate().await.unwrap();
Udp 套接字
let socket =
nrf_modem::UdpSocket::bind(SocketAddr::from_str("0.0.0.0:53").unwrap())
.await
.unwrap();
// Do a DNS request
socket
.send_to(
&[
0xdb, 0x42, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77,
0x77, 0x77, 0x0C, 0x6E, 0x6F, 0x72, 0x74, 0x68, 0x65, 0x61, 0x73, 0x74, 0x65, 0x72,
0x6E, 0x03, 0x65, 0x64, 0x75, 0x00, 0x00, 0x01, 0x00, 0x01,
],
SocketAddr::from_str("8.8.8.8:53").unwrap(),
)
.await
.unwrap();
let (response, source_addr) = socket.receive_from(&mut buffer).await.unwrap();
println!("Result: {:X}", response);
println!("Source: {}", source_addr);
依赖项
~5–10MB
~177K SLoC