| /* The Clear BSD License | |
| * | |
| * Copyright (c) 2025 EdgeImpulse Inc. | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted (subject to the limitations in the disclaimer | |
| * below) provided that the following conditions are met: | |
| * | |
| * * Redistributions of source code must retain the above copyright notice, | |
| * this list of conditions and the following disclaimer. | |
| * | |
| * * Redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution. | |
| * | |
| * * Neither the name of the copyright holder nor the names of its | |
| * contributors may be used to endorse or promote products derived from this | |
| * software without specific prior written permission. | |
| * | |
| * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY | |
| * THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |
| * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
| * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR | |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | |
| * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| * POSSIBILITY OF SUCH DAMAGE. | |
| */ | |
| extern "C" { | |
| /* Private functions ------------------------------------------------------- */ | |
| EI_IMPULSE_ERROR ei_run_impulse_check_canceled(); | |
| void ei_serial_set_baudrate(int baudrate); | |
| /* Public functions -------------------------------------------------------- */ | |
| /** | |
| * @defgroup ei_user_functions User-defined functions | |
| * | |
| * These functions are required to be implemented by the user for the target platform. | |
| * See [this porting guide](https://docs.edgeimpulse.com/docs/edge-ai-hardware/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](https://github.com/edgeimpulse/inferencing-sdk-cpp/blob/master/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: | |
| * * [Arduino classifier porting](https://github.com/edgeimpulse/inferencing-sdk-cpp/blob/master/porting/arduino/ei_classifier_porting.cpp) | |
| * * [mbed classifier porting](https://github.com/edgeimpulse/inferencing-sdk-cpp/blob/master/porting/mbed/ei_classifier_porting.cpp) | |
| * * [POSIX classifier porting](https://github.com/edgeimpulse/inferencing-sdk-cpp/blob/master/porting/posix/ei_classifier_porting.cpp) | |
| * * [Silicon Labs classifier porting](https://github.com/edgeimpulse/inferencing-sdk-cpp/blob/master/porting/silabs/ei_classifier_porting.cpp) | |
| * * [STM32 classifier porting](https://github.com/edgeimpulse/inferencing-sdk-cpp/blob/master/porting/stm32-cubeai/ei_classifier_porting.cpp) | |
| * * [TI classifier porting](https://github.com/edgeimpulse/inferencing-sdk-cpp/blob/master/porting/ti/debug_log.cpp) | |
| * * [Zephyr classifier porting](https://github.com/edgeimpulse/inferencing-sdk-cpp/blob/master/porting/zephyr/ei_classifier_porting.cpp) | |
| * | |
| * @addtogroup ei_user_functions | |
| * @{ | |
| */ | |
| /** | |
| * Cancelable sleep, can be triggered with signal from other thread | |
| */ | |
| /** | |
| * @brief Cancellable sleep, can be triggered with signal from other thread | |
| * | |
| * Allow the processor or thread to sleep or block for the given time. | |
| * | |
| * @param[in] time_ms Time in milliseconds to sleep | |
| * | |
| * @return `EI_IMPULSE_OK` if successful, error code otherwise | |
| */ | |
| EI_IMPULSE_ERROR ei_sleep(int32_t time_ms); | |
| /** | |
| * Read the millisecond timer | |
| */ | |
| /** | |
| * @brief 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. | |
| * | |
| * @return The number of milliseconds that have passed since the start of the program | |
| */ | |
| uint64_t ei_read_timer_ms(); | |
| /** | |
| * @brief Read the microsecond 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. | |
| * | |
| * @return The number of microseconds that have passed since the start of the program | |
| */ | |
| uint64_t ei_read_timer_us(); | |
| /** | |
| * @brief Send a single character to the serial port | |
| * | |
| * @param[in] c The chararater to send | |
| */ | |
| void ei_putchar(char c); | |
| /** | |
| * @brief Read a single character from the serial port | |
| * | |
| * @return The character read from the serial port | |
| */ | |
| char ei_getchar(void); | |
| /** | |
| * @brief Print wrapper around printf() | |
| * | |
| * `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. | |
| * | |
| * @param[in] format Pointer to a character array or string that should be printed | |
| * @param[in] ... 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. | |
| */ | |
| __attribute__ ((format (printf, 1, 2))) | |
| void ei_printf(const char *format, ...); | |
| /** | |
| * @brief Used to print floating point numbers | |
| * | |
| * 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); | |
| * } | |
| * ``` | |
| * | |
| * @param[in] f The floating point number to print | |
| */ | |
| void ei_printf_float(float f); | |
| /** | |
| * @brief Wrapper around malloc | |
| * | |
| * 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); | |
| * } | |
| * ``` | |
| * | |
| * @param[in] size The number of bytes to allocate | |
| */ | |
| void *ei_malloc(size_t size); | |
| /** | |
| * @brief Wrapper around calloc | |
| * | |
| * 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; | |
| * } | |
| * ``` | |
| * | |
| * @param[in] nitems Number of blocks to allocate and clear | |
| * @param[in] size Size (in bytes) of each block | |
| */ | |
| void *ei_calloc(size_t nitems, size_t size); | |
| /** | |
| * @brief Wrapper around free | |
| * | |
| * 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); | |
| * } | |
| * ``` | |
| * | |
| * @param[in] ptr Pointer to the memory to free | |
| */ | |
| void ei_free(void *ptr); | |
| /** @} */ | |
| } | |
| // Load porting layer depending on target | |
| // First check if any of the general frameworks or operating systems are supported/enabled | |
| // Then check for target spcific build systems | |
| // End load porting layer depending on target | |
| // Additional configuration for specific architecture for Armv8.1-M architecture ie CM55 and CM85 | |
| // End additional configuration | |