Преглед изворни кода

[FL-1910, FL-2146] Update to new FreeRTOS, fix CMSIS thread flags collision with stream buffer. New cube. (#917)

* Libs: add FreeRTOS submodule. FuriHal: replace ST provided FreeRTOS with original one. FuriHal: for cmsis os hal and patch it for better compatibility with stream buffer.
* Makefile: fix svd plugin on blackmagic
* Lib: update STM32CubeWB package. Project: update project to match new cube package.
* Lib: properly rebase and upload STM32CubeWB
* BleGlue: switch ack logging level to trace
あく пре 4 година
родитељ
комит
439fb9c18d
39 измењених фајлова са 4317 додато и 358 уклоњено
  1. 3 0
      .gitmodules
  2. 1 1
      Makefile
  3. 1 1
      applications/debug_tools/usb_test.c
  4. 3 2
      applications/rpc/rpc.c
  5. 2 1
      applications/rpc/rpc.h
  6. 1 1
      applications/subghz/views/subghz_test_carrier.c
  7. 2 2
      applications/subghz/views/subghz_test_packet.c
  8. 74 127
      firmware/targets/f6/Inc/FreeRTOSConfig.h
  9. 0 21
      firmware/targets/f6/Src/freertos-openocd.c
  10. 0 1
      firmware/targets/f6/ble-glue/ble_app.c
  11. 0 1
      firmware/targets/f6/ble-glue/ble_glue.c
  12. 2 3
      firmware/targets/f6/ble-glue/gap.c
  13. 1 1
      firmware/targets/f6/ble-glue/serial_service.c
  14. 0 1
      firmware/targets/f6/fatfs/ffconf.h
  15. 2 2
      firmware/targets/f6/furi-hal/furi-hal-os.c
  16. 0 1
      firmware/targets/f6/furi-hal/furi-hal-task.c
  17. 12 11
      firmware/targets/f6/target.mk
  18. 74 127
      firmware/targets/f7/Inc/FreeRTOSConfig.h
  19. 0 21
      firmware/targets/f7/Src/freertos-openocd.c
  20. 0 1
      firmware/targets/f7/ble-glue/ble_app.c
  21. 0 1
      firmware/targets/f7/ble-glue/ble_glue.c
  22. 2 3
      firmware/targets/f7/ble-glue/gap.c
  23. 1 1
      firmware/targets/f7/ble-glue/serial_service.c
  24. 0 1
      firmware/targets/f7/fatfs/ffconf.h
  25. 2 2
      firmware/targets/f7/furi-hal/furi-hal-os.c
  26. 0 1
      firmware/targets/f7/furi-hal/furi-hal-task.c
  27. 12 11
      firmware/targets/f7/target.mk
  28. 1 0
      lib/FreeRTOS-Kernel
  29. 2873 0
      lib/FreeRTOS-glue/cmsis_os2.c
  30. 756 0
      lib/FreeRTOS-glue/cmsis_os2.h
  31. 63 0
      lib/FreeRTOS-glue/freertos_mpool.h
  32. 336 0
      lib/FreeRTOS-glue/freertos_os2.h
  33. 80 0
      lib/FreeRTOS-glue/os_tick.h
  34. 1 1
      lib/ST25RFAL002/platform.c
  35. 1 1
      lib/STM32CubeWB
  36. 2 2
      lib/lib.mk
  37. 2 1
      make/rules.mk
  38. 5 5
      scripts/flipper/copro.py
  39. 2 2
      scripts/ob.data

+ 3 - 0
.gitmodules

@@ -16,3 +16,6 @@
 [submodule "lib/libusb_stm32"]
 [submodule "lib/libusb_stm32"]
 	path = lib/libusb_stm32
 	path = lib/libusb_stm32
 	url = https://github.com/flipperdevices/libusb_stm32.git
 	url = https://github.com/flipperdevices/libusb_stm32.git
+[submodule "lib/FreeRTOS-Kernel"]
+	path = lib/FreeRTOS-Kernel
+	url = https://github.com/FreeRTOS/FreeRTOS-Kernel.git

+ 1 - 1
Makefile

@@ -71,7 +71,7 @@ endif
 
 
 .PHONY: flash_radio
 .PHONY: flash_radio
 flash_radio:
 flash_radio:
-	@$(PROJECT_ROOT)/scripts/flash.py core2radio 0x080CA000 $(COPRO_DIR)/stm32wb5x_BLE_Stack_full_fw.bin
+	@$(PROJECT_ROOT)/scripts/flash.py core2radio 0x080C7000 $(COPRO_DIR)/stm32wb5x_BLE_Stack_full_fw.bin
 	@$(PROJECT_ROOT)/scripts/ob.py set
 	@$(PROJECT_ROOT)/scripts/ob.py set
 
 
 .PHONY: flash_radio_fus
 .PHONY: flash_radio_fus

+ 1 - 1
applications/debug_tools/usb_test.c

@@ -1,10 +1,10 @@
 #include <furi.h>
 #include <furi.h>
 #include <furi-hal.h>
 #include <furi-hal.h>
+
 #include <gui/view.h>
 #include <gui/view.h>
 #include <gui/view_dispatcher.h>
 #include <gui/view_dispatcher.h>
 #include <gui/modules/submenu.h>
 #include <gui/modules/submenu.h>
 #include <gui/gui.h>
 #include <gui/gui.h>
-#include <cmsis_os.h>
 
 
 typedef struct {
 typedef struct {
     Gui* gui;
     Gui* gui;

+ 3 - 2
applications/rpc/rpc.c

@@ -1,13 +1,14 @@
 #include "rpc_i.h"
 #include "rpc_i.h"
+
 #include <pb.h>
 #include <pb.h>
 #include <pb_decode.h>
 #include <pb_decode.h>
 #include <pb_encode.h>
 #include <pb_encode.h>
+
 #include <status.pb.h>
 #include <status.pb.h>
 #include <storage.pb.h>
 #include <storage.pb.h>
 #include <flipper.pb.h>
 #include <flipper.pb.h>
-#include <cmsis_os.h>
-#include <cmsis_os2.h>
 #include <portmacro.h>
 #include <portmacro.h>
+
 #include <furi.h>
 #include <furi.h>
 
 
 #include <cli/cli.h>
 #include <cli/cli.h>

+ 2 - 1
applications/rpc/rpc.h

@@ -1,8 +1,9 @@
 #pragma once
 #pragma once
+
 #include <stddef.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdbool.h>
-#include "cmsis_os.h"
+#include <furi.h>
 
 
 #define RPC_BUFFER_SIZE (1024)
 #define RPC_BUFFER_SIZE (1024)
 #define RPC_MAX_MESSAGE_SIZE (1536)
 #define RPC_MAX_MESSAGE_SIZE (1536)

+ 1 - 1
applications/subghz/views/subghz_test_carrier.c

@@ -8,7 +8,7 @@
 
 
 struct SubghzTestCarrier {
 struct SubghzTestCarrier {
     View* view;
     View* view;
-    osTimerId timer;
+    osTimerId_t timer;
     SubghzTestCarrierCallback callback;
     SubghzTestCarrierCallback callback;
     void* context;
     void* context;
 };
 };

+ 2 - 2
applications/subghz/views/subghz_test_packet.c

@@ -12,7 +12,7 @@
 
 
 struct SubghzTestPacket {
 struct SubghzTestPacket {
     View* view;
     View* view;
-    osTimerId timer;
+    osTimerId_t timer;
 
 
     SubGhzDecoderPrinceton* decoder;
     SubGhzDecoderPrinceton* decoder;
     SubGhzEncoderPrinceton* encoder;
     SubGhzEncoderPrinceton* encoder;
@@ -262,4 +262,4 @@ void subghz_test_packet_free(SubghzTestPacket* instance) {
 View* subghz_test_packet_get_view(SubghzTestPacket* instance) {
 View* subghz_test_packet_get_view(SubghzTestPacket* instance) {
     furi_assert(instance);
     furi_assert(instance);
     return instance->view;
     return instance->view;
-}
+}

+ 74 - 127
firmware/targets/f6/Inc/FreeRTOSConfig.h

@@ -1,133 +1,89 @@
-/* USER CODE BEGIN Header */
-/*
- * FreeRTOS Kernel V10.2.1
- * Portion Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
- * Portion Copyright (C) 2019 StMicroelectronics, Inc.  All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * http://www.FreeRTOS.org
- * http://aws.amazon.com/freertos
- *
- * 1 tab == 4 spaces!
- */
-/* USER CODE END Header */
-
-#ifndef FREERTOS_CONFIG_H
-#define FREERTOS_CONFIG_H
-
-/*-----------------------------------------------------------
- * Application specific definitions.
- *
- * These definitions should be adjusted for your particular hardware and
- * application requirements.
- *
- * These parameters and more are described within the 'configuration' section of the
- * FreeRTOS API documentation available on the FreeRTOS.org web site.
- *
- * See http://www.freertos.org/a00110.html
- *----------------------------------------------------------*/
-
-/* USER CODE BEGIN Includes */
-/* Section where include file can be added */
-/* USER CODE END Includes */
-
-/* Ensure definitions are only used by the compiler, and not by the assembler. */
+#pragma once
+
 #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
 #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
-  #include <stdint.h>
-  extern uint32_t SystemCoreClock;
+#include <stdint.h>
+extern uint32_t SystemCoreClock;
 #endif
 #endif
+
 #ifndef CMSIS_device_header
 #ifndef CMSIS_device_header
 #define CMSIS_device_header "stm32wbxx.h"
 #define CMSIS_device_header "stm32wbxx.h"
 #endif /* CMSIS_device_header */
 #endif /* CMSIS_device_header */
 
 
-#define configENABLE_FPU                         1
-#define configENABLE_MPU                         0
-
-#define configUSE_PREEMPTION                     1
-#define configSUPPORT_STATIC_ALLOCATION          0
-#define configSUPPORT_DYNAMIC_ALLOCATION         1
-#define configUSE_IDLE_HOOK                      0
-#define configUSE_TICK_HOOK                      0
-#define configCPU_CLOCK_HZ                       ( SystemCoreClock )
-#define configTICK_RATE_HZ                       ((TickType_t)1024)
-#define configMAX_PRIORITIES                     ( 56 )
-#define configMINIMAL_STACK_SIZE                 ((uint16_t)128)
+#define configENABLE_FPU                            1
+#define configENABLE_MPU                            0
+
+#define configUSE_PREEMPTION                        1
+#define configSUPPORT_STATIC_ALLOCATION             0
+#define configSUPPORT_DYNAMIC_ALLOCATION            1
+#define configUSE_IDLE_HOOK                         0
+#define configUSE_TICK_HOOK                         0
+#define configCPU_CLOCK_HZ                          ( SystemCoreClock )
+#define configTICK_RATE_HZ                          ((TickType_t)1024)
+#define configMAX_PRIORITIES                        ( 56 )
+#define configMINIMAL_STACK_SIZE                    ((uint16_t)128)
+
 /* Heap size determined automatically by linker */
 /* Heap size determined automatically by linker */
 // #define configTOTAL_HEAP_SIZE                    ((size_t)0)
 // #define configTOTAL_HEAP_SIZE                    ((size_t)0)
-#define configMAX_TASK_NAME_LEN                  ( 16 )
-#define configGENERATE_RUN_TIME_STATS            0
-#define configUSE_TRACE_FACILITY                 1
-#define configUSE_16_BIT_TICKS                   0
-#define configUSE_MUTEXES                        1
-#define configQUEUE_REGISTRY_SIZE                8
-#define configCHECK_FOR_STACK_OVERFLOW           1
-#define configUSE_RECURSIVE_MUTEXES              1
-#define configUSE_COUNTING_SEMAPHORES            1
-#define configENABLE_BACKWARD_COMPATIBILITY      0
-#define configUSE_PORT_OPTIMISED_TASK_SELECTION  0
-#define configUSE_TICKLESS_IDLE                  2
-#define configRECORD_STACK_HIGH_ADDRESS          1
-#define configUSE_NEWLIB_REENTRANT               0
-/* USER CODE BEGIN MESSAGE_BUFFER_LENGTH_TYPE */
+#define configMAX_TASK_NAME_LEN                     ( 16 )
+#define configGENERATE_RUN_TIME_STATS               0
+#define configUSE_TRACE_FACILITY                    1
+#define configUSE_16_BIT_TICKS                      0
+#define configUSE_MUTEXES                           1
+#define configQUEUE_REGISTRY_SIZE                   8
+#define configCHECK_FOR_STACK_OVERFLOW              1
+#define configUSE_RECURSIVE_MUTEXES                 1
+#define configUSE_COUNTING_SEMAPHORES               1
+#define configENABLE_BACKWARD_COMPATIBILITY         0
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION     0
+#define configUSE_TICKLESS_IDLE                     2
+#define configRECORD_STACK_HIGH_ADDRESS             1
+#define configUSE_NEWLIB_REENTRANT                  0
+
 /* Defaults to size_t for backward compatibility, but can be changed
 /* Defaults to size_t for backward compatibility, but can be changed
    if lengths will always be less than the number of bytes in a size_t. */
    if lengths will always be less than the number of bytes in a size_t. */
-#define configMESSAGE_BUFFER_LENGTH_TYPE         size_t
-#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1
-#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP   8
-/* USER CODE END MESSAGE_BUFFER_LENGTH_TYPE */
+#define configMESSAGE_BUFFER_LENGTH_TYPE            size_t
+#define configNUM_THREAD_LOCAL_STORAGE_POINTERS     1
+#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP       4
 
 
 /* Co-routine definitions. */
 /* Co-routine definitions. */
-#define configUSE_CO_ROUTINES                    0
-#define configMAX_CO_ROUTINE_PRIORITIES          ( 2 )
+#define configUSE_CO_ROUTINES                       0
 
 
 /* Software timer definitions. */
 /* Software timer definitions. */
-#define configUSE_TIMERS                         1
-#define configTIMER_TASK_PRIORITY                ( 2 )
-#define configTIMER_QUEUE_LENGTH                 32
-#define configTIMER_TASK_STACK_DEPTH             256
-#define configTIMER_SERVICE_TASK_NAME          "TimersSrv"
+#define configUSE_TIMERS                            1
+#define configTIMER_TASK_PRIORITY                   ( 2 )
+#define configTIMER_QUEUE_LENGTH                    32
+#define configTIMER_TASK_STACK_DEPTH                256
+#define configTIMER_SERVICE_TASK_NAME               "TimersSrv"
 
 
-#define configIDLE_TASK_NAME                  "(-_-)"
+#define configIDLE_TASK_NAME                        "(-_-)"
 
 
 /* Set the following definitions to 1 to include the API function, or zero
 /* Set the following definitions to 1 to include the API function, or zero
 to exclude the API function. */
 to exclude the API function. */
-#define INCLUDE_eTaskGetState                1
-#define INCLUDE_uxTaskGetStackHighWaterMark  1
-#define INCLUDE_uxTaskPriorityGet            1
-#define INCLUDE_vTaskCleanUpResources        0
-#define INCLUDE_vTaskDelay                   1
-#define INCLUDE_vTaskDelayUntil              1
-#define INCLUDE_vTaskDelete                  1
-#define INCLUDE_vTaskPrioritySet             1
-#define INCLUDE_vTaskSuspend                 1
-#define INCLUDE_xQueueGetMutexHolder         1
-#define INCLUDE_xTaskGetCurrentTaskHandle    1
-#define INCLUDE_xTaskGetSchedulerState       1
-#define INCLUDE_xTimerPendFunctionCall       1
+#define INCLUDE_eTaskGetState                       1
+#define INCLUDE_uxTaskGetStackHighWaterMark         1
+#define INCLUDE_uxTaskPriorityGet                   1
+#define INCLUDE_vTaskCleanUpResources               0
+#define INCLUDE_vTaskDelay                          1
+#define INCLUDE_vTaskDelayUntil                     1
+#define INCLUDE_vTaskDelete                         1
+#define INCLUDE_vTaskPrioritySet                    1
+#define INCLUDE_vTaskSuspend                        1
+#define INCLUDE_xQueueGetMutexHolder                1
+#define INCLUDE_xTaskGetCurrentTaskHandle           1
+#define INCLUDE_xTaskGetSchedulerState              1
+#define INCLUDE_xTimerPendFunctionCall              1
 
 
 /* CMSIS-RTOS V2 flags */
 /* CMSIS-RTOS V2 flags */
-#define configUSE_OS2_THREAD_SUSPEND_RESUME  1
-#define configUSE_OS2_THREAD_ENUMERATE       1
-#define configUSE_OS2_EVENTFLAGS_FROM_ISR    1
-#define configUSE_OS2_THREAD_FLAGS           1
-#define configUSE_OS2_TIMER                  1
-#define configUSE_OS2_MUTEX                  1
+#define configUSE_OS2_THREAD_SUSPEND_RESUME         1
+#define configUSE_OS2_THREAD_ENUMERATE              1
+#define configUSE_OS2_EVENTFLAGS_FROM_ISR           1
+#define configUSE_OS2_THREAD_FLAGS                  1
+#define configUSE_OS2_TIMER                         1
+#define configUSE_OS2_MUTEX                         1
+
+/* CMSIS-RTOS */
+#define configTASK_NOTIFICATION_ARRAY_ENTRIES       2
+#define CMSIS_TASK_NOTIFY_INDEX 1
 
 
 /*
 /*
  * The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
  * The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
@@ -137,15 +93,15 @@ to exclude the API function. */
 
 
 /* Cortex-M specific definitions. */
 /* Cortex-M specific definitions. */
 #ifdef __NVIC_PRIO_BITS
 #ifdef __NVIC_PRIO_BITS
- /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
- #define configPRIO_BITS         __NVIC_PRIO_BITS
+    /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
+    #define configPRIO_BITS                         __NVIC_PRIO_BITS
 #else
 #else
- #define configPRIO_BITS         4
+    #define configPRIO_BITS                         4
 #endif
 #endif
 
 
 /* The lowest interrupt priority that can be used in a call to a "set priority"
 /* The lowest interrupt priority that can be used in a call to a "set priority"
 function. */
 function. */
-#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY     15
 
 
 /* The highest interrupt priority that can be used by any interrupt service
 /* The highest interrupt priority that can be used by any interrupt service
 routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
 routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
@@ -155,29 +111,20 @@ PRIORITY THAN THIS! (higher priorities are lower numeric values. */
 
 
 /* Interrupt priorities used by the kernel port layer itself.  These are generic
 /* Interrupt priorities used by the kernel port layer itself.  These are generic
 to all Cortex-M ports, and do not rely on any particular library functions. */
 to all Cortex-M ports, and do not rely on any particular library functions. */
-#define configKERNEL_INTERRUPT_PRIORITY         ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+#define configKERNEL_INTERRUPT_PRIORITY             ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+
 /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
 /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
 See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
 See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
-#define configMAX_SYSCALL_INTERRUPT_PRIORITY    ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY        ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
 
 
 /* Normal assert() semantics without relying on the provision of an assert.h
 /* Normal assert() semantics without relying on the provision of an assert.h
 header file. */
 header file. */
-/* USER CODE BEGIN 1 */
-#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); asm("bkpt 1"); for( ;; );}
-/* USER CODE END 1 */
+#define configASSERT( x ) if ((x) == 0) { taskDISABLE_INTERRUPTS(); asm("bkpt 1"); for( ;; ); }
 
 
 /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
 /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
 standard names. */
 standard names. */
 #define vPortSVCHandler    SVC_Handler
 #define vPortSVCHandler    SVC_Handler
 #define xPortPendSVHandler PendSV_Handler
 #define xPortPendSVHandler PendSV_Handler
 
 
-/* IMPORTANT: After 10.3.1 update, Systick_Handler comes from NVIC (if SYS timebase = systick), otherwise from cmsis_os2.c */
-
 #define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1
 #define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1
-
-/* USER CODE BEGIN Defines */
-/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
 #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 1  /* required only for Keil but does not hurt otherwise */
 #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 1  /* required only for Keil but does not hurt otherwise */
-/* USER CODE END Defines */
-
-#endif /* FREERTOS_CONFIG_H */

+ 0 - 21
firmware/targets/f6/Src/freertos-openocd.c

@@ -1,21 +0,0 @@
-
-/*
- * Since at least FreeRTOS V7.5.3 uxTopUsedPriority is no longer
- * present in the kernel, so it has to be supplied by other means for
- * OpenOCD's threads awareness.
- *
- * Add this file to your project, and, if you're using --gc-sections,
- * ``--undefined=uxTopUsedPriority'' (or
- * ``-Wl,--undefined=uxTopUsedPriority'' when using gcc for final
- * linking) to your LDFLAGS; same with all the other symbols you need.
- */
-
-#include "FreeRTOS.h"
-
-#ifdef __GNUC__
-#define USED __attribute__((used))
-#else
-#define USED
-#endif
-
-const int USED uxTopUsedPriority = configMAX_PRIORITIES - 1;

+ 0 - 1
firmware/targets/f6/ble-glue/ble_app.c

@@ -3,7 +3,6 @@
 #include "hci_tl.h"
 #include "hci_tl.h"
 #include "ble.h"
 #include "ble.h"
 #include "shci.h"
 #include "shci.h"
-#include "cmsis_os.h"
 #include "gap.h"
 #include "gap.h"
 
 
 #include <furi-hal.h>
 #include <furi-hal.h>

+ 0 - 1
firmware/targets/f6/ble-glue/ble_glue.c

@@ -5,7 +5,6 @@
 #include "ble.h"
 #include "ble.h"
 #include "tl.h"
 #include "tl.h"
 #include "shci.h"
 #include "shci.h"
-#include "cmsis_os.h"
 #include "shci_tl.h"
 #include "shci_tl.h"
 #include "app_debug.h"
 #include "app_debug.h"
 #include <furi-hal.h>
 #include <furi-hal.h>

+ 2 - 3
firmware/targets/f6/ble-glue/gap.c

@@ -2,7 +2,6 @@
 
 
 #include "ble.h"
 #include "ble.h"
 
 
-#include "cmsis_os.h"
 #include <furi-hal.h>
 #include <furi-hal.h>
 #include <furi.h>
 #include <furi.h>
 
 
@@ -28,7 +27,7 @@ typedef struct {
     osMutexId_t state_mutex;
     osMutexId_t state_mutex;
     BleEventCallback on_event_cb;
     BleEventCallback on_event_cb;
     void* context;
     void* context;
-    osTimerId advertise_timer;
+    osTimerId_t advertise_timer;
     FuriThread* thread;
     FuriThread* thread;
     osMessageQueueId_t command_queue;
     osMessageQueueId_t command_queue;
     bool enable_adv;
     bool enable_adv;
@@ -446,7 +445,7 @@ void gap_thread_stop() {
 static int32_t gap_app(void *context) {
 static int32_t gap_app(void *context) {
     GapCommand command;
     GapCommand command;
     while(1) {
     while(1) {
-        osStatus status = osMessageQueueGet(gap->command_queue, &command, NULL, osWaitForever);
+        osStatus_t status = osMessageQueueGet(gap->command_queue, &command, NULL, osWaitForever);
         if(status != osOK) {
         if(status != osOK) {
             FURI_LOG_E(TAG, "Message queue get error: %d", status);
             FURI_LOG_E(TAG, "Message queue get error: %d", status);
             continue;
             continue;

+ 1 - 1
firmware/targets/f6/ble-glue/serial_service.c

@@ -62,7 +62,7 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void *event) {
                 ret = SVCCTL_EvtAckFlowEnable;
                 ret = SVCCTL_EvtAckFlowEnable;
             }
             }
         } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
         } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
-            FURI_LOG_D(TAG, "Ack received", blecore_evt->ecode);
+            FURI_LOG_T(TAG, "Ack received", blecore_evt->ecode);
             if(serial_svc->callback) {
             if(serial_svc->callback) {
                 SerialServiceEvent event = {
                 SerialServiceEvent event = {
                     .event = SerialServiceEventTypeDataSent,
                     .event = SerialServiceEventTypeDataSent,

+ 0 - 1
firmware/targets/f6/fatfs/ffconf.h

@@ -26,7 +26,6 @@
 
 
 #include "main.h"
 #include "main.h"
 #include "stm32wbxx_hal.h"
 #include "stm32wbxx_hal.h"
-#include "cmsis_os.h" /* _FS_REENTRANT set to 1 and CMSIS API chosen */
 
 
 /*-----------------------------------------------------------------------------/
 /*-----------------------------------------------------------------------------/
 / Function Configurations
 / Function Configurations

+ 2 - 2
firmware/targets/f6/furi-hal/furi-hal-os.c

@@ -43,7 +43,7 @@ void furi_hal_os_init() {
     LL_GPIO_SetPinMode(LED_TICK_PORT, LED_TICK_PIN, LL_GPIO_MODE_OUTPUT);
     LL_GPIO_SetPinMode(LED_TICK_PORT, LED_TICK_PIN, LL_GPIO_MODE_OUTPUT);
     LL_GPIO_SetPinMode(LED_SECOND_PORT, LED_SECOND_PIN, LL_GPIO_MODE_OUTPUT);
     LL_GPIO_SetPinMode(LED_SECOND_PORT, LED_SECOND_PIN, LL_GPIO_MODE_OUTPUT);
     osTimerId_t second_timer = osTimerNew(furi_hal_os_timer_callback, osTimerPeriodic, NULL, NULL);
     osTimerId_t second_timer = osTimerNew(furi_hal_os_timer_callback, osTimerPeriodic, NULL, NULL);
-    osTimerStart(second_timer, 1024);
+    osTimerStart(second_timer, FURI_HAL_OS_TICK_PER_SECOND);
 #endif
 #endif
 
 
     FURI_LOG_I(TAG, "Init OK");
     FURI_LOG_I(TAG, "Init OK");
@@ -139,7 +139,7 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
     __enable_irq();
     __enable_irq();
 }
 }
 
 
-void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName) {
+void vApplicationStackOverflowHook(TaskHandle_t xTask, char * pcTaskName) {
     asm("bkpt 1");
     asm("bkpt 1");
     while(1) {};
     while(1) {};
 }
 }

+ 0 - 1
firmware/targets/f6/furi-hal/furi-hal-task.c

@@ -1,4 +1,3 @@
-#include "cmsis_os.h"
 #include "furi-hal-task.h"
 #include "furi-hal-task.h"
 
 
 //-----------------------------cmsis_os2.c-------------------------------
 //-----------------------------cmsis_os2.c-------------------------------

+ 12 - 11
firmware/targets/f6/target.mk

@@ -75,18 +75,19 @@ C_SOURCES += \
 
 
 # FreeRTOS
 # FreeRTOS
 CFLAGS += \
 CFLAGS += \
-	-I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/include \
-	-I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 \
-	-I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F
+	-I$(LIB_DIR)/FreeRTOS-Kernel/include \
+	-I$(LIB_DIR)/FreeRTOS-Kernel/portable/GCC/ARM_CM4F \
+	-I$(LIB_DIR)/FreeRTOS-glue/
+
 C_SOURCES += \
 C_SOURCES += \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/list.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/queue.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/stream_buffer.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/tasks.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/timers.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
+	$(LIB_DIR)/FreeRTOS-Kernel/event_groups.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/list.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/queue.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/stream_buffer.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/tasks.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/timers.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c \
+	$(LIB_DIR)/FreeRTOS-glue/cmsis_os2.c \
 
 
 # BLE glue 
 # BLE glue 
 CFLAGS += \
 CFLAGS += \

+ 74 - 127
firmware/targets/f7/Inc/FreeRTOSConfig.h

@@ -1,133 +1,89 @@
-/* USER CODE BEGIN Header */
-/*
- * FreeRTOS Kernel V10.2.1
- * Portion Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
- * Portion Copyright (C) 2019 StMicroelectronics, Inc.  All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * http://www.FreeRTOS.org
- * http://aws.amazon.com/freertos
- *
- * 1 tab == 4 spaces!
- */
-/* USER CODE END Header */
-
-#ifndef FREERTOS_CONFIG_H
-#define FREERTOS_CONFIG_H
-
-/*-----------------------------------------------------------
- * Application specific definitions.
- *
- * These definitions should be adjusted for your particular hardware and
- * application requirements.
- *
- * These parameters and more are described within the 'configuration' section of the
- * FreeRTOS API documentation available on the FreeRTOS.org web site.
- *
- * See http://www.freertos.org/a00110.html
- *----------------------------------------------------------*/
-
-/* USER CODE BEGIN Includes */
-/* Section where include file can be added */
-/* USER CODE END Includes */
-
-/* Ensure definitions are only used by the compiler, and not by the assembler. */
+#pragma once
+
 #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
 #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
-  #include <stdint.h>
-  extern uint32_t SystemCoreClock;
+#include <stdint.h>
+extern uint32_t SystemCoreClock;
 #endif
 #endif
+
 #ifndef CMSIS_device_header
 #ifndef CMSIS_device_header
 #define CMSIS_device_header "stm32wbxx.h"
 #define CMSIS_device_header "stm32wbxx.h"
 #endif /* CMSIS_device_header */
 #endif /* CMSIS_device_header */
 
 
-#define configENABLE_FPU                         1
-#define configENABLE_MPU                         0
-
-#define configUSE_PREEMPTION                     1
-#define configSUPPORT_STATIC_ALLOCATION          0
-#define configSUPPORT_DYNAMIC_ALLOCATION         1
-#define configUSE_IDLE_HOOK                      0
-#define configUSE_TICK_HOOK                      0
-#define configCPU_CLOCK_HZ                       ( SystemCoreClock )
-#define configTICK_RATE_HZ                       ((TickType_t)1024)
-#define configMAX_PRIORITIES                     ( 56 )
-#define configMINIMAL_STACK_SIZE                 ((uint16_t)128)
+#define configENABLE_FPU                            1
+#define configENABLE_MPU                            0
+
+#define configUSE_PREEMPTION                        1
+#define configSUPPORT_STATIC_ALLOCATION             0
+#define configSUPPORT_DYNAMIC_ALLOCATION            1
+#define configUSE_IDLE_HOOK                         0
+#define configUSE_TICK_HOOK                         0
+#define configCPU_CLOCK_HZ                          ( SystemCoreClock )
+#define configTICK_RATE_HZ                          ((TickType_t)1024)
+#define configMAX_PRIORITIES                        ( 56 )
+#define configMINIMAL_STACK_SIZE                    ((uint16_t)128)
+
 /* Heap size determined automatically by linker */
 /* Heap size determined automatically by linker */
 // #define configTOTAL_HEAP_SIZE                    ((size_t)0)
 // #define configTOTAL_HEAP_SIZE                    ((size_t)0)
-#define configMAX_TASK_NAME_LEN                  ( 16 )
-#define configGENERATE_RUN_TIME_STATS            0
-#define configUSE_TRACE_FACILITY                 1
-#define configUSE_16_BIT_TICKS                   0
-#define configUSE_MUTEXES                        1
-#define configQUEUE_REGISTRY_SIZE                8
-#define configCHECK_FOR_STACK_OVERFLOW           1
-#define configUSE_RECURSIVE_MUTEXES              1
-#define configUSE_COUNTING_SEMAPHORES            1
-#define configENABLE_BACKWARD_COMPATIBILITY      0
-#define configUSE_PORT_OPTIMISED_TASK_SELECTION  0
-#define configUSE_TICKLESS_IDLE                  2
-#define configRECORD_STACK_HIGH_ADDRESS          1
-#define configUSE_NEWLIB_REENTRANT               0
-/* USER CODE BEGIN MESSAGE_BUFFER_LENGTH_TYPE */
+#define configMAX_TASK_NAME_LEN                     ( 16 )
+#define configGENERATE_RUN_TIME_STATS               0
+#define configUSE_TRACE_FACILITY                    1
+#define configUSE_16_BIT_TICKS                      0
+#define configUSE_MUTEXES                           1
+#define configQUEUE_REGISTRY_SIZE                   8
+#define configCHECK_FOR_STACK_OVERFLOW              1
+#define configUSE_RECURSIVE_MUTEXES                 1
+#define configUSE_COUNTING_SEMAPHORES               1
+#define configENABLE_BACKWARD_COMPATIBILITY         0
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION     0
+#define configUSE_TICKLESS_IDLE                     2
+#define configRECORD_STACK_HIGH_ADDRESS             1
+#define configUSE_NEWLIB_REENTRANT                  0
+
 /* Defaults to size_t for backward compatibility, but can be changed
 /* Defaults to size_t for backward compatibility, but can be changed
    if lengths will always be less than the number of bytes in a size_t. */
    if lengths will always be less than the number of bytes in a size_t. */
-#define configMESSAGE_BUFFER_LENGTH_TYPE         size_t
-#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1
-#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP   8
-/* USER CODE END MESSAGE_BUFFER_LENGTH_TYPE */
+#define configMESSAGE_BUFFER_LENGTH_TYPE            size_t
+#define configNUM_THREAD_LOCAL_STORAGE_POINTERS     1
+#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP       4
 
 
 /* Co-routine definitions. */
 /* Co-routine definitions. */
-#define configUSE_CO_ROUTINES                    0
-#define configMAX_CO_ROUTINE_PRIORITIES          ( 2 )
+#define configUSE_CO_ROUTINES                       0
 
 
 /* Software timer definitions. */
 /* Software timer definitions. */
-#define configUSE_TIMERS                         1
-#define configTIMER_TASK_PRIORITY                ( 2 )
-#define configTIMER_QUEUE_LENGTH                 32
-#define configTIMER_TASK_STACK_DEPTH             256
-#define configTIMER_SERVICE_TASK_NAME          "TimersSrv"
+#define configUSE_TIMERS                            1
+#define configTIMER_TASK_PRIORITY                   ( 2 )
+#define configTIMER_QUEUE_LENGTH                    32
+#define configTIMER_TASK_STACK_DEPTH                256
+#define configTIMER_SERVICE_TASK_NAME               "TimersSrv"
 
 
-#define configIDLE_TASK_NAME                  "(-_-)"
+#define configIDLE_TASK_NAME                        "(-_-)"
 
 
 /* Set the following definitions to 1 to include the API function, or zero
 /* Set the following definitions to 1 to include the API function, or zero
 to exclude the API function. */
 to exclude the API function. */
-#define INCLUDE_eTaskGetState                1
-#define INCLUDE_uxTaskGetStackHighWaterMark  1
-#define INCLUDE_uxTaskPriorityGet            1
-#define INCLUDE_vTaskCleanUpResources        0
-#define INCLUDE_vTaskDelay                   1
-#define INCLUDE_vTaskDelayUntil              1
-#define INCLUDE_vTaskDelete                  1
-#define INCLUDE_vTaskPrioritySet             1
-#define INCLUDE_vTaskSuspend                 1
-#define INCLUDE_xQueueGetMutexHolder         1
-#define INCLUDE_xTaskGetCurrentTaskHandle    1
-#define INCLUDE_xTaskGetSchedulerState       1
-#define INCLUDE_xTimerPendFunctionCall       1
+#define INCLUDE_eTaskGetState                       1
+#define INCLUDE_uxTaskGetStackHighWaterMark         1
+#define INCLUDE_uxTaskPriorityGet                   1
+#define INCLUDE_vTaskCleanUpResources               0
+#define INCLUDE_vTaskDelay                          1
+#define INCLUDE_vTaskDelayUntil                     1
+#define INCLUDE_vTaskDelete                         1
+#define INCLUDE_vTaskPrioritySet                    1
+#define INCLUDE_vTaskSuspend                        1
+#define INCLUDE_xQueueGetMutexHolder                1
+#define INCLUDE_xTaskGetCurrentTaskHandle           1
+#define INCLUDE_xTaskGetSchedulerState              1
+#define INCLUDE_xTimerPendFunctionCall              1
 
 
 /* CMSIS-RTOS V2 flags */
 /* CMSIS-RTOS V2 flags */
-#define configUSE_OS2_THREAD_SUSPEND_RESUME  1
-#define configUSE_OS2_THREAD_ENUMERATE       1
-#define configUSE_OS2_EVENTFLAGS_FROM_ISR    1
-#define configUSE_OS2_THREAD_FLAGS           1
-#define configUSE_OS2_TIMER                  1
-#define configUSE_OS2_MUTEX                  1
+#define configUSE_OS2_THREAD_SUSPEND_RESUME         1
+#define configUSE_OS2_THREAD_ENUMERATE              1
+#define configUSE_OS2_EVENTFLAGS_FROM_ISR           1
+#define configUSE_OS2_THREAD_FLAGS                  1
+#define configUSE_OS2_TIMER                         1
+#define configUSE_OS2_MUTEX                         1
+
+/* CMSIS-RTOS */
+#define configTASK_NOTIFICATION_ARRAY_ENTRIES       2
+#define CMSIS_TASK_NOTIFY_INDEX 1
 
 
 /*
 /*
  * The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
  * The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
@@ -137,15 +93,15 @@ to exclude the API function. */
 
 
 /* Cortex-M specific definitions. */
 /* Cortex-M specific definitions. */
 #ifdef __NVIC_PRIO_BITS
 #ifdef __NVIC_PRIO_BITS
- /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
- #define configPRIO_BITS         __NVIC_PRIO_BITS
+    /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
+    #define configPRIO_BITS                         __NVIC_PRIO_BITS
 #else
 #else
- #define configPRIO_BITS         4
+    #define configPRIO_BITS                         4
 #endif
 #endif
 
 
 /* The lowest interrupt priority that can be used in a call to a "set priority"
 /* The lowest interrupt priority that can be used in a call to a "set priority"
 function. */
 function. */
-#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY     15
 
 
 /* The highest interrupt priority that can be used by any interrupt service
 /* The highest interrupt priority that can be used by any interrupt service
 routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
 routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
@@ -155,29 +111,20 @@ PRIORITY THAN THIS! (higher priorities are lower numeric values. */
 
 
 /* Interrupt priorities used by the kernel port layer itself.  These are generic
 /* Interrupt priorities used by the kernel port layer itself.  These are generic
 to all Cortex-M ports, and do not rely on any particular library functions. */
 to all Cortex-M ports, and do not rely on any particular library functions. */
-#define configKERNEL_INTERRUPT_PRIORITY         ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+#define configKERNEL_INTERRUPT_PRIORITY             ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+
 /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
 /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
 See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
 See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
-#define configMAX_SYSCALL_INTERRUPT_PRIORITY    ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY        ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
 
 
 /* Normal assert() semantics without relying on the provision of an assert.h
 /* Normal assert() semantics without relying on the provision of an assert.h
 header file. */
 header file. */
-/* USER CODE BEGIN 1 */
-#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); asm("bkpt 1"); for( ;; );}
-/* USER CODE END 1 */
+#define configASSERT( x ) if ((x) == 0) { taskDISABLE_INTERRUPTS(); asm("bkpt 1"); for( ;; ); }
 
 
 /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
 /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
 standard names. */
 standard names. */
 #define vPortSVCHandler    SVC_Handler
 #define vPortSVCHandler    SVC_Handler
 #define xPortPendSVHandler PendSV_Handler
 #define xPortPendSVHandler PendSV_Handler
 
 
-/* IMPORTANT: After 10.3.1 update, Systick_Handler comes from NVIC (if SYS timebase = systick), otherwise from cmsis_os2.c */
-
 #define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1
 #define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1
-
-/* USER CODE BEGIN Defines */
-/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
 #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 1  /* required only for Keil but does not hurt otherwise */
 #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 1  /* required only for Keil but does not hurt otherwise */
-/* USER CODE END Defines */
-
-#endif /* FREERTOS_CONFIG_H */

+ 0 - 21
firmware/targets/f7/Src/freertos-openocd.c

@@ -1,21 +0,0 @@
-
-/*
- * Since at least FreeRTOS V7.5.3 uxTopUsedPriority is no longer
- * present in the kernel, so it has to be supplied by other means for
- * OpenOCD's threads awareness.
- *
- * Add this file to your project, and, if you're using --gc-sections,
- * ``--undefined=uxTopUsedPriority'' (or
- * ``-Wl,--undefined=uxTopUsedPriority'' when using gcc for final
- * linking) to your LDFLAGS; same with all the other symbols you need.
- */
-
-#include "FreeRTOS.h"
-
-#ifdef __GNUC__
-#define USED __attribute__((used))
-#else
-#define USED
-#endif
-
-const int USED uxTopUsedPriority = configMAX_PRIORITIES - 1;

+ 0 - 1
firmware/targets/f7/ble-glue/ble_app.c

@@ -3,7 +3,6 @@
 #include "hci_tl.h"
 #include "hci_tl.h"
 #include "ble.h"
 #include "ble.h"
 #include "shci.h"
 #include "shci.h"
-#include "cmsis_os.h"
 #include "gap.h"
 #include "gap.h"
 
 
 #include <furi-hal.h>
 #include <furi-hal.h>

+ 0 - 1
firmware/targets/f7/ble-glue/ble_glue.c

@@ -5,7 +5,6 @@
 #include "ble.h"
 #include "ble.h"
 #include "tl.h"
 #include "tl.h"
 #include "shci.h"
 #include "shci.h"
-#include "cmsis_os.h"
 #include "shci_tl.h"
 #include "shci_tl.h"
 #include "app_debug.h"
 #include "app_debug.h"
 #include <furi-hal.h>
 #include <furi-hal.h>

+ 2 - 3
firmware/targets/f7/ble-glue/gap.c

@@ -2,7 +2,6 @@
 
 
 #include "ble.h"
 #include "ble.h"
 
 
-#include "cmsis_os.h"
 #include <furi-hal.h>
 #include <furi-hal.h>
 #include <furi.h>
 #include <furi.h>
 
 
@@ -28,7 +27,7 @@ typedef struct {
     osMutexId_t state_mutex;
     osMutexId_t state_mutex;
     BleEventCallback on_event_cb;
     BleEventCallback on_event_cb;
     void* context;
     void* context;
-    osTimerId advertise_timer;
+    osTimerId_t advertise_timer;
     FuriThread* thread;
     FuriThread* thread;
     osMessageQueueId_t command_queue;
     osMessageQueueId_t command_queue;
     bool enable_adv;
     bool enable_adv;
@@ -446,7 +445,7 @@ void gap_thread_stop() {
 static int32_t gap_app(void *context) {
 static int32_t gap_app(void *context) {
     GapCommand command;
     GapCommand command;
     while(1) {
     while(1) {
-        osStatus status = osMessageQueueGet(gap->command_queue, &command, NULL, osWaitForever);
+        osStatus_t status = osMessageQueueGet(gap->command_queue, &command, NULL, osWaitForever);
         if(status != osOK) {
         if(status != osOK) {
             FURI_LOG_E(TAG, "Message queue get error: %d", status);
             FURI_LOG_E(TAG, "Message queue get error: %d", status);
             continue;
             continue;

+ 1 - 1
firmware/targets/f7/ble-glue/serial_service.c

@@ -62,7 +62,7 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void *event) {
                 ret = SVCCTL_EvtAckFlowEnable;
                 ret = SVCCTL_EvtAckFlowEnable;
             }
             }
         } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
         } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
-            FURI_LOG_D(TAG, "Ack received", blecore_evt->ecode);
+            FURI_LOG_T(TAG, "Ack received", blecore_evt->ecode);
             if(serial_svc->callback) {
             if(serial_svc->callback) {
                 SerialServiceEvent event = {
                 SerialServiceEvent event = {
                     .event = SerialServiceEventTypeDataSent,
                     .event = SerialServiceEventTypeDataSent,

+ 0 - 1
firmware/targets/f7/fatfs/ffconf.h

@@ -26,7 +26,6 @@
 
 
 #include "main.h"
 #include "main.h"
 #include "stm32wbxx_hal.h"
 #include "stm32wbxx_hal.h"
-#include "cmsis_os.h" /* _FS_REENTRANT set to 1 and CMSIS API chosen */
 
 
 /*-----------------------------------------------------------------------------/
 /*-----------------------------------------------------------------------------/
 / Function Configurations
 / Function Configurations

+ 2 - 2
firmware/targets/f7/furi-hal/furi-hal-os.c

@@ -43,7 +43,7 @@ void furi_hal_os_init() {
     LL_GPIO_SetPinMode(LED_TICK_PORT, LED_TICK_PIN, LL_GPIO_MODE_OUTPUT);
     LL_GPIO_SetPinMode(LED_TICK_PORT, LED_TICK_PIN, LL_GPIO_MODE_OUTPUT);
     LL_GPIO_SetPinMode(LED_SECOND_PORT, LED_SECOND_PIN, LL_GPIO_MODE_OUTPUT);
     LL_GPIO_SetPinMode(LED_SECOND_PORT, LED_SECOND_PIN, LL_GPIO_MODE_OUTPUT);
     osTimerId_t second_timer = osTimerNew(furi_hal_os_timer_callback, osTimerPeriodic, NULL, NULL);
     osTimerId_t second_timer = osTimerNew(furi_hal_os_timer_callback, osTimerPeriodic, NULL, NULL);
-    osTimerStart(second_timer, 1024);
+    osTimerStart(second_timer, FURI_HAL_OS_TICK_PER_SECOND);
 #endif
 #endif
 
 
     FURI_LOG_I(TAG, "Init OK");
     FURI_LOG_I(TAG, "Init OK");
@@ -139,7 +139,7 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
     __enable_irq();
     __enable_irq();
 }
 }
 
 
-void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName) {
+void vApplicationStackOverflowHook(TaskHandle_t xTask, char * pcTaskName) {
     asm("bkpt 1");
     asm("bkpt 1");
     while(1) {};
     while(1) {};
 }
 }

+ 0 - 1
firmware/targets/f7/furi-hal/furi-hal-task.c

@@ -1,4 +1,3 @@
-#include "cmsis_os.h"
 #include "furi-hal-task.h"
 #include "furi-hal-task.h"
 
 
 //-----------------------------cmsis_os2.c-------------------------------
 //-----------------------------cmsis_os2.c-------------------------------

+ 12 - 11
firmware/targets/f7/target.mk

@@ -75,18 +75,19 @@ C_SOURCES += \
 
 
 # FreeRTOS
 # FreeRTOS
 CFLAGS += \
 CFLAGS += \
-	-I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/include \
-	-I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 \
-	-I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F
+	-I$(LIB_DIR)/FreeRTOS-Kernel/include \
+	-I$(LIB_DIR)/FreeRTOS-Kernel/portable/GCC/ARM_CM4F \
+	-I$(LIB_DIR)/FreeRTOS-glue/
+
 C_SOURCES += \
 C_SOURCES += \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/list.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/queue.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/stream_buffer.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/tasks.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/timers.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c \
-	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
+	$(LIB_DIR)/FreeRTOS-Kernel/event_groups.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/list.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/queue.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/stream_buffer.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/tasks.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/timers.c \
+	$(LIB_DIR)/FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c \
+	$(LIB_DIR)/FreeRTOS-glue/cmsis_os2.c \
 
 
 # BLE glue 
 # BLE glue 
 CFLAGS += \
 CFLAGS += \

+ 1 - 0
lib/FreeRTOS-Kernel

@@ -0,0 +1 @@
+Subproject commit 4c4089b1544b590ed3b72491a15365ec020c921f

+ 2873 - 0
lib/FreeRTOS-glue/cmsis_os2.c

@@ -0,0 +1,2873 @@
+/* --------------------------------------------------------------------------
+ * Copyright (c) 2013-2021 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *      Name:    cmsis_os2.c
+ *      Purpose: CMSIS RTOS2 wrapper for FreeRTOS
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <string.h>
+
+#include "cmsis_os2.h"                  // ::CMSIS:RTOS2
+#include "cmsis_compiler.h"             // Compiler agnostic definitions
+#include "os_tick.h"                    // OS Tick API
+
+#include "FreeRTOS.h"                   // ARM.FreeRTOS::RTOS:Core
+#include "task.h"                       // ARM.FreeRTOS::RTOS:Core
+#include "event_groups.h"               // ARM.FreeRTOS::RTOS:Event Groups
+#include "semphr.h"                     // ARM.FreeRTOS::RTOS:Core
+#include "timers.h"                     // ARM.FreeRTOS::RTOS:Timers
+
+#include "freertos_mpool.h"             // osMemoryPool definitions
+#include "freertos_os2.h"               // Configuration check and setup
+
+#include CMSIS_device_header
+
+#ifndef CMSIS_TASK_NOTIFY_INDEX
+#define CMSIS_TASK_NOTIFY_INDEX 0
+#endif
+
+/*---------------------------------------------------------------------------*/
+#ifndef __ARM_ARCH_6M__
+  #define __ARM_ARCH_6M__         0
+#endif
+#ifndef __ARM_ARCH_7M__
+  #define __ARM_ARCH_7M__         0
+#endif
+#ifndef __ARM_ARCH_7EM__
+  #define __ARM_ARCH_7EM__        0
+#endif
+#ifndef __ARM_ARCH_8M_MAIN__
+  #define __ARM_ARCH_8M_MAIN__    0
+#endif
+#ifndef __ARM_ARCH_7A__
+  #define __ARM_ARCH_7A__         0
+#endif
+
+#if   ((__ARM_ARCH_7M__      == 1U) || \
+       (__ARM_ARCH_7EM__     == 1U) || \
+       (__ARM_ARCH_8M_MAIN__ == 1U))
+#define IS_IRQ_MASKED()           ((__get_PRIMASK() != 0U) || (__get_BASEPRI() != 0U))
+#elif  (__ARM_ARCH_6M__      == 1U)
+#define IS_IRQ_MASKED()           (__get_PRIMASK() != 0U)
+#elif (__ARM_ARCH_7A__       == 1U)
+/* CPSR mask bits */
+#define CPSR_MASKBIT_I            0x80U
+
+#define IS_IRQ_MASKED()           ((__get_CPSR() & CPSR_MASKBIT_I) != 0U)
+#else
+#define IS_IRQ_MASKED()           (__get_PRIMASK() != 0U)
+#endif
+
+#if    (__ARM_ARCH_7A__      == 1U)
+/* CPSR mode bitmasks */
+#define CPSR_MODE_USER            0x10U
+#define CPSR_MODE_SYSTEM          0x1FU
+
+#define IS_IRQ_MODE()             ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM))
+#else
+#define IS_IRQ_MODE()             (__get_IPSR() != 0U)
+#endif
+
+/* Limits */
+#define MAX_BITS_TASK_NOTIFY      31U
+#define MAX_BITS_EVENT_GROUPS     24U
+
+#define THREAD_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_TASK_NOTIFY)  - 1U))
+#define EVENT_FLAGS_INVALID_BITS  (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U))
+
+/* Kernel version and identification string definition (major.minor.rev: mmnnnrrrr dec) */
+#define KERNEL_VERSION            (((uint32_t)tskKERNEL_VERSION_MAJOR * 10000000UL) | \
+                                   ((uint32_t)tskKERNEL_VERSION_MINOR *    10000UL) | \
+                                   ((uint32_t)tskKERNEL_VERSION_BUILD *        1UL))
+
+#define KERNEL_ID                 ("FreeRTOS " tskKERNEL_VERSION_NUMBER)
+
+/* Timer callback information structure definition */
+typedef struct {
+  osTimerFunc_t func;
+  void         *arg;
+} TimerCallback_t;
+
+/* Kernel initialization state */
+static osKernelState_t KernelState = osKernelInactive;
+
+/*
+  Heap region definition used by heap_5 variant
+
+  Define configAPPLICATION_ALLOCATED_HEAP as nonzero value in FreeRTOSConfig.h if
+  heap regions are already defined and vPortDefineHeapRegions is called in application.
+
+  Otherwise vPortDefineHeapRegions will be called by osKernelInitialize using
+  definition configHEAP_5_REGIONS as parameter. Overriding configHEAP_5_REGIONS
+  is possible by defining it globally or in FreeRTOSConfig.h.
+*/
+#if defined(USE_FreeRTOS_HEAP_5)
+#if (configAPPLICATION_ALLOCATED_HEAP == 0)
+  /*
+    FreeRTOS heap is not defined by the application.
+    Single region of size configTOTAL_HEAP_SIZE (defined in FreeRTOSConfig.h)
+    is provided by default. Define configHEAP_5_REGIONS to provide custom
+    HeapRegion_t array.
+  */
+  #define HEAP_5_REGION_SETUP   1
+  
+  #ifndef configHEAP_5_REGIONS
+    #define configHEAP_5_REGIONS xHeapRegions
+
+    static uint8_t ucHeap[configTOTAL_HEAP_SIZE];
+
+    static HeapRegion_t xHeapRegions[] = {
+      { ucHeap, configTOTAL_HEAP_SIZE },
+      { NULL,   0                     }
+    };
+  #else
+    /* Global definition is provided to override default heap array */
+    extern HeapRegion_t configHEAP_5_REGIONS[];
+  #endif
+#else
+  /*
+    The application already defined the array used for the FreeRTOS heap and
+    called vPortDefineHeapRegions to initialize heap.
+  */
+  #define HEAP_5_REGION_SETUP   0
+#endif /* configAPPLICATION_ALLOCATED_HEAP */
+#endif /* USE_FreeRTOS_HEAP_5 */
+
+/*
+  Setup SVC to reset value.
+*/
+__STATIC_INLINE void SVC_Setup (void) {
+#if (__ARM_ARCH_7A__ == 0U)
+  /* Service Call interrupt might be configured before kernel start     */
+  /* and when its priority is lower or equal to BASEPRI, svc intruction */
+  /* causes a Hard Fault.                                               */
+  NVIC_SetPriority (SVCall_IRQn, 0U);
+#endif
+}
+
+/*
+  Function macro used to retrieve semaphore count from ISR
+*/
+#ifndef uxSemaphoreGetCountFromISR
+#define uxSemaphoreGetCountFromISR( xSemaphore ) uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) ( xSemaphore ) )
+#endif
+
+/*
+  Determine if CPU executes from interrupt context or if interrupts are masked.
+*/
+__STATIC_INLINE uint32_t IRQ_Context (void) {
+  uint32_t irq;
+  BaseType_t state;
+
+  irq = 0U;
+
+  if (IS_IRQ_MODE()) {
+    /* Called from interrupt context */
+    irq = 1U;
+  }
+  else {
+    /* Get FreeRTOS scheduler state */
+    state = xTaskGetSchedulerState();
+
+    if (state != taskSCHEDULER_NOT_STARTED) {
+      /* Scheduler was started */
+      if (IS_IRQ_MASKED()) {
+        /* Interrupts are masked */
+        irq = 1U;
+      }
+    }
+  }
+
+  /* Return context, 0: thread context, 1: IRQ context */
+  return (irq);
+}
+
+
+/* ==== Kernel Management Functions ==== */
+
+/*
+  Initialize the RTOS Kernel.
+*/
+osStatus_t osKernelInitialize (void) {
+  osStatus_t stat;
+  BaseType_t state;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else {
+    state = xTaskGetSchedulerState();
+
+    /* Initialize if scheduler not started and not initialized before */
+    if ((state == taskSCHEDULER_NOT_STARTED) && (KernelState == osKernelInactive)) {
+      #if defined(USE_TRACE_EVENT_RECORDER)
+        /* Initialize the trace macro debugging output channel */
+        EvrFreeRTOSSetup(0U);
+      #endif
+      #if defined(USE_FreeRTOS_HEAP_5) && (HEAP_5_REGION_SETUP == 1)
+        /* Initialize the memory regions when using heap_5 variant */
+        vPortDefineHeapRegions (configHEAP_5_REGIONS);
+      #endif
+      KernelState = osKernelReady;
+      stat = osOK;
+    } else {
+      stat = osError;
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Get RTOS Kernel Information.
+*/
+osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) {
+
+  if (version != NULL) {
+    /* Version encoding is major.minor.rev: mmnnnrrrr dec */
+    version->api    = KERNEL_VERSION;
+    version->kernel = KERNEL_VERSION;
+  }
+
+  if ((id_buf != NULL) && (id_size != 0U)) {
+    /* Buffer for retrieving identification string is provided */
+    if (id_size > sizeof(KERNEL_ID)) {
+      id_size = sizeof(KERNEL_ID);
+    }
+    /* Copy kernel identification string into provided buffer */
+    memcpy(id_buf, KERNEL_ID, id_size);
+  }
+
+  /* Return execution status */
+  return (osOK);
+}
+
+/*
+  Get the current RTOS Kernel state.
+*/
+osKernelState_t osKernelGetState (void) {
+  osKernelState_t state;
+
+  switch (xTaskGetSchedulerState()) {
+    case taskSCHEDULER_RUNNING:
+      state = osKernelRunning;
+      break;
+
+    case taskSCHEDULER_SUSPENDED:
+      state = osKernelLocked;
+      break;
+
+    case taskSCHEDULER_NOT_STARTED:
+    default:
+      if (KernelState == osKernelReady) {
+        /* Ready, osKernelInitialize was already called */
+        state = osKernelReady;
+      } else {
+        /* Not initialized */
+        state = osKernelInactive;
+      }
+      break;
+  }
+
+  /* Return current state */
+  return (state);
+}
+
+/*
+  Start the RTOS Kernel scheduler.
+*/
+osStatus_t osKernelStart (void) {
+  osStatus_t stat;
+  BaseType_t state;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else {
+    state = xTaskGetSchedulerState();
+
+    /* Start scheduler if initialized and not started before */
+    if ((state == taskSCHEDULER_NOT_STARTED) && (KernelState == osKernelReady)) {
+      /* Ensure SVC priority is at the reset value */
+      SVC_Setup();
+      /* Change state to ensure correct API flow */
+      KernelState = osKernelRunning;
+      /* Start the kernel scheduler */
+      vTaskStartScheduler();
+      stat = osOK;
+    } else {
+      stat = osError;
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Lock the RTOS Kernel scheduler.
+*/
+int32_t osKernelLock (void) {
+  int32_t lock;
+
+  if (IRQ_Context() != 0U) {
+    lock = (int32_t)osErrorISR;
+  }
+  else {
+    switch (xTaskGetSchedulerState()) {
+      case taskSCHEDULER_SUSPENDED:
+        lock = 1;
+        break;
+
+      case taskSCHEDULER_RUNNING:
+        vTaskSuspendAll();
+        lock = 0;
+        break;
+
+      case taskSCHEDULER_NOT_STARTED:
+      default:
+        lock = (int32_t)osError;
+        break;
+    }
+  }
+
+  /* Return previous lock state */
+  return (lock);
+}
+
+/*
+  Unlock the RTOS Kernel scheduler.
+*/
+int32_t osKernelUnlock (void) {
+  int32_t lock;
+
+  if (IRQ_Context() != 0U) {
+    lock = (int32_t)osErrorISR;
+  }
+  else {
+    switch (xTaskGetSchedulerState()) {
+      case taskSCHEDULER_SUSPENDED:
+        lock = 1;
+
+        if (xTaskResumeAll() != pdTRUE) {
+          if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) {
+            lock = (int32_t)osError;
+          }
+        }
+        break;
+
+      case taskSCHEDULER_RUNNING:
+        lock = 0;
+        break;
+
+      case taskSCHEDULER_NOT_STARTED:
+      default:
+        lock = (int32_t)osError;
+        break;
+    }
+  }
+
+  /* Return previous lock state */
+  return (lock);
+}
+
+/*
+  Restore the RTOS Kernel scheduler lock state.
+*/
+int32_t osKernelRestoreLock (int32_t lock) {
+
+  if (IRQ_Context() != 0U) {
+    lock = (int32_t)osErrorISR;
+  }
+  else {
+    switch (xTaskGetSchedulerState()) {
+      case taskSCHEDULER_SUSPENDED:
+      case taskSCHEDULER_RUNNING:
+        if (lock == 1) {
+          vTaskSuspendAll();
+        }
+        else {
+          if (lock != 0) {
+            lock = (int32_t)osError;
+          }
+          else {
+            if (xTaskResumeAll() != pdTRUE) {
+              if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
+                lock = (int32_t)osError;
+              }
+            }
+          }
+        }
+        break;
+
+      case taskSCHEDULER_NOT_STARTED:
+      default:
+        lock = (int32_t)osError;
+        break;
+    }
+  }
+
+  /* Return new lock state */
+  return (lock);
+}
+
+/*
+  Get the RTOS kernel tick count.
+*/
+uint32_t osKernelGetTickCount (void) {
+  TickType_t ticks;
+
+  if (IRQ_Context() != 0U) {
+    ticks = xTaskGetTickCountFromISR();
+  } else {
+    ticks = xTaskGetTickCount();
+  }
+
+  /* Return kernel tick count */
+  return (ticks);
+}
+
+/*
+  Get the RTOS kernel tick frequency.
+*/
+uint32_t osKernelGetTickFreq (void) {
+  /* Return frequency in hertz */
+  return (configTICK_RATE_HZ);
+}
+
+/*
+  Get the RTOS kernel system timer count.
+*/
+uint32_t osKernelGetSysTimerCount (void) {
+  uint32_t irqmask = IS_IRQ_MASKED();
+  TickType_t ticks;
+  uint32_t val;
+
+  __disable_irq();
+
+  ticks = xTaskGetTickCount();
+  val   = OS_Tick_GetCount();
+
+  /* Update tick count and timer value when timer overflows */
+  if (OS_Tick_GetOverflow() != 0U) {
+    val = OS_Tick_GetCount();
+    ticks++;
+  }
+  val += ticks * OS_Tick_GetInterval();
+
+  if (irqmask == 0U) {
+    __enable_irq();
+  }
+
+  /* Return system timer count */
+  return (val);
+}
+
+/*
+  Get the RTOS kernel system timer frequency.
+*/
+uint32_t osKernelGetSysTimerFreq (void) {
+  /* Return frequency in hertz */
+  return (configCPU_CLOCK_HZ);
+}
+
+
+/* ==== Thread Management Functions ==== */
+
+/*
+  Create a thread and add it to Active Threads.
+
+  Limitations:
+  - The memory for control block and stack must be provided in the osThreadAttr_t
+    structure in order to allocate object statically.
+  - Attribute osThreadJoinable is not supported, NULL is returned if used.
+*/
+osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr) {
+  const char *name;
+  uint32_t stack;
+  TaskHandle_t hTask;
+  UBaseType_t prio;
+  int32_t mem;
+
+  hTask = NULL;
+
+  if ((IRQ_Context() == 0U) && (func != NULL)) {
+    stack = configMINIMAL_STACK_SIZE;
+    prio  = (UBaseType_t)osPriorityNormal;
+
+    name = NULL;
+    mem  = -1;
+
+    if (attr != NULL) {
+      if (attr->name != NULL) {
+        name = attr->name;
+      }
+      if (attr->priority != osPriorityNone) {
+        prio = (UBaseType_t)attr->priority;
+      }
+
+      if ((prio < osPriorityIdle) || (prio > osPriorityISR) || ((attr->attr_bits & osThreadJoinable) == osThreadJoinable)) {
+        /* Invalid priority or unsupported osThreadJoinable attribute used */
+        return (NULL);
+      }
+
+      if (attr->stack_size > 0U) {
+        /* In FreeRTOS stack is not in bytes, but in sizeof(StackType_t) which is 4 on ARM ports.       */
+        /* Stack size should be therefore 4 byte aligned in order to avoid division caused side effects */
+        stack = attr->stack_size / sizeof(StackType_t);
+      }
+
+      if ((attr->cb_mem    != NULL) && (attr->cb_size    >= sizeof(StaticTask_t)) &&
+          (attr->stack_mem != NULL) && (attr->stack_size >  0U)) {
+        /* The memory for control block and stack is provided, use static object */
+        mem = 1;
+      }
+      else {
+        if ((attr->cb_mem == NULL) && (attr->cb_size == 0U) && (attr->stack_mem == NULL)) {
+          /* Control block and stack memory will be allocated from the dynamic pool */
+          mem = 0;
+        }
+      }
+    }
+    else {
+      mem = 0;
+    }
+
+    if (mem == 1) {
+      #if (configSUPPORT_STATIC_ALLOCATION == 1)
+        hTask = xTaskCreateStatic ((TaskFunction_t)func, name, stack, argument, prio, (StackType_t  *)attr->stack_mem,
+                                                                                      (StaticTask_t *)attr->cb_mem);
+      #endif
+    }
+    else {
+      if (mem == 0) {
+        #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+          if (xTaskCreate ((TaskFunction_t)func, name, (configSTACK_DEPTH_TYPE)stack, argument, prio, &hTask) != pdPASS) {
+            hTask = NULL;
+          }
+        #endif
+      }
+    }
+  }
+
+  /* Return thread ID */
+  return ((osThreadId_t)hTask);
+}
+
+/*
+  Get name of a thread.
+*/
+const char *osThreadGetName (osThreadId_t thread_id) {
+  TaskHandle_t hTask = (TaskHandle_t)thread_id;
+  const char *name;
+
+  if ((IRQ_Context() != 0U) || (hTask == NULL)) {
+    name = NULL;
+  } else {
+    name = pcTaskGetName (hTask);
+  }
+
+  /* Return name as null-terminated string */
+  return (name);
+}
+
+/*
+  Return the thread ID of the current running thread.
+*/
+osThreadId_t osThreadGetId (void) {
+  osThreadId_t id;
+
+  id = (osThreadId_t)xTaskGetCurrentTaskHandle();
+
+  /* Return thread ID */
+  return (id);
+}
+
+/*
+  Get current thread state of a thread.
+*/
+osThreadState_t osThreadGetState (osThreadId_t thread_id) {
+  TaskHandle_t hTask = (TaskHandle_t)thread_id;
+  osThreadState_t state;
+
+  if ((IRQ_Context() != 0U) || (hTask == NULL)) {
+    state = osThreadError;
+  }
+  else {
+    switch (eTaskGetState (hTask)) {
+      case eRunning:   state = osThreadRunning;    break;
+      case eReady:     state = osThreadReady;      break;
+      case eBlocked:
+      case eSuspended: state = osThreadBlocked;    break;
+      case eDeleted:   state = osThreadTerminated; break;
+      case eInvalid:
+      default:         state = osThreadError;      break;
+    }
+  }
+
+  /* Return current thread state */
+  return (state);
+}
+
+/*
+  Get available stack space of a thread based on stack watermark recording during execution.
+*/
+uint32_t osThreadGetStackSpace (osThreadId_t thread_id) {
+  TaskHandle_t hTask = (TaskHandle_t)thread_id;
+  uint32_t sz;
+
+  if ((IRQ_Context() != 0U) || (hTask == NULL)) {
+    sz = 0U;
+  } else {
+    sz = (uint32_t)(uxTaskGetStackHighWaterMark(hTask) * sizeof(StackType_t));
+  }
+
+  /* Return remaining stack space in bytes */
+  return (sz);
+}
+
+/*
+  Change priority of a thread.
+*/
+osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority) {
+  TaskHandle_t hTask = (TaskHandle_t)thread_id;
+  osStatus_t stat;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if ((hTask == NULL) || (priority < osPriorityIdle) || (priority > osPriorityISR)) {
+    stat = osErrorParameter;
+  }
+  else {
+    stat = osOK;
+    vTaskPrioritySet (hTask, (UBaseType_t)priority);
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Get current priority of a thread.
+*/
+osPriority_t osThreadGetPriority (osThreadId_t thread_id) {
+  TaskHandle_t hTask = (TaskHandle_t)thread_id;
+  osPriority_t prio;
+
+  if ((IRQ_Context() != 0U) || (hTask == NULL)) {
+    prio = osPriorityError;
+  } else {
+    prio = (osPriority_t)((int32_t)uxTaskPriorityGet (hTask));
+  }
+
+  /* Return current thread priority */
+  return (prio);
+}
+
+/*
+  Pass control to next thread that is in state READY.
+*/
+osStatus_t osThreadYield (void) {
+  osStatus_t stat;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  } else {
+    stat = osOK;
+    taskYIELD();
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+#if (configUSE_OS2_THREAD_SUSPEND_RESUME == 1)
+/*
+  Suspend execution of a thread.
+*/
+osStatus_t osThreadSuspend (osThreadId_t thread_id) {
+  TaskHandle_t hTask = (TaskHandle_t)thread_id;
+  osStatus_t stat;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hTask == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    stat = osOK;
+    vTaskSuspend (hTask);
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Resume execution of a thread.
+*/
+osStatus_t osThreadResume (osThreadId_t thread_id) {
+  TaskHandle_t hTask = (TaskHandle_t)thread_id;
+  osStatus_t stat;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hTask == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    stat = osOK;
+    vTaskResume (hTask);
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+#endif /* (configUSE_OS2_THREAD_SUSPEND_RESUME == 1) */
+
+/*
+  Terminate execution of current running thread.
+*/
+__NO_RETURN void osThreadExit (void) {
+#ifndef USE_FreeRTOS_HEAP_1
+  vTaskDelete (NULL);
+#endif
+  for (;;);
+}
+
+/*
+  Terminate execution of a thread.
+*/
+osStatus_t osThreadTerminate (osThreadId_t thread_id) {
+  TaskHandle_t hTask = (TaskHandle_t)thread_id;
+  osStatus_t stat;
+#ifndef USE_FreeRTOS_HEAP_1
+  eTaskState tstate;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hTask == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    tstate = eTaskGetState (hTask);
+
+    if (tstate != eDeleted) {
+      stat = osOK;
+      vTaskDelete (hTask);
+    } else {
+      stat = osErrorResource;
+    }
+  }
+#else
+  stat = osError;
+#endif
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Get number of active threads.
+*/
+uint32_t osThreadGetCount (void) {
+  uint32_t count;
+
+  if (IRQ_Context() != 0U) {
+    count = 0U;
+  } else {
+    count = uxTaskGetNumberOfTasks();
+  }
+
+  /* Return number of active threads */
+  return (count);
+}
+
+#if (configUSE_OS2_THREAD_ENUMERATE == 1)
+/*
+  Enumerate active threads.
+*/
+uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items) {
+  uint32_t i, count;
+  TaskStatus_t *task;
+
+  if ((IRQ_Context() != 0U) || (thread_array == NULL) || (array_items == 0U)) {
+    count = 0U;
+  } else {
+    vTaskSuspendAll();
+
+    /* Allocate memory on heap to temporarily store TaskStatus_t information */
+    count = uxTaskGetNumberOfTasks();
+    task  = pvPortMalloc (count * sizeof(TaskStatus_t));
+
+    if (task != NULL) {
+      /* Retrieve task status information */
+      count = uxTaskGetSystemState (task, count, NULL);
+
+      /* Copy handles from task status array into provided thread array */
+      for (i = 0U; (i < count) && (i < array_items); i++) {
+        thread_array[i] = (osThreadId_t)task[i].xHandle;
+      }
+      count = i;
+    }
+    (void)xTaskResumeAll();
+
+    vPortFree (task);
+  }
+
+  /* Return number of enumerated threads */
+  return (count);
+}
+#endif /* (configUSE_OS2_THREAD_ENUMERATE == 1) */
+
+
+/* ==== Thread Flags Functions ==== */
+
+#if (configUSE_OS2_THREAD_FLAGS == 1)
+/*
+  Set the specified Thread Flags of a thread.
+*/
+uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags) {
+  TaskHandle_t hTask = (TaskHandle_t)thread_id;
+  uint32_t rflags;
+  BaseType_t yield;
+
+  if ((hTask == NULL) || ((flags & THREAD_FLAGS_INVALID_BITS) != 0U)) {
+    rflags = (uint32_t)osErrorParameter;
+  }
+  else {
+    rflags = (uint32_t)osError;
+
+    if (IRQ_Context() != 0U) {
+      yield = pdFALSE;
+
+      (void)xTaskNotifyIndexedFromISR (hTask, CMSIS_TASK_NOTIFY_INDEX, flags, eSetBits, &yield);
+      (void)xTaskNotifyAndQueryIndexedFromISR (hTask, CMSIS_TASK_NOTIFY_INDEX, 0, eNoAction, &rflags, NULL);
+
+      portYIELD_FROM_ISR (yield);
+    }
+    else {
+      (void)xTaskNotifyIndexed (hTask, CMSIS_TASK_NOTIFY_INDEX, flags, eSetBits);
+      (void)xTaskNotifyAndQueryIndexed (hTask, CMSIS_TASK_NOTIFY_INDEX, 0, eNoAction, &rflags);
+    }
+  }
+  /* Return flags after setting */
+  return (rflags);
+}
+
+/*
+  Clear the specified Thread Flags of current running thread.
+*/
+uint32_t osThreadFlagsClear (uint32_t flags) {
+  TaskHandle_t hTask;
+  uint32_t rflags, cflags;
+
+  if (IRQ_Context() != 0U) {
+    rflags = (uint32_t)osErrorISR;
+  }
+  else if ((flags & THREAD_FLAGS_INVALID_BITS) != 0U) {
+    rflags = (uint32_t)osErrorParameter;
+  }
+  else {
+    hTask = xTaskGetCurrentTaskHandle();
+
+    if (xTaskNotifyAndQueryIndexed (hTask, CMSIS_TASK_NOTIFY_INDEX, 0, eNoAction, &cflags) == pdPASS) {
+      rflags = cflags;
+      cflags &= ~flags;
+
+      if (xTaskNotifyIndexed (hTask, CMSIS_TASK_NOTIFY_INDEX, cflags, eSetValueWithOverwrite) != pdPASS) {
+        rflags = (uint32_t)osError;
+      }
+    }
+    else {
+      rflags = (uint32_t)osError;
+    }
+  }
+
+  /* Return flags before clearing */
+  return (rflags);
+}
+
+/*
+  Get the current Thread Flags of current running thread.
+*/
+uint32_t osThreadFlagsGet (void) {
+  TaskHandle_t hTask;
+  uint32_t rflags;
+
+  if (IRQ_Context() != 0U) {
+    rflags = (uint32_t)osErrorISR;
+  }
+  else {
+    hTask = xTaskGetCurrentTaskHandle();
+
+    if (xTaskNotifyAndQueryIndexed (hTask, CMSIS_TASK_NOTIFY_INDEX, 0, eNoAction, &rflags) != pdPASS) {
+      rflags = (uint32_t)osError;
+    }
+  }
+
+  /* Return current flags */
+  return (rflags);
+}
+
+/*
+  Wait for one or more Thread Flags of the current running thread to become signaled.
+*/
+uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout) {
+  uint32_t rflags, nval;
+  uint32_t clear;
+  TickType_t t0, td, tout;
+  BaseType_t rval;
+
+  if (IRQ_Context() != 0U) {
+    rflags = (uint32_t)osErrorISR;
+  }
+  else if ((flags & THREAD_FLAGS_INVALID_BITS) != 0U) {
+    rflags = (uint32_t)osErrorParameter;
+  }
+  else {
+    if ((options & osFlagsNoClear) == osFlagsNoClear) {
+      clear = 0U;
+    } else {
+      clear = flags;
+    }
+
+    rflags = 0U;
+    tout   = timeout;
+
+    t0 = xTaskGetTickCount();
+    do {
+      rval = xTaskNotifyWaitIndexed (CMSIS_TASK_NOTIFY_INDEX, 0, clear, &nval, tout);
+
+      if (rval == pdPASS) {
+        rflags &= flags;
+        rflags |= nval;
+
+        if ((options & osFlagsWaitAll) == osFlagsWaitAll) {
+          if ((flags & rflags) == flags) {
+            break;
+          } else {
+            if (timeout == 0U) {
+              rflags = (uint32_t)osErrorResource;
+              break;
+            }
+          }
+        }
+        else {
+          if ((flags & rflags) != 0) {
+            break;
+          } else {
+            if (timeout == 0U) {
+              rflags = (uint32_t)osErrorResource;
+              break;
+            }
+          }
+        }
+
+        /* Update timeout */
+        td = xTaskGetTickCount() - t0;
+
+        if (td > timeout) {
+          tout  = 0;
+        } else {
+          tout = timeout - td;
+        }
+      }
+      else {
+        if (timeout == 0) {
+          rflags = (uint32_t)osErrorResource;
+        } else {
+          rflags = (uint32_t)osErrorTimeout;
+        }
+      }
+    }
+    while (rval != pdFAIL);
+  }
+
+  /* Return flags before clearing */
+  return (rflags);
+}
+#endif /* (configUSE_OS2_THREAD_FLAGS == 1) */
+
+
+/* ==== Generic Wait Functions ==== */
+
+/*
+  Wait for Timeout (Time Delay).
+*/
+osStatus_t osDelay (uint32_t ticks) {
+  osStatus_t stat;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else {
+    stat = osOK;
+
+    if (ticks != 0U) {
+      vTaskDelay(ticks);
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Wait until specified time.
+*/
+osStatus_t osDelayUntil (uint32_t ticks) {
+  TickType_t tcnt, delay;
+  osStatus_t stat;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else {
+    stat = osOK;
+    tcnt = xTaskGetTickCount();
+
+    /* Determine remaining number of ticks to delay */
+    delay = (TickType_t)ticks - tcnt;
+
+    /* Check if target tick has not expired */
+    if((delay != 0U) && (0 == (delay >> (8 * sizeof(TickType_t) - 1)))) {
+      if (xTaskDelayUntil (&tcnt, delay) == pdFALSE) {
+        /* Did not delay */
+        stat = osError;
+      }
+    }
+    else
+    {
+      /* No delay or already expired */
+      stat = osErrorParameter;
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+
+/* ==== Timer Management Functions ==== */
+
+#if (configUSE_OS2_TIMER == 1)
+
+static void TimerCallback (TimerHandle_t hTimer) {
+  TimerCallback_t *callb;
+
+  /* Retrieve pointer to callback function and argument */
+  callb = (TimerCallback_t *)pvTimerGetTimerID (hTimer);
+
+  /* Remove dynamic allocation flag */
+  callb = (TimerCallback_t *)((uint32_t)callb & ~1U);
+
+  if (callb != NULL) {
+    callb->func (callb->arg);
+  }
+}
+
+/*
+  Create and Initialize a timer.
+*/
+osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) {
+  const char *name;
+  TimerHandle_t hTimer;
+  TimerCallback_t *callb;
+  UBaseType_t reload;
+  int32_t mem;
+  uint32_t callb_dyn;
+
+  hTimer = NULL;
+
+  if ((IRQ_Context() == 0U) && (func != NULL)) {
+    callb     = NULL;
+    callb_dyn = 0U;
+
+    #if (configSUPPORT_STATIC_ALLOCATION == 1)
+      /* Static memory allocation is available: check if memory for control block */
+      /* is provided and if it also contains space for callback and its argument  */
+      if ((attr != NULL) && (attr->cb_mem != NULL)) {
+        if (attr->cb_size >= (sizeof(StaticTimer_t) + sizeof(TimerCallback_t))) {
+          callb = (TimerCallback_t *)((uint32_t)attr->cb_mem + sizeof(StaticTimer_t));
+        }
+      }
+    #endif
+
+    #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+      /* Dynamic memory allocation is available: if memory for callback and */
+      /* its argument is not provided, allocate it from dynamic memory pool */
+      if (callb == NULL) {
+        callb = (TimerCallback_t *)pvPortMalloc (sizeof(TimerCallback_t));
+
+        if (callb != NULL) {
+          /* Callback memory was allocated from dynamic pool, set flag */
+          callb_dyn = 1U;
+        }
+      }
+    #endif
+
+    if (callb != NULL) {
+      callb->func = func;
+      callb->arg  = argument;
+
+      if (type == osTimerOnce) {
+        reload = pdFALSE;
+      } else {
+        reload = pdTRUE;
+      }
+
+      mem  = -1;
+      name = NULL;
+
+      if (attr != NULL) {
+        if (attr->name != NULL) {
+          name = attr->name;
+        }
+
+        if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticTimer_t))) {
+          /* The memory for control block is provided, use static object */
+          mem = 1;
+        }
+        else {
+          if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
+            /* Control block will be allocated from the dynamic pool */
+            mem = 0;
+          }
+        }
+      }
+      else {
+        mem = 0;
+      }
+      /* Store callback memory dynamic allocation flag */
+      callb = (TimerCallback_t *)((uint32_t)callb | callb_dyn);
+      /*
+        TimerCallback function is always provided as a callback and is used to call application
+        specified function with its argument both stored in structure callb.
+      */
+      if (mem == 1) {
+        #if (configSUPPORT_STATIC_ALLOCATION == 1)
+          hTimer = xTimerCreateStatic (name, 1, reload, callb, TimerCallback, (StaticTimer_t *)attr->cb_mem);
+        #endif
+      }
+      else {
+        if (mem == 0) {
+          #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+            hTimer = xTimerCreate (name, 1, reload, callb, TimerCallback);
+          #endif
+        }
+      }
+
+      #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+      if ((hTimer == NULL) && (callb != NULL) && (callb_dyn == 1U)) {
+        /* Failed to create a timer, release allocated resources */
+        callb = (TimerCallback_t *)((uint32_t)callb & ~1U);
+
+        vPortFree (callb);
+      }
+      #endif
+    }
+  }
+
+  /* Return timer ID */
+  return ((osTimerId_t)hTimer);
+}
+
+/*
+  Get name of a timer.
+*/
+const char *osTimerGetName (osTimerId_t timer_id) {
+  TimerHandle_t hTimer = (TimerHandle_t)timer_id;
+  const char *p;
+
+  if ((IRQ_Context() != 0U) || (hTimer == NULL)) {
+    p = NULL;
+  } else {
+    p = pcTimerGetName (hTimer);
+  }
+
+  /* Return name as null-terminated string */
+  return (p);
+}
+
+/*
+  Start or restart a timer.
+*/
+osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks) {
+  TimerHandle_t hTimer = (TimerHandle_t)timer_id;
+  osStatus_t stat;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hTimer == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    if (xTimerChangePeriod (hTimer, ticks, 0) == pdPASS) {
+      stat = osOK;
+    } else {
+      stat = osErrorResource;
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Stop a timer.
+*/
+osStatus_t osTimerStop (osTimerId_t timer_id) {
+  TimerHandle_t hTimer = (TimerHandle_t)timer_id;
+  osStatus_t stat;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hTimer == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    if (xTimerIsTimerActive (hTimer) == pdFALSE) {
+      stat = osErrorResource;
+    }
+    else {
+      if (xTimerStop (hTimer, 0) == pdPASS) {
+        stat = osOK;
+      } else {
+        stat = osError;
+      }
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Check if a timer is running.
+*/
+uint32_t osTimerIsRunning (osTimerId_t timer_id) {
+  TimerHandle_t hTimer = (TimerHandle_t)timer_id;
+  uint32_t running;
+
+  if ((IRQ_Context() != 0U) || (hTimer == NULL)) {
+    running = 0U;
+  } else {
+    running = (uint32_t)xTimerIsTimerActive (hTimer);
+  }
+
+  /* Return 0: not running, 1: running */
+  return (running);
+}
+
+/*
+  Delete a timer.
+*/
+osStatus_t osTimerDelete (osTimerId_t timer_id) {
+  TimerHandle_t hTimer = (TimerHandle_t)timer_id;
+  osStatus_t stat;
+#ifndef USE_FreeRTOS_HEAP_1
+#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+  TimerCallback_t *callb;
+#endif
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hTimer == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+    callb = (TimerCallback_t *)pvTimerGetTimerID (hTimer);
+    #endif
+
+    if (xTimerDelete (hTimer, 0) == pdPASS) {
+      #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+        if ((uint32_t)callb & 1U) {
+          /* Callback memory was allocated from dynamic pool, clear flag */
+          callb = (TimerCallback_t *)((uint32_t)callb & ~1U);
+
+          /* Return allocated memory to dynamic pool */
+          vPortFree (callb);
+        }
+      #endif
+      stat = osOK;
+    } else {
+      stat = osErrorResource;
+    }
+  }
+#else
+  stat = osError;
+#endif
+
+  /* Return execution status */
+  return (stat);
+}
+#endif /* (configUSE_OS2_TIMER == 1) */
+
+
+/* ==== Event Flags Management Functions ==== */
+
+/*
+  Create and Initialize an Event Flags object.
+
+  Limitations:
+  - Event flags are limited to 24 bits.
+*/
+osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr) {
+  EventGroupHandle_t hEventGroup;
+  int32_t mem;
+
+  hEventGroup = NULL;
+
+  if (IRQ_Context() == 0U) {
+    mem = -1;
+
+    if (attr != NULL) {
+      if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticEventGroup_t))) {
+        /* The memory for control block is provided, use static object */
+        mem = 1;
+      }
+      else {
+        if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
+          /* Control block will be allocated from the dynamic pool */
+          mem = 0;
+        }
+      }
+    }
+    else {
+      mem = 0;
+    }
+
+    if (mem == 1) {
+      #if (configSUPPORT_STATIC_ALLOCATION == 1)
+      hEventGroup = xEventGroupCreateStatic (attr->cb_mem);
+      #endif
+    }
+    else {
+      if (mem == 0) {
+        #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+          hEventGroup = xEventGroupCreate();
+        #endif
+      }
+    }
+  }
+
+  /* Return event flags ID */
+  return ((osEventFlagsId_t)hEventGroup);
+}
+
+/*
+  Set the specified Event Flags.
+
+  Limitations:
+  - Event flags are limited to 24 bits.
+*/
+uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
+  EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
+  uint32_t rflags;
+  BaseType_t yield;
+
+  if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
+    rflags = (uint32_t)osErrorParameter;
+  }
+  else if (IRQ_Context() != 0U) {
+  #if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
+    (void)yield;
+    /* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */
+    rflags = (uint32_t)osErrorResource;
+  #else
+    yield = pdFALSE;
+
+    if (xEventGroupSetBitsFromISR (hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) {
+      rflags = (uint32_t)osErrorResource;
+    } else {
+      rflags = flags;
+      portYIELD_FROM_ISR (yield);
+    }
+  #endif
+  }
+  else {
+    rflags = xEventGroupSetBits (hEventGroup, (EventBits_t)flags);
+  }
+
+  /* Return event flags after setting */
+  return (rflags);
+}
+
+/*
+  Clear the specified Event Flags.
+
+  Limitations:
+  - Event flags are limited to 24 bits.
+*/
+uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) {
+  EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
+  uint32_t rflags;
+
+  if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
+    rflags = (uint32_t)osErrorParameter;
+  }
+  else if (IRQ_Context() != 0U) {
+  #if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
+    /* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */
+    rflags = (uint32_t)osErrorResource;
+  #else
+    rflags = xEventGroupGetBitsFromISR (hEventGroup);
+
+    if (xEventGroupClearBitsFromISR (hEventGroup, (EventBits_t)flags) == pdFAIL) {
+      rflags = (uint32_t)osErrorResource;
+    }
+    else {
+      /* xEventGroupClearBitsFromISR only registers clear operation in the timer command queue. */
+      /* Yield is required here otherwise clear operation might not execute in the right order. */
+      /* See https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/93 for more info.               */
+      portYIELD_FROM_ISR (pdTRUE);
+    }
+  #endif
+  }
+  else {
+    rflags = xEventGroupClearBits (hEventGroup, (EventBits_t)flags);
+  }
+
+  /* Return event flags before clearing */
+  return (rflags);
+}
+
+/*
+  Get the current Event Flags.
+
+  Limitations:
+  - Event flags are limited to 24 bits.
+*/
+uint32_t osEventFlagsGet (osEventFlagsId_t ef_id) {
+  EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
+  uint32_t rflags;
+
+  if (ef_id == NULL) {
+    rflags = 0U;
+  }
+  else if (IRQ_Context() != 0U) {
+    rflags = xEventGroupGetBitsFromISR (hEventGroup);
+  }
+  else {
+    rflags = xEventGroupGetBits (hEventGroup);
+  }
+
+  /* Return current event flags */
+  return (rflags);
+}
+
+/*
+  Wait for one or more Event Flags to become signaled.
+
+  Limitations:
+  - Event flags are limited to 24 bits.
+  - osEventFlagsWait cannot be called from an ISR.
+*/
+uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
+  EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
+  BaseType_t wait_all;
+  BaseType_t exit_clr;
+  uint32_t rflags;
+
+  if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
+    rflags = (uint32_t)osErrorParameter;
+  }
+  else if (IRQ_Context() != 0U) {
+    rflags = (uint32_t)osErrorISR;
+  }
+  else {
+    if (options & osFlagsWaitAll) {
+      wait_all = pdTRUE;
+    } else {
+      wait_all = pdFAIL;
+    }
+
+    if (options & osFlagsNoClear) {
+      exit_clr = pdFAIL;
+    } else {
+      exit_clr = pdTRUE;
+    }
+
+    rflags = xEventGroupWaitBits (hEventGroup, (EventBits_t)flags, exit_clr, wait_all, (TickType_t)timeout);
+
+    if (options & osFlagsWaitAll) {
+      if ((flags & rflags) != flags) {
+        if (timeout > 0U) {
+          rflags = (uint32_t)osErrorTimeout;
+        } else {
+          rflags = (uint32_t)osErrorResource;
+        }
+      }
+    }
+    else {
+      if ((flags & rflags) == 0U) {
+        if (timeout > 0U) {
+          rflags = (uint32_t)osErrorTimeout;
+        } else {
+          rflags = (uint32_t)osErrorResource;
+        }
+      }
+    }
+  }
+
+  /* Return event flags before clearing */
+  return (rflags);
+}
+
+/*
+  Delete an Event Flags object.
+*/
+osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id) {
+  EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
+  osStatus_t stat;
+
+#ifndef USE_FreeRTOS_HEAP_1
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hEventGroup == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    stat = osOK;
+    vEventGroupDelete (hEventGroup);
+  }
+#else
+  stat = osError;
+#endif
+
+  /* Return execution status */
+  return (stat);
+}
+
+
+/* ==== Mutex Management Functions ==== */
+
+#if (configUSE_OS2_MUTEX == 1)
+/*
+  Create and Initialize a Mutex object.
+
+  Limitations:
+  - Priority inherit protocol is used by default, osMutexPrioInherit attribute is ignored.
+  - Robust mutex is not supported, NULL is returned if used.
+*/
+osMutexId_t osMutexNew (const osMutexAttr_t *attr) {
+  SemaphoreHandle_t hMutex;
+  uint32_t type;
+  uint32_t rmtx;
+  int32_t  mem;
+
+  hMutex = NULL;
+
+  if (IRQ_Context() == 0U) {
+    if (attr != NULL) {
+      type = attr->attr_bits;
+    } else {
+      type = 0U;
+    }
+
+    if ((type & osMutexRecursive) == osMutexRecursive) {
+      rmtx = 1U;
+    } else {
+      rmtx = 0U;
+    }
+
+    if ((type & osMutexRobust) != osMutexRobust) {
+      mem = -1;
+
+      if (attr != NULL) {
+        if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) {
+          /* The memory for control block is provided, use static object */
+          mem = 1;
+        }
+        else {
+          if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
+            /* Control block will be allocated from the dynamic pool */
+            mem = 0;
+          }
+        }
+      }
+      else {
+        mem = 0;
+      }
+
+      if (mem == 1) {
+        #if (configSUPPORT_STATIC_ALLOCATION == 1)
+          if (rmtx != 0U) {
+            #if (configUSE_RECURSIVE_MUTEXES == 1)
+            hMutex = xSemaphoreCreateRecursiveMutexStatic (attr->cb_mem);
+            #endif
+          }
+          else {
+            hMutex = xSemaphoreCreateMutexStatic (attr->cb_mem);
+          }
+        #endif
+      }
+      else {
+        if (mem == 0) {
+          #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+            if (rmtx != 0U) {
+              #if (configUSE_RECURSIVE_MUTEXES == 1)
+              hMutex = xSemaphoreCreateRecursiveMutex ();
+              #endif
+            } else {
+              hMutex = xSemaphoreCreateMutex ();
+            }
+          #endif
+        }
+      }
+
+      #if (configQUEUE_REGISTRY_SIZE > 0)
+      if (hMutex != NULL) {
+        if ((attr != NULL) && (attr->name != NULL)) {
+          /* Only non-NULL name objects are added to the Queue Registry */
+          vQueueAddToRegistry (hMutex, attr->name);
+        }
+      }
+      #endif
+
+      if ((hMutex != NULL) && (rmtx != 0U)) {
+        /* Set LSB as 'recursive mutex flag' */
+        hMutex = (SemaphoreHandle_t)((uint32_t)hMutex | 1U);
+      }
+    }
+  }
+
+  /* Return mutex ID */
+  return ((osMutexId_t)hMutex);
+}
+
+/*
+  Acquire a Mutex or timeout if it is locked.
+*/
+osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
+  SemaphoreHandle_t hMutex;
+  osStatus_t stat;
+  uint32_t rmtx;
+
+  hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
+
+  /* Extract recursive mutex flag */
+  rmtx = (uint32_t)mutex_id & 1U;
+
+  stat = osOK;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hMutex == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    if (rmtx != 0U) {
+      #if (configUSE_RECURSIVE_MUTEXES == 1)
+      if (xSemaphoreTakeRecursive (hMutex, timeout) != pdPASS) {
+        if (timeout != 0U) {
+          stat = osErrorTimeout;
+        } else {
+          stat = osErrorResource;
+        }
+      }
+      #endif
+    }
+    else {
+      if (xSemaphoreTake (hMutex, timeout) != pdPASS) {
+        if (timeout != 0U) {
+          stat = osErrorTimeout;
+        } else {
+          stat = osErrorResource;
+        }
+      }
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Release a Mutex that was acquired by osMutexAcquire.
+*/
+osStatus_t osMutexRelease (osMutexId_t mutex_id) {
+  SemaphoreHandle_t hMutex;
+  osStatus_t stat;
+  uint32_t rmtx;
+
+  hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
+
+  /* Extract recursive mutex flag */
+  rmtx = (uint32_t)mutex_id & 1U;
+
+  stat = osOK;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hMutex == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    if (rmtx != 0U) {
+      #if (configUSE_RECURSIVE_MUTEXES == 1)
+      if (xSemaphoreGiveRecursive (hMutex) != pdPASS) {
+        stat = osErrorResource;
+      }
+      #endif
+    }
+    else {
+      if (xSemaphoreGive (hMutex) != pdPASS) {
+        stat = osErrorResource;
+      }
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Get Thread which owns a Mutex object.
+*/
+osThreadId_t osMutexGetOwner (osMutexId_t mutex_id) {
+  SemaphoreHandle_t hMutex;
+  osThreadId_t owner;
+
+  hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
+
+  if ((IRQ_Context() != 0U) || (hMutex == NULL)) {
+    owner = NULL;
+  } else {
+    owner = (osThreadId_t)xSemaphoreGetMutexHolder (hMutex);
+  }
+
+  /* Return owner thread ID */
+  return (owner);
+}
+
+/*
+  Delete a Mutex object.
+*/
+osStatus_t osMutexDelete (osMutexId_t mutex_id) {
+  osStatus_t stat;
+#ifndef USE_FreeRTOS_HEAP_1
+  SemaphoreHandle_t hMutex;
+
+  hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U);
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hMutex == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    #if (configQUEUE_REGISTRY_SIZE > 0)
+    vQueueUnregisterQueue (hMutex);
+    #endif
+    stat = osOK;
+    vSemaphoreDelete (hMutex);
+  }
+#else
+  stat = osError;
+#endif
+
+  /* Return execution status */
+  return (stat);
+}
+#endif /* (configUSE_OS2_MUTEX == 1) */
+
+
+/* ==== Semaphore Management Functions ==== */
+
+/*
+  Create and Initialize a Semaphore object.
+*/
+osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) {
+  SemaphoreHandle_t hSemaphore;
+  int32_t mem;
+
+  hSemaphore = NULL;
+
+  if ((IRQ_Context() == 0U) && (max_count > 0U) && (initial_count <= max_count)) {
+    mem = -1;
+
+    if (attr != NULL) {
+      if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) {
+        /* The memory for control block is provided, use static object */
+        mem = 1;
+      }
+      else {
+        if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
+          /* Control block will be allocated from the dynamic pool */
+          mem = 0;
+        }
+      }
+    }
+    else {
+      mem = 0;
+    }
+
+    if (mem != -1) {
+      if (max_count == 1U) {
+        if (mem == 1) {
+          #if (configSUPPORT_STATIC_ALLOCATION == 1)
+            hSemaphore = xSemaphoreCreateBinaryStatic ((StaticSemaphore_t *)attr->cb_mem);
+          #endif
+        }
+        else {
+          #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+            hSemaphore = xSemaphoreCreateBinary();
+          #endif
+        }
+
+        if ((hSemaphore != NULL) && (initial_count != 0U)) {
+          if (xSemaphoreGive (hSemaphore) != pdPASS) {
+            vSemaphoreDelete (hSemaphore);
+            hSemaphore = NULL;
+          }
+        }
+      }
+      else {
+        if (mem == 1) {
+          #if (configSUPPORT_STATIC_ALLOCATION == 1)
+            hSemaphore = xSemaphoreCreateCountingStatic (max_count, initial_count, (StaticSemaphore_t *)attr->cb_mem);
+          #endif
+        }
+        else {
+          #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+            hSemaphore = xSemaphoreCreateCounting (max_count, initial_count);
+          #endif
+        }
+      }
+      
+      #if (configQUEUE_REGISTRY_SIZE > 0)
+      if (hSemaphore != NULL) {
+        if ((attr != NULL) && (attr->name != NULL)) {
+          /* Only non-NULL name objects are added to the Queue Registry */
+          vQueueAddToRegistry (hSemaphore, attr->name);
+        }
+      }
+      #endif
+    }
+  }
+
+  /* Return semaphore ID */
+  return ((osSemaphoreId_t)hSemaphore);
+}
+
+/*
+  Acquire a Semaphore token or timeout if no tokens are available.
+*/
+osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) {
+  SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
+  osStatus_t stat;
+  BaseType_t yield;
+
+  stat = osOK;
+
+  if (hSemaphore == NULL) {
+    stat = osErrorParameter;
+  }
+  else if (IRQ_Context() != 0U) {
+    if (timeout != 0U) {
+      stat = osErrorParameter;
+    }
+    else {
+      yield = pdFALSE;
+
+      if (xSemaphoreTakeFromISR (hSemaphore, &yield) != pdPASS) {
+        stat = osErrorResource;
+      } else {
+        portYIELD_FROM_ISR (yield);
+      }
+    }
+  }
+  else {
+    if (xSemaphoreTake (hSemaphore, (TickType_t)timeout) != pdPASS) {
+      if (timeout != 0U) {
+        stat = osErrorTimeout;
+      } else {
+        stat = osErrorResource;
+      }
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Release a Semaphore token up to the initial maximum count.
+*/
+osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id) {
+  SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
+  osStatus_t stat;
+  BaseType_t yield;
+
+  stat = osOK;
+
+  if (hSemaphore == NULL) {
+    stat = osErrorParameter;
+  }
+  else if (IRQ_Context() != 0U) {
+    yield = pdFALSE;
+
+    if (xSemaphoreGiveFromISR (hSemaphore, &yield) != pdTRUE) {
+      stat = osErrorResource;
+    } else {
+      portYIELD_FROM_ISR (yield);
+    }
+  }
+  else {
+    if (xSemaphoreGive (hSemaphore) != pdPASS) {
+      stat = osErrorResource;
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Get current Semaphore token count.
+*/
+uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id) {
+  SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
+  uint32_t count;
+
+  if (hSemaphore == NULL) {
+    count = 0U;
+  }
+  else if (IRQ_Context() != 0U) {
+    count = (uint32_t)uxSemaphoreGetCountFromISR (hSemaphore);
+  } else {
+    count = (uint32_t)uxSemaphoreGetCount (hSemaphore);
+  }
+
+  /* Return number of tokens */
+  return (count);
+}
+
+/*
+  Delete a Semaphore object.
+*/
+osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id) {
+  SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id;
+  osStatus_t stat;
+
+#ifndef USE_FreeRTOS_HEAP_1
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hSemaphore == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    #if (configQUEUE_REGISTRY_SIZE > 0)
+    vQueueUnregisterQueue (hSemaphore);
+    #endif
+
+    stat = osOK;
+    vSemaphoreDelete (hSemaphore);
+  }
+#else
+  stat = osError;
+#endif
+
+  /* Return execution status */
+  return (stat);
+}
+
+
+/* ==== Message Queue Management Functions ==== */
+
+/*
+  Create and Initialize a Message Queue object.
+
+  Limitations:
+  - The memory for control block and and message data must be provided in the
+    osThreadAttr_t structure in order to allocate object statically.
+*/
+osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
+  QueueHandle_t hQueue;
+  int32_t mem;
+
+  hQueue = NULL;
+
+  if ((IRQ_Context() == 0U) && (msg_count > 0U) && (msg_size > 0U)) {
+    mem = -1;
+
+    if (attr != NULL) {
+      if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticQueue_t)) &&
+          (attr->mq_mem != NULL) && (attr->mq_size >= (msg_count * msg_size))) {
+        /* The memory for control block and message data is provided, use static object */
+        mem = 1;
+      }
+      else {
+        if ((attr->cb_mem == NULL) && (attr->cb_size == 0U) &&
+            (attr->mq_mem == NULL) && (attr->mq_size == 0U)) {
+          /* Control block will be allocated from the dynamic pool */
+          mem = 0;
+        }
+      }
+    }
+    else {
+      mem = 0;
+    }
+
+    if (mem == 1) {
+      #if (configSUPPORT_STATIC_ALLOCATION == 1)
+        hQueue = xQueueCreateStatic (msg_count, msg_size, attr->mq_mem, attr->cb_mem);
+      #endif
+    }
+    else {
+      if (mem == 0) {
+        #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+          hQueue = xQueueCreate (msg_count, msg_size);
+        #endif
+      }
+    }
+
+    #if (configQUEUE_REGISTRY_SIZE > 0)
+    if (hQueue != NULL) {
+      if ((attr != NULL) && (attr->name != NULL)) {
+        /* Only non-NULL name objects are added to the Queue Registry */
+        vQueueAddToRegistry (hQueue, attr->name);
+      }
+    }
+    #endif
+
+  }
+
+  /* Return message queue ID */
+  return ((osMessageQueueId_t)hQueue);
+}
+
+/*
+  Put a Message into a Queue or timeout if Queue is full.
+
+  Limitations:
+  - Message priority is ignored
+*/
+osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
+  QueueHandle_t hQueue = (QueueHandle_t)mq_id;
+  osStatus_t stat;
+  BaseType_t yield;
+
+  (void)msg_prio; /* Message priority is ignored */
+
+  stat = osOK;
+
+  if (IRQ_Context() != 0U) {
+    if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
+      stat = osErrorParameter;
+    }
+    else {
+      yield = pdFALSE;
+
+      if (xQueueSendToBackFromISR (hQueue, msg_ptr, &yield) != pdTRUE) {
+        stat = osErrorResource;
+      } else {
+        portYIELD_FROM_ISR (yield);
+      }
+    }
+  }
+  else {
+    if ((hQueue == NULL) || (msg_ptr == NULL)) {
+      stat = osErrorParameter;
+    }
+    else {
+      if (xQueueSendToBack (hQueue, msg_ptr, (TickType_t)timeout) != pdPASS) {
+        if (timeout != 0U) {
+          stat = osErrorTimeout;
+        } else {
+          stat = osErrorResource;
+        }
+      }
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Get a Message from a Queue or timeout if Queue is empty.
+
+  Limitations:
+  - Message priority is ignored
+*/
+osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
+  QueueHandle_t hQueue = (QueueHandle_t)mq_id;
+  osStatus_t stat;
+  BaseType_t yield;
+
+  (void)msg_prio; /* Message priority is ignored */
+
+  stat = osOK;
+
+  if (IRQ_Context() != 0U) {
+    if ((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) {
+      stat = osErrorParameter;
+    }
+    else {
+      yield = pdFALSE;
+
+      if (xQueueReceiveFromISR (hQueue, msg_ptr, &yield) != pdPASS) {
+        stat = osErrorResource;
+      } else {
+        portYIELD_FROM_ISR (yield);
+      }
+    }
+  }
+  else {
+    if ((hQueue == NULL) || (msg_ptr == NULL)) {
+      stat = osErrorParameter;
+    }
+    else {
+      if (xQueueReceive (hQueue, msg_ptr, (TickType_t)timeout) != pdPASS) {
+        if (timeout != 0U) {
+          stat = osErrorTimeout;
+        } else {
+          stat = osErrorResource;
+        }
+      }
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Get maximum number of messages in a Message Queue.
+*/
+uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id) {
+  StaticQueue_t *mq = (StaticQueue_t *)mq_id;
+  uint32_t capacity;
+
+  if (mq == NULL) {
+    capacity = 0U;
+  } else {
+    /* capacity = pxQueue->uxLength */
+    capacity = mq->uxDummy4[1];
+  }
+
+  /* Return maximum number of messages */
+  return (capacity);
+}
+
+/*
+  Get maximum message size in a Message Queue.
+*/
+uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id) {
+  StaticQueue_t *mq = (StaticQueue_t *)mq_id;
+  uint32_t size;
+
+  if (mq == NULL) {
+    size = 0U;
+  } else {
+    /* size = pxQueue->uxItemSize */
+    size = mq->uxDummy4[2];
+  }
+
+  /* Return maximum message size */
+  return (size);
+}
+
+/*
+  Get number of queued messages in a Message Queue.
+*/
+uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id) {
+  QueueHandle_t hQueue = (QueueHandle_t)mq_id;
+  UBaseType_t count;
+
+  if (hQueue == NULL) {
+    count = 0U;
+  }
+  else if (IRQ_Context() != 0U) {
+    count = uxQueueMessagesWaitingFromISR (hQueue);
+  }
+  else {
+    count = uxQueueMessagesWaiting (hQueue);
+  }
+
+  /* Return number of queued messages */
+  return ((uint32_t)count);
+}
+
+/*
+  Get number of available slots for messages in a Message Queue.
+*/
+uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id) {
+  StaticQueue_t *mq = (StaticQueue_t *)mq_id;
+  uint32_t space;
+  uint32_t isrm;
+
+  if (mq == NULL) {
+    space = 0U;
+  }
+  else if (IRQ_Context() != 0U) {
+    isrm = taskENTER_CRITICAL_FROM_ISR();
+
+    /* space = pxQueue->uxLength - pxQueue->uxMessagesWaiting; */
+    space = mq->uxDummy4[1] - mq->uxDummy4[0];
+
+    taskEXIT_CRITICAL_FROM_ISR(isrm);
+  }
+  else {
+    space = (uint32_t)uxQueueSpacesAvailable ((QueueHandle_t)mq);
+  }
+
+  /* Return number of available slots */
+  return (space);
+}
+
+/*
+  Reset a Message Queue to initial empty state.
+*/
+osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id) {
+  QueueHandle_t hQueue = (QueueHandle_t)mq_id;
+  osStatus_t stat;
+
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hQueue == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    stat = osOK;
+    (void)xQueueReset (hQueue);
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Delete a Message Queue object.
+*/
+osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) {
+  QueueHandle_t hQueue = (QueueHandle_t)mq_id;
+  osStatus_t stat;
+
+#ifndef USE_FreeRTOS_HEAP_1
+  if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else if (hQueue == NULL) {
+    stat = osErrorParameter;
+  }
+  else {
+    #if (configQUEUE_REGISTRY_SIZE > 0)
+    vQueueUnregisterQueue (hQueue);
+    #endif
+
+    stat = osOK;
+    vQueueDelete (hQueue);
+  }
+#else
+  stat = osError;
+#endif
+
+  /* Return execution status */
+  return (stat);
+}
+
+
+/* ==== Memory Pool Management Functions ==== */
+
+#ifdef FREERTOS_MPOOL_H_
+/* Static memory pool functions */
+static void  FreeBlock   (MemPool_t *mp, void *block);
+static void *AllocBlock  (MemPool_t *mp);
+static void *CreateBlock (MemPool_t *mp);
+
+/*
+  Create and Initialize a Memory Pool object.
+*/
+osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
+  MemPool_t *mp;
+  const char *name;
+  int32_t mem_cb, mem_mp;
+  uint32_t sz;
+
+  if (IRQ_Context() != 0U) {
+    mp = NULL;
+  }
+  else if ((block_count == 0U) || (block_size == 0U)) {
+    mp = NULL;
+  }
+  else {
+    mp = NULL;
+    sz = MEMPOOL_ARR_SIZE (block_count, block_size);
+
+    name = NULL;
+    mem_cb = -1;
+    mem_mp = -1;
+
+    if (attr != NULL) {
+      if (attr->name != NULL) {
+        name = attr->name;
+      }
+
+      if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(MemPool_t))) {
+        /* Static control block is provided */
+        mem_cb = 1;
+      }
+      else if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
+        /* Allocate control block memory on heap */
+        mem_cb = 0;
+      }
+
+      if ((attr->mp_mem == NULL) && (attr->mp_size == 0U)) {
+        /* Allocate memory array on heap */
+          mem_mp = 0;
+      }
+      else {
+        if (attr->mp_mem != NULL) {
+          /* Check if array is 4-byte aligned */
+          if (((uint32_t)attr->mp_mem & 3U) == 0U) {
+            /* Check if array big enough */
+            if (attr->mp_size >= sz) {
+              /* Static memory pool array is provided */
+              mem_mp = 1;
+            }
+          }
+        }
+      }
+    }
+    else {
+      /* Attributes not provided, allocate memory on heap */
+      mem_cb = 0;
+      mem_mp = 0;
+    }
+
+    if (mem_cb == 0) {
+      mp = pvPortMalloc (sizeof(MemPool_t));
+    } else {
+      mp = attr->cb_mem;
+    }
+
+    if (mp != NULL) {
+      /* Create a semaphore (max count == initial count == block_count) */
+      #if (configSUPPORT_STATIC_ALLOCATION == 1)
+        mp->sem = xSemaphoreCreateCountingStatic (block_count, block_count, &mp->mem_sem);
+      #elif (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+        mp->sem = xSemaphoreCreateCounting (block_count, block_count);
+      #else
+        mp->sem = NULL;
+      #endif
+
+      if (mp->sem != NULL) {
+        /* Setup memory array */
+        if (mem_mp == 0) {
+          mp->mem_arr = pvPortMalloc (sz);
+        } else {
+          mp->mem_arr = attr->mp_mem;
+        }
+      }
+    }
+
+    if ((mp != NULL) && (mp->mem_arr != NULL)) {
+      /* Memory pool can be created */
+      mp->head    = NULL;
+      mp->mem_sz  = sz;
+      mp->name    = name;
+      mp->bl_sz   = block_size;
+      mp->bl_cnt  = block_count;
+      mp->n       = 0U;
+
+      /* Set heap allocated memory flags */
+      mp->status = MPOOL_STATUS;
+
+      if (mem_cb == 0) {
+        /* Control block on heap */
+        mp->status |= 1U;
+      }
+      if (mem_mp == 0) {
+        /* Memory array on heap */
+        mp->status |= 2U;
+      }
+    }
+    else {
+      /* Memory pool cannot be created, release allocated resources */
+      if ((mem_cb == 0) && (mp != NULL)) {
+        /* Free control block memory */
+        vPortFree (mp);
+      }
+      mp = NULL;
+    }
+  }
+
+  /* Return memory pool ID */
+  return (mp);
+}
+
+/*
+  Get name of a Memory Pool object.
+*/
+const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) {
+  MemPool_t *mp = (osMemoryPoolId_t)mp_id;
+  const char *p;
+
+  if (IRQ_Context() != 0U) {
+    p = NULL;
+  }
+  else if (mp_id == NULL) {
+    p = NULL;
+  }
+  else {
+    p = mp->name;
+  }
+
+  /* Return name as null-terminated string */
+  return (p);
+}
+
+/*
+  Allocate a memory block from a Memory Pool.
+*/
+void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
+  MemPool_t *mp;
+  void *block;
+  uint32_t isrm;
+
+  if (mp_id == NULL) {
+    /* Invalid input parameters */
+    block = NULL;
+  }
+  else {
+    block = NULL;
+
+    mp = (MemPool_t *)mp_id;
+
+    if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) {
+      if (IRQ_Context() != 0U) {
+        if (timeout == 0U) {
+          if (xSemaphoreTakeFromISR (mp->sem, NULL) == pdTRUE) {
+            if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) {
+              isrm  = taskENTER_CRITICAL_FROM_ISR();
+
+              /* Get a block from the free-list */
+              block = AllocBlock(mp);
+
+              if (block == NULL) {
+                /* List of free blocks is empty, 'create' new block */
+                block = CreateBlock(mp);
+              }
+
+              taskEXIT_CRITICAL_FROM_ISR(isrm);
+            }
+          }
+        }
+      }
+      else {
+        if (xSemaphoreTake (mp->sem, (TickType_t)timeout) == pdTRUE) {
+          if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) {
+            taskENTER_CRITICAL();
+
+            /* Get a block from the free-list */
+            block = AllocBlock(mp);
+
+            if (block == NULL) {
+              /* List of free blocks is empty, 'create' new block */
+              block = CreateBlock(mp);
+            }
+
+            taskEXIT_CRITICAL();
+          }
+        }
+      }
+    }
+  }
+
+  /* Return memory block address */
+  return (block);
+}
+
+/*
+  Return an allocated memory block back to a Memory Pool.
+*/
+osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
+  MemPool_t *mp;
+  osStatus_t stat;
+  uint32_t isrm;
+  BaseType_t yield;
+
+  if ((mp_id == NULL) || (block == NULL)) {
+    /* Invalid input parameters */
+    stat = osErrorParameter;
+  }
+  else {
+    mp = (MemPool_t *)mp_id;
+
+    if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
+      /* Invalid object status */
+      stat = osErrorResource;
+    }
+    else if ((block < (void *)&mp->mem_arr[0]) || (block > (void*)&mp->mem_arr[mp->mem_sz-1])) {
+      /* Block pointer outside of memory array area */
+      stat = osErrorParameter;
+    }
+    else {
+      stat = osOK;
+
+      if (IRQ_Context() != 0U) {
+        if (uxSemaphoreGetCountFromISR (mp->sem) == mp->bl_cnt) {
+          stat = osErrorResource;
+        }
+        else {
+          isrm = taskENTER_CRITICAL_FROM_ISR();
+
+          /* Add block to the list of free blocks */
+          FreeBlock(mp, block);
+
+          taskEXIT_CRITICAL_FROM_ISR(isrm);
+
+          yield = pdFALSE;
+          xSemaphoreGiveFromISR (mp->sem, &yield);
+          portYIELD_FROM_ISR (yield);
+        }
+      }
+      else {
+        if (uxSemaphoreGetCount (mp->sem) == mp->bl_cnt) {
+          stat = osErrorResource;
+        }
+        else {
+          taskENTER_CRITICAL();
+
+          /* Add block to the list of free blocks */
+          FreeBlock(mp, block);
+
+          taskEXIT_CRITICAL();
+
+          xSemaphoreGive (mp->sem);
+        }
+      }
+    }
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Get maximum number of memory blocks in a Memory Pool.
+*/
+uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
+  MemPool_t *mp;
+  uint32_t  n;
+
+  if (mp_id == NULL) {
+    /* Invalid input parameters */
+    n = 0U;
+  }
+  else {
+    mp = (MemPool_t *)mp_id;
+
+    if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
+      /* Invalid object status */
+      n = 0U;
+    }
+    else {
+      n = mp->bl_cnt;
+    }
+  }
+
+  /* Return maximum number of memory blocks */
+  return (n);
+}
+
+/*
+  Get memory block size in a Memory Pool.
+*/
+uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
+  MemPool_t *mp;
+  uint32_t  sz;
+
+  if (mp_id == NULL) {
+    /* Invalid input parameters */
+    sz = 0U;
+  }
+  else {
+    mp = (MemPool_t *)mp_id;
+
+    if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
+      /* Invalid object status */
+      sz = 0U;
+    }
+    else {
+      sz = mp->bl_sz;
+    }
+  }
+
+  /* Return memory block size in bytes */
+  return (sz);
+}
+
+/*
+  Get number of memory blocks used in a Memory Pool.
+*/
+uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
+  MemPool_t *mp;
+  uint32_t  n;
+
+  if (mp_id == NULL) {
+    /* Invalid input parameters */
+    n = 0U;
+  }
+  else {
+    mp = (MemPool_t *)mp_id;
+
+    if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
+      /* Invalid object status */
+      n = 0U;
+    }
+    else {
+      if (IRQ_Context() != 0U) {
+        n = uxSemaphoreGetCountFromISR (mp->sem);
+      } else {
+        n = uxSemaphoreGetCount        (mp->sem);
+      }
+
+      n = mp->bl_cnt - n;
+    }
+  }
+
+  /* Return number of memory blocks used */
+  return (n);
+}
+
+/*
+  Get number of memory blocks available in a Memory Pool.
+*/
+uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
+  MemPool_t *mp;
+  uint32_t  n;
+
+  if (mp_id == NULL) {
+    /* Invalid input parameters */
+    n = 0U;
+  }
+  else {
+    mp = (MemPool_t *)mp_id;
+
+    if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) {
+      /* Invalid object status */
+      n = 0U;
+    }
+    else {
+      if (IRQ_Context() != 0U) {
+        n = uxSemaphoreGetCountFromISR (mp->sem);
+      } else {
+        n = uxSemaphoreGetCount        (mp->sem);
+      }
+    }
+  }
+
+  /* Return number of memory blocks available */
+  return (n);
+}
+
+/*
+  Delete a Memory Pool object.
+*/
+osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) {
+  MemPool_t *mp;
+  osStatus_t stat;
+
+  if (mp_id == NULL) {
+    /* Invalid input parameters */
+    stat = osErrorParameter;
+  }
+  else if (IRQ_Context() != 0U) {
+    stat = osErrorISR;
+  }
+  else {
+    mp = (MemPool_t *)mp_id;
+
+    taskENTER_CRITICAL();
+
+    /* Invalidate control block status */
+    mp->status  = mp->status & 3U;
+
+    /* Wake-up tasks waiting for pool semaphore */
+    while (xSemaphoreGive (mp->sem) == pdTRUE);
+
+    mp->head    = NULL;
+    mp->bl_sz   = 0U;
+    mp->bl_cnt  = 0U;
+
+    if ((mp->status & 2U) != 0U) {
+      /* Memory pool array allocated on heap */
+      vPortFree (mp->mem_arr);
+    }
+    if ((mp->status & 1U) != 0U) {
+      /* Memory pool control block allocated on heap */
+      vPortFree (mp);
+    }
+
+    taskEXIT_CRITICAL();
+
+    stat = osOK;
+  }
+
+  /* Return execution status */
+  return (stat);
+}
+
+/*
+  Create new block given according to the current block index.
+*/
+static void *CreateBlock (MemPool_t *mp) {
+  MemPoolBlock_t *p = NULL;
+
+  if (mp->n < mp->bl_cnt) {
+    /* Unallocated blocks exist, set pointer to new block */
+    p = (void *)(mp->mem_arr + (mp->bl_sz * mp->n));
+
+    /* Increment block index */
+    mp->n += 1U;
+  }
+
+  return (p);
+}
+
+/*
+  Allocate a block by reading the list of free blocks.
+*/
+static void *AllocBlock (MemPool_t *mp) {
+  MemPoolBlock_t *p = NULL;
+
+  if (mp->head != NULL) {
+    /* List of free block exists, get head block */
+    p = mp->head;
+
+    /* Head block is now next on the list */
+    mp->head = p->next;
+  }
+
+  return (p);
+}
+
+/*
+  Free block by putting it to the list of free blocks.
+*/
+static void FreeBlock (MemPool_t *mp, void *block) {
+  MemPoolBlock_t *p = block;
+
+  /* Store current head into block memory space */
+  p->next = mp->head;
+
+  /* Store current block as new head */
+  mp->head = p;
+}
+#endif /* FREERTOS_MPOOL_H_ */
+/*---------------------------------------------------------------------------*/
+
+/* Callback function prototypes */
+extern void vApplicationIdleHook (void);
+extern void vApplicationMallocFailedHook (void);
+extern void vApplicationDaemonTaskStartupHook (void);
+
+/**
+  Dummy implementation of the callback function vApplicationIdleHook().
+*/
+#if (configUSE_IDLE_HOOK == 1)
+__WEAK void vApplicationIdleHook (void){}
+#endif
+
+/**
+  Dummy implementation of the callback function vApplicationTickHook().
+*/
+#if (configUSE_TICK_HOOK == 1)
+ __WEAK void vApplicationTickHook (void){}
+#endif
+
+/**
+  Dummy implementation of the callback function vApplicationMallocFailedHook().
+*/
+#if (configUSE_MALLOC_FAILED_HOOK == 1)
+__WEAK void vApplicationMallocFailedHook (void) {
+  /* Assert when malloc failed hook is enabled but no application defined function exists */
+  configASSERT(0);
+}
+#endif
+
+/**
+  Dummy implementation of the callback function vApplicationDaemonTaskStartupHook().
+*/
+#if (configUSE_DAEMON_TASK_STARTUP_HOOK == 1)
+__WEAK void vApplicationDaemonTaskStartupHook (void){}
+#endif
+
+/**
+  Dummy implementation of the callback function vApplicationStackOverflowHook().
+*/
+#if (configCHECK_FOR_STACK_OVERFLOW > 0)
+__WEAK void vApplicationStackOverflowHook (TaskHandle_t xTask, char *pcTaskName) {
+  (void)xTask;
+  (void)pcTaskName;
+
+  /* Assert when stack overflow is enabled but no application defined function exists */
+  configASSERT(0);
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+#if (configSUPPORT_STATIC_ALLOCATION == 1)
+/*
+  vApplicationGetIdleTaskMemory gets called when configSUPPORT_STATIC_ALLOCATION
+  equals to 1 and is required for static memory allocation support.
+*/
+__WEAK void vApplicationGetIdleTaskMemory (StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {
+  /* Idle task control block and stack */
+  static StaticTask_t Idle_TCB;
+  static StackType_t  Idle_Stack[configMINIMAL_STACK_SIZE];
+
+  *ppxIdleTaskTCBBuffer   = &Idle_TCB;
+  *ppxIdleTaskStackBuffer = &Idle_Stack[0];
+  *pulIdleTaskStackSize   = (uint32_t)configMINIMAL_STACK_SIZE;
+}
+
+/*
+  vApplicationGetTimerTaskMemory gets called when configSUPPORT_STATIC_ALLOCATION
+  equals to 1 and is required for static memory allocation support.
+*/
+__WEAK void vApplicationGetTimerTaskMemory (StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) {
+  /* Timer task control block and stack */
+  static StaticTask_t Timer_TCB;
+  static StackType_t  Timer_Stack[configTIMER_TASK_STACK_DEPTH];
+
+  *ppxTimerTaskTCBBuffer   = &Timer_TCB;
+  *ppxTimerTaskStackBuffer = &Timer_Stack[0];
+  *pulTimerTaskStackSize   = (uint32_t)configTIMER_TASK_STACK_DEPTH;
+}
+#endif

+ 756 - 0
lib/FreeRTOS-glue/cmsis_os2.h

@@ -0,0 +1,756 @@
+/*
+ * Copyright (c) 2013-2020 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ----------------------------------------------------------------------
+ *
+ * $Date:        12. June 2020
+ * $Revision:    V2.1.3
+ *
+ * Project:      CMSIS-RTOS2 API
+ * Title:        cmsis_os2.h header file
+ *
+ * Version 2.1.3
+ *    Additional functions allowed to be called from Interrupt Service Routines:
+ *    - osThreadGetId
+ * Version 2.1.2
+ *    Additional functions allowed to be called from Interrupt Service Routines:
+ *    - osKernelGetInfo, osKernelGetState
+ * Version 2.1.1
+ *    Additional functions allowed to be called from Interrupt Service Routines:
+ *    - osKernelGetTickCount, osKernelGetTickFreq
+ *    Changed Kernel Tick type to uint32_t:
+ *    - updated: osKernelGetTickCount, osDelayUntil
+ * Version 2.1.0
+ *    Support for critical and uncritical sections (nesting safe):
+ *    - updated: osKernelLock, osKernelUnlock
+ *    - added: osKernelRestoreLock
+ *    Updated Thread and Event Flags:
+ *    - changed flags parameter and return type from int32_t to uint32_t
+ * Version 2.0.0
+ *    Initial Release
+ *---------------------------------------------------------------------------*/
+ 
+#ifndef CMSIS_OS2_H_
+#define CMSIS_OS2_H_
+ 
+#ifndef __NO_RETURN
+#if   defined(__CC_ARM)
+#define __NO_RETURN __declspec(noreturn)
+#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+#define __NO_RETURN __attribute__((__noreturn__))
+#elif defined(__GNUC__)
+#define __NO_RETURN __attribute__((__noreturn__))
+#elif defined(__ICCARM__)
+#define __NO_RETURN __noreturn
+#else
+#define __NO_RETURN
+#endif
+#endif
+ 
+#include <stdint.h>
+#include <stddef.h>
+ 
+#ifdef  __cplusplus
+extern "C"
+{
+#endif
+ 
+ 
+//  ==== Enumerations, structures, defines ====
+ 
+/// Version information.
+typedef struct {
+  uint32_t                       api;   ///< API version (major.minor.rev: mmnnnrrrr dec).
+  uint32_t                    kernel;   ///< Kernel version (major.minor.rev: mmnnnrrrr dec).
+} osVersion_t;
+ 
+/// Kernel state.
+typedef enum {
+  osKernelInactive        =  0,         ///< Inactive.
+  osKernelReady           =  1,         ///< Ready.
+  osKernelRunning         =  2,         ///< Running.
+  osKernelLocked          =  3,         ///< Locked.
+  osKernelSuspended       =  4,         ///< Suspended.
+  osKernelError           = -1,         ///< Error.
+  osKernelReserved        = 0x7FFFFFFF  ///< Prevents enum down-size compiler optimization.
+} osKernelState_t;
+ 
+/// Thread state.
+typedef enum {
+  osThreadInactive        =  0,         ///< Inactive.
+  osThreadReady           =  1,         ///< Ready.
+  osThreadRunning         =  2,         ///< Running.
+  osThreadBlocked         =  3,         ///< Blocked.
+  osThreadTerminated      =  4,         ///< Terminated.
+  osThreadError           = -1,         ///< Error.
+  osThreadReserved        = 0x7FFFFFFF  ///< Prevents enum down-size compiler optimization.
+} osThreadState_t;
+ 
+/// Priority values.
+typedef enum {
+  osPriorityNone          =  0,         ///< No priority (not initialized).
+  osPriorityIdle          =  1,         ///< Reserved for Idle thread.
+  osPriorityLow           =  8,         ///< Priority: low
+  osPriorityLow1          =  8+1,       ///< Priority: low + 1
+  osPriorityLow2          =  8+2,       ///< Priority: low + 2
+  osPriorityLow3          =  8+3,       ///< Priority: low + 3
+  osPriorityLow4          =  8+4,       ///< Priority: low + 4
+  osPriorityLow5          =  8+5,       ///< Priority: low + 5
+  osPriorityLow6          =  8+6,       ///< Priority: low + 6
+  osPriorityLow7          =  8+7,       ///< Priority: low + 7
+  osPriorityBelowNormal   = 16,         ///< Priority: below normal
+  osPriorityBelowNormal1  = 16+1,       ///< Priority: below normal + 1
+  osPriorityBelowNormal2  = 16+2,       ///< Priority: below normal + 2
+  osPriorityBelowNormal3  = 16+3,       ///< Priority: below normal + 3
+  osPriorityBelowNormal4  = 16+4,       ///< Priority: below normal + 4
+  osPriorityBelowNormal5  = 16+5,       ///< Priority: below normal + 5
+  osPriorityBelowNormal6  = 16+6,       ///< Priority: below normal + 6
+  osPriorityBelowNormal7  = 16+7,       ///< Priority: below normal + 7
+  osPriorityNormal        = 24,         ///< Priority: normal
+  osPriorityNormal1       = 24+1,       ///< Priority: normal + 1
+  osPriorityNormal2       = 24+2,       ///< Priority: normal + 2
+  osPriorityNormal3       = 24+3,       ///< Priority: normal + 3
+  osPriorityNormal4       = 24+4,       ///< Priority: normal + 4
+  osPriorityNormal5       = 24+5,       ///< Priority: normal + 5
+  osPriorityNormal6       = 24+6,       ///< Priority: normal + 6
+  osPriorityNormal7       = 24+7,       ///< Priority: normal + 7
+  osPriorityAboveNormal   = 32,         ///< Priority: above normal
+  osPriorityAboveNormal1  = 32+1,       ///< Priority: above normal + 1
+  osPriorityAboveNormal2  = 32+2,       ///< Priority: above normal + 2
+  osPriorityAboveNormal3  = 32+3,       ///< Priority: above normal + 3
+  osPriorityAboveNormal4  = 32+4,       ///< Priority: above normal + 4
+  osPriorityAboveNormal5  = 32+5,       ///< Priority: above normal + 5
+  osPriorityAboveNormal6  = 32+6,       ///< Priority: above normal + 6
+  osPriorityAboveNormal7  = 32+7,       ///< Priority: above normal + 7
+  osPriorityHigh          = 40,         ///< Priority: high
+  osPriorityHigh1         = 40+1,       ///< Priority: high + 1
+  osPriorityHigh2         = 40+2,       ///< Priority: high + 2
+  osPriorityHigh3         = 40+3,       ///< Priority: high + 3
+  osPriorityHigh4         = 40+4,       ///< Priority: high + 4
+  osPriorityHigh5         = 40+5,       ///< Priority: high + 5
+  osPriorityHigh6         = 40+6,       ///< Priority: high + 6
+  osPriorityHigh7         = 40+7,       ///< Priority: high + 7
+  osPriorityRealtime      = 48,         ///< Priority: realtime
+  osPriorityRealtime1     = 48+1,       ///< Priority: realtime + 1
+  osPriorityRealtime2     = 48+2,       ///< Priority: realtime + 2
+  osPriorityRealtime3     = 48+3,       ///< Priority: realtime + 3
+  osPriorityRealtime4     = 48+4,       ///< Priority: realtime + 4
+  osPriorityRealtime5     = 48+5,       ///< Priority: realtime + 5
+  osPriorityRealtime6     = 48+6,       ///< Priority: realtime + 6
+  osPriorityRealtime7     = 48+7,       ///< Priority: realtime + 7
+  osPriorityISR           = 56,         ///< Reserved for ISR deferred thread.
+  osPriorityError         = -1,         ///< System cannot determine priority or illegal priority.
+  osPriorityReserved      = 0x7FFFFFFF  ///< Prevents enum down-size compiler optimization.
+} osPriority_t;
+ 
+/// Entry point of a thread.
+typedef void (*osThreadFunc_t) (void *argument);
+ 
+/// Timer callback function.
+typedef void (*osTimerFunc_t) (void *argument);
+ 
+/// Timer type.
+typedef enum {
+  osTimerOnce               = 0,          ///< One-shot timer.
+  osTimerPeriodic           = 1           ///< Repeating timer.
+} osTimerType_t;
+ 
+// Timeout value.
+#define osWaitForever         0xFFFFFFFFU ///< Wait forever timeout value.
+ 
+// Flags options (\ref osThreadFlagsWait and \ref osEventFlagsWait).
+#define osFlagsWaitAny        0x00000000U ///< Wait for any flag (default).
+#define osFlagsWaitAll        0x00000001U ///< Wait for all flags.
+#define osFlagsNoClear        0x00000002U ///< Do not clear flags which have been specified to wait for.
+ 
+// Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx).
+#define osFlagsError          0x80000000U ///< Error indicator.
+#define osFlagsErrorUnknown   0xFFFFFFFFU ///< osError (-1).
+#define osFlagsErrorTimeout   0xFFFFFFFEU ///< osErrorTimeout (-2).
+#define osFlagsErrorResource  0xFFFFFFFDU ///< osErrorResource (-3).
+#define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4).
+#define osFlagsErrorISR       0xFFFFFFFAU ///< osErrorISR (-6).
+ 
+// Thread attributes (attr_bits in \ref osThreadAttr_t).
+#define osThreadDetached      0x00000000U ///< Thread created in detached mode (default)
+#define osThreadJoinable      0x00000001U ///< Thread created in joinable mode
+ 
+// Mutex attributes (attr_bits in \ref osMutexAttr_t).
+#define osMutexRecursive      0x00000001U ///< Recursive mutex.
+#define osMutexPrioInherit    0x00000002U ///< Priority inherit protocol.
+#define osMutexRobust         0x00000008U ///< Robust mutex.
+ 
+/// Status code values returned by CMSIS-RTOS functions.
+typedef enum {
+  osOK                      =  0,         ///< Operation completed successfully.
+  osError                   = -1,         ///< Unspecified RTOS error: run-time error but no other error message fits.
+  osErrorTimeout            = -2,         ///< Operation not completed within the timeout period.
+  osErrorResource           = -3,         ///< Resource not available.
+  osErrorParameter          = -4,         ///< Parameter error.
+  osErrorNoMemory           = -5,         ///< System is out of memory: it was impossible to allocate or reserve memory for the operation.
+  osErrorISR                = -6,         ///< Not allowed in ISR context: the function cannot be called from interrupt service routines.
+  osStatusReserved          = 0x7FFFFFFF  ///< Prevents enum down-size compiler optimization.
+} osStatus_t;
+ 
+ 
+/// \details Thread ID identifies the thread.
+typedef void *osThreadId_t;
+ 
+/// \details Timer ID identifies the timer.
+typedef void *osTimerId_t;
+ 
+/// \details Event Flags ID identifies the event flags.
+typedef void *osEventFlagsId_t;
+ 
+/// \details Mutex ID identifies the mutex.
+typedef void *osMutexId_t;
+ 
+/// \details Semaphore ID identifies the semaphore.
+typedef void *osSemaphoreId_t;
+ 
+/// \details Memory Pool ID identifies the memory pool.
+typedef void *osMemoryPoolId_t;
+ 
+/// \details Message Queue ID identifies the message queue.
+typedef void *osMessageQueueId_t;
+ 
+ 
+#ifndef TZ_MODULEID_T
+#define TZ_MODULEID_T
+/// \details Data type that identifies secure software modules called by a process.
+typedef uint32_t TZ_ModuleId_t;
+#endif
+ 
+ 
+/// Attributes structure for thread.
+typedef struct {
+  const char                   *name;   ///< name of the thread
+  uint32_t                 attr_bits;   ///< attribute bits
+  void                      *cb_mem;    ///< memory for control block
+  uint32_t                   cb_size;   ///< size of provided memory for control block
+  void                   *stack_mem;    ///< memory for stack
+  uint32_t                stack_size;   ///< size of stack
+  osPriority_t              priority;   ///< initial thread priority (default: osPriorityNormal)
+  TZ_ModuleId_t            tz_module;   ///< TrustZone module identifier
+  uint32_t                  reserved;   ///< reserved (must be 0)
+} osThreadAttr_t;
+ 
+/// Attributes structure for timer.
+typedef struct {
+  const char                   *name;   ///< name of the timer
+  uint32_t                 attr_bits;   ///< attribute bits
+  void                      *cb_mem;    ///< memory for control block
+  uint32_t                   cb_size;   ///< size of provided memory for control block
+} osTimerAttr_t;
+ 
+/// Attributes structure for event flags.
+typedef struct {
+  const char                   *name;   ///< name of the event flags
+  uint32_t                 attr_bits;   ///< attribute bits
+  void                      *cb_mem;    ///< memory for control block
+  uint32_t                   cb_size;   ///< size of provided memory for control block
+} osEventFlagsAttr_t;
+ 
+/// Attributes structure for mutex.
+typedef struct {
+  const char                   *name;   ///< name of the mutex
+  uint32_t                 attr_bits;   ///< attribute bits
+  void                      *cb_mem;    ///< memory for control block
+  uint32_t                   cb_size;   ///< size of provided memory for control block
+} osMutexAttr_t;
+ 
+/// Attributes structure for semaphore.
+typedef struct {
+  const char                   *name;   ///< name of the semaphore
+  uint32_t                 attr_bits;   ///< attribute bits
+  void                      *cb_mem;    ///< memory for control block
+  uint32_t                   cb_size;   ///< size of provided memory for control block
+} osSemaphoreAttr_t;
+ 
+/// Attributes structure for memory pool.
+typedef struct {
+  const char                   *name;   ///< name of the memory pool
+  uint32_t                 attr_bits;   ///< attribute bits
+  void                      *cb_mem;    ///< memory for control block
+  uint32_t                   cb_size;   ///< size of provided memory for control block
+  void                      *mp_mem;    ///< memory for data storage
+  uint32_t                   mp_size;   ///< size of provided memory for data storage 
+} osMemoryPoolAttr_t;
+ 
+/// Attributes structure for message queue.
+typedef struct {
+  const char                   *name;   ///< name of the message queue
+  uint32_t                 attr_bits;   ///< attribute bits
+  void                      *cb_mem;    ///< memory for control block
+  uint32_t                   cb_size;   ///< size of provided memory for control block
+  void                      *mq_mem;    ///< memory for data storage
+  uint32_t                   mq_size;   ///< size of provided memory for data storage 
+} osMessageQueueAttr_t;
+ 
+ 
+//  ==== Kernel Management Functions ====
+ 
+/// Initialize the RTOS Kernel.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osKernelInitialize (void);
+ 
+///  Get RTOS Kernel Information.
+/// \param[out]    version       pointer to buffer for retrieving version information.
+/// \param[out]    id_buf        pointer to buffer for retrieving kernel identification string.
+/// \param[in]     id_size       size of buffer for kernel identification string.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size);
+ 
+/// Get the current RTOS Kernel state.
+/// \return current RTOS Kernel state.
+osKernelState_t osKernelGetState (void);
+ 
+/// Start the RTOS Kernel scheduler.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osKernelStart (void);
+ 
+/// Lock the RTOS Kernel scheduler.
+/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
+int32_t osKernelLock (void);
+ 
+/// Unlock the RTOS Kernel scheduler.
+/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
+int32_t osKernelUnlock (void);
+ 
+/// Restore the RTOS Kernel scheduler lock state.
+/// \param[in]     lock          lock state obtained by \ref osKernelLock or \ref osKernelUnlock.
+/// \return new lock state (1 - locked, 0 - not locked, error code if negative).
+int32_t osKernelRestoreLock (int32_t lock);
+ 
+/// Suspend the RTOS Kernel scheduler.
+/// \return time in ticks, for how long the system can sleep or power-down.
+uint32_t osKernelSuspend (void);
+ 
+/// Resume the RTOS Kernel scheduler.
+/// \param[in]     sleep_ticks   time in ticks for how long the system was in sleep or power-down mode.
+void osKernelResume (uint32_t sleep_ticks);
+ 
+/// Get the RTOS kernel tick count.
+/// \return RTOS kernel current tick count.
+uint32_t osKernelGetTickCount (void);
+ 
+/// Get the RTOS kernel tick frequency.
+/// \return frequency of the kernel tick in hertz, i.e. kernel ticks per second.
+uint32_t osKernelGetTickFreq (void);
+ 
+/// Get the RTOS kernel system timer count.
+/// \return RTOS kernel current system timer count as 32-bit value.
+uint32_t osKernelGetSysTimerCount (void);
+ 
+/// Get the RTOS kernel system timer frequency.
+/// \return frequency of the system timer in hertz, i.e. timer ticks per second.
+uint32_t osKernelGetSysTimerFreq (void);
+ 
+ 
+//  ==== Thread Management Functions ====
+ 
+/// Create a thread and add it to Active Threads.
+/// \param[in]     func          thread function.
+/// \param[in]     argument      pointer that is passed to the thread function as start argument.
+/// \param[in]     attr          thread attributes; NULL: default values.
+/// \return thread ID for reference by other functions or NULL in case of error.
+osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
+ 
+/// Get name of a thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \return name as null-terminated string.
+const char *osThreadGetName (osThreadId_t thread_id);
+ 
+/// Return the thread ID of the current running thread.
+/// \return thread ID for reference by other functions or NULL in case of error.
+osThreadId_t osThreadGetId (void);
+ 
+/// Get current thread state of a thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \return current thread state of the specified thread.
+osThreadState_t osThreadGetState (osThreadId_t thread_id);
+ 
+/// Get stack size of a thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \return stack size in bytes.
+uint32_t osThreadGetStackSize (osThreadId_t thread_id);
+ 
+/// Get available stack space of a thread based on stack watermark recording during execution.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \return remaining stack space in bytes.
+uint32_t osThreadGetStackSpace (osThreadId_t thread_id);
+ 
+/// Change priority of a thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \param[in]     priority      new priority value for the thread function.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority);
+ 
+/// Get current priority of a thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \return current priority value of the specified thread.
+osPriority_t osThreadGetPriority (osThreadId_t thread_id);
+ 
+/// Pass control to next thread that is in state \b READY.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osThreadYield (void);
+ 
+/// Suspend execution of a thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osThreadSuspend (osThreadId_t thread_id);
+ 
+/// Resume execution of a thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osThreadResume (osThreadId_t thread_id);
+ 
+/// Detach a thread (thread storage can be reclaimed when thread terminates).
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osThreadDetach (osThreadId_t thread_id);
+ 
+/// Wait for specified thread to terminate.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osThreadJoin (osThreadId_t thread_id);
+ 
+/// Terminate execution of current running thread.
+__NO_RETURN void osThreadExit (void);
+ 
+/// Terminate execution of a thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osThreadTerminate (osThreadId_t thread_id);
+ 
+/// Get number of active threads.
+/// \return number of active threads.
+uint32_t osThreadGetCount (void);
+ 
+/// Enumerate active threads.
+/// \param[out]    thread_array  pointer to array for retrieving thread IDs.
+/// \param[in]     array_items   maximum number of items in array for retrieving thread IDs.
+/// \return number of enumerated threads.
+uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items);
+ 
+ 
+//  ==== Thread Flags Functions ====
+ 
+/// Set the specified Thread Flags of a thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
+/// \param[in]     flags         specifies the flags of the thread that shall be set.
+/// \return thread flags after setting or error code if highest bit set.
+uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags);
+ 
+/// Clear the specified Thread Flags of current running thread.
+/// \param[in]     flags         specifies the flags of the thread that shall be cleared.
+/// \return thread flags before clearing or error code if highest bit set.
+uint32_t osThreadFlagsClear (uint32_t flags);
+ 
+/// Get the current Thread Flags of current running thread.
+/// \return current thread flags.
+uint32_t osThreadFlagsGet (void);
+ 
+/// Wait for one or more Thread Flags of the current running thread to become signaled.
+/// \param[in]     flags         specifies the flags to wait for.
+/// \param[in]     options       specifies flags options (osFlagsXxxx).
+/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return thread flags before clearing or error code if highest bit set.
+uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout);
+ 
+ 
+//  ==== Generic Wait Functions ====
+ 
+/// Wait for Timeout (Time Delay).
+/// \param[in]     ticks         \ref CMSIS_RTOS_TimeOutValue "time ticks" value
+/// \return status code that indicates the execution status of the function.
+osStatus_t osDelay (uint32_t ticks);
+ 
+/// Wait until specified time.
+/// \param[in]     ticks         absolute time in ticks
+/// \return status code that indicates the execution status of the function.
+osStatus_t osDelayUntil (uint32_t ticks);
+ 
+ 
+//  ==== Timer Management Functions ====
+ 
+/// Create and Initialize a timer.
+/// \param[in]     func          function pointer to callback function.
+/// \param[in]     type          \ref osTimerOnce for one-shot or \ref osTimerPeriodic for periodic behavior.
+/// \param[in]     argument      argument to the timer callback function.
+/// \param[in]     attr          timer attributes; NULL: default values.
+/// \return timer ID for reference by other functions or NULL in case of error.
+osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr);
+ 
+/// Get name of a timer.
+/// \param[in]     timer_id      timer ID obtained by \ref osTimerNew.
+/// \return name as null-terminated string.
+const char *osTimerGetName (osTimerId_t timer_id);
+ 
+/// Start or restart a timer.
+/// \param[in]     timer_id      timer ID obtained by \ref osTimerNew.
+/// \param[in]     ticks         \ref CMSIS_RTOS_TimeOutValue "time ticks" value of the timer.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks);
+ 
+/// Stop a timer.
+/// \param[in]     timer_id      timer ID obtained by \ref osTimerNew.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osTimerStop (osTimerId_t timer_id);
+ 
+/// Check if a timer is running.
+/// \param[in]     timer_id      timer ID obtained by \ref osTimerNew.
+/// \return 0 not running, 1 running.
+uint32_t osTimerIsRunning (osTimerId_t timer_id);
+ 
+/// Delete a timer.
+/// \param[in]     timer_id      timer ID obtained by \ref osTimerNew.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osTimerDelete (osTimerId_t timer_id);
+ 
+ 
+//  ==== Event Flags Management Functions ====
+ 
+/// Create and Initialize an Event Flags object.
+/// \param[in]     attr          event flags attributes; NULL: default values.
+/// \return event flags ID for reference by other functions or NULL in case of error.
+osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr);
+ 
+/// Get name of an Event Flags object.
+/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
+/// \return name as null-terminated string.
+const char *osEventFlagsGetName (osEventFlagsId_t ef_id);
+ 
+/// Set the specified Event Flags.
+/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
+/// \param[in]     flags         specifies the flags that shall be set.
+/// \return event flags after setting or error code if highest bit set.
+uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags);
+ 
+/// Clear the specified Event Flags.
+/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
+/// \param[in]     flags         specifies the flags that shall be cleared.
+/// \return event flags before clearing or error code if highest bit set.
+uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags);
+ 
+/// Get the current Event Flags.
+/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
+/// \return current event flags.
+uint32_t osEventFlagsGet (osEventFlagsId_t ef_id);
+ 
+/// Wait for one or more Event Flags to become signaled.
+/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
+/// \param[in]     flags         specifies the flags to wait for.
+/// \param[in]     options       specifies flags options (osFlagsXxxx).
+/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return event flags before clearing or error code if highest bit set.
+uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout);
+ 
+/// Delete an Event Flags object.
+/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id);
+ 
+ 
+//  ==== Mutex Management Functions ====
+ 
+/// Create and Initialize a Mutex object.
+/// \param[in]     attr          mutex attributes; NULL: default values.
+/// \return mutex ID for reference by other functions or NULL in case of error.
+osMutexId_t osMutexNew (const osMutexAttr_t *attr);
+ 
+/// Get name of a Mutex object.
+/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexNew.
+/// \return name as null-terminated string.
+const char *osMutexGetName (osMutexId_t mutex_id);
+ 
+/// Acquire a Mutex or timeout if it is locked.
+/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexNew.
+/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout);
+ 
+/// Release a Mutex that was acquired by \ref osMutexAcquire.
+/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexNew.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osMutexRelease (osMutexId_t mutex_id);
+ 
+/// Get Thread which owns a Mutex object.
+/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexNew.
+/// \return thread ID of owner thread or NULL when mutex was not acquired.
+osThreadId_t osMutexGetOwner (osMutexId_t mutex_id);
+ 
+/// Delete a Mutex object.
+/// \param[in]     mutex_id      mutex ID obtained by \ref osMutexNew.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osMutexDelete (osMutexId_t mutex_id);
+ 
+ 
+//  ==== Semaphore Management Functions ====
+ 
+/// Create and Initialize a Semaphore object.
+/// \param[in]     max_count     maximum number of available tokens.
+/// \param[in]     initial_count initial number of available tokens.
+/// \param[in]     attr          semaphore attributes; NULL: default values.
+/// \return semaphore ID for reference by other functions or NULL in case of error.
+osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr);
+ 
+/// Get name of a Semaphore object.
+/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
+/// \return name as null-terminated string.
+const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id);
+ 
+/// Acquire a Semaphore token or timeout if no tokens are available.
+/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
+/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout);
+ 
+/// Release a Semaphore token up to the initial maximum count.
+/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id);
+ 
+/// Get current Semaphore token count.
+/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
+/// \return number of tokens available.
+uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id);
+ 
+/// Delete a Semaphore object.
+/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id);
+ 
+ 
+//  ==== Memory Pool Management Functions ====
+ 
+/// Create and Initialize a Memory Pool object.
+/// \param[in]     block_count   maximum number of memory blocks in memory pool.
+/// \param[in]     block_size    memory block size in bytes.
+/// \param[in]     attr          memory pool attributes; NULL: default values.
+/// \return memory pool ID for reference by other functions or NULL in case of error.
+osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr);
+ 
+/// Get name of a Memory Pool object.
+/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
+/// \return name as null-terminated string.
+const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id);
+ 
+/// Allocate a memory block from a Memory Pool.
+/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
+/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return address of the allocated memory block or NULL in case of no memory is available.
+void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout);
+ 
+/// Return an allocated memory block back to a Memory Pool.
+/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
+/// \param[in]     block         address of the allocated memory block to be returned to the memory pool.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block);
+ 
+/// Get maximum number of memory blocks in a Memory Pool.
+/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
+/// \return maximum number of memory blocks.
+uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id);
+ 
+/// Get memory block size in a Memory Pool.
+/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
+/// \return memory block size in bytes.
+uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id);
+ 
+/// Get number of memory blocks used in a Memory Pool.
+/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
+/// \return number of memory blocks used.
+uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id);
+ 
+/// Get number of memory blocks available in a Memory Pool.
+/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
+/// \return number of memory blocks available.
+uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id);
+ 
+/// Delete a Memory Pool object.
+/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id);
+ 
+ 
+//  ==== Message Queue Management Functions ====
+ 
+/// Create and Initialize a Message Queue object.
+/// \param[in]     msg_count     maximum number of messages in queue.
+/// \param[in]     msg_size      maximum message size in bytes.
+/// \param[in]     attr          message queue attributes; NULL: default values.
+/// \return message queue ID for reference by other functions or NULL in case of error.
+osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr);
+ 
+/// Get name of a Message Queue object.
+/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
+/// \return name as null-terminated string.
+const char *osMessageQueueGetName (osMessageQueueId_t mq_id);
+ 
+/// Put a Message into a Queue or timeout if Queue is full.
+/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
+/// \param[in]     msg_ptr       pointer to buffer with message to put into a queue.
+/// \param[in]     msg_prio      message priority.
+/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout);
+ 
+/// Get a Message from a Queue or timeout if Queue is empty.
+/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
+/// \param[out]    msg_ptr       pointer to buffer for message to get from a queue.
+/// \param[out]    msg_prio      pointer to buffer for message priority or NULL.
+/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout);
+ 
+/// Get maximum number of messages in a Message Queue.
+/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
+/// \return maximum number of messages.
+uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id);
+ 
+/// Get maximum message size in a Message Queue.
+/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
+/// \return maximum message size in bytes.
+uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id);
+ 
+/// Get number of queued messages in a Message Queue.
+/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
+/// \return number of queued messages.
+uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id);
+ 
+/// Get number of available slots for messages in a Message Queue.
+/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
+/// \return number of available slots for messages.
+uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id);
+ 
+/// Reset a Message Queue to initial empty state.
+/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id);
+ 
+/// Delete a Message Queue object.
+/// \param[in]     mq_id         message queue ID obtained by \ref osMessageQueueNew.
+/// \return status code that indicates the execution status of the function.
+osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id);
+ 
+ 
+#ifdef  __cplusplus
+}
+#endif
+ 
+#endif  // CMSIS_OS2_H_

