Hello Nordic Support,
I am developing a bare-metal, non-secure firmware for nRF9160 using nrf_modem
from SDK nrfxlib v2.9.0
, without Zephyr or RTOS.
I followed the porting guide here:
https://docs.nordicsemi.com/bundle/ncs-latest/page/nrfxlib/nrf_modem/doc/ug_nrf_modem_porting_os.html
However, calling nrf_modem_init()
consistently fails with:
Modem init failed: -22
which maps to -EINVAL
.
/********************************************************************* * SEGGER Microcontroller GmbH * * The Embedded Experts * ********************************************************************** -------------------------- END-OF-HEADER ----------------------------- File : main_ns.c Purpose : Generic application start */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <nrfx.h> #include <nrf_gpio.h> #include <nrf_errno.h> #include <nrf.h> #include <pins_def.h> #include <nrfx_ipc.h> #include <nrf_modem.h> #include <nrf_modem_os.h> #include "NSCFunctions.h" #define SHMEM_TX_SIZE ( 0x3000 ) // 12 KB #define SHMEM_RX_SIZE ( 0x3000 ) #define SHMEM_TRACE_SIZE ( 0x3000 ) #define SHMEM_SIZE (NRF_MODEM_CELLULAR_SHMEM_CTRL_SIZE + SHMEM_TX_SIZE + SHMEM_RX_SIZE + SHMEM_TRACE_SIZE) // Create one contiguous memory space for the buffers required by the modem driver typedef struct { uint8_t nrf_modem_ctrl[NRF_MODEM_CELLULAR_SHMEM_CTRL_SIZE]; uint8_t nrf_modem_tx[SHMEM_TX_SIZE]; uint8_t nrf_modem_rx[SHMEM_RX_SIZE]; uint8_t nrf_modem_trace[SHMEM_TRACE_SIZE]; } nrf_modem_bufs_t; static nrf_modem_bufs_t modem_shm __attribute__(( section(".modem_shm"), aligned(4))); const struct nrf_modem_shmem_cfg modem_shmem_cfg = { .ctrl = { .base = (uint32_t)&modem_shm.nrf_modem_ctrl, .size = NRF_MODEM_CELLULAR_SHMEM_CTRL_SIZE, }, .tx = { .base = (uint32_t)&modem_shm.nrf_modem_tx, .size = SHMEM_TX_SIZE, }, .rx = { .base = (uint32_t)&modem_shm.nrf_modem_rx, .size = SHMEM_RX_SIZE, }, .trace = { .base = (uint32_t)&modem_shm.nrf_modem_trace, .size = SHMEM_TRACE_SIZE, } }; //*********************************** // modem_fault_handler //*********************************** void modem_fault_handler(struct nrf_modem_fault_info *info) { printf("MODEM FAULT! PC=0x%08X Reason=%u\n", info->program_counter, info->reason); } void nrf_modem_os_init(void) { /* Initialize the glue layer and required peripherals. */ } void nrf_modem_os_shutdown(void) { /* Deinitialize the glue layer. When shutdown is called, all pending calls to nrf_modem_os_timedwait shall exit and return -NRF_ESHUTDOWN. */ } void *nrf_modem_os_shm_tx_alloc(size_t bytes) { /* Allocate a buffer on the TX area of shared memory. */ } void nrf_modem_os_shm_tx_free(void *mem) { /* Free a shared memory buffer in the TX area. */ } void *nrf_modem_os_alloc(size_t bytes) { /* Allocate a buffer on the library heap. */ } void nrf_modem_os_free(void *mem) { /* Free a memory buffer in the library heap. */ } void nrf_modem_os_busywait(int32_t usec) { /* Busy wait for a given number of microseconds. */ } int32_t nrf_modem_os_timedwait(uint32_t context, int32_t *timeout) { if (!nrf_modem_is_initialized()) { return -NRF_ESHUTDOWN; } /* Put a thread to sleep for a specific time or until an event occurs. Wait for the timeout. All waiting threads shall be woken by nrf_modem_event_notify. A blind return value of zero will cause a blocking wait. */ if (!nrf_modem_is_initialized()) { return -NRF_ESHUTDOWN; } return 0; } void nrf_modem_os_event_notify(uint32_t context) { // Notify the application that an event has occurred. // This shall wake all threads sleeping in nrf_modem_os_timedwait. } void nrf_modem_os_errno_set(int errno_val) { /* Set OS errno. */ } bool nrf_modem_os_is_in_isr(void) { // Check if executing in interrupt context. return false; } int nrf_modem_os_sem_init(void **sem, unsigned int initial_count, unsigned int limit) { /* If multithreaded access to modem functionalities is needed, the function must allocate * and initialize a semaphore and return its address through the `sem` parameter. If the * address of an already allocated semaphore is provided as an input, the allocation part is * skipped and the semaphore is only reinitialized. */ return 0; } void nrf_modem_os_sem_give(void *sem) { /* Give a semaphore. */ } int nrf_modem_os_sem_take(void *sem, int timeout) { /* Try to take a semaphore with the given timeout. */ return 0; } unsigned int nrf_modem_os_sem_count_get(void *sem) { /* Get a semaphore's count. */ return 0; } int nrf_modem_os_mutex_init(void **mutex) { /* If multithreaded access to modem functionalities is needed, the function must allocate * and initialize a reentrant mutex and return its address through the `mutex` parameter. * If the address of an already allocated mutex is provided as an input, the allocation part * is skipped and the mutex is only reinitialized. * Mutexes are not required if multithreaded access to modem functionalities is not needed. * In this case, the function must blindly return ``0``. */ return 0; } /* void nrf_modem_os_mutex_unlock(void *sem) { // Unlock a mutex. } */ int nrf_modem_os_mutex_lock(void *sem, int timeout) { /* Try to lock a reentrant mutex with the given timeout. */ return 0; } void nrf_modem_os_log(int level, const char *fmt, ...) { /* Generic logging procedure. */ // va_list ap; // va_start(ap, fmt); // vprintf(fmt, ap); // printf("\n"); // va_end(ap); } void nrf_modem_os_logdump(int level, const char *str, const void *data, size_t len) { /* Log hex representation of object. */ } // Configure non-secure peripherals. void nrf_spu_periph_set(uint16_t id, uint32_t flags); void nrf_spu_periph_clear(uint16_t id, uint32_t flags); void nrf_spu_gpio_set(uint16_t id); void nrf_spu_gpio_clear(uint16_t id); // Non-secure callable function extern uint32_t pxNSCFunctionHandler( uint32_t value ); //*********************************** // Print modem SHMEM CFG //*********************************** void print_modem_shmem_cfg(void) { printf("======== Modem SHMEM Config ========\n"); printf("CTRL : base = 0x%08X, size = %u bytes\n", (unsigned int)(uintptr_t)modem_shmem_cfg.ctrl.base, (unsigned int)modem_shmem_cfg.ctrl.size); printf("TX : base = 0x%08X, size = %u bytes\n", (unsigned int)(uintptr_t)modem_shmem_cfg.tx.base, (unsigned int)modem_shmem_cfg.tx.size); printf("RX : base = 0x%08X, size = %u bytes\n", (unsigned int)(uintptr_t)modem_shmem_cfg.rx.base, (unsigned int)modem_shmem_cfg.rx.size); printf("TRACE : base = 0x%08X, size = %u bytes\n", (unsigned int)(uintptr_t)modem_shmem_cfg.trace.base, (unsigned int)modem_shmem_cfg.trace.size); printf("====================================\n"); } //********************************************************************* // main() //********************************************************************* int main(void) { int i, j, k = 0; printf("Hello World!\n"); printf(nrf_modem_build_version()); printf("\n"); print_modem_shmem_cfg(); struct nrf_modem_init_params init_params = { .shmem = modem_shmem_cfg, .ipc_irq_prio = 0, // 0 ... 7 .fault_handler = modem_fault_handler, .dfu_handler = NULL, // optional }; int err = nrf_modem_init(&init_params); if (err < 0) { printf("Modem init failed: %d\n", err); } nrf_gpio_cfg_output(2); nrf_gpio_pin_set(2); nrf_gpio_cfg_output(3); nrf_gpio_pin_set(3); nrf_gpio_cfg_output(4); nrf_gpio_pin_set(4); nrf_gpio_cfg_output(5); nrf_gpio_pin_set(5); printf("NSC function 1 call result: %d\n", entry1(2)); printf("NSC function 2 call result: %d\n", entry2(2)); j = 0; do { for (i = 0; i < 10000; i++) { printf("Hello World %d!\n", i);; } nrf_gpio_pin_toggle( j + 2 ); j = ( j + 1 ) % 4; } while (1); } /*************************** End of file ****************************/
Given that:
-
SHMEM areas are correctly aligned
-
Memory is below 0x20020000
-
Sizes are valid (4K + 3×12K = 40K)
-
Fault handler is defined correctly
-
nrf_modem_os_*
stubs are implemented
I cannot identify why nrf_modem_init()
returns -EINVAL
. Could you help confirm whether this is a modem validation bug, a missing requirement, or a configuration issue?
Best regards,
Neculai