These functions are required to be implemented by the user for the target platform. See this porting guide for more information. They are declared internally in the Edge Impulse C++ SDK library, and they must be defined by the user.
Source: porting/ei_classifier_porting.h
Examples: The following examples demonstrate possible implementations of this function for various platforms. Note the __attribute__((weak))
in most of the definitions, which means that a user could override the implementation elsewhere in the program:
Brief: Cancellable sleep, can be triggered with signal from other thread.
Description: Cancelable sleep, can be triggered with signal from other thread Allow the processor or thread to sleep or block for the given time.
time_ms
Time in milliseconds to sleep
EI_IMPULSE_OK
if successful, error code otherwise
Brief: Read the millisecond timer.
Description: Read the millisecond timer This function should return the number of milliseconds that have passed since the start of the program. If you do not need to determine the run times for DSP and inference blocks, you can simply return 0 from this function. Your impulse will still work correctly without timing information.
The number of milliseconds that have passed since the start of the program
Brief: Read the microsecond timer.
Description: This function should return the number of milliseconds that have passed since the start of the program. If you do not need to determine the run times for DSP and inference blocks, you can simply return 0 from this function. Your impulse will still work correctly without timing information.
The number of microseconds that have passed since the start of the program
Brief: Send a single character to the serial port.
Description:
c
The chararater to send
Brief: Read a single character from the serial port.
Description:
The character read from the serial port
Brief: Print wrapper around printf()
Description:
ei_printf()
is declared internally to the Edge Impulse SDK library so that debugging information (e.g. during inference) can be printed out. However, the function must be defined by the user, as printing methods can change depending on the platform and use case. For example, you may want to print debugging information to stdout in Linux or over a UART serial port on a microcontroller.
format
Pointer to a character array or string that should be printed
...
Other optional arguments may be passed as necessary (e.g. handle to a UART object). Note that any calls to ei_printf()
from within the edge-impulse-sdk library do not pass anything other than the format
argument.
Brief: Used to print floating point numbers.
Description:
Some platforms cannot handle directly printing floating point numbers (e.g. to a console or over a serial port). If your platform cannot directly print floats, provide an implementation of this function to print them as needed (for example, construct a string containing scientific notation with integers and call ei_printf()
).
If your platform can print floating point values, the easiest implementation of this function is as follows:
attribute((weak)) void ei_printf_float(float f) { printf("%f", f); }
f
The floating point number to print
Brief: Wrapper around malloc.
Description:
This function should allocate size
bytes and return a pointer to the allocated memory. In bare-metal implementations, it can simply be a wrapper for malloc()
. For example:
attribute((weak)) void *ei_malloc(size_t size) { return malloc(size); }
If you intend to run your impulse in a multi-threaded environment, you will need to ensure that your implementation of ei_malloc()
is thread-safe. For example, if you are using FreeRTOS, here is one possible implementation:
attribute((weak)) void *ei_malloc(size_t size) { return pvPortMalloc(size); }
size
The number of bytes to allocate
Brief: Wrapper around calloc.
Description:
This function should allocate nitems * size
bytes and initialize all bytes in this allocated memory to 0. It should return a pointer to the allocated memory. In bare-metal implementations, it can simply be a wrapper for calloc()
. For example:
attribute((weak)) void *ei_calloc(size_t nitems, size_t size) { return calloc(nitems, size); }
If you intend to run your impulse in a multi-threaded environment, you will need to ensure that your implementation of ei_calloc()
is thread-safe. For example, if you are using FreeRTOS, here is one possible implementation:
attribute((weak)) void *ei_calloc(size_t nitems, size_t size) { void *ptr = NULL; if (size > 0) { ptr = pvPortMalloc(nitems * size); if(ptr) memset(ptr, 0, (nitems * size)); } return ptr; }
nitems
Number of blocks to allocate and clear
size
Size (in bytes) of each block
Brief: Wrapper around free.
Description:
This function should free the memory space pointed to by ptr
. If ptr
is NULL
, no operation should be performed. In bare-metal implementations, it can simply be a wrapper for free()
. For example:
attribute((weak)) void ei_free(void *ptr) { free(ptr); }
If you intend to run your impulse in a multi-threaded environment, you will need to ensure that your implementation of ei_free()
is thread-safe. For example, if you are using FreeRTOS, here is one possible implementation:
attribute((weak)) void ei_free(void *ptr) { pvPortFree(ptr); }
ptr
Pointer to the memory to free