+ 63 - 0
lib/FreeRTOS-glue/freertos_mpool.h

@@ -0,0 +1,63 @@
+/* --------------------------------------------------------------------------
+ * Copyright (c) 2013-2020 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *      Name:    freertos_mpool.h
+ *      Purpose: CMSIS RTOS2 wrapper for FreeRTOS
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef FREERTOS_MPOOL_H_
+#define FREERTOS_MPOOL_H_
+
+#include <stdint.h>
+#include "FreeRTOS.h"
+#include "semphr.h"
+
+/* Memory Pool implementation definitions */
+#define MPOOL_STATUS              0x5EED0000U
+
+/* Memory Block header */
+typedef struct {
+  void *next;                   /* Pointer to next block  */
+} MemPoolBlock_t;
+
+/* Memory Pool control block */
+typedef struct MemPoolDef_t {
+  MemPoolBlock_t    *head;      /* Pointer to head block   */
+  SemaphoreHandle_t  sem;       /* Pool semaphore handle   */
+  uint8_t           *mem_arr;   /* Pool memory array       */
+  uint32_t           mem_sz;    /* Pool memory array size  */
+  const char        *name;      /* Pointer to name string  */
+  uint32_t           bl_sz;     /* Size of a single block  */
+  uint32_t           bl_cnt;    /* Number of blocks        */
+  uint32_t           n;         /* Block allocation index  */
+  volatile uint32_t  status;    /* Object status flags     */
+#if (configSUPPORT_STATIC_ALLOCATION == 1)
+  StaticSemaphore_t  mem_sem;   /* Semaphore object memory */
+#endif
+} MemPool_t;
+
+/* No need to hide static object type, just align to coding style */
+#define StaticMemPool_t         MemPool_t
+
+/* Define memory pool control block size */
+#define MEMPOOL_CB_SIZE         (sizeof(StaticMemPool_t))
+
+/* Define size of the byte array required to create count of blocks of given size */
+#define MEMPOOL_ARR_SIZE(bl_count, bl_size) (((((bl_size) + (4 - 1)) / 4) * 4)*(bl_count))
+
+#endif /* FREERTOS_MPOOL_H_ */

