diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bfe0419..27bb589 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,5 @@ jobs: components: clippy, rustfmt, llvm-tools-preview targets: thumbv8m.main-none-eabihf - - run: cargo install cargo-binutils - run: cargo fmt -- --check - run: cargo clippy --target thumbv8m.main-none-eabihf diff --git a/CHANGELOG.md b/CHANGELOG.md index d2f3e50..8dacc73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.4.0 (2023-09-07) + +- Update nrfxlib-sys to 2.4.2, removing the need for the `EGU1` interrupt + ## 0.3.4 (05-09-23) - Fixed issue where LTE link waiting couldn't be cancelled diff --git a/Cargo.toml b/Cargo.toml index 41bd15e..3417dea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nrf-modem" -version = "0.3.4" +version = "0.4.0" edition = "2021" rust-version = "1.64" license = "MIT OR Apache-2.0" @@ -13,7 +13,7 @@ keywords = ["nRF9160", "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.1.0" +nrfxlib-sys = "2.4.2" futures = { version = "0.3.24", default-features = false, features = ["async-await"] } num_enum = { version = "0.6.1", default-features = false } defmt = { version = "0.3.2", optional = true } diff --git a/README.md b/README.md index 7edcb8a..c546d58 100644 --- a/README.md +++ b/README.md @@ -43,14 +43,6 @@ Make sure you are in that context by using e.g. the SPM. The `EGU1` and `IPC` interrupts must be routed to the modem software. ```rust,ignore -// Interrupt Handler for LTE related hardware. Defer straight to the library. -#[interrupt] -#[allow(non_snake_case)] -fn EGU1() { - nrf_modem::application_irq_handler(); - cortex_m::asm::sev(); -} - // Interrupt Handler for LTE related hardware. Defer straight to the library. #[interrupt] #[allow(non_snake_case)] @@ -63,9 +55,7 @@ let mut cp = unwrap!(cortex_m::Peripherals::take()); // Enable the modem interrupts unsafe { - NVIC::unmask(pac::Interrupt::EGU1); NVIC::unmask(pac::Interrupt::IPC); - cp.NVIC.set_priority(pac::Interrupt::EGU1, 4 << 5); cp.NVIC.set_priority(pac::Interrupt::IPC, 0 << 5); } ``` diff --git a/src/at.rs b/src/at.rs index 0778c3c..9bccb6d 100644 --- a/src/at.rs +++ b/src/at.rs @@ -31,7 +31,9 @@ static AT_DATA_WAKER: AtomicWaker = AtomicWaker::new(); /// The callback that will be called by nrfxlib when the at command has a response. /// The `resp` is a null-terminated string. -unsafe extern "C" fn at_callback(resp: *const u8) { +unsafe extern "C" fn at_callback(resp: *const core::ffi::c_char) { + let resp = resp as *const u8; + #[cfg(feature = "defmt")] defmt::trace!( "AT <- {}", @@ -102,7 +104,7 @@ pub fn send_at_blocking(command: &str) -> Result(command: &str) -> Result Future for SendATFuture<'c, CAP> { let result = unsafe { nrfxlib_sys::nrf_modem_at_cmd_async( Some(at_callback), - b"%.*s\0".as_ptr(), + b"%.*s\0".as_ptr() as *const core::ffi::c_char, self.command.len(), self.command.as_ptr(), ) diff --git a/src/at_notifications.rs b/src/at_notifications.rs index 8dba77d..3e9d7a5 100644 --- a/src/at_notifications.rs +++ b/src/at_notifications.rs @@ -9,7 +9,9 @@ use critical_section::Mutex; static WAKER_NODE_LIST: Mutex>> = Mutex::new(RefCell::new(WakerNodeList::new())); -pub(crate) unsafe extern "C" fn at_notification_handler(notif: *const u8) { +pub(crate) unsafe extern "C" fn at_notification_handler(notif: *const core::ffi::c_char) { + let notif = notif as *const u8; + #[cfg(feature = "defmt")] defmt::trace!( "AT notification <- {}", diff --git a/src/dns.rs b/src/dns.rs index 68b7e33..61c00e5 100644 --- a/src/dns.rs +++ b/src/dns.rs @@ -69,7 +69,7 @@ pub async fn get_host_by_name_with_cancellation( hostname.push('\0'); let err = nrfxlib_sys::nrf_getaddrinfo( - hostname.as_ptr(), + hostname.as_ptr() as *const core::ffi::c_char, core::ptr::null(), &hints as *const _, &mut result as *mut *mut _, diff --git a/src/ffi.rs b/src/ffi.rs index 36d7a72..2bdb07f 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -31,7 +31,8 @@ pub struct NrfxIpcConfig { } /// IPC callback function type -type NrfxIpcHandler = extern "C" fn(event_mask: u32, ptr: *mut u8); +// based on https://github.com/NordicSemiconductor/nrfx/blob/98d6f433313a3d8dcf08dce25e744617b45aa913/drivers/include/nrfx_ipc.h#L56 +type NrfxIpcHandler = extern "C" fn(event_idx: u8, ptr: *mut u8); /// IPC error type #[repr(u32)] @@ -75,33 +76,15 @@ static IPC_CONTEXT: core::sync::atomic::AtomicUsize = core::sync::atomic::Atomic /// Remembers the IPC handler function we were given static IPC_HANDLER: core::sync::atomic::AtomicUsize = core::sync::atomic::AtomicUsize::new(0); -/// Function required by BSD library. We need to set the EGU1 interrupt. -#[no_mangle] -pub extern "C" fn nrf_modem_os_application_irq_set() { - cortex_m::peripheral::NVIC::pend(nrf9160_pac::Interrupt::EGU1); -} - -/// Function required by BSD library. We need to clear the EGU1 interrupt. -#[no_mangle] -pub extern "C" fn nrf_modem_os_application_irq_clear() { - cortex_m::peripheral::NVIC::unpend(nrf9160_pac::Interrupt::EGU1); -} - -/// Function required by BSD library. We need to set the EGU2 interrupt. -#[no_mangle] -pub extern "C" fn nrf_modem_os_trace_irq_set() { - cortex_m::peripheral::NVIC::pend(nrf9160_pac::Interrupt::EGU2); -} - -/// Function required by BSD library. We need to clear the EGU2 interrupt. +/// Function required by BSD library. We have no init to do. #[no_mangle] -pub extern "C" fn nrf_modem_os_trace_irq_clear() { - cortex_m::peripheral::NVIC::unpend(nrf9160_pac::Interrupt::EGU2); +pub extern "C" fn nrf_modem_os_init() { + // Nothing } -/// Function required by BSD library. We have no init to do. +/// Function required by BSD library. We have no shutdown to do. #[no_mangle] -pub extern "C" fn nrf_modem_os_init() { +pub extern "C" fn nrf_modem_os_shutdown() { // Nothing } @@ -177,19 +160,6 @@ pub extern "C" fn nrf_modem_os_event_notify() { NOTIFY_ACTIVE.store(true, Ordering::SeqCst); } -/// Function required by BSD library -#[no_mangle] -pub extern "C" fn nrf_modem_os_trace_put(_data: *const u8, _len: u32) -> i32 { - // Do nothing - 0 -} - -/// Function required by BSD library -#[no_mangle] -pub extern "C" fn nrf_modem_irrecoverable_error_handler(err: u32) -> ! { - panic!("bsd_irrecoverable_error_handler({})", err); -} - /// The Modem library needs to dynamically allocate memory (a heap) for proper /// functioning. This memory is used to store the internal data structures that /// are used to manage the communication between the application core and the @@ -229,16 +199,6 @@ pub unsafe extern "C" fn nrf_modem_os_shm_tx_free(ptr: *mut u8) { generic_free(ptr, &crate::TX_ALLOCATOR); } -#[no_mangle] -pub extern "C" fn nrf_modem_os_trace_alloc(_bytes: usize) -> *mut u8 { - unimplemented!() -} - -#[no_mangle] -pub extern "C" fn nrf_modem_os_trace_free(_mem: *mut u8) { - unimplemented!() -} - /// @brief Function for loading configuration directly into IPC peripheral. /// /// @param p_config Pointer to the structure with the initial configuration. @@ -260,7 +220,6 @@ pub unsafe extern "C" fn nrfx_ipc_config_load(p_config: *const NrfxIpcConfig) { .write(|w| w.bits(config.receive_events_enabled)); } -/// /// @brief Function for initializing the IPC driver. /// /// @param irq_priority Interrupt priority. @@ -374,23 +333,39 @@ unsafe fn generic_free(ptr: *mut u8, heap: &crate::WrappedHeap) { /// Call this when we have an IPC IRQ. Not `extern C` as its not called by the /// library, only our interrupt handler code. +// This function seems to be based on this verion in C: +// 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(); + // Fetch interrupt handler and context to use during event resolution + let handler_addr = IPC_HANDLER.load(core::sync::atomic::Ordering::SeqCst); + let handler = if handler_addr != 0 { + let handler = core::mem::transmute::(handler_addr); + Some(handler) + } else { + #[cfg(feature = "defmt")] + defmt::warn!("No IPC handler registered"); + None + }; + let context = IPC_CONTEXT.load(core::sync::atomic::Ordering::SeqCst); + // Clear these events let mut bitmask = events_map; 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)); - } - // Execute interrupt handler to provide information about events to app - let handler_addr = IPC_HANDLER.load(core::sync::atomic::Ordering::SeqCst); - let handler = core::mem::transmute::(handler_addr); - let context = IPC_CONTEXT.load(core::sync::atomic::Ordering::SeqCst); - (handler)(events_map, context as *mut u8); + // Execute interrupt handler to provide information about events to app + if let Some(handler) = handler { + let event_idx = event_idx + .try_into() + .expect("A u32 has less then 255 trailing zeroes"); + (handler)(event_idx, context as *mut u8); + } + } } /// Initialize a semaphore. @@ -407,10 +382,10 @@ pub unsafe fn nrf_ipc_irq_handler() { /// - 0 on success, a negative errno otherwise. #[no_mangle] pub unsafe extern "C" fn nrf_modem_os_sem_init( - sem: *mut *mut nrfxlib_sys::ctypes::c_void, - initial_count: nrfxlib_sys::ctypes::c_uint, - limit: nrfxlib_sys::ctypes::c_uint, -) -> nrfxlib_sys::ctypes::c_int { + sem: *mut *mut core::ffi::c_void, + initial_count: core::ffi::c_uint, + limit: core::ffi::c_uint, +) -> core::ffi::c_int { if sem.is_null() || initial_count > limit { return -(nrfxlib_sys::NRF_EINVAL as i32); } @@ -442,7 +417,7 @@ pub unsafe extern "C" fn nrf_modem_os_sem_init( /// **Parameters** /// - sem – The semaphore. #[no_mangle] -pub extern "C" fn nrf_modem_os_sem_give(sem: *mut nrfxlib_sys::ctypes::c_void) { +pub extern "C" fn nrf_modem_os_sem_give(sem: *mut core::ffi::c_void) { unsafe { if sem.is_null() { return; @@ -471,9 +446,9 @@ pub extern "C" fn nrf_modem_os_sem_give(sem: *mut nrfxlib_sys::ctypes::c_void) { /// - -NRF_EAGAIN – If the semaphore could not be taken. #[no_mangle] pub extern "C" fn nrf_modem_os_sem_take( - sem: *mut nrfxlib_sys::ctypes::c_void, - mut timeout: nrfxlib_sys::ctypes::c_int, -) -> nrfxlib_sys::ctypes::c_int { + sem: *mut core::ffi::c_void, + mut timeout: core::ffi::c_int, +) -> core::ffi::c_int { unsafe { if sem.is_null() { return -(nrfxlib_sys::NRF_EAGAIN as i32); @@ -520,9 +495,7 @@ pub extern "C" fn nrf_modem_os_sem_take( /// **Returns** /// - Current semaphore count. #[no_mangle] -pub extern "C" fn nrf_modem_os_sem_count_get( - sem: *mut nrfxlib_sys::ctypes::c_void, -) -> nrfxlib_sys::ctypes::c_uint { +pub extern "C" fn nrf_modem_os_sem_count_get(sem: *mut core::ffi::c_void) -> core::ffi::c_uint { unsafe { if sem.is_null() { return 0; diff --git a/src/gnss.rs b/src/gnss.rs index e20df8b..83a9d35 100644 --- a/src/gnss.rs +++ b/src/gnss.rs @@ -416,7 +416,7 @@ impl GnssData { ) .into_result()?; - let data = data.assume_init().nmea_str; + let data = core::mem::transmute(data.assume_init().nmea_str); // Make data be u8 let mut string_data = ArrayString::from_byte_string(&data)?; string_data.truncate( string_data diff --git a/src/lib.rs b/src/lib.rs index b506230..286c048 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,22 +93,25 @@ pub async fn init(mode: SystemMode) -> Result<(), Error> { // At start of shared memory (see memory.x) base: 0x2001_0000, // This is the amount specified in the NCS 1.5.1 release. - size: 0x0000_04e8, + size: nrfxlib_sys::NRF_MODEM_SHMEM_CTRL_SIZE, }, tx: nrfxlib_sys::nrf_modem_shmem_cfg__bindgen_ty_2 { // Follows on from control buffer - base: 0x2001_04e8, + base: 0x2001_0000 + nrfxlib_sys::NRF_MODEM_SHMEM_CTRL_SIZE, // This is the amount specified in the NCS 1.5.1 release. size: 0x0000_2000, }, rx: nrfxlib_sys::nrf_modem_shmem_cfg__bindgen_ty_3 { // Follows on from TX buffer - base: 0x2001_24e8, + base: 0x2001_0000 + nrfxlib_sys::NRF_MODEM_SHMEM_CTRL_SIZE + 0x2000, // This is the amount specified in the NCS 1.5.1 release. size: 0x0000_2000, }, // No trace info - trace: nrfxlib_sys::nrf_modem_shmem_cfg__bindgen_ty_4 { base: 0, size: 0 }, + trace: nrfxlib_sys::nrf_modem_shmem_cfg__bindgen_ty_4 { + base: 0x2001_0000, + size: 0, + }, }, ipc_irq_prio: 0, fault_handler: Some(modem_fault_handler), @@ -125,8 +128,7 @@ pub async fn init(mode: SystemMode) -> Result<(), Error> { } // OK, let's start the library - unsafe { nrfxlib_sys::nrf_modem_init(¶ms, nrfxlib_sys::nrf_modem_mode_NORMAL_MODE) } - .into_result()?; + unsafe { nrfxlib_sys::nrf_modem_init(¶ms) }.into_result()?; // Initialize AT notifications at_notifications::initialize()?; @@ -166,19 +168,11 @@ unsafe extern "C" fn modem_fault_handler(_info: *mut nrfxlib_sys::nrf_modem_faul ); } -/// You must call this when an EGU1 interrupt occurs. -pub fn application_irq_handler() { - unsafe { - nrfxlib_sys::nrf_modem_application_irq_handler(); - nrfxlib_sys::nrf_modem_os_event_notify(); - } -} - /// IPC code now lives outside `lib_modem`, so call our IPC handler function. pub fn ipc_irq_handler() { unsafe { crate::ffi::nrf_ipc_irq_handler(); - nrfxlib_sys::nrf_modem_os_event_notify(); + nrfxlib_sys::nrf_modem_os_event_notify(0); crate::socket::wake_sockets(); } } diff --git a/src/socket.rs b/src/socket.rs index c27fca8..16355a2 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -601,12 +601,12 @@ impl<'a> SocketOption<'a> { } } - pub(crate) fn get_value(&self) -> *const nrfxlib_sys::ctypes::c_void { + pub(crate) fn get_value(&self) -> *const core::ffi::c_void { match self { - SocketOption::TlsHostName(s) => s.as_ptr() as *const nrfxlib_sys::ctypes::c_void, - SocketOption::TlsPeerVerify(x) => x as *const _ as *const nrfxlib_sys::ctypes::c_void, - SocketOption::TlsSessionCache(x) => x as *const _ as *const nrfxlib_sys::ctypes::c_void, - SocketOption::TlsTagList(x) => x.as_ptr() as *const nrfxlib_sys::ctypes::c_void, + SocketOption::TlsHostName(s) => s.as_ptr() as *const core::ffi::c_void, + SocketOption::TlsPeerVerify(x) => x as *const _ as *const core::ffi::c_void, + SocketOption::TlsSessionCache(x) => x as *const _ as *const core::ffi::c_void, + SocketOption::TlsTagList(x) => x.as_ptr() as *const core::ffi::c_void, } }