sp500/dsp.h File Reference#
|
Mobilint REGULUS v4.1
SP500 DSP API
|
Mobilint SP500 DSP offload - status codes, lifecycle and shared memory. More...
#include <stdint.h>#include <stddef.h>Go to the source code of this file.
Data Structures | |
| struct | sp500_buffer |
| A tensor handed to or received from the DSP. More... | |
Macros | |
| #define | SP500_VERSION_MAJOR 1 |
| #define | SP500_VERSION_MINOR 0 |
| #define | SP500_VERSION_PATCH 0 |
| #define | SP500_VERSION_INT |
| Header version as one integer: major*10000 + minor*100 + patch. | |
| #define | SP500_API |
| #define | SP500_INLINE static inline |
| #define | SP500_DEFAULT_OPEN_TIMEOUT_MS 10000u |
| Default deadline for sp500_dsp_open(), in milliseconds. | |
| #define | SP500_DEFAULT_DSP_TIMEOUT_MS 3000u |
| Default deadline for a single DSP call, in milliseconds. | |
| #define | SP500_ALIGN_DSP 32u |
| Smallest alignment the DSP accepts. | |
| #define | SP500_ALIGN_NPU 4096u |
| Alignment to use for a buffer that the NPU also reads or writes. | |
Typedefs | |
| typedef int32_t | sp500_status |
| Result of every sp500 call. | |
Enumerations | |
| enum | { SP500_OK = 0 , SP500_ERR_INVALID_ARG = -1 , SP500_ERR_UNSUPPORTED = -2 , SP500_ERR_BUFFER_TOO_SMALL = -3 , SP500_ERR_NOT_READY = -4 , SP500_ERR_NO_MEMORY = -5 , SP500_ERR_TIMEOUT = -6 , SP500_ERR_DSP = -7 , SP500_ERR_INTERNAL = -8 } |
| enum | { SP500_BUFFER_SHARED = 1u << 0 } |
| sp500_buffer::flags bits. More... | |
Functions | |
| const char * | sp500_status_string (sp500_status status) |
| Human-readable name of a status code. Never NULL, never allocates. | |
| uint32_t | sp500_version (void) |
| Version of the loaded library, encoded like SP500_VERSION_INT. | |
| const char * | sp500_version_string (void) |
| Version of the loaded library as "major.minor.patch". Never NULL. | |
| sp500_status | sp500_dsp_open (uint32_t timeout_ms) |
| Attach to the DSP. Must succeed before any other DSP call. | |
| int | sp500_dsp_is_open (void) |
| Non-blocking: 1 once sp500_dsp_open() has succeeded, 0 otherwise. | |
| void | sp500_set_dsp_timeout_ms (uint32_t timeout_ms) |
| Raise the deadline applied to every subsequent DSP call. | |
| uint32_t | sp500_get_dsp_timeout_ms (void) |
| Deadline currently in force, in milliseconds, after clamping. | |
| void | sp500_dsp_lock (void) |
| Take the one reentrant DSP lock, across threads and across processes. | |
| void | sp500_dsp_unlock (void) |
| Release one level of the lock taken by sp500_dsp_lock(). | |
| void * | sp500_shmem_alloc (uint32_t size, uint32_t alignment) |
| Allocate inside the DSP shared-memory window. | |
| void | sp500_shmem_free (void *ptr) |
| Release a buffer from sp500_shmem_alloc(). NULL is ignored. | |
| int | sp500_shmem_contains (const void *ptr) |
1 when ptr lies inside the shared-memory window, 0 otherwise. | |
| uint64_t | sp500_shmem_phys_addr (const void *ptr) |
| Physical address of a shared-memory pointer, for NPU DMA. | |
| sp500_buffer | sp500_buffer_none (void) |
| An unused buffer, for an optional tensor. | |
| sp500_buffer | sp500_buffer_alloc (uint32_t size, uint32_t alignment) |
| Allocate a zero-copy buffer in shared memory. | |
| sp500_buffer | sp500_buffer_wrap (void *data, uint32_t size) |
| Wrap memory you already own. The call stages one copy in each direction; nothing is taken over and nothing needs freeing. | |
| void | sp500_buffer_release (sp500_buffer *buffer) |
| Release a buffer and reset it to unused. | |
Detailed Description
Mobilint SP500 DSP offload - status codes, lifecycle and shared memory.
This is the foundation header. sp500/letterbox.h, sp500/log_mel.h and sp500/yolo.h all include it; include the module headers you need.
The only dependencies are <stdint.h> and <stddef.h>. No C++ standard library, no OpenCV, no vendor SDK header, no using directive, and no macro that is not prefixed SP500_.
- The binary interface
- Everything inside the extern "C" block is the ABI of the shared library:
- Every function returns sp500_status (an int32_t) or a fixed-width scalar. Enumerations name constants only; what crosses the boundary is int32_t or uint32_t, never an enum type whose width is implementation defined.
- No struct is passed or returned by value across the boundary. Pointers only.
- Every struct ends with a reserved array. It must be zero. A later library version may give those words a meaning whose zero value is today's behaviour.
- Always fill a parameter struct with its *_params_init() function before setting fields. The defaults are not all zero, and a struct you only zeroed carries none of them. An all-zero struct is always rejected, because the fields documented as required are invalid at zero - but if you zero a struct and then set exactly those required fields, the call runs with every remaining option at zero rather than at its default. Initialise first.
- Nothing throws. Every entry point is an exception firewall.
- Threading
- Every entry point may be called concurrently from several threads and several processes. A DSP call serialises itself against every other DSP call and every shared-memory allocation, system wide, for the duration of the round trip. Use sp500_dsp_lock() only when a multi-call sequence must be atomic as a whole.
- Buffers
- Every tensor is a sp500_buffer. A buffer from sp500_buffer_alloc() lives in the shared-memory window the DSP reads directly, so it costs no copy. A buffer from sp500_buffer_wrap() points at memory you already own and is staged through shared memory, which costs one copy in each direction. Prefer the former for anything large, and for anything you also hand to the NPU.
Definition in file dsp.h.
Macro Definition Documentation
◆ SP500_VERSION_MAJOR
◆ SP500_VERSION_MINOR
◆ SP500_VERSION_PATCH
◆ SP500_VERSION_INT
| #define SP500_VERSION_INT |
◆ SP500_API
◆ SP500_INLINE
◆ SP500_DEFAULT_OPEN_TIMEOUT_MS
| #define SP500_DEFAULT_OPEN_TIMEOUT_MS 10000u |
Default deadline for sp500_dsp_open(), in milliseconds.
◆ SP500_DEFAULT_DSP_TIMEOUT_MS
| #define SP500_DEFAULT_DSP_TIMEOUT_MS 3000u |
◆ SP500_ALIGN_DSP
| #define SP500_ALIGN_DSP 32u |
◆ SP500_ALIGN_NPU
| #define SP500_ALIGN_NPU 4096u |
Typedef Documentation
◆ sp500_status
| typedef int32_t sp500_status |
Result of every sp500 call.
A typedef over int32_t rather than an enum type, so a code introduced by a later library version is never an out-of-range enum value in your build. Zero is success and every error is negative, so both rc != SP500_OK and rc < 0 are correct tests. Treat an unrecognised negative value as a generic failure.
Enumeration Type Documentation
◆ anonymous enum
| anonymous enum |
| Enumerator | ||
|---|---|---|
| SP500_OK | 0 | completed; output buffers are valid |
| SP500_ERR_INVALID_ARG | -1 | a parameter is missing, out of range, or inconsistent with another |
| SP500_ERR_UNSUPPORTED | -2 | this module cannot run that combination |
| SP500_ERR_BUFFER_TOO_SMALL | -3 | a supplied buffer cannot hold the result |
| SP500_ERR_NOT_READY | -4 | sp500_dsp_open() has not succeeded |
| SP500_ERR_NO_MEMORY | -5 | host or shared-memory allocation failed |
| SP500_ERR_TIMEOUT | -6 | the DSP did not answer within the deadline |
| SP500_ERR_DSP | -7 | the DSP reported a failure |
| SP500_ERR_INTERNAL | -8 | unexpected internal condition |
◆ anonymous enum
| anonymous enum |
sp500_buffer::flags bits.
| Enumerator | ||
|---|---|---|
| SP500_BUFFER_SHARED | 1u << 0 | Set by sp500_buffer_alloc(): the memory is inside the shared-memory window, so the DSP reads and writes it in place with no copy. |
Function Documentation
◆ sp500_version()
| uint32_t sp500_version | ( | void | ) |
Version of the loaded library, encoded like SP500_VERSION_INT.
Compare against SP500_VERSION_INT at start-up to catch a header/library mismatch before it becomes a silent misinterpretation of a struct.
◆ sp500_dsp_open()
| sp500_status sp500_dsp_open | ( | uint32_t | timeout_ms | ) |
Attach to the DSP. Must succeed before any other DSP call.
Attaching waits for the DSP-side firmware to register itself, so it blocks until the DSP is up. timeout_ms bounds that wait; pass 0 for SP500_DEFAULT_OPEN_TIMEOUT_MS. Calling it again after success is a cheap no-op, so it is safe to call from every module of an application.
On success the shared-memory window is also mapped, which is what makes sp500_shmem_contains() and sp500_shmem_phys_addr() usable from an NPU setup path that runs before the first DSP call.
- Parameters
-
timeout_ms Deadline in milliseconds, or 0 for the default.
- Returns
- SP500_OK, SP500_ERR_TIMEOUT if the DSP did not register in time, or SP500_ERR_NOT_READY if the link could not be established.
- Note
- A timeout leaves one worker thread parked inside the vendor link layer until the DSP appears. Load the DSP firmware before calling, and treat a timeout as a fatal start-up error rather than something to retry in a loop.
◆ sp500_set_dsp_timeout_ms()
| void sp500_set_dsp_timeout_ms | ( | uint32_t | timeout_ms | ) |
Raise the deadline applied to every subsequent DSP call.
This is a dead-DSP guard, not a latency budget. It must sit comfortably ABOVE the longest operation you submit; the case to check is a long log-mel clip.
A deadline that expires does not cancel anything: the DSP keeps working on buffers the call has already given up on and released, the late completion desynchronises the single-slot channel, and the next call can return the previous call's result. Recovering from that needs a DSP reload. Because of that, the deadline can only be raised - a value below SP500_DEFAULT_DSP_TIMEOUT_MS is clamped up to it, and sp500_get_dsp_timeout_ms() reports what actually took effect.
- Parameters
-
timeout_ms Deadline in milliseconds; 0 restores SP500_DEFAULT_DSP_TIMEOUT_MS, and anything below it is clamped up to it.
◆ sp500_dsp_lock()
| void sp500_dsp_lock | ( | void | ) |
Take the one reentrant DSP lock, across threads and across processes.
Individual calls already lock themselves, so this is only needed to make a multi-step sequence atomic against other threads and other processes - for example allocate, letterbox, read, free. The lock is reentrant, so the per-call lock simply nests inside it.
Every sp500_dsp_lock() must be paired with exactly one sp500_dsp_unlock(). An unbalanced lock stalls the DSP and the shared-memory allocator for every process on the system.
◆ sp500_shmem_alloc()
| void * sp500_shmem_alloc | ( | uint32_t | size, |
| uint32_t | alignment ) |
Allocate inside the DSP shared-memory window.
- Parameters
-
size Bytes to allocate. alignment Byte alignment; must be at least SP500_ALIGN_DSP. Use SP500_ALIGN_NPU for buffers the NPU also touches.
- Returns
- Pointer to the buffer, or NULL if the window is exhausted or the DSP is not open. Release it with sp500_shmem_free().
- Note
- The window is served by a first-fit allocator with no compaction. Freeing does reclaim, in any order, and the freed span rejoins its neighbors - but allocating and freeing buffers of mixed lifetimes every frame fragments the pool. It then carries roughly a quarter more than your live bytes, and a large request can be refused while smaller gaps go unused. Allocate your working set once and reuse it.
- Never hold a shared-memory buffer in a global or static object. It would be released after the link has already been torn down.
◆ sp500_shmem_contains()
| int sp500_shmem_contains | ( | const void * | ptr | ) |
1 when ptr lies inside the shared-memory window, 0 otherwise.
Interior pointers count, so this also answers "is this row of my image in shared memory". Never blocks; returns 0 until sp500_dsp_open() has succeeded.
◆ sp500_shmem_phys_addr()
| uint64_t sp500_shmem_phys_addr | ( | const void * | ptr | ) |
Physical address of a shared-memory pointer, for NPU DMA.
The window is physically contiguous, so any pointer inside it maps to a fixed physical base plus its offset. Hand the result to the NPU runtime to let it read and write the same buffer the DSP uses, with no copy in between.
- Returns
- The physical address, or 0 if
ptris not inside the window (including before sp500_dsp_open() has succeeded).
◆ sp500_buffer_none()
| sp500_buffer sp500_buffer_none | ( | void | ) |
◆ sp500_buffer_alloc()
| sp500_buffer sp500_buffer_alloc | ( | uint32_t | size, |
| uint32_t | alignment ) |
Allocate a zero-copy buffer in shared memory.
- Parameters
-
size Bytes to allocate. alignment Byte alignment; at least SP500_ALIGN_DSP.
- Returns
- The buffer, or an unused buffer (data == NULL) if the window is exhausted. Release it with sp500_buffer_release().
◆ sp500_buffer_wrap()
| sp500_buffer sp500_buffer_wrap | ( | void * | data, |
| uint32_t | size ) |
◆ sp500_buffer_release()
| void sp500_buffer_release | ( | sp500_buffer * | buffer | ) |
Release a buffer and reset it to unused.
Frees the shared-memory allocation of a buffer from sp500_buffer_alloc(); does nothing to a wrapped buffer beyond clearing the handle.
Generated by