+ 336 - 0
lib/FreeRTOS-glue/freertos_os2.h

@@ -0,0 +1,336 @@
+/* --------------------------------------------------------------------------
+ * Copyright (c) 2013-2021 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *      Name:    freertos_os2.h
+ *      Purpose: CMSIS RTOS2 wrapper for FreeRTOS
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef FREERTOS_OS2_H_
+#define FREERTOS_OS2_H_
+
+#include <string.h>
+#include <stdint.h>
+
+#include "FreeRTOS.h"                   // ARM.FreeRTOS::RTOS:Core
+
+#if defined(_RTE_)
+#include "RTE_Components.h"             // Component selection
+#include CMSIS_device_header
+
+/* Configuration and component setup check */
+#if defined(RTE_Compiler_EventRecorder)
+  #if !defined(EVR_FREERTOS_DISABLE)
+    #define USE_TRACE_EVENT_RECORDER
+    /*
+      FreeRTOS provides functions and hooks to support execution tracing. This
+      functionality is only enabled if configUSE_TRACE_FACILITY == 1.
+      Set #define configUSE_TRACE_FACILITY 1 in FreeRTOSConfig.h to enable trace events.
+    */
+    #if (configUSE_TRACE_FACILITY == 0)
+      #error "Definition configUSE_TRACE_FACILITY must equal 1 to enable FreeRTOS trace events."
+    #endif
+  #endif
+#endif
+
+#if defined(RTE_RTOS_FreeRTOS_HEAP_1)
+  #define USE_FreeRTOS_HEAP_1
+#endif
+
+#if defined(RTE_RTOS_FreeRTOS_HEAP_5)
+  #define USE_FreeRTOS_HEAP_5
+#endif
+#endif /* _RTE_ */
+
+/*
+  CMSIS-RTOS2 FreeRTOS image size optimization definitions.
+
+  Note: Definitions configUSE_OS2 can be used to optimize FreeRTOS image size when
+        certain functionality is not required when using CMSIS-RTOS2 API.
+        In general optimization decisions are left to the tool chain but in cases
+        when coding style prevents it to optimize the code following optional
+        definitions can be used.
+*/
+
+/*
+  Option to exclude CMSIS-RTOS2 functions osThreadSuspend and osThreadResume from
+  the application image.
+*/
+#ifndef configUSE_OS2_THREAD_SUSPEND_RESUME
+#define configUSE_OS2_THREAD_SUSPEND_RESUME   1
+#endif
+
+/*
+  Option to exclude CMSIS-RTOS2 function osThreadEnumerate from the application image.
+*/
+#ifndef configUSE_OS2_THREAD_ENUMERATE
+#define configUSE_OS2_THREAD_ENUMERATE        1
+#endif
+
+/*
+  Option to disable CMSIS-RTOS2 function osEventFlagsSet and osEventFlagsClear
+  operation from ISR.
+*/
+#ifndef configUSE_OS2_EVENTFLAGS_FROM_ISR
+#define configUSE_OS2_EVENTFLAGS_FROM_ISR     1
+#endif
+
+/*
+  Option to exclude CMSIS-RTOS2 Thread Flags API functions from the application image.
+*/
+#ifndef configUSE_OS2_THREAD_FLAGS
+#define configUSE_OS2_THREAD_FLAGS            configUSE_TASK_NOTIFICATIONS
+#endif
+
+/*
+  Option to exclude CMSIS-RTOS2 Timer API functions from the application image.
+*/
+#ifndef configUSE_OS2_TIMER
+#define configUSE_OS2_TIMER                   configUSE_TIMERS
+#endif
+
+/*
+  Option to exclude CMSIS-RTOS2 Mutex API functions from the application image.
+*/
+#ifndef configUSE_OS2_MUTEX
+#define configUSE_OS2_MUTEX                   configUSE_MUTEXES
+#endif
+
+
+/*
+  CMSIS-RTOS2 FreeRTOS configuration check (FreeRTOSConfig.h).
+
+  Note: CMSIS-RTOS API requires functions included by using following definitions.
+        In case if certain API function is not used compiler will optimize it away.
+*/
+#if (INCLUDE_xSemaphoreGetMutexHolder == 0)
+  /*
+    CMSIS-RTOS2 function osMutexGetOwner uses FreeRTOS function xSemaphoreGetMutexHolder. In case if
+    osMutexGetOwner is not used in the application image, compiler will optimize it away.
+    Set #define INCLUDE_xSemaphoreGetMutexHolder 1 to fix this error.
+  */
+  #error "Definition INCLUDE_xSemaphoreGetMutexHolder must equal 1 to implement Mutex Management API."
+#endif
+#if (INCLUDE_vTaskDelay == 0)
+  /*
+    CMSIS-RTOS2 function osDelay uses FreeRTOS function vTaskDelay. In case if
+    osDelay is not used in the application image, compiler will optimize it away.
+    Set #define INCLUDE_vTaskDelay 1 to fix this error.
+  */
+  #error "Definition INCLUDE_vTaskDelay must equal 1 to implement Generic Wait Functions API."
+#endif
+#if (INCLUDE_xTaskDelayUntil == 0)
+  /*
+    CMSIS-RTOS2 function osDelayUntil uses FreeRTOS function xTaskDelayUntil. In case if
+    osDelayUntil is not used in the application image, compiler will optimize it away.
+    Set #define INCLUDE_xTaskDelayUntil 1 to fix this error.
+  */
+  #error "Definition INCLUDE_xTaskDelayUntil must equal 1 to implement Generic Wait Functions API."
+#endif
+#if (INCLUDE_vTaskDelete == 0)
+  /*
+    CMSIS-RTOS2 function osThreadTerminate and osThreadExit uses FreeRTOS function
+    vTaskDelete. In case if they are not used in the application image, compiler
+    will optimize them away.
+    Set #define INCLUDE_vTaskDelete 1 to fix this error.
+  */
+  #error "Definition INCLUDE_vTaskDelete must equal 1 to implement Thread Management API."
+#endif
+#if (INCLUDE_xTaskGetCurrentTaskHandle == 0)
+  /*
+    CMSIS-RTOS2 API uses FreeRTOS function xTaskGetCurrentTaskHandle to implement
+    functions osThreadGetId, osThreadFlagsClear and osThreadFlagsGet. In case if these
+    functions are not used in the application image, compiler will optimize them away.
+    Set #define INCLUDE_xTaskGetCurrentTaskHandle 1 to fix this error.
+  */
+  #error "Definition INCLUDE_xTaskGetCurrentTaskHandle must equal 1 to implement Thread Management API."
+#endif
+#if (INCLUDE_xTaskGetSchedulerState == 0)
+  /*
+    CMSIS-RTOS2 API uses FreeRTOS function xTaskGetSchedulerState to implement Kernel
+    tick handling and therefore it is vital that xTaskGetSchedulerState is included into
+    the application image.
+    Set #define INCLUDE_xTaskGetSchedulerState 1 to fix this error.
+  */
+  #error "Definition INCLUDE_xTaskGetSchedulerState must equal 1 to implement Kernel Information and Control API."
+#endif
+#if (INCLUDE_uxTaskGetStackHighWaterMark == 0)
+  /*
+    CMSIS-RTOS2 function osThreadGetStackSpace uses FreeRTOS function uxTaskGetStackHighWaterMark.
+    In case if osThreadGetStackSpace is not used in the application image, compiler will
+    optimize it away.
+    Set #define INCLUDE_uxTaskGetStackHighWaterMark 1 to fix this error.
+  */
+  #error "Definition INCLUDE_uxTaskGetStackHighWaterMark must equal 1 to implement Thread Management API."
+#endif
+#if (INCLUDE_uxTaskPriorityGet == 0)
+  /*
+    CMSIS-RTOS2 function osThreadGetPriority uses FreeRTOS function uxTaskPriorityGet. In case if
+    osThreadGetPriority is not used in the application image, compiler will optimize it away.
+    Set #define INCLUDE_uxTaskPriorityGet 1 to fix this error.
+  */
+  #error "Definition INCLUDE_uxTaskPriorityGet must equal 1 to implement Thread Management API."
+#endif
+#if (INCLUDE_vTaskPrioritySet == 0)
+  /*
+    CMSIS-RTOS2 function osThreadSetPriority uses FreeRTOS function vTaskPrioritySet. In case if
+    osThreadSetPriority is not used in the application image, compiler will optimize it away.
+    Set #define INCLUDE_vTaskPrioritySet 1 to fix this error.
+  */
+  #error "Definition INCLUDE_vTaskPrioritySet must equal 1 to implement Thread Management API."
+#endif
+#if (INCLUDE_eTaskGetState == 0)
+  /*
+    CMSIS-RTOS2 API uses FreeRTOS function vTaskDelayUntil to implement functions osThreadGetState
+    and osThreadTerminate. In case if these functions are not used in the application image,
+    compiler will optimize them away.
+    Set #define INCLUDE_eTaskGetState 1 to fix this error.
+  */
+  #error "Definition INCLUDE_eTaskGetState must equal 1 to implement Thread Management API."
+#endif
+#if (INCLUDE_vTaskSuspend == 0)
+  /*
+    CMSIS-RTOS2 API uses FreeRTOS functions vTaskSuspend and vTaskResume to implement
+    functions osThreadSuspend and osThreadResume. In case if these functions are not
+    used in the application image, compiler will optimize them away.
+    Set #define INCLUDE_vTaskSuspend 1 to fix this error.
+
+    Alternatively, if the application does not use osThreadSuspend and
+    osThreadResume they can be excluded from the image code by setting:
+    #define configUSE_OS2_THREAD_SUSPEND_RESUME 0 (in FreeRTOSConfig.h)
+  */
+  #if (configUSE_OS2_THREAD_SUSPEND_RESUME == 1)
+    #error "Definition INCLUDE_vTaskSuspend must equal 1 to implement Kernel Information and Control API."
+  #endif
+#endif
+#if (INCLUDE_xTimerPendFunctionCall == 0)
+  /*
+    CMSIS-RTOS2 function osEventFlagsSet and osEventFlagsClear, when called from
+    the ISR, call FreeRTOS functions xEventGroupSetBitsFromISR and
+    xEventGroupClearBitsFromISR which are only enabled if timers are operational and
+    xTimerPendFunctionCall in enabled.
+    Set #define INCLUDE_xTimerPendFunctionCall 1 and #define configUSE_TIMERS 1
+    to fix this error.
+
+    Alternatively, if the application does not use osEventFlagsSet and osEventFlagsClear
+    from the ISR their operation from ISR can be restricted by setting:
+    #define configUSE_OS2_EVENTFLAGS_FROM_ISR 0 (in FreeRTOSConfig.h)
+  */
+  #if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 1)
+    #error "Definition INCLUDE_xTimerPendFunctionCall must equal 1 to implement Event Flags API."
+  #endif
+#endif
+
+#if (configUSE_TIMERS == 0)
+  /*
+    CMSIS-RTOS2 Timer Management API functions use FreeRTOS timer functions to implement
+    timer management. In case if these functions are not used in the application image,
+    compiler will optimize them away.
+    Set #define configUSE_TIMERS 1 to fix this error.
+
+    Alternatively, if the application does not use timer functions they can be
+    excluded from the image code by setting:
+    #define configUSE_OS2_TIMER 0 (in FreeRTOSConfig.h)
+  */
+  #if (configUSE_OS2_TIMER == 1)
+    #error "Definition configUSE_TIMERS must equal 1 to implement Timer Management API."
+  #endif
+#endif
+
+#if (configUSE_MUTEXES == 0)
+  /*
+    CMSIS-RTOS2 Mutex Management API functions use FreeRTOS mutex functions to implement
+    mutex management. In case if these functions are not used in the application image,
+    compiler will optimize them away.
+    Set #define configUSE_MUTEXES 1 to fix this error.
+
+    Alternatively, if the application does not use mutex functions they can be
+    excluded from the image code by setting:
+    #define configUSE_OS2_MUTEX 0 (in FreeRTOSConfig.h)
+  */
+  #if (configUSE_OS2_MUTEX == 1)
+    #error "Definition configUSE_MUTEXES must equal 1 to implement Mutex Management API."
+  #endif
+#endif
+
+#if (configUSE_COUNTING_SEMAPHORES == 0)
+  /*
+    CMSIS-RTOS2 Memory Pool functions use FreeRTOS function xSemaphoreCreateCounting
+    to implement memory pools. In case if these functions are not used in the application image,
+    compiler will optimize them away.
+    Set #define configUSE_COUNTING_SEMAPHORES 1 to fix this error.
+  */
+  #error "Definition configUSE_COUNTING_SEMAPHORES must equal 1 to implement Memory Pool API."
+#endif
+#if (configUSE_TASK_NOTIFICATIONS == 0)
+  /*
+    CMSIS-RTOS2 Thread Flags API functions use FreeRTOS Task Notification functions to implement
+    thread flag management. In case if these functions are not used in the application image,
+    compiler will optimize them away.
+    Set #define configUSE_TASK_NOTIFICATIONS 1 to fix this error.
+
+    Alternatively, if the application does not use thread flags functions they can be
+    excluded from the image code by setting:
+    #define configUSE_OS2_THREAD_FLAGS 0 (in FreeRTOSConfig.h)
+  */
+  #if (configUSE_OS2_THREAD_FLAGS == 1)
+    #error "Definition configUSE_TASK_NOTIFICATIONS must equal 1 to implement Thread Flags API."
+  #endif
+#endif
+
+#if (configUSE_TRACE_FACILITY == 0)
+  /*
+    CMSIS-RTOS2 function osThreadEnumerate requires FreeRTOS function uxTaskGetSystemState
+    which is only enabled if configUSE_TRACE_FACILITY == 1.
+    Set #define configUSE_TRACE_FACILITY 1 to fix this error.
+
+    Alternatively, if the application does not use osThreadEnumerate it can be
+    excluded from the image code by setting:
+    #define configUSE_OS2_THREAD_ENUMERATE 0 (in FreeRTOSConfig.h)
+  */
+  #if (configUSE_OS2_THREAD_ENUMERATE == 1)
+    #error "Definition configUSE_TRACE_FACILITY must equal 1 to implement osThreadEnumerate."
+  #endif
+#endif
+
+#if (configUSE_16_BIT_TICKS == 1)
+  /*
+    CMSIS-RTOS2 wrapper for FreeRTOS relies on 32-bit tick timer which is also optimal on
+    a 32-bit CPU architectures.
+    Set #define configUSE_16_BIT_TICKS 0 to fix this error.
+  */
+  #error "Definition configUSE_16_BIT_TICKS must be zero to implement CMSIS-RTOS2 API."
+#endif
+
+#if (configMAX_PRIORITIES != 56)
+  /*
+    CMSIS-RTOS2 defines 56 different priorities (see osPriority_t) and portable CMSIS-RTOS2
+    implementation should implement the same number of priorities.
+    Set #define configMAX_PRIORITIES 56 to fix this error.
+  */
+  #error "Definition configMAX_PRIORITIES must equal 56 to implement Thread Management API."
+#endif
+#if (configUSE_PORT_OPTIMISED_TASK_SELECTION != 0)
+  /*
+    CMSIS-RTOS2 requires handling of 56 different priorities (see osPriority_t) while FreeRTOS port
+    optimised selection for Cortex core only handles 32 different priorities.
+    Set #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 to fix this error.
+  */
+  #error "Definition configUSE_PORT_OPTIMISED_TASK_SELECTION must be zero to implement Thread Management API."
+#endif
+
+#endif /* FREERTOS_OS2_H_ */

