Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nrf9151 preview #23

Merged
merged 11 commits into from
Aug 9, 2024
15 changes: 11 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,32 @@ description = "Async modem api for the nRF9160"
homepage = "https://github.com/diondokter/nrf-modem"
repository = "https://github.com/diondokter/nrf-modem"
readme = "README.md"
keywords = ["nRF9160", "LTE", "GPS", "NB-IoT", "embedded"]
keywords = ["nRF9160", "nRF9151", "LTE", "GPS", "NB-IoT", "embedded"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
nrfxlib-sys = "2.4.2"
nrfxlib-sys = "2.7.0"
nerwalt marked this conversation as resolved.
Show resolved Hide resolved

futures = { version = "0.3.24", default-features = false, features = ["async-await"] }
num_enum = { version = "0.7.0", default-features = false }
defmt = { version = "0.3", optional = true }
cortex-m = "0.7"
linked_list_allocator = { version="0.10.1", default-features=false, features=["use_spin"] }
nrf9160-pac = "0.12.2"
arrayvec = { version = "0.7", default-features = false }
nrf9160-pac = { version = "0.12.2", optional = true }
nrf9120-pac = { version = "0.12.2", optional = true }
at-commands = "0.5.2"
no-std-net = "0.6.0"
critical-section = "1.1"
embassy-sync = "0.6.0"
grounded = "0.2.0"

[features]
default = []
default = ["nrf9160"]
defmt = ["dep:defmt", "at-commands/defmt"]

nrf9160 = ["nrfxlib-sys/nrf9160", "dep:nrf9160-pac"]
nrf9151 = ["nrf9120"]
nrf9161 = ["nrf9120"]
nrf9120 = ["nrfxlib-sys/nrf9120", "dep:nrf9120-pac"]
4 changes: 2 additions & 2 deletions src/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,13 @@ pub async fn get_host_by_name_with_cancellation(
while !result_iter.is_null() && found_ip.is_none() {
let address = (*result_iter).ai_addr;

if (*address).sa_family == nrfxlib_sys::NRF_AF_INET as i32 {
if (*address).sa_family == nrfxlib_sys::NRF_AF_INET as u16 {
let dns_addr: &nrfxlib_sys::nrf_sockaddr_in =
&*(address as *const nrfxlib_sys::nrf_sockaddr_in);

let socket_addr: SocketAddr = NrfSockAddr::from(*dns_addr).into();
found_ip = Some(socket_addr.ip());
} else if (*address).sa_family == nrfxlib_sys::NRF_AF_INET6 as i32 {
} else if (*address).sa_family == nrfxlib_sys::NRF_AF_INET6 as u16 {
let dns_addr: &nrfxlib_sys::nrf_sockaddr_in6 =
&*(address as *const nrfxlib_sys::nrf_sockaddr_in6);

Expand Down
173 changes: 165 additions & 8 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@

use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};

#[cfg(feature = "nrf9160")]
use nrf9160_pac as pac;

#[cfg(feature = "nrf9120")]
use nrf9120_pac as pac;

/// Number of IPC configurations in `NrfxIpcConfig`
const IPC_CONF_NUM: usize = 8;

Expand Down Expand Up @@ -103,7 +109,7 @@ pub fn get_last_error() -> isize {
#[no_mangle]
pub extern "C" fn nrf_modem_os_busywait(usec: i32) {
if usec > 0 {
// NRF9160 runs at 64 MHz, so this is close enough
// The nRF91* Arm Cortex-M33 runs at 64 MHz, so this is close enough
cortex_m::asm::delay((usec as u32) * 64);
}
}
Expand Down Expand Up @@ -206,7 +212,7 @@ pub unsafe extern "C" fn nrf_modem_os_shm_tx_free(ptr: *mut u8) {
pub unsafe extern "C" fn nrfx_ipc_config_load(p_config: *const NrfxIpcConfig) {
let config: &NrfxIpcConfig = &*p_config;

let ipc = &(*nrf9160_pac::IPC_NS::ptr());
let ipc = &(*pac::IPC_NS::ptr());

for (i, value) in config.send_task_config.iter().enumerate() {
ipc.send_cnf[i].write(|w| w.bits(*value));
Expand Down Expand Up @@ -235,7 +241,7 @@ pub extern "C" fn nrfx_ipc_init(
p_context: usize,
) -> NrfxErr {
use cortex_m::interrupt::InterruptNumber;
let irq = nrf9160_pac::Interrupt::IPC;
let irq = pac::Interrupt::IPC;
let irq_num = usize::from(irq.number());
unsafe {
cortex_m::peripheral::NVIC::unmask(irq);
Expand All @@ -250,7 +256,7 @@ pub extern "C" fn nrfx_ipc_init(
/// Function for uninitializing the IPC module.
#[no_mangle]
pub extern "C" fn nrfx_ipc_uninit() {
let ipc = unsafe { &(*nrf9160_pac::IPC_NS::ptr()) };
let ipc = unsafe { &(*pac::IPC_NS::ptr()) };

for i in 0..IPC_CONF_NUM {
ipc.send_cnf[i].reset();
Expand All @@ -265,14 +271,14 @@ pub extern "C" fn nrfx_ipc_uninit() {

#[no_mangle]
pub extern "C" fn nrfx_ipc_receive_event_enable(event_index: u8) {
let ipc = unsafe { &(*nrf9160_pac::IPC_NS::ptr()) };
let ipc = unsafe { &(*pac::IPC_NS::ptr()) };
ipc.inten
.modify(|r, w| unsafe { w.bits(r.bits() | 1 << event_index) })
}

#[no_mangle]
pub extern "C" fn nrfx_ipc_receive_event_disable(event_index: u8) {
let ipc = unsafe { &(*nrf9160_pac::IPC_NS::ptr()) };
let ipc = unsafe { &(*pac::IPC_NS::ptr()) };
ipc.inten
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << event_index)) })
}
Expand Down Expand Up @@ -337,7 +343,7 @@ unsafe fn generic_free(ptr: *mut u8, heap: &crate::WrappedHeap) {
// https://github.com/NordicSemiconductor/nrfx/blob/98d6f433313a3d8dcf08dce25e744617b45aa913/drivers/src/nrfx_ipc.c#L146-L163
pub unsafe fn nrf_ipc_irq_handler() {
// Get the information about events that fired this interrupt
let events_map = (*nrf9160_pac::IPC_NS::ptr()).intpend.read().bits();
let events_map = (*pac::IPC_NS::ptr()).intpend.read().bits();

// Fetch interrupt handler and context to use during event resolution
let handler_addr = IPC_HANDLER.load(core::sync::atomic::Ordering::SeqCst);
Expand All @@ -356,7 +362,7 @@ pub unsafe fn nrf_ipc_irq_handler() {
while bitmask != 0 {
let event_idx = bitmask.trailing_zeros();
bitmask &= !(1 << event_idx);
(*nrf9160_pac::IPC_NS::ptr()).events_receive[event_idx as usize].write(|w| w.bits(0));
(*pac::IPC_NS::ptr()).events_receive[event_idx as usize].write(|w| w.bits(0));

// Execute interrupt handler to provide information about events to app
if let Some(handler) = handler {
Expand Down Expand Up @@ -517,3 +523,154 @@ struct Semaphore {
pub extern "C" fn nrf_modem_os_is_in_isr() -> bool {
cortex_m::peripheral::SCB::vect_active() != cortex_m::peripheral::scb::VectActive::ThreadMode
}

// A basic mutex lock implementation for the os mutex functions below
struct MutexLock {
lock: AtomicBool
}

impl MutexLock {
pub fn lock(&self) -> bool {
match self.lock.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) {
Ok(false) => true,
_ => false
}
}

pub fn unlock(&self) {
self.lock.store(false, Ordering::SeqCst);
}
}

/// Initialize a mutex.
///
/// The function shall allocate and initialize a mutex and return its address
/// as an output. If an address of an already allocated mutex is provided as
/// an input, the allocation part is skipped and the mutex is only reinitialized.
///
/// **Parameters**:
/// - mutex – (inout) The address of the mutex.
///
/// **Returns**
/// - 0 on success, a negative errno otherwise.
#[no_mangle]
pub unsafe extern "C" fn nrf_modem_os_mutex_init(
mutex: *mut *mut core::ffi::c_void
) -> core::ffi::c_int {
if mutex.is_null() {
return -(nrfxlib_sys::NRF_EINVAL as i32);
}

// Allocate if we need to
if (*mutex).is_null() {
// Allocate our mutex datastructure
*mutex = nrf_modem_os_alloc(core::mem::size_of::<MutexLock>()) as *mut _;

if (*mutex).is_null() {
// We are out of memory
return -(nrfxlib_sys::NRF_ENOMEM as i32);
}
}

// (Re-)Initialize (unlock) the mutex
(*(mutex as *mut MutexLock)).unlock();
diondokter marked this conversation as resolved.
Show resolved Hide resolved

0
}

/// Lock a mutex.
///
/// **Parameters**:
/// - mutex – (in) The mutex.
/// - timeout – Timeout in milliseconds. NRF_MODEM_OS_FOREVER indicates infinite timeout. NRF_MODEM_OS_NO_WAIT indicates no timeout.
///
/// **Return values**
/// - 0 – on success.
/// - -NRF_EAGAIN – If the mutex could not be taken.
#[no_mangle]
pub unsafe extern "C" fn nrf_modem_os_mutex_lock(
mutex: *mut core::ffi::c_void,
timeout: core::ffi::c_int,
) -> core::ffi::c_int {
if mutex.is_null() {
return -(nrfxlib_sys::NRF_EINVAL as i32);
}

let mutex = &*(mutex as *mut MutexLock);

let mut locked = mutex.lock();

if locked || timeout == nrfxlib_sys::NRF_MODEM_OS_NO_WAIT as i32 {
return if locked { 0 } else { -(nrfxlib_sys::NRF_EAGAIN as i32) }
}

let mut elapsed = 0;
const WAIT_US: core::ffi::c_int = 100;

while !locked {
nrf_modem_os_busywait(WAIT_US);

if timeout != nrfxlib_sys::NRF_MODEM_OS_FOREVER as i32 {
elapsed += WAIT_US;
if (elapsed / 1000) > timeout {
return -(nrfxlib_sys::NRF_EAGAIN as i32);
}
}

locked = mutex.lock();
}

0
}


/// Unlock a mutex.
///
/// **Parameters**:
/// - mutex – (in) The mutex.
///
/// **Return values**
/// - 0 – on success.
/// - -NRF_EPERM – If the current thread does not own this mutex.
/// - -NRF_EINVAL – If the mutex is not locked.
#[no_mangle]
pub unsafe extern "C" fn nrf_modem_os_mutex_unlock(
mutex: *mut core::ffi::c_void
) -> core::ffi::c_int {
if mutex.is_null() {
return -(nrfxlib_sys::NRF_EINVAL as i32);
}
(*(mutex as *mut MutexLock)).unlock();
0
}

/// Generic logging procedure
///
/// **Parameters**:
/// - level – Log level
/// - fmt – Format string
/// - ... – Varargs
#[no_mangle]
pub extern "C" fn nrf_modem_os_log(
_level: core::ffi::c_int,
_fmt: *const core::ffi::c_char
) {
// TODO FIXME
}

/// Logging procedure for dumping hex representation of object.
///
/// **Parameters**:
/// - level – Log level.
/// - strdata - String to print in the log.
/// - data - Data whose hex representation we want to log.
/// - len - Length of the data to hex dump.
#[no_mangle]
pub extern "C" fn nrf_modem_os_logdump(
_level: core::ffi::c_int,
_strdata: *const core::ffi::c_char,
_data: *const core::ffi::c_void,
_len: core::ffi::c_int,
) {
// TODO FIXME
}
8 changes: 4 additions & 4 deletions src/gnss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ enum GnssEventType {
/// NMEA event.
Nmea = nrfxlib_sys::NRF_MODEM_GNSS_EVT_NMEA,
/// Need new APGS data event.
AgpsRequest = nrfxlib_sys::NRF_MODEM_GNSS_EVT_AGPS_REQ,
AgpsRequest = nrfxlib_sys::NRF_MODEM_GNSS_EVT_AGNSS_REQ,
/// GNSS is blocked by LTE event.
BlockedByLte = nrfxlib_sys::NRF_MODEM_GNSS_EVT_BLOCKED,
/// GNSS is unblocked by LTE event.
Expand Down Expand Up @@ -374,7 +374,7 @@ pub enum GnssPowerSaveMode {
enum GnssDataType {
PositionVelocityTime = nrfxlib_sys::NRF_MODEM_GNSS_DATA_PVT,
Nmea = nrfxlib_sys::NRF_MODEM_GNSS_DATA_NMEA,
Agps = nrfxlib_sys::NRF_MODEM_GNSS_DATA_AGPS_REQ,
Agps = nrfxlib_sys::NRF_MODEM_GNSS_DATA_AGNSS_REQ,
}

/// An enum containing all possible GNSS data types
Expand All @@ -385,7 +385,7 @@ pub enum GnssData {
/// An NMEA string
Nmea(ArrayString<83>),
/// An assisted gps data frame
Agps(nrfxlib_sys::nrf_modem_gnss_agps_data_frame),
Agps(nrfxlib_sys::nrf_modem_gnss_agnss_data_frame),
}

impl GnssData {
Expand Down Expand Up @@ -435,7 +435,7 @@ impl GnssData {
unsafe {
nrfxlib_sys::nrf_modem_gnss_read(
data.as_mut_ptr() as *mut _,
size_of::<nrfxlib_sys::nrf_modem_gnss_agps_data_frame>() as i32,
size_of::<nrfxlib_sys::nrf_modem_gnss_agnss_data_frame>() as i32,
data_type as u32 as _,
)
.into_result()?;
Expand Down
16 changes: 8 additions & 8 deletions src/ip.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::socket::SocketFamily;
use core::mem::size_of;
// use core::mem::size_of;
use no_std_net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use nrfxlib_sys::{nrf_sockaddr, nrf_sockaddr_in, nrf_sockaddr_in6};

Expand All @@ -12,22 +12,22 @@ impl From<SocketAddr> for NrfSockAddr {
fn from(addr: SocketAddr) -> Self {
match addr {
SocketAddr::V4(addr) => nrf_sockaddr_in {
sin_len: size_of::<nrf_sockaddr_in>() as u8,
sin_family: SocketFamily::Ipv4 as u32,
// sin_len: size_of::<nrf_sockaddr_in>() as u8,
sin_family: SocketFamily::Ipv4 as u16,
sin_port: addr.port().to_be(),
sin_addr: nrfxlib_sys::nrf_in_addr {
s_addr: u32::to_be((*addr.ip()).into()),
},
}
.into(),
SocketAddr::V6(addr) => nrf_sockaddr_in6 {
sin6_len: size_of::<nrf_sockaddr_in6>() as u8,
sin6_family: SocketFamily::Ipv6 as u32,
// sin6_len: size_of::<nrf_sockaddr_in6>() as u8,
sin6_family: SocketFamily::Ipv6 as u16,
sin6_port: addr.port().to_be(),
sin6_addr: nrfxlib_sys::nrf_in6_addr {
s6_addr: addr.ip().octets(),
},
sin6_flowinfo: 0,
// sin6_flowinfo: 0,
sin6_scope_id: 0,
}
.into(),
Expand All @@ -54,8 +54,8 @@ impl From<NrfSockAddr> for SocketAddr {

impl From<*const nrf_sockaddr> for NrfSockAddr {
fn from(v: *const nrf_sockaddr) -> Self {
const IPV4: i32 = SocketFamily::Ipv4 as u32 as i32;
const IPV6: i32 = SocketFamily::Ipv6 as u32 as i32;
const IPV4: u16 = SocketFamily::Ipv4 as u16;
const IPV6: u16 = SocketFamily::Ipv6 as u16;

unsafe {
match (*v).sa_family {
Expand Down
Loading
Loading