88//! Dual-licensed under MIT and Apache 2.0. See the [README](../README.md) for
99//! more details.
1010
11- use log:: debug;
12-
13- /// Number of IPC configurations in `NrfxIpcConfig`
14- const IPC_CONF_NUM : usize = 8 ;
15-
16- /// Used by `libmodem` to configure the IPC peripheral. See `nrfx_ipc_config_t`
17- /// in `nrfx/drivers/include/nrfx_ipc.h`.
18- #[ derive( Debug , Clone ) ]
19- pub struct NrfxIpcConfig {
20- /// Configuration of the connection between signals and IPC channels.
21- send_task_config : [ u32 ; IPC_CONF_NUM ] ,
22- /// Configuration of the connection between events and IPC channels.
23- receive_event_config : [ u32 ; IPC_CONF_NUM ] ,
24- /// Bitmask with events to be enabled to generate interrupt.
25- receive_events_enabled : u32 ,
26- }
27-
28- /// IPC callback function type
29- type NrfxIpcHandler = extern "C" fn ( event_mask : u32 , ptr : * mut u8 ) ;
30-
31- /// IPC error type
32- #[ repr( u32 ) ]
33- #[ derive( Debug , Copy , Clone ) ]
34- pub enum NrfxErr {
35- ///< Operation performed successfully.
36- Success = 0x0BAD0000 ,
37- ///< Internal error.
38- ErrorInternal = ( 0x0BAD0000 + 1 ) ,
39- ///< No memory for operation.
40- ErrorNoMem = ( 0x0BAD0000 + 2 ) ,
41- ///< Not supported.
42- ErrorNotSupported = ( 0x0BAD0000 + 3 ) ,
43- ///< Invalid parameter.
44- ErrorInvalidParam = ( 0x0BAD0000 + 4 ) ,
45- ///< Invalid state, operation disallowed in this state.
46- ErrorInvalidState = ( 0x0BAD0000 + 5 ) ,
47- ///< Invalid length.
48- ErrorInvalidLength = ( 0x0BAD0000 + 6 ) ,
49- ///< Operation timed out.
50- ErrorTimeout = ( 0x0BAD0000 + 7 ) ,
51- ///< Operation is forbidden.
52- ErrorForbidden = ( 0x0BAD0000 + 8 ) ,
53- ///< Null pointer.
54- ErrorNull = ( 0x0BAD0000 + 9 ) ,
55- ///< Bad memory address.
56- ErrorInvalidAddr = ( 0x0BAD0000 + 10 ) ,
57- ///< Busy.
58- ErrorBusy = ( 0x0BAD0000 + 11 ) ,
59- ///< Module already initialized.
60- ErrorAlreadyInitialized = ( 0x0BAD0000 + 12 ) ,
61- }
62-
63- /// Stores the last error from the library. See `nrf_modem_os_errno_set` and
11+ /// Stores the last error from the library. See `bsd_os_errno_set` and
6412/// `get_last_error`.
6513static LAST_ERROR : core:: sync:: atomic:: AtomicI32 = core:: sync:: atomic:: AtomicI32 :: new ( 0 ) ;
6614
67- /// Remembers the IPC interrupt context we were given
68- static IPC_CONTEXT : core :: sync :: atomic :: AtomicUsize = core :: sync :: atomic :: AtomicUsize :: new ( 0 ) ;
69-
70- /// Remembers the IPC handler function we were given
71- static IPC_HANDLER : core :: sync :: atomic :: AtomicUsize = core :: sync :: atomic :: AtomicUsize :: new ( 0 ) ;
15+ extern "C" {
16+ // This function is in the C library but not in the headers generated by
17+ // nrfxlib-sys.
18+ pub fn IPC_IRQHandler ( ) ;
19+ }
7220
7321/// Function required by BSD library. We need to set the EGU1 interrupt.
7422#[ no_mangle]
75- pub extern "C" fn nrf_modem_os_application_irq_set ( ) {
23+ pub extern "C" fn bsd_os_application_irq_set ( ) {
7624 cortex_m:: peripheral:: NVIC :: pend ( crate :: cpu:: Interrupt :: EGU1 ) ;
7725}
7826
7927/// Function required by BSD library. We need to clear the EGU1 interrupt.
8028#[ no_mangle]
81- pub extern "C" fn nrf_modem_os_application_irq_clear ( ) {
29+ pub extern "C" fn bsd_os_application_irq_clear ( ) {
8230 cortex_m:: peripheral:: NVIC :: unpend ( crate :: cpu:: Interrupt :: EGU1 ) ;
8331}
8432
8533/// Function required by BSD library. We need to set the EGU2 interrupt.
8634#[ no_mangle]
87- pub extern "C" fn nrf_modem_os_trace_irq_set ( ) {
35+ pub extern "C" fn bsd_os_trace_irq_set ( ) {
8836 cortex_m:: peripheral:: NVIC :: pend ( crate :: cpu:: Interrupt :: EGU2 ) ;
8937}
9038
9139/// Function required by BSD library. We need to clear the EGU2 interrupt.
9240#[ no_mangle]
93- pub extern "C" fn nrf_modem_os_trace_irq_clear ( ) {
41+ pub extern "C" fn bsd_os_trace_irq_clear ( ) {
9442 cortex_m:: peripheral:: NVIC :: unpend ( crate :: cpu:: Interrupt :: EGU2 ) ;
9543}
9644
9745/// Function required by BSD library. We have no init to do.
9846#[ no_mangle]
99- pub extern "C" fn nrf_modem_os_init ( ) {
47+ pub extern "C" fn bsd_os_init ( ) {
10048 // Nothing
10149}
10250
10351/// Function required by BSD library. Stores an error code we can read later.
10452#[ no_mangle]
105- pub extern "C" fn nrf_modem_os_errno_set ( errno : i32 ) {
53+ pub extern "C" fn bsd_os_errno_set ( errno : i32 ) {
10654 LAST_ERROR . store ( errno, core:: sync:: atomic:: Ordering :: SeqCst ) ;
10755}
10856
@@ -113,7 +61,7 @@ pub fn get_last_error() -> i32 {
11361
11462/// Function required by BSD library
11563#[ no_mangle]
116- pub extern "C" fn nrf_modem_os_timedwait ( _context : u32 , p_timeout_ms : * const i32 ) -> i32 {
64+ pub extern "C" fn bsd_os_timedwait ( _context : u32 , p_timeout_ms : * const i32 ) -> i32 {
11765 let timeout_ms = unsafe { * p_timeout_ms } ;
11866 if timeout_ms < 0 {
11967 // With Zephyr, negative timeouts pend on a semaphore with K_FOREVER.
@@ -128,189 +76,13 @@ pub extern "C" fn nrf_modem_os_timedwait(_context: u32, p_timeout_ms: *const i32
12876
12977/// Function required by BSD library
13078#[ no_mangle]
131- pub extern "C" fn nrf_modem_os_trace_put ( _data : * const u8 , _len : u32 ) -> i32 {
79+ pub extern "C" fn bsd_os_trace_put ( _data : * const u8 , _len : u32 ) -> i32 {
13280 // Do nothing
13381 0
13482}
13583
13684/// Function required by BSD library
13785#[ no_mangle]
138- pub extern "C" fn nrf_modem_irrecoverable_error_handler ( err : u32 ) -> ! {
86+ pub extern "C" fn bsd_irrecoverable_error_handler ( err : u32 ) -> ! {
13987 panic ! ( "bsd_irrecoverable_error_handler({})" , err) ;
14088}
141-
142- /// The Modem library needs to dynamically allocate memory (a heap) for proper
143- /// functioning. This memory is used to store the internal data structures that
144- /// are used to manage the communication between the application core and the
145- /// modem core. This memory is never shared with the modem core and hence, it
146- /// can be located anywhere in the application core's RAM instead of the shared
147- /// memory regions. This function allocates dynamic memory for the library.
148- #[ no_mangle]
149- pub extern "C" fn nrf_modem_os_alloc ( num_bytes_requested : usize ) -> * mut u8 {
150- unsafe { generic_alloc ( num_bytes_requested, & crate :: LIBRARY_ALLOCATOR ) }
151- }
152-
153- /// The Modem library needs to dynamically allocate memory (a heap) for proper
154- /// functioning. This memory is used to store the internal data structures that
155- /// are used to manage the communication between the application core and the
156- /// modem core. This memory is never shared with the modem core and hence, it
157- /// can be located anywhere in the application core's RAM instead of the shared
158- /// memory regions. This function allocates dynamic memory for the library.
159- #[ no_mangle]
160- pub extern "C" fn nrf_modem_os_free ( ptr : * mut u8 ) {
161- unsafe {
162- generic_free ( ptr, & crate :: LIBRARY_ALLOCATOR ) ;
163- }
164- }
165-
166- /// Allocate a buffer on the TX area of shared memory.
167- ///
168- /// @param bytes Buffer size.
169- /// @return pointer to allocated memory
170- #[ no_mangle]
171- pub extern "C" fn nrf_modem_os_shm_tx_alloc ( num_bytes_requested : usize ) -> * mut u8 {
172- unsafe { generic_alloc ( num_bytes_requested, & crate :: TX_ALLOCATOR ) }
173- }
174-
175- /// Free a shared memory buffer in the TX area.
176- ///
177- /// @param ptr Th buffer to free.
178- #[ no_mangle]
179- pub extern "C" fn nrf_modem_os_shm_tx_free ( ptr : * mut u8 ) {
180- unsafe {
181- generic_free ( ptr, & crate :: TX_ALLOCATOR ) ;
182- }
183- }
184-
185- /// @brief Function for loading configuration directly into IPC peripheral.
186- ///
187- /// @param p_config Pointer to the structure with the initial configuration.
188- #[ no_mangle]
189- pub extern "C" fn nrfx_ipc_config_load ( p_config : * const NrfxIpcConfig ) {
190- unsafe {
191- let config: & NrfxIpcConfig = & * p_config;
192- debug ! ( "nrfx_ipc_config_load({:?})" , config) ;
193-
194- let ipc = & ( * nrf9160_pac:: IPC_NS :: ptr ( ) ) ;
195-
196- for ( i, value) in config. send_task_config . iter ( ) . enumerate ( ) {
197- ipc. send_cnf [ i as usize ] . write ( |w| w. bits ( * value) ) ;
198- }
199-
200- for ( i, value) in config. receive_event_config . iter ( ) . enumerate ( ) {
201- ipc. receive_cnf [ i as usize ] . write ( |w| w. bits ( * value) ) ;
202- }
203-
204- ipc. intenset
205- . write ( |w| w. bits ( config. receive_events_enabled ) ) ;
206- }
207- }
208-
209- ///
210- /// @brief Function for initializing the IPC driver.
211- ///
212- /// @param irq_priority Interrupt priority.
213- /// @param handler Event handler provided by the user. Cannot be NULL.
214- /// @param p_context Context passed to event handler.
215- ///
216- /// @retval NRFX_SUCCESS Initialization was successful.
217- /// @retval NRFX_ERROR_INVALID_STATE Driver is already initialized.
218- #[ no_mangle]
219- pub extern "C" fn nrfx_ipc_init (
220- irq_priority : u8 ,
221- handler : NrfxIpcHandler ,
222- p_context : usize ,
223- ) -> NrfxErr {
224- use cortex_m:: interrupt:: InterruptNumber ;
225- let irq = nrf9160_pac:: Interrupt :: IPC ;
226- let irq_num = usize:: from ( irq. number ( ) ) ;
227- unsafe {
228- cortex_m:: peripheral:: NVIC :: unmask ( irq) ;
229- ( * cortex_m:: peripheral:: NVIC :: ptr ( ) ) . ipr [ irq_num] . write ( irq_priority) ;
230- }
231- IPC_CONTEXT . store ( p_context, core:: sync:: atomic:: Ordering :: SeqCst ) ;
232- IPC_HANDLER . store ( handler as usize , core:: sync:: atomic:: Ordering :: SeqCst ) ;
233- // Report success
234- NrfxErr :: Success
235- }
236-
237- /// Function for uninitializing the IPC module.
238- #[ no_mangle]
239- pub extern "C" fn nrfx_ipc_uninit ( ) {
240- unimplemented ! ( ) ;
241- }
242-
243- /// Allocate some memory from the given heap.
244- ///
245- /// We allocate four extra bytes so that we can store the number of bytes
246- /// requested. This will be needed later when the memory is freed.
247- ///
248- /// This function is safe to call from an ISR.
249- unsafe fn generic_alloc ( num_bytes_requested : usize , heap : & crate :: WrappedHeap ) -> * mut u8 {
250- let sizeof_usize = core:: mem:: size_of :: < usize > ( ) ;
251- let mut result = core:: ptr:: null_mut ( ) ;
252- cortex_m:: interrupt:: free ( |cs| {
253- let num_bytes_allocated = num_bytes_requested + sizeof_usize;
254- let layout =
255- core:: alloc:: Layout :: from_size_align_unchecked ( num_bytes_allocated, sizeof_usize) ;
256- if let Some ( ref mut inner_alloc) = * heap. borrow ( cs) . borrow_mut ( ) {
257- match inner_alloc. allocate_first_fit ( layout) {
258- Ok ( real_block) => {
259- let real_ptr = real_block. as_ptr ( ) ;
260- // We need the block size to run the de-allocation. Store it in the first four bytes.
261- core:: ptr:: write_volatile :: < usize > ( real_ptr as * mut usize , num_bytes_allocated) ;
262- // Give them the rest of the block
263- result = real_ptr. add ( sizeof_usize) ;
264- }
265- Err ( _e) => {
266- // Ignore
267- }
268- }
269- }
270- } ) ;
271- result
272- }
273-
274- /// Free some memory back on to the given heap.
275- ///
276- /// First we must wind the pointer back four bytes to recover the `usize` we
277- /// stashed during the allocation. We use this to recreate the `Layout` required
278- /// for the `deallocate` function.
279- ///
280- /// This function is safe to call from an ISR.
281- unsafe fn generic_free ( ptr : * mut u8 , heap : & crate :: WrappedHeap ) {
282- let sizeof_usize = core:: mem:: size_of :: < usize > ( ) as isize ;
283- cortex_m:: interrupt:: free ( |cs| {
284- // Fetch the size from the previous four bytes
285- let real_ptr = ptr. offset ( -sizeof_usize) ;
286- let num_bytes_allocated = core:: ptr:: read_volatile :: < usize > ( real_ptr as * const usize ) ;
287- let layout = core:: alloc:: Layout :: from_size_align_unchecked (
288- num_bytes_allocated,
289- sizeof_usize as usize ,
290- ) ;
291- if let Some ( ref mut inner_alloc) = * heap. borrow ( cs) . borrow_mut ( ) {
292- inner_alloc. deallocate ( core:: ptr:: NonNull :: new_unchecked ( real_ptr) , layout) ;
293- }
294- } ) ;
295- }
296-
297- /// Call this when we have an IPC IRQ. Not `extern C` as its not called by the
298- /// library, only our interrupt handler code.
299- pub unsafe fn ipc_irq_handler ( ) {
300- // Get the information about events that fired this interrupt
301- let events_map = ( * nrf9160_pac:: IPC_NS :: ptr ( ) ) . intpend . read ( ) . bits ( ) as u32 ;
302-
303- // Clear these events
304- let mut bitmask = events_map;
305- while bitmask != 0 {
306- let event_idx = bitmask. trailing_zeros ( ) ;
307- bitmask ^= 1 << event_idx;
308- ( * nrf9160_pac:: IPC_NS :: ptr ( ) ) . events_receive [ event_idx as usize ] . write ( |w| w. bits ( 0 ) ) ;
309- }
310-
311- // Execute interrupt handler to provide information about events to app
312- let handler_addr = IPC_HANDLER . load ( core:: sync:: atomic:: Ordering :: SeqCst ) ;
313- let handler = core:: mem:: transmute :: < usize , NrfxIpcHandler > ( handler_addr) ;
314- let context = IPC_CONTEXT . load ( core:: sync:: atomic:: Ordering :: SeqCst ) ;
315- ( handler) ( events_map, context as * mut u8 ) ;
316- }
0 commit comments