+ 80 - 0
lib/FreeRTOS-glue/os_tick.h

@@ -0,0 +1,80 @@
+/**************************************************************************//**
+ * @file     os_tick.h
+ * @brief    CMSIS OS Tick header file
+ * @version  V1.0.2
+ * @date     19. March 2021
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017-2021 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OS_TICK_H
+#define OS_TICK_H
+
+#include <stdint.h>
+
+#ifdef  __cplusplus
+extern "C"
+{
+#endif
+
+/// IRQ Handler.
+#ifndef IRQHANDLER_T
+#define IRQHANDLER_T
+typedef void (*IRQHandler_t) (void);
+#endif
+
+/// Setup OS Tick timer to generate periodic RTOS Kernel Ticks
+/// \param[in]     freq         tick frequency in Hz
+/// \param[in]     handler      tick IRQ handler
+/// \return 0 on success, -1 on error.
+int32_t  OS_Tick_Setup (uint32_t freq, IRQHandler_t handler);
+
+/// Enable OS Tick timer interrupt
+void     OS_Tick_Enable (void);
+
+/// Disable OS Tick timer interrupt
+void     OS_Tick_Disable (void);
+
+/// Acknowledge execution of OS Tick timer interrupt
+void     OS_Tick_AcknowledgeIRQ (void);
+
+/// Get OS Tick timer IRQ number
+/// \return OS Tick IRQ number
+int32_t  OS_Tick_GetIRQn (void);
+
+/// Get OS Tick timer clock frequency
+/// \return OS Tick timer clock frequency in Hz
+uint32_t OS_Tick_GetClock (void);
+
+/// Get OS Tick timer interval reload value
+/// \return OS Tick timer interval reload value
+uint32_t OS_Tick_GetInterval (void);
+
+/// Get OS Tick timer counter value
+/// \return OS Tick timer counter value
+uint32_t OS_Tick_GetCount (void);
+
+/// Get OS Tick timer overflow status
+/// \return OS Tick overflow status (1 - overflow, 0 - no overflow).
+uint32_t OS_Tick_GetOverflow (void);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif  /* OS_TICK_H */

+ 1 - 1
lib/ST25RFAL002/platform.c

@@ -39,7 +39,7 @@ void platformSetIrqCallback(PlatformIrqCallback callback) {
     platform_irq_callback = callback;
     platform_irq_callback = callback;
     platform_irq_thread_attr.name = "RfalIrqWorker";
     platform_irq_thread_attr.name = "RfalIrqWorker";
     platform_irq_thread_attr.stack_size = 1024;
     platform_irq_thread_attr.stack_size = 1024;
-    platform_irq_thread_attr.priority = osPriorityISR;
+    platform_irq_thread_attr.priority = osPriorityRealtime;
     platform_irq_thread_id = osThreadNew(platformIrqWorker, NULL, &platform_irq_thread_attr);
     platform_irq_thread_id = osThreadNew(platformIrqWorker, NULL, &platform_irq_thread_attr);
     hal_gpio_add_int_callback(&pin, nfc_isr, NULL);
     hal_gpio_add_int_callback(&pin, nfc_isr, NULL);
     // Disable interrupt callback as the pin is shared between 2 apps
     // Disable interrupt callback as the pin is shared between 2 apps

+ 1 - 1
lib/STM32CubeWB

@@ -1 +1 @@
-Subproject commit 9c78e7f25506db18c35c6be51ab5aa14c7e0a622
+Subproject commit 528461f8276f06783d46461bfb31d77aa8bac419

+ 2 - 2
lib/lib.mk

@@ -88,7 +88,7 @@ C_SOURCES		+= $(wildcard $(LIB_DIR)/drivers/*.c)
 CFLAGS			+= -I$(LIB_DIR)/file_reader
 CFLAGS			+= -I$(LIB_DIR)/file_reader
 CPP_SOURCES		+= $(wildcard $(LIB_DIR)/file_reader/*.cpp)
 CPP_SOURCES		+= $(wildcard $(LIB_DIR)/file_reader/*.cpp)
 
 
-#irda lib
+# IR lib
 CFLAGS			+= -I$(LIB_DIR)/irda/encoder_decoder
 CFLAGS			+= -I$(LIB_DIR)/irda/encoder_decoder
 CFLAGS			+= -I$(LIB_DIR)/irda/worker
 CFLAGS			+= -I$(LIB_DIR)/irda/worker
 C_SOURCES		+= $(wildcard $(LIB_DIR)/irda/encoder_decoder/*.c)
 C_SOURCES		+= $(wildcard $(LIB_DIR)/irda/encoder_decoder/*.c)
@@ -123,4 +123,4 @@ C_SOURCES		+= $(wildcard $(LIB_DIR)/heatshrink/*.c)
 
 
 # Toolbox
 # Toolbox
 CFLAGS			+= -I$(LIB_DIR)/flipper_file
 CFLAGS			+= -I$(LIB_DIR)/flipper_file
-C_SOURCES		+= $(wildcard $(LIB_DIR)/flipper_file/*.c)
+C_SOURCES		+= $(wildcard $(LIB_DIR)/flipper_file/*.c)

+ 2 - 1
make/rules.mk

@@ -108,7 +108,8 @@ blackmagic:
 		-ex 'monitor swdp_scan' \
 		-ex 'monitor swdp_scan' \
 		-ex 'monitor debug_bmp enable' \
 		-ex 'monitor debug_bmp enable' \
 		-ex 'attach 1' \
 		-ex 'attach 1' \
-		-ex "set confirm off" \
+		-ex 'set confirm off' \
+		-ex 'set mem inaccessible-by-default off' \
 		-ex "source ../debug/FreeRTOS/FreeRTOS.py" \
 		-ex "source ../debug/FreeRTOS/FreeRTOS.py" \
 		-ex "source ../debug/PyCortexMDebug/PyCortexMDebug.py" \
 		-ex "source ../debug/PyCortexMDebug/PyCortexMDebug.py" \
 		-ex "svd_load $(SVD_FILE)" \
 		-ex "svd_load $(SVD_FILE)" \

+ 5 - 5
scripts/flipper/copro.py

@@ -16,10 +16,10 @@ MANIFEST_TEMPLATE = {
             "version": {
             "version": {
                 "type": 1,
                 "type": 1,
                 "major": 1,
                 "major": 1,
-                "minor": 12,
-                "sub": 1,
+                "minor": 13,
+                "sub": 0,
                 "branch": 0,
                 "branch": 0,
-                "release": 1,
+                "release": 5,
             },
             },
             "files": [],
             "files": [],
         },
         },
@@ -51,7 +51,7 @@ class Copro:
         if not cube_version or not cube_version.startswith("FW.WB"):
         if not cube_version or not cube_version.startswith("FW.WB"):
             raise Exception(f"Incorrect Cube package or version info")
             raise Exception(f"Incorrect Cube package or version info")
         cube_version = cube_version.replace("FW.WB.", "", 1)
         cube_version = cube_version.replace("FW.WB.", "", 1)
-        if cube_version != "1.12.1":
+        if cube_version != "1.13.1":
             raise Exception(f"Unknonwn cube version")
             raise Exception(f"Unknonwn cube version")
         self.version = cube_version
         self.version = cube_version
 
 
@@ -89,7 +89,7 @@ class Copro:
         self.addFile(
         self.addFile(
             manifest["copro"]["radio"]["files"],
             manifest["copro"]["radio"]["files"],
             "stm32wb5x_BLE_Stack_full_fw.bin",
             "stm32wb5x_BLE_Stack_full_fw.bin",
-            address="0x080CA000",
+            address="0x080C7000",
         )
         )
         # Save manifest to
         # Save manifest to
         json.dump(manifest, open(manifest_file, "w"))
         json.dump(manifest, open(manifest_file, "w"))

+ 2 - 2
scripts/ob.data

@@ -14,7 +14,7 @@ IWDGSTOP:0x1:rw
 IWDGSW:0x1:rw
 IWDGSW:0x1:rw
 IPCCDBA:0x0:rw
 IPCCDBA:0x0:rw
 ESE:0x1:r
 ESE:0x1:r
-SFSA:0xCA:r
+SFSA:0xC7:r
 FSD:0x0:r
 FSD:0x0:r
 DDS:0x1:r
 DDS:0x1:r
 C2OPT:0x1:r
 C2OPT:0x1:r
@@ -22,7 +22,7 @@ NBRSD:0x0:r
 SNBRSA:0xF:r
 SNBRSA:0xF:r
 BRSD:0x0:r
 BRSD:0x0:r
 SBRSA:0xA:r
 SBRSA:0xA:r
-SBRV:0x32800:r
+SBRV:0x31C00:r
 PCROP1A_STRT:0x1FF:r
 PCROP1A_STRT:0x1FF:r
 PCROP1A_END:0x0:r
 PCROP1A_END:0x0:r
 PCROP_RDP:0x1:rw
 PCROP_RDP:0x1:rw