diff --git a/source/.gitignore b/source/.gitignore
new file mode 100644
index 0000000..e10e727
--- /dev/null
+++ b/source/.gitignore
@@ -0,0 +1 @@
+/.metadata/
diff --git a/source/.mcuxpressoide_packages_support/crt_directory.xml b/source/.mcuxpressoide_packages_support/crt_directory.xml
new file mode 100644
index 0000000..3102557
--- /dev/null
+++ b/source/.mcuxpressoide_packages_support/crt_directory.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/source/.mcuxpressoide_packages_support/info.properties b/source/.mcuxpressoide_packages_support/info.properties
new file mode 100644
index 0000000..fb8ca66
--- /dev/null
+++ b/source/.mcuxpressoide_packages_support/info.properties
@@ -0,0 +1,5 @@
+#MCUXpresso IDE
+#Thu Mar 23 12:55:50 EET 2023
+product.name=MCUXpresso IDE v11.5.1 [Build 7266] [2022-04-13]
+product.version=11.5.1
+product.build=7266
diff --git a/source/.mcuxpressoide_packages_support/readme.txt b/source/.mcuxpressoide_packages_support/readme.txt
new file mode 100644
index 0000000..00460b7
--- /dev/null
+++ b/source/.mcuxpressoide_packages_support/readme.txt
@@ -0,0 +1,2 @@
+This folder is automatically created and contains the SDK part support for the IDE
+*** DO NOT REMOVE OR MODIFY, YOUR CHANGES WILL BE OVERWRITTEN ON SDK REFRESH ***
\ No newline at end of file
diff --git a/source/freertos_blinky/.cproject b/source/freertos_blinky/.cproject
new file mode 100644
index 0000000..827e7ea
--- /dev/null
+++ b/source/freertos_blinky/.cproject
@@ -0,0 +1,243 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<TargetConfig>
+<Properties property_2="LPC11U6x_256K.cfx" property_3="NXP" property_4="LPC11U68" property_count="5" version="100300"/>
+<infoList vendor="NXP">
+<info chip="LPC11U68" flash_driver="LPC11U6x_256K.cfx" match_id="0x0" name="LPC11U68" stub="crt_emu_cm3_gen">
+<chip>
+<name>LPC11U68</name>
+<family>LPC11U6x</family>
+<vendor>NXP (formerly Philips)</vendor>
+<reset board="None" core="Real" sys="Real"/>
+<clock changeable="TRUE" freq="12MHz" is_accurate="TRUE"/>
+<memory can_program="true" id="Flash" is_ro="true" type="Flash"/>
+<memory id="RAM" type="RAM"/>
+<memory id="Periph" is_volatile="true" type="Peripheral"/>
+<memoryInstance derived_from="Flash" id="MFlash256" location="0x0" size="0x40000"/>
+<memoryInstance derived_from="RAM" id="Ram0_32" location="0x10000000" size="0x8000"/>
+<memoryInstance derived_from="RAM" id="Ram1_2" location="0x20000000" size="0x800"/>
+<memoryInstance derived_from="RAM" id="Ram2USB_2" location="0x20004000" size="0x800"/>
+</chip>
+<processor>
+<name gcc_name="cortex-m0">Cortex-M0</name>
+<family>Cortex-M</family>
+</processor>
+</info>
+</infoList>
+</TargetConfig>
+
+
+
+
+
\ No newline at end of file
diff --git a/source/freertos_blinky/.gitignore b/source/freertos_blinky/.gitignore
new file mode 100644
index 0000000..3df573f
--- /dev/null
+++ b/source/freertos_blinky/.gitignore
@@ -0,0 +1 @@
+/Debug/
diff --git a/source/freertos_blinky/.project b/source/freertos_blinky/.project
new file mode 100644
index 0000000..5ea2517
--- /dev/null
+++ b/source/freertos_blinky/.project
@@ -0,0 +1,28 @@
+
+
+ freertos_blinky
+
+
+ lpc_chip_11u6x
+ lpc_board_nxp_lpcxpresso_11u68
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/source/freertos_blinky/.settings/language.settings.xml b/source/freertos_blinky/.settings/language.settings.xml
new file mode 100644
index 0000000..ceb5b38
--- /dev/null
+++ b/source/freertos_blinky/.settings/language.settings.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/freertos_blinky/example/inc/FreeRTOSConfig.h b/source/freertos_blinky/example/inc/FreeRTOSConfig.h
new file mode 100644
index 0000000..21f882b
--- /dev/null
+++ b/source/freertos_blinky/example/inc/FreeRTOSConfig.h
@@ -0,0 +1,158 @@
+/*
+ FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
+
+
+ ***************************************************************************
+ * *
+ * FreeRTOS tutorial books are available in pdf and paperback. *
+ * Complete, revised, and edited pdf reference manuals are also *
+ * available. *
+ * *
+ * Purchasing FreeRTOS documentation will not only help you, by *
+ * ensuring you get running as quickly as possible and with an *
+ * in-depth knowledge of how to use FreeRTOS, it will also help *
+ * the FreeRTOS project to continue with its mission of providing *
+ * professional grade, cross platform, de facto standard solutions *
+ * for microcontrollers - completely free of charge! *
+ * *
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
+ * *
+ * Thank you for using FreeRTOS, and thank you for your support! *
+ * *
+ ***************************************************************************
+
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+ >>>NOTE<<< The modification to the GPL is included to allow you to
+ distribute a combined work that includes FreeRTOS without being obliged to
+ provide the source code for proprietary components outside of the FreeRTOS
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details. You should have received a copy of the GNU General Public
+ License and the FreeRTOS license exception along with FreeRTOS; if not it
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained
+ by writing to Richard Barry, contact details for whom are available on the
+ FreeRTOS WEB site.
+
+ 1 tab == 4 spaces!
+
+ http://www.FreeRTOS.org - Documentation, latest information, license and
+ contact details.
+
+ http://www.SafeRTOS.com - A version that is certified for use in safety
+ critical systems.
+
+ http://www.OpenRTOS.com - Commercial support, development, porting,
+ licensing and training services.
+*/
+
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+#ifndef __IASMARM__
+/* For SystemCoreClock */
+#include "board.h"
+#endif
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS 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.
+ *----------------------------------------------------------*/
+
+#define configUSE_PREEMPTION 1
+#define configUSE_IDLE_HOOK 1
+#define configUSE_TICK_HOOK 0
+#define configCPU_CLOCK_HZ ( SystemCoreClock )
+#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
+#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 8 )
+#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 64 )
+#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 1024 + 512) )
+#define configMAX_TASK_NAME_LEN ( 10 )
+#define configUSE_TRACE_FACILITY 1
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_MUTEXES 1
+#define configQUEUE_REGISTRY_SIZE 8
+#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_MALLOC_FAILED_HOOK 1
+#define configUSE_APPLICATION_TASK_TAG 0
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configGENERATE_RUN_TIME_STATS 0
+#define configUSE_TICKLESS_IDLE 1
+
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES 0
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
+
+/* Software timer definitions. This example uses I2C to write to the LEDs. As
+this takes a finite time, and because a timer callback writes to an LED, the
+priority of the timer task is kept to a minimum to ensure it does not disrupt
+test tasks that check their own execution times. */
+#define configUSE_TIMERS 0
+#define configTIMER_TASK_PRIORITY ( 0 )
+#define configTIMER_QUEUE_LENGTH 5
+#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
+
+/* Set the following definitions to 1 to include the API function, or zero
+to exclude the API function. */
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskCleanUpResources 1
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+
+/* Cortex-M specific definitions. */
+#ifdef __NVIC_PRIO_BITS
+ /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
+ #define configPRIO_BITS __NVIC_PRIO_BITS
+#else
+ #define configPRIO_BITS 5 /* 32 priority levels */
+#endif
+
+/* The lowest interrupt priority that can be used in a call to a "set priority"
+function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x1f
+
+/* 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
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
+
+/* 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. */
+#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_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
+header file. */
+#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
+
+#define configUSE_CUSTOM_TICK 0
+
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+standard names - or at least those used in the unmodified vector table. */
+#define vPortSVCHandler SVC_Handler
+#define xPortPendSVHandler PendSV_Handler
+#define xPortSysTickHandler SysTick_Handler
+
+#endif /* FREERTOS_CONFIG_H */
+
diff --git a/source/freertos_blinky/example/src/aeabi_romdiv_patch.s b/source/freertos_blinky/example/src/aeabi_romdiv_patch.s
new file mode 100644
index 0000000..bbbf1e9
--- /dev/null
+++ b/source/freertos_blinky/example/src/aeabi_romdiv_patch.s
@@ -0,0 +1,93 @@
+//*****************************************************************************
+// aeabi_romdiv_patch.s
+// - Provides "patch" versions of the aeabi integer divide functions to
+// replace the standard ones pulled in from the C library, which vector
+// integer divides onto the rom division functions contained in
+// specific NXP MCUs such as LPC11Uxx and LPC12xx.
+// - Note that this patching will only occur if "__USE_ROMDIVIDE" is
+// defined for the project build for both the compiler and assembler.
+//*****************************************************************************
+//
+// Copyright(C) NXP Semiconductors, 2013
+// All rights reserved.
+//
+// Software that is described herein is for illustrative purposes only
+// which provides customers with programming information regarding the
+// LPC products. This software is supplied "AS IS" without any warranties of
+// any kind, and NXP Semiconductors and its licensor disclaim any and
+// all warranties, express or implied, including all implied warranties of
+// merchantability, fitness for a particular purpose and non-infringement of
+// intellectual property rights. NXP Semiconductors assumes no responsibility
+// or liability for the use of the software, conveys no license or rights under any
+// patent, copyright, mask work right, or any other intellectual property rights in
+// or to any products. NXP Semiconductors reserves the right to make changes
+// in the software without notification. NXP Semiconductors also makes no
+// representation or warranty that such application will be suitable for the
+// specified use without further testing or modification.
+//
+// Permission to use, copy, modify, and distribute this software and its
+// documentation is hereby granted, under NXP Semiconductors' and its
+// licensor's relevant copyrights in the software, without fee, provided that it
+// is used in conjunction with NXP Semiconductors microcontrollers. This
+// copyright, permission, and disclaimer notice must appear in all copies of
+// this code.
+//*****************************************************************************
+#if defined(__USE_ROMDIVIDE)
+
+// Note that the romdivide "divmod" functions are not actually called from
+// the below code, as these functions are actually just wrappers to the
+// main romdivide "div" functions which push the quotient and remainder onto
+// the stack, so as to be compatible with the way that C returns structures.
+//
+// This is not needed for the aeabi "divmod" functions, as the compiler
+// automatically generates code that handles the return values being passed
+// back in registers when it generates inline calls to __aeabi_idivmod and
+// __aeabi_uidivmod routines.
+
+ .syntax unified
+ .text
+
+// ========= __aeabi_idiv & __aeabi_idivmod =========
+ .align 2
+ .section .text.__aeabi_idiv
+
+ .global __aeabi_idiv
+ .set __aeabi_idivmod, __aeabi_idiv // make __aeabi_uidivmod an alias
+ .global __aeabi_idivmod
+ .global pDivRom_idiv // pointer to the romdivide 'idiv' functione
+ .func
+ .thumb_func
+ .type __aeabi_idiv, %function
+
+__aeabi_idiv:
+ push {r4, lr}
+ ldr r3, =pDivRom_idiv
+ ldr r3, [r3, #0] // Load address of function
+ blx r3 // Call divide function
+ pop {r4, pc}
+
+ .endfunc
+
+// ======== __aeabi_uidiv & __aeabi_uidivmod ========
+ .align 2
+
+ .section .text.__aeabi_uidiv
+
+ .global __aeabi_uidiv
+ .set __aeabi_uidivmod, __aeabi_uidiv // make __aeabi_uidivmod an alias
+ .global __aeabi_uidivmod
+ .global pDivRom_uidiv // pointer to the romdivide 'uidiv' function
+ .func
+ .thumb_func
+ .type __aeabi_uidiv, %function
+
+__aeabi_uidiv:
+ push {r4, lr}
+ ldr r3, =pDivRom_uidiv
+ ldr r3, [r3, #0] // Load address of function
+ blx r3 // Call divide function
+ pop {r4, pc}
+
+ .endfunc
+
+#endif // (__USE_ROMDIVIDE)
diff --git a/source/freertos_blinky/example/src/cr_startup_lpc11u6x.c b/source/freertos_blinky/example/src/cr_startup_lpc11u6x.c
new file mode 100644
index 0000000..a9a3fd4
--- /dev/null
+++ b/source/freertos_blinky/example/src/cr_startup_lpc11u6x.c
@@ -0,0 +1,352 @@
+//*****************************************************************************
+// LPC11U6x Microcontroller Startup code for use with LPCXpresso IDE
+//
+// Version : 140113
+//*****************************************************************************
+//
+// Copyright(C) NXP Semiconductors, 2014
+// All rights reserved.
+//
+// Software that is described herein is for illustrative purposes only
+// which provides customers with programming information regarding the
+// LPC products. This software is supplied "AS IS" without any warranties of
+// any kind, and NXP Semiconductors and its licensor disclaim any and
+// all warranties, express or implied, including all implied warranties of
+// merchantability, fitness for a particular purpose and non-infringement of
+// intellectual property rights. NXP Semiconductors assumes no responsibility
+// or liability for the use of the software, conveys no license or rights under any
+// patent, copyright, mask work right, or any other intellectual property rights in
+// or to any products. NXP Semiconductors reserves the right to make changes
+// in the software without notification. NXP Semiconductors also makes no
+// representation or warranty that such application will be suitable for the
+// specified use without further testing or modification.
+//
+// Permission to use, copy, modify, and distribute this software and its
+// documentation is hereby granted, under NXP Semiconductors' and its
+// licensor's relevant copyrights in the software, without fee, provided that it
+// is used in conjunction with NXP Semiconductors microcontrollers. This
+// copyright, permission, and disclaimer notice must appear in all copies of
+// this code.
+//*****************************************************************************
+
+#if defined (__cplusplus)
+#ifdef __REDLIB__
+#error Redlib does not support C++
+#else
+//*****************************************************************************
+//
+// The entry point for the C++ library startup
+//
+//*****************************************************************************
+extern "C" {
+ extern void __libc_init_array(void);
+}
+#endif
+#endif
+
+#define WEAK __attribute__ ((weak))
+#define ALIAS(f) __attribute__ ((weak, alias (#f)))
+
+//*****************************************************************************
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+//*****************************************************************************
+#if defined (__USE_CMSIS) || defined (__USE_LPCOPEN)
+// Declaration of external SystemInit function
+extern void SystemInit(void);
+#endif
+
+// Patch the AEABI integer divide functions to use MCU's romdivide library
+#ifdef __USE_ROMDIVIDE
+// Location in memory that holds the address of the ROM Driver table
+#define PTR_ROM_DRIVER_TABLE ((unsigned int *)(0x1FFF1FF8))
+// Variables to store addresses of idiv and udiv functions within MCU ROM
+unsigned int *pDivRom_idiv;
+unsigned int *pDivRom_uidiv;
+#endif
+
+//*****************************************************************************
+//
+// Forward declaration of the default handlers. These are aliased.
+// When the application defines a handler (with the same name), this will
+// automatically take precedence over these weak definitions
+//
+//*****************************************************************************
+ void ResetISR(void);
+WEAK void NMI_Handler(void);
+WEAK void HardFault_Handler(void);
+WEAK void SVC_Handler(void);
+WEAK void PendSV_Handler(void);
+WEAK void SysTick_Handler(void);
+WEAK void IntDefaultHandler(void);
+//*****************************************************************************
+//
+// Forward declaration of the specific IRQ handlers. These are aliased
+// to the IntDefaultHandler, which is a 'forever' loop. When the application
+// defines a handler (with the same name), this will automatically take
+// precedence over these weak definitions
+//
+//*****************************************************************************
+void PIN_INT0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIN_INT1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIN_INT2_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIN_INT3_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIN_INT4_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIN_INT5_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIN_INT6_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIN_INT7_IRQHandler (void) ALIAS(IntDefaultHandler);
+void GINT0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void GINT1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void I2C1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void USART1_4_IRQHandler (void) ALIAS(IntDefaultHandler);
+void USART2_3_IRQHandler (void) ALIAS(IntDefaultHandler);
+void SCT0_1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void SSP1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void I2C0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void TIMER16_0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void TIMER16_1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void TIMER32_0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void TIMER32_1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void SSP0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void USART0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void USB_IRQHandler (void) ALIAS(IntDefaultHandler);
+void USB_FIQHandler (void) ALIAS(IntDefaultHandler);
+void ADCA_IRQHandler (void) ALIAS(IntDefaultHandler);
+void RTC_IRQHandler (void) ALIAS(IntDefaultHandler);
+void BOD_WDT_IRQHandler (void) ALIAS(IntDefaultHandler);
+void FMC_IRQHandler (void) ALIAS(IntDefaultHandler);
+void DMA_IRQHandler (void) ALIAS(IntDefaultHandler);
+void ADCB_IRQHandler (void) ALIAS(IntDefaultHandler);
+void USBWakeup_IRQHandler (void) ALIAS(IntDefaultHandler);
+
+//*****************************************************************************
+// The entry point for the application.
+// __main() is the entry point for redlib based applications
+// main() is the entry point for newlib based applications
+//*****************************************************************************
+#if defined (__REDLIB__)
+extern void __main(void);
+#endif
+extern int main(void);
+//*****************************************************************************
+//
+// External declaration for the pointer to the stack top from the Linker Script
+//
+//*****************************************************************************
+extern void _vStackTop(void);
+
+//*****************************************************************************
+#if defined (__cplusplus)
+} // extern "C"
+#endif
+//*****************************************************************************
+//
+// The vector table. Note that the proper constructs must be placed on this to
+// ensure that it ends up at physical address 0x0000.0000.
+//
+//*****************************************************************************
+extern void (* const g_pfnVectors[])(void);
+__attribute__ ((section(".isr_vector")))
+void (* const g_pfnVectors[])(void) = {
+ &_vStackTop, // The initial stack pointer
+ ResetISR, // The reset handler
+ NMI_Handler, // The NMI handler
+ HardFault_Handler, // The hard fault handler
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ SVC_Handler, // SVCall handler
+ 0, // Reserved
+ 0, // Reserved
+ PendSV_Handler, // The PendSV handler
+ SysTick_Handler, // The SysTick handler
+
+ // LPC11U6x specific handlers
+ PIN_INT0_IRQHandler, // 0 - GPIO pin interrupt 0
+ PIN_INT1_IRQHandler, // 1 - GPIO pin interrupt 1
+ PIN_INT2_IRQHandler, // 2 - GPIO pin interrupt 2
+ PIN_INT3_IRQHandler, // 3 - GPIO pin interrupt 3
+ PIN_INT4_IRQHandler, // 4 - GPIO pin interrupt 4
+ PIN_INT5_IRQHandler, // 5 - GPIO pin interrupt 5
+ PIN_INT6_IRQHandler, // 6 - GPIO pin interrupt 6
+ PIN_INT7_IRQHandler, // 7 - GPIO pin interrupt 7
+ GINT0_IRQHandler, // 8 - GPIO GROUP0 interrupt
+ GINT1_IRQHandler, // 9 - GPIO GROUP1 interrupt
+ I2C1_IRQHandler, // 10 - I2C1
+ USART1_4_IRQHandler, // 11 - combined USART1 & 4 interrupt
+ USART2_3_IRQHandler, // 12 - combined USART2 & 3 interrupt
+ SCT0_1_IRQHandler, // 13 - combined SCT0 and 1 interrupt
+ SSP1_IRQHandler, // 14 - SPI/SSP1 Interrupt
+ I2C0_IRQHandler, // 15 - I2C0
+ TIMER16_0_IRQHandler, // 16 - CT16B0 (16-bit Timer 0)
+ TIMER16_1_IRQHandler, // 17 - CT16B1 (16-bit Timer 1)
+ TIMER32_0_IRQHandler, // 18 - CT32B0 (32-bit Timer 0)
+ TIMER32_1_IRQHandler, // 19 - CT32B1 (32-bit Timer 1)
+ SSP0_IRQHandler, // 20 - SPI/SSP0 Interrupt
+ USART0_IRQHandler, // 21 - USART0
+ USB_IRQHandler, // 22 - USB IRQ
+ USB_FIQHandler, // 23 - USB FIQ
+ ADCA_IRQHandler, // 24 - ADC A(A/D Converter)
+ RTC_IRQHandler, // 25 - Real Time CLock interrpt
+ BOD_WDT_IRQHandler, // 25 - Combined Brownout/Watchdog interrupt
+ FMC_IRQHandler, // 27 - IP2111 Flash Memory Controller
+ DMA_IRQHandler, // 28 - DMA interrupt
+ ADCB_IRQHandler, // 24 - ADC B (A/D Converter)
+ USBWakeup_IRQHandler, // 30 - USB wake-up interrupt
+ 0, // 31 - Reserved
+};
+
+//*****************************************************************************
+// Functions to carry out the initialization of RW and BSS data sections. These
+// are written as separate functions rather than being inlined within the
+// ResetISR() function in order to cope with MCUs with multiple banks of
+// memory.
+//*****************************************************************************
+__attribute__ ((section(".after_vectors")))
+void data_init(unsigned int romstart, unsigned int start, unsigned int len) {
+ unsigned int *pulDest = (unsigned int*) start;
+ unsigned int *pulSrc = (unsigned int*) romstart;
+ unsigned int loop;
+ for (loop = 0; loop < len; loop = loop + 4)
+ *pulDest++ = *pulSrc++;
+}
+
+__attribute__ ((section(".after_vectors")))
+void bss_init(unsigned int start, unsigned int len) {
+ unsigned int *pulDest = (unsigned int*) start;
+ unsigned int loop;
+ for (loop = 0; loop < len; loop = loop + 4)
+ *pulDest++ = 0;
+}
+
+//*****************************************************************************
+// The following symbols are constructs generated by the linker, indicating
+// the location of various points in the "Global Section Table". This table is
+// created by the linker via the Code Red managed linker script mechanism. It
+// contains the load address, execution address and length of each RW data
+// section and the execution and length of each BSS (zero initialized) section.
+//*****************************************************************************
+extern unsigned int __data_section_table;
+extern unsigned int __data_section_table_end;
+extern unsigned int __bss_section_table;
+extern unsigned int __bss_section_table_end;
+
+//*****************************************************************************
+// Reset entry point for your code.
+// Sets up a simple runtime environment and initializes the C/C++
+// library.
+//*****************************************************************************
+__attribute__ ((section(".after_vectors")))
+void
+ResetISR(void) {
+
+ // Optionally enable RAM banks that may be off by default at reset
+#if !defined (DONT_ENABLE_DISABLED_RAMBANKS)
+ volatile unsigned int *SYSCON_SYSAHBCLKCTRL = (unsigned int *) 0x40048080;
+ // Ensure that RAM1(26) and USBSRAM(27) bits in SYSAHBCLKCTRL are set
+ *SYSCON_SYSAHBCLKCTRL |= (1 << 26) | (1 <<27);
+#endif
+
+ //
+ // Copy the data sections from flash to SRAM.
+ //
+ unsigned int LoadAddr, ExeAddr, SectionLen;
+ unsigned int *SectionTableAddr;
+
+ // Load base address of Global Section Table
+ SectionTableAddr = &__data_section_table;
+
+ // Copy the data sections from flash to SRAM.
+ while (SectionTableAddr < &__data_section_table_end) {
+ LoadAddr = *SectionTableAddr++;
+ ExeAddr = *SectionTableAddr++;
+ SectionLen = *SectionTableAddr++;
+ data_init(LoadAddr, ExeAddr, SectionLen);
+ }
+ // At this point, SectionTableAddr = &__bss_section_table;
+ // Zero fill the bss segment
+ while (SectionTableAddr < &__bss_section_table_end) {
+ ExeAddr = *SectionTableAddr++;
+ SectionLen = *SectionTableAddr++;
+ bss_init(ExeAddr, SectionLen);
+ }
+
+ // Patch the AEABI integer divide functions to use MCU's romdivide library
+#ifdef __USE_ROMDIVIDE
+ // Get address of Integer division routines function table in ROM
+ unsigned int *div_ptr = (unsigned int *)((unsigned int *)*(PTR_ROM_DRIVER_TABLE))[4];
+ // Get addresses of integer divide routines in ROM
+ // These address are then used by the code in aeabi_romdiv_patch.s
+ pDivRom_idiv = (unsigned int *)div_ptr[0];
+ pDivRom_uidiv = (unsigned int *)div_ptr[1];
+#endif
+
+#if defined (__USE_CMSIS) || defined (__USE_LPCOPEN)
+ SystemInit();
+#endif
+
+#if defined (__cplusplus)
+ //
+ // Call C++ library initialisation
+ //
+ __libc_init_array();
+#endif
+
+#if defined (__REDLIB__)
+ // Call the Redlib library, which in turn calls main()
+ __main() ;
+#else
+ main();
+#endif
+ //
+ // main() shouldn't return, but if it does, we'll just enter an infinite loop
+ //
+ while (1) {
+ ;
+ }
+}
+
+//*****************************************************************************
+// Default exception handlers. Override the ones here by defining your own
+// handler routines in your application code.
+//*****************************************************************************
+__attribute__ ((section(".after_vectors")))
+void NMI_Handler(void)
+{ while(1) { }
+}
+__attribute__ ((section(".after_vectors")))
+void HardFault_Handler(void)
+{ while(1) { }
+}
+
+__attribute__ ((section(".after_vectors")))
+void SVC_Handler(void)
+{ while(1) { }
+}
+
+__attribute__ ((section(".after_vectors")))
+void PendSV_Handler(void)
+{ while(1) { }
+}
+
+__attribute__ ((section(".after_vectors")))
+void SysTick_Handler(void)
+{ while(1) { }
+}
+
+//*****************************************************************************
+//
+// Processor ends up here if an unexpected interrupt occurs or a specific
+// handler is not present in the application code.
+//
+//*****************************************************************************
+__attribute__ ((section(".after_vectors")))
+void IntDefaultHandler(void)
+{ while(1) { }
+}
diff --git a/source/freertos_blinky/example/src/crp.c b/source/freertos_blinky/example/src/crp.c
new file mode 100644
index 0000000..5bbb587
--- /dev/null
+++ b/source/freertos_blinky/example/src/crp.c
@@ -0,0 +1,14 @@
+/*
+ * crp.c
+ * Source file to create CRP word expected by Code Red linker
+ */
+
+#ifdef __CODE_RED
+#include
+
+// Variable to store CRP value in. Will be placed automatically
+// by the linker when "Enable Code Read Protect" selected.
+// See crp.h header for more information
+__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
+
+#endif
diff --git a/source/freertos_blinky/example/src/freertos_blinky.c b/source/freertos_blinky/example/src/freertos_blinky.c
new file mode 100644
index 0000000..05d31d5
--- /dev/null
+++ b/source/freertos_blinky/example/src/freertos_blinky.c
@@ -0,0 +1,120 @@
+/*
+ * @brief FreeRTOS Blinky example
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "board.h"
+#include "FreeRTOS.h"
+#include "task.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/* Sets up system hardware */
+static void prvSetupHardware(void)
+{
+ SystemCoreClockUpdate();
+ Board_Init();
+}
+
+/* LED0 toggle thread */
+static void vLEDTask0(void *pvParameters) {
+ bool LedState = false;
+ while (1) {
+ Board_LED_Set(0, LedState);
+ LedState = (bool) !LedState;
+
+ vTaskDelay(configTICK_RATE_HZ / 2);
+ }
+}
+
+/* LED1 toggle thread */
+static void vLEDTask1(void *pvParameters) {
+ bool LedState = false;
+ while (1) {
+ Board_LED_Set(1, LedState);
+ LedState = (bool) !LedState;
+
+ vTaskDelay(configTICK_RATE_HZ * 2);
+ }
+}
+
+/* LED2 toggle thread */
+static void vLEDTask2(void *pvParameters) {
+ bool LedState = false;
+ while (1) {
+ Board_LED_Set(2, LedState);
+ LedState = (bool) !LedState;
+
+ vTaskDelay(configTICK_RATE_HZ);
+ }
+}
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/**
+ * @brief main routine for FreeRTOS blinky example
+ * @return Nothing, function should not exit
+ */
+int main(void)
+{
+ prvSetupHardware();
+
+ /* LED1 toggle thread */
+ xTaskCreate(vLEDTask1, (signed char *) "vTaskLed1",
+ configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY + 1UL),
+ (xTaskHandle *) NULL);
+
+ /* LED2 toggle thread */
+ xTaskCreate(vLEDTask2, (signed char *) "vTaskLed2",
+ configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY + 1UL),
+ (xTaskHandle *) NULL);
+
+ /* LED0 toggle thread */
+ xTaskCreate(vLEDTask0, (signed char *) "vTaskLed0",
+ configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY + 1UL),
+ (xTaskHandle *) NULL);
+
+ /* Start the scheduler */
+ vTaskStartScheduler();
+
+ /* Should never arrive here */
+ return 1;
+}
diff --git a/source/freertos_blinky/example/src/mtb.c b/source/freertos_blinky/example/src/mtb.c
new file mode 100644
index 0000000..4a65389
--- /dev/null
+++ b/source/freertos_blinky/example/src/mtb.c
@@ -0,0 +1,86 @@
+//*****************************************************************************
+// +--+
+// | ++----+
+// +-++ |
+// | |
+// +-+--+ |
+// | +--+--+
+// +----+ Copyright (c) 2013 Code Red Technologies Ltd.
+//
+// mtb.c
+//
+// Optionally defines an array to be used as a buffer for Micro Trace
+// Buffer (MTB) instruction trace on Cortex-M0+ parts
+//
+// Version : 130502
+//
+// Software License Agreement
+//
+// The software is owned by Code Red Technologies and/or its suppliers, and is
+// protected under applicable copyright laws. All rights are reserved. Any
+// use in violation of the foregoing restrictions may subject the user to criminal
+// sanctions under applicable laws, as well as to civil liability for the breach
+// of the terms and conditions of this license.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT
+// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH
+// CODE RED TECHNOLOGIES LTD.
+//
+//*****************************************************************************
+
+/*******************************************************************
+ * Symbols controlling behavior of this code...
+ *
+ * __MTB_DISABLE
+ * If this symbol is defined, then the buffer array for the MTB
+ * will not be created.
+ *
+ * __MTB_BUFFER_SIZE
+ * Symbol specifying the sizer of the buffer array for the MTB.
+ * This must be a power of 2 in size, and fit into the available
+ * RAM. The MTB buffer will also be aligned to its 'size'
+ * boundary and be placed at the start of a RAM bank (which
+ * should ensure minimal or zero padding due to alignment).
+ *
+ * __MTB_RAM_BANK
+ * Allows MTB Buffer to be placed into specific RAM bank. When
+ * this is not defined, the "default" (first if there are
+ * several) RAM bank is used.
+ *******************************************************************/
+
+// Ignore with none Code Red tools
+#if defined (__CODE_RED)
+
+// Allow MTB to be removed by setting a define (via command line)
+#if !defined (__MTB_DISABLE)
+
+ // Allow for MTB buffer size being set by define set via command line
+ // Otherwise provide small default buffer
+ #if !defined (__MTB_BUFFER_SIZE)
+ #define __MTB_BUFFER_SIZE 128
+ #endif
+
+ // Check that buffer size requested is >0 bytes in size
+ #if (__MTB_BUFFER_SIZE > 0)
+ // Pull in MTB related macros
+ #include
+
+ // Check if MYTB buffer is to be placed in specific RAM bank
+ #if defined(__MTB_RAM_BANK)
+ // Place MTB buffer into explicit bank of RAM
+ __CR_MTB_BUFFER_EXT(__MTB_BUFFER_SIZE,__MTB_RAM_BANK);
+ #else
+ // Place MTB buffer into 'default' bank of RAM
+ __CR_MTB_BUFFER(__MTB_BUFFER_SIZE);
+
+ #endif // defined(__MTB_RAM_BANK)
+
+ #endif // (__MTB_BUFFER_SIZE > 0)
+
+#endif // !defined (__MTB_DISABLE)
+
+#endif // defined (__CODE_RED)
+
diff --git a/source/freertos_blinky/example/src/sysinit.c b/source/freertos_blinky/example/src/sysinit.c
new file mode 100644
index 0000000..65dcf24
--- /dev/null
+++ b/source/freertos_blinky/example/src/sysinit.c
@@ -0,0 +1,60 @@
+/*
+ * @brief Common SystemInit function for LPC11u6x chips
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+ #include "board.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Set up and initialize hardware prior to call to main */
+void SystemInit(void)
+{
+#if defined(NO_BOARD_LIB)
+ /* Chip specific SystemInit */
+ Chip_SystemInit();
+#else
+ /* Setup system clocking and muxing */
+ Board_SystemInit();
+#endif
+}
diff --git a/source/freertos_blinky/freertos/inc/FreeRTOS.h b/source/freertos_blinky/freertos/inc/FreeRTOS.h
new file mode 100644
index 0000000..d2e6904
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/FreeRTOS.h
@@ -0,0 +1,621 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+#ifndef INC_FREERTOS_H
+#define INC_FREERTOS_H
+
+
+/*
+ * Include the generic headers required for the FreeRTOS port being used.
+ */
+#include
+
+/* Basic FreeRTOS definitions. */
+#include "projdefs.h"
+
+/* Application specific configuration options. */
+#include "FreeRTOSConfig.h"
+
+/* configUSE_PORT_OPTIMISED_TASK_SELECTION must be defined before portable.h
+is included as it is used by the port layer. */
+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
+ #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
+#endif
+
+/* Definitions specific to the port being used. */
+#include "portable.h"
+
+
+/* Defines the prototype to which the application task hook function must
+conform. */
+typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
+
+
+
+
+
+/*
+ * Check all the required application specific macros have been defined.
+ * These macros are application specific and (as downloaded) are defined
+ * within FreeRTOSConfig.h.
+ */
+
+#ifndef configUSE_PREEMPTION
+ #error Missing definition: configUSE_PREEMPTION should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_IDLE_HOOK
+ #error Missing definition: configUSE_IDLE_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_TICK_HOOK
+ #error Missing definition: configUSE_TICK_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_CO_ROUTINES
+ #error Missing definition: configUSE_CO_ROUTINES should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskPrioritySet
+ #error Missing definition: INCLUDE_vTaskPrioritySet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_uxTaskPriorityGet
+ #error Missing definition: INCLUDE_uxTaskPriorityGet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskDelete
+ #error Missing definition: INCLUDE_vTaskDelete should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskSuspend
+ #error Missing definition: INCLUDE_vTaskSuspend should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskDelayUntil
+ #error Missing definition: INCLUDE_vTaskDelayUntil should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskDelay
+ #error Missing definition: INCLUDE_vTaskDelay should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_16_BIT_TICKS
+ #error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_xTaskGetIdleTaskHandle
+ #define INCLUDE_xTaskGetIdleTaskHandle 0
+#endif
+
+#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle
+ #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
+#endif
+
+#ifndef INCLUDE_xQueueGetMutexHolder
+ #define INCLUDE_xQueueGetMutexHolder 0
+#endif
+
+#ifndef INCLUDE_xSemaphoreGetMutexHolder
+ #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder
+#endif
+
+#ifndef INCLUDE_pcTaskGetTaskName
+ #define INCLUDE_pcTaskGetTaskName 0
+#endif
+
+#ifndef configUSE_APPLICATION_TASK_TAG
+ #define configUSE_APPLICATION_TASK_TAG 0
+#endif
+
+#ifndef INCLUDE_uxTaskGetStackHighWaterMark
+ #define INCLUDE_uxTaskGetStackHighWaterMark 0
+#endif
+
+#ifndef INCLUDE_eTaskGetState
+ #define INCLUDE_eTaskGetState 0
+#endif
+
+#ifndef configUSE_RECURSIVE_MUTEXES
+ #define configUSE_RECURSIVE_MUTEXES 0
+#endif
+
+#ifndef configUSE_MUTEXES
+ #define configUSE_MUTEXES 0
+#endif
+
+#ifndef configUSE_TIMERS
+ #define configUSE_TIMERS 0
+#endif
+
+#ifndef configUSE_COUNTING_SEMAPHORES
+ #define configUSE_COUNTING_SEMAPHORES 0
+#endif
+
+#ifndef configUSE_ALTERNATIVE_API
+ #define configUSE_ALTERNATIVE_API 0
+#endif
+
+#ifndef portCRITICAL_NESTING_IN_TCB
+ #define portCRITICAL_NESTING_IN_TCB 0
+#endif
+
+#ifndef configMAX_TASK_NAME_LEN
+ #define configMAX_TASK_NAME_LEN 16
+#endif
+
+#ifndef configIDLE_SHOULD_YIELD
+ #define configIDLE_SHOULD_YIELD 1
+#endif
+
+#if configMAX_TASK_NAME_LEN < 1
+ #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h
+#endif
+
+#ifndef INCLUDE_xTaskResumeFromISR
+ #define INCLUDE_xTaskResumeFromISR 1
+#endif
+
+#ifndef configASSERT
+ #define configASSERT( x )
+ #define configASSERT_DEFINED 0
+#else
+ #define configASSERT_DEFINED 1
+#endif
+
+/* The timers module relies on xTaskGetSchedulerState(). */
+#if configUSE_TIMERS == 1
+
+ #ifndef configTIMER_TASK_PRIORITY
+ #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined.
+ #endif /* configTIMER_TASK_PRIORITY */
+
+ #ifndef configTIMER_QUEUE_LENGTH
+ #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined.
+ #endif /* configTIMER_QUEUE_LENGTH */
+
+ #ifndef configTIMER_TASK_STACK_DEPTH
+ #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined.
+ #endif /* configTIMER_TASK_STACK_DEPTH */
+
+#endif /* configUSE_TIMERS */
+
+#ifndef INCLUDE_xTaskGetSchedulerState
+ #define INCLUDE_xTaskGetSchedulerState 0
+#endif
+
+#ifndef INCLUDE_xTaskGetCurrentTaskHandle
+ #define INCLUDE_xTaskGetCurrentTaskHandle 0
+#endif
+
+
+#ifndef portSET_INTERRUPT_MASK_FROM_ISR
+ #define portSET_INTERRUPT_MASK_FROM_ISR() 0
+#endif
+
+#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR
+ #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
+#endif
+
+#ifndef portCLEAN_UP_TCB
+ #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB
+#endif
+
+#ifndef portSETUP_TCB
+ #define portSETUP_TCB( pxTCB ) ( void ) pxTCB
+#endif
+
+#ifndef configQUEUE_REGISTRY_SIZE
+ #define configQUEUE_REGISTRY_SIZE 0U
+#endif
+
+#if ( configQUEUE_REGISTRY_SIZE < 1 )
+ #define vQueueAddToRegistry( xQueue, pcName )
+ #define vQueueUnregisterQueue( xQueue )
+#endif
+
+#ifndef portPOINTER_SIZE_TYPE
+ #define portPOINTER_SIZE_TYPE unsigned long
+#endif
+
+/* Remove any unused trace macros. */
+#ifndef traceSTART
+ /* Used to perform any necessary initialisation - for example, open a file
+ into which trace is to be written. */
+ #define traceSTART()
+#endif
+
+#ifndef traceEND
+ /* Use to close a trace, for example close a file into which trace has been
+ written. */
+ #define traceEND()
+#endif
+
+#ifndef traceTASK_SWITCHED_IN
+ /* Called after a task has been selected to run. pxCurrentTCB holds a pointer
+ to the task control block of the selected task. */
+ #define traceTASK_SWITCHED_IN()
+#endif
+
+#ifndef traceINCREASE_TICK_COUNT
+ /* Called before stepping the tick count after waking from tickless idle
+ sleep. */
+ #define traceINCREASE_TICK_COUNT( x )
+#endif
+
+#ifndef traceLOW_POWER_IDLE_BEGIN
+ /* Called immediately before entering tickless idle. */
+ #define traceLOW_POWER_IDLE_BEGIN()
+#endif
+
+#ifndef traceLOW_POWER_IDLE_END
+ /* Called when returning to the Idle task after a tickless idle. */
+ #define traceLOW_POWER_IDLE_END()
+#endif
+
+#ifndef traceTASK_SWITCHED_OUT
+ /* Called before a task has been selected to run. pxCurrentTCB holds a pointer
+ to the task control block of the task being switched out. */
+ #define traceTASK_SWITCHED_OUT()
+#endif
+
+#ifndef traceTASK_PRIORITY_INHERIT
+ /* Called when a task attempts to take a mutex that is already held by a
+ lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task
+ that holds the mutex. uxInheritedPriority is the priority the mutex holder
+ will inherit (the priority of the task that is attempting to obtain the
+ muted. */
+ #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority )
+#endif
+
+#ifndef traceTASK_PRIORITY_DISINHERIT
+ /* Called when a task releases a mutex, the holding of which had resulted in
+ the task inheriting the priority of a higher priority task.
+ pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the
+ mutex. uxOriginalPriority is the task's configured (base) priority. */
+ #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority )
+#endif
+
+#ifndef traceBLOCKING_ON_QUEUE_RECEIVE
+ /* Task is about to block because it cannot read from a
+ queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore
+ upon which the read was attempted. pxCurrentTCB points to the TCB of the
+ task that attempted the read. */
+ #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue )
+#endif
+
+#ifndef traceBLOCKING_ON_QUEUE_SEND
+ /* Task is about to block because it cannot write to a
+ queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore
+ upon which the write was attempted. pxCurrentTCB points to the TCB of the
+ task that attempted the write. */
+ #define traceBLOCKING_ON_QUEUE_SEND( pxQueue )
+#endif
+
+#ifndef configCHECK_FOR_STACK_OVERFLOW
+ #define configCHECK_FOR_STACK_OVERFLOW 0
+#endif
+
+/* The following event macros are embedded in the kernel API calls. */
+
+#ifndef traceMOVED_TASK_TO_READY_STATE
+ #define traceMOVED_TASK_TO_READY_STATE( pxTCB )
+#endif
+
+#ifndef traceQUEUE_CREATE
+ #define traceQUEUE_CREATE( pxNewQueue )
+#endif
+
+#ifndef traceQUEUE_CREATE_FAILED
+ #define traceQUEUE_CREATE_FAILED( ucQueueType )
+#endif
+
+#ifndef traceCREATE_MUTEX
+ #define traceCREATE_MUTEX( pxNewQueue )
+#endif
+
+#ifndef traceCREATE_MUTEX_FAILED
+ #define traceCREATE_MUTEX_FAILED()
+#endif
+
+#ifndef traceGIVE_MUTEX_RECURSIVE
+ #define traceGIVE_MUTEX_RECURSIVE( pxMutex )
+#endif
+
+#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED
+ #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex )
+#endif
+
+#ifndef traceTAKE_MUTEX_RECURSIVE
+ #define traceTAKE_MUTEX_RECURSIVE( pxMutex )
+#endif
+
+#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED
+ #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex )
+#endif
+
+#ifndef traceCREATE_COUNTING_SEMAPHORE
+ #define traceCREATE_COUNTING_SEMAPHORE()
+#endif
+
+#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED
+ #define traceCREATE_COUNTING_SEMAPHORE_FAILED()
+#endif
+
+#ifndef traceQUEUE_SEND
+ #define traceQUEUE_SEND( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FAILED
+ #define traceQUEUE_SEND_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE
+ #define traceQUEUE_RECEIVE( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK
+ #define traceQUEUE_PEEK( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK_FROM_ISR
+ #define traceQUEUE_PEEK_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FAILED
+ #define traceQUEUE_RECEIVE_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FROM_ISR
+ #define traceQUEUE_SEND_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FROM_ISR_FAILED
+ #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FROM_ISR
+ #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED
+ #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED
+ #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_DELETE
+ #define traceQUEUE_DELETE( pxQueue )
+#endif
+
+#ifndef traceTASK_CREATE
+ #define traceTASK_CREATE( pxNewTCB )
+#endif
+
+#ifndef traceTASK_CREATE_FAILED
+ #define traceTASK_CREATE_FAILED()
+#endif
+
+#ifndef traceTASK_DELETE
+ #define traceTASK_DELETE( pxTaskToDelete )
+#endif
+
+#ifndef traceTASK_DELAY_UNTIL
+ #define traceTASK_DELAY_UNTIL()
+#endif
+
+#ifndef traceTASK_DELAY
+ #define traceTASK_DELAY()
+#endif
+
+#ifndef traceTASK_PRIORITY_SET
+ #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority )
+#endif
+
+#ifndef traceTASK_SUSPEND
+ #define traceTASK_SUSPEND( pxTaskToSuspend )
+#endif
+
+#ifndef traceTASK_RESUME
+ #define traceTASK_RESUME( pxTaskToResume )
+#endif
+
+#ifndef traceTASK_RESUME_FROM_ISR
+ #define traceTASK_RESUME_FROM_ISR( pxTaskToResume )
+#endif
+
+#ifndef traceTASK_INCREMENT_TICK
+ #define traceTASK_INCREMENT_TICK( xTickCount )
+#endif
+
+#ifndef traceTIMER_CREATE
+ #define traceTIMER_CREATE( pxNewTimer )
+#endif
+
+#ifndef traceTIMER_CREATE_FAILED
+ #define traceTIMER_CREATE_FAILED()
+#endif
+
+#ifndef traceTIMER_COMMAND_SEND
+ #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn )
+#endif
+
+#ifndef traceTIMER_EXPIRED
+ #define traceTIMER_EXPIRED( pxTimer )
+#endif
+
+#ifndef traceTIMER_COMMAND_RECEIVED
+ #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue )
+#endif
+
+#ifndef traceMALLOC
+ #define traceMALLOC( pvAddress, uiSize )
+#endif
+
+#ifndef traceFREE
+ #define traceFREE( pvAddress, uiSize )
+#endif
+
+#ifndef configGENERATE_RUN_TIME_STATS
+ #define configGENERATE_RUN_TIME_STATS 0
+#endif
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+ #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
+ #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base.
+ #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */
+
+ #ifndef portGET_RUN_TIME_COUNTER_VALUE
+ #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE
+ #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information.
+ #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */
+ #endif /* portGET_RUN_TIME_COUNTER_VALUE */
+
+#endif /* configGENERATE_RUN_TIME_STATS */
+
+#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
+ #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
+#endif
+
+#ifndef configUSE_MALLOC_FAILED_HOOK
+ #define configUSE_MALLOC_FAILED_HOOK 0
+#endif
+
+#ifndef portPRIVILEGE_BIT
+ #define portPRIVILEGE_BIT ( ( unsigned portBASE_TYPE ) 0x00 )
+#endif
+
+#ifndef portYIELD_WITHIN_API
+ #define portYIELD_WITHIN_API portYIELD
+#endif
+
+#ifndef pvPortMallocAligned
+ #define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMalloc( ( x ) ) ) : ( puxStackBuffer ) )
+#endif
+
+#ifndef vPortFreeAligned
+ #define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree )
+#endif
+
+#ifndef portSUPPRESS_TICKS_AND_SLEEP
+ #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )
+#endif
+
+#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP
+ #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
+#endif
+
+#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2
+ #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2
+#endif
+
+#ifndef configUSE_TICKLESS_IDLE
+ #define configUSE_TICKLESS_IDLE 0
+#endif
+
+#ifndef configPRE_SLEEP_PROCESSING
+ #define configPRE_SLEEP_PROCESSING( x )
+#endif
+
+#ifndef configPOST_SLEEP_PROCESSING
+ #define configPOST_SLEEP_PROCESSING( x )
+#endif
+
+#ifndef configUSE_QUEUE_SETS
+ #define configUSE_QUEUE_SETS 0
+#endif
+
+#ifndef portTASK_USES_FLOATING_POINT
+ #define portTASK_USES_FLOATING_POINT()
+#endif
+
+#ifndef configUSE_TIME_SLICING
+ #define configUSE_TIME_SLICING 1
+#endif
+
+#ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS
+ #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
+#endif
+
+#ifndef configUSE_NEWLIB_REENTRANT
+ #define configUSE_NEWLIB_REENTRANT 0
+#endif
+
+#ifndef configUSE_STATS_FORMATTING_FUNCTIONS
+ #define configUSE_STATS_FORMATTING_FUNCTIONS 0
+#endif
+
+#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
+#endif
+
+/* For backward compatability. */
+#define eTaskStateGet eTaskGetState
+
+#endif /* INC_FREERTOS_H */
+
diff --git a/source/freertos_blinky/freertos/inc/StackMacros.h b/source/freertos_blinky/freertos/inc/StackMacros.h
new file mode 100644
index 0000000..9c51c70
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/StackMacros.h
@@ -0,0 +1,180 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+#ifndef STACK_MACROS_H
+#define STACK_MACROS_H
+
+/*
+ * Call the stack overflow hook function if the stack of the task being swapped
+ * out is currently overflowed, or looks like it might have overflowed in the
+ * past.
+ *
+ * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
+ * the current stack state only - comparing the current top of stack value to
+ * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
+ * will also cause the last few stack bytes to be checked to ensure the value
+ * to which the bytes were set when the task was created have not been
+ * overwritten. Note this second test does not guarantee that an overflowed
+ * stack will always be recognised.
+ */
+
+/*-----------------------------------------------------------*/
+
+#if( configCHECK_FOR_STACK_OVERFLOW == 0 )
+
+ /* FreeRTOSConfig.h is not set to check for stack overflows. */
+ #define taskFIRST_CHECK_FOR_STACK_OVERFLOW()
+ #define taskSECOND_CHECK_FOR_STACK_OVERFLOW()
+
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */
+/*-----------------------------------------------------------*/
+
+#if( configCHECK_FOR_STACK_OVERFLOW == 1 )
+
+ /* FreeRTOSConfig.h is only set to use the first method of
+ overflow checking. */
+ #define taskSECOND_CHECK_FOR_STACK_OVERFLOW()
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) )
+
+ /* Only the current stack state is to be checked. */
+ #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \
+ { \
+ /* Is the currently saved stack pointer within the stack limit? */ \
+ if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
+ { \
+ vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
+ } \
+ }
+
+#endif /* configCHECK_FOR_STACK_OVERFLOW > 0 */
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) )
+
+ /* Only the current stack state is to be checked. */
+ #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \
+ { \
+ \
+ /* Is the currently saved stack pointer within the stack limit? */ \
+ if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \
+ { \
+ vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
+ } \
+ }
+
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
+
+ #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \
+ { \
+ static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
+ \
+ \
+ /* Has the extremity of the task stack ever been written over? */ \
+ if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
+ { \
+ vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
+ } \
+ }
+
+#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
+
+ #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \
+ { \
+ char *pcEndOfStack = ( char * ) pxCurrentTCB->pxEndOfStack; \
+ static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
+ \
+ \
+ pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
+ \
+ /* Has the extremity of the task stack ever been written over? */ \
+ if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
+ { \
+ vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
+ } \
+ }
+
+#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
+/*-----------------------------------------------------------*/
+
+#endif /* STACK_MACROS_H */
+
diff --git a/source/freertos_blinky/freertos/inc/croutine.h b/source/freertos_blinky/freertos/inc/croutine.h
new file mode 100644
index 0000000..85d7bf3
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/croutine.h
@@ -0,0 +1,758 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+#ifndef CO_ROUTINE_H
+#define CO_ROUTINE_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h must appear in source files before include croutine.h"
+#endif
+
+#include "list.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Used to hide the implementation of the co-routine control block. The
+control block structure however has to be included in the header due to
+the macro implementation of the co-routine functionality. */
+typedef void * xCoRoutineHandle;
+
+/* Defines the prototype to which co-routine functions must conform. */
+typedef void (*crCOROUTINE_CODE)( xCoRoutineHandle, unsigned portBASE_TYPE );
+
+typedef struct corCoRoutineControlBlock
+{
+ crCOROUTINE_CODE pxCoRoutineFunction;
+ xListItem xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */
+ xListItem xEventListItem; /*< List item used to place the CRCB in event lists. */
+ unsigned portBASE_TYPE uxPriority; /*< The priority of the co-routine in relation to other co-routines. */
+ unsigned portBASE_TYPE uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
+ unsigned short uxState; /*< Used internally by the co-routine implementation. */
+} corCRCB; /* Co-routine control block. Note must be identical in size down to uxPriority with tskTCB. */
+
+/**
+ * croutine. h
+ *
+ *
+ * Create a new co-routine and add it to the list of co-routines that are
+ * ready to run.
+ *
+ * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
+ * functions require special syntax - see the co-routine section of the WEB
+ * documentation for more information.
+ *
+ * @param uxPriority The priority with respect to other co-routines at which
+ * the co-routine will run.
+ *
+ * @param uxIndex Used to distinguish between different co-routines that
+ * execute the same function. See the example below and the co-routine section
+ * of the WEB documentation for further information.
+ *
+ * @return pdPASS if the co-routine was successfully created and added to a ready
+ * list, otherwise an error code defined with ProjDefs.h.
+ *
+ * Example usage:
+
+ // Co-routine to be created.
+ void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ static const char cLedToFlash[ 2 ] = { 5, 6 };
+ static const portTickType uxFlashRates[ 2 ] = { 200, 400 };
+
+ // Must start every co-routine with a call to crSTART();
+ crSTART( xHandle );
+
+ for( ;; )
+ {
+ // This co-routine just delays for a fixed period, then toggles
+ // an LED. Two co-routines are created using this function, so
+ // the uxIndex parameter is used to tell the co-routine which
+ // LED to flash and how long to delay. This assumes xQueue has
+ // already been created.
+ vParTestToggleLED( cLedToFlash[ uxIndex ] );
+ crDELAY( xHandle, uxFlashRates[ uxIndex ] );
+ }
+
+ // Must end every co-routine with a call to crEND();
+ crEND();
+ }
+
+ // Function that creates two co-routines.
+ void vOtherFunction( void )
+ {
+ unsigned char ucParameterToPass;
+ xTaskHandle xHandle;
+
+ // Create two co-routines at priority 0. The first is given index 0
+ // so (from the code above) toggles LED 5 every 200 ticks. The second
+ // is given index 1 so toggles LED 6 every 400 ticks.
+ for( uxIndex = 0; uxIndex < 2; uxIndex++ )
+ {
+ xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
+ }
+ }
+
+ *
+ * Run a co-routine.
+ *
+ * vCoRoutineSchedule() executes the highest priority co-routine that is able
+ * to run. The co-routine will execute until it either blocks, yields or is
+ * preempted by a task. Co-routines execute cooperatively so one
+ * co-routine cannot be preempted by another, but can be preempted by a task.
+ *
+ * If an application comprises of both tasks and co-routines then
+ * vCoRoutineSchedule should be called from the idle task (in an idle task
+ * hook).
+ *
+ * Example usage:
+
+ // This idle task hook will schedule a co-routine each time it is called.
+ // The rest of the idle task will execute between co-routine calls.
+ void vApplicationIdleHook( void )
+ {
+ vCoRoutineSchedule();
+ }
+
+ // Alternatively, if you do not require any other part of the idle task to
+ // execute, the idle task hook can call vCoRoutineScheduler() within an
+ // infinite loop.
+ void vApplicationIdleHook( void )
+ {
+ for( ;; )
+ {
+ vCoRoutineSchedule();
+ }
+ }
+
+ *
+ * This macro MUST always be called at the start of a co-routine function.
+ *
+ * Example usage:
+
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static long ulAVariable;
+
+ // Must start every co-routine with a call to crSTART();
+ crSTART( xHandle );
+
+ for( ;; )
+ {
+ // Co-routine functionality goes here.
+ }
+
+ // Must end every co-routine with a call to crEND();
+ crEND();
+ }
+ *
+ * This macro MUST always be called at the end of a co-routine function.
+ *
+ * Example usage:
+
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static long ulAVariable;
+
+ // Must start every co-routine with a call to crSTART();
+ crSTART( xHandle );
+
+ for( ;; )
+ {
+ // Co-routine functionality goes here.
+ }
+
+ // Must end every co-routine with a call to crEND();
+ crEND();
+ }
+ * \defgroup crSTART crSTART
+ * \ingroup Tasks
+ */
+#define crEND() }
+
+/*
+ * These macros are intended for internal use by the co-routine implementation
+ * only. The macros should not be used directly by application writers.
+ */
+#define crSET_STATE0( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
+#define crSET_STATE1( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
+
+/**
+ * croutine. h
+ *
+ *
+ * Delay a co-routine for a fixed period of time.
+ *
+ * crDELAY can only be called from the co-routine function itself - not
+ * from within a function called by the co-routine function. This is because
+ * co-routines do not maintain their own stack.
+ *
+ * @param xHandle The handle of the co-routine to delay. This is the xHandle
+ * parameter of the co-routine function.
+ *
+ * @param xTickToDelay The number of ticks that the co-routine should delay
+ * for. The actual amount of time this equates to is defined by
+ * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_RATE_MS
+ * can be used to convert ticks to milliseconds.
+ *
+ * Example usage:
+
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ // We are to delay for 200ms.
+ static const xTickType xDelayTime = 200 / portTICK_RATE_MS;
+
+ // Must start every co-routine with a call to crSTART();
+ crSTART( xHandle );
+
+ for( ;; )
+ {
+ // Delay for 200ms.
+ crDELAY( xHandle, xDelayTime );
+
+ // Do something here.
+ }
+
+ // Must end every co-routine with a call to crEND();
+ crEND();
+ }
+ *
+ * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
+ * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
+ *
+ * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
+ * xQueueSend() and xQueueReceive() can only be used from tasks.
+ *
+ * crQUEUE_SEND can only be called from the co-routine function itself - not
+ * from within a function called by the co-routine function. This is because
+ * co-routines do not maintain their own stack.
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xHandle The handle of the calling co-routine. This is the xHandle
+ * parameter of the co-routine function.
+ *
+ * @param pxQueue The handle of the queue on which the data will be posted.
+ * The handle is obtained as the return value when the queue is created using
+ * the xQueueCreate() API function.
+ *
+ * @param pvItemToQueue A pointer to the data being posted onto the queue.
+ * The number of bytes of each queued item is specified when the queue is
+ * created. This number of bytes is copied from pvItemToQueue into the queue
+ * itself.
+ *
+ * @param xTickToDelay The number of ticks that the co-routine should block
+ * to wait for space to become available on the queue, should space not be
+ * available immediately. The actual amount of time this equates to is defined
+ * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
+ * portTICK_RATE_MS can be used to convert ticks to milliseconds (see example
+ * below).
+ *
+ * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
+ * data was successfully posted onto the queue, otherwise it will be set to an
+ * error defined within ProjDefs.h.
+ *
+ * Example usage:
+
+ // Co-routine function that blocks for a fixed period then posts a number onto
+ // a queue.
+ static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static portBASE_TYPE xNumberToPost = 0;
+ static portBASE_TYPE xResult;
+
+ // Co-routines must begin with a call to crSTART().
+ crSTART( xHandle );
+
+ for( ;; )
+ {
+ // This assumes the queue has already been created.
+ crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
+
+ if( xResult != pdPASS )
+ {
+ // The message was not posted!
+ }
+
+ // Increment the number to be posted onto the queue.
+ xNumberToPost++;
+
+ // Delay for 100 ticks.
+ crDELAY( xHandle, 100 );
+ }
+
+ // Co-routines must end with a call to crEND().
+ crEND();
+ }
+ *
+ * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
+ * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
+ *
+ * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
+ * xQueueSend() and xQueueReceive() can only be used from tasks.
+ *
+ * crQUEUE_RECEIVE can only be called from the co-routine function itself - not
+ * from within a function called by the co-routine function. This is because
+ * co-routines do not maintain their own stack.
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xHandle The handle of the calling co-routine. This is the xHandle
+ * parameter of the co-routine function.
+ *
+ * @param pxQueue The handle of the queue from which the data will be received.
+ * The handle is obtained as the return value when the queue is created using
+ * the xQueueCreate() API function.
+ *
+ * @param pvBuffer The buffer into which the received item is to be copied.
+ * The number of bytes of each queued item is specified when the queue is
+ * created. This number of bytes is copied into pvBuffer.
+ *
+ * @param xTickToDelay The number of ticks that the co-routine should block
+ * to wait for data to become available from the queue, should data not be
+ * available immediately. The actual amount of time this equates to is defined
+ * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
+ * portTICK_RATE_MS can be used to convert ticks to milliseconds (see the
+ * crQUEUE_SEND example).
+ *
+ * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
+ * data was successfully retrieved from the queue, otherwise it will be set to
+ * an error code as defined within ProjDefs.h.
+ *
+ * Example usage:
+
+ // A co-routine receives the number of an LED to flash from a queue. It
+ // blocks on the queue until the number is received.
+ static void prvCoRoutineFlashWorkTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static portBASE_TYPE xResult;
+ static unsigned portBASE_TYPE uxLEDToFlash;
+
+ // All co-routines must start with a call to crSTART().
+ crSTART( xHandle );
+
+ for( ;; )
+ {
+ // Wait for data to become available on the queue.
+ crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+ if( xResult == pdPASS )
+ {
+ // We received the LED to flash - flash it!
+ vParTestToggleLED( uxLEDToFlash );
+ }
+ }
+
+ crEND();
+ }
+ *
+ * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
+ * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
+ * functions used by tasks.
+ *
+ * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
+ * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
+ * xQueueReceiveFromISR() can only be used to pass data between a task and and
+ * ISR.
+ *
+ * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
+ * that is being used from within a co-routine.
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
+ * the same queue multiple times from a single interrupt. The first call
+ * should always pass in pdFALSE. Subsequent calls should pass in
+ * the value returned from the previous call.
+ *
+ * @return pdTRUE if a co-routine was woken by posting onto the queue. This is
+ * used by the ISR to determine if a context switch may be required following
+ * the ISR.
+ *
+ * Example usage:
+
+ // A co-routine that blocks on a queue waiting for characters to be received.
+ static void vReceivingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ char cRxedChar;
+ portBASE_TYPE xResult;
+
+ // All co-routines must start with a call to crSTART().
+ crSTART( xHandle );
+
+ for( ;; )
+ {
+ // Wait for data to become available on the queue. This assumes the
+ // queue xCommsRxQueue has already been created!
+ crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+ // Was a character received?
+ if( xResult == pdPASS )
+ {
+ // Process the character here.
+ }
+ }
+
+ // All co-routines must end with a call to crEND().
+ crEND();
+ }
+
+ // An ISR that uses a queue to send characters received on a serial port to
+ // a co-routine.
+ void vUART_ISR( void )
+ {
+ char cRxedChar;
+ portBASE_TYPE xCRWokenByPost = pdFALSE;
+
+ // We loop around reading characters until there are none left in the UART.
+ while( UART_RX_REG_NOT_EMPTY() )
+ {
+ // Obtain the character from the UART.
+ cRxedChar = UART_RX_REG;
+
+ // Post the character onto a queue. xCRWokenByPost will be pdFALSE
+ // the first time around the loop. If the post causes a co-routine
+ // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
+ // In this manner we can ensure that if more than one co-routine is
+ // blocked on the queue only one is woken by this ISR no matter how
+ // many characters are posted to the queue.
+ xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
+ }
+ }
+ *
+ * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
+ * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
+ * functions used by tasks.
+ *
+ * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
+ * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
+ * xQueueReceiveFromISR() can only be used to pass data between a task and and
+ * ISR.
+ *
+ * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
+ * from a queue that is being used from within a co-routine (a co-routine
+ * posted to the queue).
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvBuffer A pointer to a buffer into which the received item will be
+ * placed. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from the queue into
+ * pvBuffer.
+ *
+ * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
+ * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
+ * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
+ * *pxCoRoutineWoken will remain unchanged.
+ *
+ * @return pdTRUE an item was successfully received from the queue, otherwise
+ * pdFALSE.
+ *
+ * Example usage:
+
+ // A co-routine that posts a character to a queue then blocks for a fixed
+ // period. The character is incremented each time.
+ static void vSendingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // cChar holds its value while this co-routine is blocked and must therefore
+ // be declared static.
+ static char cCharToTx = 'a';
+ portBASE_TYPE xResult;
+
+ // All co-routines must start with a call to crSTART().
+ crSTART( xHandle );
+
+ for( ;; )
+ {
+ // Send the next character to the queue.
+ crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
+
+ if( xResult == pdPASS )
+ {
+ // The character was successfully posted to the queue.
+ }
+ else
+ {
+ // Could not post the character to the queue.
+ }
+
+ // Enable the UART Tx interrupt to cause an interrupt in this
+ // hypothetical UART. The interrupt will obtain the character
+ // from the queue and send it.
+ ENABLE_RX_INTERRUPT();
+
+ // Increment to the next character then block for a fixed period.
+ // cCharToTx will maintain its value across the delay as it is
+ // declared static.
+ cCharToTx++;
+ if( cCharToTx > 'x' )
+ {
+ cCharToTx = 'a';
+ }
+ crDELAY( 100 );
+ }
+
+ // All co-routines must end with a call to crEND().
+ crEND();
+ }
+
+ // An ISR that uses a queue to receive characters to send on a UART.
+ void vUART_ISR( void )
+ {
+ char cCharToTx;
+ portBASE_TYPE xCRWokenByPost = pdFALSE;
+
+ while( UART_TX_REG_EMPTY() )
+ {
+ // Are there any characters in the queue waiting to be sent?
+ // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
+ // is woken by the post - ensuring that only a single co-routine is
+ // woken no matter how many times we go around this loop.
+ if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
+ {
+ SEND_CHARACTER( cCharToTx );
+ }
+ }
+ }
+ * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
+ * \ingroup Tasks
+ */
+#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
+
+/*
+ * This function is intended for internal use by the co-routine macros only.
+ * The macro nature of the co-routine implementation requires that the
+ * prototype appears here. The function should not be used by application
+ * writers.
+ *
+ * Removes the current co-routine from its ready list and places it in the
+ * appropriate delayed list.
+ */
+void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList );
+
+/*
+ * This function is intended for internal use by the queue implementation only.
+ * The function should not be used by application writers.
+ *
+ * Removes the highest priority co-routine from the event list and places it in
+ * the pending ready list.
+ */
+signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CO_ROUTINE_H */
diff --git a/source/freertos_blinky/freertos/inc/list.h b/source/freertos_blinky/freertos/inc/list.h
new file mode 100644
index 0000000..34e6809
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/list.h
@@ -0,0 +1,379 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/*
+ * This is the list implementation used by the scheduler. While it is tailored
+ * heavily for the schedulers needs, it is also available for use by
+ * application code.
+ *
+ * xLists can only store pointers to xListItems. Each xListItem contains a
+ * numeric value (xItemValue). Most of the time the lists are sorted in
+ * descending item value order.
+ *
+ * Lists are created already containing one list item. The value of this
+ * item is the maximum possible that can be stored, it is therefore always at
+ * the end of the list and acts as a marker. The list member pxHead always
+ * points to this marker - even though it is at the tail of the list. This
+ * is because the tail contains a wrap back pointer to the true head of
+ * the list.
+ *
+ * In addition to it's value, each list item contains a pointer to the next
+ * item in the list (pxNext), a pointer to the list it is in (pxContainer)
+ * and a pointer to back to the object that contains it. These later two
+ * pointers are included for efficiency of list manipulation. There is
+ * effectively a two way link between the object containing the list item and
+ * the list item itself.
+ *
+ *
+ * \page ListIntroduction List Implementation
+ * \ingroup FreeRTOSIntro
+ */
+
+
+#ifndef LIST_H
+#define LIST_H
+
+/*
+ * The list structure members are modified from within interrupts, and therefore
+ * by rights should be declared volatile. However, they are only modified in a
+ * functionally atomic way (within critical sections of with the scheduler
+ * suspended) and are either passed by reference into a function or indexed via
+ * a volatile variable. Therefore, in all use cases tested so far, the volatile
+ * qualifier can be omitted in order to provide a moderate performance
+ * improvement without adversely affecting functional behaviour. The assembly
+ * instructions generated by the IAR, ARM and GCC compilers when the respective
+ * compiler's options were set for maximum optimisation has been inspected and
+ * deemed to be as intended. That said, as compiler technology advances, and
+ * especially if aggressive cross module optimisation is used (a use case that
+ * has not been exercised to any great extend) then it is feasible that the
+ * volatile qualifier will be needed for correct optimisation. It is expected
+ * that a compiler removing essential code because, without the volatile
+ * qualifier on the list structure members and with aggressive cross module
+ * optimisation, the compiler deemed the code unnecessary will result in
+ * complete and obvious failure of the scheduler. If this is ever experienced
+ * then the volatile qualifier can be inserted in the relevant places within the
+ * list structures by simply defining configLIST_VOLATILE to volatile in
+ * FreeRTOSConfig.h (as per the example at the bottom of this comment block).
+ * If configLIST_VOLATILE is not defined then the preprocessor directives below
+ * will simply #define configLIST_VOLATILE away completely.
+ *
+ * To use volatile list structure members then add the following line to
+ * FreeRTOSConfig.h (without the quotes):
+ * "#define configLIST_VOLATILE volatile"
+ */
+#ifndef configLIST_VOLATILE
+ #define configLIST_VOLATILE
+#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Definition of the only type of object that a list can contain.
+ */
+struct xLIST_ITEM
+{
+ configLIST_VOLATILE portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
+ struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next xListItem in the list. */
+ struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;/*< Pointer to the previous xListItem in the list. */
+ void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
+ void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */
+};
+typedef struct xLIST_ITEM xListItem; /* For some reason lint wants this as two separate definitions. */
+
+struct xMINI_LIST_ITEM
+{
+ configLIST_VOLATILE portTickType xItemValue;
+ struct xLIST_ITEM * configLIST_VOLATILE pxNext;
+ struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
+};
+typedef struct xMINI_LIST_ITEM xMiniListItem;
+
+/*
+ * Definition of the type of queue used by the scheduler.
+ */
+typedef struct xLIST
+{
+ configLIST_VOLATILE unsigned portBASE_TYPE uxNumberOfItems;
+ xListItem * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */
+ xMiniListItem xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
+} xList;
+
+/*
+ * Access macro to set the owner of a list item. The owner of a list item
+ * is the object (usually a TCB) that contains the list item.
+ *
+ * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
+ * \ingroup LinkedList
+ */
+#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
+
+/*
+ * Access macro to get the owner of a list item. The owner of a list item
+ * is the object (usually a TCB) that contains the list item.
+ *
+ * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
+ * \ingroup LinkedList
+ */
+#define listGET_LIST_ITEM_OWNER( pxListItem ) ( pxListItem )->pvOwner
+
+/*
+ * Access macro to set the value of the list item. In most cases the value is
+ * used to sort the list in descending order.
+ *
+ * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
+ * \ingroup LinkedList
+ */
+#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
+
+/*
+ * Access macro to retrieve the value of the list item. The value can
+ * represent anything - for example a the priority of a task, or the time at
+ * which a task should be unblocked.
+ *
+ * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
+ * \ingroup LinkedList
+ */
+#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
+
+/*
+ * Access macro the retrieve the value of the list item at the head of a given
+ * list.
+ *
+ * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
+ * \ingroup LinkedList
+ */
+#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->xItemValue )
+
+/*
+ * Access macro to determine if a list contains any items. The macro will
+ * only have the value true if the list is empty.
+ *
+ * \page listLIST_IS_EMPTY listLIST_IS_EMPTY
+ * \ingroup LinkedList
+ */
+#define listLIST_IS_EMPTY( pxList ) ( ( portBASE_TYPE ) ( ( pxList )->uxNumberOfItems == ( unsigned portBASE_TYPE ) 0 ) )
+
+/*
+ * Access macro to return the number of items in the list.
+ */
+#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
+
+/*
+ * Access function to obtain the owner of the next entry in a list.
+ *
+ * The list member pxIndex is used to walk through a list. Calling
+ * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
+ * and returns that entries pxOwner parameter. Using multiple calls to this
+ * function it is therefore possible to move through every item contained in
+ * a list.
+ *
+ * The pxOwner parameter of a list item is a pointer to the object that owns
+ * the list item. In the scheduler this is normally a task control block.
+ * The pxOwner parameter effectively creates a two way link between the list
+ * item and its owner.
+ *
+ * @param pxList The list from which the next item owner is to be returned.
+ *
+ * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
+ * \ingroup LinkedList
+ */
+#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
+{ \
+xList * const pxConstList = ( pxList ); \
+ /* Increment the index to the next item and return the item, ensuring */ \
+ /* we don't return the marker used at the end of the list. */ \
+ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
+ if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
+ { \
+ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
+ } \
+ ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
+}
+
+
+/*
+ * Access function to obtain the owner of the first entry in a list. Lists
+ * are normally sorted in ascending item value order.
+ *
+ * This function returns the pxOwner member of the first item in the list.
+ * The pxOwner parameter of a list item is a pointer to the object that owns
+ * the list item. In the scheduler this is normally a task control block.
+ * The pxOwner parameter effectively creates a two way link between the list
+ * item and its owner.
+ *
+ * @param pxList The list from which the owner of the head item is to be
+ * returned.
+ *
+ * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
+ * \ingroup LinkedList
+ */
+#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )
+
+/*
+ * Check to see if a list item is within a list. The list item maintains a
+ * "container" pointer that points to the list it is in. All this macro does
+ * is check to see if the container and the list match.
+ *
+ * @param pxList The list we want to know if the list item is within.
+ * @param pxListItem The list item we want to know if is in the list.
+ * @return pdTRUE is the list item is in the list, otherwise pdFALSE.
+ * pointer against
+ */
+#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( portBASE_TYPE ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) )
+
+/*
+ * Return the list a list item is contained within (referenced from).
+ *
+ * @param pxListItem The list item being queried.
+ * @return A pointer to the xList object that references the pxListItem
+ */
+#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer )
+
+/*
+ * This provides a crude means of knowing if a list has been initialised, as
+ * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
+ * function.
+ */
+#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
+
+/*
+ * Must be called before a list is used! This initialises all the members
+ * of the list structure and inserts the xListEnd item into the list as a
+ * marker to the back of the list.
+ *
+ * @param pxList Pointer to the list being initialised.
+ *
+ * \page vListInitialise vListInitialise
+ * \ingroup LinkedList
+ */
+void vListInitialise( xList * const pxList );
+
+/*
+ * Must be called before a list item is used. This sets the list container to
+ * null so the item does not think that it is already contained in a list.
+ *
+ * @param pxItem Pointer to the list item being initialised.
+ *
+ * \page vListInitialiseItem vListInitialiseItem
+ * \ingroup LinkedList
+ */
+void vListInitialiseItem( xListItem * const pxItem );
+
+/*
+ * Insert a list item into a list. The item will be inserted into the list in
+ * a position determined by its item value (descending item value order).
+ *
+ * @param pxList The list into which the item is to be inserted.
+ *
+ * @param pxNewListItem The item to that is to be placed in the list.
+ *
+ * \page vListInsert vListInsert
+ * \ingroup LinkedList
+ */
+void vListInsert( xList * const pxList, xListItem * const pxNewListItem );
+
+/*
+ * Insert a list item into a list. The item will be inserted in a position
+ * such that it will be the last item within the list returned by multiple
+ * calls to listGET_OWNER_OF_NEXT_ENTRY.
+ *
+ * The list member pvIndex is used to walk through a list. Calling
+ * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list.
+ * Placing an item in a list using vListInsertEnd effectively places the item
+ * in the list position pointed to by pvIndex. This means that every other
+ * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
+ * the pvIndex parameter again points to the item being inserted.
+ *
+ * @param pxList The list into which the item is to be inserted.
+ *
+ * @param pxNewListItem The list item to be inserted into the list.
+ *
+ * \page vListInsertEnd vListInsertEnd
+ * \ingroup LinkedList
+ */
+void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem );
+
+/*
+ * Remove an item from a list. The list item has a pointer to the list that
+ * it is in, so only the list item need be passed into the function.
+ *
+ * @param uxListRemove The item to be removed. The item will remove itself from
+ * the list pointed to by it's pxContainer parameter.
+ *
+ * @return The number of items that remain in the list after the list item has
+ * been removed.
+ *
+ * \page uxListRemove uxListRemove
+ * \ingroup LinkedList
+ */
+unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/freertos_blinky/freertos/inc/mpu_wrappers.h b/source/freertos_blinky/freertos/inc/mpu_wrappers.h
new file mode 100644
index 0000000..149ca0a
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/mpu_wrappers.h
@@ -0,0 +1,153 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+#ifndef MPU_WRAPPERS_H
+#define MPU_WRAPPERS_H
+
+/* This file redefines API functions to be called through a wrapper macro, but
+only for ports that are using the MPU. */
+#ifdef portUSING_MPU_WRAPPERS
+
+ /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
+ included from queue.c or task.c to prevent it from having an effect within
+ those files. */
+ #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+ #define xTaskGenericCreate MPU_xTaskGenericCreate
+ #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions
+ #define vTaskDelete MPU_vTaskDelete
+ #define vTaskDelayUntil MPU_vTaskDelayUntil
+ #define vTaskDelay MPU_vTaskDelay
+ #define uxTaskPriorityGet MPU_uxTaskPriorityGet
+ #define vTaskPrioritySet MPU_vTaskPrioritySet
+ #define eTaskGetState MPU_eTaskGetState
+ #define vTaskSuspend MPU_vTaskSuspend
+ #define xTaskIsTaskSuspended MPU_xTaskIsTaskSuspended
+ #define vTaskResume MPU_vTaskResume
+ #define vTaskSuspendAll MPU_vTaskSuspendAll
+ #define xTaskResumeAll MPU_xTaskResumeAll
+ #define xTaskGetTickCount MPU_xTaskGetTickCount
+ #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks
+ #define vTaskList MPU_vTaskList
+ #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats
+ #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
+ #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
+ #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
+ #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
+ #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
+ #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
+ #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
+ #define uxTaskGetSystemState MPU_uxTaskGetSystemState
+
+ #define xQueueGenericCreate MPU_xQueueGenericCreate
+ #define xQueueCreateMutex MPU_xQueueCreateMutex
+ #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
+ #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
+ #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
+ #define xQueueGenericSend MPU_xQueueGenericSend
+ #define xQueueAltGenericSend MPU_xQueueAltGenericSend
+ #define xQueueAltGenericReceive MPU_xQueueAltGenericReceive
+ #define xQueueGenericReceive MPU_xQueueGenericReceive
+ #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
+ #define vQueueDelete MPU_vQueueDelete
+ #define xQueueGenericReset MPU_xQueueGenericReset
+ #define xQueueCreateSet MPU_xQueueCreateSet
+ #define xQueueSelectFromSet MPU_xQueueSelectFromSet
+ #define xQueueAddToSet MPU_xQueueAddToSet
+ #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
+ #define xQueuePeekFromISR MPU_xQueuePeekFromISR
+
+ #define pvPortMalloc MPU_pvPortMalloc
+ #define vPortFree MPU_vPortFree
+ #define xPortGetFreeHeapSize MPU_xPortGetFreeHeapSize
+ #define vPortInitialiseBlocks MPU_vPortInitialiseBlocks
+
+ #if configQUEUE_REGISTRY_SIZE > 0
+ #define vQueueAddToRegistry MPU_vQueueAddToRegistry
+ #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
+ #endif
+
+ /* Remove the privileged function macro. */
+ #define PRIVILEGED_FUNCTION
+
+ #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
+
+ /* Ensure API functions go in the privileged execution section. */
+ #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions")))
+ #define PRIVILEGED_DATA __attribute__((section("privileged_data")))
+
+ #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
+
+#else /* portUSING_MPU_WRAPPERS */
+
+ #define PRIVILEGED_FUNCTION
+ #define PRIVILEGED_DATA
+ #define portUSING_MPU_WRAPPERS 0
+
+#endif /* portUSING_MPU_WRAPPERS */
+
+
+#endif /* MPU_WRAPPERS_H */
+
diff --git a/source/freertos_blinky/freertos/inc/portable.h b/source/freertos_blinky/freertos/inc/portable.h
new file mode 100644
index 0000000..8df01d1
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/portable.h
@@ -0,0 +1,402 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/*-----------------------------------------------------------
+ * Portable layer API. Each function must be defined for each port.
+ *----------------------------------------------------------*/
+
+#ifndef PORTABLE_H
+#define PORTABLE_H
+
+/* Include the macro file relevant to the port being used. */
+
+#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
+ #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
+ typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
+ #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
+ typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef GCC_MEGA_AVR
+ #include "../portable/GCC/ATMega323/portmacro.h"
+#endif
+
+#ifdef IAR_MEGA_AVR
+ #include "../portable/IAR/ATMega323/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC24_PORT
+ #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h"
+#endif
+
+#ifdef MPLAB_DSPIC_PORT
+ #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC18F_PORT
+ #include "..\..\Source\portable\MPLAB\PIC18F\portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC32MX_PORT
+ #include "..\..\Source\portable\MPLAB\PIC32MX\portmacro.h"
+#endif
+
+#ifdef _FEDPICC
+ #include "libFreeRTOS/Include/portmacro.h"
+#endif
+
+#ifdef SDCC_CYGNAL
+ #include "../../Source/portable/SDCC/Cygnal/portmacro.h"
+#endif
+
+#ifdef GCC_ARM7
+ #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
+#endif
+
+#ifdef GCC_ARM7_ECLIPSE
+ #include "portmacro.h"
+#endif
+
+#ifdef ROWLEY_LPC23xx
+ #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
+#endif
+
+#ifdef IAR_MSP430
+ #include "..\..\Source\portable\IAR\MSP430\portmacro.h"
+#endif
+
+#ifdef GCC_MSP430
+ #include "../../Source/portable/GCC/MSP430F449/portmacro.h"
+#endif
+
+#ifdef ROWLEY_MSP430
+ #include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
+#endif
+
+#ifdef ARM7_LPC21xx_KEIL_RVDS
+ #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
+#endif
+
+#ifdef SAM7_GCC
+ #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
+#endif
+
+#ifdef SAM7_IAR
+ #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
+#endif
+
+#ifdef SAM9XE_IAR
+ #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
+#endif
+
+#ifdef LPC2000_IAR
+ #include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
+#endif
+
+#ifdef STR71X_IAR
+ #include "..\..\Source\portable\IAR\STR71x\portmacro.h"
+#endif
+
+#ifdef STR75X_IAR
+ #include "..\..\Source\portable\IAR\STR75x\portmacro.h"
+#endif
+
+#ifdef STR75X_GCC
+ #include "..\..\Source\portable\GCC\STR75x\portmacro.h"
+#endif
+
+#ifdef STR91X_IAR
+ #include "..\..\Source\portable\IAR\STR91x\portmacro.h"
+#endif
+
+#ifdef GCC_H8S
+ #include "../../Source/portable/GCC/H8S2329/portmacro.h"
+#endif
+
+#ifdef GCC_AT91FR40008
+ #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
+#endif
+
+#ifdef RVDS_ARMCM3_LM3S102
+ #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef GCC_ARMCM3_LM3S102
+ #include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef GCC_ARMCM3
+ #include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef IAR_ARM_CM3
+ #include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef IAR_ARMCM3_LM
+ #include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef HCS12_CODE_WARRIOR
+ #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
+#endif
+
+#ifdef MICROBLAZE_GCC
+ #include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
+#endif
+
+#ifdef TERN_EE
+ #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
+#endif
+
+#ifdef GCC_HCS12
+ #include "../../Source/portable/GCC/HCS12/portmacro.h"
+#endif
+
+#ifdef GCC_MCF5235
+ #include "../../Source/portable/GCC/MCF5235/portmacro.h"
+#endif
+
+#ifdef COLDFIRE_V2_GCC
+ #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
+#endif
+
+#ifdef COLDFIRE_V2_CODEWARRIOR
+ #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
+#endif
+
+#ifdef GCC_PPC405
+ #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
+#endif
+
+#ifdef GCC_PPC440
+ #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
+#endif
+
+#ifdef _16FX_SOFTUNE
+ #include "..\..\Source\portable\Softune\MB96340\portmacro.h"
+#endif
+
+#ifdef BCC_INDUSTRIAL_PC_PORT
+ /* A short file name has to be used in place of the normal
+ FreeRTOSConfig.h when using the Borland compiler. */
+ #include "frconfig.h"
+ #include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
+ typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef BCC_FLASH_LITE_186_PORT
+ /* A short file name has to be used in place of the normal
+ FreeRTOSConfig.h when using the Borland compiler. */
+ #include "frconfig.h"
+ #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
+ typedef void ( __interrupt __far *pxISR )();
+#endif
+
+#ifdef __GNUC__
+ #ifdef __AVR32_AVR32A__
+ #include "portmacro.h"
+ #endif
+#endif
+
+#ifdef __ICCAVR32__
+ #ifdef __CORE__
+ #if __CORE__ == __AVR32A__
+ #include "portmacro.h"
+ #endif
+ #endif
+#endif
+
+#ifdef __91467D
+ #include "portmacro.h"
+#endif
+
+#ifdef __96340
+ #include "portmacro.h"
+#endif
+
+
+#ifdef __IAR_V850ES_Fx3__
+ #include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx3__
+ #include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx3_L__
+ #include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx2__
+ #include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Hx2__
+ #include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_78K0R_Kx3__
+ #include "../../Source/portable/IAR/78K0R/portmacro.h"
+#endif
+
+#ifdef __IAR_78K0R_Kx3L__
+ #include "../../Source/portable/IAR/78K0R/portmacro.h"
+#endif
+
+/* Catch all to ensure portmacro.h is included in the build. Newer demos
+have the path as part of the project options, rather than as relative from
+the project location. If portENTER_CRITICAL() has not been defined then
+portmacro.h has not yet been included - as every portmacro.h provides a
+portENTER_CRITICAL() definition. Check the demo application for your demo
+to find the path to the correct portmacro.h file. */
+#ifndef portENTER_CRITICAL
+ #include "portmacro.h"
+#endif
+
+#if portBYTE_ALIGNMENT == 8
+ #define portBYTE_ALIGNMENT_MASK ( 0x0007 )
+#endif
+
+#if portBYTE_ALIGNMENT == 4
+ #define portBYTE_ALIGNMENT_MASK ( 0x0003 )
+#endif
+
+#if portBYTE_ALIGNMENT == 2
+ #define portBYTE_ALIGNMENT_MASK ( 0x0001 )
+#endif
+
+#if portBYTE_ALIGNMENT == 1
+ #define portBYTE_ALIGNMENT_MASK ( 0x0000 )
+#endif
+
+#ifndef portBYTE_ALIGNMENT_MASK
+ #error "Invalid portBYTE_ALIGNMENT definition"
+#endif
+
+#ifndef portNUM_CONFIGURABLE_REGIONS
+ #define portNUM_CONFIGURABLE_REGIONS 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mpu_wrappers.h"
+
+/*
+ * Setup the stack of a new task so it is ready to be placed under the
+ * scheduler control. The registers have to be placed on the stack in
+ * the order that the port expects to find them.
+ *
+ */
+#if( portUSING_MPU_WRAPPERS == 1 )
+ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters, portBASE_TYPE xRunPrivileged ) PRIVILEGED_FUNCTION;
+#else
+ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * Map to the memory management routines required for the port.
+ */
+void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
+void vPortFree( void *pv ) PRIVILEGED_FUNCTION;
+void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
+size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Setup the hardware ready for the scheduler to take control. This generally
+ * sets up a tick interrupt and sets timers for the correct tick frequency.
+ */
+portBASE_TYPE xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
+ * the hardware is left in its original condition after the scheduler stops
+ * executing.
+ */
+void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * The structures and methods of manipulating the MPU are contained within the
+ * port layer.
+ *
+ * Fills the xMPUSettings structure with the memory region information
+ * contained in xRegions.
+ */
+#if( portUSING_MPU_WRAPPERS == 1 )
+ struct xMEMORY_REGION;
+ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, portSTACK_TYPE *pxBottomOfStack, unsigned short usStackDepth ) PRIVILEGED_FUNCTION;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTABLE_H */
+
diff --git a/source/freertos_blinky/freertos/inc/portmacro.h b/source/freertos_blinky/freertos/inc/portmacro.h
new file mode 100644
index 0000000..5e4fc64
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/portmacro.h
@@ -0,0 +1,145 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-----------------------------------------------------------
+ * Port specific definitions.
+ *
+ * The settings in this file configure FreeRTOS correctly for the
+ * given hardware and compiler.
+ *
+ * These settings should not be altered.
+ *-----------------------------------------------------------
+ */
+
+/* Type definitions. */
+#define portCHAR char
+#define portFLOAT float
+#define portDOUBLE double
+#define portLONG long
+#define portSHORT short
+#define portSTACK_TYPE unsigned portLONG
+#define portBASE_TYPE long
+
+#if( configUSE_16_BIT_TICKS == 1 )
+ typedef unsigned portSHORT portTickType;
+ #define portMAX_DELAY ( portTickType ) 0xffff
+#else
+ typedef unsigned portLONG portTickType;
+ #define portMAX_DELAY ( portTickType ) 0xffffffff
+#endif
+/*-----------------------------------------------------------*/
+
+/* Architecture specifics. */
+#define portSTACK_GROWTH ( -1 )
+#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )
+#define portBYTE_ALIGNMENT 8
+/*-----------------------------------------------------------*/
+
+
+/* Scheduler utilities. */
+extern void vPortYield( void );
+#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )
+#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
+#define portYIELD() vPortYield()
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
+#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
+/*-----------------------------------------------------------*/
+
+
+/* Critical section management. */
+extern void vPortEnterCritical( void );
+extern void vPortExitCritical( void );
+extern unsigned long ulSetInterruptMaskFromISR( void ) __attribute__((naked));
+extern void vClearInterruptMaskFromISR( unsigned long ulMask ) __attribute__((naked));
+
+#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMaskFromISR( x )
+#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " )
+#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " )
+#define portENTER_CRITICAL() vPortEnterCritical()
+#define portEXIT_CRITICAL() vPortExitCritical()
+
+/*-----------------------------------------------------------*/
+
+/* Task function macros as described on the FreeRTOS.org WEB site. */
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
+
+#define portNOP()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTMACRO_H */
+
diff --git a/source/freertos_blinky/freertos/inc/projdefs.h b/source/freertos_blinky/freertos/inc/projdefs.h
new file mode 100644
index 0000000..86ca641
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/projdefs.h
@@ -0,0 +1,89 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+#ifndef PROJDEFS_H
+#define PROJDEFS_H
+
+/* Defines the prototype to which task functions must conform. */
+typedef void (*pdTASK_CODE)( void * );
+
+#define pdFALSE ( ( portBASE_TYPE ) 0 )
+#define pdTRUE ( ( portBASE_TYPE ) 1 )
+
+#define pdPASS ( pdTRUE )
+#define pdFAIL ( pdFALSE )
+#define errQUEUE_EMPTY ( ( portBASE_TYPE ) 0 )
+#define errQUEUE_FULL ( ( portBASE_TYPE ) 0 )
+
+/* Error definitions. */
+#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 )
+#define errNO_TASK_TO_RUN ( -2 )
+#define errQUEUE_BLOCKED ( -4 )
+#define errQUEUE_YIELD ( -5 )
+
+#endif /* PROJDEFS_H */
+
+
+
diff --git a/source/freertos_blinky/freertos/inc/queue.h b/source/freertos_blinky/freertos/inc/queue.h
new file mode 100644
index 0000000..6618330
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/queue.h
@@ -0,0 +1,1685 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h" must appear in source files before "include queue.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Type by which queues are referenced. For example, a call to xQueueCreate()
+ * returns an xQueueHandle variable that can then be used as a parameter to
+ * xQueueSend(), xQueueReceive(), etc.
+ */
+typedef void * xQueueHandle;
+
+/**
+ * Type by which queue sets are referenced. For example, a call to
+ * xQueueCreateSet() returns an xQueueSet variable that can then be used as a
+ * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc.
+ */
+typedef void * xQueueSetHandle;
+
+/**
+ * Queue sets can contain both queues and semaphores, so the
+ * xQueueSetMemberHandle is defined as a type to be used where a parameter or
+ * return value can be either an xQueueHandle or an xSemaphoreHandle.
+ */
+typedef void * xQueueSetMemberHandle;
+
+/* For internal use only. */
+#define queueSEND_TO_BACK ( ( portBASE_TYPE ) 0 )
+#define queueSEND_TO_FRONT ( ( portBASE_TYPE ) 1 )
+#define queueOVERWRITE ( ( portBASE_TYPE ) 2 )
+
+/* For internal use only. These definitions *must* match those in queue.c. */
+#define queueQUEUE_TYPE_BASE ( ( unsigned char ) 0U )
+#define queueQUEUE_TYPE_SET ( ( unsigned char ) 0U )
+#define queueQUEUE_TYPE_MUTEX ( ( unsigned char ) 1U )
+#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( unsigned char ) 2U )
+#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( unsigned char ) 3U )
+#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( unsigned char ) 4U )
+
+/**
+ * queue. h
+ *
+ *
+ * Creates a new queue instance. This allocates the storage required by the
+ * new queue and returns a handle for the queue.
+ *
+ * @param uxQueueLength The maximum number of items that the queue can contain.
+ *
+ * @param uxItemSize The number of bytes each item in the queue will require.
+ * Items are queued by copy, not by reference, so this is the number of bytes
+ * that will be copied for each posted item. Each item on the queue must be
+ * the same size.
+ *
+ * @return If the queue is successfully create then a handle to the newly
+ * created queue is returned. If the queue cannot be created then 0 is
+ * returned.
+ *
+ * Example usage:
+
+ struct AMessage
+ {
+ char ucMessageID;
+ char ucData[ 20 ];
+ };
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+
+ // Create a queue capable of containing 10 unsigned long values.
+ xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+ if( xQueue1 == 0 )
+ {
+ // Queue was not created and must not be used.
+ }
+
+ // Create a queue capable of containing 10 pointers to AMessage structures.
+ // These should be passed by pointer as they contain a lot of data.
+ xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ if( xQueue2 == 0 )
+ {
+ // Queue was not created and must not be used.
+ }
+
+ // ... Rest of task code.
+ }
+
+ *
+ * This is a macro that calls xQueueGenericSend().
+ *
+ * Post an item to the front of a queue. The item is queued by copy, not by
+ * reference. This function must not be called from an interrupt service
+ * routine. See xQueueSendFromISR () for an alternative which may be used
+ * in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full. The call will return immediately if this is set to 0 and the
+ * queue is full. The time is defined in tick periods so the constant
+ * portTICK_RATE_MS should be used to convert to real time if this is required.
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+
+ struct AMessage
+ {
+ char ucMessageID;
+ char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+ // Create a queue capable of containing 10 unsigned long values.
+ xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+ // Create a queue capable of containing 10 pointers to AMessage structures.
+ // These should be passed by pointer as they contain a lot of data.
+ xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+ // ...
+
+ if( xQueue1 != 0 )
+ {
+ // Send an unsigned long. Wait for 10 ticks for space to become
+ // available if necessary.
+ if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+ {
+ // Failed to post the message, even after 10 ticks.
+ }
+ }
+
+ if( xQueue2 != 0 )
+ {
+ // Send a pointer to a struct AMessage object. Don't block if the
+ // queue is already full.
+ pxMessage = & xMessage;
+ xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+ }
+
+ // ... Rest of task code.
+ }
+
+ *
+ * This is a macro that calls xQueueGenericSend().
+ *
+ * Post an item to the back of a queue. The item is queued by copy, not by
+ * reference. This function must not be called from an interrupt service
+ * routine. See xQueueSendFromISR () for an alternative which may be used
+ * in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full. The call will return immediately if this is set to 0 and the queue
+ * is full. The time is defined in tick periods so the constant
+ * portTICK_RATE_MS should be used to convert to real time if this is required.
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+
+ struct AMessage
+ {
+ char ucMessageID;
+ char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+ // Create a queue capable of containing 10 unsigned long values.
+ xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+ // Create a queue capable of containing 10 pointers to AMessage structures.
+ // These should be passed by pointer as they contain a lot of data.
+ xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+ // ...
+
+ if( xQueue1 != 0 )
+ {
+ // Send an unsigned long. Wait for 10 ticks for space to become
+ // available if necessary.
+ if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+ {
+ // Failed to post the message, even after 10 ticks.
+ }
+ }
+
+ if( xQueue2 != 0 )
+ {
+ // Send a pointer to a struct AMessage object. Don't block if the
+ // queue is already full.
+ pxMessage = & xMessage;
+ xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+ }
+
+ // ... Rest of task code.
+ }
+
+ *
+ * This is a macro that calls xQueueGenericSend(). It is included for
+ * backward compatibility with versions of FreeRTOS.org that did not
+ * include the xQueueSendToFront() and xQueueSendToBack() macros. It is
+ * equivalent to xQueueSendToBack().
+ *
+ * Post an item on a queue. The item is queued by copy, not by reference.
+ * This function must not be called from an interrupt service routine.
+ * See xQueueSendFromISR () for an alternative which may be used in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full. The call will return immediately if this is set to 0 and the
+ * queue is full. The time is defined in tick periods so the constant
+ * portTICK_RATE_MS should be used to convert to real time if this is required.
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+
+ struct AMessage
+ {
+ char ucMessageID;
+ char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+ // Create a queue capable of containing 10 unsigned long values.
+ xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+ // Create a queue capable of containing 10 pointers to AMessage structures.
+ // These should be passed by pointer as they contain a lot of data.
+ xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+ // ...
+
+ if( xQueue1 != 0 )
+ {
+ // Send an unsigned long. Wait for 10 ticks for space to become
+ // available if necessary.
+ if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+ {
+ // Failed to post the message, even after 10 ticks.
+ }
+ }
+
+ if( xQueue2 != 0 )
+ {
+ // Send a pointer to a struct AMessage object. Don't block if the
+ // queue is already full.
+ pxMessage = & xMessage;
+ xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+ }
+
+ // ... Rest of task code.
+ }
+
+ *
+ * Only for use with queues that have a length of one - so the queue is either
+ * empty or full.
+ *
+ * Post an item on a queue. If the queue is already full then overwrite the
+ * value held in the queue. The item is queued by copy, not by reference.
+ *
+ * This function must not be called from an interrupt service routine.
+ * See xQueueOverwriteFromISR () for an alternative which may be used in an ISR.
+ *
+ * @param xQueue The handle of the queue to which the data is being sent.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @return xQueueOverwrite() is a macro that calls xQueueGenericSend(), and
+ * therefore has the same return values as xQueueSendToFront(). However, pdPASS
+ * is the only value that can be returned because xQueueOverwrite() will write
+ * to the queue even when the queue is already full.
+ *
+ * Example usage:
+
+
+ void vFunction( void *pvParameters )
+ {
+ xQueueHandle xQueue;
+ unsigned long ulVarToSend, ulValReceived;
+
+ // Create a queue to hold one unsigned long value. It is strongly
+ // recommended *not* to use xQueueOverwrite() on queues that can
+ // contain more than one value, and doing so will trigger an assertion
+ // if configASSERT() is defined.
+ xQueue = xQueueCreate( 1, sizeof( unsigned long ) );
+
+ // Write the value 10 to the queue using xQueueOverwrite().
+ ulVarToSend = 10;
+ xQueueOverwrite( xQueue, &ulVarToSend );
+
+ // Peeking the queue should now return 10, but leave the value 10 in
+ // the queue. A block time of zero is used as it is known that the
+ // queue holds a value.
+ ulValReceived = 0;
+ xQueuePeek( xQueue, &ulValReceived, 0 );
+
+ if( ulValReceived != 10 )
+ {
+ // Error unless the item was removed by a different task.
+ }
+
+ // The queue is still full. Use xQueueOverwrite() to overwrite the
+ // value held in the queue with 100.
+ ulVarToSend = 100;
+ xQueueOverwrite( xQueue, &ulVarToSend );
+
+ // This time read from the queue, leaving the queue empty once more.
+ // A block time of 0 is used again.
+ xQueueReceive( xQueue, &ulValReceived, 0 );
+
+ // The value read should be the last value written, even though the
+ // queue was already full when the value was written.
+ if( ulValReceived != 100 )
+ {
+ // Error!
+ }
+
+ // ...
+}
+
+ *
+ * It is preferred that the macros xQueueSend(), xQueueSendToFront() and
+ * xQueueSendToBack() are used in place of calling this function directly.
+ *
+ * Post an item on a queue. The item is queued by copy, not by reference.
+ * This function must not be called from an interrupt service routine.
+ * See xQueueSendFromISR () for an alternative which may be used in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full. The call will return immediately if this is set to 0 and the
+ * queue is full. The time is defined in tick periods so the constant
+ * portTICK_RATE_MS should be used to convert to real time if this is required.
+ *
+ * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the
+ * item at the back of the queue, or queueSEND_TO_FRONT to place the item
+ * at the front of the queue (for high priority messages).
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+
+ struct AMessage
+ {
+ char ucMessageID;
+ char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+ // Create a queue capable of containing 10 unsigned long values.
+ xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+ // Create a queue capable of containing 10 pointers to AMessage structures.
+ // These should be passed by pointer as they contain a lot of data.
+ xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+ // ...
+
+ if( xQueue1 != 0 )
+ {
+ // Send an unsigned long. Wait for 10 ticks for space to become
+ // available if necessary.
+ if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10, queueSEND_TO_BACK ) != pdPASS )
+ {
+ // Failed to post the message, even after 10 ticks.
+ }
+ }
+
+ if( xQueue2 != 0 )
+ {
+ // Send a pointer to a struct AMessage object. Don't block if the
+ // queue is already full.
+ pxMessage = & xMessage;
+ xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0, queueSEND_TO_BACK );
+ }
+
+ // ... Rest of task code.
+ }
+
+ *
+ * This is a macro that calls the xQueueGenericReceive() function.
+ *
+ * Receive an item from a queue without removing the item from the queue.
+ * The item is received by copy so a buffer of adequate size must be
+ * provided. The number of bytes copied into the buffer was defined when
+ * the queue was created.
+ *
+ * Successfully received items remain on the queue so will be returned again
+ * by the next call, or a call to xQueueReceive().
+ *
+ * This macro must not be used in an interrupt service routine. See
+ * xQueuePeekFromISR() for an alternative that can be called from an interrupt
+ * service routine.
+ *
+ * @param xQueue The handle to the queue from which the item is to be
+ * received.
+ *
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for an item to receive should the queue be empty at the time
+ * of the call. The time is defined in tick periods so the constant
+ * portTICK_RATE_MS should be used to convert to real time if this is required.
+ * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue
+ * is empty.
+ *
+ * @return pdTRUE if an item was successfully received from the queue,
+ * otherwise pdFALSE.
+ *
+ * Example usage:
+
+ struct AMessage
+ {
+ char ucMessageID;
+ char ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+ // Create a queue capable of containing 10 pointers to AMessage structures.
+ // These should be passed by pointer as they contain a lot of data.
+ xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ if( xQueue == 0 )
+ {
+ // Failed to create the queue.
+ }
+
+ // ...
+
+ // Send a pointer to a struct AMessage object. Don't block if the
+ // queue is already full.
+ pxMessage = & xMessage;
+ xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+ // ... Rest of task code.
+ }
+
+ // Task to peek the data from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+ if( xQueue != 0 )
+ {
+ // Peek a message on the created queue. Block for 10 ticks if a
+ // message is not immediately available.
+ if( xQueuePeek( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+ {
+ // pcRxedMessage now points to the struct AMessage variable posted
+ // by vATask, but the item still remains on the queue.
+ }
+ }
+
+ // ... Rest of task code.
+ }
+
+ *
+ * A version of xQueuePeek() that can be called from an interrupt service
+ * routine (ISR).
+ *
+ * Receive an item from a queue without removing the item from the queue.
+ * The item is received by copy so a buffer of adequate size must be
+ * provided. The number of bytes copied into the buffer was defined when
+ * the queue was created.
+ *
+ * Successfully received items remain on the queue so will be returned again
+ * by the next call, or a call to xQueueReceive().
+ *
+ * @param xQueue The handle to the queue from which the item is to be
+ * received.
+ *
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
+ *
+ * @return pdTRUE if an item was successfully received from the queue,
+ * otherwise pdFALSE.
+ *
+ * \defgroup xQueuePeekFromISR xQueuePeekFromISR
+ * \ingroup QueueManagement
+ */
+signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const pvBuffer ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ *
+ *
+ * This is a macro that calls the xQueueGenericReceive() function.
+ *
+ * Receive an item from a queue. The item is received by copy so a buffer of
+ * adequate size must be provided. The number of bytes copied into the buffer
+ * was defined when the queue was created.
+ *
+ * Successfully received items are removed from the queue.
+ *
+ * This function must not be used in an interrupt service routine. See
+ * xQueueReceiveFromISR for an alternative that can.
+ *
+ * @param xQueue The handle to the queue from which the item is to be
+ * received.
+ *
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for an item to receive should the queue be empty at the time
+ * of the call. xQueueReceive() will return immediately if xTicksToWait
+ * is zero and the queue is empty. The time is defined in tick periods so the
+ * constant portTICK_RATE_MS should be used to convert to real time if this is
+ * required.
+ *
+ * @return pdTRUE if an item was successfully received from the queue,
+ * otherwise pdFALSE.
+ *
+ * Example usage:
+
+ struct AMessage
+ {
+ char ucMessageID;
+ char ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+ // Create a queue capable of containing 10 pointers to AMessage structures.
+ // These should be passed by pointer as they contain a lot of data.
+ xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ if( xQueue == 0 )
+ {
+ // Failed to create the queue.
+ }
+
+ // ...
+
+ // Send a pointer to a struct AMessage object. Don't block if the
+ // queue is already full.
+ pxMessage = & xMessage;
+ xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+ // ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+ if( xQueue != 0 )
+ {
+ // Receive a message on the created queue. Block for 10 ticks if a
+ // message is not immediately available.
+ if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+ {
+ // pcRxedMessage now points to the struct AMessage variable posted
+ // by vATask.
+ }
+ }
+
+ // ... Rest of task code.
+ }
+
+ *
+ * It is preferred that the macro xQueueReceive() be used rather than calling
+ * this function directly.
+ *
+ * Receive an item from a queue. The item is received by copy so a buffer of
+ * adequate size must be provided. The number of bytes copied into the buffer
+ * was defined when the queue was created.
+ *
+ * This function must not be used in an interrupt service routine. See
+ * xQueueReceiveFromISR for an alternative that can.
+ *
+ * @param xQueue The handle to the queue from which the item is to be
+ * received.
+ *
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for an item to receive should the queue be empty at the time
+ * of the call. The time is defined in tick periods so the constant
+ * portTICK_RATE_MS should be used to convert to real time if this is required.
+ * xQueueGenericReceive() will return immediately if the queue is empty and
+ * xTicksToWait is 0.
+ *
+ * @param xJustPeek When set to true, the item received from the queue is not
+ * actually removed from the queue - meaning a subsequent call to
+ * xQueueReceive() will return the same item. When set to false, the item
+ * being received from the queue is also removed from the queue.
+ *
+ * @return pdTRUE if an item was successfully received from the queue,
+ * otherwise pdFALSE.
+ *
+ * Example usage:
+
+ struct AMessage
+ {
+ char ucMessageID;
+ char ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+ // Create a queue capable of containing 10 pointers to AMessage structures.
+ // These should be passed by pointer as they contain a lot of data.
+ xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ if( xQueue == 0 )
+ {
+ // Failed to create the queue.
+ }
+
+ // ...
+
+ // Send a pointer to a struct AMessage object. Don't block if the
+ // queue is already full.
+ pxMessage = & xMessage;
+ xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+ // ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+ if( xQueue != 0 )
+ {
+ // Receive a message on the created queue. Block for 10 ticks if a
+ // message is not immediately available.
+ if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+ {
+ // pcRxedMessage now points to the struct AMessage variable posted
+ // by vATask.
+ }
+ }
+
+ // ... Rest of task code.
+ }
+
+ *
+ * Return the number of messages stored in a queue.
+ *
+ * @param xQueue A handle to the queue being queried.
+ *
+ * @return The number of messages available in the queue.
+ *
+ * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting
+ * \ingroup QueueManagement
+ */
+unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ *
+ *
+ * Return the number of free spaces available in a queue. This is equal to the
+ * number of items that can be sent to the queue before the queue becomes full
+ * if no items are removed.
+ *
+ * @param xQueue A handle to the queue being queried.
+ *
+ * @return The number of spaces available in the queue.
+ *
+ * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting
+ * \ingroup QueueManagement
+ */
+unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ *
void vQueueDelete( xQueueHandle xQueue );
+ *
+ * Delete a queue - freeing all the memory allocated for storing of items
+ * placed on the queue.
+ *
+ * @param xQueue A handle to the queue to be deleted.
+ *
+ * \defgroup vQueueDelete vQueueDelete
+ * \ingroup QueueManagement
+ */
+void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ *
+ *
+ * This is a macro that calls xQueueGenericSendFromISR().
+ *
+ * Post an item to the front of a queue. It is safe to use this macro from
+ * within an interrupt service routine.
+ *
+ * Items are queued by copy not reference so it is preferable to only
+ * queue small items, especially when called from an ISR. In most cases
+ * it would be preferable to store a pointer to the item being queued.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the data was successfully sent to the queue, otherwise
+ * errQUEUE_FULL.
+ *
+ * Example usage for buffered IO (where the ISR can obtain more than one value
+ * per call):
+
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPrioritTaskWoken;
+
+ // We have not woken a task at the start of the ISR.
+ xHigherPriorityTaskWoken = pdFALSE;
+
+ // Loop until the buffer is empty.
+ do
+ {
+ // Obtain a byte from the buffer.
+ cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+ // Post the byte.
+ xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+ } while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+ // Now the buffer is empty we can switch context if necessary.
+ if( xHigherPriorityTaskWoken )
+ {
+ taskYIELD ();
+ }
+ }
+
+ *
+ * This is a macro that calls xQueueGenericSendFromISR().
+ *
+ * Post an item to the back of a queue. It is safe to use this macro from
+ * within an interrupt service routine.
+ *
+ * Items are queued by copy not reference so it is preferable to only
+ * queue small items, especially when called from an ISR. In most cases
+ * it would be preferable to store a pointer to the item being queued.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the data was successfully sent to the queue, otherwise
+ * errQUEUE_FULL.
+ *
+ * Example usage for buffered IO (where the ISR can obtain more than one value
+ * per call):
+
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPriorityTaskWoken;
+
+ // We have not woken a task at the start of the ISR.
+ xHigherPriorityTaskWoken = pdFALSE;
+
+ // Loop until the buffer is empty.
+ do
+ {
+ // Obtain a byte from the buffer.
+ cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+ // Post the byte.
+ xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+ } while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+ // Now the buffer is empty we can switch context if necessary.
+ if( xHigherPriorityTaskWoken )
+ {
+ taskYIELD ();
+ }
+ }
+
+ *
+ * A version of xQueueOverwrite() that can be used in an interrupt service
+ * routine (ISR).
+ *
+ * Only for use with queues that can hold a single item - so the queue is either
+ * empty or full.
+ *
+ * Post an item on a queue. If the queue is already full then overwrite the
+ * value held in the queue. The item is queued by copy, not by reference.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xQueueOverwriteFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return xQueueOverwriteFromISR() is a macro that calls
+ * xQueueGenericSendFromISR(), and therefore has the same return values as
+ * xQueueSendToFrontFromISR(). However, pdPASS is the only value that can be
+ * returned because xQueueOverwriteFromISR() will write to the queue even when
+ * the queue is already full.
+ *
+ * Example usage:
+
+
+ xQueueHandle xQueue;
+
+ void vFunction( void *pvParameters )
+ {
+ // Create a queue to hold one unsigned long value. It is strongly
+ // recommended *not* to use xQueueOverwriteFromISR() on queues that can
+ // contain more than one value, and doing so will trigger an assertion
+ // if configASSERT() is defined.
+ xQueue = xQueueCreate( 1, sizeof( unsigned long ) );
+}
+
+void vAnInterruptHandler( void )
+{
+// xHigherPriorityTaskWoken must be set to pdFALSE before it is used.
+portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
+unsigned long ulVarToSend, ulValReceived;
+
+ // Write the value 10 to the queue using xQueueOverwriteFromISR().
+ ulVarToSend = 10;
+ xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+ // The queue is full, but calling xQueueOverwriteFromISR() again will still
+ // pass because the value held in the queue will be overwritten with the
+ // new value.
+ ulVarToSend = 100;
+ xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+ // Reading from the queue will now return 100.
+
+ // ...
+
+ if( xHigherPrioritytaskWoken == pdTRUE )
+ {
+ // Writing to the queue caused a task to unblock and the unblocked task
+ // has a priority higher than or equal to the priority of the currently
+ // executing task (the task this interrupt interrupted). Perform a context
+ // switch so this interrupt returns directly to the unblocked task.
+ portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port.
+ }
+}
+
+ *
+ * This is a macro that calls xQueueGenericSendFromISR(). It is included
+ * for backward compatibility with versions of FreeRTOS.org that did not
+ * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR()
+ * macros.
+ *
+ * Post an item to the back of a queue. It is safe to use this function from
+ * within an interrupt service routine.
+ *
+ * Items are queued by copy not reference so it is preferable to only
+ * queue small items, especially when called from an ISR. In most cases
+ * it would be preferable to store a pointer to the item being queued.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xQueueSendFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the data was successfully sent to the queue, otherwise
+ * errQUEUE_FULL.
+ *
+ * Example usage for buffered IO (where the ISR can obtain more than one value
+ * per call):
+
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPriorityTaskWoken;
+
+ // We have not woken a task at the start of the ISR.
+ xHigherPriorityTaskWoken = pdFALSE;
+
+ // Loop until the buffer is empty.
+ do
+ {
+ // Obtain a byte from the buffer.
+ cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+ // Post the byte.
+ xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+ } while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+ // Now the buffer is empty we can switch context if necessary.
+ if( xHigherPriorityTaskWoken )
+ {
+ // Actual macro used here is port specific.
+ taskYIELD_FROM_ISR ();
+ }
+ }
+
+ *
+ * It is preferred that the macros xQueueSendFromISR(),
+ * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place
+ * of calling this function directly.
+ *
+ * Post an item on a queue. It is safe to use this function from within an
+ * interrupt service routine.
+ *
+ * Items are queued by copy not reference so it is preferable to only
+ * queue small items, especially when called from an ISR. In most cases
+ * it would be preferable to store a pointer to the item being queued.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the
+ * item at the back of the queue, or queueSEND_TO_FRONT to place the item
+ * at the front of the queue (for high priority messages).
+ *
+ * @return pdTRUE if the data was successfully sent to the queue, otherwise
+ * errQUEUE_FULL.
+ *
+ * Example usage for buffered IO (where the ISR can obtain more than one value
+ * per call):
+
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPriorityTaskWokenByPost;
+
+ // We have not woken a task at the start of the ISR.
+ xHigherPriorityTaskWokenByPost = pdFALSE;
+
+ // Loop until the buffer is empty.
+ do
+ {
+ // Obtain a byte from the buffer.
+ cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+ // Post each byte.
+ xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
+
+ } while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+ // Now the buffer is empty we can switch context if necessary. Note that the
+ // name of the yield function required is port specific.
+ if( xHigherPriorityTaskWokenByPost )
+ {
+ taskYIELD_YIELD_FROM_ISR();
+ }
+ }
+
+ *
+ * Receive an item from a queue. It is safe to use this function from within an
+ * interrupt service routine.
+ *
+ * @param xQueue The handle to the queue from which the item is to be
+ * received.
+ *
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
+ *
+ * @param pxTaskWoken A task may be blocked waiting for space to become
+ * available on the queue. If xQueueReceiveFromISR causes such a task to
+ * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will
+ * remain unchanged.
+ *
+ * @return pdTRUE if an item was successfully received from the queue,
+ * otherwise pdFALSE.
+ *
+ * Example usage:
+
+
+ xQueueHandle xQueue;
+
+ // Function to create a queue and post some values.
+ void vAFunction( void *pvParameters )
+ {
+ char cValueToPost;
+ const portTickType xBlockTime = ( portTickType )0xff;
+
+ // Create a queue capable of containing 10 characters.
+ xQueue = xQueueCreate( 10, sizeof( char ) );
+ if( xQueue == 0 )
+ {
+ // Failed to create the queue.
+ }
+
+ // ...
+
+ // Post some characters that will be used within an ISR. If the queue
+ // is full then this task will block for xBlockTime ticks.
+ cValueToPost = 'a';
+ xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+ cValueToPost = 'b';
+ xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+
+ // ... keep posting characters ... this task may block when the queue
+ // becomes full.
+
+ cValueToPost = 'c';
+ xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+ }
+
+ // ISR that outputs all the characters received on the queue.
+ void vISR_Routine( void )
+ {
+ portBASE_TYPE xTaskWokenByReceive = pdFALSE;
+ char cRxedChar;
+
+ while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+ {
+ // A character was received. Output the character now.
+ vOutputCharacter( cRxedChar );
+
+ // If removing the character from the queue woke the task that was
+ // posting onto the queue cTaskWokenByReceive will have been set to
+ // pdTRUE. No matter how many times this loop iterates only one
+ // task will be woken.
+ }
+
+ if( cTaskWokenByPost != ( char ) pdFALSE;
+ {
+ taskYIELD ();
+ }
+ }
+
+ * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR
+ * \ingroup QueueManagement
+ */
+signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, const void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+
+/*
+ * Utilities to query queues that are safe to use from an ISR. These utilities
+ * should be used only from witin an ISR, or within a critical section.
+ */
+signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+
+
+/*
+ * xQueueAltGenericSend() is an alternative version of xQueueGenericSend().
+ * Likewise xQueueAltGenericReceive() is an alternative version of
+ * xQueueGenericReceive().
+ *
+ * The source code that implements the alternative (Alt) API is much
+ * simpler because it executes everything from within a critical section.
+ * This is the approach taken by many other RTOSes, but FreeRTOS.org has the
+ * preferred fully featured API too. The fully featured API has more
+ * complex code that takes longer to execute, but makes much less use of
+ * critical sections. Therefore the alternative API sacrifices interrupt
+ * responsiveness to gain execution speed, whereas the fully featured API
+ * sacrifices execution speed to ensure better interrupt responsiveness.
+ */
+signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
+signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
+#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
+#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
+#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE )
+#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE )
+
+/*
+ * The functions defined above are for passing data to and from tasks. The
+ * functions below are the equivalents for passing data to and from
+ * co-routines.
+ *
+ * These functions are called from the co-routine macro implementation and
+ * should not be called directly from application code. Instead use the macro
+ * wrappers defined within croutine.h.
+ */
+signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );
+signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );
+signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait );
+signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait );
+
+/*
+ * For internal use only. Use xSemaphoreCreateMutex(),
+ * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling
+ * these functions directly.
+ */
+xQueueHandle xQueueCreateMutex( unsigned char ucQueueType ) PRIVILEGED_FUNCTION;
+xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;
+void* xQueueGetMutexHolder( xQueueHandle xSemaphore ) PRIVILEGED_FUNCTION;
+
+/*
+ * For internal use only. Use xSemaphoreTakeMutexRecursive() or
+ * xSemaphoreGiveMutexRecursive() instead of calling these functions directly.
+ */
+portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
+portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) PRIVILEGED_FUNCTION;
+
+/*
+ * Reset a queue back to its original empty state. pdPASS is returned if the
+ * queue is successfully reset. pdFAIL is returned if the queue could not be
+ * reset because there are tasks blocked on the queue waiting to either
+ * receive from the queue or send to the queue.
+ */
+#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE )
+
+/*
+ * The registry is provided as a means for kernel aware debuggers to
+ * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add
+ * a queue, semaphore or mutex handle to the registry if you want the handle
+ * to be available to a kernel aware debugger. If you are not using a kernel
+ * aware debugger then this function can be ignored.
+ *
+ * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the
+ * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0
+ * within FreeRTOSConfig.h for the registry to be available. Its value
+ * does not effect the number of queues, semaphores and mutexes that can be
+ * created - just the number that the registry can hold.
+ *
+ * @param xQueue The handle of the queue being added to the registry. This
+ * is the handle returned by a call to xQueueCreate(). Semaphore and mutex
+ * handles can also be passed in here.
+ *
+ * @param pcName The name to be associated with the handle. This is the
+ * name that the kernel aware debugger will display.
+ */
+#if configQUEUE_REGISTRY_SIZE > 0
+ void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcName ) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * The registry is provided as a means for kernel aware debuggers to
+ * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add
+ * a queue, semaphore or mutex handle to the registry if you want the handle
+ * to be available to a kernel aware debugger, and vQueueUnregisterQueue() to
+ * remove the queue, semaphore or mutex from the register. If you are not using
+ * a kernel aware debugger then this function can be ignored.
+ *
+ * @param xQueue The handle of the queue being removed from the registry.
+ */
+#if configQUEUE_REGISTRY_SIZE > 0
+ void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * Generic version of the queue creation function, which is in turn called by
+ * any queue, semaphore or mutex creation function or macro.
+ */
+xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType ) PRIVILEGED_FUNCTION;
+
+/*
+ * Queue sets provide a mechanism to allow a task to block (pend) on a read
+ * operation from multiple queues or semaphores simultaneously.
+ *
+ * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
+ * function.
+ *
+ * A queue set must be explicitly created using a call to xQueueCreateSet()
+ * before it can be used. Once created, standard FreeRTOS queues and semaphores
+ * can be added to the set using calls to xQueueAddToSet().
+ * xQueueSelectFromSet() is then used to determine which, if any, of the queues
+ * or semaphores contained in the set is in a state where a queue read or
+ * semaphore take operation would be successful.
+ *
+ * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html
+ * for reasons why queue sets are very rarely needed in practice as there are
+ * simpler methods of blocking on multiple objects.
+ *
+ * Note 2: Blocking on a queue set that contains a mutex will not cause the
+ * mutex holder to inherit the priority of the blocked task.
+ *
+ * Note 3: An additional 4 bytes of RAM is required for each space in a every
+ * queue added to a queue set. Therefore counting semaphores that have a high
+ * maximum count value should not be added to a queue set.
+ *
+ * Note 4: A receive (in the case of a queue) or take (in the case of a
+ * semaphore) operation must not be performed on a member of a queue set unless
+ * a call to xQueueSelectFromSet() has first returned a handle to that set member.
+ *
+ * @param uxEventQueueLength Queue sets store events that occur on
+ * the queues and semaphores contained in the set. uxEventQueueLength specifies
+ * the maximum number of events that can be queued at once. To be absolutely
+ * certain that events are not lost uxEventQueueLength should be set to the
+ * total sum of the length of the queues added to the set, where binary
+ * semaphores and mutexes have a length of 1, and counting semaphores have a
+ * length set by their maximum count value. Examples:
+ * + If a queue set is to hold a queue of length 5, another queue of length 12,
+ * and a binary semaphore, then uxEventQueueLength should be set to
+ * (5 + 12 + 1), or 18.
+ * + If a queue set is to hold three binary semaphores then uxEventQueueLength
+ * should be set to (1 + 1 + 1 ), or 3.
+ * + If a queue set is to hold a counting semaphore that has a maximum count of
+ * 5, and a counting semaphore that has a maximum count of 3, then
+ * uxEventQueueLength should be set to (5 + 3), or 8.
+ *
+ * @return If the queue set is created successfully then a handle to the created
+ * queue set is returned. Otherwise NULL is returned.
+ */
+xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) PRIVILEGED_FUNCTION;
+
+/*
+ * Adds a queue or semaphore to a queue set that was previously created by a
+ * call to xQueueCreateSet().
+ *
+ * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
+ * function.
+ *
+ * Note 1: A receive (in the case of a queue) or take (in the case of a
+ * semaphore) operation must not be performed on a member of a queue set unless
+ * a call to xQueueSelectFromSet() has first returned a handle to that set member.
+ *
+ * @param xQueueOrSemaphore The handle of the queue or semaphore being added to
+ * the queue set (cast to an xQueueSetMemberHandle type).
+ *
+ * @param xQueueSet The handle of the queue set to which the queue or semaphore
+ * is being added.
+ *
+ * @return If the queue or semaphore was successfully added to the queue set
+ * then pdPASS is returned. If the queue could not be successfully added to the
+ * queue set because it is already a member of a different queue set then pdFAIL
+ * is returned.
+ */
+portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION;
+
+/*
+ * Removes a queue or semaphore from a queue set. A queue or semaphore can only
+ * be removed from a set if the queue or semaphore is empty.
+ *
+ * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
+ * function.
+ *
+ * @param xQueueOrSemaphore The handle of the queue or semaphore being removed
+ * from the queue set (cast to an xQueueSetMemberHandle type).
+ *
+ * @param xQueueSet The handle of the queue set in which the queue or semaphore
+ * is included.
+ *
+ * @return If the queue or semaphore was successfully removed from the queue set
+ * then pdPASS is returned. If the queue was not in the queue set, or the
+ * queue (or semaphore) was not empty, then pdFAIL is returned.
+ */
+portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION;
+
+/*
+ * xQueueSelectFromSet() selects from the members of a queue set a queue or
+ * semaphore that either contains data (in the case of a queue) or is available
+ * to take (in the case of a semaphore). xQueueSelectFromSet() effectively
+ * allows a task to block (pend) on a read operation on all the queues and
+ * semaphores in a queue set simultaneously.
+ *
+ * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
+ * function.
+ *
+ * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html
+ * for reasons why queue sets are very rarely needed in practice as there are
+ * simpler methods of blocking on multiple objects.
+ *
+ * Note 2: Blocking on a queue set that contains a mutex will not cause the
+ * mutex holder to inherit the priority of the blocked task.
+ *
+ * Note 3: A receive (in the case of a queue) or take (in the case of a
+ * semaphore) operation must not be performed on a member of a queue set unless
+ * a call to xQueueSelectFromSet() has first returned a handle to that set member.
+ *
+ * @param xQueueSet The queue set on which the task will (potentially) block.
+ *
+ * @param xBlockTimeTicks The maximum time, in ticks, that the calling task will
+ * remain in the Blocked state (with other tasks executing) to wait for a member
+ * of the queue set to be ready for a successful queue read or semaphore take
+ * operation.
+ *
+ * @return xQueueSelectFromSet() will return the handle of a queue (cast to
+ * a xQueueSetMemberHandle type) contained in the queue set that contains data,
+ * or the handle of a semaphore (cast to a xQueueSetMemberHandle type) contained
+ * in the queue set that is available, or NULL if no such queue or semaphore
+ * exists before before the specified block time expires.
+ */
+xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks ) PRIVILEGED_FUNCTION;
+
+/*
+ * A version of xQueueSelectFromSet() that can be used from an ISR.
+ */
+xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION;
+
+/* Not public API functions. */
+void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
+portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue ) PRIVILEGED_FUNCTION;
+void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber ) PRIVILEGED_FUNCTION;
+unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+unsigned char ucQueueGetQueueType( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* QUEUE_H */
+
diff --git a/source/freertos_blinky/freertos/inc/semphr.h b/source/freertos_blinky/freertos/inc/semphr.h
new file mode 100644
index 0000000..863b873
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/semphr.h
@@ -0,0 +1,786 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+#ifndef SEMAPHORE_H
+#define SEMAPHORE_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h" must appear in source files before "include semphr.h"
+#endif
+
+#include "queue.h"
+
+typedef xQueueHandle xSemaphoreHandle;
+
+#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned char ) 1U )
+#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned char ) 0U )
+#define semGIVE_BLOCK_TIME ( ( portTickType ) 0U )
+
+
+/**
+ * semphr. h
+ *
+ *
+ * Macro that implements a semaphore by using the existing queue mechanism.
+ * The queue length is 1 as this is a binary semaphore. The data size is 0
+ * as we don't want to actually store any data - we just want to know if the
+ * queue is empty or full.
+ *
+ * This type of semaphore can be used for pure synchronisation between tasks or
+ * between an interrupt and a task. The semaphore need not be given back once
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while
+ * another continuously 'takes' the semaphore. For this reason this type of
+ * semaphore does not use a priority inheritance mechanism. For an alternative
+ * that does use priority inheritance see xSemaphoreCreateMutex().
+ *
+ * @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle.
+ *
+ * Example usage:
+
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+ // This is a macro so pass the variable in directly.
+ vSemaphoreCreateBinary( xSemaphore );
+
+ if( xSemaphore != NULL )
+ {
+ // The semaphore was created successfully.
+ // The semaphore can now be used.
+ }
+ }
+
+ *
+ * Macro to obtain a semaphore. The semaphore must have previously been
+ * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
+ * xSemaphoreCreateCounting().
+ *
+ * @param xSemaphore A handle to the semaphore being taken - obtained when
+ * the semaphore was created.
+ *
+ * @param xBlockTime The time in ticks to wait for the semaphore to become
+ * available. The macro portTICK_RATE_MS can be used to convert this to a
+ * real time. A block time of zero can be used to poll the semaphore. A block
+ * time of portMAX_DELAY can be used to block indefinitely (provided
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).
+ *
+ * @return pdTRUE if the semaphore was obtained. pdFALSE
+ * if xBlockTime expired without the semaphore becoming available.
+ *
+ * Example usage:
+
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // A task that creates a semaphore.
+ void vATask( void * pvParameters )
+ {
+ // Create the semaphore to guard a shared resource.
+ vSemaphoreCreateBinary( xSemaphore );
+ }
+
+ // A task that uses the semaphore.
+ void vAnotherTask( void * pvParameters )
+ {
+ // ... Do other things.
+
+ if( xSemaphore != NULL )
+ {
+ // See if we can obtain the semaphore. If the semaphore is not available
+ // wait 10 ticks to see if it becomes free.
+ if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+ {
+ // We were able to obtain the semaphore and can now access the
+ // shared resource.
+
+ // ...
+
+ // We have finished accessing the shared resource. Release the
+ // semaphore.
+ xSemaphoreGive( xSemaphore );
+ }
+ else
+ {
+ // We could not obtain the semaphore and can therefore not access
+ // the shared resource safely.
+ }
+ }
+ }
+
+ * \defgroup xSemaphoreTake xSemaphoreTake
+ * \ingroup Semaphores
+ */
+#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
+
+/**
+ * semphr. h
+ * xSemaphoreTakeRecursive(
+ * xSemaphoreHandle xMutex,
+ * portTickType xBlockTime
+ * )
+ *
+ * Macro to recursively obtain, or 'take', a mutex type semaphore.
+ * The mutex must have previously been created using a call to
+ * xSemaphoreCreateRecursiveMutex();
+ *
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
+ * macro to be available.
+ *
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
+ * exactly five times.
+ *
+ * @param xMutex A handle to the mutex being obtained. This is the
+ * handle returned by xSemaphoreCreateRecursiveMutex();
+ *
+ * @param xBlockTime The time in ticks to wait for the semaphore to become
+ * available. The macro portTICK_RATE_MS can be used to convert this to a
+ * real time. A block time of zero can be used to poll the semaphore. If
+ * the task already owns the semaphore then xSemaphoreTakeRecursive() will
+ * return immediately no matter what the value of xBlockTime.
+ *
+ * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime
+ * expired without the semaphore becoming available.
+ *
+ * Example usage:
+
+ xSemaphoreHandle xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+ // Create the mutex to guard a shared resource.
+ xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+ // ... Do other things.
+
+ if( xMutex != NULL )
+ {
+ // See if we can obtain the mutex. If the mutex is not available
+ // wait 10 ticks to see if it becomes free.
+ if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+ {
+ // We were able to obtain the mutex and can now access the
+ // shared resource.
+
+ // ...
+ // For some reason due to the nature of the code further calls to
+ // xSemaphoreTakeRecursive() are made on the same mutex. In real
+ // code these would not be just sequential calls as this would make
+ // no sense. Instead the calls are likely to be buried inside
+ // a more complex call structure.
+ xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+ xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+
+ // The mutex has now been 'taken' three times, so will not be
+ // available to another task until it has also been given back
+ // three times. Again it is unlikely that real code would have
+ // these calls sequentially, but instead buried in a more complex
+ // call structure. This is just for illustrative purposes.
+ xSemaphoreGiveRecursive( xMutex );
+ xSemaphoreGiveRecursive( xMutex );
+ xSemaphoreGiveRecursive( xMutex );
+
+ // Now the mutex can be taken by other tasks.
+ }
+ else
+ {
+ // We could not obtain the mutex and can therefore not access
+ // the shared resource safely.
+ }
+ }
+ }
+
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive
+ * \ingroup Semaphores
+ */
+#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
+
+
+/*
+ * xSemaphoreAltTake() is an alternative version of xSemaphoreTake().
+ *
+ * The source code that implements the alternative (Alt) API is much
+ * simpler because it executes everything from within a critical section.
+ * This is the approach taken by many other RTOSes, but FreeRTOS.org has the
+ * preferred fully featured API too. The fully featured API has more
+ * complex code that takes longer to execute, but makes much less use of
+ * critical sections. Therefore the alternative API sacrifices interrupt
+ * responsiveness to gain execution speed, whereas the fully featured API
+ * sacrifices execution speed to ensure better interrupt responsiveness.
+ */
+#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
+
+/**
+ * semphr. h
+ *
xSemaphoreGive( xSemaphoreHandle xSemaphore )
+ *
+ * Macro to release a semaphore. The semaphore must have previously been
+ * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
+ * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake().
+ *
+ * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for
+ * an alternative which can be used from an ISR.
+ *
+ * This macro must also not be used on semaphores created using
+ * xSemaphoreCreateRecursiveMutex().
+ *
+ * @param xSemaphore A handle to the semaphore being released. This is the
+ * handle returned when the semaphore was created.
+ *
+ * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred.
+ * Semaphores are implemented using queues. An error can occur if there is
+ * no space on the queue to post a message - indicating that the
+ * semaphore was not first obtained correctly.
+ *
+ * Example usage:
+
+ xSemaphoreHandle xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+ // Create the semaphore to guard a shared resource.
+ vSemaphoreCreateBinary( xSemaphore );
+
+ if( xSemaphore != NULL )
+ {
+ if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+ {
+ // We would expect this call to fail because we cannot give
+ // a semaphore without first "taking" it!
+ }
+
+ // Obtain the semaphore - don't block if the semaphore is not
+ // immediately available.
+ if( xSemaphoreTake( xSemaphore, ( portTickType ) 0 ) )
+ {
+ // We now have the semaphore and can access the shared resource.
+
+ // ...
+
+ // We have finished accessing the shared resource so can free the
+ // semaphore.
+ if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+ {
+ // We would not expect this call to fail because we must have
+ // obtained the semaphore to get here.
+ }
+ }
+ }
+ }
+
+ *
+ * Macro to recursively release, or 'give', a mutex type semaphore.
+ * The mutex must have previously been created using a call to
+ * xSemaphoreCreateRecursiveMutex();
+ *
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
+ * macro to be available.
+ *
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
+ * exactly five times.
+ *
+ * @param xMutex A handle to the mutex being released, or 'given'. This is the
+ * handle returned by xSemaphoreCreateMutex();
+ *
+ * @return pdTRUE if the semaphore was given.
+ *
+ * Example usage:
+
+ xSemaphoreHandle xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+ // Create the mutex to guard a shared resource.
+ xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+ // ... Do other things.
+
+ if( xMutex != NULL )
+ {
+ // See if we can obtain the mutex. If the mutex is not available
+ // wait 10 ticks to see if it becomes free.
+ if( xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ) == pdTRUE )
+ {
+ // We were able to obtain the mutex and can now access the
+ // shared resource.
+
+ // ...
+ // For some reason due to the nature of the code further calls to
+ // xSemaphoreTakeRecursive() are made on the same mutex. In real
+ // code these would not be just sequential calls as this would make
+ // no sense. Instead the calls are likely to be buried inside
+ // a more complex call structure.
+ xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+ xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+
+ // The mutex has now been 'taken' three times, so will not be
+ // available to another task until it has also been given back
+ // three times. Again it is unlikely that real code would have
+ // these calls sequentially, it would be more likely that the calls
+ // to xSemaphoreGiveRecursive() would be called as a call stack
+ // unwound. This is just for demonstrative purposes.
+ xSemaphoreGiveRecursive( xMutex );
+ xSemaphoreGiveRecursive( xMutex );
+ xSemaphoreGiveRecursive( xMutex );
+
+ // Now the mutex can be taken by other tasks.
+ }
+ else
+ {
+ // We could not obtain the mutex and can therefore not access
+ // the shared resource safely.
+ }
+ }
+ }
+
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive
+ * \ingroup Semaphores
+ */
+#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) )
+
+/*
+ * xSemaphoreAltGive() is an alternative version of xSemaphoreGive().
+ *
+ * The source code that implements the alternative (Alt) API is much
+ * simpler because it executes everything from within a critical section.
+ * This is the approach taken by many other RTOSes, but FreeRTOS.org has the
+ * preferred fully featured API too. The fully featured API has more
+ * complex code that takes longer to execute, but makes much less use of
+ * critical sections. Therefore the alternative API sacrifices interrupt
+ * responsiveness to gain execution speed, whereas the fully featured API
+ * sacrifices execution speed to ensure better interrupt responsiveness.
+ */
+#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
+
+/**
+ * semphr. h
+ *
+ *
+ * Macro to release a semaphore. The semaphore must have previously been
+ * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting().
+ *
+ * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
+ * must not be used with this macro.
+ *
+ * This macro can be used from an ISR.
+ *
+ * @param xSemaphore A handle to the semaphore being released. This is the
+ * handle returned when the semaphore was created.
+ *
+ * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+
+ \#define LONG_TIME 0xffff
+ \#define TICKS_TO_WAIT 10
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // Repetitive task.
+ void vATask( void * pvParameters )
+ {
+ for( ;; )
+ {
+ // We want this task to run every 10 ticks of a timer. The semaphore
+ // was created before this task was started.
+
+ // Block waiting for the semaphore to become available.
+ if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+ {
+ // It is time to execute.
+
+ // ...
+
+ // We have finished our task. Return to the top of the loop where
+ // we will block on the semaphore until it is time to execute
+ // again. Note when using the semaphore for synchronisation with an
+ // ISR in this manner there is no need to 'give' the semaphore back.
+ }
+ }
+ }
+
+ // Timer ISR
+ void vTimerISR( void * pvParameters )
+ {
+ static unsigned char ucLocalTickCount = 0;
+ static signed portBASE_TYPE xHigherPriorityTaskWoken;
+
+ // A timer tick has occurred.
+
+ // ... Do other time functions.
+
+ // Is it time for vATask () to run?
+ xHigherPriorityTaskWoken = pdFALSE;
+ ucLocalTickCount++;
+ if( ucLocalTickCount >= TICKS_TO_WAIT )
+ {
+ // Unblock the task by releasing the semaphore.
+ xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+
+ // Reset the count so we release the semaphore again in 10 ticks time.
+ ucLocalTickCount = 0;
+ }
+
+ if( xHigherPriorityTaskWoken != pdFALSE )
+ {
+ // We can force a context switch here. Context switching from an
+ // ISR uses port specific syntax. Check the demo task for your port
+ // to find the syntax required.
+ }
+ }
+
+ *
+ * Macro to take a semaphore from an ISR. The semaphore must have
+ * previously been created with a call to vSemaphoreCreateBinary() or
+ * xSemaphoreCreateCounting().
+ *
+ * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
+ * must not be used with this macro.
+ *
+ * This macro can be used from an ISR, however taking a semaphore from an ISR
+ * is not a common operation. It is likely to only be useful when taking a
+ * counting semaphore when an interrupt is obtaining an object from a resource
+ * pool (when the semaphore count indicates the number of resources available).
+ *
+ * @param xSemaphore A handle to the semaphore being taken. This is the
+ * handle returned when the semaphore was created.
+ *
+ * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the semaphore was successfully taken, otherwise
+ * pdFALSE
+ */
+#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * semphr. h
+ *
xSemaphoreHandle xSemaphoreCreateMutex( void )
+ *
+ * Macro that implements a mutex semaphore by using the existing queue
+ * mechanism.
+ *
+ * Mutexes created using this macro can be accessed using the xSemaphoreTake()
+ * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and
+ * xSemaphoreGiveRecursive() macros should not be used.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See vSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @return xSemaphore Handle to the created mutex semaphore. Should be of type
+ * xSemaphoreHandle.
+ *
+ * Example usage:
+
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+ // This is a macro so pass the variable in directly.
+ xSemaphore = xSemaphoreCreateMutex();
+
+ if( xSemaphore != NULL )
+ {
+ // The semaphore was created successfully.
+ // The semaphore can now be used.
+ }
+ }
+
+ *
+ * Macro that implements a recursive mutex by using the existing queue
+ * mechanism.
+ *
+ * Mutexes created using this macro can be accessed using the
+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The
+ * xSemaphoreTake() and xSemaphoreGive() macros should not be used.
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
+ * exactly five times.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See vSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @return xSemaphore Handle to the created mutex semaphore. Should be of type
+ * xSemaphoreHandle.
+ *
+ * Example usage:
+
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+ // This is a macro so pass the variable in directly.
+ xSemaphore = xSemaphoreCreateRecursiveMutex();
+
+ if( xSemaphore != NULL )
+ {
+ // The semaphore was created successfully.
+ // The semaphore can now be used.
+ }
+ }
+
+ *
+ * Macro that creates a counting semaphore by using the existing
+ * queue mechanism.
+ *
+ * Counting semaphores are typically used for two things:
+ *
+ * 1) Counting events.
+ *
+ * In this usage scenario an event handler will 'give' a semaphore each time
+ * an event occurs (incrementing the semaphore count value), and a handler
+ * task will 'take' a semaphore each time it processes an event
+ * (decrementing the semaphore count value). The count value is therefore
+ * the difference between the number of events that have occurred and the
+ * number that have been processed. In this case it is desirable for the
+ * initial count value to be zero.
+ *
+ * 2) Resource management.
+ *
+ * In this usage scenario the count value indicates the number of resources
+ * available. To obtain control of a resource a task must first obtain a
+ * semaphore - decrementing the semaphore count value. When the count value
+ * reaches zero there are no free resources. When a task finishes with the
+ * resource it 'gives' the semaphore back - incrementing the semaphore count
+ * value. In this case it is desirable for the initial count value to be
+ * equal to the maximum count value, indicating that all resources are free.
+ *
+ * @param uxMaxCount The maximum count value that can be reached. When the
+ * semaphore reaches this value it can no longer be 'given'.
+ *
+ * @param uxInitialCount The count value assigned to the semaphore when it is
+ * created.
+ *
+ * @return Handle to the created semaphore. Null if the semaphore could not be
+ * created.
+ *
+ * Example usage:
+
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+ // The max value to which the semaphore can count should be 10, and the
+ // initial value assigned to the count should be 0.
+ xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+
+ if( xSemaphore != NULL )
+ {
+ // The semaphore was created successfully.
+ // The semaphore can now be used.
+ }
+ }
+
+ *
+ * Delete a semaphore. This function must be used with care. For example,
+ * do not delete a mutex type semaphore if the mutex is held by a task.
+ *
+ * @param xSemaphore A handle to the semaphore to be deleted.
+ *
+ * \defgroup vSemaphoreDelete vSemaphoreDelete
+ * \ingroup Semaphores
+ */
+#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( xQueueHandle ) ( xSemaphore ) )
+
+/**
+ * semphr.h
+ *
+ *
+ * If xMutex is indeed a mutex type semaphore, return the current mutex holder.
+ * If xMutex is not a mutex type semaphore, or the mutex is available (not held
+ * by a task), return NULL.
+ *
+ * Note: This Is is a good way of determining if the calling task is the mutex
+ * holder, but not a good way of determining the identity of the mutex holder as
+ * the holder may change between the function exiting and the returned value
+ * being tested.
+ */
+#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) )
+
+#endif /* SEMAPHORE_H */
+
+
diff --git a/source/freertos_blinky/freertos/inc/task.h b/source/freertos_blinky/freertos/inc/task.h
new file mode 100644
index 0000000..0a98d4e
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/task.h
@@ -0,0 +1,1520 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+#ifndef INC_TASK_H
+#define INC_TASK_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h must appear in source files before include task.h"
+#endif
+
+#include "list.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-----------------------------------------------------------
+ * MACROS AND DEFINITIONS
+ *----------------------------------------------------------*/
+
+#define tskKERNEL_VERSION_NUMBER "V7.5.3"
+
+/**
+ * task. h
+ *
+ * Type by which tasks are referenced. For example, a call to xTaskCreate
+ * returns (via a pointer parameter) an xTaskHandle variable that can then
+ * be used as a parameter to vTaskDelete to delete the task.
+ *
+ * \defgroup xTaskHandle xTaskHandle
+ * \ingroup Tasks
+ */
+typedef void * xTaskHandle;
+
+/* Task states returned by eTaskGetState. */
+typedef enum
+{
+ eRunning = 0, /* A task is querying the state of itself, so must be running. */
+ eReady, /* The task being queried is in a read or pending ready list. */
+ eBlocked, /* The task being queried is in the Blocked state. */
+ eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */
+ eDeleted /* The task being queried has been deleted, but its TCB has not yet been freed. */
+} eTaskState;
+
+/*
+ * Used internally only.
+ */
+typedef struct xTIME_OUT
+{
+ portBASE_TYPE xOverflowCount;
+ portTickType xTimeOnEntering;
+} xTimeOutType;
+
+/*
+ * Defines the memory ranges allocated to the task when an MPU is used.
+ */
+typedef struct xMEMORY_REGION
+{
+ void *pvBaseAddress;
+ unsigned long ulLengthInBytes;
+ unsigned long ulParameters;
+} xMemoryRegion;
+
+/*
+ * Parameters required to create an MPU protected task.
+ */
+typedef struct xTASK_PARAMTERS
+{
+ pdTASK_CODE pvTaskCode;
+ const signed char * const pcName;
+ unsigned short usStackDepth;
+ void *pvParameters;
+ unsigned portBASE_TYPE uxPriority;
+ portSTACK_TYPE *puxStackBuffer;
+ xMemoryRegion xRegions[ portNUM_CONFIGURABLE_REGIONS ];
+} xTaskParameters;
+
+/* Used with the uxTaskGetSystemState() function to return the state of each task
+in the system. */
+typedef struct xTASK_STATUS
+{
+ xTaskHandle xHandle; /* The handle of the task to which the rest of the information in the structure relates. */
+ const signed char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */
+ unsigned portBASE_TYPE xTaskNumber; /* A number unique to the task. */
+ eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */
+ unsigned portBASE_TYPE uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */
+ unsigned portBASE_TYPE uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */
+ unsigned long ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
+ unsigned short usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
+} xTaskStatusType;
+
+/* Possible return values for eTaskConfirmSleepModeStatus(). */
+typedef enum
+{
+ eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */
+ eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */
+ eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */
+} eSleepModeStatus;
+
+
+/*
+ * Defines the priority used by the idle task. This must not be modified.
+ *
+ * \ingroup TaskUtils
+ */
+#define tskIDLE_PRIORITY ( ( unsigned portBASE_TYPE ) 0U )
+
+/**
+ * task. h
+ *
+ * Macro for forcing a context switch.
+ *
+ * \defgroup taskYIELD taskYIELD
+ * \ingroup SchedulerControl
+ */
+#define taskYIELD() portYIELD()
+
+/**
+ * task. h
+ *
+ * Macro to mark the start of a critical code region. Preemptive context
+ * switches cannot occur when in a critical region.
+ *
+ * NOTE: This may alter the stack (depending on the portable implementation)
+ * so must be used with care!
+ *
+ * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
+ * \ingroup SchedulerControl
+ */
+#define taskENTER_CRITICAL() portENTER_CRITICAL()
+
+/**
+ * task. h
+ *
+ * Macro to mark the end of a critical code region. Preemptive context
+ * switches cannot occur when in a critical region.
+ *
+ * NOTE: This may alter the stack (depending on the portable implementation)
+ * so must be used with care!
+ *
+ * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
+ * \ingroup SchedulerControl
+ */
+#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
+
+/**
+ * task. h
+ *
+ * Macro to disable all maskable interrupts.
+ *
+ * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS
+ * \ingroup SchedulerControl
+ */
+#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
+
+/**
+ * task. h
+ *
+ * Macro to enable microcontroller interrupts.
+ *
+ * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS
+ * \ingroup SchedulerControl
+ */
+#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
+
+/* Definitions returned by xTaskGetSchedulerState(). */
+#define taskSCHEDULER_NOT_STARTED ( ( portBASE_TYPE ) 0 )
+#define taskSCHEDULER_RUNNING ( ( portBASE_TYPE ) 1 )
+#define taskSCHEDULER_SUSPENDED ( ( portBASE_TYPE ) 2 )
+
+/*-----------------------------------------------------------
+ * TASK CREATION API
+ *----------------------------------------------------------*/
+
+/**
+ * task. h
+ *
+ *
+ * Create a new task and add it to the list of tasks that are ready to run.
+ *
+ * xTaskCreate() can only be used to create a task that has unrestricted
+ * access to the entire microcontroller memory map. Systems that include MPU
+ * support can alternatively create an MPU constrained task using
+ * xTaskCreateRestricted().
+ *
+ * @param pvTaskCode Pointer to the task entry function. Tasks
+ * must be implemented to never return (i.e. continuous loop).
+ *
+ * @param pcName A descriptive name for the task. This is mainly used to
+ * facilitate debugging. Max length defined by tskMAX_TASK_NAME_LEN - default
+ * is 16.
+ *
+ * @param usStackDepth The size of the task stack specified as the number of
+ * variables the stack can hold - not the number of bytes. For example, if
+ * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes
+ * will be allocated for stack storage.
+ *
+ * @param pvParameters Pointer that will be used as the parameter for the task
+ * being created.
+ *
+ * @param uxPriority The priority at which the task should run. Systems that
+ * include MPU support can optionally create tasks in a privileged (system)
+ * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For
+ * example, to create a privileged task at priority 2 the uxPriority parameter
+ * should be set to ( 2 | portPRIVILEGE_BIT ).
+ *
+ * @param pvCreatedTask Used to pass back a handle by which the created task
+ * can be referenced.
+ *
+ * @return pdPASS if the task was successfully created and added to a ready
+ * list, otherwise an error code defined in the file errors. h
+ *
+ * Example usage:
+
+ // Task to be created.
+ void vTaskCode( void * pvParameters )
+ {
+ for( ;; )
+ {
+ // Task code goes here.
+ }
+ }
+
+ // Function that creates a task.
+ void vOtherFunction( void )
+ {
+ static unsigned char ucParameterToPass;
+ xTaskHandle xHandle;
+
+ // Create the task, storing the handle. Note that the passed parameter ucParameterToPass
+ // must exist for the lifetime of the task, so in this case is declared static. If it was just an
+ // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
+ // the new task attempts to access it.
+ xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+
+ // Use the handle to delete the task.
+ vTaskDelete( xHandle );
+ }
+
+ *
+ * xTaskCreateRestricted() should only be used in systems that include an MPU
+ * implementation.
+ *
+ * Create a new task and add it to the list of tasks that are ready to run.
+ * The function parameters define the memory regions and associated access
+ * permissions allocated to the task.
+ *
+ * @param pxTaskDefinition Pointer to a structure that contains a member
+ * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
+ * documentation) plus an optional stack buffer and the memory region
+ * definitions.
+ *
+ * @param pxCreatedTask Used to pass back a handle by which the created task
+ * can be referenced.
+ *
+ * @return pdPASS if the task was successfully created and added to a ready
+ * list, otherwise an error code defined in the file errors. h
+ *
+ * Example usage:
+
+// Create an xTaskParameters structure that defines the task to be created.
+static const xTaskParameters xCheckTaskParameters =
+{
+ vATask, // pvTaskCode - the function that implements the task.
+ "ATask", // pcName - just a text name for the task to assist debugging.
+ 100, // usStackDepth - the stack size DEFINED IN WORDS.
+ NULL, // pvParameters - passed into the task function as the function parameters.
+ ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+ cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+ // xRegions - Allocate up to three separate memory regions for access by
+ // the task, with appropriate access permissions. Different processors have
+ // different memory alignment requirements - refer to the FreeRTOS documentation
+ // for full information.
+ {
+ // Base address Length Parameters
+ { cReadWriteArray, 32, portMPU_REGION_READ_WRITE },
+ { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY },
+ { cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE }
+ }
+};
+
+int main( void )
+{
+xTaskHandle xHandle;
+
+ // Create a task from the const structure defined above. The task handle
+ // is requested (the second parameter is not NULL) but in this case just for
+ // demonstration purposes as its not actually used.
+ xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+ // Start the scheduler.
+ vTaskStartScheduler();
+
+ // Will only get here if there was insufficient memory to create the idle
+ // task.
+ for( ;; );
+}
+
+ *
+ * Memory regions are assigned to a restricted task when the task is created by
+ * a call to xTaskCreateRestricted(). These regions can be redefined using
+ * vTaskAllocateMPURegions().
+ *
+ * @param xTask The handle of the task being updated.
+ *
+ * @param xRegions A pointer to an xMemoryRegion structure that contains the
+ * new memory region definitions.
+ *
+ * Example usage:
+
+// Define an array of xMemoryRegion structures that configures an MPU region
+// allowing read/write access for 1024 bytes starting at the beginning of the
+// ucOneKByte array. The other two of the maximum 3 definable regions are
+// unused so set to zero.
+static const xMemoryRegion xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
+{
+ // Base address Length Parameters
+ { ucOneKByte, 1024, portMPU_REGION_READ_WRITE },
+ { 0, 0, 0 },
+ { 0, 0, 0 }
+};
+
+void vATask( void *pvParameters )
+{
+ // This task was created such that it has access to certain regions of
+ // memory as defined by the MPU configuration. At some point it is
+ // desired that these MPU regions are replaced with that defined in the
+ // xAltRegions const struct above. Use a call to vTaskAllocateMPURegions()
+ // for this purpose. NULL is used as the task handle to indicate that this
+ // function should modify the MPU regions of the calling task.
+ vTaskAllocateMPURegions( NULL, xAltRegions );
+
+ // Now the task can continue its function, but from this point on can only
+ // access its stack and the ucOneKByte array (unless any other statically
+ // defined or shared regions have been declared elsewhere).
+}
+
+ *
+ * INCLUDE_vTaskDelete must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Remove a task from the RTOS real time kernels management. The task being
+ * deleted will be removed from all ready, blocked, suspended and event lists.
+ *
+ * NOTE: The idle task is responsible for freeing the kernel allocated
+ * memory from tasks that have been deleted. It is therefore important that
+ * the idle task is not starved of microcontroller processing time if your
+ * application makes any calls to vTaskDelete (). Memory allocated by the
+ * task code is not automatically freed, and should be freed before the task
+ * is deleted.
+ *
+ * See the demo application file death.c for sample code that utilises
+ * vTaskDelete ().
+ *
+ * @param xTask The handle of the task to be deleted. Passing NULL will
+ * cause the calling task to be deleted.
+ *
+ * Example usage:
+
+ void vOtherFunction( void )
+ {
+ xTaskHandle xHandle;
+
+ // Create the task, storing the handle.
+ xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+ // Use the handle to delete the task.
+ vTaskDelete( xHandle );
+ }
+
+ *
+ * Delay a task for a given number of ticks. The actual time that the
+ * task remains blocked depends on the tick rate. The constant
+ * portTICK_RATE_MS can be used to calculate real time from the tick
+ * rate - with the resolution of one tick period.
+ *
+ * INCLUDE_vTaskDelay must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ *
+ * vTaskDelay() specifies a time at which the task wishes to unblock relative to
+ * the time at which vTaskDelay() is called. For example, specifying a block
+ * period of 100 ticks will cause the task to unblock 100 ticks after
+ * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method
+ * of controlling the frequency of a cyclical task as the path taken through the
+ * code, as well as other task and interrupt activity, will effect the frequency
+ * at which vTaskDelay() gets called and therefore the time at which the task
+ * next executes. See vTaskDelayUntil() for an alternative API function designed
+ * to facilitate fixed frequency execution. It does this by specifying an
+ * absolute time (rather than a relative time) at which the calling task should
+ * unblock.
+ *
+ * @param xTicksToDelay The amount of time, in tick periods, that
+ * the calling task should block.
+ *
+ * Example usage:
+
+ void vTaskFunction( void * pvParameters )
+ {
+ void vTaskFunction( void * pvParameters )
+ {
+ // Block for 500ms.
+ const portTickType xDelay = 500 / portTICK_RATE_MS;
+
+ for( ;; )
+ {
+ // Simply toggle the LED every 500ms, blocking between each toggle.
+ vToggleLED();
+ vTaskDelay( xDelay );
+ }
+ }
+
+ * \defgroup vTaskDelay vTaskDelay
+ * \ingroup TaskCtrl
+ */
+void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ *
+ *
+ * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Delay a task until a specified time. This function can be used by cyclical
+ * tasks to ensure a constant execution frequency.
+ *
+ * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will
+ * cause a task to block for the specified number of ticks from the time vTaskDelay () is
+ * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed
+ * execution frequency as the time between a task starting to execute and that task
+ * calling vTaskDelay () may not be fixed [the task may take a different path though the
+ * code between calls, or may get interrupted or preempted a different number of times
+ * each time it executes].
+ *
+ * Whereas vTaskDelay () specifies a wake time relative to the time at which the function
+ * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to
+ * unblock.
+ *
+ * The constant portTICK_RATE_MS can be used to calculate real time from the tick
+ * rate - with the resolution of one tick period.
+ *
+ * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the
+ * task was last unblocked. The variable must be initialised with the current time
+ * prior to its first use (see the example below). Following this the variable is
+ * automatically updated within vTaskDelayUntil ().
+ *
+ * @param xTimeIncrement The cycle time period. The task will be unblocked at
+ * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the
+ * same xTimeIncrement parameter value will cause the task to execute with
+ * a fixed interface period.
+ *
+ * Example usage:
+
+ // Perform an action every 10 ticks.
+ void vTaskFunction( void * pvParameters )
+ {
+ portTickType xLastWakeTime;
+ const portTickType xFrequency = 10;
+
+ // Initialise the xLastWakeTime variable with the current time.
+ xLastWakeTime = xTaskGetTickCount ();
+ for( ;; )
+ {
+ // Wait for the next cycle.
+ vTaskDelayUntil( &xLastWakeTime, xFrequency );
+
+ // Perform action here.
+ }
+ }
+
+ *
+ * INCLUDE_xTaskPriorityGet must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Obtain the priority of any task.
+ *
+ * @param xTask Handle of the task to be queried. Passing a NULL
+ * handle results in the priority of the calling task being returned.
+ *
+ * @return The priority of xTask.
+ *
+ * Example usage:
+
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+ // Create a task, storing the handle.
+ xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+ // ...
+
+ // Use the handle to obtain the priority of the created task.
+ // It was created with tskIDLE_PRIORITY, but may have changed
+ // it itself.
+ if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
+ {
+ // The task has changed it's priority.
+ }
+
+ // ...
+
+ // Is our priority higher than the created task?
+ if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
+ {
+ // Our priority (obtained using NULL handle) is higher.
+ }
+ }
+
+ *
+ * INCLUDE_eTaskGetState must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Obtain the state of any task. States are encoded by the eTaskState
+ * enumerated type.
+ *
+ * @param xTask Handle of the task to be queried.
+ *
+ * @return The state of xTask at the time the function was called. Note the
+ * state of the task might change between the function being called, and the
+ * functions return value being tested by the calling task.
+ */
+eTaskState eTaskGetState( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ *
+ *
+ * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Set the priority of any task.
+ *
+ * A context switch will occur before the function returns if the priority
+ * being set is higher than the currently executing task.
+ *
+ * @param xTask Handle to the task for which the priority is being set.
+ * Passing a NULL handle results in the priority of the calling task being set.
+ *
+ * @param uxNewPriority The priority to which the task will be set.
+ *
+ * Example usage:
+
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+ // Create a task, storing the handle.
+ xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+ // ...
+
+ // Use the handle to raise the priority of the created task.
+ vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
+
+ // ...
+
+ // Use a NULL handle to raise our priority to the same value.
+ vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
+ }
+
+ *
+ * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Suspend any task. When suspended a task will never get any microcontroller
+ * processing time, no matter what its priority.
+ *
+ * Calls to vTaskSuspend are not accumulative -
+ * i.e. calling vTaskSuspend () twice on the same task still only requires one
+ * call to vTaskResume () to ready the suspended task.
+ *
+ * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL
+ * handle will cause the calling task to be suspended.
+ *
+ * Example usage:
+
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+ // Create a task, storing the handle.
+ xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+ // ...
+
+ // Use the handle to suspend the created task.
+ vTaskSuspend( xHandle );
+
+ // ...
+
+ // The created task will not run during this period, unless
+ // another task calls vTaskResume( xHandle ).
+
+ //...
+
+
+ // Suspend ourselves.
+ vTaskSuspend( NULL );
+
+ // We cannot get here unless another task calls vTaskResume
+ // with our handle as the parameter.
+ }
+
+ *
+ * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Resumes a suspended task.
+ *
+ * A task that has been suspended by one of more calls to vTaskSuspend ()
+ * will be made available for running again by a single call to
+ * vTaskResume ().
+ *
+ * @param xTaskToResume Handle to the task being readied.
+ *
+ * Example usage:
+
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+ // Create a task, storing the handle.
+ xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+ // ...
+
+ // Use the handle to suspend the created task.
+ vTaskSuspend( xHandle );
+
+ // ...
+
+ // The created task will not run during this period, unless
+ // another task calls vTaskResume( xHandle ).
+
+ //...
+
+
+ // Resume the suspended task ourselves.
+ vTaskResume( xHandle );
+
+ // The created task will once again get microcontroller processing
+ // time in accordance with it priority within the system.
+ }
+
+ *
+ * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be
+ * available. See the configuration section for more information.
+ *
+ * An implementation of vTaskResume() that can be called from within an ISR.
+ *
+ * A task that has been suspended by one of more calls to vTaskSuspend ()
+ * will be made available for running again by a single call to
+ * xTaskResumeFromISR ().
+ *
+ * @param xTaskToResume Handle to the task being readied.
+ *
+ * \defgroup vTaskResumeFromISR vTaskResumeFromISR
+ * \ingroup TaskCtrl
+ */
+portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) PRIVILEGED_FUNCTION;
+
+/*-----------------------------------------------------------
+ * SCHEDULER CONTROL
+ *----------------------------------------------------------*/
+
+/**
+ * task. h
+ *
void vTaskStartScheduler( void );
+ *
+ * Starts the real time kernel tick processing. After calling the kernel
+ * has control over which tasks are executed and when. This function
+ * does not return until an executing task calls vTaskEndScheduler ().
+ *
+ * At least one task should be created via a call to xTaskCreate ()
+ * before calling vTaskStartScheduler (). The idle task is created
+ * automatically when the first application task is created.
+ *
+ * See the demo application file main.c for an example of creating
+ * tasks and starting the kernel.
+ *
+ * Example usage:
+
+ void vAFunction( void )
+ {
+ // Create at least one task before starting the kernel.
+ xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+ // Start the real time kernel with preemption.
+ vTaskStartScheduler ();
+
+ // Will not get here unless a task calls vTaskEndScheduler ()
+ }
+
+ *
+ * Stops the real time kernel tick. All created tasks will be automatically
+ * deleted and multitasking (either preemptive or cooperative) will
+ * stop. Execution then resumes from the point where vTaskStartScheduler ()
+ * was called, as if vTaskStartScheduler () had just returned.
+ *
+ * See the demo application file main. c in the demo/PC directory for an
+ * example that uses vTaskEndScheduler ().
+ *
+ * vTaskEndScheduler () requires an exit function to be defined within the
+ * portable layer (see vPortEndScheduler () in port. c for the PC port). This
+ * performs hardware specific operations such as stopping the kernel tick.
+ *
+ * vTaskEndScheduler () will cause all of the resources allocated by the
+ * kernel to be freed - but will not free resources allocated by application
+ * tasks.
+ *
+ * Example usage:
+
+ void vTaskCode( void * pvParameters )
+ {
+ for( ;; )
+ {
+ // Task code goes here.
+
+ // At some point we want to end the real time kernel processing
+ // so call ...
+ vTaskEndScheduler ();
+ }
+ }
+
+ void vAFunction( void )
+ {
+ // Create at least one task before starting the kernel.
+ xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+ // Start the real time kernel with preemption.
+ vTaskStartScheduler ();
+
+ // Will only get here when the vTaskCode () task has called
+ // vTaskEndScheduler (). When we get here we are back to single task
+ // execution.
+ }
+
+ *
+ * Suspends all real time kernel activity while keeping interrupts (including the
+ * kernel tick) enabled.
+ *
+ * After calling vTaskSuspendAll () the calling task will continue to execute
+ * without risk of being swapped out until a call to xTaskResumeAll () has been
+ * made.
+ *
+ * API functions that have the potential to cause a context switch (for example,
+ * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler
+ * is suspended.
+ *
+ * Example usage:
+
+ void vTask1( void * pvParameters )
+ {
+ for( ;; )
+ {
+ // Task code goes here.
+
+ // ...
+
+ // At some point the task wants to perform a long operation during
+ // which it does not want to get swapped out. It cannot use
+ // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+ // operation may cause interrupts to be missed - including the
+ // ticks.
+
+ // Prevent the real time kernel swapping out the task.
+ vTaskSuspendAll ();
+
+ // Perform the operation here. There is no need to use critical
+ // sections as we have all the microcontroller processing time.
+ // During this time interrupts will still operate and the kernel
+ // tick count will be maintained.
+
+ // ...
+
+ // The operation is complete. Restart the kernel.
+ xTaskResumeAll ();
+ }
+ }
+
+ *
+ * Resumes real time kernel activity following a call to vTaskSuspendAll ().
+ * After a call to vTaskSuspendAll () the kernel will take control of which
+ * task is executing at any time.
+ *
+ * @return If resuming the scheduler caused a context switch then pdTRUE is
+ * returned, otherwise pdFALSE is returned.
+ *
+ * Example usage:
+
+ void vTask1( void * pvParameters )
+ {
+ for( ;; )
+ {
+ // Task code goes here.
+
+ // ...
+
+ // At some point the task wants to perform a long operation during
+ // which it does not want to get swapped out. It cannot use
+ // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+ // operation may cause interrupts to be missed - including the
+ // ticks.
+
+ // Prevent the real time kernel swapping out the task.
+ vTaskSuspendAll ();
+
+ // Perform the operation here. There is no need to use critical
+ // sections as we have all the microcontroller processing time.
+ // During this time interrupts will still operate and the real
+ // time kernel tick count will be maintained.
+
+ // ...
+
+ // The operation is complete. Restart the kernel. We want to force
+ // a context switch - but there is no point if resuming the scheduler
+ // caused a context switch already.
+ if( !xTaskResumeAll () )
+ {
+ taskYIELD ();
+ }
+ }
+ }
+
signed portBASE_TYPE xTaskIsTaskSuspended( const xTaskHandle xTask );
+ *
+ * Utility task that simply returns pdTRUE if the task referenced by xTask is
+ * currently in the Suspended state, or pdFALSE if the task referenced by xTask
+ * is in any other state.
+ *
+ */
+signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
+
+/*-----------------------------------------------------------
+ * TASK UTILITIES
+ *----------------------------------------------------------*/
+
+/**
+ * task. h
+ *
portTickType xTaskGetTickCount( void );
+ *
+ * @return The count of ticks since vTaskStartScheduler was called.
+ *
+ * \defgroup xTaskGetTickCount xTaskGetTickCount
+ * \ingroup TaskUtils
+ */
+portTickType xTaskGetTickCount( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ *
portTickType xTaskGetTickCountFromISR( void );
+ *
+ * @return The count of ticks since vTaskStartScheduler was called.
+ *
+ * This is a version of xTaskGetTickCount() that is safe to be called from an
+ * ISR - provided that portTickType is the natural word size of the
+ * microcontroller being used or interrupt nesting is either not supported or
+ * not being used.
+ *
+ * \defgroup xTaskGetTickCount xTaskGetTickCount
+ * \ingroup TaskUtils
+ */
+portTickType xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ *
unsigned short uxTaskGetNumberOfTasks( void );
+ *
+ * @return The number of tasks that the real time kernel is currently managing.
+ * This includes all ready, blocked and suspended tasks. A task that
+ * has been deleted but not yet freed by the idle task will also be
+ * included in the count.
+ *
+ * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks
+ * \ingroup TaskUtils
+ */
+unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ *
signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery );
+ *
+ * @return The text (human readable) name of the task referenced by the handle
+ * xTaskToQueury. A task can query its own name by either passing in its own
+ * handle, or by setting xTaskToQuery to NULL. INCLUDE_pcTaskGetTaskName must be
+ * set to 1 in FreeRTOSConfig.h for pcTaskGetTaskName() to be available.
+ *
+ * \defgroup pcTaskGetTaskName pcTaskGetTaskName
+ * \ingroup TaskUtils
+ */
+signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery );
+
+/**
+ * task.h
+ *
+ *
+ * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for
+ * this function to be available.
+ *
+ * Returns the high water mark of the stack associated with xTask. That is,
+ * the minimum free stack space there has been (in words, so on a 32 bit machine
+ * a value of 1 means 4 bytes) since the task started. The smaller the returned
+ * number the closer the task has come to overflowing its stack.
+ *
+ * @param xTask Handle of the task associated with the stack to be checked.
+ * Set xTask to NULL to check the stack of the calling task.
+ *
+ * @return The smallest amount of free stack space there has been (in bytes)
+ * since the task referenced by xTask was created.
+ */
+unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
+
+/* When using trace macros it is sometimes necessary to include tasks.h before
+FreeRTOS.h. When this is done pdTASK_HOOK_CODE will not yet have been defined,
+so the following two prototypes will cause a compilation error. This can be
+fixed by simply guarding against the inclusion of these two prototypes unless
+they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration
+constant. */
+#ifdef configUSE_APPLICATION_TASK_TAG
+ #if configUSE_APPLICATION_TASK_TAG == 1
+ /**
+ * task.h
+ *
+ *
+ * Sets pxHookFunction to be the task hook function used by the task xTask.
+ * Passing xTask as NULL has the effect of setting the calling tasks hook
+ * function.
+ */
+ void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) PRIVILEGED_FUNCTION;
+
+ /**
+ * task.h
+ *
+ *
+ * Calls the hook function associated with xTask. Passing xTask as NULL has
+ * the effect of calling the Running tasks (the calling task) hook function.
+ *
+ * pvParameter is passed to the hook function for the task to interpret as it
+ * wants.
+ */
+portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) PRIVILEGED_FUNCTION;
+
+/**
+ * xTaskGetIdleTaskHandle() is only available if
+ * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h.
+ *
+ * Simply returns the handle of the idle task. It is not valid to call
+ * xTaskGetIdleTaskHandle() before the scheduler has been started.
+ */
+xTaskHandle xTaskGetIdleTaskHandle( void );
+
+/**
+ * configUSE_TRACE_FACILITY must bet defined as 1 in FreeRTOSConfig.h for
+ * uxTaskGetSystemState() to be available.
+ *
+ * uxTaskGetSystemState() populates an xTaskStatusType structure for each task in
+ * the system. xTaskStatusType structures contain, among other things, members
+ * for the task handle, task name, task priority, task state, and total amount
+ * of run time consumed by the task. See the xTaskStatusType structure
+ * definition in this file for the full member list.
+ *
+ * NOTE: This function is intended for debugging use only as its use results in
+ * the scheduler remaining suspended for an extended period.
+ *
+ * @param pxTaskStatusArray A pointer to an array of xTaskStatusType structures.
+ * The array must contain at least one xTaskStatusType structure for each task
+ * that is under the control of the RTOS. The number of tasks under the control
+ * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function.
+ *
+ * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray
+ * parameter. The size is specified as the number of indexes in the array, or
+ * the number of xTaskStatusType structures contained in the array, not by the
+ * number of bytes in the array.
+ *
+ * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in
+ * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to the
+ * total run time (as defined by the run time stats clock, see
+ * http://www.freertos.org/rtos-run-time-stats.html) since the target booted.
+ * pulTotalRunTime can be set to NULL to omit the total run time information.
+ *
+ * @return The number of xTaskStatusType structures that were populated by
+ * uxTaskGetSystemState(). This should equal the number returned by the
+ * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed
+ * in the uxArraySize parameter was too small.
+ *
+ * Example usage:
+
+ // This example demonstrates how a human readable table of run time stats
+ // information is generated from raw data provided by uxTaskGetSystemState().
+ // The human readable table is written to pcWriteBuffer
+ void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
+ {
+ xTaskStatusType *pxTaskStatusArray;
+ volatile unsigned portBASE_TYPE uxArraySize, x;
+ unsigned long ulTotalRunTime, ulStatsAsPercentage;
+
+ // Make sure the write buffer does not contain a string.
+ *pcWriteBuffer = 0x00;
+
+ // Take a snapshot of the number of tasks in case it changes while this
+ // function is executing.
+ uxArraySize = uxCurrentNumberOfTasks();
+
+ // Allocate a xTaskStatusType structure for each task. An array could be
+ // allocated statically at compile time.
+ pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) );
+
+ if( pxTaskStatusArray != NULL )
+ {
+ // Generate raw status information about each task.
+ uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
+
+ // For percentage calculations.
+ ulTotalRunTime /= 100UL;
+
+ // Avoid divide by zero errors.
+ if( ulTotalRunTime > 0 )
+ {
+ // For each populated position in the pxTaskStatusArray array,
+ // format the raw data as human readable ASCII data
+ for( x = 0; x < uxArraySize; x++ )
+ {
+ // What percentage of the total run time has the task used?
+ // This will always be rounded down to the nearest integer.
+ // ulTotalRunTimeDiv100 has already been divided by 100.
+ ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
+
+ if( ulStatsAsPercentage > 0UL )
+ {
+ sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
+ }
+ else
+ {
+ // If the percentage is zero here then the task has
+ // consumed less than 1% of the total run time.
+ sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
+ }
+
+ pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
+ }
+ }
+
+ // The array is no longer needed, free the memory it consumes.
+ vPortFree( pxTaskStatusArray );
+ }
+ }
+
+ *
+ * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must
+ * both be defined as 1 for this function to be available. See the
+ * configuration section of the FreeRTOS.org website for more information.
+ *
+ * NOTE 1: This function will disable interrupts for its duration. It is
+ * not intended for normal application runtime use but as a debug aid.
+ *
+ * Lists all the current tasks, along with their current state and stack
+ * usage high water mark.
+ *
+ * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or
+ * suspended ('S').
+ *
+ * PLEASE NOTE:
+ *
+ * This function is provided for convenience only, and is used by many of the
+ * demo applications. Do not consider it to be part of the scheduler.
+ *
+ * vTaskList() calls uxTaskGetSystemState(), then formats part of the
+ * uxTaskGetSystemState() output into a human readable table that displays task
+ * names, states and stack usage.
+ *
+ * vTaskList() has a dependency on the sprintf() C library function that might
+ * bloat the code size, use a lot of stack, and provide different results on
+ * different platforms. An alternative, tiny, third party, and limited
+ * functionality implementation of sprintf() is provided in many of the
+ * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note
+ * printf-stdarg.c does not provide a full snprintf() implementation!).
+ *
+ * It is recommended that production systems call uxTaskGetSystemState()
+ * directly to get access to raw stats data, rather than indirectly through a
+ * call to vTaskList().
+ *
+ * @param pcWriteBuffer A buffer into which the above mentioned details
+ * will be written, in ascii form. This buffer is assumed to be large
+ * enough to contain the generated report. Approximately 40 bytes per
+ * task should be sufficient.
+ *
+ * \defgroup vTaskList vTaskList
+ * \ingroup TaskUtils
+ */
+void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ *
void vTaskGetRunTimeStats( char *pcWriteBuffer );
+ *
+ * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS
+ * must both be defined as 1 for this function to be available. The application
+ * must also then provide definitions for
+ * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE
+ * to configure a peripheral timer/counter and return the timers current count
+ * value respectively. The counter should be at least 10 times the frequency of
+ * the tick count.
+ *
+ * NOTE 1: This function will disable interrupts for its duration. It is
+ * not intended for normal application runtime use but as a debug aid.
+ *
+ * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total
+ * accumulated execution time being stored for each task. The resolution
+ * of the accumulated time value depends on the frequency of the timer
+ * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro.
+ * Calling vTaskGetRunTimeStats() writes the total execution time of each
+ * task into a buffer, both as an absolute count value and as a percentage
+ * of the total system execution time.
+ *
+ * NOTE 2:
+ *
+ * This function is provided for convenience only, and is used by many of the
+ * demo applications. Do not consider it to be part of the scheduler.
+ *
+ * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part of the
+ * uxTaskGetSystemState() output into a human readable table that displays the
+ * amount of time each task has spent in the Running state in both absolute and
+ * percentage terms.
+ *
+ * vTaskGetRunTimeStats() has a dependency on the sprintf() C library function
+ * that might bloat the code size, use a lot of stack, and provide different
+ * results on different platforms. An alternative, tiny, third party, and
+ * limited functionality implementation of sprintf() is provided in many of the
+ * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note
+ * printf-stdarg.c does not provide a full snprintf() implementation!).
+ *
+ * It is recommended that production systems call uxTaskGetSystemState() directly
+ * to get access to raw stats data, rather than indirectly through a call to
+ * vTaskGetRunTimeStats().
+ *
+ * @param pcWriteBuffer A buffer into which the execution times will be
+ * written, in ascii form. This buffer is assumed to be large enough to
+ * contain the generated report. Approximately 40 bytes per task should
+ * be sufficient.
+ *
+ * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats
+ * \ingroup TaskUtils
+ */
+void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION;
+
+/*-----------------------------------------------------------
+ * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
+ *----------------------------------------------------------*/
+
+/*
+ * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY
+ * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS
+ * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+ *
+ * Called from the real time kernel tick (either preemptive or cooperative),
+ * this increments the tick count and checks if any tasks that are blocked
+ * for a finite period required removing from a blocked list and placing on
+ * a ready list. If a non-zero value is returned then a context switch is
+ * required because either:
+ * + A task was removed from a blocked list because its timeout had expired,
+ * or
+ * + Time slicing is in use and there is a task of equal priority to the
+ * currently running task.
+ */
+portBASE_TYPE xTaskIncrementTick( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
+ * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+ *
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED.
+ *
+ * Removes the calling task from the ready list and places it both
+ * on the list of tasks waiting for a particular event, and the
+ * list of delayed tasks. The task will be removed from both lists
+ * and replaced on the ready list should either the event occur (and
+ * there be no higher priority tasks waiting on the same event) or
+ * the delay period expires.
+ *
+ * @param pxEventList The list containing tasks that are blocked waiting
+ * for the event to occur.
+ *
+ * @param xTicksToWait The maximum amount of time that the task should wait
+ * for the event to occur. This is specified in kernel ticks,the constant
+ * portTICK_RATE_MS can be used to convert kernel ticks into a real time
+ * period.
+ */
+void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/*
+ * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
+ * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+ *
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED.
+ *
+ * This function performs nearly the same function as vTaskPlaceOnEventList().
+ * The difference being that this function does not permit tasks to block
+ * indefinitely, whereas vTaskPlaceOnEventList() does.
+ *
+ * @return pdTRUE if the task being removed has a higher priority than the task
+ * making the call, otherwise pdFALSE.
+ */
+void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/*
+ * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
+ * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+ *
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED.
+ *
+ * Removes a task from both the specified event list and the list of blocked
+ * tasks, and places it on a ready queue.
+ *
+ * xTaskRemoveFromEventList () will be called if either an event occurs to
+ * unblock a task, or the block timeout period expires.
+ *
+ * @return pdTRUE if the task being removed has a higher priority than the task
+ * making the call, otherwise pdFALSE.
+ */
+signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) PRIVILEGED_FUNCTION;
+
+/*
+ * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY
+ * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS
+ * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+ *
+ * Sets the pointer to the current TCB to the TCB of the highest priority task
+ * that is ready to run.
+ */
+void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Return the handle of the calling task.
+ */
+xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Capture the current time status for future reference.
+ */
+void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) PRIVILEGED_FUNCTION;
+
+/*
+ * Compare the time status now with that previously captured to see if the
+ * timeout has expired.
+ */
+portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) PRIVILEGED_FUNCTION;
+
+/*
+ * Shortcut used by the queue implementation to prevent unnecessary call to
+ * taskYIELD();
+ */
+void vTaskMissedYield( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Returns the scheduler state as taskSCHEDULER_RUNNING,
+ * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED.
+ */
+portBASE_TYPE xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Raises the priority of the mutex holder to that of the calling task should
+ * the mutex holder have a priority less than the calling task.
+ */
+void vTaskPriorityInherit( xTaskHandle const pxMutexHolder ) PRIVILEGED_FUNCTION;
+
+/*
+ * Set the priority of a task back to its proper priority in the case that it
+ * inherited a higher priority while it was holding a semaphore.
+ */
+void vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder ) PRIVILEGED_FUNCTION;
+
+/*
+ * Generic version of the task creation function which is in turn called by the
+ * xTaskCreate() and xTaskCreateRestricted() macros.
+ */
+signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) PRIVILEGED_FUNCTION;
+
+/*
+ * Get the uxTCBNumber assigned to the task referenced by the xTask parameter.
+ */
+unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask );
+
+/*
+ * Set the uxTCBNumber of the task referenced by the xTask parameter to
+ * ucHandle.
+ */
+void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle );
+
+/*
+ * If tickless mode is being used, or a low power mode is implemented, then
+ * the tick interrupt will not execute during idle periods. When this is the
+ * case, the tick count value maintained by the scheduler needs to be kept up
+ * to date with the actual execution time by being skipped forward by the by
+ * a time equal to the idle period.
+ */
+void vTaskStepTick( portTickType xTicksToJump );
+
+/*
+ * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port
+ * specific sleep function to determine if it is ok to proceed with the sleep,
+ * and if it is ok to proceed, if it is ok to sleep indefinitely.
+ *
+ * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only
+ * called with the scheduler suspended, not from within a critical section. It
+ * is therefore possible for an interrupt to request a context switch between
+ * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being
+ * entered. eTaskConfirmSleepModeStatus() should be called from a short
+ * critical section between the timer being stopped and the sleep mode being
+ * entered to ensure it is ok to proceed into the sleep mode.
+ */
+eSleepModeStatus eTaskConfirmSleepModeStatus( void );
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* INC_TASK_H */
+
+
+
diff --git a/source/freertos_blinky/freertos/inc/timers.h b/source/freertos_blinky/freertos/inc/timers.h
new file mode 100644
index 0000000..60758d9
--- /dev/null
+++ b/source/freertos_blinky/freertos/inc/timers.h
@@ -0,0 +1,960 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+#ifndef TIMERS_H
+#define TIMERS_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h must appear in source files before include timers.h"
+#endif
+
+/*lint -e537 This headers are only multiply included if the application code
+happens to also be including task.h. */
+#include "task.h"
+/*lint +e956 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* IDs for commands that can be sent/received on the timer queue. These are to
+be used solely through the macros that make up the public software timer API,
+as defined below. */
+#define tmrCOMMAND_START ( ( portBASE_TYPE ) 0 )
+#define tmrCOMMAND_STOP ( ( portBASE_TYPE ) 1 )
+#define tmrCOMMAND_CHANGE_PERIOD ( ( portBASE_TYPE ) 2 )
+#define tmrCOMMAND_DELETE ( ( portBASE_TYPE ) 3 )
+
+/*-----------------------------------------------------------
+ * MACROS AND DEFINITIONS
+ *----------------------------------------------------------*/
+
+ /**
+ * Type by which software timers are referenced. For example, a call to
+ * xTimerCreate() returns an xTimerHandle variable that can then be used to
+ * reference the subject timer in calls to other software timer API functions
+ * (for example, xTimerStart(), xTimerReset(), etc.).
+ */
+typedef void * xTimerHandle;
+
+/* Define the prototype to which timer callback functions must conform. */
+typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer );
+
+/**
+ * xTimerHandle xTimerCreate( const signed char *pcTimerName,
+ * portTickType xTimerPeriodInTicks,
+ * unsigned portBASE_TYPE uxAutoReload,
+ * void * pvTimerID,
+ * tmrTIMER_CALLBACK pxCallbackFunction );
+ *
+ * Creates a new software timer instance. This allocates the storage required
+ * by the new timer, initialises the new timers internal state, and returns a
+ * handle by which the new timer can be referenced.
+ *
+ * Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
+ * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
+ * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the
+ * active state.
+ *
+ * @param pcTimerName A text name that is assigned to the timer. This is done
+ * purely to assist debugging. The kernel itself only ever references a timer by
+ * its handle, and never by its name.
+ *
+ * @param xTimerPeriodInTicks The timer period. The time is defined in tick periods so
+ * the constant portTICK_RATE_MS can be used to convert a time that has been
+ * specified in milliseconds. For example, if the timer must expire after 100
+ * ticks, then xTimerPeriodInTicks should be set to 100. Alternatively, if the timer
+ * must expire after 500ms, then xPeriod can be set to ( 500 / portTICK_RATE_MS )
+ * provided configTICK_RATE_HZ is less than or equal to 1000.
+ *
+ * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will
+ * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. If
+ * uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and
+ * enter the dormant state after it expires.
+ *
+ * @param pvTimerID An identifier that is assigned to the timer being created.
+ * Typically this would be used in the timer callback function to identify which
+ * timer expired when the same callback function is assigned to more than one
+ * timer.
+ *
+ * @param pxCallbackFunction The function to call when the timer expires.
+ * Callback functions must have the prototype defined by tmrTIMER_CALLBACK,
+ * which is "void vCallbackFunction( xTimerHandle xTimer );".
+ *
+ * @return If the timer is successfully create then a handle to the newly
+ * created timer is returned. If the timer cannot be created (because either
+ * there is insufficient FreeRTOS heap remaining to allocate the timer
+ * structures, or the timer period was set to 0) then 0 is returned.
+ *
+ * Example usage:
+ * @verbatim
+ * #define NUM_TIMERS 5
+ *
+ * // An array to hold handles to the created timers.
+ * xTimerHandle xTimers[ NUM_TIMERS ];
+ *
+ * // An array to hold a count of the number of times each timer expires.
+ * long lExpireCounters[ NUM_TIMERS ] = { 0 };
+ *
+ * // Define a callback function that will be used by multiple timer instances.
+ * // The callback function does nothing but count the number of times the
+ * // associated timer expires, and stop the timer once the timer has expired
+ * // 10 times.
+ * void vTimerCallback( xTimerHandle pxTimer )
+ * {
+ * long lArrayIndex;
+ * const long xMaxExpiryCountBeforeStopping = 10;
+ *
+ * // Optionally do something if the pxTimer parameter is NULL.
+ * configASSERT( pxTimer );
+ *
+ * // Which timer expired?
+ * lArrayIndex = ( long ) pvTimerGetTimerID( pxTimer );
+ *
+ * // Increment the number of times that pxTimer has expired.
+ * lExpireCounters[ lArrayIndex ] += 1;
+ *
+ * // If the timer has expired 10 times then stop it from running.
+ * if( lExpireCounters[ lArrayIndex ] == xMaxExpiryCountBeforeStopping )
+ * {
+ * // Do not use a block time if calling a timer API function from a
+ * // timer callback function, as doing so could cause a deadlock!
+ * xTimerStop( pxTimer, 0 );
+ * }
+ * }
+ *
+ * void main( void )
+ * {
+ * long x;
+ *
+ * // Create then start some timers. Starting the timers before the scheduler
+ * // has been started means the timers will start running immediately that
+ * // the scheduler starts.
+ * for( x = 0; x < NUM_TIMERS; x++ )
+ * {
+ * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel.
+ * ( 100 * x ), // The timer period in ticks.
+ * pdTRUE, // The timers will auto-reload themselves when they expire.
+ * ( void * ) x, // Assign each timer a unique id equal to its array index.
+ * vTimerCallback // Each timer calls the same callback when it expires.
+ * );
+ *
+ * if( xTimers[ x ] == NULL )
+ * {
+ * // The timer was not created.
+ * }
+ * else
+ * {
+ * // Start the timer. No block time is specified, and even if one was
+ * // it would be ignored because the scheduler has not yet been
+ * // started.
+ * if( xTimerStart( xTimers[ x ], 0 ) != pdPASS )
+ * {
+ * // The timer could not be set into the Active state.
+ * }
+ * }
+ * }
+ *
+ * // ...
+ * // Create tasks here.
+ * // ...
+ *
+ * // Starting the scheduler will start the timers running as they have already
+ * // been set into the active state.
+ * xTaskStartScheduler();
+ *
+ * // Should not reach here.
+ * for( ;; );
+ * }
+ * @endverbatim
+ */
+xTimerHandle xTimerCreate( const signed char * const pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void * pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) PRIVILEGED_FUNCTION;
+
+/**
+ * void *pvTimerGetTimerID( xTimerHandle xTimer );
+ *
+ * Returns the ID assigned to the timer.
+ *
+ * IDs are assigned to timers using the pvTimerID parameter of the call to
+ * xTimerCreated() that was used to create the timer.
+ *
+ * If the same callback function is assigned to multiple timers then the timer
+ * ID can be used within the callback function to identify which timer actually
+ * expired.
+ *
+ * @param xTimer The timer being queried.
+ *
+ * @return The ID assigned to the timer being queried.
+ *
+ * Example usage:
+ *
+ * See the xTimerCreate() API function example usage scenario.
+ */
+void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION;
+
+/**
+ * portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer );
+ *
+ * Queries a timer to see if it is active or dormant.
+ *
+ * A timer will be dormant if:
+ * 1) It has been created but not started, or
+ * 2) It is an expired on-shot timer that has not been restarted.
+ *
+ * Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
+ * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
+ * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the
+ * active state.
+ *
+ * @param xTimer The timer being queried.
+ *
+ * @return pdFALSE will be returned if the timer is dormant. A value other than
+ * pdFALSE will be returned if the timer is active.
+ *
+ * Example usage:
+ * @verbatim
+ * // This function assumes xTimer has already been created.
+ * void vAFunction( xTimerHandle xTimer )
+ * {
+ * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )"
+ * {
+ * // xTimer is active, do something.
+ * }
+ * else
+ * {
+ * // xTimer is not active, do something else.
+ * }
+ * }
+ * @endverbatim
+ */
+portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) PRIVILEGED_FUNCTION;
+
+/**
+ * xTimerGetTimerDaemonTaskHandle() is only available if
+ * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h.
+ *
+ * Simply returns the handle of the timer service/daemon task. It it not valid
+ * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started.
+ */
+xTaskHandle xTimerGetTimerDaemonTaskHandle( void );
+
+/**
+ * portBASE_TYPE xTimerStart( xTimerHandle xTimer, portTickType xBlockTime );
+ *
+ * Timer functionality is provided by a timer service/daemon task. Many of the
+ * public FreeRTOS timer API functions send commands to the timer service task
+ * though a queue called the timer command queue. The timer command queue is
+ * private to the kernel itself and is not directly accessible to application
+ * code. The length of the timer command queue is set by the
+ * configTIMER_QUEUE_LENGTH configuration constant.
+ *
+ * xTimerStart() starts a timer that was previously created using the
+ * xTimerCreate() API function. If the timer had already been started and was
+ * already in the active state, then xTimerStart() has equivalent functionality
+ * to the xTimerReset() API function.
+ *
+ * Starting a timer ensures the timer is in the active state. If the timer
+ * is not stopped, deleted, or reset in the mean time, the callback function
+ * associated with the timer will get called 'n' ticks after xTimerStart() was
+ * called, where 'n' is the timers defined period.
+ *
+ * It is valid to call xTimerStart() before the scheduler has been started, but
+ * when this is done the timer will not actually start until the scheduler is
+ * started, and the timers expiry time will be relative to when the scheduler is
+ * started, not relative to when xTimerStart() was called.
+ *
+ * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart()
+ * to be available.
+ *
+ * @param xTimer The handle of the timer being started/restarted.
+ *
+ * @param xBlockTime Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the start command to be successfully
+ * sent to the timer command queue, should the queue already be full when
+ * xTimerStart() was called. xBlockTime is ignored if xTimerStart() is called
+ * before the scheduler is started.
+ *
+ * @return pdFAIL will be returned if the start command could not be sent to
+ * the timer command queue even after xBlockTime ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
+ * timer service/daemon task relative to other tasks in the system, although the
+ * timers expiry time is relative to when xTimerStart() is actually called. The
+ * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
+ * configuration constant.
+ *
+ * Example usage:
+ *
+ * See the xTimerCreate() API function example usage scenario.
+ *
+ */
+#define xTimerStart( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) )
+
+/**
+ * portBASE_TYPE xTimerStop( xTimerHandle xTimer, portTickType xBlockTime );
+ *
+ * Timer functionality is provided by a timer service/daemon task. Many of the
+ * public FreeRTOS timer API functions send commands to the timer service task
+ * though a queue called the timer command queue. The timer command queue is
+ * private to the kernel itself and is not directly accessible to application
+ * code. The length of the timer command queue is set by the
+ * configTIMER_QUEUE_LENGTH configuration constant.
+ *
+ * xTimerStop() stops a timer that was previously started using either of the
+ * The xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(),
+ * xTimerChangePeriod() or xTimerChangePeriodFromISR() API functions.
+ *
+ * Stopping a timer ensures the timer is not in the active state.
+ *
+ * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStop()
+ * to be available.
+ *
+ * @param xTimer The handle of the timer being stopped.
+ *
+ * @param xBlockTime Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the stop command to be successfully
+ * sent to the timer command queue, should the queue already be full when
+ * xTimerStop() was called. xBlockTime is ignored if xTimerStop() is called
+ * before the scheduler is started.
+ *
+ * @return pdFAIL will be returned if the stop command could not be sent to
+ * the timer command queue even after xBlockTime ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
+ * timer service/daemon task relative to other tasks in the system. The timer
+ * service/daemon task priority is set by the configTIMER_TASK_PRIORITY
+ * configuration constant.
+ *
+ * Example usage:
+ *
+ * See the xTimerCreate() API function example usage scenario.
+ *
+ */
+#define xTimerStop( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xBlockTime ) )
+
+/**
+ * portBASE_TYPE xTimerChangePeriod( xTimerHandle xTimer,
+ * portTickType xNewPeriod,
+ * portTickType xBlockTime );
+ *
+ * Timer functionality is provided by a timer service/daemon task. Many of the
+ * public FreeRTOS timer API functions send commands to the timer service task
+ * though a queue called the timer command queue. The timer command queue is
+ * private to the kernel itself and is not directly accessible to application
+ * code. The length of the timer command queue is set by the
+ * configTIMER_QUEUE_LENGTH configuration constant.
+ *
+ * xTimerChangePeriod() changes the period of a timer that was previously
+ * created using the xTimerCreate() API function.
+ *
+ * xTimerChangePeriod() can be called to change the period of an active or
+ * dormant state timer.
+ *
+ * The configUSE_TIMERS configuration constant must be set to 1 for
+ * xTimerChangePeriod() to be available.
+ *
+ * @param xTimer The handle of the timer that is having its period changed.
+ *
+ * @param xNewPeriod The new period for xTimer. Timer periods are specified in
+ * tick periods, so the constant portTICK_RATE_MS can be used to convert a time
+ * that has been specified in milliseconds. For example, if the timer must
+ * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively,
+ * if the timer must expire after 500ms, then xNewPeriod can be set to
+ * ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than
+ * or equal to 1000.
+ *
+ * @param xBlockTime Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the change period command to be
+ * successfully sent to the timer command queue, should the queue already be
+ * full when xTimerChangePeriod() was called. xBlockTime is ignored if
+ * xTimerChangePeriod() is called before the scheduler is started.
+ *
+ * @return pdFAIL will be returned if the change period command could not be
+ * sent to the timer command queue even after xBlockTime ticks had passed.
+ * pdPASS will be returned if the command was successfully sent to the timer
+ * command queue. When the command is actually processed will depend on the
+ * priority of the timer service/daemon task relative to other tasks in the
+ * system. The timer service/daemon task priority is set by the
+ * configTIMER_TASK_PRIORITY configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // This function assumes xTimer has already been created. If the timer
+ * // referenced by xTimer is already active when it is called, then the timer
+ * // is deleted. If the timer referenced by xTimer is not active when it is
+ * // called, then the period of the timer is set to 500ms and the timer is
+ * // started.
+ * void vAFunction( xTimerHandle xTimer )
+ * {
+ * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )"
+ * {
+ * // xTimer is already active - delete it.
+ * xTimerDelete( xTimer );
+ * }
+ * else
+ * {
+ * // xTimer is not active, change its period to 500ms. This will also
+ * // cause the timer to start. Block for a maximum of 100 ticks if the
+ * // change period command cannot immediately be sent to the timer
+ * // command queue.
+ * if( xTimerChangePeriod( xTimer, 500 / portTICK_RATE_MS, 100 ) == pdPASS )
+ * {
+ * // The command was successfully sent.
+ * }
+ * else
+ * {
+ * // The command could not be sent, even after waiting for 100 ticks
+ * // to pass. Take appropriate action here.
+ * }
+ * }
+ * }
+ * @endverbatim
+ */
+ #define xTimerChangePeriod( xTimer, xNewPeriod, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xBlockTime ) )
+
+/**
+ * portBASE_TYPE xTimerDelete( xTimerHandle xTimer, portTickType xBlockTime );
+ *
+ * Timer functionality is provided by a timer service/daemon task. Many of the
+ * public FreeRTOS timer API functions send commands to the timer service task
+ * though a queue called the timer command queue. The timer command queue is
+ * private to the kernel itself and is not directly accessible to application
+ * code. The length of the timer command queue is set by the
+ * configTIMER_QUEUE_LENGTH configuration constant.
+ *
+ * xTimerDelete() deletes a timer that was previously created using the
+ * xTimerCreate() API function.
+ *
+ * The configUSE_TIMERS configuration constant must be set to 1 for
+ * xTimerDelete() to be available.
+ *
+ * @param xTimer The handle of the timer being deleted.
+ *
+ * @param xBlockTime Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the delete command to be
+ * successfully sent to the timer command queue, should the queue already be
+ * full when xTimerDelete() was called. xBlockTime is ignored if xTimerDelete()
+ * is called before the scheduler is started.
+ *
+ * @return pdFAIL will be returned if the delete command could not be sent to
+ * the timer command queue even after xBlockTime ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
+ * timer service/daemon task relative to other tasks in the system. The timer
+ * service/daemon task priority is set by the configTIMER_TASK_PRIORITY
+ * configuration constant.
+ *
+ * Example usage:
+ *
+ * See the xTimerChangePeriod() API function example usage scenario.
+ */
+#define xTimerDelete( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xBlockTime ) )
+
+/**
+ * portBASE_TYPE xTimerReset( xTimerHandle xTimer, portTickType xBlockTime );
+ *
+ * Timer functionality is provided by a timer service/daemon task. Many of the
+ * public FreeRTOS timer API functions send commands to the timer service task
+ * though a queue called the timer command queue. The timer command queue is
+ * private to the kernel itself and is not directly accessible to application
+ * code. The length of the timer command queue is set by the
+ * configTIMER_QUEUE_LENGTH configuration constant.
+ *
+ * xTimerReset() re-starts a timer that was previously created using the
+ * xTimerCreate() API function. If the timer had already been started and was
+ * already in the active state, then xTimerReset() will cause the timer to
+ * re-evaluate its expiry time so that it is relative to when xTimerReset() was
+ * called. If the timer was in the dormant state then xTimerReset() has
+ * equivalent functionality to the xTimerStart() API function.
+ *
+ * Resetting a timer ensures the timer is in the active state. If the timer
+ * is not stopped, deleted, or reset in the mean time, the callback function
+ * associated with the timer will get called 'n' ticks after xTimerReset() was
+ * called, where 'n' is the timers defined period.
+ *
+ * It is valid to call xTimerReset() before the scheduler has been started, but
+ * when this is done the timer will not actually start until the scheduler is
+ * started, and the timers expiry time will be relative to when the scheduler is
+ * started, not relative to when xTimerReset() was called.
+ *
+ * The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset()
+ * to be available.
+ *
+ * @param xTimer The handle of the timer being reset/started/restarted.
+ *
+ * @param xBlockTime Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the reset command to be successfully
+ * sent to the timer command queue, should the queue already be full when
+ * xTimerReset() was called. xBlockTime is ignored if xTimerReset() is called
+ * before the scheduler is started.
+ *
+ * @return pdFAIL will be returned if the reset command could not be sent to
+ * the timer command queue even after xBlockTime ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
+ * timer service/daemon task relative to other tasks in the system, although the
+ * timers expiry time is relative to when xTimerStart() is actually called. The
+ * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
+ * configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass
+ * // without a key being pressed, then the LCD back-light is switched off. In
+ * // this case, the timer is a one-shot timer.
+ *
+ * xTimerHandle xBacklightTimer = NULL;
+ *
+ * // The callback function assigned to the one-shot timer. In this case the
+ * // parameter is not used.
+ * void vBacklightTimerCallback( xTimerHandle pxTimer )
+ * {
+ * // The timer expired, therefore 5 seconds must have passed since a key
+ * // was pressed. Switch off the LCD back-light.
+ * vSetBacklightState( BACKLIGHT_OFF );
+ * }
+ *
+ * // The key press event handler.
+ * void vKeyPressEventHandler( char cKey )
+ * {
+ * // Ensure the LCD back-light is on, then reset the timer that is
+ * // responsible for turning the back-light off after 5 seconds of
+ * // key inactivity. Wait 10 ticks for the command to be successfully sent
+ * // if it cannot be sent immediately.
+ * vSetBacklightState( BACKLIGHT_ON );
+ * if( xTimerReset( xBacklightTimer, 100 ) != pdPASS )
+ * {
+ * // The reset command was not executed successfully. Take appropriate
+ * // action here.
+ * }
+ *
+ * // Perform the rest of the key processing here.
+ * }
+ *
+ * void main( void )
+ * {
+ * long x;
+ *
+ * // Create then start the one-shot timer that is responsible for turning
+ * // the back-light off if no keys are pressed within a 5 second period.
+ * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel.
+ * ( 5000 / portTICK_RATE_MS), // The timer period in ticks.
+ * pdFALSE, // The timer is a one-shot timer.
+ * 0, // The id is not used by the callback so can take any value.
+ * vBacklightTimerCallback // The callback function that switches the LCD back-light off.
+ * );
+ *
+ * if( xBacklightTimer == NULL )
+ * {
+ * // The timer was not created.
+ * }
+ * else
+ * {
+ * // Start the timer. No block time is specified, and even if one was
+ * // it would be ignored because the scheduler has not yet been
+ * // started.
+ * if( xTimerStart( xBacklightTimer, 0 ) != pdPASS )
+ * {
+ * // The timer could not be set into the Active state.
+ * }
+ * }
+ *
+ * // ...
+ * // Create tasks here.
+ * // ...
+ *
+ * // Starting the scheduler will start the timer running as it has already
+ * // been set into the active state.
+ * xTaskStartScheduler();
+ *
+ * // Should not reach here.
+ * for( ;; );
+ * }
+ * @endverbatim
+ */
+#define xTimerReset( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) )
+
+/**
+ * portBASE_TYPE xTimerStartFromISR( xTimerHandle xTimer,
+ * portBASE_TYPE *pxHigherPriorityTaskWoken );
+ *
+ * A version of xTimerStart() that can be called from an interrupt service
+ * routine.
+ *
+ * @param xTimer The handle of the timer being started/restarted.
+ *
+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most
+ * of its time in the Blocked state, waiting for messages to arrive on the timer
+ * command queue. Calling xTimerStartFromISR() writes a message to the timer
+ * command queue, so has the potential to transition the timer service/daemon
+ * task out of the Blocked state. If calling xTimerStartFromISR() causes the
+ * timer service/daemon task to leave the Blocked state, and the timer service/
+ * daemon task has a priority equal to or greater than the currently executing
+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will
+ * get set to pdTRUE internally within the xTimerStartFromISR() function. If
+ * xTimerStartFromISR() sets this value to pdTRUE then a context switch should
+ * be performed before the interrupt exits.
+ *
+ * @return pdFAIL will be returned if the start command could not be sent to
+ * the timer command queue. pdPASS will be returned if the command was
+ * successfully sent to the timer command queue. When the command is actually
+ * processed will depend on the priority of the timer service/daemon task
+ * relative to other tasks in the system, although the timers expiry time is
+ * relative to when xTimerStartFromISR() is actually called. The timer service/daemon
+ * task priority is set by the configTIMER_TASK_PRIORITY configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // This scenario assumes xBacklightTimer has already been created. When a
+ * // key is pressed, an LCD back-light is switched on. If 5 seconds pass
+ * // without a key being pressed, then the LCD back-light is switched off. In
+ * // this case, the timer is a one-shot timer, and unlike the example given for
+ * // the xTimerReset() function, the key press event handler is an interrupt
+ * // service routine.
+ *
+ * // The callback function assigned to the one-shot timer. In this case the
+ * // parameter is not used.
+ * void vBacklightTimerCallback( xTimerHandle pxTimer )
+ * {
+ * // The timer expired, therefore 5 seconds must have passed since a key
+ * // was pressed. Switch off the LCD back-light.
+ * vSetBacklightState( BACKLIGHT_OFF );
+ * }
+ *
+ * // The key press interrupt service routine.
+ * void vKeyPressEventInterruptHandler( void )
+ * {
+ * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // Ensure the LCD back-light is on, then restart the timer that is
+ * // responsible for turning the back-light off after 5 seconds of
+ * // key inactivity. This is an interrupt service routine so can only
+ * // call FreeRTOS API functions that end in "FromISR".
+ * vSetBacklightState( BACKLIGHT_ON );
+ *
+ * // xTimerStartFromISR() or xTimerResetFromISR() could be called here
+ * // as both cause the timer to re-calculate its expiry time.
+ * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was
+ * // declared (in this function).
+ * if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS )
+ * {
+ * // The start command was not executed successfully. Take appropriate
+ * // action here.
+ * }
+ *
+ * // Perform the rest of the key processing here.
+ *
+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch
+ * // should be performed. The syntax required to perform a context switch
+ * // from inside an ISR varies from port to port, and from compiler to
+ * // compiler. Inspect the demos for the port you are using to find the
+ * // actual syntax required.
+ * if( xHigherPriorityTaskWoken != pdFALSE )
+ * {
+ * // Call the interrupt safe yield function here (actual function
+ * // depends on the FreeRTOS port being used.
+ * }
+ * }
+ * @endverbatim
+ */
+#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )
+
+/**
+ * portBASE_TYPE xTimerStopFromISR( xTimerHandle xTimer,
+ * portBASE_TYPE *pxHigherPriorityTaskWoken );
+ *
+ * A version of xTimerStop() that can be called from an interrupt service
+ * routine.
+ *
+ * @param xTimer The handle of the timer being stopped.
+ *
+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most
+ * of its time in the Blocked state, waiting for messages to arrive on the timer
+ * command queue. Calling xTimerStopFromISR() writes a message to the timer
+ * command queue, so has the potential to transition the timer service/daemon
+ * task out of the Blocked state. If calling xTimerStopFromISR() causes the
+ * timer service/daemon task to leave the Blocked state, and the timer service/
+ * daemon task has a priority equal to or greater than the currently executing
+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will
+ * get set to pdTRUE internally within the xTimerStopFromISR() function. If
+ * xTimerStopFromISR() sets this value to pdTRUE then a context switch should
+ * be performed before the interrupt exits.
+ *
+ * @return pdFAIL will be returned if the stop command could not be sent to
+ * the timer command queue. pdPASS will be returned if the command was
+ * successfully sent to the timer command queue. When the command is actually
+ * processed will depend on the priority of the timer service/daemon task
+ * relative to other tasks in the system. The timer service/daemon task
+ * priority is set by the configTIMER_TASK_PRIORITY configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // This scenario assumes xTimer has already been created and started. When
+ * // an interrupt occurs, the timer should be simply stopped.
+ *
+ * // The interrupt service routine that stops the timer.
+ * void vAnExampleInterruptServiceRoutine( void )
+ * {
+ * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // The interrupt has occurred - simply stop the timer.
+ * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined
+ * // (within this function). As this is an interrupt service routine, only
+ * // FreeRTOS API functions that end in "FromISR" can be used.
+ * if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS )
+ * {
+ * // The stop command was not executed successfully. Take appropriate
+ * // action here.
+ * }
+ *
+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch
+ * // should be performed. The syntax required to perform a context switch
+ * // from inside an ISR varies from port to port, and from compiler to
+ * // compiler. Inspect the demos for the port you are using to find the
+ * // actual syntax required.
+ * if( xHigherPriorityTaskWoken != pdFALSE )
+ * {
+ * // Call the interrupt safe yield function here (actual function
+ * // depends on the FreeRTOS port being used.
+ * }
+ * }
+ * @endverbatim
+ */
+#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0, ( pxHigherPriorityTaskWoken ), 0U )
+
+/**
+ * portBASE_TYPE xTimerChangePeriodFromISR( xTimerHandle xTimer,
+ * portTickType xNewPeriod,
+ * portBASE_TYPE *pxHigherPriorityTaskWoken );
+ *
+ * A version of xTimerChangePeriod() that can be called from an interrupt
+ * service routine.
+ *
+ * @param xTimer The handle of the timer that is having its period changed.
+ *
+ * @param xNewPeriod The new period for xTimer. Timer periods are specified in
+ * tick periods, so the constant portTICK_RATE_MS can be used to convert a time
+ * that has been specified in milliseconds. For example, if the timer must
+ * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively,
+ * if the timer must expire after 500ms, then xNewPeriod can be set to
+ * ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than
+ * or equal to 1000.
+ *
+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most
+ * of its time in the Blocked state, waiting for messages to arrive on the timer
+ * command queue. Calling xTimerChangePeriodFromISR() writes a message to the
+ * timer command queue, so has the potential to transition the timer service/
+ * daemon task out of the Blocked state. If calling xTimerChangePeriodFromISR()
+ * causes the timer service/daemon task to leave the Blocked state, and the
+ * timer service/daemon task has a priority equal to or greater than the
+ * currently executing task (the task that was interrupted), then
+ * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the
+ * xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets
+ * this value to pdTRUE then a context switch should be performed before the
+ * interrupt exits.
+ *
+ * @return pdFAIL will be returned if the command to change the timers period
+ * could not be sent to the timer command queue. pdPASS will be returned if the
+ * command was successfully sent to the timer command queue. When the command
+ * is actually processed will depend on the priority of the timer service/daemon
+ * task relative to other tasks in the system. The timer service/daemon task
+ * priority is set by the configTIMER_TASK_PRIORITY configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // This scenario assumes xTimer has already been created and started. When
+ * // an interrupt occurs, the period of xTimer should be changed to 500ms.
+ *
+ * // The interrupt service routine that changes the period of xTimer.
+ * void vAnExampleInterruptServiceRoutine( void )
+ * {
+ * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // The interrupt has occurred - change the period of xTimer to 500ms.
+ * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined
+ * // (within this function). As this is an interrupt service routine, only
+ * // FreeRTOS API functions that end in "FromISR" can be used.
+ * if( xTimerChangePeriodFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS )
+ * {
+ * // The command to change the timers period was not executed
+ * // successfully. Take appropriate action here.
+ * }
+ *
+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch
+ * // should be performed. The syntax required to perform a context switch
+ * // from inside an ISR varies from port to port, and from compiler to
+ * // compiler. Inspect the demos for the port you are using to find the
+ * // actual syntax required.
+ * if( xHigherPriorityTaskWoken != pdFALSE )
+ * {
+ * // Call the interrupt safe yield function here (actual function
+ * // depends on the FreeRTOS port being used.
+ * }
+ * }
+ * @endverbatim
+ */
+#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U )
+
+/**
+ * portBASE_TYPE xTimerResetFromISR( xTimerHandle xTimer,
+ * portBASE_TYPE *pxHigherPriorityTaskWoken );
+ *
+ * A version of xTimerReset() that can be called from an interrupt service
+ * routine.
+ *
+ * @param xTimer The handle of the timer that is to be started, reset, or
+ * restarted.
+ *
+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most
+ * of its time in the Blocked state, waiting for messages to arrive on the timer
+ * command queue. Calling xTimerResetFromISR() writes a message to the timer
+ * command queue, so has the potential to transition the timer service/daemon
+ * task out of the Blocked state. If calling xTimerResetFromISR() causes the
+ * timer service/daemon task to leave the Blocked state, and the timer service/
+ * daemon task has a priority equal to or greater than the currently executing
+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will
+ * get set to pdTRUE internally within the xTimerResetFromISR() function. If
+ * xTimerResetFromISR() sets this value to pdTRUE then a context switch should
+ * be performed before the interrupt exits.
+ *
+ * @return pdFAIL will be returned if the reset command could not be sent to
+ * the timer command queue. pdPASS will be returned if the command was
+ * successfully sent to the timer command queue. When the command is actually
+ * processed will depend on the priority of the timer service/daemon task
+ * relative to other tasks in the system, although the timers expiry time is
+ * relative to when xTimerResetFromISR() is actually called. The timer service/daemon
+ * task priority is set by the configTIMER_TASK_PRIORITY configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // This scenario assumes xBacklightTimer has already been created. When a
+ * // key is pressed, an LCD back-light is switched on. If 5 seconds pass
+ * // without a key being pressed, then the LCD back-light is switched off. In
+ * // this case, the timer is a one-shot timer, and unlike the example given for
+ * // the xTimerReset() function, the key press event handler is an interrupt
+ * // service routine.
+ *
+ * // The callback function assigned to the one-shot timer. In this case the
+ * // parameter is not used.
+ * void vBacklightTimerCallback( xTimerHandle pxTimer )
+ * {
+ * // The timer expired, therefore 5 seconds must have passed since a key
+ * // was pressed. Switch off the LCD back-light.
+ * vSetBacklightState( BACKLIGHT_OFF );
+ * }
+ *
+ * // The key press interrupt service routine.
+ * void vKeyPressEventInterruptHandler( void )
+ * {
+ * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // Ensure the LCD back-light is on, then reset the timer that is
+ * // responsible for turning the back-light off after 5 seconds of
+ * // key inactivity. This is an interrupt service routine so can only
+ * // call FreeRTOS API functions that end in "FromISR".
+ * vSetBacklightState( BACKLIGHT_ON );
+ *
+ * // xTimerStartFromISR() or xTimerResetFromISR() could be called here
+ * // as both cause the timer to re-calculate its expiry time.
+ * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was
+ * // declared (in this function).
+ * if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS )
+ * {
+ * // The reset command was not executed successfully. Take appropriate
+ * // action here.
+ * }
+ *
+ * // Perform the rest of the key processing here.
+ *
+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch
+ * // should be performed. The syntax required to perform a context switch
+ * // from inside an ISR varies from port to port, and from compiler to
+ * // compiler. Inspect the demos for the port you are using to find the
+ * // actual syntax required.
+ * if( xHigherPriorityTaskWoken != pdFALSE )
+ * {
+ * // Call the interrupt safe yield function here (actual function
+ * // depends on the FreeRTOS port being used.
+ * }
+ * }
+ * @endverbatim
+ */
+#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )
+
+/*
+ * Functions beyond this part are not part of the public API and are intended
+ * for use by the kernel only.
+ */
+portBASE_TYPE xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION;
+portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* TIMERS_H */
+
+
+
diff --git a/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.c b/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.c
new file mode 100644
index 0000000..9b0a3c6
--- /dev/null
+++ b/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.c
@@ -0,0 +1,94 @@
+/*
+ * @brief Common FreeRTOS functions shared among platforms
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2012
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "FreeRTOSCommonHooks.h"
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Delay for the specified number of milliSeconds */
+void FreeRTOSDelay(uint32_t ms)
+{
+ portTickType xDelayTime;
+
+ xDelayTime = xTaskGetTickCount();
+ vTaskDelayUntil(&xDelayTime, ms);
+}
+
+/* FreeRTOS malloc fail hook */
+void vApplicationMallocFailedHook(void)
+{
+ DEBUGSTR("DIE:ERROR:FreeRTOS: Malloc Failure!\r\n");
+ taskDISABLE_INTERRUPTS();
+ for (;; ) {}
+}
+
+/* FreeRTOS application idle hook */
+void vApplicationIdleHook(void)
+{
+ /* Best to sleep here until next systick */
+ __WFI();
+}
+
+/* FreeRTOS stack overflow hook */
+void vApplicationStackOverflowHook(xTaskHandle pxTask, signed char *pcTaskName)
+{
+ (void) pxTask;
+ (void) pcTaskName;
+
+ DEBUGOUT("DIE:ERROR:FreeRTOS: Stack overflow in task %s\r\n", pcTaskName);
+ /* Run time stack overflow checking is performed if
+ configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
+ function is called if a stack overflow is detected. */
+ taskDISABLE_INTERRUPTS();
+ for (;; ) {}
+}
+
+/* FreeRTOS application tick hook */
+void vApplicationTickHook(void)
+{}
diff --git a/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.h b/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.h
new file mode 100644
index 0000000..3136682
--- /dev/null
+++ b/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.h
@@ -0,0 +1,81 @@
+/*
+ * @brief Common FreeRTOS functions shared among platforms
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2012
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __FREERTOSCOMMONHOOKS_H_
+#define __FREERTOSCOMMONHOOKS_H_
+
+/** @ingroup FreeRTOS_COMMON
+ * @{
+ */
+
+/**
+ * @brief Delay for the specified number of milliSeconds
+ * @param ms : Delay in milliSeconds
+ * @return Nothing
+ * @note Delays the specified number of milliSeoconds using a task delay
+ */
+void FreeRTOSDelay(uint32_t ms);
+
+/**
+ * @brief FreeRTOS malloc fail hook
+ * @return Nothing
+ * @note This function is alled when a malloc fails to allocate data.
+ */
+void vApplicationMallocFailedHook(void);
+
+/**
+ * @brief FreeRTOS application idle hook
+ * @return Nothing
+ * @note Calls ARM Wait for Interrupt function to idle core
+ */
+void vApplicationIdleHook(void);
+
+/**
+ * @brief FreeRTOS stack overflow hook
+ * @param pxTask : Task handle that overflowed stack
+ * @param pcTaskName : Task name that overflowed stack
+ * @return Nothing
+ * @note This function is alled when a stack overflow occurs.
+ */
+void vApplicationStackOverflowHook(xTaskHandle pxTask, signed char *pcTaskName);
+
+/**
+ * @brief FreeRTOS application tick hook
+ * @return Nothing
+ * @note This just returns to the caller.
+ */
+void vApplicationTickHook(void);
+
+/**
+ * @}
+ */
+
+#endif /* __FREERTOSCOMMONHOOKS_H_ */
diff --git a/source/freertos_blinky/freertos/src/heap_3.c b/source/freertos_blinky/freertos/src/heap_3.c
new file mode 100644
index 0000000..f6d2537
--- /dev/null
+++ b/source/freertos_blinky/freertos/src/heap_3.c
@@ -0,0 +1,131 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+/*
+ * Implementation of pvPortMalloc() and vPortFree() that relies on the
+ * compilers own malloc() and free() implementations.
+ *
+ * This file can only be used if the linker is configured to to generate
+ * a heap memory area.
+ *
+ * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the
+ * memory management pages of http://www.FreeRTOS.org for more information.
+ */
+
+#include
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers. That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/*-----------------------------------------------------------*/
+
+void *pvPortMalloc( size_t xWantedSize )
+{
+void *pvReturn;
+
+ vTaskSuspendAll();
+ {
+ pvReturn = malloc( xWantedSize );
+ traceMALLOC( pvReturn, xWantedSize );
+ }
+ xTaskResumeAll();
+
+ #if( configUSE_MALLOC_FAILED_HOOK == 1 )
+ {
+ if( pvReturn == NULL )
+ {
+ extern void vApplicationMallocFailedHook( void );
+ vApplicationMallocFailedHook();
+ }
+ }
+ #endif
+
+ return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void *pv )
+{
+ if( pv )
+ {
+ vTaskSuspendAll();
+ {
+ free( pv );
+ traceFREE( pv, 0 );
+ }
+ xTaskResumeAll();
+ }
+}
+
+
+
diff --git a/source/freertos_blinky/freertos/src/list.c b/source/freertos_blinky/freertos/src/list.c
new file mode 100644
index 0000000..9c22dbc
--- /dev/null
+++ b/source/freertos_blinky/freertos/src/list.c
@@ -0,0 +1,204 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+#include
+#include "FreeRTOS.h"
+#include "list.h"
+
+/*-----------------------------------------------------------
+ * PUBLIC LIST API documented in list.h
+ *----------------------------------------------------------*/
+
+void vListInitialise( xList * const pxList )
+{
+ /* The list structure contains a list item which is used to mark the
+ end of the list. To initialise the list the list end is inserted
+ as the only list entry. */
+ pxList->pxIndex = ( xListItem * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
+
+ /* The list end value is the highest possible value in the list to
+ ensure it remains at the end of the list. */
+ pxList->xListEnd.xItemValue = portMAX_DELAY;
+
+ /* The list end next and previous pointers point to itself so we know
+ when the list is empty. */
+ pxList->xListEnd.pxNext = ( xListItem * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
+ pxList->xListEnd.pxPrevious = ( xListItem * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
+
+ pxList->uxNumberOfItems = ( unsigned portBASE_TYPE ) 0U;
+}
+/*-----------------------------------------------------------*/
+
+void vListInitialiseItem( xListItem * const pxItem )
+{
+ /* Make sure the list item is not recorded as being on a list. */
+ pxItem->pvContainer = NULL;
+}
+/*-----------------------------------------------------------*/
+
+void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem )
+{
+xListItem * pxIndex;
+
+ /* Insert a new list item into pxList, but rather than sort the list,
+ makes the new list item the last item to be removed by a call to
+ pvListGetOwnerOfNextEntry. */
+ pxIndex = pxList->pxIndex;
+
+ pxNewListItem->pxNext = pxIndex;
+ pxNewListItem->pxPrevious = pxIndex->pxPrevious;
+ pxIndex->pxPrevious->pxNext = pxNewListItem;
+ pxIndex->pxPrevious = pxNewListItem;
+
+ /* Remember which list the item is in. */
+ pxNewListItem->pvContainer = ( void * ) pxList;
+
+ ( pxList->uxNumberOfItems )++;
+}
+/*-----------------------------------------------------------*/
+
+void vListInsert( xList * const pxList, xListItem * const pxNewListItem )
+{
+xListItem *pxIterator;
+portTickType xValueOfInsertion;
+
+ /* Insert the new list item into the list, sorted in ulListItem order. */
+ xValueOfInsertion = pxNewListItem->xItemValue;
+
+ /* If the list already contains a list item with the same item value then
+ the new list item should be placed after it. This ensures that TCB's which
+ are stored in ready lists (all of which have the same ulListItem value)
+ get an equal share of the CPU. However, if the xItemValue is the same as
+ the back marker the iteration loop below will not end. This means we need
+ to guard against this by checking the value first and modifying the
+ algorithm slightly if necessary. */
+ if( xValueOfInsertion == portMAX_DELAY )
+ {
+ pxIterator = pxList->xListEnd.pxPrevious;
+ }
+ else
+ {
+ /* *** NOTE ***********************************************************
+ If you find your application is crashing here then likely causes are:
+ 1) Stack overflow -
+ see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
+ 2) Incorrect interrupt priority assignment, especially on Cortex-M3
+ parts where numerically high priority values denote low actual
+ interrupt priories, which can seem counter intuitive. See
+ configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html
+ 3) Calling an API function from within a critical section or when
+ the scheduler is suspended, or calling an API function that does
+ not end in "FromISR" from an interrupt.
+ 4) Using a queue or semaphore before it has been initialised or
+ before the scheduler has been started (are interrupts firing
+ before vTaskStartScheduler() has been called?).
+ See http://www.freertos.org/FAQHelp.html for more tips.
+ **********************************************************************/
+
+ for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
+ {
+ /* There is nothing to do here, we are just iterating to the
+ wanted insertion position. */
+ }
+ }
+
+ pxNewListItem->pxNext = pxIterator->pxNext;
+ pxNewListItem->pxNext->pxPrevious = pxNewListItem;
+ pxNewListItem->pxPrevious = pxIterator;
+ pxIterator->pxNext = pxNewListItem;
+
+ /* Remember which list the item is in. This allows fast removal of the
+ item later. */
+ pxNewListItem->pvContainer = ( void * ) pxList;
+
+ ( pxList->uxNumberOfItems )++;
+}
+/*-----------------------------------------------------------*/
+
+unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove )
+{
+xList * pxList;
+
+ pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
+ pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
+
+ /* The list item knows which list it is in. Obtain the list from the list
+ item. */
+ pxList = ( xList * ) pxItemToRemove->pvContainer;
+
+ /* Make sure the index is left pointing to a valid item. */
+ if( pxList->pxIndex == pxItemToRemove )
+ {
+ pxList->pxIndex = pxItemToRemove->pxPrevious;
+ }
+
+ pxItemToRemove->pvContainer = NULL;
+ ( pxList->uxNumberOfItems )--;
+
+ return pxList->uxNumberOfItems;
+}
+/*-----------------------------------------------------------*/
+
diff --git a/source/freertos_blinky/freertos/src/port.c b/source/freertos_blinky/freertos/src/port.c
new file mode 100644
index 0000000..de10b9e
--- /dev/null
+++ b/source/freertos_blinky/freertos/src/port.c
@@ -0,0 +1,366 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/*-----------------------------------------------------------
+ * Implementation of functions defined in portable.h for the ARM CM0 port.
+ *----------------------------------------------------------*/
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* Constants required to manipulate the NVIC. */
+#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 )
+#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 )
+#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 )
+#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 )
+#define portNVIC_SYSTICK_CLK 0x00000004
+#define portNVIC_SYSTICK_INT 0x00000002
+#define portNVIC_SYSTICK_ENABLE 0x00000001
+#define portNVIC_PENDSVSET 0x10000000
+#define portMIN_INTERRUPT_PRIORITY ( 255UL )
+#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
+#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
+
+/* Constants required to set up the initial stack. */
+#define portINITIAL_XPSR ( 0x01000000 )
+
+/* Let the user override the pre-loading of the initial LR with the address of
+prvTaskExitError() in case is messes up unwinding of the stack in the
+debugger. */
+#ifdef configTASK_RETURN_ADDRESS
+ #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
+#else
+ #define portTASK_RETURN_ADDRESS prvTaskExitError
+#endif
+
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
+
+/*
+ * Setup the timer to generate the tick interrupts.
+ */
+static void prvSetupTimerInterrupt( void );
+
+/*
+ * Exception handlers.
+ */
+void xPortPendSVHandler( void ) __attribute__ (( naked ));
+void xPortSysTickHandler( void );
+void vPortSVCHandler( void ) __attribute__ (( naked ));
+
+/*
+ * Start first task is a separate function so it can be tested in isolation.
+ */
+static void vPortStartFirstTask( void ) __attribute__ (( naked ));
+
+/*
+ * Used to catch tasks that attempt to return from their implementing function.
+ */
+static void prvTaskExitError( void );
+
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
+{
+ /* Simulate the stack frame as it would be created by a context switch
+ interrupt. */
+ pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
+ pxTopOfStack--;
+ *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
+ pxTopOfStack--;
+ *pxTopOfStack = ( portSTACK_TYPE ) portTASK_RETURN_ADDRESS; /* LR */
+ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+ *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
+ pxTopOfStack -= 8; /* R11..R4. */
+
+ return pxTopOfStack;
+}
+/*-----------------------------------------------------------*/
+
+static void prvTaskExitError( void )
+{
+ /* A function that implements a task must not exit or attempt to return to
+ its caller as there is nothing to return to. If a task wants to exit it
+ should instead call vTaskDelete( NULL ).
+
+ Artificially force an assert() to be triggered if configASSERT() is
+ defined, then stop here so application writers can catch the error. */
+ configASSERT( uxCriticalNesting == ~0UL );
+ portDISABLE_INTERRUPTS();
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+void vPortSVCHandler( void )
+{
+ __asm volatile (
+ " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
+ " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
+ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
+ " add r0, r0, #16 \n" /* Move to the high registers. */
+ " ldmia r0!, {r4-r7} \n" /* Pop the high registers. */
+ " mov r8, r4 \n"
+ " mov r9, r5 \n"
+ " mov r10, r6 \n"
+ " mov r11, r7 \n"
+ " \n"
+ " msr psp, r0 \n" /* Remember the new top of stack for the task. */
+ " \n"
+ " sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */
+ " ldmia r0!, {r4-r7} \n" /* Pop low registers. */
+ " mov r1, r14 \n" /* OR R14 with 0x0d. */
+ " movs r0, #0x0d \n"
+ " orr r1, r0 \n"
+ " bx r1 \n"
+ " \n"
+ " .align 2 \n"
+ "pxCurrentTCBConst2: .word pxCurrentTCB \n"
+ );
+}
+/*-----------------------------------------------------------*/
+
+void vPortStartFirstTask( void )
+{
+ /* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector
+ table offset register that can be used to locate the initial stack value.
+ Not all M0 parts have the application vector table at address 0. */
+ __asm volatile(
+ " cpsie i \n" /* Globally enable interrupts. */
+ " svc 0 \n" /* System call to start first task. */
+ " nop \n"
+ );
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+portBASE_TYPE xPortStartScheduler( void )
+{
+ /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */
+ *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;
+ *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;
+
+ /* Start the timer that generates the tick ISR. Interrupts are disabled
+ here already. */
+ prvSetupTimerInterrupt();
+
+ /* Initialise the critical nesting count ready for the first task. */
+ uxCriticalNesting = 0;
+
+ /* Start the first task. */
+ vPortStartFirstTask();
+
+ /* Should not get here! */
+ return 0;
+}
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler( void )
+{
+ /* It is unlikely that the CM0 port will require this function as there
+ is nothing to return to. */
+}
+/*-----------------------------------------------------------*/
+
+void vPortYield( void )
+{
+ /* Set a PendSV to request a context switch. */
+ *( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
+
+ /* Barriers are normally not required but do ensure the code is completely
+ within the specified behaviour for the architecture. */
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+}
+/*-----------------------------------------------------------*/
+
+void vPortEnterCritical( void )
+{
+ portDISABLE_INTERRUPTS();
+ uxCriticalNesting++;
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+}
+/*-----------------------------------------------------------*/
+
+void vPortExitCritical( void )
+{
+ uxCriticalNesting--;
+ if( uxCriticalNesting == 0 )
+ {
+ portENABLE_INTERRUPTS();
+ }
+}
+/*-----------------------------------------------------------*/
+
+unsigned long ulSetInterruptMaskFromISR( void )
+{
+ __asm volatile(
+ " mrs r0, PRIMASK \n"
+ " cpsid i \n"
+ " bx lr "
+ );
+
+ /* To avoid compiler warnings. This line will never be reached. */
+ return 0;
+}
+/*-----------------------------------------------------------*/
+
+void vClearInterruptMaskFromISR( unsigned long ulMask )
+{
+ __asm volatile(
+ " msr PRIMASK, r0 \n"
+ " bx lr "
+ );
+
+ /* Just to avoid compiler warning. */
+ ( void ) ulMask;
+}
+/*-----------------------------------------------------------*/
+
+void xPortPendSVHandler( void )
+{
+ /* This is a naked function. */
+
+ __asm volatile
+ (
+ " mrs r0, psp \n"
+ " \n"
+ " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
+ " ldr r2, [r3] \n"
+ " \n"
+ " sub r0, r0, #32 \n" /* Make space for the remaining low registers. */
+ " str r0, [r2] \n" /* Save the new top of stack. */
+ " stmia r0!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */
+ " mov r4, r8 \n" /* Store the high registers. */
+ " mov r5, r9 \n"
+ " mov r6, r10 \n"
+ " mov r7, r11 \n"
+ " stmia r0!, {r4-r7} \n"
+ " \n"
+ " push {r3, r14} \n"
+ " cpsid i \n"
+ " bl vTaskSwitchContext \n"
+ " cpsie i \n"
+ " pop {r2, r3} \n" /* lr goes in r3. r2 now holds tcb pointer. */
+ " \n"
+ " ldr r1, [r2] \n"
+ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
+ " add r0, r0, #16 \n" /* Move to the high registers. */
+ " ldmia r0!, {r4-r7} \n" /* Pop the high registers. */
+ " mov r8, r4 \n"
+ " mov r9, r5 \n"
+ " mov r10, r6 \n"
+ " mov r11, r7 \n"
+ " \n"
+ " msr psp, r0 \n" /* Remember the new top of stack for the task. */
+ " \n"
+ " sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */
+ " ldmia r0!, {r4-r7} \n" /* Pop low registers. */
+ " \n"
+ " bx r3 \n"
+ " \n"
+ " .align 2 \n"
+ "pxCurrentTCBConst: .word pxCurrentTCB "
+ );
+}
+/*-----------------------------------------------------------*/
+
+void xPortSysTickHandler( void )
+{
+unsigned long ulPreviousMask;
+
+ ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ /* Increment the RTOS tick. */
+ if( xTaskIncrementTick() != pdFALSE )
+ {
+ /* Pend a context switch. */
+ *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Setup the systick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+void prvSetupTimerInterrupt( void )
+{
+ /* Configure SysTick to interrupt at the requested rate. */
+ *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
+ *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
+}
+/*-----------------------------------------------------------*/
+
diff --git a/source/freertos_blinky/freertos/src/queue.c b/source/freertos_blinky/freertos/src/queue.c
new file mode 100644
index 0000000..75fc158
--- /dev/null
+++ b/source/freertos_blinky/freertos/src/queue.c
@@ -0,0 +1,2084 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+#include
+#include
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers. That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+#if ( configUSE_CO_ROUTINES == 1 )
+ #include "croutine.h"
+#endif
+
+/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
+MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
+header files above, but not in this file, in order to generate the correct
+privileged Vs unprivileged linkage and placement. */
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
+
+
+/* Constants used with the cRxLock and xTxLock structure members. */
+#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
+#define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
+
+/* When the xQUEUE structure is used to represent a base queue its pcHead and
+pcTail members are used as pointers into the queue storage area. When the
+xQUEUE structure is used to represent a mutex pcHead and pcTail pointers are
+not necessary, and the pcHead pointer is set to NULL to indicate that the
+pcTail pointer actually points to the mutex holder (if any). Map alternative
+names to the pcHead and pcTail structure members to ensure the readability of
+the code is maintained despite this dual use of two structure members. An
+alternative implementation would be to use a union, but use of a union is
+against the coding standard (although an exception to the standard has been
+permitted where the dual use also significantly changes the type of the
+structure member). */
+#define pxMutexHolder pcTail
+#define uxQueueType pcHead
+#define queueQUEUE_IS_MUTEX NULL
+
+/* Semaphores do not actually store or copy data, so have an item size of
+zero. */
+#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )
+#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U )
+
+
+/*
+ * Definition of the queue used by the scheduler.
+ * Items are queued by copy, not reference.
+ */
+typedef struct QueueDefinition
+{
+ signed char *pcHead; /*< Points to the beginning of the queue storage area. */
+ signed char *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
+
+ signed char *pcWriteTo; /*< Points to the free next place in the storage area. */
+
+ union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */
+ {
+ signed char *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */
+ unsigned portBASE_TYPE uxRecursiveCallCount;/*< Maintains a count of the numebr of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */
+ } u;
+
+ xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
+ xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
+
+ volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
+ unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
+ unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
+
+ volatile signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
+ volatile signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ unsigned char ucQueueNumber;
+ unsigned char ucQueueType;
+ #endif
+
+ #if ( configUSE_QUEUE_SETS == 1 )
+ struct QueueDefinition *pxQueueSetContainer;
+ #endif
+
+} xQUEUE;
+/*-----------------------------------------------------------*/
+
+/*
+ * The queue registry is just a means for kernel aware debuggers to locate
+ * queue structures. It has no other purpose so is an optional component.
+ */
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+
+ /* The type stored within the queue registry array. This allows a name
+ to be assigned to each queue making kernel aware debugging a little
+ more user friendly. */
+ typedef struct QUEUE_REGISTRY_ITEM
+ {
+ signed char *pcQueueName;
+ xQueueHandle xHandle;
+ } xQueueRegistryItem;
+
+ /* The queue registry is simply an array of xQueueRegistryItem structures.
+ The pcQueueName member of a structure being NULL is indicative of the
+ array position being vacant. */
+ xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
+
+#endif /* configQUEUE_REGISTRY_SIZE */
+
+/*
+ * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
+ * prevent an ISR from adding or removing items to the queue, but does prevent
+ * an ISR from removing tasks from the queue event lists. If an ISR finds a
+ * queue is locked it will instead increment the appropriate queue lock count
+ * to indicate that a task may require unblocking. When the queue in unlocked
+ * these lock counts are inspected, and the appropriate action taken.
+ */
+static void prvUnlockQueue( xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * Uses a critical section to determine if there is any data in a queue.
+ *
+ * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
+ */
+static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * Uses a critical section to determine if there is any space in a queue.
+ *
+ * @return pdTRUE if there is no space, otherwise pdFALSE;
+ */
+static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * Copies an item into the queue, either at the front of the queue or the
+ * back of the queue.
+ */
+static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
+
+/*
+ * Copies an item out of a queue.
+ */
+static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer ) PRIVILEGED_FUNCTION;
+
+#if ( configUSE_QUEUE_SETS == 1 )
+ /*
+ * Checks to see if a queue is a member of a queue set, and if so, notifies
+ * the queue set that the queue contains data.
+ */
+ static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
+#endif
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Macro to mark a queue as locked. Locking a queue prevents an ISR from
+ * accessing the queue event lists.
+ */
+#define prvLockQueue( pxQueue ) \
+ taskENTER_CRITICAL(); \
+ { \
+ if( ( pxQueue )->xRxLock == queueUNLOCKED ) \
+ { \
+ ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \
+ } \
+ if( ( pxQueue )->xTxLock == queueUNLOCKED ) \
+ { \
+ ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \
+ } \
+ } \
+ taskEXIT_CRITICAL()
+/*-----------------------------------------------------------*/
+
+portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue )
+{
+xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ configASSERT( pxQueue );
+
+ taskENTER_CRITICAL();
+ {
+ pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );
+ pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
+ pxQueue->pcWriteTo = pxQueue->pcHead;
+ pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize );
+ pxQueue->xRxLock = queueUNLOCKED;
+ pxQueue->xTxLock = queueUNLOCKED;
+
+ if( xNewQueue == pdFALSE )
+ {
+ /* If there are tasks blocked waiting to read from the queue, then
+ the tasks will remain blocked as after this function exits the queue
+ will still be empty. If there are tasks blocked waiting to write to
+ the queue, then one should be unblocked as after this function exits
+ it will be possible to write to it. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ }
+ }
+ else
+ {
+ /* Ensure the event queues start in the correct state. */
+ vListInitialise( &( pxQueue->xTasksWaitingToSend ) );
+ vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ /* A value is returned for calling semantic consistency with previous
+ versions. */
+ return pdPASS;
+}
+/*-----------------------------------------------------------*/
+
+xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType )
+{
+xQUEUE *pxNewQueue;
+size_t xQueueSizeInBytes;
+xQueueHandle xReturn = NULL;
+
+ /* Remove compiler warnings about unused parameters should
+ configUSE_TRACE_FACILITY not be set to 1. */
+ ( void ) ucQueueType;
+
+ /* Allocate the new queue structure. */
+ if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
+ {
+ pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
+ if( pxNewQueue != NULL )
+ {
+ /* Create the list of pointers to queue items. The queue is one byte
+ longer than asked for to make wrap checking easier/faster. */
+ xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
+ if( pxNewQueue->pcHead != NULL )
+ {
+ /* Initialise the queue members as described above where the
+ queue type is defined. */
+ pxNewQueue->uxLength = uxQueueLength;
+ pxNewQueue->uxItemSize = uxItemSize;
+ ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ pxNewQueue->ucQueueType = ucQueueType;
+ }
+ #endif /* configUSE_TRACE_FACILITY */
+
+ #if( configUSE_QUEUE_SETS == 1 )
+ {
+ pxNewQueue->pxQueueSetContainer = NULL;
+ }
+ #endif /* configUSE_QUEUE_SETS */
+
+ traceQUEUE_CREATE( pxNewQueue );
+ xReturn = pxNewQueue;
+ }
+ else
+ {
+ traceQUEUE_CREATE_FAILED( ucQueueType );
+ vPortFree( pxNewQueue );
+ }
+ }
+ }
+
+ configASSERT( xReturn );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+ xQueueHandle xQueueCreateMutex( unsigned char ucQueueType )
+ {
+ xQUEUE *pxNewQueue;
+
+ /* Prevent compiler warnings about unused parameters if
+ configUSE_TRACE_FACILITY does not equal 1. */
+ ( void ) ucQueueType;
+
+ /* Allocate the new queue structure. */
+ pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
+ if( pxNewQueue != NULL )
+ {
+ /* Information required for priority inheritance. */
+ pxNewQueue->pxMutexHolder = NULL;
+ pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
+
+ /* Queues used as a mutex no data is actually copied into or out
+ of the queue. */
+ pxNewQueue->pcWriteTo = NULL;
+ pxNewQueue->u.pcReadFrom = NULL;
+
+ /* Each mutex has a length of 1 (like a binary semaphore) and
+ an item size of 0 as nothing is actually copied into or out
+ of the mutex. */
+ pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
+ pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;
+ pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;
+ pxNewQueue->xRxLock = queueUNLOCKED;
+ pxNewQueue->xTxLock = queueUNLOCKED;
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ pxNewQueue->ucQueueType = ucQueueType;
+ }
+ #endif
+
+ #if ( configUSE_QUEUE_SETS == 1 )
+ {
+ pxNewQueue->pxQueueSetContainer = NULL;
+ }
+ #endif
+
+ /* Ensure the event queues start with the correct state. */
+ vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
+ vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
+
+ traceCREATE_MUTEX( pxNewQueue );
+
+ /* Start with the semaphore in the expected state. */
+ ( void ) xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );
+ }
+ else
+ {
+ traceCREATE_MUTEX_FAILED();
+ }
+
+ configASSERT( pxNewQueue );
+ return pxNewQueue;
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
+
+ void* xQueueGetMutexHolder( xQueueHandle xSemaphore )
+ {
+ void *pxReturn;
+
+ /* This function is called by xSemaphoreGetMutexHolder(), and should not
+ be called directly. Note: This is is a good way of determining if the
+ calling task is the mutex holder, but not a good way of determining the
+ identity of the mutex holder, as the holder may change between the
+ following critical section exiting and the function returning. */
+ taskENTER_CRITICAL();
+ {
+ if( ( ( xQUEUE * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ pxReturn = ( void * ) ( ( xQUEUE * ) xSemaphore )->pxMutexHolder;
+ }
+ else
+ {
+ pxReturn = NULL;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return pxReturn;
+ }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_RECURSIVE_MUTEXES == 1 )
+
+ portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex )
+ {
+ portBASE_TYPE xReturn;
+ xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
+
+ configASSERT( pxMutex );
+
+ /* If this is the task that holds the mutex then pxMutexHolder will not
+ change outside of this task. If this task does not hold the mutex then
+ pxMutexHolder can never coincidentally equal the tasks handle, and as
+ this is the only condition we are interested in it does not matter if
+ pxMutexHolder is accessed simultaneously by another task. Therefore no
+ mutual exclusion is required to test the pxMutexHolder variable. */
+ if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as xTaskHandle is a typedef. */
+ {
+ traceGIVE_MUTEX_RECURSIVE( pxMutex );
+
+ /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
+ the task handle, therefore no underflow check is required. Also,
+ uxRecursiveCallCount is only modified by the mutex holder, and as
+ there can only be one, no mutual exclusion is required to modify the
+ uxRecursiveCallCount member. */
+ ( pxMutex->u.uxRecursiveCallCount )--;
+
+ /* Have we unwound the call count? */
+ if( pxMutex->u.uxRecursiveCallCount == ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* Return the mutex. This will automatically unblock any other
+ task that might be waiting to access the mutex. */
+ ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
+ }
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ /* We cannot give the mutex because we are not the holder. */
+ xReturn = pdFAIL;
+
+ traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_RECURSIVE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_RECURSIVE_MUTEXES == 1 )
+
+ portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime )
+ {
+ portBASE_TYPE xReturn;
+ xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
+
+ configASSERT( pxMutex );
+
+ /* Comments regarding mutual exclusion as per those within
+ xQueueGiveMutexRecursive(). */
+
+ traceTAKE_MUTEX_RECURSIVE( pxMutex );
+
+ if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
+ {
+ ( pxMutex->u.uxRecursiveCallCount )++;
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
+
+ /* pdPASS will only be returned if we successfully obtained the mutex,
+ we may have blocked to reach here. */
+ if( xReturn == pdPASS )
+ {
+ ( pxMutex->u.uxRecursiveCallCount )++;
+ }
+ else
+ {
+ traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
+ }
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_RECURSIVE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_COUNTING_SEMAPHORES == 1 )
+
+ xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
+ {
+ xQueueHandle xHandle;
+
+ xHandle = xQueueGenericCreate( uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
+
+ if( xHandle != NULL )
+ {
+ ( ( xQUEUE * ) xHandle )->uxMessagesWaiting = uxInitialCount;
+
+ traceCREATE_COUNTING_SEMAPHORE();
+ }
+ else
+ {
+ traceCREATE_COUNTING_SEMAPHORE_FAILED();
+ }
+
+ configASSERT( xHandle );
+ return xHandle;
+ }
+
+#endif /* configUSE_COUNTING_SEMAPHORES */
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
+{
+signed portBASE_TYPE xEntryTimeSet = pdFALSE;
+xTimeOutType xTimeOut;
+xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
+ configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
+
+ /* This function relaxes the coding standard somewhat to allow return
+ statements within the function itself. This is done in the interest
+ of execution time efficiency. */
+ for( ;; )
+ {
+ taskENTER_CRITICAL();
+ {
+ /* Is there room on the queue now? The running task must be
+ the highest priority task wanting to access the queue. If
+ the head item in the queue is to be overwritten then it does
+ not matter if the queue is full. */
+ if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
+ {
+ traceQUEUE_SEND( pxQueue );
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
+
+ #if ( configUSE_QUEUE_SETS == 1 )
+ {
+ if( pxQueue->pxQueueSetContainer != NULL )
+ {
+ if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
+ {
+ /* The queue is a member of a queue set, and posting
+ to the queue set caused a higher priority task to
+ unblock. A context switch is required. */
+ portYIELD_WITHIN_API();
+ }
+ }
+ else
+ {
+ /* If there was a task waiting for data to arrive on the
+ queue then unblock it now. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
+ {
+ /* The unblocked task has a priority higher than
+ our own so yield immediately. Yes it is ok to
+ do this from within the critical section - the
+ kernel takes care of that. */
+ portYIELD_WITHIN_API();
+ }
+ }
+ }
+ }
+ #else /* configUSE_QUEUE_SETS */
+ {
+ /* If there was a task waiting for data to arrive on the
+ queue then unblock it now. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
+ {
+ /* The unblocked task has a priority higher than
+ our own so yield immediately. Yes it is ok to do
+ this from within the critical section - the kernel
+ takes care of that. */
+ portYIELD_WITHIN_API();
+ }
+ }
+ }
+ #endif /* configUSE_QUEUE_SETS */
+
+ taskEXIT_CRITICAL();
+
+ /* Return to the original privilege level before exiting the
+ function. */
+ return pdPASS;
+ }
+ else
+ {
+ if( xTicksToWait == ( portTickType ) 0 )
+ {
+ /* The queue was full and no block time is specified (or
+ the block time has expired) so leave now. */
+ taskEXIT_CRITICAL();
+
+ /* Return to the original privilege level before exiting
+ the function. */
+ traceQUEUE_SEND_FAILED( pxQueue );
+ return errQUEUE_FULL;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ /* The queue was full and a block time was specified so
+ configure the timeout structure. */
+ vTaskSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
+ else
+ {
+ /* Entry time was already set. */
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ /* Interrupts and other tasks can send to and receive from the queue
+ now the critical section has been exited. */
+
+ vTaskSuspendAll();
+ prvLockQueue( pxQueue );
+
+ /* Update the timeout state to see if it has expired yet. */
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+ {
+ if( prvIsQueueFull( pxQueue ) != pdFALSE )
+ {
+ traceBLOCKING_ON_QUEUE_SEND( pxQueue );
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
+
+ /* Unlocking the queue means queue events can effect the
+ event list. It is possible that interrupts occurring now
+ remove this task from the event list again - but as the
+ scheduler is suspended the task will go onto the pending
+ ready last instead of the actual ready list. */
+ prvUnlockQueue( pxQueue );
+
+ /* Resuming the scheduler will move tasks from the pending
+ ready list into the ready list - so it is feasible that this
+ task is already in a ready list before it yields - in which
+ case the yield will not cause a context switch unless there
+ is also a higher priority task in the pending ready list. */
+ if( xTaskResumeAll() == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ }
+ else
+ {
+ /* Try again. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ }
+ }
+ else
+ {
+ /* The timeout has expired. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+
+ /* Return to the original privilege level before exiting the
+ function. */
+ traceQUEUE_SEND_FAILED( pxQueue );
+ return errQUEUE_FULL;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_ALTERNATIVE_API == 1 )
+
+ signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
+ {
+ signed portBASE_TYPE xEntryTimeSet = pdFALSE;
+ xTimeOutType xTimeOut;
+ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
+
+ for( ;; )
+ {
+ taskENTER_CRITICAL();
+ {
+ /* Is there room on the queue now? To be running we must be
+ the highest priority task wanting to access the queue. */
+ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
+ {
+ traceQUEUE_SEND( pxQueue );
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
+
+ /* If there was a task waiting for data to arrive on the
+ queue then unblock it now. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
+ {
+ /* The unblocked task has a priority higher than
+ our own so yield immediately. */
+ portYIELD_WITHIN_API();
+ }
+ }
+
+ taskEXIT_CRITICAL();
+ return pdPASS;
+ }
+ else
+ {
+ if( xTicksToWait == ( portTickType ) 0 )
+ {
+ taskEXIT_CRITICAL();
+ return errQUEUE_FULL;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ vTaskSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ taskENTER_CRITICAL();
+ {
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+ {
+ if( prvIsQueueFull( pxQueue ) != pdFALSE )
+ {
+ traceBLOCKING_ON_QUEUE_SEND( pxQueue );
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
+ portYIELD_WITHIN_API();
+ }
+ }
+ else
+ {
+ taskEXIT_CRITICAL();
+ traceQUEUE_SEND_FAILED( pxQueue );
+ return errQUEUE_FULL;
+ }
+ }
+ taskEXIT_CRITICAL();
+ }
+ }
+
+#endif /* configUSE_ALTERNATIVE_API */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_ALTERNATIVE_API == 1 )
+
+ signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
+ {
+ signed portBASE_TYPE xEntryTimeSet = pdFALSE;
+ xTimeOutType xTimeOut;
+ signed char *pcOriginalReadPosition;
+ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
+
+ for( ;; )
+ {
+ taskENTER_CRITICAL();
+ {
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* Remember our read position in case we are just peeking. */
+ pcOriginalReadPosition = pxQueue->u.pcReadFrom;
+
+ prvCopyDataFromQueue( pxQueue, pvBuffer );
+
+ if( xJustPeeking == pdFALSE )
+ {
+ traceQUEUE_RECEIVE( pxQueue );
+
+ /* Data is actually being removed (not just peeked). */
+ --( pxQueue->uxMessagesWaiting );
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ /* Record the information required to implement
+ priority inheritance should it become necessary. */
+ pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle();
+ }
+ }
+ #endif
+
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ }
+ }
+ else
+ {
+ traceQUEUE_PEEK( pxQueue );
+
+ /* We are not removing the data, so reset our read
+ pointer. */
+ pxQueue->u.pcReadFrom = pcOriginalReadPosition;
+
+ /* The data is being left in the queue, so see if there are
+ any other tasks waiting for the data. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ /* Tasks that are removed from the event list will get added to
+ the pending ready list as the scheduler is still suspended. */
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority than this task. */
+ portYIELD_WITHIN_API();
+ }
+ }
+
+ }
+
+ taskEXIT_CRITICAL();
+ return pdPASS;
+ }
+ else
+ {
+ if( xTicksToWait == ( portTickType ) 0 )
+ {
+ taskEXIT_CRITICAL();
+ traceQUEUE_RECEIVE_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ vTaskSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ taskENTER_CRITICAL();
+ {
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+ {
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+ {
+ traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ portENTER_CRITICAL();
+ {
+ vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
+ }
+ portEXIT_CRITICAL();
+ }
+ }
+ #endif
+
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+ portYIELD_WITHIN_API();
+ }
+ }
+ else
+ {
+ taskEXIT_CRITICAL();
+ traceQUEUE_RECEIVE_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ }
+ taskEXIT_CRITICAL();
+ }
+ }
+
+
+#endif /* configUSE_ALTERNATIVE_API */
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
+{
+signed portBASE_TYPE xReturn;
+unsigned portBASE_TYPE uxSavedInterruptStatus;
+xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
+ configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
+
+ /* RTOS ports that support interrupt nesting have the concept of a maximum
+ system call (or maximum API call) interrupt priority. Interrupts that are
+ above the maximum system call priority are keep permanently enabled, even
+ when the RTOS kernel is in a critical section, but cannot make any calls to
+ FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
+ then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ failure if a FreeRTOS API function is called from an interrupt that has been
+ assigned a priority above the configured maximum system call priority.
+ Only FreeRTOS functions that end in FromISR can be called from interrupts
+ that have been assigned a priority at or (logically) below the maximum
+ system call interrupt priority. FreeRTOS maintains a separate interrupt
+ safe API to ensure interrupt entry is as fast and as simple as possible.
+ More information (albeit Cortex-M specific) is provided on the following
+ link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ /* Similar to xQueueGenericSend, except we don't block if there is no room
+ in the queue. Also we don't directly wake a task that was blocked on a
+ queue read, instead we return a flag to say whether a context switch is
+ required or not (i.e. has a task with a higher priority than us been woken
+ by this post). */
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
+ {
+ traceQUEUE_SEND_FROM_ISR( pxQueue );
+
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
+
+ /* If the queue is locked we do not alter the event list. This will
+ be done when the queue is unlocked later. */
+ if( pxQueue->xTxLock == queueUNLOCKED )
+ {
+ #if ( configUSE_QUEUE_SETS == 1 )
+ {
+ if( pxQueue->pxQueueSetContainer != NULL )
+ {
+ if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
+ {
+ /* The queue is a member of a queue set, and posting
+ to the queue set caused a higher priority task to
+ unblock. A context switch is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ }
+ }
+ else
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority so record that a
+ context switch is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ }
+ }
+ }
+ }
+ #else /* configUSE_QUEUE_SETS */
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority so record that a
+ context switch is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ }
+ }
+ }
+ #endif /* configUSE_QUEUE_SETS */
+ }
+ else
+ {
+ /* Increment the lock count so the task that unlocks the queue
+ knows that data was posted while it was locked. */
+ ++( pxQueue->xTxLock );
+ }
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
+ xReturn = errQUEUE_FULL;
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
+{
+signed portBASE_TYPE xEntryTimeSet = pdFALSE;
+xTimeOutType xTimeOut;
+signed char *pcOriginalReadPosition;
+xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
+
+ /* This function relaxes the coding standard somewhat to allow return
+ statements within the function itself. This is done in the interest
+ of execution time efficiency. */
+
+ for( ;; )
+ {
+ taskENTER_CRITICAL();
+ {
+ /* Is there data in the queue now? To be running we must be
+ the highest priority task wanting to access the queue. */
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* Remember the read position in case the queue is only being
+ peeked. */
+ pcOriginalReadPosition = pxQueue->u.pcReadFrom;
+
+ prvCopyDataFromQueue( pxQueue, pvBuffer );
+
+ if( xJustPeeking == pdFALSE )
+ {
+ traceQUEUE_RECEIVE( pxQueue );
+
+ /* Actually removing data, not just peeking. */
+ --( pxQueue->uxMessagesWaiting );
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ /* Record the information required to implement
+ priority inheritance should it become necessary. */
+ pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
+ }
+ }
+ #endif
+
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ }
+ }
+ else
+ {
+ traceQUEUE_PEEK( pxQueue );
+
+ /* The data is not being removed, so reset the read
+ pointer. */
+ pxQueue->u.pcReadFrom = pcOriginalReadPosition;
+
+ /* The data is being left in the queue, so see if there are
+ any other tasks waiting for the data. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ /* Tasks that are removed from the event list will get added to
+ the pending ready list as the scheduler is still suspended. */
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority than this task. */
+ portYIELD_WITHIN_API();
+ }
+ }
+ }
+
+ taskEXIT_CRITICAL();
+ return pdPASS;
+ }
+ else
+ {
+ if( xTicksToWait == ( portTickType ) 0 )
+ {
+ /* The queue was empty and no block time is specified (or
+ the block time has expired) so leave now. */
+ taskEXIT_CRITICAL();
+ traceQUEUE_RECEIVE_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ /* The queue was empty and a block time was specified so
+ configure the timeout structure. */
+ vTaskSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
+ else
+ {
+ /* Entry time was already set. */
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ /* Interrupts and other tasks can send to and receive from the queue
+ now the critical section has been exited. */
+
+ vTaskSuspendAll();
+ prvLockQueue( pxQueue );
+
+ /* Update the timeout state to see if it has expired yet. */
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+ {
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+ {
+ traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ portENTER_CRITICAL();
+ {
+ vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
+ }
+ portEXIT_CRITICAL();
+ }
+ }
+ #endif
+
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+ prvUnlockQueue( pxQueue );
+ if( xTaskResumeAll() == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ }
+ else
+ {
+ /* Try again. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ }
+ }
+ else
+ {
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ traceQUEUE_RECEIVE_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, const void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken )
+{
+signed portBASE_TYPE xReturn;
+unsigned portBASE_TYPE uxSavedInterruptStatus;
+xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
+
+ /* RTOS ports that support interrupt nesting have the concept of a maximum
+ system call (or maximum API call) interrupt priority. Interrupts that are
+ above the maximum system call priority are keep permanently enabled, even
+ when the RTOS kernel is in a critical section, but cannot make any calls to
+ FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
+ then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ failure if a FreeRTOS API function is called from an interrupt that has been
+ assigned a priority above the configured maximum system call priority.
+ Only FreeRTOS functions that end in FromISR can be called from interrupts
+ that have been assigned a priority at or (logically) below the maximum
+ system call interrupt priority. FreeRTOS maintains a separate interrupt
+ safe API to ensure interrupt entry is as fast and as simple as possible.
+ More information (albeit Cortex-M specific) is provided on the following
+ link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ /* Cannot block in an ISR, so check there is data available. */
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
+ {
+ traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
+
+ prvCopyDataFromQueue( pxQueue, pvBuffer );
+ --( pxQueue->uxMessagesWaiting );
+
+ /* If the queue is locked the event list will not be modified.
+ Instead update the lock count so the task that unlocks the queue
+ will know that an ISR has removed data while the queue was
+ locked. */
+ if( pxQueue->xRxLock == queueUNLOCKED )
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority than us so
+ force a context switch. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Increment the lock count so the task that unlocks the queue
+ knows that data was removed while it was locked. */
+ ++( pxQueue->xRxLock );
+ }
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const pvBuffer )
+{
+signed portBASE_TYPE xReturn;
+unsigned portBASE_TYPE uxSavedInterruptStatus;
+signed char *pcOriginalReadPosition;
+xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
+
+ /* RTOS ports that support interrupt nesting have the concept of a maximum
+ system call (or maximum API call) interrupt priority. Interrupts that are
+ above the maximum system call priority are keep permanently enabled, even
+ when the RTOS kernel is in a critical section, but cannot make any calls to
+ FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
+ then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ failure if a FreeRTOS API function is called from an interrupt that has been
+ assigned a priority above the configured maximum system call priority.
+ Only FreeRTOS functions that end in FromISR can be called from interrupts
+ that have been assigned a priority at or (logically) below the maximum
+ system call interrupt priority. FreeRTOS maintains a separate interrupt
+ safe API to ensure interrupt entry is as fast and as simple as possible.
+ More information (albeit Cortex-M specific) is provided on the following
+ link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ /* Cannot block in an ISR, so check there is data available. */
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
+ {
+ traceQUEUE_PEEK_FROM_ISR( pxQueue );
+
+ /* Remember the read position so it can be reset as nothing is
+ actually being removed from the queue. */
+ pcOriginalReadPosition = pxQueue->u.pcReadFrom;
+ prvCopyDataFromQueue( pxQueue, pvBuffer );
+ pxQueue->u.pcReadFrom = pcOriginalReadPosition;
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue )
+{
+unsigned portBASE_TYPE uxReturn;
+
+ configASSERT( xQueue );
+
+ taskENTER_CRITICAL();
+ uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
+ taskEXIT_CRITICAL();
+
+ return uxReturn;
+} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
+/*-----------------------------------------------------------*/
+
+unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue )
+{
+unsigned portBASE_TYPE uxReturn;
+xQUEUE *pxQueue;
+
+ pxQueue = ( xQUEUE * ) xQueue;
+ configASSERT( pxQueue );
+
+ taskENTER_CRITICAL();
+ uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;
+ taskEXIT_CRITICAL();
+
+ return uxReturn;
+} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
+/*-----------------------------------------------------------*/
+
+unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue )
+{
+unsigned portBASE_TYPE uxReturn;
+
+ configASSERT( xQueue );
+
+ uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
+
+ return uxReturn;
+} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
+/*-----------------------------------------------------------*/
+
+void vQueueDelete( xQueueHandle xQueue )
+{
+xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ configASSERT( pxQueue );
+
+ traceQUEUE_DELETE( pxQueue );
+ #if ( configQUEUE_REGISTRY_SIZE > 0 )
+ {
+ vQueueUnregisterQueue( pxQueue );
+ }
+ #endif
+ vPortFree( pxQueue->pcHead );
+ vPortFree( pxQueue );
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue )
+ {
+ return ( ( xQUEUE * ) xQueue )->ucQueueNumber;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber )
+ {
+ ( ( xQUEUE * ) xQueue )->ucQueueNumber = ucQueueNumber;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ unsigned char ucQueueGetQueueType( xQueueHandle xQueue )
+ {
+ return ( ( xQUEUE * ) xQueue )->ucQueueType;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
+{
+ if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
+ {
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ /* The mutex is no longer being held. */
+ vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
+ pxQueue->pxMutexHolder = NULL;
+ }
+ }
+ #endif /* configUSE_MUTEXES */
+ }
+ else if( xPosition == queueSEND_TO_BACK )
+ {
+ ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */
+ pxQueue->pcWriteTo += pxQueue->uxItemSize;
+ if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
+ {
+ pxQueue->pcWriteTo = pxQueue->pcHead;
+ }
+ }
+ else
+ {
+ ( void ) memcpy( ( void * ) pxQueue->u.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ pxQueue->u.pcReadFrom -= pxQueue->uxItemSize;
+ if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
+ {
+ pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
+ }
+
+ if( xPosition == queueOVERWRITE )
+ {
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* An item is not being added but overwritten, so subtract
+ one from the recorded number of items in the queue so when
+ one is added again below the number of recorded items remains
+ correct. */
+ --( pxQueue->uxMessagesWaiting );
+ }
+ }
+ }
+
+ ++( pxQueue->uxMessagesWaiting );
+}
+/*-----------------------------------------------------------*/
+
+static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer )
+{
+ if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
+ {
+ pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
+ if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
+ {
+ pxQueue->u.pcReadFrom = pxQueue->pcHead;
+ }
+ ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvUnlockQueue( xQUEUE *pxQueue )
+{
+ /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
+
+ /* The lock counts contains the number of extra data items placed or
+ removed from the queue while the queue was locked. When a queue is
+ locked items can be added or removed, but the event lists cannot be
+ updated. */
+ taskENTER_CRITICAL();
+ {
+ /* See if data was added to the queue while it was locked. */
+ while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
+ {
+ /* Data was posted while the queue was locked. Are any tasks
+ blocked waiting for data to become available? */
+ #if ( configUSE_QUEUE_SETS == 1 )
+ {
+ if( pxQueue->pxQueueSetContainer != NULL )
+ {
+ if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
+ {
+ /* The queue is a member of a queue set, and posting to
+ the queue set caused a higher priority task to unblock.
+ A context switch is required. */
+ vTaskMissedYield();
+ }
+ }
+ else
+ {
+ /* Tasks that are removed from the event list will get added to
+ the pending ready list as the scheduler is still suspended. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority so record that a
+ context switch is required. */
+ vTaskMissedYield();
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ #else /* configUSE_QUEUE_SETS */
+ {
+ /* Tasks that are removed from the event list will get added to
+ the pending ready list as the scheduler is still suspended. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority so record that a
+ context switch is required. */
+ vTaskMissedYield();
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ #endif /* configUSE_QUEUE_SETS */
+
+ --( pxQueue->xTxLock );
+ }
+
+ pxQueue->xTxLock = queueUNLOCKED;
+ }
+ taskEXIT_CRITICAL();
+
+ /* Do the same for the Rx lock. */
+ taskENTER_CRITICAL();
+ {
+ while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ vTaskMissedYield();
+ }
+
+ --( pxQueue->xRxLock );
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ pxQueue->xRxLock = queueUNLOCKED;
+ }
+ taskEXIT_CRITICAL();
+}
+/*-----------------------------------------------------------*/
+
+static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue )
+{
+signed portBASE_TYPE xReturn;
+
+ taskENTER_CRITICAL();
+ {
+ if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue )
+{
+signed portBASE_TYPE xReturn;
+
+ configASSERT( xQueue );
+ if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+
+ return xReturn;
+} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
+/*-----------------------------------------------------------*/
+
+static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue )
+{
+signed portBASE_TYPE xReturn;
+
+ taskENTER_CRITICAL();
+ {
+ if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue )
+{
+signed portBASE_TYPE xReturn;
+
+ configASSERT( xQueue );
+ if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+
+ return xReturn;
+} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+ signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait )
+ {
+ signed portBASE_TYPE xReturn;
+ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ /* If the queue is already full we may have to block. A critical section
+ is required to prevent an interrupt removing something from the queue
+ between the check to see if the queue is full and blocking on the queue. */
+ portDISABLE_INTERRUPTS();
+ {
+ if( prvIsQueueFull( pxQueue ) != pdFALSE )
+ {
+ /* The queue is full - do we want to block or just leave without
+ posting? */
+ if( xTicksToWait > ( portTickType ) 0 )
+ {
+ /* As this is called from a coroutine we cannot block directly, but
+ return indicating that we need to block. */
+ vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
+ portENABLE_INTERRUPTS();
+ return errQUEUE_BLOCKED;
+ }
+ else
+ {
+ portENABLE_INTERRUPTS();
+ return errQUEUE_FULL;
+ }
+ }
+ }
+ portENABLE_INTERRUPTS();
+
+ portDISABLE_INTERRUPTS();
+ {
+ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
+ {
+ /* There is room in the queue, copy the data into the queue. */
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
+ xReturn = pdPASS;
+
+ /* Were any co-routines waiting for data to become available? */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ /* In this instance the co-routine could be placed directly
+ into the ready list as we are within a critical section.
+ Instead the same pending ready list mechanism is used as if
+ the event were caused from within an interrupt. */
+ if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The co-routine waiting has a higher priority so record
+ that a yield might be appropriate. */
+ xReturn = errQUEUE_YIELD;
+ }
+ }
+ }
+ else
+ {
+ xReturn = errQUEUE_FULL;
+ }
+ }
+ portENABLE_INTERRUPTS();
+
+ return xReturn;
+ }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+ signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait )
+ {
+ signed portBASE_TYPE xReturn;
+ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ /* If the queue is already empty we may have to block. A critical section
+ is required to prevent an interrupt adding something to the queue
+ between the check to see if the queue is empty and blocking on the queue. */
+ portDISABLE_INTERRUPTS();
+ {
+ if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* There are no messages in the queue, do we want to block or just
+ leave with nothing? */
+ if( xTicksToWait > ( portTickType ) 0 )
+ {
+ /* As this is a co-routine we cannot block directly, but return
+ indicating that we need to block. */
+ vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
+ portENABLE_INTERRUPTS();
+ return errQUEUE_BLOCKED;
+ }
+ else
+ {
+ portENABLE_INTERRUPTS();
+ return errQUEUE_FULL;
+ }
+ }
+ }
+ portENABLE_INTERRUPTS();
+
+ portDISABLE_INTERRUPTS();
+ {
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* Data is available from the queue. */
+ pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
+ if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
+ {
+ pxQueue->u.pcReadFrom = pxQueue->pcHead;
+ }
+ --( pxQueue->uxMessagesWaiting );
+ ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
+
+ xReturn = pdPASS;
+
+ /* Were any co-routines waiting for space to become available? */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ /* In this instance the co-routine could be placed directly
+ into the ready list as we are within a critical section.
+ Instead the same pending ready list mechanism is used as if
+ the event were caused from within an interrupt. */
+ if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ xReturn = errQUEUE_YIELD;
+ }
+ }
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+ }
+ portENABLE_INTERRUPTS();
+
+ return xReturn;
+ }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+ signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
+ {
+ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ /* Cannot block within an ISR so if there is no space on the queue then
+ exit without doing anything. */
+ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
+ {
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
+
+ /* We only want to wake one co-routine per ISR, so check that a
+ co-routine has not already been woken. */
+ if( xCoRoutinePreviouslyWoken == pdFALSE )
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ return pdTRUE;
+ }
+ }
+ }
+ }
+
+ return xCoRoutinePreviouslyWoken;
+ }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+ signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
+ {
+ signed portBASE_TYPE xReturn;
+ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ /* We cannot block from an ISR, so check there is data available. If
+ not then just leave without doing anything. */
+ if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* Copy the data from the queue. */
+ pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
+ if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
+ {
+ pxQueue->u.pcReadFrom = pxQueue->pcHead;
+ }
+ --( pxQueue->uxMessagesWaiting );
+ ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
+
+ if( ( *pxCoRoutineWoken ) == pdFALSE )
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ *pxCoRoutineWoken = pdTRUE;
+ }
+ }
+ }
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+
+ void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
+ {
+ unsigned portBASE_TYPE ux;
+
+ /* See if there is an empty space in the registry. A NULL name denotes
+ a free slot. */
+ for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
+ {
+ if( xQueueRegistry[ ux ].pcQueueName == NULL )
+ {
+ /* Store the information on this queue. */
+ xQueueRegistry[ ux ].pcQueueName = pcQueueName;
+ xQueueRegistry[ ux ].xHandle = xQueue;
+ break;
+ }
+ }
+ }
+
+#endif /* configQUEUE_REGISTRY_SIZE */
+/*-----------------------------------------------------------*/
+
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+
+ void vQueueUnregisterQueue( xQueueHandle xQueue )
+ {
+ unsigned portBASE_TYPE ux;
+
+ /* See if the handle of the queue being unregistered in actually in the
+ registry. */
+ for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
+ {
+ if( xQueueRegistry[ ux ].xHandle == xQueue )
+ {
+ /* Set the name to NULL to show that this slot if free again. */
+ xQueueRegistry[ ux ].pcQueueName = NULL;
+ break;
+ }
+ }
+
+ } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
+
+#endif /* configQUEUE_REGISTRY_SIZE */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TIMERS == 1 )
+
+ void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait )
+ {
+ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
+
+ /* This function should not be called by application code hence the
+ 'Restricted' in its name. It is not part of the public API. It is
+ designed for use by kernel code, and has special calling requirements.
+ It can result in vListInsert() being called on a list that can only
+ possibly ever have one item in it, so the list will be fast, but even
+ so it should be called with the scheduler locked and not from a critical
+ section. */
+
+ /* Only do anything if there are no messages in the queue. This function
+ will not actually cause the task to block, just place it on a blocked
+ list. It will not block until the scheduler is unlocked - at which
+ time a yield will be performed. If an item is added to the queue while
+ the queue is locked, and the calling task blocks on the queue, then the
+ calling task will be immediately unblocked when the queue is unlocked. */
+ prvLockQueue( pxQueue );
+ if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
+ {
+ /* There is nothing in the queue, block for the specified period. */
+ vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+ }
+ prvUnlockQueue( pxQueue );
+ }
+
+#endif /* configUSE_TIMERS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength )
+ {
+ xQueueSetHandle pxQueue;
+
+ pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET );
+
+ return pxQueue;
+ }
+
+#endif /* configUSE_QUEUE_SETS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
+ {
+ portBASE_TYPE xReturn;
+
+ if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
+ {
+ /* Cannot add a queue/semaphore to more than one queue set. */
+ xReturn = pdFAIL;
+ }
+ else if( ( ( xQUEUE * ) xQueueOrSemaphore )->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* Cannot add a queue/semaphore to a queue set if there are already
+ items in the queue/semaphore. */
+ xReturn = pdFAIL;
+ }
+ else
+ {
+ taskENTER_CRITICAL();
+ {
+ ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
+ }
+ taskEXIT_CRITICAL();
+ xReturn = pdPASS;
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_QUEUE_SETS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
+ {
+ portBASE_TYPE xReturn;
+ xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
+
+ if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
+ {
+ /* The queue was not a member of the set. */
+ xReturn = pdFAIL;
+ }
+ else if( pxQueueOrSemaphore->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* It is dangerous to remove a queue from a set when the queue is
+ not empty because the queue set will still hold pending events for
+ the queue. */
+ xReturn = pdFAIL;
+ }
+ else
+ {
+ taskENTER_CRITICAL();
+ {
+ /* The queue is no longer contained in the set. */
+ pxQueueOrSemaphore->pxQueueSetContainer = NULL;
+ }
+ taskEXIT_CRITICAL();
+ xReturn = pdPASS;
+ }
+
+ return xReturn;
+ } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */
+
+#endif /* configUSE_QUEUE_SETS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks )
+ {
+ xQueueSetMemberHandle xReturn = NULL;
+
+ ( void ) xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */
+ return xReturn;
+ }
+
+#endif /* configUSE_QUEUE_SETS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet )
+ {
+ xQueueSetMemberHandle xReturn = NULL;
+
+ ( void ) xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */
+ return xReturn;
+ }
+
+#endif /* configUSE_QUEUE_SETS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition )
+ {
+ xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
+ portBASE_TYPE xReturn = pdFALSE;
+
+ configASSERT( pxQueueSetContainer );
+ configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
+
+ if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
+ {
+ traceQUEUE_SEND( pxQueueSetContainer );
+ /* The data copies is the handle of the queue that contains data. */
+ prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );
+ if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority */
+ xReturn = pdTRUE;
+ }
+ }
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_QUEUE_SETS */
+
diff --git a/source/freertos_blinky/freertos/src/tasks.c b/source/freertos_blinky/freertos/src/tasks.c
new file mode 100644
index 0000000..c47121d
--- /dev/null
+++ b/source/freertos_blinky/freertos/src/tasks.c
@@ -0,0 +1,2957 @@
+/*
+ FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that has become a de facto standard. *
+ * *
+ * Help yourself get started quickly and support the FreeRTOS *
+ * project by purchasing a FreeRTOS tutorial book, reference *
+ * manual, or both from: http://www.FreeRTOS.org/Documentation *
+ * *
+ * Thank you! *
+ * *
+ ***************************************************************************
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ >>! NOTE: The modification to the GPL is included to allow you to distribute
+ >>! a combined work that includes FreeRTOS without being obliged to provide
+ >>! the source code for proprietary components outside of the FreeRTOS
+ >>! kernel.
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available from the following
+ link: http://www.freertos.org/a00114.html
+
+ 1 tab == 4 spaces!
+
+ ***************************************************************************
+ * *
+ * Having a problem? Start by reading the FAQ "My application does *
+ * not run, what could be wrong?" *
+ * *
+ * http://www.FreeRTOS.org/FAQHelp.html *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ license and Real Time Engineers Ltd. contact details.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+ Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/* Standard includes. */
+#include
+#include
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers. That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "timers.h"
+#include "StackMacros.h"
+
+/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
+MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
+header files above, but not in this file, in order to generate the correct
+privileged Vs unprivileged linkage and placement. */
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
+
+#if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
+ /* At the bottom of this file are two optional functions that can be used
+ to generate human readable text from the raw data generated by the
+ uxTaskGetSystemState() function. Note the formatting functions are provided
+ for convenience only, and are NOT considered part of the kernel. */
+ #include
+#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
+
+/* Sanity check the configuration. */
+#if configUSE_TICKLESS_IDLE != 0
+ #if INCLUDE_vTaskSuspend != 1
+ #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
+ #endif /* INCLUDE_vTaskSuspend */
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Defines the size, in words, of the stack allocated to the idle task.
+ */
+#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
+
+/*
+ * Task control block. A task control block (TCB) is allocated for each task,
+ * and stores task state information, including a pointer to the task's context
+ * (the task's run time environment, including register values)
+ */
+typedef struct tskTaskControlBlock
+{
+ volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
+
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
+ #endif
+
+ xListItem xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
+ xListItem xEventListItem; /*< Used to reference a task from an event list. */
+ unsigned portBASE_TYPE uxPriority; /*< The priority of the task. 0 is the lowest priority. */
+ portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */
+ signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */
+
+ #if ( portSTACK_GROWTH > 0 )
+ portSTACK_TYPE *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
+ #endif
+
+ #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+ unsigned portBASE_TYPE uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
+ #endif
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ unsigned portBASE_TYPE uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
+ unsigned portBASE_TYPE uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
+ #endif
+
+ #if ( configUSE_MUTEXES == 1 )
+ unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
+ #endif
+
+ #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+ pdTASK_HOOK_CODE pxTaskTag;
+ #endif
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ unsigned long ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
+ #endif
+
+ #if ( configUSE_NEWLIB_REENTRANT == 1 )
+ /* Allocate a Newlib reent structure that is specific to this task.
+ Note Newlib support has been included by popular demand, but is not
+ used by the FreeRTOS maintainers themselves. FreeRTOS is not
+ responsible for resulting newlib operation. User must be familiar with
+ newlib and must provide system-wide implementations of the necessary
+ stubs. Be warned that (at the time of writing) the current newlib design
+ implements a system-wide malloc() that must be provided with locks. */
+ struct _reent xNewLib_reent;
+ #endif
+
+} tskTCB;
+
+
+/*
+ * Some kernel aware debuggers require the data the debugger needs access to to
+ * be global, rather than file scope.
+ */
+#ifdef portREMOVE_STATIC_QUALIFIER
+ #define static
+#endif
+
+/*lint -e956 A manual analysis and inspection has been used to determine which
+static variables must be declared volatile. */
+
+PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
+
+/* Lists for ready and blocked tasks. --------------------*/
+PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */
+PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */
+PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
+PRIVILEGED_DATA static xList * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
+PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
+PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
+
+#if ( INCLUDE_vTaskDelete == 1 )
+
+ PRIVILEGED_DATA static xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */
+ PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0U;
+
+#endif
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */
+
+#endif
+
+#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
+
+ PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
+
+#endif
+
+/* Other file private variables. --------------------------------*/
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U;
+PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U;
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY;
+PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE;
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE;
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxPendedTicks = ( unsigned portBASE_TYPE ) 0U;
+PRIVILEGED_DATA static volatile portBASE_TYPE xYieldPending = pdFALSE;
+PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
+PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U;
+PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_DELAY;
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+ PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
+ PRIVILEGED_DATA static unsigned long ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
+
+#endif
+
+/*lint +e956 */
+
+/* Debugging and trace facilities private variables and macros. ------------*/
+
+/*
+ * The value used to fill the stack of a task when the task is created. This
+ * is used purely for checking the high water mark for tasks.
+ */
+#define tskSTACK_FILL_BYTE ( 0xa5U )
+
+/*
+ * Macros used by vListTask to indicate which state a task is in.
+ */
+#define tskBLOCKED_CHAR ( ( signed char ) 'B' )
+#define tskREADY_CHAR ( ( signed char ) 'R' )
+#define tskDELETED_CHAR ( ( signed char ) 'D' )
+#define tskSUSPENDED_CHAR ( ( signed char ) 'S' )
+
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
+
+ /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
+ performed in a generic way that is not optimised to any particular
+ microcontroller architecture. */
+
+ /* uxTopReadyPriority holds the priority of the highest priority ready
+ state task. */
+ #define taskRECORD_READY_PRIORITY( uxPriority ) \
+ { \
+ if( ( uxPriority ) > uxTopReadyPriority ) \
+ { \
+ uxTopReadyPriority = ( uxPriority ); \
+ } \
+ } /* taskRECORD_READY_PRIORITY */
+
+ /*-----------------------------------------------------------*/
+
+ #define taskSELECT_HIGHEST_PRIORITY_TASK() \
+ { \
+ /* Find the highest priority queue that contains ready tasks. */ \
+ while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
+ { \
+ configASSERT( uxTopReadyPriority ); \
+ --uxTopReadyPriority; \
+ } \
+ \
+ /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
+ the same priority get an equal share of the processor time. */ \
+ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
+ } /* taskSELECT_HIGHEST_PRIORITY_TASK */
+
+ /*-----------------------------------------------------------*/
+
+ /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
+ they are only required when a port optimised method of task selection is
+ being used. */
+ #define taskRESET_READY_PRIORITY( uxPriority )
+ #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
+
+#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
+
+ /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
+ performed in a way that is tailored to the particular microcontroller
+ architecture being used. */
+
+ /* A port optimised version is provided. Call the port defined macros. */
+ #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
+
+ /*-----------------------------------------------------------*/
+
+ #define taskSELECT_HIGHEST_PRIORITY_TASK() \
+ { \
+ unsigned portBASE_TYPE uxTopPriority; \
+ \
+ /* Find the highest priority queue that contains ready tasks. */ \
+ portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
+ configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
+ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
+ } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
+
+ /*-----------------------------------------------------------*/
+
+ /* A port optimised version is provided, call it only if the TCB being reset
+ is being referenced from a ready list. If it is referenced from a delayed
+ or suspended list then it won't be in a ready list. */
+ #define taskRESET_READY_PRIORITY( uxPriority ) \
+ { \
+ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 ) \
+ { \
+ portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
+ } \
+ }
+
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
+
+/*-----------------------------------------------------------*/
+
+/* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
+count overflows. */
+#define taskSWITCH_DELAYED_LISTS() \
+{ \
+ xList *pxTemp; \
+ \
+ /* The delayed tasks list should be empty when the lists are switched. */ \
+ configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
+ \
+ pxTemp = pxDelayedTaskList; \
+ pxDelayedTaskList = pxOverflowDelayedTaskList; \
+ pxOverflowDelayedTaskList = pxTemp; \
+ xNumOfOverflows++; \
+ \
+ if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \
+ { \
+ /* The new current delayed list is empty. Set \
+ xNextTaskUnblockTime to the maximum possible value so it is \
+ extremely unlikely that the \
+ if( xTickCount >= xNextTaskUnblockTime ) test will pass until \
+ there is an item in the delayed list. */ \
+ xNextTaskUnblockTime = portMAX_DELAY; \
+ } \
+ else \
+ { \
+ /* The new current delayed list is not empty, get the value of \
+ the item at the head of the delayed list. This is the time at \
+ which the task at the head of the delayed list should be removed \
+ from the Blocked state. */ \
+ pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); \
+ xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); \
+ } \
+}
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Place the task represented by pxTCB into the appropriate ready list for
+ * the task. It is inserted at the end of the list.
+ */
+#define prvAddTaskToReadyList( pxTCB ) \
+ traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
+ taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
+ vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
+/*-----------------------------------------------------------*/
+
+/*
+ * Several functions take an xTaskHandle parameter that can optionally be NULL,
+ * where NULL is used to indicate that the handle of the currently executing
+ * task should be used in place of the parameter. This macro simply checks to
+ * see if the parameter is NULL and returns a pointer to the appropriate TCB.
+ */
+#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) ( pxHandle ) )
+
+/* Callback function prototypes. --------------------------*/
+extern void vApplicationStackOverflowHook( xTaskHandle xTask, signed char *pcTaskName );
+extern void vApplicationTickHook( void );
+
+/* File private functions. --------------------------------*/
+
+/*
+ * Utility to ready a TCB for a given task. Mainly just copies the parameters
+ * into the TCB structure.
+ */
+static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION;
+
+/*
+ * Utility to ready all the lists used by the scheduler. This is called
+ * automatically upon the creation of the first task.
+ */
+static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * The idle task, which as all tasks is implemented as a never ending loop.
+ * The idle task is automatically created and added to the ready lists upon
+ * creation of the first user task.
+ *
+ * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
+ * language extensions. The equivalent prototype for this function is:
+ *
+ * void prvIdleTask( void *pvParameters );
+ *
+ */
+static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
+
+/*
+ * Utility to free all memory allocated by the scheduler to hold a TCB,
+ * including the stack pointed to by the TCB.
+ *
+ * This does not free memory allocated by the task itself (i.e. memory
+ * allocated by calls to pvPortMalloc from within the tasks application code).
+ */
+#if ( INCLUDE_vTaskDelete == 1 )
+
+ static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * Used only by the idle task. This checks to see if anything has been placed
+ * in the list of tasks waiting to be deleted. If so the task is cleaned up
+ * and its TCB deleted.
+ */
+static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * The currently executing task is entering the Blocked state. Add the task to
+ * either the current or the overflow delayed task list.
+ */
+static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION;
+
+/*
+ * Allocates memory from the heap for a TCB and associated stack. Checks the
+ * allocation was successful.
+ */
+static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION;
+
+/*
+ * Fills an xTaskStatusType structure with information on each task that is
+ * referenced from the pxList list (which may be a ready list, a delayed list,
+ * a suspended list, etc.).
+ *
+ * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
+ * NORMAL APPLICATION CODE.
+ */
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * When a task is created, the stack of the task is filled with a known value.
+ * This function determines the 'high water mark' of the task stack by
+ * determining how much of the stack remains at the original preset value.
+ */
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
+
+ static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * Return the amount of time, in ticks, that will pass before the kernel will
+ * next move a task from the Blocked state to the Running state.
+ *
+ * This conditional compilation should use inequality to 0, not equality to 1.
+ * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
+ * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
+ * set to a value other than 1.
+ */
+#if ( configUSE_TICKLESS_IDLE != 0 )
+
+ static portTickType prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
+
+#endif
+
+signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions )
+{
+signed portBASE_TYPE xReturn;
+tskTCB * pxNewTCB;
+
+ configASSERT( pxTaskCode );
+ configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );
+
+ /* Allocate the memory required by the TCB and stack for the new task,
+ checking that the allocation was successful. */
+ pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
+
+ if( pxNewTCB != NULL )
+ {
+ portSTACK_TYPE *pxTopOfStack;
+
+ #if( portUSING_MPU_WRAPPERS == 1 )
+ /* Should the task be created in privileged mode? */
+ portBASE_TYPE xRunPrivileged;
+ if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
+ {
+ xRunPrivileged = pdTRUE;
+ }
+ else
+ {
+ xRunPrivileged = pdFALSE;
+ }
+ uxPriority &= ~portPRIVILEGE_BIT;
+ #endif /* portUSING_MPU_WRAPPERS == 1 */
+
+ /* Calculate the top of stack address. This depends on whether the
+ stack grows from high memory to low (as per the 80x86) or visa versa.
+ portSTACK_GROWTH is used to make the result positive or negative as
+ required by the port. */
+ #if( portSTACK_GROWTH < 0 )
+ {
+ pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 );
+ pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
+
+ /* Check the alignment of the calculated top of stack is correct. */
+ configASSERT( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ }
+ #else /* portSTACK_GROWTH */
+ {
+ pxTopOfStack = pxNewTCB->pxStack;
+
+ /* Check the alignment of the stack buffer is correct. */
+ configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+
+ /* If we want to use stack checking on architectures that use
+ a positive stack growth direction then we also need to store the
+ other extreme of the stack space. */
+ pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
+ }
+ #endif /* portSTACK_GROWTH */
+
+ /* Setup the newly allocated TCB with the initial state of the task. */
+ prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
+
+ /* Initialize the TCB stack to look as if the task was already running,
+ but had been interrupted by the scheduler. The return address is set
+ to the start of the task function. Once the stack has been initialised
+ the top of stack variable is updated. */
+ #if( portUSING_MPU_WRAPPERS == 1 )
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
+ }
+ #else /* portUSING_MPU_WRAPPERS */
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
+ }
+ #endif /* portUSING_MPU_WRAPPERS */
+
+ if( ( void * ) pxCreatedTask != NULL )
+ {
+ /* Pass the TCB out - in an anonymous way. The calling function/
+ task can use this as a handle to delete the task later if
+ required.*/
+ *pxCreatedTask = ( xTaskHandle ) pxNewTCB;
+ }
+
+ /* Ensure interrupts don't access the task lists while they are being
+ updated. */
+ taskENTER_CRITICAL();
+ {
+ uxCurrentNumberOfTasks++;
+ if( pxCurrentTCB == NULL )
+ {
+ /* There are no other tasks, or all the other tasks are in
+ the suspended state - make this the current task. */
+ pxCurrentTCB = pxNewTCB;
+
+ if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
+ {
+ /* This is the first task to be created so do the preliminary
+ initialisation required. We will not recover if this call
+ fails, but we will report the failure. */
+ prvInitialiseTaskLists();
+ }
+ }
+ else
+ {
+ /* If the scheduler is not already running, make this task the
+ current task if it is the highest priority task to be created
+ so far. */
+ if( xSchedulerRunning == pdFALSE )
+ {
+ if( pxCurrentTCB->uxPriority <= uxPriority )
+ {
+ pxCurrentTCB = pxNewTCB;
+ }
+ }
+ }
+
+ uxTaskNumber++;
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ /* Add a counter into the TCB for tracing only. */
+ pxNewTCB->uxTCBNumber = uxTaskNumber;
+ }
+ #endif /* configUSE_TRACE_FACILITY */
+ traceTASK_CREATE( pxNewTCB );
+
+ prvAddTaskToReadyList( pxNewTCB );
+
+ xReturn = pdPASS;
+ portSETUP_TCB( pxNewTCB );
+ }
+ taskEXIT_CRITICAL();
+ }
+ else
+ {
+ xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+ traceTASK_CREATE_FAILED();
+ }
+
+ if( xReturn == pdPASS )
+ {
+ if( xSchedulerRunning != pdFALSE )
+ {
+ /* If the created task is of a higher priority than the current task
+ then it should run now. */
+ if( pxCurrentTCB->uxPriority < uxPriority )
+ {
+ portYIELD_WITHIN_API();
+ }
+ }
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelete == 1 )
+
+ void vTaskDelete( xTaskHandle xTaskToDelete )
+ {
+ tskTCB *pxTCB;
+
+ taskENTER_CRITICAL();
+ {
+ /* If null is passed in here then we are deleting ourselves. */
+ pxTCB = prvGetTCBFromHandle( xTaskToDelete );
+
+ /* Remove task from the ready list and place in the termination list.
+ This will stop the task from be scheduled. The idle task will check
+ the termination list and free up any memory allocated by the
+ scheduler for the TCB and stack. */
+ if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
+ {
+ taskRESET_READY_PRIORITY( pxTCB->uxPriority );
+ }
+
+ /* Is the task waiting on an event also? */
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
+ }
+
+ vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
+
+ /* Increment the ucTasksDeleted variable so the idle task knows
+ there is a task that has been deleted and that it should therefore
+ check the xTasksWaitingTermination list. */
+ ++uxTasksDeleted;
+
+ /* Increment the uxTaskNumberVariable also so kernel aware debuggers
+ can detect that the task lists need re-generating. */
+ uxTaskNumber++;
+
+ traceTASK_DELETE( pxTCB );
+ }
+ taskEXIT_CRITICAL();
+
+ /* Force a reschedule if we have just deleted the current task. */
+ if( xSchedulerRunning != pdFALSE )
+ {
+ if( pxTCB == pxCurrentTCB )
+ {
+ portYIELD_WITHIN_API();
+ }
+ }
+ }
+
+#endif /* INCLUDE_vTaskDelete */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelayUntil == 1 )
+
+ void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )
+ {
+ portTickType xTimeToWake;
+ portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
+
+ configASSERT( pxPreviousWakeTime );
+ configASSERT( ( xTimeIncrement > 0U ) );
+
+ vTaskSuspendAll();
+ {
+ /* Minor optimisation. The tick count cannot change in this
+ block. */
+ const portTickType xConstTickCount = xTickCount;
+
+ /* Generate the tick time at which the task wants to wake. */
+ xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
+
+ if( xConstTickCount < *pxPreviousWakeTime )
+ {
+ /* The tick count has overflowed since this function was
+ lasted called. In this case the only time we should ever
+ actually delay is if the wake time has also overflowed,
+ and the wake time is greater than the tick time. When this
+ is the case it is as if neither time had overflowed. */
+ if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
+ {
+ xShouldDelay = pdTRUE;
+ }
+ }
+ else
+ {
+ /* The tick time has not overflowed. In this case we will
+ delay if either the wake time has overflowed, and/or the
+ tick time is less than the wake time. */
+ if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
+ {
+ xShouldDelay = pdTRUE;
+ }
+ }
+
+ /* Update the wake time ready for the next call. */
+ *pxPreviousWakeTime = xTimeToWake;
+
+ if( xShouldDelay != pdFALSE )
+ {
+ traceTASK_DELAY_UNTIL();
+
+ /* We must remove ourselves from the ready list before adding
+ ourselves to the blocked list as the same list item is used for
+ both lists. */
+ if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* The current task must be in a ready list, so there is
+ no need to check, and the port reset macro can be called
+ directly. */
+ portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
+ }
+
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
+ }
+ }
+ xAlreadyYielded = xTaskResumeAll();
+
+ /* Force a reschedule if xTaskResumeAll has not already done so, we may
+ have put ourselves to sleep. */
+ if( xAlreadyYielded == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ }
+
+#endif /* INCLUDE_vTaskDelayUntil */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelay == 1 )
+
+ void vTaskDelay( portTickType xTicksToDelay )
+ {
+ portTickType xTimeToWake;
+ signed portBASE_TYPE xAlreadyYielded = pdFALSE;
+
+ /* A delay time of zero just forces a reschedule. */
+ if( xTicksToDelay > ( portTickType ) 0U )
+ {
+ vTaskSuspendAll();
+ {
+ traceTASK_DELAY();
+
+ /* A task that is removed from the event list while the
+ scheduler is suspended will not get placed in the ready
+ list or removed from the blocked list until the scheduler
+ is resumed.
+
+ This task cannot be in an event list as it is the currently
+ executing task. */
+
+ /* Calculate the time to wake - this may overflow but this is
+ not a problem. */
+ xTimeToWake = xTickCount + xTicksToDelay;
+
+ /* We must remove ourselves from the ready list before adding
+ ourselves to the blocked list as the same list item is used for
+ both lists. */
+ if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* The current task must be in a ready list, so there is
+ no need to check, and the port reset macro can be called
+ directly. */
+ portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
+ }
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
+ }
+ xAlreadyYielded = xTaskResumeAll();
+ }
+
+ /* Force a reschedule if xTaskResumeAll has not already done so, we may
+ have put ourselves to sleep. */
+ if( xAlreadyYielded == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ }
+
+#endif /* INCLUDE_vTaskDelay */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_eTaskGetState == 1 )
+
+ eTaskState eTaskGetState( xTaskHandle xTask )
+ {
+ eTaskState eReturn;
+ xList *pxStateList;
+ const tskTCB * const pxTCB = ( tskTCB * ) xTask;
+
+ if( pxTCB == pxCurrentTCB )
+ {
+ /* The task calling this function is querying its own state. */
+ eReturn = eRunning;
+ }
+ else
+ {
+ taskENTER_CRITICAL();
+ {
+ pxStateList = ( xList * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
+ }
+ taskEXIT_CRITICAL();
+
+ if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
+ {
+ /* The task being queried is referenced from one of the Blocked
+ lists. */
+ eReturn = eBlocked;
+ }
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ else if( pxStateList == &xSuspendedTaskList )
+ {
+ /* The task being queried is referenced from the suspended
+ list. */
+ eReturn = eSuspended;
+ }
+ #endif
+
+ #if ( INCLUDE_vTaskDelete == 1 )
+ else if( pxStateList == &xTasksWaitingTermination )
+ {
+ /* The task being queried is referenced from the deleted
+ tasks list. */
+ eReturn = eDeleted;
+ }
+ #endif
+
+ else
+ {
+ /* If the task is not in any other state, it must be in the
+ Ready (including pending ready) state. */
+ eReturn = eReady;
+ }
+ }
+
+ return eReturn;
+ }
+
+#endif /* INCLUDE_eTaskGetState */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_uxTaskPriorityGet == 1 )
+
+ unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask )
+ {
+ tskTCB *pxTCB;
+ unsigned portBASE_TYPE uxReturn;
+
+ taskENTER_CRITICAL();
+ {
+ /* If null is passed in here then we are changing the
+ priority of the calling function. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+ uxReturn = pxTCB->uxPriority;
+ }
+ taskEXIT_CRITICAL();
+
+ return uxReturn;
+ }
+
+#endif /* INCLUDE_uxTaskPriorityGet */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskPrioritySet == 1 )
+
+ void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority )
+ {
+ tskTCB *pxTCB;
+ unsigned portBASE_TYPE uxCurrentBasePriority, uxPriorityUsedOnEntry;
+ portBASE_TYPE xYieldRequired = pdFALSE;
+
+ configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
+
+ /* Ensure the new priority is valid. */
+ if( uxNewPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES )
+ {
+ uxNewPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U;
+ }
+
+ taskENTER_CRITICAL();
+ {
+ /* If null is passed in here then it is the priority of the calling
+ task that is being changed. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ uxCurrentBasePriority = pxTCB->uxBasePriority;
+ }
+ #else
+ {
+ uxCurrentBasePriority = pxTCB->uxPriority;
+ }
+ #endif
+
+ if( uxCurrentBasePriority != uxNewPriority )
+ {
+ /* The priority change may have readied a task of higher
+ priority than the calling task. */
+ if( uxNewPriority > uxCurrentBasePriority )
+ {
+ if( pxTCB != pxCurrentTCB )
+ {
+ /* The priority of a task other than the currently
+ running task is being raised. Is the priority being
+ raised above that of the running task? */
+ if( uxNewPriority >= pxCurrentTCB->uxPriority )
+ {
+ xYieldRequired = pdTRUE;
+ }
+ }
+ else
+ {
+ /* The priority of the running task is being raised,
+ but the running task must already be the highest
+ priority task able to run so no yield is required. */
+ }
+ }
+ else if( pxTCB == pxCurrentTCB )
+ {
+ /* Setting the priority of the running task down means
+ there may now be another task of higher priority that
+ is ready to execute. */
+ xYieldRequired = pdTRUE;
+ }
+ else
+ {
+ /* Setting the priority of any other task down does not
+ require a yield as the running task must be above the
+ new priority of the task being modified. */
+ }
+
+ /* Remember the ready list the task might be referenced from
+ before its uxPriority member is changed so the
+ taskRESET_READY_PRIORITY() macro can function correctly. */
+ uxPriorityUsedOnEntry = pxTCB->uxPriority;
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ /* Only change the priority being used if the task is not
+ currently using an inherited priority. */
+ if( pxTCB->uxBasePriority == pxTCB->uxPriority )
+ {
+ pxTCB->uxPriority = uxNewPriority;
+ }
+
+ /* The base priority gets set whatever. */
+ pxTCB->uxBasePriority = uxNewPriority;
+ }
+ #else
+ {
+ pxTCB->uxPriority = uxNewPriority;
+ }
+ #endif
+
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ /* If the task is in the blocked or suspended list we need do
+ nothing more than change it's priority variable. However, if
+ the task is in a ready list it needs to be removed and placed
+ in the list appropriate to its new priority. */
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
+ {
+ /* The task is currently in its ready list - remove before adding
+ it to it's new ready list. As we are in a critical section we
+ can do this even if the scheduler is suspended. */
+ if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* It is known that the task is in its ready list so
+ there is no need to check again and the port level
+ reset macro can be called directly. */
+ portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
+ }
+ prvAddTaskToReadyList( pxTCB );
+ }
+
+ if( xYieldRequired == pdTRUE )
+ {
+ portYIELD_WITHIN_API();
+ }
+
+ /* Remove compiler warning about unused variables when the port
+ optimised task selection is not being used. */
+ ( void ) uxPriorityUsedOnEntry;
+ }
+ }
+ taskEXIT_CRITICAL();
+ }
+
+#endif /* INCLUDE_vTaskPrioritySet */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ void vTaskSuspend( xTaskHandle xTaskToSuspend )
+ {
+ tskTCB *pxTCB;
+
+ taskENTER_CRITICAL();
+ {
+ /* If null is passed in here then it is the running task that is
+ being suspended. */
+ pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
+
+ traceTASK_SUSPEND( pxTCB );
+
+ /* Remove task from the ready/delayed list and place in the suspended list. */
+ if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
+ {
+ taskRESET_READY_PRIORITY( pxTCB->uxPriority );
+ }
+
+ /* Is the task waiting on an event also? */
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
+ }
+
+ vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
+ }
+ taskEXIT_CRITICAL();
+
+ if( pxTCB == pxCurrentTCB )
+ {
+ if( xSchedulerRunning != pdFALSE )
+ {
+ /* The current task has just been suspended. */
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ /* The scheduler is not running, but the task that was pointed
+ to by pxCurrentTCB has just been suspended and pxCurrentTCB
+ must be adjusted to point to a different task. */
+ if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
+ {
+ /* No other tasks are ready, so set pxCurrentTCB back to
+ NULL so when the next task is created pxCurrentTCB will
+ be set to point to it no matter what its relative priority
+ is. */
+ pxCurrentTCB = NULL;
+ }
+ else
+ {
+ vTaskSwitchContext();
+ }
+ }
+ }
+ }
+
+#endif /* INCLUDE_vTaskSuspend */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask )
+ {
+ portBASE_TYPE xReturn = pdFALSE;
+ const tskTCB * const pxTCB = ( tskTCB * ) xTask;
+
+ /* It does not make sense to check if the calling task is suspended. */
+ configASSERT( xTask );
+
+ /* Is the task we are attempting to resume actually in the
+ suspended list? */
+ if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
+ {
+ /* Has the task already been resumed from within an ISR? */
+ if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
+ {
+ /* Is it in the suspended list because it is in the
+ Suspended state? It is possible to be in the suspended
+ list because it is blocked on a task with no timeout
+ specified. */
+ if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
+ {
+ xReturn = pdTRUE;
+ }
+ }
+ }
+
+ return xReturn;
+ } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
+
+#endif /* INCLUDE_vTaskSuspend */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ void vTaskResume( xTaskHandle xTaskToResume )
+ {
+ tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
+
+ /* It does not make sense to resume the calling task. */
+ configASSERT( xTaskToResume );
+
+ /* The parameter cannot be NULL as it is impossible to resume the
+ currently executing task. */
+ if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
+ {
+ taskENTER_CRITICAL();
+ {
+ if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
+ {
+ traceTASK_RESUME( pxTCB );
+
+ /* As we are in a critical section we can access the ready
+ lists even if the scheduler is suspended. */
+ ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ prvAddTaskToReadyList( pxTCB );
+
+ /* We may have just resumed a higher priority task. */
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
+ {
+ /* This yield may not cause the task just resumed to run, but
+ will leave the lists in the correct state for the next yield. */
+ portYIELD_WITHIN_API();
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+ }
+ }
+
+#endif /* INCLUDE_vTaskSuspend */
+
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
+
+ portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume )
+ {
+ portBASE_TYPE xYieldRequired = pdFALSE;
+ tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
+ unsigned portBASE_TYPE uxSavedInterruptStatus;
+
+ configASSERT( xTaskToResume );
+
+ /* RTOS ports that support interrupt nesting have the concept of a
+ maximum system call (or maximum API call) interrupt priority.
+ Interrupts that are above the maximum system call priority are keep
+ permanently enabled, even when the RTOS kernel is in a critical section,
+ but cannot make any calls to FreeRTOS API functions. If configASSERT()
+ is defined in FreeRTOSConfig.h then
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ failure if a FreeRTOS API function is called from an interrupt that has
+ been assigned a priority above the configured maximum system call
+ priority. Only FreeRTOS functions that end in FromISR can be called
+ from interrupts that have been assigned a priority at or (logically)
+ below the maximum system call interrupt priority. FreeRTOS maintains a
+ separate interrupt safe API to ensure interrupt entry is as fast and as
+ simple as possible. More information (albeit Cortex-M specific) is
+ provided on the following link:
+ http://www.freertos.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
+ {
+ traceTASK_RESUME_FROM_ISR( pxTCB );
+
+ if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
+ {
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
+ {
+ xYieldRequired = pdTRUE;
+ }
+
+ ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ prvAddTaskToReadyList( pxTCB );
+ }
+ else
+ {
+ /* We cannot access the delayed or ready lists, so will hold this
+ task pending until the scheduler is resumed, at which point a
+ yield will be performed if necessary. */
+ vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
+ }
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xYieldRequired;
+ }
+
+#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+void vTaskStartScheduler( void )
+{
+portBASE_TYPE xReturn;
+
+ /* Add the idle task at the lowest priority. */
+ #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
+ {
+ /* Create the idle task, storing its handle in xIdleTaskHandle so it can
+ be returned by the xTaskGetIdleTaskHandle() function. */
+ xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
+ }
+ #else
+ {
+ /* Create the idle task without storing its handle. */
+ xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
+ }
+ #endif /* INCLUDE_xTaskGetIdleTaskHandle */
+
+ #if ( configUSE_TIMERS == 1 )
+ {
+ if( xReturn == pdPASS )
+ {
+ xReturn = xTimerCreateTimerTask();
+ }
+ }
+ #endif /* configUSE_TIMERS */
+
+ if( xReturn == pdPASS )
+ {
+ /* Interrupts are turned off here, to ensure a tick does not occur
+ before or during the call to xPortStartScheduler(). The stacks of
+ the created tasks contain a status word with interrupts switched on
+ so interrupts will automatically get re-enabled when the first task
+ starts to run. */
+ portDISABLE_INTERRUPTS();
+
+ #if ( configUSE_NEWLIB_REENTRANT == 1 )
+ {
+ /* Switch Newlib's _impure_ptr variable to point to the _reent
+ structure specific to the task that will run first. */
+ _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
+ }
+ #endif /* configUSE_NEWLIB_REENTRANT */
+
+ xSchedulerRunning = pdTRUE;
+ xTickCount = ( portTickType ) 0U;
+
+ /* If configGENERATE_RUN_TIME_STATS is defined then the following
+ macro must be defined to configure the timer/counter used to generate
+ the run time counter time base. */
+ portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
+
+ /* Setting up the timer tick is hardware specific and thus in the
+ portable interface. */
+ if( xPortStartScheduler() != pdFALSE )
+ {
+ /* Should not reach here as if the scheduler is running the
+ function will not return. */
+ }
+ else
+ {
+ /* Should only reach here if a task calls xTaskEndScheduler(). */
+ }
+ }
+ else
+ {
+ /* This line will only be reached if the kernel could not be started,
+ because there was not enough FreeRTOS heap to create the idle task
+ or the timer task. */
+ configASSERT( xReturn );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vTaskEndScheduler( void )
+{
+ /* Stop the scheduler interrupts and call the portable scheduler end
+ routine so the original ISRs can be restored if necessary. The port
+ layer must ensure interrupts enable bit is left in the correct state. */
+ portDISABLE_INTERRUPTS();
+ xSchedulerRunning = pdFALSE;
+ vPortEndScheduler();
+}
+/*----------------------------------------------------------*/
+
+void vTaskSuspendAll( void )
+{
+ /* A critical section is not required as the variable is of type
+ portBASE_TYPE. */
+ ++uxSchedulerSuspended;
+}
+/*----------------------------------------------------------*/
+
+#if ( configUSE_TICKLESS_IDLE != 0 )
+
+ static portTickType prvGetExpectedIdleTime( void )
+ {
+ portTickType xReturn;
+
+ if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
+ {
+ xReturn = 0;
+ }
+ else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
+ {
+ /* There are other idle priority tasks in the ready state. If
+ time slicing is used then the very next tick interrupt must be
+ processed. */
+ xReturn = 0;
+ }
+ else
+ {
+ xReturn = xNextTaskUnblockTime - xTickCount;
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_TICKLESS_IDLE */
+/*----------------------------------------------------------*/
+
+signed portBASE_TYPE xTaskResumeAll( void )
+{
+tskTCB *pxTCB;
+portBASE_TYPE xAlreadyYielded = pdFALSE;
+
+ /* If uxSchedulerSuspended is zero then this function does not match a
+ previous call to vTaskSuspendAll(). */
+ configASSERT( uxSchedulerSuspended );
+
+ /* It is possible that an ISR caused a task to be removed from an event
+ list while the scheduler was suspended. If this was the case then the
+ removed task will have been added to the xPendingReadyList. Once the
+ scheduler has been resumed it is safe to move all the pending ready
+ tasks from this list into their appropriate ready list. */
+ taskENTER_CRITICAL();
+ {
+ --uxSchedulerSuspended;
+
+ if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
+ {
+ if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U )
+ {
+ /* Move any readied tasks from the pending list into the
+ appropriate ready list. */
+ while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
+ {
+ pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
+ ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ prvAddTaskToReadyList( pxTCB );
+
+ /* If we have moved a task that has a priority higher than
+ the current task then we should yield. */
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
+ {
+ xYieldPending = pdTRUE;
+ }
+ }
+
+ /* If any ticks occurred while the scheduler was suspended then
+ they should be processed now. This ensures the tick count does not
+ slip, and that any delayed tasks are resumed at the correct time. */
+ if( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U )
+ {
+ while( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U )
+ {
+ if( xTaskIncrementTick() != pdFALSE )
+ {
+ xYieldPending = pdTRUE;
+ }
+ --uxPendedTicks;
+ }
+ }
+
+ if( xYieldPending == pdTRUE )
+ {
+ xAlreadyYielded = pdTRUE;
+ portYIELD_WITHIN_API();
+ }
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xAlreadyYielded;
+}
+/*-----------------------------------------------------------*/
+
+portTickType xTaskGetTickCount( void )
+{
+portTickType xTicks;
+
+ /* Critical section required if running on a 16 bit processor. */
+ taskENTER_CRITICAL();
+ {
+ xTicks = xTickCount;
+ }
+ taskEXIT_CRITICAL();
+
+ return xTicks;
+}
+/*-----------------------------------------------------------*/
+
+portTickType xTaskGetTickCountFromISR( void )
+{
+portTickType xReturn;
+unsigned portBASE_TYPE uxSavedInterruptStatus;
+
+ /* RTOS ports that support interrupt nesting have the concept of a maximum
+ system call (or maximum API call) interrupt priority. Interrupts that are
+ above the maximum system call priority are keep permanently enabled, even
+ when the RTOS kernel is in a critical section, but cannot make any calls to
+ FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
+ then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ failure if a FreeRTOS API function is called from an interrupt that has been
+ assigned a priority above the configured maximum system call priority.
+ Only FreeRTOS functions that end in FromISR can be called from interrupts
+ that have been assigned a priority at or (logically) below the maximum
+ system call interrupt priority. FreeRTOS maintains a separate interrupt
+ safe API to ensure interrupt entry is as fast and as simple as possible.
+ More information (albeit Cortex-M specific) is provided on the following
+ link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ xReturn = xTickCount;
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
+{
+ /* A critical section is not required because the variables are of type
+ portBASE_TYPE. */
+ return uxCurrentNumberOfTasks;
+}
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_pcTaskGetTaskName == 1 )
+
+ signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery )
+ {
+ tskTCB *pxTCB;
+
+ /* If null is passed in here then the name of the calling task is being queried. */
+ pxTCB = prvGetTCBFromHandle( xTaskToQuery );
+ configASSERT( pxTCB );
+ return &( pxTCB->pcTaskName[ 0 ] );
+ }
+
+#endif /* INCLUDE_pcTaskGetTaskName */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, unsigned portBASE_TYPE uxArraySize, unsigned long *pulTotalRunTime )
+ {
+ unsigned portBASE_TYPE uxTask = 0, uxQueue = configMAX_PRIORITIES;
+
+ vTaskSuspendAll();
+ {
+ /* Is there a space in the array for each task in the system? */
+ if( uxArraySize >= uxCurrentNumberOfTasks )
+ {
+ /* Fill in an xTaskStatusType structure with information on each
+ task in the Ready state. */
+ do
+ {
+ uxQueue--;
+ uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
+
+ } while( uxQueue > ( unsigned portBASE_TYPE ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ /* Fill in an xTaskStatusType structure with information on each
+ task in the Blocked state. */
+ uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxDelayedTaskList, eBlocked );
+ uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxOverflowDelayedTaskList, eBlocked );
+
+ #if( INCLUDE_vTaskDelete == 1 )
+ {
+ /* Fill in an xTaskStatusType structure with information on
+ each task that has been deleted but not yet cleaned up. */
+ uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
+ }
+ #endif
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ {
+ /* Fill in an xTaskStatusType structure with information on
+ each task in the Suspended state. */
+ uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
+ }
+ #endif
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1)
+ {
+ if( pulTotalRunTime != NULL )
+ {
+ #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
+ portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
+ #else
+ *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
+ #endif
+ }
+ }
+ #else
+ {
+ if( pulTotalRunTime != NULL )
+ {
+ *pulTotalRunTime = 0;
+ }
+ }
+ #endif
+ }
+ }
+ ( void ) xTaskResumeAll();
+
+ return uxTask;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
+
+ xTaskHandle xTaskGetIdleTaskHandle( void )
+ {
+ /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
+ started, then xIdleTaskHandle will be NULL. */
+ configASSERT( ( xIdleTaskHandle != NULL ) );
+ return xIdleTaskHandle;
+ }
+
+#endif /* INCLUDE_xTaskGetIdleTaskHandle */
+/*----------------------------------------------------------*/
+
+/* This conditional compilation should use inequality to 0, not equality to 1.
+This is to ensure vTaskStepTick() is available when user defined low power mode
+implementations require configUSE_TICKLESS_IDLE to be set to a value other than
+1. */
+#if ( configUSE_TICKLESS_IDLE != 0 )
+
+ void vTaskStepTick( portTickType xTicksToJump )
+ {
+ /* Correct the tick count value after a period during which the tick
+ was suppressed. Note this does *not* call the tick hook function for
+ each stepped tick. */
+ configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
+ xTickCount += xTicksToJump;
+ traceINCREASE_TICK_COUNT( xTicksToJump );
+ }
+
+#endif /* configUSE_TICKLESS_IDLE */
+/*----------------------------------------------------------*/
+
+portBASE_TYPE xTaskIncrementTick( void )
+{
+tskTCB * pxTCB;
+portTickType xItemValue;
+portBASE_TYPE xSwitchRequired = pdFALSE;
+
+ /* Called by the portable layer each time a tick interrupt occurs.
+ Increments the tick then checks to see if the new tick value will cause any
+ tasks to be unblocked. */
+ traceTASK_INCREMENT_TICK( xTickCount );
+ if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
+ {
+ /* Increment the RTOS tick, switching the delayed and overflowed
+ delayed lists if it wraps to 0. */
+ ++xTickCount;
+
+ {
+ /* Minor optimisation. The tick count cannot change in this
+ block. */
+ const portTickType xConstTickCount = xTickCount;
+
+ if( xConstTickCount == ( portTickType ) 0U )
+ {
+ taskSWITCH_DELAYED_LISTS();
+ }
+
+ /* See if this tick has made a timeout expire. Tasks are stored in the
+ queue in the order of their wake time - meaning once one tasks has been
+ found whose block time has not expired there is no need not look any
+ further down the list. */
+ if( xConstTickCount >= xNextTaskUnblockTime )
+ {
+ for( ;; )
+ {
+ if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
+ {
+ /* The delayed list is empty. Set xNextTaskUnblockTime to
+ the maximum possible value so it is extremely unlikely that
+ the if( xTickCount >= xNextTaskUnblockTime ) test will pass
+ next time through. */
+ xNextTaskUnblockTime = portMAX_DELAY;
+ break;
+ }
+ else
+ {
+ /* The delayed list is not empty, get the value of the item
+ at the head of the delayed list. This is the time at which
+ the task at the head of the delayed list must be removed
+ from the Blocked state. */
+ pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
+ xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
+
+ if( xConstTickCount < xItemValue )
+ {
+ /* It is not time to unblock this item yet, but the item
+ value is the time at which the task at the head of the
+ blocked list must be removed from the Blocked state -
+ so record the item value in xNextTaskUnblockTime. */
+ xNextTaskUnblockTime = xItemValue;
+ break;
+ }
+
+ /* It is time to remove the item from the Blocked state. */
+ ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+
+ /* Is the task waiting on an event also? If so remove it
+ from the event list. */
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
+ }
+
+ /* Place the unblocked task into the appropriate ready
+ list. */
+ prvAddTaskToReadyList( pxTCB );
+
+ /* A task being unblocked cannot cause an immediate context
+ switch if preemption is turned off. */
+ #if ( configUSE_PREEMPTION == 1 )
+ {
+ /* Preemption is on, but a context switch should only
+ be performed if the unblocked task has a priority that
+ is equal to or higher than the currently executing
+ task. */
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
+ {
+ xSwitchRequired = pdTRUE;
+ }
+ }
+ #endif /* configUSE_PREEMPTION */
+ }
+ }
+ }
+ }
+
+ /* Tasks of equal priority to the currently running task will share
+ processing time (time slice) if preemption is on, and the application
+ writer has not explicitly turned time slicing off. */
+ #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
+ {
+ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 1 )
+ {
+ xSwitchRequired = pdTRUE;
+ }
+ }
+ #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
+
+ #if ( configUSE_TICK_HOOK == 1 )
+ {
+ /* Guard against the tick hook being called when the pended tick
+ count is being unwound (when the scheduler is being unlocked). */
+ if( uxPendedTicks == ( unsigned portBASE_TYPE ) 0U )
+ {
+ vApplicationTickHook();
+ }
+ }
+ #endif /* configUSE_TICK_HOOK */
+ }
+ else
+ {
+ ++uxPendedTicks;
+
+ /* The tick hook gets called at regular intervals, even if the
+ scheduler is locked. */
+ #if ( configUSE_TICK_HOOK == 1 )
+ {
+ vApplicationTickHook();
+ }
+ #endif
+ }
+
+ #if ( configUSE_PREEMPTION == 1 )
+ {
+ if( xYieldPending != pdFALSE )
+ {
+ xSwitchRequired = pdTRUE;
+ }
+ }
+ #endif /* configUSE_PREEMPTION */
+
+ return xSwitchRequired;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+ void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction )
+ {
+ tskTCB *xTCB;
+
+ /* If xTask is NULL then we are setting our own task hook. */
+ if( xTask == NULL )
+ {
+ xTCB = ( tskTCB * ) pxCurrentTCB;
+ }
+ else
+ {
+ xTCB = ( tskTCB * ) xTask;
+ }
+
+ /* Save the hook function in the TCB. A critical section is required as
+ the value can be accessed from an interrupt. */
+ taskENTER_CRITICAL();
+ xTCB->pxTaskTag = pxHookFunction;
+ taskEXIT_CRITICAL();
+ }
+
+#endif /* configUSE_APPLICATION_TASK_TAG */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+ pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask )
+ {
+ tskTCB *xTCB;
+ pdTASK_HOOK_CODE xReturn;
+
+ /* If xTask is NULL then we are setting our own task hook. */
+ if( xTask == NULL )
+ {
+ xTCB = ( tskTCB * ) pxCurrentTCB;
+ }
+ else
+ {
+ xTCB = ( tskTCB * ) xTask;
+ }
+
+ /* Save the hook function in the TCB. A critical section is required as
+ the value can be accessed from an interrupt. */
+ taskENTER_CRITICAL();
+ xReturn = xTCB->pxTaskTag;
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+ }
+
+#endif /* configUSE_APPLICATION_TASK_TAG */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+ portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter )
+ {
+ tskTCB *xTCB;
+ portBASE_TYPE xReturn;
+
+ /* If xTask is NULL then we are calling our own task hook. */
+ if( xTask == NULL )
+ {
+ xTCB = ( tskTCB * ) pxCurrentTCB;
+ }
+ else
+ {
+ xTCB = ( tskTCB * ) xTask;
+ }
+
+ if( xTCB->pxTaskTag != NULL )
+ {
+ xReturn = xTCB->pxTaskTag( pvParameter );
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_APPLICATION_TASK_TAG */
+/*-----------------------------------------------------------*/
+
+void vTaskSwitchContext( void )
+{
+ if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
+ {
+ /* The scheduler is currently suspended - do not allow a context
+ switch. */
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ xYieldPending = pdFALSE;
+ traceTASK_SWITCHED_OUT();
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ {
+ #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
+ portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
+ #else
+ ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
+ #endif
+
+ /* Add the amount of time the task has been running to the
+ accumulated time so far. The time the task started running was
+ stored in ulTaskSwitchedInTime. Note that there is no overflow
+ protection here so count values are only valid until the timer
+ overflows. The guard against negative values is to protect
+ against suspect run time stat counter implementations - which
+ are provided by the application, not the kernel. */
+ if( ulTotalRunTime > ulTaskSwitchedInTime )
+ {
+ pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
+ }
+ ulTaskSwitchedInTime = ulTotalRunTime;
+ }
+ #endif /* configGENERATE_RUN_TIME_STATS */
+
+ taskFIRST_CHECK_FOR_STACK_OVERFLOW();
+ taskSECOND_CHECK_FOR_STACK_OVERFLOW();
+
+ taskSELECT_HIGHEST_PRIORITY_TASK();
+
+ traceTASK_SWITCHED_IN();
+
+ #if ( configUSE_NEWLIB_REENTRANT == 1 )
+ {
+ /* Switch Newlib's _impure_ptr variable to point to the _reent
+ structure specific to this task. */
+ _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
+ }
+ #endif /* configUSE_NEWLIB_REENTRANT */
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait )
+{
+portTickType xTimeToWake;
+
+ configASSERT( pxEventList );
+
+ /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
+ SCHEDULER SUSPENDED. */
+
+ /* Place the event list item of the TCB in the appropriate event list.
+ This is placed in the list in priority order so the highest priority task
+ is the first to be woken by the event. */
+ vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
+
+ /* We must remove ourselves from the ready list before adding ourselves
+ to the blocked list as the same list item is used for both lists. We have
+ exclusive access to the ready lists as the scheduler is locked. */
+ if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* The current task must be in a ready list, so there is no need to
+ check, and the port reset macro can be called directly. */
+ portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
+ }
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ {
+ if( xTicksToWait == portMAX_DELAY )
+ {
+ /* Add ourselves to the suspended task list instead of a delayed task
+ list to ensure we are not woken by a timing event. We will block
+ indefinitely. */
+ vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
+ }
+ else
+ {
+ /* Calculate the time at which the task should be woken if the event does
+ not occur. This may overflow but this doesn't matter. */
+ xTimeToWake = xTickCount + xTicksToWait;
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
+ }
+ }
+ #else /* INCLUDE_vTaskSuspend */
+ {
+ /* Calculate the time at which the task should be woken if the event does
+ not occur. This may overflow but this doesn't matter. */
+ xTimeToWake = xTickCount + xTicksToWait;
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
+ }
+ #endif /* INCLUDE_vTaskSuspend */
+}
+/*-----------------------------------------------------------*/
+
+#if configUSE_TIMERS == 1
+
+ void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait )
+ {
+ portTickType xTimeToWake;
+
+ configASSERT( pxEventList );
+
+ /* This function should not be called by application code hence the
+ 'Restricted' in its name. It is not part of the public API. It is
+ designed for use by kernel code, and has special calling requirements -
+ it should be called from a critical section. */
+
+
+ /* Place the event list item of the TCB in the appropriate event list.
+ In this case it is assume that this is the only task that is going to
+ be waiting on this event list, so the faster vListInsertEnd() function
+ can be used in place of vListInsert. */
+ vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
+
+ /* We must remove this task from the ready list before adding it to the
+ blocked list as the same list item is used for both lists. This
+ function is called form a critical section. */
+ if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
+ {
+ /* The current task must be in a ready list, so there is no need to
+ check, and the port reset macro can be called directly. */
+ portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
+ }
+
+ /* Calculate the time at which the task should be woken if the event does
+ not occur. This may overflow but this doesn't matter. */
+ xTimeToWake = xTickCount + xTicksToWait;
+
+ traceTASK_DELAY_UNTIL();
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
+ }
+
+#endif /* configUSE_TIMERS */
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )
+{
+tskTCB *pxUnblockedTCB;
+portBASE_TYPE xReturn;
+
+ /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
+ SCHEDULER SUSPENDED. It can also be called from within an ISR. */
+
+ /* The event list is sorted in priority order, so we can remove the
+ first in the list, remove the TCB from the delayed list, and add
+ it to the ready list.
+
+ If an event is for a queue that is locked then this function will never
+ get called - the lock count on the queue will get modified instead. This
+ means we can always expect exclusive access to the event list here.
+
+ This function assumes that a check has already been made to ensure that
+ pxEventList is not empty. */
+ pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
+ configASSERT( pxUnblockedTCB );
+ ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
+
+ if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
+ {
+ ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
+ prvAddTaskToReadyList( pxUnblockedTCB );
+ }
+ else
+ {
+ /* We cannot access the delayed or ready lists, so will hold this
+ task pending until the scheduler is resumed. */
+ vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
+ }
+
+ if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority )
+ {
+ /* Return true if the task removed from the event list has
+ a higher priority than the calling task. This allows
+ the calling task to know if it should force a context
+ switch now. */
+ xReturn = pdTRUE;
+
+ /* Mark that a yield is pending in case the user is not using the
+ "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
+{
+ configASSERT( pxTimeOut );
+ pxTimeOut->xOverflowCount = xNumOfOverflows;
+ pxTimeOut->xTimeOnEntering = xTickCount;
+}
+/*-----------------------------------------------------------*/
+
+portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )
+{
+portBASE_TYPE xReturn;
+
+ configASSERT( pxTimeOut );
+ configASSERT( pxTicksToWait );
+
+ taskENTER_CRITICAL();
+ {
+ /* Minor optimisation. The tick count cannot change in this block. */
+ const portTickType xConstTickCount = xTickCount;
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
+ the maximum block time then the task should block indefinitely, and
+ therefore never time out. */
+ if( *pxTicksToWait == portMAX_DELAY )
+ {
+ xReturn = pdFALSE;
+ }
+ else /* We are not blocking indefinitely, perform the checks below. */
+ #endif
+
+ if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
+ {
+ /* The tick count is greater than the time at which vTaskSetTimeout()
+ was called, but has also overflowed since vTaskSetTimeOut() was called.
+ It must have wrapped all the way around and gone past us again. This
+ passed since vTaskSetTimeout() was called. */
+ xReturn = pdTRUE;
+ }
+ else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )
+ {
+ /* Not a genuine timeout. Adjust parameters for time remaining. */
+ *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
+ vTaskSetTimeOutState( pxTimeOut );
+ xReturn = pdFALSE;
+ }
+ else
+ {
+ xReturn = pdTRUE;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vTaskMissedYield( void )
+{
+ xYieldPending = pdTRUE;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask )
+ {
+ unsigned portBASE_TYPE uxReturn;
+ tskTCB *pxTCB;
+
+ if( xTask != NULL )
+ {
+ pxTCB = ( tskTCB * ) xTask;
+ uxReturn = pxTCB->uxTaskNumber;
+ }
+ else
+ {
+ uxReturn = 0U;
+ }
+
+ return uxReturn;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle )
+ {
+ tskTCB *pxTCB;
+
+ if( xTask != NULL )
+ {
+ pxTCB = ( tskTCB * ) xTask;
+ pxTCB->uxTaskNumber = uxHandle;
+ }
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+
+/*
+ * -----------------------------------------------------------
+ * The Idle task.
+ * ----------------------------------------------------------
+ *
+ * The portTASK_FUNCTION() macro is used to allow port/compiler specific
+ * language extensions. The equivalent prototype for this function is:
+ *
+ * void prvIdleTask( void *pvParameters );
+ *
+ */
+static portTASK_FUNCTION( prvIdleTask, pvParameters )
+{
+ /* Stop warnings. */
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* See if any tasks have been deleted. */
+ prvCheckTasksWaitingTermination();
+
+ #if ( configUSE_PREEMPTION == 0 )
+ {
+ /* If we are not using preemption we keep forcing a task switch to
+ see if any other task has become available. If we are using
+ preemption we don't need to do this as any task becoming available
+ will automatically get the processor anyway. */
+ taskYIELD();
+ }
+ #endif /* configUSE_PREEMPTION */
+
+ #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
+ {
+ /* When using preemption tasks of equal priority will be
+ timesliced. If a task that is sharing the idle priority is ready
+ to run then the idle task should yield before the end of the
+ timeslice.
+
+ A critical region is not required here as we are just reading from
+ the list, and an occasional incorrect value will not matter. If
+ the ready list at the idle priority contains more than one task
+ then a task other than the idle task is ready to execute. */
+ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 )
+ {
+ taskYIELD();
+ }
+ }
+ #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
+
+ #if ( configUSE_IDLE_HOOK == 1 )
+ {
+ extern void vApplicationIdleHook( void );
+
+ /* Call the user defined function from within the idle task. This
+ allows the application designer to add background functionality
+ without the overhead of a separate task.
+ NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
+ CALL A FUNCTION THAT MIGHT BLOCK. */
+ vApplicationIdleHook();
+ }
+ #endif /* configUSE_IDLE_HOOK */
+
+ /* This conditional compilation should use inequality to 0, not equality
+ to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
+ user defined low power mode implementations require
+ configUSE_TICKLESS_IDLE to be set to a value other than 1. */
+ #if ( configUSE_TICKLESS_IDLE != 0 )
+ {
+ portTickType xExpectedIdleTime;
+
+ /* It is not desirable to suspend then resume the scheduler on
+ each iteration of the idle task. Therefore, a preliminary
+ test of the expected idle time is performed without the
+ scheduler suspended. The result here is not necessarily
+ valid. */
+ xExpectedIdleTime = prvGetExpectedIdleTime();
+
+ if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
+ {
+ vTaskSuspendAll();
+ {
+ /* Now the scheduler is suspended, the expected idle
+ time can be sampled again, and this time its value can
+ be used. */
+ configASSERT( xNextTaskUnblockTime >= xTickCount );
+ xExpectedIdleTime = prvGetExpectedIdleTime();
+
+ if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
+ {
+ traceLOW_POWER_IDLE_BEGIN();
+ portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
+ traceLOW_POWER_IDLE_END();
+ }
+ }
+ ( void ) xTaskResumeAll();
+ }
+ }
+ #endif /* configUSE_TICKLESS_IDLE */
+ }
+}
+/*-----------------------------------------------------------*/
+
+#if configUSE_TICKLESS_IDLE != 0
+
+ eSleepModeStatus eTaskConfirmSleepModeStatus( void )
+ {
+ eSleepModeStatus eReturn = eStandardSleep;
+
+ if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
+ {
+ /* A task was made ready while the scheduler was suspended. */
+ eReturn = eAbortSleep;
+ }
+ else if( xYieldPending != pdFALSE )
+ {
+ /* A yield was pended while the scheduler was suspended. */
+ eReturn = eAbortSleep;
+ }
+ else
+ {
+ #if configUSE_TIMERS == 0
+ {
+ /* The idle task exists in addition to the application tasks. */
+ const unsigned portBASE_TYPE uxNonApplicationTasks = 1;
+
+ /* If timers are not being used and all the tasks are in the
+ suspended list (which might mean they have an infinite block
+ time rather than actually being suspended) then it is safe to
+ turn all clocks off and just wait for external interrupts. */
+ if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
+ {
+ eReturn = eNoTasksWaitingTimeout;
+ }
+ }
+ #endif /* configUSE_TIMERS */
+ }
+
+ return eReturn;
+ }
+#endif /* configUSE_TICKLESS_IDLE */
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth )
+{
+unsigned portBASE_TYPE x;
+
+ /* Store the task name in the TCB. */
+ for( x = ( unsigned portBASE_TYPE ) 0; x < ( unsigned portBASE_TYPE ) configMAX_TASK_NAME_LEN; x++ )
+ {
+ pxTCB->pcTaskName[ x ] = pcName[ x ];
+
+ /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
+ configMAX_TASK_NAME_LEN characters just in case the memory after the
+ string is not accessible (extremely unlikely). */
+ if( pcName[ x ] == 0x00 )
+ {
+ break;
+ }
+ }
+
+ /* Ensure the name string is terminated in the case that the string length
+ was greater or equal to configMAX_TASK_NAME_LEN. */
+ pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = ( signed char ) '\0';
+
+ /* This is used as an array index so must ensure it's not too large. First
+ remove the privilege bit if one is present. */
+ if( uxPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES )
+ {
+ uxPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U;
+ }
+
+ pxTCB->uxPriority = uxPriority;
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ pxTCB->uxBasePriority = uxPriority;
+ }
+ #endif /* configUSE_MUTEXES */
+
+ vListInitialiseItem( &( pxTCB->xGenericListItem ) );
+ vListInitialiseItem( &( pxTCB->xEventListItem ) );
+
+ /* Set the pxTCB as a link back from the xListItem. This is so we can get
+ back to the containing TCB from a generic item in a list. */
+ listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
+
+ /* Event lists are always in priority order. */
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
+
+ #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+ {
+ pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0U;
+ }
+ #endif /* portCRITICAL_NESTING_IN_TCB */
+
+ #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+ {
+ pxTCB->pxTaskTag = NULL;
+ }
+ #endif /* configUSE_APPLICATION_TASK_TAG */
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ {
+ pxTCB->ulRunTimeCounter = 0UL;
+ }
+ #endif /* configGENERATE_RUN_TIME_STATS */
+
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ {
+ vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
+ }
+ #else /* portUSING_MPU_WRAPPERS */
+ {
+ ( void ) xRegions;
+ ( void ) usStackDepth;
+ }
+ #endif /* portUSING_MPU_WRAPPERS */
+
+ #if ( configUSE_NEWLIB_REENTRANT == 1 )
+ {
+ /* Initialise this task's Newlib reent structure. */
+ _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
+ }
+ #endif /* configUSE_NEWLIB_REENTRANT */
+}
+/*-----------------------------------------------------------*/
+
+#if ( portUSING_MPU_WRAPPERS == 1 )
+
+ void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
+ {
+ tskTCB *pxTCB;
+
+ /* If null is passed in here then we are deleting ourselves. */
+ pxTCB = prvGetTCBFromHandle( xTaskToModify );
+
+ vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
+ }
+
+#endif /* portUSING_MPU_WRAPPERS */
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseTaskLists( void )
+{
+unsigned portBASE_TYPE uxPriority;
+
+ for( uxPriority = ( unsigned portBASE_TYPE ) 0U; uxPriority < ( unsigned portBASE_TYPE ) configMAX_PRIORITIES; uxPriority++ )
+ {
+ vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
+ }
+
+ vListInitialise( &xDelayedTaskList1 );
+ vListInitialise( &xDelayedTaskList2 );
+ vListInitialise( &xPendingReadyList );
+
+ #if ( INCLUDE_vTaskDelete == 1 )
+ {
+ vListInitialise( &xTasksWaitingTermination );
+ }
+ #endif /* INCLUDE_vTaskDelete */
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ {
+ vListInitialise( &xSuspendedTaskList );
+ }
+ #endif /* INCLUDE_vTaskSuspend */
+
+ /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
+ using list2. */
+ pxDelayedTaskList = &xDelayedTaskList1;
+ pxOverflowDelayedTaskList = &xDelayedTaskList2;
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckTasksWaitingTermination( void )
+{
+ #if ( INCLUDE_vTaskDelete == 1 )
+ {
+ portBASE_TYPE xListIsEmpty;
+
+ /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
+ too often in the idle task. */
+ while( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U )
+ {
+ vTaskSuspendAll();
+ xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
+ ( void ) xTaskResumeAll();
+
+ if( xListIsEmpty == pdFALSE )
+ {
+ tskTCB *pxTCB;
+
+ taskENTER_CRITICAL();
+ {
+ pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
+ ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ --uxCurrentNumberOfTasks;
+ --uxTasksDeleted;
+ }
+ taskEXIT_CRITICAL();
+
+ prvDeleteTCB( pxTCB );
+ }
+ }
+ }
+ #endif /* vTaskDelete */
+}
+/*-----------------------------------------------------------*/
+
+static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
+{
+ /* The list item will be inserted in wake time order. */
+ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
+
+ if( xTimeToWake < xTickCount )
+ {
+ /* Wake time has overflowed. Place this item in the overflow list. */
+ vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
+ }
+ else
+ {
+ /* The wake time has not overflowed, so we can use the current block list. */
+ vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
+
+ /* If the task entering the blocked state was placed at the head of the
+ list of blocked tasks then xNextTaskUnblockTime needs to be updated
+ too. */
+ if( xTimeToWake < xNextTaskUnblockTime )
+ {
+ xNextTaskUnblockTime = xTimeToWake;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer )
+{
+tskTCB *pxNewTCB;
+
+ /* Allocate space for the TCB. Where the memory comes from depends on
+ the implementation of the port malloc function. */
+ pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) );
+
+ if( pxNewTCB != NULL )
+ {
+ /* Allocate space for the stack used by the task being created.
+ The base of the stack memory stored in the TCB so the task can
+ be deleted later if required. */
+ pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ if( pxNewTCB->pxStack == NULL )
+ {
+ /* Could not allocate the stack. Delete the allocated TCB. */
+ vPortFree( pxNewTCB );
+ pxNewTCB = NULL;
+ }
+ else
+ {
+ /* Just to help debugging. */
+ ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ) );
+ }
+ }
+
+ return pxNewTCB;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState )
+ {
+ volatile tskTCB *pxNextTCB, *pxFirstTCB;
+ unsigned portBASE_TYPE uxTask = 0;
+
+ if( listCURRENT_LIST_LENGTH( pxList ) > ( unsigned portBASE_TYPE ) 0 )
+ {
+ listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
+
+ /* Populate an xTaskStatusType structure within the
+ pxTaskStatusArray array for each task that is referenced from
+ pxList. See the definition of xTaskStatusType in task.h for the
+ meaning of each xTaskStatusType structure member. */
+ do
+ {
+ listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
+
+ pxTaskStatusArray[ uxTask ].xHandle = ( xTaskHandle ) pxNextTCB;
+ pxTaskStatusArray[ uxTask ].pcTaskName = ( const signed char * ) &( pxNextTCB->pcTaskName [ 0 ] );
+ pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;
+ pxTaskStatusArray[ uxTask ].eCurrentState = eState;
+ pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;
+ }
+ #else
+ {
+ pxTaskStatusArray[ uxTask ].uxBasePriority = 0;
+ }
+ #endif
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ {
+ pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;
+ }
+ #else
+ {
+ pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;
+ }
+ #endif
+
+ #if ( portSTACK_GROWTH > 0 )
+ {
+ ppxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack );
+ }
+ #else
+ {
+ pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
+ }
+ #endif
+
+ uxTask++;
+
+ } while( pxNextTCB != pxFirstTCB );
+ }
+
+ return uxTask;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
+
+ static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte )
+ {
+ unsigned short usCount = 0U;
+
+ while( *pucStackByte == tskSTACK_FILL_BYTE )
+ {
+ pucStackByte -= portSTACK_GROWTH;
+ usCount++;
+ }
+
+ usCount /= sizeof( portSTACK_TYPE );
+
+ return usCount;
+ }
+
+#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
+
+ unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask )
+ {
+ tskTCB *pxTCB;
+ unsigned char *pcEndOfStack;
+ unsigned portBASE_TYPE uxReturn;
+
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ #if portSTACK_GROWTH < 0
+ {
+ pcEndOfStack = ( unsigned char * ) pxTCB->pxStack;
+ }
+ #else
+ {
+ pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack;
+ }
+ #endif
+
+ uxReturn = ( unsigned portBASE_TYPE ) prvTaskCheckFreeStackSpace( pcEndOfStack );
+
+ return uxReturn;
+ }
+
+#endif /* INCLUDE_uxTaskGetStackHighWaterMark */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelete == 1 )
+
+ static void prvDeleteTCB( tskTCB *pxTCB )
+ {
+ /* This call is required specifically for the TriCore port. It must be
+ above the vPortFree() calls. The call is also used by ports/demos that
+ want to allocate and clean RAM statically. */
+ portCLEAN_UP_TCB( pxTCB );
+
+ /* Free up the memory allocated by the scheduler for the task. It is up to
+ the task to free any memory allocated at the application level. */
+ vPortFreeAligned( pxTCB->pxStack );
+ vPortFree( pxTCB );
+ }
+
+#endif /* INCLUDE_vTaskDelete */
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
+
+ xTaskHandle xTaskGetCurrentTaskHandle( void )
+ {
+ xTaskHandle xReturn;
+
+ /* A critical section is not required as this is not called from
+ an interrupt and the current TCB will always be the same for any
+ individual execution thread. */
+ xReturn = pxCurrentTCB;
+
+ return xReturn;
+ }
+
+#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+
+ portBASE_TYPE xTaskGetSchedulerState( void )
+ {
+ portBASE_TYPE xReturn;
+
+ if( xSchedulerRunning == pdFALSE )
+ {
+ xReturn = taskSCHEDULER_NOT_STARTED;
+ }
+ else
+ {
+ if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
+ {
+ xReturn = taskSCHEDULER_RUNNING;
+ }
+ else
+ {
+ xReturn = taskSCHEDULER_SUSPENDED;
+ }
+ }
+
+ return xReturn;
+ }
+
+#endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+ void vTaskPriorityInherit( xTaskHandle const pxMutexHolder )
+ {
+ tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
+
+ /* If the mutex was given back by an interrupt while the queue was
+ locked then the mutex holder might now be NULL. */
+ if( pxMutexHolder != NULL )
+ {
+ if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
+ {
+ /* Adjust the mutex holder state to account for its new priority. */
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ /* If the task being modified is in the ready state it will need to
+ be moved into a new list. */
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
+ {
+ if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
+ {
+ taskRESET_READY_PRIORITY( pxTCB->uxPriority );
+ }
+
+ /* Inherit the priority before being moved into the new list. */
+ pxTCB->uxPriority = pxCurrentTCB->uxPriority;
+ prvAddTaskToReadyList( pxTCB );
+ }
+ else
+ {
+ /* Just inherit the priority. */
+ pxTCB->uxPriority = pxCurrentTCB->uxPriority;
+ }
+
+ traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
+ }
+ }
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+ void vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder )
+ {
+ tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
+
+ if( pxMutexHolder != NULL )
+ {
+ if( pxTCB->uxPriority != pxTCB->uxBasePriority )
+ {
+ /* We must be the running task to be able to give the mutex back.
+ Remove ourselves from the ready list we currently appear in. */
+ if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
+ {
+ taskRESET_READY_PRIORITY( pxTCB->uxPriority );
+ }
+
+ /* Disinherit the priority before adding the task into the new
+ ready list. */
+ traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
+ pxTCB->uxPriority = pxTCB->uxBasePriority;
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ prvAddTaskToReadyList( pxTCB );
+ }
+ }
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+
+ void vTaskEnterCritical( void )
+ {
+ portDISABLE_INTERRUPTS();
+
+ if( xSchedulerRunning != pdFALSE )
+ {
+ ( pxCurrentTCB->uxCriticalNesting )++;
+ }
+ }
+
+#endif /* portCRITICAL_NESTING_IN_TCB */
+/*-----------------------------------------------------------*/
+
+#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+
+ void vTaskExitCritical( void )
+ {
+ if( xSchedulerRunning != pdFALSE )
+ {
+ if( pxCurrentTCB->uxCriticalNesting > 0U )
+ {
+ ( pxCurrentTCB->uxCriticalNesting )--;
+
+ if( pxCurrentTCB->uxCriticalNesting == 0U )
+ {
+ portENABLE_INTERRUPTS();
+ }
+ }
+ }
+ }
+
+#endif /* portCRITICAL_NESTING_IN_TCB */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
+
+ void vTaskList( signed char *pcWriteBuffer )
+ {
+ xTaskStatusType *pxTaskStatusArray;
+ volatile unsigned portBASE_TYPE uxArraySize, x;
+ char cStatus;
+
+ /*
+ * PLEASE NOTE:
+ *
+ * This function is provided for convenience only, and is used by many
+ * of the demo applications. Do not consider it to be part of the
+ * scheduler.
+ *
+ * vTaskList() calls uxTaskGetSystemState(), then formats part of the
+ * uxTaskGetSystemState() output into a human readable table that
+ * displays task names, states and stack usage.
+ *
+ * vTaskList() has a dependency on the sprintf() C library function that
+ * might bloat the code size, use a lot of stack, and provide different
+ * results on different platforms. An alternative, tiny, third party,
+ * and limited functionality implementation of sprintf() is provided in
+ * many of the FreeRTOS/Demo sub-directories in a file called
+ * printf-stdarg.c (note printf-stdarg.c does not provide a full
+ * snprintf() implementation!).
+ *
+ * It is recommended that production systems call uxTaskGetSystemState()
+ * directly to get access to raw stats data, rather than indirectly
+ * through a call to vTaskList().
+ */
+
+
+ /* Make sure the write buffer does not contain a string. */
+ *pcWriteBuffer = 0x00;
+
+ /* Take a snapshot of the number of tasks in case it changes while this
+ function is executing. */
+ uxArraySize = uxCurrentNumberOfTasks;
+
+ /* Allocate an array index for each task. */
+ pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) );
+
+ if( pxTaskStatusArray != NULL )
+ {
+ /* Generate the (binary) data. */
+ uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
+
+ /* Create a human readable table from the binary data. */
+ for( x = 0; x < uxArraySize; x++ )
+ {
+ switch( pxTaskStatusArray[ x ].eCurrentState )
+ {
+ case eReady: cStatus = tskREADY_CHAR;
+ break;
+
+ case eBlocked: cStatus = tskBLOCKED_CHAR;
+ break;
+
+ case eSuspended: cStatus = tskSUSPENDED_CHAR;
+ break;
+
+ case eDeleted: cStatus = tskDELETED_CHAR;
+ break;
+
+ default: /* Should not get here, but it is included
+ to prevent static checking errors. */
+ cStatus = 0x00;
+ break;
+ }
+
+ sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
+ pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
+ }
+
+ /* Free the array again. */
+ vPortFree( pxTaskStatusArray );
+ }
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*----------------------------------------------------------*/
+
+#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
+
+ void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
+ {
+ xTaskStatusType *pxTaskStatusArray;
+ volatile unsigned portBASE_TYPE uxArraySize, x;
+ unsigned long ulTotalTime, ulStatsAsPercentage;
+
+ /*
+ * PLEASE NOTE:
+ *
+ * This function is provided for convenience only, and is used by many
+ * of the demo applications. Do not consider it to be part of the
+ * scheduler.
+ *
+ * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
+ * of the uxTaskGetSystemState() output into a human readable table that
+ * displays the amount of time each task has spent in the Running state
+ * in both absolute and percentage terms.
+ *
+ * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
+ * function that might bloat the code size, use a lot of stack, and
+ * provide different results on different platforms. An alternative,
+ * tiny, third party, and limited functionality implementation of
+ * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
+ * a file called printf-stdarg.c (note printf-stdarg.c does not provide
+ * a full snprintf() implementation!).
+ *
+ * It is recommended that production systems call uxTaskGetSystemState()
+ * directly to get access to raw stats data, rather than indirectly
+ * through a call to vTaskGetRunTimeStats().
+ */
+
+ /* Make sure the write buffer does not contain a string. */
+ *pcWriteBuffer = 0x00;
+
+ /* Take a snapshot of the number of tasks in case it changes while this
+ function is executing. */
+ uxArraySize = uxCurrentNumberOfTasks;
+
+ /* Allocate an array index for each task. */
+ pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) );
+
+ if( pxTaskStatusArray != NULL )
+ {
+ /* Generate the (binary) data. */
+ uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
+
+ /* For percentage calculations. */
+ ulTotalTime /= 100UL;
+
+ /* Avoid divide by zero errors. */
+ if( ulTotalTime > 0 )
+ {
+ /* Create a human readable table from the binary data. */
+ for( x = 0; x < uxArraySize; x++ )
+ {
+ /* What percentage of the total run time has the task used?
+ This will always be rounded down to the nearest integer.
+ ulTotalRunTimeDiv100 has already been divided by 100. */
+ ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
+
+ if( ulStatsAsPercentage > 0UL )
+ {
+ #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
+ {
+ sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
+ }
+ #else
+ {
+ /* sizeof( int ) == sizeof( long ) so a smaller
+ printf() library can be used. */
+ sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
+ }
+ #endif
+ }
+ else
+ {
+ /* If the percentage is zero here then the task has
+ consumed less than 1% of the total run time. */
+ #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
+ {
+ sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
+ }
+ #else
+ {
+ /* sizeof( int ) == sizeof( long ) so a smaller
+ printf() library can be used. */
+ sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
+ }
+ #endif
+ }
+
+ pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
+ }
+ }
+
+ /* Free the array again. */
+ vPortFree( pxTaskStatusArray );
+ }
+ }
+
+#endif /* configGENERATE_RUN_TIME_STATS */
+
+
+
diff --git a/source/freertos_blinky/readme.txt b/source/freertos_blinky/readme.txt
new file mode 100644
index 0000000..c3c5e76
--- /dev/null
+++ b/source/freertos_blinky/readme.txt
@@ -0,0 +1,12 @@
+Example description
+Welcome to the FreeRTOS basic blinky example. This example starts up
+FreeRTOS and creates 3 tasks that blink LEDs at different rates.
+
+Special connection requirements
+There are no special connection requirements for this example.
+
+
+Supported boards and board setup:
+ LPCOPEN_11U6X_BOARD_LPCXPRESSO_11U68
+ LPCOPEN_11U6X_BOARD_MANLEY_11U68
+
diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/.cproject b/source/lpc_board_nxp_lpcxpresso_11u68/.cproject
new file mode 100644
index 0000000..ed8ef6a
--- /dev/null
+++ b/source/lpc_board_nxp_lpcxpresso_11u68/.cproject
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<TargetConfig>
+<Properties property_2="LPC11U6x_256K.cfx" property_3="NXP" property_4="LPC11U68" property_count="5" version="100300"/>
+<infoList vendor="NXP">
+<info chip="LPC11U68" flash_driver="LPC11U6x_256K.cfx" match_id="0x0" name="LPC11U68" stub="crt_emu_cm3_gen">
+<chip>
+<name>LPC11U68</name>
+<family>LPC11U6x</family>
+<vendor>NXP (formerly Philips)</vendor>
+<reset board="None" core="Real" sys="Real"/>
+<clock changeable="TRUE" freq="12MHz" is_accurate="TRUE"/>
+<memory can_program="true" id="Flash" is_ro="true" type="Flash"/>
+<memory id="RAM" type="RAM"/>
+<memory id="Periph" is_volatile="true" type="Peripheral"/>
+<memoryInstance derived_from="Flash" id="MFlash256" location="0x0" size="0x40000"/>
+<memoryInstance derived_from="RAM" id="Ram0_32" location="0x10000000" size="0x8000"/>
+<memoryInstance derived_from="RAM" id="Ram1_2" location="0x20000000" size="0x800"/>
+<memoryInstance derived_from="RAM" id="Ram2USB_2" location="0x20004000" size="0x800"/>
+</chip>
+<processor>
+<name gcc_name="cortex-m0">Cortex-M0</name>
+<family>Cortex-M</family>
+</processor>
+</info>
+</infoList>
+</TargetConfig>
+
+
+
+
+
\ No newline at end of file
diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/.gitignore b/source/lpc_board_nxp_lpcxpresso_11u68/.gitignore
new file mode 100644
index 0000000..3df573f
--- /dev/null
+++ b/source/lpc_board_nxp_lpcxpresso_11u68/.gitignore
@@ -0,0 +1 @@
+/Debug/
diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/.project b/source/lpc_board_nxp_lpcxpresso_11u68/.project
new file mode 100644
index 0000000..df8c992
--- /dev/null
+++ b/source/lpc_board_nxp_lpcxpresso_11u68/.project
@@ -0,0 +1,26 @@
+
+
+ lpc_board_nxp_lpcxpresso_11u68
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/.settings/language.settings.xml b/source/lpc_board_nxp_lpcxpresso_11u68/.settings/language.settings.xml
new file mode 100644
index 0000000..8669d52
--- /dev/null
+++ b/source/lpc_board_nxp_lpcxpresso_11u68/.settings/language.settings.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/inc/board.h b/source/lpc_board_nxp_lpcxpresso_11u68/inc/board.h
new file mode 100644
index 0000000..84a20ff
--- /dev/null
+++ b/source/lpc_board_nxp_lpcxpresso_11u68/inc/board.h
@@ -0,0 +1,111 @@
+/*
+ * @brief LPCXpresso 11U68 board file
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __BOARD_H_
+#define __BOARD_H_
+
+#include "chip.h"
+/* board_api.h is included at the bottom of this file after DEBUG setup */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup BOARD_NXP_LPCXPRESSO_11U68 NXP LPC11U68 LPCXpresso board support software API functions
+ * @ingroup LPCOPEN_11U6X_BOARD_LPCXPRESSO_11U68
+ * The board support software API functions provide some simple abstracted
+ * functions used across multiple LPCOpen board examples. See @ref BOARD_COMMON_API
+ * for the functions defined by this board support layer.
+ * @{
+ */
+
+/** @defgroup BOARD_NXP_LPCXPRESSO_11U68_OPTIONS BOARD: NXP LPC11U68 LPCXpresso board build options
+ * This board has options that configure its operation at build-time.
+ * @{
+ */
+
+/** Define DEBUG_ENABLE to enable IO via the DEBUGSTR, DEBUGOUT, and
+ DEBUGIN macros. If not defined, DEBUG* functions will be optimized
+ out of the code at build time.
+ */
+#define DEBUG_ENABLE
+
+/** Define DEBUG_SEMIHOSTING along with DEBUG_ENABLE to enable IO support
+ via semihosting. You may need to use a C library that supports
+ semihosting with this option.
+ */
+// #define DEBUG_SEMIHOSTING
+
+/** Board UART used for debug output and input using the DEBUG* macros. This
+ is also the port used for Board_UARTPutChar, Board_UARTGetChar, and
+ Board_UARTPutSTR functions.
+ */
+#define DEBUG_UART LPC_USART0
+
+/**
+ * @}
+ */
+
+/* Board name */
+#define BOARD_NXP_LPCXPRESSO_11U68
+
+/**
+ * Joystick defines
+ */
+#define JOY_UP 0x01
+#define JOY_DOWN 0x02
+#define JOY_LEFT 0x04
+#define JOY_RIGHT 0x08
+#define JOY_PRESS 0x10
+
+/**
+ * @brief Initialize Joystick
+ * @return Nothing
+ */
+void Board_Joystick_Init(void);
+
+/**
+ * @brief Get Joystick status
+ * @return status of Joystick
+ */
+uint8_t Joystick_GetStatus(void);
+
+/**
+ * @}
+ */
+
+#include "board_api.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BOARD_H_ */
diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/inc/board_api.h b/source/lpc_board_nxp_lpcxpresso_11u68/inc/board_api.h
new file mode 100644
index 0000000..7156104
--- /dev/null
+++ b/source/lpc_board_nxp_lpcxpresso_11u68/inc/board_api.h
@@ -0,0 +1,187 @@
+/*
+ * @brief Common board API functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __BOARD_API_H_
+#define __BOARD_API_H_
+
+#include "lpc_types.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup BOARD_COMMON_API BOARD: Common board functions
+ * @ingroup BOARD_Common
+ * This file contains common board definitions that are shared across
+ * boards and devices. All of these functions do not need to be
+ * implemented for a specific board, but if they are implemented, they
+ * should use this API standard.
+ * @{
+ */
+
+/**
+ * @brief Setup and initialize hardware prior to call to main()
+ * @return None
+ * @note Board_SystemInit() is called prior to the application and sets up system
+ * clocking, memory, and any resources needed prior to the application
+ * starting.
+ */
+void Board_SystemInit(void);
+
+/**
+ * @brief Setup pin multiplexer per board schematics
+ * @return None
+ * @note Board_SetupMuxing() should be called from SystemInit() prior to application
+ * main() is called. So that the PINs are set in proper state.
+ */
+void Board_SetupMuxing(void);
+
+/**
+ * @brief Setup system clocking
+ * @return None
+ * @note This sets up board clocking.
+ */
+void Board_SetupClocking(void);
+
+/**
+ * @brief Setup external system memory
+ * @return None
+ * @note This function is typically called after pin mux setup and clock setup and
+ * sets up any external memory needed by the system (DRAM, SRAM, etc.). Not all
+ * boards need this function.
+ */
+void Board_SetupExtMemory(void);
+
+/**
+ * @brief Set up and initialize all required blocks and functions related to the board hardware.
+ * @return None
+ */
+void Board_Init(void);
+
+/**
+ * @brief Initializes board UART for output, required for printf redirection
+ * @return None
+ */
+void Board_Debug_Init(void);
+
+/**
+ * @brief Sends a single character on the UART, required for printf redirection
+ * @param ch : character to send
+ * @return None
+ */
+void Board_UARTPutChar(char ch);
+
+/**
+ * @brief Get a single character from the UART, required for scanf input
+ * @return EOF if not character was received, or character value
+ */
+int Board_UARTGetChar(void);
+
+/**
+ * @brief Prints a string to the UART
+ * @param str : Terminated string to output
+ * @return None
+ */
+void Board_UARTPutSTR(char *str);
+
+/**
+ * @brief Sets the state of a board LED to on or off
+ * @param LEDNumber : LED number to set state for
+ * @param State : true for on, false for off
+ * @return None
+ */
+void Board_LED_Set(uint8_t LEDNumber, bool State);
+
+/**
+ * @brief Returns the current state of a board LED
+ * @param LEDNumber : LED number to set state for
+ * @return true if the LED is on, otherwise false
+ */
+bool Board_LED_Test(uint8_t LEDNumber);
+
+/**
+ * @brief Toggles the current state of a board LED
+ * @param LEDNumber : LED number to change state for
+ * @return None
+ */
+void Board_LED_Toggle(uint8_t LEDNumber);
+
+/**
+ * @brief Turn on Board LCD Backlight
+ * @param Intensity : Backlight intensity (0 = off, >=1 = on)
+ * @return None
+ * @note On boards where a GPIO is used to control backlight on/off state, a '0' or '1'
+ * value will turn off or on the backlight. On some boards, a non-0 value will
+ * control backlight intensity via a PWN. For PWM systems, the intensity value
+ * is a percentage value between 0 and 100%.
+ */
+void Board_SetLCDBacklight(uint8_t Intensity);
+
+/**
+ * @brief Function prototype for a MS delay function. Board layers or example code may
+ * define this function as needed.
+ */
+typedef void (*p_msDelay_func_t)(uint32_t);
+
+/* The DEBUG* functions are selected based on system configuration.
+ Code that uses the DEBUG* functions will have their I/O routed to
+ the UART, semihosting, or nowhere. */
+#if defined(DEBUG_ENABLE)
+#if defined(DEBUG_SEMIHOSTING)
+#define DEBUGINIT()
+#define DEBUGOUT(...) printf(__VA_ARGS__)
+#define DEBUGSTR(str) printf(str)
+#define DEBUGIN() (int) EOF
+
+#else
+#define DEBUGINIT() Board_Debug_Init()
+#define DEBUGOUT(...) printf(__VA_ARGS__)
+#define DEBUGSTR(str) Board_UARTPutSTR(str)
+#define DEBUGIN() Board_UARTGetChar()
+#endif /* defined(DEBUG_SEMIHOSTING) */
+
+#else
+#define DEBUGINIT()
+#define DEBUGOUT(...)
+#define DEBUGSTR(str)
+#define DEBUGIN() (int) EOF
+#endif /* defined(DEBUG_ENABLE) */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BOARD_API_H_ */
diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/src/board.c b/source/lpc_board_nxp_lpcxpresso_11u68/src/board.c
new file mode 100644
index 0000000..318dcab
--- /dev/null
+++ b/source/lpc_board_nxp_lpcxpresso_11u68/src/board.c
@@ -0,0 +1,188 @@
+/*
+ * @brief NXP LPCXpresso 11U68 board file
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "board.h"
+#include "retarget.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/* System oscillator rate and RTC oscillator rate */
+const uint32_t OscRateIn = 12000000;
+const uint32_t RTCOscRateIn = 32768;
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Sends a character on the UART */
+void Board_UARTPutChar(char ch)
+{
+#if defined(DEBUG_UART)
+ Chip_UART0_SendBlocking(DEBUG_UART, &ch, 1);
+#endif
+}
+
+/* Gets a character from the UART, returns EOF if no character is ready */
+int Board_UARTGetChar(void)
+{
+#if defined(DEBUG_UART)
+ uint8_t data;
+
+ if (Chip_UART0_Read(DEBUG_UART, &data, 1) == 1) {
+ return (int) data;
+ }
+#endif
+ return EOF;
+}
+
+/* Outputs a string on the debug UART */
+void Board_UARTPutSTR(char *str)
+{
+#if defined(DEBUG_UART)
+ while (*str != '\0') {
+ Board_UARTPutChar(*str++);
+ }
+#endif
+}
+
+/* Initialize debug output via UART for board */
+void Board_Debug_Init(void)
+{
+#if defined(DEBUG_UART)
+ Chip_UART0_Init(DEBUG_UART);
+ Chip_UART0_SetBaud(DEBUG_UART, 115200);
+ Chip_UART0_ConfigData(DEBUG_UART, (UART0_LCR_WLEN8 | UART0_LCR_SBS_1BIT));
+ Chip_UART0_SetupFIFOS(DEBUG_UART, (UART0_FCR_FIFO_EN | UART0_FCR_TRG_LEV2));
+ Chip_UART0_TXEnable(DEBUG_UART);
+#endif
+}
+
+#define MAXLEDS 3
+static const uint8_t ledports[MAXLEDS] = {2, 2, 2};
+static const uint8_t ledpins[MAXLEDS] = {17, 16, 18};
+
+/* Initializes board LED(s) */
+static void Board_LED_Init(void)
+{
+ int idx;
+
+ for (idx = 0; idx < MAXLEDS; idx++) {
+ /* Set the GPIO as output with initial state off (high) */
+ Chip_GPIO_SetPinDIROutput(LPC_GPIO, ledports[idx], ledpins[idx]);
+ Chip_GPIO_SetPinState(LPC_GPIO, ledports[idx], ledpins[idx], true);
+ }
+}
+
+/* Sets the state of a board LED to on or off */
+void Board_LED_Set(uint8_t LEDNumber, bool On)
+{
+ if (LEDNumber < MAXLEDS) {
+ /* Toggle state, low is on, high is off */
+ Chip_GPIO_SetPinState(LPC_GPIO, ledports[LEDNumber], ledpins[LEDNumber], !On);
+ }
+}
+
+/* Returns the current state of a board LED */
+bool Board_LED_Test(uint8_t LEDNumber)
+{
+ bool state = false;
+
+ if (LEDNumber < MAXLEDS) {
+ state = !Chip_GPIO_GetPinState(LPC_GPIO, ledports[LEDNumber], ledpins[LEDNumber]);
+ }
+
+ return state;
+}
+
+/* Toggles the current state of a board LED */
+void Board_LED_Toggle(uint8_t LEDNumber)
+{
+ if (LEDNumber < MAXLEDS) {
+ Chip_GPIO_SetPinToggle(LPC_GPIO, ledports[LEDNumber], ledpins[LEDNumber]);
+ }
+}
+
+/* Set up and initialize all required blocks and functions related to the
+ board hardware */
+void Board_Init(void)
+{
+ /* Sets up DEBUG UART */
+ DEBUGINIT();
+
+ /* Initialize GPIO */
+ Chip_GPIO_Init(LPC_GPIO);
+
+ /* Initialize LEDs */
+ Board_LED_Init();
+}
+
+/* Baseboard joystick buttons */
+#define NUM_BUTTONS 5
+static const uint8_t portButton[NUM_BUTTONS] = {0, 0, 0, 2, 2};
+static const uint8_t pinButton[NUM_BUTTONS] = {17, 20, 21, 2, 19};
+static const uint8_t stateButton[NUM_BUTTONS] = {JOY_PRESS, JOY_RIGHT, JOY_UP,
+ JOY_DOWN, JOY_LEFT};
+
+/* Initialize Joystick */
+void Board_Joystick_Init(void)
+{
+ int i;
+
+ /* IOCON states already selected in SystemInit(), GPIO setup only. Pullups
+ are external, so IOCON with no states */
+ for (i = 0; i < NUM_BUTTONS; i++) {
+ Chip_GPIO_SetPinDIRInput(LPC_GPIO, portButton[i], pinButton[i]);
+ }
+}
+
+/* Get Joystick status */
+uint8_t Joystick_GetStatus(void)
+{
+ uint8_t i, ret = 0;
+
+ for (i = 0; i < NUM_BUTTONS; i++) {
+ if ((Chip_GPIO_GetPinState(LPC_GPIO, portButton[i], pinButton[i])) == false) {
+ ret |= stateButton[i];
+ }
+ }
+
+ return ret;
+}
diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/src/board_sysinit.c b/source/lpc_board_nxp_lpcxpresso_11u68/src/board_sysinit.c
new file mode 100644
index 0000000..efb0c3e
--- /dev/null
+++ b/source/lpc_board_nxp_lpcxpresso_11u68/src/board_sysinit.c
@@ -0,0 +1,186 @@
+/*
+ * @brief NXP LPCXpresso 11U68 Sysinit file
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+ #include "board.h"
+ #include "string.h"
+
+/* The System initialization code is called prior to the application and
+ initializes the board for run-time operation. Board initialization
+ includes clock setup and default pin muxing configuration. */
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/* Pin muxing table, only items that need changing from their default pin
+ state are in this table. Not every pin is mapped. */
+STATIC const PINMUX_GRP_T pinmuxing[] = {
+ /* LPCXpresso pin - Base board function - Mapped function */
+ /* RESET-PIO0_0 - PIO/RESET (pin 4) - Reset */
+ /* PIO0_1-ISP_EN - PIO (pin 51) - GPIO input */
+ /* PIO0_2-SSP0_SSEL - PIO/SSEL (pin 8) - GPIO output for SSP0 CS */
+ /* PIO0_3-VBUS - - USB VBUS */
+ {0, 3, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO0_4-I2C_SCL - PIO/I2C-SCL (pin 41) - I2C0 SCL */
+ {0, 4, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO0_5-I2C_SDA - PIO/I2C-SDA (pin 40) - I2C0 SDA */
+ {0, 5, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO0_6 - - GPIO */
+ /* PIO0_7 - PIO (pin 11) - GPIO */
+ /* PIO0_8-SSP0_MISO - PIO/MISO (pin 6) - SSP0 MISO */
+ {0, 8, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO0_9-SSP0_MOSI - PIO/MOSI (pin 5) - SSP0 MOSI */
+ {0, 9, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* SWCLK-PIO0_10 - - SWCLK */
+ /* PIO0_11-ADC_9 - PIO/AD5 (pin 20) - ADC_9 */
+ {0, 11, (IOCON_FUNC2 | IOCON_MODE_INACT)},
+ /* PIO0_12-ADC_8 - PIO/AD4/SWDIO (pin 19) - ADC_8 */
+ {0, 12, (IOCON_FUNC2 | IOCON_MODE_INACT)},
+ /* PIO0_13-ADC_7 - PIO/AD3 (pin 18) - ADC_7 */
+ {0, 13, (IOCON_FUNC2 | IOCON_MODE_INACT)},
+ /* PIO0_14-ADC_6 - PIO/AD2 (pin 17) - ADC_6 */
+ {0, 14, (IOCON_FUNC2 | IOCON_MODE_INACT)},
+ /* PIO0_16-WAKEUP - - GPIO input */
+ /* PIO0_17 - PIO (pin 12) - GPIO */
+ /* TO_MUX_PIO0_18-ISP_RX - PIO/RXD (pin 10) - UART0 RX */
+ {0, 18, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO0_19-ISP_TX - PIO/TXD (pin 9) - UART0 TX */
+ {0, 19, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO0_20 - PIO (pin 13) - GPIO */
+ /* PIO0_21 - PIO (pin 14) - GPIO */
+ /* PIO0_22 - PIO (pin 21) - GPIO */
+ /* PIO0_23-ADC_1 - PIO/AD1 (pin 16) - ADC_1 */
+ {0, 23, (IOCON_FUNC1 | IOCON_MODE_INACT)},
+ /* PIO1_0 - PIO (pin 22) - GPIO */
+ /* PIO1_1 - PIO/USB_CONNECT (pin 23) - GPIO */
+ /* PIO1_2 - PIO/SWCLK (pin 24) - SWCLK */
+ /* PIO1_3 - PIO (pin 25) - GPIO */
+ /* PIO1_4 - PIO (pin 26) - GPIO */
+ /* PIO1_5 - PIO (pin 27) - GPIO */
+ /* PIO1_6 - PIO (pin 53) - GPIO */
+ /* PIO1_7 - PIO (pin 52) - GPIO */
+ /* PIO1_8 - PIO (pin 50) - GPIO */
+ /* PIO1_9-ADC_0 - PIO/AD0 (pin 15) - ADC_0 */
+ {1, 9, (IOCON_FUNC1 | IOCON_MODE_INACT)},
+ /* PIO1_10 - PIO (pin 49) - GPIO */
+ /* PIO1_11-I2C1_SCL - - I2C1 SCL */
+ {1, 11, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO1_12 - PIO/USB_VBUS (pin 39) - GPIO input */
+ /* PIO1_13 - PIO (pin 38) - GPIO output */
+ /* PIO1_14-I2C_SDA - - I2C SDA */
+ {1, 14, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO1_15 - PIO (pin 48) - GPIO */
+ /* PIO1_16 - - GPIO */
+ /* PIO1_17 - - GPIO */
+ /* PIO1_18 - - GPIO input, with pullup */
+ /* PIO1_19 - - GPIO */
+ /* PIO1_20-SSP1_SCK - - SSP1 CLK */
+ {1, 20, (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO1_21-SSP1_MISO - - SSP1 MISO */
+ {1, 21, (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO1_22-SSP1_MOSI - - SSP1 MOSI */
+ {1, 22, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO1_23-SSP1_SSEL - - SSP1 SSEL */
+ {1, 23, (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO1_24-CT32B0_MAT0 - - GPIO input, with pullup */
+ /* PIO1_25 - - GPIO */
+ /* PIO1_26-CT32B0_MAT2 - - CT32B0_MAT2 */
+ {1, 26, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO1_27-CT32B0_MAT3 - - CT32B0_MAT3 */
+ {1, 27, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO1_28 - - GPIO */
+ /* PIO1_29-SSP0_SCK - PIO/SCK (pin 7) - SSP0 CLK */
+ {1, 29, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO1_30 - - GPIO */
+ /* PIO1_31 - - GPIO */
+ /* PIO2_0 - - XTALIN */
+ {2, 0, (IOCON_FUNC1 | IOCON_MODE_INACT)},
+ /* PIO2_1 - - XTALOUT */
+ {2, 1, (IOCON_FUNC1 | IOCON_MODE_INACT)},
+ /* PIO2_2-SCT0_OUT1 - PIO (pin 46) - GPIO */
+ /* PIO2_3-CT32B0_MAT1 - - CT32B0_MAT1 */
+ {2, 3, (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)},
+ /* PIO2_4 - - GPIO */
+ /* PIO2_5 - - GPIO */
+ /* PIO2_6 - - GPIO */
+ /* PIO2_7-SCT0_OUT2 - PIO (pin 47) - GPIO */
+ /* PIO2_8 - - GPIO */
+ /* PIO2_9 - - GPIO */
+ /* PIO2_10 - - GPIO */
+ /* PIO2_11 - - GPIO */
+ /* PIO2_12 - - GPIO */
+ /* PIO2_13 - - GPIO */
+ /* PIO2_14 - - GPIO */
+ /* PIO2_15 - - GPIO */
+ /* PIO2_16-SCT1_OUT0 - PIO/MAT=PWM (pin 42) - LED1 GREEN */
+ /* PIO2_17-SCT1_OUT1 - PIO/MAT=PWM (pin 43) - LED0 RED */
+ /* PIO2_18-SCT1_OUT2 - PIO (pin 44) - LED2 BLUE */
+ /* PIO2_19-SCT1_OUT3 - PIO (pin 45) - GPIO */
+ /* PIO2_20 - - GPIO */
+ /* PIO2_21 - - GPIO */
+ /* PIO2_22 - - GPIO */
+ /* PIO2_23 - - GPIO */
+};
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Sets up system pin muxing */
+void Board_SetupMuxing(void)
+{
+ /* Enable IOCON clock */
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_IOCON);
+
+ Chip_IOCON_SetPinMuxing(LPC_IOCON, pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T));
+}
+
+/* Set up and initialize clocking prior to call to main */
+void Board_SetupClocking(void)
+{
+ Chip_SetupXtalClocking();
+}
+
+/* Set up and initialize hardware prior to call to main */
+void Board_SystemInit(void)
+{
+ /* Setup system clocking and muxing */
+ Board_SetupMuxing();/* Muxing first as it sets up ext oscillator pins */
+ Board_SetupClocking();
+}
diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/src/retarget.h b/source/lpc_board_nxp_lpcxpresso_11u68/src/retarget.h
new file mode 100644
index 0000000..83372ed
--- /dev/null
+++ b/source/lpc_board_nxp_lpcxpresso_11u68/src/retarget.h
@@ -0,0 +1,251 @@
+/*
+ * @brief IO redirection support
+ *
+ * This file adds re-direction support to the library for various
+ * projects. It can be configured in one of 3 ways - no redirection,
+ * redirection via a UART, or redirection via semihosting. If DEBUG
+ * is not defined, all printf statements will do nothing with the
+ * output being throw away. If DEBUG is defined, then the choice of
+ * output is selected by the DEBUG_SEMIHOSTING define. If the
+ * DEBUG_SEMIHOSTING is not defined, then output is redirected via
+ * the UART. If DEBUG_SEMIHOSTING is defined, then output will be
+ * attempted to be redirected via semihosting. If the UART method
+ * is used, then the Board_UARTPutChar and Board_UARTGetChar
+ * functions must be defined to be used by this driver and the UART
+ * must already be initialized to the correct settings.
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2012
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "board.h"
+
+/* Keil (Realview) support */
+#if defined(__CC_ARM)
+
+#include
+#include
+
+#if defined(DEBUG_ENABLE)
+#if defined(DEBUG_SEMIHOSTING)
+#define ITM_Port8(n) (*((volatile unsigned char *) (0xE0000000 + 4 * n)))
+#define ITM_Port16(n) (*((volatile unsigned short *) (0xE0000000 + 4 * n)))
+#define ITM_Port32(n) (*((volatile unsigned long *) (0xE0000000 + 4 * n)))
+
+#define DEMCR (*((volatile unsigned long *) (0xE000EDFC)))
+#define TRCENA 0x01000000
+
+/* Write to SWO */
+void _ttywrch(int ch)
+{
+ if (DEMCR & TRCENA) {
+ while (ITM_Port32(0) == 0) {}
+ ITM_Port8(0) = ch;
+ }
+}
+
+#else
+static INLINE void BoardOutChar(char ch)
+{
+ Board_UARTPutChar(ch);
+}
+
+#endif /* defined(DEBUG_SEMIHOSTING) */
+#endif /* defined(DEBUG_ENABLE) */
+
+struct __FILE {
+ int handle;
+};
+
+FILE __stdout;
+FILE __stdin;
+FILE __stderr;
+
+void *_sys_open(const char *name, int openmode)
+{
+ return 0;
+}
+
+int fputc(int c, FILE *f)
+{
+#if defined(DEBUG_ENABLE)
+#if defined(DEBUG_SEMIHOSTING)
+ _ttywrch(c);
+#else
+ BoardOutChar((char) c);
+#endif
+#endif
+ return 0;
+}
+
+int fgetc(FILE *f)
+{
+#if defined(DEBUG_ENABLE) && !defined(DEBUG_SEMIHOSTING)
+ return Board_UARTGetChar();
+#else
+ return 0;
+#endif
+}
+
+int ferror(FILE *f)
+{
+ return EOF;
+}
+
+void _sys_exit(int return_code)
+{
+label:
+ __WFI();
+ goto label; /* endless loop */
+}
+
+#endif /* defined (__CC_ARM) */
+
+/* IAR support */
+#if defined(__ICCARM__)
+/*******************
+ *
+ * Copyright 1998-2003 IAR Systems. All rights reserved.
+ *
+ * $Revision: 30870 $
+ *
+ * This is a template implementation of the "__write" function used by
+ * the standard library. Replace it with a system-specific
+ * implementation.
+ *
+ * The "__write" function should output "size" number of bytes from
+ * "buffer" in some application-specific way. It should return the
+ * number of characters written, or _LLIO_ERROR on failure.
+ *
+ * If "buffer" is zero then __write should perform flushing of
+ * internal buffers, if any. In this case "handle" can be -1 to
+ * indicate that all handles should be flushed.
+ *
+ * The template implementation below assumes that the application
+ * provides the function "MyLowLevelPutchar". It should return the
+ * character written, or -1 on failure.
+ *
+ ********************/
+
+#include
+
+#if defined(DEBUG_ENABLE) && !defined(DEBUG_SEMIHOSTING)
+
+_STD_BEGIN
+
+#pragma module_name = "?__write"
+
+/*
+ If the __write implementation uses internal buffering, uncomment
+ the following line to ensure that we are called with "buffer" as 0
+ (i.e. flush) when the application terminates. */
+size_t __write(int handle, const unsigned char *buffer, size_t size)
+{
+#if defined(DEBUG_ENABLE)
+ size_t nChars = 0;
+
+ if (buffer == 0) {
+ /*
+ This means that we should flush internal buffers. Since we
+ don't we just return. (Remember, "handle" == -1 means that all
+ handles should be flushed.)
+ */
+ return 0;
+ }
+
+ /* This template only writes to "standard out" and "standard err",
+ for all other file handles it returns failure. */
+ if (( handle != _LLIO_STDOUT) && ( handle != _LLIO_STDERR) ) {
+ return _LLIO_ERROR;
+ }
+
+ for ( /* Empty */; size != 0; --size) {
+ Board_UARTPutChar(*buffer++);
+ ++nChars;
+ }
+
+ return nChars;
+#else
+ return size;
+#endif /* defined(DEBUG_ENABLE) */
+}
+
+_STD_END
+#endif
+
+#endif /* defined (__ICCARM__) */
+
+#if defined( __GNUC__ )
+/* Include stdio.h to pull in __REDLIB_INTERFACE_VERSION__ */
+#include
+
+#if (__REDLIB_INTERFACE_VERSION__ >= 20000)
+/* We are using new Redlib_v2 semihosting interface */
+ #define WRITEFUNC __sys_write
+ #define READFUNC __sys_readc
+#else
+/* We are using original Redlib semihosting interface */
+ #define WRITEFUNC __write
+ #define READFUNC __readc
+#endif
+
+#if defined(DEBUG_ENABLE)
+#if defined(DEBUG_SEMIHOSTING)
+/* Do nothing, semihosting is enabled by default in LPCXpresso */
+#endif /* defined(DEBUG_SEMIHOSTING) */
+#endif /* defined(DEBUG_ENABLE) */
+
+#if !defined(DEBUG_SEMIHOSTING)
+int WRITEFUNC(int iFileHandle, char *pcBuffer, int iLength)
+{
+#if defined(DEBUG_ENABLE)
+ unsigned int i;
+ for (i = 0; i < iLength; i++) {
+ Board_UARTPutChar(pcBuffer[i]);
+ }
+#endif
+
+ return iLength;
+}
+
+/* Called by bottom level of scanf routine within RedLib C library to read
+ a character. With the default semihosting stub, this would read the character
+ from the debugger console window (which acts as stdin). But this version reads
+ the character from the LPC1768/RDB1768 UART. */
+int READFUNC(void)
+{
+#if defined(DEBUG_ENABLE)
+ char c = Board_UARTGetChar();
+ return (int) c;
+
+#else
+ return (int) -1;
+#endif
+}
+
+#endif /* !defined(DEBUG_SEMIHOSTING) */
+#endif /* defined ( __GNUC__ ) */
diff --git a/source/lpc_chip_11u6x/.DS_Store b/source/lpc_chip_11u6x/.DS_Store
new file mode 100644
index 0000000..6da1c1f
Binary files /dev/null and b/source/lpc_chip_11u6x/.DS_Store differ
diff --git a/source/lpc_chip_11u6x/.cproject b/source/lpc_chip_11u6x/.cproject
new file mode 100644
index 0000000..b9d879a
--- /dev/null
+++ b/source/lpc_chip_11u6x/.cproject
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<TargetConfig>
+<Properties property_2="LPC11U6x_256K.cfx" property_3="NXP" property_4="LPC11U68" property_count="5" version="100300"/>
+<infoList vendor="NXP">
+<info chip="LPC11U68" flash_driver="LPC11U6x_256K.cfx" match_id="0x0" name="LPC11U68" stub="crt_emu_cm3_gen">
+<chip>
+<name>LPC11U68</name>
+<family>LPC11U6x</family>
+<vendor>NXP (formerly Philips)</vendor>
+<reset board="None" core="Real" sys="Real"/>
+<clock changeable="TRUE" freq="12MHz" is_accurate="TRUE"/>
+<memory can_program="true" id="Flash" is_ro="true" type="Flash"/>
+<memory id="RAM" type="RAM"/>
+<memory id="Periph" is_volatile="true" type="Peripheral"/>
+<memoryInstance derived_from="Flash" id="MFlash256" location="0x0" size="0x40000"/>
+<memoryInstance derived_from="RAM" id="Ram0_32" location="0x10000000" size="0x8000"/>
+<memoryInstance derived_from="RAM" id="Ram1_2" location="0x20000000" size="0x800"/>
+<memoryInstance derived_from="RAM" id="Ram2USB_2" location="0x20004000" size="0x800"/>
+</chip>
+<processor>
+<name gcc_name="cortex-m0">Cortex-M0</name>
+<family>Cortex-M</family>
+</processor>
+</info>
+</infoList>
+</TargetConfig>
+
+
+
+
+
\ No newline at end of file
diff --git a/source/lpc_chip_11u6x/.gitignore b/source/lpc_chip_11u6x/.gitignore
new file mode 100644
index 0000000..3df573f
--- /dev/null
+++ b/source/lpc_chip_11u6x/.gitignore
@@ -0,0 +1 @@
+/Debug/
diff --git a/source/lpc_chip_11u6x/.project b/source/lpc_chip_11u6x/.project
new file mode 100644
index 0000000..5c96e51
--- /dev/null
+++ b/source/lpc_chip_11u6x/.project
@@ -0,0 +1,26 @@
+
+
+ lpc_chip_11u6x
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/source/lpc_chip_11u6x/.settings/language.settings.xml b/source/lpc_chip_11u6x/.settings/language.settings.xml
new file mode 100644
index 0000000..2db10a1
--- /dev/null
+++ b/source/lpc_chip_11u6x/.settings/language.settings.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/lpc_chip_11u6x/inc/adc_11u6x.h b/source/lpc_chip_11u6x/inc/adc_11u6x.h
new file mode 100644
index 0000000..dd9fb05
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/adc_11u6x.h
@@ -0,0 +1,549 @@
+/*
+ * @brief LPC11u6x ADC driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __ADC_11U6X_H_
+#define __ADC_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup ADC_11U6X CHIP: LPC11u6x A/D conversion driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/** Sequence index enumerations, used in various parts of the code for
+ register indexing and sequencer selection */
+typedef enum {
+ ADC_SEQA_IDX,
+ ADC_SEQB_IDX
+} ADC_SEQ_IDX_T;
+
+/**
+ * @brief ADC register block structure
+ */
+typedef struct { /*!< ADCn Structure */
+ __IO uint32_t CTRL; /*!< A/D Control Register. The AD0CR register must be written to select the operating mode before A/D conversion can occur. */
+ __I uint32_t RESERVED0;
+ __IO uint32_t SEQ_CTRL[ADC_SEQB_IDX + 1]; /*!< A/D Sequence A & B Control Register. Controls triggering and channel selection for sonversion sequence. */
+ __IO uint32_t SEQ_GDAT[ADC_SEQB_IDX + 1]; /*!< A/D Sequence A & B Global Data Register. Contains the result of the most recent A/D conversion for sequence. */
+ __I uint32_t RESERVED1[2];
+ __I uint32_t DR[12]; /*!< A/D Channel Data Register. This register contains the result of the most recent conversion completed on channel n. */
+ __IO uint32_t THR_LOW[2]; /*!< A/D Low Compare Threshold Register 0 & 1. Contains the lower threshold level for automatic threshold comparison. */
+ __IO uint32_t THR_HIGH[2]; /*!< A/D High Compare Threshold Register 0 & 1. Contains the higher threshold level for automatic threshold comparison. */
+ __IO uint32_t CHAN_THRSEL; /*!< A/D Channel Threshold Select Register. Specifies which set of threshold compare registers to use. */
+ __IO uint32_t INTEN; /*!< A/D Interrupt Enable Register. This register contains enable bits that enable sequence-A, sequence-B, threshold compare and overrun interrupts. */
+ __IO uint32_t FLAGS; /*!< A/D Flags Register. This register contains interrupt flags. - To be checked */
+ __IO uint32_t TRM; /*!< A/D Trim Register. */
+} LPC_ADC_T;
+
+/** Maximum clock rate in Hz (12-bit conversions) */
+#define ADC_MAX_CLOCK_RATE 50000000
+#define ADC_CALIBRATE_RATE 500000
+
+/**
+ * @brief ADC register support bitfields and mask
+ */
+/** ADC Control register bit fields */
+#define ADC_CR_CLKDIV_MASK (0xFF << 0) /*!< Mask for Clock divider value */
+#define ADC_CR_CLKDIV_BITPOS (0) /*!< Bit position for Clock divider value */
+#define ADC_CR_MODE10BIT (1 << 9) /*!< 10-bit mode enable bit */
+#define ADC_CR_LPWRMODEBIT (1 << 10) /*!< Low power mode enable bit */
+#define ADC_CR_CALMODEBIT (1 << 30) /*!< Self calibration cycle enable bit */
+#define ADC_CR_BITACC(n) ((((n) & 0x1) << 9)) /*!< 12-bit or 10-bit ADC accuracy */
+#define ADC_CR_CLKDIV(n) ((((n) & 0xFF) << 0)) /*!< The APB clock (PCLK) is divided by (this value plus one) to produce the clock for the A/D */
+#define ADC_SAMPLE_RATE_CONFIG_MASK (ADC_CR_CLKDIV(0xFF) | ADC_CR_BITACC(0x01))
+
+/** ADC Sequence Control register bit fields */
+#define ADC_SEQ_CTRL_CHANSEL(n) (1 << (n)) /*!< Channel select macro */
+#define ADC_SEQ_CTRL_CHANSEL_MASK (0xFFF) /*!< Channel select mask */
+
+/** ADC hardware trigger sources in SEQ_CTRL */
+#define ADC_SEQ_CTRL_HWTRIG_ARM_TXEV (0 << 12) /*!< HW trigger input - ARM TXEV */
+#define ADC_SEQ_CTRL_HWTRIG_CT32B0_MAT0 (1 << 12) /*!< HW trigger input - Match output 0 of CT32B0 */
+#define ADC_SEQ_CTRL_HWTRIG_CT32B0_MAT1 (2 << 12) /*!< HW trigger input - Match output 1 of CT32B1 or SCT_OUT0 */
+#define ADC_SEQ_CTRL_HWTRIG_SCT_OUT0 (2 << 12) /*!< HW trigger input - Match output 1 of CT32B1 or SCT_OUT0 */
+#define ADC_SEQ_CTRL_HWTRIG_CT16B0_MAT0 (3 << 12) /*!< HW trigger input - Match output 0 of CT16B0 */
+#define ADC_SEQ_CTRL_HWTRIG_CT16B0_MAT1 (4 << 12) /*!< HW trigger input - Match output 1 of CT16B1 or SCT_OUT1 */
+#define ADC_SEQ_CTRL_HWTRIG_SCT_OUT1 (4 << 12) /*!< HW trigger input - Match output 1 of CT16B1 or SCT_OUT1 */
+#define ADC_SEQ_CTRL_HWTRIG_CT16B0_CAP0 (5 << 12) /*!< HW trigger input - Capture input 0 of CT16B0 */
+#define ADC_SEQ_CTRL_HWTRIG_CT16B1_CAP0 (6 << 12) /*!< HW trigger input - Capture input 0 of CT16B1 */
+#define ADC_SEQ_CTRL_HWTRIG_CT32B0_CAP0 (7 << 12) /*!< HW trigger input - Capture input 0 of CT32B1 */
+#define ADC_SEQ_CTRL_HWTRIG_MASK (0x3F << 12) /*!< HW trigger input bitfield mask */
+
+/** SEQ_CTRL register bit fields */
+#define ADC_SEQ_CTRL_HWTRIG_POLPOS (1 << 18) /*!< HW trigger polarity - positive edge */
+#define ADC_SEQ_CTRL_HWTRIG_SYNCBYPASS (1 << 19) /*!< HW trigger bypass synchronisation */
+#define ADC_SEQ_CTRL_START (1 << 26) /*!< Start conversion enable bit */
+#define ADC_SEQ_CTRL_BURST (1 << 27) /*!< Repeated conversion enable bit */
+#define ADC_SEQ_CTRL_SINGLESTEP (1 << 28) /*!< Single step enable bit */
+#define ADC_SEQ_CTRL_LOWPRIO (1 << 29) /*!< High priority enable bit (regardless of name) */
+#define ADC_SEQ_CTRL_MODE_EOS (1 << 30) /*!< Mode End of sequence enable bit */
+#define ADC_SEQ_CTRL_SEQ_ENA (1UL << 31) /*!< Sequence enable bit */
+
+/** ADC global data register bit fields */
+#define ADC_SEQ_GDAT_RESULT_MASK (0xFFF << 4) /*!< Result value mask */
+#define ADC_SEQ_GDAT_RESULT_BITPOS (4) /*!< Result start bit position */
+#define ADC_SEQ_GDAT_THCMPRANGE_MASK (0x3 << 16) /*!< Comparion range mask */
+#define ADC_SEQ_GDAT_THCMPRANGE_BITPOS (16) /*!< Comparison range bit position */
+#define ADC_SEQ_GDAT_THCMPCROSS_MASK (0x3 << 18) /*!< Comparion cross mask */
+#define ADC_SEQ_GDAT_THCMPCROSS_BITPOS (18) /*!< Comparison cross bit position */
+#define ADC_SEQ_GDAT_CHAN_MASK (0xF << 26) /*!< Channel number mask */
+#define ADC_SEQ_GDAT_CHAN_BITPOS (26) /*!< Channel number bit position */
+#define ADC_SEQ_GDAT_OVERRUN (1 << 30) /*!< Overrun bit */
+#define ADC_SEQ_GDAT_DATAVALID (1UL << 31) /*!< Data valid bit */
+
+/** ADC Data register bit fields */
+#define ADC_DR_RESULT(n) ((((n) >> 4) & 0xFFF)) /*!< Macro for getting the ADC data value */
+#define ADC_DR_THCMPRANGE_MASK (0x3 << 16) /*!< Comparion range mask */
+#define ADC_DR_THCMPRANGE_BITPOS (16) /*!< Comparison range bit position */
+#define ADC_DR_THCMPRANGE(n) (((n) >> ADC_DR_THCMPRANGE_BITPOS) & 0x3)
+#define ADC_DR_THCMPCROSS_MASK (0x3 << 18) /*!< Comparion cross mask */
+#define ADC_DR_THCMPCROSS_BITPOS (18) /*!< Comparison cross bit position */
+#define ADC_DR_THCMPCROSS(n) (((n) >> ADC_DR_THCMPCROSS_BITPOS) & 0x3)
+#define ADC_DR_CHAN_MASK (0xF << 26) /*!< Channel number mask */
+#define ADC_DR_CHAN_BITPOS (26) /*!< Channel number bit position */
+#define ADC_DR_CHANNEL(n) (((n) >> ADC_DR_CHAN_BITPOS) & 0xF) /*!< Channel number bit position */
+#define ADC_DR_OVERRUN (1 << 30) /*!< Overrun bit */
+#define ADC_DR_DATAVALID (1UL << 31) /*!< Data valid bit */
+#define ADC_DR_DONE(n) (((n) >> 31))
+
+/** ADC low/high Threshold register bit fields */
+#define ADC_THR_VAL_MASK (0xFFF << 4) /*!< Threshold value bit mask */
+#define ADC_THR_VAL_POS (4) /*!< Threshold value bit position */
+
+/** ADC Threshold select register bit fields */
+#define ADC_THRSEL_CHAN_SEL_THR1(n) (1 << (n)) /*!< Select THR1 register for channel n */
+
+/** ADC Interrupt Enable register bit fields */
+#define ADC_INTEN_SEQA_ENABLE (1 << 0) /*!< Sequence A Interrupt enable bit */
+#define ADC_INTEN_SEQB_ENABLE (1 << 1) /*!< Sequence B Interrupt enable bit */
+#define ADC_INTEN_SEQN_ENABLE(seq) (1 << (seq)) /*!< Sequence A/B Interrupt enable bit */
+#define ADC_INTEN_OVRRUN_ENABLE (1 << 2) /*!< Overrun Interrupt enable bit */
+#define ADC_INTEN_CMP_DISBALE (0) /*!< Disable comparison interrupt value */
+#define ADC_INTEN_CMP_OUTSIDETH (1) /*!< Outside threshold interrupt value */
+#define ADC_INTEN_CMP_CROSSTH (2) /*!< Crossing threshold interrupt value */
+#define ADC_INTEN_CMP_MASK (3) /*!< Comparison interrupt value mask */
+#define ADC_INTEN_CMP_ENABLE(isel, ch) (((isel) & ADC_INTEN_CMP_MASK) << ((2 * (ch)) + 3)) /*!< Interrupt selection for channel */
+
+/** ADC Flags register bit fields */
+#define ADC_FLAGS_THCMP_MASK(ch) (1 << (ch)) /*!< Threshold comparison status for channel */
+#define ADC_FLAGS_OVRRUN_MASK(ch) (1 << (12 + (ch))) /*!< Overrun status for channel */
+#define ADC_FLAGS_SEQA_OVRRUN_MASK (1 << 24) /*!< Seq A Overrun status */
+#define ADC_FLAGS_SEQB_OVRRUN_MASK (1 << 25) /*!< Seq B Overrun status */
+#define ADC_FLAGS_SEQN_OVRRUN_MASK(seq) (1 << (24 + (seq))) /*!< Seq A/B Overrun status */
+#define ADC_FLAGS_SEQA_INT_MASK (1 << 28) /*!< Seq A Interrupt status */
+#define ADC_FLAGS_SEQB_INT_MASK (1 << 29) /*!< Seq B Interrupt status */
+#define ADC_FLAGS_SEQN_INT_MASK(seq) (1 << (28 + (seq)))/*!< Seq A/B Interrupt status */
+#define ADC_FLAGS_THCMP_INT_MASK (1 << 30) /*!< Threshold comparison Interrupt status */
+#define ADC_FLAGS_OVRRUN_INT_MASK (1UL << 31) /*!< Overrun Interrupt status */
+
+/** ADC Trim register bit fields */
+#define ADC_TRIM_VRANGE_HIGHV (0 << 5) /*!< Voltage range bit - High volatge (2.7V to 3.6V) */
+#define ADC_TRIM_VRANGE_LOWV (1 << 5) /*!< Voltage range bit - Low volatge (1.8V to 2.7V) */
+
+/**
+ * @brief Initialize the ADC peripheral
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param flags : ADC flags for init (ADC_CR_MODE10BIT and/or ADC_CR_LPWRMODEBIT)
+ * @return Nothing
+ * @note To select low-power ADC mode, enable the ADC_CR_LPWRMODEBIT flag.
+ * To select 10-bit conversion mode, enable the ADC_CR_MODE10BIT flag.
+ * Example: Chip_ADC_Init(LPC_ADC, (ADC_CR_MODE10BIT | ADC_CR_LPWRMODEBIT));
+ */
+void Chip_ADC_Init(LPC_ADC_T *pADC, uint32_t flags);
+
+/**
+ * @brief Shutdown ADC
+ * @param pADC : The base of ADC peripheral on the chip
+ * @return Nothing
+ * @note Disables the ADC clocks and ADC power
+ */
+void Chip_ADC_DeInit(LPC_ADC_T *pADC);
+
+/**
+ * @brief Set ADC divider
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param div : ADC divider value to set minus 1
+ * @return Nothing
+ * @note The value is used as a divider to generate the ADC
+ * clock rate from the ADC input clock. The ADC input clock is based
+ * on the system clock. Valid values for this function are from 0 to 255
+ * with 0=divide by 1, 1=divide by 2, 2=divide by 3, etc.
+ * Do not decrement this value by 1.
+ * To set the ADC clock rate to 1MHz, use the following function:
+ * Chip_ADC_SetDivider(LPC_ADC, (Chip_Clock_GetSystemClockRate() / 1000000) - 1);
+ */
+STATIC INLINE void Chip_ADC_SetDivider(LPC_ADC_T *pADC, uint8_t div)
+{
+ uint32_t temp;
+
+ temp = pADC->CTRL & ~(ADC_CR_CLKDIV_MASK);
+ pADC->CTRL = temp | (uint32_t) div;
+}
+
+/**
+ * @brief Set ADC clock rate
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param rate : rate in Hz to set ADC clock to (maximum ADC_MAX_SAMPLE_RATE)
+ * @return Nothing
+ */
+void Chip_ADC_SetClockRate(LPC_ADC_T *pADC, uint32_t rate);
+
+/**
+ * @brief Get ADC divider
+ * @param pADC : The base of ADC peripheral on the chip
+ * @return the current ADC divider
+ * @note This function returns the divider that is used to generate the
+ * ADC frequency. The returned value must be incremented by 1. The
+ * frequency can be determined with the following function:
+ * adc_freq = Chip_Clock_GetSystemClockRate() / (Chip_ADC_GetDivider(LPC_ADC) + 1);
+ */
+STATIC INLINE uint8_t Chip_ADC_GetDivider(LPC_ADC_T *pADC)
+{
+ return pADC->CTRL & ADC_CR_CLKDIV_MASK;
+}
+
+/**
+ * @brief Start ADC calibration
+ * @param pADC : The base of ADC peripheral on the chip
+ * @return Nothing
+ * @note Calibration is not done as part of Chip_ADC_Init(), but
+ * is required after the call to Chip_ADC_Init() or after returning
+ * from a power-down state.
+ */
+void Chip_ADC_StartCalibration(LPC_ADC_T *pADC);
+
+/**
+ * @brief Check if ADC calibration is done
+ * @param pADC : The base of ADC peripheral on the chip
+ * @return TRUE if calibration is complete, otherwise FALSE.
+ */
+bool Chip_ADC_IsCalibrationDone(LPC_ADC_T *pADC);
+
+/**
+ * @brief Helper function for safely setting ADC sequencer register bits
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param seqIndex : Sequencer to set bits for
+ * @param bits : Or'ed bits of a sequencer register to set
+ * @return Nothing
+ * @note This function will safely set the ADC sequencer register bits
+ * while maintaining bits 20..25 as 0, regardless of the read state of those bits.
+ */
+void Chip_ADC_SetSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits);
+
+/**
+ * @brief Helper function for safely clearing ADC sequencer register bits
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param seqIndex : Sequencer to clear bits for
+ * @param bits : Or'ed bits of a sequencer register to clear
+ * @return Nothing
+ * @note This function will safely clear the ADC sequencer register bits
+ * while maintaining bits 20..25 as 0, regardless of the read state of those bits.
+ */
+void Chip_ADC_ClearSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits);
+
+/**
+ * @brief Sets up ADC conversion sequencer A or B
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param seqIndex : Sequencer to setup
+ * @param options : OR'ed Sequencer options to setup (see notes)
+ * @return Nothing
+ * @note Sets up sequencer options for a conversion sequence. This function
+ * should be used to setup the selected channels for the sequence, the sequencer
+ * trigger, the trigger polarity, synchronization bypass, priority, and mode. All
+ * options are passed to the functions as a OR'ed list of values. This function will
+ * disable/clear the sequencer start/burst/single step/enable if they are enabled.
+ * Select the channels by OR'ing in one or more ADC_SEQ_CTRL_CHANSEL(ch) values.
+ * Select the hardware trigger by OR'ing in one ADC_SEQ_CTRL_HWTRIG_* value.
+ * Select a positive edge hardware trigger by OR'ing in ADC_SEQ_CTRL_HWTRIG_POLPOS.
+ * Select trigger bypass synchronisation by OR'ing in ADC_SEQ_CTRL_HWTRIG_SYNCBYPASS.
+ * Select ADC single step on trigger/start by OR'ing in ADC_SEQ_CTRL_SINGLESTEP.
+ * Select higher priority conversion on the other sequencer by OR'ing in ADC_SEQ_CTRL_LOWPRIO.
+ * Select end of seqeuence instead of end of conversion interrupt by OR'ing in ADC_SEQ_CTRL_MODE_EOS.
+ * Example for setting up sequencer A (channels 0-2, trigger on high edge of PIO0_2, interrupt on end of sequence):
+ * Chip_ADC_SetupSequencer(LPC_ADC, ADC_SEQA_IDX, (
+ * ADC_SEQ_CTRL_CHANSEL(0) | ADC_SEQ_CTRL_CHANSEL(1) | ADC_SEQ_CTRL_CHANSEL(2) |
+ * ADC_SEQ_CTRL_HWTRIG_PIO0_2 | ADC_SEQ_CTRL_HWTRIG_POLPOS | ADC_SEQ_CTRL_MODE_EOS));
+ */
+STATIC INLINE void Chip_ADC_SetupSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t options)
+{
+ pADC->SEQ_CTRL[seqIndex] = options;
+}
+
+/**
+ * @brief Enables a sequencer
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param seqIndex : Sequencer to enable
+ * @return Nothing
+ */
+STATIC INLINE void Chip_ADC_EnableSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
+{
+ Chip_ADC_SetSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_SEQ_ENA);
+}
+
+/**
+ * @brief Disables a sequencer
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param seqIndex : Sequencer to disable
+ * @return Nothing
+ */
+STATIC INLINE void Chip_ADC_DisableSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
+{
+ Chip_ADC_ClearSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_SEQ_ENA);
+}
+
+/**
+ * @brief Forces a sequencer trigger event (software trigger of ADC)
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param seqIndex : Sequencer to start
+ * @return Nothing
+ * @note This function sets the START bit for the sequencer to force a
+ * single conversion sequence or a single step conversion.
+ */
+STATIC INLINE void Chip_ADC_StartSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
+{
+ Chip_ADC_SetSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_START);
+}
+
+/**
+ * @brief Starts sequencer burst mode
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param seqIndex : Sequencer to start burst on
+ * @return Nothing
+ * @note This function sets the BURST bit for the sequencer to force
+ * continuous conversion. Use Chip_ADC_StopBurstSequencer() to stop the
+ * ADC burst sequence.
+ */
+STATIC INLINE void Chip_ADC_StartBurstSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
+{
+ Chip_ADC_SetSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_BURST);
+}
+
+/**
+ * @brief Stops sequencer burst mode
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param seqIndex : Sequencer to stop burst on
+ * @return Nothing
+ */
+STATIC INLINE void Chip_ADC_StopBurstSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
+{
+ Chip_ADC_ClearSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_BURST);
+}
+
+/** ADC sequence global data register threshold comparison range enumerations */
+typedef enum {
+ ADC_DR_THCMPRANGE_INRANGE,
+ ADC_DR_THCMPRANGE_RESERVED,
+ ADC_DR_THCMPRANGE_BELOW,
+ ADC_DR_THCMPRANGE_ABOVE
+} ADC_DR_THCMPRANGE_T;
+
+/** ADC sequence global data register threshold comparison cross enumerations */
+typedef enum {
+ ADC_DR_THCMPCROSS_NOCROSS,
+ ADC_DR_THCMPCROSS_RESERVED,
+ ADC_DR_THCMPCROSS_DOWNWARD,
+ ADC_DR_THCMPCROSS_UPWARD
+} ADC_DR_THCMPCROSS_T;
+
+/**
+ * @brief Read a ADC sequence global data register
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param seqIndex : Sequencer to read
+ * @return Current raw value of the ADC sequence A or B global data register
+ * @note This function returns the raw value of the data register and clears
+ * the overrun and datavalid status for the register. Once this register is read,
+ * the following functions can be used to parse the raw value:
+ * uint32_t adcDataRawValue = Chip_ADC_ReadSequencerDataReg(LPC_ADC, ADC_SEQA_IDX); // Get raw value
+ * uint32_t adcDataValue = ADC_DR_RESULT(adcDataRawValue); // Aligned and masked ADC data value
+ * ADC_DR_THCMPRANGE_T adcRange = (ADC_DR_THCMPRANGE_T) ADC_DR_THCMPRANGE(adcDataRawValue); // Sample range compared to threshold low/high
+ * ADC_DR_THCMPCROSS_T adcRange = (ADC_DR_THCMPCROSS_T) ADC_DR_THCMPCROSS(adcDataRawValue); // Sample cross compared to threshold low
+ * uint32_t channel = ADC_DR_CHANNEL(adcDataRawValue); // ADC channel for this sample/data
+ * bool adcDataOverrun = (bool) ((adcDataRawValue & ADC_DR_OVERRUN) != 0); // Data overrun flag
+ * bool adcDataValid = (bool) ((adcDataRawValue & ADC_SEQ_GDAT_DATAVALID) != 0); // Data valid flag
+ */
+STATIC INLINE uint32_t Chip_ADC_GetSequencerDataReg(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex)
+{
+ return pADC->SEQ_GDAT[seqIndex];
+}
+
+/**
+ * @brief Read a ADC data register
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param index : Data register to read, 1-8
+ * @return Current raw value of the ADC data register
+ * @note This function returns the raw value of the data register and clears
+ * the overrun and datavalid status for the register. Once this register is read,
+ * the following functions can be used to parse the raw value:
+ * uint32_t adcDataRawValue = Chip_ADC_ReadSequencerDataReg(LPC_ADC, ADC_SEQA_IDX); // Get raw value
+ * uint32_t adcDataValue = ADC_DR_RESULT(adcDataRawValue); // Aligned and masked ADC data value
+ * ADC_DR_THCMPRANGE_T adcRange = (ADC_DR_THCMPRANGE_T) ADC_DR_THCMPRANGE(adcDataRawValue); // Sample range compared to threshold low/high
+ * ADC_DR_THCMPCROSS_T adcRange = (ADC_DR_THCMPCROSS_T) ADC_DR_THCMPCROSS(adcDataRawValue); // Sample cross compared to threshold low
+ * uint32_t channel = ADC_DR_CHANNEL(adcDataRawValue); // ADC channel for this sample/data
+ * bool adcDataOverrun = (bool) ((adcDataRawValue & ADC_DR_OVERRUN) != 0); // Data overrun flag
+ * bool adcDataValid = (bool) ((adcDataRawValue & ADC_SEQ_GDAT_DATAVALID) != 0); // Data valid flag
+ */
+STATIC INLINE uint32_t Chip_ADC_GetDataReg(LPC_ADC_T *pADC, uint8_t index)
+{
+ return pADC->DR[index];
+}
+
+/**
+ * @brief Set Threshold low value in ADC
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param thrnum : Threshold register value (1 for threshold register 1, 0 for threshold register 0)
+ * @param value : Threshold low data value (should be 12-bit value)
+ * @return None
+ */
+STATIC INLINE void Chip_ADC_SetThrLowValue(LPC_ADC_T *pADC, uint8_t thrnum, uint16_t value)
+{
+ pADC->THR_LOW[thrnum] = (((uint32_t) value) << ADC_THR_VAL_POS);
+}
+
+/**
+ * @brief Set Threshold high value in ADC
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param thrnum : Threshold register value (1 for threshold register 1, 0 for threshold register 0)
+ * @param value : Threshold high data value (should be 12-bit value)
+ * @return None
+ */
+STATIC INLINE void Chip_ADC_SetThrHighValue(LPC_ADC_T *pADC, uint8_t thrnum, uint16_t value)
+{
+ pADC->THR_HIGH[thrnum] = (((uint32_t) value) << ADC_THR_VAL_POS);
+}
+
+/**
+ * @brief Select threshold 0 values for comparison for selected channels
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param channels : An OR'ed value of one or more ADC_THRSEL_CHAN_SEL_THR1(ch) values
+ * @return None
+ * @note Select multiple channels to use the threshold 0 comparison.
+ * Example:
+ * Chip_ADC_SelectTH0Channels(LPC_ADC, (ADC_THRSEL_CHAN_SEL_THR1(1) | ADC_THRSEL_CHAN_SEL_THR1(2))); // Selects channels 1 and 2 for threshold 0
+ */
+void Chip_ADC_SelectTH0Channels(LPC_ADC_T *pADC, uint32_t channels);
+
+/**
+ * @brief Select threshold 1 value for comparison for selected channels
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param channels : An OR'ed value of one or more ADC_THRSEL_CHAN_SEL_THR1(ch) values
+ * @return None
+ * @note Select multiple channels to use the 1 threshold comparison.
+ * Example:
+ * Chip_ADC_SelectTH1Channels(LPC_ADC, (ADC_THRSEL_CHAN_SEL_THR1(4) | ADC_THRSEL_CHAN_SEL_THR1(5))); // Selects channels 4 and 5 for 1 threshold
+ */
+void Chip_ADC_SelectTH1Channels(LPC_ADC_T *pADC, uint32_t channels);
+
+/**
+ * @brief Enable interrupts in ADC (sequencers A/B and overrun)
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param intMask : Interrupt values to be enabled (see notes)
+ * @return None
+ * @note Select one or more OR'ed values of ADC_INTEN_SEQA_ENABLE,
+ * ADC_INTEN_SEQB_ENABLE, and ADC_INTEN_OVRRUN_ENABLE to enable the
+ * specific ADC interrupts.
+ */
+void Chip_ADC_EnableInt(LPC_ADC_T *pADC, uint32_t intMask);
+
+/**
+ * @brief Disable interrupts in ADC (sequencers A/B and overrun)
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param intMask : Interrupt values to be disabled (see notes)
+ * @return None
+ * @note Select one or more OR'ed values of ADC_INTEN_SEQA_ENABLE,
+ * ADC_INTEN_SEQB_ENABLE, and ADC_INTEN_OVRRUN_ENABLE to disable the
+ * specific ADC interrupts.
+ */
+void Chip_ADC_DisableInt(LPC_ADC_T *pADC, uint32_t intMask);
+
+/** Threshold interrupt event options */
+typedef enum {
+ ADC_INTEN_THCMP_DISABLE,
+ ADC_INTEN_THCMP_OUTSIDE,
+ ADC_INTEN_THCMP_CROSSING,
+} ADC_INTEN_THCMP_T;
+
+/**
+ * @brief Enable a threshold event interrupt in ADC
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param ch : ADC channel to set threshold inetrrupt for, 1-8
+ * @param thInt : Selected threshold interrupt type
+ * @return None
+ */
+void Chip_ADC_SetThresholdInt(LPC_ADC_T *pADC, uint8_t ch, ADC_INTEN_THCMP_T thInt);
+
+/**
+ * @brief Get flags register in ADC
+ * @param pADC : The base of ADC peripheral on the chip
+ * @return Flags register value (ORed ADC_FLAG* values)
+ * @note Mask the return value of this function with the ADC_FLAGS_*
+ * definitions to determine the overall ADC interrupt events.
+ * Example:
+ * if (Chip_ADC_GetFlags(LPC_ADC) & ADC_FLAGS_THCMP_MASK(3) // Check of threshold comp status for ADC channel 3
+ */
+STATIC INLINE uint32_t Chip_ADC_GetFlags(LPC_ADC_T *pADC)
+{
+ return pADC->FLAGS;
+}
+
+/**
+ * @brief Clear flags register in ADC
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param flags : An Or'ed values of ADC_FLAGS_* values to clear
+ * @return Flags register value (ORed ADC_FLAG* values)
+ */
+STATIC INLINE void Chip_ADC_ClearFlags(LPC_ADC_T *pADC, uint32_t flags)
+{
+ pADC->FLAGS = flags;
+}
+
+/**
+ * @brief Set Trim register in ADC
+ * @param pADC : The base of ADC peripheral on the chip
+ * @param trim : Trim value (ADC_TRIM_VRANGE_HIGHV or ADC_TRIM_VRANGE_LOWV)
+ * @return None
+ */
+STATIC INLINE void Chip_ADC_SetTrim(LPC_ADC_T *pADC, uint32_t trim)
+{
+ pADC->TRM = trim;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ADC_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/chip.h b/source/lpc_chip_11u6x/inc/chip.h
new file mode 100644
index 0000000..7bb889b
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/chip.h
@@ -0,0 +1,229 @@
+/*
+ * @brief LPC11U6x basic chip inclusion file
+ *
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __CHIP_H_
+#define __CHIP_H_
+
+#include "lpc_types.h"
+#include "sys_config.h"
+#include "cmsis.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef CORE_M0PLUS
+#error CORE_M0PLUS is not defined for the LPC11U6x architecture
+#error CORE_M0PLUS should be defined as part of your compiler define list
+#endif
+
+#if !defined(CHIP_LPC11U6X)
+#error "CHIP_LPC11U6X is not defined!"
+#endif
+
+/** @defgroup PERIPH_11U6X_BASE CHIP: LPC11u6x Peripheral addresses and register set declarations
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+#define LPC_PMU_BASE 0x40038000
+#define LPC_IOCON_BASE 0x40044000
+#define LPC_SYSCTL_BASE 0x40048000
+#define LPC_GPIO_PORT_BASE 0xA0000000
+#define LPC_GPIO_GROUP_INT0_BASE 0x4005C000
+#define LPC_GPIO_GROUP_INT1_BASE 0x40060000
+#define LPC_PIN_INT_BASE 0xA0004000
+#define LPC_USART0_BASE 0x40008000
+#define LPC_USART1_BASE 0x4006C000
+#define LPC_USART2_BASE 0x40070000
+#define LPC_USART3_BASE 0x40074000
+#define LPC_USART4_BASE 0x4004C000
+#define LPC_I2C0_BASE 0x40000000
+#define LPC_I2C1_BASE 0x40020000
+#define LPC_SSP0_BASE 0x40040000
+#define LPC_SSP1_BASE 0x40058000
+#define LPC_USB0_BASE 0x40080000
+#define LPC_ADC_BASE 0x4001C000
+#define LPC_SCT0_BASE 0x5000C000
+#define LPC_SCT1_BASE 0x5000E000
+#define LPC_TIMER16_0_BASE 0x4000C000
+#define LPC_TIMER16_1_BASE 0x40010000
+#define LPC_TIMER32_0_BASE 0x40014000
+#define LPC_TIMER32_1_BASE 0x40018000
+#define LPC_RTC_BASE 0x40024000
+#define LPC_WWDT_BASE 0x40004000
+#define LPC_DMA_BASE 0x50004000
+#define LPC_CRC_BASE 0x50000000
+#define LPC_FLASH_BASE 0x4003C000
+#define LPC_DMATRIGMUX_BASE 0x40028000UL
+
+#define LPC_PMU ((LPC_PMU_T *) LPC_PMU_BASE)
+#define LPC_IOCON ((LPC_IOCON_T *) LPC_IOCON_BASE)
+#define LPC_SYSCTL ((LPC_SYSCTL_T *) LPC_SYSCTL_BASE)
+#define LPC_GPIO ((LPC_GPIO_T *) LPC_GPIO_PORT_BASE)
+#define LPC_GPIOGROUP ((LPC_GPIOGROUPINT_T *) LPC_GPIO_GROUP_INT0_BASE)
+#define LPC_PININT ((LPC_PIN_INT_T *) LPC_PIN_INT_BASE)
+#define LPC_USART0 ((LPC_USART0_T *) LPC_USART0_BASE)
+#define LPC_USART1 ((LPC_USARTN_T *) LPC_USART1_BASE)
+#define LPC_USART2 ((LPC_USARTN_T *) LPC_USART2_BASE)
+#define LPC_USART3 ((LPC_USARTN_T *) LPC_USART3_BASE)
+#define LPC_USART4 ((LPC_USARTN_T *) LPC_USART4_BASE)
+#define LPC_I2C0 ((LPC_I2C_T *) LPC_I2C0_BASE)
+#define LPC_I2C1 ((LPC_I2C_T *) LPC_I2C1_BASE)
+#define LPC_SSP0 ((LPC_SSP_T *) LPC_SSP0_BASE)
+#define LPC_SSP1 ((LPC_SSP_T *) LPC_SSP1_BASE)
+#define LPC_USB ((LPC_USB_T *) LPC_USB0_BASE)
+#define LPC_ADC ((LPC_ADC_T *) LPC_ADC_BASE)
+#define LPC_SCT0 ((LPC_SCT_T *) LPC_SCT0_BASE)
+#define LPC_SCT1 ((LPC_SCT_T *) LPC_SCT1_BASE)
+#define LPC_TIMER16_0 ((LPC_TIMER_T *) LPC_TIMER16_0_BASE)
+#define LPC_TIMER16_1 ((LPC_TIMER_T *) LPC_TIMER16_1_BASE)
+#define LPC_TIMER32_0 ((LPC_TIMER_T *) LPC_TIMER32_0_BASE)
+#define LPC_TIMER32_1 ((LPC_TIMER_T *) LPC_TIMER32_1_BASE)
+#define LPC_RTC ((LPC_RTC_T *) LPC_RTC_BASE)
+#define LPC_WWDT ((LPC_WWDT_T *) LPC_WWDT_BASE)
+#define LPC_DMA ((LPC_DMA_T *) LPC_DMA_BASE)
+#define LPC_DMATRIGMUX ((LPC_DMATRIGMUX_T *) LPC_DMATRIGMUX_BASE)
+#define LPC_CRC ((LPC_CRC_T *) LPC_CRC_BASE)
+#define LPC_FMC ((LPC_FMC_T *) LPC_FLASH_BASE)
+
+/* IRQ Handler Alias list */
+#define UART1_4_IRQHandler USART1_4_IRQHandler
+#define UART2_3_IRQHandler USART2_3_IRQHandler
+#define UART0_IRQHandler USART0_IRQHandler
+
+/**
+ * @}
+ */
+
+/** @ingroup CHIP_11U6X_DRIVER_OPTIONS
+ * @{
+ */
+
+/**
+ * @brief System oscillator rate
+ * This value is defined externally to the chip layer and contains
+ * the value in Hz for the external oscillator for the board. If using the
+ * internal oscillator, this rate can be 0.
+ */
+extern const uint32_t OscRateIn;
+
+/**
+ * @brief RTC oscillator rate
+ * This value is defined externally to the chip layer and contains
+ * the value in Hz for the RTC oscillator for the board. This is
+ * usually 32KHz (32768). If not using the RTC, this rate can be 0.
+ */
+extern const uint32_t RTCOscRateIn;
+
+/**
+ * @}
+ */
+
+/* Include order is important! */
+#include "romapi_11u6x.h"
+#include "syscon_11u6x.h"
+#include "clock_11u6x.h"
+#include "iocon_11u6x.h"
+#include "pmu_11u6x.h"
+#include "crc_11u6x.h"
+#include "gpio_11u6x.h"
+#include "pinint_11u6x.h"
+#include "gpiogroup_11u6x.h"
+#include "timer_11u6x.h"
+#include "uart_0_11u6x.h"
+#include "uart_n_11u6x.h"
+#include "ssp_11u6x.h"
+#include "adc_11u6x.h"
+#include "dma_11u6x.h"
+#include "i2c_11u6x.h"
+#include "i2cm_11u6x.h"
+#include "usbd_11u6x.h"
+#include "sct_11u6x.h"
+#include "rtc_11u6x.h"
+#include "wwdt_11u6x.h"
+#include "fmc_11u6x.h"
+
+/** @defgroup SUPPORT_11U6X_FUNC CHIP: LPC11u6x support functions
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief Current system clock rate, mainly used for sysTick
+ */
+extern uint32_t SystemCoreClock;
+
+/**
+ * @brief Update system core clock rate, should be called if the
+ * system has a clock rate change
+ * @return None
+ */
+void SystemCoreClockUpdate(void);
+
+/**
+ * @brief Set up and initialize hardware prior to call to main()
+ * @return None
+ * @note Chip_SystemInit() is called prior to the application and sets up
+ * system clocking prior to the application starting.
+ */
+void Chip_SystemInit(void);
+
+/**
+ * @brief USB Pin and clock initialization
+ * Calling this function will initialize the USB pins and the clock
+ * @return None
+ * @note This function will assume that the chip is clocked by an
+ * external crystal oscillator of frequency 12MHz and the Oscillator
+ * is running.
+ */
+void Chip_USB_Init(void);
+
+/**
+ * @brief Clock and PLL initialization based on the external oscillator
+ * @return None
+ * @note This function assumes an external crystal oscillator
+ * frequency of 12MHz.
+ */
+void Chip_SetupXtalClocking(void);
+
+/**
+ * @brief Clock and PLL initialization based on the internal oscillator
+ * @return None
+ */
+void Chip_SetupIrcClocking(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CHIP_H_ */
diff --git a/source/lpc_chip_11u6x/inc/clock_11u6x.h b/source/lpc_chip_11u6x/inc/clock_11u6x.h
new file mode 100644
index 0000000..600f087
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/clock_11u6x.h
@@ -0,0 +1,589 @@
+/*
+ * @brief LPC11U6X Clock control functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __CLOCK_11U6X_H_
+#define __CLOCK_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup CLOCK_11U6X CHIP: LPC11u6x Clock Control block driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/** Internal oscillator frequency */
+#define SYSCTL_IRC_FREQ (12000000)
+
+/**
+ * @brief Set System PLL divider values
+ * @param msel : PLL feedback divider value. M = msel + 1.
+ * @param psel : PLL post divider value. P = (1<SYSPLLCTRL = (msel & 0x1F) | ((psel & 0x3) << 5);
+}
+
+/**
+ * @brief Read System PLL lock status
+ * @return true of the PLL is locked. false if not locked
+ */
+STATIC INLINE bool Chip_Clock_IsSystemPLLLocked(void)
+{
+ return (bool) ((LPC_SYSCTL->SYSPLLSTAT & 1) != 0);
+}
+
+/**
+ * Clock sources for system PLL
+ */
+typedef enum CHIP_SYSCTL_PLLCLKSRC {
+ SYSCTL_PLLCLKSRC_IRC = 0, /*!< Internal oscillator in */
+ SYSCTL_PLLCLKSRC_MAINOSC, /*!< Crystal (main) oscillator in */
+ SYSCTL_PLLCLKSRC_SYSOSC = SYSCTL_PLLCLKSRC_MAINOSC,
+ SYSCTL_PLLCLKSRC_RESERVED1, /*!< Reserved */
+ SYSCTL_PLLCLKSRC_RTC32K, /*!< RTC 32KHz clock */
+} CHIP_SYSCTL_PLLCLKSRC_T;
+
+/**
+ * @brief Set System PLL clock source
+ * @param src : Clock source for system PLL
+ * @return Nothing
+ * @note This function will also toggle the clock source update register
+ * to update the clock source.
+ */
+void Chip_Clock_SetSystemPLLSource(CHIP_SYSCTL_PLLCLKSRC_T src);
+
+/**
+ * @brief Set USB PLL divider values
+ * @param msel : PLL feedback divider value. M = msel + 1.
+ * @param psel : PLL post divider value. P = (1<USBPLLCTRL = (msel & 0x1F) | ((psel & 0x3) << 5);
+}
+
+/**
+ * @brief Read USB PLL lock status
+ * @return true of the PLL is locked. false if not locked
+ */
+STATIC INLINE bool Chip_Clock_IsUSBPLLLocked(void)
+{
+ return (bool) ((LPC_SYSCTL->USBPLLSTAT & 1) != 0);
+}
+
+/**
+ * Clock sources for USB PLL
+ */
+typedef enum CHIP_SYSCTL_USBPLLCLKSRC {
+ SYSCTL_USBPLLCLKSRC_IRC = 0, /*!< Internal oscillator in */
+ SYSCTL_USBPLLCLKSRC_MAINOSC, /*!< Crystal (main) oscillator in */
+ SYSCTL_USBPLLCLKSRC_SYSOSC = SYSCTL_USBPLLCLKSRC_MAINOSC,
+ SYSCTL_USBPLLCLKSRC_RESERVED1, /*!< Reserved */
+ SYSCTL_USBPLLCLKSRC_RESERVED2, /*!< Reserved */
+} CHIP_SYSCTL_USBPLLCLKSRC_T;
+
+/**
+ * @brief Set USB PLL clock source
+ * @param src : Clock source for USB PLL
+ * @return Nothing
+ * @note This function will also toggle the clock source update register
+ * to update the clock source.
+ */
+void Chip_Clock_SetUSBPLLSource(CHIP_SYSCTL_USBPLLCLKSRC_T src);
+
+/**
+ * @brief Bypass System Oscillator and set oscillator frequency range
+ * @param bypass : Flag to bypass oscillator
+ * @param highfr : Flag to set oscillator range from 15-25 MHz
+ * @return Nothing
+ * @note Sets the PLL input to bypass the oscillator. This would be
+ * used if an external clock that is not an oscillator is attached
+ * to the XTALIN pin.
+ */
+void Chip_Clock_SetPLLBypass(bool bypass, bool highfr);
+
+/**
+ * @brief Enable the RTC 32KHz output
+ * @return Nothing
+ * @note This clock can be used for the main clock directly, but
+ * do not use this clock with the system PLL.
+ */
+STATIC INLINE void Chip_Clock_EnableRTCOsc(void)
+{
+ LPC_SYSCTL->RTCOSCCTRL = 1;
+}
+
+/**
+ * @brief Disable the RTC 32KHz output
+ * @return Nothing
+ */
+STATIC INLINE void Chip_Clock_DisableRTCOsc(void)
+{
+ LPC_SYSCTL->RTCOSCCTRL = 0;
+}
+
+/**
+ * Watchdog and low frequency oscillator frequencies plus or minus 40%
+ */
+typedef enum CHIP_WDTLFO_OSC {
+ WDTLFO_OSC_ILLEGAL,
+ WDTLFO_OSC_0_60, /*!< 0.6 MHz watchdog/LFO rate */
+ WDTLFO_OSC_1_05, /*!< 1.05 MHz watchdog/LFO rate */
+ WDTLFO_OSC_1_40, /*!< 1.4 MHz watchdog/LFO rate */
+ WDTLFO_OSC_1_75, /*!< 1.75 MHz watchdog/LFO rate */
+ WDTLFO_OSC_2_10, /*!< 2.1 MHz watchdog/LFO rate */
+ WDTLFO_OSC_2_40, /*!< 2.4 MHz watchdog/LFO rate */
+ WDTLFO_OSC_2_70, /*!< 2.7 MHz watchdog/LFO rate */
+ WDTLFO_OSC_3_00, /*!< 3.0 MHz watchdog/LFO rate */
+ WDTLFO_OSC_3_25, /*!< 3.25 MHz watchdog/LFO rate */
+ WDTLFO_OSC_3_50, /*!< 3.5 MHz watchdog/LFO rate */
+ WDTLFO_OSC_3_75, /*!< 3.75 MHz watchdog/LFO rate */
+ WDTLFO_OSC_4_00, /*!< 4.0 MHz watchdog/LFO rate */
+ WDTLFO_OSC_4_20, /*!< 4.2 MHz watchdog/LFO rate */
+ WDTLFO_OSC_4_40, /*!< 4.4 MHz watchdog/LFO rate */
+ WDTLFO_OSC_4_60 /*!< 4.6 MHz watchdog/LFO rate */
+} CHIP_WDTLFO_OSC_T;
+
+/**
+ * @brief Setup Watchdog oscillator rate and divider
+ * @param wdtclk : Selected watchdog clock rate
+ * @param div : Watchdog divider value, even value between 2 and 64
+ * @return Nothing
+ * @note Watchdog rate = selected rate divided by divider rate
+ */
+STATIC INLINE void Chip_Clock_SetWDTOSC(CHIP_WDTLFO_OSC_T wdtclk, uint8_t div)
+{
+ LPC_SYSCTL->WDTOSCCTRL = (((uint32_t) wdtclk) << 5) | ((div >> 1) - 1);
+}
+
+/**
+ * Clock sources for main system clock
+ */
+typedef enum CHIP_SYSCTL_MAINCLKSRC {
+ SYSCTL_MAINCLKSRC_IRC = 0, /*!< Internal oscillator */
+ SYSCTL_MAINCLKSRC_PLLIN, /*!< System PLL input */
+ SYSCTL_MAINCLKSRC_WDTOSC, /*!< Watchdog oscillator rate */
+ SYSCTL_MAINCLKSRC_PLLOUT, /*!< System PLL output */
+} CHIP_SYSCTL_MAINCLKSRC_T;
+
+/**
+ * @brief Set main system clock source
+ * @param src : Clock source for main system
+ * @return Nothing
+ * @note This function will also toggle the clock source update register
+ * to update the clock source.
+ */
+void Chip_Clock_SetMainClockSource(CHIP_SYSCTL_MAINCLKSRC_T src);
+
+/**
+ * @brief Returns the main clock source
+ * @return Which clock is used for the core clock source?
+ */
+STATIC INLINE CHIP_SYSCTL_MAINCLKSRC_T Chip_Clock_GetMainClockSource(void)
+{
+ return (CHIP_SYSCTL_MAINCLKSRC_T) (LPC_SYSCTL->MAINCLKSEL);
+}
+
+/**
+ * @brief Set system clock divider
+ * @param div : divider for system clock
+ * @return Nothing
+ * @note Use 0 to disable, or a divider value of 1 to 255. The system clock
+ * rate is the main system clock divided by this value.
+ */
+STATIC INLINE void Chip_Clock_SetSysClockDiv(uint32_t div)
+{
+ LPC_SYSCTL->SYSAHBCLKDIV = div;
+}
+
+/**
+ * System and peripheral clocks
+ */
+typedef enum CHIP_SYSCTL_CLOCK {
+ SYSCTL_CLOCK_SYS = 0, /*!< 0: System clock */
+ SYSCTL_CLOCK_ROM, /*!< 1: ROM clock */
+ SYSCTL_CLOCK_RAM0, /*!< 2: RAM0 clock */
+ SYSCTL_CLOCK_FLASHREG, /*!< 3: FLASH register interface clock */
+ SYSCTL_CLOCK_FLASHARRAY, /*!< 4: FLASH array access clock */
+ SYSCTL_CLOCK_I2C0, /*!< 5: I2C0 clock */
+ SYSCTL_CLOCK_GPIO, /*!< 6: GPIO clock */
+ SYSCTL_CLOCK_CT16B0, /*!< 7: 16-bit Counter/timer 0 clock */
+ SYSCTL_CLOCK_CT16B1, /*!< 8: 16-bit Counter/timer 1 clock */
+ SYSCTL_CLOCK_CT32B0, /*!< 9: 32-bit Counter/timer 0 clock */
+ SYSCTL_CLOCK_CT32B1, /*!< 10: 32-bit Counter/timer 1 clock */
+ SYSCTL_CLOCK_SSP0, /*!< 11: SSP0 clock */
+ SYSCTL_CLOCK_UART0, /*!< 12: UART0 clock */
+ SYSCTL_CLOCK_ADC, /*!< 13: ADC clock */
+ SYSCTL_CLOCK_USB, /*!< 14: USB clock */
+ SYSCTL_CLOCK_WDT, /*!< 15: Watchdog timer clock */
+ SYSCTL_CLOCK_IOCON, /*!< 16: IOCON block clock */
+ SYSCTL_CLOCK_RESERVED17, /*!< 17: Reserved */
+ SYSCTL_CLOCK_SSP1, /*!< 18: SSP1 clock */
+ SYSCTL_CLOCK_PINT, /*!< 19: GPIO Pin int register interface clock */
+ SYSCTL_CLOCK_USART1, /*!< 20: USART1 clock */
+ SYSCTL_CLOCK_USART2, /*!< 21: USART2 clock */
+ SYSCTL_CLOCK_USART3_4, /*!< 22: USART3_4 clock */
+ SYSCTL_CLOCK_P0INT, /*!< 23: GPIO GROUP1 interrupt register clock */
+ SYSCTL_CLOCK_GROUP0INT = SYSCTL_CLOCK_P0INT,/*!< 23: GPIO GROUP0 interrupt register interface clock */
+ SYSCTL_CLOCK_P1INT, /*!< 24: GPIO GROUP1 interrupt register clock */
+ SYSCTL_CLOCK_GROUP1INT = SYSCTL_CLOCK_P1INT,/*!< 24: GPIO GROUP1 interrupt register interface clock */
+ SYSCTL_CLOCK_I2C1, /*!< 25: I2C1 clock */
+ SYSCTL_CLOCK_RAM1, /*!< 26: SRAM block clock */
+ SYSCTL_CLOCK_USBRAM, /*!< 27: USB SRAM block clock */
+ SYSCTL_CLOCK_CRC, /*!< 25: CRC clock */
+ SYSCTL_CLOCK_DMA, /*!< 25: DMA clock */
+ SYSCTL_CLOCK_RTC, /*!< 25: RTC clock */
+ SYSCTL_CLOCK_SCT0_1, /*!< 25: SCT 0/1 clock */
+} CHIP_SYSCTL_CLOCK_T;
+
+/**
+ * @brief Enable a system or peripheral clock
+ * @param clk : Clock to enable
+ * @return Nothing
+ */
+STATIC INLINE void Chip_Clock_EnablePeriphClock(CHIP_SYSCTL_CLOCK_T clk)
+{
+ LPC_SYSCTL->SYSAHBCLKCTRL |= (1 << clk);
+}
+
+/**
+ * @brief Disable a system or peripheral clock
+ * @param clk : Clock to disable
+ * @return Nothing
+ */
+STATIC INLINE void Chip_Clock_DisablePeriphClock(CHIP_SYSCTL_CLOCK_T clk)
+{
+ LPC_SYSCTL->SYSAHBCLKCTRL &= ~(1 << clk);
+}
+
+/**
+ * @brief Set SSP0 divider
+ * @param div : divider for SSP0 clock
+ * @return Nothing
+ * @note Use 0 to disable, or a divider value of 1 to 255. The SSP0 clock
+ * rate is the main system clock divided by this value.
+ */
+STATIC INLINE void Chip_Clock_SetSSP0ClockDiv(uint32_t div)
+{
+ LPC_SYSCTL->SSP0CLKDIV = div;
+}
+
+/**
+ * @brief Return SSP0 divider
+ * @return divider for SSP0 clock
+ * @note A value of 0 means the clock is disabled.
+ */
+STATIC INLINE uint32_t Chip_Clock_GetSSP0ClockDiv(void)
+{
+ return LPC_SYSCTL->SSP0CLKDIV;
+}
+
+/**
+ * @brief Set USART0 divider clock
+ * @param div : divider for UART clock
+ * @return Nothing
+ * @note Use 0 to disable, or a divider value of 1 to 255. The UART clock
+ * rate is the main system clock divided by this value.
+ */
+STATIC INLINE void Chip_Clock_SetUSART0ClockDiv(uint32_t div)
+{
+ LPC_SYSCTL->USART0CLKDIV = div;
+}
+
+/**
+ * @brief Return USART0 divider
+ * @return divider for UART clock
+ * @note A value of 0 means the clock is disabled.
+ */
+STATIC INLINE uint32_t Chip_Clock_GetUASRT0ClockDiv(void)
+{
+ return LPC_SYSCTL->USART0CLKDIV;
+}
+
+/**
+ * @brief Set SSP1 divider clock
+ * @param div : divider for SSP1 clock
+ * @return Nothing
+ * @note Use 0 to disable, or a divider value of 1 to 255. The SSP1 clock
+ * rate is the main system clock divided by this value.
+ */
+STATIC INLINE void Chip_Clock_SetSSP1ClockDiv(uint32_t div)
+{
+ LPC_SYSCTL->SSP1CLKDIV = div;
+}
+
+/**
+ * @brief Return SSP1 divider
+ * @return divider for SSP1 clock
+ * @note A value of 0 means the clock is disabled.
+ */
+STATIC INLINE uint32_t Chip_Clock_GetSSP1ClockDiv(void)
+{
+ return LPC_SYSCTL->SSP1CLKDIV;
+}
+
+/**
+ * @brief Set USART 1/2/3/4 UART base rate (up to main clock rate)
+ * @param rate : Desired rate for fractional divider/multipler output
+ * @param fEnable : true to use fractional clocking, false for integer clocking
+ * @return Actual rate generated
+ * @note USARTs 1 - 4 use the same base clock for their baud rate
+ * basis. This function is used to generate that clock, while the
+ * UART driver's SetBaud functions will attempt to get the closest
+ * baud rate from this base clock without altering it. This needs
+ * to be setup prior to individual UART setup.
+ * UARTs need a base clock 16x faster than the baud rate, so if you
+ * need a 115.2Kbps baud rate, you will need a clock rate of at
+ * least (115.2K * 16). The UART base clock is generated from the
+ * main system clock, so fractional clocking may be the only
+ * possible choice when using a low main system clock frequency.
+ * Do not alter the FRGCLKDIV register after this call.
+ */
+uint32_t Chip_Clock_SetUSARTNBaseClockRate(uint32_t rate, bool fEnable);
+
+/**
+ * @brief Get USART 1/2/3/4 UART base rate
+ * @return USART 1/2/3/4 UART base rate
+ */
+uint32_t Chip_Clock_GetUSARTNBaseClockRate(void);
+
+/**
+ * @brief Set USART 1/2/3/4 fractional baud rate divider clock
+ * @param div : divider for USART 1/2/3/4 fractional baud rate clock
+ * @return Nothing
+ * @note Use 0 to disable, or a divider value of 1 to 255.
+ * This does not affect USART0.
+ */
+STATIC INLINE void Chip_Clock_SetUSARTNBaseClockDiv(uint8_t div)
+{
+ LPC_SYSCTL->FRGCLKDIV = (uint32_t) div;
+}
+
+/**
+ * @brief Return USART 1/2/3/4 fractional baud rate divider
+ * @return divider for USART 1/2/3/4 fractional baud rate clock
+ * @note A value of 0 means the clock is disabled.
+ * This does not affect USART0.
+ */
+STATIC INLINE uint32_t Chip_Clock_GetUSARTNBaseClockDiv(void)
+{
+ return LPC_SYSCTL->FRGCLKDIV;
+}
+
+/**
+ * @brief Set The USART Fractional Generator Divider
+ * @param div : Fractional Generator Divider value, should be 0xFF
+ * @return Nothing
+ */
+STATIC INLINE void Chip_Clock_SetUSARTNFRGDivider(uint8_t div)
+{
+ LPC_SYSCTL->UARTFRGDIV = (uint32_t) div;
+}
+
+/**
+ * @brief Set The USART Fractional Generator Divider
+ * @return Value of USART Fractional Generator Divider
+ */
+STATIC INLINE uint32_t Chip_Clock_GetUSARTNFRGDivider(void)
+{
+ return LPC_SYSCTL->UARTFRGDIV;
+}
+
+/**
+ * @brief Set The USART Fractional Generator Multiplier
+ * @param mult : An 8-bit value (0-255) U_PCLK = UARTCLKDIV/(1 + MULT/256)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_Clock_SetUSARTNFRGMultiplier(uint8_t mult)
+{
+ LPC_SYSCTL->UARTFRGMULT = (uint32_t) mult;
+}
+
+/**
+ * @brief Get The USART Fractional Generator Multiplier
+ * @return Value of USART Fractional Generator Multiplier
+ */
+STATIC INLINE uint32_t Chip_Clock_GetUSARTNFRGMultiplier(void)
+{
+ return LPC_SYSCTL->UARTFRGMULT;
+}
+
+/**
+ * Clock sources for USB
+ */
+typedef enum CHIP_SYSCTL_USBCLKSRC {
+ SYSCTL_USBCLKSRC_PLLOUT = 0, /*!< USB PLL out */
+ SYSCTL_USBCLKSRC_MAINSYSCLK, /*!< Main system clock */
+} CHIP_SYSCTL_USBCLKSRC_T;
+
+/**
+ * @brief Set USB clock source and divider
+ * @param src : Clock source for USB
+ * @param div : divider for USB clock
+ * @return Nothing
+ * @note Use 0 to disable, or a divider value of 1 to 255. The USB clock
+ * rate is either the main system clock or USB PLL output clock divided
+ * by this value. This function will also toggle the clock source
+ * update register to update the clock source.
+ */
+void Chip_Clock_SetUSBClockSource(CHIP_SYSCTL_USBCLKSRC_T src, uint32_t div);
+
+/**
+ * Clock sources for CLKOUT
+ */
+typedef enum CHIP_SYSCTL_CLKOUTSRC {
+ SYSCTL_CLKOUTSRC_IRC = 0, /*!< Internal oscillator for CLKOUT */
+ SYSCTL_CLKOUTSRC_MAINOSC, /*!< Main oscillator for CLKOUT */
+ SYSCTL_CLKOUTSRC_SYSOSC = SYSCTL_CLKOUTSRC_MAINOSC,
+ SYSCTL_CLKOUTSRC_WDTOSC, /*!< Watchdog oscillator for CLKOUT */
+ SYSCTL_CLKOUTSRC_MAINSYSCLK, /*!< Main system clock for CLKOUT */
+} CHIP_SYSCTL_CLKOUTSRC_T;
+
+/**
+ * @brief Set CLKOUT clock source and divider
+ * @param src : Clock source for CLKOUT
+ * @param div : divider for CLKOUT clock
+ * @return Nothing
+ * @note Use 0 to disable, or a divider value of 1 to 255. The CLKOUT clock
+ * rate is the clock source divided by the divider. This function will
+ * also toggle the clock source update register to update the clock
+ * source.
+ */
+void Chip_Clock_SetCLKOUTSource(CHIP_SYSCTL_CLKOUTSRC_T src, uint32_t div);
+
+/**
+ * @brief Set IOCON glitch filter clock divider value
+ * @param index : IOCON divider index (0 - 6) to set
+ * @param div : value for IOCON filter divider value
+ * @return Nothing
+ * @note Use 0 to disable, or a divider value of 1 to 255.
+ */
+STATIC INLINE void Chip_Clock_SetIOCONFiltClockDiv(int index, uint32_t div)
+{
+ LPC_SYSCTL->IOCONCLKDIV[6 - index] = div;
+}
+
+/**
+ * @brief Return IOCON glitch filter clock divider value
+ * @param index : IOCON divider index (0 - 6) to get
+ * @return IOCON glitch filter clock divider value
+ */
+STATIC INLINE uint32_t Chip_Clock_GetIOCONFiltClockDiv(int index)
+{
+ return LPC_SYSCTL->IOCONCLKDIV[6 - index];
+}
+
+/**
+ * @brief Returns the main oscillator clock rate
+ * @return main oscillator clock rate in Hz
+ */
+STATIC INLINE uint32_t Chip_Clock_GetMainOscRate(void)
+{
+ return OscRateIn;
+}
+
+/**
+ * @brief Returns the internal oscillator (IRC) clock rate
+ * @return internal oscillator (IRC) clock rate in Hz
+ */
+STATIC INLINE uint32_t Chip_Clock_GetIntOscRate(void)
+{
+ return SYSCTL_IRC_FREQ;
+}
+
+/**
+ * @brief Returns the RTC clock rate
+ * @return RTC oscillator clock rate in Hz
+ */
+STATIC INLINE uint32_t Chip_Clock_GetRTCOscRate(void)
+{
+ return RTCOscRateIn;
+}
+
+/**
+ * @brief Return estimated watchdog oscillator rate
+ * @return Estimated watchdog oscillator rate
+ * @note This rate is accurate to plus or minus 40%.
+ */
+uint32_t Chip_Clock_GetWDTOSCRate(void);
+
+/**
+ * @brief Return System PLL input clock rate
+ * @return System PLL input clock rate
+ */
+uint32_t Chip_Clock_GetSystemPLLInClockRate(void);
+
+/**
+ * @brief Return System PLL output clock rate
+ * @return System PLL output clock rate
+ */
+uint32_t Chip_Clock_GetSystemPLLOutClockRate(void);
+
+/**
+ * @brief Return USB PLL input clock rate
+ * @return USB PLL input clock rate
+ */
+uint32_t Chip_Clock_GetUSBPLLInClockRate(void);
+
+/**
+ * @brief Return USB PLL output clock rate
+ * @return USB PLL output clock rate
+ */
+uint32_t Chip_Clock_GetUSBPLLOutClockRate(void);
+
+/**
+ * @brief Return main clock rate
+ * @return main clock rate
+ */
+uint32_t Chip_Clock_GetMainClockRate(void);
+
+/**
+ * @brief Return system clock rate
+ * @return system clock rate
+ */
+uint32_t Chip_Clock_GetSystemClockRate(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CLOCK_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/cmsis.h b/source/lpc_chip_11u6x/inc/cmsis.h
new file mode 100644
index 0000000..7fd0c75
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/cmsis.h
@@ -0,0 +1,153 @@
+/*
+ * @brief Basic CMSIS include file for LPC11U6X
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __CMSIS_11U6X_H_
+#define __CMSIS_11U6X_H_
+
+#include "lpc_types.h"
+#include "sys_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup CMSIS_11U6X CHIP: LPC11U6X CMSIS include file
+ * @ingroup CHIP_11U6X_CMSIS_Drivers
+ * @{
+ */
+
+#if defined(__ARMCC_VERSION)
+// Kill warning "#pragma push with no matching #pragma pop"
+ #pragma diag_suppress 2525
+ #pragma push
+ #pragma anon_unions
+#elif defined(__CWCC__)
+ #pragma push
+ #pragma cpp_extensions on
+#elif defined(__GNUC__)
+/* anonymous unions are enabled by default */
+#elif defined(__IAR_SYSTEMS_ICC__)
+// #pragma push // FIXME not usable for IAR
+ #pragma language=extended
+#else
+ #error Not supported compiler type
+#endif
+
+/*
+ * ==========================================================================
+ * ---------- Interrupt Number Definition -----------------------------------
+ * ==========================================================================
+ */
+
+#if !defined(CHIP_LPC11U6X)
+#error Incorrect or missing device variant (CHIP_LPC11U6X)
+#endif
+
+/** @defgroup CMSIS_11U6X_IRQ CHIP_LPC11U6X: CHIP_LPC11U6X peripheral interrupt numbers
+ * @{
+ */
+
+typedef enum {
+ NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
+ HardFault_IRQn = -13, /*!< 3 Cortex-M0 Hard Fault Interrupt */
+ SVCall_IRQn = -5, /*!< 11 Cortex-M0 SV Call Interrupt */
+ PendSV_IRQn = -2, /*!< 14 Cortex-M0 Pend SV Interrupt */
+ SysTick_IRQn = -1, /*!< 15 Cortex-M0 System Tick Interrupt */
+
+ PIN_INT0_IRQn = 0, /*!< Pin Interrupt 0 */
+ PIN_INT1_IRQn = 1, /*!< Pin Interrupt 1 */
+ PIN_INT2_IRQn = 2, /*!< Pin Interrupt 2 */
+ PIN_INT3_IRQn = 3, /*!< Pin Interrupt 3 */
+ PIN_INT4_IRQn = 4, /*!< Pin Interrupt 4 */
+ PIN_INT5_IRQn = 5, /*!< Pin Interrupt 5 */
+ PIN_INT6_IRQn = 6, /*!< Pin Interrupt 6 */
+ PIN_INT7_IRQn = 7, /*!< Pin Interrupt 7 */
+ GINT0_IRQn = 8, /*!< GPIO interrupt status of port 0 */
+ GINT1_IRQn = 9, /*!< GPIO interrupt status of port 1 */
+ I2C1_IRQn = 10, /*!< I2C1 Interrupt */
+ USART1_4_IRQn = 11, /*!< Combined USART1 and USART4 interrupts */
+ USART2_3_IRQn = 12, /*!< Combined USART2 and USART3 interrupts */
+ SCT0_1_IRQn = 13, /*!< Combined SCT0 and SCT1 interrupts */
+ SSP1_IRQn = 14, /*!< SSP1 Interrupt */
+ I2C0_IRQn = 15, /*!< I2C0 Interrupt */
+ TIMER_16_0_IRQn = 16, /*!< 16-bit Timer0 Interrupt */
+ TIMER_16_1_IRQn = 17, /*!< 16-bit Timer1 Interrupt */
+ TIMER_32_0_IRQn = 18, /*!< 32-bit Timer0 Interrupt */
+ TIMER_32_1_IRQn = 19, /*!< 32-bit Timer1 Interrupt */
+ SSP0_IRQn = 20, /*!< SSP0 Interrupt */
+ USART0_IRQn = 21, /*!< USART0 interrupt */
+ USB0_IRQn = 22, /*!< USB IRQ interrupt */
+ USB0_FIQ_IRQn = 23, /*!< USB FIQ interrupt */
+ ADC_A_IRQn = 24, /*!< ADC_A Converter Interrupt */
+ RTC_IRQn = 25, /*!< RTC Interrupt */
+ BOD_WDT_IRQn = 26, /*!< Shared Brown Out Detect(BOD) and WDT Interrupts */
+ FMC_IRQn = 27, /*!< FLASH Interrupt */
+ DMA_IRQn = 28, /*!< DMA Interrupt */
+ ADC_B_IRQn = 29, /*!< ADC_B Interrupt */
+ USB_WAKEUP_IRQn = 30, /*!< USB wake-up interrupt Interrupt */
+ RESERVED31_IRQn = 31,
+} IRQn_Type;
+
+/**
+ * @}
+ */
+
+/*
+ * ==========================================================================
+ * ----------- Processor and Core Peripheral Section ------------------------
+ * ==========================================================================
+ */
+
+/** @defgroup CMSIS_11U6X_COMMON CHIP: LPC11U6X Cortex CMSIS definitions
+ * @{
+ */
+
+/* Configuration of the Cortex-M0+ Processor and Core Peripherals */
+#define __CM0_REV 0x0000 /*!< Cortex-M0 Core Revision */
+#define __MPU_PRESENT 0 /*!< MPU present or not */
+#define __NVIC_PRIO_BITS 2 /*!< Number of Bits used for Priority Levels */
+#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
+
+/**
+ * @}
+ */
+
+#include "core_cm0plus.h" /*!< Cortex-M0+ processor and core peripherals */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CMSIS_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/core_cm0plus.h b/source/lpc_chip_11u6x/inc/core_cm0plus.h
new file mode 100644
index 0000000..5cea74e
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/core_cm0plus.h
@@ -0,0 +1,793 @@
+/**************************************************************************//**
+ * @file core_cm0plus.h
+ * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File
+ * @version V3.20
+ * @date 25. February 2013
+ *
+ * @note
+ *
+ ******************************************************************************/
+/* Copyright (c) 2009 - 2013 ARM LIMITED
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ - Neither the name of ARM nor the names of its contributors may be used
+ to endorse or promote products derived from this software without
+ specific prior written permission.
+ *
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ ---------------------------------------------------------------------------*/
+
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#ifndef __CORE_CM0PLUS_H_GENERIC
+#define __CORE_CM0PLUS_H_GENERIC
+
+/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/** \ingroup Cortex-M0+
+ @{
+ */
+
+/* CMSIS CM0P definitions */
+#define __CM0PLUS_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */
+#define __CM0PLUS_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */
+#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16) | \
+ __CM0PLUS_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */
+
+#define __CORTEX_M (0x00) /*!< Cortex-M Core */
+
+
+#if defined ( __CC_ARM )
+ #define __ASM __asm /*!< asm keyword for ARM Compiler */
+ #define __INLINE __inline /*!< inline keyword for ARM Compiler */
+ #define __STATIC_INLINE static __inline
+
+#elif defined ( __ICCARM__ )
+ #define __ASM __asm /*!< asm keyword for IAR Compiler */
+ #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
+ #define __STATIC_INLINE static inline
+
+#elif defined ( __GNUC__ )
+ #define __ASM __asm /*!< asm keyword for GNU Compiler */
+ #define __INLINE inline /*!< inline keyword for GNU Compiler */
+ #define __STATIC_INLINE static inline
+
+#elif defined ( __TASKING__ )
+ #define __ASM __asm /*!< asm keyword for TASKING Compiler */
+ #define __INLINE inline /*!< inline keyword for TASKING Compiler */
+ #define __STATIC_INLINE static inline
+
+#endif
+
+/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all
+*/
+#define __FPU_USED 0
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+#endif
+
+#include /* standard types definitions */
+#include /* Core Instruction Access */
+#include /* Core Function Access */
+
+#endif /* __CORE_CM0PLUS_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM0PLUS_H_DEPENDANT
+#define __CORE_CM0PLUS_H_DEPENDANT
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM0PLUS_REV
+ #define __CM0PLUS_REV 0x0000
+ #warning "__CM0PLUS_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __VTOR_PRESENT
+ #define __VTOR_PRESENT 0
+ #warning "__VTOR_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/*@} end of group Cortex-M0+ */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core MPU Register
+ ******************************************************************************/
+/** \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/** \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/** \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+#if (__CORTEX_M != 0x04)
+ uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */
+#else
+ uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
+#endif
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+
+/** \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+
+/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+#if (__CORTEX_M != 0x04)
+ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
+#else
+ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
+#endif
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+
+/** \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
+ uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */
+ uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/*@} end of group CMSIS_CORE */
+
+
+/** \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[31];
+ __IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[31];
+ __IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[31];
+ __IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[31];
+ uint32_t RESERVED4[64];
+ __IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
+} NVIC_Type;
+
+/*@} end of group CMSIS_NVIC */
+
+
+/** \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/** \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+#if (__VTOR_PRESENT == 1)
+ __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+#else
+ uint32_t RESERVED0;
+#endif
+ __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ uint32_t RESERVED1;
+ __IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
+ __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */
+
+#if (__VTOR_PRESENT == 1)
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 8 /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+#endif
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/** \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/** \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+#if (__MPU_PRESENT == 1)
+/** \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/** \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */
+ __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */
+} MPU_Type;
+
+/* MPU Type Register */
+#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register */
+#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register */
+#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register */
+#define MPU_RBAR_ADDR_Pos 8 /*!< MPU RBAR: ADDR Position */
+#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */
+
+#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */
+#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */
+
+#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */
+#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */
+
+/* MPU Region Attribute and Size Register */
+#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */
+#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */
+
+#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */
+#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */
+
+#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */
+#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */
+
+#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */
+#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */
+
+#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */
+#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */
+
+#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */
+#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */
+
+#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */
+#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */
+
+#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */
+#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */
+
+#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */
+#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */
+
+#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */
+#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+/** \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR)
+ are only accessible over DAP and not via processor. Therefore
+ they are not covered by the Cortex-M0 header file.
+ @{
+ */
+/*@} end of group CMSIS_CoreDebug */
+
+
+/** \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Cortex-M0+ Hardware */
+#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+
+#if (__MPU_PRESENT == 1)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+#endif
+
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/** \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+/* Interrupt Priorities are WORD accessible only under ARMv6M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 )
+#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) )
+#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) )
+
+
+/** \brief Enable External Interrupt
+
+ The function enables a device-specific interrupt in the NVIC interrupt controller.
+
+ \param [in] IRQn External interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
+}
+
+
+/** \brief Disable External Interrupt
+
+ The function disables a device-specific interrupt in the NVIC interrupt controller.
+
+ \param [in] IRQn External interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
+}
+
+
+/** \brief Get Pending Interrupt
+
+ The function reads the pending register in the NVIC and returns the pending bit
+ for the specified interrupt.
+
+ \param [in] IRQn Interrupt number.
+
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ */
+__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
+}
+
+
+/** \brief Set Pending Interrupt
+
+ The function sets the pending bit of an external interrupt.
+
+ \param [in] IRQn Interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F));
+}
+
+
+/** \brief Clear Pending Interrupt
+
+ The function clears the pending bit of an external interrupt.
+
+ \param [in] IRQn External interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
+}
+
+
+/** \brief Set Interrupt Priority
+
+ The function sets the priority of an interrupt.
+
+ \note The priority cannot be set for every core interrupt.
+
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ */
+__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if(IRQn < 0) {
+ SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
+ (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
+ else {
+ NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
+ (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
+}
+
+
+/** \brief Get Interrupt Priority
+
+ The function reads the priority of an interrupt. The interrupt
+ number can be positive to specify an external (device specific)
+ interrupt, or negative to specify an internal (core) interrupt.
+
+
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented
+ priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if(IRQn < 0) {
+ return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */
+ else {
+ return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */
+}
+
+
+/** \brief System Reset
+
+ The function initiates a system reset request to reset the MCU.
+ */
+__STATIC_INLINE void NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+ while(1); /* wait until reset */
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+
+
+/* ################################## SysTick function ############################################ */
+/** \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if (__Vendor_SysTickConfig == 0)
+
+/** \brief System Tick Configuration
+
+ The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+
+ \param [in] ticks Number of ticks between two interrupts.
+
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
+
+ SysTick->LOAD = ticks - 1; /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0); /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+
+#endif /* __CORE_CM0PLUS_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/lpc_chip_11u6x/inc/core_cmFunc.h b/source/lpc_chip_11u6x/inc/core_cmFunc.h
new file mode 100644
index 0000000..0a18faf
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/core_cmFunc.h
@@ -0,0 +1,636 @@
+/**************************************************************************//**
+ * @file core_cmFunc.h
+ * @brief CMSIS Cortex-M Core Function Access Header File
+ * @version V3.20
+ * @date 25. February 2013
+ *
+ * @note
+ *
+ ******************************************************************************/
+/* Copyright (c) 2009 - 2013 ARM LIMITED
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ - Neither the name of ARM nor the names of its contributors may be used
+ to endorse or promote products derived from this software without
+ specific prior written permission.
+ *
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ ---------------------------------------------------------------------------*/
+
+
+#ifndef __CORE_CMFUNC_H
+#define __CORE_CMFUNC_H
+
+
+/* ########################### Core Function Access ########################### */
+/** \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
+ @{
+ */
+
+#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
+/* ARM armcc specific functions */
+
+#if (__ARMCC_VERSION < 400677)
+ #error "Please use ARM Compiler Toolchain V4.0.677 or later!"
+#endif
+
+/* intrinsic void __enable_irq(); */
+/* intrinsic void __disable_irq(); */
+
+/** \brief Get Control Register
+
+ This function returns the content of the Control Register.
+
+ \return Control Register value
+ */
+__STATIC_INLINE uint32_t __get_CONTROL(void)
+{
+ register uint32_t __regControl __ASM("control");
+ return(__regControl);
+}
+
+
+/** \brief Set Control Register
+
+ This function writes the given value to the Control Register.
+
+ \param [in] control Control Register value to set
+ */
+__STATIC_INLINE void __set_CONTROL(uint32_t control)
+{
+ register uint32_t __regControl __ASM("control");
+ __regControl = control;
+}
+
+
+/** \brief Get IPSR Register
+
+ This function returns the content of the IPSR Register.
+
+ \return IPSR Register value
+ */
+__STATIC_INLINE uint32_t __get_IPSR(void)
+{
+ register uint32_t __regIPSR __ASM("ipsr");
+ return(__regIPSR);
+}
+
+
+/** \brief Get APSR Register
+
+ This function returns the content of the APSR Register.
+
+ \return APSR Register value
+ */
+__STATIC_INLINE uint32_t __get_APSR(void)
+{
+ register uint32_t __regAPSR __ASM("apsr");
+ return(__regAPSR);
+}
+
+
+/** \brief Get xPSR Register
+
+ This function returns the content of the xPSR Register.
+
+ \return xPSR Register value
+ */
+__STATIC_INLINE uint32_t __get_xPSR(void)
+{
+ register uint32_t __regXPSR __ASM("xpsr");
+ return(__regXPSR);
+}
+
+
+/** \brief Get Process Stack Pointer
+
+ This function returns the current value of the Process Stack Pointer (PSP).
+
+ \return PSP Register value
+ */
+__STATIC_INLINE uint32_t __get_PSP(void)
+{
+ register uint32_t __regProcessStackPointer __ASM("psp");
+ return(__regProcessStackPointer);
+}
+
+
+/** \brief Set Process Stack Pointer
+
+ This function assigns the given value to the Process Stack Pointer (PSP).
+
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
+{
+ register uint32_t __regProcessStackPointer __ASM("psp");
+ __regProcessStackPointer = topOfProcStack;
+}
+
+
+/** \brief Get Main Stack Pointer
+
+ This function returns the current value of the Main Stack Pointer (MSP).
+
+ \return MSP Register value
+ */
+__STATIC_INLINE uint32_t __get_MSP(void)
+{
+ register uint32_t __regMainStackPointer __ASM("msp");
+ return(__regMainStackPointer);
+}
+
+
+/** \brief Set Main Stack Pointer
+
+ This function assigns the given value to the Main Stack Pointer (MSP).
+
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
+{
+ register uint32_t __regMainStackPointer __ASM("msp");
+ __regMainStackPointer = topOfMainStack;
+}
+
+
+/** \brief Get Priority Mask
+
+ This function returns the current state of the priority mask bit from the Priority Mask Register.
+
+ \return Priority Mask value
+ */
+__STATIC_INLINE uint32_t __get_PRIMASK(void)
+{
+ register uint32_t __regPriMask __ASM("primask");
+ return(__regPriMask);
+}
+
+
+/** \brief Set Priority Mask
+
+ This function assigns the given value to the Priority Mask Register.
+
+ \param [in] priMask Priority Mask
+ */
+__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
+{
+ register uint32_t __regPriMask __ASM("primask");
+ __regPriMask = (priMask);
+}
+
+
+#if (__CORTEX_M >= 0x03)
+
+/** \brief Enable FIQ
+
+ This function enables FIQ interrupts by clearing the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+#define __enable_fault_irq __enable_fiq
+
+
+/** \brief Disable FIQ
+
+ This function disables FIQ interrupts by setting the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+#define __disable_fault_irq __disable_fiq
+
+
+/** \brief Get Base Priority
+
+ This function returns the current value of the Base Priority register.
+
+ \return Base Priority register value
+ */
+__STATIC_INLINE uint32_t __get_BASEPRI(void)
+{
+ register uint32_t __regBasePri __ASM("basepri");
+ return(__regBasePri);
+}
+
+
+/** \brief Set Base Priority
+
+ This function assigns the given value to the Base Priority register.
+
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
+{
+ register uint32_t __regBasePri __ASM("basepri");
+ __regBasePri = (basePri & 0xff);
+}
+
+
+/** \brief Get Fault Mask
+
+ This function returns the current value of the Fault Mask register.
+
+ \return Fault Mask register value
+ */
+__STATIC_INLINE uint32_t __get_FAULTMASK(void)
+{
+ register uint32_t __regFaultMask __ASM("faultmask");
+ return(__regFaultMask);
+}
+
+
+/** \brief Set Fault Mask
+
+ This function assigns the given value to the Fault Mask register.
+
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
+{
+ register uint32_t __regFaultMask __ASM("faultmask");
+ __regFaultMask = (faultMask & (uint32_t)1);
+}
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+
+#if (__CORTEX_M == 0x04)
+
+/** \brief Get FPSCR
+
+ This function returns the current value of the Floating Point Status/Control register.
+
+ \return Floating Point Status/Control register value
+ */
+__STATIC_INLINE uint32_t __get_FPSCR(void)
+{
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+ register uint32_t __regfpscr __ASM("fpscr");
+ return(__regfpscr);
+#else
+ return(0);
+#endif
+}
+
+
+/** \brief Set FPSCR
+
+ This function assigns the given value to the Floating Point Status/Control register.
+
+ \param [in] fpscr Floating Point Status/Control value to set
+ */
+__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
+{
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+ register uint32_t __regfpscr __ASM("fpscr");
+ __regfpscr = (fpscr);
+#endif
+}
+
+#endif /* (__CORTEX_M == 0x04) */
+
+
+#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
+/* IAR iccarm specific functions */
+
+#include
+
+
+#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
+/* TI CCS specific functions */
+
+#include
+
+
+#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
+/* GNU gcc specific functions */
+
+/** \brief Enable IRQ Interrupts
+
+ This function enables IRQ interrupts by clearing the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
+{
+ __ASM volatile ("cpsie i" : : : "memory");
+}
+
+
+/** \brief Disable IRQ Interrupts
+
+ This function disables IRQ interrupts by setting the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
+{
+ __ASM volatile ("cpsid i" : : : "memory");
+}
+
+
+/** \brief Get Control Register
+
+ This function returns the content of the Control Register.
+
+ \return Control Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, control" : "=r" (result) );
+ return(result);
+}
+
+
+/** \brief Set Control Register
+
+ This function writes the given value to the Control Register.
+
+ \param [in] control Control Register value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
+{
+ __ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
+}
+
+
+/** \brief Get IPSR Register
+
+ This function returns the content of the IPSR Register.
+
+ \return IPSR Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, ipsr" : "=r" (result) );
+ return(result);
+}
+
+
+/** \brief Get APSR Register
+
+ This function returns the content of the APSR Register.
+
+ \return APSR Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, apsr" : "=r" (result) );
+ return(result);
+}
+
+
+/** \brief Get xPSR Register
+
+ This function returns the content of the xPSR Register.
+
+ \return xPSR Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, xpsr" : "=r" (result) );
+ return(result);
+}
+
+
+/** \brief Get Process Stack Pointer
+
+ This function returns the current value of the Process Stack Pointer (PSP).
+
+ \return PSP Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
+{
+ register uint32_t result;
+
+ __ASM volatile ("MRS %0, psp\n" : "=r" (result) );
+ return(result);
+}
+
+
+/** \brief Set Process Stack Pointer
+
+ This function assigns the given value to the Process Stack Pointer (PSP).
+
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
+{
+ __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp");
+}
+
+
+/** \brief Get Main Stack Pointer
+
+ This function returns the current value of the Main Stack Pointer (MSP).
+
+ \return MSP Register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
+{
+ register uint32_t result;
+
+ __ASM volatile ("MRS %0, msp\n" : "=r" (result) );
+ return(result);
+}
+
+
+/** \brief Set Main Stack Pointer
+
+ This function assigns the given value to the Main Stack Pointer (MSP).
+
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
+{
+ __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp");
+}
+
+
+/** \brief Get Priority Mask
+
+ This function returns the current state of the priority mask bit from the Priority Mask Register.
+
+ \return Priority Mask value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, primask" : "=r" (result) );
+ return(result);
+}
+
+
+/** \brief Set Priority Mask
+
+ This function assigns the given value to the Priority Mask Register.
+
+ \param [in] priMask Priority Mask
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
+{
+ __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
+}
+
+
+#if (__CORTEX_M >= 0x03)
+
+/** \brief Enable FIQ
+
+ This function enables FIQ interrupts by clearing the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
+{
+ __ASM volatile ("cpsie f" : : : "memory");
+}
+
+
+/** \brief Disable FIQ
+
+ This function disables FIQ interrupts by setting the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
+{
+ __ASM volatile ("cpsid f" : : : "memory");
+}
+
+
+/** \brief Get Base Priority
+
+ This function returns the current value of the Base Priority register.
+
+ \return Base Priority register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
+ return(result);
+}
+
+
+/** \brief Set Base Priority
+
+ This function assigns the given value to the Base Priority register.
+
+ \param [in] basePri Base Priority value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
+{
+ __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory");
+}
+
+
+/** \brief Get Fault Mask
+
+ This function returns the current value of the Fault Mask register.
+
+ \return Fault Mask register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, faultmask" : "=r" (result) );
+ return(result);
+}
+
+
+/** \brief Set Fault Mask
+
+ This function assigns the given value to the Fault Mask register.
+
+ \param [in] faultMask Fault Mask value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
+{
+ __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
+}
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+
+#if (__CORTEX_M == 0x04)
+
+/** \brief Get FPSCR
+
+ This function returns the current value of the Floating Point Status/Control register.
+
+ \return Floating Point Status/Control register value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
+{
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+ uint32_t result;
+
+ /* Empty asm statement works as a scheduling barrier */
+ __ASM volatile ("");
+ __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
+ __ASM volatile ("");
+ return(result);
+#else
+ return(0);
+#endif
+}
+
+
+/** \brief Set FPSCR
+
+ This function assigns the given value to the Floating Point Status/Control register.
+
+ \param [in] fpscr Floating Point Status/Control value to set
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
+{
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+ /* Empty asm statement works as a scheduling barrier */
+ __ASM volatile ("");
+ __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc");
+ __ASM volatile ("");
+#endif
+}
+
+#endif /* (__CORTEX_M == 0x04) */
+
+
+#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
+/* TASKING carm specific functions */
+
+/*
+ * The CMSIS functions have been implemented as intrinsics in the compiler.
+ * Please use "carm -?i" to get an up to date list of all instrinsics,
+ * Including the CMSIS ones.
+ */
+
+#endif
+
+/*@} end of CMSIS_Core_RegAccFunctions */
+
+
+#endif /* __CORE_CMFUNC_H */
diff --git a/source/lpc_chip_11u6x/inc/core_cmInstr.h b/source/lpc_chip_11u6x/inc/core_cmInstr.h
new file mode 100644
index 0000000..d213f0e
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/core_cmInstr.h
@@ -0,0 +1,688 @@
+/**************************************************************************//**
+ * @file core_cmInstr.h
+ * @brief CMSIS Cortex-M Core Instruction Access Header File
+ * @version V3.20
+ * @date 05. March 2013
+ *
+ * @note
+ *
+ ******************************************************************************/
+/* Copyright (c) 2009 - 2013 ARM LIMITED
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ - Neither the name of ARM nor the names of its contributors may be used
+ to endorse or promote products derived from this software without
+ specific prior written permission.
+ *
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ ---------------------------------------------------------------------------*/
+
+
+#ifndef __CORE_CMINSTR_H
+#define __CORE_CMINSTR_H
+
+
+/* ########################## Core Instruction Access ######################### */
+/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
+ Access to dedicated instructions
+ @{
+*/
+
+#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
+/* ARM armcc specific functions */
+
+#if (__ARMCC_VERSION < 400677)
+ #error "Please use ARM Compiler Toolchain V4.0.677 or later!"
+#endif
+
+
+/** \brief No Operation
+
+ No Operation does nothing. This instruction can be used for code alignment purposes.
+ */
+#define __NOP __nop
+
+
+/** \brief Wait For Interrupt
+
+ Wait For Interrupt is a hint instruction that suspends execution
+ until one of a number of events occurs.
+ */
+#define __WFI __wfi
+
+
+/** \brief Wait For Event
+
+ Wait For Event is a hint instruction that permits the processor to enter
+ a low-power state until one of a number of events occurs.
+ */
+#define __WFE __wfe
+
+
+/** \brief Send Event
+
+ Send Event is a hint instruction. It causes an event to be signaled to the CPU.
+ */
+#define __SEV __sev
+
+
+/** \brief Instruction Synchronization Barrier
+
+ Instruction Synchronization Barrier flushes the pipeline in the processor,
+ so that all instructions following the ISB are fetched from cache or
+ memory, after the instruction has been completed.
+ */
+#define __ISB() __isb(0xF)
+
+
+/** \brief Data Synchronization Barrier
+
+ This function acts as a special kind of Data Memory Barrier.
+ It completes when all explicit memory accesses before this instruction complete.
+ */
+#define __DSB() __dsb(0xF)
+
+
+/** \brief Data Memory Barrier
+
+ This function ensures the apparent order of the explicit memory operations before
+ and after the instruction, without ensuring their completion.
+ */
+#define __DMB() __dmb(0xF)
+
+
+/** \brief Reverse byte order (32 bit)
+
+ This function reverses the byte order in integer value.
+
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV __rev
+
+
+/** \brief Reverse byte order (16 bit)
+
+ This function reverses the byte order in two unsigned short values.
+
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#ifndef __NO_EMBEDDED_ASM
+__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
+{
+ rev16 r0, r0
+ bx lr
+}
+#endif
+
+/** \brief Reverse byte order in signed short value
+
+ This function reverses the byte order in a signed short value with sign extension to integer.
+
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#ifndef __NO_EMBEDDED_ASM
+__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
+{
+ revsh r0, r0
+ bx lr
+}
+#endif
+
+
+/** \brief Rotate Right in unsigned value (32 bit)
+
+ This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+
+ \param [in] value Value to rotate
+ \param [in] value Number of Bits to rotate
+ \return Rotated value
+ */
+#define __ROR __ror
+
+
+/** \brief Breakpoint
+
+ This function causes the processor to enter Debug state.
+ Debug tools can use this to investigate system state when the instruction at a particular address is reached.
+
+ \param [in] value is ignored by the processor.
+ If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value) __breakpoint(value)
+
+
+#if (__CORTEX_M >= 0x03)
+
+/** \brief Reverse bit order of value
+
+ This function reverses the bit order of the given value.
+
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __RBIT __rbit
+
+
+/** \brief LDR Exclusive (8 bit)
+
+ This function performs a exclusive LDR command for 8 bit value.
+
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
+
+
+/** \brief LDR Exclusive (16 bit)
+
+ This function performs a exclusive LDR command for 16 bit values.
+
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
+
+
+/** \brief LDR Exclusive (32 bit)
+
+ This function performs a exclusive LDR command for 32 bit values.
+
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
+
+
+/** \brief STR Exclusive (8 bit)
+
+ This function performs a exclusive STR command for 8 bit values.
+
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXB(value, ptr) __strex(value, ptr)
+
+
+/** \brief STR Exclusive (16 bit)
+
+ This function performs a exclusive STR command for 16 bit values.
+
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXH(value, ptr) __strex(value, ptr)
+
+
+/** \brief STR Exclusive (32 bit)
+
+ This function performs a exclusive STR command for 32 bit values.
+
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXW(value, ptr) __strex(value, ptr)
+
+
+/** \brief Remove the exclusive lock
+
+ This function removes the exclusive lock which is created by LDREX.
+
+ */
+#define __CLREX __clrex
+
+
+/** \brief Signed Saturate
+
+ This function saturates a signed value.
+
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+#define __SSAT __ssat
+
+
+/** \brief Unsigned Saturate
+
+ This function saturates an unsigned value.
+
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+#define __USAT __usat
+
+
+/** \brief Count leading zeros
+
+ This function counts the number of leading zeros of a data value.
+
+ \param [in] value Value to count the leading zeros
+ \return number of leading zeros in value
+ */
+#define __CLZ __clz
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+
+
+#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
+/* IAR iccarm specific functions */
+
+#include
+
+
+#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/
+/* TI CCS specific functions */
+
+#include
+
+
+#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
+/* GNU gcc specific functions */
+
+/* Define macros for porting to both thumb1 and thumb2.
+ * For thumb1, use low register (r0-r7), specified by constrant "l"
+ * Otherwise, use general registers, specified by constrant "r" */
+#if defined (__thumb__) && !defined (__thumb2__)
+#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
+#define __CMSIS_GCC_USE_REG(r) "l" (r)
+#else
+#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
+#define __CMSIS_GCC_USE_REG(r) "r" (r)
+#endif
+
+/** \brief No Operation
+
+ No Operation does nothing. This instruction can be used for code alignment purposes.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void)
+{
+ __ASM volatile ("nop");
+}
+
+
+/** \brief Wait For Interrupt
+
+ Wait For Interrupt is a hint instruction that suspends execution
+ until one of a number of events occurs.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void)
+{
+ __ASM volatile ("wfi");
+}
+
+
+/** \brief Wait For Event
+
+ Wait For Event is a hint instruction that permits the processor to enter
+ a low-power state until one of a number of events occurs.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void)
+{
+ __ASM volatile ("wfe");
+}
+
+
+/** \brief Send Event
+
+ Send Event is a hint instruction. It causes an event to be signaled to the CPU.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void)
+{
+ __ASM volatile ("sev");
+}
+
+
+/** \brief Instruction Synchronization Barrier
+
+ Instruction Synchronization Barrier flushes the pipeline in the processor,
+ so that all instructions following the ISB are fetched from cache or
+ memory, after the instruction has been completed.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void)
+{
+ __ASM volatile ("isb");
+}
+
+
+/** \brief Data Synchronization Barrier
+
+ This function acts as a special kind of Data Memory Barrier.
+ It completes when all explicit memory accesses before this instruction complete.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void)
+{
+ __ASM volatile ("dsb");
+}
+
+
+/** \brief Data Memory Barrier
+
+ This function ensures the apparent order of the explicit memory operations before
+ and after the instruction, without ensuring their completion.
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void)
+{
+ __ASM volatile ("dmb");
+}
+
+
+/** \brief Reverse byte order (32 bit)
+
+ This function reverses the byte order in integer value.
+
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value)
+{
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+ return __builtin_bswap32(value);
+#else
+ uint32_t result;
+
+ __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return(result);
+#endif
+}
+
+
+/** \brief Reverse byte order (16 bit)
+
+ This function reverses the byte order in two unsigned short values.
+
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value)
+{
+ uint32_t result;
+
+ __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return(result);
+}
+
+
+/** \brief Reverse byte order in signed short value
+
+ This function reverses the byte order in a signed short value with sign extension to integer.
+
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value)
+{
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ return (short)__builtin_bswap16(value);
+#else
+ uint32_t result;
+
+ __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return(result);
+#endif
+}
+
+
+/** \brief Rotate Right in unsigned value (32 bit)
+
+ This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+
+ \param [in] value Value to rotate
+ \param [in] value Number of Bits to rotate
+ \return Rotated value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
+{
+ return (op1 >> op2) | (op1 << (32 - op2));
+}
+
+
+/** \brief Breakpoint
+
+ This function causes the processor to enter Debug state.
+ Debug tools can use this to investigate system state when the instruction at a particular address is reached.
+
+ \param [in] value is ignored by the processor.
+ If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value) __ASM volatile ("bkpt "#value)
+
+
+#if (__CORTEX_M >= 0x03)
+
+/** \brief Reverse bit order of value
+
+ This function reverses the bit order of the given value.
+
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
+{
+ uint32_t result;
+
+ __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
+ return(result);
+}
+
+
+/** \brief LDR Exclusive (8 bit)
+
+ This function performs a exclusive LDR command for 8 bit value.
+
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
+{
+ uint32_t result;
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
+#else
+ /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
+ accepted by assembler. So has to use following less efficient pattern.
+ */
+ __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
+#endif
+ return(result);
+}
+
+
+/** \brief LDR Exclusive (16 bit)
+
+ This function performs a exclusive LDR command for 16 bit values.
+
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
+{
+ uint32_t result;
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
+#else
+ /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
+ accepted by assembler. So has to use following less efficient pattern.
+ */
+ __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
+#endif
+ return(result);
+}
+
+
+/** \brief LDR Exclusive (32 bit)
+
+ This function performs a exclusive LDR command for 32 bit values.
+
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
+ return(result);
+}
+
+
+/** \brief STR Exclusive (8 bit)
+
+ This function performs a exclusive STR command for 8 bit values.
+
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
+ return(result);
+}
+
+
+/** \brief STR Exclusive (16 bit)
+
+ This function performs a exclusive STR command for 16 bit values.
+
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
+ return(result);
+}
+
+
+/** \brief STR Exclusive (32 bit)
+
+ This function performs a exclusive STR command for 32 bit values.
+
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
+ return(result);
+}
+
+
+/** \brief Remove the exclusive lock
+
+ This function removes the exclusive lock which is created by LDREX.
+
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void)
+{
+ __ASM volatile ("clrex" ::: "memory");
+}
+
+
+/** \brief Signed Saturate
+
+ This function saturates a signed value.
+
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+#define __SSAT(ARG1,ARG2) \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+
+/** \brief Unsigned Saturate
+
+ This function saturates an unsigned value.
+
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+#define __USAT(ARG1,ARG2) \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+
+/** \brief Count leading zeros
+
+ This function counts the number of leading zeros of a data value.
+
+ \param [in] value Value to count the leading zeros
+ \return number of leading zeros in value
+ */
+__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value)
+{
+ uint32_t result;
+
+ __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
+ return(result);
+}
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+
+
+
+#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
+/* TASKING carm specific functions */
+
+/*
+ * The CMSIS functions have been implemented as intrinsics in the compiler.
+ * Please use "carm -?i" to get an up to date list of all intrinsics,
+ * Including the CMSIS ones.
+ */
+
+#endif
+
+/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
+
+#endif /* __CORE_CMINSTR_H */
diff --git a/source/lpc_chip_11u6x/inc/crc_11u6x.h b/source/lpc_chip_11u6x/inc/crc_11u6x.h
new file mode 100644
index 0000000..45ed474
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/crc_11u6x.h
@@ -0,0 +1,262 @@
+/*
+ * @brief LPC11u6x Cyclic Redundancy Check (CRC) Engine driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licenser disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __CRC_11U6X_H_
+#define __CRC_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup CRC_11U6X CHIP: LPC11u6x Cyclic Redundancy Check Engine driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief CRC register block structure
+ */
+typedef struct { /*!< CRC Structure */
+ __IO uint32_t MODE; /*!< CRC Mode Register */
+ __IO uint32_t SEED; /*!< CRC SEED Register */
+ union {
+ __I uint32_t SUM; /*!< CRC Checksum Register. */
+ __O uint32_t WRDATA32; /*!< CRC Data Register: write size 32-bit*/
+ __O uint16_t WRDATA16; /*!< CRC Data Register: write size 16-bit*/
+ __O uint8_t WRDATA8; /*!< CRC Data Register: write size 8-bit*/
+ };
+
+} LPC_CRC_T;
+
+/*
+ * @brief CRC MODE register description
+ */
+#define CRC_MODE_POLY_BITMASK ((0x03)) /** CRC polynomial Bit mask */
+#define CRC_MODE_POLY_CCITT (0x00) /** Select CRC-CCITT polynomial */
+#define CRC_MODE_POLY_CRC16 (0x01) /** Select CRC-16 polynomial */
+#define CRC_MODE_POLY_CRC32 (0x02) /** Select CRC-32 polynomial */
+#define CRC_MODE_WRDATA_BITMASK (0x03 << 2) /** CRC WR_Data Config Bit mask */
+#define CRC_MODE_WRDATA_BIT_RVS (1 << 2) /** Select Bit order reverse for WR_DATA (per byte) */
+#define CRC_MODE_WRDATA_CMPL (1 << 3) /** Select One's complement for WR_DATA */
+#define CRC_MODE_SUM_BITMASK (0x03 << 4) /** CRC Sum Config Bit mask */
+#define CRC_MODE_SUM_BIT_RVS (1 << 4) /** Select Bit order reverse for CRC_SUM */
+#define CRC_MODE_SUM_CMPL (1 << 5) /** Select One's complement for CRC_SUM */
+
+#define MODE_CFG_CCITT (0x00) /** Pre-defined mode word for default CCITT setup */
+#define MODE_CFG_CRC16 (0x15) /** Pre-defined mode word for default CRC16 setup */
+#define MODE_CFG_CRC32 (0x36) /** Pre-defined mode word for default CRC32 setup */
+
+#define CRC_SEED_CCITT (0x0000FFFF)/** Initial seed value for CCITT mode */
+#define CRC_SEED_CRC16 (0x00000000)/** Initial seed value for CRC16 mode */
+#define CRC_SEED_CRC32 (0xFFFFFFFF)/** Initial seed value for CRC32 mode */
+
+/**
+ * @brief CRC polynomial
+ */
+typedef enum IP_CRC_001_POLY {
+ CRC_POLY_CCITT = CRC_MODE_POLY_CCITT, /**< CRC-CCIT polynomial */
+ CRC_POLY_CRC16 = CRC_MODE_POLY_CRC16, /**< CRC-16 polynomial */
+ CRC_POLY_CRC32 = CRC_MODE_POLY_CRC32, /**< CRC-32 polynomial */
+ CRC_POLY_LAST,
+} CRC_POLY_T;
+
+/**
+ * @brief Initializes the CRC Engine
+ * @return Nothing
+ */
+void Chip_CRC_Init(void);
+
+/**
+ * @brief Deinitializes the CRC Engine
+ * @return Nothing
+ */
+void Chip_CRC_Deinit(void);
+
+/**
+ * @brief Set the polynomial used for the CRC calculation
+ * @param poly : The enumerated polynomial to be used
+ * @param flags : An Or'ed value of flags that setup the mode
+ * @return Nothing
+ * @note Flags for setting up the mode word include CRC_MODE_WRDATA_BIT_RVS,
+ * CRC_MODE_WRDATA_CMPL, CRC_MODE_SUM_BIT_RVS, and CRC_MODE_SUM_CMPL.
+ */
+STATIC INLINE void Chip_CRC_SetPoly(CRC_POLY_T poly, uint32_t flags)
+{
+ LPC_CRC->MODE = (uint32_t) poly | flags;
+}
+
+/**
+ * @brief Sets up the CRC engine for CRC16 mode
+ * @return Nothing
+ */
+STATIC INLINE void Chip_CRC_UseCRC16(void)
+{
+ LPC_CRC->MODE = MODE_CFG_CRC16;
+ LPC_CRC->SEED = CRC_SEED_CRC16;
+}
+
+/**
+ * @brief Sets up the CRC engine for CRC32 mode
+ * @return Nothing
+ */
+STATIC INLINE void Chip_CRC_UseCRC32(void)
+{
+ LPC_CRC->MODE = MODE_CFG_CRC32;
+ LPC_CRC->SEED = CRC_SEED_CRC32;
+}
+
+/**
+ * @brief Sets up the CRC engine for CCITT mode
+ * @return Nothing
+ */
+STATIC INLINE void Chip_CRC_UseCCITT(void)
+{
+ LPC_CRC->MODE = MODE_CFG_CCITT;
+ LPC_CRC->SEED = CRC_SEED_CCITT;
+}
+
+/**
+ * @brief Engage the CRC engine with defaults based on the polynomial to be used
+ * @param poly : The enumerated polynomial to be used
+ * @return Nothing
+ */
+void Chip_CRC_UseDefaultConfig(CRC_POLY_T poly);
+
+/**
+ * @brief Set the CRC Mode bits
+ * @param mode : Mode value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_CRC_SetMode(uint32_t mode)
+{
+ LPC_CRC->MODE = mode;
+}
+
+/**
+ * @brief Get the CRC Mode bits
+ * @return The current value of the CRC Mode bits
+ */
+STATIC INLINE uint32_t Chip_CRC_GetMode(void)
+{
+ return LPC_CRC->MODE;
+}
+
+/**
+ * @brief Set the seed bits used by the CRC_SUM register
+ * @param seed : Seed value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_CRC_SetSeed(uint32_t seed)
+{
+ LPC_CRC->SEED = seed;
+}
+
+/**
+ * @brief Get the CRC seed value
+ * @return Seed value
+ */
+STATIC INLINE uint32_t Chip_CRC_GetSeed(void)
+{
+ return LPC_CRC->SEED;
+}
+
+/**
+ * @brief Convenience function for writing 8-bit data to the CRC engine
+ * @param data : 8-bit data to write
+ * @return Nothing
+ */
+STATIC INLINE void Chip_CRC_Write8(uint8_t data)
+{
+ LPC_CRC->WRDATA8 = data;
+}
+
+/**
+ * @brief Convenience function for writing 16-bit data to the CRC engine
+ * @param data : 16-bit data to write
+ * @return Nothing
+ */
+STATIC INLINE void Chip_CRC_Write16(uint16_t data)
+{
+ LPC_CRC->WRDATA16 = data;
+}
+
+/**
+ * @brief Convenience function for writing 32-bit data to the CRC engine
+ * @param data : 32-bit data to write
+ * @return Nothing
+ */
+STATIC INLINE void Chip_CRC_Write32(uint32_t data)
+{
+ LPC_CRC->WRDATA32 = data;
+}
+
+/**
+ * @brief Gets the CRC Sum based on the Mode and Seed as previously configured
+ * @return CRC Checksum value
+ */
+STATIC INLINE uint32_t Chip_CRC_Sum(void)
+{
+ return LPC_CRC->SUM;
+}
+
+/**
+ * @brief Convenience function for computing a standard CCITT checksum from an 8-bit data block
+ * @param data : Pointer to the block of 8-bit data
+ * @param bytes : The number of bytes pointed to by data
+ * @return Check sum value
+ */
+uint32_t Chip_CRC_CRC8(const uint8_t *data, uint32_t bytes);
+
+/**
+ * @brief Convenience function for computing a standard CRC16 checksum from 16-bit data block
+ * @param data : Pointer to the block of 16-bit data
+ * @param hwords : The number of 16 byte entries pointed to by data
+ * @return Check sum value
+ */
+uint32_t Chip_CRC_CRC16(const uint16_t *data, uint32_t hwords);
+
+/**
+ * @brief Convenience function for computing a standard CRC32 checksum from 32-bit data block
+ * @param data : Pointer to the block of 32-bit data
+ * @param words : The number of 32-bit entries pointed to by data
+ * @return Check sum value
+ */
+uint32_t Chip_CRC_CRC32(const uint32_t *data, uint32_t words);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CRC_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/dma_11u6x.h b/source/lpc_chip_11u6x/inc/dma_11u6x.h
new file mode 100644
index 0000000..a25caff
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/dma_11u6x.h
@@ -0,0 +1,734 @@
+/*
+ * @brief LPC11u6x DMA chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __DMA_11U6X_H_
+#define __DMA_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup DMA_11U6X CHIP: LPC11u6x DMA Controller driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief DMA Controller shared registers structure
+ */
+typedef struct { /*!< DMA shared registers structure */
+ __IO uint32_t ENABLESET; /*!< DMA Channel Enable read and Set for all DMA channels */
+ __I uint32_t RESERVED0;
+ __O uint32_t ENABLECLR; /*!< DMA Channel Enable Clear for all DMA channels */
+ __I uint32_t RESERVED1;
+ __I uint32_t ACTIVE; /*!< DMA Channel Active status for all DMA channels */
+ __I uint32_t RESERVED2;
+ __I uint32_t BUSY; /*!< DMA Channel Busy status for all DMA channels */
+ __I uint32_t RESERVED3;
+ __IO uint32_t ERRINT; /*!< DMA Error Interrupt status for all DMA channels */
+ __I uint32_t RESERVED4;
+ __IO uint32_t INTENSET; /*!< DMA Interrupt Enable read and Set for all DMA channels */
+ __I uint32_t RESERVED5;
+ __O uint32_t INTENCLR; /*!< DMA Interrupt Enable Clear for all DMA channels */
+ __I uint32_t RESERVED6;
+ __IO uint32_t INTA; /*!< DMA Interrupt A status for all DMA channels */
+ __I uint32_t RESERVED7;
+ __IO uint32_t INTB; /*!< DMA Interrupt B status for all DMA channels */
+ __I uint32_t RESERVED8;
+ __O uint32_t SETVALID; /*!< DMA Set ValidPending control bits for all DMA channels */
+ __I uint32_t RESERVED9;
+ __O uint32_t SETTRIG; /*!< DMA Set Trigger control bits for all DMA channels */
+ __I uint32_t RESERVED10;
+ __O uint32_t ABORT; /*!< DMA Channel Abort control for all DMA channels */
+} LPC_DMA_COMMON_T;
+
+/**
+ * @brief DMA Controller shared registers structure
+ */
+typedef struct { /*!< DMA channel register structure */
+ __IO uint32_t CFG; /*!< DMA Configuration register */
+ __I uint32_t CTLSTAT; /*!< DMA Control and status register */
+ __IO uint32_t XFERCFG; /*!< DMA Transfer configuration register */
+ __I uint32_t RESERVED;
+} LPC_DMA_CHANNEL_T;
+
+/* DMA channel mapping - each channel is mapped to an individual peripheral
+ and direction or a DMA imput mux trigger */
+typedef enum {
+ SSP0_RX_DMA = 0, /*!< SSP0 receive DMA channel */
+ DMA_CH0 = SSP0_RX_DMA,
+ DMAREQ_SSP0_TX, /*!< SSP0 transmit DMA channel */
+ DMA_CH1 = DMAREQ_SSP0_TX,
+ DMAREQ_SSP1_RX, /*!< SSP1 receive DMA channel */
+ DMA_CH2 = DMAREQ_SSP1_RX,
+ DMAREQ_SSP1_TX, /*!< SSP1 transmit DMA channel */
+ DMA_CH3 = DMAREQ_SSP1_TX,
+ DMAREQ_USART0_RX, /*!< USART0 receive DMA channel */
+ DMA_CH4 = DMAREQ_USART0_RX,
+ DMAREQ_USART0_TX, /*!< USART0 transmit DMA channel */
+ DMA_CH5 = DMAREQ_USART0_TX,
+ DMAREQ_USART1_RX, /*!< USART1 transmit DMA channel */
+ DMA_CH6 = DMAREQ_USART1_RX,
+ DMAREQ_USART1_TX, /*!< USART1 transmit DMA channel */
+ DMA_CH7 = DMAREQ_USART1_TX,
+ DMAREQ_USART2_RX, /*!< USART2 transmit DMA channel */
+ DMA_CH8 = DMAREQ_USART2_RX,
+ DMAREQ_USART2_TX, /*!< USART2 transmit DMA channel */
+ DMA_CH9 = DMAREQ_USART2_TX,
+ DMAREQ_USART3_RX, /*!< USART3 transmit DMA channel */
+ DMA_CH10 = DMAREQ_USART3_RX,
+ DMAREQ_USART3_TX, /*!< USART3 transmit DMA channel */
+ DMA_CH11 = DMAREQ_USART3_TX,
+ DMAREQ_USART4_RX, /*!< USART4 transmit DMA channel */
+ DMA_CH12 = DMAREQ_USART4_RX,
+ DMAREQ_USART4_TX, /*!< USART4 transmit DMA channel */
+ DMA_CH13 = DMAREQ_USART4_TX,
+ DMAREQ_RESERVED_14,
+ DMA_CH14 = DMAREQ_RESERVED_14,
+ DMAREQ_RESERVED_15,
+ DMA_CH15 = DMAREQ_RESERVED_15
+} DMA_CHID_T;
+
+/* On LPC412x, Max DMA channel is 22 */
+#define MAX_DMA_CHANNEL (DMA_CH15 + 1)
+
+/**
+ * @brief DMA Controller register block structure
+ */
+typedef struct { /*!< DMA Structure */
+ __IO uint32_t CTRL; /*!< DMA control register */
+ __I uint32_t INTSTAT; /*!< DMA Interrupt status register */
+ __IO uint32_t SRAMBASE; /*!< DMA SRAM address of the channel configuration table */
+ __I uint32_t RESERVED2[5];
+ LPC_DMA_COMMON_T DMACOMMON[1]; /*!< DMA shared channel (common) registers */
+ __I uint32_t RESERVED0[225];
+ LPC_DMA_CHANNEL_T DMACH[MAX_DMA_CHANNEL]; /*!< DMA channel registers */
+} LPC_DMA_T;
+
+/** @defgroup DMA_COMMONDRV_11U6X CHIP: LPC11u6x DMA Controller driver common functions
+ * @{
+ */
+
+/**
+ * @brief Initialize DMA controller
+ * @param pDMA : The base of DMA controller on the chip
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_Init(LPC_DMA_T *pDMA)
+{
+ (void) pDMA;
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_DMA);
+}
+
+/**
+ * @brief De-Initialize DMA controller
+ * @param pDMA : The base of DMA controller on the chip
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_DeInit(LPC_DMA_T *pDMA)
+{
+ (void) pDMA;
+ Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_DMA);
+}
+
+/**
+ * @brief Enable DMA controller
+ * @param pDMA : The base of DMA controller on the chip
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_Enable(LPC_DMA_T *pDMA)
+{
+ pDMA->CTRL = 1;
+}
+
+/**
+ * @brief Disable DMA controller
+ * @param pDMA : The base of DMA controller on the chip
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_Disable(LPC_DMA_T *pDMA)
+{
+ pDMA->CTRL = 0;
+}
+
+/* DMA interrupt status bits (common) */
+#define DMA_INTSTAT_ACTIVEINT 0x2 /*!< Summarizes whether any enabled interrupts are pending */
+#define DMA_INTSTAT_ACTIVEERRINT 0x4 /*!< Summarizes whether any error interrupts are pending */
+
+/**
+ * @brief Get pending interrupt or error interrupts
+ * @param pDMA : The base of DMA controller on the chip
+ * @return An Or'ed value of DMA_INTSTAT_* types
+ * @note If any DMA channels have an active interrupt or error interrupt
+ * pending, this functional will a common status that applies to all
+ * channels.
+ */
+STATIC INLINE uint32_t Chip_DMA_GetIntStatus(LPC_DMA_T *pDMA)
+{
+ return pDMA->INTSTAT;
+}
+
+/* DMA channel source/address/next descriptor */
+typedef struct {
+ uint32_t xfercfg; /*!< Transfer configuration (only used in linked lists and ping-pong configs) */
+ uint32_t source; /*!< DMA transfer source end address */
+ uint32_t dest; /*!< DMA transfer desintation end address */
+ uint32_t next; /*!< Link to next DMA descriptor, must be 16 byte aligned */
+} DMA_CHDESC_T;
+
+/* DMA SRAM table - this can be optionally used with the Chip_DMA_SetSRAMBase()
+ function if a DMA SRAM table is needed. */
+extern DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL];
+
+/**
+ * @brief Set DMA controller SRAM base address
+ * @param pDMA : The base of DMA controller on the chip
+ * @param base : The base address where the DMA descriptors will be stored
+ * @return Nothing
+ * @note A 256 byte block of memory aligned on a 256 byte boundary must be
+ * provided for this function. It sets the base address used for
+ * DMA descriptor table (16 descriptors total that use 16 bytes each).
+ *
+ * A pre-defined table with correct alignment can be used for this
+ * function by calling Chip_DMA_SetSRAMBase(LPC_DMA, DMA_ADDR(Chip_DMA_Table));
+ */
+STATIC INLINE void Chip_DMA_SetSRAMBase(LPC_DMA_T *pDMA, uint32_t base)
+{
+ pDMA->SRAMBASE = base;
+}
+
+/**
+ * @brief Returns DMA controller SRAM base address
+ * @param pDMA : The base of DMA controller on the chip
+ * @return The base address where the DMA descriptors are stored
+ */
+STATIC INLINE uint32_t Chip_DMA_GetSRAMBase(LPC_DMA_T *pDMA)
+{
+ return pDMA->SRAMBASE;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DMA_COMMON_11U6X CHIP: LPC11u6x DMA Controller driver common channel functions
+ * @{
+ */
+
+/**
+ * @brief Enables a single DMA channel
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_EnableChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ pDMA->DMACOMMON[0].ENABLESET = (1 << ch);
+}
+
+/**
+ * @brief Disables a single DMA channel
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_DisableChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ pDMA->DMACOMMON[0].ENABLECLR = (1 << ch);
+}
+
+/**
+ * @brief Returns all enabled DMA channels
+ * @param pDMA : The base of DMA controller on the chip
+ * @return An Or'ed value of all enabled DMA channels (0 - 15)
+ * @note A high values in bits 0 .. 15 in the return values indicates
+ * that the channel for that bit (bit 0 = channel 0, bit 1 -
+ * channel 1, etc.) is enabled. A low state is disabled.
+ */
+STATIC INLINE uint32_t Chip_DMA_GetEnabledChannels(LPC_DMA_T *pDMA)
+{
+ return pDMA->DMACOMMON[0].ENABLESET;
+}
+
+/**
+ * @brief Returns all active DMA channels
+ * @param pDMA : The base of DMA controller on the chip
+ * @return An Or'ed value of all active DMA channels (0 - 15)
+ * @note A high values in bits 0 .. 15 in the return values indicates
+ * that the channel for that bit (bit 0 = channel 0, bit 1 -
+ * channel 1, etc.) is active. A low state is inactive. A active
+ * channel indicates that a DMA operation has been started but
+ * not yet fully completed.
+ */
+STATIC INLINE uint32_t Chip_DMA_GetActiveChannels(LPC_DMA_T *pDMA)
+{
+ return pDMA->DMACOMMON[0].ACTIVE;
+}
+
+/**
+ * @brief Returns all busy DMA channels
+ * @param pDMA : The base of DMA controller on the chip
+ * @return An Or'ed value of all busy DMA channels (0 - 15)
+ * @note A high values in bits 0 .. 15 in the return values indicates
+ * that the channel for that bit (bit 0 = channel 0, bit 1 -
+ * channel 1, etc.) is busy. A low state is not busy. A DMA
+ * channel is considered busy when there is any operation
+ * related to that channel in the DMA controller�s internal
+ * pipeline.
+ */
+STATIC INLINE uint32_t Chip_DMA_GetBusyChannels(LPC_DMA_T *pDMA)
+{
+ return pDMA->DMACOMMON[0].BUSY;
+}
+
+/**
+ * @brief Returns pending error interrupt status for all DMA channels
+ * @param pDMA : The base of DMA controller on the chip
+ * @return An Or'ed value of all channels (0 - 15) error interrupt status
+ * @note A high values in bits 0 .. 15 in the return values indicates
+ * that the channel for that bit (bit 0 = channel 0, bit 1 -
+ * channel 1, etc.) has a pending error interrupt. A low state
+ * indicates no error interrupt.
+ */
+STATIC INLINE uint32_t Chip_DMA_GetErrorIntChannels(LPC_DMA_T *pDMA)
+{
+ return pDMA->DMACOMMON[0].ERRINT;
+}
+
+/**
+ * @brief Clears a pending error interrupt status for a single DMA channel
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_ClearErrorIntChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ pDMA->DMACOMMON[0].ERRINT = (1 << ch);
+}
+
+/**
+ * @brief Enables a single DMA channel's interrupt used in common DMA interrupt
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_EnableIntChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ pDMA->DMACOMMON[0].INTENSET = (1 << ch);
+}
+
+/**
+ * @brief Disables a single DMA channel's interrupt used in common DMA interrupt
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_DisableIntChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ pDMA->DMACOMMON[0].INTENCLR = (1 << ch);
+}
+
+/**
+ * @brief Returns all enabled interrupt channels
+ * @param pDMA : The base of DMA controller on the chip
+ * @return Nothing
+ * @note A high values in bits 0 .. 15 in the return values indicates
+ * that the channel for that bit (bit 0 = channel 0, bit 1 -
+ * channel 1, etc.) has an enabled interrupt for the channel.
+ * A low state indicates that the DMA channel will not contribute
+ * to the common DMA interrupt status.
+ */
+STATIC INLINE uint32_t Chip_DMA_GetEnableIntChannels(LPC_DMA_T *pDMA)
+{
+ return pDMA->DMACOMMON[0].INTENSET;
+}
+
+/**
+ * @brief Returns active A interrupt status for all channels
+ * @param pDMA : The base of DMA controller on the chip
+ * @return Nothing
+ * @note A high values in bits 0 .. 15 in the return values indicates
+ * that the channel for that bit (bit 0 = channel 0, bit 1 -
+ * channel 1, etc.) has an active A interrupt for the channel.
+ * A low state indicates that the A interrupt is not active.
+ */
+STATIC INLINE uint32_t Chip_DMA_GetActiveIntAChannels(LPC_DMA_T *pDMA)
+{
+ return pDMA->DMACOMMON[0].INTA;
+}
+
+/**
+ * @brief Clears active A interrupt status for a single channel
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_ClearActiveIntAChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ pDMA->DMACOMMON[0].INTA = (1 << ch);
+}
+
+/**
+ * @brief Returns active B interrupt status for all channels
+ * @param pDMA : The base of DMA controller on the chip
+ * @return Nothing
+ * @note A high values in bits 0 .. 15 in the return values indicates
+ * that the channel for that bit (bit 0 = channel 0, bit 1 -
+ * channel 1, etc.) has an active B interrupt for the channel.
+ * A low state indicates that the B interrupt is not active.
+ */
+STATIC INLINE uint32_t Chip_DMA_GetActiveIntBChannels(LPC_DMA_T *pDMA)
+{
+ return pDMA->DMACOMMON[0].INTB;
+}
+
+/**
+ * @brief Clears active B interrupt status for a single channel
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_ClearActiveIntBChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ pDMA->DMACOMMON[0].INTB = (1 << ch);
+}
+
+/**
+ * @brief Sets the VALIDPENDING control bit for a single channel
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ * @note See the User Manual for more information for what this bit does.
+ *
+ */
+STATIC INLINE void Chip_DMA_SetValidChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ pDMA->DMACOMMON[0].SETVALID = (1 << ch);
+}
+
+/**
+ * @brief Sets the TRIG bit for a single channel
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ * @note See the User Manual for more information for what this bit does.
+ */
+STATIC INLINE void Chip_DMA_SetTrigChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ pDMA->DMACOMMON[0].SETTRIG = (1 << ch);
+}
+
+/**
+ * @brief Aborts a DMA operation for a single channel
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ * @note To abort a channel, the channel should first be disabled. Then wait
+ * until the channel is no longer busy by checking the corresponding
+ * bit in BUSY. Finally, abort the channel operation. This prevents the
+ * channel from restarting an incomplete operation when it is enabled
+ * again.
+ */
+STATIC INLINE void Chip_DMA_AbortChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ pDMA->DMACOMMON[0].ABORT = (1 << ch);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DMATRIGMUX_11U6X CHIP: LPC11u6x DMA trigger selection driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief DMA trigger pin muxing structure
+ */
+typedef struct { /*!< DMA trigger pin muxing register structure */
+ __IO uint32_t DMA_ITRIG_INMUX[MAX_DMA_CHANNEL]; /*!< Trigger input select register for DMA channels */
+} LPC_DMATRIGMUX_T;
+
+/* DMA triggers that can mapped to DMA channels */
+typedef enum {
+ DMATRIG_ADC0_SEQA_IRQ = 0, /*!< ADC0 sequencer A interrupt as trigger */
+ DMATRIG_ADC0_SEQB_IRQ, /*!< ADC0 sequencer B interrupt as trigger */
+ DMATRIG_CT16B0_MAT0, /*!< 16-bit counter/timer 0 interrupt as trigger */
+ DMATRIG_CT16B1_MAT0, /*!< 16-bit counter/timer 1 interrupt as trigger */
+ DMATRIG_CT32B0_MAT0, /*!< 32-bit counter/timer 0 interrupt as trigger */
+ DMATRIG_CT32B1_MAT0, /*!< 32-bit counter/timer 1 interrupt as trigger */
+ DMATRIG_PINT0, /*!< Pin interrupt 0 as trigger */
+ DMATRIG_PINT1, /*!< Pin interrupt 1 as trigger */
+ DMATRIG_SCT0_DMA0, /*!< SCT 0, DMA 0 as trigger */
+ DMATRIG_SCT0_DMA1, /*!< SCT 1, DMA 1 as trigger */
+ DMATRIG_SCT1_DMA0, /*!< SCT 0, DMA 0 as trigger */
+ DMATRIG_SCT1_DMA1 /*!< SCT 1, DMA 1 as trigger */
+} DMA_TRIGSRC_T;
+
+/**
+ * @brief Select a trigger source for a DMA channel
+ * @param pDMATRIG : The base of DMA trigger setup block on the chip
+ * @param ch : DMA channel ID
+ * @param trig : Trigger source for the DMA channel
+ * @return Nothing
+ * @note A DMA trigger source only needs to be setup when the DMA is setup
+ * for hardware trigger mode (when Chip_DMA_SetupChannelConfig() is
+ * called with DMA_CFG_HWTRIGEN as OR'ed option).
+ */
+STATIC INLINE void Chip_DMA_SetHWTrigger(LPC_DMATRIGMUX_T *pDMATRIG, DMA_CHID_T ch, DMA_TRIGSRC_T trig)
+{
+ pDMATRIG->DMA_ITRIG_INMUX[ch] = (uint32_t) trig;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup DMA_CHANNEL_11U6X CHIP: LPC11u6x DMA Controller driver channel specific functions
+ * @{
+ */
+
+/* Support macro for DMA_CHDESC_T */
+#define DMA_ADDR(addr) ((uint32_t) (addr))
+
+/* Support definitions for setting the configuration of a DMA channel. You
+ will need to get more information on these options from the User manual. */
+#define DMA_CFG_PERIPHREQEN (1 << 0) /*!< Enables Peripheral DMA requests */
+#define DMA_CFG_HWTRIGEN (1 << 1) /*!< Use hardware triggering via imput mux */
+#define DMA_CFG_TRIGPOL_LOW (0 << 4) /*!< Hardware trigger is active low or falling edge */
+#define DMA_CFG_TRIGPOL_HIGH (1 << 4) /*!< Hardware trigger is active high or rising edge */
+#define DMA_CFG_TRIGTYPE_EDGE (0 << 5) /*!< Hardware trigger is edge triggered */
+#define DMA_CFG_TRIGTYPE_LEVEL (1 << 5) /*!< Hardware trigger is level triggered */
+#define DMA_CFG_TRIGBURST_SNGL (0 << 6) /*!< Single transfer. Hardware trigger causes a single transfer */
+#define DMA_CFG_TRIGBURST_BURST (1 << 6) /*!< Burst transfer (see UM) */
+#define DMA_CFG_BURSTPOWER_1 (0 << 8) /*!< Set DMA burst size to 1 transfer */
+#define DMA_CFG_BURSTPOWER_2 (1 << 8) /*!< Set DMA burst size to 2 transfers */
+#define DMA_CFG_BURSTPOWER_4 (2 << 8) /*!< Set DMA burst size to 4 transfers */
+#define DMA_CFG_BURSTPOWER_8 (3 << 8) /*!< Set DMA burst size to 8 transfers */
+#define DMA_CFG_BURSTPOWER_16 (4 << 8) /*!< Set DMA burst size to 16 transfers */
+#define DMA_CFG_BURSTPOWER_32 (5 << 8) /*!< Set DMA burst size to 32 transfers */
+#define DMA_CFG_BURSTPOWER_64 (6 << 8) /*!< Set DMA burst size to 64 transfers */
+#define DMA_CFG_BURSTPOWER_128 (7 << 8) /*!< Set DMA burst size to 128 transfers */
+#define DMA_CFG_BURSTPOWER_256 (8 << 8) /*!< Set DMA burst size to 256 transfers */
+#define DMA_CFG_BURSTPOWER_512 (9 << 8) /*!< Set DMA burst size to 512 transfers */
+#define DMA_CFG_BURSTPOWER_1024 (10 << 8) /*!< Set DMA burst size to 1024 transfers */
+#define DMA_CFG_BURSTPOWER(n) ((n) << 8) /*!< Set DMA burst size to 2^n transfers, max n=10 */
+#define DMA_CFG_SRCBURSTWRAP (1 << 14) /*!< Source burst wrapping is enabled for this DMA channel */
+#define DMA_CFG_DSTBURSTWRAP (1 << 15) /*!< Destination burst wrapping is enabled for this DMA channel */
+#define DMA_CFG_CHPRIORITY(p) ((p) << 16) /*!< Sets DMA channel priority, min 0 (highest), max 3 (lowest) */
+
+/**
+ * @brief Setup a DMA channel configuration
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @param cfg : An Or'ed value of DMA_CFG_* values that define the channel's configuration
+ * @return Nothing
+ * @note This function sets up all configurable options for the DMA channel.
+ * These options are usually set once for a channel and then unchanged.
+ *
+ * The following example show how to configure the channel for peripheral
+ * DMA requests, burst transfer size of 1 (in 'transfers', not bytes),
+ * continuous reading of the same source address, incrementing destination
+ * address, and highest channel priority.
+ * Example: Chip_DMA_SetupChannelConfig(pDMA, SSP0_RX_DMA,
+ * (DMA_CFG_PERIPHREQEN | DMA_CFG_TRIGBURST_BURST | DMA_CFG_BURSTPOWER_1 |
+ * DMA_CFG_SRCBURSTWRAP | DMA_CFG_CHPRIORITY(0)));
+ *
+ * The following example show how to configure the channel for an external
+ * trigger from the imput mux with low edge polarity, a burst transfer size of 8,
+ * incrementing source and destination addresses, and lowest channel
+ * priority.
+ * Example: Chip_DMA_SetupChannelConfig(pDMA, DMA_CH14,
+ * (DMA_CFG_HWTRIGEN | DMA_CFG_TRIGPOL_LOW | DMA_CFG_TRIGTYPE_EDGE |
+ * DMA_CFG_TRIGBURST_BURST | DMA_CFG_BURSTPOWER_8 |
+ * DMA_CFG_CHPRIORITY(3)));
+ *
+ * For non-peripheral DMA triggering (DMA_CFG_HWTRIGEN definition), use the
+ * DMA input mux functions to configure the DMA trigger source for a DMA channel.
+ */
+STATIC INLINE void Chip_DMA_SetupChannelConfig(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t cfg)
+{
+ pDMA->DMACH[ch].CFG = cfg;
+}
+
+/* DMA channel control and status register definitions */
+#define DMA_CTLSTAT_VALIDPENDING (1 << 0) /*!< Valid pending flag for this channel */
+#define DMA_CTLSTAT_TRIG (1 << 2) /*!< Trigger flag. Indicates that the trigger for this channel is currently set */
+
+/**
+ * @brief Returns channel specific status flags
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return AN Or'ed value of DMA_CTLSTAT_VALIDPENDING and DMA_CTLSTAT_TRIG
+ */
+STATIC INLINE uint32_t Chip_DMA_GetChannelStatus(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ return pDMA->DMACH[ch].XFERCFG;
+}
+
+/* DMA channel transfer configuration registers definitions */
+#define DMA_XFERCFG_CFGVALID (1 << 0) /*!< Configuration Valid flag */
+#define DMA_XFERCFG_RELOAD (1 << 1) /*!< Indicates whether the channels control structure will be reloaded when the current descriptor is exhausted */
+#define DMA_XFERCFG_SWTRIG (1 << 2) /*!< Software Trigger */
+#define DMA_XFERCFG_CLRTRIG (1 << 3) /*!< Clear Trigger */
+#define DMA_XFERCFG_SETINTA (1 << 4) /*!< Set Interrupt flag A for this channel to fire when descriptor is complete */
+#define DMA_XFERCFG_SETINTB (1 << 5) /*!< Set Interrupt flag B for this channel to fire when descriptor is complete */
+#define DMA_XFERCFG_WIDTH_8 (0 << 8) /*!< 8-bit transfers are performed */
+#define DMA_XFERCFG_WIDTH_16 (1 << 8) /*!< 16-bit transfers are performed */
+#define DMA_XFERCFG_WIDTH_32 (2 << 8) /*!< 32-bit transfers are performed */
+#define DMA_XFERCFG_SRCINC_0 (0 << 12) /*!< DMA source address is not incremented after a transfer */
+#define DMA_XFERCFG_SRCINC_1 (1 << 12) /*!< DMA source address is incremented by 1 (width) after a transfer */
+#define DMA_XFERCFG_SRCINC_2 (2 << 12) /*!< DMA source address is incremented by 2 (width) after a transfer */
+#define DMA_XFERCFG_SRCINC_4 (3 << 12) /*!< DMA source address is incremented by 4 (width) after a transfer */
+#define DMA_XFERCFG_DSTINC_0 (0 << 14) /*!< DMA destination address is not incremented after a transfer */
+#define DMA_XFERCFG_DSTINC_1 (1 << 14) /*!< DMA destination address is incremented by 1 (width) after a transfer */
+#define DMA_XFERCFG_DSTINC_2 (2 << 14) /*!< DMA destination address is incremented by 2 (width) after a transfer */
+#define DMA_XFERCFG_DSTINC_4 (3 << 14) /*!< DMA destination address is incremented by 4 (width) after a transfer */
+#define DMA_XFERCFG_XFERCOUNT(n) ((n - 1) << 16) /*!< DMA transfer count in 'transfers', between (0)1 and (1023)1024 */
+
+/**
+ * @brief Setup a DMA channel transfer configuration
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @param cfg : An Or'ed value of DMA_XFERCFG_* values that define the channel's transfer configuration
+ * @return Nothing
+ * @note This function sets up the transfer configuration for the DMA channel.
+ *
+ * The following example show how to configure the channel's transfer for
+ * multiple transfer descriptors (ie, ping-pong), interrupt 'A' trigger on
+ * transfer descriptor completion, 128 byte size transfers, and source and
+ * destination address increment.
+ * Example: Chip_DMA_SetupChannelTransfer(pDMA, SSP0_RX_DMA,
+ * (DMA_XFERCFG_CFGVALID | DMA_XFERCFG_RELOAD | DMA_XFERCFG_SETINTA |
+ * DMA_XFERCFG_WIDTH_8 | DMA_XFERCFG_SRCINC_1 | DMA_XFERCFG_DSTINC_1 |
+ * DMA_XFERCFG_XFERCOUNT(128)));
+ */
+STATIC INLINE void Chip_DMA_SetupChannelTransfer(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t cfg)
+{
+ pDMA->DMACH[ch].XFERCFG = cfg;
+}
+
+/**
+ * @brief Set DMA transfer register interrupt bits (safe)
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @param mask : Bits to set
+ * @return Nothing
+ * @note This function safely sets bits in the DMA channel specific XFERCFG
+ * register.
+ */
+void Chip_DMA_SetTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask);
+
+/**
+ * @brief Clear DMA transfer register interrupt bits (safe)
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @param mask : Bits to clear
+ * @return Nothing
+ * @note This function safely clears bits in the DMA channel specific XFERCFG
+ * register.
+ */
+void Chip_DMA_ClearTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask);
+
+/**
+ * @brief Update the transfer size in an existing DMA channel transfer configuration
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @param trans : Number of transfers to update the transfer configuration to (1 - 1023)
+ * @return Nothing
+ */
+void Chip_DMA_SetupChannelTransferSize(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t trans);
+
+/**
+ * @brief Sets a DMA channel configuration as valid
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_SetChannelValid(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ Chip_DMA_SetTranBits(pDMA, ch, DMA_XFERCFG_CFGVALID);
+}
+
+/**
+ * @brief Sets a DMA channel configuration as invalid
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_SetChannelInValid(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ Chip_DMA_ClearTranBits(pDMA, ch, DMA_XFERCFG_CFGVALID);
+}
+
+/**
+ * @brief Performs a software trigger of the DMA channel
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @return Nothing
+ */
+STATIC INLINE void Chip_DMA_SWTriggerChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch)
+{
+ Chip_DMA_SetTranBits(pDMA, ch, DMA_XFERCFG_SWTRIG);
+}
+
+/**
+ * @brief Sets up a DMA channel with the passed DMA transfer descriptor
+ * @param pDMA : The base of DMA controller on the chip
+ * @param ch : DMA channel ID
+ * @param desc : Pointer to DMA transfer descriptor
+ * @return false if the DMA channel was active, otherwise true
+ * @note This function will set the DMA descriptor in the SRAM table to the
+ * the passed descriptor. This function is only meant to be used when
+ * the DMA channel is not active and can be used to setup the
+ * initial transfer for a linked list or ping-pong buffer or just a
+ * single transfer without a next descriptor.
+ *
+ * If using this function to write the initial transfer descriptor in
+ * a linked list or ping-pong buffer configuration, it should contain a
+ * non-NULL 'next' field pointer.
+ */
+bool Chip_DMA_SetupTranChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch, DMA_CHDESC_T *desc);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DMA_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/error.h b/source/lpc_chip_11u6x/inc/error.h
new file mode 100644
index 0000000..b1528ff
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/error.h
@@ -0,0 +1,156 @@
+/*
+ * @brief Error code returned by Boot ROM drivers/library functions
+ * @ingroup Common
+ *
+ * This file contains unified error codes to be used across driver,
+ * middleware, applications, hal and demo software.
+ *
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2012
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __LPC_ERROR_H__
+#define __LPC_ERROR_H__
+
+/** Error code returned by Boot ROM drivers/library functions
+ *
+ * Error codes are a 32-bit value with :
+ * - The 16 MSB contains the peripheral code number
+ * - The 16 LSB contains an error code number associated to that peripheral
+ *
+ */
+typedef enum {
+ /**\b 0x00000000*/ LPC_OK = 0, /**< enum value returned on Success */
+ /**\b 0xFFFFFFFF*/ ERR_FAILED = -1, /**< enum value returned on general failure */
+ /**\b 0xFFFFFFFE*/ ERR_TIME_OUT = -2, /**< enum value returned on general timeout */
+ /**\b 0xFFFFFFFD*/ ERR_BUSY = -3, /**< enum value returned when resource is busy */
+
+ /* ISP related errors */
+ ERR_ISP_BASE = 0x00000000,
+ /*0x00000001*/ ERR_ISP_INVALID_COMMAND = ERR_ISP_BASE + 1,
+ /*0x00000002*/ ERR_ISP_SRC_ADDR_ERROR, /* Source address not on word boundary */
+ /*0x00000003*/ ERR_ISP_DST_ADDR_ERROR, /* Destination address not on word or 256 byte boundary */
+ /*0x00000004*/ ERR_ISP_SRC_ADDR_NOT_MAPPED,
+ /*0x00000005*/ ERR_ISP_DST_ADDR_NOT_MAPPED,
+ /*0x00000006*/ ERR_ISP_COUNT_ERROR, /* Byte count is not multiple of 4 or is not a permitted value */
+ /*0x00000007*/ ERR_ISP_INVALID_SECTOR,
+ /*0x00000008*/ ERR_ISP_SECTOR_NOT_BLANK,
+ /*0x00000009*/ ERR_ISP_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION,
+ /*0x0000000A*/ ERR_ISP_COMPARE_ERROR,
+ /*0x0000000B*/ ERR_ISP_BUSY,/* Flash programming hardware interface is busy */
+ /*0x0000000C*/ ERR_ISP_PARAM_ERROR, /* Insufficient number of parameters */
+ /*0x0000000D*/ ERR_ISP_ADDR_ERROR, /* Address not on word boundary */
+ /*0x0000000E*/ ERR_ISP_ADDR_NOT_MAPPED,
+ /*0x0000000F*/ ERR_ISP_CMD_LOCKED, /* Command is locked */
+ /*0x00000010*/ ERR_ISP_INVALID_CODE,/* Unlock code is invalid */
+ /*0x00000011*/ ERR_ISP_INVALID_BAUD_RATE,
+ /*0x00000012*/ ERR_ISP_INVALID_STOP_BIT,
+ /*0x00000013*/ ERR_ISP_CODE_READ_PROTECTION_ENABLED,
+
+ /* ROM API related errors */
+ ERR_API_BASE = 0x00010000,
+ /**\b 0x00010001*/ ERR_API_INVALID_PARAMS = ERR_API_BASE + 1, /**< Invalid parameters*/
+ /**\b 0x00010002*/ ERR_API_INVALID_PARAM1, /**< PARAM1 is invalid */
+ /**\b 0x00010003*/ ERR_API_INVALID_PARAM2, /**< PARAM2 is invalid */
+ /**\b 0x00010004*/ ERR_API_INVALID_PARAM3, /**< PARAM3 is invalid */
+ /**\b 0x00010005*/ ERR_API_MOD_INIT,/**< API is called before module init */
+
+ /* SPIFI API related errors */
+ ERR_SPIFI_BASE = 0x00020000,
+ /*0x00020001*/ ERR_SPIFI_DEVICE_ERROR = ERR_SPIFI_BASE + 1,
+ /*0x00020002*/ ERR_SPIFI_INTERNAL_ERROR,
+ /*0x00020003*/ ERR_SPIFI_TIMEOUT,
+ /*0x00020004*/ ERR_SPIFI_OPERAND_ERROR,
+ /*0x00020005*/ ERR_SPIFI_STATUS_PROBLEM,
+ /*0x00020006*/ ERR_SPIFI_UNKNOWN_EXT,
+ /*0x00020007*/ ERR_SPIFI_UNKNOWN_ID,
+ /*0x00020008*/ ERR_SPIFI_UNKNOWN_TYPE,
+ /*0x00020009*/ ERR_SPIFI_UNKNOWN_MFG,
+
+ /* Security API related errors */
+ ERR_SEC_BASE = 0x00030000,
+ /*0x00030001*/ ERR_SEC_AES_WRONG_CMD = ERR_SEC_BASE + 1,
+ /*0x00030002*/ ERR_SEC_AES_NOT_SUPPORTED,
+ /*0x00030003*/ ERR_SEC_AES_KEY_ALREADY_PROGRAMMED,
+
+ /* USB device stack related errors */
+ ERR_USBD_BASE = 0x00040000,
+ /**\b 0x00040001*/ ERR_USBD_INVALID_REQ = ERR_USBD_BASE + 1,/**< invalid request */
+ /**\b 0x00040002*/ ERR_USBD_UNHANDLED, /**< Callback did not process the event */
+ /**\b 0x00040003*/ ERR_USBD_STALL, /**< Stall the endpoint on which the call back is called */
+ /**\b 0x00040004*/ ERR_USBD_SEND_ZLP, /**< Send ZLP packet on the endpoint on which the call back is called */
+ /**\b 0x00040005*/ ERR_USBD_SEND_DATA, /**< Send data packet on the endpoint on which the call back is called */
+ /**\b 0x00040006*/ ERR_USBD_BAD_DESC, /**< Bad descriptor*/
+ /**\b 0x00040007*/ ERR_USBD_BAD_CFG_DESC, /**< Bad config descriptor*/
+ /**\b 0x00040008*/ ERR_USBD_BAD_INTF_DESC, /**< Bad interface descriptor*/
+ /**\b 0x00040009*/ ERR_USBD_BAD_EP_DESC,/**< Bad endpoint descriptor*/
+ /**\b 0x0004000a*/ ERR_USBD_BAD_MEM_BUF,/**< Bad alignment of buffer passed. */
+ /**\b 0x0004000b*/ ERR_USBD_TOO_MANY_CLASS_HDLR,/**< Too many class handlers. */
+
+ /* CGU related errors */
+ ERR_CGU_BASE = 0x00050000,
+ /*0x00050001*/ ERR_CGU_NOT_IMPL = ERR_CGU_BASE + 1,
+ /*0x00050002*/ ERR_CGU_INVALID_PARAM,
+ /*0x00050003*/ ERR_CGU_INVALID_SLICE,
+ /*0x00050004*/ ERR_CGU_OUTPUT_GEN,
+ /*0x00050005*/ ERR_CGU_DIV_SRC,
+ /*0x00050006*/ ERR_CGU_DIV_VAL,
+ /*0x00050007*/ ERR_CGU_SRC,
+
+ /* I2C related errors */
+ ERR_I2C_BASE = 0x00060000,
+ /*0x00060001*/ ERR_I2C_NAK = ERR_I2C_BASE + 1,
+ /*0x00060002*/ ERR_I2C_BUFFER_OVERFLOW,
+ /*0x00060003*/ ERR_I2C_BYTE_COUNT_ERR,
+ /*0x00060004*/ ERR_I2C_LOSS_OF_ARBRITRATION,
+ /*0x00060005*/ ERR_I2C_SLAVE_NOT_ADDRESSED,
+ /*0x00060006*/ ERR_I2C_LOSS_OF_ARBRITRATION_NAK_BIT,
+ /*0x00060007*/ ERR_I2C_GENERAL_FAILURE,
+ /*0x00060008*/ ERR_I2C_REGS_SET_TO_DEFAULT,
+ /*0x00060009*/ ERR_I2C_TIMEOUT,
+ /*0x0006000A*/ ERR_I2C_BUFFER_UNDERFLOW,
+
+ ERR_DMA_BASE = 0x000D0000,
+ /*0x000D0001*/ ERR_DMA_ERROR_INT = ERR_DMA_BASE + 1,
+ /*0x000D0002*/ ERR_DMA_CHANNEL_NUMBER,
+ /*0x000D0003*/ ERR_DMA_CHANNEL_DISABLED,
+ /*0x000D0004*/ ERR_DMA_BUSY,
+ /*0x000D0005*/ ERR_DMA_NOT_ALIGNMENT,
+ /*0x000D0006*/ ERR_DMA_PING_PONG_EN,
+ /*0x000D0007*/ ERR_DMA_CHANNEL_VALID_PENDING
+} ErrorCode_t;
+
+#ifndef offsetof
+#define offsetof(s, m) (int) &(((s *) 0)->m)
+#endif
+
+#define COMPILE_TIME_ASSERT(pred) switch (0) { \
+ case 0: \
+ case pred:; }
+
+#endif /* __LPC_ERROR_H__ */
diff --git a/source/lpc_chip_11u6x/inc/fmc_11u6x.h b/source/lpc_chip_11u6x/inc/fmc_11u6x.h
new file mode 100644
index 0000000..1056fc3
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/fmc_11u6x.h
@@ -0,0 +1,140 @@
+/*
+ * @brief FLASH Memory Controller (FMC) registers and control functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __FMC_11U6X_H_
+#define __FMC_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup FMC_11U6X CHIP: LPC11u6x FLASH Memory Controller driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief FLASH Memory Controller Unit register block structure
+ */
+typedef struct { /*!< FMC Structure */
+ __I uint32_t RESERVED1[4];
+ __IO uint32_t FLASHTIM;
+ __I uint32_t RESERVED2[3];
+ __IO uint32_t FMSSTART;
+ __IO uint32_t FMSSTOP;
+ __I uint32_t RESERVED3;
+ __I uint32_t FMSW[1];
+} LPC_FMC_T;
+
+/**
+ * @brief FLASH Access time definitions
+ */
+typedef enum {
+ FLASHTIM_1CLK_CPU = 0, /*!< Flash accesses use 1 CPU clocks */
+ FLASHTIM_2CLK_CPU = 1, /*!< Flash accesses use 2 CPU clocks */
+ FLASHTIM_3CLK_CPU = 2, /*!< Flash accesses use 3 CPU clocks */
+} FMC_FLASHTIM_T;
+
+/**
+ * @brief Set FLASH access time in clocks
+ * @param clks : Clock cycles for FLASH access (minus 1)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_FMC_SetFLASHAccess(FMC_FLASHTIM_T clks)
+{
+ uint32_t tmp = LPC_FMC->FLASHTIM & (~(0x3));
+
+ /* Don't alter upper bits */
+ LPC_FMC->FLASHTIM = tmp | clks;
+}
+
+/* Flash signature start and busy status bit */
+#define FMC_FLASHSIG_BUSY (1UL << 17)
+
+/**
+ * @brief Start computation of a signature for a FLASH memory range
+ * @param start : Starting FLASH address for computation, must be aligned on 16 byte boundary
+ * @param stop : Ending FLASH address for computation, must be aligned on 16 byte boundary
+ * @return Nothing
+ * @note Only bits 20..4 are used for the FLASH signature computation.
+ * Use the Chip_FMC_IsSignatureBusy() function to determine when the
+ * signature computation operation is complete and use the
+ * Chip_FMC_GetSignature() function to get the computed signature.
+ */
+STATIC INLINE void Chip_FMC_ComputeSignature(uint32_t start, uint32_t stop)
+{
+ LPC_FMC->FMSSTART = (start >> 4);
+ LPC_FMC->FMSSTOP = (stop >> 4) | FMC_FLASHSIG_BUSY;
+}
+
+/**
+ * @brief Start computation of a signature for a FLASH memory address and block count
+ * @param start : Starting FLASH address for computation, must be aligned on 16 byte boundary
+ * @param blocks : Number of 16 byte blocks used for computation
+ * @return Nothing
+ * @note Only bits 20..4 are used for the FLASH signature computation.
+ * Use the Chip_FMC_IsSignatureBusy() function to determine when the
+ * signature computation operation is complete and the
+ * Chip_FMC_GetSignature() function to get the computed signature.
+ */
+STATIC INLINE void Chip_FMC_ComputeSignatureBlocks(uint32_t start, uint32_t blocks)
+{
+ Chip_FMC_ComputeSignature(start, (start + (blocks * 16)));
+}
+
+/**
+ * @brief Check for signature geenration completion
+ * @return true if the signature computation is running, false if finished
+ */
+STATIC INLINE bool Chip_FMC_IsSignatureBusy(void)
+{
+ return (bool) ((LPC_FMC->FMSSTOP & FMC_FLASHSIG_BUSY) != 0);
+}
+
+/**
+ * @brief Returns the generated FLASH signature value
+ * @param index : Not used, must be 0
+ * @return the generated FLASH signature value
+ */
+STATIC INLINE uint32_t Chip_FMC_GetSignature(int index)
+{
+ return LPC_FMC->FMSW[index];
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FMC_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/gpio_11u6x.h b/source/lpc_chip_11u6x/inc/gpio_11u6x.h
new file mode 100644
index 0000000..eb14c74
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/gpio_11u6x.h
@@ -0,0 +1,471 @@
+/*
+ * @brief LPC11u6x GPIO driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __GPIO_11U6X_H_
+#define __GPIO_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup GPIO_11U6X CHIP: LPC11u6x GPIO driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief GPIO port register block structure
+ */
+typedef struct { /*!< GPIO_PORT Structure */
+ __IO uint8_t B[128][32]; /*!< Offset 0x0000: Byte pin registers ports 0 to n; pins PIOn_0 to PIOn_31 */
+ __IO uint32_t W[32][32]; /*!< Offset 0x1000: Word pin registers port 0 to n */
+ __IO uint32_t DIR[32]; /*!< Offset 0x2000: Direction registers port n */
+ __IO uint32_t MASK[32]; /*!< Offset 0x2080: Mask register port n */
+ __IO uint32_t PIN[32]; /*!< Offset 0x2100: Portpin register port n */
+ __IO uint32_t MPIN[32]; /*!< Offset 0x2180: Masked port register port n */
+ __IO uint32_t SET[32]; /*!< Offset 0x2200: Write: Set register for port n Read: output bits for port n */
+ __O uint32_t CLR[32]; /*!< Offset 0x2280: Clear port n */
+ __O uint32_t NOT[32]; /*!< Offset 0x2300: Toggle port n */
+} LPC_GPIO_T;
+
+/**
+ * @brief Initialize GPIO block
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @return Nothing
+ */
+void Chip_GPIO_Init(LPC_GPIO_T *pGPIO);
+
+/**
+ * @brief De-Initialize GPIO block
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @return Nothing
+ */
+void Chip_GPIO_DeInit(LPC_GPIO_T *pGPIO);
+
+/**
+ * @brief Set a GPIO port/bit state
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO port to set
+ * @param pin : GPIO pin to set
+ * @param setting : true for high, false for low
+ * @return Nothing
+ */
+STATIC INLINE void Chip_GPIO_WritePortBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t pin, bool setting)
+{
+ pGPIO->B[port][pin] = setting;
+}
+
+/**
+ * @brief Set a GPIO pin state via the GPIO byte register
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pin : GPIO pin to set
+ * @param setting : true for high, false for low
+ * @return Nothing
+ * @note This function replaces Chip_GPIO_WritePortBit()
+ */
+STATIC INLINE void Chip_GPIO_SetPinState(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin, bool setting)
+{
+ pGPIO->B[port][pin] = setting;
+}
+
+/**
+ * @brief Read a GPIO state
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO port to read
+ * @param pin : GPIO pin to read
+ * @return true of the GPIO is high, false if low
+ * @note It is recommended to use the Chip_GPIO_GetPinState() function instead.
+ */
+STATIC INLINE bool Chip_GPIO_ReadPortBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t pin)
+{
+ return (bool) pGPIO->B[port][pin];
+}
+
+/**
+ * @brief Get a GPIO pin state via the GPIO byte register
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pin : GPIO pin to get state for
+ * @return true if the GPIO is high, false if low
+ * @note This function replaces Chip_GPIO_ReadPortBit()
+ */
+STATIC INLINE bool Chip_GPIO_GetPinState(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin)
+{
+ return (bool) pGPIO->B[port][pin];
+}
+
+/**
+ * @brief Set a GPIO direction
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO port to set
+ * @param bit : GPIO bit to set
+ * @param setting : true for output, false for input
+ * @return Nothing
+ * @note It is recommended to use the Chip_GPIO_SetPinDIROutput(),
+ * Chip_GPIO_SetPinDIRInput() or Chip_GPIO_SetPinDIR() functions instead
+ * of this function.
+ */
+void Chip_GPIO_WriteDirBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t bit, bool setting);
+
+/**
+ * @brief Set GPIO direction for a single GPIO pin to an output
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pin : GPIO pin to set direction on as output
+ * @return Nothing
+ */
+STATIC INLINE void Chip_GPIO_SetPinDIROutput(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin)
+{
+ pGPIO->DIR[port] |= 1UL << pin;
+}
+
+/**
+ * @brief Set GPIO direction for a single GPIO pin to an input
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pin : GPIO pin to set direction on as input
+ * @return Nothing
+ */
+STATIC INLINE void Chip_GPIO_SetPinDIRInput(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin)
+{
+ pGPIO->DIR[port] &= ~(1UL << pin);
+}
+
+/**
+ * @brief Set GPIO direction for a single GPIO pin
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pin : GPIO pin to set direction for
+ * @param output : true for output, false for input
+ * @return Nothing
+ */
+void Chip_GPIO_SetPinDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin, bool output);
+
+/**
+ * @brief Read a GPIO direction (out or in)
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO port to read
+ * @param bit : GPIO bit to read
+ * @return true of the GPIO is an output, false if input
+ * @note It is recommended to use the Chip_GPIO_GetPinDIR() function instead.
+ */
+STATIC INLINE bool Chip_GPIO_ReadDirBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t bit)
+{
+ return (bool) (((pGPIO->DIR[port]) >> bit) & 1);
+}
+
+/**
+ * @brief Get GPIO direction for a single GPIO pin
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pin : GPIO pin to get direction for
+ * @return true if the GPIO is an output, false if input
+ */
+STATIC INLINE bool Chip_GPIO_GetPinDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin)
+{
+ return (bool) (((pGPIO->DIR[port]) >> pin) & 1);
+}
+
+/**
+ * @brief Set Direction for a GPIO port
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param portNum : port Number
+ * @param bitValue : GPIO bit to set
+ * @param out : Direction value, 0 = input, !0 = output
+ * @return None
+ * @note Bits set to '0' are not altered. It is recommended to use the
+ * Chip_GPIO_SetPortDIR() function instead.
+ */
+void Chip_GPIO_SetDir(LPC_GPIO_T *pGPIO, uint8_t portNum, uint32_t bitValue, uint8_t out);
+
+/**
+ * @brief Set GPIO direction for a all selected GPIO pins to an output
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pinMask : GPIO pin mask to set direction on as output (bits 0..b for pins 0..n)
+ * @return Nothing
+ * @note Sets multiple GPIO pins to the output direction, each bit's position that is
+ * high sets the corresponding pin number for that bit to an output.
+ */
+STATIC INLINE void Chip_GPIO_SetPortDIROutput(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask)
+{
+ pGPIO->DIR[port] |= pinMask;
+}
+
+/**
+ * @brief Set GPIO direction for a all selected GPIO pins to an input
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pinMask : GPIO pin mask to set direction on as input (bits 0..b for pins 0..n)
+ * @return Nothing
+ * @note Sets multiple GPIO pins to the input direction, each bit's position that is
+ * high sets the corresponding pin number for that bit to an input.
+ */
+STATIC INLINE void Chip_GPIO_SetPortDIRInput(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask)
+{
+ pGPIO->DIR[port] &= ~pinMask;
+}
+
+/**
+ * @brief Set GPIO direction for a all selected GPIO pins to an input or output
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pinMask : GPIO pin mask to set direction on (bits 0..b for pins 0..n)
+ * @param outSet : Direction value, false = set as inputs, true = set as outputs
+ * @return Nothing
+ * @note Sets multiple GPIO pins to the input direction, each bit's position that is
+ * high sets the corresponding pin number for that bit to an input.
+ */
+void Chip_GPIO_SetPortDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask, bool outSet);
+
+/**
+ * @brief Get GPIO direction for a all GPIO pins
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @return a bitfield containing the input and output states for each pin
+ * @note For pins 0..n, a high state in a bit corresponds to an output state for the
+ * same pin, while a low state corresponds to an input state.
+ */
+STATIC INLINE uint32_t Chip_GPIO_GetPortDIR(LPC_GPIO_T *pGPIO, uint8_t port)
+{
+ return pGPIO->DIR[port];
+}
+
+/**
+ * @brief Set GPIO port mask value for GPIO masked read and write
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : port Number
+ * @param mask : Mask value for read and write (only low bits are enabled)
+ * @return Nothing
+ * @note Controls which bits are set or unset when using the masked
+ * GPIO read and write functions. A low state indicates the pin is settable
+ * and readable via the masked write and read functions.
+ */
+STATIC INLINE void Chip_GPIO_SetPortMask(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t mask)
+{
+ pGPIO->MASK[port] = mask;
+}
+
+/**
+ * @brief Get GPIO port mask value used for GPIO masked read and write
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : port Number
+ * @return Returns value set with the Chip_GPIO_SetPortMask() function.
+ * @note A high bit in the return value indicates that that GPIO pin for the
+ * port cannot be set using the masked write function.
+ */
+STATIC INLINE uint32_t Chip_GPIO_GetPortMask(LPC_GPIO_T *pGPIO, uint8_t port)
+{
+ return pGPIO->MASK[port];
+}
+
+/**
+ * @brief Set all GPIO raw pin states (regardless of masking)
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param value : Value to set all GPIO pin states (0..n) to
+ * @return Nothing
+ */
+STATIC INLINE void Chip_GPIO_SetPortValue(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t value)
+{
+ pGPIO->PIN[port] = value;
+}
+
+/**
+ * @brief Get all GPIO raw pin states (regardless of masking)
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @return Current (raw) state of all GPIO pins
+ */
+STATIC INLINE uint32_t Chip_GPIO_GetPortValue(LPC_GPIO_T *pGPIO, uint8_t port)
+{
+ return pGPIO->PIN[port];
+}
+
+/**
+ * @brief Set all GPIO pin states, but mask via the MASKP0 register
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param value : Value to set all GPIO pin states (0..n) to
+ * @return Nothing
+ */
+STATIC INLINE void Chip_GPIO_SetMaskedPortValue(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t value)
+{
+ pGPIO->MPIN[port] = value;
+}
+
+/**
+ * @brief Get all GPIO pin statesm but mask via the MASKP0 register
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @return Current (masked) state of all GPIO pins
+ */
+STATIC INLINE uint32_t Chip_GPIO_GetMaskedPortValue(LPC_GPIO_T *pGPIO, uint8_t port)
+{
+ return pGPIO->MPIN[port];
+}
+
+/**
+ * @brief Set a GPIO port/bit to the high state
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param portNum : port number
+ * @param bitValue : bit(s) in the port to set high
+ * @return None
+ * @note Any bit set as a '0' will not have it's state changed. This only
+ * applies to ports configured as an output. It is recommended to use the
+ * Chip_GPIO_SetPortOutHigh() function instead.
+ */
+STATIC INLINE void Chip_GPIO_SetValue(LPC_GPIO_T *pGPIO, uint8_t portNum, uint32_t bitValue)
+{
+ pGPIO->SET[portNum] = bitValue;
+}
+
+/**
+ * @brief Set selected GPIO output pins to the high state
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pins : pins (0..n) to set high
+ * @return None
+ * @note Any bit set as a '0' will not have it's state changed. This only
+ * applies to ports configured as an output.
+ */
+STATIC INLINE void Chip_GPIO_SetPortOutHigh(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pins)
+{
+ pGPIO->SET[port] = pins;
+}
+
+/**
+ * @brief Set an individual GPIO output pin to the high state
+ * @param pGPIO : The base of GPIO peripheral on the chip'
+ * @param port : GPIO Port number where @a pin is located
+ * @param pin : pin number (0..n) to set high
+ * @return None
+ * @note Any bit set as a '0' will not have it's state changed. This only
+ * applies to ports configured as an output.
+ */
+STATIC INLINE void Chip_GPIO_SetPinOutHigh(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin)
+{
+ pGPIO->SET[port] = (1 << pin);
+}
+
+/**
+ * @brief Set a GPIO port/bit to the low state
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param portNum : port number
+ * @param bitValue : bit(s) in the port to set low
+ * @return None
+ * @note Any bit set as a '0' will not have it's state changed. This only
+ * applies to ports configured as an output.
+ */
+STATIC INLINE void Chip_GPIO_ClearValue(LPC_GPIO_T *pGPIO, uint8_t portNum, uint32_t bitValue)
+{
+ pGPIO->CLR[portNum] = bitValue;
+}
+
+/**
+ * @brief Set selected GPIO output pins to the low state
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pins : pins (0..n) to set low
+ * @return None
+ * @note Any bit set as a '0' will not have it's state changed. This only
+ * applies to ports configured as an output.
+ */
+STATIC INLINE void Chip_GPIO_SetPortOutLow(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pins)
+{
+ pGPIO->CLR[port] = pins;
+}
+
+/**
+ * @brief Set an individual GPIO output pin to the low state
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pin : pin number (0..n) to set low
+ * @return None
+ * @note Any bit set as a '0' will not have it's state changed. This only
+ * applies to ports configured as an output.
+ */
+STATIC INLINE void Chip_GPIO_SetPinOutLow(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin)
+{
+ pGPIO->CLR[port] = (1 << pin);
+}
+
+/**
+ * @brief Toggle selected GPIO output pins to the opposite state
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pins : pins (0..n) to toggle
+ * @return None
+ * @note Any bit set as a '0' will not have it's state changed. This only
+ * applies to ports configured as an output.
+ */
+STATIC INLINE void Chip_GPIO_SetPortToggle(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pins)
+{
+ pGPIO->NOT[port] = pins;
+}
+
+/**
+ * @brief Toggle an individual GPIO output pin to the opposite state
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param port : GPIO Port number where @a pin is located
+ * @param pin : pin number (0..n) to toggle
+ * @return None
+ * @note Any bit set as a '0' will not have it's state changed. This only
+ * applies to ports configured as an output.
+ */
+STATIC INLINE void Chip_GPIO_SetPinToggle(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin)
+{
+ pGPIO->NOT[port] = (1 << pin);
+}
+
+/**
+ * @brief Read current bit states for the selected port
+ * @param pGPIO : The base of GPIO peripheral on the chip
+ * @param portNum : port number to read
+ * @return Current value of GPIO port
+ * @note The current states of the bits for the port are read, regardless of
+ * whether the GPIO port bits are input or output.
+ */
+STATIC INLINE uint32_t Chip_GPIO_ReadValue(LPC_GPIO_T *pGPIO, uint8_t portNum)
+{
+ return pGPIO->PIN[portNum];
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPIO_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/gpiogroup_11u6x.h b/source/lpc_chip_11u6x/inc/gpiogroup_11u6x.h
new file mode 100644
index 0000000..6a42612
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/gpiogroup_11u6x.h
@@ -0,0 +1,205 @@
+/*
+ * @brief LPC11U6x GPIO group driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __GPIOGROUP_11U6X_H_
+#define __GPIOGROUP_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup GPIOGP_11U6X CHIP: LPC11u6x GPIO group driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief GPIO grouped interrupt register block structure
+ */
+typedef struct { /*!< GPIO_GROUP_INTn Structure */
+ __IO uint32_t CTRL; /*!< GPIO grouped interrupt control register */
+ __I uint32_t RESERVED0[7];
+ __IO uint32_t PORT_POL[8]; /*!< GPIO grouped interrupt port polarity register */
+ __IO uint32_t PORT_ENA[8]; /*!< GPIO grouped interrupt port m enable register */
+ uint32_t RESERVED1[4072];
+} LPC_GPIOGROUPINT_T;
+
+/**
+ * LPC11u6x GPIO group bit definitions
+ */
+#define GPIOGR_INT (1 << 0) /*!< GPIO interrupt pending/clear bit */
+#define GPIOGR_COMB (1 << 1) /*!< GPIO interrupt OR(0)/AND(1) mode bit */
+#define GPIOGR_TRIG (1 << 2) /*!< GPIO interrupt edge(0)/level(1) mode bit */
+
+/**
+ * @brief Clear interrupt pending status for the selected group
+ * @param pGPIOGPINT : Pointer to GPIO group register block
+ * @param group : GPIO group number
+ * @return None
+ */
+STATIC INLINE void Chip_GPIOGP_ClearIntStatus(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group)
+{
+ uint32_t temp;
+
+ temp = pGPIOGPINT[group].CTRL;
+ pGPIOGPINT[group].CTRL = temp | GPIOGR_INT;
+}
+
+/**
+ * @brief Returns current GPIO group inetrrupt pending status
+ * @param pGPIOGPINT : Pointer to GPIO group register block
+ * @param group : GPIO group number
+ * @return true if the group interrupt is pending, otherwise false.
+ */
+STATIC INLINE bool Chip_GPIOGP_GetIntStatus(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group)
+{
+ return (bool) ((pGPIOGPINT[group].CTRL & GPIOGR_INT) != 0);
+}
+
+/**
+ * @brief Selected GPIO group functionality for trigger on any pin in group (OR mode)
+ * @param pGPIOGPINT : Pointer to GPIO group register block
+ * @param group : GPIO group number
+ * @return None
+ */
+STATIC INLINE void Chip_GPIOGP_SelectOrMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group)
+{
+ pGPIOGPINT[group].CTRL &= ~GPIOGR_COMB;
+}
+
+/**
+ * @brief Selected GPIO group functionality for trigger on all matching pins in group (AND mode)
+ * @param pGPIOGPINT : Pointer to GPIO group register block
+ * @param group : GPIO group number
+ * @return None
+ */
+STATIC INLINE void Chip_GPIOGP_SelectAndMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group)
+{
+ pGPIOGPINT[group].CTRL |= GPIOGR_COMB;
+}
+
+/**
+ * @brief Selected GPIO group functionality edge trigger mode
+ * @param pGPIOGPINT : Pointer to GPIO group register block
+ * @param group : GPIO group number
+ * @return None
+ */
+STATIC INLINE void Chip_GPIOGP_SelectEdgeMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group)
+{
+ pGPIOGPINT[group].CTRL &= ~GPIOGR_TRIG;
+}
+
+/**
+ * @brief Selected GPIO group functionality level trigger mode
+ * @param pGPIOGPINT : Pointer to GPIO group register block
+ * @param group : GPIO group number
+ * @return None
+ */
+STATIC INLINE void Chip_GPIOGP_SelectLevelMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group)
+{
+ pGPIOGPINT[group].CTRL |= GPIOGR_TRIG;
+}
+
+/**
+ * @brief Set selected pins for the group and port to low level trigger
+ * @param pGPIOGPINT : Pointer to GPIO group register block
+ * @param group : GPIO group number
+ * @param port : GPIO port number
+ * @param pinMask : Or'ed value of pins to select for low level (bit 0 = pin 0, 1 = pin1, etc.)
+ * @return None
+ */
+STATIC INLINE void Chip_GPIOGP_SelectLowLevel(LPC_GPIOGROUPINT_T *pGPIOGPINT,
+ uint8_t group,
+ uint8_t port,
+ uint32_t pinMask)
+{
+ pGPIOGPINT[group].PORT_POL[port] &= ~pinMask;
+}
+
+/**
+ * @brief Set selected pins for the group and port to high level trigger
+ * @param pGPIOGPINT : Pointer to GPIO group register block
+ * @param group : GPIO group number
+ * @param port : GPIO port number
+ * @param pinMask : Or'ed value of pins to select for high level (bit 0 = pin 0, 1 = pin1, etc.)
+ * @return None
+ */
+STATIC INLINE void Chip_GPIOGP_SelectHighLevel(LPC_GPIOGROUPINT_T *pGPIOGPINT,
+ uint8_t group,
+ uint8_t port,
+ uint32_t pinMask)
+{
+ pGPIOGPINT[group].PORT_POL[port] |= pinMask;
+}
+
+/**
+ * @brief Disabled selected pins for the group interrupt
+ * @param pGPIOGPINT : Pointer to GPIO group register block
+ * @param group : GPIO group number
+ * @param port : GPIO port number
+ * @param pinMask : Or'ed value of pins to disable interrupt for (bit 0 = pin 0, 1 = pin1, etc.)
+ * @return None
+ * @note Disabled pins do not contribute to the group interrupt.
+ */
+STATIC INLINE void Chip_GPIOGP_DisableGroupPins(LPC_GPIOGROUPINT_T *pGPIOGPINT,
+ uint8_t group,
+ uint8_t port,
+ uint32_t pinMask)
+{
+ pGPIOGPINT[group].PORT_ENA[port] &= ~pinMask;
+}
+
+/**
+ * @brief Enable selected pins for the group interrupt
+ * @param pGPIOGPINT : Pointer to GPIO group register block
+ * @param group : GPIO group number
+ * @param port : GPIO port number
+ * @param pinMask : Or'ed value of pins to enable interrupt for (bit 0 = pin 0, 1 = pin1, etc.)
+ * @return None
+ * @note Enabled pins contribute to the group interrupt.
+ */
+STATIC INLINE void Chip_GPIOGP_EnableGroupPins(LPC_GPIOGROUPINT_T *pGPIOGPINT,
+ uint8_t group,
+ uint8_t port,
+ uint32_t pinMask)
+{
+ pGPIOGPINT[group].PORT_ENA[port] |= pinMask;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPIOGROUP_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/i2c_11u6x.h b/source/lpc_chip_11u6x/inc/i2c_11u6x.h
new file mode 100644
index 0000000..add6834
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/i2c_11u6x.h
@@ -0,0 +1,400 @@
+/*
+ * @brief LPC11u6x I2C driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __I2C_11U6X_H_
+#define __I2C_11U6X_H_
+
+#include "i2c_common_11u6x.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @ingroup I2C_11U6X
+ * @{
+ */
+
+/**
+ * @brief Return values for SLAVE handler
+ * @note
+ * Chip drivers will usally be designed to match their events with this value
+ */
+#define RET_SLAVE_TX 6 /**< Return value, when 1 byte TX'd successfully */
+#define RET_SLAVE_RX 5 /**< Return value, when 1 byte RX'd successfully */
+#define RET_SLAVE_IDLE 2 /**< Return value, when slave enter idle mode */
+#define RET_SLAVE_BUSY 0 /**< Return value, when slave is busy */
+
+/**
+ * @brief I2C state handle return values
+ */
+#define I2C_STA_STO_RECV 0x20
+
+/*
+ * @brief I2C return status code definitions
+ */
+#define I2C_I2STAT_NO_INF ((0xF8))/*!< No relevant information */
+#define I2C_I2STAT_BUS_ERROR ((0x00))/*!< Bus Error */
+
+/*
+ * @brief I2C status values
+ */
+#define I2C_SETUP_STATUS_ARBF (1 << 8) /**< Arbitration false */
+#define I2C_SETUP_STATUS_NOACKF (1 << 9) /**< No ACK returned */
+#define I2C_SETUP_STATUS_DONE (1 << 10) /**< Status DONE */
+
+/*
+ * @brief I2C state handle return values
+ */
+#define I2C_OK 0x00
+#define I2C_BYTE_SENT 0x01
+#define I2C_BYTE_RECV 0x02
+#define I2C_LAST_BYTE_RECV 0x04
+#define I2C_SEND_END 0x08
+#define I2C_RECV_END 0x10
+#define I2C_STA_STO_RECV 0x20
+
+#define I2C_ERR (0x10000000)
+#define I2C_NAK_RECV (0x10000000 | 0x01)
+
+#define I2C_CheckError(ErrorCode) (ErrorCode & 0x10000000)
+
+/*
+ * @brief I2C monitor control configuration defines
+ */
+#define I2C_MONITOR_CFG_SCL_OUTPUT I2C_I2MMCTRL_ENA_SCL /**< SCL output enable */
+#define I2C_MONITOR_CFG_MATCHALL I2C_I2MMCTRL_MATCH_ALL /**< Select interrupt register match */
+
+/**
+ * @brief I2C Slave Identifiers
+ */
+typedef enum {
+ I2C_SLAVE_GENERAL, /**< Slave ID for general calls */
+ I2C_SLAVE_0, /**< Slave ID fo Slave Address 0 */
+ I2C_SLAVE_1, /**< Slave ID fo Slave Address 1 */
+ I2C_SLAVE_2, /**< Slave ID fo Slave Address 2 */
+ I2C_SLAVE_3, /**< Slave ID fo Slave Address 3 */
+ I2C_SLAVE_NUM_INTERFACE /**< Number of slave interfaces */
+} I2C_SLAVE_ID;
+
+/**
+ * @brief I2C transfer status
+ */
+typedef enum {
+ I2C_STATUS_DONE, /**< Transfer done successfully */
+ I2C_STATUS_NAK, /**< NAK received during transfer */
+ I2C_STATUS_ARBLOST, /**< Aribitration lost during transfer */
+ I2C_STATUS_BUSERR, /**< Bus error in I2C transfer */
+ I2C_STATUS_BUSY, /**< I2C is busy doing transfer */
+ I2C_STATUS_SLAVENAK,/**< NAK received after SLA+W or SLA+R */
+} I2C_STATUS_T;
+
+/**
+ * @brief Master transfer data structure definitions
+ */
+typedef struct {
+ uint8_t slaveAddr; /**< 7-bit I2C Slave address */
+ const uint8_t *txBuff; /**< Pointer to array of bytes to be transmitted */
+ int txSz; /**< Number of bytes in transmit array,
+ if 0 only receive transfer will be carried on */
+ uint8_t *rxBuff; /**< Pointer memory where bytes received from I2C be stored */
+ int rxSz; /**< Number of bytes to received,
+ if 0 only transmission we be carried on */
+ I2C_STATUS_T status; /**< Status of the current I2C transfer */
+} I2C_XFER_T;
+
+/**
+ * @brief I2C interface IDs
+ * @note
+ * All Chip functions will take this as the first parameter,
+ * I2C_NUM_INTERFACE must never be used for calling any Chip
+ * functions, it is only used to find the number of interfaces
+ * available in the Chip.
+ */
+typedef enum I2C_ID {
+ I2C0, /**< ID I2C0 */
+ I2C1, /**< ID I2C1 */
+ I2C_NUM_INTERFACE /**< Number of I2C interfaces in the chip */
+} I2C_ID_T;
+
+/**
+ * @brief I2C master events
+ */
+typedef enum {
+ I2C_EVENT_WAIT = 1, /**< I2C Wait event */
+ I2C_EVENT_DONE, /**< Done event that wakes up Wait event */
+ I2C_EVENT_LOCK, /**< Re-entrency lock event for I2C transfer */
+ I2C_EVENT_UNLOCK, /**< Re-entrency unlock event for I2C transfer */
+ I2C_EVENT_SLAVE_RX, /**< Slave receive event */
+ I2C_EVENT_SLAVE_TX, /**< Slave transmit event */
+} I2C_EVENT_T;
+
+/**
+ * @brief Event handler function type
+ */
+typedef void (*I2C_EVENTHANDLER_T)(I2C_ID_T, I2C_EVENT_T);
+
+/**
+ * @brief Initializes the LPC_I2C peripheral with specified parameter.
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @return Nothing
+ */
+void Chip_I2C_Init(I2C_ID_T id);
+
+/**
+ * @brief De-initializes the I2C peripheral registers to their default reset values
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @return Nothing
+ */
+void Chip_I2C_DeInit(I2C_ID_T id);
+
+/**
+ * @brief Set up clock rate for LPC_I2C peripheral.
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @param clockrate : Target clock rate value to initialized I2C peripheral (Hz)
+ * @return Nothing
+ * @note
+ * Parameter @a clockrate for I2C0 should be from 1000 up to 1000000
+ * (1 KHz to 1 MHz), as I2C0 support Fast Mode Plus. If the @a clockrate
+ * is more than 400 KHz (Fast Plus Mode) Board_I2C_EnableFastPlus()
+ * must be called prior to calling this function.
+ */
+void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate);
+
+/**
+ * @brief Get current clock rate for LPC_I2C peripheral.
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @return The current I2C peripheral clock rate
+ */
+uint32_t Chip_I2C_GetClockRate(I2C_ID_T id);
+
+/**
+ * @brief Transmit and Receive data in master mode
+ * @param id : I2C peripheral selected (I2C0, I2C1 etc)
+ * @param xfer : Pointer to a I2C_XFER_T structure see notes below
+ * @return
+ * Any of #I2C_STATUS_T values, xfer->txSz will have number of bytes
+ * not sent due to error, xfer->rxSz will have the number of bytes yet
+ * to be received.
+ * @note
+ * The parameter @a xfer should have its member @a slaveAddr initialized
+ * to the 7-Bit slave address to which the master will do the xfer, Bit0
+ * to bit6 should have the address and Bit8 is ignored. During the transfer
+ * no code (like event handler) must change the content of the memory
+ * pointed to by @a xfer. The member of @a xfer, @a txBuff and @a txSz be
+ * initialized to the memory from which the I2C must pick the data to be
+ * transfered to slave and the number of bytes to send respectively, similarly
+ * @a rxBuff and @a rxSz must have pointer to memroy where data received
+ * from slave be stored and the number of data to get from slave respectilvely.
+ */
+int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer);
+
+/**
+ * @brief Transmit data to I2C slave using I2C Master mode
+ * @param id : I2C peripheral ID (I2C0, I2C1 .. etc)
+ * @param slaveAddr : Slave address to which the data be written
+ * @param buff : Pointer to buffer having the array of data
+ * @param len : Number of bytes to be transfered from @a buff
+ * @return Number of bytes successfully transfered
+ */
+int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len);
+
+/**
+ * @brief Transfer a command to slave and receive data from slave after a repeated start
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @param slaveAddr : Slave address of the I2C device
+ * @param cmd : Command (Address/Register) to be written
+ * @param buff : Pointer to memory that will hold the data received
+ * @param len : Number of bytes to receive
+ * @return Number of bytes successfully received
+ */
+int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len);
+
+/**
+ * @brief Get pointer to current function handling the events
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @return Pointer to function handing events of I2C
+ */
+I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id);
+
+/**
+ * @brief Set function that must handle I2C events
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @param event : Pointer to function that will handle the event (Should not be NULL)
+ * @return 1 when successful, 0 when a transfer is on going with its own event handler
+ */
+int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event);
+
+/**
+ * @brief Set function that must handle I2C events
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @param slaveAddr : Slave address from which data be read
+ * @param buff : Pointer to memory where data read be stored
+ * @param len : Number of bytes to read from slave
+ * @return Number of bytes read successfully
+ */
+int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len);
+
+/**
+ * @brief Default event handler for polling operation
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @param event : Event ID of the event that called the function
+ * @return Nothing
+ */
+void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event);
+
+/**
+ * @brief Default event handler for interrupt base operation
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @param event : Event ID of the event that called the function
+ * @return Nothing
+ */
+void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event);
+
+/**
+ * @brief I2C Master transfer state change handler
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @return Nothing
+ * @note Usually called from the appropriate Interrupt handler
+ */
+void Chip_I2C_MasterStateHandler(I2C_ID_T id);
+
+/**
+ * @brief Disable I2C peripheral's operation
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @return Nothing
+ */
+void Chip_I2C_Disable(I2C_ID_T id);
+
+/**
+ * @brief Checks if master xfer in progress
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @return 1 if master xfer in progress 0 otherwise
+ * @note
+ * This API is generally used in interrupt handler
+ * of the application to decide whether to call
+ * master state handler or to call slave state handler
+ */
+int Chip_I2C_IsMasterActive(I2C_ID_T id);
+
+/**
+ * @brief Setup a slave I2C device
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @param sid : I2C Slave peripheral ID (I2C_SLAVE_0, I2C_SLAVE_1 etc)
+ * @param xfer : Pointer to transfer structure (see note below for more info)
+ * @param event : Event handler for slave transfers
+ * @param addrMask : Address mask to use along with slave address (see notes below for more info)
+ * @return Nothing
+ * @note
+ * Parameter @a xfer should point to a valid I2C_XFER_T structure object
+ * and must have @a slaveAddr initialized with 7bit Slave address (From Bit1 to Bit7),
+ * Bit0 when set enables general call handling, @a slaveAddr along with @a addrMask will
+ * be used to match the slave address. @a rxBuff and @a txBuff must point to valid buffers
+ * where slave can receive or send the data from, size of which will be provided by
+ * @a rxSz and @a txSz respectively. Function pointed to by @a event will be called
+ * for the following events #I2C_EVENT_SLAVE_RX (One byte of data received successfully
+ * from the master and stored inside memory pointed by xfer->rxBuff, incremented
+ * the pointer and decremented the @a xfer->rxSz), #I2C_EVENT_SLAVE_TX (One byte of
+ * data from xfer->txBuff was sent to master successfully, incremented the pointer
+ * and decremented xfer->txSz), #I2C_EVENT_DONE (Master is done doing its transfers
+ * with the slave).
+ * Bit-0 of the parameter @a addrMask is reserved and should always be 0. Any bit (BIT1
+ * to BIT7) set in @a addrMask will make the corresponding bit in *xfer->slaveAddr* as
+ * don't care. Thit is, if *xfer->slaveAddr* is (0x10 << 1) and @a addrMask is (0x03 << 1) then
+ * 0x10, 0x11, 0x12, 0x13 will all be considered as valid slave addresses for the registered
+ * slave. Upon receving any event *xfer->slaveAddr* (BIT1 to BIT7) will hold the actual
+ * address which was received from master.
+ * General Call Handling
+ * Slave can receive data from master using general call address (0x00). General call
+ * handling must be setup as given below
+ * - Call Chip_I2C_SlaveSetup() with argument @a sid as I2C_SLAVE_GENERAL
+ * - xfer->slaveAddr ignored, argument @a addrMask ignored
+ * - function provided by @a event will registered to be called when slave received data using addr 0x00
+ * - xfer->rxBuff and xfer->rxSz should be valid in argument @a xfer
+ * - To handle General Call only (No other slaves are configured)
+ * - Call Chip_I2C_SlaveSetup() with sid as I2C_SLAVE_X (X=0,1,2,3)
+ * - setup @a xfer with slaveAddr member set to 0, @a event is ignored hence can be NULL
+ * - provide @a addrMask (typically 0, if not you better be knowing what you are doing)
+ * - To handler General Call when other slave is active
+ * - Call Chip_I2C_SlaveSetup() with sid as I2C_SLAVE_X (X=0,1,2,3)
+ * - setup @a xfer with slaveAddr member set to 7-Bit Slave address [from Bit1 to 7]
+ * - Set Bit0 of @a xfer->slaveAddr as 1
+ * - Provide appropriate @a addrMask
+ * - Argument @a event must point to function, that handles events from actual slaveAddress and not the GC
+ * @warning
+ * If the slave has only one byte in its txBuff, once that byte is transfered to master the event handler
+ * will be called for event #I2C_EVENT_DONE. If the master attempts to read more bytes in the same transfer
+ * then the slave hardware will send 0xFF to master till the end of transfer, event handler will not be
+ * called to notify this. For more info see section below
+ * Last data handling in slave
+ * If the user wants to implement a slave which will read a byte from a specific location over and over
+ * again whenever master reads the slave. If the user initializes the xfer->txBuff as the location to read
+ * the byte from and xfer->txSz as 1, then say, if master reads one byte; slave will send the byte read from
+ * xfer->txBuff and will call the event handler with #I2C_EVENT_DONE. If the master attempts to read another
+ * byte instead of sending the byte read from xfer->txBuff the slave hardware will send 0xFF and no event will
+ * occur. To handle this issue, slave should set xfer->txSz to 2, in which case when master reads the byte
+ * event handler will be called with #I2C_EVENT_SLAVE_TX, in which the slave implementation can reset the buffer
+ * and size back to original location (i.e, xfer->txBuff--, xfer->txSz++), if the master reads another byte
+ * in the same transfer, byte read from xfer->txBuff will be sent and #I2C_EVENT_SLAVE_TX will be called again, and
+ * the process repeats.
+ */
+void Chip_I2C_SlaveSetup(I2C_ID_T id,
+ I2C_SLAVE_ID sid,
+ I2C_XFER_T *xfer,
+ I2C_EVENTHANDLER_T event,
+ uint8_t addrMask);
+
+/**
+ * @brief I2C Slave event handler
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @return Nothing
+ */
+void Chip_I2C_SlaveStateHandler(I2C_ID_T id);
+
+/**
+ * @brief I2C peripheral state change checking
+ * @param id : I2C peripheral ID (I2C0, I2C1 ... etc)
+ * @return 1 if I2C peripheral @a id has changed its state,
+ * 0 if there is no state change
+ * @note
+ * This function must be used by the application when
+ * the polling has to be done based on state change.
+ */
+int Chip_I2C_IsStateChanged(I2C_ID_T id);
+
+/**
+ * @}
+ */
+
+ #ifdef __cplusplus
+}
+#endif
+
+#endif /* __I2C_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/i2c_common_11u6x.h b/source/lpc_chip_11u6x/inc/i2c_common_11u6x.h
new file mode 100644
index 0000000..36a2a1b
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/i2c_common_11u6x.h
@@ -0,0 +1,200 @@
+/*
+ * @brief LPC11u6x I2C driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __I2C_COMMON_11U6X_H_
+#define __I2C_COMMON_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup I2C_11U6X CHIP: LPC11u6x I2C driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief I2C register block structure
+ */
+typedef struct { /* I2C0 Structure */
+ __IO uint32_t CONSET; /*!< I2C Control Set Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is set. Writing a zero has no effect on the corresponding bit in the I2C control register. */
+ __I uint32_t STAT; /*!< I2C Status Register. During I2C operation, this register provides detailed status codes that allow software to determine the next action needed. */
+ __IO uint32_t DAT; /*!< I2C Data Register. During master or slave transmit mode, data to be transmitted is written to this register. During master or slave receive mode, data that has been received may be read from this register. */
+ __IO uint32_t ADR0; /*!< I2C Slave Address Register 0. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */
+ __IO uint32_t SCLH; /*!< SCH Duty Cycle Register High Half Word. Determines the high time of the I2C clock. */
+ __IO uint32_t SCLL; /*!< SCL Duty Cycle Register Low Half Word. Determines the low time of the I2C clock. SCLL and SCLH together determine the clock frequency generated by an I2C master and certain times used in slave mode. */
+ __O uint32_t CONCLR; /*!< I2C Control Clear Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is cleared. Writing a zero has no effect on the corresponding bit in the I2C control register. */
+ __IO uint32_t MMCTRL; /*!< Monitor mode control register. */
+ __IO uint32_t ADR1; /*!< I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */
+ __IO uint32_t ADR2; /*!< I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */
+ __IO uint32_t ADR3; /*!< I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */
+ __I uint32_t DATA_BUFFER; /*!< Data buffer register. The contents of the 8 MSBs of the DAT shift register will be transferred to the DATA_BUFFER automatically after every nine bits (8 bits of data plus ACK or NACK) has been received on the bus. */
+ __IO uint32_t MASK[4]; /*!< I2C Slave address mask register */
+} LPC_I2C_T;
+
+/*
+ * @brief I2C Control Set register description
+ */
+#define I2C_I2CONSET_AA ((0x04))/*!< Assert acknowledge flag */
+#define I2C_I2CONSET_SI ((0x08))/*!< I2C interrupt flag */
+#define I2C_I2CONSET_STO ((0x10))/*!< STOP flag */
+#define I2C_I2CONSET_STA ((0x20))/*!< START flag */
+#define I2C_I2CONSET_I2EN ((0x40))/*!< I2C interface enable */
+
+/*
+ * @brief I2C Control Clear register description
+ */
+#define I2C_I2CONCLR_AAC ((1 << 2)) /*!< Assert acknowledge Clear bit */
+#define I2C_I2CONCLR_SIC ((1 << 3)) /*!< I2C interrupt Clear bit */
+#define I2C_I2CONCLR_STOC ((1 << 4)) /*!< I2C STOP Clear bit */
+#define I2C_I2CONCLR_STAC ((1 << 5)) /*!< START flag Clear bit */
+#define I2C_I2CONCLR_I2ENC ((1 << 6)) /*!< I2C interface Disable bit */
+
+/*
+ * @brief I2C Common Control register description
+ */
+#define I2C_CON_AA (1UL << 2) /*!< Assert acknowledge bit */
+#define I2C_CON_SI (1UL << 3) /*!< I2C interrupt bit */
+#define I2C_CON_STO (1UL << 4) /*!< I2C STOP bit */
+#define I2C_CON_STA (1UL << 5) /*!< START flag bit */
+#define I2C_CON_I2EN (1UL << 6) /*!< I2C interface bit */
+
+/*
+ * @brief I2C Status Code definition (I2C Status register)
+ */
+#define I2C_STAT_CODE_BITMASK ((0xF8))/*!< Return Code mask in I2C status register */
+#define I2C_STAT_CODE_ERROR ((0xFF))/*!< Return Code error mask in I2C status register */
+
+/*
+ * @brief I2C Master transmit mode
+ */
+#define I2C_I2STAT_M_TX_START ((0x08))/*!< A start condition has been transmitted */
+#define I2C_I2STAT_M_TX_RESTART ((0x10))/*!< A repeat start condition has been transmitted */
+#define I2C_I2STAT_M_TX_SLAW_ACK ((0x18))/*!< SLA+W has been transmitted, ACK has been received */
+#define I2C_I2STAT_M_TX_SLAW_NACK ((0x20))/*!< SLA+W has been transmitted, NACK has been received */
+#define I2C_I2STAT_M_TX_DAT_ACK ((0x28))/*!< Data has been transmitted, ACK has been received */
+#define I2C_I2STAT_M_TX_DAT_NACK ((0x30))/*!< Data has been transmitted, NACK has been received */
+#define I2C_I2STAT_M_TX_ARB_LOST ((0x38))/*!< Arbitration lost in SLA+R/W or Data bytes */
+
+/*
+ * @brief I2C Master receive mode
+ */
+#define I2C_I2STAT_M_RX_START ((0x08))/*!< A start condition has been transmitted */
+#define I2C_I2STAT_M_RX_RESTART ((0x10))/*!< A repeat start condition has been transmitted */
+#define I2C_I2STAT_M_RX_ARB_LOST ((0x38))/*!< Arbitration lost */
+#define I2C_I2STAT_M_RX_SLAR_ACK ((0x40))/*!< SLA+R has been transmitted, ACK has been received */
+#define I2C_I2STAT_M_RX_SLAR_NACK ((0x48))/*!< SLA+R has been transmitted, NACK has been received */
+#define I2C_I2STAT_M_RX_DAT_ACK ((0x50))/*!< Data has been received, ACK has been returned */
+#define I2C_I2STAT_M_RX_DAT_NACK ((0x58))/*!< Data has been received, NACK has been returned */
+
+/*
+ * @brief I2C Slave receive mode
+ */
+#define I2C_I2STAT_S_RX_SLAW_ACK ((0x60))/*!< Own slave address has been received, ACK has been returned */
+#define I2C_I2STAT_S_RX_ARB_LOST_M_SLA ((0x68))/*!< Arbitration lost in SLA+R/W as master */
+// #define I2C_I2STAT_S_RX_SLAW_ACK ((0x68)) /*!< Own SLA+W has been received, ACK returned */
+#define I2C_I2STAT_S_RX_GENCALL_ACK ((0x70))/*!< General call address has been received, ACK has been returned */
+#define I2C_I2STAT_S_RX_ARB_LOST_M_GENCALL ((0x78))/*!< Arbitration lost in SLA+R/W (GENERAL CALL) as master */
+// #define I2C_I2STAT_S_RX_GENCALL_ACK ((0x78)) /*!< General call address has been received, ACK has been returned */
+#define I2C_I2STAT_S_RX_PRE_SLA_DAT_ACK ((0x80))/*!< Previously addressed with own SLA; Data has been received, ACK has been returned */
+#define I2C_I2STAT_S_RX_PRE_SLA_DAT_NACK ((0x88))/*!< Previously addressed with own SLA;Data has been received and NOT ACK has been returned */
+#define I2C_I2STAT_S_RX_PRE_GENCALL_DAT_ACK ((0x90))/*!< Previously addressed with General Call; Data has been received and ACK has been returned */
+#define I2C_I2STAT_S_RX_PRE_GENCALL_DAT_NACK ((0x98))/*!< Previously addressed with General Call; Data has been received and NOT ACK has been returned */
+#define I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX ((0xA0))/*!< A STOP condition or repeated START condition has been received while still addressed as SLV/REC (Slave Receive) or
+ SLV/TRX (Slave Transmit) */
+
+/*
+ * @brief I2C Slave transmit mode
+ */
+#define I2C_I2STAT_S_TX_SLAR_ACK ((0xA8))/*!< Own SLA+R has been received, ACK has been returned */
+#define I2C_I2STAT_S_TX_ARB_LOST_M_SLA ((0xB0))/*!< Arbitration lost in SLA+R/W as master */
+// #define I2C_I2STAT_S_TX_SLAR_ACK ((0xB0)) /*!< Own SLA+R has been received, ACK has been returned */
+#define I2C_I2STAT_S_TX_DAT_ACK ((0xB8))/*!< Data has been transmitted, ACK has been received */
+#define I2C_I2STAT_S_TX_DAT_NACK ((0xC0))/*!< Data has been transmitted, NACK has been received */
+#define I2C_I2STAT_S_TX_LAST_DAT_ACK ((0xC8))/*!< Last data byte in I2DAT has been transmitted (AA = 0); ACK has been received */
+#define I2C_SLAVE_TIME_OUT 0x10000000UL/*!< Time out in case of using I2C slave mode */
+
+/*
+ * @brief I2C Data register definition
+ */
+#define I2C_I2DAT_BITMASK ((0xFF))/*!< Mask for I2DAT register */
+#define I2C_I2DAT_IDLE_CHAR (0xFF) /*!< Idle data value will be send out in slave mode in case of the actual expecting data requested from the master is greater than
+ its sending data length that can be supported */
+
+/*
+ * @brief I2C Monitor mode control register description
+ */
+#define I2C_I2MMCTRL_MM_ENA ((1 << 0)) /**< Monitor mode enable */
+#define I2C_I2MMCTRL_ENA_SCL ((1 << 1)) /**< SCL output enable */
+#define I2C_I2MMCTRL_MATCH_ALL ((1 << 2)) /**< Select interrupt register match */
+#define I2C_I2MMCTRL_BITMASK ((0x07)) /**< Mask for I2MMCTRL register */
+
+/*
+ * @brief I2C Data buffer register description
+ */
+#define I2DATA_BUFFER_BITMASK ((0xFF))/*!< I2C Data buffer register bit mask */
+
+/*
+ * @brief I2C Slave Address registers definition
+ */
+#define I2C_I2ADR_GC ((1 << 0)) /*!< General Call enable bit */
+#define I2C_I2ADR_BITMASK ((0xFF))/*!< I2C Slave Address registers bit mask */
+
+/*
+ * @brief I2C Mask Register definition
+ */
+#define I2C_I2MASK_MASK(n) ((n & 0xFE))/*!< I2C Mask Register mask field */
+
+/*
+ * @brief I2C SCL HIGH duty cycle Register definition
+ */
+#define I2C_I2SCLH_BITMASK ((0xFFFF)) /*!< I2C SCL HIGH duty cycle Register bit mask */
+
+/*
+ * @brief I2C SCL LOW duty cycle Register definition
+ */
+#define I2C_I2SCLL_BITMASK ((0xFFFF)) /*!< I2C SCL LOW duty cycle Register bit mask */
+
+/*
+ * @brief I2C monitor control configuration defines
+ */
+#define I2C_MONITOR_CFG_SCL_OUTPUT I2C_I2MMCTRL_ENA_SCL /**< SCL output enable */
+#define I2C_MONITOR_CFG_MATCHALL I2C_I2MMCTRL_MATCH_ALL /**< Select interrupt register match */
+
+/**
+ * @}
+ */
+
+ #ifdef __cplusplus
+}
+#endif
+
+#endif /* __I2C_COMMON_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/i2cm_11u6x.h b/source/lpc_chip_11u6x/inc/i2cm_11u6x.h
new file mode 100644
index 0000000..4b3d0e7
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/i2cm_11u6x.h
@@ -0,0 +1,418 @@
+/*
+ * @brief LPC11u6x I2C driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __I2CM_11U6X_H_
+#define __I2CM_11U6X_H_
+
+#include "i2c_common_11u6x.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup I2CM_11U6X CHIP: LPC11u6x I2C master-only driver
+ * @ingroup I2C_11U6X
+ * This driver only works in master mode. To describe the I2C transactions
+ * following symbols are used in driver documentation.
+ *
+ * Key to symbols
+ * ==============
+ * S (1 bit) : Start bit
+ * P (1 bit) : Stop bit
+ * Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.
+ * A, NA (1 bit) : Acknowledge and Not-Acknowledge bit.
+ * Addr (7 bits): I2C 7 bit address. Note that this can be expanded as usual to
+ * get a 10 bit I2C address.
+ * Data (8 bits): A plain data byte. Sometimes, I write DataLow, DataHigh
+ * for 16 bit data.
+ * [..]: Data sent by I2C device, as opposed to data sent by the host adapter.
+ * @{
+ */
+
+/** I2CM_11U6X_OPTIONS_TYPES I2C master transfer options
+ * @{
+ */
+
+/** Ignore NACK during data transfer. By default transfer is aborted. */
+#define I2CM_XFER_OPTION_IGNORE_NACK 0x01
+/** ACK last byte received. By default we NACK last byte we receive per I2C spec. */
+#define I2CM_XFER_OPTION_LAST_RX_ACK 0x02
+
+/**
+ * @}
+ */
+
+/** I2CM_11U6X_STATUS_TYPES I2C master transfer status types
+ * @{
+ */
+
+#define I2CM_STATUS_OK 0x00 /*!< Requested Request was executed successfully. */
+#define I2CM_STATUS_ERROR 0x01 /*!< Unknown error condition. */
+#define I2CM_STATUS_NAK 0x02 /*!< No acknowledgement received from slave. */
+#define I2CM_STATUS_BUS_ERROR 0x03 /*!< I2C bus error */
+#define I2CM_STATUS_SLAVE_NAK 0x04 /*!< No device responded for given slave address during SLA+W or SLA+R */
+#define I2CM_STATUS_ARBLOST 0x05 /*!< Arbitration lost. */
+#define I2CM_STATUS_BUSY 0xFF /*!< I2C transmistter is busy. */
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Master transfer data structure definitions
+ */
+typedef struct {
+ uint8_t slaveAddr; /*!< 7-bit I2C Slave address */
+ uint8_t options; /*!< Options for transfer*/
+ uint16_t status; /*!< Status of the current I2C transfer */
+ uint16_t txSz; /*!< Number of bytes in transmit array,
+ if 0 only receive transfer will be carried on */
+ uint16_t rxSz; /*!< Number of bytes to received,
+ if 0 only transmission we be carried on */
+ const uint8_t *txBuff; /*!< Pointer to array of bytes to be transmitted */
+ uint8_t *rxBuff; /*!< Pointer memory where bytes received from I2C be stored */
+} I2CM_XFER_T;
+
+/**
+ * @brief Initialize I2C Interface
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Nothing
+ * @note This function enables the I2C clock.
+ */
+void Chip_I2CM_Init(LPC_I2C_T *pI2C);
+
+/**
+ * @brief Shutdown I2C Interface
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Nothing
+ * @note This function disables the I2C clock.
+ */
+void Chip_I2CM_DeInit(LPC_I2C_T *pI2C);
+
+/**
+ * @brief Sets HIGH and LOW duty cycle registers
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @param sclH : Number of I2C_PCLK cycles for the SCL HIGH time.
+ * @param sclL : Number of I2C_PCLK cycles for the SCL LOW time.
+ * @return Nothing
+ * @note The frequency is determined by the following formula (I2C_PCLK
+ * is the frequency of the peripheral I2C clock):
+ * I2C_bitFrequency = (I2C_PCLK)/(sclH + sclL);
+ */
+static INLINE void Chip_I2CM_SetDutyCycle(LPC_I2C_T *pI2C, uint16_t sclH, uint16_t sclL)
+{
+ pI2C->SCLH = (uint32_t) sclH;
+ pI2C->SCLL = (uint32_t) sclL;
+}
+
+/**
+ * @brief Set up bus speed for LPC_I2C controller
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @param busSpeed : I2C bus clock rate
+ * @return Nothing
+ * @note Per I2C specification the busSpeed should be
+ * @li 100000 for Standard mode
+ * @li 400000 for Fast mode
+ * @li 1000000 for Fast mode plus
+ * IOCON registers corresponding to I2C pads should be updated
+ * according to the bus mode.
+ */
+void Chip_I2CM_SetBusSpeed(LPC_I2C_T *pI2C, uint32_t busSpeed);
+
+/**
+ * @brief Transmit START or Repeat-START signal on I2C bus
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Nothing
+ * @note This function sets the controller to transmit START condition when
+ * the bus becomes free.
+ */
+static INLINE void Chip_I2CM_SendStart(LPC_I2C_T *pI2C)
+{
+ pI2C->CONSET = I2C_CON_I2EN | I2C_CON_STA;
+}
+
+/**
+ * @brief Reset I2C controller state
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Nothing
+ * @note This function clears all control/status flags.
+ */
+static INLINE void Chip_I2CM_ResetControl(LPC_I2C_T *pI2C)
+{
+ /* Reset STA, STO, SI */
+ pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA;
+
+}
+
+/**
+ * @brief Transmit a single data byte through the I2C peripheral
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @param data : Byte to transmit
+ * @return Nothing
+ * @note This function attempts to place a byte into the UART transmit
+ * FIFO or transmit hold register regard regardless of UART state
+ *
+ */
+static INLINE void Chip_I2CM_WriteByte(LPC_I2C_T *pI2C, uint8_t data)
+{
+ pI2C->DAT = (uint32_t) data;
+}
+
+/**
+ * @brief Read a single byte data from the I2C peripheral
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return A single byte of data read
+ * @note This function reads a byte from the I2C receive hold register
+ * regardless of I2C state. The I2C status should be read first prior
+ * to using this function.
+ */
+static INLINE uint8_t Chip_I2CM_ReadByte(LPC_I2C_T *pI2C)
+{
+ return (uint8_t) (pI2C->DAT & I2C_I2DAT_BITMASK);
+}
+
+/**
+ * @brief Generate NACK after receiving next byte
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Nothing
+ * @note This function sets the controller to NACK after receiving next
+ * byte from slave transmitter. Used before receiving last byte.
+ */
+static INLINE void Chip_I2CM_NackNextByte(LPC_I2C_T *pI2C)
+{
+ pI2C->CONCLR = I2C_CON_AA;
+}
+
+/**
+ * @brief Transmit STOP signal on I2C bus
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Nothing
+ * @note This function sets the controller to transmit STOP condition.
+ */
+static INLINE void Chip_I2CM_SendStop(LPC_I2C_T *pI2C)
+{
+ pI2C->CONSET = I2C_CON_STO;
+}
+
+/**
+ * @brief Force start I2C transmit
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Nothing
+ * @note This function force I2C state machine to start transmitting.
+ * If an uncontrolled source generates a superfluous START or masks
+ * a STOP condition, then the I2C-bus stays busy indefinitely. If
+ * the STA flag is set and bus access is not obtained within a
+ * reasonable amount of time, then a forced access to the I2C-bus is
+ * possible. This is achieved by setting the STO flag while the STA
+ * flag is still set. No STOP condition is transmitted.
+ */
+static INLINE void Chip_I2CM_ForceStart(LPC_I2C_T *pI2C)
+{
+ /* check if we are pending on start */
+ if (pI2C->CONSET & I2C_CON_STA) {
+ pI2C->CONSET = I2C_CON_STO;
+ }
+ else {
+ Chip_I2CM_SendStart(pI2C);
+ }
+}
+
+/**
+ * @brief Transmit STOP+START signal on I2C bus
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Nothing
+ * @note This function sets the controller to transmit STOP condition
+ * followed by a START condition.
+ */
+static INLINE void Chip_I2CM_SendStartAfterStop(LPC_I2C_T *pI2C)
+{
+ pI2C->CONSET = I2C_CON_STO | I2C_CON_STA;
+}
+
+/**
+ * @brief Check if I2C controller state changed
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Returns 0 if state didn't change
+ * @note
+ */
+static INLINE uint32_t Chip_I2CM_StateChanged(LPC_I2C_T *pI2C)
+{
+ return pI2C->CONSET & I2C_CON_SI;
+}
+
+/**
+ * @brief Clear state change interrupt flag
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Nothing
+ * @note
+ */
+static INLINE void Chip_I2CM_ClearSI(LPC_I2C_T *pI2C)
+{
+ pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA;
+}
+
+/**
+ * @brief Check if I2C bus is free per our controller
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Returns 0 if busy else a non-zero value.
+ * @note I2C controller clears STO bit when it sees STOP
+ * condition after a START condition on the bus.
+ */
+static INLINE uint32_t Chip_I2CM_BusFree(LPC_I2C_T *pI2C)
+{
+ return !(pI2C->CONSET & I2C_CON_STO);
+}
+
+/**
+ * @brief Get current state of the I2C controller
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Returns 0 if busy else a non-zero value.
+ * @note I2C controller clears STO bit when it sees STOP
+ * condition after a START condition on the bus.
+ */
+static INLINE uint32_t Chip_I2CM_GetCurState(LPC_I2C_T *pI2C)
+{
+ return pI2C->STAT & I2C_STAT_CODE_BITMASK;
+}
+
+/**
+ * @brief Disable I2C interface
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @return Nothing
+ * @note
+ */
+static INLINE void Chip_I2CM_Disable(LPC_I2C_T *pI2C)
+{
+ pI2C->CONCLR = I2C_CON_I2EN;
+}
+
+/**
+ * @brief Transfer state change handler handler
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @param xfer : Pointer to a I2CM_XFER_T structure see notes below
+ * @return Returns non-zero value on completion of transfer. The @a status
+ * member of @a xfer structure contains the current status of the
+ * transfer at the end of the call.
+ * @note
+ * The parameter @a xfer should be same as the one passed to Chip_I2CM_Xfer()
+ * routine.
+ */
+uint32_t Chip_I2CM_XferHandler(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer);
+
+/**
+ * @brief Transmit and Receive data in master mode
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @param xfer : Pointer to a I2CM_XFER_T structure see notes below
+ * @return Nothing.
+ * @note
+ * The parameter @a xfer should have its member @a slaveAddr initialized
+ * to the 7-Bit slave address to which the master will do the xfer, Bit0
+ * to bit6 should have the address and Bit8 is ignored. During the transfer
+ * no code (like event handler) must change the content of the memory
+ * pointed to by @a xfer. The member of @a xfer, @a txBuff and @a txSz be
+ * initialized to the memory from which the I2C must pick the data to be
+ * transfered to slave and the number of bytes to send respectively, similarly
+ * @a rxBuff and @a rxSz must have pointer to memroy where data received
+ * from slave be stored and the number of data to get from slave respectilvely.
+ * Following types of transfers are possible:
+ * - Write-only transfer: When @a rxSz member of @a xfer is set to 0.
+ *
+ * S Addr Wr [A] txBuff0 [A] txBuff1 [A] ... txBuffN [A] P
+ *
+ * - If I2CM_XFER_OPTION_IGNORE_NACK is set in @a options memeber
+ *
+ * S Addr Wr [A] txBuff0 [A or NA] ... txBuffN [A or NA] P
+ *
+ * - Read-only transfer: When @a txSz member of @a xfer is set to 0.
+ *
+ * S Addr Rd [A] [rxBuff0] A [rxBuff1] A ... [rxBuffN] NA P
+ *
+ * - If I2CM_XFER_OPTION_LAST_RX_ACK is set in @a options memeber
+ *
+ * S Addr Rd [A] [rxBuff0] A [rxBuff1] A ... [rxBuffN] A P
+ *
+ * - Read-Write transfer: When @a rxSz and @ txSz members of @a xfer are non-zero.
+ *
+ * S Addr Wr [A] txBuff0 [A] txBuff1 [A] ... txBuffN [A]
+ * S Addr Rd [A] [rxBuff0] A [rxBuff1] A ... [rxBuffN] NA P
+ *
+ */
+void Chip_I2CM_Xfer(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer);
+
+/**
+ * @brief Transmit and Receive data in master mode
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @param xfer : Pointer to a I2CM_XFER_T structure see notes below
+ * @return Returns non-zero value on succesful completion of transfer.
+ * @note
+ * This function operates same as Chip_I2CM_Xfer(), but is a blocking call.
+ */
+uint32_t Chip_I2CM_XferBlocking(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer);
+
+/**
+ * @brief Write given buffer of data to I2C interface
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @param buff : Pointer to buffer to be transmitted
+ * @param len : Length of the buffer
+ * @return Returns number of bytes written.
+ * @note This function is a blocking call. The function generates
+ * START/repeat-START condition on bus and starts transmitting
+ * data untill transfer finishes or a NACK is received. No
+ * STOP condition is transmitted on the bus.
+ *
+ * S Data0 [A] Data1 [A] ... DataN [A]
+ */
+uint32_t Chip_I2CM_Write(LPC_I2C_T *pI2C, const uint8_t *buff, uint32_t len);
+
+/**
+ * @brief Read data from I2C slave to given buffer
+ * @param pI2C : Pointer to selected I2C peripheral
+ * @param buff : Pointer to buffer for data received from I2C slave
+ * @param len : Length of the buffer
+ * @return Returns number of bytes read.
+ * @note This function is a blocking call. The function generates
+ * START/repeat-START condition on bus and starts reading
+ * data untill requested number of bytes are read. No
+ * STOP condition is transmitted on the bus.
+ *
+ * S [Data0] A [Data1] A ... [DataN] A
+ */
+uint32_t Chip_I2CM_Read(LPC_I2C_T *pI2C, uint8_t *buff, uint32_t len);
+
+/**
+ * @}
+ */
+
+ #ifdef __cplusplus
+}
+#endif
+
+#endif /* __I2C_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/iap.h b/source/lpc_chip_11u6x/inc/iap.h
new file mode 100644
index 0000000..e04ec83
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/iap.h
@@ -0,0 +1,91 @@
+/*
+ * @brief Common IAP support functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licenser disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __IAP_H_
+#define __IAP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup COMMON_IAP CHIP: Common Chip ISP/IAP commands and return codes
+ * @ingroup CHIP_Common
+ * @{
+ */
+
+/* IAP command definitions */
+#define IAP_PREWRRITE_CMD 50 /*!< Prepare sector for write operation command */
+#define IAP_WRISECTOR_CMD 51 /*!< Write Sector command */
+#define IAP_ERSSECTOR_CMD 52 /*!< Erase Sector command */
+#define IAP_BLANK_CHECK_SECTOR_CMD 53 /*!< Blank check sector */
+#define IAP_REPID_CMD 54 /*!< Read PartID command */
+#define IAP_READ_BOOT_CODE_CMD 55 /*!< Read Boot code version */
+#define IAP_COMPARE_CMD 56 /*!< Compare two RAM address locations */
+#define IAP_REINVOKE_ISP_CMD 57 /*!< Reinvoke ISP */
+#define IAP_READ_UID_CMD 58 /*!< Read UID */
+#define IAP_ERASE_PAGE_CMD 59 /*!< Erase page */
+#define IAP_EEPROM_WRITE 61 /*!< EEPROM Write command */
+#define IAP_EEPROM_READ 62 /*!< EEPROM READ command */
+
+/* IAP response definitions */
+#define IAP_CMD_SUCCESS 0 /*!< Command is executed successfully */
+#define IAP_INVALID_COMMAND 1 /*!< Invalid command */
+#define IAP_SRC_ADDR_ERROR 2 /*!< Source address is not on word boundary */
+#define IAP_DST_ADDR_ERROR 3 /*!< Destination address is not on a correct boundary */
+#define IAP_SRC_ADDR_NOT_MAPPED 4 /*!< Source address is not mapped in the memory map */
+#define IAP_DST_ADDR_NOT_MAPPED 5 /*!< Destination address is not mapped in the memory map */
+#define IAP_COUNT_ERROR 6 /*!< Byte count is not multiple of 4 or is not a permitted value */
+#define IAP_INVALID_SECTOR 7 /*!< Sector number is invalid or end sector number is greater than start sector number */
+#define IAP_SECTOR_NOT_BLANK 8 /*!< Sector is not blank */
+#define IAP_SECTOR_NOT_PREPARED 9 /*!< Command to prepare sector for write operation was not executed */
+#define IAP_COMPARE_ERROR 10 /*!< Source and destination data not equal */
+#define IAP_BUSY 11 /*!< Flash programming hardware interface is busy */
+#define IAP_PARAM_ERROR 12 /*!< nsufficient number of parameters or invalid parameter */
+#define IAP_ADDR_ERROR 13 /*!< Address is not on word boundary */
+#define IAP_ADDR_NOT_MAPPED 14 /*!< Address is not mapped in the memory map */
+#define IAP_CMD_LOCKED 15 /*!< Command is locked */
+#define IAP_INVALID_CODE 16 /*!< Unlock code is invalid */
+#define IAP_INVALID_BAUD_RATE 17 /*!< Invalid baud rate setting */
+#define IAP_INVALID_STOP_BIT 18 /*!< Invalid stop bit setting */
+#define IAP_CRP_ENABLED 19 /*!< Code read protection enabled */
+
+/* IAP_ENTRY API function type */
+typedef void (*IAP_ENTRY_T)(unsigned int[5], unsigned int[4]);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __IAP_H_ */
diff --git a/source/lpc_chip_11u6x/inc/iocon_11u6x.h b/source/lpc_chip_11u6x/inc/iocon_11u6x.h
new file mode 100644
index 0000000..2bc00de
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/iocon_11u6x.h
@@ -0,0 +1,139 @@
+/*
+ * @brief LPC11u6x IOCON driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __IOCON_11U6X_H_
+#define __IOCON_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup IOCON_11U6X CHIP: LPC11u6x IO Control driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief LPC11u6x IO Configuration Unit register block structure
+ */
+typedef struct { /*!< LPC11U6X IOCON Structure */
+ __IO uint32_t PIO0[24];
+ __IO uint32_t PIO1[32];
+ __I uint32_t reserved[4];
+ __IO uint32_t PIO2A[2];/* PIO2_0/1 only */
+ __I uint32_t reserved1[1];
+ __IO uint32_t PIO2B[22]; /* PIO2_2 to PIO_2_23 */
+} LPC_IOCON_T;
+
+/**
+ * @brief Array of IOCON pin definitions passed to Chip_IOCON_SetPinMuxing() must be in this format
+ */
+typedef struct {
+ uint32_t port : 8; /* Pin port */
+ uint32_t pin : 8; /* Pin number */
+ uint32_t modefunc : 16; /* Function and mode */
+} PINMUX_GRP_T;
+
+/**
+ * IOCON function and mode selection definitions
+ * See the User Manual for specific modes and functions supported by the
+ * various LPC11u6x pins.
+ */
+#define IOCON_FUNC0 0x0 /*!< Selects pin function 0 */
+#define IOCON_FUNC1 0x1 /*!< Selects pin function 1 */
+#define IOCON_FUNC2 0x2 /*!< Selects pin function 2 */
+#define IOCON_FUNC3 0x3 /*!< Selects pin function 3 */
+#define IOCON_FUNC4 0x4 /*!< Selects pin function 4 */
+#define IOCON_FUNC5 0x5 /*!< Selects pin function 5 */
+#define IOCON_FUNC6 0x6 /*!< Selects pin function 6 */
+#define IOCON_FUNC7 0x7 /*!< Selects pin function 7 */
+#define IOCON_MODE_INACT (0x0 << 3) /*!< No addition pin function */
+#define IOCON_MODE_PULLDOWN (0x1 << 3) /*!< Selects pull-down function */
+#define IOCON_MODE_PULLUP (0x2 << 3) /*!< Selects pull-up function */
+#define IOCON_MODE_REPEATER (0x3 << 3) /*!< Selects pin repeater function */
+#define IOCON_HYS_EN (0x1 << 5) /*!< Enables hysteresis */
+#define IOCON_INV_EN (0x1 << 6) /*!< Enables invert function on input */
+#define IOCON_ADMODE_EN (0x0 << 7) /*!< Enables analog input function (analog pins only) */
+#define IOCON_DIGMODE_EN (0x1 << 7) /*!< Enables digital function (analog pins only) */
+#define IOCON_SFI2C_EN (0x0 << 8) /*!< I2C standard mode/fast-mode */
+#define IOCON_STDI2C_EN (0x1 << 8) /*!< I2C standard I/O functionality */
+#define IOCON_FASTI2C_EN (0x2 << 8) /*!< I2C Fast-mode Plus */
+#define IOCON_FILT_DIS (0x1 << 8) /*!< Disables noise pulses filtering (10nS glitch filter) */
+#define IOCON_OPENDRAIN_EN (0x1 << 10) /*!< Enables open-drain function */
+#define IOCON_S_MODE_0CLK (0x0 << 11) /*!< Bypass input filter */
+#define IOCON_S_MODE_1CLK (0x1 << 11) /*!< Input pulses shorter than 1 filter clock are rejected */
+#define IOCON_S_MODE_2CLK (0x2 << 11) /*!< Input pulses shorter than 2 filter clock2 are rejected */
+#define IOCON_S_MODE_3CLK (0x3 << 11) /*!< Input pulses shorter than 3 filter clock2 are rejected */
+#define IOCON_S_MODE(clks) ((clks) << 11) /*!< Select clocks for digital input filter mode */
+#define IOCON_CLKDIV(div) ((div) << 13) /*!< Select peripheral clock divider for input filter sampling clock, 0 -6 */
+
+/**
+ * @brief Sets I/O Control pin mux
+ * @param pIOCON : The base of IOCON peripheral on the chip
+ * @param port : GPIO port to mux
+ * @param pin : GPIO pin to mux
+ * @param modefunc : OR'ed values or type IOCON_*
+ * @return Nothing
+ */
+void Chip_IOCON_PinMuxSet(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint32_t modefunc);
+
+/**
+ * @brief I/O Control pin mux
+ * @param pIOCON : The base of IOCON peripheral on the chip
+ * @param port : GPIO port to mux
+ * @param pin : GPIO pin to mux
+ * @param mode : OR'ed values or type IOCON_*
+ * @param func : Pin function, value of type IOCON_FUNC?
+ * @return Nothing
+ */
+STATIC INLINE void Chip_IOCON_PinMux(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint16_t mode, uint8_t func)
+{
+ Chip_IOCON_PinMuxSet(pIOCON, port, pin, (uint32_t) (mode | func));
+}
+
+/**
+ * @brief Set all I/O Control pin muxing
+ * @param pIOCON : The base of IOCON peripheral on the chip
+ * @param pinArray : Pointer to array of pin mux selections
+ * @param arrayLength : Number of entries in pinArray
+ * @return Nothing
+ */
+void Chip_IOCON_SetPinMuxing(LPC_IOCON_T *pIOCON, const PINMUX_GRP_T* pinArray, uint32_t arrayLength);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __IOCON_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/lpc_types.h b/source/lpc_chip_11u6x/inc/lpc_types.h
new file mode 100644
index 0000000..14c7b60
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/lpc_types.h
@@ -0,0 +1,216 @@
+/*
+ * @brief Common types used in LPC functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2012
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __LPC_TYPES_H_
+#define __LPC_TYPES_H_
+
+#include
+#include
+
+/** @defgroup LPC_Types CHIP: LPC Common Types
+ * @ingroup CHIP_Common
+ * @{
+ */
+
+/** @defgroup LPC_Types_Public_Types LPC Public Types
+ * @{
+ */
+
+/**
+ * @brief Boolean Type definition
+ */
+typedef enum {FALSE = 0, TRUE = !FALSE} Bool;
+
+/**
+ * @brief Boolean Type definition
+ */
+#if !defined(__cplusplus)
+// typedef enum {false = 0, true = !false} bool;
+#endif
+
+/**
+ * @brief Flag Status and Interrupt Flag Status type definition
+ */
+typedef enum {RESET = 0, SET = !RESET} FlagStatus, IntStatus, SetState;
+#define PARAM_SETSTATE(State) ((State == RESET) || (State == SET))
+
+/**
+ * @brief Functional State Definition
+ */
+typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
+#define PARAM_FUNCTIONALSTATE(State) ((State == DISABLE) || (State == ENABLE))
+
+/**
+ * @ Status type definition
+ */
+typedef enum {ERROR = 0, SUCCESS = !ERROR} Status;
+
+/**
+ * Read/Write transfer type mode (Block or non-block)
+ */
+typedef enum {
+ NONE_BLOCKING = 0, /**< None Blocking type */
+ BLOCKING, /**< Blocking type */
+} TRANSFER_BLOCK_T;
+
+/** Pointer to Function returning Void (any number of parameters) */
+typedef void (*PFV)();
+
+/** Pointer to Function returning int32_t (any number of parameters) */
+typedef int32_t (*PFI)();
+
+/**
+ * @}
+ */
+
+/** @defgroup LPC_Types_Public_Macros LPC Public Macros
+ * @{
+ */
+
+/* _BIT(n) sets the bit at position "n"
+ * _BIT(n) is intended to be used in "OR" and "AND" expressions:
+ * e.g., "(_BIT(3) | _BIT(7))".
+ */
+#undef _BIT
+/* Set bit macro */
+#define _BIT(n) (1 << (n))
+
+/* _SBF(f,v) sets the bit field starting at position "f" to value "v".
+ * _SBF(f,v) is intended to be used in "OR" and "AND" expressions:
+ * e.g., "((_SBF(5,7) | _SBF(12,0xF)) & 0xFFFF)"
+ */
+#undef _SBF
+/* Set bit field macro */
+#define _SBF(f, v) ((v) << (f))
+
+/* _BITMASK constructs a symbol with 'field_width' least significant
+ * bits set.
+ * e.g., _BITMASK(5) constructs '0x1F', _BITMASK(16) == 0xFFFF
+ * The symbol is intended to be used to limit the bit field width
+ * thusly:
+ * = (any_expression) & _BITMASK(x), where 0 < x <= 32.
+ * If "any_expression" results in a value that is larger than can be
+ * contained in 'x' bits, the bits above 'x - 1' are masked off. When
+ * used with the _SBF example above, the example would be written:
+ * a_reg = ((_SBF(5,7) | _SBF(12,0xF)) & _BITMASK(16))
+ * This ensures that the value written to a_reg is no wider than
+ * 16 bits, and makes the code easier to read and understand.
+ */
+#undef _BITMASK
+/* Bitmask creation macro */
+#define _BITMASK(field_width) ( _BIT(field_width) - 1)
+
+/* NULL pointer */
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+/* Number of elements in an array */
+#define NELEMENTS(array) (sizeof(array) / sizeof(array[0]))
+
+/* Static data/function define */
+#define STATIC static
+/* External data/function define */
+#define EXTERN extern
+
+#if !defined(MAX)
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+#if !defined(MIN)
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+/**
+ * @}
+ */
+
+/* Old Type Definition compatibility */
+/** @addtogroup LPC_Types_Public_Types
+ * @{
+ */
+
+/** LPC type for character type */
+typedef char CHAR;
+
+/** LPC type for 8 bit unsigned value */
+typedef uint8_t UNS_8;
+
+/** LPC type for 8 bit signed value */
+typedef int8_t INT_8;
+
+/** LPC type for 16 bit unsigned value */
+typedef uint16_t UNS_16;
+
+/** LPC type for 16 bit signed value */
+typedef int16_t INT_16;
+
+/** LPC type for 32 bit unsigned value */
+typedef uint32_t UNS_32;
+
+/** LPC type for 32 bit signed value */
+typedef int32_t INT_32;
+
+/** LPC type for 64 bit signed value */
+typedef int64_t INT_64;
+
+/** LPC type for 64 bit unsigned value */
+typedef uint64_t UNS_64;
+
+#ifdef __CODE_RED
+#define BOOL_32 bool
+#define BOOL_16 bool
+#define BOOL_8 bool
+#else
+/** 32 bit boolean type */
+typedef bool BOOL_32;
+
+/** 16 bit boolean type */
+typedef bool BOOL_16;
+
+/** 8 bit boolean type */
+typedef bool BOOL_8;
+#endif
+
+#ifdef __CC_ARM
+#define INLINE __inline
+#else
+#define INLINE inline
+#endif
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* __LPC_TYPES_H_ */
diff --git a/source/lpc_chip_11u6x/inc/pinint_11u6x.h b/source/lpc_chip_11u6x/inc/pinint_11u6x.h
new file mode 100644
index 0000000..660ba0e
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/pinint_11u6x.h
@@ -0,0 +1,358 @@
+/*
+ * @brief LPC11u6x Pin Interrupt and Pattern Match Registers and driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __PININT_11U6X_H_
+#define __PININT_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup PININT_11U6X CHIP: LPC11u6x Pin Interrupt and Pattern Match driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief LPC11u6x Pin Interrupt and Pattern Match register block structure
+ */
+typedef struct { /*!< PIN_INT Structure */
+ __IO uint32_t ISEL; /*!< Pin Interrupt Mode register */
+ __IO uint32_t IENR; /*!< Pin Interrupt Enable (Rising) register */
+ __IO uint32_t SIENR; /*!< Set Pin Interrupt Enable (Rising) register */
+ __IO uint32_t CIENR; /*!< Clear Pin Interrupt Enable (Rising) register */
+ __IO uint32_t IENF; /*!< Pin Interrupt Enable Falling Edge / Active Level register */
+ __IO uint32_t SIENF; /*!< Set Pin Interrupt Enable Falling Edge / Active Level register */
+ __IO uint32_t CIENF; /*!< Clear Pin Interrupt Enable Falling Edge / Active Level address */
+ __IO uint32_t RISE; /*!< Pin Interrupt Rising Edge register */
+ __IO uint32_t FALL; /*!< Pin Interrupt Falling Edge register */
+ __IO uint32_t IST; /*!< Pin Interrupt Status register */
+ __IO uint32_t PMCTRL; /*!< GPIO pattern match interrupt control register */
+ __IO uint32_t PMSRC; /*!< GPIO pattern match interrupt bit-slice source register */
+ __IO uint32_t PMCFG; /*!< GPIO pattern match interrupt bit slice configuration register */
+} LPC_PIN_INT_T;
+
+/**
+ * LPC11u6x Pin Interrupt and Pattern match engine register
+ * bit fields and macros
+ */
+/* PININT interrupt control register */
+#define PININT_PMCTRL_PMATCH_SEL (1 << 0)
+#define PININT_PMCTRL_RXEV_ENA (1 << 1)
+
+/* PININT Bit slice source register bits */
+#define PININT_SRC_BITSOURCE_START 8
+#define PININT_SRC_BITSOURCE_MASK 7
+
+/* PININT Bit slice configuration register bits */
+#define PININT_SRC_BITCFG_START 8
+#define PININT_SRC_BITCFG_MASK 7
+
+/**
+ * LPC11u6x Pin Interrupt channel values
+ */
+#define PININTCH0 (1 << 0)
+#define PININTCH1 (1 << 1)
+#define PININTCH2 (1 << 2)
+#define PININTCH3 (1 << 3)
+#define PININTCH4 (1 << 4)
+#define PININTCH5 (1 << 5)
+#define PININTCH6 (1 << 6)
+#define PININTCH7 (1 << 7)
+#define PININTCH(ch) (1 << (ch))
+
+/**
+ * LPC11u6x Pin Matching Interrupt bit slice enum values
+ */
+typedef enum Chip_PININT_BITSLICE {
+ PININTBITSLICE0 = 0, /*!< PININT Bit slice 0 */
+ PININTBITSLICE1 = 1, /*!< PININT Bit slice 1 */
+ PININTBITSLICE2 = 2, /*!< PININT Bit slice 2 */
+ PININTBITSLICE3 = 3, /*!< PININT Bit slice 3 */
+ PININTBITSLICE4 = 4, /*!< PININT Bit slice 4 */
+ PININTBITSLICE5 = 5, /*!< PININT Bit slice 5 */
+ PININTBITSLICE6 = 6, /*!< PININT Bit slice 6 */
+ PININTBITSLICE7 = 7 /*!< PININT Bit slice 7 */
+} Chip_PININT_BITSLICE_T;
+
+/**
+ * LPC11u6x Pin Matching Interrupt bit slice configuration enum values
+ */
+typedef enum Chip_PININT_BITSLICE_CFG {
+ PININT_PATTERNCONST1 = 0x0, /*!< Contributes to product term match */
+ PININT_PATTERNRISING = 0x1, /*!< Rising edge */
+ PININT_PATTERNFALLING = 0x2, /*!< Falling edge */
+ PININT_PATTERNRISINGRFALLING = 0x3, /*!< Rising or Falling edge */
+ PININT_PATTERNHIGH = 0x4, /*!< High level */
+ PININT_PATTERNLOW = 0x5, /*!< Low level */
+ PININT_PATTERCONST0 = 0x6, /*!< Never contributes for match */
+ PININT_PATTEREVENT = 0x7 /*!< Match occurs on event */
+} Chip_PININT_BITSLICE_CFG_T;
+
+/**
+ * @brief Initialize Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @return Nothing
+ * @note This function should be used after the Chip_GPIO_Init() function.
+ */
+STATIC INLINE void Chip_PININT_Init(LPC_PIN_INT_T *pPININT) {}
+
+/**
+ * @brief De-Initialize Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_DeInit(LPC_PIN_INT_T *pPININT) {}
+
+/**
+ * @brief Configure the pins as edge sensitive in Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @param pins : Pins (ORed value of PININTCH*)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_SetPinModeEdge(LPC_PIN_INT_T *pPININT, uint32_t pins)
+{
+ pPININT->ISEL &= ~pins;
+}
+
+/**
+ * @brief Configure the pins as level sensitive in Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @param pins : Pins (ORed value of PININTCH*)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_SetPinModeLevel(LPC_PIN_INT_T *pPININT, uint32_t pins)
+{
+ pPININT->ISEL |= pins;
+}
+
+/**
+ * @brief Return current PININT rising edge or high level interrupt enable state
+ * @param pPININT : The base address of Pin interrupt block
+ * @return A bifield containing the high edge/level interrupt enables for each
+ * interrupt. Bit 0 = PININT0, 1 = PININT1, etc.
+ * For each bit, a 0 means the high edge/level interrupt is disabled, while a 1
+ * means it's enabled.
+ */
+STATIC INLINE uint32_t Chip_PININT_GetHighEnabled(LPC_PIN_INT_T *pPININT)
+{
+ return pPININT->IENR;
+}
+
+/**
+ * @brief Enable high edge/level PININT interrupts for pins
+ * @param pPININT : The base address of Pin interrupt block
+ * @param pins : Pins to enable (ORed value of PININTCH*)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_EnableIntHigh(LPC_PIN_INT_T *pPININT, uint32_t pins)
+{
+ pPININT->SIENR = pins;
+}
+
+/**
+ * @brief Disable high edge/level PININT interrupts for pins
+ * @param pPININT : The base address of Pin interrupt block
+ * @param pins : Pins to disable (ORed value of PININTCH*)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_DisableIntHigh(LPC_PIN_INT_T *pPININT, uint32_t pins)
+{
+ pPININT->CIENR = pins;
+}
+
+/**
+ * @brief Return current PININT falling edge or low level interrupt enable state
+ * @param pPININT : The base address of Pin interrupt block
+ * @return A bifield containing the low edge/level interrupt enables for each
+ * interrupt. Bit 0 = PININT0, 1 = PININT1, etc.
+ * For each bit, a 0 means the low edge/level interrupt is disabled, while a 1
+ * means it's enabled.
+ */
+STATIC INLINE uint32_t Chip_PININT_GetLowEnabled(LPC_PIN_INT_T *pPININT)
+{
+ return pPININT->IENF;
+}
+
+/**
+ * @brief Enable low edge/level PININT interrupts for pins
+ * @param pPININT : The base address of Pin interrupt block
+ * @param pins : Pins to enable (ORed value of PININTCH*)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_EnableIntLow(LPC_PIN_INT_T *pPININT, uint32_t pins)
+{
+ pPININT->SIENF = pins;
+}
+
+/**
+ * @brief Disable low edge/level PININT interrupts for pins
+ * @param pPININT : The base address of Pin interrupt block
+ * @param pins : Pins to disable (ORed value of PININTCH*)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_DisableIntLow(LPC_PIN_INT_T *pPININT, uint32_t pins)
+{
+ pPININT->CIENF = pins;
+}
+
+/**
+ * @brief Return pin states that have a detected latched high edge (RISE) state
+ * @param pPININT : The base address of Pin interrupt block
+ * @return PININT states (bit n = high) with a latched rise state detected
+ */
+STATIC INLINE uint32_t Chip_PININT_GetRiseStates(LPC_PIN_INT_T *pPININT)
+{
+ return pPININT->RISE;
+}
+
+/**
+ * @brief Clears pin states that had a latched high edge (RISE) state
+ * @param pPININT : The base address of Pin interrupt block
+ * @param pins : Pins with latched states to clear
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_ClearRiseStates(LPC_PIN_INT_T *pPININT, uint32_t pins)
+{
+ pPININT->RISE = pins;
+}
+
+/**
+ * @brief Return pin states that have a detected latched falling edge (FALL) state
+ * @param pPININT : The base address of Pin interrupt block
+ * @return PININT states (bit n = high) with a latched rise state detected
+ */
+STATIC INLINE uint32_t Chip_PININT_GetFallStates(LPC_PIN_INT_T *pPININT)
+{
+ return pPININT->FALL;
+}
+
+/**
+ * @brief Clears pin states that had a latched falling edge (FALL) state
+ * @param pPININT : The base address of Pin interrupt block
+ * @param pins : Pins with latched states to clear
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_ClearFallStates(LPC_PIN_INT_T *pPININT, uint32_t pins)
+{
+ pPININT->FALL = pins;
+}
+
+/**
+ * @brief Get interrupt status from Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @return Interrupt status (bit n for PININTn = high means interrupt ie pending)
+ */
+STATIC INLINE uint32_t Chip_PININT_GetIntStatus(LPC_PIN_INT_T *pPININT)
+{
+ return pPININT->IST;
+}
+
+/**
+ * @brief Clear interrupt status in Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @param pins : Pin interrupts to clear (ORed value of PININTCH*)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_ClearIntStatus(LPC_PIN_INT_T *pPININT, uint32_t pins)
+{
+ pPININT->IST = pins;
+}
+
+/**
+ * @brief Set source for pattern match in Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @param chan : PININT channel number (From 0 to 7)
+ * @param slice : PININT slice number
+ * @return Nothing
+ */
+void Chip_PININT_SetPatternMatchSrc(LPC_PIN_INT_T *pPININT, uint8_t chan, Chip_PININT_BITSLICE_T slice);
+
+/**
+ * @brief Configure the pattern matcch in Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @param slice : PININT slice number
+ * @param slice_cfg : PININT slice configuration value (enum Chip_PININT_BITSLICE_CFG_T)
+ * @param end_point : If true, current slice is final component
+ * @return Nothing
+ */
+void Chip_PININT_SetPatternMatchConfig(LPC_PIN_INT_T *pPININT, Chip_PININT_BITSLICE_T slice,
+ Chip_PININT_BITSLICE_CFG_T slice_cfg, bool end_point);
+
+/**
+ * @brief Enable pattern match interrupts in Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_EnablePatternMatch(LPC_PIN_INT_T *pPININT)
+{
+ pPININT->PMCTRL |= PININT_PMCTRL_PMATCH_SEL;
+}
+
+/**
+ * @brief Disable pattern match interrupts in Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_DisablePatternMatch(LPC_PIN_INT_T *pPININT)
+{
+ pPININT->PMCTRL &= ~PININT_PMCTRL_PMATCH_SEL;
+}
+
+/**
+ * @brief Enable RXEV output in Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_EnablePatternMatchRxEv(LPC_PIN_INT_T *pPININT)
+{
+ pPININT->PMCTRL |= PININT_PMCTRL_RXEV_ENA;
+}
+
+/**
+ * @brief Disable RXEV output in Pin interrupt block
+ * @param pPININT : The base address of Pin interrupt block
+ * @return Nothing
+ */
+STATIC INLINE void Chip_PININT_DisablePatternMatchRxEv(LPC_PIN_INT_T *pPININT)
+{
+ pPININT->PMCTRL &= ~PININT_PMCTRL_RXEV_ENA;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PININT_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/pmu_11u6x.h b/source/lpc_chip_11u6x/inc/pmu_11u6x.h
new file mode 100644
index 0000000..9960783
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/pmu_11u6x.h
@@ -0,0 +1,231 @@
+/*
+ * @brief LPC11U6x PMU chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __PMU_11U6X_H_
+#define __PMU_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup PMU_11U6X CHIP: LPC11u6x Power Management Unit block driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief LPC11u6x Power Management Unit register block structure
+ */
+typedef struct {
+ __IO uint32_t PCON; /*!< Offset: 0x000 Power control Register (R/W) */
+ __IO uint32_t GPREG[4]; /*!< Offset: 0x004 General purpose Registers 0..3 (R/W) */
+ __IO uint32_t DPDCTRL; /*!< Offset: 0x014 Deep power-down control register (R/W) */
+} LPC_PMU_T;
+
+/**
+ * @brief LPC11u6x low power mode type definitions
+ */
+typedef enum CHIP_PMU_MCUPOWER {
+ PMU_MCU_SLEEP = 0, /*!< Sleep mode */
+ PMU_MCU_DEEP_SLEEP, /*!< Deep Sleep mode */
+ PMU_MCU_POWER_DOWN, /*!< Power down mode */
+ PMU_MCU_DEEP_PWRDOWN /*!< Deep power down mode */
+} CHIP_PMU_MCUPOWER_T;
+
+/**
+ * PMU PCON register bit fields & masks
+ */
+#define PMU_PCON_PM_SLEEP (0x0) /*!< ARM WFI enter sleep mode */
+#define PMU_PCON_PM_DEEPSLEEP (0x1) /*!< ARM WFI enter Deep-sleep mode */
+#define PMU_PCON_PM_POWERDOWN (0x2) /*!< ARM WFI enter Power-down mode */
+#define PMU_PCON_PM_DEEPPOWERDOWN (0x3) /*!< ARM WFI enter Deep Power-down mode */
+#define PMU_PCON_NODPD (1 << 3) /*!< Disable deep power-down mode */
+#define PMU_PCON_SLEEPFLAG (1 << 8) /*!< Sleep mode flag */
+#define PMU_PCON_DPDFLAG (1 << 11) /*!< Deep power-down flag */
+
+/**
+ * PMU DPDCTRL register bit fields & masks
+ */
+#define PMU_DPDCTRL_WAKEUPPHYS (1 << 10) /** Enable wake-up pin hysteresis */
+#define PMU_DPDCTRL_WAKEPAD (1 << 11) /** Disable the Wake-up function on pin PIO0_16 */
+
+/**
+ * @brief Write a value to a GPREG register
+ * @param pPMU : Pointer to PMU register block
+ * @param regIndex : Register index to write to, must be 0..3
+ * @param value : Value to write
+ * @return None
+ */
+STATIC INLINE void Chip_PMU_WriteGPREG(LPC_PMU_T *pPMU, uint8_t regIndex, uint32_t value)
+{
+ pPMU->GPREG[regIndex] = value;
+}
+
+/**
+ * @brief Read a value to a GPREG register
+ * @param pPMU : Pointer to PMU register block
+ * @param regIndex : Register index to read from, must be 0..3
+ * @return Value read from the GPREG register
+ */
+STATIC INLINE uint32_t Chip_PMU_ReadGPREG(LPC_PMU_T *pPMU, uint8_t regIndex)
+{
+ return pPMU->GPREG[regIndex];
+}
+
+/**
+ * @brief Enter MCU Sleep mode
+ * @param pPMU : Pointer to PMU register block
+ * @return None
+ * @note The sleep mode affects the ARM Cortex-M0+ core only. Peripherals
+ * and memories are active.
+ */
+void Chip_PMU_SleepState(LPC_PMU_T *pPMU);
+
+/**
+ * @brief Enter MCU Deep Sleep mode
+ * @param pPMU : Pointer to PMU register block
+ * @return None
+ * @note In Deep-sleep mode, the peripherals receive no internal clocks.
+ * The flash is in stand-by mode. The SRAM memory and all peripheral registers
+ * as well as the processor maintain their internal states. The WWDT, WKT,
+ * and BOD can remain active to wake up the system on an interrupt.
+ */
+void Chip_PMU_DeepSleepState(LPC_PMU_T *pPMU);
+
+/**
+ * @brief Enter MCU Power down mode
+ * @param pPMU : Pointer to PMU register block
+ * @return None
+ * @note In Power-down mode, the peripherals receive no internal clocks.
+ * The internal SRAM memory and all peripheral registers as well as the
+ * processor maintain their internal states. The flash memory is powered
+ * down. The WWDT, WKT, and BOD can remain active to wake up the system
+ * on an interrupt.
+ */
+void Chip_PMU_PowerDownState(LPC_PMU_T *pPMU);
+
+/**
+ * @brief Enter MCU Deep Power down mode
+ * @param pPMU : Pointer to PMU register block
+ * @return None
+ * @note For maximal power savings, the entire system is shut down
+ * except for the general purpose registers in the PMU and the self
+ * wake-up timer. Only the general purpose registers in the PMU maintain
+ * their internal states. The part can wake up on a pulse on the WAKEUP
+ * pin or when the self wake-up timer times out. On wake-up, the part
+ * reboots.
+ */
+void Chip_PMU_DeepPowerDownState(LPC_PMU_T *pPMU);
+
+/**
+ * @brief Place the MCU in a low power state
+ * @param pPMU : Pointer to PMU register block
+ * @param SleepMode : Sleep mode
+ * @return None
+ */
+void Chip_PMU_Sleep(LPC_PMU_T *pPMU, CHIP_PMU_MCUPOWER_T SleepMode);
+
+/**
+ * @brief Disables deep power-down mode
+ * @param pPMU : Pointer to PMU register block
+ * @return None
+ * @note Calling this functions prevents entry to Deep power-down
+ * mode. Once set, this can only be cleared by power-on reset.
+ */
+STATIC INLINE void Chip_PMU_DisableDeepPowerDown(LPC_PMU_T *pPMU)
+{
+ pPMU->PCON |= PMU_PCON_NODPD;
+}
+
+/**
+ * @brief Returns sleep/power-down flags
+ * @param pPMU : Pointer to PMU register block
+ * @return Or'ed values of PMU_PCON_SLEEPFLAG and PMU_PCON_DPDFLAG
+ * @note These indicate that the PMU is setup for entry into a low
+ * power state on the next WFI() instruction.
+ */
+STATIC INLINE uint32_t Chip_PMU_GetSleepFlags(LPC_PMU_T *pPMU)
+{
+ return pPMU->PCON & (PMU_PCON_SLEEPFLAG | PMU_PCON_DPDFLAG);
+}
+
+/**
+ * @brief Clears sleep/power-down flags
+ * @param pPMU : Pointer to PMU register block
+ * @param flags : Or'ed value of PMU_PCON_SLEEPFLAG and PMU_PCON_DPDFLAG
+ * @return Nothing
+ * @note Use this function to clear a low power state prior to calling
+ * WFI().
+ */
+STATIC INLINE void Chip_PMU_ClearSleepFlags(LPC_PMU_T *pPMU, uint32_t flags)
+{
+ pPMU->PCON &= ~flags;
+}
+
+/**
+ * @brief Sets deep power-down functions
+ * @param pPMU : Pointer to PMU register block
+ * @param flags : Or'ed value of PMU_DPDCTRL_* values
+ * @return Nothing
+ * @note Some of these functions may need to be set prior to going
+ * into a low power mode. Note that some calls to this function enable
+ * functions while others disable it based on the PMU_DPDCTRL_*
+ * definitions.
+ */
+STATIC INLINE void Chip_PMU_SetPowerDownControl(LPC_PMU_T *pPMU, uint32_t flags)
+{
+ pPMU->DPDCTRL |= flags;
+}
+
+/**
+ * @brief Cleats deep power-down functions
+ * @param pPMU : Pointer to PMU register block
+ * @param flags : Or'ed value of PMU_DPDCTRL_* values
+ * @return Nothing
+ * @note Some of these functions may need to be cleared prior to going
+ * into a low power mode. Note that some calls to this function enable
+ * functions while others disable it based on the PMU_DPDCTRL_*
+ * definitions.
+ */
+STATIC INLINE void Chip_PMU_ClearPowerDownControl(LPC_PMU_T *pPMU, uint32_t flags)
+{
+ pPMU->DPDCTRL &= ~flags;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PMU_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/ring_buffer.h b/source/lpc_chip_11u6x/inc/ring_buffer.h
new file mode 100644
index 0000000..8c205fd
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/ring_buffer.h
@@ -0,0 +1,188 @@
+/*
+ * @brief Common ring buffer support functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2012
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __RING_BUFFER_H_
+#define __RING_BUFFER_H_
+
+#include "lpc_types.h"
+
+/** @defgroup Ring_Buffer CHIP: Simple ring buffer implementation
+ * @ingroup CHIP_Common
+ * @{
+ */
+
+/**
+ * @brief Ring buffer structure
+ */
+typedef struct {
+ void *data;
+ int count;
+ int itemSz;
+ uint32_t head;
+ uint32_t tail;
+} RINGBUFF_T;
+
+/**
+ * @def RB_VHEAD(rb)
+ * volatile typecasted head index
+ */
+#define RB_VHEAD(rb) (*(volatile uint32_t *) &(rb)->head)
+
+/**
+ * @def RB_VTAIL(rb)
+ * volatile typecasted tail index
+ */
+#define RB_VTAIL(rb) (*(volatile uint32_t *) &(rb)->tail)
+
+/**
+ * @brief Initialize ring buffer
+ * @param RingBuff : Pointer to ring buffer to initialize
+ * @param buffer : Pointer to buffer to associate with RingBuff
+ * @param itemSize : Size of each buffer item size
+ * @param count : Size of ring buffer
+ * @note Memory pointed by @a buffer must have correct alignment of
+ * @a itemSize, and @a count must be a power of 2 and must at
+ * least be 2 or greater.
+ * @return Nothing
+ */
+int RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count);
+
+/**
+ * @brief Resets the ring buffer to empty
+ * @param RingBuff : Pointer to ring buffer
+ * @return Nothing
+ */
+STATIC INLINE void RingBuffer_Flush(RINGBUFF_T *RingBuff)
+{
+ RingBuff->head = RingBuff->tail = 0;
+}
+
+/**
+ * @brief Return size the ring buffer
+ * @param RingBuff : Pointer to ring buffer
+ * @return Size of the ring buffer in bytes
+ */
+STATIC INLINE int RingBuffer_GetSize(RINGBUFF_T *RingBuff)
+{
+ return RingBuff->count;
+}
+
+/**
+ * @brief Return number of items in the ring buffer
+ * @param RingBuff : Pointer to ring buffer
+ * @return Number of items in the ring buffer
+ */
+STATIC INLINE int RingBuffer_GetCount(RINGBUFF_T *RingBuff)
+{
+ return RB_VHEAD(RingBuff) - RB_VTAIL(RingBuff);
+}
+
+/**
+ * @brief Return number of free items in the ring buffer
+ * @param RingBuff : Pointer to ring buffer
+ * @return Number of free items in the ring buffer
+ */
+STATIC INLINE int RingBuffer_GetFree(RINGBUFF_T *RingBuff)
+{
+ return RingBuff->count - RingBuffer_GetCount(RingBuff);
+}
+
+/**
+ * @brief Return number of items in the ring buffer
+ * @param RingBuff : Pointer to ring buffer
+ * @return 1 if the ring buffer is full, otherwise 0
+ */
+STATIC INLINE int RingBuffer_IsFull(RINGBUFF_T *RingBuff)
+{
+ return (RingBuffer_GetCount(RingBuff) >= RingBuff->count);
+}
+
+/**
+ * @brief Return empty status of ring buffer
+ * @param RingBuff : Pointer to ring buffer
+ * @return 1 if the ring buffer is empty, otherwise 0
+ */
+STATIC INLINE int RingBuffer_IsEmpty(RINGBUFF_T *RingBuff)
+{
+ return RB_VHEAD(RingBuff) == RB_VTAIL(RingBuff);
+}
+
+/**
+ * @brief Insert a single item into ring buffer
+ * @param RingBuff : Pointer to ring buffer
+ * @param data : pointer to item
+ * @return 1 when successfully inserted,
+ * 0 on error (Buffer not initialized using
+ * RingBuffer_Init() or attempted to insert
+ * when buffer is full)
+ */
+int RingBuffer_Insert(RINGBUFF_T *RingBuff, const void *data);
+
+/**
+ * @brief Insert an array of items into ring buffer
+ * @param RingBuff : Pointer to ring buffer
+ * @param data : Pointer to first element of the item array
+ * @param num : Number of items in the array
+ * @return number of items successfully inserted,
+ * 0 on error (Buffer not initialized using
+ * RingBuffer_Init() or attempted to insert
+ * when buffer is full)
+ */
+int RingBuffer_InsertMult(RINGBUFF_T *RingBuff, const void *data, int num);
+
+/**
+ * @brief Pop an item from the ring buffer
+ * @param RingBuff : Pointer to ring buffer
+ * @param data : Pointer to memory where popped item be stored
+ * @return 1 when item popped successfuly onto @a data,
+ * 0 When error (Buffer not initialized using
+ * RingBuffer_Init() or attempted to pop item when
+ * the buffer is empty)
+ */
+int RingBuffer_Pop(RINGBUFF_T *RingBuff, void *data);
+
+/**
+ * @brief Pop an array of items from the ring buffer
+ * @param RingBuff : Pointer to ring buffer
+ * @param data : Pointer to memory where popped items be stored
+ * @param num : Max number of items array @a data can hold
+ * @return Number of items popped onto @a data,
+ * 0 on error (Buffer not initialized using RingBuffer_Init()
+ * or attempted to pop when the buffer is empty)
+ */
+int RingBuffer_PopMult(RINGBUFF_T *RingBuff, void *data, int num);
+
+
+/**
+ * @}
+ */
+
+#endif /* __RING_BUFFER_H_ */
diff --git a/source/lpc_chip_11u6x/inc/rom_dma_11u6x.h b/source/lpc_chip_11u6x/inc/rom_dma_11u6x.h
new file mode 100644
index 0000000..66ae98d
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/rom_dma_11u6x.h
@@ -0,0 +1,140 @@
+/*
+ * @brief LPC11u6x DMA ROM API declarations and functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __ROM_DMA_11U6X_H_
+#define __ROM_DMA_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup CHIP_DMAROM_11U6X CHIP: LPC11U6X DMA ROM API declarations and functions
+ * @ingroup ROMAPI_11U6X
+ * @{
+ */
+
+/**
+ * @brief LPC11U6X DMA ROM driver handle structure
+ */
+typedef void *DMA_HANDLE_T;
+
+/**
+ * @brief LPC11U6X DMA ROM driver callback function
+ * @param res0 : error code
+ * @param res1 : 0 = INTA is issued, 1 = INTB is issued
+ */
+typedef void (*DMA_CALLBK_T)(uint32_t res0, uint32_t res1);
+
+/**
+ * @brief LPC11U6X DMA ROM event values
+ */
+#define DMA_EVENT_SW_REQ 0
+#define DMA_EVENT_PERIPH_REQ 1
+#define DMA_EVENT_HW_REQ 2
+
+/**
+ * @brief LPC11U6X DMA ROM hardware trigger values
+ */
+#define DMA_HWTRIG_BURST_SIZE(n) (n) /*!< Burst size is 2^n, n <= 15 */
+#define DMA_HWTRIG_SRC_BURST_WRAP (1 << 4) /*!< Source burst wrapping enabled */
+#define DMA_HWTRIG_TRIGGER_BURST (1 << 6) /*!< Hardware trigger cause a burst transfer */
+
+/**
+ * @brief LPC11U6X DMA ROM channel configuration structure
+ */
+typedef struct DMA_CHANNEL {
+ uint8_t event; /*!< Event type selection for DMA transfer, a value of DMA_EVENT_* types */
+ uint8_t hd_trigger; /*!< In case hardware trigger is enabled, OR'ed values of type DMA_HWTRIG_* */
+ uint8_t Priority; /*!< Priority level 0 - 7, 0 = lowest, 7 = highest */
+ DMA_CALLBK_T callback_func_pt; /*!< Callback function, only invoked when INTA or INTB is enabled */
+} DMA_CHANNEL_T ;
+
+/**
+ * @brief LPC11U6X DMA ROM task configuration values
+ */
+#define DMA_TASK_PINGPONG (1 << 0) /*!< Linked with previous task for Ping_Pong transfer */
+#define DMA_TASK_SWTRIG (1 << 1) /*!< The trigger for this channel is set immediately */
+#define DMA_TASK_CLEARTRIG (1 << 2) /*!< The trigger is cleared when this task is finished */
+#define DMA_TASK_SELINTA (1 << 3) /*!< The IntA flag for this channel will be set when this task is finished */
+#define DMA_TASK_SELINTB (1 << 4) /*!< The IntB flag for this channel will be set when this task is finished */
+
+/**
+ * @brief LPC11U6X DMA ROM data type values
+ */
+#define DMA_DATA_SIZE(n) (n) /*!< Data width, 0: 8-bit, 1: 16-bit, 2: 32-bit, 3: reserved */
+/* DMA_DATA_SRCINC = 0 : The source address is not incremented for each transfer */
+/* DMA_DATA_SRCINC = 1 : The source address is incremented by the amount specified by Width for each transfer */
+/* DMA_DATA_SRCINC = 2 : The source address is incremented by 2 times the amount specified by Width for each transfer */
+/* DMA_DATA_SRCINC = 3 : The source address is incremented by 4 times the amount specified by Width for each transfer */
+#define DMA_DATA_SRCINC(n) (n << 2) /*!< Source address incrementation */
+/* DMA_DATA_DSTINC = 0 : The destination address is not incremented for each transfer */
+/* DMA_DATA_DSTINC = 1 : The destination address is incremented by the amount specified by Width for each transfer */
+/* DMA_DATA_DSTINC = 2 : The destination address is incremented by 2 times the amount specified by Width for each transfer */
+/* DMA_DATA_DSTINC = 3 : The destination address is incremented by 4 times the amount specified by Width for each transfer */
+#define DMA_DATA_DSTINC(n) (n << 4) /*!< Destination address incrementation */
+
+/**
+ * @brief LPC11U6X DMA ROM task structure
+ */
+typedef struct DMA_TASK {
+ uint8_t ch_num; /*!< DMA channel number */
+ uint8_t config; /*!< Configuration of this task, OR'ed values of DMA_TASK_* */
+ uint8_t data_type; /*!< Data type, OR'ed values of DMA_DATA_* */
+ uint16_t data_length; /*!< 0: 1 transfer, 1: 2 transfer, … 1023: 1024 transfers */
+ uint32_t src; /*!< Source data end address */
+ uint32_t dst; /*!< Destination end address */
+ uint32_t task_addr; /*!< the address of RAM for saving this task. Must be 16 butes and aligned on a 16 byte boundary */
+} DMA_TASK_T ;
+
+/**
+ * LPC11U6X DMA ROM driver APIs structure
+ */
+typedef struct DMAD_API {
+ void (*dma_isr)(DMA_HANDLE_T* handle);
+ uint32_t (*dma_get_mem_size)( void);
+ DMA_HANDLE_T* (*dma_setup)( uint32_t base_addr, uint8_t *ram );
+ ErrorCode_t (*dma_init)( DMA_HANDLE_T* handle, DMA_CHANNEL_T *channel, DMA_TASK_T *task);
+ ErrorCode_t (*dma_link)( DMA_HANDLE_T* handle, DMA_TASK_T *task, uint8_t valid);
+ ErrorCode_t (*dma_set_valid)( DMA_HANDLE_T* handle, uint8_t chl_num);
+ ErrorCode_t (*dma_pause)( DMA_HANDLE_T* handle, uint8_t chl_num);
+ ErrorCode_t (*dma_unpause)( DMA_HANDLE_T* handle, uint8_t chl_num);
+ ErrorCode_t (*dma_abort)( DMA_HANDLE_T* handle, uint8_t chl_num);
+} DMAD_API_T ;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ROM_DMA_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/rom_i2c_11u6x.h b/source/lpc_chip_11u6x/inc/rom_i2c_11u6x.h
new file mode 100644
index 0000000..ba5d4f9
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/rom_i2c_11u6x.h
@@ -0,0 +1,124 @@
+/*
+ * @brief LPC11u6x I2C ROM API declarations and functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __ROM_I2C_11U6X_H_
+#define __ROM_I2C_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup CHIP_I2CROM_11U6X CHIP: LPC11U6X I2C ROM API declarations and functions
+ * @ingroup ROMAPI_11U6X
+ * @{
+ */
+
+/**
+ * @brief LPC11U6X I2C ROM driver handle structure
+ */
+typedef void *I2C_HANDLE_T;
+
+/**
+ * @brief LPC11U6X I2C ROM driver callback function
+ */
+typedef void (*I2C_CALLBK_T)(uint32_t err_code, uint32_t n);
+
+/**
+ * LPC11U6X I2C ROM driver parameter structure
+ */
+typedef struct I2C_PARAM {
+ uint32_t num_bytes_send; /*!< No. of bytes to send */
+ uint32_t num_bytes_rec; /*!< No. of bytes to receive */
+ uint8_t *buffer_ptr_send; /*!< Pointer to send buffer */
+ uint8_t *buffer_ptr_rec; /*!< Pointer to receive buffer */
+ I2C_CALLBK_T func_pt; /*!< Callback function */
+ uint8_t stop_flag; /*!< Stop flag */
+ uint8_t dummy[3];
+} I2C_PARAM_T;
+
+/**
+ * LPC11U6X I2C ROM driver result structure
+ */
+typedef struct I2C_RESULT {
+ uint32_t n_bytes_sent; /*!< No. of bytes sent */
+ uint32_t n_bytes_recd; /*!< No. of bytes received */
+} I2C_RESULT_T;
+
+/**
+ * LPC11U6X I2C ROM driver modes enum
+ */
+typedef enum CHIP_I2C_MODE {
+ IDLE, /*!< IDLE state */
+ MASTER_SEND, /*!< Master send state */
+ MASTER_RECEIVE, /*!< Master Receive state */
+ SLAVE_SEND, /*!< Slave send state */
+ SLAVE_RECEIVE /*!< Slave receive state */
+} CHIP_I2C_MODE_T;
+
+/**
+ * LPC11U6X I2C ROM driver APIs structure
+ */
+typedef struct I2CD_API {
+ /*!< Interrupt Support Routine */
+ void (*i2c_isr_handler)(I2C_HANDLE_T *handle);
+
+ /*!< MASTER functions */
+ ErrorCode_t (*i2c_master_transmit_poll)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result);
+ ErrorCode_t (*i2c_master_receive_poll)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result);
+ ErrorCode_t (*i2c_master_tx_rx_poll)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result);
+ ErrorCode_t (*i2c_master_transmit_intr)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result);
+ ErrorCode_t (*i2c_master_receive_intr)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result);
+ ErrorCode_t (*i2c_master_tx_rx_intr)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result);
+
+ /*!< SLAVE functions */
+ ErrorCode_t (*i2c_slave_receive_poll)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result);
+ ErrorCode_t (*i2c_slave_transmit_poll)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result);
+ ErrorCode_t (*i2c_slave_receive_intr)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result);
+ ErrorCode_t (*i2c_slave_transmit_intr)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result);
+ ErrorCode_t (*i2c_set_slave_addr)(I2C_HANDLE_T *handle, uint32_t slave_addr_0_3, uint32_t slave_mask_0_3);
+
+ /*!< OTHER support functions */
+ uint32_t (*i2c_get_mem_size)(void);
+ I2C_HANDLE_T * (*i2c_setup)( uint32_t i2c_base_addr, uint32_t * start_of_ram);
+ ErrorCode_t (*i2c_set_bitrate)(I2C_HANDLE_T *handle, uint32_t p_clk_in_hz, uint32_t bitrate_in_bps);
+ uint32_t (*i2c_get_firmware_version)(void);
+ CHIP_I2C_MODE_T (*i2c_get_status)(I2C_HANDLE_T *handle);
+} I2CD_API_T;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ROM_I2C_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/rom_pwr_11u6x.h b/source/lpc_chip_11u6x/inc/rom_pwr_11u6x.h
new file mode 100644
index 0000000..1d41955
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/rom_pwr_11u6x.h
@@ -0,0 +1,94 @@
+/*
+ * @brief LPC11u6x Power ROM API declarations and functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __ROM_PWR_11U6X_H_
+#define __ROM_PWR_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup PWRROM_11U6X CHIP: LPC11U6X Power ROM API declarations and functions
+ * @ingroup ROMAPI_11U6X
+ * @{
+ */
+
+/**
+ * @brief Power ROM APIs - set_pll mode options
+ */
+#define CPU_FREQ_EQU 0
+#define CPU_FREQ_LTE 1
+#define CPU_FREQ_GTE 2
+#define CPU_FREQ_APPROX 3
+
+/**
+ * @brief Power ROM APIs - set_pll response0 options
+ */
+#define PLL_CMD_SUCCESS 0
+#define PLL_INVALID_FREQ 1
+#define PLL_INVALID_MODE 2
+#define PLL_FREQ_NOT_FOUND 3
+#define PLL_NOT_LOCKED 4
+
+/**
+ * @brief Power ROM APIs - set_power mode options
+ */
+#define PWR_DEFAULT 0
+#define PWR_CPU_PERFORMANCE 1
+#define PWR_EFFICIENCY 2
+#define PWR_LOW_CURRENT 3
+
+/**
+ * @brief Power ROM APIs - set_power response0 options
+ */
+#define PWR_CMD_SUCCESS 0
+#define PWR_INVALID_FREQ 1
+#define PWR_INVALID_MODE 2
+
+/**
+ * @brief Power ROM API structure
+ * The power profile API provides functions to configure the system clock and optimize the
+ * system setting for lowest power consumption.
+ */
+typedef struct PWRD_API {
+ void (*set_pll)(uint32_t cmd[], uint32_t resp[]); /*!< Set PLL function */
+ void (*set_power)(uint32_t cmd[], uint32_t resp[]); /*!< Set power function */
+} PWRD_API_T;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ROM_PWR_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/rom_uart_11u6x.h b/source/lpc_chip_11u6x/inc/rom_uart_11u6x.h
new file mode 100644
index 0000000..1647688
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/rom_uart_11u6x.h
@@ -0,0 +1,180 @@
+/*
+ * @brief LPC11U6x UART ROM API declarations and functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __ROM_UART_11U6X_H_
+#define __ROM_UART_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup UARTROM_11U6X CHIP: LPC11U6X UART ROM API declarations and functions
+ * @ingroup ROMAPI_11U6X
+ * @{
+ */
+
+/**
+ * @brief UART ROM driver - UART errors in UART configuration used in uart_init function
+ */
+#define OVERRUN_ERR_EN (1 << 0) /*!< Bit 0: Enable overrun error */
+#define UNDERRUN_ERR_EN (1 << 1) /*!< Bit 1: Enable underrun error */
+#define FRAME_ERR_EN (1 << 2) /*!< Bit 2: enable frame error */
+#define PARITY_ERR_EN (1 << 3) /*!< Bit 3: enable parity error */
+#define RXNOISE_ERR_EN (1 << 4) /*!< Bit 4: enable receive noise error */
+
+/**
+ * Macros for UART errors
+ */
+/*!< Enable all the UART errors */
+#define ALL_ERR_EN (OVERRUN_ERR_EN | UNDERRUN_ERR_EN | FRAME_ERR_EN | PARITY_ERR_EN | \
+ RXNOISE_ERR_EN)
+/*!< Disable all the errors */
+#define NO_ERR_EN (0)
+
+/**
+ * Transfer mode values in UART parameter structure.
+ * Used in uart_get_line & uart_put_line function
+ */
+/*!< 0x00: uart_get_line: stop transfer when the buffer is full */
+/*!< 0x00: uart_put_line: stop transfer when the buffer is empty */
+#define TX_MODE_BUF_EMPTY (0x00)
+#define RX_MODE_BUF_FULL (0x00)
+/*!< 0x01: uart_get_line: stop transfer when CRLF are received */
+/*!< 0x01: uart_put_line: transfer stopped after reaching \0 and CRLF is sent out after that */
+#define TX_MODE_SZERO_SEND_CRLF (0x01)
+#define RX_MODE_CRLF_RECVD (0x01)
+/*!< 0x02: uart_get_line: stop transfer when LF are received */
+/*!< 0x02: uart_put_line: transfer stopped after reaching \0. And LF is sent out after that */
+#define TX_MODE_SZERO_SEND_LF (0x02)
+#define RX_MODE_LF_RECVD (0x02)
+/*!< 0x03: uart_get_line: RESERVED */
+/*!< 0x03: uart_put_line: transfer stopped after reaching \0 */
+#define TX_MODE_SZERO (0x03)
+
+/**
+ * @brief UART ROM driver modes
+ */
+#define DRIVER_MODE_POLLING (0x00) /*!< Polling mode */
+#define DRIVER_MODE_INTERRUPT (0x01) /*!< Interrupt mode */
+#define DRIVER_MODE_DMA (0x02) /*!< DMA mode */
+
+/**
+ * @brief UART ROM driver UART handle
+ */
+typedef void UART_HANDLE_T;
+
+/**
+ * @brief UART ROM driver UART callback function
+ */
+typedef void (*UART_CALLBK_T)(uint32_t err_code, uint32_t n);
+
+/**
+ * @brief UART ROM driver UART DMA callback function
+ */
+typedef void (*UART_DMA_REQ_T)(uint32_t src_adr, uint32_t dst_adr, uint32_t size);
+
+/**
+ * @brief UART ROM driver configutaion structure
+ */
+typedef struct {
+ uint32_t sys_clk_in_hz; /*!< System clock in Hz */
+ uint32_t baudrate_in_hz; /*!< Baud rate in Hz */
+ uint8_t config; /*!< Configuration value */
+ /*!< bit1:0 Data Length: 00: 7 bits length, 01: 8 bits length, others: reserved */
+ /*!< bit3:2 Parity: 00: No Parity, 01: reserved, 10: Even, 11: Odd */
+ /*!< bit4: Stop Bit(s): 0: 1 Stop bit, 1: 2 Stop bits */
+ uint8_t sync_mod; /*!< Sync mode settings */
+ /*!< bit0: Mode: 0: Asynchronous mode, 1: Synchronous mode */
+ /*!< bit1: 0: Un_RXD is sampled on the falling edge of SCLK */
+ /*!< 1: Un_RXD is sampled on the rising edge of SCLK */
+ /*!< bit2: 0: Start and stop bits are transmitted as in asynchronous mode) */
+ /*!< 1: Start and stop bits are not transmitted) */
+ /*!< bit3: 0: The UART is a slave in Synchronous mode */
+ /*!< 1: The UART is a master in Synchronous mode */
+ uint16_t error_en; /*!< Errors to be enabled */
+ /*!< bit0: Overrun Errors Enabled */
+ /*!< bit1: Underrun Errors Enabled */
+ /*!< bit2: FrameErr Errors Enabled */
+ /*!< bit3: ParityErr Errors Enabled */
+ /*!< bit4: RxNoise Errors Enabled */
+} UART_CONFIG_T;
+
+/**
+ * @brief UART ROM driver parameter structure
+ */
+typedef struct {
+ uint8_t *buffer; /*!< Pointer to data buffer */
+ uint32_t size; /*!< Size of the buffer */
+ uint16_t transfer_mode; /*!< Transfer mode settings */
+ /*!< 0x00: uart_get_line: stop transfer when the buffer is full */
+ /*!< 0x00: uart_put_line: stop transfer when the buffer is empty */
+ /*!< 0x01: uart_get_line: stop transfer when CRLF are received */
+ /*!< 0x01: uart_put_line: transfer stopped after reaching \0 and CRLF is sent out after that */
+ /*!< 0x02: uart_get_line: stop transfer when LF are received */
+ /*!< 0x02: uart_put_line: transfer stopped after reaching \0 and LF is sent out after that */
+ /*!< 0x03: uart_get_line: RESERVED */
+ /*!< 0x03: uart_put_line: transfer stopped after reaching \0 */
+ uint16_t driver_mode; /*!< Driver mode */
+ /*!< 0x00: Polling mode, function blocked until transfer completes */
+ /*!< 0x01: Interrupt mode, function immediately returns, callback invoked when transfer completes */
+ /*!< 0x02: DMA mode, in case DMA block is available, DMA req function is called for UART DMA channel setup, then callback function indicate that transfer completes */
+ UART_CALLBK_T callback_func_pt; /*!< callback function pointer */
+ UART_DMA_REQ_T dma_req_func_pt; /*!< UART DMA channel setup function pointer, not applicable on LPC8xx */
+} UART_PARAM_T;
+
+/**
+ * @brief UART ROM driver APIs structure
+ */
+typedef struct UARTD_API {
+ /*!< UART Configuration functions */
+ uint32_t (*uart_get_mem_size)(void); /*!< Get the memory size needed by one Min UART instance */
+ UART_HANDLE_T * (*uart_setup)(uint32_t base_addr, uint8_t * ram); /*!< Setup Min UART instance with provided memory and return the handle to this instance */
+ uint32_t (*uart_init)(UART_HANDLE_T *handle, UART_CONFIG_T *set); /*!< Setup baud rate and operation mode for uart, then enable uart */
+
+ /*!< UART polling functions block until completed */
+ uint8_t (*uart_get_char)(UART_HANDLE_T *handle); /*!< Receive one Char from uart. This functions is only returned after Char is received. In case Echo is enabled, the received data is sent out immediately */
+ void (*uart_put_char)(UART_HANDLE_T *handle, uint8_t data); /*!< Send one Char through uart. This function is only returned after data is sent */
+ uint32_t (*uart_get_line)(UART_HANDLE_T *handle, UART_PARAM_T *param); /*!< Receive multiple bytes from UART */
+ uint32_t (*uart_put_line)(UART_HANDLE_T *handle, UART_PARAM_T *param); /*!< Send string (end with \0) or raw data through UART */
+
+ /*!< UART interrupt functions return immediately and callback when completed */
+ void (*uart_isr)(UART_HANDLE_T *handle); /*!< UART interrupt service routine. To use this routine, the corresponding USART interrupt must be enabled. This function is invoked by the user ISR */
+} UARTD_API_T;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ROM_UART_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/romapi_11u6x.h b/source/lpc_chip_11u6x/inc/romapi_11u6x.h
new file mode 100644
index 0000000..ef27fef
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/romapi_11u6x.h
@@ -0,0 +1,108 @@
+/*
+ * @brief LPC11xx ROM API declarations and functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __ROMAPI_11U6X_H_
+#define __ROMAPI_11U6X_H_
+
+#include "iap.h"
+#include "error.h"
+#include "rom_dma_11u6x.h"
+#include "rom_i2c_11u6x.h"
+#include "rom_pwr_11u6x.h"
+#include "rom_uart_11u6x.h"
+#include "romdiv_11u6x.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup ROMAPI_11U6X CHIP: LPC11U6X ROM API declarations and functions
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief LPC11U6X High level ROM API structure
+ */
+typedef struct {
+ const uint32_t usbdApiBase; /*!< USBD API function table base address */
+ const uint32_t reserved0; /*!< Reserved */
+ const uint32_t reserved1; /*!< Reserved */
+ const PWRD_API_T *pPWRD; /*!< Power API function table base address */
+ const ROM_DIV_API_T *divApiBase; /*!< Divider API function table base address */
+ const I2CD_API_T *pI2CD; /*!< I2C driver API function table base address */
+ const DMAD_API_T *pDMAD; /*!< DMA driver API function table base address */
+ const uint32_t reserved2; /*!< Reserved */
+ const uint32_t reserved3; /*!< Reserved */
+ const UARTD_API_T *pUARTND; /*!< USART 1/2/3/4 driver API function table base address */
+ const uint32_t reserved4; /*!< Reserved */
+ const UARTD_API_T *pUART0D; /*!< USART 0 driver API function table base address */
+} LPC_ROM_API_T;
+
+/* Pointer to ROM API function address */
+#define LPC_ROM_API_BASE_LOC 0x1FFF1FF8
+#define LPC_ROM_API (*(LPC_ROM_API_T * *) LPC_ROM_API_BASE_LOC)
+
+/* Pointer to @ref PWRD_API_T functions in ROM */
+#define LPC_PWRD_API ((LPC_ROM_API)->pPWRD)
+
+/* Pointer to @ref I2CD_API_T functions in ROM */
+#define LPC_I2CD_API ((LPC_ROM_API)->pI2CD)
+
+/* Pointer to @ref UARTD_API_T functions in ROM for UART 0 */
+#define LPC_UART0D_API ((LPC_ROM_API)->pUART0D)
+
+/* Pointer to @ref UARTD_API_T functions in ROM for UARTS 1-4 */
+#define LPC_UARTND_API ((LPC_ROM_API)->pUARTND)
+
+/* Pointer to @ref DMAD_API_T functions in ROM for DMA */
+#define LPC_DMAD_API ((LPC_ROM_API)->pDMAD)
+
+/* Pointer to ROM IAP entry functions */
+#define IAP_ENTRY_LOCATION 0X1FFF1FF1
+
+/**
+ * @brief LPC11U6X IAP_ENTRY API function type
+ */
+static INLINE void iap_entry(unsigned int cmd_param[5], unsigned int status_result[4])
+{
+ ((IAP_ENTRY_T) IAP_ENTRY_LOCATION)(cmd_param, status_result);
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ROMAPI_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/romdiv_11u6x.h b/source/lpc_chip_11u6x/inc/romdiv_11u6x.h
new file mode 100644
index 0000000..11b69d1
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/romdiv_11u6x.h
@@ -0,0 +1,81 @@
+/*
+ * @brief Routines to overload "/" and "%" operator in C using ROM based divider library
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __ROMDIV_11U6X_H_
+#define __ROMDIV_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup ROMAPI_DIV_11U6X ROM divider API declarations
+ * @ingroup ROMAPI_11U6X
+ * The ROM-based 32-bit integer division routines are available for all LPC11U6x.
+ * These routines are performance optimized and reduce application code space. As
+ * part of chip library these routines overload “/†and “%†operators in C.
+ * @{
+ */
+
+/**
+ * @brief Structure containing signed integer divider return data.
+ */
+typedef struct {
+ int quot; /*!< Quotient */
+ int rem; /*!< Reminder */
+} IDIV_RETURN_T;
+
+/**
+ * @brief Structure containing unsigned integer divider return data.
+ */
+typedef struct {
+ unsigned quot; /*!< Quotient */
+ unsigned rem; /*!< Reminder */
+} UIDIV_RETURN_T;
+
+/**
+ * @brief ROM divider API Structure.
+ */
+typedef struct {
+ int (*sidiv)(int numerator, int denominator); /*!< Signed integer division */
+ unsigned (*uidiv)(unsigned numerator, unsigned denominator); /*!< Unsigned integer division */
+ IDIV_RETURN_T (*sidivmod)(int numerator, int denominator); /*!< Signed integer division with remainder */
+ UIDIV_RETURN_T (*uidivmod)(unsigned numerator, unsigned denominator); /*!< Unsigned integer division with remainder */
+} ROM_DIV_API_T;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ROMDIV_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/rtc_11u6x.h b/source/lpc_chip_11u6x/inc/rtc_11u6x.h
new file mode 100644
index 0000000..a208a87
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/rtc_11u6x.h
@@ -0,0 +1,302 @@
+/*
+ * @brief LPC11u6x RTC chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __RTC_11U6X_H_
+#define __RTC_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup RTC_11U6X CHIP: LPC11u6x RTC driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief LPC11u6x RTC register block structure
+ */
+typedef struct { /*!< RTC */
+ __IO uint32_t CTRL; /*!< RTC control register */
+ __IO uint32_t MATCH; /*!< PRTC match (alarm) register */
+ __IO uint32_t COUNT; /*!< RTC counter register */
+ __IO uint32_t WAKE; /*!< RTC high-resolution/wake-up timer control register */
+} LPC_RTC_T;
+
+/* CTRL register defniitions */
+#define RTC_CTRL_SWRESET (1 << 0) /*!< Apply reset to RTC */
+#define RTC_CTRL_OFD (1 << 1) /*!< Oscillator fail detect status (failed bit) */
+#define RTC_CTRL_ALARM1HZ (1 << 2) /*!< RTC 1 Hz timer alarm flag status (match) bit */
+#define RTC_CTRL_WAKE1KHZ (1 << 3) /*!< RTC 1 kHz timer wake-up flag status (timeout) bit */
+#define RTC_CTRL_ALARMDPD_EN (1 << 4) /*!< RTC 1 Hz timer alarm for Deep power-down enable bit */
+#define RTC_CTRL_WAKEDPD_EN (1 << 5) /*!< RTC 1 kHz timer wake-up for Deep power-down enable bit */
+#define RTC_CTRL_RTC1KHZ_EN (1 << 6) /*!< RTC 1 kHz clock enable bit */
+#define RTC_CTRL_RTC_EN (1 << 7) /*!< RTC enable bit */
+
+/**
+ * @brief Initialize the RTC peripheral
+ * @param pRTC : RTC peripheral selected
+ * @return None
+ */
+void Chip_RTC_Init(LPC_RTC_T *pRTC);
+
+/**
+ * @brief De-initialize the RTC peripheral
+ * @param pRTC : RTC peripheral selected
+ * @return None
+ */
+void Chip_RTC_DeInit(LPC_RTC_T *pRTC);
+
+/**
+ * @brief Enable RTC options
+ * @param pRTC : The base address of RTC block
+ * @param flags : And OR'ed value of RTC_CTRL_* definitions to enable
+ * @return Nothing
+ * @note You can enable multiple RTC options at once using this function
+ * by OR'ing them together. It is recommended to only use the
+ * RTC_CTRL_ALARMDPD_EN, RTC_CTRL_WAKEDPD_EN, RTC_CTRL_RTC1KHZ_EN, and
+ * RTC_CTRL_RTC_EN flags with this function.
+ */
+STATIC INLINE void Chip_RTC_EnableOptions(LPC_RTC_T *pRTC, uint32_t flags)
+{
+ pRTC->CTRL |= flags;
+}
+
+/**
+ * @brief Disable RTC options
+ * @param pRTC : The base address of RTC block
+ * @param flags : And OR'ed value of RTC_CTRL_* definitions to disable
+ * @return Nothing
+ * @note You can enable multiple RTC options at once using this function
+ * by OR'ing them together. It is recommended to only use the
+ * RTC_CTRL_ALARMDPD_EN, RTC_CTRL_WAKEDPD_EN, RTC_CTRL_RTC1KHZ_EN, and
+ * RTC_CTRL_RTC_EN flags with this function.
+ */
+STATIC INLINE void Chip_RTC_DisableOptions(LPC_RTC_T *pRTC, uint32_t flags)
+{
+ pRTC->CTRL &= ~flags;
+}
+
+/**
+ * @brief Reset RTC
+ * @param pRTC : The base address of RTC block
+ * @return Nothing
+ * @note The RTC state will be returned to it's default.
+ */
+STATIC INLINE void Chip_RTC_Reset(LPC_RTC_T *pRTC)
+{
+ Chip_RTC_EnableOptions(pRTC, RTC_CTRL_SWRESET);
+ Chip_RTC_DisableOptions(pRTC, RTC_CTRL_SWRESET);
+}
+
+/**
+ * @brief Enables the RTC
+ * @param pRTC : The base address of RTC block
+ * @return Nothing
+ * @note You can also use Chip_RTC_EnableOptions() with the
+ * RTC_CTRL_RTC_EN flag to enable the RTC.
+ */
+STATIC INLINE void Chip_RTC_Enable(LPC_RTC_T *pRTC)
+{
+ Chip_RTC_EnableOptions(pRTC, RTC_CTRL_RTC_EN);
+}
+
+/**
+ * @brief Disables the RTC
+ * @param pRTC : The base address of RTC block
+ * @return Nothing
+ * @note You can also use Chip_RTC_DisableOptions() with the
+ * RTC_CTRL_RTC_EN flag to enable the RTC.
+ */
+STATIC INLINE void Chip_RTC_Disable(LPC_RTC_T *pRTC)
+{
+ Chip_RTC_DisableOptions(pRTC, RTC_CTRL_RTC_EN);
+}
+
+/**
+ * @brief Enables the RTC 1KHz high resolution timer
+ * @param pRTC : The base address of RTC block
+ * @return Nothing
+ * @note You can also use Chip_RTC_EnableOptions() with the
+ * RTC_CTRL_RTC1KHZ_EN flag to enable the high resolution
+ * timer.
+ */
+STATIC INLINE void Chip_RTC_Enable1KHZ(LPC_RTC_T *pRTC)
+{
+ Chip_RTC_EnableOptions(pRTC, RTC_CTRL_RTC1KHZ_EN);
+}
+
+/**
+ * @brief Disables the RTC 1KHz high resolution timer
+ * @param pRTC : The base address of RTC block
+ * @return Nothing
+ * @note You can also use Chip_RTC_DisableOptions() with the
+ * RTC_CTRL_RTC1KHZ_EN flag to disable the high resolution
+ * timer.
+ */
+STATIC INLINE void Chip_RTC_Disable1KHZ(LPC_RTC_T *pRTC)
+{
+ Chip_RTC_DisableOptions(pRTC, RTC_CTRL_RTC1KHZ_EN);
+}
+
+/**
+ * @brief Enables selected RTC wakeup events
+ * @param pRTC : The base address of RTC block
+ * @param ints : Wakeup events to enable
+ * @return Nothing
+ * @note Select either one or both (OR'ed) RTC_CTRL_ALARMDPD_EN
+ * and RTC_CTRL_WAKEDPD_EN values to enabled. You can also
+ * use Chip_RTC_EnableOptions() with the flags to enable
+ * the events.
+ */
+STATIC INLINE void Chip_RTC_EnableWakeup(LPC_RTC_T *pRTC, uint32_t ints)
+{
+ Chip_RTC_EnableOptions(pRTC, ints);
+}
+
+/**
+ * @brief Disables selected RTC wakeup events
+ * @param pRTC : The base address of RTC block
+ * @param ints : Wakeup events to disable
+ * @return Nothing
+ * @note Select either one or both (OR'ed) RTC_CTRL_ALARMDPD_EN
+ * and RTC_CTRL_WAKEDPD_EN values to disabled. You can also
+ * use Chip_RTC_DisableOptions() with the flags to disable
+ * the events.
+ */
+STATIC INLINE void Chip_RTC_DisableWakeup(LPC_RTC_T *pRTC, uint32_t ints)
+{
+ Chip_RTC_DisableOptions(pRTC, ints);
+}
+
+/**
+ * @brief Clears latched RTC statuses
+ * @param pRTC : The base address of RTC block
+ * @param stsMask : OR'ed status bits to clear
+ * @return Nothing
+ * @note Use and OR'ed stsMask value of RTC_CTRL_OFD, RTC_CTRL_ALARM1HZ,
+ * and RTC_CTRL_WAKE1KHZ to clear specific RTC states.
+ */
+STATIC INLINE uint32_t Chip_RTC_ClearStatus(LPC_RTC_T *pRTC, uint32_t stsMask)
+{
+ return pRTC->CTRL;
+}
+
+/**
+ * @brief Return RTC control/status register
+ * @param pRTC : The base address of RTC block
+ * @return The current RTC control/status register
+ * @note Mask the return value with a RTC_CTRL_* definitions to determine
+ * which bits are set. For example, mask the return value with
+ * RTC_CTRL_ALARM1HZ to determine if the alarm interrupt is pending.
+ */
+STATIC INLINE uint32_t Chip_RTC_GetStatus(LPC_RTC_T *pRTC)
+{
+ return pRTC->CTRL;
+}
+
+/**
+ * @brief Set RTC match value for alarm status/interrupt
+ * @param pRTC : The base address of RTC block
+ * @param count : Alarm event time
+ * @return Nothing
+ */
+STATIC INLINE void Chip_RTC_SetAlarm(LPC_RTC_T *pRTC, uint32_t count)
+{
+ pRTC->MATCH = count;
+}
+
+/**
+ * @brief Return the RTC match value used for alarm status/interrupt
+ * @param pRTC : The base address of RTC block
+ * @return Alarm event time
+ */
+STATIC INLINE uint32_t Chip_RTC_GetAlarm(LPC_RTC_T *pRTC)
+{
+ return pRTC->MATCH;
+}
+
+/**
+ * @brief Set RTC match count for 1 second timer count
+ * @param pRTC : The base address of RTC block
+ * @param count : Initial count to set
+ * @return Nothing
+ * @note Only write to this register when the RTC_CTRL_RTC_EN bit in
+ * the CTRL Register is 0. The counter increments one second
+ * after the RTC_CTRL_RTC_EN bit is set.
+ */
+STATIC INLINE void Chip_RTC_SetCount(LPC_RTC_T *pRTC, uint32_t count)
+{
+ pRTC->COUNT = count;
+}
+
+/**
+ * @brief Get current RTC 1 second timer count
+ * @param pRTC : The base address of RTC block
+ * @return current RTC 1 second timer count
+ */
+STATIC INLINE uint32_t Chip_RTC_GetCount(LPC_RTC_T *pRTC)
+{
+ return pRTC->COUNT;
+}
+
+/**
+ * @brief Set RTC wake count countdown value (in mS ticks)
+ * @param pRTC : The base address of RTC block
+ * @param count : wakeup time in milliSeconds
+ * @return Nothing
+ * @note A write pre-loads a start count value into the wake-up
+ * timer and initializes a count-down sequence.
+ */
+STATIC INLINE void Chip_RTC_SetWake(LPC_RTC_T *pRTC, uint16_t count)
+{
+ pRTC->WAKE = count;
+}
+
+/**
+ * @brief Get RTC wake count countdown value
+ * @param pRTC : The base address of RTC block
+ * @return current RTC wake count countdown value (in mS)
+ */
+STATIC INLINE uint16_t Chip_RTC_GetWake(LPC_RTC_T *pRTC)
+{
+ return pRTC->WAKE;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RTC_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/sct_11u6x.h b/source/lpc_chip_11u6x/inc/sct_11u6x.h
new file mode 100644
index 0000000..292bc4e
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/sct_11u6x.h
@@ -0,0 +1,440 @@
+/*
+ * @brief LPC11u6x State Configurable Timer (SCT) Chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licenser disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __SCT_11U6X_H_
+#define __SCT_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup SCT_11U6X CHIP: LPC11u6x State Configurable Timer driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/*
+ * @brief SCT Module configuration
+ */
+#define CONFIG_SCT_nEV (6) /*!< Number of events */
+#define CONFIG_SCT_nRG (5) /*!< Number of match/compare registers */
+#define CONFIG_SCT_nOU (4) /*!< Number of outputs */
+
+/**
+ * @brief State Configurable Timer register block structure
+ */
+typedef struct {
+ __IO uint32_t CONFIG; /*!< Configuration Register */
+ union {
+ __IO uint32_t CTRL_U; /*!< Control Register */
+ struct {
+ __IO uint16_t CTRL_L; /*!< Low control register */
+ __IO uint16_t CTRL_H; /*!< High control register */
+ };
+
+ };
+
+ union {
+ __IO uint32_t LIMIT; /*!< limit Register */
+ struct {
+ __IO uint16_t LIMIT_L; /*!< limit register for counter L */
+ __IO uint16_t LIMIT_H; /*!< limit register for counter H */
+ };
+
+ };
+
+ union {
+ __IO uint32_t HALT; /*!< Halt Register */
+ struct {
+ __IO uint16_t HALT_L; /*!< halt register for counter L */
+ __IO uint16_t HALT_H; /*!< halt register for counter H */
+ };
+
+ };
+
+ union {
+ __IO uint32_t STOP; /*!< Stop Register */
+ struct {
+ __IO uint16_t STOP_L; /*!< stop register for counter L */
+ __IO uint16_t STOP_H; /*!< stop register for counter H */
+ };
+
+ };
+
+ union {
+ __IO uint32_t START; /*!< start Register */
+ struct {
+ __IO uint16_t START_L; /*!< start register for counter L */
+ __IO uint16_t START_H; /*!< start register for counter H */
+ };
+
+ };
+
+ uint32_t RESERVED1[10]; /*!< 0x03C reserved */
+ union {
+ __IO uint32_t COUNT_U; /*!< counter register */
+ struct {
+ __IO uint16_t COUNT_L; /*!< counter register for counter L */
+ __IO uint16_t COUNT_H; /*!< counter register for counter H */
+ };
+
+ };
+
+ union {
+ __IO uint32_t STATE; /*!< State register */
+ struct {
+ __IO uint16_t STATE_L; /*!< state register for counter L */
+ __IO uint16_t STATE_H; /*!< state register for counter H */
+ };
+
+ };
+
+ __I uint32_t INPUT; /*!< input register */
+ union {
+ __IO uint32_t REGMODE; /*!< RegMode register */
+ struct {
+ __IO uint16_t REGMODE_L; /*!< match - capture registers mode register L */
+ __IO uint16_t REGMODE_H; /*!< match - capture registers mode register H */
+ };
+
+ };
+
+ __IO uint32_t OUTPUT; /*!< output register */
+ __IO uint32_t OUTPUTDIRCTRL; /*!< output counter direction Control Register */
+ __IO uint32_t RES; /*!< conflict resolution register */
+ __IO uint32_t DMA0REQUEST; /*!< DMA0 Request Register */
+ __IO uint32_t DMA1REQUEST; /*!< DMA1 Request Register */
+ uint32_t RESERVED2[35];
+ __IO uint32_t EVEN; /*!< event enable register */
+ __IO uint32_t EVFLAG; /*!< event flag register */
+ __IO uint32_t CONEN; /*!< conflict enable register */
+ __IO uint32_t CONFLAG; /*!< conflict flag register */
+ union {
+ __IO union { /*!< ... Match / Capture value */
+ uint32_t U; /*!< SCTMATCH[i].U Unified 32-bit register */
+ struct {
+ uint16_t L; /*!< SCTMATCH[i].L Access to L value */
+ uint16_t H; /*!< SCTMATCH[i].H Access to H value */
+ };
+
+ } MATCH[CONFIG_SCT_nRG];
+
+ __I union {
+ uint32_t U; /*!< SCTCAP[i].U Unified 32-bit register */
+ struct {
+ uint16_t L; /*!< SCTCAP[i].L Access to L value */
+ uint16_t H; /*!< SCTCAP[i].H Access to H value */
+ };
+
+ } CAP[CONFIG_SCT_nRG];
+
+ };
+
+ uint32_t RESERVED3[64 - CONFIG_SCT_nRG]; /*!< ...-0x1FC reserved */
+
+ union {
+ __IO union { /*!< ... Match reload value */
+ uint32_t U; /*!< MATCHREL[i].U Unified 32-bit register */
+ struct {
+ uint16_t L; /*!< MATCHREL[i].L Access to L value */
+ uint16_t H; /*!< MATCHREL[i].H Access to H value */
+ };
+
+ } MATCHREL[CONFIG_SCT_nRG];
+
+ __I union {
+ uint32_t U; /*!< CAPCTRL[i].U Unified 32-bit register */
+ struct {
+ uint16_t L; /*!< CAPCTRL[i].L Access to L value */
+ uint16_t H; /*!< CAPCTRL[i].H Access to H value */
+ };
+
+ } CAPCTRL[CONFIG_SCT_nRG];
+
+ };
+
+ uint32_t RESERVED4[64 - CONFIG_SCT_nRG]; /*!< ...-0x2FC reserved */
+
+ __IO struct { /*!< SCTEVENT[i].STATE / SCTEVENT[i].CTRL*/
+ uint32_t STATE; /*!< Event State Register */
+ uint32_t CTRL; /*!< Event Control Register */
+ } EVENT[CONFIG_SCT_nEV];
+
+ uint32_t RESERVED9[128 - 2 * CONFIG_SCT_nEV]; /*!< ...-0x4FC reserved */
+ __IO struct { /*!< SCTOUT[i].SET / SCTOUT[i].CLR */
+ uint32_t SET; /*!< Output n Set Register */
+ uint32_t CLR; /*!< Output n Clear Register */
+ } OUT[CONFIG_SCT_nOU];
+
+} LPC_SCT_T;
+
+/*
+ * @brief Macro defines for SCT configuration register
+ */
+#define SCT_CONFIG_16BIT_COUNTER 0x00000000 /*!< Operate as 2 16-bit counters */
+#define SCT_CONFIG_32BIT_COUNTER 0x00000001 /*!< Operate as 1 32-bit counter */
+
+#define SCT_CONFIG_CLKMODE_BUSCLK (0x0 << 1) /*!< Bus clock */
+#define SCT_CONFIG_CLKMODE_SCTCLK (0x1 << 1) /*!< SCT clock */
+#define SCT_CONFIG_CLKMODE_INCLK (0x2 << 1) /*!< Input clock selected in CLKSEL field */
+#define SCT_CONFIG_CLKMODE_INEDGECLK (0x3 << 1) /*!< Input clock edge selected in CLKSEL field */
+
+#define SCT_CONFIG_NORELOADL_U (0x1 << 7) /*!< Operate as 1 32-bit counter */
+#define SCT_CONFIG_NORELOADH (0x1 << 8) /*!< Operate as 1 32-bit counter */
+
+/*
+ * @brief Macro defines for SCT control register
+ */
+#define COUNTUP_TO_LIMIT_THEN_CLEAR_TO_ZERO 0 /*!< Direction for low or unified counter */
+#define COUNTUP_TO LIMIT_THEN_COUNTDOWN_TO_ZERO 1
+
+#define SCT_CTRL_STOP_L (1 << 1) /*!< Stop low counter */
+#define SCT_CTRL_HALT_L (1 << 2) /*!< Halt low counter */
+#define SCT_CTRL_CLRCTR_L (1 << 3) /*!< Clear low or unified counter */
+#define SCT_CTRL_BIDIR_L(x) (((x) & 0x01) << 4) /*!< Bidirectional bit */
+#define SCT_CTRL_PRE_L(x) (((x) & 0xFF) << 5) /*!< Prescale clock for low or unified counter */
+
+#define COUNTUP_TO_LIMIT_THEN_CLEAR_TO_ZERO 0 /*!< Direction for high counter */
+#define COUNTUP_TO LIMIT_THEN_COUNTDOWN_TO_ZERO 1
+#define SCT_CTRL_STOP_H (1 << 17) /*!< Stop high counter */
+#define SCT_CTRL_HALT_H (1 << 18) /*!< Halt high counter */
+#define SCT_CTRL_CLRCTR_H (1 << 19) /*!< Clear high counter */
+#define SCT_CTRL_BIDIR_H(x) (((x) & 0x01) << 20)
+#define SCT_CTRL_PRE_H(x) (((x) & 0xFF) << 21) /*!< Prescale clock for high counter */
+
+/*
+ * @brief Macro defines for SCT Conflict resolution register
+ */
+#define SCT_RES_NOCHANGE (0)
+#define SCT_RES_SET_OUTPUT (1)
+#define SCT_RES_CLEAR_OUTPUT (2)
+#define SCT_RES_TOGGLE_OUTPUT (3)
+
+/**
+ * SCT Match register values enum
+ */
+typedef enum CHIP_SCT_MATCH_REG {
+ SCT_MATCH_0 = 0, /*!< SCT Match register 0 */
+ SCT_MATCH_1 = 1, /*!< SCT Match register 1 */
+ SCT_MATCH_2 = 2, /*!< SCT Match register 2 */
+ SCT_MATCH_3 = 3, /*!< SCT Match register 3 */
+ SCT_MATCH_4 = 4 /*!< SCT Match register 4 */
+} CHIP_SCT_MATCH_REG_T;
+
+/**
+ * SCT Event values enum
+ */
+typedef enum CHIP_SCT_EVENT {
+ SCT_EVT_0 = (1 << 0), /*!< Event 0 */
+ SCT_EVT_1 = (1 << 1), /*!< Event 1 */
+ SCT_EVT_2 = (1 << 2), /*!< Event 2 */
+ SCT_EVT_3 = (1 << 3), /*!< Event 3 */
+ SCT_EVT_4 = (1 << 4), /*!< Event 4 */
+ SCT_EVT_5 = (1 << 5) /*!< Event 5 */
+} CHIP_SCT_EVENT_T;
+
+/**
+ * @brief Configures the State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param value : The 32-bit CONFIG register value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_Config(LPC_SCT_T *pSCT, uint32_t value)
+{
+ pSCT->CONFIG = value;
+}
+
+/**
+ * @brief Set or Clear the Control register
+ * @param pSCT : Pointer to SCT register block
+ * @param value : SCT Control register value
+ * @param ena : ENABLE - To set the fields specified by value
+ * : DISABLE - To clear the field specified by value
+ * @return Nothing
+ * Set or clear the control register bits as specified by the \a value
+ * parameter. If \a ena is set to ENABLE, the mentioned register fields
+ * will be set. If \a ena is set to DISABLE, the mentioned register
+ * fields will be cleared
+ */
+void Chip_SCT_SetClrControl(LPC_SCT_T *pSCT, uint32_t value, FunctionalState ena);
+
+/**
+ * @brief Set the conflict resolution
+ * @param pSCT : Pointer to SCT register block
+ * @param outnum : Output number
+ * @param value : Output value
+ * - SCT_RES_NOCHANGE :No change
+ * - SCT_RES_SET_OUTPUT :Set output
+ * - SCT_RES_CLEAR_OUTPUT :Clear output
+ * - SCT_RES_TOGGLE_OUTPUT :Toggle output
+ * : SCT_RES_NOCHANGE
+ * : DISABLE - To clear the field specified by value
+ * @return Nothing
+ * Set conflict resolution for the output \a outnum
+ */
+void Chip_SCT_SetConflictResolution(LPC_SCT_T *pSCT, uint8_t outnum, uint8_t value);
+
+/**
+ * @brief Set unified count value in State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param count : The 32-bit count value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_SetCount(LPC_SCT_T *pSCT, uint32_t count)
+{
+ pSCT->COUNT_U = count;
+}
+
+/**
+ * @brief Set lower count value in State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param count : The 16-bit count value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_SetCountL(LPC_SCT_T *pSCT, uint16_t count)
+{
+ pSCT->COUNT_L = count;
+}
+
+/**
+ * @brief Set higher count value in State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param count : The 16-bit count value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_SetCountH(LPC_SCT_T *pSCT, uint16_t count)
+{
+ pSCT->COUNT_H = count;
+}
+
+/**
+ * @brief Set unified match count value in State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param n : Match register value
+ * @param value : The 32-bit match count value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_SetMatchCount(LPC_SCT_T *pSCT, CHIP_SCT_MATCH_REG_T n, uint32_t value)
+{
+ pSCT->MATCH[n].U = value;
+}
+
+/**
+ * @brief Set unified match reload count value in State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param n : Match register value
+ * @param value : The 32-bit match count reload value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_SetMatchReload(LPC_SCT_T *pSCT, CHIP_SCT_MATCH_REG_T n, uint32_t value)
+{
+ pSCT->MATCHREL[n].U = value;
+}
+
+/**
+ * @brief Enable the interrupt for the specified event in State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param evt : Event value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_EnableEventInt(LPC_SCT_T *pSCT, CHIP_SCT_EVENT_T evt)
+{
+ pSCT->EVEN |= evt;
+}
+
+/**
+ * @brief Disable the interrupt for the specified event in State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param evt : Event value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_DisableEventInt(LPC_SCT_T *pSCT, CHIP_SCT_EVENT_T evt)
+{
+ pSCT->EVEN &= ~(evt);
+}
+
+/**
+ * @brief Clear the specified event flag in State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param evt : Event value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_ClearEventFlag(LPC_SCT_T *pSCT, CHIP_SCT_EVENT_T evt)
+{
+ pSCT->EVFLAG |= evt;
+}
+
+/**
+ * @brief Set control register in State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param value : Value (ORed value of SCT_CTRL_* bits)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_SetControl(LPC_SCT_T *pSCT, uint32_t value)
+{
+ pSCT->CTRL_U |= value;
+}
+
+/**
+ * @brief Clear control register in State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @param value : Value (ORed value of SCT_CTRL_* bits)
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SCT_ClearControl(LPC_SCT_T *pSCT, uint32_t value)
+{
+ pSCT->CTRL_U &= ~(value);
+}
+
+/**
+ * @brief Initializes the State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @return Nothing
+ */
+void Chip_SCT_Init(LPC_SCT_T *pSCT);
+
+/**
+ * @brief Deinitializes the State Configurable Timer
+ * @param pSCT : The base of SCT peripheral on the chip
+ * @return Nothing
+ */
+void Chip_SCT_DeInit(LPC_SCT_T *pSCT);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+
+#endif
+
+#endif /* __SCT_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/ssp_11u6x.h b/source/lpc_chip_11u6x/inc/ssp_11u6x.h
new file mode 100644
index 0000000..66798b3
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/ssp_11u6x.h
@@ -0,0 +1,572 @@
+/*
+ * @brief LPC11u6x SSP Registers and control functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __SSP_11U6X_H_
+#define __SSP_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup SSP_11U6X CHIP: LPC11u6x SSP register block and driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief SSP register block structure
+ */
+typedef struct { /*!< SSPn Structure */
+ __IO uint32_t CR0; /*!< Control Register 0. Selects the serial clock rate, bus type, and data size. */
+ __IO uint32_t CR1; /*!< Control Register 1. Selects master/slave and other modes. */
+ __IO uint32_t DR; /*!< Data Register. Writes fill the transmit FIFO, and reads empty the receive FIFO. */
+ __I uint32_t SR; /*!< Status Register */
+ __IO uint32_t CPSR; /*!< Clock Prescale Register */
+ __IO uint32_t IMSC; /*!< Interrupt Mask Set and Clear Register */
+ __I uint32_t RIS; /*!< Raw Interrupt Status Register */
+ __I uint32_t MIS; /*!< Masked Interrupt Status Register */
+ __O uint32_t ICR; /*!< SSPICR Interrupt Clear Register */
+ __O uint32_t DMACR; /*!< DMA control Register */
+} LPC_SSP_T;
+
+/**
+ * Macro defines for CR0 register
+ */
+
+/** SSP data size select, must be 4 bits to 16 bits */
+#define SSP_CR0_DSS(n) ((uint32_t) ((n) & 0xF))
+/** SSP control 0 Motorola SPI mode */
+#define SSP_CR0_FRF_SPI ((uint32_t) (0 << 4))
+/** SSP control 0 TI synchronous serial mode */
+#define SSP_CR0_FRF_TI ((uint32_t) (1 << 4))
+/** SSP control 0 National Micro-wire mode */
+#define SSP_CR0_FRF_MICROWIRE ((uint32_t) (2 << 4))
+/** SPI clock polarity bit (used in SPI mode only), (1) = maintains the
+ bus clock high between frames, (0) = low */
+#define SSP_CR0_CPOL_LO ((uint32_t) (0))
+#define SSP_CR0_CPOL_HI ((uint32_t) (1 << 6))
+/** SPI clock out phase bit (used in SPI mode only), (1) = captures data
+ on the second clock transition of the frame, (0) = first */
+#define SSP_CR0_CPHA_FIRST ((uint32_t) (0))
+#define SSP_CR0_CPHA_SECOND ((uint32_t) (1 << 7))
+/** SSP serial clock rate value load macro, divider rate is
+ PERIPH_CLK / (cpsr * (SCR + 1)) */
+#define SSP_CR0_SCR(n) ((uint32_t) ((n & 0xFF) << 8))
+/** SSP CR0 bit mask */
+#define SSP_CR0_BITMASK ((uint32_t) (0xFFFF))
+/** SSP CR0 bit mask */
+#define SSP_CR0_BITMASK ((uint32_t) (0xFFFF))
+/** SSP serial clock rate value load macro, divider rate is
+ PERIPH_CLK / (cpsr * (SCR + 1)) */
+#define SSP_CR0_SCR(n) ((uint32_t) ((n & 0xFF) << 8))
+
+/**
+ * Macro defines for CR1 register
+ */
+
+/** SSP control 1 loopback mode enable bit */
+#define SSP_CR1_LBM_EN ((uint32_t) (1 << 0))
+/** SSP control 1 enable bit */
+#define SSP_CR1_SSP_EN ((uint32_t) (1 << 1))
+/** SSP control 1 slave enable */
+#define SSP_CR1_SLAVE_EN ((uint32_t) (1 << 2))
+#define SSP_CR1_MASTER_EN ((uint32_t) (0))
+/** SSP control 1 slave out disable bit, disables transmit line in slave
+ mode */
+#define SSP_CR1_SO_DISABLE ((uint32_t) (1 << 3))
+/** SSP CR1 bit mask */
+#define SSP_CR1_BITMASK ((uint32_t) (0x0F))
+
+/** SSP CPSR bit mask */
+#define SSP_CPSR_BITMASK ((uint32_t) (0xFF))
+/**
+ * Macro defines for DR register
+ */
+
+/** SSP data bit mask */
+#define SSP_DR_BITMASK(n) ((n) & 0xFFFF)
+
+/**
+ * Macro defines for SR register
+ */
+
+/** SSP SR bit mask */
+#define SSP_SR_BITMASK ((uint32_t) (0x1F))
+
+/** ICR bit mask */
+#define SSP_ICR_BITMASK ((uint32_t) (0x03))
+
+/**
+ * @brief SSP Type of Status
+ */
+typedef enum _SSP_STATUS {
+ SSP_STAT_TFE = ((uint32_t)(1 << 0)),/**< TX FIFO Empty */
+ SSP_STAT_TNF = ((uint32_t)(1 << 1)),/**< TX FIFO not full */
+ SSP_STAT_RNE = ((uint32_t)(1 << 2)),/**< RX FIFO not empty */
+ SSP_STAT_RFF = ((uint32_t)(1 << 3)),/**< RX FIFO full */
+ SSP_STAT_BSY = ((uint32_t)(1 << 4)),/**< SSP Busy */
+} SSP_STATUS_T;
+
+/**
+ * @brief SSP Type of Interrupt Mask
+ */
+typedef enum _SSP_INTMASK {
+ SSP_RORIM = ((uint32_t)(1 << 0)), /**< Overun */
+ SSP_RTIM = ((uint32_t)(1 << 1)),/**< TimeOut */
+ SSP_RXIM = ((uint32_t)(1 << 2)),/**< Rx FIFO is at least half full */
+ SSP_TXIM = ((uint32_t)(1 << 3)),/**< Tx FIFO is at least half empty */
+ SSP_INT_MASK_BITMASK = ((uint32_t)(0xF)),
+} SSP_INTMASK_T;
+
+/**
+ * @brief SSP Type of Mask Interrupt Status
+ */
+typedef enum _SSP_MASKINTSTATUS {
+ SSP_RORMIS = ((uint32_t)(1 << 0)), /**< Overun */
+ SSP_RTMIS = ((uint32_t)(1 << 1)), /**< TimeOut */
+ SSP_RXMIS = ((uint32_t)(1 << 2)), /**< Rx FIFO is at least half full */
+ SSP_TXMIS = ((uint32_t)(1 << 3)), /**< Tx FIFO is at least half empty */
+ SSP_MASK_INT_STAT_BITMASK = ((uint32_t)(0xF)),
+} SSP_MASKINTSTATUS_T;
+
+/**
+ * @brief SSP Type of Raw Interrupt Status
+ */
+typedef enum _SSP_RAWINTSTATUS {
+ SSP_RORRIS = ((uint32_t)(1 << 0)), /**< Overun */
+ SSP_RTRIS = ((uint32_t)(1 << 1)), /**< TimeOut */
+ SSP_RXRIS = ((uint32_t)(1 << 2)), /**< Rx FIFO is at least half full */
+ SSP_TXRIS = ((uint32_t)(1 << 3)), /**< Tx FIFO is at least half empty */
+ SSP_RAW_INT_STAT_BITMASK = ((uint32_t)(0xF)),
+} SSP_RAWINTSTATUS_T;
+
+typedef enum _SSP_INTCLEAR {
+ SSP_RORIC = 0x0,
+ SSP_RTIC = 0x1,
+ SSP_INT_CLEAR_BITMASK = 0x3,
+} SSP_INTCLEAR_T;
+
+/*
+ * @brief SSP clock format
+ */
+typedef enum CHIP_SSP_CLOCK_FORMAT {
+ SSP_CLOCK_CPHA0_CPOL0 = (0 << 6), /**< CPHA = 0, CPOL = 0 */
+ SSP_CLOCK_CPHA0_CPOL1 = (1u << 6), /**< CPHA = 0, CPOL = 1 */
+ SSP_CLOCK_CPHA1_CPOL0 = (2u << 6), /**< CPHA = 1, CPOL = 0 */
+ SSP_CLOCK_CPHA1_CPOL1 = (3u << 6), /**< CPHA = 1, CPOL = 1 */
+ SSP_CLOCK_MODE0 = SSP_CLOCK_CPHA0_CPOL0,/**< alias */
+ SSP_CLOCK_MODE1 = SSP_CLOCK_CPHA1_CPOL0,/**< alias */
+ SSP_CLOCK_MODE2 = SSP_CLOCK_CPHA0_CPOL1,/**< alias */
+ SSP_CLOCK_MODE3 = SSP_CLOCK_CPHA1_CPOL1,/**< alias */
+} CHIP_SSP_CLOCK_MODE_T;
+
+/*
+ * @brief SSP frame format
+ */
+typedef enum CHIP_SSP_FRAME_FORMAT {
+ SSP_FRAMEFORMAT_SPI = (0 << 4), /**< Frame format: SPI */
+ CHIP_SSP_FRAME_FORMAT_TI = (1u << 4), /**< Frame format: TI SSI */
+ SSP_FRAMEFORMAT_MICROWIRE = (2u << 4), /**< Frame format: Microwire */
+} CHIP_SSP_FRAME_FORMAT_T;
+
+/*
+ * @brief Number of bits per frame
+ */
+typedef enum CHIP_SSP_BITS {
+ SSP_BITS_4 = (3u << 0), /*!< 4 bits/frame */
+ SSP_BITS_5 = (4u << 0), /*!< 5 bits/frame */
+ SSP_BITS_6 = (5u << 0), /*!< 6 bits/frame */
+ SSP_BITS_7 = (6u << 0), /*!< 7 bits/frame */
+ SSP_BITS_8 = (7u << 0), /*!< 8 bits/frame */
+ SSP_BITS_9 = (8u << 0), /*!< 9 bits/frame */
+ SSP_BITS_10 = (9u << 0), /*!< 10 bits/frame */
+ SSP_BITS_11 = (10u << 0), /*!< 11 bits/frame */
+ SSP_BITS_12 = (11u << 0), /*!< 12 bits/frame */
+ SSP_BITS_13 = (12u << 0), /*!< 13 bits/frame */
+ SSP_BITS_14 = (13u << 0), /*!< 14 bits/frame */
+ SSP_BITS_15 = (14u << 0), /*!< 15 bits/frame */
+ SSP_BITS_16 = (15u << 0), /*!< 16 bits/frame */
+} CHIP_SSP_BITS_T;
+
+/*
+ * @brief SSP config format
+ */
+typedef struct SSP_ConfigFormat {
+ CHIP_SSP_BITS_T bits; /*!< Format config: bits/frame */
+ CHIP_SSP_CLOCK_MODE_T clockMode; /*!< Format config: clock phase/polarity */
+ CHIP_SSP_FRAME_FORMAT_T frameFormat; /*!< Format config: SPI/TI/Microwire */
+} SSP_ConfigFormat;
+
+/**
+ * @brief Enable SSP operation
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SSP_Enable(LPC_SSP_T *pSSP)
+{
+ pSSP->CR1 |= SSP_CR1_SSP_EN;
+}
+
+/**
+ * @brief Disable SSP operation
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SSP_Disable(LPC_SSP_T *pSSP)
+{
+ pSSP->CR1 &= (~SSP_CR1_SSP_EN) & SSP_CR1_BITMASK;
+}
+
+/**
+ * @brief Enable loopback mode
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @return Nothing
+ * @note Serial input is taken from the serial output (MOSI or MISO) rather
+ * than the serial input pin
+ */
+STATIC INLINE void Chip_SSP_EnableLoopBack(LPC_SSP_T *pSSP)
+{
+ pSSP->CR1 |= SSP_CR1_LBM_EN;
+}
+
+/**
+ * @brief Disable loopback mode
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @return Nothing
+ * @note Serial input is taken from the serial output (MOSI or MISO) rather
+ * than the serial input pin
+ */
+STATIC INLINE void Chip_SSP_DisableLoopBack(LPC_SSP_T *pSSP)
+{
+ pSSP->CR1 &= (~SSP_CR1_LBM_EN) & SSP_CR1_BITMASK;
+}
+
+/**
+ * @brief Get the current status of SSP controller
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @param Stat : Type of status, should be :
+ * - SSP_STAT_TFE
+ * - SSP_STAT_TNF
+ * - SSP_STAT_RNE
+ * - SSP_STAT_RFF
+ * - SSP_STAT_BSY
+ * @return SSP controller status, SET or RESET
+ */
+STATIC INLINE FlagStatus Chip_SSP_GetStatus(LPC_SSP_T *pSSP, SSP_STATUS_T Stat)
+{
+ return (pSSP->SR & Stat) ? SET : RESET;
+}
+
+/**
+ * @brief Get the masked interrupt status
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @return SSP Masked Interrupt Status Register value
+ * @note The return value contains a 1 for each interrupt condition that is asserted and enabled (masked)
+ */
+STATIC INLINE uint32_t Chip_SSP_GetIntStatus(LPC_SSP_T *pSSP)
+{
+ return pSSP->MIS;
+}
+
+/**
+ * @brief Get the raw interrupt status
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @param RawInt : Interrupt condition to be get status, shoud be :
+ * - SSP_RORRIS
+ * - SSP_RTRIS
+ * - SSP_RXRIS
+ * - SSP_TXRIS
+ * @return Raw interrupt status corresponding to interrupt condition , SET or RESET
+ * @note Get the status of each interrupt condition ,regardless of whether or not the interrupt is enabled
+ */
+STATIC INLINE IntStatus Chip_SSP_GetRawIntStatus(LPC_SSP_T *pSSP, SSP_RAWINTSTATUS_T RawInt)
+{
+ return (pSSP->RIS & RawInt) ? SET : RESET;
+}
+
+/**
+ * @brief Get the number of bits transferred in each frame
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @return the number of bits transferred in each frame minus one
+ * @note The return value is 0x03 -> 0xF corresponding to 4bit -> 16bit transfer
+ */
+STATIC INLINE uint8_t Chip_SSP_GetDataSize(LPC_SSP_T *pSSP)
+{
+ return SSP_CR0_DSS(pSSP->CR0);
+}
+
+/**
+ * @brief Clear the corresponding interrupt condition(s) in the SSP controller
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @param IntClear: Type of cleared interrupt, should be :
+ * - SSP_RORIC
+ * - SSP_RTIC
+ * @return Nothing
+ * @note Software can clear one or more interrupt condition(s) in the SSP controller
+ */
+STATIC INLINE void Chip_SSP_ClearIntPending(LPC_SSP_T *pSSP, SSP_INTCLEAR_T IntClear)
+{
+ pSSP->ICR = IntClear;
+}
+
+/**
+ * @brief Enable interrupt for the SSP
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SSP_Int_Enable(LPC_SSP_T *pSSP)
+{
+ pSSP->IMSC |= SSP_TXIM;
+}
+
+/**
+ * @brief Disable interrupt for the SSP
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SSP_Int_Disable(LPC_SSP_T *pSSP)
+{
+ pSSP->IMSC &= (~SSP_TXIM);
+}
+
+/**
+ * @brief Get received SSP data
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @return SSP 16-bit data received
+ */
+STATIC INLINE uint16_t Chip_SSP_ReceiveFrame(LPC_SSP_T *pSSP)
+{
+ return (uint16_t) (SSP_DR_BITMASK(pSSP->DR));
+}
+
+/**
+ * @brief Send SSP 16-bit data
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @param tx_data : SSP 16-bit data to be transmited
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SSP_SendFrame(LPC_SSP_T *pSSP, uint16_t tx_data)
+{
+ pSSP->DR = SSP_DR_BITMASK(tx_data);
+}
+
+/**
+ * @brief Set up output clocks per bit for SSP bus
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @param clk_rate fs: The number of prescaler-output clocks per bit on the bus, minus one
+ * @param prescale : The factor by which the Prescaler divides the SSP peripheral clock PCLK
+ * @return Nothing
+ * @note The bit frequency is PCLK / (prescale x[clk_rate+1])
+ */
+void Chip_SSP_SetClockRate(LPC_SSP_T *pSSP, uint32_t clk_rate, uint32_t prescale);
+
+/**
+ * @brief Set up the SSP frame format
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @param bits : The number of bits transferred in each frame, should be SSP_BITS_4 to SSP_BITS_16
+ * @param frameFormat : Frame format, should be :
+ * - SSP_FRAMEFORMAT_SPI
+ * - SSP_FRAME_FORMAT_TI
+ * - SSP_FRAMEFORMAT_MICROWIRE
+ * @param clockMode : Select Clock polarity and Clock phase, should be :
+ * - SSP_CLOCK_CPHA0_CPOL0
+ * - SSP_CLOCK_CPHA0_CPOL1
+ * - SSP_CLOCK_CPHA1_CPOL0
+ * - SSP_CLOCK_CPHA1_CPOL1
+ * @return Nothing
+ * @note Note: The clockFormat is only used in SPI mode
+ */
+STATIC INLINE void Chip_SSP_SetFormat(LPC_SSP_T *pSSP, uint32_t bits, uint32_t frameFormat, uint32_t clockMode)
+{
+ pSSP->CR0 = (pSSP->CR0 & ~0xFF) | bits | frameFormat | clockMode;
+}
+
+/**
+ * @brief Set the SSP working as master or slave mode
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @param mode : Operating mode, should be
+ * - SSP_MODE_MASTER
+ * - SSP_MODE_SLAVE
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SSP_Set_Mode(LPC_SSP_T *pSSP, uint32_t mode)
+{
+ pSSP->CR1 = (pSSP->CR1 & ~(1 << 2)) | mode;
+}
+
+/*
+ * @brief SSP mode
+ */
+typedef enum CHIP_SSP_MODE {
+ SSP_MODE_MASTER = (0 << 2), /**< Master mode */
+ SSP_MODE_SLAVE = (1u << 2), /**< Slave mode */
+} CHIP_SSP_MODE_T;
+
+/*
+ * @brief SPI address
+ */
+typedef struct {
+ uint8_t port; /*!< Port Number */
+ uint8_t pin; /*!< Pin number */
+} SPI_Address_t;
+
+/*
+ * @brief SSP data setup structure
+ */
+typedef struct {
+ void *tx_data; /*!< Pointer to transmit data */
+ uint32_t tx_cnt; /*!< Transmit counter */
+ void *rx_data; /*!< Pointer to transmit data */
+ uint32_t rx_cnt; /*!< Receive counter */
+ uint32_t length; /*!< Length of transfer data */
+} Chip_SSP_DATA_SETUP_T;
+
+/** SSP configuration parameter defines */
+/** Clock phase control bit */
+#define SSP_CPHA_FIRST SSP_CR0_CPHA_FIRST
+#define SSP_CPHA_SECOND SSP_CR0_CPHA_SECOND
+
+/** Clock polarity control bit */
+/* There's no bug here!!!
+ * - If bit[6] in SSPnCR0 is 0: SSP controller maintains the bus clock low between frames.
+ * That means the active clock is in HI state.
+ * - If bit[6] in SSPnCR0 is 1 (SSP_CR0_CPOL_HI): SSP controller maintains the bus clock
+ * high between frames. That means the active clock is in LO state.
+ */
+#define SSP_CPOL_HI SSP_CR0_CPOL_LO
+#define SSP_CPOL_LO SSP_CR0_CPOL_HI
+
+/** SSP master mode enable */
+#define SSP_SLAVE_MODE SSP_CR1_SLAVE_EN
+#define SSP_MASTER_MODE SSP_CR1_MASTER_EN
+
+/**
+ * @brief Clean all data in RX FIFO of SSP
+ * @param pSSP : The base SSP peripheral on the chip
+ * @return Nothing
+ */
+void Chip_SSP_Int_FlushData(LPC_SSP_T *pSSP);
+
+/**
+ * @brief SSP Interrupt Read/Write with 8-bit frame width
+ * @param pSSP : The base SSP peripheral on the chip
+ * @param xf_setup : Pointer to a SSP_DATA_SETUP_T structure that contains specified
+ * information about transmit/receive data configuration
+ * @return SUCCESS or ERROR
+ */
+Status Chip_SSP_Int_RWFrames8Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup);
+
+/**
+ * @brief SSP Interrupt Read/Write with 16-bit frame width
+ * @param pSSP : The base SSP peripheral on the chip
+ * @param xf_setup : Pointer to a SSP_DATA_SETUP_T structure that contains specified
+ * information about transmit/receive data configuration
+ * @return SUCCESS or ERROR
+ */
+Status Chip_SSP_Int_RWFrames16Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup);
+
+/**
+ * @brief SSP Polling Read/Write in blocking mode
+ * @param pSSP : The base SSP peripheral on the chip
+ * @param xf_setup : Pointer to a SSP_DATA_SETUP_T structure that contains specified
+ * information about transmit/receive data configuration
+ * @return Actual data length has been transferred
+ * @note
+ * This function can be used in both master and slave mode. It starts with writing phase and after that,
+ * a reading phase is generated to read any data available in RX_FIFO. All needed information is prepared
+ * through xf_setup param.
+ */
+uint32_t Chip_SSP_RWFrames_Blocking(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup);
+
+/**
+ * @brief SSP Polling Write in blocking mode
+ * @param pSSP : The base SSP peripheral on the chip
+ * @param buffer : Buffer address
+ * @param buffer_len : Buffer length
+ * @return Actual data length has been transferred
+ * @note
+ * This function can be used in both master and slave mode. First, a writing operation will send
+ * the needed data. After that, a dummy reading operation is generated to clear data buffer
+ */
+uint32_t Chip_SSP_WriteFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len);
+
+/**
+ * @brief SSP Polling Read in blocking mode
+ * @param pSSP : The base SSP peripheral on the chip
+ * @param buffer : Buffer address
+ * @param buffer_len : The length of buffer
+ * @return Actual data length has been transferred
+ * @note
+ * This function can be used in both master and slave mode. First, a dummy writing operation is generated
+ * to clear data buffer. After that, a reading operation will receive the needed data
+ */
+uint32_t Chip_SSP_ReadFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len);
+
+/**
+ * @brief Initialize the SSP
+ * @param pSSP : The base SSP peripheral on the chip
+ * @return Nothing
+ */
+void Chip_SSP_Init(LPC_SSP_T *pSSP);
+
+/**
+ * @brief Deinitialise the SSP
+ * @param pSSP : The base of SSP peripheral on the chip
+ * @return Nothing
+ * @note The SSP controller is disabled
+ */
+void Chip_SSP_DeInit(LPC_SSP_T *pSSP);
+
+/**
+ * @brief Set the SSP operating modes, master or slave
+ * @param pSSP : The base SSP peripheral on the chip
+ * @param master : 1 to set master, 0 to set slave
+ * @return Nothing
+ */
+void Chip_SSP_SetMaster(LPC_SSP_T *pSSP, bool master);
+
+/**
+ * @brief Set the clock frequency for SSP interface
+ * @param pSSP : The base SSP peripheral on the chip
+ * @param bitRate : The SSP bit rate
+ * @return Nothing
+ */
+void Chip_SSP_SetBitRate(LPC_SSP_T *pSSP, uint32_t bitRate);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SSP_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/stopwatch.h b/source/lpc_chip_11u6x/inc/stopwatch.h
new file mode 100644
index 0000000..c298735
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/stopwatch.h
@@ -0,0 +1,137 @@
+/*
+ * @brief Common stopwatch support
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __STOPWATCH_H_
+#define __STOPWATCH_H_
+
+#include "cmsis.h"
+
+/** @defgroup Stop_Watch CHIP: Stopwatch primitives.
+ * @ingroup CHIP_Common
+ * @{
+ */
+
+/**
+ * @brief Initialize stopwatch
+ * @return Nothing
+ */
+void StopWatch_Init(void);
+
+/**
+ * @brief Start a stopwatch
+ * @return Current cycle count
+ */
+uint32_t StopWatch_Start(void);
+
+/**
+ * @brief Returns number of ticks elapsed since stopwatch was started
+ * @param startTime : Time returned by StopWatch_Start().
+ * @return Number of ticks elapsed since stopwatch was started
+ */
+STATIC INLINE uint32_t StopWatch_Elapsed(uint32_t startTime)
+{
+ return StopWatch_Start() - startTime;
+}
+
+/**
+ * @brief Returns number of ticks per second of the stopwatch timer
+ * @return Number of ticks per second of the stopwatch timer
+ */
+uint32_t StopWatch_TicksPerSecond(void);
+
+/**
+ * @brief Converts from stopwatch ticks to mS.
+ * @param ticks : Duration in ticks to convert to mS.
+ * @return Number of mS in given number of ticks
+ */
+uint32_t StopWatch_TicksToMs(uint32_t ticks);
+
+/**
+ * @brief Converts from stopwatch ticks to uS.
+ * @param ticks : Duration in ticks to convert to uS.
+ * @return Number of uS in given number of ticks
+ */
+uint32_t StopWatch_TicksToUs(uint32_t ticks);
+
+/**
+ * @brief Converts from mS to stopwatch ticks.
+ * @param mS : Duration in mS to convert to ticks.
+ * @return Number of ticks in given number of mS
+ */
+uint32_t StopWatch_MsToTicks(uint32_t mS);
+
+/**
+ * @brief Converts from uS to stopwatch ticks.
+ * @param uS : Duration in uS to convert to ticks.
+ * @return Number of ticks in given number of uS
+ */
+uint32_t StopWatch_UsToTicks(uint32_t uS);
+
+/**
+ * @brief Delays the given number of ticks using stopwatch primitives
+ * @param ticks : Number of ticks to delay
+ * @return Nothing
+ */
+STATIC INLINE void StopWatch_DelayTicks(uint32_t ticks)
+{
+ uint32_t startTime = StopWatch_Start();
+ while (StopWatch_Elapsed(startTime) < ticks) {}
+}
+
+/**
+ * @brief Delays the given number of mS using stopwatch primitives
+ * @param mS : Number of mS to delay
+ * @return Nothing
+ */
+STATIC INLINE void StopWatch_DelayMs(uint32_t mS)
+{
+ uint32_t ticks = StopWatch_MsToTicks(mS);
+ uint32_t startTime = StopWatch_Start();
+ while (StopWatch_Elapsed(startTime) < ticks) {}
+}
+
+/**
+ * @brief Delays the given number of uS using stopwatch primitives
+ * @param uS : Number of uS to delay
+ * @return Nothing
+ */
+STATIC INLINE void StopWatch_DelayUs(uint32_t uS)
+{
+ uint32_t ticks = StopWatch_UsToTicks(uS);
+ uint32_t startTime = StopWatch_Start();
+ while (StopWatch_Elapsed(startTime) < ticks) {}
+}
+
+/**
+ * @}
+ */
+
+#endif /* __STOPWATCH_H_ */
diff --git a/source/lpc_chip_11u6x/inc/sys_config.h b/source/lpc_chip_11u6x/inc/sys_config.h
new file mode 100644
index 0000000..47cc449
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/sys_config.h
@@ -0,0 +1,36 @@
+/*
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __SYS_CONFIG_H_
+#define __SYS_CONFIG_H_
+
+/* Required for the LPC11U6x device */
+#define CHIP_LPC11U6X
+
+#endif /* __SYS_CONFIG_H_ */
diff --git a/source/lpc_chip_11u6x/inc/syscon_11u6x.h b/source/lpc_chip_11u6x/inc/syscon_11u6x.h
new file mode 100644
index 0000000..44d90f0
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/syscon_11u6x.h
@@ -0,0 +1,569 @@
+/*
+ * @brief LPC11U6X System Control registers and control functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __SYSCTL_11U6X_H_
+#define __SYSCTL_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup SYSCTL_11U6X CHIP: LPC11u6x System Control block driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief LPC11U6X System Control block structure
+ */
+typedef struct { /*!< SYSCTL Structure */
+ __IO uint32_t SYSMEMREMAP; /*!< System Memory remap register */
+ __IO uint32_t PRESETCTRL; /*!< Peripheral reset Control register */
+ __IO uint32_t SYSPLLCTRL; /*!< System PLL control register */
+ __I uint32_t SYSPLLSTAT; /*!< System PLL status register */
+ __IO uint32_t USBPLLCTRL; /*!< USB PLL control register */
+ __I uint32_t USBPLLSTAT; /*!< USB PLL status register */
+ __I uint32_t RESERVED1[1];
+ __IO uint32_t RTCOSCCTRL; /*!< RTC Oscillator control register */
+ __IO uint32_t SYSOSCCTRL; /*!< System Oscillator control register */
+ __IO uint32_t WDTOSCCTRL; /*!< Watchdog Oscillator control register */
+ __I uint32_t RESERVED2[2];
+ __IO uint32_t SYSRSTSTAT; /*!< System Reset Status register */
+ __I uint32_t RESERVED3[3];
+ __IO uint32_t SYSPLLCLKSEL; /*!< System PLL clock source select register */
+ __IO uint32_t SYSPLLCLKUEN; /*!< System PLL clock source update enable register*/
+ __IO uint32_t USBPLLCLKSEL; /*!< USB PLL clock source select register */
+ __IO uint32_t USBPLLCLKUEN; /*!< USB PLL clock source update enable register */
+ __I uint32_t RESERVED4[8];
+ __IO uint32_t MAINCLKSEL; /*!< Main clock source select register */
+ __IO uint32_t MAINCLKUEN; /*!< Main clock source update enable register */
+ __IO uint32_t SYSAHBCLKDIV; /*!< System Clock divider register */
+ __I uint32_t RESERVED5;
+ __IO uint32_t SYSAHBCLKCTRL; /*!< System clock control register */
+ __I uint32_t RESERVED6[4];
+ __IO uint32_t SSP0CLKDIV; /*!< SSP0 clock divider register */
+ __IO uint32_t USART0CLKDIV; /*!< UART clock divider register */
+ __IO uint32_t SSP1CLKDIV; /*!< SSP1 clock divider register */
+ __IO uint32_t FRGCLKDIV; /*!< FRG clock divider (USARTS 1 - 4) register */
+ __I uint32_t RESERVED7[7];
+ __IO uint32_t USBCLKSEL; /*!< USB clock source select register */
+ __IO uint32_t USBCLKUEN; /*!< USB clock source update enable register */
+ __IO uint32_t USBCLKDIV; /*!< USB clock source divider register */
+ __I uint32_t RESERVED8[5];
+ __IO uint32_t CLKOUTSEL; /*!< Clock out source select register */
+ __IO uint32_t CLKOUTUEN; /*!< Clock out source update enable register */
+ __IO uint32_t CLKOUTDIV; /*!< Clock out divider register */
+ __I uint32_t RESERVED9;
+ __IO uint32_t UARTFRGDIV; /*!< USART fractional generator divider (USARTS 1 - 4) register */
+ __IO uint32_t UARTFRGMULT; /*!< USART fractional generator multiplier (USARTS 1 - 4) register */
+ __I uint32_t RESERVED10;
+ __IO uint32_t EXTTRACECMD; /*!< External trace buffer command register */
+ __I uint32_t PIOPORCAP[3]; /*!< POR captured PIO status registers */
+ __I uint32_t RESERVED11[10];
+ __IO uint32_t IOCONCLKDIV[7]; /*!< IOCON block for programmable glitch filter divider registers */
+ __IO uint32_t BODCTRL; /*!< Brown Out Detect register */
+ __IO uint32_t SYSTCKCAL; /*!< System tick counter calibration register */
+ __I uint32_t RESERVED12[6];
+ __IO uint32_t IRQLATENCY; /*!< IRQ delay register */
+ __IO uint32_t NMISRC; /*!< NMI source control register */
+ __IO uint32_t PINTSEL[8]; /*!< GPIO pin interrupt select register 0-7 */
+ __IO uint32_t USBCLKCTRL; /*!< USB clock control register */
+ __I uint32_t USBCLKST; /*!< USB clock status register */
+ __I uint32_t RESERVED13[25];
+ __IO uint32_t STARTERP0; /*!< Start logic 0 interrupt wake-up enable register */
+ __I uint32_t RESERVED14[3];
+ __IO uint32_t STARTERP1; /*!< Start logic 1 interrupt wake-up enable register */
+ __I uint32_t RESERVED15[6];
+ __IO uint32_t PDSLEEPCFG; /*!< Power down states in deep sleep mode register */
+ __IO uint32_t PDWAKECFG; /*!< Power down states in wake up from deep sleep register */
+ __IO uint32_t PDRUNCFG; /*!< Power configuration register*/
+ __I uint32_t RESERVED16[110];
+ __I uint32_t DEVICEID; /*!< Device ID register */
+} LPC_SYSCTL_T;
+
+/**
+ * System memory remap modes used to remap interrupt vectors
+ */
+typedef enum CHIP_SYSCTL_BOOT_MODE_REMAP {
+ REMAP_BOOT_LOADER_MODE, /*!< Interrupt vectors are re-mapped to Boot ROM */
+ REMAP_USER_RAM_MODE, /*!< Interrupt vectors are re-mapped to Static RAM */
+ REMAP_USER_FLASH_MODE /*!< Interrupt vectors are not re-mapped and reside in Flash */
+} CHIP_SYSCTL_BOOT_MODE_REMAP_T;
+
+/**
+ * @brief Re-map interrupt vectors
+ * @param remap : system memory map value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SYSCTL_Map(CHIP_SYSCTL_BOOT_MODE_REMAP_T remap)
+{
+ LPC_SYSCTL->SYSMEMREMAP = (uint32_t) remap;
+}
+
+/**
+ * Peripheral reset identifiers, not available on all devices
+ */
+typedef enum {
+ RESET_SSP0, /*!< SSP0 reset control */
+ RESET_I2C0, /*!< I2C0 reset control */
+ RESET_SSP1, /*!< SSP1 reset control */
+ RESET_I2C1, /*!< I2C1 reset control */
+ RESET_FRG, /*!< FRG reset control */
+ RESET_USART1, /*!< USART1 reset control */
+ RESET_USART2, /*!< USART1 reset control */
+ RESET_USART3, /*!< USART1 reset control */
+ RESET_USART4, /*!< USART1 reset control */
+ RESET_SCT0, /*!< SCT0 reset control */
+ RESET_SCT1 /*!< SCT1 reset control */
+} CHIP_SYSCTL_PERIPH_RESET_T;
+
+/**
+ * @brief Assert reset for a peripheral
+ * @param periph : Peripheral to assert reset for
+ * @return Nothing
+ * @note The peripheral will stay in reset until reset is de-asserted. Call
+ * Chip_SYSCTL_DeassertPeriphReset() to de-assert the reset.
+ */
+STATIC INLINE void Chip_SYSCTL_AssertPeriphReset(CHIP_SYSCTL_PERIPH_RESET_T periph)
+{
+ LPC_SYSCTL->PRESETCTRL &= ~(1 << (uint32_t) periph);
+}
+
+/**
+ * @brief De-assert reset for a peripheral
+ * @param periph : Peripheral to de-assert reset for
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SYSCTL_DeassertPeriphReset(CHIP_SYSCTL_PERIPH_RESET_T periph)
+{
+ LPC_SYSCTL->PRESETCTRL |= (1 << (uint32_t) periph);
+}
+
+/**
+ * @brief Resets a peripheral
+ * @param periph : Peripheral to reset
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SYSCTL_PeriphReset(CHIP_SYSCTL_PERIPH_RESET_T periph)
+{
+ Chip_SYSCTL_AssertPeriphReset(periph);
+ Chip_SYSCTL_DeassertPeriphReset(periph);
+}
+
+/**
+ * System reset status
+ */
+#define SYSCTL_RST_POR (1 << 0) /*!< POR reset status */
+#define SYSCTL_RST_EXTRST (1 << 1) /*!< External reset status */
+#define SYSCTL_RST_WDT (1 << 2) /*!< Watchdog reset status */
+#define SYSCTL_RST_BOD (1 << 3) /*!< Brown-out detect reset status */
+#define SYSCTL_RST_SYSRST (1 << 4) /*!< software system reset status */
+
+/**
+ * @brief Get system reset status
+ * @return An Or'ed value of SYSCTL_RST_*
+ * @note This function returns the detected reset source(s).
+ */
+STATIC INLINE uint32_t Chip_SYSCTL_GetSystemRSTStatus(void)
+{
+ return LPC_SYSCTL->SYSRSTSTAT;
+}
+
+/**
+ * @brief Clear system reset status
+ * @param reset : An Or'ed value of SYSCTL_RST_* status to clear
+ * @return Nothing
+ * @note This function returns the detected reset source(s).
+ */
+STATIC INLINE void Chip_SYSCTL_ClearSystemRSTStatus(uint32_t reset)
+{
+ LPC_SYSCTL->SYSRSTSTAT = reset;
+}
+
+/**
+ * @brief Read POR captured PIO status
+ * @param index : POR register index, 0 or 1
+ * @return captured POR PIO status
+ */
+STATIC INLINE uint32_t Chip_SYSCTL_GetPORPIOStatus(int index)
+{
+ return LPC_SYSCTL->PIOPORCAP[index];
+}
+
+/**
+ * Brown-out detector reset level
+ */
+typedef enum CHIP_SYSCTL_BODRSTLVL {
+ // FIXME - will update with correct voltages
+ SYSCTL_BODRSTLVL_LEVEL0, /*!< Brown-out reset at TBD volts */
+ SYSCTL_BODRSTLVL_LEVEL1, /*!< Brown-out reset at TBD volts */
+ SYSCTL_BODRSTLVL_LEVEL2, /*!< Brown-out reset at TBD volts */
+ SYSCTL_BODRSTLVL_LEVEL3, /*!< Brown-out reset at TBD volts */
+} CHIP_SYSCTL_BODRSTLVL_T;
+
+/**
+ * Brown-out detector interrupt level
+ */
+typedef enum CHIP_SYSCTL_BODRINTVAL {
+ // FIXME - will update with correct voltages
+ SYSCTL_BODINTVAL_RESERVED1,
+ SYSCTL_BODINTVAL_RESERVED2,
+ SYSCTL_BODINTVAL_2_LEVEL2, /*!< Brown-out interrupt at TBD volts */
+ SYSCTL_BODINTVAL_2_LEVEL3, /*!< Brown-out interrupt at TBD volts */
+} CHIP_SYSCTL_BODRINTVAL_T;
+
+/**
+ * @brief Set brown-out detection interrupt and reset levels
+ * @param rstlvl : Brown-out detector reset level
+ * @param intlvl : Brown-out interrupt level
+ * @return Nothing
+ * @note Brown-out detection reset will be disabled upon exiting this function.
+ * Use Chip_SYSCTL_EnableBODReset() to re-enable.
+ */
+STATIC INLINE void Chip_SYSCTL_SetBODLevels(CHIP_SYSCTL_BODRSTLVL_T rstlvl,
+ CHIP_SYSCTL_BODRINTVAL_T intlvl)
+{
+ LPC_SYSCTL->BODCTRL = ((uint32_t) rstlvl) | (((uint32_t) intlvl) << 2);
+}
+
+/**
+ * @brief Enable brown-out detection reset
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SYSCTL_EnableBODReset(void)
+{
+ LPC_SYSCTL->BODCTRL |= (1 << 4);
+}
+
+/**
+ * @brief Disable brown-out detection reset
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SYSCTL_DisableBODReset(void)
+{
+ LPC_SYSCTL->BODCTRL &= ~(1 << 4);
+}
+
+/**
+ * @brief Set System tick timer calibration value
+ * @param sysCalVal : System tick timer calibration value
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SYSCTL_SetSYSTCKCAL(uint32_t sysCalVal)
+{
+ LPC_SYSCTL->SYSTCKCAL = sysCalVal;
+}
+
+/**
+ * @brief Set System IRQ latency
+ * @param latency : Latency in clock ticks
+ * @return Nothing
+ * @note Sets the IRQ latency, a value between 0 and 255 clocks. Lower
+ * values allow better latency.
+ */
+STATIC INLINE void Chip_SYSCTL_SetIRQLatency(uint32_t latency)
+{
+ LPC_SYSCTL->IRQLATENCY = latency;
+}
+
+/**
+ * @brief Get System IRQ latency
+ * @return Latency in clock ticks
+ */
+STATIC INLINE uint32_t Chip_SYSCTL_GetIRQLatency(void)
+{
+ return LPC_SYSCTL->IRQLATENCY;
+}
+
+/**
+ * Non-Maskable Interrupt Enable/Disable value
+ */
+#define SYSCTL_NMISRC_ENABLE ((uint32_t) 1 << 31) /*!< Enable the Non-Maskable Interrupt (NMI) source */
+
+/**
+ * @brief Set source for non-maskable interrupt (NMI)
+ * @param intsrc : IRQ number to assign to the NMI
+ * @return Nothing
+ * @note The NMI source will be disabled upon exiting this function. use the
+ * Chip_SYSCTL_EnableNMISource() function to enable the NMI source.
+ */
+STATIC INLINE void Chip_SYSCTL_SetNMISource(uint32_t intsrc)
+{
+ LPC_SYSCTL->NMISRC = 0; /* Disable first */
+ LPC_SYSCTL->NMISRC = intsrc;
+}
+
+/**
+ * @brief Enable interrupt used for NMI source
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SYSCTL_EnableNMISource(void)
+{
+ LPC_SYSCTL->NMISRC |= SYSCTL_NMISRC_ENABLE;
+}
+
+/**
+ * @brief Disable interrupt used for NMI source
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SYSCTL_DisableNMISource(void)
+{
+ LPC_SYSCTL->NMISRC &= ~(SYSCTL_NMISRC_ENABLE);
+}
+
+/**
+ * @brief Setup a GPIO pin source for a pin interrupt (0-7)
+ * @param intno : IRQ number
+ * @param port : port number 0, 1, or 2)
+ * @param pin : pin number (0-23 for Port 0, 0-31 for Port 1, 0-7 for port 2)
+ * @return Nothing
+ */
+void Chip_SYSCTL_SetPinInterrupt(uint32_t intno, uint8_t port, uint8_t pin);
+
+/**
+ * @brief Setup USB clock control
+ * @param ap_clk : USB need_clock signal control (0 or 1)
+ * @param pol_clk : USB need_clock polarity for triggering the USB wake-up interrupt (0 or 1)
+ * @return Nothing
+ * @note See the USBCLKCTRL register in the user manual for these settings.
+ */
+STATIC INLINE void Chip_SYSCTL_SetUSBCLKCTRL(uint32_t ap_clk, uint32_t pol_clk)
+{
+ LPC_SYSCTL->USBCLKCTRL = ap_clk | (pol_clk << 1);
+}
+
+/**
+ * @brief Use the internal pull-up resistor for the the USB_DP/DM pull-up/pull-down resistors
+ * @return Nothing
+ * @note See the USBCLKCTRL register in the user manual for more information.
+ */
+STATIC INLINE void Chip_SYSCTL_UseIntPullup(void)
+{
+ LPC_SYSCTL->USBCLKCTRL |= (1 << 2);
+}
+
+/**
+ * @brief Use the external pull-up resistor for the the USB_DP/DM pull-up/pull-down resistors
+ * @return Nothing
+ * @note See the USBCLKCTRL register in the user manual for more information.
+ */
+STATIC INLINE void Chip_SYSCTL_UseExtPullup(void)
+{
+ LPC_SYSCTL->USBCLKCTRL &= ~(1 << 2);
+}
+
+/**
+ * @brief Returns the status of the USB need_clock signal
+ * @return true if USB need_clock status is high, otherwise false
+ */
+STATIC INLINE bool Chip_SYSCTL_GetUSBCLKStatus(void)
+{
+ return (bool) ((LPC_SYSCTL->USBCLKST & 0x1) != 0);
+}
+
+/**
+ * @brief Enable PIO start logic for a PININT pin
+ * @param pin : PIO pin number
+ * @return Nothing
+ * @note Different devices support different pins, see the user manual for supported pins.
+ */
+STATIC INLINE void Chip_SYSCTL_EnableStartPin(uint32_t pin)
+{
+ LPC_SYSCTL->STARTERP0 |= (1 << pin);
+}
+
+/**
+ * @brief Disable PIO start logic for a PININT pin
+ * @param pin : PIO pin number
+ * @return Nothing
+ * @note Different devices support different pins, see the user manual for supported pins.
+ */
+STATIC INLINE void Chip_SYSCTL_DisableStartPin(uint32_t pin)
+{
+ LPC_SYSCTL->STARTERP0 &= ~(1 << pin);
+}
+
+/**
+ * Peripheral interrupt wakeup events
+ */
+// FIXME - Need to recheck these bit positions
+// FIXME - LPC11U6X user manual shows this as bit 13. This is the bit that works!
+#define SYSCTL_WAKEUP_BOD_WDT_INT (1 << 12) /*!< Shared Brown Out Detect (BOD) and WDT interrupt wake-up */
+// FIXME - LPC11U6X user manual shows this as bit 12. This is the bit that works!
+#define SYSCTL_WAKEUP_RTCINT (1 << 19) /*!< RTC interrupt wake-up */
+#define SYSCTL_WAKEUP_USB_WAKEUP (1 << 19) /*!< USB need_clock signal wake-up */
+#define SYSCTL_WAKEUP_GPIOINT0 (1 << 20) /*!< GPIO GROUP0 interrupt wake-up */
+#define SYSCTL_WAKEUP_GPIOINT1 (1 << 21) /*!< GPIO GROUP1 interrupt wake-up */
+#define SYSCTL_WAKEUP_USART1_4 (1 << 23) /*!< Combined USART1 and USART4 wake-up */
+#define SYSCTL_WAKEUP_USART2_3 (1 << 24) /*!< Combined USART2 and USART3 interrupt wake-up */
+
+/**
+ * @brief Enables a peripheral's wakeup logic
+ * @param periphmask : OR'ed values of SYSCTL_WAKEUP_* for wakeup
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SYSCTL_EnablePeriphWakeup(uint32_t periphmask)
+{
+ LPC_SYSCTL->STARTERP1 |= periphmask;
+}
+
+/**
+ * @brief Disables a peripheral's wakeup logic
+ * @param periphmask : OR'ed values of SYSCTL_WAKEUP_* for wakeup
+ * @return Nothing
+ */
+STATIC INLINE void Chip_SYSCTL_DisablePeriphWakeup(uint32_t periphmask)
+{
+ LPC_SYSCTL->STARTERP1 &= ~periphmask;
+}
+
+/**
+ * Deep sleep setup values
+ */
+#define SYSCTL_DEEPSLP_BOD_PD (1 << 3) /*!< BOD power-down control in Deep-sleep mode, powered down */
+#define SYSCTL_DEEPSLP_WDTOSC_PD (1 << 6) /*!< Watchdog oscillator power control in Deep-sleep, powered down */
+
+/**
+ * @brief Setup deep sleep behaviour for power down
+ * @param sleepmask : OR'ed values of SYSCTL_DEEPSLP_* values (high to powerdown on deepsleep)
+ * @return Nothing
+ * @note This must be setup prior to using deep sleep. See the user manual
+ * (PDSLEEPCFG register) for more info on setting this up. This function selects
+ * which peripherals are powered down on deep sleep.
+ * This function should only be called once with all options for power-down
+ * in that call.
+ */
+void Chip_SYSCTL_SetDeepSleepPD(uint32_t sleepmask);
+
+/**
+ * @brief Returns current deep sleep mask
+ * @return OR'ed values of SYSCTL_DEEPSLP_* values
+ * @note A high bit indicates the peripheral will power down on deep sleep.
+ */
+STATIC INLINE uint32_t Chip_SYSCTL_GetDeepSleepPD(void)
+{
+ return LPC_SYSCTL->PDSLEEPCFG;
+}
+
+/**
+ * Deep sleep to wakeup setup values
+ */
+#define SYSCTL_SLPWAKE_IRCOUT_PD (1 << 0) /*!< IRC oscillator output wake-up configuration */
+#define SYSCTL_SLPWAKE_IRC_PD (1 << 1) /*!< IRC oscillator power-down wake-up configuration */
+#define SYSCTL_SLPWAKE_FLASH_PD (1 << 2) /*!< Flash wake-up configuration */
+#define SYSCTL_SLPWAKE_BOD_PD (1 << 3) /*!< BOD wake-up configuration */
+#define SYSCTL_SLPWAKE_ADC_PD (1 << 4) /*!< ADC wake-up configuration */
+#define SYSCTL_SLPWAKE_SYSOSC_PD (1 << 5) /*!< System oscillator wake-up configuration */
+#define SYSCTL_SLPWAKE_WDTOSC_PD (1 << 6) /*!< Watchdog oscillator wake-up configuration */
+#define SYSCTL_SLPWAKE_SYSPLL_PD (1 << 7) /*!< System PLL wake-up configuration */
+#define SYSCTL_SLPWAKE_USBPLL_PD (1 << 8) /*!< USB PLL wake-up configuration */
+#define SYSCTL_SLPWAKE_USBPAD_PD (1 << 10) /*!< USB transceiver wake-up configuration */
+#define SYSCTL_SLPWAKE_TS_PD (1 << 13) /*!< Temperature sensor wake-up configuration */
+
+/**
+ * @brief Setup wakeup behaviour from deep sleep
+ * @param wakeupmask : OR'ed values of SYSCTL_SLPWAKE_* values (high is powered down)
+ * @return Nothing
+ * @note This must be setup prior to using deep sleep. See the user manual
+ * (PDWAKECFG register) for more info on setting this up. This function selects
+ * which peripherals are powered up on exit from deep sleep.
+ * This function should only be called once with all options for wakeup
+ * in that call.
+ */
+void Chip_SYSCTL_SetWakeup(uint32_t wakeupmask);
+
+/**
+ * @brief Return current wakeup mask
+ * @return OR'ed values of SYSCTL_SLPWAKE_* values
+ * @note A high state indicates the peripehral will powerup on wakeup.
+ */
+STATIC INLINE uint32_t Chip_SYSCTL_GetWakeup(void)
+{
+ return LPC_SYSCTL->PDWAKECFG;
+}
+
+/**
+ * Power down configuration values
+ */
+#define SYSCTL_POWERDOWN_IRCOUT_PD (1 << 0) /*!< IRC oscillator output power down */
+#define SYSCTL_POWERDOWN_IRC_PD (1 << 1) /*!< IRC oscillator power-down */
+#define SYSCTL_POWERDOWN_FLASH_PD (1 << 2) /*!< Flash power down */
+#define SYSCTL_POWERDOWN_BOD_PD (1 << 3) /*!< BOD power down */
+#define SYSCTL_POWERDOWN_ADC_PD (1 << 4) /*!< ADC power down */
+#define SYSCTL_POWERDOWN_SYSOSC_PD (1 << 5) /*!< System oscillator power down */
+#define SYSCTL_POWERDOWN_WDTOSC_PD (1 << 6) /*!< Watchdog oscillator power down */
+#define SYSCTL_POWERDOWN_SYSPLL_PD (1 << 7) /*!< System PLL power down */
+#define SYSCTL_POWERDOWN_USBPLL_PD (1 << 8) /*!< USB PLL power-down */
+#define SYSCTL_POWERDOWN_USBPAD_PD (1 << 10) /*!< USB transceiver power-down */
+#define SYSCTL_POWERDOWN_TS_PD (1 << 13) /*!< Temperature Sensor power-down */
+
+/**
+ * @brief Power down one or more blocks or peripherals
+ * @param powerdownmask : OR'ed values of SYSCTL_POWERDOWN_* values
+ * @return Nothing
+ */
+void Chip_SYSCTL_PowerDown(uint32_t powerdownmask);
+
+/**
+ * @brief Power up one or more blocks or peripherals
+ * @param powerupmask : OR'ed values of SYSCTL_POWERDOWN_* values
+ * @return Nothing
+ */
+void Chip_SYSCTL_PowerUp(uint32_t powerupmask);
+
+/**
+ * @brief Get power status
+ * @return OR'ed values of SYSCTL_POWERDOWN_* values
+ * @note A high state indicates the peripheral is powered down.
+ */
+STATIC INLINE uint32_t Chip_SYSCTL_GetPowerStates(void)
+{
+ return LPC_SYSCTL->PDRUNCFG;
+}
+
+/**
+ * @brief Return the device ID
+ * @return the device ID
+ */
+STATIC INLINE uint32_t Chip_SYSCTL_GetDeviceID(void)
+{
+ return LPC_SYSCTL->DEVICEID;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*!< __SYSCTL_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/timer_11u6x.h b/source/lpc_chip_11u6x/inc/timer_11u6x.h
new file mode 100644
index 0000000..8543340
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/timer_11u6x.h
@@ -0,0 +1,493 @@
+/*
+ * @brief LPC11u6x 16/32-bit Timer/PWM control functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __TIMER_11U6X_H_
+#define __TIMER_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup TIMER_11U6X CHIP: LPC11u6x 16/32-bit Timer driver
+ * @ingroup CHIP_11U6X_Drivers
+ * IMPORTANT NOTE ABOUT lpc11u6x TIMERS
+ * For timer 0 on both the 16-bit and 32-bit timers, the capture functions
+ * use index 0 for capture 0 functions and index 2 for capture 1 functions,
+ * while timer 1 for both the 16-bit and 32-bit timers uses index 0 and
+ * index 1. Use care when selecting
+ * The LPC11U6X User manual is inconsistent in it's designation of capture
+ * channels for each timer. See the comments for each function for special
+ * handling per timer when dealing with capture channels.
+ * @{
+ */
+
+/**
+ * @brief 32-bit Standard timer register block structure
+ */
+typedef struct { /*!< TIMERn Structure */
+ __IO uint32_t IR; /*!< Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */
+ __IO uint32_t TCR; /*!< Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */
+ __IO uint32_t TC; /*!< Timer Counter. The 32 bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */
+ __IO uint32_t PR; /*!< Prescale Register. The Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */
+ __IO uint32_t PC; /*!< Prescale Counter. The 32 bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */
+ __IO uint32_t MCR; /*!< Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */
+ __IO uint32_t MR[4]; /*!< Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */
+ __IO uint32_t CCR; /*!< Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */
+ __IO uint32_t CR[4]; /*!< Capture Register. CR is loaded with the value of TC when there is an event on the CAPn.0 input. */
+ __IO uint32_t EMR; /*!< External Match Register. The EMR controls the external match pins MATn.0-3 (MAT0.0-3 and MAT1.0-3 respectively). */
+ __I uint32_t RESERVED0[12];
+ __IO uint32_t CTCR; /*!< Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */
+ __IO uint32_t PWMC;
+} LPC_TIMER_T;
+
+/** Macro to clear interrupt pending */
+#define TIMER_IR_CLR(n) _BIT(n)
+
+/** Macro for getting a timer match interrupt bit */
+#define TIMER_MATCH_INT(n) (_BIT((n) & 0x0F))
+/** Macro for getting a capture event interrupt bit */
+#define TIMER_CAP_INT(n) (_BIT((((n) & 0x0F) + 4)))
+
+/** Timer/counter enable bit */
+#define TIMER_ENABLE ((uint32_t) (1 << 0))
+/** Timer/counter reset bit */
+#define TIMER_RESET ((uint32_t) (1 << 1))
+
+/** Bit location for interrupt on MRx match, n = 0 to 3 */
+#define TIMER_INT_ON_MATCH(n) (_BIT(((n) * 3)))
+/** Bit location for reset on MRx match, n = 0 to 3 */
+#define TIMER_RESET_ON_MATCH(n) (_BIT((((n) * 3) + 1)))
+/** Bit location for stop on MRx match, n = 0 to 3 */
+#define TIMER_STOP_ON_MATCH(n) (_BIT((((n) * 3) + 2)))
+
+/** Bit location for CAP.n on CRx rising edge, n = 0 to 3 */
+#define TIMER_CAP_RISING(n) (_BIT(((n) * 3)))
+/** Bit location for CAP.n on CRx falling edge, n = 0 to 3 */
+#define TIMER_CAP_FALLING(n) (_BIT((((n) * 3) + 1)))
+/** Bit location for CAP.n on CRx interrupt enable, n = 0 to 3 */
+#define TIMER_INT_ON_CAP(n) (_BIT((((n) * 3) + 2)))
+
+/**
+ * @brief Initialize a timer
+ * @param pTMR : Pointer to timer IP register address
+ * @return Nothing
+ */
+void Chip_TIMER_Init(LPC_TIMER_T *pTMR);
+
+/**
+ * @brief Shutdown a timer
+ * @param pTMR : Pointer to timer IP register address
+ * @return Nothing
+ */
+void Chip_TIMER_DeInit(LPC_TIMER_T *pTMR);
+
+/**
+ * @brief Determine if a match interrupt is pending
+ * @param pTMR : Pointer to timer IP register address
+ * @param matchnum : Match interrupt number to check
+ * @return false if the interrupt is not pending, otherwise true
+ * @note Determine if the match interrupt for the passed timer and match
+ * counter is pending.
+ */
+STATIC INLINE bool Chip_TIMER_MatchPending(LPC_TIMER_T *pTMR, int8_t matchnum)
+{
+ return (bool) ((pTMR->IR & TIMER_MATCH_INT(matchnum)) != 0);
+}
+
+/**
+ * @brief Determine if a capture interrupt is pending
+ * @param pTMR : Pointer to timer IP register address
+ * @param capnum : Capture interrupt number to check
+ * @return false if the interrupt is not pending, otherwise true
+ * @note Determine if the capture interrupt for the passed capture pin is
+ * pending.
+ * Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to check the capture
+ * interrupt status for channel 1. For 16-bit and 32-bit timers 1, select
+ * channel 1. (User manual designation of channel 1 is capture slot 2
+ * for timer 0).
+ */
+STATIC INLINE bool Chip_TIMER_CapturePending(LPC_TIMER_T *pTMR, int8_t capnum)
+{
+ return (bool) ((pTMR->IR & TIMER_CAP_INT(capnum)) != 0);
+}
+
+/**
+ * @brief Clears a (pending) match interrupt
+ * @param pTMR : Pointer to timer IP register address
+ * @param matchnum : Match interrupt number to clear
+ * @return Nothing
+ * @note Clears a pending timer match interrupt.
+ */
+STATIC INLINE void Chip_TIMER_ClearMatch(LPC_TIMER_T *pTMR, int8_t matchnum)
+{
+ pTMR->IR = TIMER_IR_CLR(matchnum);
+}
+
+/**
+ * @brief Clears a (pending) capture interrupt
+ * @param pTMR : Pointer to timer IP register address
+ * @param capnum : Capture interrupt number to clear
+ * @return Nothing
+ * @note Clears a pending timer capture interrupt.
+ * Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to check the capture
+ * interrupt status for channel 1. For 16-bit and 32-bit timers 1, select
+ * channel 1. (User manual designation of channel 1 is capture slot 2
+ * for timer 0).
+ */
+STATIC INLINE void Chip_TIMER_ClearCapture(LPC_TIMER_T *pTMR, int8_t capnum)
+{
+ pTMR->IR = (0x10 << capnum);
+}
+
+/**
+ * @brief Enables the timer (starts count)
+ * @param pTMR : Pointer to timer IP register address
+ * @return Nothing
+ * @note Enables the timer to start counting.
+ */
+STATIC INLINE void Chip_TIMER_Enable(LPC_TIMER_T *pTMR)
+{
+ pTMR->TCR |= TIMER_ENABLE;
+}
+
+/**
+ * @brief Disables the timer (stops count)
+ * @param pTMR : Pointer to timer IP register address
+ * @return Nothing
+ * @note Disables the timer to stop counting.
+ */
+STATIC INLINE void Chip_TIMER_Disable(LPC_TIMER_T *pTMR)
+{
+ pTMR->TCR &= ~TIMER_ENABLE;
+}
+
+/**
+ * @brief Returns the current timer count
+ * @param pTMR : Pointer to timer IP register address
+ * @return Current timer terminal count value
+ * @note Returns the current timer terminal count.
+ */
+STATIC INLINE uint32_t Chip_TIMER_ReadCount(LPC_TIMER_T *pTMR)
+{
+ return pTMR->TC;
+}
+
+/**
+ * @brief Returns the current prescale count
+ * @param pTMR : Pointer to timer IP register address
+ * @return Current timer prescale count value
+ * @note Returns the current prescale count.
+ */
+STATIC INLINE uint32_t Chip_TIMER_ReadPrescale(LPC_TIMER_T *pTMR)
+{
+ return pTMR->PC;
+}
+
+/**
+ * @brief Sets the prescaler value
+ * @param pTMR : Pointer to timer IP register address
+ * @param prescale : Prescale value to set the prescale register to
+ * @return Nothing
+ * @note Sets the prescale count value.
+ */
+STATIC INLINE void Chip_TIMER_PrescaleSet(LPC_TIMER_T *pTMR, uint32_t prescale)
+{
+ pTMR->PR = prescale;
+}
+
+/**
+ * @brief Sets a timer match value
+ * @param pTMR : Pointer to timer IP register address
+ * @param matchnum : Match timer to set match count for
+ * @param matchval : Match value for the selected match count
+ * @return Nothing
+ * @note Sets one of the timer match values.
+ */
+STATIC INLINE void Chip_TIMER_SetMatch(LPC_TIMER_T *pTMR, int8_t matchnum, uint32_t matchval)
+{
+ pTMR->MR[matchnum] = matchval;
+}
+
+/**
+ * @brief Reads a capture register
+ * @param pTMR : Pointer to timer IP register address
+ * @param capnum : Capture register to read
+ * @return The selected capture register value
+ * @note Returns the selected capture register value.
+ * Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to get the capture
+ * count for channel 1. For 16-bit and 32-bit timers 1, select
+ * channel 1. (User manual designation of channel 1 is capture slot 2
+ * for timer 0).
+ */
+STATIC INLINE uint32_t Chip_TIMER_ReadCapture(LPC_TIMER_T *pTMR, int8_t capnum)
+{
+ return pTMR->CR[capnum];
+}
+
+/**
+ * @brief Resets the timer terminal and prescale counts to 0
+ * @param pTMR : Pointer to timer IP register address
+ * @return Nothing
+ */
+void Chip_TIMER_Reset(LPC_TIMER_T *pTMR);
+
+/**
+ * @brief Enables a match interrupt that fires when the terminal count
+ * matches the match counter value.
+ * @param pTMR : Pointer to timer IP register address
+ * @param matchnum : Match timer, 0 to 3
+ * @return Nothing
+ */
+STATIC INLINE void Chip_TIMER_MatchEnableInt(LPC_TIMER_T *pTMR, int8_t matchnum)
+{
+ pTMR->MCR |= TIMER_INT_ON_MATCH(matchnum);
+}
+
+/**
+ * @brief Disables a match interrupt for a match counter.
+ * @param pTMR : Pointer to timer IP register address
+ * @param matchnum : Match timer, 0 to 3
+ * @return Nothing
+ */
+STATIC INLINE void Chip_TIMER_MatchDisableInt(LPC_TIMER_T *pTMR, int8_t matchnum)
+{
+ pTMR->MCR &= ~TIMER_INT_ON_MATCH(matchnum);
+}
+
+/**
+ * @brief For the specific match counter, enables reset of the terminal count register when a match occurs
+ * @param pTMR : Pointer to timer IP register address
+ * @param matchnum : Match timer, 0 to 3
+ * @return Nothing
+ */
+STATIC INLINE void Chip_TIMER_ResetOnMatchEnable(LPC_TIMER_T *pTMR, int8_t matchnum)
+{
+ pTMR->MCR |= TIMER_RESET_ON_MATCH(matchnum);
+}
+
+/**
+ * @brief For the specific match counter, disables reset of the terminal count register when a match occurs
+ * @param pTMR : Pointer to timer IP register address
+ * @param matchnum : Match timer, 0 to 3
+ * @return Nothing
+ */
+STATIC INLINE void Chip_TIMER_ResetOnMatchDisable(LPC_TIMER_T *pTMR, int8_t matchnum)
+{
+ pTMR->MCR &= ~TIMER_RESET_ON_MATCH(matchnum);
+}
+
+/**
+ * @brief Enable a match timer to stop the terminal count when a
+ * match count equals the terminal count.
+ * @param pTMR : Pointer to timer IP register address
+ * @param matchnum : Match timer, 0 to 3
+ * @return Nothing
+ */
+STATIC INLINE void Chip_TIMER_StopOnMatchEnable(LPC_TIMER_T *pTMR, int8_t matchnum)
+{
+ pTMR->MCR |= TIMER_STOP_ON_MATCH(matchnum);
+}
+
+/**
+ * @brief Disable stop on match for a match timer. Disables a match timer
+ * to stop the terminal count when a match count equals the terminal count.
+ * @param pTMR : Pointer to timer IP register address
+ * @param matchnum : Match timer, 0 to 3
+ * @return Nothing
+ */
+STATIC INLINE void Chip_TIMER_StopOnMatchDisable(LPC_TIMER_T *pTMR, int8_t matchnum)
+{
+ pTMR->MCR &= ~TIMER_STOP_ON_MATCH(matchnum);
+}
+
+/**
+ * @brief Enables capture on on rising edge of selected CAP signal for the
+ * selected capture register, enables the selected CAPn.capnum signal to load
+ * the capture register with the terminal coount on a rising edge.
+ * @param pTMR : Pointer to timer IP register address
+ * @param capnum : Capture signal/register to use
+ * @return Nothing
+ * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and
+ * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture
+ * slot 2).
+ */
+STATIC INLINE void Chip_TIMER_CaptureRisingEdgeEnable(LPC_TIMER_T *pTMR, int8_t capnum)
+{
+ pTMR->CCR |= TIMER_CAP_RISING(capnum);
+}
+
+/**
+ * @brief Disables capture on on rising edge of selected CAP signal. For the
+ * selected capture register, disables the selected CAPn.capnum signal to load
+ * the capture register with the terminal coount on a rising edge.
+ * @param pTMR : Pointer to timer IP register address
+ * @param capnum : Capture signal/register to use
+ * @return Nothing
+ * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and
+ * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture
+ * slot 2).
+ */
+STATIC INLINE void Chip_TIMER_CaptureRisingEdgeDisable(LPC_TIMER_T *pTMR, int8_t capnum)
+{
+ pTMR->CCR &= ~TIMER_CAP_RISING(capnum);
+}
+
+/**
+ * @brief Enables capture on on falling edge of selected CAP signal. For the
+ * selected capture register, enables the selected CAPn.capnum signal to load
+ * the capture register with the terminal coount on a falling edge.
+ * @param pTMR : Pointer to timer IP register address
+ * @param capnum : Capture signal/register to use
+ * @return Nothing
+ * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and
+ * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture
+ * slot 2).
+ */
+STATIC INLINE void Chip_TIMER_CaptureFallingEdgeEnable(LPC_TIMER_T *pTMR, int8_t capnum)
+{
+ pTMR->CCR |= TIMER_CAP_FALLING(capnum);
+}
+
+/**
+ * @brief Disables capture on on falling edge of selected CAP signal. For the
+ * selected capture register, disables the selected CAPn.capnum signal to load
+ * the capture register with the terminal coount on a falling edge.
+ * @param pTMR : Pointer to timer IP register address
+ * @param capnum : Capture signal/register to use
+ * @return Nothing
+ * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and
+ * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture
+ * slot 2).
+ */
+STATIC INLINE void Chip_TIMER_CaptureFallingEdgeDisable(LPC_TIMER_T *pTMR, int8_t capnum)
+{
+ pTMR->CCR &= ~TIMER_CAP_FALLING(capnum);
+}
+
+/**
+ * @brief Enables interrupt on capture of selected CAP signal. For the
+ * selected capture register, an interrupt will be generated when the enabled
+ * rising or falling edge on CAPn.capnum is detected.
+ * @param pTMR : Pointer to timer IP register address
+ * @param capnum : Capture signal/register to use
+ * @return Nothing
+ * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and
+ * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture
+ * slot 2).
+ */
+STATIC INLINE void Chip_TIMER_CaptureEnableInt(LPC_TIMER_T *pTMR, int8_t capnum)
+{
+ pTMR->CCR |= TIMER_INT_ON_CAP(capnum);
+}
+
+/**
+ * @brief Disables interrupt on capture of selected CAP signal
+ * @param pTMR : Pointer to timer IP register address
+ * @param capnum : Capture signal/register to use
+ * @return Nothing
+ * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and
+ * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture
+ * slot 2).
+ */
+STATIC INLINE void Chip_TIMER_CaptureDisableInt(LPC_TIMER_T *pTMR, int8_t capnum)
+{
+ pTMR->CCR &= ~TIMER_INT_ON_CAP(capnum);
+}
+
+/**
+ * @brief Standard timer initial match pin state and change state
+ */
+typedef enum IP_TIMER_PIN_MATCH_STATE {
+ TIMER_EXTMATCH_DO_NOTHING = 0, /*!< Timer match state does nothing on match pin */
+ TIMER_EXTMATCH_CLEAR = 1, /*!< Timer match state sets match pin low */
+ TIMER_EXTMATCH_SET = 2, /*!< Timer match state sets match pin high */
+ TIMER_EXTMATCH_TOGGLE = 3 /*!< Timer match state toggles match pin */
+} TIMER_PIN_MATCH_STATE_T;
+
+/**
+ * @brief Sets external match control (MATn.matchnum) pin control. For the pin
+ * selected with matchnum, sets the function of the pin that occurs on
+ * a terminal count match for the match count.
+ * @param pTMR : Pointer to timer IP register address
+ * @param initial_state : Initial state of the pin, high(1) or low(0)
+ * @param matchState : Selects the match state for the pin
+ * @param matchnum : MATn.matchnum signal to use
+ * @return Nothing
+ * @note For the pin selected with matchnum, sets the function of the pin that occurs on
+ * a terminal count match for the match count.
+ */
+void Chip_TIMER_ExtMatchControlSet(LPC_TIMER_T *pTMR, int8_t initial_state,
+ TIMER_PIN_MATCH_STATE_T matchState, int8_t matchnum);
+
+/**
+ * @brief Standard timer clock and edge for count source
+ */
+typedef enum IP_TIMER_CAP_SRC_STATE {
+ TIMER_CAPSRC_RISING_PCLK = 0, /*!< Timer ticks on PCLK rising edge */
+ TIMER_CAPSRC_RISING_CAPN = 1, /*!< Timer ticks on CAPn.x rising edge */
+ TIMER_CAPSRC_FALLING_CAPN = 2, /*!< Timer ticks on CAPn.x falling edge */
+ TIMER_CAPSRC_BOTH_CAPN = 3 /*!< Timer ticks on CAPn.x both edges */
+} TIMER_CAP_SRC_STATE_T;
+
+/**
+ * @brief Sets timer count source and edge with the selected passed from CapSrc.
+ * If CapSrc selected a CAPn pin, select the specific CAPn pin with the capnum value.
+ * @param pTMR : Pointer to timer IP register address
+ * @param capSrc : timer clock source and edge
+ * @param capnum : CAPn.capnum pin to use (if used)
+ * @return Nothing
+ * @note If CapSrc selected a CAPn pin, select the specific CAPn pin with the capnum value.
+ */
+STATIC INLINE void Chip_TIMER_TIMER_SetCountClockSrc(LPC_TIMER_T *pTMR,
+ TIMER_CAP_SRC_STATE_T capSrc,
+ int8_t capnum)
+{
+ pTMR->CTCR = (uint32_t) capSrc | ((uint32_t) capnum) << 2;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIMER_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/uart_0_11u6x.h b/source/lpc_chip_11u6x/inc/uart_0_11u6x.h
new file mode 100644
index 0000000..ac719ed
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/uart_0_11u6x.h
@@ -0,0 +1,777 @@
+/*
+ * @brief LPC11u6x USART0 chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __UART_0_11U6X_H_
+#define __UART_0_11U6X_H_
+
+#include "ring_buffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup UART_11U6X CHIP: LPC11u6x UART 0 driver
+ * @ingroup CHIP_11U6X_Drivers
+ * This driver only works with USART 0. Do not mix UART0_* and UARTN_*
+ * macro definitions across UUSART 0 and USART 1-4 drivers.
+ * @{
+ */
+
+/**
+ * @brief USART 0 register block structure
+ */
+typedef struct { /*!< USARTn Structure */
+
+ union {
+ __IO uint32_t DLL; /*!< Divisor Latch LSB. Least significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider (DLAB = 1). */
+ __O uint32_t THR; /*!< Transmit Holding Register. The next character to be transmitted is written here (DLAB = 0). */
+ __I uint32_t RBR; /*!< Receiver Buffer Register. Contains the next received character to be read (DLAB = 0). */
+ };
+
+ union {
+ __IO uint32_t IER; /*!< Interrupt Enable Register. Contains individual interrupt enable bits for the 7 potential UART interrupts (DLAB = 0). */
+ __IO uint32_t DLM; /*!< Divisor Latch MSB. Most significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider (DLAB = 1). */
+ };
+
+ union {
+ __O uint32_t FCR; /*!< FIFO Control Register. Controls UART FIFO usage and modes. */
+ __I uint32_t IIR; /*!< Interrupt ID Register. Identifies which interrupt(s) are pending. */
+ };
+
+ __IO uint32_t LCR; /*!< Line Control Register. Contains controls for frame formatting and break generation. */
+ __IO uint32_t MCR; /*!< Modem Control Register. Only present on USART ports with full modem support. */
+ __I uint32_t LSR; /*!< Line Status Register. Contains flags for transmit and receive status, including line errors. */
+ __I uint32_t MSR; /*!< Modem Status Register. Only present on USART ports with full modem support. */
+ __IO uint32_t SCR; /*!< Scratch Pad Register. Eight-bit temporary storage for software. */
+ __IO uint32_t ACR; /*!< Auto-baud Control Register. Contains controls for the auto-baud feature. */
+ __IO uint32_t ICR; /*!< IrDA control register (not all UARTS) */
+ __IO uint32_t FDR; /*!< Fractional Divider Register. Generates a clock input for the baud rate divider. */
+ __IO uint32_t OSR; /*!< Oversampling Register. Controls the degree of oversampling during each bit time. Only on some UARTS. */
+ __IO uint32_t TER; /*!< Transmit Enable Register. Turns off USART transmitter for use with software flow control. */
+ __I uint32_t RESERVED0[3];
+ __IO uint32_t HDEN; /*!< Half-duplex enable Register- only on some UARTs */
+ __I uint32_t RESERVED1[1];
+ __IO uint32_t SCICTRL; /*!< Smart card interface control register- only on some UARTs */
+ __IO uint32_t RS485CTRL; /*!< RS-485/EIA-485 Control. Contains controls to configure various aspects of RS-485/EIA-485 modes. */
+ __IO uint32_t RS485ADRMATCH; /*!< RS-485/EIA-485 address match. Contains the address match value for RS-485/EIA-485 mode. */
+ __IO uint32_t RS485DLY; /*!< RS-485/EIA-485 direction control delay. */
+ __IO uint32_t SYNCCTRL; /*!< Synchronous mode control register. Only on USARTs. */
+} LPC_USART0_T;
+
+/**
+ * @brief Macro defines for UART Receive Buffer register
+ */
+#define UART0_RBR_MASKBIT (0xFF) /*!< UART Received Buffer mask bit (8 bits) */
+
+/**
+ * @brief Macro defines for UART Divisor Latch LSB register
+ */
+#define UART0_LOAD_DLL(div) ((div) & 0xFF) /*!< Macro for loading LSB of divisor */
+#define UART0_DLL_MASKBIT (0xFF) /*!< Divisor latch LSB bit mask */
+
+/**
+ * @brief Macro defines for UART Divisor Latch MSB register
+ */
+#define UART0_LOAD_DLM(div) (((div) >> 8) & 0xFF) /*!< Macro for loading MSB of divisors */
+#define UART0_DLM_MASKBIT (0xFF) /*!< Divisor latch MSB bit mask */
+
+/**
+ * @brief Macro defines for UART Interrupt Enable Register
+ */
+#define UART0_IER_RBRINT (1 << 0) /*!< RBR Interrupt enable */
+#define UART0_IER_THREINT (1 << 1) /*!< THR Interrupt enable */
+#define UART0_IER_RLSINT (1 << 2) /*!< RX line status interrupt enable */
+#define UART0_IER_MSINT (1 << 3) /*!< Modem status interrupt enable - valid for 11xx, 17xx/40xx UART1, 18xx/43xx UART1 only */
+#define UART0_IER_CTSINT (1 << 7) /*!< CTS signal transition interrupt enable - valid for 17xx/40xx UART1, 18xx/43xx UART1 only */
+#define UART0_IER_ABEOINT (1 << 8) /*!< Enables the end of auto-baud interrupt */
+#define UART0_IER_ABTOINT (1 << 9) /*!< Enables the auto-baud time-out interrupt */
+#define UART0_IER_BITMASK (0x307) /*!< UART interrupt enable register bit mask - valid for 13xx, 17xx/40xx UART0/2/3, 18xx/43xx UART0/2/3 only*/
+
+/**
+ * @brief Macro defines for UART Interrupt Identification Register
+ */
+#define UART0_IIR_INTSTAT_PEND (1 << 0) /*!< Interrupt pending status - Active low */
+#define UART0_IIR_FIFO_EN (3 << 6) /*!< These bits are equivalent to FCR[0] */
+#define UART0_IIR_ABEO_INT (1 << 8) /*!< End of auto-baud interrupt */
+#define UART0_IIR_ABTO_INT (1 << 9) /*!< Auto-baud time-out interrupt */
+#define UART0_IIR_BITMASK (0x3CF) /*!< UART interrupt identification register bit mask */
+
+/* Interrupt ID bit definitions */
+#define UART0_IIR_INTID_MASK (7 << 1) /*!< Interrupt identification: Interrupt ID mask */
+#define UART0_IIR_INTID_RLS (3 << 1) /*!< Interrupt identification: Receive line interrupt */
+#define UART0_IIR_INTID_RDA (2 << 1) /*!< Interrupt identification: Receive data available interrupt */
+#define UART0_IIR_INTID_CTI (6 << 1) /*!< Interrupt identification: Character time-out indicator interrupt */
+#define UART0_IIR_INTID_THRE (1 << 1) /*!< Interrupt identification: THRE interrupt */
+#define UART0_IIR_INTID_MODEM (0 << 1) /*!< Interrupt identification: Modem interrupt */
+
+/**
+ * @brief Macro defines for UART FIFO Control Register
+ */
+#define UART0_FCR_FIFO_EN (1 << 0) /*!< UART FIFO enable */
+#define UART0_FCR_RX_RS (1 << 1) /*!< UART RX FIFO reset */
+#define UART0_FCR_TX_RS (1 << 2) /*!< UART TX FIFO reset */
+#define UART0_FCR_DMAMODE_SEL (1 << 3) /*!< UART DMA mode selection */
+#define UART0_FCR_BITMASK (0xCF) /*!< UART FIFO control bit mask */
+
+#define UART0_TX_FIFO_SIZE (16)
+
+/* FIFO trigger level bit definitions */
+#define UART0_FCR_TRG_LEV0 (0) /*!< UART FIFO trigger level 0: 1 character */
+#define UART0_FCR_TRG_LEV1 (1 << 6) /*!< UART FIFO trigger level 1: 4 character */
+#define UART0_FCR_TRG_LEV2 (2 << 6) /*!< UART FIFO trigger level 2: 8 character */
+#define UART0_FCR_TRG_LEV3 (3 << 6) /*!< UART FIFO trigger level 3: 14 character */
+
+/**
+ * @brief Macro defines for UART Line Control Register
+ */
+/* UART word length select bit definitions */
+#define UART0_LCR_WLEN_MASK (3 << 0) /*!< UART word length select bit mask */
+#define UART0_LCR_WLEN5 (0 << 0) /*!< UART word length select: 5 bit data mode */
+#define UART0_LCR_WLEN6 (1 << 0) /*!< UART word length select: 6 bit data mode */
+#define UART0_LCR_WLEN7 (2 << 0) /*!< UART word length select: 7 bit data mode */
+#define UART0_LCR_WLEN8 (3 << 0) /*!< UART word length select: 8 bit data mode */
+
+/* UART Stop bit select bit definitions */
+#define UART0_LCR_SBS_MASK (1 << 2) /*!< UART stop bit select: bit mask */
+#define UART0_LCR_SBS_1BIT (0 << 2) /*!< UART stop bit select: 1 stop bit */
+#define UART0_LCR_SBS_2BIT (1 << 2) /*!< UART stop bit select: 2 stop bits (in 5 bit data mode, 1.5 stop bits) */
+
+/* UART Parity enable bit definitions */
+#define UART0_LCR_PARITY_EN (1 << 3) /*!< UART Parity Enable */
+#define UART0_LCR_PARITY_DIS (0 << 3) /*!< UART Parity Disable */
+#define UART0_LCR_PARITY_ODD (0 << 4) /*!< UART Parity select: Odd parity */
+#define UART0_LCR_PARITY_EVEN (1 << 4) /*!< UART Parity select: Even parity */
+#define UART0_LCR_PARITY_F_1 (2 << 4) /*!< UART Parity select: Forced 1 stick parity */
+#define UART0_LCR_PARITY_F_0 (3 << 4) /*!< UART Parity select: Forced 0 stick parity */
+#define UART0_LCR_BREAK_EN (1 << 6) /*!< UART Break transmission enable */
+#define UART0_LCR_DLAB_EN (1 << 7) /*!< UART Divisor Latches Access bit enable */
+#define UART0_LCR_BITMASK (0xFF) /*!< UART line control bit mask */
+
+/**
+ * @brief Macro defines for UART Modem Control Register
+ */
+#define UART0_MCR_DTR_CTRL (1 << 0) /*!< Source for modem output pin DTR */
+#define UART0_MCR_RTS_CTRL (1 << 1) /*!< Source for modem output pin RTS */
+#define UART0_MCR_LOOPB_EN (1 << 4) /*!< Loop back mode select */
+#define UART0_MCR_AUTO_RTS_EN (1 << 6) /*!< Enable Auto RTS flow-control */
+#define UART0_MCR_AUTO_CTS_EN (1 << 7) /*!< Enable Auto CTS flow-control */
+#define UART0_MCR_BITMASK (0xD3) /*!< UART bit mask value */
+
+/**
+ * @brief Macro defines for UART Line Status Register
+ */
+#define UART0_LSR_RDR (1 << 0) /*!< Line status: Receive data ready */
+#define UART0_LSR_OE (1 << 1) /*!< Line status: Overrun error */
+#define UART0_LSR_PE (1 << 2) /*!< Line status: Parity error */
+#define UART0_LSR_FE (1 << 3) /*!< Line status: Framing error */
+#define UART0_LSR_BI (1 << 4) /*!< Line status: Break interrupt */
+#define UART0_LSR_THRE (1 << 5) /*!< Line status: Transmit holding register empty */
+#define UART0_LSR_TEMT (1 << 6) /*!< Line status: Transmitter empty */
+#define UART0_LSR_RXFE (1 << 7) /*!< Line status: Error in RX FIFO */
+#define UART0_LSR_TXFE (1 << 8) /*!< Line status: Error in RX FIFO */
+#define UART0_LSR_BITMASK (0xFF) /*!< UART Line status bit mask */
+
+/**
+ * @brief Macro defines for UART Modem Status Register
+ */
+#define UART0_MSR_DELTA_CTS (1 << 0) /*!< Modem status: State change of input CTS */
+#define UART0_MSR_DELTA_DSR (1 << 1) /*!< Modem status: State change of input DSR */
+#define UART0_MSR_LO2HI_RI (1 << 2) /*!< Modem status: Low to high transition of input RI */
+#define UART0_MSR_DELTA_DCD (1 << 3) /*!< Modem status: State change of input DCD */
+#define UART0_MSR_CTS (1 << 4) /*!< Modem status: Clear To Send State */
+#define UART0_MSR_DSR (1 << 5) /*!< Modem status: Data Set Ready State */
+#define UART0_MSR_RI (1 << 6) /*!< Modem status: Ring Indicator State */
+#define UART0_MSR_DCD (1 << 7) /*!< Modem status: Data Carrier Detect State */
+#define UART0_MSR_BITMASK (0xFF) /*!< Modem status: MSR register bit-mask value */
+
+/**
+ * @brief Macro defines for UART Auto baudrate control register
+ */
+#define UART0_ACR_START (1 << 0) /*!< UART Auto-baud start */
+#define UART0_ACR_MODE (1 << 1) /*!< UART Auto baudrate Mode 1 */
+#define UART0_ACR_AUTO_RESTART (1 << 2) /*!< UART Auto baudrate restart */
+#define UART0_ACR_ABEOINT_CLR (1 << 8) /*!< UART End of auto-baud interrupt clear */
+#define UART0_ACR_ABTOINT_CLR (1 << 9) /*!< UART Auto-baud time-out interrupt clear */
+#define UART0_ACR_BITMASK (0x307) /*!< UART Auto Baudrate register bit mask */
+
+/**
+ * @brief Macro defines for UART RS485 Control register
+ */
+#define UART0_RS485CTRL_NMM_EN (1 << 0) /*!< RS-485/EIA-485 Normal Multi-drop Mode (NMM) is disabled */
+#define UART0_RS485CTRL_RX_DIS (1 << 1) /*!< The receiver is disabled */
+#define UART0_RS485CTRL_AADEN (1 << 2) /*!< Auto Address Detect (AAD) is enabled */
+#define UART0_RS485CTRL_SEL_DTR (1 << 3) /*!< If direction control is enabled (bit DCTRL = 1), pin DTR is
+ used for direction control */
+#define UART0_RS485CTRL_DCTRL_EN (1 << 4) /*!< Enable Auto Direction Control */
+#define UART0_RS485CTRL_OINV_1 (1 << 5) /*!< This bit reverses the polarity of the direction
+ control signal on the RTS (or DTR) pin. The direction control pin
+ will be driven to logic "1" when the transmitter has data to be sent */
+#define UART0_RS485CTRL_BITMASK (0x3F) /*!< RS485 control bit-mask value */
+
+/**
+ * @brief Macro defines for UART IrDA Control Register
+ */
+#define UART0_ICR_IRDAEN (1 << 0) /*!< IrDA mode enable */
+#define UART0_ICR_IRDAINV (1 << 1) /*!< IrDA serial input inverted */
+#define UART0_ICR_FIXPULSE_EN (1 << 2) /*!< IrDA fixed pulse width mode */
+#define UART0_ICR_PULSEDIV(n) ((n & 0x07) << 3) /*!< PulseDiv - Configures the pulse when FixPulseEn = 1 */
+#define UART0_ICR_BITMASK (0x3F) /*!< UART IRDA bit mask */
+
+/**
+ * @brief Macro defines for UART half duplex register - ????
+ */
+#define UART0_HDEN_HDEN ((1 << 0)) /*!< enable half-duplex mode*/
+
+/**
+ * @brief Macro defines for UART Smart card interface Control Register
+ */
+#define UART0_SCICTRL_SCIEN (1 << 0) /*!< enable asynchronous half-duplex smart card interface*/
+#define UART0_SCICTRL_NACKDIS (1 << 1) /*!< NACK response is inhibited*/
+#define UART0_SCICTRL_PROTSEL_T1 (1 << 2) /*!< ISO7816-3 protocol T1 is selected*/
+#define UART0_SCICTRL_TXRETRY(n) ((n & 0x07) << 5) /*!< number of retransmission*/
+#define UART0_SCICTRL_GUARDTIME(n) ((n & 0xFF) << 8) /*!< Extra guard time*/
+
+/**
+ * @brief Macro defines for UART Fractional Divider Register
+ */
+#define UART0_FDR_DIVADDVAL(n) (n & 0x0F) /*!< Baud-rate generation pre-scaler divisor */
+#define UART0_FDR_MULVAL(n) ((n << 4) & 0xF0) /*!< Baud-rate pre-scaler multiplier value */
+#define UART0_FDR_BITMASK (0xFF) /*!< UART Fractional Divider register bit mask */
+
+/**
+ * @brief Macro defines for UART Tx Enable Register
+ */
+#define UART0_TER1_TXEN (1 << 7) /*!< Transmit enable bit */
+
+/**
+ * @brief Macro defines for UART Synchronous Control Register
+ */
+#define UART0_SYNCCTRL_SYNC (1 << 0) /*!< enable synchronous mode*/
+#define UART0_SYNCCTRL_CSRC_MASTER (1 << 1) /*!< synchronous master mode*/
+#define UART0_SYNCCTRL_FES (1 << 2) /*!< sample on falling edge*/
+#define UART0_SYNCCTRL_TSBYPASS (1 << 3) /*!< to be defined*/
+#define UART0_SYNCCTRL_CSCEN (1 << 4) /*!< Continuous running clock enable (master mode only)*/
+#define UART0_SYNCCTRL_STARTSTOPDISABLE (1 << 5) /*!< Do not send start/stop bit*/
+#define UART0_SYNCCTRL_CCCLR (1 << 6) /*!< stop continuous clock*/
+
+/**
+ * @brief Enable transmission on UART TxD pin
+ * @param pUART : Pointer to selected pUART peripheral
+ * @return Nothing
+ */
+STATIC INLINE void Chip_UART0_TXEnable(LPC_USART0_T *pUART)
+{
+ pUART->TER = UART0_TER1_TXEN;
+}
+
+/**
+ * @brief Disable transmission on UART TxD pin
+ * @param pUART : Pointer to selected pUART peripheral
+ * @return Nothing
+ */
+STATIC INLINE void Chip_UART0_TXDisable(LPC_USART0_T *pUART)
+{
+ pUART->TER = 0;
+}
+
+/**
+ * @brief Transmit a single data byte through the UART peripheral
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Byte to transmit
+ * @return Nothing
+ * @note This function attempts to place a byte into the UART transmit
+ * FIFO or transmit hold register regard regardless of UART state
+ */
+STATIC INLINE void Chip_UART0_SendByte(LPC_USART0_T *pUART, uint8_t data)
+{
+ pUART->THR = (uint32_t) data;
+}
+
+/**
+ * @brief Read a single byte data from the UART peripheral
+ * @param pUART : Pointer to selected UART peripheral
+ * @return A single byte of data read
+ * @note This function reads a byte from the UART receive FIFO or
+ * receive hold register regard regardless of UART state. The
+ * FIFO status should be read first prior to using this function
+ */
+STATIC INLINE uint8_t Chip_UART0_ReadByte(LPC_USART0_T *pUART)
+{
+ return (uint8_t) (pUART->RBR & UART0_RBR_MASKBIT);
+}
+
+/**
+ * @brief Enable UART interrupts
+ * @param pUART : Pointer to selected UART peripheral
+ * @param intMask : OR'ed Interrupts to enable in the Interrupt Enable Register (IER)
+ * @return Nothing
+ * @note Use an OR'ed value of UART0_IER_* definitions with this function
+ * to enable specific UART interrupts. The Divisor Latch Access Bit
+ * (DLAB) in LCR must be cleared in order to access the IER register.
+ * This function doesn't alter the DLAB state
+ */
+STATIC INLINE void Chip_UART0_IntEnable(LPC_USART0_T *pUART, uint32_t intMask)
+{
+ pUART->IER |= intMask;
+}
+
+/**
+ * @brief Disable UART interrupts
+ * @param pUART : Pointer to selected UART peripheral
+ * @param intMask : OR'ed Interrupts to disable in the Interrupt Enable Register (IER)
+ * @return Nothing
+ * @note Use an OR'ed value of UART0_IER_* definitions with this function
+ * to disable specific UART interrupts. The Divisor Latch Access Bit
+ * (DLAB) in LCR must be cleared in order to access the IER register.
+ * This function doesn't alter the DLAB state
+ */
+STATIC INLINE void Chip_UART0_IntDisable(LPC_USART0_T *pUART, uint32_t intMask)
+{
+ pUART->IER &= ~intMask;
+}
+
+/**
+ * @brief Returns UART interrupts that are enabled
+ * @param pUART : Pointer to selected UART peripheral
+ * @return Returns the enabled UART interrupts
+ * @note Use an OR'ed value of UART0_IER_* definitions with this function
+ * to determine which interrupts are enabled. You can check
+ * for multiple enabled bits if needed.
+ */
+STATIC INLINE uint32_t Chip_UART0_GetIntsEnabled(LPC_USART0_T *pUART)
+{
+ return pUART->IER;
+}
+
+/**
+ * @brief Read the Interrupt Identification Register (IIR)
+ * @param pUART : Pointer to selected UART peripheral
+ * @return Current pending interrupt status per the IIR register
+ */
+STATIC INLINE uint32_t Chip_UART0_ReadIntIDReg(LPC_USART0_T *pUART)
+{
+ return pUART->IIR;
+}
+
+/**
+ * @brief Setup the UART FIFOs
+ * @param pUART : Pointer to selected UART peripheral
+ * @param fcr : FIFO control register setup OR'ed flags
+ * @return Nothing
+ * @note Use OR'ed value of UART0_FCR_* definitions with this function
+ * to select specific options. For example, to enable the FIFOs
+ * with a RX trip level of 8 characters, use something like
+ * (UART0_FCR_FIFO_EN | UART0_FCR_TRG_LEV2)
+ */
+STATIC INLINE void Chip_UART0_SetupFIFOS(LPC_USART0_T *pUART, uint32_t fcr)
+{
+ pUART->FCR = fcr;
+}
+
+/**
+ * @brief Configure data width, parity and stop bits
+ * @param pUART : Pointer to selected pUART peripheral
+ * @param config : UART configuration, OR'ed values of UART0_LCR_* defines
+ * @return Nothing
+ * @note Select OR'ed config options for the UART from the UART0_LCR_*
+ * definitions. For example, a configuration of 8 data bits, 1
+ * stop bit, and even (enabled) parity would be
+ * (UART0_LCR_WLEN8 | UART0_LCR_SBS_1BIT | UART0_LCR_PARITY_EN | UART0_LCR_PARITY_EVEN)
+ */
+STATIC INLINE void Chip_UART0_ConfigData(LPC_USART0_T *pUART, uint32_t config)
+{
+ pUART->LCR = config;
+}
+
+/**
+ * @brief Enable access to Divisor Latches
+ * @param pUART : Pointer to selected UART peripheral
+ * @return Nothing
+ */
+STATIC INLINE void Chip_UART0_EnableDivisorAccess(LPC_USART0_T *pUART)
+{
+ pUART->LCR |= UART0_LCR_DLAB_EN;
+}
+
+/**
+ * @brief Disable access to Divisor Latches
+ * @param pUART : Pointer to selected UART peripheral
+ * @return Nothing
+ */
+STATIC INLINE void Chip_UART0_DisableDivisorAccess(LPC_USART0_T *pUART)
+{
+ pUART->LCR &= ~UART0_LCR_DLAB_EN;
+}
+
+/**
+ * @brief Set LSB and MSB divisor latch registers
+ * @param pUART : Pointer to selected UART peripheral
+ * @param dll : Divisor Latch LSB value
+ * @param dlm : Divisor Latch MSB value
+ * @return Nothing
+ * @note The Divisor Latch Access Bit (DLAB) in LCR must be set in
+ * order to access the USART Divisor Latches. This function
+ * doesn't alter the DLAB state.
+ */
+STATIC INLINE void Chip_UART0_SetDivisorLatches(LPC_USART0_T *pUART, uint8_t dll, uint8_t dlm)
+{
+ pUART->DLL = (uint32_t) dll;
+ pUART->DLM = (uint32_t) dlm;
+}
+
+/**
+ * @brief Return modem control register/status
+ * @param pUART : Pointer to selected UART peripheral
+ * @return Modem control register (status)
+ * @note Mask bits of the returned status value with UART0_MCR_*
+ * definitions for specific statuses.
+ */
+STATIC INLINE uint32_t Chip_UART0_ReadModemControl(LPC_USART0_T *pUART)
+{
+ return pUART->MCR;
+}
+
+/**
+ * @brief Set modem control register/status
+ * @param pUART : Pointer to selected UART peripheral
+ * @param mcr : Modem control register flags to set
+ * @return Nothing
+ * @note Use an Or'ed value of UART0_MCR_* definitions with this
+ * call to set specific options.
+ */
+STATIC INLINE void Chip_UART0_SetModemControl(LPC_USART0_T *pUART, uint32_t mcr)
+{
+ pUART->MCR |= mcr;
+}
+
+/**
+ * @brief Clear modem control register/status
+ * @param pUART : Pointer to selected UART peripheral
+ * @param mcr : Modem control register flags to clear
+ * @return Nothing
+ * @note Use an Or'ed value of UART0_MCR_* definitions with this
+ * call to clear specific options.
+ */
+STATIC INLINE void Chip_UART0_ClearModemControl(LPC_USART0_T *pUART, uint32_t mcr)
+{
+ pUART->MCR &= ~mcr;
+}
+
+/**
+ * @brief Return Line Status register/status (LSR)
+ * @param pUART : Pointer to selected UART peripheral
+ * @return Line Status register (status)
+ * @note Mask bits of the returned status value with UART0_LSR_*
+ * definitions for specific statuses.
+ */
+STATIC INLINE uint32_t Chip_UART0_ReadLineStatus(LPC_USART0_T *pUART)
+{
+ return pUART->LSR;
+}
+
+/**
+ * @brief Return Modem Status register/status (MSR)
+ * @param pUART : Pointer to selected UART peripheral
+ * @return Modem Status register (status)
+ * @note Mask bits of the returned status value with UART0_MSR_*
+ * definitions for specific statuses.
+ */
+STATIC INLINE uint32_t Chip_UART0_ReadModemStatus(LPC_USART0_T *pUART)
+{
+ return pUART->MSR;
+}
+
+/**
+ * @brief Write a byte to the scratchpad register
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Byte value to write
+ * @return Nothing
+ */
+STATIC INLINE void Chip_UART0_SetScratch(LPC_USART0_T *pUART, uint8_t data)
+{
+ pUART->SCR = (uint32_t) data;
+}
+
+/**
+ * @brief Returns current byte value in the scratchpad register
+ * @param pUART : Pointer to selected UART peripheral
+ * @return Byte value read from scratchpad register
+ */
+STATIC INLINE uint8_t Chip_UART0_ReadScratch(LPC_USART0_T *pUART)
+{
+ return (uint8_t) (pUART->SCR & 0xFF);
+}
+
+/**
+ * @brief Set autobaud register options
+ * @param pUART : Pointer to selected UART peripheral
+ * @param acr : Or'ed values to set for ACR register
+ * @return Nothing
+ * @note Use an Or'ed value of UART0_ACR_* definitions with this
+ * call to set specific options.
+ */
+STATIC INLINE void Chip_UART0_SetAutoBaudReg(LPC_USART0_T *pUART, uint32_t acr)
+{
+ pUART->ACR |= acr;
+}
+
+/**
+ * @brief Clear autobaud register options
+ * @param pUART : Pointer to selected UART peripheral
+ * @param acr : Or'ed values to clear for ACR register
+ * @return Nothing
+ * @note Use an Or'ed value of UART0_ACR_* definitions with this
+ * call to clear specific options.
+ */
+STATIC INLINE void Chip_UART0_ClearAutoBaudReg(LPC_USART0_T *pUART, uint32_t acr)
+{
+ pUART->ACR &= ~acr;
+}
+
+/**
+ * @brief Set RS485 control register options
+ * @param pUART : Pointer to selected UART peripheral
+ * @param ctrl : Or'ed values to set for RS485 control register
+ * @return Nothing
+ * @note Use an Or'ed value of UART0_RS485CTRL_* definitions with this
+ * call to set specific options.
+ */
+STATIC INLINE void Chip_UART0_SetRS485Flags(LPC_USART0_T *pUART, uint32_t ctrl)
+{
+ pUART->RS485CTRL |= ctrl;
+}
+
+/**
+ * @brief Clear RS485 control register options
+ * @param pUART : Pointer to selected UART peripheral
+ * @param ctrl : Or'ed values to clear for RS485 control register
+ * @return Nothing
+ * @note Use an Or'ed value of UART0_RS485CTRL_* definitions with this
+ * call to clear specific options.
+ */
+STATIC INLINE void Chip_UART0_ClearRS485Flags(LPC_USART0_T *pUART, uint32_t ctrl)
+{
+ pUART->RS485CTRL &= ~ctrl;
+}
+
+/**
+ * @brief Set RS485 address match value
+ * @param pUART : Pointer to selected UART peripheral
+ * @param addr : Address match value for RS-485/EIA-485 mode
+ * @return Nothing
+ */
+STATIC INLINE void Chip_UART0_SetRS485Addr(LPC_USART0_T *pUART, uint8_t addr)
+{
+ pUART->RS485ADRMATCH = (uint32_t) addr;
+}
+
+/**
+ * @brief Read RS485 address match value
+ * @param pUART : Pointer to selected UART peripheral
+ * @return Address match value for RS-485/EIA-485 mode
+ */
+STATIC INLINE uint8_t Chip_UART0_GetRS485Addr(LPC_USART0_T *pUART)
+{
+ return (uint8_t) (pUART->RS485ADRMATCH & 0xFF);
+}
+
+/**
+ * @brief Set RS485 direction control (RTS or DTR) delay value
+ * @param pUART : Pointer to selected UART peripheral
+ * @param dly : direction control (RTS or DTR) delay value
+ * @return Nothing
+ * @note This delay time is in periods of the baud clock. Any delay
+ * time from 0 to 255 bit times may be programmed.
+ */
+STATIC INLINE void Chip_UART0_SetRS485Delay(LPC_USART0_T *pUART, uint8_t dly)
+{
+ pUART->RS485DLY = (uint32_t) dly;
+}
+
+/**
+ * @brief Read RS485 direction control (RTS or DTR) delay value
+ * @param pUART : Pointer to selected UART peripheral
+ * @return direction control (RTS or DTR) delay value
+ * @note This delay time is in periods of the baud clock. Any delay
+ * time from 0 to 255 bit times may be programmed.
+ */
+STATIC INLINE uint8_t Chip_UART0_GetRS485Delay(LPC_USART0_T *pUART)
+{
+ return (uint8_t) (pUART->RS485DLY & 0xFF);
+}
+
+/**
+ * @brief Initializes the pUART peripheral
+ * @param pUART : Pointer to selected pUART peripheral
+ * @return Nothing
+ */
+void Chip_UART0_Init(LPC_USART0_T *pUART);
+
+/**
+ * @brief De-initializes the pUART peripheral.
+ * @param pUART : Pointer to selected pUART peripheral
+ * @return Nothing
+ */
+void Chip_UART0_DeInit(LPC_USART0_T *pUART);
+
+/**
+ * @brief Transmit a byte array through the UART peripheral (non-blocking)
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Pointer to bytes to transmit
+ * @param numBytes : Number of bytes to transmit
+ * @return The actual number of bytes placed into the FIFO
+ * @note This function places data into the transmit FIFO until either
+ * all the data is in the FIFO or the FIFO is full. This function
+ * will not block in the FIFO is full. The actual number of bytes
+ * placed into the FIFO is returned. This function ignores errors.
+ */
+int Chip_UART0_Send(LPC_USART0_T *pUART, const void *data, int numBytes);
+
+/**
+ * @brief Read data through the UART peripheral (non-blocking)
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Pointer to bytes array to fill
+ * @param numBytes : Size of the passed data array
+ * @return The actual number of bytes read
+ * @note This function reads data from the receive FIFO until either
+ * all the data has been read or the passed buffer is completely full.
+ * This function will not block. This function ignores errors.
+ */
+int Chip_UART0_Read(LPC_USART0_T *pUART, void *data, int numBytes);
+
+/**
+ * @brief Sets best dividers to get a target bit rate (without fractional divider)
+ * @param pUART : Pointer to selected UART peripheral
+ * @param baudrate : Target baud rate (baud rate = bit rate)
+ * @return The actual baud rate, or 0 if no rate can be found
+ */
+uint32_t Chip_UART0_SetBaud(LPC_USART0_T *pUART, uint32_t baudrate);
+
+/**
+ * @brief Sets best dividers to get a target bit rate (with fractional divider)
+ * @param pUART : Pointer to selected UART peripheral
+ * @param baudrate : Target baud rate (baud rate = bit rate)
+ * @return The actual baud rate, or 0 if no rate can be found
+ */
+uint32_t Chip_UART0_SetBaudFDR(LPC_USART0_T *pUART, uint32_t baudrate);
+
+/**
+ * @brief Transmit a byte array through the UART peripheral (blocking)
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Pointer to data to transmit
+ * @param numBytes : Number of bytes to transmit
+ * @return The number of bytes transmitted
+ * @note This function will send or place all bytes into the transmit
+ * FIFO. This function will block until the last bytes are in the FIFO.
+ */
+int Chip_UART0_SendBlocking(LPC_USART0_T *pUART, const void *data, int numBytes);
+
+/**
+ * @brief Read data through the UART peripheral (blocking)
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Pointer to data array to fill
+ * @param numBytes : Size of the passed data array
+ * @return The size of the dat array
+ * @note This function reads data from the receive FIFO until the passed
+ * buffer is completely full. The function will block until full.
+ * This function ignores errors.
+ */
+int Chip_UART0_ReadBlocking(LPC_USART0_T *pUART, void *data, int numBytes);
+
+/**
+ * @brief UART receive-only interrupt handler for ring buffers
+ * @param pUART : Pointer to selected UART peripheral
+ * @param pRB : Pointer to ring buffer structure to use
+ * @return Nothing
+ * @note If ring buffer support is desired for the receive side
+ * of data transfer, the UART interrupt should call this
+ * function for a receive based interrupt status.
+ */
+void Chip_UART0_RXIntHandlerRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB);
+
+/**
+ * @brief UART transmit-only interrupt handler for ring buffers
+ * @param pUART : Pointer to selected UART peripheral
+ * @param pRB : Pointer to ring buffer structure to use
+ * @return Nothing
+ * @note If ring buffer support is desired for the transmit side
+ * of data transfer, the UART interrupt should call this
+ * function for a transmit based interrupt status.
+ */
+void Chip_UART0_TXIntHandlerRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB);
+
+/**
+ * @brief Populate a transmit ring buffer and start UART transmit
+ * @param pUART : Pointer to selected UART peripheral
+ * @param pRB : Pointer to ring buffer structure to use
+ * @param data : Pointer to buffer to move to ring buffer
+ * @param bytes : Number of bytes to move
+ * @return The number of bytes placed into the ring buffer
+ * @note Will move the data into the TX ring buffer and start the
+ * transfer. If the number of bytes returned is less than the
+ * number of bytes to send, the ring buffer is considered full.
+ */
+uint32_t Chip_UART0_SendRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB, const void *data, int bytes);
+
+/**
+ * @brief Copy data from a receive ring buffer
+ * @param pUART : Pointer to selected UART peripheral
+ * @param pRB : Pointer to ring buffer structure to use
+ * @param data : Pointer to buffer to fill from ring buffer
+ * @param bytes : Size of the passed buffer in bytes
+ * @return The number of bytes placed into the ring buffer
+ * @note Will move the data from the RX ring buffer up to the
+ * the maximum passed buffer size. Returns 0 if there is
+ * no data in the ring buffer.
+ */
+int Chip_UART0_ReadRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB, void *data, int bytes);
+
+/**
+ * @brief UART receive/transmit interrupt handler for ring buffers
+ * @param pUART : Pointer to selected UART peripheral
+ * @param pRXRB : Pointer to transmit ring buffer
+ * @param pTXRB : Pointer to receive ring buffer
+ * @return Nothing
+ * @note This provides a basic implementation of the UART IRQ
+ * handler for support of a ring buffer implementation for
+ * transmit and receive.
+ */
+void Chip_UART0_IRQRBHandler(LPC_USART0_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UART_0_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/uart_n_11u6x.h b/source/lpc_chip_11u6x/inc/uart_n_11u6x.h
new file mode 100644
index 0000000..691c116
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/uart_n_11u6x.h
@@ -0,0 +1,440 @@
+/*
+ * @brief LPC11u6xx USART1/2/3/4 driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __UART_N_11U6X_H_
+#define __UART_N_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ring_buffer.h"
+
+/** @defgroup UART_11U6X_2 CHIP: LPC11u6x USART N Driver (UARTS 1/2/3/4)
+ * @ingroup CHIP_11U6X_Drivers
+ * This driver only works with USARTs 1-4. Do not mix UART0_* and UARTN_*
+ * macro definitions across UUSART 0 and USART 1-4 drivers.
+ * @{
+ */
+
+/**
+ * @brief UART register block structure
+ */
+typedef struct {
+ __IO uint32_t CFG; /*!< Configuration register */
+ __IO uint32_t CTRL; /*!< Control register */
+ __IO uint32_t STAT; /*!< Status register */
+ __IO uint32_t INTENSET; /*!< Interrupt Enable read and set register */
+ __O uint32_t INTENCLR; /*!< Interrupt Enable clear register */
+ __I uint32_t RXDATA; /*!< Receive Data register */
+ __I uint32_t RXDATA_STAT; /*!< Receive Data with status register */
+ __IO uint32_t TXDATA; /*!< Transmit data register */
+ __IO uint32_t BRG; /*!< Baud Rate Generator register */
+ __IO uint32_t INTSTAT; /*!< Interrupt status register */
+ __IO uint32_t OSR; /*!< Oversample selection register for asynchronous communication */
+ __IO uint32_t ADDR; /*!< Address register for automatic address matching */
+} LPC_USARTN_T;
+
+/**
+ * @brief UART CFG register definitions
+ */
+#define UARTN_CFG_ENABLE (0x01 << 0)
+#define UARTN_CFG_DATALEN_7 (0x00 << 2) /*!< UART 7 bit length mode */
+#define UARTN_CFG_DATALEN_8 (0x01 << 2) /*!< UART 8 bit length mode */
+#define UARTN_CFG_DATALEN_9 (0x02 << 2) /*!< UART 9 bit length mode */
+#define UARTN_CFG_PARITY_NONE (0x00 << 4) /*!< No parity */
+#define UARTN_CFG_PARITY_EVEN (0x02 << 4) /*!< Even parity */
+#define UARTN_CFG_PARITY_ODD (0x03 << 4) /*!< Odd parity */
+#define UARTN_CFG_STOPLEN_1 (0x00 << 6) /*!< UART One Stop Bit Select */
+#define UARTN_CFG_STOPLEN_2 (0x01 << 6) /*!< UART Two Stop Bits Select */
+#define UARTN_MODE_32K (0x01 << 7) /*!< Selects the 32 kHz clock from the RTC oscillator as the clock source to the BRG */
+#define UARTN_CFG_CTSEN (0x01 << 9) /*!< CTS enable bit */
+#define UARTN_CFG_SYNCEN (0x01 << 11) /*!< Synchronous mode enable bit */
+#define UARTN_CFG_CLKPOL (0x01 << 12) /*!< Un_RXD rising edge sample enable bit */
+#define UARTN_CFG_SYNCMST (0x01 << 14) /*!< Select master mode (synchronous mode) enable bit */
+#define UARTN_CFG_LOOP (0x01 << 15) /*!< Loopback mode enable bit */
+
+/**
+ * @brief UART CTRL register definitions
+ */
+#define UARTN_CTRL_TXBRKEN (0x01 << 1) /*!< Continuous break enable bit */
+#define UARTN_CTRL_ADDRDET (0x01 << 2) /*!< Address detect mode enable bit */
+#define UARTN_CTRL_TXDIS (0x01 << 6) /*!< Transmit disable bit */
+#define UARTN_CTRL_CC (0x01 << 8) /*!< Continuous Clock mode enable bit */
+#define UARTN_CTRL_CLRCC (0x01 << 9) /*!< Clear Continuous Clock bit */
+
+/**
+ * @brief UART STAT register definitions
+ */
+#define UARTN_STAT_RXRDY (0x01 << 0) /*!< Receiver ready */
+#define UARTN_STAT_RXIDLE (0x01 << 1) /*!< Receiver idle */
+#define UARTN_STAT_TXRDY (0x01 << 2) /*!< Transmitter ready for data */
+#define UARTN_STAT_TXIDLE (0x01 << 3) /*!< Transmitter idle */
+#define UARTN_STAT_CTS (0x01 << 4) /*!< Status of CTS signal */
+#define UARTN_STAT_DELTACTS (0x01 << 5) /*!< Change in CTS state */
+#define UARTN_STAT_TXDISINT (0x01 << 6) /*!< Transmitter disabled */
+#define UARTN_STAT_OVERRUNINT (0x01 << 8) /*!< Overrun Error interrupt flag. */
+#define UARTN_STAT_RXBRK (0x01 << 10) /*!< Received break */
+#define UARTN_STAT_DELTARXBRK (0x01 << 11) /*!< Change in receive break detection */
+#define UARTN_STAT_START (0x01 << 12) /*!< Start detected */
+#define UARTN_STAT_FRM_ERRINT (0x01 << 13) /*!< Framing Error interrupt flag */
+#define UARTN_STAT_PAR_ERRINT (0x01 << 14) /*!< Parity Error interrupt flag */
+#define UARTN_STAT_RXNOISEINT (0x01 << 15) /*!< Received Noise interrupt flag */
+
+/**
+ * @brief UART INTENSET/INTENCLR register definitions
+ */
+#define UARTN_INTEN_RXRDY (0x01 << 0) /*!< Receive Ready interrupt */
+#define UARTN_INTEN_TXRDY (0x01 << 2) /*!< Transmit Ready interrupt */
+#define UARTN_INTEN_DELTACTS (0x01 << 5) /*!< Change in CTS state interrupt */
+#define UARTN_INTEN_TXDIS (0x01 << 6) /*!< Transmitter disable interrupt */
+#define UARTN_INTEN_OVERRUN (0x01 << 8) /*!< Overrun error interrupt */
+#define UARTN_INTEN_DELTARXBRK (0x01 << 11) /*!< Change in receiver break detection interrupt */
+#define UARTN_INTEN_START (0x01 << 12) /*!< Start detect interrupt */
+#define UARTN_INTEN_FRAMERR (0x01 << 13) /*!< Frame error interrupt */
+#define UARTN_INTEN_PARITYERR (0x01 << 14) /*!< Parity error interrupt */
+#define UARTN_INTEN_RXNOISE (0x01 << 15) /*!< Received noise interrupt */
+
+/**
+ * @brief Enable the UART
+ * @param pUART : Pointer to selected UARTx peripheral
+ * @return Nothing
+ */
+STATIC INLINE void Chip_UARTN_Enable(LPC_USARTN_T *pUART)
+{
+ pUART->CFG |= UARTN_CFG_ENABLE;
+}
+
+/**
+ * @brief Disable the UART
+ * @param pUART : Pointer to selected UARTx peripheral
+ * @return Nothing
+ */
+STATIC INLINE void Chip_UARTN_Disable(LPC_USARTN_T *pUART)
+{
+ pUART->CFG &= ~UARTN_CFG_ENABLE;
+}
+
+/**
+ * @brief Enable transmission on UART TxD pin
+ * @param pUART : Pointer to selected pUART peripheral
+ * @return Nothing
+ */
+STATIC INLINE void Chip_UARTN_TXEnable(LPC_USARTN_T *pUART)
+{
+ pUART->CTRL &= ~UARTN_CTRL_TXDIS;
+}
+
+/**
+ * @brief Disable transmission on UART TxD pin
+ * @param pUART : Pointer to selected pUART peripheral
+ * @return Nothing
+ */
+STATIC INLINE void Chip_UARTN_TXDisable(LPC_USARTN_T *pUART)
+{
+ pUART->CTRL |= UARTN_CTRL_TXDIS;
+}
+
+/**
+ * @brief Transmit a single data byte through the UART peripheral
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Byte to transmit
+ * @return Nothing
+ * @note This function attempts to place a byte into the UART transmit
+ * holding register regard regardless of UART state.
+ */
+STATIC INLINE void Chip_UARTN_SendByte(LPC_USARTN_T *pUART, uint8_t data)
+{
+ pUART->TXDATA = (uint32_t) data;
+}
+
+/**
+ * @brief Read a single byte data from the UART peripheral
+ * @param pUART : Pointer to selected UART peripheral
+ * @return A single byte of data read
+ * @note This function reads a byte from the UART receive FIFO or
+ * receive hold register regard regardless of UART state. The
+ * FIFO status should be read first prior to using this function
+ */
+STATIC INLINE uint32_t Chip_UARTN_ReadByte(LPC_USARTN_T *pUART)
+{
+ /* Strip off undefined reserved bits, keep 9 lower bits */
+ return (uint32_t) (pUART->RXDATA & 0x000001FF);
+}
+
+/**
+ * @brief Enable UART interrupts
+ * @param pUART : Pointer to selected UART peripheral
+ * @param intMask : OR'ed Interrupts to enable
+ * @return Nothing
+ * @note Use an OR'ed value of UARTN_INTEN_* definitions with this function
+ * to enable specific UART interrupts.
+ */
+STATIC INLINE void Chip_UARTN_IntEnable(LPC_USARTN_T *pUART, uint32_t intMask)
+{
+ pUART->INTENSET = intMask;
+}
+
+/**
+ * @brief Disable UART interrupts
+ * @param pUART : Pointer to selected UART peripheral
+ * @param intMask : OR'ed Interrupts to disable
+ * @return Nothing
+ * @note Use an OR'ed value of UARTN_INTEN_* definitions with this function
+ * to disable specific UART interrupts.
+ */
+STATIC INLINE void Chip_UARTN_IntDisable(LPC_USARTN_T *pUART, uint32_t intMask)
+{
+ pUART->INTENCLR = intMask;
+}
+
+/**
+ * @brief Returns UART interrupts that are enabled
+ * @param pUART : Pointer to selected UART peripheral
+ * @return Returns the enabled UART interrupts
+ * @note Use an OR'ed value of UARTN_INTEN_* definitions with this function
+ * to determine which interrupts are enabled. You can check
+ * for multiple enabled bits if needed.
+ */
+STATIC INLINE uint32_t Chip_UARTN_GetIntsEnabled(LPC_USARTN_T *pUART)
+{
+ return pUART->INTENSET;
+}
+
+/**
+ * @brief Get UART interrupt status
+ * @param pUART : The base of UART peripheral on the chip
+ * @return The Interrupt status register of UART
+ * @note Multiple interrupts may be pending. Mask the return value
+ * with one or more UARTN_INTEN_* definitions to determine
+ * pending interrupts.
+ */
+STATIC INLINE uint32_t Chip_UARTN_GetIntStatus(LPC_USARTN_T *pUART)
+{
+ return pUART->INTSTAT;
+}
+
+/**
+ * @brief Configure data width, parity and stop bits
+ * @param pUART : Pointer to selected pUART peripheral
+ * @param config : UART configuration, OR'ed values of select UARTN_CFG_* defines
+ * @return Nothing
+ * @note Select OR'ed config options for the UART from the UARTN_CFG_PARITY_*,
+ * UARTN_CFG_STOPLEN_*, and UARTN_CFG_DATALEN_* definitions. For example,
+ * a configuration of 8 data bits, 1 stop bit, and even (enabled) parity would be
+ * (UARTN_CFG_DATALEN_8 | UARTN_CFG_STOPLEN_1 | UARTN_CFG_PARITY_EVEN). Will not
+ * alter other bits in the CFG register.
+ */
+STATIC INLINE void Chip_UARTN_ConfigData(LPC_USARTN_T *pUART, uint32_t config)
+{
+ uint32_t reg;
+
+ reg = pUART->CFG & ~((0x3 << 2) | (0x3 << 4) | (0x1 << 6));
+ pUART->CFG = reg | config;
+}
+
+/**
+ * @brief Get the UART status register
+ * @param pUART : Pointer to selected UARTx peripheral
+ * @return UART status register
+ * @note Multiple statuses may be pending. Mask the return value
+ * with one or more UARTN_STAT_* definitions to determine
+ * statuses.
+ */
+STATIC INLINE uint32_t Chip_UARTN_GetStatus(LPC_USARTN_T *pUART)
+{
+ return pUART->STAT;
+}
+
+/**
+ * @brief Clear the UART status register
+ * @param pUART : Pointer to selected UARTx peripheral
+ * @param stsMask : OR'ed statuses to disable
+ * @return Nothing
+ * @note Multiple interrupts may be pending. Mask the return value
+ * with one or more UARTN_INTEN_* definitions to determine
+ * pending interrupts.
+ */
+STATIC INLINE void Chip_UARTN_ClearStatus(LPC_USARTN_T *pUART, uint32_t stsMask)
+{
+ pUART->STAT = stsMask;
+}
+
+/**
+ * @brief Initialize the UART peripheral
+ * @param pUART : The base of UART peripheral on the chip
+ * @return Nothing
+ */
+void Chip_UARTN_Init(LPC_USARTN_T *pUART);
+
+/**
+ * @brief Deinitialize the UART peripheral
+ * @param pUART : The base of UART peripheral on the chip
+ * @return Nothing
+ */
+void Chip_UARTN_DeInit(LPC_USARTN_T *pUART);
+
+/**
+ * @brief Transmit a byte array through the UART peripheral (non-blocking)
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Pointer to bytes to transmit
+ * @param numBytes : Number of bytes to transmit
+ * @return The actual number of bytes placed into the FIFO
+ * @note This function places data into the transmit FIFO until either
+ * all the data is in the FIFO or the FIFO is full. This function
+ * will not block in the FIFO is full. The actual number of bytes
+ * placed into the FIFO is returned. This function ignores errors.
+ */
+int Chip_UARTN_Send(LPC_USARTN_T *pUART, const void *data, int numBytes);
+
+/**
+ * @brief Read data through the UART peripheral (non-blocking)
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Pointer to bytes array to fill
+ * @param numBytes : Size of the passed data array
+ * @return The actual number of bytes read
+ * @note This function reads data from the receive FIFO until either
+ * all the data has been read or the passed buffer is completely full.
+ * This function will not block. This function ignores errors.
+ */
+int Chip_UARTN_Read(LPC_USARTN_T *pUART, void *data, int numBytes);
+
+/**
+ * @brief Set baud rate for UART
+ * @param pUART : The base of UART peripheral on the chip
+ * @param baudrate: Baud rate to be set
+ * @return Nothing
+ */
+void Chip_UARTN_SetBaud(LPC_USARTN_T *pUART, uint32_t baudrate);
+
+/**
+ * @brief Set baud rate for UART using RTC32K oscillator
+ * @param pUART : The base of UART peripheral on the chip
+ * @param baudrate: Baud rate to be set
+ * @return Nothing
+ * @note Since the baud rate is divided from the 32KHz oscillator,
+ * this function should only be used with baud rates less
+ * than or equal to 9600 baud. Don't expect any accuracy.
+ */
+void Chip_UARTN_SetBaudWithRTC32K(LPC_USARTN_T *pUART, uint32_t baudrate);
+
+/**
+ * @brief Transmit a byte array through the UART peripheral (blocking)
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Pointer to data to transmit
+ * @param numBytes : Number of bytes to transmit
+ * @return The number of bytes transmitted
+ * @note This function will send or place all bytes into the transmit
+ * FIFO. This function will block until the last bytes are in the FIFO.
+ */
+int Chip_UARTN_SendBlocking(LPC_USARTN_T *pUART, const void *data, int numBytes);
+
+/**
+ * @brief Read data through the UART peripheral (blocking)
+ * @param pUART : Pointer to selected UART peripheral
+ * @param data : Pointer to data array to fill
+ * @param numBytes : Size of the passed data array
+ * @return The size of the dat array
+ * @note This function reads data from the receive FIFO until the passed
+ * buffer is completely full. The function will block until full.
+ * This function ignores errors.
+ */
+int Chip_UARTN_ReadBlocking(LPC_USARTN_T *pUART, void *data, int numBytes);
+
+/**
+ * @brief UART receive-only interrupt handler for ring buffers
+ * @param pUART : Pointer to selected UART peripheral
+ * @param pRB : Pointer to ring buffer structure to use
+ * @return Nothing
+ * @note If ring buffer support is desired for the receive side
+ * of data transfer, the UART interrupt should call this
+ * function for a receive based interrupt status.
+ */
+void Chip_UARTN_RXIntHandlerRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB);
+
+/**
+ * @brief UART transmit-only interrupt handler for ring buffers
+ * @param pUART : Pointer to selected UART peripheral
+ * @param pRB : Pointer to ring buffer structure to use
+ * @return Nothing
+ * @note If ring buffer support is desired for the transmit side
+ * of data transfer, the UART interrupt should call this
+ * function for a transmit based interrupt status.
+ */
+void Chip_UARTN_TXIntHandlerRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB);
+
+/**
+ * @brief Populate a transmit ring buffer and start UART transmit
+ * @param pUART : Pointer to selected UART peripheral
+ * @param pRB : Pointer to ring buffer structure to use
+ * @param data : Pointer to buffer to move to ring buffer
+ * @param count : Number of bytes to move
+ * @return The number of bytes placed into the ring buffer
+ * @note Will move the data into the TX ring buffer and start the
+ * transfer. If the number of bytes returned is less than the
+ * number of bytes to send, the ring buffer is considered full.
+ */
+uint32_t Chip_UARTN_SendRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB, const void *data, int count);
+
+/**
+ * @brief Copy data from a receive ring buffer
+ * @param pUART : Pointer to selected UART peripheral
+ * @param pRB : Pointer to ring buffer structure to use
+ * @param data : Pointer to buffer to fill from ring buffer
+ * @param bytes : Size of the passed buffer in bytes
+ * @return The number of bytes placed into the ring buffer
+ * @note Will move the data from the RX ring buffer up to the
+ * the maximum passed buffer size. Returns 0 if there is
+ * no data in the ring buffer.
+ */
+int Chip_UARTN_ReadRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB, void *data, int bytes);
+
+/**
+ * @brief UART receive/transmit interrupt handler for ring buffers
+ * @param pUART : Pointer to selected UART peripheral
+ * @param pRXRB : Pointer to transmit ring buffer
+ * @param pTXRB : Pointer to receive ring buffer
+ * @return Nothing
+ * @note This provides a basic implementation of the UART IRQ
+ * handler for support of a ring buffer implementation for
+ * transmit and receive.
+ */
+void Chip_UARTN_IRQRBHandler(LPC_USARTN_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UART_N_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd.h b/source/lpc_chip_11u6x/inc/usbd/usbd.h
new file mode 100644
index 0000000..a37775a
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd.h
@@ -0,0 +1,704 @@
+/***********************************************************************
+* $Id:: mw_usbd.h 575 2012-11-20 01:35:56Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* USB Definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+
+#ifndef __USBD_H__
+#define __USBD_H__
+
+/** \file
+ * \brief Common definitions and declarations for the USB stack.
+ *
+ * Common definitions and declarations for the USB stack.
+ * \addtogroup USBD_Core
+ * @{
+ */
+
+#include "lpc_types.h"
+
+#if defined(__GNUC__)
+/* As per http://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax,
+6.29 Attributes Syntax
+"An attribute specifier list may appear as part of a struct, union or
+enum specifier. It may go either immediately after the struct, union
+or enum keyword, or after the closing brace. The former syntax is
+preferred. Where attribute specifiers follow the closing brace, they
+are considered to relate to the structure, union or enumerated type
+defined, not to any enclosing declaration the type specifier appears
+in, and the type defined is not complete until after the attribute
+specifiers."
+So use POST_PACK immediately after struct keyword
+*/
+#define PRE_PACK
+#define POST_PACK __attribute__((__packed__))
+#define ALIGNED(n) __attribute__((aligned (n)))
+
+#elif defined(__arm)
+#define PRE_PACK __packed
+#define POST_PACK
+#define ALIGNED(n) __align(n)
+
+#elif defined(__ICCARM__)
+#define PRE_PACK __packed
+#define POST_PACK
+#define PRAGMA_ALIGN_4096 _Pragma("data_alignment=4096")
+#define PRAGMA_ALIGN_2048 _Pragma("data_alignment=2048")
+#define PRAGMA_ALIGN_256 _Pragma("data_alignment=256")
+#define PRAGMA_ALIGN_128 _Pragma("data_alignment=128")
+#define PRAGMA_ALIGN_64 _Pragma("data_alignment=64")
+#define PRAGMA_ALIGN_48 _Pragma("data_alignment=48")
+#define PRAGMA_ALIGN_32 _Pragma("data_alignment=32")
+#define PRAGMA_ALIGN_4 _Pragma("data_alignment=4")
+#define ALIGNED(n) PRAGMA_ALIGN_##n
+
+#pragma diag_suppress=Pe021
+#endif
+
+/** Structure to pack lower and upper byte to form 16 bit word. */
+PRE_PACK struct POST_PACK _WB_T
+{
+ uint8_t L; /**< lower byte */
+ uint8_t H; /**< upper byte */
+};
+/** Structure to pack lower and upper byte to form 16 bit word.*/
+typedef struct _WB_T WB_T;
+
+/** Union of \ref _WB_T struct and 16 bit word.*/
+PRE_PACK union POST_PACK __WORD_BYTE
+{
+ uint16_t W; /**< data member to do 16 bit access */
+ WB_T WB; /**< data member to do 8 bit access */
+} ;
+/** Union of \ref _WB_T struct and 16 bit word.*/
+typedef union __WORD_BYTE WORD_BYTE;
+
+/** bmRequestType.Dir defines
+ * @{
+ */
+/** Request from host to device */
+#define REQUEST_HOST_TO_DEVICE 0
+/** Request from device to host */
+#define REQUEST_DEVICE_TO_HOST 1
+/** @} */
+
+/** bmRequestType.Type defines
+ * @{
+ */
+/** Standard Request */
+#define REQUEST_STANDARD 0
+/** Class Request */
+#define REQUEST_CLASS 1
+/** Vendor Request */
+#define REQUEST_VENDOR 2
+/** Reserved Request */
+#define REQUEST_RESERVED 3
+/** @} */
+
+/** bmRequestType.Recipient defines
+ * @{
+ */
+/** Request to device */
+#define REQUEST_TO_DEVICE 0
+/** Request to interface */
+#define REQUEST_TO_INTERFACE 1
+/** Request to endpoint */
+#define REQUEST_TO_ENDPOINT 2
+/** Request to other */
+#define REQUEST_TO_OTHER 3
+/** @} */
+
+/** Structure to define 8 bit USB request.*/
+PRE_PACK struct POST_PACK _BM_T
+{
+ uint8_t Recipient : 5; /**< Recipient type. */
+ uint8_t Type : 2; /**< Request type. */
+ uint8_t Dir : 1; /**< Direction type. */
+};
+/** Structure to define 8 bit USB request.*/
+typedef struct _BM_T BM_T;
+
+/** Union of \ref _BM_T struct and 8 bit byte.*/
+PRE_PACK union POST_PACK _REQUEST_TYPE
+{
+ uint8_t B; /**< byte wide access memeber */
+ BM_T BM; /**< bitfield structure access memeber */
+} ;
+/** Union of \ref _BM_T struct and 8 bit byte.*/
+typedef union _REQUEST_TYPE REQUEST_TYPE;
+
+/** USB Standard Request Codes
+ * @{
+ */
+/** GET_STATUS request */
+#define USB_REQUEST_GET_STATUS 0
+/** CLEAR_FEATURE request */
+#define USB_REQUEST_CLEAR_FEATURE 1
+/** SET_FEATURE request */
+#define USB_REQUEST_SET_FEATURE 3
+/** SET_ADDRESS request */
+#define USB_REQUEST_SET_ADDRESS 5
+/** GET_DESCRIPTOR request */
+#define USB_REQUEST_GET_DESCRIPTOR 6
+/** SET_DESCRIPTOR request */
+#define USB_REQUEST_SET_DESCRIPTOR 7
+/** GET_CONFIGURATION request */
+#define USB_REQUEST_GET_CONFIGURATION 8
+/** SET_CONFIGURATION request */
+#define USB_REQUEST_SET_CONFIGURATION 9
+/** GET_INTERFACE request */
+#define USB_REQUEST_GET_INTERFACE 10
+/** SET_INTERFACE request */
+#define USB_REQUEST_SET_INTERFACE 11
+/** SYNC_FRAME request */
+#define USB_REQUEST_SYNC_FRAME 12
+/** @} */
+
+/** USB GET_STATUS Bit Values
+ * @{
+ */
+/** SELF_POWERED status*/
+#define USB_GETSTATUS_SELF_POWERED 0x01
+/** REMOTE_WAKEUP capable status*/
+#define USB_GETSTATUS_REMOTE_WAKEUP 0x02
+/** ENDPOINT_STALL status*/
+#define USB_GETSTATUS_ENDPOINT_STALL 0x01
+/** @} */
+
+/** USB Standard Feature selectors
+ * @{
+ */
+/** ENDPOINT_STALL feature*/
+#define USB_FEATURE_ENDPOINT_STALL 0
+/** REMOTE_WAKEUP feature*/
+#define USB_FEATURE_REMOTE_WAKEUP 1
+/** TEST_MODE feature*/
+#define USB_FEATURE_TEST_MODE 2
+/** @} */
+
+/** USB Default Control Pipe Setup Packet*/
+PRE_PACK struct POST_PACK _USB_SETUP_PACKET
+{
+ REQUEST_TYPE bmRequestType; /**< This bitmapped field identifies the characteristics
+ of the specific request. \sa _BM_T.
+ */
+ uint8_t bRequest; /**< This field specifies the particular request. The
+ Type bits in the bmRequestType field modify the meaning
+ of this field. \sa USBD_REQUEST.
+ */
+ WORD_BYTE wValue; /**< Used to pass a parameter to the device, specific
+ to the request.
+ */
+ WORD_BYTE wIndex; /**< Used to pass a parameter to the device, specific
+ to the request. The wIndex field is often used in
+ requests to specify an endpoint or an interface.
+ */
+ uint16_t wLength; /**< This field specifies the length of the data
+ transferred during the second phase of the control
+ transfer.
+ */
+} ;
+/** USB Default Control Pipe Setup Packet*/
+typedef struct _USB_SETUP_PACKET USB_SETUP_PACKET;
+
+
+/** USB Descriptor Types
+ * @{
+ */
+/** Device descriptor type */
+#define USB_DEVICE_DESCRIPTOR_TYPE 1
+/** Configuration descriptor type */
+#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
+/** String descriptor type */
+#define USB_STRING_DESCRIPTOR_TYPE 3
+/** Interface descriptor type */
+#define USB_INTERFACE_DESCRIPTOR_TYPE 4
+/** Endpoint descriptor type */
+#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
+/** Device qualifier descriptor type */
+#define USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE 6
+/** Other speed configuration descriptor type */
+#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE 7
+/** Interface power descriptor type */
+#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 8
+/** OTG descriptor type */
+#define USB_OTG_DESCRIPTOR_TYPE 9
+/** Debug descriptor type */
+#define USB_DEBUG_DESCRIPTOR_TYPE 10
+/** Interface association descriptor type */
+#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE 11
+/** @} */
+
+/** USB Device Classes
+ * @{
+ */
+/** Reserved device class */
+#define USB_DEVICE_CLASS_RESERVED 0x00
+/** Audio device class */
+#define USB_DEVICE_CLASS_AUDIO 0x01
+/** Communications device class */
+#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
+/** Human interface device class */
+#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
+/** monitor device class */
+#define USB_DEVICE_CLASS_MONITOR 0x04
+/** physical interface device class */
+#define USB_DEVICE_CLASS_PHYSICAL_INTERFACE 0x05
+/** power device class */
+#define USB_DEVICE_CLASS_POWER 0x06
+/** Printer device class */
+#define USB_DEVICE_CLASS_PRINTER 0x07
+/** Storage device class */
+#define USB_DEVICE_CLASS_STORAGE 0x08
+/** Hub device class */
+#define USB_DEVICE_CLASS_HUB 0x09
+/** miscellaneous device class */
+#define USB_DEVICE_CLASS_MISCELLANEOUS 0xEF
+/** Application device class */
+#define USB_DEVICE_CLASS_APP 0xFE
+/** Vendor specific device class */
+#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
+/** @} */
+
+/** bmAttributes in Configuration Descriptor
+ * @{
+ */
+/** Power field mask */
+#define USB_CONFIG_POWERED_MASK 0x40
+/** Bus powered */
+#define USB_CONFIG_BUS_POWERED 0x80
+/** Self powered */
+#define USB_CONFIG_SELF_POWERED 0xC0
+/** remote wakeup */
+#define USB_CONFIG_REMOTE_WAKEUP 0x20
+/** @} */
+
+/** bMaxPower in Configuration Descriptor */
+#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
+
+/** bEndpointAddress in Endpoint Descriptor
+ * @{
+ */
+/** Endopint address mask */
+#define USB_ENDPOINT_DIRECTION_MASK 0x80
+/** Macro to convert OUT endopint number to endpoint address value. */
+#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
+/** Macro to convert IN endopint number to endpoint address value. */
+#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
+/** @} */
+
+/** bmAttributes in Endpoint Descriptor
+ * @{
+ */
+/** Endopint type mask */
+#define USB_ENDPOINT_TYPE_MASK 0x03
+/** Control Endopint type */
+#define USB_ENDPOINT_TYPE_CONTROL 0x00
+/** isochronous Endopint type */
+#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
+/** bulk Endopint type */
+#define USB_ENDPOINT_TYPE_BULK 0x02
+/** interrupt Endopint type */
+#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
+/** Endopint sync type mask */
+#define USB_ENDPOINT_SYNC_MASK 0x0C
+/** no synchronization Endopint */
+#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION 0x00
+/** Asynchronous sync Endopint */
+#define USB_ENDPOINT_SYNC_ASYNCHRONOUS 0x04
+/** Adaptive sync Endopint */
+#define USB_ENDPOINT_SYNC_ADAPTIVE 0x08
+/** Synchronous sync Endopint */
+#define USB_ENDPOINT_SYNC_SYNCHRONOUS 0x0C
+/** Endopint usage type mask */
+#define USB_ENDPOINT_USAGE_MASK 0x30
+/** Endopint data usage type */
+#define USB_ENDPOINT_USAGE_DATA 0x00
+/** Endopint feedback usage type */
+#define USB_ENDPOINT_USAGE_FEEDBACK 0x10
+/** Endopint implicit feedback usage type */
+#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK 0x20
+/** Endopint reserved usage type */
+#define USB_ENDPOINT_USAGE_RESERVED 0x30
+/** @} */
+
+/** Control endopint EP0's maximum packet size in high-speed mode.*/
+#define USB_ENDPOINT_0_HS_MAXP 64
+/** Control endopint EP0's maximum packet size in low-speed mode.*/
+#define USB_ENDPOINT_0_LS_MAXP 8
+/** Bulk endopint's maximum packet size in high-speed mode.*/
+#define USB_ENDPOINT_BULK_HS_MAXP 512
+
+/** USB Standard Device Descriptor */
+PRE_PACK struct POST_PACK _USB_DEVICE_DESCRIPTOR
+{
+ uint8_t bLength; /**< Size of this descriptor in bytes. */
+ uint8_t bDescriptorType; /**< DEVICE Descriptor Type. */
+ uint16_t bcdUSB; /**< BUSB Specification Release Number in
+ Binary-Coded Decimal (i.e., 2.10 is 210H).
+ This field identifies the release of the USB
+ Specification with which the device and its
+ descriptors are compliant.
+ */
+ uint8_t bDeviceClass; /**< Class code (assigned by the USB-IF).
+ If this field is reset to zero, each interface
+ within a configuration specifies its own
+ class information and the various
+ interfaces operate independently.\n
+ If this field is set to a value between 1 and
+ FEH, the device supports different class
+ specifications on different interfaces and
+ the interfaces may not operate
+ independently. This value identifies the
+ class definition used for the aggregate
+ interfaces. \n
+ If this field is set to FFH, the device class
+ is vendor-specific.
+ */
+ uint8_t bDeviceSubClass; /**< Subclass code (assigned by the USB-IF).
+ These codes are qualified by the value of
+ the bDeviceClass field. \n
+ If the bDeviceClass field is reset to zero,
+ this field must also be reset to zero. \n
+ If the bDeviceClass field is not set to FFH,
+ all values are reserved for assignment by
+ the USB-IF.
+ */
+ uint8_t bDeviceProtocol; /**< Protocol code (assigned by the USB-IF).
+ These codes are qualified by the value of
+ the bDeviceClass and the
+ bDeviceSubClass fields. If a device
+ supports class-specific protocols on a
+ device basis as opposed to an interface
+ basis, this code identifies the protocols
+ that the device uses as defined by the
+ specification of the device class. \n
+ If this field is reset to zero, the device
+ does not use class-specific protocols on a
+ device basis. However, it may use classspecific
+ protocols on an interface basis. \n
+ If this field is set to FFH, the device uses a
+ vendor-specific protocol on a device basis.
+ */
+ uint8_t bMaxPacketSize0; /**< Maximum packet size for endpoint zero
+ (only 8, 16, 32, or 64 are valid). For HS devices
+ is fixed to 64.
+ */
+
+ uint16_t idVendor; /**< Vendor ID (assigned by the USB-IF). */
+ uint16_t idProduct; /**< Product ID (assigned by the manufacturer). */
+ uint16_t bcdDevice; /**< Device release number in binary-coded decimal. */
+ uint8_t iManufacturer; /**< Index of string descriptor describing manufacturer. */
+ uint8_t iProduct; /**< Index of string descriptor describing product. */
+ uint8_t iSerialNumber; /**< Index of string descriptor describing the device’s
+ serial number.
+ */
+ uint8_t bNumConfigurations; /**< Number of possible configurations. */
+} ;
+/** USB Standard Device Descriptor */
+typedef struct _USB_DEVICE_DESCRIPTOR USB_DEVICE_DESCRIPTOR;
+
+/** USB 2.0 Device Qualifier Descriptor */
+PRE_PACK struct POST_PACK _USB_DEVICE_QUALIFIER_DESCRIPTOR
+{
+ uint8_t bLength; /**< Size of descriptor */
+ uint8_t bDescriptorType; /**< Device Qualifier Type */
+ uint16_t bcdUSB; /**< USB specification version number (e.g., 0200H for V2.00) */
+ uint8_t bDeviceClass; /**< Class Code */
+ uint8_t bDeviceSubClass; /**< SubClass Code */
+ uint8_t bDeviceProtocol; /**< Protocol Code */
+ uint8_t bMaxPacketSize0; /**< Maximum packet size for other speed */
+ uint8_t bNumConfigurations; /**< Number of Other-speed Configurations */
+ uint8_t bReserved; /**< Reserved for future use, must be zero */
+} ;
+/** USB 2.0 Device Qualifier Descriptor */
+typedef struct _USB_DEVICE_QUALIFIER_DESCRIPTOR USB_DEVICE_QUALIFIER_DESCRIPTOR;
+
+/** USB Standard Configuration Descriptor */
+PRE_PACK struct POST_PACK _USB_CONFIGURATION_DESCRIPTOR
+{
+ uint8_t bLength; /**< Size of this descriptor in bytes */
+ uint8_t bDescriptorType; /**< CONFIGURATION Descriptor Type*/
+ uint16_t wTotalLength; /**< Total length of data returned for this
+ configuration. Includes the combined length
+ of all descriptors (configuration, interface,
+ endpoint, and class- or vendor-specific)
+ returned for this configuration.*/
+ uint8_t bNumInterfaces; /**< Number of interfaces supported by this configuration*/
+ uint8_t bConfigurationValue; /**< Value to use as an argument to the
+ SetConfiguration() request to select this
+ configuration. */
+ uint8_t iConfiguration; /**< Index of string descriptor describing this
+ configuration*/
+ uint8_t bmAttributes; /**< Configuration characteristics \n
+ D7: Reserved (set to one)\n
+ D6: Self-powered \n
+ D5: Remote Wakeup \n
+ D4...0: Reserved (reset to zero) \n
+ D7 is reserved and must be set to one for
+ historical reasons. \n
+ A device configuration that uses power from
+ the bus and a local source reports a non-zero
+ value in bMaxPower to indicate the amount of
+ bus power required and sets D6. The actual
+ power source at runtime may be determined
+ using the GetStatus(DEVICE) request (see
+ USB 2.0 spec Section 9.4.5). \n
+ If a device configuration supports remote
+ wakeup, D5 is set to one.*/
+ uint8_t bMaxPower; /**< Maximum power consumption of the USB
+ device from the bus in this specific
+ configuration when the device is fully
+ operational. Expressed in 2 mA units
+ (i.e., 50 = 100 mA). \n
+ Note: A device configuration reports whether
+ the configuration is bus-powered or selfpowered.
+ Device status reports whether the
+ device is currently self-powered. If a device is
+ disconnected from its external power source, it
+ updates device status to indicate that it is no
+ longer self-powered. \n
+ A device may not increase its power draw
+ from the bus, when it loses its external power
+ source, beyond the amount reported by its
+ configuration. \n
+ If a device can continue to operate when
+ disconnected from its external power source, it
+ continues to do so. If the device cannot
+ continue to operate, it fails operations it can
+ no longer support. The USB System Software
+ may determine the cause of the failure by
+ checking the status and noting the loss of the
+ device’s power source.*/
+} ;
+/** USB Standard Configuration Descriptor */
+typedef struct _USB_CONFIGURATION_DESCRIPTOR USB_CONFIGURATION_DESCRIPTOR;
+
+/** USB Standard Interface Association Descriptor */
+PRE_PACK struct POST_PACK _USB_IAD_DESCRIPTOR
+{
+ uint8_t bLength; /**< Size of this descriptor in bytes*/
+ uint8_t bDescriptorType; /**< INTERFACE ASSOCIATION Descriptor Type*/
+ uint8_t bFirstInterface; /**< Interface number of the first interface that is
+ associated with this function.*/
+ uint8_t bInterfaceCount; /**< Number of contiguous interfaces that are
+ associated with this function. */
+ uint8_t bFunctionClass; /**< Class code (assigned by USB-IF). \n
+ A value of zero is not allowed in this descriptor.
+ If this field is FFH, the function class is vendorspecific.
+ All other values are reserved for assignment by
+ the USB-IF.*/
+ uint8_t bFunctionSubClass; /**< Subclass code (assigned by USB-IF). \n
+ If the bFunctionClass field is not set to FFH all
+ values are reserved for assignment by the USBIF.*/
+ uint8_t bFunctionProtocol; /**< Protocol code (assigned by the USB). \n
+ These codes are qualified by the values of the
+ bFunctionClass and bFunctionSubClass fields.*/
+ uint8_t iFunction; /**< Index of string descriptor describing this function.*/
+} ;
+/** USB Standard Interface Association Descriptor */
+typedef struct _USB_IAD_DESCRIPTOR USB_IAD_DESCRIPTOR;
+
+/** USB Standard Interface Descriptor */
+PRE_PACK struct POST_PACK _USB_INTERFACE_DESCRIPTOR
+{
+ uint8_t bLength; /**< Size of this descriptor in bytes*/
+ uint8_t bDescriptorType; /**< INTERFACE Descriptor Type*/
+ uint8_t bInterfaceNumber; /**< Number of this interface. Zero-based
+ value identifying the index in the array of
+ concurrent interfaces supported by this
+ configuration.*/
+ uint8_t bAlternateSetting; /**< Value used to select this alternate setting
+ for the interface identified in the prior field*/
+ uint8_t bNumEndpoints; /**< Number of endpoints used by this
+ interface (excluding endpoint zero). If this
+ value is zero, this interface only uses the
+ Default Control Pipe.*/
+ uint8_t bInterfaceClass; /**< Class code (assigned by the USB-IF). \n
+ A value of zero is reserved for future
+ standardization. \n
+ If this field is set to FFH, the interface
+ class is vendor-specific. \n
+ All other values are reserved for
+ assignment by the USB-IF.*/
+ uint8_t bInterfaceSubClass; /**< Subclass code (assigned by the USB-IF). \n
+ These codes are qualified by the value of
+ the bInterfaceClass field. \n
+ If the bInterfaceClass field is reset to zero,
+ this field must also be reset to zero. \n
+ If the bInterfaceClass field is not set to
+ FFH, all values are reserved for
+ assignment by the USB-IF.*/
+ uint8_t bInterfaceProtocol; /**< Protocol code (assigned by the USB). \n
+ These codes are qualified by the value of
+ the bInterfaceClass and the
+ bInterfaceSubClass fields. If an interface
+ supports class-specific requests, this code
+ identifies the protocols that the device
+ uses as defined by the specification of the
+ device class. \n
+ If this field is reset to zero, the device
+ does not use a class-specific protocol on
+ this interface. \n
+ If this field is set to FFH, the device uses
+ a vendor-specific protocol for this
+ interface.*/
+ uint8_t iInterface; /**< Index of string descriptor describing this interface*/
+} ;
+/** USB Standard Interface Descriptor */
+typedef struct _USB_INTERFACE_DESCRIPTOR USB_INTERFACE_DESCRIPTOR;
+
+/** USB Standard Endpoint Descriptor */
+PRE_PACK struct POST_PACK _USB_ENDPOINT_DESCRIPTOR
+{
+ uint8_t bLength; /**< Size of this descriptor in bytes*/
+ uint8_t bDescriptorType; /**< ENDPOINT Descriptor Type*/
+ uint8_t bEndpointAddress; /**< The address of the endpoint on the USB device
+ described by this descriptor. The address is
+ encoded as follows: \n
+ Bit 3...0: The endpoint number \n
+ Bit 6...4: Reserved, reset to zero \n
+ Bit 7: Direction, ignored for control endpoints
+ 0 = OUT endpoint
+ 1 = IN endpoint. \n \sa USBD_ENDPOINT_ADR_Type*/
+ uint8_t bmAttributes; /**< This field describes the endpoint’s attributes when it is
+ configured using the bConfigurationValue. \n
+ Bits 1..0: Transfer Type
+ \li 00 = Control
+ \li 01 = Isochronous
+ \li 10 = Bulk
+ \li 11 = Interrupt \n
+ If not an isochronous endpoint, bits 5..2 are reserved
+ and must be set to zero. If isochronous, they are
+ defined as follows: \n
+ Bits 3..2: Synchronization Type
+ \li 00 = No Synchronization
+ \li 01 = Asynchronous
+ \li 10 = Adaptive
+ \li 11 = Synchronous \n
+ Bits 5..4: Usage Type
+ \li 00 = Data endpoint
+ \li 01 = Feedback endpoint
+ \li 10 = Implicit feedback Data endpoint
+ \li 11 = Reserved \n
+ Refer to Chapter 5 of USB 2.0 specification for more information. \n
+ All other bits are reserved and must be reset to zero.
+ Reserved bits must be ignored by the host.
+ \n \sa USBD_EP_ATTR_Type*/
+ uint16_t wMaxPacketSize; /**< Maximum packet size this endpoint is capable of
+ sending or receiving when this configuration is
+ selected. \n
+ For isochronous endpoints, this value is used to
+ reserve the bus time in the schedule, required for the
+ per-(micro)frame data payloads. The pipe may, on an
+ ongoing basis, actually use less bandwidth than that
+ reserved. The device reports, if necessary, the actual
+ bandwidth used via its normal, non-USB defined
+ mechanisms. \n
+ For all endpoints, bits 10..0 specify the maximum
+ packet size (in bytes). \n
+ For high-speed isochronous and interrupt endpoints: \n
+ Bits 12..11 specify the number of additional transaction
+ opportunities per microframe: \n
+ \li 00 = None (1 transaction per microframe)
+ \li 01 = 1 additional (2 per microframe)
+ \li 10 = 2 additional (3 per microframe)
+ \li 11 = Reserved \n
+ Bits 15..13 are reserved and must be set to zero.*/
+ uint8_t bInterval; /**< Interval for polling endpoint for data transfers.
+ Expressed in frames or microframes depending on the
+ device operating speed (i.e., either 1 millisecond or
+ 125 µs units).
+ \li For full-/high-speed isochronous endpoints, this value
+ must be in the range from 1 to 16. The bInterval value
+ is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a
+ bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$).
+ \li For full-/low-speed interrupt endpoints, the value of
+ this field may be from 1 to 255.
+ \li For high-speed interrupt endpoints, the bInterval value
+ is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a
+ bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value
+ must be from 1 to 16.
+ \li For high-speed bulk/control OUT endpoints, the
+ bInterval must specify the maximum NAK rate of the
+ endpoint. A value of 0 indicates the endpoint never
+ NAKs. Other values indicate at most 1 NAK each
+ bInterval number of microframes. This value must be
+ in the range from 0 to 255. \n
+ Refer to Chapter 5 of USB 2.0 specification for more information.
+ */
+} ;
+/** USB Standard Endpoint Descriptor */
+typedef struct _USB_ENDPOINT_DESCRIPTOR USB_ENDPOINT_DESCRIPTOR;
+
+/** USB String Descriptor */
+PRE_PACK struct POST_PACK _USB_STRING_DESCRIPTOR
+{
+ uint8_t bLength; /**< Size of this descriptor in bytes*/
+ uint8_t bDescriptorType; /**< STRING Descriptor Type*/
+ uint16_t bString/*[]*/; /**< UNICODE encoded string */
+} ;
+/** USB String Descriptor */
+typedef struct _USB_STRING_DESCRIPTOR USB_STRING_DESCRIPTOR;
+
+/** USB Common Descriptor */
+PRE_PACK struct POST_PACK _USB_COMMON_DESCRIPTOR
+{
+ uint8_t bLength; /**< Size of this descriptor in bytes*/
+ uint8_t bDescriptorType; /**< Descriptor Type*/
+} ;
+/** USB Common Descriptor */
+typedef struct _USB_COMMON_DESCRIPTOR USB_COMMON_DESCRIPTOR;
+
+/** USB Other Speed Configuration */
+PRE_PACK struct POST_PACK _USB_OTHER_SPEED_CONFIGURATION
+{
+ uint8_t bLength; /**< Size of descriptor*/
+ uint8_t bDescriptorType; /**< Other_speed_Configuration Type*/
+ uint16_t wTotalLength; /**< Total length of data returned*/
+ uint8_t bNumInterfaces; /**< Number of interfaces supported by this speed configuration*/
+ uint8_t bConfigurationValue; /**< Value to use to select configuration*/
+ uint8_t IConfiguration; /**< Index of string descriptor*/
+ uint8_t bmAttributes; /**< Same as Configuration descriptor*/
+ uint8_t bMaxPower; /**< Same as Configuration descriptor*/
+} ;
+/** USB Other Speed Configuration */
+typedef struct _USB_OTHER_SPEED_CONFIGURATION USB_OTHER_SPEED_CONFIGURATION;
+
+/** \ingroup USBD_Core
+ * USB device stack/module handle.
+ */
+typedef void* USBD_HANDLE_T;
+
+#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
+#define B3VAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF),(((x) >> 16) & 0xFF)
+
+#define USB_DEVICE_DESC_SIZE (sizeof(USB_DEVICE_DESCRIPTOR))
+#define USB_CONFIGURATION_DESC_SIZE (sizeof(USB_CONFIGURATION_DESCRIPTOR))
+#define USB_INTERFACE_DESC_SIZE (sizeof(USB_INTERFACE_DESCRIPTOR))
+#define USB_INTERFACE_ASSOC_DESC_SIZE (sizeof(USB_IAD_DESCRIPTOR))
+#define USB_ENDPOINT_DESC_SIZE (sizeof(USB_ENDPOINT_DESCRIPTOR))
+#define USB_DEVICE_QUALI_SIZE (sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR))
+#define USB_OTHER_SPEED_CONF_SIZE (sizeof(USB_OTHER_SPEED_CONFIGURATION))
+
+/** @}*/
+
+#endif /* __USBD_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_adc.h b/source/lpc_chip_11u6x/inc/usbd/usbd_adc.h
new file mode 100644
index 0000000..9d42948
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_adc.h
@@ -0,0 +1,377 @@
+/***********************************************************************
+* $Id:: mw_usbd_audio.h 165 2011-04-14 17:41:11Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* USB Audio Device Class Definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+#ifndef __AUDIO_H__
+#define __AUDIO_H__
+
+
+/* Audio Interface Subclass Codes */
+#define AUDIO_SUBCLASS_UNDEFINED 0x00
+#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01
+#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02
+#define AUDIO_SUBCLASS_MIDISTREAMING 0x03
+
+/* Audio Interface Protocol Codes */
+#define AUDIO_PROTOCOL_UNDEFINED 0x00
+
+
+/* Audio Descriptor Types */
+#define AUDIO_UNDEFINED_DESCRIPTOR_TYPE 0x20
+#define AUDIO_DEVICE_DESCRIPTOR_TYPE 0x21
+#define AUDIO_CONFIGURATION_DESCRIPTOR_TYPE 0x22
+#define AUDIO_STRING_DESCRIPTOR_TYPE 0x23
+#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24
+#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25
+
+
+/* Audio Control Interface Descriptor Subtypes */
+#define AUDIO_CONTROL_UNDEFINED 0x00
+#define AUDIO_CONTROL_HEADER 0x01
+#define AUDIO_CONTROL_INPUT_TERMINAL 0x02
+#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03
+#define AUDIO_CONTROL_MIXER_UNIT 0x04
+#define AUDIO_CONTROL_SELECTOR_UNIT 0x05
+#define AUDIO_CONTROL_FEATURE_UNIT 0x06
+#define AUDIO_CONTROL_PROCESSING_UNIT 0x07
+#define AUDIO_CONTROL_EXTENSION_UNIT 0x08
+
+/* Audio Streaming Interface Descriptor Subtypes */
+#define AUDIO_STREAMING_UNDEFINED 0x00
+#define AUDIO_STREAMING_GENERAL 0x01
+#define AUDIO_STREAMING_FORMAT_TYPE 0x02
+#define AUDIO_STREAMING_FORMAT_SPECIFIC 0x03
+
+/* Audio Endpoint Descriptor Subtypes */
+#define AUDIO_ENDPOINT_UNDEFINED 0x00
+#define AUDIO_ENDPOINT_GENERAL 0x01
+
+
+/* Audio Descriptor Sizes */
+#define AUDIO_CONTROL_INTERFACE_DESC_SZ(n) 0x08+n
+#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07
+#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0C
+#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09
+#define AUDIO_MIXER_UNIT_DESC_SZ(p,n) 0x0A+p+n
+#define AUDIO_SELECTOR_UNIT_DESC_SZ(p) 0x06+p
+#define AUDIO_FEATURE_UNIT_DESC_SZ(ch,n) 0x07+(ch+1)*n
+#define AUDIO_PROCESSING_UNIT_DESC_SZ(p,n,x) 0x0D+p+n+x
+#define AUDIO_EXTENSION_UNIT_DESC_SZ(p,n) 0x0D+p+n
+#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE 0x09
+#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE 0x07
+
+
+/* Audio Processing Unit Process Types */
+#define AUDIO_UNDEFINED_PROCESS 0x00
+#define AUDIO_UP_DOWN_MIX_PROCESS 0x01
+#define AUDIO_DOLBY_PROLOGIC_PROCESS 0x02
+#define AUDIO_3D_STEREO_PROCESS 0x03
+#define AUDIO_REVERBERATION_PROCESS 0x04
+#define AUDIO_CHORUS_PROCESS 0x05
+#define AUDIO_DYN_RANGE_COMP_PROCESS 0x06
+
+
+/* Audio Request Codes */
+#define AUDIO_REQUEST_UNDEFINED 0x00
+#define AUDIO_REQUEST_SET_CUR 0x01
+#define AUDIO_REQUEST_GET_CUR 0x81
+#define AUDIO_REQUEST_SET_MIN 0x02
+#define AUDIO_REQUEST_GET_MIN 0x82
+#define AUDIO_REQUEST_SET_MAX 0x03
+#define AUDIO_REQUEST_GET_MAX 0x83
+#define AUDIO_REQUEST_SET_RES 0x04
+#define AUDIO_REQUEST_GET_RES 0x84
+#define AUDIO_REQUEST_SET_MEM 0x05
+#define AUDIO_REQUEST_GET_MEM 0x85
+#define AUDIO_REQUEST_GET_STAT 0xFF
+
+
+/* Audio Control Selector Codes */
+#define AUDIO_CONTROL_UNDEFINED 0x00 /* Common Selector */
+
+/* Terminal Control Selectors */
+#define AUDIO_COPY_PROTECT_CONTROL 0x01
+
+/* Feature Unit Control Selectors */
+#define AUDIO_MUTE_CONTROL 0x01
+#define AUDIO_VOLUME_CONTROL 0x02
+#define AUDIO_BASS_CONTROL 0x03
+#define AUDIO_MID_CONTROL 0x04
+#define AUDIO_TREBLE_CONTROL 0x05
+#define AUDIO_GRAPHIC_EQUALIZER_CONTROL 0x06
+#define AUDIO_AUTOMATIC_GAIN_CONTROL 0x07
+#define AUDIO_DELAY_CONTROL 0x08
+#define AUDIO_BASS_BOOST_CONTROL 0x09
+#define AUDIO_LOUDNESS_CONTROL 0x0A
+
+/* Processing Unit Control Selectors: */
+#define AUDIO_ENABLE_CONTROL 0x01 /* Common Selector */
+#define AUDIO_MODE_SELECT_CONTROL 0x02 /* Common Selector */
+
+/* - Up/Down-mix Control Selectors */
+/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
+/* AUDIO_MODE_SELECT_CONTROL 0x02 Common Selector */
+
+/* - Dolby Prologic Control Selectors */
+/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
+/* AUDIO_MODE_SELECT_CONTROL 0x02 Common Selector */
+
+/* - 3D Stereo Extender Control Selectors */
+/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
+#define AUDIO_SPACIOUSNESS_CONTROL 0x02
+
+/* - Reverberation Control Selectors */
+/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
+#define AUDIO_REVERB_LEVEL_CONTROL 0x02
+#define AUDIO_REVERB_TIME_CONTROL 0x03
+#define AUDIO_REVERB_FEEDBACK_CONTROL 0x04
+
+/* - Chorus Control Selectors */
+/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
+#define AUDIO_CHORUS_LEVEL_CONTROL 0x02
+#define AUDIO_SHORUS_RATE_CONTROL 0x03
+#define AUDIO_CHORUS_DEPTH_CONTROL 0x04
+
+/* - Dynamic Range Compressor Control Selectors */
+/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
+#define AUDIO_COMPRESSION_RATE_CONTROL 0x02
+#define AUDIO_MAX_AMPL_CONTROL 0x03
+#define AUDIO_THRESHOLD_CONTROL 0x04
+#define AUDIO_ATTACK_TIME_CONTROL 0x05
+#define AUDIO_RELEASE_TIME_CONTROL 0x06
+
+/* Extension Unit Control Selectors */
+/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */
+
+/* Endpoint Control Selectors */
+#define AUDIO_SAMPLING_FREQ_CONTROL 0x01
+#define AUDIO_PITCH_CONTROL 0x02
+
+
+/* Audio Format Specific Control Selectors */
+
+/* MPEG Control Selectors */
+#define AUDIO_MPEG_CONTROL_UNDEFINED 0x00
+#define AUDIO_MPEG_DUAL_CHANNEL_CONTROL 0x01
+#define AUDIO_MPEG_SECOND_STEREO_CONTROL 0x02
+#define AUDIO_MPEG_MULTILINGUAL_CONTROL 0x03
+#define AUDIO_MPEG_DYN_RANGE_CONTROL 0x04
+#define AUDIO_MPEG_SCALING_CONTROL 0x05
+#define AUDIO_MPEG_HILO_SCALING_CONTROL 0x06
+
+/* AC-3 Control Selectors */
+#define AUDIO_AC3_CONTROL_UNDEFINED 0x00
+#define AUDIO_AC3_MODE_CONTROL 0x01
+#define AUDIO_AC3_DYN_RANGE_CONTROL 0x02
+#define AUDIO_AC3_SCALING_CONTROL 0x03
+#define AUDIO_AC3_HILO_SCALING_CONTROL 0x04
+
+
+/* Audio Format Types */
+#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00
+#define AUDIO_FORMAT_TYPE_I 0x01
+#define AUDIO_FORMAT_TYPE_II 0x02
+#define AUDIO_FORMAT_TYPE_III 0x03
+
+
+/* Audio Format Type Descriptor Sizes */
+#define AUDIO_FORMAT_TYPE_I_DESC_SZ(n) 0x08+(n*3)
+#define AUDIO_FORMAT_TYPE_II_DESC_SZ(n) 0x09+(n*3)
+#define AUDIO_FORMAT_TYPE_III_DESC_SZ(n) 0x08+(n*3)
+#define AUDIO_FORMAT_MPEG_DESC_SIZE 0x09
+#define AUDIO_FORMAT_AC3_DESC_SIZE 0x0A
+
+
+/* Audio Data Format Codes */
+
+/* Audio Data Format Type I Codes */
+#define AUDIO_FORMAT_TYPE_I_UNDEFINED 0x0000
+#define AUDIO_FORMAT_PCM 0x0001
+#define AUDIO_FORMAT_PCM8 0x0002
+#define AUDIO_FORMAT_IEEE_FLOAT 0x0003
+#define AUDIO_FORMAT_ALAW 0x0004
+#define AUDIO_FORMAT_MULAW 0x0005
+
+/* Audio Data Format Type II Codes */
+#define AUDIO_FORMAT_TYPE_II_UNDEFINED 0x1000
+#define AUDIO_FORMAT_MPEG 0x1001
+#define AUDIO_FORMAT_AC3 0x1002
+
+/* Audio Data Format Type III Codes */
+#define AUDIO_FORMAT_TYPE_III_UNDEFINED 0x2000
+#define AUDIO_FORMAT_IEC1937_AC3 0x2001
+#define AUDIO_FORMAT_IEC1937_MPEG1_L1 0x2002
+#define AUDIO_FORMAT_IEC1937_MPEG1_L2_3 0x2003
+#define AUDIO_FORMAT_IEC1937_MPEG2_NOEXT 0x2003
+#define AUDIO_FORMAT_IEC1937_MPEG2_EXT 0x2004
+#define AUDIO_FORMAT_IEC1937_MPEG2_L1_LS 0x2005
+#define AUDIO_FORMAT_IEC1937_MPEG2_L2_3 0x2006
+
+
+/* Predefined Audio Channel Configuration Bits */
+#define AUDIO_CHANNEL_M 0x0000 /* Mono */
+#define AUDIO_CHANNEL_L 0x0001 /* Left Front */
+#define AUDIO_CHANNEL_R 0x0002 /* Right Front */
+#define AUDIO_CHANNEL_C 0x0004 /* Center Front */
+#define AUDIO_CHANNEL_LFE 0x0008 /* Low Freq. Enhance. */
+#define AUDIO_CHANNEL_LS 0x0010 /* Left Surround */
+#define AUDIO_CHANNEL_RS 0x0020 /* Right Surround */
+#define AUDIO_CHANNEL_LC 0x0040 /* Left of Center */
+#define AUDIO_CHANNEL_RC 0x0080 /* Right of Center */
+#define AUDIO_CHANNEL_S 0x0100 /* Surround */
+#define AUDIO_CHANNEL_SL 0x0200 /* Side Left */
+#define AUDIO_CHANNEL_SR 0x0400 /* Side Right */
+#define AUDIO_CHANNEL_T 0x0800 /* Top */
+
+
+/* Feature Unit Control Bits */
+#define AUDIO_CONTROL_MUTE 0x0001
+#define AUDIO_CONTROL_VOLUME 0x0002
+#define AUDIO_CONTROL_BASS 0x0004
+#define AUDIO_CONTROL_MID 0x0008
+#define AUDIO_CONTROL_TREBLE 0x0010
+#define AUDIO_CONTROL_GRAPHIC_EQUALIZER 0x0020
+#define AUDIO_CONTROL_AUTOMATIC_GAIN 0x0040
+#define AUDIO_CONTROL_DEALY 0x0080
+#define AUDIO_CONTROL_BASS_BOOST 0x0100
+#define AUDIO_CONTROL_LOUDNESS 0x0200
+
+/* Processing Unit Control Bits: */
+#define AUDIO_CONTROL_ENABLE 0x0001 /* Common Bit */
+#define AUDIO_CONTROL_MODE_SELECT 0x0002 /* Common Bit */
+
+/* - Up/Down-mix Control Bits */
+/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
+/* AUDIO_CONTROL_MODE_SELECT 0x0002 Common Bit */
+
+/* - Dolby Prologic Control Bits */
+/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
+/* AUDIO_CONTROL_MODE_SELECT 0x0002 Common Bit */
+
+/* - 3D Stereo Extender Control Bits */
+/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
+#define AUDIO_CONTROL_SPACIOUSNESS 0x0002
+
+/* - Reverberation Control Bits */
+/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
+#define AUDIO_CONTROL_REVERB_TYPE 0x0002
+#define AUDIO_CONTROL_REVERB_LEVEL 0x0004
+#define AUDIO_CONTROL_REVERB_TIME 0x0008
+#define AUDIO_CONTROL_REVERB_FEEDBACK 0x0010
+
+/* - Chorus Control Bits */
+/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
+#define AUDIO_CONTROL_CHORUS_LEVEL 0x0002
+#define AUDIO_CONTROL_SHORUS_RATE 0x0004
+#define AUDIO_CONTROL_CHORUS_DEPTH 0x0008
+
+/* - Dynamic Range Compressor Control Bits */
+/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
+#define AUDIO_CONTROL_COMPRESSION_RATE 0x0002
+#define AUDIO_CONTROL_MAX_AMPL 0x0004
+#define AUDIO_CONTROL_THRESHOLD 0x0008
+#define AUDIO_CONTROL_ATTACK_TIME 0x0010
+#define AUDIO_CONTROL_RELEASE_TIME 0x0020
+
+/* Extension Unit Control Bits */
+/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */
+
+/* Endpoint Control Bits */
+#define AUDIO_CONTROL_SAMPLING_FREQ 0x01
+#define AUDIO_CONTROL_PITCH 0x02
+#define AUDIO_MAX_PACKETS_ONLY 0x80
+
+
+/* Audio Terminal Types */
+
+/* USB Terminal Types */
+#define AUDIO_TERMINAL_USB_UNDEFINED 0x0100
+#define AUDIO_TERMINAL_USB_STREAMING 0x0101
+#define AUDIO_TERMINAL_USB_VENDOR_SPECIFIC 0x01FF
+
+/* Input Terminal Types */
+#define AUDIO_TERMINAL_INPUT_UNDEFINED 0x0200
+#define AUDIO_TERMINAL_MICROPHONE 0x0201
+#define AUDIO_TERMINAL_DESKTOP_MICROPHONE 0x0202
+#define AUDIO_TERMINAL_PERSONAL_MICROPHONE 0x0203
+#define AUDIO_TERMINAL_OMNI_DIR_MICROPHONE 0x0204
+#define AUDIO_TERMINAL_MICROPHONE_ARRAY 0x0205
+#define AUDIO_TERMINAL_PROCESSING_MIC_ARRAY 0x0206
+
+/* Output Terminal Types */
+#define AUDIO_TERMINAL_OUTPUT_UNDEFINED 0x0300
+#define AUDIO_TERMINAL_SPEAKER 0x0301
+#define AUDIO_TERMINAL_HEADPHONES 0x0302
+#define AUDIO_TERMINAL_HEAD_MOUNTED_AUDIO 0x0303
+#define AUDIO_TERMINAL_DESKTOP_SPEAKER 0x0304
+#define AUDIO_TERMINAL_ROOM_SPEAKER 0x0305
+#define AUDIO_TERMINAL_COMMUNICATION_SPEAKER 0x0306
+#define AUDIO_TERMINAL_LOW_FREQ_SPEAKER 0x0307
+
+/* Bi-directional Terminal Types */
+#define AUDIO_TERMINAL_BIDIRECTIONAL_UNDEFINED 0x0400
+#define AUDIO_TERMINAL_HANDSET 0x0401
+#define AUDIO_TERMINAL_HEAD_MOUNTED_HANDSET 0x0402
+#define AUDIO_TERMINAL_SPEAKERPHONE 0x0403
+#define AUDIO_TERMINAL_SPEAKERPHONE_ECHOSUPRESS 0x0404
+#define AUDIO_TERMINAL_SPEAKERPHONE_ECHOCANCEL 0x0405
+
+/* Telephony Terminal Types */
+#define AUDIO_TERMINAL_TELEPHONY_UNDEFINED 0x0500
+#define AUDIO_TERMINAL_PHONE_LINE 0x0501
+#define AUDIO_TERMINAL_TELEPHONE 0x0502
+#define AUDIO_TERMINAL_DOWN_LINE_PHONE 0x0503
+
+/* External Terminal Types */
+#define AUDIO_TERMINAL_EXTERNAL_UNDEFINED 0x0600
+#define AUDIO_TERMINAL_ANALOG_CONNECTOR 0x0601
+#define AUDIO_TERMINAL_DIGITAL_AUDIO_INTERFACE 0x0602
+#define AUDIO_TERMINAL_LINE_CONNECTOR 0x0603
+#define AUDIO_TERMINAL_LEGACY_AUDIO_CONNECTOR 0x0604
+#define AUDIO_TERMINAL_SPDIF_INTERFACE 0x0605
+#define AUDIO_TERMINAL_1394_DA_STREAM 0x0606
+#define AUDIO_TERMINAL_1394_DA_STREAM_TRACK 0x0607
+
+/* Embedded Function Terminal Types */
+#define AUDIO_TERMINAL_EMBEDDED_UNDEFINED 0x0700
+#define AUDIO_TERMINAL_CALIBRATION_NOISE 0x0701
+#define AUDIO_TERMINAL_EQUALIZATION_NOISE 0x0702
+#define AUDIO_TERMINAL_CD_PLAYER 0x0703
+#define AUDIO_TERMINAL_DAT 0x0704
+#define AUDIO_TERMINAL_DCC 0x0705
+#define AUDIO_TERMINAL_MINI_DISK 0x0706
+#define AUDIO_TERMINAL_ANALOG_TAPE 0x0707
+#define AUDIO_TERMINAL_PHONOGRAPH 0x0708
+#define AUDIO_TERMINAL_VCR_AUDIO 0x0709
+#define AUDIO_TERMINAL_VIDEO_DISC_AUDIO 0x070A
+#define AUDIO_TERMINAL_DVD_AUDIO 0x070B
+#define AUDIO_TERMINAL_TV_TUNER_AUDIO 0x070C
+#define AUDIO_TERMINAL_SATELLITE_RECEIVER_AUDIO 0x070D
+#define AUDIO_TERMINAL_CABLE_TUNER_AUDIO 0x070E
+#define AUDIO_TERMINAL_DSS_AUDIO 0x070F
+#define AUDIO_TERMINAL_RADIO_RECEIVER 0x0710
+#define AUDIO_TERMINAL_RADIO_TRANSMITTER 0x0711
+#define AUDIO_TERMINAL_MULTI_TRACK_RECORDER 0x0712
+#define AUDIO_TERMINAL_SYNTHESIZER 0x0713
+
+
+#endif /* __AUDIO_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_cdc.h b/source/lpc_chip_11u6x/inc/usbd/usbd_cdc.h
new file mode 100644
index 0000000..5703539
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_cdc.h
@@ -0,0 +1,249 @@
+/***********************************************************************
+* $Id:: mw_usbd_cdc.h 165 2011-04-14 17:41:11Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* USB Communication Device Class User module Definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+#ifndef __CDC_H
+#define __CDC_H
+
+#include "usbd.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions based on usbcdc11.pdf (www.usb.org)
+ *---------------------------------------------------------------------------*/
+/* Communication device class specification version 1.10 */
+#define CDC_V1_10 0x0110
+
+/* Communication interface class code */
+/* (usbcdc11.pdf, 4.2, Table 15) */
+#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
+
+/* Communication interface class subclass codes */
+/* (usbcdc11.pdf, 4.3, Table 16) */
+#define CDC_DIRECT_LINE_CONTROL_MODEL 0x01
+#define CDC_ABSTRACT_CONTROL_MODEL 0x02
+#define CDC_TELEPHONE_CONTROL_MODEL 0x03
+#define CDC_MULTI_CHANNEL_CONTROL_MODEL 0x04
+#define CDC_CAPI_CONTROL_MODEL 0x05
+#define CDC_ETHERNET_NETWORKING_CONTROL_MODEL 0x06
+#define CDC_ATM_NETWORKING_CONTROL_MODEL 0x07
+
+/* Communication interface class control protocol codes */
+/* (usbcdc11.pdf, 4.4, Table 17) */
+#define CDC_PROTOCOL_COMMON_AT_COMMANDS 0x01
+
+/* Data interface class code */
+/* (usbcdc11.pdf, 4.5, Table 18) */
+#define CDC_DATA_INTERFACE_CLASS 0x0A
+
+/* Data interface class protocol codes */
+/* (usbcdc11.pdf, 4.7, Table 19) */
+#define CDC_PROTOCOL_ISDN_BRI 0x30
+#define CDC_PROTOCOL_HDLC 0x31
+#define CDC_PROTOCOL_TRANSPARENT 0x32
+#define CDC_PROTOCOL_Q921_MANAGEMENT 0x50
+#define CDC_PROTOCOL_Q921_DATA_LINK 0x51
+#define CDC_PROTOCOL_Q921_MULTIPLEXOR 0x52
+#define CDC_PROTOCOL_V42 0x90
+#define CDC_PROTOCOL_EURO_ISDN 0x91
+#define CDC_PROTOCOL_V24_RATE_ADAPTATION 0x92
+#define CDC_PROTOCOL_CAPI 0x93
+#define CDC_PROTOCOL_HOST_BASED_DRIVER 0xFD
+#define CDC_PROTOCOL_DESCRIBED_IN_PUFD 0xFE
+
+/* Type values for bDescriptorType field of functional descriptors */
+/* (usbcdc11.pdf, 5.2.3, Table 24) */
+#define CDC_CS_INTERFACE 0x24
+#define CDC_CS_ENDPOINT 0x25
+
+/* Type values for bDescriptorSubtype field of functional descriptors */
+/* (usbcdc11.pdf, 5.2.3, Table 25) */
+#define CDC_HEADER 0x00
+#define CDC_CALL_MANAGEMENT 0x01
+#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
+#define CDC_DIRECT_LINE_MANAGEMENT 0x03
+#define CDC_TELEPHONE_RINGER 0x04
+#define CDC_REPORTING_CAPABILITIES 0x05
+#define CDC_UNION 0x06
+#define CDC_COUNTRY_SELECTION 0x07
+#define CDC_TELEPHONE_OPERATIONAL_MODES 0x08
+#define CDC_USB_TERMINAL 0x09
+#define CDC_NETWORK_CHANNEL 0x0A
+#define CDC_PROTOCOL_UNIT 0x0B
+#define CDC_EXTENSION_UNIT 0x0C
+#define CDC_MULTI_CHANNEL_MANAGEMENT 0x0D
+#define CDC_CAPI_CONTROL_MANAGEMENT 0x0E
+#define CDC_ETHERNET_NETWORKING 0x0F
+#define CDC_ATM_NETWORKING 0x10
+
+/* CDC class-specific request codes */
+/* (usbcdc11.pdf, 6.2, Table 46) */
+/* see Table 45 for info about the specific requests. */
+#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
+#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
+#define CDC_SET_COMM_FEATURE 0x02
+#define CDC_GET_COMM_FEATURE 0x03
+#define CDC_CLEAR_COMM_FEATURE 0x04
+#define CDC_SET_AUX_LINE_STATE 0x10
+#define CDC_SET_HOOK_STATE 0x11
+#define CDC_PULSE_SETUP 0x12
+#define CDC_SEND_PULSE 0x13
+#define CDC_SET_PULSE_TIME 0x14
+#define CDC_RING_AUX_JACK 0x15
+#define CDC_SET_LINE_CODING 0x20
+#define CDC_GET_LINE_CODING 0x21
+#define CDC_SET_CONTROL_LINE_STATE 0x22
+#define CDC_SEND_BREAK 0x23
+#define CDC_SET_RINGER_PARMS 0x30
+#define CDC_GET_RINGER_PARMS 0x31
+#define CDC_SET_OPERATION_PARMS 0x32
+#define CDC_GET_OPERATION_PARMS 0x33
+#define CDC_SET_LINE_PARMS 0x34
+#define CDC_GET_LINE_PARMS 0x35
+#define CDC_DIAL_DIGITS 0x36
+#define CDC_SET_UNIT_PARAMETER 0x37
+#define CDC_GET_UNIT_PARAMETER 0x38
+#define CDC_CLEAR_UNIT_PARAMETER 0x39
+#define CDC_GET_PROFILE 0x3A
+#define CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
+#define CDC_SET_ETHERNET_PMP_FILTER 0x41
+#define CDC_GET_ETHERNET_PMP_FILTER 0x42
+#define CDC_SET_ETHERNET_PACKET_FILTER 0x43
+#define CDC_GET_ETHERNET_STATISTIC 0x44
+#define CDC_SET_ATM_DATA_FORMAT 0x50
+#define CDC_GET_ATM_DEVICE_STATISTICS 0x51
+#define CDC_SET_ATM_DEFAULT_VC 0x52
+#define CDC_GET_ATM_VC_STATISTICS 0x53
+
+/* Communication feature selector codes */
+/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */
+#define CDC_ABSTRACT_STATE 0x01
+#define CDC_COUNTRY_SETTING 0x02
+
+/* Feature Status returned for ABSTRACT_STATE Selector */
+/* (usbcdc11.pdf, 6.2.3, Table 48) */
+#define CDC_IDLE_SETTING (1 << 0)
+#define CDC_DATA_MULTPLEXED_STATE (1 << 1)
+
+
+/* Control signal bitmap values for the SetControlLineState request */
+/* (usbcdc11.pdf, 6.2.14, Table 51) */
+#define CDC_DTE_PRESENT (1 << 0)
+#define CDC_ACTIVATE_CARRIER (1 << 1)
+
+/* CDC class-specific notification codes */
+/* (usbcdc11.pdf, 6.3, Table 68) */
+/* see Table 67 for Info about class-specific notifications */
+#define CDC_NOTIFICATION_NETWORK_CONNECTION 0x00
+#define CDC_RESPONSE_AVAILABLE 0x01
+#define CDC_AUX_JACK_HOOK_STATE 0x08
+#define CDC_RING_DETECT 0x09
+#define CDC_NOTIFICATION_SERIAL_STATE 0x20
+#define CDC_CALL_STATE_CHANGE 0x28
+#define CDC_LINE_STATE_CHANGE 0x29
+#define CDC_CONNECTION_SPEED_CHANGE 0x2A
+
+/* UART state bitmap values (Serial state notification). */
+/* (usbcdc11.pdf, 6.3.5, Table 69) */
+#define CDC_SERIAL_STATE_OVERRUN (1 << 6) /* receive data overrun error has occurred */
+#define CDC_SERIAL_STATE_PARITY (1 << 5) /* parity error has occurred */
+#define CDC_SERIAL_STATE_FRAMING (1 << 4) /* framing error has occurred */
+#define CDC_SERIAL_STATE_RING (1 << 3) /* state of ring signal detection */
+#define CDC_SERIAL_STATE_BREAK (1 << 2) /* state of break detection */
+#define CDC_SERIAL_STATE_TX_CARRIER (1 << 1) /* state of transmission carrier */
+#define CDC_SERIAL_STATE_RX_CARRIER (1 << 0) /* state of receiver carrier */
+
+
+/*----------------------------------------------------------------------------
+ * Structures based on usbcdc11.pdf (www.usb.org)
+ *---------------------------------------------------------------------------*/
+
+/* Header functional descriptor */
+/* (usbcdc11.pdf, 5.2.3.1) */
+/* This header must precede any list of class-specific descriptors. */
+PRE_PACK struct POST_PACK _CDC_HEADER_DESCRIPTOR{
+ uint8_t bFunctionLength; /* size of this descriptor in bytes */
+ uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
+ uint8_t bDescriptorSubtype; /* Header functional descriptor subtype */
+ uint16_t bcdCDC; /* USB CDC specification release version */
+};
+typedef struct _CDC_HEADER_DESCRIPTOR CDC_HEADER_DESCRIPTOR;
+
+/* Call management functional descriptor */
+/* (usbcdc11.pdf, 5.2.3.2) */
+/* Describes the processing of calls for the communication class interface. */
+PRE_PACK struct POST_PACK _CDC_CALL_MANAGEMENT_DESCRIPTOR {
+ uint8_t bFunctionLength; /* size of this descriptor in bytes */
+ uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
+ uint8_t bDescriptorSubtype; /* call management functional descriptor subtype */
+ uint8_t bmCapabilities; /* capabilities that this configuration supports */
+ uint8_t bDataInterface; /* interface number of the data class interface used for call management (optional) */
+};
+typedef struct _CDC_CALL_MANAGEMENT_DESCRIPTOR CDC_CALL_MANAGEMENT_DESCRIPTOR;
+
+/* Abstract control management functional descriptor */
+/* (usbcdc11.pdf, 5.2.3.3) */
+/* Describes the command supported by the communication interface class with the Abstract Control Model subclass code. */
+PRE_PACK struct POST_PACK _CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR {
+ uint8_t bFunctionLength; /* size of this descriptor in bytes */
+ uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
+ uint8_t bDescriptorSubtype; /* abstract control management functional descriptor subtype */
+ uint8_t bmCapabilities; /* capabilities supported by this configuration */
+};
+typedef struct _CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR;
+
+/* Union functional descriptors */
+/* (usbcdc11.pdf, 5.2.3.8) */
+/* Describes the relationship between a group of interfaces that can be considered to form a functional unit. */
+PRE_PACK struct POST_PACK _CDC_UNION_DESCRIPTOR {
+ uint8_t bFunctionLength; /* size of this descriptor in bytes */
+ uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
+ uint8_t bDescriptorSubtype; /* union functional descriptor subtype */
+ uint8_t bMasterInterface; /* interface number designated as master */
+};
+typedef struct _CDC_UNION_DESCRIPTOR CDC_UNION_DESCRIPTOR;
+
+/* Union functional descriptors with one slave interface */
+/* (usbcdc11.pdf, 5.2.3.8) */
+PRE_PACK struct POST_PACK _CDC_UNION_1SLAVE_DESCRIPTOR {
+ CDC_UNION_DESCRIPTOR sUnion; /* Union functional descriptor */
+ uint8_t bSlaveInterfaces[1]; /* Slave interface 0 */
+};
+typedef struct _CDC_UNION_1SLAVE_DESCRIPTOR CDC_UNION_1SLAVE_DESCRIPTOR;
+
+/* Line coding structure */
+/* Format of the data returned when a GetLineCoding request is received */
+/* (usbcdc11.pdf, 6.2.13) */
+PRE_PACK struct POST_PACK _CDC_LINE_CODING {
+ uint32_t dwDTERate; /* Data terminal rate in bits per second */
+ uint8_t bCharFormat; /* Number of stop bits */
+ uint8_t bParityType; /* Parity bit type */
+ uint8_t bDataBits; /* Number of data bits */
+};
+typedef struct _CDC_LINE_CODING CDC_LINE_CODING;
+
+/* Notification header */
+/* Data sent on the notification endpoint must follow this header. */
+/* see USB_SETUP_PACKET in file usb.h */
+typedef USB_SETUP_PACKET CDC_NOTIFICATION_HEADER;
+
+#endif /* __CDC_H */
+
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_cdcuser.h b/source/lpc_chip_11u6x/inc/usbd/usbd_cdcuser.h
new file mode 100644
index 0000000..5eef601
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_cdcuser.h
@@ -0,0 +1,529 @@
+/***********************************************************************
+* $Id:: mw_usbd_cdcuser.h 331 2012-08-09 18:54:34Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* USB Communication Device Class User module Definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+#ifndef __CDCUSER_H__
+#define __CDCUSER_H__
+
+#include "error.h"
+#include "usbd.h"
+#include "usbd_cdc.h"
+
+/** \file
+ * \brief Communication Device Class (CDC) API structures and function prototypes.
+ *
+ * Definition of functions exported by ROM based CDC function driver.
+ *
+ */
+
+/** \ingroup Group_USBD
+ * @defgroup USBD_CDC Communication Device Class (CDC) Function Driver
+ * \section Sec_CDCModDescription Module Description
+ * CDC Class Function Driver module. This module contains an internal implementation of the USB CDC Class.
+ *
+ * User applications can use this class driver instead of implementing the CDC-ACM class manually
+ * via the low-level USBD_HW and USBD_Core APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Devices using the USB CDC-ACM Class.
+ */
+
+/*----------------------------------------------------------------------------
+ We need a buffer for incoming data on USB port because USB receives
+ much faster than UART transmits
+ *---------------------------------------------------------------------------*/
+/* Buffer masks */
+#define CDC_BUF_SIZE (128) /* Output buffer in bytes (power 2) */
+ /* large enough for file transfer */
+#define CDC_BUF_MASK (CDC_BUF_SIZE-1ul)
+
+/** \brief Communication Device Class function driver initialization parameter data structure.
+ * \ingroup USBD_CDC
+ *
+ * \details This data structure is used to pass initialization parameters to the
+ * Communication Device Class function driver's init function.
+ *
+ */
+typedef struct USBD_CDC_INIT_PARAM
+{
+ /* memory allocation params */
+ uint32_t mem_base; /**< Base memory location from where the stack can allocate
+ data and buffers. \note The memory address set in this field
+ should be accessible by USB DMA controller. Also this value
+ should be aligned on 4 byte boundary.
+ */
+ uint32_t mem_size; /**< The size of memory buffer which stack can use.
+ \note The \em mem_size should be greater than the size
+ returned by USBD_CDC_API::GetMemSize() routine.*/
+ /** Pointer to the control interface descriptor within the descriptor
+ * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T
+ * structure. The stack assumes both HS and FS use same BULK endpoints.
+ */
+ uint8_t* cif_intf_desc;
+ /** Pointer to the data interface descriptor within the descriptor
+ * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T
+ * structure. The stack assumes both HS and FS use same BULK endpoints.
+ */
+ uint8_t* dif_intf_desc;
+
+ /* user defined functions */
+
+ /* required functions */
+ /**
+ * Communication Interface Class specific get request call-back function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends CIC management element get requests.
+ * \note Applications implementing Abstract Control Model subclass can set this
+ * param to NULL. As the default driver parses ACM requests and calls the
+ * individual ACM call-back routines defined in this structure. For all other subclasses
+ * this routine should be provided by the application.
+ * \n
+ * The setup packet data (\em pSetup) is passed to the call-back so that application
+ * can extract the CIC request type and other associated data. By default the stack
+ * will assign \em pBuffer pointer to \em EP0Buff allocated at init. The application
+ * code can directly write data into this buffer as long as data is less than 64 byte.
+ * If more data has to be sent then application code should update \em pBuffer pointer
+ * and length accordingly.
+ *
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in] pSetup Pointer to setup packet received from host.
+ * \param[in, out] pBuffer Pointer to a pointer of data buffer containing request data.
+ * Pointer-to-pointer is used to implement zero-copy buffers.
+ * See \ref USBD_ZeroCopy for more details on zero-copy concept.
+ * \param[in, out] length Amount of data to be sent back to host.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*CIC_GetRequest)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length);
+
+ /**
+ * Communication Interface Class specific set request call-back function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a CIC management element requests.
+ * \note Applications implementing Abstract Control Model subclass can set this
+ * param to NULL. As the default driver parses ACM requests and calls the
+ * individual ACM call-back routines defined in this structure. For all other subclasses
+ * this routine should be provided by the application.
+ * \n
+ * The setup packet data (\em pSetup) is passed to the call-back so that application can
+ * extract the CIC request type and other associated data. If a set request has data associated,
+ * then this call-back is called twice.
+ * -# First when setup request is received, at this time application code could update
+ * \em pBuffer pointer to point to the intended destination. The length param is set to 0
+ * so that application code knows this is first time. By default the stack will
+ * assign \em pBuffer pointer to \em EP0Buff allocated at init. Note, if data length is
+ * greater than 64 bytes and application code doesn't update \em pBuffer pointer the
+ * stack will send STALL condition to host.
+ * -# Second when the data is received from the host. This time the length param is set
+ * with number of data bytes received.
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in] pSetup Pointer to setup packet received from host.
+ * \param[in, out] pBuffer Pointer to a pointer of data buffer containing request data.
+ * Pointer-to-pointer is used to implement zero-copy buffers.
+ * See \ref USBD_ZeroCopy for more details on zero-copy concept.
+ * \param[in] length Amount of data copied to destination buffer.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*CIC_SetRequest)( USBD_HANDLE_T hCdc, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length);
+
+ /**
+ * Communication Device Class specific BULK IN endpoint handler.
+ *
+ * The application software should provide the BULK IN endpoint handler.
+ * Applications should transfer data depending on the communication protocol type set in descriptors.
+ * \n
+ * \note
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*CDC_BulkIN_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event);
+
+ /**
+ * Communication Device Class specific BULK OUT endpoint handler.
+ *
+ * The application software should provide the BULK OUT endpoint handler.
+ * Applications should transfer data depending on the communication protocol type set in descriptors.
+ * \n
+ * \note
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*CDC_BulkOUT_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event);
+
+ /**
+ * Abstract control model(ACM) subclass specific SEND_ENCAPSULATED_COMMAND request call-back function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a SEND_ENCAPSULATED_COMMAND set request.
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in] buffer Pointer to the command buffer.
+ * \param[in] len Length of the command buffer.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*SendEncpsCmd) (USBD_HANDLE_T hCDC, uint8_t* buffer, uint16_t len);
+
+ /**
+ * Abstract control model(ACM) subclass specific GET_ENCAPSULATED_RESPONSE request call-back function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a GET_ENCAPSULATED_RESPONSE request.
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in, out] buffer Pointer to a pointer of data buffer containing response data.
+ * Pointer-to-pointer is used to implement zero-copy buffers.
+ * See \ref USBD_ZeroCopy for more details on zero-copy concept.
+ * \param[in, out] len Amount of data to be sent back to host.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*GetEncpsResp) (USBD_HANDLE_T hCDC, uint8_t** buffer, uint16_t* len);
+
+ /**
+ * Abstract control model(ACM) subclass specific SET_COMM_FEATURE request call-back function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a SET_COMM_FEATURE set request.
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in] feature Communication feature type. See usbcdc11.pdf, section 6.2.4, Table 47.
+ * \param[in] buffer Pointer to the settings buffer for the specified communication feature.
+ * \param[in] len Length of the request buffer.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*SetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t* buffer, uint16_t len);
+
+ /**
+ * Abstract control model(ACM) subclass specific GET_COMM_FEATURE request call-back function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a GET_ENCAPSULATED_RESPONSE request.
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in] feature Communication feature type. See usbcdc11.pdf, section 6.2.4, Table 47.
+ * \param[in, out] buffer Pointer to a pointer of data buffer containing current settings
+ * for the communication feature.
+ * Pointer-to-pointer is used to implement zero-copy buffers.
+ * \param[in, out] len Amount of data to be sent back to host.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*GetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t** pBuffer, uint16_t* len);
+
+ /**
+ * Abstract control model(ACM) subclass specific CLEAR_COMM_FEATURE request call-back function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a CLEAR_COMM_FEATURE request. In the call-back the application
+ * should Clears the settings for a particular communication feature.
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in] feature Communication feature type. See usbcdc11.pdf, section 6.2.4, Table 47.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*ClrCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature);
+
+ /**
+ * Abstract control model(ACM) subclass specific SET_CONTROL_LINE_STATE request call-back function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a SET_CONTROL_LINE_STATE request. RS-232 signal used to tell the DCE
+ * device the DTE device is now present
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in] state The state value uses bitmap values defined in usbcdc11.pdf,
+ * section 6.2.14, Table 51.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*SetCtrlLineState) (USBD_HANDLE_T hCDC, uint16_t state);
+
+ /**
+ * Abstract control model(ACM) subclass specific SEND_BREAK request call-back function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a SEND_BREAK request.
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in] mstime Duration of Break signal in milliseconds. If mstime is FFFFh, then
+ * the application should send break until another SendBreak request is received
+ * with the wValue of 0000h.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*SendBreak) (USBD_HANDLE_T hCDC, uint16_t mstime);
+
+ /**
+ * Abstract control model(ACM) subclass specific SET_LINE_CODING request call-back function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a SET_LINE_CODING request. The application should configure the device
+ * per DTE rate, stop-bits, parity, and number-of-character bits settings provided in
+ * command buffer. See usbcdc11.pdf, section 6.2.13, table 50 for detail of the command buffer.
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in] line_coding Pointer to the CDC_LINE_CODING command buffer.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*SetLineCode) (USBD_HANDLE_T hCDC, CDC_LINE_CODING* line_coding);
+
+ /**
+ * Optional Communication Device Class specific INTERRUPT IN endpoint handler.
+ *
+ * The application software should provide the INT IN endpoint handler.
+ * Applications should transfer data depending on the communication protocol type set in descriptors.
+ * \n
+ * \note
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*CDC_InterruptEP_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event);
+
+ /**
+ * Optional user override-able function to replace the default CDC class handler.
+ *
+ * The application software could override the default EP0 class handler with their
+ * own by providing the handler function address as this data member of the parameter
+ * structure. Application which like the default handler should set this data member
+ * to zero before calling the USBD_CDC_API::Init().
+ * \n
+ * \note
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*CDC_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event);
+
+} USBD_CDC_INIT_PARAM_T;
+
+/** \brief CDC class API functions structure.
+ * \ingroup USBD_CDC
+ *
+ * This module exposes functions which interact directly with USB device controller hardware.
+ *
+ */
+typedef struct USBD_CDC_API
+{
+ /** \fn uint32_t GetMemSize(USBD_CDC_INIT_PARAM_T* param)
+ * Function to determine the memory required by the CDC function driver module.
+ *
+ * This function is called by application layer before calling pUsbApi->CDC->Init(), to allocate memory used
+ * by CDC function driver module. The application should allocate the memory which is accessible by USB
+ * controller/DMA controller.
+ * \note Some memory areas are not accessible by all bus masters.
+ *
+ * \param[in] param Structure containing CDC function driver module initialization parameters.
+ * \return Returns the required memory size in bytes.
+ */
+ uint32_t (*GetMemSize)(USBD_CDC_INIT_PARAM_T* param);
+
+ /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_CDC_INIT_PARAM_T* param)
+ * Function to initialize CDC function driver module.
+ *
+ * This function is called by application layer to initialize CDC function driver module.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in, out] param Structure containing CDC function driver module initialization parameters.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success
+ * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte
+ * aligned or smaller than required.
+ * \retval ERR_API_INVALID_PARAM2 Either CDC_Write() or CDC_Read() or
+ * CDC_Verify() callbacks are not defined.
+ * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed.
+ * \retval ERR_USBD_BAD_EP_DESC Wrong endpoint descriptor is passed.
+ */
+ ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_CDC_INIT_PARAM_T* param, USBD_HANDLE_T* phCDC);
+
+ /** \fn ErrorCode_t SendNotification(USBD_HANDLE_T hCdc, uint8_t bNotification, uint16_t data)
+ * Function to send CDC class notifications to host.
+ *
+ * This function is called by application layer to send CDC class notifications to host.
+ * See usbcdc11.pdf, section 6.3, Table 67 for various notification types the CDC device can send.
+ * \note The current version of the driver only supports following notifications allowed by ACM subclass:
+ * CDC_NOTIFICATION_NETWORK_CONNECTION, CDC_RESPONSE_AVAILABLE, CDC_NOTIFICATION_SERIAL_STATE.
+ * \n
+ * For all other notifications application should construct the notification buffer appropriately
+ * and call hw->USB_WriteEP() for interrupt endpoint associated with the interface.
+ *
+ * \param[in] hCdc Handle to CDC function driver.
+ * \param[in] bNotification Notification type allowed by ACM subclass. Should be CDC_NOTIFICATION_NETWORK_CONNECTION,
+ * CDC_RESPONSE_AVAILABLE or CDC_NOTIFICATION_SERIAL_STATE. For all other types ERR_API_INVALID_PARAM2
+ * is returned. See usbcdc11.pdf, section 3.6.2.1, table 5.
+ * \param[in] data Data associated with notification.
+ * \n For CDC_NOTIFICATION_NETWORK_CONNECTION a non-zero data value is interpreted as connected state.
+ * \n For CDC_RESPONSE_AVAILABLE this parameter is ignored.
+ * \n For CDC_NOTIFICATION_SERIAL_STATE the data should use bitmap values defined in usbcdc11.pdf,
+ * section 6.3.5, Table 69.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success
+ * \retval ERR_API_INVALID_PARAM2 If unsupported notification type is passed.
+ *
+ */
+ ErrorCode_t (*SendNotification)(USBD_HANDLE_T hCdc, uint8_t bNotification, uint16_t data);
+
+} USBD_CDC_API_T;
+
+/*-----------------------------------------------------------------------------
+ * Private functions & structures prototypes
+ *-----------------------------------------------------------------------------*/
+/** @cond ADVANCED_API */
+
+typedef struct _CDC_CTRL_T
+{
+ USB_CORE_CTRL_T* pUsbCtrl;
+ /* notification buffer */
+ uint8_t notice_buf[12];
+ CDC_LINE_CODING line_coding;
+ uint8_t pad0;
+
+ uint8_t cif_num; /* control interface number */
+ uint8_t dif_num; /* data interface number */
+ uint8_t epin_num; /* BULK IN endpoint number */
+ uint8_t epout_num; /* BULK OUT endpoint number */
+ uint8_t epint_num; /* Interrupt IN endpoint number */
+ uint8_t pad[3];
+ /* user defined functions */
+ ErrorCode_t (*SendEncpsCmd) (USBD_HANDLE_T hCDC, uint8_t* buffer, uint16_t len);
+ ErrorCode_t (*GetEncpsResp) (USBD_HANDLE_T hCDC, uint8_t** buffer, uint16_t* len);
+ ErrorCode_t (*SetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t* buffer, uint16_t len);
+ ErrorCode_t (*GetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t** pBuffer, uint16_t* len);
+ ErrorCode_t (*ClrCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature);
+ ErrorCode_t (*SetCtrlLineState) (USBD_HANDLE_T hCDC, uint16_t state);
+ ErrorCode_t (*SendBreak) (USBD_HANDLE_T hCDC, uint16_t state);
+ ErrorCode_t (*SetLineCode) (USBD_HANDLE_T hCDC, CDC_LINE_CODING* line_coding);
+
+ /* virtual functions */
+ ErrorCode_t (*CIC_GetRequest)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length);
+ ErrorCode_t (*CIC_SetRequest)( USBD_HANDLE_T hCdc, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length);
+
+} USB_CDC_CTRL_T;
+
+/* structure used by old ROM drivers, needed for workaround */
+typedef struct _CDC0_CTRL_T {
+ USB_CORE_CTRL_T *pUsbCtrl;
+ /* notification buffer */
+ uint8_t notice_buf[12];
+ CDC_LINE_CODING line_coding;
+
+ uint8_t cif_num; /* control interface number */
+ uint8_t dif_num; /* data interface number */
+ uint8_t epin_num; /* BULK IN endpoint number */
+ uint8_t epout_num; /* BULK OUT endpoint number */
+ uint8_t epint_num; /* Interrupt IN endpoint number */
+ /* user defined functions */
+ ErrorCode_t (*SendEncpsCmd)(USBD_HANDLE_T hCDC, uint8_t *buffer, uint16_t len);
+ ErrorCode_t (*GetEncpsResp)(USBD_HANDLE_T hCDC, uint8_t * *buffer, uint16_t *len);
+ ErrorCode_t (*SetCommFeature)(USBD_HANDLE_T hCDC, uint16_t feature, uint8_t *buffer, uint16_t len);
+ ErrorCode_t (*GetCommFeature)(USBD_HANDLE_T hCDC, uint16_t feature, uint8_t * *pBuffer, uint16_t *len);
+ ErrorCode_t (*ClrCommFeature)(USBD_HANDLE_T hCDC, uint16_t feature);
+ ErrorCode_t (*SetCtrlLineState)(USBD_HANDLE_T hCDC, uint16_t state);
+ ErrorCode_t (*SendBreak)(USBD_HANDLE_T hCDC, uint16_t state);
+ ErrorCode_t (*SetLineCode)(USBD_HANDLE_T hCDC, CDC_LINE_CODING *line_coding);
+
+ /* virtual functions */
+ ErrorCode_t (*CIC_GetRequest)(USBD_HANDLE_T hHid, USB_SETUP_PACKET *pSetup, uint8_t * *pBuffer, uint16_t *length);
+ ErrorCode_t (*CIC_SetRequest)(USBD_HANDLE_T hCdc, USB_SETUP_PACKET *pSetup, uint8_t * *pBuffer, uint16_t length);
+
+} USB_CDC0_CTRL_T;
+
+typedef ErrorCode_t (*CIC_SetRequest_t)(USBD_HANDLE_T hCdc, USB_SETUP_PACKET *pSetup, uint8_t * *pBuffer, uint16_t length);
+
+/** @cond DIRECT_API */
+extern uint32_t mwCDC_GetMemSize(USBD_CDC_INIT_PARAM_T* param);
+extern ErrorCode_t mwCDC_init(USBD_HANDLE_T hUsb, USBD_CDC_INIT_PARAM_T* param, USBD_HANDLE_T* phCDC);
+extern ErrorCode_t mwCDC_SendNotification (USBD_HANDLE_T hCdc, uint8_t bNotification, uint16_t data);
+/** @endcond */
+
+/** @endcond */
+
+
+
+
+
+#endif /* __CDCUSER_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_core.h b/source/lpc_chip_11u6x/inc/usbd/usbd_core.h
new file mode 100644
index 0000000..dbbbcbe
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_core.h
@@ -0,0 +1,585 @@
+/***********************************************************************
+* $Id:: mw_usbd_core.h 331 2012-08-09 18:54:34Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* USB core controller structure definitions and function prototypes.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+#ifndef __MW_USBD_CORE_H__
+#define __MW_USBD_CORE_H__
+
+#include "error.h"
+#include "usbd.h"
+#include "app_usbd_cfg.h"
+
+/** \file
+ * \brief ROM API for USB device stack.
+ *
+ * Definition of functions exported by core layer of ROM based USB device stack.
+ *
+ */
+
+/** \ingroup Group_USBD
+ * @defgroup USBD_Core USB Core Layer
+ * \section Sec_CoreModDescription Module Description
+ * The USB Core Layer implements the device abstraction defined in the Universal Serial Bus Specification,
+ * for applications to interact with the USB device interface on the device. The software in this layer responds to
+ * standard requests and returns standard descriptors. In current stack the Init() routine part of
+ * \ref USBD_HW_API_T structure initializes both hardware layer and core layer.
+ */
+
+
+/* function pointer types */
+
+/** \ingroup USBD_Core
+ * \typedef USB_CB_T
+ * \brief USB device stack's event callback function type.
+ *
+ * The USB device stack exposes several event triggers through callback to application layer. The
+ * application layer can register methods to be called when such USB event happens.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx Other error conditions.
+ *
+ */
+typedef ErrorCode_t (*USB_CB_T) (USBD_HANDLE_T hUsb);
+
+/** \ingroup USBD_Core
+ * \typedef USB_PARAM_CB_T
+ * \brief USB device stack's event callback function type.
+ *
+ * The USB device stack exposes several event triggers through callback to application layer. The
+ * application layer can register methods to be called when such USB event happens.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] param1 Extra information related to the event.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+typedef ErrorCode_t (*USB_PARAM_CB_T) (USBD_HANDLE_T hUsb, uint32_t param1);
+
+/** \ingroup USBD_Core
+ * \typedef USB_EP_HANDLER_T
+ * \brief USBD setup request and endpoint event handler type.
+ *
+ * The application layer should define the custom class's EP0 handler with function signature.
+ * The stack calls all the registered class handlers on any EP0 event before going through default
+ * handling of the event. This gives the class handlers to implement class specific request handlers
+ * and also to override the default stack handling for a particular event targeted to the interface.
+ * If an event is not handled by the callback the function should return ERR_USBD_UNHANDLED. For all
+ * other return codes the stack assumes that callback has taken care of the event and hence will not
+ * process the event any further and issues a STALL condition on EP0 indicating error to the host.
+ * \n
+ * For endpoint interrupt handler the return value is ignored by the stack.
+ * \n
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+typedef ErrorCode_t (*USB_EP_HANDLER_T)(USBD_HANDLE_T hUsb, void* data, uint32_t event);
+
+
+/** \ingroup USBD_Core
+ * \brief USB descriptors data structure.
+ * \ingroup USBD_Core
+ *
+ * \details This structure is used as part of USB device stack initialization
+ * parameter structure \ref USBD_API_INIT_PARAM_T. This structure contains
+ * pointers to various descriptor arrays needed by the stack. These descriptors
+ * are reported to USB host as part of enumerations process.
+ *
+ * \note All descriptor pointers assigned in this structure should be on 4 byte
+ * aligned address boundary.
+ */
+typedef struct _USB_CORE_DESCS_T
+{
+ uint8_t *device_desc; /**< Pointer to USB device descriptor */
+ uint8_t *string_desc; /**< Pointer to array of USB string descriptors */
+ uint8_t *full_speed_desc; /**< Pointer to USB device configuration descriptor
+ * when device is operating in full speed mode.
+ */
+ uint8_t *high_speed_desc; /**< Pointer to USB device configuration descriptor
+ * when device is operating in high speed mode. For
+ * full-speed only implementation this pointer should
+ * be same as full_speed_desc.
+ */
+ uint8_t *device_qualifier; /**< Pointer to USB device qualifier descriptor. For
+ * full-speed only implementation this pointer should
+ * be set to null (0).
+ */
+} USB_CORE_DESCS_T;
+
+/** \brief USB device stack initialization parameter data structure.
+ * \ingroup USBD_Core
+ *
+ * \details This data structure is used to pass initialization parameters to the
+ * USB device stack's init function.
+ *
+ */
+typedef struct USBD_API_INIT_PARAM
+{
+ uint32_t usb_reg_base; /**< USB device controller's base register address. */
+ uint32_t mem_base; /**< Base memory location from where the stack can allocate
+ data and buffers. \note The memory address set in this field
+ should be accessible by USB DMA controller. Also this value
+ should be aligned on 2048 byte boundary.
+ */
+ uint32_t mem_size; /**< The size of memory buffer which stack can use.
+ \note The \em mem_size should be greater than the size
+ returned by USBD_HW_API::GetMemSize() routine.*/
+ uint8_t max_num_ep; /**< max number of endpoints supported by the USB device
+ controller instance (specified by \em usb_reg_base field)
+ to which this instance of stack is attached.
+ */
+ uint8_t pad0[3];
+ /* USB Device Events Callback Functions */
+ /** Event for USB interface reset. This event fires when the USB host requests that the device
+ * reset its interface. This event fires after the control endpoint has been automatically
+ * configured by the library.
+ * \n
+ * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this
+ * callback will prevent the device from enumerating correctly or operate properly.
+ *
+ */
+ USB_CB_T USB_Reset_Event;
+
+ /** Event for USB suspend. This event fires when the USB host suspends the device by halting its
+ * transmission of Start Of Frame pulses to the device. This is generally hooked in order to move
+ * the device over to a low power state until the host wakes up the device.
+ * \n
+ * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this
+ * callback will cause other system issues.
+ */
+ USB_CB_T USB_Suspend_Event;
+
+ /** Event for USB wake up or resume. This event fires when a the USB device interface is suspended
+ * and the host wakes up the device by supplying Start Of Frame pulses. This is generally
+ * hooked to pull the user application out of a low power state and back into normal operating
+ * mode.
+ * \n
+ * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this
+ * callback will cause other system issues.
+ *
+ */
+ USB_CB_T USB_Resume_Event;
+
+ /** Reserved parameter should be set to zero. */
+ USB_CB_T reserved_sbz;
+
+ /** Event for USB Start Of Frame detection, when enabled. This event fires at the start of each USB
+ * frame, once per millisecond in full-speed mode or once per 125 microseconds in high-speed mode,
+ * and is synchronized to the USB bus.
+ *
+ * This event is time-critical; it is run once per millisecond (full-speed mode) and thus long handlers
+ * will significantly degrade device performance. This event should only be enabled when needed to
+ * reduce device wake-ups.
+ *
+ * \note This event is not normally active - it must be manually enabled and disabled via the USB interrupt
+ * register.
+ * \n\n
+ */
+ USB_CB_T USB_SOF_Event;
+
+ /** Event for remote wake-up configuration, when enabled. This event fires when the USB host
+ * request the device to configure itself for remote wake-up capability. The USB host sends
+ * this request to device which report remote wake-up capable in their device descriptors,
+ * before going to low-power state. The application layer should implement this callback if
+ * they have any special on board circuit to trigger remote wake up event. Also application
+ * can use this callback to differentiate the following SUSPEND event is caused by cable plug-out
+ * or host SUSPEND request. The device can wake-up host only after receiving this callback and
+ * remote wake-up feature is enabled by host. To signal remote wake-up the device has to generate
+ * resume signaling on bus by calling usapi.hw->WakeUp() routine.
+ *
+ * \n\n
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] param1 When 0 - Clear the wake-up configuration, 1 - Enable the wake-up configuration.
+ * \return The call back should return \ref ErrorCode_t type to indicate success or error condition.
+ */
+ USB_PARAM_CB_T USB_WakeUpCfg;
+
+ /** Reserved parameter should be set to zero. */
+ USB_PARAM_CB_T USB_Power_Event;
+
+ /** Event for error condition. This event fires when USB device controller detect
+ * an error condition in the system.
+ *
+ * \n\n
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] param1 USB device interrupt status register.
+ * \return The call back should return \ref ErrorCode_t type to indicate success or error condition.
+ */
+ USB_PARAM_CB_T USB_Error_Event;
+
+ /* USB Core Events Callback Functions */
+ /** Event for USB configuration number changed. This event fires when a the USB host changes the
+ * selected configuration number. On receiving configuration change request from host, the stack
+ * enables/configures the endpoints needed by the new configuration before calling this callback
+ * function.
+ * \n
+ * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this
+ * callback will prevent the device from enumerating correctly or operate properly.
+ *
+ */
+ USB_CB_T USB_Configure_Event;
+
+ /** Event for USB interface setting changed. This event fires when a the USB host changes the
+ * interface setting to one of alternate interface settings. On receiving interface change
+ * request from host, the stack enables/configures the endpoints needed by the new alternate
+ * interface setting before calling this callback function.
+ * \n
+ * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this
+ * callback will prevent the device from enumerating correctly or operate properly.
+ *
+ */
+ USB_CB_T USB_Interface_Event;
+
+ /** Event for USB feature changed. This event fires when a the USB host send set/clear feature
+ * request. The stack handles this request for USB_FEATURE_REMOTE_WAKEUP, USB_FEATURE_TEST_MODE
+ * and USB_FEATURE_ENDPOINT_STALL features only. On receiving feature request from host, the
+ * stack handle the request appropriately and then calls this callback function.
+ * \n
+ * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this
+ * callback will prevent the device from enumerating correctly or operate properly.
+ *
+ */
+ USB_CB_T USB_Feature_Event;
+
+ /* cache and MMU translation functions */
+ /** Reserved parameter for future use. should be set to zero. */
+ uint32_t (* virt_to_phys)(void* vaddr);
+ /** Reserved parameter for future use. should be set to zero. */
+ void (* cache_flush)(uint32_t* start_adr, uint32_t* end_adr);
+
+} USBD_API_INIT_PARAM_T;
+
+
+/** \brief USBD stack Core API functions structure.
+ * \ingroup USBD_Core
+ *
+ * \details This module exposes functions which interact directly with USB device stack's core layer.
+ * The application layer uses this component when it has to implement custom class function driver or
+ * standard class function driver which is not part of the current USB device stack.
+ * The functions exposed by this interface are to register class specific EP0 handlers and corresponding
+ * utility functions to manipulate EP0 state machine of the stack. This interface also exposes
+ * function to register custom endpoint interrupt handler.
+ *
+ */
+typedef struct USBD_CORE_API
+{
+ /** \fn ErrorCode_t RegisterClassHandler(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data)
+ * Function to register class specific EP0 event handler with USB device stack.
+ *
+ * The application layer uses this function when it has to register the custom class's EP0 handler.
+ * The stack calls all the registered class handlers on any EP0 event before going through default
+ * handling of the event. This gives the class handlers to implement class specific request handlers
+ * and also to override the default stack handling for a particular event targeted to the interface.
+ * Check \ref USB_EP_HANDLER_T for more details on how the callback function should be implemented. Also
+ * application layer could use this function to register EP0 handler which responds to vendor specific
+ * requests.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] pfn Class specific EP0 handler function.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success
+ * \retval ERR_USBD_TOO_MANY_CLASS_HDLR(0x0004000c) The number of class handlers registered is
+ greater than the number of handlers allowed by the stack.
+ *
+ */
+ ErrorCode_t (*RegisterClassHandler)(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data);
+
+ /** \fn ErrorCode_t RegisterEpHandler(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data)
+ * Function to register interrupt/event handler for the requested endpoint with USB device stack.
+ *
+ * The application layer uses this function to register the endpoint event handler.
+ * The stack calls all the registered endpoint handlers when
+ * - USB_EVT_OUT or USB_EVT_OUT_NAK events happen for OUT endpoint.
+ * - USB_EVT_IN or USB_EVT_IN_NAK events happen for IN endpoint.
+ * Check USB_EP_HANDLER_T for more details on how the callback function should be implemented.
+ * \note By default endpoint _NAK events are not enabled. Application should call \ref USBD_HW_API_T::EnableEvent
+ * for the corresponding endpoint.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] ep_index Endpoint index. Computed as
+ * - For OUT endpoints = 2 * endpoint number eg. for EP2_OUT it is 4.
+ * - For IN endopoints = (2 * endpoint number) + 1 eg. for EP2_IN it is 5.
+ * \param[in] pfn Endpoint event handler function.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success
+ * \retval ERR_API_INVALID_PARAM2 ep_index is outside the boundary ( < 2 * USBD_API_INIT_PARAM_T::max_num_ep).
+ *
+ */
+ ErrorCode_t (*RegisterEpHandler)(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data);
+
+ /** \fn void SetupStage(USBD_HANDLE_T hUsb)
+ * Function to set EP0 state machine in setup state.
+ *
+ * This function is called by USB stack and the application layer to
+ * set the EP0 state machine in setup state. This function will read
+ * the setup packet received from USB host into stack's buffer.
+ * \n
+ * \note This interface is provided to users to invoke this function in other
+ * scenarios which are not handle by current stack. In most user applications
+ * this function is not called directly.Also this function can be used by
+ * users who are selectively modifying the USB device stack's standard handlers
+ * through callback interface exposed by the stack.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \return Nothing.
+ */
+ void (*SetupStage )(USBD_HANDLE_T hUsb);
+
+ /** \fn void DataInStage(USBD_HANDLE_T hUsb)
+ * Function to set EP0 state machine in data_in state.
+ *
+ * This function is called by USB stack and the application layer to
+ * set the EP0 state machine in data_in state. This function will write
+ * the data present in EP0Data buffer to EP0 FIFO for transmission to host.
+ * \n
+ * \note This interface is provided to users to invoke this function in other
+ * scenarios which are not handle by current stack. In most user applications
+ * this function is not called directly.Also this function can be used by
+ * users who are selectively modifying the USB device stack's standard handlers
+ * through callback interface exposed by the stack.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \return Nothing.
+ */
+ void (*DataInStage)(USBD_HANDLE_T hUsb);
+
+ /** \fn void DataOutStage(USBD_HANDLE_T hUsb)
+ * Function to set EP0 state machine in data_out state.
+ *
+ * This function is called by USB stack and the application layer to
+ * set the EP0 state machine in data_out state. This function will read
+ * the control data (EP0 out packets) received from USB host into EP0Data buffer.
+ * \n
+ * \note This interface is provided to users to invoke this function in other
+ * scenarios which are not handle by current stack. In most user applications
+ * this function is not called directly.Also this function can be used by
+ * users who are selectively modifying the USB device stack's standard handlers
+ * through callback interface exposed by the stack.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \return Nothing.
+ */
+ void (*DataOutStage)(USBD_HANDLE_T hUsb);
+
+ /** \fn void StatusInStage(USBD_HANDLE_T hUsb)
+ * Function to set EP0 state machine in status_in state.
+ *
+ * This function is called by USB stack and the application layer to
+ * set the EP0 state machine in status_in state. This function will send
+ * zero length IN packet on EP0 to host, indicating positive status.
+ * \n
+ * \note This interface is provided to users to invoke this function in other
+ * scenarios which are not handle by current stack. In most user applications
+ * this function is not called directly.Also this function can be used by
+ * users who are selectively modifying the USB device stack's standard handlers
+ * through callback interface exposed by the stack.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \return Nothing.
+ */
+ void (*StatusInStage)(USBD_HANDLE_T hUsb);
+ /** \fn void StatusOutStage(USBD_HANDLE_T hUsb)
+ * Function to set EP0 state machine in status_out state.
+ *
+ * This function is called by USB stack and the application layer to
+ * set the EP0 state machine in status_out state. This function will read
+ * the zero length OUT packet received from USB host on EP0.
+ * \n
+ * \note This interface is provided to users to invoke this function in other
+ * scenarios which are not handle by current stack. In most user applications
+ * this function is not called directly.Also this function can be used by
+ * users who are selectively modifying the USB device stack's standard handlers
+ * through callback interface exposed by the stack.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \return Nothing.
+ */
+ void (*StatusOutStage)(USBD_HANDLE_T hUsb);
+
+ /** \fn void StallEp0(USBD_HANDLE_T hUsb)
+ * Function to set EP0 state machine in stall state.
+ *
+ * This function is called by USB stack and the application layer to
+ * generate STALL signaling on EP0 endpoint. This function will also
+ * reset the EP0Data buffer.
+ * \n
+ * \note This interface is provided to users to invoke this function in other
+ * scenarios which are not handle by current stack. In most user applications
+ * this function is not called directly.Also this function can be used by
+ * users who are selectively modifying the USB device stack's standard handlers
+ * through callback interface exposed by the stack.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \return Nothing.
+ */
+ void (*StallEp0)(USBD_HANDLE_T hUsb);
+
+} USBD_CORE_API_T;
+
+/*-----------------------------------------------------------------------------
+ * Private functions & structures prototypes
+ *-----------------------------------------------------------------------------*/
+
+ /** @cond ADVANCED_API */
+
+/* forward declaration */
+struct _USB_CORE_CTRL_T;
+typedef struct _USB_CORE_CTRL_T USB_CORE_CTRL_T;
+
+/* USB device Speed status defines */
+#define USB_FULL_SPEED 0
+#define USB_HIGH_SPEED 1
+
+/* USB Endpoint Data Structure */
+typedef struct _USB_EP_DATA
+{
+ uint8_t *pData;
+ uint16_t Count;
+ uint16_t pad0;
+} USB_EP_DATA;
+
+
+/* USB core controller data structure */
+struct _USB_CORE_CTRL_T
+{
+ /* override-able function pointers ~ c++ style virtual functions*/
+ USB_CB_T USB_EvtSetupHandler;
+ USB_CB_T USB_EvtOutHandler;
+ USB_PARAM_CB_T USB_ReqVendor;
+ USB_CB_T USB_ReqGetStatus;
+ USB_CB_T USB_ReqGetDescriptor;
+ USB_CB_T USB_ReqGetConfiguration;
+ USB_CB_T USB_ReqSetConfiguration;
+ USB_CB_T USB_ReqGetInterface;
+ USB_CB_T USB_ReqSetInterface;
+ USB_PARAM_CB_T USB_ReqSetClrFeature;
+
+ /* USB Device Events Callback Functions */
+ USB_CB_T USB_Reset_Event;
+ USB_CB_T USB_Suspend_Event;
+ USB_CB_T USB_Resume_Event;
+ USB_CB_T USB_SOF_Event;
+ USB_PARAM_CB_T USB_Power_Event;
+ USB_PARAM_CB_T USB_Error_Event;
+ USB_PARAM_CB_T USB_WakeUpCfg;
+
+ /* USB Core Events Callback Functions */
+ USB_CB_T USB_Configure_Event;
+ USB_CB_T USB_Interface_Event;
+ USB_CB_T USB_Feature_Event;
+
+ /* cache and MMU translation functions */
+ uint32_t (* virt_to_phys)(void* vaddr);
+ void (* cache_flush)(uint32_t* start_adr, uint32_t* end_adr);
+
+ /* event handlers for endpoints. */
+ USB_EP_HANDLER_T ep_event_hdlr[2 * USB_MAX_EP_NUM];
+ void* ep_hdlr_data[2 * USB_MAX_EP_NUM];
+
+ /* USB class handlers */
+ USB_EP_HANDLER_T ep0_hdlr_cb[USB_MAX_IF_NUM];
+ void* ep0_cb_data[USB_MAX_IF_NUM];
+ uint8_t num_ep0_hdlrs;
+ /* USB Core data Variables */
+ uint8_t max_num_ep; /* max number of endpoints supported by the HW */
+ uint8_t device_speed;
+ uint8_t num_interfaces;
+ uint8_t device_addr;
+ uint8_t config_value;
+ uint16_t device_status;
+ uint8_t *device_desc;
+ uint8_t *string_desc;
+ uint8_t *full_speed_desc;
+ uint8_t *high_speed_desc;
+ uint8_t *device_qualifier;
+ uint32_t ep_mask;
+ uint32_t ep_halt;
+ uint32_t ep_stall;
+ uint8_t alt_setting[USB_MAX_IF_NUM];
+ /* HW driver data pointer */
+ void* hw_data;
+
+ /* USB Endpoint 0 Data Info */
+ USB_EP_DATA EP0Data;
+
+ /* USB Endpoint 0 Buffer */
+ //ALIGNED(4)
+ uint8_t EP0Buf[64];
+
+ /* USB Setup Packet */
+ //ALIGNED(4)
+ USB_SETUP_PACKET SetupPacket;
+
+};
+
+/* USB Core Functions */
+extern void mwUSB_InitCore(USB_CORE_CTRL_T* pCtrl, USB_CORE_DESCS_T* pdescr, USBD_API_INIT_PARAM_T* param);
+extern void mwUSB_ResetCore(USBD_HANDLE_T hUsb);
+
+/* inline functions */
+static INLINE void USB_SetSpeedMode(USB_CORE_CTRL_T* pCtrl, uint8_t mode)
+{
+ pCtrl->device_speed = mode;
+}
+
+static INLINE bool USB_IsConfigured(USBD_HANDLE_T hUsb)
+{
+ USB_CORE_CTRL_T* pCtrl = (USB_CORE_CTRL_T*) hUsb;
+ return (bool) (pCtrl->config_value != 0);
+}
+
+/** @cond DIRECT_API */
+/* midleware API */
+extern ErrorCode_t mwUSB_RegisterClassHandler(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data);
+extern ErrorCode_t mwUSB_RegisterEpHandler(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data);
+extern void mwUSB_SetupStage (USBD_HANDLE_T hUsb);
+extern void mwUSB_DataInStage(USBD_HANDLE_T hUsb);
+extern void mwUSB_DataOutStage(USBD_HANDLE_T hUsb);
+extern void mwUSB_StatusInStage(USBD_HANDLE_T hUsb);
+extern void mwUSB_StatusOutStage(USBD_HANDLE_T hUsb);
+extern void mwUSB_StallEp0(USBD_HANDLE_T hUsb);
+extern ErrorCode_t mwUSB_RegisterClassHandler(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data);
+extern ErrorCode_t mwUSB_RegisterEpHandler(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data);
+extern void mwUSB_SetupStage (USBD_HANDLE_T hUsb);
+extern void mwUSB_DataInStage(USBD_HANDLE_T hUsb);
+extern void mwUSB_DataOutStage(USBD_HANDLE_T hUsb);
+extern void mwUSB_StatusInStage(USBD_HANDLE_T hUsb);
+extern void mwUSB_StatusOutStage(USBD_HANDLE_T hUsb);
+extern void mwUSB_StallEp0(USBD_HANDLE_T hUsb);
+/** @endcond */
+
+/** @endcond */
+
+#endif /* __MW_USBD_CORE_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_desc.h b/source/lpc_chip_11u6x/inc/usbd/usbd_desc.h
new file mode 100644
index 0000000..510f936
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_desc.h
@@ -0,0 +1,48 @@
+/***********************************************************************
+* $Id:: mw_usbd_desc.h 165 2011-04-14 17:41:11Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* USB Descriptors Definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+
+#ifndef __USBDESC_H__
+#define __USBDESC_H__
+
+#include "usbd.h"
+
+#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
+#define B3VAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF),(((x) >> 16) & 0xFF)
+
+#define USB_DEVICE_DESC_SIZE (sizeof(USB_DEVICE_DESCRIPTOR))
+#define USB_CONFIGUARTION_DESC_SIZE (sizeof(USB_CONFIGURATION_DESCRIPTOR))
+#define USB_INTERFACE_DESC_SIZE (sizeof(USB_INTERFACE_DESCRIPTOR))
+#define USB_ENDPOINT_DESC_SIZE (sizeof(USB_ENDPOINT_DESCRIPTOR))
+#define USB_DEVICE_QUALI_SIZE (sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR))
+#define USB_OTHER_SPEED_CONF_SIZE (sizeof(USB_OTHER_SPEED_CONFIGURATION))
+
+//#define HID_DESC_SIZE (sizeof(HID_DESCRIPTOR))
+//#define HID_REPORT_DESC_SIZE (sizeof(HID_ReportDescriptor))
+
+extern const uint8_t HID_ReportDescriptor[];
+extern const uint16_t HID_ReportDescSize;
+extern const uint16_t HID_DescOffset;
+
+
+#endif /* __USBDESC_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_dfu.h b/source/lpc_chip_11u6x/inc/usbd/usbd_dfu.h
new file mode 100644
index 0000000..950f5a3
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_dfu.h
@@ -0,0 +1,120 @@
+/***********************************************************************
+* $Id:: mw_usbd_dfu.h 331 2012-08-09 18:54:34Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* Device Firmware Upgrade (DFU) module.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+#ifndef __MW_USBD_DFU_H__
+#define __MW_USBD_DFU_H__
+
+#include "usbd.h"
+
+/** \file
+ * \brief Device Firmware Upgrade (DFU) class descriptors.
+ *
+ * Definition of DFU class descriptors and their bit defines.
+ *
+ */
+
+/**
+ * If USB device is only DFU capable, DFU Interface number is always 0.
+ * if USB device is (DFU + Other Class (Audio/Mass Storage/HID), DFU
+ * Interface number should also be 0 in this implementation.
+ */
+#define USB_DFU_IF_NUM 0x0
+
+#define USB_DFU_DESCRIPTOR_TYPE 0x21
+#define USB_DFU_DESCRIPTOR_SIZE 9
+#define USB_DFU_SUBCLASS 0x01
+
+/* DFU class-specific requests (Section 3, DFU Rev 1.1) */
+#define USB_REQ_DFU_DETACH 0x00
+#define USB_REQ_DFU_DNLOAD 0x01
+#define USB_REQ_DFU_UPLOAD 0x02
+#define USB_REQ_DFU_GETSTATUS 0x03
+#define USB_REQ_DFU_CLRSTATUS 0x04
+#define USB_REQ_DFU_GETSTATE 0x05
+#define USB_REQ_DFU_ABORT 0x06
+
+#define DFU_STATUS_OK 0x00
+#define DFU_STATUS_errTARGET 0x01
+#define DFU_STATUS_errFILE 0x02
+#define DFU_STATUS_errWRITE 0x03
+#define DFU_STATUS_errERASE 0x04
+#define DFU_STATUS_errCHECK_ERASED 0x05
+#define DFU_STATUS_errPROG 0x06
+#define DFU_STATUS_errVERIFY 0x07
+#define DFU_STATUS_errADDRESS 0x08
+#define DFU_STATUS_errNOTDONE 0x09
+#define DFU_STATUS_errFIRMWARE 0x0a
+#define DFU_STATUS_errVENDOR 0x0b
+#define DFU_STATUS_errUSBR 0x0c
+#define DFU_STATUS_errPOR 0x0d
+#define DFU_STATUS_errUNKNOWN 0x0e
+#define DFU_STATUS_errSTALLEDPKT 0x0f
+
+enum dfu_state {
+ DFU_STATE_appIDLE = 0,
+ DFU_STATE_appDETACH = 1,
+ DFU_STATE_dfuIDLE = 2,
+ DFU_STATE_dfuDNLOAD_SYNC = 3,
+ DFU_STATE_dfuDNBUSY = 4,
+ DFU_STATE_dfuDNLOAD_IDLE = 5,
+ DFU_STATE_dfuMANIFEST_SYNC = 6,
+ DFU_STATE_dfuMANIFEST = 7,
+ DFU_STATE_dfuMANIFEST_WAIT_RST= 8,
+ DFU_STATE_dfuUPLOAD_IDLE = 9,
+ DFU_STATE_dfuERROR = 10
+};
+
+#define DFU_EP0_NONE 0
+#define DFU_EP0_UNHANDLED 1
+#define DFU_EP0_STALL 2
+#define DFU_EP0_ZLP 3
+#define DFU_EP0_DATA 4
+
+#define USB_DFU_CAN_DOWNLOAD (1 << 0)
+#define USB_DFU_CAN_UPLOAD (1 << 1)
+#define USB_DFU_MANIFEST_TOL (1 << 2)
+#define USB_DFU_WILL_DETACH (1 << 3)
+
+PRE_PACK struct POST_PACK _USB_DFU_FUNC_DESCRIPTOR {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bmAttributes;
+ uint16_t wDetachTimeOut;
+ uint16_t wTransferSize;
+ uint16_t bcdDFUVersion;
+};
+typedef struct _USB_DFU_FUNC_DESCRIPTOR USB_DFU_FUNC_DESCRIPTOR;
+
+PRE_PACK struct POST_PACK _DFU_STATUS {
+ uint8_t bStatus;
+ uint8_t bwPollTimeout[3];
+ uint8_t bState;
+ uint8_t iString;
+};
+typedef struct _DFU_STATUS DFU_STATUS_T;
+
+#define DFU_FUNC_DESC_SIZE sizeof(USB_DFU_FUNC_DESCRIPTOR)
+#define DFU_GET_STATUS_SIZE 0x6
+
+
+#endif /* __MW_USBD_DFU_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_dfuuser.h b/source/lpc_chip_11u6x/inc/usbd/usbd_dfuuser.h
new file mode 100644
index 0000000..1477aa1
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_dfuuser.h
@@ -0,0 +1,270 @@
+/***********************************************************************
+* $Id:: mw_usbd_dfuuser.h 331 2012-08-09 18:54:34Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* Device Firmware Upgrade Class Custom User Module Definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+
+#ifndef __DFUUSER_H__
+#define __DFUUSER_H__
+
+#include "usbd.h"
+#include "usbd_dfu.h"
+#include "usbd_core.h"
+
+/** \file
+ * \brief Device Firmware Upgrade (DFU) API structures and function prototypes.
+ *
+ * Definition of functions exported by ROM based DFU function driver.
+ *
+ */
+
+
+/** \ingroup Group_USBD
+ * @defgroup USBD_DFU Device Firmware Upgrade (DFU) Class Function Driver
+ * \section Sec_MSCModDescription Module Description
+ * DFU Class Function Driver module. This module contains an internal implementation of the USB DFU Class.
+ * User applications can use this class driver instead of implementing the DFU class manually
+ * via the low-level USBD_HW and USBD_Core APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Devices using the USB DFU Class.
+ */
+
+/** \brief USB descriptors data structure.
+ * \ingroup USBD_DFU
+ *
+ * \details This module exposes functions which interact directly with USB device stack's core layer.
+ * The application layer uses this component when it has to implement custom class function driver or
+ * standard class function driver which is not part of the current USB device stack.
+ * The functions exposed by this interface are to register class specific EP0 handlers and corresponding
+ * utility functions to manipulate EP0 state machine of the stack. This interface also exposes
+ * function to register custom endpoint interrupt handler.
+ *
+ */
+typedef struct USBD_DFU_INIT_PARAM
+{
+ /* memory allocation params */
+ uint32_t mem_base; /**< Base memory location from where the stack can allocate
+ data and buffers. \note The memory address set in this field
+ should be accessible by USB DMA controller. Also this value
+ should be aligned on 4 byte boundary.
+ */
+ uint32_t mem_size; /**< The size of memory buffer which stack can use.
+ \note The \em mem_size should be greater than the size
+ returned by USBD_DFU_API::GetMemSize() routine.*/
+ /* DFU paramas */
+ uint16_t wTransferSize; /**< DFU transfer block size in number of bytes.
+ This value should match the value set in DFU descriptor
+ provided as part of the descriptor array
+ (\em high_speed_desc) passed to Init() through
+ \ref USB_CORE_DESCS_T structure. */
+
+ uint16_t pad;
+ /** Pointer to the DFU interface descriptor within the descriptor
+ * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T
+ * structure.
+ */
+ uint8_t* intf_desc;
+ /* user defined functions */
+ /**
+ * DFU Write callback function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a write command. For application using zero-copy buffer scheme
+ * this function is called for the first time with \em length parameter set to 0.
+ * The application code should update the buffer pointer.
+ *
+ * \param[in] block_num Destination start address.
+ * \param[in, out] src Pointer to a pointer to the source of data. Pointer-to-pointer
+ * is used to implement zero-copy buffers. See \ref USBD_ZeroCopy
+ * for more details on zero-copy concept.
+ * \param[out] bwPollTimeout Pointer to a 3 byte buffer which the callback implementer
+ * should fill with the amount of minimum time, in milliseconds,
+ * that the host should wait before sending a subsequent
+ * DFU_GETSTATUS request.
+ * \param[in] length Number of bytes to be written.
+ * \return Returns DFU_STATUS_ values defined in mw_usbd_dfu.h.
+ *
+ */
+ uint8_t (*DFU_Write)( uint32_t block_num, uint8_t** src, uint32_t length, uint8_t* bwPollTimeout);
+
+ /**
+ * DFU Read callback function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a read command.
+ *
+ * \param[in] block_num Destination start address.
+ * \param[in, out] dst Pointer to a pointer to the source of data. Pointer-to-pointer
+ * is used to implement zero-copy buffers. See \ref USBD_ZeroCopy
+ * for more details on zero-copy concept.
+ * \param[in] length Amount of data copied to destination buffer.
+ * \return Returns
+ * - DFU_STATUS_ values defined in mw_usbd_dfu.h to return error conditions.
+ * - 0 if there is no more data to be read. Stack will send EOF frame and set
+ * DFU state-machine to dfuIdle state.
+ * - length of the data copied, should be greater than or equal to 16. If the data copied
+ * is less than DFU \em wTransferSize the stack will send EOF frame and
+ * goes to dfuIdle state.
+ *
+ */
+ uint32_t (*DFU_Read)( uint32_t block_num, uint8_t** dst, uint32_t length);
+
+ /**
+ * DFU done callback function.
+ *
+ * This function is provided by the application software. This function gets called
+ * after firmware download completes.
+ *
+ * \return Nothing.
+ *
+ */
+ void (*DFU_Done)(void);
+
+ /**
+ * DFU detach callback function.
+ *
+ * This function is provided by the application software. This function gets called
+ * after USB_REQ_DFU_DETACH is received. Applications which set USB_DFU_WILL_DETACH
+ * bit in DFU descriptor should define this function. As part of this function
+ * application can call Connect() routine to disconnect and then connect back with
+ * host. For application which rely on WinUSB based host application should use this
+ * feature since USB reset can be invoked only by kernel drivers on Windows host.
+ * By implementing this feature host doen't have to issue reset instead the device
+ * has to do it automatically by disconnect and connect procedure.
+ *
+ * \param[in] hUsb Handle DFU control structure.
+ * \return Nothing.
+ *
+ */
+ void (*DFU_Detach)(USBD_HANDLE_T hUsb);
+
+ /**
+ * Optional user override-able function to replace the default DFU class handler.
+ *
+ * The application software could override the default EP0 class handler with their
+ * own by providing the handler function address as this data member of the parameter
+ * structure. Application which like the default handler should set this data member
+ * to zero before calling the USBD_DFU_API::Init().
+ * \n
+ * \note
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*DFU_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event);
+
+} USBD_DFU_INIT_PARAM_T;
+
+
+/** \brief DFU class API functions structure.
+ * \ingroup USBD_DFU
+ *
+ * This module exposes functions which interact directly with USB device controller hardware.
+ *
+ */
+typedef struct USBD_DFU_API
+{
+ /** \fn uint32_t GetMemSize(USBD_DFU_INIT_PARAM_T* param)
+ * Function to determine the memory required by the DFU function driver module.
+ *
+ * This function is called by application layer before calling pUsbApi->dfu->Init(), to allocate memory used
+ * by DFU function driver module. The application should allocate the memory which is accessible by USB
+ * controller/DMA controller.
+ * \note Some memory areas are not accessible by all bus masters.
+ *
+ * \param[in] param Structure containing DFU function driver module initialization parameters.
+ * \return Returns the required memory size in bytes.
+ */
+ uint32_t (*GetMemSize)(USBD_DFU_INIT_PARAM_T* param);
+
+ /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_DFU_INIT_PARAM_T* param)
+ * Function to initialize DFU function driver module.
+ *
+ * This function is called by application layer to initialize DFU function driver module.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in, out] param Structure containing DFU function driver module initialization parameters.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success
+ * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte aligned or smaller than required.
+ * \retval ERR_API_INVALID_PARAM2 Either DFU_Write() or DFU_Done() or DFU_Read() call-backs are not defined.
+ * \retval ERR_USBD_BAD_DESC
+ * - USB_DFU_DESCRIPTOR_TYPE is not defined immediately after
+ * interface descriptor.
+ * - wTransferSize in descriptor doesn't match the value passed
+ * in param->wTransferSize.
+ * - DFU_Detach() is not defined while USB_DFU_WILL_DETACH is set
+ * in DFU descriptor.
+ * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed.
+ */
+ ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_DFU_INIT_PARAM_T* param, uint32_t init_state);
+
+} USBD_DFU_API_T;
+
+/*-----------------------------------------------------------------------------
+ * Private functions & structures prototypes
+ *-----------------------------------------------------------------------------*/
+/** @cond ADVANCED_API */
+
+typedef struct _USBD_DFU_CTRL_T
+{
+ /*ALIGNED(4)*/ DFU_STATUS_T dfu_req_get_status;
+ uint16_t pad;
+ uint8_t dfu_state;
+ uint8_t dfu_status;
+ uint8_t download_done;
+ uint8_t if_num; /* interface number */
+
+ uint8_t* xfr_buf;
+ USB_DFU_FUNC_DESCRIPTOR* dfu_desc;
+
+ USB_CORE_CTRL_T* pUsbCtrl;
+ /* user defined functions */
+ /* return DFU_STATUS_ values defined in mw_usbd_dfu.h */
+ uint8_t (*DFU_Write)( uint32_t block_num, uint8_t** src, uint32_t length, uint8_t* bwPollTimeout);
+ /* return
+ * DFU_STATUS_ : values defined in mw_usbd_dfu.h in case of errors
+ * 0 : If end of memory reached
+ * length : Amount of data copied to destination buffer
+ */
+ uint32_t (*DFU_Read)( uint32_t block_num, uint8_t** dst, uint32_t length);
+ /* callback called after download is finished */
+ void (*DFU_Done)(void);
+ /* callback called after USB_REQ_DFU_DETACH is recived */
+ void (*DFU_Detach)(USBD_HANDLE_T hUsb);
+
+} USBD_DFU_CTRL_T;
+
+/** @cond DIRECT_API */
+uint32_t mwDFU_GetMemSize(USBD_DFU_INIT_PARAM_T* param);
+extern ErrorCode_t mwDFU_init(USBD_HANDLE_T hUsb, USBD_DFU_INIT_PARAM_T* param, uint32_t init_state);
+/** @endcond */
+
+/** @endcond */
+
+#endif /* __DFUUSER_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_hid.h b/source/lpc_chip_11u6x/inc/usbd/usbd_hid.h
new file mode 100644
index 0000000..b1e88cf
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_hid.h
@@ -0,0 +1,430 @@
+/***********************************************************************
+* $Id: mw_usbd_hid.h.rca 1.2 Tue Nov 1 11:45:07 2011 nlv09221 Experimental $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* HID Definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+#ifndef __HID_H__
+#define __HID_H__
+
+#include "usbd.h"
+
+/** \file
+ * \brief Common definitions and declarations for the library USB HID Class driver.
+ *
+ * Common definitions and declarations for the library USB HID Class driver.
+ * \addtogroup USBD_HID
+ * @{
+ */
+
+
+/** HID Subclass Codes
+ * @{
+ */
+/** Descriptor Subclass value indicating that the device or interface does not implement a HID boot protocol. */
+#define HID_SUBCLASS_NONE 0x00
+/** Descriptor Subclass value indicating that the device or interface implements a HID boot protocol. */
+#define HID_SUBCLASS_BOOT 0x01
+/** @} */
+
+/** HID Protocol Codes
+ * @{
+ */
+/** Descriptor Protocol value indicating that the device or interface does not belong to a HID boot protocol. */
+#define HID_PROTOCOL_NONE 0x00
+/** Descriptor Protocol value indicating that the device or interface belongs to the Keyboard HID boot protocol. */
+#define HID_PROTOCOL_KEYBOARD 0x01
+/** Descriptor Protocol value indicating that the device or interface belongs to the Mouse HID boot protocol. */
+#define HID_PROTOCOL_MOUSE 0x02
+/** @} */
+
+
+
+/** Descriptor Types
+ * @{
+ */
+/** Descriptor header type value, to indicate a HID class HID descriptor. */
+#define HID_HID_DESCRIPTOR_TYPE 0x21
+/** Descriptor header type value, to indicate a HID class HID report descriptor. */
+#define HID_REPORT_DESCRIPTOR_TYPE 0x22
+/** Descriptor header type value, to indicate a HID class HID Physical descriptor. */
+#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23
+/** @} */
+
+
+/** \brief HID class-specific HID Descriptor.
+ *
+ * Type define for the HID class-specific HID descriptor, to describe the HID device's specifications. Refer to the HID
+ * specification for details on the structure elements.
+ *
+ */
+PRE_PACK struct POST_PACK _HID_DESCRIPTOR {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of HID descriptor. */
+ uint16_t bcdHID; /**< BCD encoded version that the HID descriptor and device complies to. */
+ uint8_t bCountryCode; /**< Country code of the localized device, or zero if universal. */
+ uint8_t bNumDescriptors; /**< Total number of HID report descriptors for the interface. */
+
+ PRE_PACK struct POST_PACK _HID_DESCRIPTOR_LIST {
+ uint8_t bDescriptorType; /**< Type of HID report. */
+ uint16_t wDescriptorLength; /**< Length of the associated HID report descriptor, in bytes. */
+ } DescriptorList[1]; /**< Array of one or more descriptors */
+} ;
+/** HID class-specific HID Descriptor. */
+typedef struct _HID_DESCRIPTOR HID_DESCRIPTOR;
+
+#define HID_DESC_SIZE sizeof(HID_DESCRIPTOR)
+
+/** HID Request Codes
+ * @{
+ */
+#define HID_REQUEST_GET_REPORT 0x01
+#define HID_REQUEST_GET_IDLE 0x02
+#define HID_REQUEST_GET_PROTOCOL 0x03
+#define HID_REQUEST_SET_REPORT 0x09
+#define HID_REQUEST_SET_IDLE 0x0A
+#define HID_REQUEST_SET_PROTOCOL 0x0B
+/** @} */
+
+/** HID Report Types
+ * @{
+ */
+#define HID_REPORT_INPUT 0x01
+#define HID_REPORT_OUTPUT 0x02
+#define HID_REPORT_FEATURE 0x03
+/** @} */
+
+
+/** Usage Pages
+ * @{
+ */
+#define HID_USAGE_PAGE_UNDEFINED 0x00
+#define HID_USAGE_PAGE_GENERIC 0x01
+#define HID_USAGE_PAGE_SIMULATION 0x02
+#define HID_USAGE_PAGE_VR 0x03
+#define HID_USAGE_PAGE_SPORT 0x04
+#define HID_USAGE_PAGE_GAME 0x05
+#define HID_USAGE_PAGE_DEV_CONTROLS 0x06
+#define HID_USAGE_PAGE_KEYBOARD 0x07
+#define HID_USAGE_PAGE_LED 0x08
+#define HID_USAGE_PAGE_BUTTON 0x09
+#define HID_USAGE_PAGE_ORDINAL 0x0A
+#define HID_USAGE_PAGE_TELEPHONY 0x0B
+#define HID_USAGE_PAGE_CONSUMER 0x0C
+#define HID_USAGE_PAGE_DIGITIZER 0x0D
+#define HID_USAGE_PAGE_UNICODE 0x10
+#define HID_USAGE_PAGE_ALPHANUMERIC 0x14
+/** @} */
+
+
+/** Generic Desktop Page (0x01)
+ * @{
+ */
+#define HID_USAGE_GENERIC_POINTER 0x01
+#define HID_USAGE_GENERIC_MOUSE 0x02
+#define HID_USAGE_GENERIC_JOYSTICK 0x04
+#define HID_USAGE_GENERIC_GAMEPAD 0x05
+#define HID_USAGE_GENERIC_KEYBOARD 0x06
+#define HID_USAGE_GENERIC_KEYPAD 0x07
+#define HID_USAGE_GENERIC_X 0x30
+#define HID_USAGE_GENERIC_Y 0x31
+#define HID_USAGE_GENERIC_Z 0x32
+#define HID_USAGE_GENERIC_RX 0x33
+#define HID_USAGE_GENERIC_RY 0x34
+#define HID_USAGE_GENERIC_RZ 0x35
+#define HID_USAGE_GENERIC_SLIDER 0x36
+#define HID_USAGE_GENERIC_DIAL 0x37
+#define HID_USAGE_GENERIC_WHEEL 0x38
+#define HID_USAGE_GENERIC_HATSWITCH 0x39
+#define HID_USAGE_GENERIC_COUNTED_BUFFER 0x3A
+#define HID_USAGE_GENERIC_BYTE_COUNT 0x3B
+#define HID_USAGE_GENERIC_MOTION_WAKEUP 0x3C
+#define HID_USAGE_GENERIC_VX 0x40
+#define HID_USAGE_GENERIC_VY 0x41
+#define HID_USAGE_GENERIC_VZ 0x42
+#define HID_USAGE_GENERIC_VBRX 0x43
+#define HID_USAGE_GENERIC_VBRY 0x44
+#define HID_USAGE_GENERIC_VBRZ 0x45
+#define HID_USAGE_GENERIC_VNO 0x46
+#define HID_USAGE_GENERIC_SYSTEM_CTL 0x80
+#define HID_USAGE_GENERIC_SYSCTL_POWER 0x81
+#define HID_USAGE_GENERIC_SYSCTL_SLEEP 0x82
+#define HID_USAGE_GENERIC_SYSCTL_WAKE 0x83
+#define HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU 0x84
+#define HID_USAGE_GENERIC_SYSCTL_MAIN_MENU 0x85
+#define HID_USAGE_GENERIC_SYSCTL_APP_MENU 0x86
+#define HID_USAGE_GENERIC_SYSCTL_HELP_MENU 0x87
+#define HID_USAGE_GENERIC_SYSCTL_MENU_EXIT 0x88
+#define HID_USAGE_GENERIC_SYSCTL_MENU_SELECT 0x89
+#define HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT 0x8A
+#define HID_USAGE_GENERIC_SYSCTL_MENU_LEFT 0x8B
+#define HID_USAGE_GENERIC_SYSCTL_MENU_UP 0x8C
+#define HID_USAGE_GENERIC_SYSCTL_MENU_DOWN 0x8D
+/** @} */
+
+/** Simulation Controls Page (0x02)
+ * @{
+ */
+#define HID_USAGE_SIMULATION_RUDDER 0xBA
+#define HID_USAGE_SIMULATION_THROTTLE 0xBB
+/** @} */
+
+/* Virtual Reality Controls Page (0x03) */
+/* ... */
+
+/* Sport Controls Page (0x04) */
+/* ... */
+
+/* Game Controls Page (0x05) */
+/* ... */
+
+/* Generic Device Controls Page (0x06) */
+/* ... */
+
+/** Keyboard/Keypad Page (0x07)
+ * @{
+ */
+/** Error "keys" */
+#define HID_USAGE_KEYBOARD_NOEVENT 0x00
+#define HID_USAGE_KEYBOARD_ROLLOVER 0x01
+#define HID_USAGE_KEYBOARD_POSTFAIL 0x02
+#define HID_USAGE_KEYBOARD_UNDEFINED 0x03
+
+/** Letters */
+#define HID_USAGE_KEYBOARD_aA 0x04
+#define HID_USAGE_KEYBOARD_zZ 0x1D
+
+/** Numbers */
+#define HID_USAGE_KEYBOARD_ONE 0x1E
+#define HID_USAGE_KEYBOARD_ZERO 0x27
+
+#define HID_USAGE_KEYBOARD_RETURN 0x28
+#define HID_USAGE_KEYBOARD_ESCAPE 0x29
+#define HID_USAGE_KEYBOARD_DELETE 0x2A
+
+/** Funtion keys */
+#define HID_USAGE_KEYBOARD_F1 0x3A
+#define HID_USAGE_KEYBOARD_F12 0x45
+
+#define HID_USAGE_KEYBOARD_PRINT_SCREEN 0x46
+
+/** Modifier Keys */
+#define HID_USAGE_KEYBOARD_LCTRL 0xE0
+#define HID_USAGE_KEYBOARD_LSHFT 0xE1
+#define HID_USAGE_KEYBOARD_LALT 0xE2
+#define HID_USAGE_KEYBOARD_LGUI 0xE3
+#define HID_USAGE_KEYBOARD_RCTRL 0xE4
+#define HID_USAGE_KEYBOARD_RSHFT 0xE5
+#define HID_USAGE_KEYBOARD_RALT 0xE6
+#define HID_USAGE_KEYBOARD_RGUI 0xE7
+#define HID_USAGE_KEYBOARD_SCROLL_LOCK 0x47
+#define HID_USAGE_KEYBOARD_NUM_LOCK 0x53
+#define HID_USAGE_KEYBOARD_CAPS_LOCK 0x39
+/** @} */
+
+/* ... */
+
+/** LED Page (0x08)
+ * @{
+ */
+#define HID_USAGE_LED_NUM_LOCK 0x01
+#define HID_USAGE_LED_CAPS_LOCK 0x02
+#define HID_USAGE_LED_SCROLL_LOCK 0x03
+#define HID_USAGE_LED_COMPOSE 0x04
+#define HID_USAGE_LED_KANA 0x05
+#define HID_USAGE_LED_POWER 0x06
+#define HID_USAGE_LED_SHIFT 0x07
+#define HID_USAGE_LED_DO_NOT_DISTURB 0x08
+#define HID_USAGE_LED_MUTE 0x09
+#define HID_USAGE_LED_TONE_ENABLE 0x0A
+#define HID_USAGE_LED_HIGH_CUT_FILTER 0x0B
+#define HID_USAGE_LED_LOW_CUT_FILTER 0x0C
+#define HID_USAGE_LED_EQUALIZER_ENABLE 0x0D
+#define HID_USAGE_LED_SOUND_FIELD_ON 0x0E
+#define HID_USAGE_LED_SURROUND_FIELD_ON 0x0F
+#define HID_USAGE_LED_REPEAT 0x10
+#define HID_USAGE_LED_STEREO 0x11
+#define HID_USAGE_LED_SAMPLING_RATE_DETECT 0x12
+#define HID_USAGE_LED_SPINNING 0x13
+#define HID_USAGE_LED_CAV 0x14
+#define HID_USAGE_LED_CLV 0x15
+#define HID_USAGE_LED_RECORDING_FORMAT_DET 0x16
+#define HID_USAGE_LED_OFF_HOOK 0x17
+#define HID_USAGE_LED_RING 0x18
+#define HID_USAGE_LED_MESSAGE_WAITING 0x19
+#define HID_USAGE_LED_DATA_MODE 0x1A
+#define HID_USAGE_LED_BATTERY_OPERATION 0x1B
+#define HID_USAGE_LED_BATTERY_OK 0x1C
+#define HID_USAGE_LED_BATTERY_LOW 0x1D
+#define HID_USAGE_LED_SPEAKER 0x1E
+#define HID_USAGE_LED_HEAD_SET 0x1F
+#define HID_USAGE_LED_HOLD 0x20
+#define HID_USAGE_LED_MICROPHONE 0x21
+#define HID_USAGE_LED_COVERAGE 0x22
+#define HID_USAGE_LED_NIGHT_MODE 0x23
+#define HID_USAGE_LED_SEND_CALLS 0x24
+#define HID_USAGE_LED_CALL_PICKUP 0x25
+#define HID_USAGE_LED_CONFERENCE 0x26
+#define HID_USAGE_LED_STAND_BY 0x27
+#define HID_USAGE_LED_CAMERA_ON 0x28
+#define HID_USAGE_LED_CAMERA_OFF 0x29
+#define HID_USAGE_LED_ON_LINE 0x2A
+#define HID_USAGE_LED_OFF_LINE 0x2B
+#define HID_USAGE_LED_BUSY 0x2C
+#define HID_USAGE_LED_READY 0x2D
+#define HID_USAGE_LED_PAPER_OUT 0x2E
+#define HID_USAGE_LED_PAPER_JAM 0x2F
+#define HID_USAGE_LED_REMOTE 0x30
+#define HID_USAGE_LED_FORWARD 0x31
+#define HID_USAGE_LED_REVERSE 0x32
+#define HID_USAGE_LED_STOP 0x33
+#define HID_USAGE_LED_REWIND 0x34
+#define HID_USAGE_LED_FAST_FORWARD 0x35
+#define HID_USAGE_LED_PLAY 0x36
+#define HID_USAGE_LED_PAUSE 0x37
+#define HID_USAGE_LED_RECORD 0x38
+#define HID_USAGE_LED_ERROR 0x39
+#define HID_USAGE_LED_SELECTED_INDICATOR 0x3A
+#define HID_USAGE_LED_IN_USE_INDICATOR 0x3B
+#define HID_USAGE_LED_MULTI_MODE_INDICATOR 0x3C
+#define HID_USAGE_LED_INDICATOR_ON 0x3D
+#define HID_USAGE_LED_INDICATOR_FLASH 0x3E
+#define HID_USAGE_LED_INDICATOR_SLOW_BLINK 0x3F
+#define HID_USAGE_LED_INDICATOR_FAST_BLINK 0x40
+#define HID_USAGE_LED_INDICATOR_OFF 0x41
+#define HID_USAGE_LED_FLASH_ON_TIME 0x42
+#define HID_USAGE_LED_SLOW_BLINK_ON_TIME 0x43
+#define HID_USAGE_LED_SLOW_BLINK_OFF_TIME 0x44
+#define HID_USAGE_LED_FAST_BLINK_ON_TIME 0x45
+#define HID_USAGE_LED_FAST_BLINK_OFF_TIME 0x46
+#define HID_USAGE_LED_INDICATOR_COLOR 0x47
+#define HID_USAGE_LED_RED 0x48
+#define HID_USAGE_LED_GREEN 0x49
+#define HID_USAGE_LED_AMBER 0x4A
+#define HID_USAGE_LED_GENERIC_INDICATOR 0x4B
+/** @} */
+
+/* Button Page (0x09)
+ */
+/* There is no need to label these usages. */
+
+/* Ordinal Page (0x0A)
+ */
+/* There is no need to label these usages. */
+
+/** Telephony Device Page (0x0B)
+ * @{
+ */
+#define HID_USAGE_TELEPHONY_PHONE 0x01
+#define HID_USAGE_TELEPHONY_ANSWERING_MACHINE 0x02
+#define HID_USAGE_TELEPHONY_MESSAGE_CONTROLS 0x03
+#define HID_USAGE_TELEPHONY_HANDSET 0x04
+#define HID_USAGE_TELEPHONY_HEADSET 0x05
+#define HID_USAGE_TELEPHONY_KEYPAD 0x06
+#define HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON 0x07
+/** @} */
+/* ... */
+
+/** Consumer Page (0x0C)
+ * @{
+ */
+#define HID_USAGE_CONSUMER_CONTROL 0x01
+#define HID_USAGE_CONSUMER_FAST_FORWARD 0xB3
+#define HID_USAGE_CONSUMER_REWIND 0xB4
+#define HID_USAGE_CONSUMER_PLAY_PAUSE 0xCD
+#define HID_USAGE_CONSUMER_VOLUME_INCREMENT 0xE9
+#define HID_USAGE_CONSUMER_VOLUME_DECREMENT 0xEA
+/** @} */
+/* ... */
+
+/* and others ... */
+
+
+/** HID Report Item Macros
+ * @{
+ */
+/** Main Items */
+#define HID_Input(x) 0x81,x
+#define HID_Output(x) 0x91,x
+#define HID_Feature(x) 0xB1,x
+#define HID_Collection(x) 0xA1,x
+#define HID_EndCollection 0xC0
+
+/** Data (Input, Output, Feature) */
+#define HID_Data 0<<0
+#define HID_Constant 1<<0
+#define HID_Array 0<<1
+#define HID_Variable 1<<1
+#define HID_Absolute 0<<2
+#define HID_Relative 1<<2
+#define HID_NoWrap 0<<3
+#define HID_Wrap 1<<3
+#define HID_Linear 0<<4
+#define HID_NonLinear 1<<4
+#define HID_PreferredState 0<<5
+#define HID_NoPreferred 1<<5
+#define HID_NoNullPosition 0<<6
+#define HID_NullState 1<<6
+#define HID_NonVolatile 0<<7
+#define HID_Volatile 1<<7
+
+/** Collection Data */
+#define HID_Physical 0x00
+#define HID_Application 0x01
+#define HID_Logical 0x02
+#define HID_Report 0x03
+#define HID_NamedArray 0x04
+#define HID_UsageSwitch 0x05
+#define HID_UsageModifier 0x06
+
+/** Global Items */
+#define HID_UsagePage(x) 0x05,x
+#define HID_UsagePageVendor(x) 0x06,x,0xFF
+#define HID_LogicalMin(x) 0x15,x
+#define HID_LogicalMinS(x) 0x16,(x&0xFF),((x>>8)&0xFF)
+#define HID_LogicalMinL(x) 0x17,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF)
+#define HID_LogicalMax(x) 0x25,x
+#define HID_LogicalMaxS(x) 0x26,(x&0xFF),((x>>8)&0xFF)
+#define HID_LogicalMaxL(x) 0x27,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF)
+#define HID_PhysicalMin(x) 0x35,x
+#define HID_PhysicalMinS(x) 0x36,(x&0xFF),((x>>8)&0xFF)
+#define HID_PhysicalMinL(x) 0x37,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF)
+#define HID_PhysicalMax(x) 0x45,x
+#define HID_PhysicalMaxS(x) 0x46,(x&0xFF),((x>>8)&0xFF)
+#define HID_PhysicalMaxL(x) 0x47,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF)
+#define HID_UnitExponent(x) 0x55,x
+#define HID_Unit(x) 0x65,x
+#define HID_UnitS(x) 0x66,(x&0xFF),((x>>8)&0xFF)
+#define HID_UnitL(x) 0x67,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF)
+#define HID_ReportSize(x) 0x75,x
+#define HID_ReportID(x) 0x85,x
+#define HID_ReportCount(x) 0x95,x
+#define HID_Push 0xA0
+#define HID_Pop 0xB0
+
+/** Local Items */
+#define HID_Usage(x) 0x09,x
+#define HID_UsageMin(x) 0x19,x
+#define HID_UsageMax(x) 0x29,x
+/** @} */
+
+/** @} */
+
+#endif /* __HID_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_hiduser.h b/source/lpc_chip_11u6x/inc/usbd/usbd_hiduser.h
new file mode 100644
index 0000000..77a1554
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_hiduser.h
@@ -0,0 +1,421 @@
+/***********************************************************************
+* $Id:: mw_usbd_hiduser.h 331 2012-08-09 18:54:34Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* HID Custom User Module Definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+
+#ifndef __HIDUSER_H__
+#define __HIDUSER_H__
+
+#include "usbd.h"
+#include "usbd_hid.h"
+#include "usbd_core.h"
+
+/** \file
+ * \brief Human Interface Device (HID) API structures and function prototypes.
+ *
+ * Definition of functions exported by ROM based HID function driver.
+ *
+ */
+
+/** \ingroup Group_USBD
+ * @defgroup USBD_HID HID Class Function Driver
+ * \section Sec_HIDModDescription Module Description
+ * HID Class Function Driver module. This module contains an internal implementation of the USB HID Class.
+ * User applications can use this class driver instead of implementing the HID class manually
+ * via the low-level HW and core APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Devices using the USB HID Class.
+ */
+
+/** \brief HID report descriptor data structure.
+ * \ingroup USBD_HID
+ *
+ * \details This structure is used as part of HID function driver initialization
+ * parameter structure \ref USBD_HID_INIT_PARAM. This structure contains
+ * details of a report type supported by the application. An application
+ * can support multiple report types as a single HID device. The application
+ * should define this report type data structure per report it supports and
+ * the array of report types to USBD_HID_API::init() through \ref USBD_HID_INIT_PARAM
+ * structure.
+ *
+ * \note All descriptor pointers assigned in this structure should be on 4 byte
+ * aligned address boundary.
+ *
+ */
+typedef struct _HID_REPORT_T {
+ uint16_t len; /**< Size of the report descriptor in bytes. */
+ uint8_t idle_time; /**< This value is used by stack to respond to Set_Idle &
+ GET_Idle requests for the specified report ID. The value
+ of this field specified the rate at which duplicate reports
+ are generated for the specified Report ID. For example, a
+ device with two input reports could specify an idle rate of
+ 20 milliseconds for report ID 1 and 500 milliseconds for
+ report ID 2.
+ */
+ uint8_t __pad; /**< Padding space. */
+ uint8_t* desc; /**< Report descriptor. */
+} USB_HID_REPORT_T;
+
+/** \brief USB descriptors data structure.
+ * \ingroup USBD_HID
+ *
+ * \details This module exposes functions which interact directly with USB device stack's core layer.
+ * The application layer uses this component when it has to implement custom class function driver or
+ * standard class function driver which is not part of the current USB device stack.
+ * The functions exposed by this interface are to register class specific EP0 handlers and corresponding
+ * utility functions to manipulate EP0 state machine of the stack. This interface also exposes
+ * function to register custom endpoint interrupt handler.
+ *
+ */
+typedef struct USBD_HID_INIT_PARAM
+{
+ /* memory allocation params */
+ uint32_t mem_base; /**< Base memory location from where the stack can allocate
+ data and buffers. \note The memory address set in this field
+ should be accessible by USB DMA controller. Also this value
+ should be aligned on 4 byte boundary.
+ */
+ uint32_t mem_size; /**< The size of memory buffer which stack can use.
+ \note The \em mem_size should be greater than the size
+ returned by USBD_HID_API::GetMemSize() routine.*/
+ /* HID paramas */
+ uint8_t max_reports; /**< Number of HID reports supported by this instance
+ of HID class driver.
+ */
+ uint8_t pad[3];
+ uint8_t* intf_desc; /**< Pointer to the HID interface descriptor within the
+ descriptor array (\em high_speed_desc) passed to Init()
+ through \ref USB_CORE_DESCS_T structure.
+ */
+ USB_HID_REPORT_T* report_data; /**< Pointer to an array of HID report descriptor
+ data structure (\ref USB_HID_REPORT_T). The number
+ of elements in the array should be same a \em max_reports
+ value. The stack uses this array to respond to
+ requests received for various HID report descriptor
+ information. \note This array should be of global scope.
+ */
+
+ /* user defined functions */
+ /* required functions */
+ /**
+ * HID get report callback function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a HID_REQUEST_GET_REPORT request. The setup packet data (\em pSetup)
+ * is passed to the callback so that application can extract the report ID, report
+ * type and other information need to generate the report. \note HID reports are sent
+ * via interrupt IN endpoint also. This function is called only when report request
+ * is received on control endpoint. Application should implement \em HID_EpIn_Hdlr to
+ * send reports to host via interrupt IN endpoint.
+ *
+ *
+ * \param[in] hHid Handle to HID function driver.
+ * \param[in] pSetup Pointer to setup packet received from host.
+ * \param[in, out] pBuffer Pointer to a pointer of data buffer containing report data.
+ * Pointer-to-pointer is used to implement zero-copy buffers.
+ * See \ref USBD_ZeroCopy for more details on zero-copy concept.
+ * \param[in] length Amount of data copied to destination buffer.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*HID_GetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length);
+
+ /**
+ * HID set report callback function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a HID_REQUEST_SET_REPORT request. The setup packet data (\em pSetup)
+ * is passed to the callback so that application can extract the report ID, report
+ * type and other information need to modify the report. An application might choose
+ * to ignore input Set_Report requests as meaningless. Alternatively these reports
+ * could be used to reset the origin of a control (that is, current position should
+ * report zero).
+ *
+ * \param[in] hHid Handle to HID function driver.
+ * \param[in] pSetup Pointer to setup packet received from host.
+ * \param[in, out] pBuffer Pointer to a pointer of data buffer containing report data.
+ * Pointer-to-pointer is used to implement zero-copy buffers.
+ * See \ref USBD_ZeroCopy for more details on zero-copy concept.
+ * \param[in] length Amount of data copied to destination buffer.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*HID_SetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length);
+
+ /* optional functions */
+
+ /**
+ * Optional callback function to handle HID_GetPhysDesc request.
+ *
+ * The application software could provide this callback HID_GetPhysDesc handler to
+ * handle get physical descriptor requests sent by the host. When host requests
+ * Physical Descriptor set 0, application should return a special descriptor
+ * identifying the number of descriptor sets and their sizes. A Get_Descriptor
+ * request with the Physical Index equal to 1 should return the first Physical
+ * Descriptor set. A device could possibly have alternate uses for its items.
+ * These can be enumerated by issuing subsequent Get_Descriptor requests while
+ * incrementing the Descriptor Index. A device should return the last descriptor
+ * set to requests with an index greater than the last number defined in the HID
+ * descriptor.
+ * \note Applications which don't have physical descriptor should set this data member
+ * to zero before calling the USBD_HID_API::Init().
+ * \n
+ *
+ * \param[in] hHid Handle to HID function driver.
+ * \param[in] pSetup Pointer to setup packet received from host.
+ * \param[in] pBuf Pointer to a pointer of data buffer containing physical descriptor
+ * data. If the physical descriptor is in USB accessible memory area
+ * application could just update the pointer or else it should copy
+ * the descriptor to the address pointed by this pointer.
+ * \param[in] length Amount of data copied to destination buffer or descriptor length.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*HID_GetPhysDesc)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length);
+
+ /**
+ * Optional callback function to handle HID_REQUEST_SET_IDLE request.
+ *
+ * The application software could provide this callback to handle HID_REQUEST_SET_IDLE
+ * requests sent by the host. This callback is provided to applications to adjust
+ * timers associated with various reports, which are sent to host over interrupt
+ * endpoint. The setup packet data (\em pSetup) is passed to the callback so that
+ * application can extract the report ID, report type and other information need
+ * to modify the report's idle time.
+ * \note Applications which don't send reports on Interrupt endpoint or don't
+ * have idle time between reports should set this data member to zero before
+ * calling the USBD_HID_API::Init().
+ * \n
+ *
+ * \param[in] hHid Handle to HID function driver.
+ * \param[in] pSetup Pointer to setup packet received from host.
+ * \param[in] idleTime Idle time to be set for the specified report.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*HID_SetIdle)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t idleTime);
+
+ /**
+ * Optional callback function to handle HID_REQUEST_SET_PROTOCOL request.
+ *
+ * The application software could provide this callback to handle HID_REQUEST_SET_PROTOCOL
+ * requests sent by the host. This callback is provided to applications to adjust
+ * modes of their code between boot mode and report mode.
+ * \note Applications which don't support protocol modes should set this data member
+ * to zero before calling the USBD_HID_API::Init().
+ * \n
+ *
+ * \param[in] hHid Handle to HID function driver.
+ * \param[in] pSetup Pointer to setup packet received from host.
+ * \param[in] protocol Protocol mode.
+ * 0 = Boot Protocol
+ * 1 = Report Protocol
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*HID_SetProtocol)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t protocol);
+
+ /**
+ * Optional Interrupt IN endpoint event handler.
+ *
+ * The application software could provide Interrupt IN endpoint event handler.
+ * Application which send reports to host on interrupt endpoint should provide
+ * an endpoint event handler through this data member. This data member is
+ * ignored if the interface descriptor \em intf_desc doesn't have any IN interrupt
+ * endpoint descriptor associated.
+ * \n
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Handle to HID function driver.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should return \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*HID_EpIn_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event);
+ /**
+ * Optional Interrupt OUT endpoint event handler.
+ *
+ * The application software could provide Interrupt OUT endpoint event handler.
+ * Application which receives reports from host on interrupt endpoint should provide
+ * an endpoint event handler through this data member. This data member is
+ * ignored if the interface descriptor \em intf_desc doesn't have any OUT interrupt
+ * endpoint descriptor associated.
+ * \n
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Handle to HID function driver.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should return \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*HID_EpOut_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event);
+
+ /* user override-able function */
+ /**
+ * Optional user override-able function to replace the default HID_GetReportDesc handler.
+ *
+ * The application software could override the default HID_GetReportDesc handler with their
+ * own by providing the handler function address as this data member of the parameter
+ * structure. Application which like the default handler should set this data member
+ * to zero before calling the USBD_HID_API::Init() and also provide report data array
+ * \em report_data field.
+ * \n
+ * \note
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*HID_GetReportDesc)(USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length);
+ /**
+ * Optional user override-able function to replace the default HID class handler.
+ *
+ * The application software could override the default EP0 class handler with their
+ * own by providing the handler function address as this data member of the parameter
+ * structure. Application which like the default handler should set this data member
+ * to zero before calling the USBD_HID_API::Init().
+ * \n
+ * \note
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*HID_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event);
+
+} USBD_HID_INIT_PARAM_T;
+
+/** \brief HID class API functions structure.
+ * \ingroup USBD_HID
+ *
+ * This structure contains pointers to all the function exposed by HID function driver module.
+ *
+ */
+typedef struct USBD_HID_API
+{
+ /** \fn uint32_t GetMemSize(USBD_HID_INIT_PARAM_T* param)
+ * Function to determine the memory required by the HID function driver module.
+ *
+ * This function is called by application layer before calling pUsbApi->hid->Init(), to allocate memory used
+ * by HID function driver module. The application should allocate the memory which is accessible by USB
+ * controller/DMA controller.
+ * \note Some memory areas are not accessible by all bus masters.
+ *
+ * \param[in] param Structure containing HID function driver module initialization parameters.
+ * \return Returns the required memory size in bytes.
+ */
+ uint32_t (*GetMemSize)(USBD_HID_INIT_PARAM_T* param);
+
+ /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_HID_INIT_PARAM_T* param)
+ * Function to initialize HID function driver module.
+ *
+ * This function is called by application layer to initialize HID function driver
+ * module. On successful initialization the function returns a handle to HID
+ * function driver module in passed param structure.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in, out] param Structure containing HID function driver module
+ * initialization parameters.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success
+ * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte
+ * aligned or smaller than required.
+ * \retval ERR_API_INVALID_PARAM2 Either HID_GetReport() or HID_SetReport()
+ * callback are not defined.
+ * \retval ERR_USBD_BAD_DESC HID_HID_DESCRIPTOR_TYPE is not defined
+ * immediately after interface descriptor.
+ * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed.
+ * \retval ERR_USBD_BAD_EP_DESC Wrong endpoint descriptor is passed.
+ */
+ ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_HID_INIT_PARAM_T* param);
+
+} USBD_HID_API_T;
+
+/*-----------------------------------------------------------------------------
+ * Private functions & structures prototypes
+ *-----------------------------------------------------------------------------*/
+/** @cond ADVANCED_API */
+
+typedef struct _HID_CTRL_T {
+ /* pointer to controller */
+ USB_CORE_CTRL_T* pUsbCtrl;
+ /* descriptor pointers */
+ uint8_t* hid_desc;
+ USB_HID_REPORT_T* report_data;
+
+ uint8_t protocol;
+ uint8_t if_num; /* interface number */
+ uint8_t epin_adr; /* IN interrupt endpoint */
+ uint8_t epout_adr; /* OUT interrupt endpoint */
+
+ /* user defined functions */
+ ErrorCode_t (*HID_GetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length);
+ ErrorCode_t (*HID_SetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length);
+ ErrorCode_t (*HID_GetPhysDesc)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length);
+ ErrorCode_t (*HID_SetIdle)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t idleTime);
+ ErrorCode_t (*HID_SetProtocol)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t protocol);
+
+ /* virtual overridable functions */
+ ErrorCode_t (*HID_GetReportDesc)(USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length);
+
+}USB_HID_CTRL_T;
+
+/** @cond DIRECT_API */
+extern uint32_t mwHID_GetMemSize(USBD_HID_INIT_PARAM_T* param);
+extern ErrorCode_t mwHID_init(USBD_HANDLE_T hUsb, USBD_HID_INIT_PARAM_T* param);
+/** @endcond */
+
+/** @endcond */
+
+#endif /* __HIDUSER_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_hw.h b/source/lpc_chip_11u6x/inc/usbd/usbd_hw.h
new file mode 100644
index 0000000..e34485c
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_hw.h
@@ -0,0 +1,457 @@
+/***********************************************************************
+* $Id:: mw_usbd_hw.h 331 2012-08-09 18:54:34Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* USB Hardware Function prototypes.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+#ifndef __USBHW_H__
+#define __USBHW_H__
+
+#include "error.h"
+#include "usbd.h"
+#include "usbd_core.h"
+
+/** \file
+ * \brief USB Hardware Function prototypes.
+ *
+ * Definition of functions exported by ROM based Device Controller Driver (DCD).
+ *
+ */
+
+/** \ingroup Group_USBD
+ * @defgroup USBD_HW USB Device Controller Driver
+ * \section Sec_HWModDescription Module Description
+ * The Device Controller Driver Layer implements the routines to deal directly with the hardware.
+ */
+
+/** \ingroup USBD_HW
+* USB Endpoint/class handler Callback Events.
+*
+*/
+enum USBD_EVENT_T {
+ USB_EVT_SETUP =1, /**< 1 Setup Packet received */
+ USB_EVT_OUT, /**< 2 OUT Packet received */
+ USB_EVT_IN, /**< 3 IN Packet sent */
+ USB_EVT_OUT_NAK, /**< 4 OUT Packet - Not Acknowledged */
+ USB_EVT_IN_NAK, /**< 5 IN Packet - Not Acknowledged */
+ USB_EVT_OUT_STALL, /**< 6 OUT Packet - Stalled */
+ USB_EVT_IN_STALL, /**< 7 IN Packet - Stalled */
+ USB_EVT_OUT_DMA_EOT, /**< 8 DMA OUT EP - End of Transfer */
+ USB_EVT_IN_DMA_EOT, /**< 9 DMA IN EP - End of Transfer */
+ USB_EVT_OUT_DMA_NDR, /**< 10 DMA OUT EP - New Descriptor Request */
+ USB_EVT_IN_DMA_NDR, /**< 11 DMA IN EP - New Descriptor Request */
+ USB_EVT_OUT_DMA_ERR, /**< 12 DMA OUT EP - Error */
+ USB_EVT_IN_DMA_ERR, /**< 13 DMA IN EP - Error */
+ USB_EVT_RESET, /**< 14 Reset event recieved */
+ USB_EVT_SOF, /**< 15 Start of Frame event */
+ USB_EVT_DEV_STATE, /**< 16 Device status events */
+ USB_EVT_DEV_ERROR /**< 17 Device error events */
+};
+
+/**
+ * \brief Hardware API functions structure.
+ * \ingroup USBD_HW
+ *
+ * This module exposes functions which interact directly with USB device controller hardware.
+ *
+ */
+typedef struct USBD_HW_API
+{
+ /** \fn uint32_t GetMemSize(USBD_API_INIT_PARAM_T* param)
+ * Function to determine the memory required by the USB device stack's DCD and core layers.
+ *
+ * This function is called by application layer before calling pUsbApi->hw->Init(), to allocate memory used
+ * by DCD and core layers. The application should allocate the memory which is accessible by USB
+ * controller/DMA controller.
+ * \note Some memory areas are not accessible by all bus masters.
+ *
+ * \param[in] param Structure containing USB device stack initialization parameters.
+ * \return Returns the required memory size in bytes.
+ */
+ uint32_t (*GetMemSize)(USBD_API_INIT_PARAM_T* param);
+
+ /** \fn ErrorCode_t Init(USBD_HANDLE_T* phUsb, USB_CORE_DESCS_T* pDesc, USBD_API_INIT_PARAM_T* param)
+ * Function to initialize USB device stack's DCD and core layers.
+ *
+ * This function is called by application layer to initialize USB hardware and core layers.
+ * On successful initialization the function returns a handle to USB device stack which should
+ * be passed to the rest of the functions.
+ *
+ * \param[in,out] phUsb Pointer to the USB device stack handle of type USBD_HANDLE_T.
+ * \param[in] pDesc Structure containing pointers to various descriptor arrays needed by the stack.
+ * These descriptors are reported to USB host as part of enumerations process.
+ * \param[in] param Structure containing USB device stack initialization parameters.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK(0) On success
+ * \retval ERR_USBD_BAD_MEM_BUF(0x0004000b) When insufficient memory buffer is passed or memory
+ * is not aligned on 2048 boundary.
+ */
+ ErrorCode_t (*Init)(USBD_HANDLE_T* phUsb, USB_CORE_DESCS_T* pDesc, USBD_API_INIT_PARAM_T* param);
+
+ /** \fn void Connect(USBD_HANDLE_T hUsb, uint32_t con)
+ * Function to make USB device visible/invisible on the USB bus.
+ *
+ * This function is called after the USB initialization. This function uses the soft connect
+ * feature to make the device visible on the USB bus. This function is called only after the
+ * application is ready to handle the USB data. The enumeration process is started by the
+ * host after the device detection. The driver handles the enumeration process according to
+ * the USB descriptors passed in the USB initialization function.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] con States whether to connect (1) or to disconnect (0).
+ * \return Nothing.
+ */
+ void (*Connect)(USBD_HANDLE_T hUsb, uint32_t con);
+
+ /** \fn void ISR(USBD_HANDLE_T hUsb)
+ * Function to USB device controller interrupt events.
+ *
+ * When the user application is active the interrupt handlers are mapped in the user flash
+ * space. The user application must provide an interrupt handler for the USB interrupt and
+ * call this function in the interrupt handler routine. The driver interrupt handler takes
+ * appropriate action according to the data received on the USB bus.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \return Nothing.
+ */
+ void (*ISR)(USBD_HANDLE_T hUsb);
+
+ /** \fn void Reset(USBD_HANDLE_T hUsb)
+ * Function to Reset USB device stack and hardware controller.
+ *
+ * Reset USB device stack and hardware controller. Disables all endpoints except EP0.
+ * Clears all pending interrupts and resets endpoint transfer queues.
+ * This function is called internally by pUsbApi->hw->init() and from reset event.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \return Nothing.
+ */
+ void (*Reset)(USBD_HANDLE_T hUsb);
+
+ /** \fn void ForceFullSpeed(USBD_HANDLE_T hUsb, uint32_t cfg)
+ * Function to force high speed USB device to operate in full speed mode.
+ *
+ * This function is useful for testing the behavior of current device when connected
+ * to a full speed only hosts.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] cfg When 1 - set force full-speed or
+ * 0 - clear force full-speed.
+ * \return Nothing.
+ */
+ void (*ForceFullSpeed )(USBD_HANDLE_T hUsb, uint32_t cfg);
+
+ /** \fn void WakeUpCfg(USBD_HANDLE_T hUsb, uint32_t cfg)
+ * Function to configure USB device controller to wake-up host on remote events.
+ *
+ * This function is called by application layer to configure the USB device controller
+ * to wakeup on remote events. It is recommended to call this function from users's
+ * USB_WakeUpCfg() callback routine registered with stack.
+ * \note User's USB_WakeUpCfg() is registered with stack by setting the USB_WakeUpCfg member
+ * of USBD_API_INIT_PARAM_T structure before calling pUsbApi->hw->Init() routine.
+ * Certain USB device controllers needed to keep some clocks always on to generate
+ * resume signaling through pUsbApi->hw->WakeUp(). This hook is provided to support
+ * such controllers. In most controllers cases this is an empty routine.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] cfg When 1 - Configure controller to wake on remote events or
+ * 0 - Configure controller not to wake on remote events.
+ * \return Nothing.
+ */
+ void (*WakeUpCfg)(USBD_HANDLE_T hUsb, uint32_t cfg);
+
+ /** \fn void SetAddress(USBD_HANDLE_T hUsb, uint32_t adr)
+ * Function to set USB address assigned by host in device controller hardware.
+ *
+ * This function is called automatically when USB_REQUEST_SET_ADDRESS request is received
+ * by the stack from USB host.
+ * This interface is provided to users to invoke this function in other scenarios which are not
+ * handle by current stack. In most user applications this function is not called directly.
+ * Also this function can be used by users who are selectively modifying the USB device stack's
+ * standard handlers through callback interface exposed by the stack.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] adr USB bus Address to which the device controller should respond. Usually
+ * assigned by the USB host.
+ * \return Nothing.
+ */
+ void (*SetAddress)(USBD_HANDLE_T hUsb, uint32_t adr);
+
+ /** \fn void Configure(USBD_HANDLE_T hUsb, uint32_t cfg)
+ * Function to configure device controller hardware with selected configuration.
+ *
+ * This function is called automatically when USB_REQUEST_SET_CONFIGURATION request is received
+ * by the stack from USB host.
+ * This interface is provided to users to invoke this function in other scenarios which are not
+ * handle by current stack. In most user applications this function is not called directly.
+ * Also this function can be used by users who are selectively modifying the USB device stack's
+ * standard handlers through callback interface exposed by the stack.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] cfg Configuration index.
+ * \return Nothing.
+ */
+ void (*Configure)(USBD_HANDLE_T hUsb, uint32_t cfg);
+
+ /** \fn void ConfigEP(USBD_HANDLE_T hUsb, USB_ENDPOINT_DESCRIPTOR *pEPD)
+ * Function to configure USB Endpoint according to descriptor.
+ *
+ * This function is called automatically when USB_REQUEST_SET_CONFIGURATION request is received
+ * by the stack from USB host. All the endpoints associated with the selected configuration
+ * are configured.
+ * This interface is provided to users to invoke this function in other scenarios which are not
+ * handle by current stack. In most user applications this function is not called directly.
+ * Also this function can be used by users who are selectively modifying the USB device stack's
+ * standard handlers through callback interface exposed by the stack.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] pEPD Endpoint descriptor structure defined in USB 2.0 specification.
+ * \return Nothing.
+ */
+ void (*ConfigEP)(USBD_HANDLE_T hUsb, USB_ENDPOINT_DESCRIPTOR *pEPD);
+
+ /** \fn void DirCtrlEP(USBD_HANDLE_T hUsb, uint32_t dir)
+ * Function to set direction for USB control endpoint EP0.
+ *
+ * This function is called automatically by the stack on need basis.
+ * This interface is provided to users to invoke this function in other scenarios which are not
+ * handle by current stack. In most user applications this function is not called directly.
+ * Also this function can be used by users who are selectively modifying the USB device stack's
+ * standard handlers through callback interface exposed by the stack.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] cfg When 1 - Set EP0 in IN transfer mode
+ * 0 - Set EP0 in OUT transfer mode
+ * \return Nothing.
+ */
+ void (*DirCtrlEP)(USBD_HANDLE_T hUsb, uint32_t dir);
+
+ /** \fn void EnableEP(USBD_HANDLE_T hUsb, uint32_t EPNum)
+ * Function to enable selected USB endpoint.
+ *
+ * This function enables interrupts on selected endpoint.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] EPNum Endpoint number as per USB specification.
+ * ie. An EP1_IN is represented by 0x81 number.
+ * \return Nothing.
+ */
+ void (*EnableEP)(USBD_HANDLE_T hUsb, uint32_t EPNum);
+
+ /** \fn void DisableEP(USBD_HANDLE_T hUsb, uint32_t EPNum)
+ * Function to disable selected USB endpoint.
+ *
+ * This function disables interrupts on selected endpoint.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] EPNum Endpoint number as per USB specification.
+ * ie. An EP1_IN is represented by 0x81 number.
+ * \return Nothing.
+ */
+ void (*DisableEP)(USBD_HANDLE_T hUsb, uint32_t EPNum);
+
+ /** \fn void ResetEP(USBD_HANDLE_T hUsb, uint32_t EPNum)
+ * Function to reset selected USB endpoint.
+ *
+ * This function flushes the endpoint buffers and resets data toggle logic.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] EPNum Endpoint number as per USB specification.
+ * ie. An EP1_IN is represented by 0x81 number.
+ * \return Nothing.
+ */
+ void (*ResetEP)(USBD_HANDLE_T hUsb, uint32_t EPNum);
+
+ /** \fn void SetStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum)
+ * Function to STALL selected USB endpoint.
+ *
+ * Generates STALL signaling for requested endpoint.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] EPNum Endpoint number as per USB specification.
+ * ie. An EP1_IN is represented by 0x81 number.
+ * \return Nothing.
+ */
+ void (*SetStallEP)(USBD_HANDLE_T hUsb, uint32_t EPNum);
+
+ /** \fn void ClrStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum)
+ * Function to clear STALL state for the requested endpoint.
+ *
+ * This function clears STALL state for the requested endpoint.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] EPNum Endpoint number as per USB specification.
+ * ie. An EP1_IN is represented by 0x81 number.
+ * \return Nothing.
+ */
+ void (*ClrStallEP)(USBD_HANDLE_T hUsb, uint32_t EPNum);
+
+ /** \fn ErrorCode_t SetTestMode(USBD_HANDLE_T hUsb, uint8_t mode)
+ * Function to set high speed USB device controller in requested test mode.
+ *
+ * USB-IF requires the high speed device to be put in various test modes
+ * for electrical testing. This USB device stack calls this function whenever
+ * it receives USB_REQUEST_CLEAR_FEATURE request for USB_FEATURE_TEST_MODE.
+ * Users can put the device in test mode by directly calling this function.
+ * Returns ERR_USBD_INVALID_REQ when device controller is full-speed only.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] mode Test mode defined in USB 2.0 electrical testing specification.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK(0) - On success
+ * \retval ERR_USBD_INVALID_REQ(0x00040001) - Invalid test mode or
+ * Device controller is full-speed only.
+ */
+ ErrorCode_t (*SetTestMode)(USBD_HANDLE_T hUsb, uint8_t mode);
+
+ /** \fn uint32_t ReadEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData)
+ * Function to read data received on the requested endpoint.
+ *
+ * This function is called by USB stack and the application layer to read the data
+ * received on the requested endpoint.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] EPNum Endpoint number as per USB specification.
+ * ie. An EP1_IN is represented by 0x81 number.
+ * \param[in,out] pData Pointer to the data buffer where data is to be copied.
+ * \return Returns the number of bytes copied to the buffer.
+ */
+ uint32_t (*ReadEP)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData);
+
+ /** \fn uint32_t ReadReqEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t len)
+ * Function to queue read request on the specified endpoint.
+ *
+ * This function is called by USB stack and the application layer to queue a read request
+ * on the specified endpoint.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] EPNum Endpoint number as per USB specification.
+ * ie. An EP1_IN is represented by 0x81 number.
+ * \param[in,out] pData Pointer to the data buffer where data is to be copied. This buffer
+ * address should be accessible by USB DMA master.
+ * \param[in] len Length of the buffer passed.
+ * \return Returns the length of the requested buffer.
+ */
+ uint32_t (*ReadReqEP)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t len);
+
+ /** \fn uint32_t ReadSetupPkt(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t *pData)
+ * Function to read setup packet data received on the requested endpoint.
+ *
+ * This function is called by USB stack and the application layer to read setup packet data
+ * received on the requested endpoint.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] EPNum Endpoint number as per USB specification.
+ * ie. An EP0_IN is represented by 0x80 number.
+ * \param[in,out] pData Pointer to the data buffer where data is to be copied.
+ * \return Returns the number of bytes copied to the buffer.
+ */
+ uint32_t (*ReadSetupPkt)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t *pData);
+
+ /** \fn uint32_t WriteEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t cnt)
+ * Function to write data to be sent on the requested endpoint.
+ *
+ * This function is called by USB stack and the application layer to send data
+ * on the requested endpoint.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] EPNum Endpoint number as per USB specification.
+ * ie. An EP1_IN is represented by 0x81 number.
+ * \param[in] pData Pointer to the data buffer from where data is to be copied.
+ * \param[in] cnt Number of bytes to write.
+ * \return Returns the number of bytes written.
+ */
+ uint32_t (*WriteEP)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t cnt);
+
+ /** \fn void WakeUp(USBD_HANDLE_T hUsb)
+ * Function to generate resume signaling on bus for remote host wakeup.
+ *
+ * This function is called by application layer to remotely wakeup host controller
+ * when system is in suspend state. Application should indicate this remote wakeup
+ * capability by setting USB_CONFIG_REMOTE_WAKEUP in bmAttributes of Configuration
+ * Descriptor. Also this routine will generate resume signalling only if host
+ * enables USB_FEATURE_REMOTE_WAKEUP by sending SET_FEATURE request before suspending
+ * the bus.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \return Nothing.
+ */
+ void (*WakeUp)(USBD_HANDLE_T hUsb);
+
+ /** \fn void EnableEvent(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t event_type, uint32_t enable)
+ * Function to enable/disable selected USB event.
+ *
+ * This function enables interrupts on selected endpoint.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] EPNum Endpoint number corresponding to the event.
+ * ie. An EP1_IN is represented by 0x81 number. For device events
+ * set this param to 0x0.
+ * \param[in] event_type Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \param[in] enable 1 - enable event, 0 - disable event.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK(0) - On success
+ * \retval ERR_USBD_INVALID_REQ(0x00040001) - Invalid event type.
+ */
+ ErrorCode_t (*EnableEvent)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t event_type, uint32_t enable);
+
+} USBD_HW_API_T;
+
+/*-----------------------------------------------------------------------------
+ * Private functions & structures prototypes used by stack internally
+ *-----------------------------------------------------------------------------*/
+/** @cond DIRECT_API */
+
+/* Driver functions */
+uint32_t hwUSB_GetMemSize(USBD_API_INIT_PARAM_T* param);
+ErrorCode_t hwUSB_Init(USBD_HANDLE_T* phUsb, USB_CORE_DESCS_T* pDesc, USBD_API_INIT_PARAM_T* param);
+void hwUSB_Connect(USBD_HANDLE_T hUsb, uint32_t con);
+void hwUSB_ISR(USBD_HANDLE_T hUsb);
+
+/* USB Hardware Functions */
+extern void hwUSB_Reset(USBD_HANDLE_T hUsb);
+extern void hwUSB_ForceFullSpeed (USBD_HANDLE_T hUsb, uint32_t con);
+extern void hwUSB_WakeUpCfg(USBD_HANDLE_T hUsb, uint32_t cfg);
+extern void hwUSB_SetAddress(USBD_HANDLE_T hUsb, uint32_t adr);
+extern void hwUSB_Configure(USBD_HANDLE_T hUsb, uint32_t cfg);
+extern void hwUSB_ConfigEP(USBD_HANDLE_T hUsb, USB_ENDPOINT_DESCRIPTOR *pEPD);
+extern void hwUSB_DirCtrlEP(USBD_HANDLE_T hUsb, uint32_t dir);
+extern void hwUSB_EnableEP(USBD_HANDLE_T hUsb, uint32_t EPNum);
+extern void hwUSB_DisableEP(USBD_HANDLE_T hUsb, uint32_t EPNum);
+extern void hwUSB_ResetEP(USBD_HANDLE_T hUsb, uint32_t EPNum);
+extern void hwUSB_SetStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum);
+extern void hwUSB_ClrStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum);
+extern ErrorCode_t hwUSB_SetTestMode(USBD_HANDLE_T hUsb, uint8_t mode); /* for FS only devices return ERR_USBD_INVALID_REQ */
+extern uint32_t hwUSB_ReadEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData);
+extern uint32_t hwUSB_ReadReqEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t len);
+extern uint32_t hwUSB_ReadSetupPkt(USBD_HANDLE_T hUsb, uint32_t, uint32_t *);
+extern uint32_t hwUSB_WriteEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t cnt);
+
+/* generate resume signaling on the bus */
+extern void hwUSB_WakeUp(USBD_HANDLE_T hUsb);
+extern ErrorCode_t hwUSB_EnableEvent(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t event_type, uint32_t enable);
+/* TODO implement following routines
+- function to program TD and queue them to ep Qh
+*/
+
+/** @endcond */
+
+
+#endif /* __USBHW_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_msc.h b/source/lpc_chip_11u6x/inc/usbd/usbd_msc.h
new file mode 100644
index 0000000..a62938f
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_msc.h
@@ -0,0 +1,119 @@
+/***********************************************************************
+* $Id:: mw_usbd_msc.h 331 2012-08-09 18:54:34Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* Mass Storage Class definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+
+#ifndef __MSC_H__
+#define __MSC_H__
+
+#include "usbd.h"
+
+/** \file
+ * \brief Mass Storage class (MSC) descriptors.
+ *
+ * Definition of MSC class descriptors and their bit defines.
+ *
+ */
+
+/* MSC Subclass Codes */
+#define MSC_SUBCLASS_RBC 0x01
+#define MSC_SUBCLASS_SFF8020I_MMC2 0x02
+#define MSC_SUBCLASS_QIC157 0x03
+#define MSC_SUBCLASS_UFI 0x04
+#define MSC_SUBCLASS_SFF8070I 0x05
+#define MSC_SUBCLASS_SCSI 0x06
+
+/* MSC Protocol Codes */
+#define MSC_PROTOCOL_CBI_INT 0x00
+#define MSC_PROTOCOL_CBI_NOINT 0x01
+#define MSC_PROTOCOL_BULK_ONLY 0x50
+
+
+/* MSC Request Codes */
+#define MSC_REQUEST_RESET 0xFF
+#define MSC_REQUEST_GET_MAX_LUN 0xFE
+
+
+/* MSC Bulk-only Stage */
+#define MSC_BS_CBW 0 /* Command Block Wrapper */
+#define MSC_BS_DATA_OUT 1 /* Data Out Phase */
+#define MSC_BS_DATA_IN 2 /* Data In Phase */
+#define MSC_BS_DATA_IN_LAST 3 /* Data In Last Phase */
+#define MSC_BS_DATA_IN_LAST_STALL 4 /* Data In Last Phase with Stall */
+#define MSC_BS_CSW 5 /* Command Status Wrapper */
+#define MSC_BS_ERROR 6 /* Error */
+
+
+/* Bulk-only Command Block Wrapper */
+PRE_PACK struct POST_PACK _MSC_CBW
+{
+ uint32_t dSignature;
+ uint32_t dTag;
+ uint32_t dDataLength;
+ uint8_t bmFlags;
+ uint8_t bLUN;
+ uint8_t bCBLength;
+ uint8_t CB[16];
+} ;
+typedef struct _MSC_CBW MSC_CBW;
+
+/* Bulk-only Command Status Wrapper */
+PRE_PACK struct POST_PACK _MSC_CSW
+{
+ uint32_t dSignature;
+ uint32_t dTag;
+ uint32_t dDataResidue;
+ uint8_t bStatus;
+} ;
+typedef struct _MSC_CSW MSC_CSW;
+
+#define MSC_CBW_Signature 0x43425355
+#define MSC_CSW_Signature 0x53425355
+
+
+/* CSW Status Definitions */
+#define CSW_CMD_PASSED 0x00
+#define CSW_CMD_FAILED 0x01
+#define CSW_PHASE_ERROR 0x02
+
+
+/* SCSI Commands */
+#define SCSI_TEST_UNIT_READY 0x00
+#define SCSI_REQUEST_SENSE 0x03
+#define SCSI_FORMAT_UNIT 0x04
+#define SCSI_INQUIRY 0x12
+#define SCSI_MODE_SELECT6 0x15
+#define SCSI_MODE_SENSE6 0x1A
+#define SCSI_START_STOP_UNIT 0x1B
+#define SCSI_MEDIA_REMOVAL 0x1E
+#define SCSI_READ_FORMAT_CAPACITIES 0x23
+#define SCSI_READ_CAPACITY 0x25
+#define SCSI_READ10 0x28
+#define SCSI_WRITE10 0x2A
+#define SCSI_VERIFY10 0x2F
+#define SCSI_READ12 0xA8
+#define SCSI_WRITE12 0xAA
+#define SCSI_MODE_SELECT10 0x55
+#define SCSI_MODE_SENSE10 0x5A
+
+
+#endif /* __MSC_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_mscuser.h b/source/lpc_chip_11u6x/inc/usbd/usbd_mscuser.h
new file mode 100644
index 0000000..eddc1b9
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_mscuser.h
@@ -0,0 +1,270 @@
+/***********************************************************************
+* $Id:: mw_usbd_mscuser.h 577 2012-11-20 01:42:04Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* Mass Storage Class Custom User Module definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+#ifndef __MSCUSER_H__
+#define __MSCUSER_H__
+
+#include "error.h"
+#include "usbd.h"
+#include "usbd_msc.h"
+#include "usbd_core.h"
+#include "app_usbd_cfg.h"
+
+/** \file
+ * \brief Mass Storage Class (MSC) API structures and function prototypes.
+ *
+ * Definition of functions exported by ROM based MSC function driver.
+ *
+ */
+
+/** \ingroup Group_USBD
+ * @defgroup USBD_MSC Mass Storage Class (MSC) Function Driver
+ * \section Sec_MSCModDescription Module Description
+ * MSC Class Function Driver module. This module contains an internal implementation of the USB MSC Class.
+ * User applications can use this class driver instead of implementing the MSC class manually
+ * via the low-level USBD_HW and USBD_Core APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Devices using the USB MSC Class.
+ */
+
+/** \brief Mass Storage class function driver initialization parameter data structure.
+ * \ingroup USBD_MSC
+ *
+ * \details This data structure is used to pass initialization parameters to the
+ * Mass Storage class function driver's init function.
+ *
+ */
+typedef struct USBD_MSC_INIT_PARAM
+{
+ /* memory allocation params */
+ uint32_t mem_base; /**< Base memory location from where the stack can allocate
+ data and buffers. \note The memory address set in this field
+ should be accessible by USB DMA controller. Also this value
+ should be aligned on 4 byte boundary.
+ */
+ uint32_t mem_size; /**< The size of memory buffer which stack can use.
+ \note The \em mem_size should be greater than the size
+ returned by USBD_MSC_API::GetMemSize() routine.*/
+ /* mass storage params */
+ uint8_t* InquiryStr; /**< Pointer to the 28 character string. This string is
+ sent in response to the SCSI Inquiry command. \note The data
+ pointed by the pointer should be of global scope.
+ */
+ uint32_t BlockCount; /**< Number of blocks present in the mass storage device */
+ uint32_t BlockSize; /**< Block size in number of bytes */
+ uint32_t MemorySize; /**< Memory size in number of bytes */
+ /** Pointer to the interface descriptor within the descriptor
+ * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T
+ * structure. The stack assumes both HS and FS use same BULK endpoints.
+ */
+
+ uint8_t* intf_desc;
+ /* user defined functions */
+
+ /**
+ * MSC Write callback function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a write command.
+ *
+ * \param[in] offset Destination start address.
+ * \param[in, out] src Pointer to a pointer to the source of data. Pointer-to-pointer
+ * is used to implement zero-copy buffers. See \ref USBD_ZeroCopy
+ * for more details on zero-copy concept.
+ * \param[in] length Number of bytes to be written.
+ * \return Nothing.
+ *
+ */
+ void (*MSC_Write)( uint32_t offset, uint8_t** src, uint32_t length, uint32_t high_offset);
+ /**
+ * MSC Read callback function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a read command.
+ *
+ * \param[in] offset Source start address.
+ * \param[in, out] dst Pointer to a pointer to the source of data. The MSC function drivers
+ * implemented in stack are written with zero-copy model. Meaning the stack doesn't make an
+ * extra copy of buffer before writing/reading data from USB hardware FIFO. Hence the
+ * parameter is pointer to a pointer containing address buffer (uint8_t** dst).
+ * So that the user application can update the buffer pointer instead of copying data to
+ * address pointed by the parameter. /note The updated buffer address should be accessible
+ * by USB DMA master. If user doesn't want to use zero-copy model, then the user should copy
+ * data to the address pointed by the passed buffer pointer parameter and shouldn't change
+ * the address value. See \ref USBD_ZeroCopy for more details on zero-copy concept.
+ * \param[in] length Number of bytes to be read.
+ * \return Nothing.
+ *
+ */
+ void (*MSC_Read)( uint32_t offset, uint8_t** dst, uint32_t length, uint32_t high_offset);
+ /**
+ * MSC Verify callback function.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends a verify command. The callback function should compare the buffer
+ * with the destination memory at the requested offset and
+ *
+ * \param[in] offset Destination start address.
+ * \param[in] buf Buffer containing the data sent by the host.
+ * \param[in] length Number of bytes to verify.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK If data in the buffer matches the data at destination
+ * \retval ERR_FAILED At least one byte is different.
+ *
+ */
+ ErrorCode_t (*MSC_Verify)( uint32_t offset, uint8_t buf[], uint32_t length, uint32_t high_offset);
+ /**
+ * Optional callback function to optimize MSC_Write buffer transfer.
+ *
+ * This function is provided by the application software. This function gets called
+ * when host sends SCSI_WRITE10/SCSI_WRITE12 command. The callback function should
+ * update the \em buff_adr pointer so that the stack transfers the data directly
+ * to the target buffer. /note The updated buffer address should be accessible
+ * by USB DMA master. If user doesn't want to use zero-copy model, then the user
+ * should not update the buffer pointer. See \ref USBD_ZeroCopy for more details
+ * on zero-copy concept.
+ *
+ * \param[in] offset Destination start address.
+ * \param[in,out] buf Buffer containing the data sent by the host.
+ * \param[in] length Number of bytes to write.
+ * \return Nothing.
+ *
+ */
+ void (*MSC_GetWriteBuf)( uint32_t offset, uint8_t** buff_adr, uint32_t length, uint32_t high_offset);
+
+ /**
+ * Optional user override-able function to replace the default MSC class handler.
+ *
+ * The application software could override the default EP0 class handler with their
+ * own by providing the handler function address as this data member of the parameter
+ * structure. Application which like the default handler should set this data member
+ * to zero before calling the USBD_MSC_API::Init().
+ * \n
+ * \note
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in] data Pointer to the data which will be passed when callback function is called by the stack.
+ * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details.
+ * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success.
+ * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line.
+ * \retval ERR_USBD_xxx For other error conditions.
+ *
+ */
+ ErrorCode_t (*MSC_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event);
+
+ uint64_t MemorySize64;
+
+} USBD_MSC_INIT_PARAM_T;
+
+/** \brief MSC class API functions structure.
+ * \ingroup USBD_MSC
+ *
+ * This module exposes functions which interact directly with USB device controller hardware.
+ *
+ */
+typedef struct USBD_MSC_API
+{
+ /** \fn uint32_t GetMemSize(USBD_MSC_INIT_PARAM_T* param)
+ * Function to determine the memory required by the MSC function driver module.
+ *
+ * This function is called by application layer before calling pUsbApi->msc->Init(), to allocate memory used
+ * by MSC function driver module. The application should allocate the memory which is accessible by USB
+ * controller/DMA controller.
+ * \note Some memory areas are not accessible by all bus masters.
+ *
+ * \param[in] param Structure containing MSC function driver module initialization parameters.
+ * \return Returns the required memory size in bytes.
+ */
+ uint32_t (*GetMemSize)(USBD_MSC_INIT_PARAM_T* param);
+
+ /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param)
+ * Function to initialize MSC function driver module.
+ *
+ * This function is called by application layer to initialize MSC function driver module.
+ *
+ * \param[in] hUsb Handle to the USB device stack.
+ * \param[in, out] param Structure containing MSC function driver module initialization parameters.
+ * \return Returns \ref ErrorCode_t type to indicate success or error condition.
+ * \retval LPC_OK On success
+ * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte
+ * aligned or smaller than required.
+ * \retval ERR_API_INVALID_PARAM2 Either MSC_Write() or MSC_Read() or
+ * MSC_Verify() callbacks are not defined.
+ * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed.
+ * \retval ERR_USBD_BAD_EP_DESC Wrong endpoint descriptor is passed.
+ */
+ ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param);
+
+} USBD_MSC_API_T;
+
+/*-----------------------------------------------------------------------------
+ * Private functions & structures prototypes
+ *-----------------------------------------------------------------------------*/
+/** @cond ADVANCED_API */
+
+typedef struct _MSC_CTRL_T
+{
+ /* If it's a USB HS, the max packet is 512, if it's USB FS,
+ the max packet is 64. Use 512 for both HS and FS. */
+ /*ALIGNED(4)*/ uint8_t BulkBuf[USB_HS_MAX_BULK_PACKET]; /* Bulk In/Out Buffer */
+ /*ALIGNED(4)*/MSC_CBW CBW; /* Command Block Wrapper */
+ /*ALIGNED(4)*/MSC_CSW CSW; /* Command Status Wrapper */
+
+ USB_CORE_CTRL_T* pUsbCtrl;
+
+ uint64_t Offset; /* R/W Offset */
+ uint32_t Length; /* R/W Length */
+ uint32_t BulkLen; /* Bulk In/Out Length */
+ uint8_t* rx_buf;
+
+ uint8_t BulkStage; /* Bulk Stage */
+ uint8_t if_num; /* interface number */
+ uint8_t epin_num; /* BULK IN endpoint number */
+ uint8_t epout_num; /* BULK OUT endpoint number */
+ uint32_t MemOK; /* Memory OK */
+
+ uint8_t* InquiryStr;
+ uint32_t BlockCount;
+ uint32_t BlockSize;
+ uint64_t MemorySize;
+ /* user defined functions */
+ void (*MSC_Write)( uint32_t offset, uint8_t** src, uint32_t length, uint32_t high_offset);
+ void (*MSC_Read)( uint32_t offset, uint8_t** dst, uint32_t length, uint32_t high_offset);
+ ErrorCode_t (*MSC_Verify)( uint32_t offset, uint8_t src[], uint32_t length, uint32_t high_offset);
+ /* optional call back for MSC_Write optimization */
+ void (*MSC_GetWriteBuf)( uint32_t offset, uint8_t** buff_adr, uint32_t length, uint32_t high_offset);
+
+
+}USB_MSC_CTRL_T;
+
+/** @cond DIRECT_API */
+extern uint32_t mwMSC_GetMemSize(USBD_MSC_INIT_PARAM_T* param);
+extern ErrorCode_t mwMSC_init(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param);
+/** @endcond */
+
+/** @endcond */
+
+
+#endif /* __MSCUSER_H__ */
diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_rom_api.h b/source/lpc_chip_11u6x/inc/usbd/usbd_rom_api.h
new file mode 100644
index 0000000..464bbab
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd/usbd_rom_api.h
@@ -0,0 +1,92 @@
+/***********************************************************************
+* $Id:: mw_usbd_rom_api.h 331 2012-08-09 18:54:34Z usb10131 $
+*
+* Project: USB device ROM Stack
+*
+* Description:
+* ROM API Module definitions.
+*
+***********************************************************************
+* Copyright(C) 2011, NXP Semiconductor
+* All rights reserved.
+*
+* Software that is described herein is for illustrative purposes only
+* which provides customers with programming information regarding the
+* products. This software is supplied "AS IS" without any warranties.
+* NXP Semiconductors assumes no responsibility or liability for the
+* use of the software, conveys no license or title under any patent,
+* copyright, or mask work right to the product. NXP Semiconductors
+* reserves the right to make changes in the software without
+* notification. NXP Semiconductors also make no representation or
+* warranty that such application will be suitable for the specified
+* use without further testing or modification.
+**********************************************************************/
+#ifndef __MW_USBD_ROM_API_H
+#define __MW_USBD_ROM_API_H
+/** \file
+ * \brief ROM API for USB device stack.
+ *
+ * Definition of functions exported by ROM based USB device stack.
+ *
+ */
+
+#include "error.h"
+#include "usbd.h"
+#include "usbd_hw.h"
+#include "usbd_core.h"
+#include "usbd_mscuser.h"
+#include "usbd_dfuuser.h"
+#include "usbd_hiduser.h"
+#include "usbd_cdcuser.h"
+
+/** \brief Main USBD API functions structure.
+ * \ingroup Group_USBD
+ *
+ * This structure contains pointer to various USB Device stack's sub-module
+ * function tables. This structure is used as main entry point to access
+ * various methods (grouped in sub-modules) exposed by ROM based USB device
+ * stack.
+ *
+ */
+typedef struct USBD_API
+{
+ const USBD_HW_API_T* hw; /**< Pointer to function table which exposes functions
+ which interact directly with USB device stack's core
+ layer.*/
+ const USBD_CORE_API_T* core; /**< Pointer to function table which exposes functions
+ which interact directly with USB device controller
+ hardware.*/
+ const USBD_MSC_API_T* msc; /**< Pointer to function table which exposes functions
+ provided by MSC function driver module.
+ */
+ const USBD_DFU_API_T* dfu; /**< Pointer to function table which exposes functions
+ provided by DFU function driver module.
+ */
+ const USBD_HID_API_T* hid; /**< Pointer to function table which exposes functions
+ provided by HID function driver module.
+ */
+ const USBD_CDC_API_T* cdc; /**< Pointer to function table which exposes functions
+ provided by CDC-ACM function driver module.
+ */
+ const uint32_t* reserved6; /**< Reserved for future function driver module.
+ */
+ const uint32_t version; /**< Version identifier of USB ROM stack. The version is
+ defined as 0x0CHDMhCC where each nibble represents version
+ number of the corresponding component.
+ CC - 7:0 - 8bit core version number
+ h - 11:8 - 4bit hardware interface version number
+ M - 15:12 - 4bit MSC class module version number
+ D - 19:16 - 4bit DFU class module version number
+ H - 23:20 - 4bit HID class module version number
+ C - 27:24 - 4bit CDC class module version number
+ H - 31:28 - 4bit reserved
+ */
+
+} USBD_API_T;
+
+/* Applications using USBD ROM API should define this instance. The pointer should be assigned a value computed based on chip definitions. */
+extern const USBD_API_T* g_pUsbApi;
+#define USBD_API g_pUsbApi
+
+#endif /*__MW_USBD_ROM_API_H*/
+
diff --git a/source/lpc_chip_11u6x/inc/usbd_11u6x.h b/source/lpc_chip_11u6x/inc/usbd_11u6x.h
new file mode 100644
index 0000000..8f63f4c
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/usbd_11u6x.h
@@ -0,0 +1,72 @@
+/*
+ * @brief LPC11U6x USB device register block
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __USBD_11U6X_H_
+#define __USBD_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup USBD_11U6X CHIP: LPC11u6x USB Device driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief USB device register block structure
+ */
+typedef struct { /*!< USB Structure */
+ __IO uint32_t DEVCMDSTAT; /*!< USB Device Command/Status register */
+ __IO uint32_t INFO; /*!< USB Info register */
+ __IO uint32_t EPLISTSTART; /*!< USB EP Command/Status List start address */
+ __IO uint32_t DATABUFSTART; /*!< USB Data buffer start address */
+ __IO uint32_t LPM; /*!< Link Power Management register */
+ __IO uint32_t EPSKIP; /*!< USB Endpoint skip */
+ __IO uint32_t EPINUSE; /*!< USB Endpoint Buffer in use */
+ __IO uint32_t EPBUFCFG; /*!< USB Endpoint Buffer Configuration register */
+ __IO uint32_t INTSTAT; /*!< USB interrupt status register */
+ __IO uint32_t INTEN; /*!< USB interrupt enable register */
+ __IO uint32_t INTSETSTAT; /*!< USB set interrupt status register */
+ __IO uint32_t INTROUTING; /*!< USB interrupt routing register */
+ __I uint32_t RESERVED0[1];
+ __I uint32_t EPTOGGLE; /*!< USB Endpoint toggle register */
+} LPC_USB_T;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBD_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/inc/wwdt_11u6x.h b/source/lpc_chip_11u6x/inc/wwdt_11u6x.h
new file mode 100644
index 0000000..2aabd5a
--- /dev/null
+++ b/source/lpc_chip_11u6x/inc/wwdt_11u6x.h
@@ -0,0 +1,246 @@
+/*
+ * @brief LPC11u6x WWDT chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#ifndef __WWDT_11U6X_H_
+#define __WWDT_11U6X_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup WWDT_11U6X CHIP: LPC11u6x Windowed Watchdog driver
+ * @ingroup CHIP_11U6X_Drivers
+ * @{
+ */
+
+/**
+ * @brief Windowed Watchdog register block structure
+ */
+typedef struct { /*!< WWDT Structure */
+ __IO uint32_t MOD; /*!< Watchdog mode register. This register contains the basic mode and status of the Watchdog Timer. */
+ __IO uint32_t TC; /*!< Watchdog timer constant register. This register determines the time-out value. */
+ __O uint32_t FEED; /*!< Watchdog feed sequence register. Writing 0xAA followed by 0x55 to this register reloads the Watchdog timer with the value contained in WDTC. */
+ __I uint32_t TV; /*!< Watchdog timer value register. This register reads out the current value of the Watchdog timer. */
+ __IO uint32_t CLKSEL; /*!< Watchdog clock select register. */
+ __IO uint32_t WARNINT; /*!< Watchdog warning interrupt register. This register contains the Watchdog warning interrupt compare value. */
+ __IO uint32_t WINDOW; /*!< Watchdog timer window register. This register contains the Watchdog window value. */
+} LPC_WWDT_T;
+
+/**
+ * @brief Watchdog Mode register definitions
+ */
+/** Watchdog Mode Bitmask */
+#define WWDT_WDMOD_BITMASK ((uint32_t) 0x1F)
+/** WWDT interrupt enable bit */
+#define WWDT_WDMOD_WDEN ((uint32_t) (1 << 0))
+/** WWDT interrupt enable bit */
+#define WWDT_WDMOD_WDRESET ((uint32_t) (1 << 1))
+/** WWDT time out flag bit */
+#define WWDT_WDMOD_WDTOF ((uint32_t) (1 << 2))
+/** WDT Time Out flag bit */
+#define WWDT_WDMOD_WDINT ((uint32_t) (1 << 3))
+/** WWDT Protect flag bit */
+#define WWDT_WDMOD_WDPROTECT ((uint32_t) (1 << 4))
+/** WWDT lock bit */
+#define WWDT_WDMOD_LOCK ((uint32_t) (1 << 5))
+
+/**
+ * @brief Initialize the Watchdog timer
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @return None
+ */
+void Chip_WWDT_Init(LPC_WWDT_T *pWWDT);
+
+/**
+ * @brief Shutdown the Watchdog timer
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @return None
+ */
+void Chip_WWDT_DeInit(LPC_WWDT_T *pWWDT);
+
+/**
+ * @brief Set WDT timeout constant value used for feed
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @param timeout : WDT timeout in ticks, between WWDT_TICKS_MIN and WWDT_TICKS_MAX
+ * @return none
+ */
+STATIC INLINE void Chip_WWDT_SetTimeOut(LPC_WWDT_T *pWWDT, uint32_t timeout)
+{
+ pWWDT->TC = timeout;
+}
+
+/**
+ * @brief Feed watchdog timer
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @return None
+ * @note If this function isn't called, a watchdog timer warning will occur.
+ * After the warning, a timeout will occur if a feed has happened.
+ */
+STATIC INLINE void Chip_WWDT_Feed(LPC_WWDT_T *pWWDT)
+{
+ pWWDT->FEED = 0xAA;
+ pWWDT->FEED = 0x55;
+}
+
+/**
+ * @brief Set WWDT warning interrupt
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @param timeout : WDT warning in ticks, between 0 and 1023
+ * @return None
+ * @note This is the number of ticks after the watchdog interrupt that the
+ * warning interrupt will be generated.
+ */
+STATIC INLINE void Chip_WWDT_SetWarning(LPC_WWDT_T *pWWDT, uint32_t timeout)
+{
+ pWWDT->WARNINT = timeout;
+}
+
+/**
+ * @brief Set WWDT window time
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @param timeout : WDT timeout in ticks, between WWDT_TICKS_MIN and WWDT_TICKS_MAX
+ * @return None
+ * @note The watchdog timer must be fed between the timeout from the Chip_WWDT_SetTimeOut()
+ * function and this function, with this function defining the last tick before the
+ * watchdog window interrupt occurs.
+ */
+STATIC INLINE void Chip_WWDT_SetWindow(LPC_WWDT_T *pWWDT, uint32_t timeout)
+{
+ pWWDT->WINDOW = timeout;
+}
+
+/**
+ * @brief Enable watchdog timer options
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @param options : An or'ed set of options of values
+ * WWDT_WDMOD_WDEN, WWDT_WDMOD_WDRESET, and WWDT_WDMOD_WDPROTECT
+ * @return None
+ * @note You can enable more than one option at once (ie, WWDT_WDMOD_WDRESET |
+ * WWDT_WDMOD_WDPROTECT), but use the WWDT_WDMOD_WDEN after all other options
+ * are set (or unset) with no other options. If WWDT_WDMOD_LOCK is used, it cannot
+ * be unset.
+ */
+STATIC INLINE void Chip_WWDT_SetOption(LPC_WWDT_T *pWWDT, uint32_t options)
+{
+ pWWDT->MOD |= options;
+}
+
+/**
+ * @brief Disable/clear watchdog timer options
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @param options : An or'ed set of options of values
+ * WWDT_WDMOD_WDEN, WWDT_WDMOD_WDRESET, and WWDT_WDMOD_WDPROTECT
+ * @return None
+ * @note You can disable more than one option at once (ie, WWDT_WDMOD_WDRESET |
+ * WWDT_WDMOD_WDTOF).
+ */
+STATIC INLINE void Chip_WWDT_UnsetOption(LPC_WWDT_T *pWWDT, uint32_t options)
+{
+ pWWDT->MOD &= (~options) & WWDT_WDMOD_BITMASK;
+}
+
+/**
+ * @brief Enable WWDT activity
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @return None
+ */
+STATIC INLINE void Chip_WWDT_Start(LPC_WWDT_T *pWWDT)
+{
+ Chip_WWDT_SetOption(pWWDT, WWDT_WDMOD_WDEN);
+ Chip_WWDT_Feed(pWWDT);
+}
+
+/**
+ * @brief Read WWDT status flag
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @return Watchdog status, an Or'ed value of WWDT_WDMOD_*
+ */
+STATIC INLINE uint32_t Chip_WWDT_GetStatus(LPC_WWDT_T *pWWDT)
+{
+ return pWWDT->MOD;
+}
+
+/**
+ * @brief Clear WWDT interrupt status flags
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @param status : Or'ed value of status flag(s) that you want to clear, should be:
+ * - WWDT_WDMOD_WDTOF: Clear watchdog timeout flag
+ * - WWDT_WDMOD_WDINT: Clear watchdog warning flag
+ * @return None
+ */
+void Chip_WWDT_ClearStatusFlag(LPC_WWDT_T *pWWDT, uint32_t status);
+
+/**
+ * @brief Get the current value of WDT
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @return current value of WDT
+ */
+STATIC INLINE uint32_t Chip_WWDT_GetCurrentCount(LPC_WWDT_T *pWWDT)
+{
+ return pWWDT->TV;
+}
+
+/**
+ * @brief Watchdog Timer Clock Source Selection register definitions
+ */
+/** Clock source select bitmask */
+#define WWDT_CLKSEL_BITMASK ((uint32_t) 0x10000001)
+/** Lock the clock source selection */
+#define WWDT_CLKSEL_LOCK ((uint32_t) (1 << 31))
+
+/**
+ * @brief Watchdog Clock Source definitions
+ */
+typedef enum {
+ WWDT_CLKSRC_IRC = 0, /*!< Internal RC oscillator */
+ WWDT_CLKSRC_WATCHDOG_WDOSC = 1, /*!< Watchdog oscillator (WDOSC) */
+} CHIP_WWDT_CLK_SRC_T;
+
+/**
+ * @brief Get the current value of WDT
+ * @param pWWDT : The base of WatchDog Timer peripheral on the chip
+ * @param wdtClkSrc : Selected watchdog clock source
+ * @return Nothing
+ */
+STATIC INLINE void Chip_WWDT_SelClockSource(LPC_WWDT_T *pWWDT, CHIP_WWDT_CLK_SRC_T wdtClkSrc)
+{
+ pWWDT->CLKSEL = wdtClkSrc & WWDT_CLKSEL_BITMASK;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WWDT_11U6X_H_ */
diff --git a/source/lpc_chip_11u6x/src/adc_11u6x.c b/source/lpc_chip_11u6x/src/adc_11u6x.c
new file mode 100644
index 0000000..9d7b848
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/adc_11u6x.c
@@ -0,0 +1,209 @@
+/*
+ * @brief LPC11u6x ADC driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/* Set ADC interrupt bits (safe) */
+void Chip_ADC_SetIntBits(LPC_ADC_T *pADC, uint32_t intMask)
+{
+ uint32_t temp;
+
+ /* Read and write values may not be the same, write 0 to
+ undefined bits */
+ temp = pADC->INTEN & 0x07FFFFFF;
+
+ pADC->INTEN = temp | intMask;
+}
+
+/* Clear ADC interrupt bits (safe) */
+void Chip_ADC_ClearIntBits(LPC_ADC_T *pADC, uint32_t intMask)
+{
+ uint32_t temp;
+
+ /* Read and write values may not be the same, write 0 to
+ undefined bits */
+ temp = pADC->INTEN & 0x07FFFFFF;
+
+ pADC->INTEN = temp & ~intMask;
+}
+
+/* Set ADC threshold selection bits (safe) */
+void Chip_ADC_SetTHRSELBits(LPC_ADC_T *pADC, uint32_t mask)
+{
+ uint32_t temp;
+
+ /* Read and write values may not be the same, write 0 to
+ undefined bits */
+ temp = pADC->CHAN_THRSEL & 0x00000FFF;
+
+ pADC->CHAN_THRSEL = temp | mask;
+}
+
+/* Clear ADC threshold selection bits (safe) */
+void Chip_ADC_ClearTHRSELBits(LPC_ADC_T *pADC, uint32_t mask)
+{
+ uint32_t temp;
+
+ /* Read and write values may not be the same, write 0 to
+ undefined bits */
+ temp = pADC->CHAN_THRSEL & 0x00000FFF;
+
+ pADC->CHAN_THRSEL = temp & ~mask;
+}
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initialize the ADC peripheral */
+void Chip_ADC_Init(LPC_ADC_T *pADC, uint32_t flags)
+{
+ /* Power up ADC and enable ADC base clock */
+ Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_ADC_PD);
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_ADC);
+
+ /* Disable ADC interrupts */
+ pADC->INTEN = 0;
+
+ /* Set ADC control options */
+ pADC->CTRL = flags;
+}
+
+/* Start ADC calibration */
+void Chip_ADC_StartCalibration(LPC_ADC_T *pADC)
+{
+ uint32_t save_ADC_CTRL;
+
+ save_ADC_CTRL = pADC->CTRL;
+ Chip_ADC_SetClockRate(LPC_ADC, ADC_CALIBRATE_RATE);
+
+ pADC->CTRL = (pADC->CTRL | ADC_CR_CALMODEBIT) & ~ADC_CR_LPWRMODEBIT;
+}
+
+/**
+ * @brief Start ADC calibration
+ * @param pADC : The base of ADC peripheral on the chip
+ * @return TRUE if calibration is complete, otherwise FALSE.
+ */
+bool Chip_ADC_IsCalibrationDone(LPC_ADC_T *pADC)
+{
+ return (bool) ((pADC->CTRL & ADC_CR_CALMODEBIT) == 0);
+}
+
+
+/* Shutdown ADC */
+void Chip_ADC_DeInit(LPC_ADC_T *pADC)
+{
+ pADC->INTEN = 0;
+ pADC->CTRL = 0;
+
+ /* Stop ADC clock and then power down ADC */
+ Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_ADC);
+ Chip_SYSCTL_PowerDown(SYSCTL_POWERDOWN_ADC_PD);
+}
+
+/* Set ADC clock rate */
+void Chip_ADC_SetClockRate(LPC_ADC_T *pADC, uint32_t rate)
+{
+ Chip_ADC_SetDivider(pADC, ((Chip_Clock_GetSystemClockRate() + (rate>>2)) / rate) -1);
+}
+
+/* Helper function for safely setting ADC sequencer register bits */
+void Chip_ADC_SetSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits)
+{
+ uint32_t temp;
+
+ /* Read sequencer register and mask off bits 20..25 */
+ temp = pADC->SEQ_CTRL[seqIndex] & ~(0x3F << 20);
+
+ /* OR in passed bits */
+ pADC->SEQ_CTRL[seqIndex] = temp | bits;
+}
+
+/* Helper function for safely clearing ADC sequencer register bits */
+void Chip_ADC_ClearSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits)
+{
+ uint32_t temp;
+
+ /* Read sequencer register and mask off bits 20..25 */
+ temp = pADC->SEQ_CTRL[seqIndex] & ~(0x3F << 20);
+
+ /* OR in passed bits */
+ pADC->SEQ_CTRL[seqIndex] = temp & ~bits;
+}
+
+/* Enable interrupts in ADC (sequencers A/B and overrun) */
+void Chip_ADC_EnableInt(LPC_ADC_T *pADC, uint32_t intMask)
+{
+ Chip_ADC_SetIntBits(pADC, intMask);
+}
+
+/* Disable interrupts in ADC (sequencers A/B and overrun) */
+void Chip_ADC_DisableInt(LPC_ADC_T *pADC, uint32_t intMask)
+{
+ Chip_ADC_ClearIntBits(pADC, intMask);
+}
+
+/* Enable a threshold event interrupt in ADC */
+void Chip_ADC_SetThresholdInt(LPC_ADC_T *pADC, uint8_t ch, ADC_INTEN_THCMP_T thInt)
+{
+ int shiftIndex = 3 + (ch * 2);
+
+ /* Clear current bits first */
+ Chip_ADC_ClearIntBits(pADC, (ADC_INTEN_CMP_MASK << shiftIndex));
+
+ /* Set new threshold interrupt type */
+ Chip_ADC_SetIntBits(pADC, ((uint32_t) thInt << shiftIndex));
+}
+
+/* Select threshold 0 values for comparison for selected channels */
+void Chip_ADC_SelectTH0Channels(LPC_ADC_T *pADC, uint32_t channels)
+{
+ Chip_ADC_ClearTHRSELBits(pADC, channels);
+}
+
+/* Select threshold 1 value for comparison for selected channels */
+void Chip_ADC_SelectTH1Channels(LPC_ADC_T *pADC, uint32_t channels)
+{
+ Chip_ADC_SetTHRSELBits(pADC, channels);
+}
diff --git a/source/lpc_chip_11u6x/src/chip_11u6x.c b/source/lpc_chip_11u6x/src/chip_11u6x.c
new file mode 100644
index 0000000..5292a06
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/chip_11u6x.c
@@ -0,0 +1,84 @@
+/*
+ * @brief LPC11u6x Miscellaneous chip specific functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/* System Clock Frequency (Core Clock) */
+uint32_t SystemCoreClock;
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Update system core clock rate, should be called if the system has
+ a clock rate change */
+void SystemCoreClockUpdate(void)
+{
+ /* CPU core speed */
+ SystemCoreClock = Chip_Clock_GetSystemClockRate();
+}
+
+void Chip_USB_Init(void)
+{
+ /* Set USB PLL input to main oscillator */
+ Chip_Clock_SetUSBPLLSource(SYSCTL_USBPLLCLKSRC_MAINOSC);
+ /* Setup USB PLL (FCLKIN = 12MHz) * 4 = 48MHz
+ MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2)
+ FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz
+ FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) */
+ Chip_Clock_SetupUSBPLL(3, 1);
+
+ /* Powerup USB PLL */
+ Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_USBPLL_PD);
+
+ /* Wait for PLL to lock */
+ while (!Chip_Clock_IsUSBPLLLocked()) {}
+
+ /* enable USB main clock */
+ Chip_Clock_SetUSBClockSource(SYSCTL_USBCLKSRC_PLLOUT, 1);
+ /* Enable AHB clock to the USB block and USB RAM. */
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USB);
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USBRAM);
+ /* power UP USB Phy */
+ Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_USBPAD_PD);
+}
diff --git a/source/lpc_chip_11u6x/src/clock_11u6x.c b/source/lpc_chip_11u6x/src/clock_11u6x.c
new file mode 100644
index 0000000..3e57145
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/clock_11u6x.c
@@ -0,0 +1,319 @@
+/*
+ * @brief LPC11U6X System clock control functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/* Inprecise clock rates for the watchdog oscillator */
+STATIC const uint32_t wdtOSCRate[WDTLFO_OSC_4_60 + 1] = {
+ 0, /* WDT_OSC_ILLEGAL */
+ 600000, /* WDT_OSC_0_60 */
+ 1050000, /* WDT_OSC_1_05 */
+ 1400000, /* WDT_OSC_1_40 */
+ 1750000, /* WDT_OSC_1_75 */
+ 2100000, /* WDT_OSC_2_10 */
+ 2400000, /* WDT_OSC_2_40 */
+ 2700000, /* WDT_OSC_2_70 */
+ 3000000, /* WDT_OSC_3_00 */
+ 3250000, /* WDT_OSC_3_25 */
+ 3500000, /* WDT_OSC_3_50 */
+ 3750000, /* WDT_OSC_3_75 */
+ 4000000, /* WDT_OSC_4_00 */
+ 4200000, /* WDT_OSC_4_20 */
+ 4400000, /* WDT_OSC_4_40 */
+ 4600000 /* WDT_OSC_4_60 */
+};
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/* Compute a WDT rate */
+STATIC uint32_t Chip_Clock_GetWDTRate(uint32_t reg)
+{
+ uint32_t div;
+ CHIP_WDTLFO_OSC_T clk;
+
+ /* Get WDT oscillator settings */
+ clk = (CHIP_WDTLFO_OSC_T) ((reg >> 5) & 0xF);
+ div = reg & 0x1F;
+
+ /* Compute clock rate and divided by divde value */
+ return wdtOSCRate[clk] / ((div + 1) << 1);
+}
+
+/* Compute a PLL frequency */
+STATIC uint32_t Chip_Clock_GetPLLFreq(uint32_t PLLReg, uint32_t inputRate)
+{
+ uint32_t msel = ((PLLReg & 0x1F) + 1);
+
+ return inputRate * msel;
+}
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Get USART 1/2/3/4 UART base rate */
+uint32_t Chip_Clock_GetUSARTNBaseClockRate(void)
+{
+ uint64_t inclk;
+ uint32_t div;
+
+ div = (uint32_t) Chip_Clock_GetUSARTNBaseClockDiv();
+ if (div == 0) {
+ /* Divider is 0 so UART clock is disabled */
+ inclk = 0;
+ }
+ else {
+ uint32_t mult, divf;
+
+ /* Input clock into FRG block is the divided main system clock */
+ inclk = (uint64_t) (Chip_Clock_GetMainClockRate() / div);
+
+ divf = Chip_Clock_GetUSARTNFRGDivider();
+ if (divf == 0xFF) {
+ /* Fractional part is enabled, get multiplier */
+ mult = (uint32_t) Chip_Clock_GetUSARTNFRGMultiplier();
+
+ /* Get fractional error */
+ inclk = (inclk * 256) / (uint64_t) (256 + mult);
+ }
+ else {
+ /* Integer divide from fractional divider */
+ inclk = inclk / (uint64_t) div;
+ }
+ }
+
+ return (uint32_t) inclk;
+}
+
+/* Set USART 1/2/3/4 UART base rate */
+uint32_t Chip_Clock_SetUSARTNBaseClockRate(uint32_t rate, bool fEnable)
+{
+ uint32_t div, inclk;
+
+ /* Input clock into FRG block is the main system clock */
+ inclk = Chip_Clock_GetMainClockRate();
+
+ /* Get integer divider for coarse rate */
+ div = inclk / rate;
+ if (div == 0) {
+ div = 1;
+ }
+
+ /* Approximated rate with only integer divider */
+ Chip_Clock_SetUSARTNBaseClockDiv((uint8_t) div);
+
+ if (fEnable) {
+ uint32_t uart_fra_multiplier;
+
+ /* Reset FRG */
+ Chip_SYSCTL_PeriphReset(RESET_FRG);
+
+ /* Enable fractional divider */
+ Chip_Clock_SetUSARTNFRGDivider(0xFF);
+
+ /* Compute the fractional divisor (the lower byte is the
+ fractional portion) */
+ uart_fra_multiplier = ((inclk / div) * 256) / rate;
+
+ /* ...just the fractional portion (the lower byte) */
+ Chip_Clock_SetUSARTNFRGMultiplier((uint8_t) uart_fra_multiplier);
+ }
+ else {
+ /* Disable fractional generator and use integer divider only */
+ Chip_Clock_SetUSARTNFRGDivider(0);
+ }
+
+ return Chip_Clock_GetUSARTNBaseClockRate();
+}
+
+/* Set System PLL clock source */
+void Chip_Clock_SetSystemPLLSource(CHIP_SYSCTL_PLLCLKSRC_T src)
+{
+ LPC_SYSCTL->SYSPLLCLKSEL = (uint32_t) src;
+ LPC_SYSCTL->SYSPLLCLKUEN = 0;
+ LPC_SYSCTL->SYSPLLCLKUEN = 1;
+}
+
+/* Bypass System Oscillator and set oscillator frequency range */
+void Chip_Clock_SetPLLBypass(bool bypass, bool highfr)
+{
+ uint32_t ctrl = 0;
+
+ if (bypass) {
+ ctrl |= (1 << 0);
+ }
+ if (highfr) {
+ ctrl |= (1 << 1);
+ }
+
+ LPC_SYSCTL->SYSOSCCTRL = ctrl;
+}
+
+/* Set USB PLL clock source */
+void Chip_Clock_SetUSBPLLSource(CHIP_SYSCTL_USBPLLCLKSRC_T src)
+{
+ LPC_SYSCTL->USBPLLCLKSEL = (uint32_t) src;
+ LPC_SYSCTL->USBPLLCLKUEN = 0;
+ LPC_SYSCTL->USBPLLCLKUEN = 1;
+}
+
+/* Set main system clock source */
+void Chip_Clock_SetMainClockSource(CHIP_SYSCTL_MAINCLKSRC_T src)
+{
+ LPC_SYSCTL->MAINCLKSEL = (uint32_t) src;
+ LPC_SYSCTL->MAINCLKUEN = 0;
+ LPC_SYSCTL->MAINCLKUEN = 1;
+}
+
+/* Set USB clock source and divider */
+void Chip_Clock_SetUSBClockSource(CHIP_SYSCTL_USBCLKSRC_T src, uint32_t div)
+{
+ LPC_SYSCTL->USBCLKSEL = (uint32_t) src;
+ LPC_SYSCTL->USBCLKUEN = 0;
+ LPC_SYSCTL->USBCLKUEN = 1;
+ LPC_SYSCTL->USBCLKDIV = div;
+}
+
+/* Set CLKOUT clock source and divider */
+void Chip_Clock_SetCLKOUTSource(CHIP_SYSCTL_CLKOUTSRC_T src, uint32_t div)
+{
+ LPC_SYSCTL->CLKOUTSEL = (uint32_t) src;
+ LPC_SYSCTL->CLKOUTUEN = 0;
+ LPC_SYSCTL->CLKOUTUEN = 1;
+ LPC_SYSCTL->CLKOUTDIV = div;
+}
+
+/* Return estimated watchdog oscillator rate */
+uint32_t Chip_Clock_GetWDTOSCRate(void)
+{
+ return Chip_Clock_GetWDTRate(LPC_SYSCTL->WDTOSCCTRL);
+}
+
+/* Return System PLL input clock rate */
+uint32_t Chip_Clock_GetSystemPLLInClockRate(void)
+{
+ uint32_t clkRate;
+
+ switch ((CHIP_SYSCTL_PLLCLKSRC_T) (LPC_SYSCTL->SYSPLLCLKSEL & 0x3)) {
+ case SYSCTL_PLLCLKSRC_IRC:
+ clkRate = Chip_Clock_GetIntOscRate();
+ break;
+
+ case SYSCTL_PLLCLKSRC_MAINOSC:
+ clkRate = Chip_Clock_GetMainOscRate();
+ break;
+
+ case SYSCTL_PLLCLKSRC_RTC32K:
+ clkRate = Chip_Clock_GetRTCOscRate();
+ break;
+
+ default:
+ clkRate = 0;
+ }
+
+ return clkRate;
+}
+
+/* Return System PLL output clock rate */
+uint32_t Chip_Clock_GetSystemPLLOutClockRate(void)
+{
+ return Chip_Clock_GetPLLFreq(LPC_SYSCTL->SYSPLLCTRL,
+ Chip_Clock_GetSystemPLLInClockRate());
+}
+
+/* Return USB PLL input clock rate */
+uint32_t Chip_Clock_GetUSBPLLInClockRate(void)
+{
+ uint32_t clkRate;
+
+ switch ((CHIP_SYSCTL_USBPLLCLKSRC_T) (LPC_SYSCTL->USBPLLCLKSEL & 0x3)) {
+ case SYSCTL_PLLCLKSRC_IRC:
+ clkRate = Chip_Clock_GetIntOscRate();
+ break;
+
+ case SYSCTL_PLLCLKSRC_MAINOSC:
+ clkRate = Chip_Clock_GetMainOscRate();
+ break;
+
+ default:
+ clkRate = 0;
+ }
+
+ return clkRate;
+}
+
+/* Return USB PLL output clock rate */
+uint32_t Chip_Clock_GetUSBPLLOutClockRate(void)
+{
+ return Chip_Clock_GetPLLFreq(LPC_SYSCTL->USBPLLCTRL,
+ Chip_Clock_GetUSBPLLInClockRate());
+}
+
+/* Return main clock rate */
+uint32_t Chip_Clock_GetMainClockRate(void)
+{
+ uint32_t clkRate = 0;
+
+ switch ((CHIP_SYSCTL_MAINCLKSRC_T) (LPC_SYSCTL->MAINCLKSEL & 0x3)) {
+ case SYSCTL_MAINCLKSRC_IRC:
+ clkRate = Chip_Clock_GetIntOscRate();
+ break;
+
+ case SYSCTL_MAINCLKSRC_PLLIN:
+ clkRate = Chip_Clock_GetSystemPLLInClockRate();
+ break;
+
+ case SYSCTL_MAINCLKSRC_WDTOSC:
+ clkRate = Chip_Clock_GetWDTOSCRate();
+ break;
+
+ case SYSCTL_MAINCLKSRC_PLLOUT:
+ clkRate = Chip_Clock_GetSystemPLLOutClockRate();
+ break;
+ }
+
+ return clkRate;
+}
+
+/* Return system clock rate */
+uint32_t Chip_Clock_GetSystemClockRate(void)
+{
+ /* No point in checking for divide by 0 */
+ return Chip_Clock_GetMainClockRate() / LPC_SYSCTL->SYSAHBCLKDIV;
+}
diff --git a/source/lpc_chip_11u6x/src/crc_11u6x.c b/source/lpc_chip_11u6x/src/crc_11u6x.c
new file mode 100644
index 0000000..802fa1e
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/crc_11u6x.c
@@ -0,0 +1,117 @@
+/*
+ * @brief LPC11u6x Cyclic Redundancy Check (CRC) Engine driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licenser disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initialize CRC engine */
+void Chip_CRC_Init(void)
+{
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_CRC);
+}
+
+/* De-initialize CRC engine */
+void Chip_CRC_Deinit(void)
+{
+ Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_CRC);
+}
+
+/* Sets up the CRC engine with defaults based on the polynomial to be used */
+void Chip_CRC_UseDefaultConfig(CRC_POLY_T poly)
+{
+ switch (poly) {
+ case CRC_POLY_CRC16:
+ Chip_CRC_UseCRC16();
+ break;
+
+ case CRC_POLY_CRC32:
+ Chip_CRC_UseCRC32();
+ break;
+
+ case CRC_POLY_CCITT:
+ default:
+ Chip_CRC_UseCCITT();
+ break;
+ }
+}
+
+/* configure CRC engine and compute CCITT checksum from 8-bit data */
+uint32_t Chip_CRC_CRC8(const uint8_t *data, uint32_t bytes)
+{
+ Chip_CRC_UseCCITT();
+ while (bytes > 0) {
+ Chip_CRC_Write8(*data);
+ data++;
+ bytes--;
+ }
+
+ return Chip_CRC_Sum();
+}
+
+/* Convenience function for computing a standard CRC16 checksum from 16-bit data block */
+uint32_t Chip_CRC_CRC16(const uint16_t *data, uint32_t hwords)
+{
+ Chip_CRC_UseCRC16();
+ while (hwords > 0) {
+ Chip_CRC_Write16(*data);
+ data++;
+ hwords--;
+ }
+
+ return Chip_CRC_Sum();
+}
+
+/* Convenience function for computing a standard CRC32 checksum from 32-bit data block */
+uint32_t Chip_CRC_CRC32(const uint32_t *data, uint32_t words)
+{
+ Chip_CRC_UseCRC32();
+ while (words > 0) {
+ Chip_CRC_Write32(*data);
+ data++;
+ words--;
+ }
+
+ return Chip_CRC_Sum();
+}
diff --git a/source/lpc_chip_11u6x/src/dma_11u6x.c b/source/lpc_chip_11u6x/src/dma_11u6x.c
new file mode 100644
index 0000000..294a769
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/dma_11u6x.c
@@ -0,0 +1,115 @@
+/*
+ * @brief LPC11u6x DMA chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/* DMA SRAM table - this can be optionally used with the Chip_DMA_SetSRAMBase()
+ function if a DMA SRAM table is needed. This table is correctly aligned for
+ the DMA controller. */
+#if defined(__CC_ARM)
+/* Keil alignement to 256 bytes */
+__align(256) DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL];
+#endif /* defined (__CC_ARM) */
+
+/* IAR support */
+#if defined(__ICCARM__)
+/* IAR EWARM alignement to 256 bytes */
+#pragma data_alignment=256
+DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL];
+#endif /* defined (__ICCARM__) */
+
+#if defined( __GNUC__ )
+/* GNU alignement to 256 bytes */
+DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL] __attribute__ ((aligned(256)));
+#endif /* defined (__GNUC__) */
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Set DMA transfer register interrupt bits (safe) */
+void Chip_DMA_SetTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask)
+{
+ uint32_t temp;
+
+ /* Read and write values may not be the same, write 0 to
+ undefined bits */
+ temp = pDMA->DMACH[ch].XFERCFG & ~0xFC000CC0;
+
+ pDMA->DMACH[ch].XFERCFG = temp | mask;
+}
+
+/* Clear DMA transfer register interrupt bits (safe) */
+void Chip_DMA_ClearTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask)
+{
+ uint32_t temp;
+
+ /* Read and write values may not be the same, write 0 to
+ undefined bits */
+ temp = pDMA->DMACH[ch].XFERCFG & ~0xFC000CC0;
+
+ pDMA->DMACH[ch].XFERCFG = temp & ~mask;
+}
+
+/* Update the transfer size in an existing DMA channel transfer configuration */
+void Chip_DMA_SetupChannelTransferSize(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t trans)
+{
+ Chip_DMA_ClearTranBits(pDMA, ch, (0x3FF << 16));
+ Chip_DMA_SetTranBits(pDMA, ch, DMA_XFERCFG_XFERCOUNT(trans));
+}
+
+/* Sets up a DMA channel with the passed DMA transfer descriptor */
+bool Chip_DMA_SetupTranChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch, DMA_CHDESC_T *desc)
+{
+ bool good = false;
+ DMA_CHDESC_T *pDesc = (DMA_CHDESC_T *) pDMA->SRAMBASE;
+
+ if ((Chip_DMA_GetActiveChannels(pDMA) & (1 << ch)) == 0) {
+ /* Channel is not active, so update the descriptor */
+ pDesc[ch] = *desc;
+
+ good = true;
+ }
+
+ return good;
+}
diff --git a/source/lpc_chip_11u6x/src/gpio_11u6x.c b/source/lpc_chip_11u6x/src/gpio_11u6x.c
new file mode 100644
index 0000000..63d7123
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/gpio_11u6x.c
@@ -0,0 +1,104 @@
+/*
+ * @brief LPC11u6x GPIO driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initialize GPIO block */
+void Chip_GPIO_Init(LPC_GPIO_T *pGPIO)
+{
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPIO);
+}
+
+/* De-Initialize GPIO block */
+void Chip_GPIO_DeInit(LPC_GPIO_T *pGPIO)
+{
+ Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_GPIO);
+}
+
+/* Set a GPIO direction */
+void Chip_GPIO_WriteDirBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t bit, bool setting)
+{
+ if (setting) {
+ pGPIO->DIR[port] |= 1UL << bit;
+ }
+ else {
+ pGPIO->DIR[port] &= ~(1UL << bit);
+ }
+}
+
+/* Set Direction for a GPIO port */
+void Chip_GPIO_SetDir(LPC_GPIO_T *pGPIO, uint8_t portNum, uint32_t bitValue, uint8_t out)
+{
+ if (out) {
+ pGPIO->DIR[portNum] |= bitValue;
+ }
+ else {
+ pGPIO->DIR[portNum] &= ~bitValue;
+ }
+}
+
+/* Set GPIO direction for a single GPIO pin */
+void Chip_GPIO_SetPinDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin, bool output)
+{
+ if (output) {
+ Chip_GPIO_SetPinDIROutput(pGPIO, port, pin);
+ }
+ else {
+ Chip_GPIO_SetPinDIRInput(pGPIO, port, pin);
+ }
+}
+
+/* Set GPIO direction for a all selected GPIO pins to an input or output */
+void Chip_GPIO_SetPortDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask, bool outSet)
+{
+ if (outSet) {
+ Chip_GPIO_SetPortDIROutput(pGPIO, port, pinMask);
+ }
+ else {
+ Chip_GPIO_SetPortDIRInput(pGPIO, port, pinMask);
+ }
+}
diff --git a/source/lpc_chip_11u6x/src/gpiogroup_11u6x.c b/source/lpc_chip_11u6x/src/gpiogroup_11u6x.c
new file mode 100644
index 0000000..34f9840
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/gpiogroup_11u6x.c
@@ -0,0 +1,48 @@
+/*
+ * @brief LPC11U6x GPIO group driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
diff --git a/source/lpc_chip_11u6x/src/i2c_11u6x.c b/source/lpc_chip_11u6x/src/i2c_11u6x.c
new file mode 100644
index 0000000..7efad75
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/i2c_11u6x.c
@@ -0,0 +1,554 @@
+/*
+ * @brief LPC11u6x I2C driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/* Control flags */
+#define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA)
+#define LPC_I2Cx(id) ((i2c[id].ip))
+#define SLAVE_ACTIVE(iic) (((iic)->flags & 0xFF00) != 0)
+
+/* I2C common interface structure */
+struct i2c_interface {
+ LPC_I2C_T *ip; /* IP base address of the I2C device */
+ CHIP_SYSCTL_CLOCK_T clk; /* Clock used by I2C */
+ I2C_EVENTHANDLER_T mEvent; /* Current active Master event handler */
+ I2C_EVENTHANDLER_T sEvent; /* Slave transfer events */
+ I2C_XFER_T *mXfer; /* Current active xfer pointer */
+ I2C_XFER_T *sXfer; /* Pointer to store xfer when bus is busy */
+ uint32_t flags; /* Flags used by I2C master and slave */
+};
+
+/* Slave interface structure */
+struct i2c_slave_interface {
+ I2C_XFER_T *xfer;
+ I2C_EVENTHANDLER_T event;
+};
+
+/* I2C interfaces */
+static struct i2c_interface i2c[I2C_NUM_INTERFACE] = {
+ {LPC_I2C0, SYSCTL_CLOCK_I2C0, Chip_I2C_EventHandler, NULL, NULL, NULL, 0},
+ {LPC_I2C1, SYSCTL_CLOCK_I2C1, Chip_I2C_EventHandler, NULL, NULL, NULL, 0}
+};
+
+static struct i2c_slave_interface i2c_slave[I2C_NUM_INTERFACE][I2C_SLAVE_NUM_INTERFACE];
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+STATIC INLINE void enableClk(I2C_ID_T id)
+{
+ Chip_Clock_EnablePeriphClock(i2c[id].clk);
+}
+
+STATIC INLINE void disableClk(I2C_ID_T id)
+{
+ Chip_Clock_DisablePeriphClock(i2c[id].clk);
+}
+
+/* Get the ADC Clock Rate */
+STATIC INLINE uint32_t getClkRate(I2C_ID_T id)
+{
+ return Chip_Clock_GetMainClockRate();
+}
+
+/* Enable I2C and start master transfer */
+STATIC INLINE void startMasterXfer(LPC_I2C_T *pI2C)
+{
+ /* Reset STA, STO, SI */
+ pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA;
+
+ /* Enter to Master Transmitter mode */
+ pI2C->CONSET = I2C_CON_I2EN | I2C_CON_STA;
+}
+
+/* Enable I2C and enable slave transfers */
+STATIC INLINE void startSlaverXfer(LPC_I2C_T *pI2C)
+{
+ /* Reset STA, STO, SI */
+ pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA;
+
+ /* Enter to Master Transmitter mode */
+ pI2C->CONSET = I2C_CON_I2EN | I2C_CON_AA;
+}
+
+/* Check if I2C bus is free */
+STATIC INLINE int isI2CBusFree(LPC_I2C_T *pI2C)
+{
+ return !(pI2C->CONSET & I2C_CON_STO);
+}
+
+/* Get current state of the I2C peripheral */
+STATIC INLINE int getCurState(LPC_I2C_T *pI2C)
+{
+ return (int) (pI2C->STAT & I2C_STAT_CODE_BITMASK);
+}
+
+/* Check if the active state belongs to master mode*/
+STATIC INLINE int isMasterState(LPC_I2C_T *pI2C)
+{
+ return getCurState(pI2C) < 0x60;
+}
+
+/* Set OWN slave address for specific slave ID */
+STATIC void setSlaveAddr(LPC_I2C_T *pI2C, I2C_SLAVE_ID sid, uint8_t addr, uint8_t mask)
+{
+ uint32_t index = (uint32_t) sid - 1;
+ pI2C->MASK[index] = mask;
+ if (sid == I2C_SLAVE_0) {
+ pI2C->ADR0 = addr;
+ }
+ else {
+ volatile uint32_t *abase = &pI2C->ADR1;
+ abase[index - 1] = addr;
+ }
+}
+
+/* Match the slave address */
+STATIC int isSlaveAddrMatching(uint8_t addr1, uint8_t addr2, uint8_t mask)
+{
+ mask |= 1;
+ return (addr1 & ~mask) == (addr2 & ~mask);
+}
+
+/* Get the index of the active slave */
+STATIC I2C_SLAVE_ID lookupSlaveIndex(LPC_I2C_T *pI2C, uint8_t slaveAddr)
+{
+ if (!(slaveAddr >> 1)) {
+ return I2C_SLAVE_GENERAL; /* General call address */
+ }
+ if (isSlaveAddrMatching(pI2C->ADR0, slaveAddr, pI2C->MASK[0])) {
+ return I2C_SLAVE_0;
+ }
+ if (isSlaveAddrMatching(pI2C->ADR1, slaveAddr, pI2C->MASK[1])) {
+ return I2C_SLAVE_1;
+ }
+ if (isSlaveAddrMatching(pI2C->ADR2, slaveAddr, pI2C->MASK[2])) {
+ return I2C_SLAVE_2;
+ }
+ if (isSlaveAddrMatching(pI2C->ADR3, slaveAddr, pI2C->MASK[3])) {
+ return I2C_SLAVE_3;
+ }
+
+ /* If everything is fine the code should never come here */
+ return I2C_SLAVE_GENERAL;
+}
+
+/* Master transfer state change handler handler */
+int handleMasterXferState(LPC_I2C_T *pI2C, I2C_XFER_T *xfer)
+{
+ uint32_t cclr = I2C_CON_FLAGS;
+
+ switch (getCurState(pI2C)) {
+ case 0x08: /* Start condition on bus */
+ case 0x10: /* Repeated start condition */
+ pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0);
+ break;
+
+ /* Tx handling */
+ case 0x18: /* SLA+W sent and ACK received */
+ case 0x28: /* DATA sent and ACK received */
+ if (!xfer->txSz) {
+ cclr &= ~(xfer->rxSz ? I2C_CON_STA : I2C_CON_STO);
+ }
+ else {
+ pI2C->DAT = *xfer->txBuff++;
+ xfer->txSz--;
+ }
+ break;
+
+ /* Rx handling */
+ case 0x58: /* Data Received and NACK sent */
+ cclr &= ~I2C_CON_STO;
+
+ case 0x50: /* Data Received and ACK sent */
+ *xfer->rxBuff++ = pI2C->DAT;
+ xfer->rxSz--;
+
+ case 0x40: /* SLA+R sent and ACK received */
+ if (xfer->rxSz > 1) {
+ cclr &= ~I2C_CON_AA;
+ }
+ break;
+
+ /* NAK Handling */
+ case 0x20: /* SLA+W sent NAK received */
+ case 0x48: /* SLA+R sent NAK received */
+ xfer->status = I2C_STATUS_SLAVENAK;
+ cclr &= ~I2C_CON_STO;
+ break;
+
+ case 0x30: /* DATA sent NAK received */
+ xfer->status = I2C_STATUS_NAK;
+ cclr &= ~I2C_CON_STO;
+ break;
+
+ case 0x38: /* Arbitration lost */
+ xfer->status = I2C_STATUS_ARBLOST;
+ break;
+
+ /* Bus Error */
+ case 0x00:
+ xfer->status = I2C_STATUS_BUSERR;
+ cclr &= ~I2C_CON_STO;
+ }
+
+ /* Set clear control flags */
+ pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
+ pI2C->CONCLR = cclr;
+
+ /* If stopped return 0 */
+ if (!(cclr & I2C_CON_STO) || (xfer->status == I2C_STATUS_ARBLOST)) {
+ if (xfer->status == I2C_STATUS_BUSY) {
+ xfer->status = I2C_STATUS_DONE;
+ }
+ return 0;
+ }
+ return 1;
+}
+
+/* Find the slave address of SLA+W or SLA+R */
+I2C_SLAVE_ID getSlaveIndex(LPC_I2C_T *pI2C)
+{
+ switch (getCurState(pI2C)) {
+ case 0x60:
+ case 0x68:
+ case 0x70:
+ case 0x78:
+ case 0xA8:
+ case 0xB0:
+ return lookupSlaveIndex(pI2C, pI2C->DAT);
+ }
+
+ /* If everything is fine code should never come here */
+ return I2C_SLAVE_GENERAL;
+}
+
+/* Slave state machine handler */
+int handleSlaveXferState(LPC_I2C_T *pI2C, I2C_XFER_T *xfer)
+{
+ uint32_t cclr = I2C_CON_FLAGS;
+ int ret = RET_SLAVE_BUSY;
+
+ xfer->status = I2C_STATUS_BUSY;
+ switch (getCurState(pI2C)) {
+ case 0x80: /* SLA: Data received + ACK sent */
+ case 0x90: /* GC: Data received + ACK sent */
+ *xfer->rxBuff++ = pI2C->DAT;
+ xfer->rxSz--;
+ ret = RET_SLAVE_RX;
+ if (xfer->rxSz > 1) {
+ cclr &= ~I2C_CON_AA;
+ }
+ break;
+
+ case 0x60: /* Own SLA+W received */
+ case 0x68: /* Own SLA+W received after losing arbitration */
+ case 0x70: /* GC+W received */
+ case 0x78: /* GC+W received after losing arbitration */
+ xfer->slaveAddr = pI2C->DAT & ~1;
+ if (xfer->rxSz > 1) {
+ cclr &= ~I2C_CON_AA;
+ }
+ break;
+
+ case 0xA8: /* SLA+R received */
+ case 0xB0: /* SLA+R received after losing arbitration */
+ xfer->slaveAddr = pI2C->DAT & ~1;
+
+ case 0xB8: /* DATA sent and ACK received */
+ pI2C->DAT = *xfer->txBuff++;
+ xfer->txSz--;
+ if (xfer->txSz > 0) {
+ cclr &= ~I2C_CON_AA;
+ }
+ ret = RET_SLAVE_TX;
+ break;
+
+ case 0xC0: /* Data transmitted and NAK received */
+ case 0xC8: /* Last data transmitted and ACK received */
+ case 0x88: /* SLA: Data received + NAK sent */
+ case 0x98: /* GC: Data received + NAK sent */
+ case 0xA0: /* STOP/Repeated START condition received */
+ ret = RET_SLAVE_IDLE;
+ cclr &= ~I2C_CON_AA;
+ xfer->status = I2C_STATUS_DONE;
+ if (xfer->slaveAddr & 1) {
+ cclr &= ~I2C_CON_STA;
+ }
+ break;
+ }
+
+ /* Set clear control flags */
+ pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
+ pI2C->CONCLR = cclr;
+
+ return ret;
+}
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Chip event handler interrupt based */
+void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event)
+{
+ struct i2c_interface *iic = &i2c[id];
+ volatile I2C_STATUS_T *stat;
+
+ /* Only WAIT event needs to be handled */
+ if (event != I2C_EVENT_WAIT) {
+ return;
+ }
+
+ stat = &iic->mXfer->status;
+ /* Wait for the status to change */
+ while (*stat == I2C_STATUS_BUSY) {}
+}
+
+/* Chip polling event handler */
+void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event)
+{
+ struct i2c_interface *iic = &i2c[id];
+ volatile I2C_STATUS_T *stat;
+
+ /* Only WAIT event needs to be handled */
+ if (event != I2C_EVENT_WAIT) {
+ return;
+ }
+
+ stat = &iic->mXfer->status;
+ /* Call the state change handler till xfer is done */
+ while (*stat == I2C_STATUS_BUSY) {
+ if (Chip_I2C_IsStateChanged(id)) {
+ Chip_I2C_MasterStateHandler(id);
+ }
+ }
+}
+
+/* Initializes the LPC_I2C peripheral with specified parameter */
+void Chip_I2C_Init(I2C_ID_T id)
+{
+ enableClk(id);
+
+ /* Set I2C operation to default */
+ LPC_I2Cx(id)->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN);
+}
+
+/* De-initializes the I2C peripheral registers to their default reset values */
+void Chip_I2C_DeInit(I2C_ID_T id)
+{
+ /* Disable I2C control */
+ LPC_I2Cx(id)->CONCLR = I2C_CON_I2EN | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA;
+
+ disableClk(id);
+}
+
+/* Set up clock rate for LPC_I2C peripheral */
+void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate)
+{
+ uint32_t SCLValue;
+
+ SCLValue = (getClkRate(id) / clockrate);
+ LPC_I2Cx(id)->SCLH = (uint32_t) (SCLValue >> 1);
+ LPC_I2Cx(id)->SCLL = (uint32_t) (SCLValue - LPC_I2Cx(id)->SCLH);
+}
+
+/* Get current clock rate for LPC_I2C peripheral */
+uint32_t Chip_I2C_GetClockRate(I2C_ID_T id)
+{
+ return getClkRate(id) / (LPC_I2Cx(id)->SCLH + LPC_I2Cx(id)->SCLL);
+}
+
+/* Set the master event handler */
+int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event)
+{
+ struct i2c_interface *iic = &i2c[id];
+ if (!iic->mXfer) {
+ iic->mEvent = event;
+ }
+ return iic->mEvent == event;
+}
+
+/* Get the master event handler */
+I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id)
+{
+ return i2c[id].mEvent;
+}
+
+/* Transmit and Receive data in master mode */
+int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer)
+{
+ struct i2c_interface *iic = &i2c[id];
+
+ iic->mEvent(id, I2C_EVENT_LOCK);
+ xfer->status = I2C_STATUS_BUSY;
+ iic->mXfer = xfer;
+
+ /* If slave xfer not in progress */
+ if (!iic->sXfer) {
+ startMasterXfer(iic->ip);
+ }
+ iic->mEvent(id, I2C_EVENT_WAIT);
+ iic->mXfer = 0;
+
+ /* Wait for stop condition to appear on bus */
+ while (!isI2CBusFree(iic->ip)) {}
+
+ /* Start slave if one is active */
+ if (SLAVE_ACTIVE(iic)) {
+ startSlaverXfer(iic->ip);
+ }
+
+ iic->mEvent(id, I2C_EVENT_UNLOCK);
+ return (int) xfer->status;
+}
+
+/* Master tx only */
+int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len)
+{
+ I2C_XFER_T xfer = {0};
+ xfer.slaveAddr = slaveAddr;
+ xfer.txBuff = buff;
+ xfer.txSz = len;
+ while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
+ return len - xfer.txSz;
+}
+
+/* Transmit one byte and receive an array of bytes after a repeated start condition is generated in Master mode.
+ * This function is useful for communicating with the I2C slave registers
+ */
+int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len)
+{
+ I2C_XFER_T xfer = {0};
+ xfer.slaveAddr = slaveAddr;
+ xfer.txBuff = &cmd;
+ xfer.txSz = 1;
+ xfer.rxBuff = buff;
+ xfer.rxSz = len;
+ while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
+ return len - xfer.rxSz;
+}
+
+/* Sequential master read */
+int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len)
+{
+ I2C_XFER_T xfer = {0};
+ xfer.slaveAddr = slaveAddr;
+ xfer.rxBuff = buff;
+ xfer.rxSz = len;
+ while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {}
+ return len - xfer.rxSz;
+}
+
+/* Check if master state is active */
+int Chip_I2C_IsMasterActive(I2C_ID_T id)
+{
+ return isMasterState(i2c[id].ip);
+}
+
+/* State change handler for master transfer */
+void Chip_I2C_MasterStateHandler(I2C_ID_T id)
+{
+ if (!handleMasterXferState(i2c[id].ip, i2c[id].mXfer)) {
+ i2c[id].mEvent(id, I2C_EVENT_DONE);
+ }
+}
+
+/* Setup slave function */
+void Chip_I2C_SlaveSetup(I2C_ID_T id,
+ I2C_SLAVE_ID sid,
+ I2C_XFER_T *xfer,
+ I2C_EVENTHANDLER_T event,
+ uint8_t addrMask)
+{
+ struct i2c_interface *iic = &i2c[id];
+ struct i2c_slave_interface *si2c = &i2c_slave[id][sid];
+ si2c->xfer = xfer;
+ si2c->event = event;
+
+ /* Set up the slave address */
+ if (sid != I2C_SLAVE_GENERAL) {
+ setSlaveAddr(iic->ip, sid, xfer->slaveAddr, addrMask);
+ }
+
+ if (!SLAVE_ACTIVE(iic) && !iic->mXfer) {
+ startSlaverXfer(iic->ip);
+ }
+ iic->flags |= 1 << (sid + 8);
+}
+
+/* I2C Slave event handler */
+void Chip_I2C_SlaveStateHandler(I2C_ID_T id)
+{
+ int ret;
+ struct i2c_interface *iic = &i2c[id];
+
+ /* Get the currently addressed slave */
+ if (!iic->sXfer) {
+ struct i2c_slave_interface *si2c;
+
+ I2C_SLAVE_ID sid = getSlaveIndex(iic->ip);
+ si2c = &i2c_slave[id][sid];
+ iic->sXfer = si2c->xfer;
+ iic->sEvent = si2c->event;
+ }
+
+ iic->sXfer->slaveAddr |= iic->mXfer != 0;
+ ret = handleSlaveXferState(iic->ip, iic->sXfer);
+ if (ret) {
+ if (iic->sXfer->status == I2C_STATUS_DONE) {
+ iic->sXfer = 0;
+ }
+ iic->sEvent(id, (I2C_EVENT_T) ret);
+ }
+}
+
+/* Disable I2C device */
+void Chip_I2C_Disable(I2C_ID_T id)
+{
+ LPC_I2Cx(id)->CONCLR = I2C_I2CONCLR_I2ENC;
+}
+
+/* State change checking */
+int Chip_I2C_IsStateChanged(I2C_ID_T id)
+{
+ return (LPC_I2Cx(id)->CONSET & I2C_CON_SI) != 0;
+}
diff --git a/source/lpc_chip_11u6x/src/i2cm_11u6x.c b/source/lpc_chip_11u6x/src/i2cm_11u6x.c
new file mode 100644
index 0000000..afc0c43
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/i2cm_11u6x.c
@@ -0,0 +1,197 @@
+/*
+ * @brief LPC11u6x I2C master driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/* Control flags */
+#define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA)
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initializes the LPC_I2C peripheral with specified parameter */
+void Chip_I2CM_Init(LPC_I2C_T *pI2C)
+{
+ CHIP_SYSCTL_CLOCK_T clk = SYSCTL_CLOCK_I2C0;
+ CHIP_SYSCTL_PERIPH_RESET_T rst = RESET_I2C0;
+
+ if (pI2C == LPC_I2C1) {
+ clk = SYSCTL_CLOCK_I2C1;
+ rst = RESET_I2C1;
+ }
+ /* Enable I2C clock */
+ Chip_Clock_EnablePeriphClock(clk);
+
+ /* Peripheral reset control to I2C */
+ Chip_SYSCTL_PeriphReset(rst);
+}
+
+/* De-initializes the I2C peripheral registers to their default reset values */
+void Chip_I2CM_DeInit(LPC_I2C_T *pI2C)
+{
+ CHIP_SYSCTL_CLOCK_T clk = SYSCTL_CLOCK_I2C0;
+
+ if (pI2C == LPC_I2C1) {
+ clk = SYSCTL_CLOCK_I2C1;
+ }
+ /* Disable I2C clock */
+ Chip_Clock_DisablePeriphClock(clk);
+}
+
+/* Set up bus speed for LPC_I2C interface */
+void Chip_I2CM_SetBusSpeed(LPC_I2C_T *pI2C, uint32_t busSpeed)
+{
+ uint32_t clockDiv = (Chip_Clock_GetMainClockRate() / busSpeed);
+
+ Chip_I2CM_SetDutyCycle(pI2C, (clockDiv >> 1), (clockDiv - (clockDiv >> 1)));
+}
+
+/* Master transfer state change handler handler */
+uint32_t Chip_I2CM_XferHandler(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
+{
+ uint32_t cclr = I2C_CON_FLAGS;
+
+ switch (Chip_I2CM_GetCurState(pI2C)) {
+ case 0x08: /* Start condition on bus */
+ case 0x10: /* Repeated start condition */
+ pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0);
+ break;
+
+ /* Tx handling */
+ case 0x20: /* SLA+W sent NAK received */
+ case 0x30: /* DATA sent NAK received */
+ if ((xfer->options & I2CM_XFER_OPTION_IGNORE_NACK) == 0) {
+ xfer->status = I2CM_STATUS_NAK;
+ cclr &= ~I2C_CON_STO;
+ break;
+ }
+
+ case 0x18: /* SLA+W sent and ACK received */
+ case 0x28: /* DATA sent and ACK received */
+ if (!xfer->txSz) {
+ if (xfer->rxSz) {
+ cclr &= ~I2C_CON_STA;
+ }
+ else {
+ xfer->status = I2CM_STATUS_OK;
+ cclr &= ~I2C_CON_STO;
+ }
+
+ }
+ else {
+ pI2C->DAT = *xfer->txBuff++;
+ xfer->txSz--;
+ }
+ break;
+
+ /* Rx handling */
+ case 0x58: /* Data Received and NACK sent */
+ case 0x50: /* Data Received and ACK sent */
+ *xfer->rxBuff++ = pI2C->DAT;
+ xfer->rxSz--;
+
+ case 0x40: /* SLA+R sent and ACK received */
+ if ((xfer->rxSz > 1) || (xfer->options & I2CM_XFER_OPTION_LAST_RX_ACK)) {
+ cclr &= ~I2C_CON_AA;
+ }
+ if (xfer->rxSz == 0) {
+ xfer->status = I2CM_STATUS_OK;
+ cclr &= ~I2C_CON_STO;
+ }
+ break;
+
+ /* NAK Handling */
+ case 0x48: /* SLA+R sent NAK received */
+ xfer->status = I2CM_STATUS_SLAVE_NAK;
+ cclr &= ~I2C_CON_STO;
+ break;
+
+ case 0x38: /* Arbitration lost */
+ xfer->status = I2CM_STATUS_ARBLOST;
+ break;
+
+ case 0x00: /* Bus Error */
+ xfer->status = I2CM_STATUS_BUS_ERROR;
+ cclr &= ~I2C_CON_STO;
+ break;
+
+ default:
+ xfer->status = I2CM_STATUS_ERROR;
+ cclr &= ~I2C_CON_STO;
+ break;
+ }
+
+ /* Set clear control flags */
+ pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
+ pI2C->CONCLR = cclr;
+
+ return xfer->status != I2CM_STATUS_BUSY;
+}
+
+/* Transmit and Receive data in master mode */
+void Chip_I2CM_Xfer(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
+{
+ /* set the transfer status as busy */
+ xfer->status = I2CM_STATUS_BUSY;
+ /* Clear controller state. */
+ Chip_I2CM_ResetControl(pI2C);
+ /* Enter to Master Transmitter mode */
+ Chip_I2CM_SendStart(pI2C);
+}
+
+/* Transmit and Receive data in master mode */
+uint32_t Chip_I2CM_XferBlocking(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer)
+{
+ uint32_t ret = 0;
+ /* start transfer */
+ Chip_I2CM_Xfer(pI2C, xfer);
+
+ while (ret == 0) {
+ /* wait for status change interrupt */
+ while ( Chip_I2CM_StateChanged(pI2C) == 0) {}
+ /* call state change handler */
+ ret = Chip_I2CM_XferHandler(pI2C, xfer);
+ }
+ return ret;
+}
diff --git a/source/lpc_chip_11u6x/src/iocon_11u6x.c b/source/lpc_chip_11u6x/src/iocon_11u6x.c
new file mode 100644
index 0000000..a2352f8
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/iocon_11u6x.c
@@ -0,0 +1,82 @@
+/*
+ * @brief LPC11u6x IOCON driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Sets I/O Control pin mux */
+void Chip_IOCON_PinMuxSet(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint32_t modefunc)
+{
+ switch (port) {
+ case 0:
+ pIOCON->PIO0[pin] = modefunc;
+ break;
+
+ case 1:
+ pIOCON->PIO1[pin] = modefunc;
+ break;
+
+ case 2:
+ if (pin >= 2) {
+ pIOCON->PIO2B[pin - 2] = modefunc;
+ }
+ else {
+ pIOCON->PIO2A[pin] = modefunc;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*Set all I/O Control pin muxing*/
+void Chip_IOCON_SetPinMuxing(LPC_IOCON_T *pIOCON, const PINMUX_GRP_T* pinArray, uint32_t arrayLength)
+{
+ uint32_t ix;
+
+ for (ix = 0; ix < arrayLength; ix++ ) {
+ Chip_IOCON_PinMuxSet(pIOCON, pinArray[ix].port, pinArray[ix].pin, pinArray[ix].modefunc);
+ }
+}
diff --git a/source/lpc_chip_11u6x/src/pinint_11u6x.c b/source/lpc_chip_11u6x/src/pinint_11u6x.c
new file mode 100644
index 0000000..f540c24
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/pinint_11u6x.c
@@ -0,0 +1,77 @@
+/*
+ * @brief LPC11u6x Pin Interrupt and Pattern Match driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licenser disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Set source for pattern match engine */
+void Chip_PININT_SetPatternMatchSrc(LPC_PIN_INT_T *pPININT, uint8_t chan, Chip_PININT_BITSLICE_T slice)
+{
+ uint32_t pmsrc_reg;
+
+ /* Source source for pattern matching */
+ pmsrc_reg = pPININT->PMSRC & ~(PININT_SRC_BITSOURCE_MASK << (PININT_SRC_BITSOURCE_START + (slice * 3)));
+ pPININT->PMSRC = pmsrc_reg | (chan << (PININT_SRC_BITSOURCE_START + (slice * 3)));
+}
+
+/* Configure Pattern match engine */
+void Chip_PININT_SetPatternMatchConfig(LPC_PIN_INT_T *pPININT, Chip_PININT_BITSLICE_T slice,
+ Chip_PININT_BITSLICE_CFG_T slice_cfg, bool end_point)
+{
+ uint32_t pmcfg_reg;
+
+ /* Configure bit slice configuration */
+ pmcfg_reg = pPININT->PMCFG & ~(PININT_SRC_BITCFG_MASK << (PININT_SRC_BITCFG_START + (slice * 3)));
+ pPININT->PMCFG = pmcfg_reg | (slice_cfg << (PININT_SRC_BITCFG_START + (slice * 3)));
+
+ /* If end point is true, enable the bits */
+ if (end_point == true) {
+ /* By default slice 7 is final component */
+ if (slice != PININTBITSLICE7) {
+ pPININT->PMCFG |= (0x1 << slice);
+ }
+ }
+}
diff --git a/source/lpc_chip_11u6x/src/pmu_11u6x.c b/source/lpc_chip_11u6x/src/pmu_11u6x.c
new file mode 100644
index 0000000..9a6bacd
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/pmu_11u6x.c
@@ -0,0 +1,105 @@
+/*
+ * @brief LPC11u6x PMU chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Enter MCU Sleep mode */
+void Chip_PMU_SleepState(LPC_PMU_T *pPMU)
+{
+ pPMU->PCON = PMU_PCON_PM_SLEEP;
+
+ /* Enter sleep mode */
+ __WFI();
+}
+
+/* Enter MCU Deep Sleep mode */
+void Chip_PMU_DeepSleepState(LPC_PMU_T *pPMU)
+{
+ SCB->SCR |= (1UL << SCB_SCR_SLEEPDEEP_Pos);
+ pPMU->PCON = PMU_PCON_PM_DEEPSLEEP;
+
+ /* Enter sleep mode */
+ __WFI();
+}
+
+/* Enter MCU Power down mode */
+void Chip_PMU_PowerDownState(LPC_PMU_T *pPMU)
+{
+ SCB->SCR |= (1UL << SCB_SCR_SLEEPDEEP_Pos);
+ pPMU->PCON = PMU_PCON_PM_POWERDOWN;
+
+ /* Enter sleep mode */
+ __WFI();
+}
+
+/* Enter MCU Deep Power down mode */
+void Chip_PMU_DeepPowerDownState(LPC_PMU_T *pPMU)
+{
+ SCB->SCR |= (1UL << SCB_SCR_SLEEPDEEP_Pos);
+ pPMU->PCON = PMU_PCON_PM_DEEPPOWERDOWN;
+
+ /* Enter sleep mode */
+ __WFI();
+}
+
+/* Put some of the peripheral in sleep mode */
+void Chip_PMU_Sleep(LPC_PMU_T *pPMU, CHIP_PMU_MCUPOWER_T SleepMode)
+{
+ if (SleepMode == PMU_MCU_DEEP_SLEEP) {
+ Chip_PMU_DeepSleepState(pPMU);
+ }
+ else if (SleepMode == PMU_MCU_POWER_DOWN) {
+ Chip_PMU_PowerDownState(pPMU);
+ }
+ else if (SleepMode == PMU_MCU_DEEP_PWRDOWN) {
+ Chip_PMU_DeepPowerDownState(pPMU);
+ }
+ else {
+ /* PMU_MCU_SLEEP */
+ Chip_PMU_SleepState(pPMU);
+ }
+}
diff --git a/source/lpc_chip_11u6x/src/ring_buffer.c b/source/lpc_chip_11u6x/src/ring_buffer.c
new file mode 100644
index 0000000..47a0c34
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/ring_buffer.c
@@ -0,0 +1,167 @@
+/*
+ * @brief Common ring buffer support functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2012
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include
+#include "ring_buffer.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+#define RB_INDH(rb) ((rb)->head & ((rb)->count - 1))
+#define RB_INDT(rb) ((rb)->tail & ((rb)->count - 1))
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initialize ring buffer */
+int RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count)
+{
+ RingBuff->data = buffer;
+ RingBuff->count = count;
+ RingBuff->itemSz = itemSize;
+ RingBuff->head = RingBuff->tail = 0;
+
+ return 1;
+}
+
+/* Insert a single item into Ring Buffer */
+int RingBuffer_Insert(RINGBUFF_T *RingBuff, const void *data)
+{
+ uint8_t *ptr = RingBuff->data;
+
+ /* We cannot insert when queue is full */
+ if (RingBuffer_IsFull(RingBuff))
+ return 0;
+
+ ptr += RB_INDH(RingBuff) * RingBuff->itemSz;
+ memcpy(ptr, data, RingBuff->itemSz);
+ RingBuff->head++;
+
+ return 1;
+}
+
+/* Insert multiple items into Ring Buffer */
+int RingBuffer_InsertMult(RINGBUFF_T *RingBuff, const void *data, int num)
+{
+ uint8_t *ptr = RingBuff->data;
+ int cnt1, cnt2;
+
+ /* We cannot insert when queue is full */
+ if (RingBuffer_IsFull(RingBuff))
+ return 0;
+
+ /* Calculate the segment lengths */
+ cnt1 = cnt2 = RingBuffer_GetFree(RingBuff);
+ if (RB_INDH(RingBuff) + cnt1 >= RingBuff->count)
+ cnt1 = RingBuff->count - RB_INDH(RingBuff);
+ cnt2 -= cnt1;
+
+ cnt1 = MIN(cnt1, num);
+ num -= cnt1;
+
+ cnt2 = MIN(cnt2, num);
+ num -= cnt2;
+
+ /* Write segment 1 */
+ ptr += RB_INDH(RingBuff) * RingBuff->itemSz;
+ memcpy(ptr, data, cnt1 * RingBuff->itemSz);
+ RingBuff->head += cnt1;
+
+ /* Write segment 2 */
+ ptr = (uint8_t *) RingBuff->data + RB_INDH(RingBuff) * RingBuff->itemSz;
+ data = (const uint8_t *) data + cnt1 * RingBuff->itemSz;
+ memcpy(ptr, data, cnt2 * RingBuff->itemSz);
+ RingBuff->head += cnt2;
+
+ return cnt1 + cnt2;
+}
+
+/* Pop single item from Ring Buffer */
+int RingBuffer_Pop(RINGBUFF_T *RingBuff, void *data)
+{
+ uint8_t *ptr = RingBuff->data;
+
+ /* We cannot pop when queue is empty */
+ if (RingBuffer_IsEmpty(RingBuff))
+ return 0;
+
+ ptr += RB_INDT(RingBuff) * RingBuff->itemSz;
+ memcpy(data, ptr, RingBuff->itemSz);
+ RingBuff->tail++;
+
+ return 1;
+}
+
+/* Pop multiple items from Ring buffer */
+int RingBuffer_PopMult(RINGBUFF_T *RingBuff, void *data, int num)
+{
+ uint8_t *ptr = RingBuff->data;
+ int cnt1, cnt2;
+
+ /* We cannot insert when queue is empty */
+ if (RingBuffer_IsEmpty(RingBuff))
+ return 0;
+
+ /* Calculate the segment lengths */
+ cnt1 = cnt2 = RingBuffer_GetCount(RingBuff);
+ if (RB_INDT(RingBuff) + cnt1 >= RingBuff->count)
+ cnt1 = RingBuff->count - RB_INDT(RingBuff);
+ cnt2 -= cnt1;
+
+ cnt1 = MIN(cnt1, num);
+ num -= cnt1;
+
+ cnt2 = MIN(cnt2, num);
+ num -= cnt2;
+
+ /* Write segment 1 */
+ ptr += RB_INDT(RingBuff) * RingBuff->itemSz;
+ memcpy(data, ptr, cnt1 * RingBuff->itemSz);
+ RingBuff->tail += cnt1;
+
+ /* Write segment 2 */
+ ptr = (uint8_t *) RingBuff->data + RB_INDT(RingBuff) * RingBuff->itemSz;
+ data = (uint8_t *) data + cnt1 * RingBuff->itemSz;
+ memcpy(data, ptr, cnt2 * RingBuff->itemSz);
+ RingBuff->tail += cnt2;
+
+ return cnt1 + cnt2;
+}
diff --git a/source/lpc_chip_11u6x/src/romdiv_11u6x.c b/source/lpc_chip_11u6x/src/romdiv_11u6x.c
new file mode 100644
index 0000000..093184a
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/romdiv_11u6x.c
@@ -0,0 +1,79 @@
+/*
+ * @brief Routines to overload "/" and "%" operator in C using ROM based divider library
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+#if !defined( __GNUC__ )
+
+/* Redirector of signed 32 bit integer divider to ROM routine */
+int __aeabi_idiv(int numerator, int denominator)
+{
+ ROM_DIV_API_T const *pROMDiv = LPC_ROM_API->divApiBase;
+ return pROMDiv->sidiv(numerator, denominator);
+}
+
+/* Redirector of unsigned 32 bit integer divider to ROM routine */
+unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator)
+{
+ ROM_DIV_API_T const *pROMDiv = LPC_ROM_API->divApiBase;
+ return pROMDiv->uidiv(numerator, denominator);
+}
+
+/* Redirector of signed 32 bit integer divider with reminder to ROM routine */
+__value_in_regs IDIV_RETURN_T __aeabi_idivmod(int numerator, int denominator)
+{
+ ROM_DIV_API_T const *pROMDiv = LPC_ROM_API->divApiBase;
+ return pROMDiv->sidivmod(numerator, denominator);
+}
+
+/* Redirector of unsigned 32 bit integer divider with reminder to ROM routine */
+__value_in_regs UIDIV_RETURN_T __aeabi_uidivmod(unsigned numerator, unsigned denominator)
+{
+ ROM_DIV_API_T const *pROMDiv = LPC_ROM_API->divApiBase;
+ return pROMDiv->uidivmod(numerator, denominator);
+}
+
+#endif /* !defined( __GNUC__ ) */
diff --git a/source/lpc_chip_11u6x/src/rtc_11u6x.c b/source/lpc_chip_11u6x/src/rtc_11u6x.c
new file mode 100644
index 0000000..a577a90
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/rtc_11u6x.c
@@ -0,0 +1,60 @@
+/*
+ * @brief LPC11u6x RTC chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initialize the RTC peripheral */
+void Chip_RTC_Init(LPC_RTC_T *pRTC)
+{
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_RTC);
+}
+
+/* De-initialize the RTC peripheral */
+void Chip_RTC_DeInit(LPC_RTC_T *pRTC)
+{
+ Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_RTC);
+}
diff --git a/source/lpc_chip_11u6x/src/sct_11u6x.c b/source/lpc_chip_11u6x/src/sct_11u6x.c
new file mode 100644
index 0000000..fa014bc
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/sct_11u6x.c
@@ -0,0 +1,98 @@
+/*
+ * @brief LPC11u6x State Configurable Timer driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/* SCT clock shared count flag */
+static uint8_t sctUsedCount;
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initialize SCT */
+void Chip_SCT_Init(LPC_SCT_T *pSCT)
+{
+ if (sctUsedCount == 0) {
+ /* Does not handle unbalanced Init() and DeInit() calls */
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SCT0_1);
+ }
+ sctUsedCount++;
+
+ if (pSCT == LPC_SCT0) {
+ Chip_SYSCTL_PeriphReset(RESET_SCT0);
+ }
+ else {
+ Chip_SYSCTL_PeriphReset(RESET_SCT1);
+ }
+}
+
+/* Shutdown SCT */
+void Chip_SCT_DeInit(LPC_SCT_T *pSCT)
+{
+ sctUsedCount--;
+ if (sctUsedCount == 0) {
+ /* Does not handle unbalanced Init() and DeInit() calls */
+ Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SCT0_1);
+ }
+}
+
+/* Set/Clear SCT control register */
+void Chip_SCT_SetClrControl(LPC_SCT_T *pSCT, uint32_t value, FunctionalState ena)
+{
+ if (ena == ENABLE) {
+ Chip_SCT_SetControl(pSCT, value);
+ }
+ else {
+ Chip_SCT_ClearControl(pSCT, value);
+ }
+}
+
+/* Set Conflict resolution */
+void Chip_SCT_SetConflictResolution(LPC_SCT_T *pSCT, uint8_t outnum, uint8_t value)
+{
+ uint32_t tem;
+
+ tem = pSCT->RES & (~(0x03 << (2 * outnum)));
+ pSCT->RES = tem | (value << (2 * outnum));
+}
diff --git a/source/lpc_chip_11u6x/src/ssp_11u6x.c b/source/lpc_chip_11u6x/src/ssp_11u6x.c
new file mode 100644
index 0000000..a35eb90
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/ssp_11u6x.c
@@ -0,0 +1,493 @@
+/*
+ * @brief LPC11u6x SSP Registers and control functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+STATIC void SSP_Write2BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
+{
+ if (xf_setup->tx_data) {
+ Chip_SSP_SendFrame(pSSP, (*(uint16_t *) ((uint32_t) xf_setup->tx_data +
+ xf_setup->tx_cnt)));
+ xf_setup->tx_cnt += 2;
+ }
+ else {
+ Chip_SSP_SendFrame(pSSP, 0xFFFF);
+ }
+}
+
+/** SSP macro: write 1 bytes to FIFO buffer */
+STATIC void SSP_Write1BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
+{
+ if (xf_setup->tx_data) {
+ Chip_SSP_SendFrame(pSSP, (*(uint8_t *) ((uint32_t) xf_setup->tx_data + xf_setup->tx_cnt)));
+ }
+ else {
+ Chip_SSP_SendFrame(pSSP, 0xFF);
+ }
+
+ xf_setup->tx_cnt++;
+}
+
+/** SSP macro: read 1 bytes from FIFO buffer */
+STATIC void SSP_Read2BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
+{
+ uint16_t rDat;
+
+ while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) &&
+ (xf_setup->rx_cnt < xf_setup->length)) {
+ rDat = Chip_SSP_ReceiveFrame(pSSP);
+ if (xf_setup->rx_data) {
+ *(uint16_t *) ((uint32_t) xf_setup->rx_data + xf_setup->rx_cnt) = rDat;
+ xf_setup->rx_cnt += 2;
+ }
+ }
+}
+
+/** SSP macro: read 2 bytes from FIFO buffer */
+STATIC void SSP_Read1BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
+{
+ uint16_t rDat;
+
+ while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) &&
+ (xf_setup->rx_cnt < xf_setup->length)) {
+ rDat = Chip_SSP_ReceiveFrame(pSSP);
+ if (xf_setup->rx_data) {
+ *(uint8_t *) ((uint32_t) xf_setup->rx_data + xf_setup->rx_cnt) = rDat;
+ }
+
+ xf_setup->rx_cnt++;
+ }
+}
+
+/* Returns clock for the peripheral block */
+STATIC CHIP_SYSCTL_CLOCK_T Chip_SSP_GetClockIndex(LPC_SSP_T *pSSP)
+{
+ CHIP_SYSCTL_CLOCK_T clkSSP;
+
+ if (pSSP == LPC_SSP0) {
+ clkSSP = SYSCTL_CLOCK_SSP0;
+ }
+ else {
+ clkSSP = SYSCTL_CLOCK_SSP1;
+ }
+
+ return clkSSP;
+}
+
+/* Returns reset ID for the peripheral block */
+STATIC CHIP_SYSCTL_PERIPH_RESET_T Chip_SSP_GetResetIndex(LPC_SSP_T *pSSP)
+{
+ CHIP_SYSCTL_PERIPH_RESET_T resetSSP;
+
+ if (pSSP == LPC_SSP0) {
+ resetSSP = RESET_SSP0;
+ }
+ else {
+ resetSSP = RESET_SSP1;
+ }
+
+ return resetSSP;
+}
+
+/* Returns reset ID for the peripheral block */
+STATIC void Chip_SSP_SetSSPClkDivider(LPC_SSP_T *pSSP, uint32_t div)
+{
+ if (pSSP == LPC_SSP0) {
+ Chip_Clock_SetSSP0ClockDiv(div);
+ }
+ else {
+ Chip_Clock_SetSSP1ClockDiv(div);
+ }
+}
+
+/* Returns SSP peripheral clock for the peripheral block */
+STATIC uint32_t Chip_SSP_GetPCLKkRate(LPC_SSP_T *pSSP)
+{
+ uint32_t sspCLK = Chip_Clock_GetMainClockRate();
+
+ if (pSSP == LPC_SSP0) {
+ sspCLK /= Chip_Clock_GetSSP0ClockDiv();
+ }
+ else {
+ sspCLK /= Chip_Clock_GetSSP1ClockDiv();
+ }
+
+ return sspCLK;
+}
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/*Set up output clocks per bit for SSP bus*/
+void Chip_SSP_SetClockRate(LPC_SSP_T *pSSP, uint32_t clk_rate, uint32_t prescale)
+{
+ uint32_t temp;
+ temp = pSSP->CR0 & (~(SSP_CR0_SCR(0xFF)));
+ pSSP->CR0 = temp | (SSP_CR0_SCR(clk_rate));
+ pSSP->CPSR = prescale;
+}
+
+/* SSP Polling Read/Write in blocking mode */
+uint32_t Chip_SSP_RWFrames_Blocking(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
+{
+ /* Clear all remaining frames in RX FIFO */
+ while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
+ Chip_SSP_ReceiveFrame(pSSP);
+ }
+
+ /* Clear status */
+ Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
+
+ if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
+ while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) {
+ /* write data to buffer */
+ if (( Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) {
+ SSP_Write2BFifo(pSSP, xf_setup);
+ }
+
+ /* Check overrun error */
+ if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
+ return ERROR;
+ }
+
+ /* Check for any data available in RX FIFO */
+ SSP_Read2BFifo(pSSP, xf_setup);
+ }
+ }
+ else {
+ while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) {
+ /* write data to buffer */
+ if (( Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) {
+ SSP_Write1BFifo(pSSP, xf_setup);
+ }
+
+ /* Check overrun error */
+ if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
+ return ERROR;
+ }
+
+ /* Check for any data available in RX FIFO */
+ SSP_Read1BFifo(pSSP, xf_setup);
+ }
+ }
+ if (xf_setup->tx_data) {
+ return xf_setup->tx_cnt;
+ }
+ else if (xf_setup->rx_data) {
+ return xf_setup->rx_cnt;
+ }
+
+ return 0;
+}
+
+/* SSP Polling Write in blocking mode */
+uint32_t Chip_SSP_WriteFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len)
+{
+ uint32_t tx_cnt = 0, rx_cnt = 0;
+
+ /* Clear all remaining frames in RX FIFO */
+ while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
+ Chip_SSP_ReceiveFrame(pSSP);
+ }
+
+ /* Clear status */
+ Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
+
+ if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
+ uint16_t *wdata16;
+
+ wdata16 = (uint16_t *) buffer;
+
+ while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
+ /* write data to buffer */
+ if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
+ Chip_SSP_SendFrame(pSSP, *wdata16);
+ wdata16++;
+ tx_cnt += 2;
+ }
+
+ /* Check overrun error */
+ if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
+ return ERROR;
+ }
+
+ /* Check for any data available in RX FIFO */
+ while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) {
+ Chip_SSP_ReceiveFrame(pSSP); /* read dummy data */
+ rx_cnt += 2;
+ }
+ }
+ }
+ else {
+ uint8_t *wdata8;
+
+ wdata8 = buffer;
+
+ while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
+ /* write data to buffer */
+ if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
+ Chip_SSP_SendFrame(pSSP, *wdata8);
+ wdata8++;
+ tx_cnt++;
+ }
+
+ /* Check overrun error */
+ if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
+ return ERROR;
+ }
+
+ /* Check for any data available in RX FIFO */
+ while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
+ Chip_SSP_ReceiveFrame(pSSP); /* read dummy data */
+ rx_cnt++;
+ }
+ }
+ }
+
+ return tx_cnt;
+
+}
+
+/* SSP Polling Read in blocking mode */
+uint32_t Chip_SSP_ReadFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len)
+{
+ uint32_t rx_cnt = 0, tx_cnt = 0;
+
+ /* Clear all remaining frames in RX FIFO */
+ while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
+ Chip_SSP_ReceiveFrame(pSSP);
+ }
+
+ /* Clear status */
+ Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
+
+ if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) {
+ uint16_t *rdata16;
+
+ rdata16 = (uint16_t *) buffer;
+
+ while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
+ /* write data to buffer */
+ if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
+ Chip_SSP_SendFrame(pSSP, 0xFFFF); /* just send dummy data */
+ tx_cnt += 2;
+ }
+
+ /* Check overrun error */
+ if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
+ return ERROR;
+ }
+
+ /* Check for any data available in RX FIFO */
+ while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
+ *rdata16 = Chip_SSP_ReceiveFrame(pSSP);
+ rdata16++;
+ rx_cnt += 2;
+ }
+ }
+ }
+ else {
+ uint8_t *rdata8;
+
+ rdata8 = buffer;
+
+ while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
+ /* write data to buffer */
+ if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
+ Chip_SSP_SendFrame(pSSP, 0xFF); /* just send dummy data */
+ tx_cnt++;
+ }
+
+ /* Check overrun error */
+ if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
+ return ERROR;
+ }
+
+ /* Check for any data available in RX FIFO */
+ while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) {
+ *rdata8 = Chip_SSP_ReceiveFrame(pSSP);
+ rdata8++;
+ rx_cnt++;
+ }
+ }
+ }
+
+ return rx_cnt;
+
+}
+
+/* Clean all data in RX FIFO of SSP */
+void Chip_SSP_Int_FlushData(LPC_SSP_T *pSSP)
+{
+ if (Chip_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {
+ while (Chip_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {}
+ }
+
+ /* Clear all remaining frames in RX FIFO */
+ while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
+ Chip_SSP_ReceiveFrame(pSSP);
+ }
+
+ /* Clear status */
+ Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK);
+}
+
+/* SSP Interrupt Read/Write with 8-bit frame width */
+Status Chip_SSP_Int_RWFrames8Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
+{
+ /* Check overrun error in RIS register */
+ if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
+ return ERROR;
+ }
+
+ if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) {
+ /* check if RX FIFO contains data */
+ SSP_Read1BFifo(pSSP, xf_setup);
+
+ while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) {
+ /* Write data to buffer */
+ SSP_Write1BFifo(pSSP, xf_setup);
+
+ /* Check overrun error in RIS register */
+ if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
+ return ERROR;
+ }
+
+ /* Check for any data available in RX FIFO */
+ SSP_Read1BFifo(pSSP, xf_setup);
+ }
+
+ return SUCCESS;
+ }
+
+ return ERROR;
+}
+
+/* SSP Interrupt Read/Write with 16-bit frame width */
+Status Chip_SSP_Int_RWFrames16Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup)
+{
+ /* Check overrun error in RIS register */
+ if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
+ return ERROR;
+ }
+
+ if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) {
+ /* check if RX FIFO contains data */
+ SSP_Read2BFifo(pSSP, xf_setup);
+
+ while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) {
+ /* Write data to buffer */
+ SSP_Write2BFifo(pSSP, xf_setup);
+
+ /* Check overrun error in RIS register */
+ if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
+ return ERROR;
+ }
+
+ /* Check for any data available in RX FIFO */
+ SSP_Read2BFifo(pSSP, xf_setup);
+ }
+
+ return SUCCESS;
+ }
+
+ return ERROR;
+}
+
+/* Set the SSP operating modes, master or slave */
+void Chip_SSP_SetMaster(LPC_SSP_T *pSSP, bool master)
+{
+ if (master) {
+ Chip_SSP_Set_Mode(pSSP, SSP_MODE_MASTER);
+ }
+ else {
+ Chip_SSP_Set_Mode(pSSP, SSP_MODE_SLAVE);
+ }
+}
+
+/* Set the clock frequency for SSP interface */
+void Chip_SSP_SetBitRate(LPC_SSP_T *pSSP, uint32_t bitRate)
+{
+ uint32_t ssp_clk, cr0_div, cmp_clk, prescale;
+
+ ssp_clk = Chip_SSP_GetPCLKkRate(pSSP);
+
+ cr0_div = 0;
+ cmp_clk = 0xFFFFFFFF;
+ prescale = 2;
+
+ while (cmp_clk > bitRate) {
+ cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
+ if (cmp_clk > bitRate) {
+ cr0_div++;
+ if (cr0_div > 0xFF) {
+ cr0_div = 0;
+ prescale += 2;
+ }
+ }
+ }
+
+ Chip_SSP_SetClockRate(pSSP, cr0_div, prescale);
+}
+
+/* Initialize the SSP */
+void Chip_SSP_Init(LPC_SSP_T *pSSP)
+{
+ Chip_Clock_EnablePeriphClock(Chip_SSP_GetClockIndex(pSSP));
+ Chip_SSP_SetSSPClkDivider(pSSP, 1);
+ Chip_SYSCTL_PeriphReset(Chip_SSP_GetResetIndex(pSSP));
+
+ Chip_SSP_Set_Mode(pSSP, SSP_MODE_MASTER);
+ Chip_SSP_SetFormat(pSSP, SSP_BITS_8, SSP_FRAMEFORMAT_SPI, SSP_CLOCK_CPHA0_CPOL0);
+ Chip_SSP_SetBitRate(pSSP, 100000);
+}
+
+/* De-initializes the SSP peripheral */
+void Chip_SSP_DeInit(LPC_SSP_T *pSSP)
+{
+ Chip_SSP_Disable(pSSP);
+
+ Chip_Clock_DisablePeriphClock(Chip_SSP_GetClockIndex(pSSP));
+ Chip_SSP_SetSSPClkDivider(pSSP, 0);
+}
diff --git a/source/lpc_chip_11u6x/src/stopwatch_11u6.c b/source/lpc_chip_11u6x/src/stopwatch_11u6.c
new file mode 100644
index 0000000..b6ce6cb
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/stopwatch_11u6.c
@@ -0,0 +1,106 @@
+/*
+ * @brief LPC11u6x specific stopwatch implementation
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+#include "stopwatch.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/* Precompute these to optimize runtime */
+static uint32_t ticksPerSecond;
+static uint32_t ticksPerMs;
+static uint32_t ticksPerUs;
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initialize stopwatch */
+void StopWatch_Init(void)
+{
+ /* Use timer 1. Set prescaler to divide by 8 */
+ const uint32_t prescaleDivisor = 8;
+ Chip_TIMER_Init(LPC_TIMER32_1);
+ Chip_TIMER_PrescaleSet(LPC_TIMER32_1, prescaleDivisor - 1);
+ Chip_TIMER_Enable(LPC_TIMER32_1);
+
+ /* Pre-compute tick rate. */
+ ticksPerSecond = Chip_Clock_GetSystemClockRate() / prescaleDivisor;
+ ticksPerMs = ticksPerSecond / 1000;
+ ticksPerUs = ticksPerSecond / 1000000;
+}
+
+/* Start a stopwatch */
+uint32_t StopWatch_Start(void)
+{
+ /* Return the current timer count. */
+ return Chip_TIMER_ReadCount(LPC_TIMER32_1);
+}
+
+/* Returns number of ticks per second of the stopwatch timer */
+uint32_t StopWatch_TicksPerSecond(void)
+{
+ return ticksPerSecond;
+}
+
+/* Converts from stopwatch ticks to mS. */
+uint32_t StopWatch_TicksToMs(uint32_t ticks)
+{
+ return ticks / ticksPerMs;
+}
+
+/* Converts from stopwatch ticks to uS. */
+uint32_t StopWatch_TicksToUs(uint32_t ticks)
+{
+ return ticks / ticksPerUs;
+}
+
+/* Converts from mS to stopwatch ticks. */
+uint32_t StopWatch_MsToTicks(uint32_t mS)
+{
+ return mS * ticksPerMs;
+}
+
+/* Converts from uS to stopwatch ticks. */
+uint32_t StopWatch_UsToTicks(uint32_t uS)
+{
+ return uS * ticksPerUs;
+}
diff --git a/source/lpc_chip_11u6x/src/syscon_11u6x.c b/source/lpc_chip_11u6x/src/syscon_11u6x.c
new file mode 100644
index 0000000..ffd122e
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/syscon_11u6x.c
@@ -0,0 +1,107 @@
+/*
+ * @brief LPC11U6X System Control functions
+ *
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/* PDSLEEPCFG register mask */
+#define PDSLEEPUSEMASK 0x00000037
+#define PDSLEEPMASKTMP (SYSCTL_DEEPSLP_BOD_PD | SYSCTL_DEEPSLP_WDTOSC_PD)
+#define PDSLEEPMASK ((PDSLEEPUSEMASK) &~(PDSLEEPMASKTMP))
+
+/* PDWAKECFG register mask */
+#define PDWAKEUPUSEMASK 0x00000800
+#define PDWAKEUPMASKTMP 0x000025FF
+
+/* PDRUNCFG register mask */
+#define PDRUNCFGUSEMASK 0x0000C800
+#define PDRUNCFGMASKTMP 0x000025FF
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Setup a pin source for the pin interrupts (0-7) */
+void Chip_SYSCTL_SetPinInterrupt(uint32_t intno, uint8_t port, uint8_t pin)
+{
+ if (port == 0) {
+ /* Pins P0.1 to P0.23 only */
+ LPC_SYSCTL->PINTSEL[intno] = (uint32_t) pin;
+ } else {
+ /* P1.1 to P1.31 and P2.0 to P2.7 */
+ LPC_SYSCTL->PINTSEL[intno] = (uint32_t) ((port - 1) * 32 + pin + 24);
+ }
+}
+
+
+/* Setup deep sleep behaviour for power down */
+void Chip_SYSCTL_SetDeepSleepPD(uint32_t sleepmask)
+{
+ /* Update new value */
+ LPC_SYSCTL->PDSLEEPCFG = PDSLEEPMASK | (sleepmask & PDSLEEPMASKTMP);
+}
+
+/* Setup wakeup behaviour from deep sleep */
+void Chip_SYSCTL_SetWakeup(uint32_t wakeupmask)
+{
+ /* Update new value */
+ LPC_SYSCTL->PDWAKECFG = PDWAKEUPUSEMASK | (wakeupmask & PDWAKEUPMASKTMP);
+}
+
+/* Power down one or more blocks or peripherals */
+void Chip_SYSCTL_PowerDown(uint32_t powerdownmask)
+{
+ uint32_t pdrun;
+
+ pdrun = LPC_SYSCTL->PDRUNCFG & PDRUNCFGMASKTMP;
+ pdrun |= (powerdownmask & PDRUNCFGMASKTMP);
+
+ LPC_SYSCTL->PDRUNCFG = (pdrun | PDRUNCFGUSEMASK);
+}
+
+/* Power up one or more blocks or peripherals */
+void Chip_SYSCTL_PowerUp(uint32_t powerupmask)
+{
+ uint32_t pdrun;
+
+ pdrun = LPC_SYSCTL->PDRUNCFG & PDRUNCFGMASKTMP;
+ pdrun &= ~(powerupmask & PDRUNCFGMASKTMP);
+
+ LPC_SYSCTL->PDRUNCFG = (pdrun | PDRUNCFGUSEMASK);
+}
diff --git a/source/lpc_chip_11u6x/src/sysinit_11u6x.c b/source/lpc_chip_11u6x/src/sysinit_11u6x.c
new file mode 100644
index 0000000..9bdbec3
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/sysinit_11u6x.c
@@ -0,0 +1,165 @@
+/*
+ * @brief LPC11u6x Chip specific SystemInit
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/* Enable this definition to use the ROM API for PLL setup */
+// #define USE_ROM_API
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Clock and PLL initialization based on the internal oscillator */
+void Chip_SetupIrcClocking(void)
+{
+#if defined(USE_ROM_API)
+ uint32_t cmd[4], resp[2];
+#endif
+
+ /* Turn on the IRC by clearing the power down bit */
+ Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_IRC_PD);
+
+ /* Select the PLL input in the IRC */
+ Chip_Clock_SetSystemPLLSource(SYSCTL_PLLCLKSRC_IRC);
+
+ /* Setup FLASH access */
+ Chip_FMC_SetFLASHAccess(FLASHTIM_3CLK_CPU);
+
+#if defined(USE_ROM_API)
+ /* Use ROM API for setting up PLL */
+ cmd[0] = Chip_Clock_GetIntOscRate() / 1000; /* in KHz */
+ cmd[1] = 48000000 / 1000; /* 48MHz system clock rate */
+ cmd[2] = CPU_FREQ_EQU;
+ cmd[3] = 48000000 / 10000; /* Timeout */
+ LPC_PWRD_API->set_pll(cmd, resp);
+
+ /* Dead loop on fail */
+ while (resp[0] != PLL_CMD_SUCCESS) {}
+#else
+ /* Power down PLL to change the PLL divider ratio */
+ Chip_SYSCTL_PowerDown(SYSCTL_POWERDOWN_SYSPLL_PD);
+
+ /* Configure the PLL M and P dividers */
+ /* Setup PLL for main oscillator rate (FCLKIN = 12MHz) * 4 = 48MHz
+ MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2)
+ FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz
+ FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) */
+ Chip_Clock_SetupSystemPLL(3, 1);
+
+ /* Turn on the PLL by clearing the power down bit */
+ Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_SYSPLL_PD);
+
+ /* Wait for PLL to lock */
+ while (!Chip_Clock_IsSystemPLLLocked()) {}
+
+ /* Set system clock divider to 1 */
+ Chip_Clock_SetSysClockDiv(1);
+
+ /* Set main clock source to the system PLL. This will drive 24MHz
+ for the main clock and 24MHz for the system clock */
+ Chip_Clock_SetMainClockSource(SYSCTL_MAINCLKSRC_PLLOUT);
+#endif
+}
+
+/* Clock and PLL initialization based on the external oscillator */
+void Chip_SetupXtalClocking(void)
+{
+ volatile int i;
+#if defined(USE_ROM_API)
+ uint32_t cmd[4], resp[2];
+#endif
+
+ /* Powerup main oscillator */
+ Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_SYSOSC_PD);
+
+ /* Wait for at least 580uS for osc to stabilize */
+ for (i = 0; i < 2500; i++) {}
+
+ /* Set system PLL input to main oscillator */
+ Chip_Clock_SetSystemPLLSource(SYSCTL_PLLCLKSRC_MAINOSC);
+
+ /* Setup FLASH access to 3 clocks */
+ Chip_FMC_SetFLASHAccess(FLASHTIM_3CLK_CPU);
+
+#if defined(USE_ROM_API)
+ /* Use ROM API for setting up PLL */
+ cmd[0] = Chip_Clock_GetMainOscRate() / 1000; /* in KHz */
+ cmd[1] = 48000000 / 1000; /* 48MHz system clock rate */
+ cmd[2] = CPU_FREQ_EQU;
+ cmd[3] = 48000000 / 10000; /* Timeout */
+ LPC_PWRD_API->set_pll(cmd, resp);
+
+ /* Dead loop on fail */
+ while (resp[0] != PLL_CMD_SUCCESS) {}
+#else
+ /* Power down PLL to change the PLL divider ratio */
+ Chip_SYSCTL_PowerDown(SYSCTL_POWERDOWN_SYSPLL_PD);
+
+ /* Setup PLL for main oscillator rate (FCLKIN = 12MHz) * 4 = 48MHz
+ MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2)
+ FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz
+ FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) */
+ Chip_Clock_SetupSystemPLL(3, 1);
+
+ /* Powerup system PLL */
+ Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_SYSPLL_PD);
+
+ /* Wait for PLL to lock */
+ while (!Chip_Clock_IsSystemPLLLocked()) {}
+
+ /* Set system clock divider to 1 */
+ Chip_Clock_SetSysClockDiv(1);
+
+ /* Set main clock source to the system PLL. This will drive 48MHz
+ for the main clock and 48MHz for the system clock */
+ Chip_Clock_SetMainClockSource(SYSCTL_MAINCLKSRC_PLLOUT);
+#endif
+}
+
+/* Set up and initialize hardware prior to call to main */
+void Chip_SystemInit(void)
+{
+ /* Initial internal clocking */
+ Chip_SetupIrcClocking();
+}
diff --git a/source/lpc_chip_11u6x/src/timer_11u6x.c b/source/lpc_chip_11u6x/src/timer_11u6x.c
new file mode 100644
index 0000000..4e35082
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/timer_11u6x.c
@@ -0,0 +1,115 @@
+/*
+ * @brief LPC11u6x 16/32-bit Timer/PWM control functions
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/* Returns clock index for a specific timer referenced by IP block address */
+STATIC CHIP_SYSCTL_CLOCK_T Chip_TIMER_GetClock(LPC_TIMER_T *pTMR)
+{
+ CHIP_SYSCTL_CLOCK_T tmrClk;
+ if (pTMR == LPC_TIMER32_1) {
+ tmrClk = SYSCTL_CLOCK_CT32B1;
+ }
+ else if (pTMR == LPC_TIMER16_0) {
+ tmrClk = SYSCTL_CLOCK_CT16B0;
+ }
+ else if (pTMR == LPC_TIMER16_1) {
+ tmrClk = SYSCTL_CLOCK_CT16B1;
+ }
+ else {
+ tmrClk = SYSCTL_CLOCK_CT32B0;
+ }
+
+ return tmrClk;
+}
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initialize a timer */
+void Chip_TIMER_Init(LPC_TIMER_T *pTMR)
+{
+ Chip_Clock_EnablePeriphClock(Chip_TIMER_GetClock(pTMR));
+}
+
+/* Shutdown a timer */
+void Chip_TIMER_DeInit(LPC_TIMER_T *pTMR)
+{
+ Chip_Clock_DisablePeriphClock(Chip_TIMER_GetClock(pTMR));
+}
+
+/* Resets the timer terminal and prescale counts to 0 */
+void Chip_TIMER_Reset(LPC_TIMER_T *pTMR)
+{
+ uint32_t reg;
+
+ /* Disable timer, set terminal count to non-0 */
+ reg = pTMR->TCR;
+ pTMR->TCR = 0;
+ pTMR->TC = 1;
+
+ /* Reset timer counter */
+ pTMR->TCR = TIMER_RESET;
+
+ /* Wait for terminal count to clear */
+ while (pTMR->TC != 0) {}
+
+ /* Restore timer state */
+ pTMR->TCR = reg;
+}
+
+/* Sets external match control (MATn.matchnum) pin control */
+void Chip_TIMER_ExtMatchControlSet(LPC_TIMER_T *pTMR, int8_t initial_state,
+ TIMER_PIN_MATCH_STATE_T matchState, int8_t matchnum)
+{
+ uint32_t mask, reg;
+
+ /* Clear bits corresponding to selected match register */
+ mask = (1 << matchnum) | (0x03 << (4 + (matchnum * 2)));
+ reg = pTMR->EMR &= ~mask;
+
+ /* Set new configuration for selected match register */
+ pTMR->EMR = reg | (((uint32_t) initial_state) << matchnum) |
+ (((uint32_t) matchState) << (4 + (matchnum * 2)));
+}
diff --git a/source/lpc_chip_11u6x/src/uart_0_11u6x.c b/source/lpc_chip_11u6x/src/uart_0_11u6x.c
new file mode 100644
index 0000000..9c89cd9
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/uart_0_11u6x.c
@@ -0,0 +1,283 @@
+/*
+ * @brief LPC11u6x USART0 chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initializes the pUART peripheral */
+void Chip_UART0_Init(LPC_USART0_T *pUART)
+{
+ /* A USART 0 divider of 1 is used with this driver */
+ Chip_Clock_SetUSART0ClockDiv(1);
+
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_UART0);
+
+ /* Enable FIFOs by default, reset them */
+ Chip_UART0_SetupFIFOS(pUART, (UART0_FCR_FIFO_EN | UART0_FCR_RX_RS | UART0_FCR_TX_RS));
+
+ /* Disable fractional divider */
+ pUART->FDR = 0x10;
+}
+
+/* De-initializes the pUART peripheral */
+void Chip_UART0_DeInit(LPC_USART0_T *pUART)
+{
+ Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_UART0);
+}
+
+/* Transmit a byte array through the UART peripheral (non-blocking) */
+int Chip_UART0_Send(LPC_USART0_T *pUART, const void *data, int numBytes)
+{
+ int sent = 0;
+ uint8_t *p8 = (uint8_t *) data;
+
+ /* Send until the transmit FIFO is full or out of bytes */
+ while ((sent < numBytes) &&
+ ((Chip_UART0_ReadLineStatus(pUART) & UART0_LSR_THRE) != 0)) {
+ Chip_UART0_SendByte(pUART, *p8);
+ p8++;
+ sent++;
+ }
+
+ return sent;
+}
+
+/* Transmit a byte array through the UART peripheral (blocking) */
+int Chip_UART0_SendBlocking(LPC_USART0_T *pUART, const void *data, int numBytes)
+{
+ int pass, sent = 0;
+ uint8_t *p8 = (uint8_t *) data;
+
+ while (numBytes > 0) {
+ pass = Chip_UART0_Send(pUART, p8, numBytes);
+ numBytes -= pass;
+ sent += pass;
+ p8 += pass;
+ }
+
+ return sent;
+}
+
+/* Read data through the UART peripheral (non-blocking) */
+int Chip_UART0_Read(LPC_USART0_T *pUART, void *data, int numBytes)
+{
+ int readBytes = 0;
+ uint8_t *p8 = (uint8_t *) data;
+
+ /* Send until the transmit FIFO is full or out of bytes */
+ while ((readBytes < numBytes) &&
+ ((Chip_UART0_ReadLineStatus(pUART) & UART0_LSR_RDR) != 0)) {
+ *p8 = Chip_UART0_ReadByte(pUART);
+ p8++;
+ readBytes++;
+ }
+
+ return readBytes;
+}
+
+/* Read data through the UART peripheral (blocking) */
+int Chip_UART0_ReadBlocking(LPC_USART0_T *pUART, void *data, int numBytes)
+{
+ int pass, readBytes = 0;
+ uint8_t *p8 = (uint8_t *) data;
+
+ while (numBytes > 0) {
+ pass = Chip_UART0_Read(pUART, p8, numBytes);
+ numBytes -= pass;
+ readBytes += pass;
+ p8 += pass;
+ }
+
+ return readBytes;
+}
+
+/* Determines and sets best dividers to get a target bit rate */
+uint32_t Chip_UART0_SetBaud(LPC_USART0_T *pUART, uint32_t baudrate)
+{
+ uint32_t div, divh, divl, clkin;
+
+ /* USART clock input divider of 1 */
+ Chip_Clock_SetUSART0ClockDiv(1);
+
+ /* Determine UART clock in rate without FDR */
+ clkin = Chip_Clock_GetMainClockRate();
+ div = clkin / (baudrate * 16);
+
+ /* High and low halves of the divider */
+ divh = div / 256;
+ divl = div - (divh * 256);
+
+ Chip_UART0_EnableDivisorAccess(pUART);
+ Chip_UART0_SetDivisorLatches(pUART, divl, divh);
+ Chip_UART0_DisableDivisorAccess(pUART);
+
+ /* Fractional FDR already setup for 1 in UART init */
+
+ return clkin / (div * 16);
+}
+
+/* UART receive-only interrupt handler for ring buffers */
+void Chip_UART0_RXIntHandlerRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB)
+{
+ /* New data will be ignored if data not popped in time */
+ while (Chip_UART0_ReadLineStatus(pUART) & UART0_LSR_RDR) {
+ uint8_t ch = Chip_UART0_ReadByte(pUART);
+ RingBuffer_Insert(pRB, &ch);
+ }
+}
+
+/* UART transmit-only interrupt handler for ring buffers */
+void Chip_UART0_TXIntHandlerRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB)
+{
+ uint8_t ch;
+
+ /* Fill FIFO until full or until TX ring buffer is empty */
+ while ((Chip_UART0_ReadLineStatus(pUART) & UART0_LSR_THRE) != 0 &&
+ RingBuffer_Pop(pRB, &ch)) {
+ Chip_UART0_SendByte(pUART, ch);
+ }
+}
+
+/* Populate a transmit ring buffer and start UART transmit */
+uint32_t Chip_UART0_SendRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB, const void *data, int bytes)
+{
+ uint32_t ret;
+ uint8_t *p8 = (uint8_t *) data;
+
+ /* Don't let UART transmit ring buffer change in the UART IRQ handler */
+ Chip_UART0_IntDisable(pUART, UART0_IER_THREINT);
+
+ /* Move as much data as possible into transmit ring buffer */
+ ret = RingBuffer_InsertMult(pRB, p8, bytes);
+ Chip_UART0_TXIntHandlerRB(pUART, pRB);
+
+ /* Add additional data to transmit ring buffer if possible */
+ ret += RingBuffer_InsertMult(pRB, (p8 + ret), (bytes - ret));
+
+ /* Enable UART transmit interrupt */
+ Chip_UART0_IntEnable(pUART, UART0_IER_THREINT);
+
+ return ret;
+}
+
+/* Copy data from a receive ring buffer */
+int Chip_UART0_ReadRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB, void *data, int bytes)
+{
+ (void) pUART;
+
+ return RingBuffer_PopMult(pRB, (uint8_t *) data, bytes);
+}
+
+/* UART receive/transmit interrupt handler for ring buffers */
+void Chip_UART0_IRQRBHandler(LPC_USART0_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB)
+{
+ /* Handle transmit interrupt if enabled */
+ if (pUART->IER & UART0_IER_THREINT) {
+ Chip_UART0_TXIntHandlerRB(pUART, pTXRB);
+
+ /* Disable transmit interrupt if the ring buffer is empty */
+ if (RingBuffer_IsEmpty(pTXRB)) {
+ Chip_UART0_IntDisable(pUART, UART0_IER_THREINT);
+ }
+ }
+
+ /* Handle receive interrupt */
+ Chip_UART0_RXIntHandlerRB(pUART, pRXRB);
+}
+
+/* Determines and sets best dividers to get a target baud rate */
+uint32_t Chip_UART0_SetBaudFDR(LPC_USART0_T *pUART, uint32_t baudrate)
+
+{
+ uint32_t uClk;
+ uint32_t dval, mval;
+ uint32_t dl;
+ uint32_t rate16 = 16 * baudrate;
+ uint32_t actualRate = 0;
+
+ /* Get Clock rate */
+ uClk = Chip_Clock_GetMainClockRate();
+
+ /* The fractional is calculated as (PCLK % (16 * Baudrate)) / (16 * Baudrate)
+ * Let's make it to be the ratio DivVal / MulVal
+ */
+ dval = uClk % rate16;
+
+ /* The PCLK / (16 * Baudrate) is fractional
+ * => dval = pclk % rate16
+ * mval = rate16;
+ * now mormalize the ratio
+ * dval / mval = 1 / new_mval
+ * new_mval = mval / dval
+ * new_dval = 1
+ */
+ if (dval > 0) {
+ mval = rate16 / dval;
+ dval = 1;
+
+ /* In case mval still bigger then 4 bits
+ * no adjustment require
+ */
+ if (mval > 12) {
+ dval = 0;
+ }
+ }
+ dval &= 0xf;
+ mval &= 0xf;
+ dl = uClk / (rate16 + rate16 * dval / mval);
+
+ /* Update UART registers */
+ Chip_UART0_EnableDivisorAccess(pUART);
+ Chip_UART0_SetDivisorLatches(pUART, UART0_LOAD_DLL(dl), UART0_LOAD_DLM(dl));
+ Chip_UART0_DisableDivisorAccess(pUART);
+
+ /* Set best fractional divider */
+ pUART->FDR = (UART0_FDR_MULVAL(mval) | UART0_FDR_DIVADDVAL(dval));
+
+ /* Return actual baud rate */
+ actualRate = uClk / (16 * dl + 16 * dl * dval / mval);
+ return actualRate;
+}
diff --git a/source/lpc_chip_11u6x/src/uart_n_11u6x.c b/source/lpc_chip_11u6x/src/uart_n_11u6x.c
new file mode 100644
index 0000000..990325e
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/uart_n_11u6x.c
@@ -0,0 +1,280 @@
+/*
+ * @brief LPC11u6xx USART0 driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licenser disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/* Counts instances of UART3 and 4 init calls for shared clock handling */
+static uint8_t uart_3_4_cnt;
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/* Return UART clock ID from the UART register address */
+static CHIP_SYSCTL_CLOCK_T getUARTClockID(LPC_USARTN_T *pUART)
+{
+ if (pUART == LPC_USART1) {
+ return SYSCTL_CLOCK_USART1;
+ }
+ else if (pUART == LPC_USART2) {
+ return SYSCTL_CLOCK_USART2;
+ }
+
+ return SYSCTL_CLOCK_USART3_4;
+}
+
+/* UART clock enable */
+static void Chip_UARTN_EnableClock(LPC_USARTN_T *pUART)
+{
+ CHIP_SYSCTL_CLOCK_T clk = getUARTClockID(pUART);
+
+ /* Special handling for shared UART 3/4 clock */
+ if (clk == SYSCTL_CLOCK_USART3_4) {
+ /* Does not handle unbalanced Init() and DeInit() calls */
+ uart_3_4_cnt++;
+ }
+
+ Chip_Clock_EnablePeriphClock(clk);
+}
+
+/* UART clock disable */
+static void Chip_UARTN_DisableClock(LPC_USARTN_T *pUART)
+{
+ CHIP_SYSCTL_CLOCK_T clk = getUARTClockID(pUART);
+
+ /* Special handling for shared UART 3/4 clock */
+ if (clk != SYSCTL_CLOCK_USART3_4) {
+ Chip_Clock_DisablePeriphClock(clk);
+ }
+ else {
+ /* Does not handle unbalanced Init() and DeInit() calls */
+ uart_3_4_cnt--;
+ if (uart_3_4_cnt == 0) {
+ Chip_Clock_DisablePeriphClock(clk);
+ }
+ }
+}
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initialize the UART peripheral */
+void Chip_UARTN_Init(LPC_USARTN_T *pUART)
+{
+ CHIP_SYSCTL_PERIPH_RESET_T resetID;
+
+ /* Enable USART clock */
+ Chip_UARTN_EnableClock(pUART);
+
+ /* Select UART reset */
+ if (pUART == LPC_USART1) {
+ resetID = RESET_USART1;
+ }
+ else if (pUART == LPC_USART2) {
+ resetID = RESET_USART2;
+ }
+ else if (pUART == LPC_USART3) {
+ resetID = RESET_USART3;
+ }
+ else {
+ resetID = RESET_USART4;
+ }
+
+ Chip_SYSCTL_PeriphReset(resetID);
+}
+
+/* Initialize the UART peripheral */
+void Chip_UARTN_DeInit(LPC_USARTN_T *pUART)
+{
+ /* Disable USART clock */
+ Chip_UARTN_DisableClock(pUART);
+}
+
+/* Transmit a byte array through the UART peripheral (non-blocking) */
+int Chip_UARTN_Send(LPC_USARTN_T *pUART, const void *data, int numBytes)
+{
+ int sent = 0;
+ uint8_t *p8 = (uint8_t *) data;
+
+ /* Send until the transmit FIFO is full or out of bytes */
+ while ((sent < numBytes) &&
+ ((Chip_UARTN_GetStatus(pUART) & UARTN_STAT_TXRDY) != 0)) {
+ Chip_UARTN_SendByte(pUART, *p8);
+ p8++;
+ sent++;
+ }
+
+ return sent;
+}
+
+/* Transmit a byte array through the UART peripheral (blocking) */
+int Chip_UARTN_SendBlocking(LPC_USARTN_T *pUART, const void *data, int numBytes)
+{
+ int pass, sent = 0;
+ uint8_t *p8 = (uint8_t *) data;
+
+ while (numBytes > 0) {
+ pass = Chip_UARTN_Send(pUART, p8, numBytes);
+ numBytes -= pass;
+ sent += pass;
+ p8 += pass;
+ }
+
+ return sent;
+}
+
+/* Read data through the UART peripheral (non-blocking) */
+int Chip_UARTN_Read(LPC_USARTN_T *pUART, void *data, int numBytes)
+{
+ int readBytes = 0;
+ uint8_t *p8 = (uint8_t *) data;
+
+ /* Send until the transmit FIFO is full or out of bytes */
+ while ((readBytes < numBytes) &&
+ ((Chip_UARTN_GetStatus(pUART) & UARTN_STAT_RXRDY) != 0)) {
+ *p8 = Chip_UARTN_ReadByte(pUART);
+ p8++;
+ readBytes++;
+ }
+
+ return readBytes;
+}
+
+/* Read data through the UART peripheral (blocking) */
+int Chip_UARTN_ReadBlocking(LPC_USARTN_T *pUART, void *data, int numBytes)
+{
+ int pass, readBytes = 0;
+ uint8_t *p8 = (uint8_t *) data;
+
+ while (readBytes < numBytes) {
+ pass = Chip_UARTN_Read(pUART, p8, numBytes);
+ numBytes -= pass;
+ readBytes += pass;
+ p8 += pass;
+ }
+
+ return readBytes;
+}
+
+/* Set baud rate for UART */
+void Chip_UARTN_SetBaud(LPC_USARTN_T *pUART, uint32_t baudrate)
+{
+ uint32_t baudRateGenerator;
+ baudRateGenerator = Chip_Clock_GetUSARTNBaseClockRate() / (16 * baudrate);
+ pUART->BRG = baudRateGenerator - 1; /* baud rate */
+}
+
+/* Set baud rate for UART using RTC32K oscillator */
+void Chip_UARTN_SetBaudWithRTC32K(LPC_USARTN_T *pUART, uint32_t baudrate)
+{
+ /* Simple integer divide. 9600 is maximum baud rate. */
+ pUART->BRG = (9600 / baudrate) - 1;
+
+ pUART->CFG |= UARTN_MODE_32K;
+}
+
+/* UART receive-only interrupt handler for ring buffers */
+void Chip_UARTN_RXIntHandlerRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB)
+{
+ /* New data will be ignored if data not popped in time */
+ while ((Chip_UARTN_GetStatus(pUART) & UARTN_STAT_RXRDY) != 0) {
+ uint8_t ch = Chip_UARTN_ReadByte(pUART);
+ RingBuffer_Insert(pRB, &ch);
+ }
+}
+
+/* UART transmit-only interrupt handler for ring buffers */
+void Chip_UARTN_TXIntHandlerRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB)
+{
+ uint8_t ch;
+
+ /* Fill FIFO until full or until TX ring buffer is empty */
+ while (((Chip_UARTN_GetStatus(pUART) & UARTN_STAT_TXRDY) != 0) &&
+ RingBuffer_Pop(pRB, &ch)) {
+ Chip_UARTN_SendByte(pUART, ch);
+ }
+}
+
+/* Populate a transmit ring buffer and start UART transmit */
+uint32_t Chip_UARTN_SendRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB, const void *data, int count)
+{
+ uint32_t ret;
+ uint8_t *p8 = (uint8_t *) data;
+
+ /* Don't let UART transmit ring buffer change in the UART IRQ handler */
+ Chip_UARTN_IntDisable(pUART, UARTN_INTEN_TXRDY);
+
+ /* Move as much data as possible into transmit ring buffer */
+ ret = RingBuffer_InsertMult(pRB, p8, count);
+ Chip_UARTN_TXIntHandlerRB(pUART, pRB);
+
+ /* Add additional data to transmit ring buffer if possible */
+ ret += RingBuffer_InsertMult(pRB, (p8 + ret), (count - ret));
+
+ /* Enable UART transmit interrupt */
+ Chip_UARTN_IntEnable(pUART, UARTN_INTEN_TXRDY);
+
+ return ret;
+}
+
+/* Copy data from a receive ring buffer */
+int Chip_UARTN_ReadRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB, void *data, int bytes)
+{
+ (void) pUART;
+
+ return RingBuffer_PopMult(pRB, (uint8_t *) data, bytes);
+}
+
+/* UART receive/transmit interrupt handler for ring buffers */
+void Chip_UARTN_IRQRBHandler(LPC_USARTN_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB)
+{
+ /* Handle transmit interrupt if enabled */
+ if ((Chip_UARTN_GetStatus(pUART) & UARTN_STAT_TXRDY) != 0) {
+ Chip_UARTN_TXIntHandlerRB(pUART, pTXRB);
+
+ /* Disable transmit interrupt if the ring buffer is empty */
+ if (RingBuffer_IsEmpty(pTXRB)) {
+ Chip_UARTN_IntDisable(pUART, UARTN_INTEN_TXRDY);
+ }
+ }
+
+ /* Handle receive interrupt */
+ Chip_UARTN_RXIntHandlerRB(pUART, pRXRB);
+}
diff --git a/source/lpc_chip_11u6x/src/wwdt_11u6x.c b/source/lpc_chip_11u6x/src/wwdt_11u6x.c
new file mode 100644
index 0000000..6ccb09e
--- /dev/null
+++ b/source/lpc_chip_11u6x/src/wwdt_11u6x.c
@@ -0,0 +1,78 @@
+/*
+ * @brief LPC11u6x WWDT chip driver
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2013
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Initialize the Watchdog timer */
+void Chip_WWDT_Init(LPC_WWDT_T *pWWDT)
+{
+ Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_WDT);
+
+ /* Disable watchdog */
+ pWWDT->MOD = 0;
+ pWWDT->TC = 0xFF;
+ pWWDT->WARNINT = 0x3FF;
+ pWWDT->WINDOW = 0xFFFFFF;
+}
+
+/* Shutdown the Watchdog timer */
+void Chip_WWDT_DeInit(LPC_WWDT_T *pWWDT)
+{
+ Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_WDT);
+}
+
+/* Clear WWDT interrupt status flags */
+void Chip_WWDT_ClearStatusFlag(LPC_WWDT_T *pWWDT, uint32_t status)
+{
+ if (status & WWDT_WDMOD_WDTOF) {
+ pWWDT->MOD &= (~WWDT_WDMOD_WDTOF) & WWDT_WDMOD_BITMASK;
+ }
+
+ if (status & WWDT_WDMOD_WDINT) {
+ pWWDT->MOD |= WWDT_WDMOD_WDINT;
+ }
+}
diff --git a/source/test/.cproject b/source/test/.cproject
new file mode 100644
index 0000000..2642b43
--- /dev/null
+++ b/source/test/.cproject
@@ -0,0 +1,331 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<TargetConfig>
+<Properties property_2="LPC11U6x_256K.cfx" property_3="NXP" property_4="LPC11U68" property_count="5" version="100300"/>
+<infoList vendor="NXP">
+<info chip="LPC11U68" flash_driver="LPC11U6x_256K.cfx" match_id="0x0" name="LPC11U68" stub="crt_emu_cm3_gen">
+<chip>
+<name>LPC11U68</name>
+<family>LPC11U6x</family>
+<vendor>NXP (formerly Philips)</vendor>
+<reset board="None" core="Real" sys="Real"/>
+<clock changeable="TRUE" freq="12MHz" is_accurate="TRUE"/>
+<memory can_program="true" id="Flash" is_ro="true" type="Flash"/>
+<memory id="RAM" type="RAM"/>
+<memory id="Periph" is_volatile="true" type="Peripheral"/>
+<memoryInstance derived_from="Flash" id="MFlash256" location="0x0" size="0x40000"/>
+<memoryInstance derived_from="RAM" id="Ram0_32" location="0x10000000" size="0x8000"/>
+<memoryInstance derived_from="RAM" id="Ram1_2" location="0x20000000" size="0x800"/>
+<memoryInstance derived_from="RAM" id="Ram2USB_2" location="0x20004000" size="0x800"/>
+</chip>
+<processor>
+<name gcc_name="cortex-m0">Cortex-M0</name>
+<family>Cortex-M</family>
+</processor>
+</info>
+</infoList>
+</TargetConfig>
+
+
+ LPCXpresso11U68
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/test/.gitignore b/source/test/.gitignore
new file mode 100644
index 0000000..3df573f
--- /dev/null
+++ b/source/test/.gitignore
@@ -0,0 +1 @@
+/Debug/
diff --git a/source/test/.project b/source/test/.project
new file mode 100644
index 0000000..76b91cc
--- /dev/null
+++ b/source/test/.project
@@ -0,0 +1,29 @@
+
+
+ test
+
+
+ lpc_board_nxp_lpcxpresso_11u68
+ lpc_chip_11u6x
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/source/test/.settings/language.settings.xml b/source/test/.settings/language.settings.xml
new file mode 100644
index 0000000..c2e0119
--- /dev/null
+++ b/source/test/.settings/language.settings.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/test/freertos/FreeRTOSConfig.h b/source/test/freertos/FreeRTOSConfig.h
new file mode 100644
index 0000000..ec2abf9
--- /dev/null
+++ b/source/test/freertos/FreeRTOSConfig.h
@@ -0,0 +1,158 @@
+/*
+ FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
+
+
+ ***************************************************************************
+ * *
+ * FreeRTOS tutorial books are available in pdf and paperback. *
+ * Complete, revised, and edited pdf reference manuals are also *
+ * available. *
+ * *
+ * Purchasing FreeRTOS documentation will not only help you, by *
+ * ensuring you get running as quickly as possible and with an *
+ * in-depth knowledge of how to use FreeRTOS, it will also help *
+ * the FreeRTOS project to continue with its mission of providing *
+ * professional grade, cross platform, de facto standard solutions *
+ * for microcontrollers - completely free of charge! *
+ * *
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
+ * *
+ * Thank you for using FreeRTOS, and thank you for your support! *
+ * *
+ ***************************************************************************
+
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+ >>>NOTE<<< The modification to the GPL is included to allow you to
+ distribute a combined work that includes FreeRTOS without being obliged to
+ provide the source code for proprietary components outside of the FreeRTOS
+ kernel. FreeRTOS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details. You should have received a copy of the GNU General Public
+ License and the FreeRTOS license exception along with FreeRTOS; if not it
+ can be viewed here: http://www.freertos.org/a00114.html and also obtained
+ by writing to Richard Barry, contact details for whom are available on the
+ FreeRTOS WEB site.
+
+ 1 tab == 4 spaces!
+
+ http://www.FreeRTOS.org - Documentation, latest information, license and
+ contact details.
+
+ http://www.SafeRTOS.com - A version that is certified for use in safety
+ critical systems.
+
+ http://www.OpenRTOS.com - Commercial support, development, porting,
+ licensing and training services.
+*/
+
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+#ifndef __IASMARM__
+/* For SystemCoreClock */
+#include "board.h"
+#endif
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS 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.
+ *----------------------------------------------------------*/
+
+#define configUSE_PREEMPTION 1
+#define configUSE_IDLE_HOOK 1
+#define configUSE_TICK_HOOK 0
+#define configCPU_CLOCK_HZ ( SystemCoreClock )
+#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
+#define configMAX_PRIORITIES (8UL)
+#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 64 )
+#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 1024 + 512) )
+#define configMAX_TASK_NAME_LEN ( 10 )
+#define configUSE_TRACE_FACILITY 1
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_MUTEXES 1
+#define configQUEUE_REGISTRY_SIZE 8
+#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_MALLOC_FAILED_HOOK 1
+#define configUSE_APPLICATION_TASK_TAG 0
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configGENERATE_RUN_TIME_STATS 0
+#define configUSE_TICKLESS_IDLE 1
+
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES 0
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
+
+/* Software timer definitions. This example uses I2C to write to the LEDs. As
+this takes a finite time, and because a timer callback writes to an LED, the
+priority of the timer task is kept to a minimum to ensure it does not disrupt
+test tasks that check their own execution times. */
+#define configUSE_TIMERS 0
+#define configTIMER_TASK_PRIORITY ( 0 )
+#define configTIMER_QUEUE_LENGTH 5
+#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
+
+/* Set the following definitions to 1 to include the API function, or zero
+to exclude the API function. */
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskCleanUpResources 1
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+
+/* Cortex-M specific definitions. */
+#ifdef __NVIC_PRIO_BITS
+ /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
+ #define configPRIO_BITS __NVIC_PRIO_BITS
+#else
+ #define configPRIO_BITS 5 /* 32 priority levels */
+#endif
+
+/* The lowest interrupt priority that can be used in a call to a "set priority"
+function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x1f
+
+/* 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
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
+
+/* 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. */
+#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_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
+header file. */
+#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
+
+#define configUSE_CUSTOM_TICK 0
+
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+standard names - or at least those used in the unmodified vector table. */
+#define vPortSVCHandler SVC_Handler
+#define xPortPendSVHandler PendSV_Handler
+#define xPortSysTickHandler SysTick_Handler
+
+#endif /* FREERTOS_CONFIG_H */
+
diff --git a/source/test/freertos/inc/FreeRTOS.h b/source/test/freertos/inc/FreeRTOS.h
new file mode 100644
index 0000000..d829d44
--- /dev/null
+++ b/source/test/freertos/inc/FreeRTOS.h
@@ -0,0 +1,1440 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef INC_FREERTOS_H
+#define INC_FREERTOS_H
+
+/*
+ * Include the generic headers required for the FreeRTOS port being used.
+ */
+#include
+
+/*
+ * If stdint.h cannot be located then:
+ * + If using GCC ensure the -nostdint options is *not* being used.
+ * + Ensure the project's include path includes the directory in which your
+ * compiler stores stdint.h.
+ * + Set any compiler options necessary for it to support C99, as technically
+ * stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any
+ * other way).
+ * + The FreeRTOS download includes a simple stdint.h definition that can be
+ * used in cases where none is provided by the compiler. The files only
+ * contains the typedefs required to build FreeRTOS. Read the instructions
+ * in FreeRTOS/source/stdint.readme for more information.
+ */
+#include /* READ COMMENT ABOVE. */
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+/* Application specific configuration options. */
+#include "FreeRTOSConfig.h"
+
+/* Basic FreeRTOS definitions. */
+#include "projdefs.h"
+
+/* Definitions specific to the port being used. */
+#include "portable.h"
+
+/* Must be defaulted before configUSE_NEWLIB_REENTRANT is used below. */
+#ifndef configUSE_NEWLIB_REENTRANT
+ #define configUSE_NEWLIB_REENTRANT 0
+#endif
+
+/* Required if struct _reent is used. */
+#if ( configUSE_NEWLIB_REENTRANT == 1 )
+
+/* Note Newlib support has been included by popular demand, but is not
+ * used by the FreeRTOS maintainers themselves. FreeRTOS is not
+ * responsible for resulting newlib operation. User must be familiar with
+ * newlib and must provide system-wide implementations of the necessary
+ * stubs. Be warned that (at the time of writing) the current newlib design
+ * implements a system-wide malloc() that must be provided with locks.
+ *
+ * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
+ * for additional information. */
+ #include
+
+ #define configUSE_C_RUNTIME_TLS_SUPPORT 1
+
+ #ifndef configTLS_BLOCK_TYPE
+ #define configTLS_BLOCK_TYPE struct _reent
+ #endif
+
+ #ifndef configINIT_TLS_BLOCK
+ #define configINIT_TLS_BLOCK( xTLSBlock ) _REENT_INIT_PTR( &( xTLSBlock ) )
+ #endif
+
+ #ifndef configSET_TLS_BLOCK
+ #define configSET_TLS_BLOCK( xTLSBlock ) _impure_ptr = &( xTLSBlock )
+ #endif
+
+ #ifndef configDEINIT_TLS_BLOCK
+ #define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) )
+ #endif
+#endif /* if ( configUSE_NEWLIB_REENTRANT == 1 ) */
+
+#ifndef configUSE_C_RUNTIME_TLS_SUPPORT
+ #define configUSE_C_RUNTIME_TLS_SUPPORT 0
+#endif
+
+#if ( ( configUSE_NEWLIB_REENTRANT == 0 ) && ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
+
+ #ifndef configTLS_BLOCK_TYPE
+ #error Missing definition: configTLS_BLOCK_TYPE must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
+ #endif
+
+ #ifndef configINIT_TLS_BLOCK
+ #error Missing definition: configINIT_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
+ #endif
+
+ #ifndef configSET_TLS_BLOCK
+ #error Missing definition: configSET_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
+ #endif
+
+ #ifndef configDEINIT_TLS_BLOCK
+ #error Missing definition: configDEINIT_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
+ #endif
+#endif /* if ( ( configUSE_NEWLIB_REENTRANT == 0 ) && ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) ) */
+
+/*
+ * Check all the required application specific macros have been defined.
+ * These macros are application specific and (as downloaded) are defined
+ * within FreeRTOSConfig.h.
+ */
+
+#ifndef configMINIMAL_STACK_SIZE
+ #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value.
+#endif
+
+#ifndef configMAX_PRIORITIES
+ #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#if configMAX_PRIORITIES < 1
+ #error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
+#endif
+
+#ifndef configUSE_PREEMPTION
+ #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_IDLE_HOOK
+ #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_TICK_HOOK
+ #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_16_BIT_TICKS
+ #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_CO_ROUTINES
+ #define configUSE_CO_ROUTINES 0
+#endif
+
+#ifndef INCLUDE_vTaskPrioritySet
+ #define INCLUDE_vTaskPrioritySet 0
+#endif
+
+#ifndef INCLUDE_uxTaskPriorityGet
+ #define INCLUDE_uxTaskPriorityGet 0
+#endif
+
+#ifndef INCLUDE_vTaskDelete
+ #define INCLUDE_vTaskDelete 0
+#endif
+
+#ifndef INCLUDE_vTaskSuspend
+ #define INCLUDE_vTaskSuspend 0
+#endif
+
+#ifdef INCLUDE_xTaskDelayUntil
+ #ifdef INCLUDE_vTaskDelayUntil
+
+/* INCLUDE_vTaskDelayUntil was replaced by INCLUDE_xTaskDelayUntil. Backward
+ * compatibility is maintained if only one or the other is defined, but
+ * there is a conflict if both are defined. */
+ #error INCLUDE_vTaskDelayUntil and INCLUDE_xTaskDelayUntil are both defined. INCLUDE_vTaskDelayUntil is no longer required and should be removed
+ #endif
+#endif
+
+#ifndef INCLUDE_xTaskDelayUntil
+ #ifdef INCLUDE_vTaskDelayUntil
+
+/* If INCLUDE_vTaskDelayUntil is set but INCLUDE_xTaskDelayUntil is not then
+ * the project's FreeRTOSConfig.h probably pre-dates the introduction of
+ * xTaskDelayUntil and setting INCLUDE_xTaskDelayUntil to whatever
+ * INCLUDE_vTaskDelayUntil is set to will ensure backward compatibility.
+ */
+ #define INCLUDE_xTaskDelayUntil INCLUDE_vTaskDelayUntil
+ #endif
+#endif
+
+#ifndef INCLUDE_xTaskDelayUntil
+ #define INCLUDE_xTaskDelayUntil 0
+#endif
+
+#ifndef INCLUDE_vTaskDelay
+ #define INCLUDE_vTaskDelay 0
+#endif
+
+#ifndef INCLUDE_xTaskGetIdleTaskHandle
+ #define INCLUDE_xTaskGetIdleTaskHandle 0
+#endif
+
+#ifndef INCLUDE_xTaskAbortDelay
+ #define INCLUDE_xTaskAbortDelay 0
+#endif
+
+#ifndef INCLUDE_xQueueGetMutexHolder
+ #define INCLUDE_xQueueGetMutexHolder 0
+#endif
+
+#ifndef INCLUDE_xSemaphoreGetMutexHolder
+ #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder
+#endif
+
+#ifndef INCLUDE_xTaskGetHandle
+ #define INCLUDE_xTaskGetHandle 0
+#endif
+
+#ifndef INCLUDE_uxTaskGetStackHighWaterMark
+ #define INCLUDE_uxTaskGetStackHighWaterMark 0
+#endif
+
+#ifndef INCLUDE_uxTaskGetStackHighWaterMark2
+ #define INCLUDE_uxTaskGetStackHighWaterMark2 0
+#endif
+
+#ifndef INCLUDE_eTaskGetState
+ #define INCLUDE_eTaskGetState 0
+#endif
+
+#ifndef INCLUDE_xTaskResumeFromISR
+ #define INCLUDE_xTaskResumeFromISR 1
+#endif
+
+#ifndef INCLUDE_xTimerPendFunctionCall
+ #define INCLUDE_xTimerPendFunctionCall 0
+#endif
+
+#ifndef INCLUDE_xTaskGetSchedulerState
+ #define INCLUDE_xTaskGetSchedulerState 0
+#endif
+
+#ifndef INCLUDE_xTaskGetCurrentTaskHandle
+ #define INCLUDE_xTaskGetCurrentTaskHandle 1
+#endif
+
+#if configUSE_CO_ROUTINES != 0
+ #ifndef configMAX_CO_ROUTINE_PRIORITIES
+ #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.
+ #endif
+#endif
+
+#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK
+ #define configUSE_DAEMON_TASK_STARTUP_HOOK 0
+#endif
+
+#ifndef configUSE_APPLICATION_TASK_TAG
+ #define configUSE_APPLICATION_TASK_TAG 0
+#endif
+
+#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS
+ #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0
+#endif
+
+#ifndef configUSE_RECURSIVE_MUTEXES
+ #define configUSE_RECURSIVE_MUTEXES 0
+#endif
+
+#ifndef configUSE_MUTEXES
+ #define configUSE_MUTEXES 0
+#endif
+
+#ifndef configUSE_TIMERS
+ #define configUSE_TIMERS 0
+#endif
+
+#ifndef configUSE_COUNTING_SEMAPHORES
+ #define configUSE_COUNTING_SEMAPHORES 0
+#endif
+
+#ifndef configUSE_ALTERNATIVE_API
+ #define configUSE_ALTERNATIVE_API 0
+#endif
+
+#ifndef portCRITICAL_NESTING_IN_TCB
+ #define portCRITICAL_NESTING_IN_TCB 0
+#endif
+
+#ifndef configMAX_TASK_NAME_LEN
+ #define configMAX_TASK_NAME_LEN 16
+#endif
+
+#ifndef configIDLE_SHOULD_YIELD
+ #define configIDLE_SHOULD_YIELD 1
+#endif
+
+#if configMAX_TASK_NAME_LEN < 1
+ #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h
+#endif
+
+#ifndef configASSERT
+ #define configASSERT( x )
+ #define configASSERT_DEFINED 0
+#else
+ #define configASSERT_DEFINED 1
+#endif
+
+/* configPRECONDITION should be defined as configASSERT.
+ * The CBMC proofs need a way to track assumptions and assertions.
+ * A configPRECONDITION statement should express an implicit invariant or
+ * assumption made. A configASSERT statement should express an invariant that must
+ * hold explicit before calling the code. */
+#ifndef configPRECONDITION
+ #define configPRECONDITION( X ) configASSERT( X )
+ #define configPRECONDITION_DEFINED 0
+#else
+ #define configPRECONDITION_DEFINED 1
+#endif
+
+#ifndef portMEMORY_BARRIER
+ #define portMEMORY_BARRIER()
+#endif
+
+#ifndef portSOFTWARE_BARRIER
+ #define portSOFTWARE_BARRIER()
+#endif
+
+/* The timers module relies on xTaskGetSchedulerState(). */
+#if configUSE_TIMERS == 1
+
+ #ifndef configTIMER_TASK_PRIORITY
+ #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined.
+ #endif /* configTIMER_TASK_PRIORITY */
+
+ #ifndef configTIMER_QUEUE_LENGTH
+ #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined.
+ #endif /* configTIMER_QUEUE_LENGTH */
+
+ #ifndef configTIMER_TASK_STACK_DEPTH
+ #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined.
+ #endif /* configTIMER_TASK_STACK_DEPTH */
+
+#endif /* configUSE_TIMERS */
+
+#ifndef portSET_INTERRUPT_MASK_FROM_ISR
+ #define portSET_INTERRUPT_MASK_FROM_ISR() 0
+#endif
+
+#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR
+ #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) ( uxSavedStatusValue )
+#endif
+
+#ifndef portCLEAN_UP_TCB
+ #define portCLEAN_UP_TCB( pxTCB ) ( void ) ( pxTCB )
+#endif
+
+#ifndef portPRE_TASK_DELETE_HOOK
+ #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending )
+#endif
+
+#ifndef portSETUP_TCB
+ #define portSETUP_TCB( pxTCB ) ( void ) ( pxTCB )
+#endif
+
+#ifndef configQUEUE_REGISTRY_SIZE
+ #define configQUEUE_REGISTRY_SIZE 0U
+#endif
+
+#if ( configQUEUE_REGISTRY_SIZE < 1 )
+ #define vQueueAddToRegistry( xQueue, pcName )
+ #define vQueueUnregisterQueue( xQueue )
+ #define pcQueueGetName( xQueue )
+#endif
+
+#ifndef configUSE_MINI_LIST_ITEM
+ #define configUSE_MINI_LIST_ITEM 1
+#endif
+
+#ifndef portPOINTER_SIZE_TYPE
+ #define portPOINTER_SIZE_TYPE uint32_t
+#endif
+
+/* Remove any unused trace macros. */
+#ifndef traceSTART
+
+/* Used to perform any necessary initialisation - for example, open a file
+ * into which trace is to be written. */
+ #define traceSTART()
+#endif
+
+#ifndef traceEND
+
+/* Use to close a trace, for example close a file into which trace has been
+ * written. */
+ #define traceEND()
+#endif
+
+#ifndef traceTASK_SWITCHED_IN
+
+/* Called after a task has been selected to run. pxCurrentTCB holds a pointer
+ * to the task control block of the selected task. */
+ #define traceTASK_SWITCHED_IN()
+#endif
+
+#ifndef traceINCREASE_TICK_COUNT
+
+/* Called before stepping the tick count after waking from tickless idle
+ * sleep. */
+ #define traceINCREASE_TICK_COUNT( x )
+#endif
+
+#ifndef traceLOW_POWER_IDLE_BEGIN
+ /* Called immediately before entering tickless idle. */
+ #define traceLOW_POWER_IDLE_BEGIN()
+#endif
+
+#ifndef traceLOW_POWER_IDLE_END
+ /* Called when returning to the Idle task after a tickless idle. */
+ #define traceLOW_POWER_IDLE_END()
+#endif
+
+#ifndef traceTASK_SWITCHED_OUT
+
+/* Called before a task has been selected to run. pxCurrentTCB holds a pointer
+ * to the task control block of the task being switched out. */
+ #define traceTASK_SWITCHED_OUT()
+#endif
+
+#ifndef traceTASK_PRIORITY_INHERIT
+
+/* Called when a task attempts to take a mutex that is already held by a
+ * lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task
+ * that holds the mutex. uxInheritedPriority is the priority the mutex holder
+ * will inherit (the priority of the task that is attempting to obtain the
+ * muted. */
+ #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority )
+#endif
+
+#ifndef traceTASK_PRIORITY_DISINHERIT
+
+/* Called when a task releases a mutex, the holding of which had resulted in
+ * the task inheriting the priority of a higher priority task.
+ * pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the
+ * mutex. uxOriginalPriority is the task's configured (base) priority. */
+ #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority )
+#endif
+
+#ifndef traceBLOCKING_ON_QUEUE_RECEIVE
+
+/* Task is about to block because it cannot read from a
+ * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore
+ * upon which the read was attempted. pxCurrentTCB points to the TCB of the
+ * task that attempted the read. */
+ #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue )
+#endif
+
+#ifndef traceBLOCKING_ON_QUEUE_PEEK
+
+/* Task is about to block because it cannot read from a
+ * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore
+ * upon which the read was attempted. pxCurrentTCB points to the TCB of the
+ * task that attempted the read. */
+ #define traceBLOCKING_ON_QUEUE_PEEK( pxQueue )
+#endif
+
+#ifndef traceBLOCKING_ON_QUEUE_SEND
+
+/* Task is about to block because it cannot write to a
+ * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore
+ * upon which the write was attempted. pxCurrentTCB points to the TCB of the
+ * task that attempted the write. */
+ #define traceBLOCKING_ON_QUEUE_SEND( pxQueue )
+#endif
+
+#ifndef configCHECK_FOR_STACK_OVERFLOW
+ #define configCHECK_FOR_STACK_OVERFLOW 0
+#endif
+
+#ifndef configRECORD_STACK_HIGH_ADDRESS
+ #define configRECORD_STACK_HIGH_ADDRESS 0
+#endif
+
+#ifndef configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H
+ #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 0
+#endif
+
+/* The following event macros are embedded in the kernel API calls. */
+
+#ifndef traceMOVED_TASK_TO_READY_STATE
+ #define traceMOVED_TASK_TO_READY_STATE( pxTCB )
+#endif
+
+#ifndef tracePOST_MOVED_TASK_TO_READY_STATE
+ #define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
+#endif
+
+#ifndef traceQUEUE_CREATE
+ #define traceQUEUE_CREATE( pxNewQueue )
+#endif
+
+#ifndef traceQUEUE_CREATE_FAILED
+ #define traceQUEUE_CREATE_FAILED( ucQueueType )
+#endif
+
+#ifndef traceCREATE_MUTEX
+ #define traceCREATE_MUTEX( pxNewQueue )
+#endif
+
+#ifndef traceCREATE_MUTEX_FAILED
+ #define traceCREATE_MUTEX_FAILED()
+#endif
+
+#ifndef traceGIVE_MUTEX_RECURSIVE
+ #define traceGIVE_MUTEX_RECURSIVE( pxMutex )
+#endif
+
+#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED
+ #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex )
+#endif
+
+#ifndef traceTAKE_MUTEX_RECURSIVE
+ #define traceTAKE_MUTEX_RECURSIVE( pxMutex )
+#endif
+
+#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED
+ #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex )
+#endif
+
+#ifndef traceCREATE_COUNTING_SEMAPHORE
+ #define traceCREATE_COUNTING_SEMAPHORE()
+#endif
+
+#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED
+ #define traceCREATE_COUNTING_SEMAPHORE_FAILED()
+#endif
+
+#ifndef traceQUEUE_SET_SEND
+ #define traceQUEUE_SET_SEND traceQUEUE_SEND
+#endif
+
+#ifndef traceQUEUE_SEND
+ #define traceQUEUE_SEND( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FAILED
+ #define traceQUEUE_SEND_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE
+ #define traceQUEUE_RECEIVE( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK
+ #define traceQUEUE_PEEK( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK_FAILED
+ #define traceQUEUE_PEEK_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK_FROM_ISR
+ #define traceQUEUE_PEEK_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FAILED
+ #define traceQUEUE_RECEIVE_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FROM_ISR
+ #define traceQUEUE_SEND_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FROM_ISR_FAILED
+ #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FROM_ISR
+ #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED
+ #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED
+ #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_DELETE
+ #define traceQUEUE_DELETE( pxQueue )
+#endif
+
+#ifndef traceTASK_CREATE
+ #define traceTASK_CREATE( pxNewTCB )
+#endif
+
+#ifndef traceTASK_CREATE_FAILED
+ #define traceTASK_CREATE_FAILED()
+#endif
+
+#ifndef traceTASK_DELETE
+ #define traceTASK_DELETE( pxTaskToDelete )
+#endif
+
+#ifndef traceTASK_DELAY_UNTIL
+ #define traceTASK_DELAY_UNTIL( x )
+#endif
+
+#ifndef traceTASK_DELAY
+ #define traceTASK_DELAY()
+#endif
+
+#ifndef traceTASK_PRIORITY_SET
+ #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority )
+#endif
+
+#ifndef traceTASK_SUSPEND
+ #define traceTASK_SUSPEND( pxTaskToSuspend )
+#endif
+
+#ifndef traceTASK_RESUME
+ #define traceTASK_RESUME( pxTaskToResume )
+#endif
+
+#ifndef traceTASK_RESUME_FROM_ISR
+ #define traceTASK_RESUME_FROM_ISR( pxTaskToResume )
+#endif
+
+#ifndef traceTASK_INCREMENT_TICK
+ #define traceTASK_INCREMENT_TICK( xTickCount )
+#endif
+
+#ifndef traceTIMER_CREATE
+ #define traceTIMER_CREATE( pxNewTimer )
+#endif
+
+#ifndef traceTIMER_CREATE_FAILED
+ #define traceTIMER_CREATE_FAILED()
+#endif
+
+#ifndef traceTIMER_COMMAND_SEND
+ #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn )
+#endif
+
+#ifndef traceTIMER_EXPIRED
+ #define traceTIMER_EXPIRED( pxTimer )
+#endif
+
+#ifndef traceTIMER_COMMAND_RECEIVED
+ #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue )
+#endif
+
+#ifndef traceMALLOC
+ #define traceMALLOC( pvAddress, uiSize )
+#endif
+
+#ifndef traceFREE
+ #define traceFREE( pvAddress, uiSize )
+#endif
+
+#ifndef traceEVENT_GROUP_CREATE
+ #define traceEVENT_GROUP_CREATE( xEventGroup )
+#endif
+
+#ifndef traceEVENT_GROUP_CREATE_FAILED
+ #define traceEVENT_GROUP_CREATE_FAILED()
+#endif
+
+#ifndef traceEVENT_GROUP_SYNC_BLOCK
+ #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor )
+#endif
+
+#ifndef traceEVENT_GROUP_SYNC_END
+ #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) ( xTimeoutOccurred )
+#endif
+
+#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK
+ #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor )
+#endif
+
+#ifndef traceEVENT_GROUP_WAIT_BITS_END
+ #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) ( xTimeoutOccurred )
+#endif
+
+#ifndef traceEVENT_GROUP_CLEAR_BITS
+ #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear )
+#endif
+
+#ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR
+ #define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear )
+#endif
+
+#ifndef traceEVENT_GROUP_SET_BITS
+ #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet )
+#endif
+
+#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR
+ #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet )
+#endif
+
+#ifndef traceEVENT_GROUP_DELETE
+ #define traceEVENT_GROUP_DELETE( xEventGroup )
+#endif
+
+#ifndef tracePEND_FUNC_CALL
+ #define tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, ret )
+#endif
+
+#ifndef tracePEND_FUNC_CALL_FROM_ISR
+ #define tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, ret )
+#endif
+
+#ifndef traceQUEUE_REGISTRY_ADD
+ #define traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName )
+#endif
+
+#ifndef traceTASK_NOTIFY_TAKE_BLOCK
+ #define traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait )
+#endif
+
+#ifndef traceTASK_NOTIFY_TAKE
+ #define traceTASK_NOTIFY_TAKE( uxIndexToWait )
+#endif
+
+#ifndef traceTASK_NOTIFY_WAIT_BLOCK
+ #define traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait )
+#endif
+
+#ifndef traceTASK_NOTIFY_WAIT
+ #define traceTASK_NOTIFY_WAIT( uxIndexToWait )
+#endif
+
+#ifndef traceTASK_NOTIFY
+ #define traceTASK_NOTIFY( uxIndexToNotify )
+#endif
+
+#ifndef traceTASK_NOTIFY_FROM_ISR
+ #define traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify )
+#endif
+
+#ifndef traceTASK_NOTIFY_GIVE_FROM_ISR
+ #define traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify )
+#endif
+
+#ifndef traceSTREAM_BUFFER_CREATE_FAILED
+ #define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer )
+#endif
+
+#ifndef traceSTREAM_BUFFER_CREATE_STATIC_FAILED
+ #define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer )
+#endif
+
+#ifndef traceSTREAM_BUFFER_CREATE
+ #define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer )
+#endif
+
+#ifndef traceSTREAM_BUFFER_DELETE
+ #define traceSTREAM_BUFFER_DELETE( xStreamBuffer )
+#endif
+
+#ifndef traceSTREAM_BUFFER_RESET
+ #define traceSTREAM_BUFFER_RESET( xStreamBuffer )
+#endif
+
+#ifndef traceBLOCKING_ON_STREAM_BUFFER_SEND
+ #define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer )
+#endif
+
+#ifndef traceSTREAM_BUFFER_SEND
+ #define traceSTREAM_BUFFER_SEND( xStreamBuffer, xBytesSent )
+#endif
+
+#ifndef traceSTREAM_BUFFER_SEND_FAILED
+ #define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer )
+#endif
+
+#ifndef traceSTREAM_BUFFER_SEND_FROM_ISR
+ #define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xBytesSent )
+#endif
+
+#ifndef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE
+ #define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer )
+#endif
+
+#ifndef traceSTREAM_BUFFER_RECEIVE
+ #define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength )
+#endif
+
+#ifndef traceSTREAM_BUFFER_RECEIVE_FAILED
+ #define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer )
+#endif
+
+#ifndef traceSTREAM_BUFFER_RECEIVE_FROM_ISR
+ #define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength )
+#endif
+
+#ifndef configGENERATE_RUN_TIME_STATS
+ #define configGENERATE_RUN_TIME_STATS 0
+#endif
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+ #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
+ #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base.
+ #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */
+
+ #ifndef portGET_RUN_TIME_COUNTER_VALUE
+ #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE
+ #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information.
+ #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */
+ #endif /* portGET_RUN_TIME_COUNTER_VALUE */
+
+#endif /* configGENERATE_RUN_TIME_STATS */
+
+#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
+ #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
+#endif
+
+#ifndef configUSE_MALLOC_FAILED_HOOK
+ #define configUSE_MALLOC_FAILED_HOOK 0
+#endif
+
+#ifndef portPRIVILEGE_BIT
+ #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 )
+#endif
+
+#ifndef portYIELD_WITHIN_API
+ #define portYIELD_WITHIN_API portYIELD
+#endif
+
+#ifndef portSUPPRESS_TICKS_AND_SLEEP
+ #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )
+#endif
+
+#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP
+ #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
+#endif
+
+#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2
+ #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2
+#endif
+
+#ifndef configUSE_TICKLESS_IDLE
+ #define configUSE_TICKLESS_IDLE 0
+#endif
+
+#ifndef configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING
+ #define configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( x )
+#endif
+
+#ifndef configPRE_SLEEP_PROCESSING
+ #define configPRE_SLEEP_PROCESSING( x )
+#endif
+
+#ifndef configPOST_SLEEP_PROCESSING
+ #define configPOST_SLEEP_PROCESSING( x )
+#endif
+
+#ifndef configUSE_QUEUE_SETS
+ #define configUSE_QUEUE_SETS 0
+#endif
+
+#ifndef portTASK_USES_FLOATING_POINT
+ #define portTASK_USES_FLOATING_POINT()
+#endif
+
+#ifndef portALLOCATE_SECURE_CONTEXT
+ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
+#endif
+
+#ifndef portDONT_DISCARD
+ #define portDONT_DISCARD
+#endif
+
+#ifndef configUSE_TIME_SLICING
+ #define configUSE_TIME_SLICING 1
+#endif
+
+#ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS
+ #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
+#endif
+
+#ifndef configUSE_STATS_FORMATTING_FUNCTIONS
+ #define configUSE_STATS_FORMATTING_FUNCTIONS 0
+#endif
+
+#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID
+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
+#endif
+
+#ifndef configUSE_TRACE_FACILITY
+ #define configUSE_TRACE_FACILITY 0
+#endif
+
+#ifndef mtCOVERAGE_TEST_MARKER
+ #define mtCOVERAGE_TEST_MARKER()
+#endif
+
+#ifndef mtCOVERAGE_TEST_DELAY
+ #define mtCOVERAGE_TEST_DELAY()
+#endif
+
+#ifndef portASSERT_IF_IN_ISR
+ #define portASSERT_IF_IN_ISR()
+#endif
+
+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
+ #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
+#endif
+
+#ifndef configAPPLICATION_ALLOCATED_HEAP
+ #define configAPPLICATION_ALLOCATED_HEAP 0
+#endif
+
+#ifndef configUSE_TASK_NOTIFICATIONS
+ #define configUSE_TASK_NOTIFICATIONS 1
+#endif
+
+#ifndef configTASK_NOTIFICATION_ARRAY_ENTRIES
+ #define configTASK_NOTIFICATION_ARRAY_ENTRIES 1
+#endif
+
+#if configTASK_NOTIFICATION_ARRAY_ENTRIES < 1
+ #error configTASK_NOTIFICATION_ARRAY_ENTRIES must be at least 1
+#endif
+
+#ifndef configUSE_POSIX_ERRNO
+ #define configUSE_POSIX_ERRNO 0
+#endif
+
+#ifndef configUSE_SB_COMPLETED_CALLBACK
+
+/* By default per-instance callbacks are not enabled for stream buffer or message buffer. */
+ #define configUSE_SB_COMPLETED_CALLBACK 0
+#endif
+
+#ifndef portTICK_TYPE_IS_ATOMIC
+ #define portTICK_TYPE_IS_ATOMIC 0
+#endif
+
+#ifndef configSUPPORT_STATIC_ALLOCATION
+ /* Defaults to 0 for backward compatibility. */
+ #define configSUPPORT_STATIC_ALLOCATION 0
+#endif
+
+#ifndef configSUPPORT_DYNAMIC_ALLOCATION
+ /* Defaults to 1 for backward compatibility. */
+ #define configSUPPORT_DYNAMIC_ALLOCATION 1
+#endif
+
+#if ( ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION != 1 ) )
+ #error configUSE_STATS_FORMATTING_FUNCTIONS cannot be used without dynamic allocation, but configSUPPORT_DYNAMIC_ALLOCATION is not set to 1.
+#endif
+
+#if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
+ #if ( ( configUSE_TRACE_FACILITY != 1 ) && ( configGENERATE_RUN_TIME_STATS != 1 ) )
+ #error configUSE_STATS_FORMATTING_FUNCTIONS is 1 but the functions it enables are not used because neither configUSE_TRACE_FACILITY or configGENERATE_RUN_TIME_STATS are 1. Set configUSE_STATS_FORMATTING_FUNCTIONS to 0 in FreeRTOSConfig.h.
+ #endif
+#endif
+
+#ifndef configSTACK_DEPTH_TYPE
+
+/* Defaults to uint16_t for backward compatibility, but can be overridden
+ * in FreeRTOSConfig.h if uint16_t is too restrictive. */
+ #define configSTACK_DEPTH_TYPE uint16_t
+#endif
+
+#ifndef configRUN_TIME_COUNTER_TYPE
+
+/* Defaults to uint32_t for backward compatibility, but can be overridden in
+ * FreeRTOSConfig.h if uint32_t is too restrictive. */
+
+ #define configRUN_TIME_COUNTER_TYPE uint32_t
+#endif
+
+#ifndef configMESSAGE_BUFFER_LENGTH_TYPE
+
+/* Defaults to size_t for backward compatibility, but can be overridden
+ * in FreeRTOSConfig.h if lengths will always be less than the number of bytes
+ * in a size_t. */
+ #define configMESSAGE_BUFFER_LENGTH_TYPE size_t
+#endif
+
+/* Sanity check the configuration. */
+#if ( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) )
+ #error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1.
+#endif
+
+#if ( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) )
+ #error configUSE_MUTEXES must be set to 1 to use recursive mutexes
+#endif
+
+#ifndef configINITIAL_TICK_COUNT
+ #define configINITIAL_TICK_COUNT 0
+#endif
+
+#if ( portTICK_TYPE_IS_ATOMIC == 0 )
+
+/* Either variables of tick type cannot be read atomically, or
+ * portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when
+ * the tick count is returned to the standard critical section macros. */
+ #define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL()
+ #define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL()
+ #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
+ #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) )
+#else
+
+/* The tick type can be read atomically, so critical sections used when the
+ * tick count is returned can be defined away. */
+ #define portTICK_TYPE_ENTER_CRITICAL()
+ #define portTICK_TYPE_EXIT_CRITICAL()
+ #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0
+ #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) ( x )
+#endif /* if ( portTICK_TYPE_IS_ATOMIC == 0 ) */
+
+/* Definitions to allow backward compatibility with FreeRTOS versions prior to
+ * V8 if desired. */
+#ifndef configENABLE_BACKWARD_COMPATIBILITY
+ #define configENABLE_BACKWARD_COMPATIBILITY 1
+#endif
+
+#ifndef configPRINTF
+
+/* configPRINTF() was not defined, so define it away to nothing. To use
+ * configPRINTF() then define it as follows (where MyPrintFunction() is
+ * provided by the application writer):
+ *
+ * void MyPrintFunction(const char *pcFormat, ... );
+ #define configPRINTF( X ) MyPrintFunction X
+ *
+ * Then call like a standard printf() function, but placing brackets around
+ * all parameters so they are passed as a single parameter. For example:
+ * configPRINTF( ("Value = %d", MyVariable) ); */
+ #define configPRINTF( X )
+#endif
+
+#ifndef configMAX
+
+/* The application writer has not provided their own MAX macro, so define
+ * the following generic implementation. */
+ #define configMAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
+#endif
+
+#ifndef configMIN
+
+/* The application writer has not provided their own MIN macro, so define
+ * the following generic implementation. */
+ #define configMIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
+#endif
+
+#if configENABLE_BACKWARD_COMPATIBILITY == 1
+ #define eTaskStateGet eTaskGetState
+ #define portTickType TickType_t
+ #define xTaskHandle TaskHandle_t
+ #define xQueueHandle QueueHandle_t
+ #define xSemaphoreHandle SemaphoreHandle_t
+ #define xQueueSetHandle QueueSetHandle_t
+ #define xQueueSetMemberHandle QueueSetMemberHandle_t
+ #define xTimeOutType TimeOut_t
+ #define xMemoryRegion MemoryRegion_t
+ #define xTaskParameters TaskParameters_t
+ #define xTaskStatusType TaskStatus_t
+ #define xTimerHandle TimerHandle_t
+ #define xCoRoutineHandle CoRoutineHandle_t
+ #define pdTASK_HOOK_CODE TaskHookFunction_t
+ #define portTICK_RATE_MS portTICK_PERIOD_MS
+ #define pcTaskGetTaskName pcTaskGetName
+ #define pcTimerGetTimerName pcTimerGetName
+ #define pcQueueGetQueueName pcQueueGetName
+ #define vTaskGetTaskInfo vTaskGetInfo
+ #define xTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter
+
+/* Backward compatibility within the scheduler code only - these definitions
+ * are not really required but are included for completeness. */
+ #define tmrTIMER_CALLBACK TimerCallbackFunction_t
+ #define pdTASK_CODE TaskFunction_t
+ #define xListItem ListItem_t
+ #define xList List_t
+
+/* For libraries that break the list data hiding, and access list structure
+ * members directly (which is not supposed to be done). */
+ #define pxContainer pvContainer
+#endif /* configENABLE_BACKWARD_COMPATIBILITY */
+
+#if ( configUSE_ALTERNATIVE_API != 0 )
+ #error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0
+#endif
+
+/* Set configUSE_TASK_FPU_SUPPORT to 0 to omit floating point support even
+ * if floating point hardware is otherwise supported by the FreeRTOS port in use.
+ * This constant is not supported by all FreeRTOS ports that include floating
+ * point support. */
+#ifndef configUSE_TASK_FPU_SUPPORT
+ #define configUSE_TASK_FPU_SUPPORT 1
+#endif
+
+/* Set configENABLE_MPU to 1 to enable MPU support and 0 to disable it. This is
+ * currently used in ARMv8M ports. */
+#ifndef configENABLE_MPU
+ #define configENABLE_MPU 0
+#endif
+
+/* Set configENABLE_FPU to 1 to enable FPU support and 0 to disable it. This is
+ * currently used in ARMv8M ports. */
+#ifndef configENABLE_FPU
+ #define configENABLE_FPU 1
+#endif
+
+/* Set configENABLE_MVE to 1 to enable MVE support and 0 to disable it. This is
+ * currently used in ARMv8M ports. */
+#ifndef configENABLE_MVE
+ #define configENABLE_MVE 0
+#endif
+
+/* Set configENABLE_TRUSTZONE to 1 enable TrustZone support and 0 to disable it.
+ * This is currently used in ARMv8M ports. */
+#ifndef configENABLE_TRUSTZONE
+ #define configENABLE_TRUSTZONE 1
+#endif
+
+/* Set configRUN_FREERTOS_SECURE_ONLY to 1 to run the FreeRTOS ARMv8M port on
+ * the Secure Side only. */
+#ifndef configRUN_FREERTOS_SECURE_ONLY
+ #define configRUN_FREERTOS_SECURE_ONLY 0
+#endif
+
+#ifndef configRUN_ADDITIONAL_TESTS
+ #define configRUN_ADDITIONAL_TESTS 0
+#endif
+
+
+/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using
+ * dynamically allocated RAM, in which case when any task is deleted it is known
+ * that both the task's stack and TCB need to be freed. Sometimes the
+ * FreeRTOSConfig.h settings only allow a task to be created using statically
+ * allocated RAM, in which case when any task is deleted it is known that neither
+ * the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h
+ * settings allow a task to be created using either statically or dynamically
+ * allocated RAM, in which case a member of the TCB is used to record whether the
+ * stack and/or TCB were allocated statically or dynamically, so when a task is
+ * deleted the RAM that was allocated dynamically is freed again and no attempt is
+ * made to free the RAM that was allocated statically.
+ * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a
+ * task to be created using either statically or dynamically allocated RAM. Note
+ * that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
+ * a statically allocated stack and a dynamically allocated TCB.
+ *
+ * The following table lists various combinations of portUSING_MPU_WRAPPERS,
+ * configSUPPORT_DYNAMIC_ALLOCATION and configSUPPORT_STATIC_ALLOCATION and
+ * when it is possible to have both static and dynamic allocation:
+ * +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+
+ * | MPU | Dynamic | Static | Available Functions | Possible Allocations | Both Dynamic and | Need Free |
+ * | | | | | | Static Possible | |
+ * +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+
+ * | 0 | 0 | 1 | xTaskCreateStatic | TCB - Static, Stack - Static | No | No |
+ * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------|
+ * | 0 | 1 | 0 | xTaskCreate | TCB - Dynamic, Stack - Dynamic | No | Yes |
+ * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------|
+ * | 0 | 1 | 1 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes |
+ * | | | | xTaskCreateStatic | 2. TCB - Static, Stack - Static | | |
+ * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------|
+ * | 1 | 0 | 1 | xTaskCreateStatic, | TCB - Static, Stack - Static | No | No |
+ * | | | | xTaskCreateRestrictedStatic | | | |
+ * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------|
+ * | 1 | 1 | 0 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes |
+ * | | | | xTaskCreateRestricted | 2. TCB - Dynamic, Stack - Static | | |
+ * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------|
+ * | 1 | 1 | 1 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes |
+ * | | | | xTaskCreateStatic, | 2. TCB - Dynamic, Stack - Static | | |
+ * | | | | xTaskCreateRestricted, | 3. TCB - Static, Stack - Static | | |
+ * | | | | xTaskCreateRestrictedStatic | | | |
+ * +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+
+ */
+#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE \
+ ( ( ( portUSING_MPU_WRAPPERS == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) || \
+ ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) )
+
+/*
+ * In line with software engineering best practice, FreeRTOS implements a strict
+ * data hiding policy, so the real structures used by FreeRTOS to maintain the
+ * state of tasks, queues, semaphores, etc. are not accessible to the application
+ * code. However, if the application writer wants to statically allocate such
+ * an object then the size of the object needs to be known. Dummy structures
+ * that are guaranteed to have the same size and alignment requirements of the
+ * real objects are used for this purpose. The dummy list and list item
+ * structures below are used for inclusion in such a dummy structure.
+ */
+struct xSTATIC_LIST_ITEM
+{
+ #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 )
+ TickType_t xDummy1;
+ #endif
+ TickType_t xDummy2;
+ void * pvDummy3[ 4 ];
+ #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 )
+ TickType_t xDummy4;
+ #endif
+};
+typedef struct xSTATIC_LIST_ITEM StaticListItem_t;
+
+#if ( configUSE_MINI_LIST_ITEM == 1 )
+ /* See the comments above the struct xSTATIC_LIST_ITEM definition. */
+ struct xSTATIC_MINI_LIST_ITEM
+ {
+ #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 )
+ TickType_t xDummy1;
+ #endif
+ TickType_t xDummy2;
+ void * pvDummy3[ 2 ];
+ };
+ typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t;
+#else /* if ( configUSE_MINI_LIST_ITEM == 1 ) */
+ typedef struct xSTATIC_LIST_ITEM StaticMiniListItem_t;
+#endif /* if ( configUSE_MINI_LIST_ITEM == 1 ) */
+
+/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
+typedef struct xSTATIC_LIST
+{
+ #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 )
+ TickType_t xDummy1;
+ #endif
+ UBaseType_t uxDummy2;
+ void * pvDummy3;
+ StaticMiniListItem_t xDummy4;
+ #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 )
+ TickType_t xDummy5;
+ #endif
+} StaticList_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the Task structure used internally by
+ * FreeRTOS is not accessible to application code. However, if the application
+ * writer wants to statically allocate the memory required to create a task then
+ * the size of the task object needs to be known. The StaticTask_t structure
+ * below is provided for this purpose. Its sizes and alignment requirements are
+ * guaranteed to match those of the genuine structure, no matter which
+ * architecture is being used, and no matter how the values in FreeRTOSConfig.h
+ * are set. Its contents are somewhat obfuscated in the hope users will
+ * recognise that it would be unwise to make direct use of the structure members.
+ */
+typedef struct xSTATIC_TCB
+{
+ void * pxDummy1;
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ xMPU_SETTINGS xDummy2;
+ #endif
+ StaticListItem_t xDummy3[ 2 ];
+ UBaseType_t uxDummy5;
+ void * pxDummy6;
+ uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ];
+ #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
+ void * pxDummy8;
+ #endif
+ #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+ UBaseType_t uxDummy9;
+ #endif
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy10[ 2 ];
+ #endif
+ #if ( configUSE_MUTEXES == 1 )
+ UBaseType_t uxDummy12[ 2 ];
+ #endif
+ #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+ void * pxDummy14;
+ #endif
+ #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
+ void * pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
+ #endif
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ configRUN_TIME_COUNTER_TYPE ulDummy16;
+ #endif
+ #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
+ configTLS_BLOCK_TYPE xDummy17;
+ #endif
+ #if ( configUSE_TASK_NOTIFICATIONS == 1 )
+ uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
+ uint8_t ucDummy19[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
+ #endif
+ #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+ uint8_t uxDummy20;
+ #endif
+
+ #if ( INCLUDE_xTaskAbortDelay == 1 )
+ uint8_t ucDummy21;
+ #endif
+ #if ( configUSE_POSIX_ERRNO == 1 )
+ int iDummy22;
+ #endif
+} StaticTask_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the Queue structure used internally by
+ * FreeRTOS is not accessible to application code. However, if the application
+ * writer wants to statically allocate the memory required to create a queue
+ * then the size of the queue object needs to be known. The StaticQueue_t
+ * structure below is provided for this purpose. Its sizes and alignment
+ * requirements are guaranteed to match those of the genuine structure, no
+ * matter which architecture is being used, and no matter how the values in
+ * FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in the hope
+ * users will recognise that it would be unwise to make direct use of the
+ * structure members.
+ */
+typedef struct xSTATIC_QUEUE
+{
+ void * pvDummy1[ 3 ];
+
+ union
+ {
+ void * pvDummy2;
+ UBaseType_t uxDummy2;
+ } u;
+
+ StaticList_t xDummy3[ 2 ];
+ UBaseType_t uxDummy4[ 3 ];
+ uint8_t ucDummy5[ 2 ];
+
+ #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucDummy6;
+ #endif
+
+ #if ( configUSE_QUEUE_SETS == 1 )
+ void * pvDummy7;
+ #endif
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy8;
+ uint8_t ucDummy9;
+ #endif
+} StaticQueue_t;
+typedef StaticQueue_t StaticSemaphore_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the event group structure used
+ * internally by FreeRTOS is not accessible to application code. However, if
+ * the application writer wants to statically allocate the memory required to
+ * create an event group then the size of the event group object needs to be
+ * know. The StaticEventGroup_t structure below is provided for this purpose.
+ * Its sizes and alignment requirements are guaranteed to match those of the
+ * genuine structure, no matter which architecture is being used, and no matter
+ * how the values in FreeRTOSConfig.h are set. Its contents are somewhat
+ * obfuscated in the hope users will recognise that it would be unwise to make
+ * direct use of the structure members.
+ */
+typedef struct xSTATIC_EVENT_GROUP
+{
+ TickType_t xDummy1;
+ StaticList_t xDummy2;
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy3;
+ #endif
+
+ #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucDummy4;
+ #endif
+} StaticEventGroup_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the software timer structure used
+ * internally by FreeRTOS is not accessible to application code. However, if
+ * the application writer wants to statically allocate the memory required to
+ * create a software timer then the size of the queue object needs to be known.
+ * The StaticTimer_t structure below is provided for this purpose. Its sizes
+ * and alignment requirements are guaranteed to match those of the genuine
+ * structure, no matter which architecture is being used, and no matter how the
+ * values in FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in
+ * the hope users will recognise that it would be unwise to make direct use of
+ * the structure members.
+ */
+typedef struct xSTATIC_TIMER
+{
+ void * pvDummy1;
+ StaticListItem_t xDummy2;
+ TickType_t xDummy3;
+ void * pvDummy5;
+ TaskFunction_t pvDummy6;
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy7;
+ #endif
+ uint8_t ucDummy8;
+} StaticTimer_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the stream buffer structure used
+ * internally by FreeRTOS is not accessible to application code. However, if
+ * the application writer wants to statically allocate the memory required to
+ * create a stream buffer then the size of the stream buffer object needs to be
+ * known. The StaticStreamBuffer_t structure below is provided for this
+ * purpose. Its size and alignment requirements are guaranteed to match those
+ * of the genuine structure, no matter which architecture is being used, and
+ * no matter how the values in FreeRTOSConfig.h are set. Its contents are
+ * somewhat obfuscated in the hope users will recognise that it would be unwise
+ * to make direct use of the structure members.
+ */
+typedef struct xSTATIC_STREAM_BUFFER
+{
+ size_t uxDummy1[ 4 ];
+ void * pvDummy2[ 3 ];
+ uint8_t ucDummy3;
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy4;
+ #endif
+ #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ void * pvDummy5[ 2 ];
+ #endif
+} StaticStreamBuffer_t;
+
+/* Message buffers are built on stream buffers. */
+typedef StaticStreamBuffer_t StaticMessageBuffer_t;
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ }
+#endif
+/* *INDENT-ON* */
+
+#endif /* INC_FREERTOS_H */
diff --git a/source/test/freertos/inc/StackMacros.h b/source/test/freertos/inc/StackMacros.h
new file mode 100644
index 0000000..099ac0c
--- /dev/null
+++ b/source/test/freertos/inc/StackMacros.h
@@ -0,0 +1,34 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+
+#ifndef _MSC_VER /* Visual Studio doesn't support #warning. */
+ #warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in a future release.
+#endif
+
+#include "stack_macros.h"
diff --git a/source/test/freertos/inc/atomic.h b/source/test/freertos/inc/atomic.h
new file mode 100644
index 0000000..8e356e1
--- /dev/null
+++ b/source/test/freertos/inc/atomic.h
@@ -0,0 +1,419 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/**
+ * @file atomic.h
+ * @brief FreeRTOS atomic operation support.
+ *
+ * This file implements atomic functions by disabling interrupts globally.
+ * Implementations with architecture specific atomic instructions can be
+ * provided under each compiler directory.
+ */
+
+#ifndef ATOMIC_H
+#define ATOMIC_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h must appear in source files before include atomic.h"
+#endif
+
+/* Standard includes. */
+#include
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+/*
+ * Port specific definitions -- entering/exiting critical section.
+ * Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h
+ *
+ * Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with
+ * ATOMIC_ENTER_CRITICAL().
+ *
+ */
+#if defined( portSET_INTERRUPT_MASK_FROM_ISR )
+
+/* Nested interrupt scheme is supported in this port. */
+ #define ATOMIC_ENTER_CRITICAL() \
+ UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR()
+
+ #define ATOMIC_EXIT_CRITICAL() \
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType )
+
+#else
+
+/* Nested interrupt scheme is NOT supported in this port. */
+ #define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL()
+ #define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL()
+
+#endif /* portSET_INTERRUPT_MASK_FROM_ISR() */
+
+/*
+ * Port specific definition -- "always inline".
+ * Inline is compiler specific, and may not always get inlined depending on your
+ * optimization level. Also, inline is considered as performance optimization
+ * for atomic. Thus, if portFORCE_INLINE is not provided by portmacro.h,
+ * instead of resulting error, simply define it away.
+ */
+#ifndef portFORCE_INLINE
+ #define portFORCE_INLINE
+#endif
+
+#define ATOMIC_COMPARE_AND_SWAP_SUCCESS 0x1U /**< Compare and swap succeeded, swapped. */
+#define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U /**< Compare and swap failed, did not swap. */
+
+/*----------------------------- Swap && CAS ------------------------------*/
+
+/**
+ * Atomic compare-and-swap
+ *
+ * @brief Performs an atomic compare-and-swap operation on the specified values.
+ *
+ * @param[in, out] pulDestination Pointer to memory location from where value is
+ * to be loaded and checked.
+ * @param[in] ulExchange If condition meets, write this value to memory.
+ * @param[in] ulComparand Swap condition.
+ *
+ * @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
+ *
+ * @note This function only swaps *pulDestination with ulExchange, if previous
+ * *pulDestination value equals ulComparand.
+ */
+static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination,
+ uint32_t ulExchange,
+ uint32_t ulComparand )
+{
+ uint32_t ulReturnValue;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ if( *pulDestination == ulComparand )
+ {
+ *pulDestination = ulExchange;
+ ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
+ }
+ else
+ {
+ ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
+ }
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return ulReturnValue;
+}
+/*-----------------------------------------------------------*/
+
+/**
+ * Atomic swap (pointers)
+ *
+ * @brief Atomically sets the address pointed to by *ppvDestination to the value
+ * of *pvExchange.
+ *
+ * @param[in, out] ppvDestination Pointer to memory location from where a pointer
+ * value is to be loaded and written back to.
+ * @param[in] pvExchange Pointer value to be written to *ppvDestination.
+ *
+ * @return The initial value of *ppvDestination.
+ */
+static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination,
+ void * pvExchange )
+{
+ void * pReturnValue;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ pReturnValue = *ppvDestination;
+ *ppvDestination = pvExchange;
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return pReturnValue;
+}
+/*-----------------------------------------------------------*/
+
+/**
+ * Atomic compare-and-swap (pointers)
+ *
+ * @brief Performs an atomic compare-and-swap operation on the specified pointer
+ * values.
+ *
+ * @param[in, out] ppvDestination Pointer to memory location from where a pointer
+ * value is to be loaded and checked.
+ * @param[in] pvExchange If condition meets, write this value to memory.
+ * @param[in] pvComparand Swap condition.
+ *
+ * @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
+ *
+ * @note This function only swaps *ppvDestination with pvExchange, if previous
+ * *ppvDestination value equals pvComparand.
+ */
+static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination,
+ void * pvExchange,
+ void * pvComparand )
+{
+ uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ if( *ppvDestination == pvComparand )
+ {
+ *ppvDestination = pvExchange;
+ ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
+ }
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return ulReturnValue;
+}
+
+
+/*----------------------------- Arithmetic ------------------------------*/
+
+/**
+ * Atomic add
+ *
+ * @brief Atomically adds count to the value of the specified pointer points to.
+ *
+ * @param[in,out] pulAddend Pointer to memory location from where value is to be
+ * loaded and written back to.
+ * @param[in] ulCount Value to be added to *pulAddend.
+ *
+ * @return previous *pulAddend value.
+ */
+static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend,
+ uint32_t ulCount )
+{
+ uint32_t ulCurrent;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ ulCurrent = *pulAddend;
+ *pulAddend += ulCount;
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return ulCurrent;
+}
+/*-----------------------------------------------------------*/
+
+/**
+ * Atomic subtract
+ *
+ * @brief Atomically subtracts count from the value of the specified pointer
+ * pointers to.
+ *
+ * @param[in,out] pulAddend Pointer to memory location from where value is to be
+ * loaded and written back to.
+ * @param[in] ulCount Value to be subtract from *pulAddend.
+ *
+ * @return previous *pulAddend value.
+ */
+static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAddend,
+ uint32_t ulCount )
+{
+ uint32_t ulCurrent;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ ulCurrent = *pulAddend;
+ *pulAddend -= ulCount;
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return ulCurrent;
+}
+/*-----------------------------------------------------------*/
+
+/**
+ * Atomic increment
+ *
+ * @brief Atomically increments the value of the specified pointer points to.
+ *
+ * @param[in,out] pulAddend Pointer to memory location from where value is to be
+ * loaded and written back to.
+ *
+ * @return *pulAddend value before increment.
+ */
+static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend )
+{
+ uint32_t ulCurrent;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ ulCurrent = *pulAddend;
+ *pulAddend += 1;
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return ulCurrent;
+}
+/*-----------------------------------------------------------*/
+
+/**
+ * Atomic decrement
+ *
+ * @brief Atomically decrements the value of the specified pointer points to
+ *
+ * @param[in,out] pulAddend Pointer to memory location from where value is to be
+ * loaded and written back to.
+ *
+ * @return *pulAddend value before decrement.
+ */
+static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend )
+{
+ uint32_t ulCurrent;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ ulCurrent = *pulAddend;
+ *pulAddend -= 1;
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return ulCurrent;
+}
+
+/*----------------------------- Bitwise Logical ------------------------------*/
+
+/**
+ * Atomic OR
+ *
+ * @brief Performs an atomic OR operation on the specified values.
+ *
+ * @param [in, out] pulDestination Pointer to memory location from where value is
+ * to be loaded and written back to.
+ * @param [in] ulValue Value to be ORed with *pulDestination.
+ *
+ * @return The original value of *pulDestination.
+ */
+static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination,
+ uint32_t ulValue )
+{
+ uint32_t ulCurrent;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ ulCurrent = *pulDestination;
+ *pulDestination |= ulValue;
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return ulCurrent;
+}
+/*-----------------------------------------------------------*/
+
+/**
+ * Atomic AND
+ *
+ * @brief Performs an atomic AND operation on the specified values.
+ *
+ * @param [in, out] pulDestination Pointer to memory location from where value is
+ * to be loaded and written back to.
+ * @param [in] ulValue Value to be ANDed with *pulDestination.
+ *
+ * @return The original value of *pulDestination.
+ */
+static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination,
+ uint32_t ulValue )
+{
+ uint32_t ulCurrent;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ ulCurrent = *pulDestination;
+ *pulDestination &= ulValue;
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return ulCurrent;
+}
+/*-----------------------------------------------------------*/
+
+/**
+ * Atomic NAND
+ *
+ * @brief Performs an atomic NAND operation on the specified values.
+ *
+ * @param [in, out] pulDestination Pointer to memory location from where value is
+ * to be loaded and written back to.
+ * @param [in] ulValue Value to be NANDed with *pulDestination.
+ *
+ * @return The original value of *pulDestination.
+ */
+static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination,
+ uint32_t ulValue )
+{
+ uint32_t ulCurrent;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ ulCurrent = *pulDestination;
+ *pulDestination = ~( ulCurrent & ulValue );
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return ulCurrent;
+}
+/*-----------------------------------------------------------*/
+
+/**
+ * Atomic XOR
+ *
+ * @brief Performs an atomic XOR operation on the specified values.
+ *
+ * @param [in, out] pulDestination Pointer to memory location from where value is
+ * to be loaded and written back to.
+ * @param [in] ulValue Value to be XORed with *pulDestination.
+ *
+ * @return The original value of *pulDestination.
+ */
+static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination,
+ uint32_t ulValue )
+{
+ uint32_t ulCurrent;
+
+ ATOMIC_ENTER_CRITICAL();
+ {
+ ulCurrent = *pulDestination;
+ *pulDestination ^= ulValue;
+ }
+ ATOMIC_EXIT_CRITICAL();
+
+ return ulCurrent;
+}
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ }
+#endif
+/* *INDENT-ON* */
+
+#endif /* ATOMIC_H */
diff --git a/source/test/freertos/inc/croutine.h b/source/test/freertos/inc/croutine.h
new file mode 100644
index 0000000..48e6f03
--- /dev/null
+++ b/source/test/freertos/inc/croutine.h
@@ -0,0 +1,753 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef CO_ROUTINE_H
+#define CO_ROUTINE_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h must appear in source files before include croutine.h"
+#endif
+
+#include "list.h"
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+/* Used to hide the implementation of the co-routine control block. The
+ * control block structure however has to be included in the header due to
+ * the macro implementation of the co-routine functionality. */
+typedef void * CoRoutineHandle_t;
+
+/* Defines the prototype to which co-routine functions must conform. */
+typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t,
+ UBaseType_t );
+
+typedef struct corCoRoutineControlBlock
+{
+ crCOROUTINE_CODE pxCoRoutineFunction;
+ ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */
+ ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */
+ UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */
+ UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
+ uint16_t uxState; /*< Used internally by the co-routine implementation. */
+} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
+
+/**
+ * croutine. h
+ * @code{c}
+ * BaseType_t xCoRoutineCreate(
+ * crCOROUTINE_CODE pxCoRoutineCode,
+ * UBaseType_t uxPriority,
+ * UBaseType_t uxIndex
+ * );
+ * @endcode
+ *
+ * Create a new co-routine and add it to the list of co-routines that are
+ * ready to run.
+ *
+ * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
+ * functions require special syntax - see the co-routine section of the WEB
+ * documentation for more information.
+ *
+ * @param uxPriority The priority with respect to other co-routines at which
+ * the co-routine will run.
+ *
+ * @param uxIndex Used to distinguish between different co-routines that
+ * execute the same function. See the example below and the co-routine section
+ * of the WEB documentation for further information.
+ *
+ * @return pdPASS if the co-routine was successfully created and added to a ready
+ * list, otherwise an error code defined with ProjDefs.h.
+ *
+ * Example usage:
+ * @code{c}
+ * // Co-routine to be created.
+ * void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ * {
+ * // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ * // This may not be necessary for const variables.
+ * static const char cLedToFlash[ 2 ] = { 5, 6 };
+ * static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
+ *
+ * // Must start every co-routine with a call to crSTART();
+ * crSTART( xHandle );
+ *
+ * for( ;; )
+ * {
+ * // This co-routine just delays for a fixed period, then toggles
+ * // an LED. Two co-routines are created using this function, so
+ * // the uxIndex parameter is used to tell the co-routine which
+ * // LED to flash and how int32_t to delay. This assumes xQueue has
+ * // already been created.
+ * vParTestToggleLED( cLedToFlash[ uxIndex ] );
+ * crDELAY( xHandle, uxFlashRates[ uxIndex ] );
+ * }
+ *
+ * // Must end every co-routine with a call to crEND();
+ * crEND();
+ * }
+ *
+ * // Function that creates two co-routines.
+ * void vOtherFunction( void )
+ * {
+ * uint8_t ucParameterToPass;
+ * TaskHandle_t xHandle;
+ *
+ * // Create two co-routines at priority 0. The first is given index 0
+ * // so (from the code above) toggles LED 5 every 200 ticks. The second
+ * // is given index 1 so toggles LED 6 every 400 ticks.
+ * for( uxIndex = 0; uxIndex < 2; uxIndex++ )
+ * {
+ * xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
+ * }
+ * }
+ * @endcode
+ * \defgroup xCoRoutineCreate xCoRoutineCreate
+ * \ingroup Tasks
+ */
+BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
+ UBaseType_t uxPriority,
+ UBaseType_t uxIndex );
+
+
+/**
+ * croutine. h
+ * @code{c}
+ * void vCoRoutineSchedule( void );
+ * @endcode
+ *
+ * Run a co-routine.
+ *
+ * vCoRoutineSchedule() executes the highest priority co-routine that is able
+ * to run. The co-routine will execute until it either blocks, yields or is
+ * preempted by a task. Co-routines execute cooperatively so one
+ * co-routine cannot be preempted by another, but can be preempted by a task.
+ *
+ * If an application comprises of both tasks and co-routines then
+ * vCoRoutineSchedule should be called from the idle task (in an idle task
+ * hook).
+ *
+ * Example usage:
+ * @code{c}
+ * // This idle task hook will schedule a co-routine each time it is called.
+ * // The rest of the idle task will execute between co-routine calls.
+ * void vApplicationIdleHook( void )
+ * {
+ * vCoRoutineSchedule();
+ * }
+ *
+ * // Alternatively, if you do not require any other part of the idle task to
+ * // execute, the idle task hook can call vCoRoutineSchedule() within an
+ * // infinite loop.
+ * void vApplicationIdleHook( void )
+ * {
+ * for( ;; )
+ * {
+ * vCoRoutineSchedule();
+ * }
+ * }
+ * @endcode
+ * \defgroup vCoRoutineSchedule vCoRoutineSchedule
+ * \ingroup Tasks
+ */
+void vCoRoutineSchedule( void );
+
+/**
+ * croutine. h
+ * @code{c}
+ * crSTART( CoRoutineHandle_t xHandle );
+ * @endcode
+ *
+ * This macro MUST always be called at the start of a co-routine function.
+ *
+ * Example usage:
+ * @code{c}
+ * // Co-routine to be created.
+ * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ * {
+ * // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ * static int32_t ulAVariable;
+ *
+ * // Must start every co-routine with a call to crSTART();
+ * crSTART( xHandle );
+ *
+ * for( ;; )
+ * {
+ * // Co-routine functionality goes here.
+ * }
+ *
+ * // Must end every co-routine with a call to crEND();
+ * crEND();
+ * }
+ * @endcode
+ * \defgroup crSTART crSTART
+ * \ingroup Tasks
+ */
+#define crSTART( pxCRCB ) \
+ switch( ( ( CRCB_t * ) ( pxCRCB ) )->uxState ) { \
+ case 0:
+
+/**
+ * croutine. h
+ * @code{c}
+ * crEND();
+ * @endcode
+ *
+ * This macro MUST always be called at the end of a co-routine function.
+ *
+ * Example usage:
+ * @code{c}
+ * // Co-routine to be created.
+ * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ * {
+ * // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ * static int32_t ulAVariable;
+ *
+ * // Must start every co-routine with a call to crSTART();
+ * crSTART( xHandle );
+ *
+ * for( ;; )
+ * {
+ * // Co-routine functionality goes here.
+ * }
+ *
+ * // Must end every co-routine with a call to crEND();
+ * crEND();
+ * }
+ * @endcode
+ * \defgroup crSTART crSTART
+ * \ingroup Tasks
+ */
+#define crEND() }
+
+/*
+ * These macros are intended for internal use by the co-routine implementation
+ * only. The macros should not be used directly by application writers.
+ */
+#define crSET_STATE0( xHandle ) \
+ ( ( CRCB_t * ) ( xHandle ) )->uxState = ( __LINE__ * 2 ); return; \
+ case ( __LINE__ * 2 ):
+#define crSET_STATE1( xHandle ) \
+ ( ( CRCB_t * ) ( xHandle ) )->uxState = ( ( __LINE__ * 2 ) + 1 ); return; \
+ case ( ( __LINE__ * 2 ) + 1 ):
+
+/**
+ * croutine. h
+ * @code{c}
+ * crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
+ * @endcode
+ *
+ * Delay a co-routine for a fixed period of time.
+ *
+ * crDELAY can only be called from the co-routine function itself - not
+ * from within a function called by the co-routine function. This is because
+ * co-routines do not maintain their own stack.
+ *
+ * @param xHandle The handle of the co-routine to delay. This is the xHandle
+ * parameter of the co-routine function.
+ *
+ * @param xTickToDelay The number of ticks that the co-routine should delay
+ * for. The actual amount of time this equates to is defined by
+ * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS
+ * can be used to convert ticks to milliseconds.
+ *
+ * Example usage:
+ * @code{c}
+ * // Co-routine to be created.
+ * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ * {
+ * // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ * // This may not be necessary for const variables.
+ * // We are to delay for 200ms.
+ * static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
+ *
+ * // Must start every co-routine with a call to crSTART();
+ * crSTART( xHandle );
+ *
+ * for( ;; )
+ * {
+ * // Delay for 200ms.
+ * crDELAY( xHandle, xDelayTime );
+ *
+ * // Do something here.
+ * }
+ *
+ * // Must end every co-routine with a call to crEND();
+ * crEND();
+ * }
+ * @endcode
+ * \defgroup crDELAY crDELAY
+ * \ingroup Tasks
+ */
+#define crDELAY( xHandle, xTicksToDelay ) \
+ if( ( xTicksToDelay ) > 0 ) \
+ { \
+ vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \
+ } \
+ crSET_STATE0( ( xHandle ) );
+
+/**
+ * @code{c}
+ * crQUEUE_SEND(
+ * CoRoutineHandle_t xHandle,
+ * QueueHandle_t pxQueue,
+ * void *pvItemToQueue,
+ * TickType_t xTicksToWait,
+ * BaseType_t *pxResult
+ * )
+ * @endcode
+ *
+ * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
+ * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
+ *
+ * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
+ * xQueueSend() and xQueueReceive() can only be used from tasks.
+ *
+ * crQUEUE_SEND can only be called from the co-routine function itself - not
+ * from within a function called by the co-routine function. This is because
+ * co-routines do not maintain their own stack.
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xHandle The handle of the calling co-routine. This is the xHandle
+ * parameter of the co-routine function.
+ *
+ * @param pxQueue The handle of the queue on which the data will be posted.
+ * The handle is obtained as the return value when the queue is created using
+ * the xQueueCreate() API function.
+ *
+ * @param pvItemToQueue A pointer to the data being posted onto the queue.
+ * The number of bytes of each queued item is specified when the queue is
+ * created. This number of bytes is copied from pvItemToQueue into the queue
+ * itself.
+ *
+ * @param xTickToDelay The number of ticks that the co-routine should block
+ * to wait for space to become available on the queue, should space not be
+ * available immediately. The actual amount of time this equates to is defined
+ * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
+ * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
+ * below).
+ *
+ * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
+ * data was successfully posted onto the queue, otherwise it will be set to an
+ * error defined within ProjDefs.h.
+ *
+ * Example usage:
+ * @code{c}
+ * // Co-routine function that blocks for a fixed period then posts a number onto
+ * // a queue.
+ * static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ * {
+ * // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ * static BaseType_t xNumberToPost = 0;
+ * static BaseType_t xResult;
+ *
+ * // Co-routines must begin with a call to crSTART().
+ * crSTART( xHandle );
+ *
+ * for( ;; )
+ * {
+ * // This assumes the queue has already been created.
+ * crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
+ *
+ * if( xResult != pdPASS )
+ * {
+ * // The message was not posted!
+ * }
+ *
+ * // Increment the number to be posted onto the queue.
+ * xNumberToPost++;
+ *
+ * // Delay for 100 ticks.
+ * crDELAY( xHandle, 100 );
+ * }
+ *
+ * // Co-routines must end with a call to crEND().
+ * crEND();
+ * }
+ * @endcode
+ * \defgroup crQUEUE_SEND crQUEUE_SEND
+ * \ingroup Tasks
+ */
+#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \
+ { \
+ *( pxResult ) = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), ( xTicksToWait ) ); \
+ if( *( pxResult ) == errQUEUE_BLOCKED ) \
+ { \
+ crSET_STATE0( ( xHandle ) ); \
+ *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \
+ } \
+ if( *pxResult == errQUEUE_YIELD ) \
+ { \
+ crSET_STATE1( ( xHandle ) ); \
+ *pxResult = pdPASS; \
+ } \
+ }
+
+/**
+ * croutine. h
+ * @code{c}
+ * crQUEUE_RECEIVE(
+ * CoRoutineHandle_t xHandle,
+ * QueueHandle_t pxQueue,
+ * void *pvBuffer,
+ * TickType_t xTicksToWait,
+ * BaseType_t *pxResult
+ * )
+ * @endcode
+ *
+ * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
+ * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
+ *
+ * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
+ * xQueueSend() and xQueueReceive() can only be used from tasks.
+ *
+ * crQUEUE_RECEIVE can only be called from the co-routine function itself - not
+ * from within a function called by the co-routine function. This is because
+ * co-routines do not maintain their own stack.
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xHandle The handle of the calling co-routine. This is the xHandle
+ * parameter of the co-routine function.
+ *
+ * @param pxQueue The handle of the queue from which the data will be received.
+ * The handle is obtained as the return value when the queue is created using
+ * the xQueueCreate() API function.
+ *
+ * @param pvBuffer The buffer into which the received item is to be copied.
+ * The number of bytes of each queued item is specified when the queue is
+ * created. This number of bytes is copied into pvBuffer.
+ *
+ * @param xTickToDelay The number of ticks that the co-routine should block
+ * to wait for data to become available from the queue, should data not be
+ * available immediately. The actual amount of time this equates to is defined
+ * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
+ * portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
+ * crQUEUE_SEND example).
+ *
+ * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
+ * data was successfully retrieved from the queue, otherwise it will be set to
+ * an error code as defined within ProjDefs.h.
+ *
+ * Example usage:
+ * @code{c}
+ * // A co-routine receives the number of an LED to flash from a queue. It
+ * // blocks on the queue until the number is received.
+ * static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ * {
+ * // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ * static BaseType_t xResult;
+ * static UBaseType_t uxLEDToFlash;
+ *
+ * // All co-routines must start with a call to crSTART().
+ * crSTART( xHandle );
+ *
+ * for( ;; )
+ * {
+ * // Wait for data to become available on the queue.
+ * crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+ *
+ * if( xResult == pdPASS )
+ * {
+ * // We received the LED to flash - flash it!
+ * vParTestToggleLED( uxLEDToFlash );
+ * }
+ * }
+ *
+ * crEND();
+ * }
+ * @endcode
+ * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
+ * \ingroup Tasks
+ */
+#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \
+ { \
+ *( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), ( xTicksToWait ) ); \
+ if( *( pxResult ) == errQUEUE_BLOCKED ) \
+ { \
+ crSET_STATE0( ( xHandle ) ); \
+ *( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), 0 ); \
+ } \
+ if( *( pxResult ) == errQUEUE_YIELD ) \
+ { \
+ crSET_STATE1( ( xHandle ) ); \
+ *( pxResult ) = pdPASS; \
+ } \
+ }
+
+/**
+ * croutine. h
+ * @code{c}
+ * crQUEUE_SEND_FROM_ISR(
+ * QueueHandle_t pxQueue,
+ * void *pvItemToQueue,
+ * BaseType_t xCoRoutinePreviouslyWoken
+ * )
+ * @endcode
+ *
+ * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
+ * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
+ * functions used by tasks.
+ *
+ * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
+ * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
+ * xQueueReceiveFromISR() can only be used to pass data between a task and and
+ * ISR.
+ *
+ * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
+ * that is being used from within a co-routine.
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
+ * the same queue multiple times from a single interrupt. The first call
+ * should always pass in pdFALSE. Subsequent calls should pass in
+ * the value returned from the previous call.
+ *
+ * @return pdTRUE if a co-routine was woken by posting onto the queue. This is
+ * used by the ISR to determine if a context switch may be required following
+ * the ISR.
+ *
+ * Example usage:
+ * @code{c}
+ * // A co-routine that blocks on a queue waiting for characters to be received.
+ * static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ * {
+ * char cRxedChar;
+ * BaseType_t xResult;
+ *
+ * // All co-routines must start with a call to crSTART().
+ * crSTART( xHandle );
+ *
+ * for( ;; )
+ * {
+ * // Wait for data to become available on the queue. This assumes the
+ * // queue xCommsRxQueue has already been created!
+ * crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+ *
+ * // Was a character received?
+ * if( xResult == pdPASS )
+ * {
+ * // Process the character here.
+ * }
+ * }
+ *
+ * // All co-routines must end with a call to crEND().
+ * crEND();
+ * }
+ *
+ * // An ISR that uses a queue to send characters received on a serial port to
+ * // a co-routine.
+ * void vUART_ISR( void )
+ * {
+ * char cRxedChar;
+ * BaseType_t xCRWokenByPost = pdFALSE;
+ *
+ * // We loop around reading characters until there are none left in the UART.
+ * while( UART_RX_REG_NOT_EMPTY() )
+ * {
+ * // Obtain the character from the UART.
+ * cRxedChar = UART_RX_REG;
+ *
+ * // Post the character onto a queue. xCRWokenByPost will be pdFALSE
+ * // the first time around the loop. If the post causes a co-routine
+ * // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
+ * // In this manner we can ensure that if more than one co-routine is
+ * // blocked on the queue only one is woken by this ISR no matter how
+ * // many characters are posted to the queue.
+ * xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
+ * }
+ * }
+ * @endcode
+ * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
+ * \ingroup Tasks
+ */
+#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) \
+ xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
+
+
+/**
+ * croutine. h
+ * @code{c}
+ * crQUEUE_SEND_FROM_ISR(
+ * QueueHandle_t pxQueue,
+ * void *pvBuffer,
+ * BaseType_t * pxCoRoutineWoken
+ * )
+ * @endcode
+ *
+ * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
+ * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
+ * functions used by tasks.
+ *
+ * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
+ * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
+ * xQueueReceiveFromISR() can only be used to pass data between a task and and
+ * ISR.
+ *
+ * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
+ * from a queue that is being used from within a co-routine (a co-routine
+ * posted to the queue).
+ *
+ * See the co-routine section of the WEB documentation for information on
+ * passing data between tasks and co-routines and between ISR's and
+ * co-routines.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvBuffer A pointer to a buffer into which the received item will be
+ * placed. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from the queue into
+ * pvBuffer.
+ *
+ * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
+ * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
+ * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
+ * *pxCoRoutineWoken will remain unchanged.
+ *
+ * @return pdTRUE an item was successfully received from the queue, otherwise
+ * pdFALSE.
+ *
+ * Example usage:
+ * @code{c}
+ * // A co-routine that posts a character to a queue then blocks for a fixed
+ * // period. The character is incremented each time.
+ * static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
+ * {
+ * // cChar holds its value while this co-routine is blocked and must therefore
+ * // be declared static.
+ * static char cCharToTx = 'a';
+ * BaseType_t xResult;
+ *
+ * // All co-routines must start with a call to crSTART().
+ * crSTART( xHandle );
+ *
+ * for( ;; )
+ * {
+ * // Send the next character to the queue.
+ * crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
+ *
+ * if( xResult == pdPASS )
+ * {
+ * // The character was successfully posted to the queue.
+ * }
+ * else
+ * {
+ * // Could not post the character to the queue.
+ * }
+ *
+ * // Enable the UART Tx interrupt to cause an interrupt in this
+ * // hypothetical UART. The interrupt will obtain the character
+ * // from the queue and send it.
+ * ENABLE_RX_INTERRUPT();
+ *
+ * // Increment to the next character then block for a fixed period.
+ * // cCharToTx will maintain its value across the delay as it is
+ * // declared static.
+ * cCharToTx++;
+ * if( cCharToTx > 'x' )
+ * {
+ * cCharToTx = 'a';
+ * }
+ * crDELAY( 100 );
+ * }
+ *
+ * // All co-routines must end with a call to crEND().
+ * crEND();
+ * }
+ *
+ * // An ISR that uses a queue to receive characters to send on a UART.
+ * void vUART_ISR( void )
+ * {
+ * char cCharToTx;
+ * BaseType_t xCRWokenByPost = pdFALSE;
+ *
+ * while( UART_TX_REG_EMPTY() )
+ * {
+ * // Are there any characters in the queue waiting to be sent?
+ * // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
+ * // is woken by the post - ensuring that only a single co-routine is
+ * // woken no matter how many times we go around this loop.
+ * if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
+ * {
+ * SEND_CHARACTER( cCharToTx );
+ * }
+ * }
+ * }
+ * @endcode
+ * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
+ * \ingroup Tasks
+ */
+#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) \
+ xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
+
+/*
+ * This function is intended for internal use by the co-routine macros only.
+ * The macro nature of the co-routine implementation requires that the
+ * prototype appears here. The function should not be used by application
+ * writers.
+ *
+ * Removes the current co-routine from its ready list and places it in the
+ * appropriate delayed list.
+ */
+void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
+ List_t * pxEventList );
+
+/*
+ * This function is intended for internal use by the queue implementation only.
+ * The function should not be used by application writers.
+ *
+ * Removes the highest priority co-routine from the event list and places it in
+ * the pending ready list.
+ */
+BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList );
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ }
+#endif
+/* *INDENT-ON* */
+
+#endif /* CO_ROUTINE_H */
diff --git a/source/test/freertos/inc/deprecated_definitions.h b/source/test/freertos/inc/deprecated_definitions.h
new file mode 100644
index 0000000..1cb9372
--- /dev/null
+++ b/source/test/freertos/inc/deprecated_definitions.h
@@ -0,0 +1,281 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef DEPRECATED_DEFINITIONS_H
+#define DEPRECATED_DEFINITIONS_H
+
+
+/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
+ * pre-processor definition was used to ensure the pre-processor found the correct
+ * portmacro.h file for the port being used. That scheme was deprecated in favour
+ * of setting the compiler's include path such that it found the correct
+ * portmacro.h file - removing the need for the constant and allowing the
+ * portmacro.h file to be located anywhere in relation to the port being used. The
+ * definitions below remain in the code for backward compatibility only. New
+ * projects should not use them. */
+
+#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
+ #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
+ typedef void ( __interrupt __far * pxISR )();
+#endif
+
+#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
+ #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
+ typedef void ( __interrupt __far * pxISR )();
+#endif
+
+#ifdef GCC_MEGA_AVR
+ #include "../portable/GCC/ATMega323/portmacro.h"
+#endif
+
+#ifdef IAR_MEGA_AVR
+ #include "../portable/IAR/ATMega323/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC24_PORT
+ #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
+#endif
+
+#ifdef MPLAB_DSPIC_PORT
+ #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC18F_PORT
+ #include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC32MX_PORT
+ #include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
+#endif
+
+#ifdef _FEDPICC
+ #include "libFreeRTOS/Include/portmacro.h"
+#endif
+
+#ifdef SDCC_CYGNAL
+ #include "../../Source/portable/SDCC/Cygnal/portmacro.h"
+#endif
+
+#ifdef GCC_ARM7
+ #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
+#endif
+
+#ifdef GCC_ARM7_ECLIPSE
+ #include "portmacro.h"
+#endif
+
+#ifdef ROWLEY_LPC23xx
+ #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
+#endif
+
+#ifdef IAR_MSP430
+ #include "..\..\Source\portable\IAR\MSP430\portmacro.h"
+#endif
+
+#ifdef GCC_MSP430
+ #include "../../Source/portable/GCC/MSP430F449/portmacro.h"
+#endif
+
+#ifdef ROWLEY_MSP430
+ #include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
+#endif
+
+#ifdef ARM7_LPC21xx_KEIL_RVDS
+ #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
+#endif
+
+#ifdef SAM7_GCC
+ #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
+#endif
+
+#ifdef SAM7_IAR
+ #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
+#endif
+
+#ifdef SAM9XE_IAR
+ #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
+#endif
+
+#ifdef LPC2000_IAR
+ #include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
+#endif
+
+#ifdef STR71X_IAR
+ #include "..\..\Source\portable\IAR\STR71x\portmacro.h"
+#endif
+
+#ifdef STR75X_IAR
+ #include "..\..\Source\portable\IAR\STR75x\portmacro.h"
+#endif
+
+#ifdef STR75X_GCC
+ #include "..\..\Source\portable\GCC\STR75x\portmacro.h"
+#endif
+
+#ifdef STR91X_IAR
+ #include "..\..\Source\portable\IAR\STR91x\portmacro.h"
+#endif
+
+#ifdef GCC_H8S
+ #include "../../Source/portable/GCC/H8S2329/portmacro.h"
+#endif
+
+#ifdef GCC_AT91FR40008
+ #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
+#endif
+
+#ifdef RVDS_ARMCM3_LM3S102
+ #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef GCC_ARMCM3_LM3S102
+ #include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef GCC_ARMCM3
+ #include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef IAR_ARM_CM3
+ #include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef IAR_ARMCM3_LM
+ #include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef HCS12_CODE_WARRIOR
+ #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
+#endif
+
+#ifdef MICROBLAZE_GCC
+ #include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
+#endif
+
+#ifdef TERN_EE
+ #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
+#endif
+
+#ifdef GCC_HCS12
+ #include "../../Source/portable/GCC/HCS12/portmacro.h"
+#endif
+
+#ifdef GCC_MCF5235
+ #include "../../Source/portable/GCC/MCF5235/portmacro.h"
+#endif
+
+#ifdef COLDFIRE_V2_GCC
+ #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
+#endif
+
+#ifdef COLDFIRE_V2_CODEWARRIOR
+ #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
+#endif
+
+#ifdef GCC_PPC405
+ #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
+#endif
+
+#ifdef GCC_PPC440
+ #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
+#endif
+
+#ifdef _16FX_SOFTUNE
+ #include "..\..\Source\portable\Softune\MB96340\portmacro.h"
+#endif
+
+#ifdef BCC_INDUSTRIAL_PC_PORT
+
+/* A short file name has to be used in place of the normal
+ * FreeRTOSConfig.h when using the Borland compiler. */
+ #include "frconfig.h"
+ #include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
+ typedef void ( __interrupt __far * pxISR )();
+#endif
+
+#ifdef BCC_FLASH_LITE_186_PORT
+
+/* A short file name has to be used in place of the normal
+ * FreeRTOSConfig.h when using the Borland compiler. */
+ #include "frconfig.h"
+ #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
+ typedef void ( __interrupt __far * pxISR )();
+#endif
+
+#ifdef __GNUC__
+ #ifdef __AVR32_AVR32A__
+ #include "portmacro.h"
+ #endif
+#endif
+
+#ifdef __ICCAVR32__
+ #ifdef __CORE__
+ #if __CORE__ == __AVR32A__
+ #include "portmacro.h"
+ #endif
+ #endif
+#endif
+
+#ifdef __91467D
+ #include "portmacro.h"
+#endif
+
+#ifdef __96340
+ #include "portmacro.h"
+#endif
+
+
+#ifdef __IAR_V850ES_Fx3__
+ #include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx3__
+ #include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx3_L__
+ #include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx2__
+ #include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Hx2__
+ #include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_78K0R_Kx3__
+ #include "../../Source/portable/IAR/78K0R/portmacro.h"
+#endif
+
+#ifdef __IAR_78K0R_Kx3L__
+ #include "../../Source/portable/IAR/78K0R/portmacro.h"
+#endif
+
+#endif /* DEPRECATED_DEFINITIONS_H */
diff --git a/source/test/freertos/inc/event_groups.h b/source/test/freertos/inc/event_groups.h
new file mode 100644
index 0000000..275f316
--- /dev/null
+++ b/source/test/freertos/inc/event_groups.h
@@ -0,0 +1,783 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef EVENT_GROUPS_H
+#define EVENT_GROUPS_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
+#endif
+
+/* FreeRTOS includes. */
+#include "timers.h"
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+/**
+ * An event group is a collection of bits to which an application can assign a
+ * meaning. For example, an application may create an event group to convey
+ * the status of various CAN bus related events in which bit 0 might mean "A CAN
+ * message has been received and is ready for processing", bit 1 might mean "The
+ * application has queued a message that is ready for sending onto the CAN
+ * network", and bit 2 might mean "It is time to send a SYNC message onto the
+ * CAN network" etc. A task can then test the bit values to see which events
+ * are active, and optionally enter the Blocked state to wait for a specified
+ * bit or a group of specified bits to be active. To continue the CAN bus
+ * example, a CAN controlling task can enter the Blocked state (and therefore
+ * not consume any processing time) until either bit 0, bit 1 or bit 2 are
+ * active, at which time the bit that was actually active would inform the task
+ * which action it had to take (process a received message, send a message, or
+ * send a SYNC).
+ *
+ * The event groups implementation contains intelligence to avoid race
+ * conditions that would otherwise occur were an application to use a simple
+ * variable for the same purpose. This is particularly important with respect
+ * to when a bit within an event group is to be cleared, and when bits have to
+ * be set and then tested atomically - as is the case where event groups are
+ * used to create a synchronisation point between multiple tasks (a
+ * 'rendezvous').
+ */
+
+
+
+/**
+ * event_groups.h
+ *
+ * Type by which event groups are referenced. For example, a call to
+ * xEventGroupCreate() returns an EventGroupHandle_t variable that can then
+ * be used as a parameter to other event group functions.
+ *
+ * \defgroup EventGroupHandle_t EventGroupHandle_t
+ * \ingroup EventGroup
+ */
+struct EventGroupDef_t;
+typedef struct EventGroupDef_t * EventGroupHandle_t;
+
+/*
+ * The type that holds event bits always matches TickType_t - therefore the
+ * number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1,
+ * 32 bits if set to 0.
+ *
+ * \defgroup EventBits_t EventBits_t
+ * \ingroup EventGroup
+ */
+typedef TickType_t EventBits_t;
+
+/**
+ * event_groups.h
+ * @code{c}
+ * EventGroupHandle_t xEventGroupCreate( void );
+ * @endcode
+ *
+ * Create a new event group.
+ *
+ * Internally, within the FreeRTOS implementation, event groups use a [small]
+ * block of memory, in which the event group's structure is stored. If an event
+ * groups is created using xEventGroupCreate() then the required memory is
+ * automatically dynamically allocated inside the xEventGroupCreate() function.
+ * (see https://www.FreeRTOS.org/a00111.html). If an event group is created
+ * using xEventGroupCreateStatic() then the application writer must instead
+ * provide the memory that will get used by the event group.
+ * xEventGroupCreateStatic() therefore allows an event group to be created
+ * without using any dynamic memory allocation.
+ *
+ * Although event groups are not related to ticks, for internal implementation
+ * reasons the number of bits available for use in an event group is dependent
+ * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
+ * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
+ * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
+ * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
+ * event bits within an event group.
+ *
+ * @return If the event group was created then a handle to the event group is
+ * returned. If there was insufficient FreeRTOS heap available to create the
+ * event group then NULL is returned. See https://www.FreeRTOS.org/a00111.html
+ *
+ * Example usage:
+ * @code{c}
+ * // Declare a variable to hold the created event group.
+ * EventGroupHandle_t xCreatedEventGroup;
+ *
+ * // Attempt to create the event group.
+ * xCreatedEventGroup = xEventGroupCreate();
+ *
+ * // Was the event group created successfully?
+ * if( xCreatedEventGroup == NULL )
+ * {
+ * // The event group was not created because there was insufficient
+ * // FreeRTOS heap available.
+ * }
+ * else
+ * {
+ * // The event group was created.
+ * }
+ * @endcode
+ * \defgroup xEventGroupCreate xEventGroupCreate
+ * \ingroup EventGroup
+ */
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
+#endif
+
+/**
+ * event_groups.h
+ * @code{c}
+ * EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
+ * @endcode
+ *
+ * Create a new event group.
+ *
+ * Internally, within the FreeRTOS implementation, event groups use a [small]
+ * block of memory, in which the event group's structure is stored. If an event
+ * groups is created using xEventGroupCreate() then the required memory is
+ * automatically dynamically allocated inside the xEventGroupCreate() function.
+ * (see https://www.FreeRTOS.org/a00111.html). If an event group is created
+ * using xEventGroupCreateStatic() then the application writer must instead
+ * provide the memory that will get used by the event group.
+ * xEventGroupCreateStatic() therefore allows an event group to be created
+ * without using any dynamic memory allocation.
+ *
+ * Although event groups are not related to ticks, for internal implementation
+ * reasons the number of bits available for use in an event group is dependent
+ * on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
+ * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
+ * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
+ * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
+ * event bits within an event group.
+ *
+ * @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type
+ * StaticEventGroup_t, which will be then be used to hold the event group's data
+ * structures, removing the need for the memory to be allocated dynamically.
+ *
+ * @return If the event group was created then a handle to the event group is
+ * returned. If pxEventGroupBuffer was NULL then NULL is returned.
+ *
+ * Example usage:
+ * @code{c}
+ * // StaticEventGroup_t is a publicly accessible structure that has the same
+ * // size and alignment requirements as the real event group structure. It is
+ * // provided as a mechanism for applications to know the size of the event
+ * // group (which is dependent on the architecture and configuration file
+ * // settings) without breaking the strict data hiding policy by exposing the
+ * // real event group internals. This StaticEventGroup_t variable is passed
+ * // into the xSemaphoreCreateEventGroupStatic() function and is used to store
+ * // the event group's data structures
+ * StaticEventGroup_t xEventGroupBuffer;
+ *
+ * // Create the event group without dynamically allocating any memory.
+ * xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
+ * @endcode
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
+#endif
+
+/**
+ * event_groups.h
+ * @code{c}
+ * EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
+ * const EventBits_t uxBitsToWaitFor,
+ * const BaseType_t xClearOnExit,
+ * const BaseType_t xWaitForAllBits,
+ * const TickType_t xTicksToWait );
+ * @endcode
+ *
+ * [Potentially] block to wait for one or more bits to be set within a
+ * previously created event group.
+ *
+ * This function cannot be called from an interrupt.
+ *
+ * @param xEventGroup The event group in which the bits are being tested. The
+ * event group must have previously been created using a call to
+ * xEventGroupCreate().
+ *
+ * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
+ * inside the event group. For example, to wait for bit 0 and/or bit 2 set
+ * uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set
+ * uxBitsToWaitFor to 0x07. Etc.
+ *
+ * @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
+ * uxBitsToWaitFor that are set within the event group will be cleared before
+ * xEventGroupWaitBits() returns if the wait condition was met (if the function
+ * returns for a reason other than a timeout). If xClearOnExit is set to
+ * pdFALSE then the bits set in the event group are not altered when the call to
+ * xEventGroupWaitBits() returns.
+ *
+ * @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
+ * xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
+ * are set or the specified block time expires. If xWaitForAllBits is set to
+ * pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
+ * in uxBitsToWaitFor is set or the specified block time expires. The block
+ * time is specified by the xTicksToWait parameter.
+ *
+ * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
+ * for one/all (depending on the xWaitForAllBits value) of the bits specified by
+ * uxBitsToWaitFor to become set. A value of portMAX_DELAY can be used to block
+ * indefinitely (provided INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).
+ *
+ * @return The value of the event group at the time either the bits being waited
+ * for became set, or the block time expired. Test the return value to know
+ * which bits were set. If xEventGroupWaitBits() returned because its timeout
+ * expired then not all the bits being waited for will be set. If
+ * xEventGroupWaitBits() returned because the bits it was waiting for were set
+ * then the returned value is the event group value before any bits were
+ * automatically cleared in the case that xClearOnExit parameter was set to
+ * pdTRUE.
+ *
+ * Example usage:
+ * @code{c}
+ * #define BIT_0 ( 1 << 0 )
+ * #define BIT_4 ( 1 << 4 )
+ *
+ * void aFunction( EventGroupHandle_t xEventGroup )
+ * {
+ * EventBits_t uxBits;
+ * const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+ *
+ * // Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
+ * // the event group. Clear the bits before exiting.
+ * uxBits = xEventGroupWaitBits(
+ * xEventGroup, // The event group being tested.
+ * BIT_0 | BIT_4, // The bits within the event group to wait for.
+ * pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
+ * pdFALSE, // Don't wait for both bits, either bit will do.
+ * xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
+ *
+ * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+ * {
+ * // xEventGroupWaitBits() returned because both bits were set.
+ * }
+ * else if( ( uxBits & BIT_0 ) != 0 )
+ * {
+ * // xEventGroupWaitBits() returned because just BIT_0 was set.
+ * }
+ * else if( ( uxBits & BIT_4 ) != 0 )
+ * {
+ * // xEventGroupWaitBits() returned because just BIT_4 was set.
+ * }
+ * else
+ * {
+ * // xEventGroupWaitBits() returned because xTicksToWait ticks passed
+ * // without either BIT_0 or BIT_4 becoming set.
+ * }
+ * }
+ * @endcode
+ * \defgroup xEventGroupWaitBits xEventGroupWaitBits
+ * \ingroup EventGroup
+ */
+EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToWaitFor,
+ const BaseType_t xClearOnExit,
+ const BaseType_t xWaitForAllBits,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/**
+ * event_groups.h
+ * @code{c}
+ * EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
+ * @endcode
+ *
+ * Clear bits within an event group. This function cannot be called from an
+ * interrupt.
+ *
+ * @param xEventGroup The event group in which the bits are to be cleared.
+ *
+ * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear
+ * in the event group. For example, to clear bit 3 only, set uxBitsToClear to
+ * 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09.
+ *
+ * @return The value of the event group before the specified bits were cleared.
+ *
+ * Example usage:
+ * @code{c}
+ * #define BIT_0 ( 1 << 0 )
+ * #define BIT_4 ( 1 << 4 )
+ *
+ * void aFunction( EventGroupHandle_t xEventGroup )
+ * {
+ * EventBits_t uxBits;
+ *
+ * // Clear bit 0 and bit 4 in xEventGroup.
+ * uxBits = xEventGroupClearBits(
+ * xEventGroup, // The event group being updated.
+ * BIT_0 | BIT_4 );// The bits being cleared.
+ *
+ * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+ * {
+ * // Both bit 0 and bit 4 were set before xEventGroupClearBits() was
+ * // called. Both will now be clear (not set).
+ * }
+ * else if( ( uxBits & BIT_0 ) != 0 )
+ * {
+ * // Bit 0 was set before xEventGroupClearBits() was called. It will
+ * // now be clear.
+ * }
+ * else if( ( uxBits & BIT_4 ) != 0 )
+ * {
+ * // Bit 4 was set before xEventGroupClearBits() was called. It will
+ * // now be clear.
+ * }
+ * else
+ * {
+ * // Neither bit 0 nor bit 4 were set in the first place.
+ * }
+ * }
+ * @endcode
+ * \defgroup xEventGroupClearBits xEventGroupClearBits
+ * \ingroup EventGroup
+ */
+EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
+
+/**
+ * event_groups.h
+ * @code{c}
+ * BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ * @endcode
+ *
+ * A version of xEventGroupClearBits() that can be called from an interrupt.
+ *
+ * Setting bits in an event group is not a deterministic operation because there
+ * are an unknown number of tasks that may be waiting for the bit or bits being
+ * set. FreeRTOS does not allow nondeterministic operations to be performed
+ * while interrupts are disabled, so protects event groups that are accessed
+ * from tasks by suspending the scheduler rather than disabling interrupts. As
+ * a result event groups cannot be accessed directly from an interrupt service
+ * routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
+ * timer task to have the clear operation performed in the context of the timer
+ * task.
+ *
+ * @note If this function returns pdPASS then the timer task is ready to run
+ * and a portYIELD_FROM_ISR(pdTRUE) should be executed to perform the needed
+ * clear on the event group. This behavior is different from
+ * xEventGroupSetBitsFromISR because the parameter xHigherPriorityTaskWoken is
+ * not present.
+ *
+ * @param xEventGroup The event group in which the bits are to be cleared.
+ *
+ * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear.
+ * For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3
+ * and bit 0 set uxBitsToClear to 0x09.
+ *
+ * @return If the request to execute the function was posted successfully then
+ * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
+ * if the timer service queue was full.
+ *
+ * Example usage:
+ * @code{c}
+ * #define BIT_0 ( 1 << 0 )
+ * #define BIT_4 ( 1 << 4 )
+ *
+ * // An event group which it is assumed has already been created by a call to
+ * // xEventGroupCreate().
+ * EventGroupHandle_t xEventGroup;
+ *
+ * void anInterruptHandler( void )
+ * {
+ * // Clear bit 0 and bit 4 in xEventGroup.
+ * xResult = xEventGroupClearBitsFromISR(
+ * xEventGroup, // The event group being updated.
+ * BIT_0 | BIT_4 ); // The bits being set.
+ *
+ * if( xResult == pdPASS )
+ * {
+ * // The message was posted successfully.
+ * portYIELD_FROM_ISR(pdTRUE);
+ * }
+ * }
+ * @endcode
+ * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
+ * \ingroup EventGroup
+ */
+#if ( configUSE_TRACE_FACILITY == 1 )
+ BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
+#else
+ #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) \
+ xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) ( xEventGroup ), ( uint32_t ) ( uxBitsToClear ), NULL )
+#endif
+
+/**
+ * event_groups.h
+ * @code{c}
+ * EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
+ * @endcode
+ *
+ * Set bits within an event group.
+ * This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
+ * is a version that can be called from an interrupt.
+ *
+ * Setting bits in an event group will automatically unblock tasks that are
+ * blocked waiting for the bits.
+ *
+ * @param xEventGroup The event group in which the bits are to be set.
+ *
+ * @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
+ * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
+ * and bit 0 set uxBitsToSet to 0x09.
+ *
+ * @return The value of the event group at the time the call to
+ * xEventGroupSetBits() returns. There are two reasons why the returned value
+ * might have the bits specified by the uxBitsToSet parameter cleared. First,
+ * if setting a bit results in a task that was waiting for the bit leaving the
+ * blocked state then it is possible the bit will be cleared automatically
+ * (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any
+ * unblocked (or otherwise Ready state) task that has a priority above that of
+ * the task that called xEventGroupSetBits() will execute and may change the
+ * event group value before the call to xEventGroupSetBits() returns.
+ *
+ * Example usage:
+ * @code{c}
+ * #define BIT_0 ( 1 << 0 )
+ * #define BIT_4 ( 1 << 4 )
+ *
+ * void aFunction( EventGroupHandle_t xEventGroup )
+ * {
+ * EventBits_t uxBits;
+ *
+ * // Set bit 0 and bit 4 in xEventGroup.
+ * uxBits = xEventGroupSetBits(
+ * xEventGroup, // The event group being updated.
+ * BIT_0 | BIT_4 );// The bits being set.
+ *
+ * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
+ * {
+ * // Both bit 0 and bit 4 remained set when the function returned.
+ * }
+ * else if( ( uxBits & BIT_0 ) != 0 )
+ * {
+ * // Bit 0 remained set when the function returned, but bit 4 was
+ * // cleared. It might be that bit 4 was cleared automatically as a
+ * // task that was waiting for bit 4 was removed from the Blocked
+ * // state.
+ * }
+ * else if( ( uxBits & BIT_4 ) != 0 )
+ * {
+ * // Bit 4 remained set when the function returned, but bit 0 was
+ * // cleared. It might be that bit 0 was cleared automatically as a
+ * // task that was waiting for bit 0 was removed from the Blocked
+ * // state.
+ * }
+ * else
+ * {
+ * // Neither bit 0 nor bit 4 remained set. It might be that a task
+ * // was waiting for both of the bits to be set, and the bits were
+ * // cleared as the task left the Blocked state.
+ * }
+ * }
+ * @endcode
+ * \defgroup xEventGroupSetBits xEventGroupSetBits
+ * \ingroup EventGroup
+ */
+EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
+
+/**
+ * event_groups.h
+ * @code{c}
+ * BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * A version of xEventGroupSetBits() that can be called from an interrupt.
+ *
+ * Setting bits in an event group is not a deterministic operation because there
+ * are an unknown number of tasks that may be waiting for the bit or bits being
+ * set. FreeRTOS does not allow nondeterministic operations to be performed in
+ * interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR()
+ * sends a message to the timer task to have the set operation performed in the
+ * context of the timer task - where a scheduler lock is used in place of a
+ * critical section.
+ *
+ * @param xEventGroup The event group in which the bits are to be set.
+ *
+ * @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
+ * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
+ * and bit 0 set uxBitsToSet to 0x09.
+ *
+ * @param pxHigherPriorityTaskWoken As mentioned above, calling this function
+ * will result in a message being sent to the timer daemon task. If the
+ * priority of the timer daemon task is higher than the priority of the
+ * currently running task (the task the interrupt interrupted) then
+ * *pxHigherPriorityTaskWoken will be set to pdTRUE by
+ * xEventGroupSetBitsFromISR(), indicating that a context switch should be
+ * requested before the interrupt exits. For that reason
+ * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
+ * example code below.
+ *
+ * @return If the request to execute the function was posted successfully then
+ * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
+ * if the timer service queue was full.
+ *
+ * Example usage:
+ * @code{c}
+ * #define BIT_0 ( 1 << 0 )
+ * #define BIT_4 ( 1 << 4 )
+ *
+ * // An event group which it is assumed has already been created by a call to
+ * // xEventGroupCreate().
+ * EventGroupHandle_t xEventGroup;
+ *
+ * void anInterruptHandler( void )
+ * {
+ * BaseType_t xHigherPriorityTaskWoken, xResult;
+ *
+ * // xHigherPriorityTaskWoken must be initialised to pdFALSE.
+ * xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // Set bit 0 and bit 4 in xEventGroup.
+ * xResult = xEventGroupSetBitsFromISR(
+ * xEventGroup, // The event group being updated.
+ * BIT_0 | BIT_4 // The bits being set.
+ * &xHigherPriorityTaskWoken );
+ *
+ * // Was the message posted successfully?
+ * if( xResult == pdPASS )
+ * {
+ * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
+ * // switch should be requested. The macro used is port specific and
+ * // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
+ * // refer to the documentation page for the port being used.
+ * portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+ * }
+ * }
+ * @endcode
+ * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
+ * \ingroup EventGroup
+ */
+#if ( configUSE_TRACE_FACILITY == 1 )
+ BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToSet,
+ BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+#else
+ #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) \
+ xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) ( xEventGroup ), ( uint32_t ) ( uxBitsToSet ), ( pxHigherPriorityTaskWoken ) )
+#endif
+
+/**
+ * event_groups.h
+ * @code{c}
+ * EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
+ * const EventBits_t uxBitsToSet,
+ * const EventBits_t uxBitsToWaitFor,
+ * TickType_t xTicksToWait );
+ * @endcode
+ *
+ * Atomically set bits within an event group, then wait for a combination of
+ * bits to be set within the same event group. This functionality is typically
+ * used to synchronise multiple tasks, where each task has to wait for the other
+ * tasks to reach a synchronisation point before proceeding.
+ *
+ * This function cannot be used from an interrupt.
+ *
+ * The function will return before its block time expires if the bits specified
+ * by the uxBitsToWait parameter are set, or become set within that time. In
+ * this case all the bits specified by uxBitsToWait will be automatically
+ * cleared before the function returns.
+ *
+ * @param xEventGroup The event group in which the bits are being tested. The
+ * event group must have previously been created using a call to
+ * xEventGroupCreate().
+ *
+ * @param uxBitsToSet The bits to set in the event group before determining
+ * if, and possibly waiting for, all the bits specified by the uxBitsToWait
+ * parameter are set.
+ *
+ * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
+ * inside the event group. For example, to wait for bit 0 and bit 2 set
+ * uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set
+ * uxBitsToWaitFor to 0x07. Etc.
+ *
+ * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
+ * for all of the bits specified by uxBitsToWaitFor to become set.
+ *
+ * @return The value of the event group at the time either the bits being waited
+ * for became set, or the block time expired. Test the return value to know
+ * which bits were set. If xEventGroupSync() returned because its timeout
+ * expired then not all the bits being waited for will be set. If
+ * xEventGroupSync() returned because all the bits it was waiting for were
+ * set then the returned value is the event group value before any bits were
+ * automatically cleared.
+ *
+ * Example usage:
+ * @code{c}
+ * // Bits used by the three tasks.
+ * #define TASK_0_BIT ( 1 << 0 )
+ * #define TASK_1_BIT ( 1 << 1 )
+ * #define TASK_2_BIT ( 1 << 2 )
+ *
+ * #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
+ *
+ * // Use an event group to synchronise three tasks. It is assumed this event
+ * // group has already been created elsewhere.
+ * EventGroupHandle_t xEventBits;
+ *
+ * void vTask0( void *pvParameters )
+ * {
+ * EventBits_t uxReturn;
+ * TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
+ *
+ * for( ;; )
+ * {
+ * // Perform task functionality here.
+ *
+ * // Set bit 0 in the event flag to note this task has reached the
+ * // sync point. The other two tasks will set the other two bits defined
+ * // by ALL_SYNC_BITS. All three tasks have reached the synchronisation
+ * // point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
+ * // for this to happen.
+ * uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
+ *
+ * if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
+ * {
+ * // All three tasks reached the synchronisation point before the call
+ * // to xEventGroupSync() timed out.
+ * }
+ * }
+ * }
+ *
+ * void vTask1( void *pvParameters )
+ * {
+ * for( ;; )
+ * {
+ * // Perform task functionality here.
+ *
+ * // Set bit 1 in the event flag to note this task has reached the
+ * // synchronisation point. The other two tasks will set the other two
+ * // bits defined by ALL_SYNC_BITS. All three tasks have reached the
+ * // synchronisation point when all the ALL_SYNC_BITS are set. Wait
+ * // indefinitely for this to happen.
+ * xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+ *
+ * // xEventGroupSync() was called with an indefinite block time, so
+ * // this task will only reach here if the synchronisation was made by all
+ * // three tasks, so there is no need to test the return value.
+ * }
+ * }
+ *
+ * void vTask2( void *pvParameters )
+ * {
+ * for( ;; )
+ * {
+ * // Perform task functionality here.
+ *
+ * // Set bit 2 in the event flag to note this task has reached the
+ * // synchronisation point. The other two tasks will set the other two
+ * // bits defined by ALL_SYNC_BITS. All three tasks have reached the
+ * // synchronisation point when all the ALL_SYNC_BITS are set. Wait
+ * // indefinitely for this to happen.
+ * xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
+ *
+ * // xEventGroupSync() was called with an indefinite block time, so
+ * // this task will only reach here if the synchronisation was made by all
+ * // three tasks, so there is no need to test the return value.
+ * }
+ * }
+ *
+ * @endcode
+ * \defgroup xEventGroupSync xEventGroupSync
+ * \ingroup EventGroup
+ */
+EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToSet,
+ const EventBits_t uxBitsToWaitFor,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+
+/**
+ * event_groups.h
+ * @code{c}
+ * EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
+ * @endcode
+ *
+ * Returns the current value of the bits in an event group. This function
+ * cannot be used from an interrupt.
+ *
+ * @param xEventGroup The event group being queried.
+ *
+ * @return The event group bits at the time xEventGroupGetBits() was called.
+ *
+ * \defgroup xEventGroupGetBits xEventGroupGetBits
+ * \ingroup EventGroup
+ */
+#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( ( xEventGroup ), 0 )
+
+/**
+ * event_groups.h
+ * @code{c}
+ * EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
+ * @endcode
+ *
+ * A version of xEventGroupGetBits() that can be called from an ISR.
+ *
+ * @param xEventGroup The event group being queried.
+ *
+ * @return The event group bits at the time xEventGroupGetBitsFromISR() was called.
+ *
+ * \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
+ * \ingroup EventGroup
+ */
+EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
+
+/**
+ * event_groups.h
+ * @code{c}
+ * void xEventGroupDelete( EventGroupHandle_t xEventGroup );
+ * @endcode
+ *
+ * Delete an event group that was previously created by a call to
+ * xEventGroupCreate(). Tasks that are blocked on the event group will be
+ * unblocked and obtain 0 as the event group's value.
+ *
+ * @param xEventGroup The event group being deleted.
+ */
+void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
+
+/* For internal use only. */
+void vEventGroupSetBitsCallback( void * pvEventGroup,
+ const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
+void vEventGroupClearBitsCallback( void * pvEventGroup,
+ const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
+
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) PRIVILEGED_FUNCTION;
+ void vEventGroupSetNumber( void * xEventGroup,
+ UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION;
+#endif
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ }
+#endif
+/* *INDENT-ON* */
+
+#endif /* EVENT_GROUPS_H */
diff --git a/source/test/freertos/inc/list.h b/source/test/freertos/inc/list.h
new file mode 100644
index 0000000..35e4789
--- /dev/null
+++ b/source/test/freertos/inc/list.h
@@ -0,0 +1,503 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/*
+ * This is the list implementation used by the scheduler. While it is tailored
+ * heavily for the schedulers needs, it is also available for use by
+ * application code.
+ *
+ * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a
+ * numeric value (xItemValue). Most of the time the lists are sorted in
+ * ascending item value order.
+ *
+ * Lists are created already containing one list item. The value of this
+ * item is the maximum possible that can be stored, it is therefore always at
+ * the end of the list and acts as a marker. The list member pxHead always
+ * points to this marker - even though it is at the tail of the list. This
+ * is because the tail contains a wrap back pointer to the true head of
+ * the list.
+ *
+ * In addition to it's value, each list item contains a pointer to the next
+ * item in the list (pxNext), a pointer to the list it is in (pxContainer)
+ * and a pointer to back to the object that contains it. These later two
+ * pointers are included for efficiency of list manipulation. There is
+ * effectively a two way link between the object containing the list item and
+ * the list item itself.
+ *
+ *
+ * \page ListIntroduction List Implementation
+ * \ingroup FreeRTOSIntro
+ */
+
+
+#ifndef LIST_H
+#define LIST_H
+
+#ifndef INC_FREERTOS_H
+ #error "FreeRTOS.h must be included before list.h"
+#endif
+
+/*
+ * The list structure members are modified from within interrupts, and therefore
+ * by rights should be declared volatile. However, they are only modified in a
+ * functionally atomic way (within critical sections of with the scheduler
+ * suspended) and are either passed by reference into a function or indexed via
+ * a volatile variable. Therefore, in all use cases tested so far, the volatile
+ * qualifier can be omitted in order to provide a moderate performance
+ * improvement without adversely affecting functional behaviour. The assembly
+ * instructions generated by the IAR, ARM and GCC compilers when the respective
+ * compiler's options were set for maximum optimisation has been inspected and
+ * deemed to be as intended. That said, as compiler technology advances, and
+ * especially if aggressive cross module optimisation is used (a use case that
+ * has not been exercised to any great extend) then it is feasible that the
+ * volatile qualifier will be needed for correct optimisation. It is expected
+ * that a compiler removing essential code because, without the volatile
+ * qualifier on the list structure members and with aggressive cross module
+ * optimisation, the compiler deemed the code unnecessary will result in
+ * complete and obvious failure of the scheduler. If this is ever experienced
+ * then the volatile qualifier can be inserted in the relevant places within the
+ * list structures by simply defining configLIST_VOLATILE to volatile in
+ * FreeRTOSConfig.h (as per the example at the bottom of this comment block).
+ * If configLIST_VOLATILE is not defined then the preprocessor directives below
+ * will simply #define configLIST_VOLATILE away completely.
+ *
+ * To use volatile list structure members then add the following line to
+ * FreeRTOSConfig.h (without the quotes):
+ * "#define configLIST_VOLATILE volatile"
+ */
+#ifndef configLIST_VOLATILE
+ #define configLIST_VOLATILE
+#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+/* Macros that can be used to place known values within the list structures,
+ * then check that the known values do not get corrupted during the execution of
+ * the application. These may catch the list data structures being overwritten in
+ * memory. They will not catch data errors caused by incorrect configuration or
+ * use of FreeRTOS.*/
+#if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
+ /* Define the macros to do nothing. */
+ #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
+ #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
+ #define listFIRST_LIST_INTEGRITY_CHECK_VALUE
+ #define listSECOND_LIST_INTEGRITY_CHECK_VALUE
+ #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
+ #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
+ #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
+ #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
+ #define listTEST_LIST_ITEM_INTEGRITY( pxItem )
+ #define listTEST_LIST_INTEGRITY( pxList )
+#else /* if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) */
+ /* Define macros that add new members into the list structures. */
+ #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1;
+ #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2;
+ #define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
+ #define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;
+
+/* Define macros that set the new structure members to known values. */
+ #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
+ #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
+ #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
+ #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
+
+/* Define macros that will assert if one of the structure members does not
+ * contain its expected value. */
+ #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
+ #define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
+#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
+
+
+/*
+ * Definition of the only type of object that a list can contain.
+ */
+struct xLIST;
+struct xLIST_ITEM
+{
+ listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+ configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in ascending order. */
+ struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */
+ struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
+ void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
+ struct xLIST * configLIST_VOLATILE pxContainer; /*< Pointer to the list in which this list item is placed (if any). */
+ listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+};
+typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */
+
+#if ( configUSE_MINI_LIST_ITEM == 1 )
+ struct xMINI_LIST_ITEM
+ {
+ listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+ configLIST_VOLATILE TickType_t xItemValue;
+ struct xLIST_ITEM * configLIST_VOLATILE pxNext;
+ struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
+ };
+ typedef struct xMINI_LIST_ITEM MiniListItem_t;
+#else
+ typedef struct xLIST_ITEM MiniListItem_t;
+#endif
+
+/*
+ * Definition of the type of queue used by the scheduler.
+ */
+typedef struct xLIST
+{
+ listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+ volatile UBaseType_t uxNumberOfItems;
+ ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
+ MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
+ listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+} List_t;
+
+/*
+ * Access macro to set the owner of a list item. The owner of a list item
+ * is the object (usually a TCB) that contains the list item.
+ *
+ * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
+ * \ingroup LinkedList
+ */
+#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
+
+/*
+ * Access macro to get the owner of a list item. The owner of a list item
+ * is the object (usually a TCB) that contains the list item.
+ *
+ * \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
+ * \ingroup LinkedList
+ */
+#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
+
+/*
+ * Access macro to set the value of the list item. In most cases the value is
+ * used to sort the list in ascending order.
+ *
+ * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
+ * \ingroup LinkedList
+ */
+#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
+
+/*
+ * Access macro to retrieve the value of the list item. The value can
+ * represent anything - for example the priority of a task, or the time at
+ * which a task should be unblocked.
+ *
+ * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
+ * \ingroup LinkedList
+ */
+#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
+
+/*
+ * Access macro to retrieve the value of the list item at the head of a given
+ * list.
+ *
+ * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
+ * \ingroup LinkedList
+ */
+#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
+
+/*
+ * Return the list item at the head of the list.
+ *
+ * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
+ * \ingroup LinkedList
+ */
+#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
+
+/*
+ * Return the next list item.
+ *
+ * \page listGET_NEXT listGET_NEXT
+ * \ingroup LinkedList
+ */
+#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
+
+/*
+ * Return the list item that marks the end of the list
+ *
+ * \page listGET_END_MARKER listGET_END_MARKER
+ * \ingroup LinkedList
+ */
+#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
+
+/*
+ * Access macro to determine if a list contains any items. The macro will
+ * only have the value true if the list is empty.
+ *
+ * \page listLIST_IS_EMPTY listLIST_IS_EMPTY
+ * \ingroup LinkedList
+ */
+#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
+
+/*
+ * Access macro to return the number of items in the list.
+ */
+#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
+
+/*
+ * Access function to obtain the owner of the next entry in a list.
+ *
+ * The list member pxIndex is used to walk through a list. Calling
+ * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
+ * and returns that entry's pxOwner parameter. Using multiple calls to this
+ * function it is therefore possible to move through every item contained in
+ * a list.
+ *
+ * The pxOwner parameter of a list item is a pointer to the object that owns
+ * the list item. In the scheduler this is normally a task control block.
+ * The pxOwner parameter effectively creates a two way link between the list
+ * item and its owner.
+ *
+ * @param pxTCB pxTCB is set to the address of the owner of the next list item.
+ * @param pxList The list from which the next item owner is to be returned.
+ *
+ * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
+ * \ingroup LinkedList
+ */
+#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
+ { \
+ List_t * const pxConstList = ( pxList ); \
+ /* Increment the index to the next item and return the item, ensuring */ \
+ /* we don't return the marker used at the end of the list. */ \
+ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
+ if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
+ { \
+ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
+ } \
+ ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
+ }
+
+/*
+ * Version of uxListRemove() that does not return a value. Provided as a slight
+ * optimisation for xTaskIncrementTick() by being inline.
+ *
+ * Remove an item from a list. The list item has a pointer to the list that
+ * it is in, so only the list item need be passed into the function.
+ *
+ * @param uxListRemove The item to be removed. The item will remove itself from
+ * the list pointed to by it's pxContainer parameter.
+ *
+ * @return The number of items that remain in the list after the list item has
+ * been removed.
+ *
+ * \page listREMOVE_ITEM listREMOVE_ITEM
+ * \ingroup LinkedList
+ */
+#define listREMOVE_ITEM( pxItemToRemove ) \
+ { \
+ /* The list item knows which list it is in. Obtain the list from the list \
+ * item. */ \
+ List_t * const pxList = ( pxItemToRemove )->pxContainer; \
+ \
+ ( pxItemToRemove )->pxNext->pxPrevious = ( pxItemToRemove )->pxPrevious; \
+ ( pxItemToRemove )->pxPrevious->pxNext = ( pxItemToRemove )->pxNext; \
+ /* Make sure the index is left pointing to a valid item. */ \
+ if( pxList->pxIndex == ( pxItemToRemove ) ) \
+ { \
+ pxList->pxIndex = ( pxItemToRemove )->pxPrevious; \
+ } \
+ \
+ ( pxItemToRemove )->pxContainer = NULL; \
+ ( pxList->uxNumberOfItems )--; \
+ }
+
+/*
+ * Inline version of vListInsertEnd() to provide slight optimisation for
+ * xTaskIncrementTick().
+ *
+ * Insert a list item into a list. The item will be inserted in a position
+ * such that it will be the last item within the list returned by multiple
+ * calls to listGET_OWNER_OF_NEXT_ENTRY.
+ *
+ * The list member pxIndex is used to walk through a list. Calling
+ * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
+ * Placing an item in a list using vListInsertEnd effectively places the item
+ * in the list position pointed to by pxIndex. This means that every other
+ * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
+ * the pxIndex parameter again points to the item being inserted.
+ *
+ * @param pxList The list into which the item is to be inserted.
+ *
+ * @param pxNewListItem The list item to be inserted into the list.
+ *
+ * \page listINSERT_END listINSERT_END
+ * \ingroup LinkedList
+ */
+#define listINSERT_END( pxList, pxNewListItem ) \
+ { \
+ ListItem_t * const pxIndex = ( pxList )->pxIndex; \
+ \
+ /* Only effective when configASSERT() is also defined, these tests may catch \
+ * the list data structures being overwritten in memory. They will not catch \
+ * data errors caused by incorrect configuration or use of FreeRTOS. */ \
+ listTEST_LIST_INTEGRITY( ( pxList ) ); \
+ listTEST_LIST_ITEM_INTEGRITY( ( pxNewListItem ) ); \
+ \
+ /* Insert a new list item into ( pxList ), but rather than sort the list, \
+ * makes the new list item the last item to be removed by a call to \
+ * listGET_OWNER_OF_NEXT_ENTRY(). */ \
+ ( pxNewListItem )->pxNext = pxIndex; \
+ ( pxNewListItem )->pxPrevious = pxIndex->pxPrevious; \
+ \
+ pxIndex->pxPrevious->pxNext = ( pxNewListItem ); \
+ pxIndex->pxPrevious = ( pxNewListItem ); \
+ \
+ /* Remember which list the item is in. */ \
+ ( pxNewListItem )->pxContainer = ( pxList ); \
+ \
+ ( ( pxList )->uxNumberOfItems )++; \
+ }
+
+/*
+ * Access function to obtain the owner of the first entry in a list. Lists
+ * are normally sorted in ascending item value order.
+ *
+ * This function returns the pxOwner member of the first item in the list.
+ * The pxOwner parameter of a list item is a pointer to the object that owns
+ * the list item. In the scheduler this is normally a task control block.
+ * The pxOwner parameter effectively creates a two way link between the list
+ * item and its owner.
+ *
+ * @param pxList The list from which the owner of the head item is to be
+ * returned.
+ *
+ * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
+ * \ingroup LinkedList
+ */
+#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner )
+
+/*
+ * Check to see if a list item is within a list. The list item maintains a
+ * "container" pointer that points to the list it is in. All this macro does
+ * is check to see if the container and the list match.
+ *
+ * @param pxList The list we want to know if the list item is within.
+ * @param pxListItem The list item we want to know if is in the list.
+ * @return pdTRUE if the list item is in the list, otherwise pdFALSE.
+ */
+#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )
+
+/*
+ * Return the list a list item is contained within (referenced from).
+ *
+ * @param pxListItem The list item being queried.
+ * @return A pointer to the List_t object that references the pxListItem
+ */
+#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer )
+
+/*
+ * This provides a crude means of knowing if a list has been initialised, as
+ * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
+ * function.
+ */
+#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
+
+/*
+ * Must be called before a list is used! This initialises all the members
+ * of the list structure and inserts the xListEnd item into the list as a
+ * marker to the back of the list.
+ *
+ * @param pxList Pointer to the list being initialised.
+ *
+ * \page vListInitialise vListInitialise
+ * \ingroup LinkedList
+ */
+void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
+
+/*
+ * Must be called before a list item is used. This sets the list container to
+ * null so the item does not think that it is already contained in a list.
+ *
+ * @param pxItem Pointer to the list item being initialised.
+ *
+ * \page vListInitialiseItem vListInitialiseItem
+ * \ingroup LinkedList
+ */
+void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
+
+/*
+ * Insert a list item into a list. The item will be inserted into the list in
+ * a position determined by its item value (ascending item value order).
+ *
+ * @param pxList The list into which the item is to be inserted.
+ *
+ * @param pxNewListItem The item that is to be placed in the list.
+ *
+ * \page vListInsert vListInsert
+ * \ingroup LinkedList
+ */
+void vListInsert( List_t * const pxList,
+ ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
+
+/*
+ * Insert a list item into a list. The item will be inserted in a position
+ * such that it will be the last item within the list returned by multiple
+ * calls to listGET_OWNER_OF_NEXT_ENTRY.
+ *
+ * The list member pxIndex is used to walk through a list. Calling
+ * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
+ * Placing an item in a list using vListInsertEnd effectively places the item
+ * in the list position pointed to by pxIndex. This means that every other
+ * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
+ * the pxIndex parameter again points to the item being inserted.
+ *
+ * @param pxList The list into which the item is to be inserted.
+ *
+ * @param pxNewListItem The list item to be inserted into the list.
+ *
+ * \page vListInsertEnd vListInsertEnd
+ * \ingroup LinkedList
+ */
+void vListInsertEnd( List_t * const pxList,
+ ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
+
+/*
+ * Remove an item from a list. The list item has a pointer to the list that
+ * it is in, so only the list item need be passed into the function.
+ *
+ * @param uxListRemove The item to be removed. The item will remove itself from
+ * the list pointed to by it's pxContainer parameter.
+ *
+ * @return The number of items that remain in the list after the list item has
+ * been removed.
+ *
+ * \page uxListRemove uxListRemove
+ * \ingroup LinkedList
+ */
+UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ }
+#endif
+/* *INDENT-ON* */
+
+#endif /* ifndef LIST_H */
diff --git a/source/test/freertos/inc/message_buffer.h b/source/test/freertos/inc/message_buffer.h
new file mode 100644
index 0000000..bb8a7f7
--- /dev/null
+++ b/source/test/freertos/inc/message_buffer.h
@@ -0,0 +1,856 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+
+/*
+ * Message buffers build functionality on top of FreeRTOS stream buffers.
+ * Whereas stream buffers are used to send a continuous stream of data from one
+ * task or interrupt to another, message buffers are used to send variable
+ * length discrete messages from one task or interrupt to another. Their
+ * implementation is light weight, making them particularly suited for interrupt
+ * to task and core to core communication scenarios.
+ *
+ * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
+ * implementation (so also the message buffer implementation, as message buffers
+ * are built on top of stream buffers) assumes there is only one task or
+ * interrupt that will write to the buffer (the writer), and only one task or
+ * interrupt that will read from the buffer (the reader). It is safe for the
+ * writer and reader to be different tasks or interrupts, but, unlike other
+ * FreeRTOS objects, it is not safe to have multiple different writers or
+ * multiple different readers. If there are to be multiple different writers
+ * then the application writer must place each call to a writing API function
+ * (such as xMessageBufferSend()) inside a critical section and set the send
+ * block time to 0. Likewise, if there are to be multiple different readers
+ * then the application writer must place each call to a reading API function
+ * (such as xMessageBufferRead()) inside a critical section and set the receive
+ * timeout to 0.
+ *
+ * Message buffers hold variable length messages. To enable that, when a
+ * message is written to the message buffer an additional sizeof( size_t ) bytes
+ * are also written to store the message's length (that happens internally, with
+ * the API function). sizeof( size_t ) is typically 4 bytes on a 32-bit
+ * architecture, so writing a 10 byte message to a message buffer on a 32-bit
+ * architecture will actually reduce the available space in the message buffer
+ * by 14 bytes (10 byte are used by the message, and 4 bytes to hold the length
+ * of the message).
+ */
+
+#ifndef FREERTOS_MESSAGE_BUFFER_H
+#define FREERTOS_MESSAGE_BUFFER_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h must appear in source files before include message_buffer.h"
+#endif
+
+/* Message buffers are built onto of stream buffers. */
+#include "stream_buffer.h"
+
+/* *INDENT-OFF* */
+#if defined( __cplusplus )
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+/**
+ * Type by which message buffers are referenced. For example, a call to
+ * xMessageBufferCreate() returns an MessageBufferHandle_t variable that can
+ * then be used as a parameter to xMessageBufferSend(), xMessageBufferReceive(),
+ * etc. Message buffer is essentially built as a stream buffer hence its handle
+ * is also set to same type as a stream buffer handle.
+ */
+typedef StreamBufferHandle_t MessageBufferHandle_t;
+
+/*-----------------------------------------------------------*/
+
+/**
+ * message_buffer.h
+ *
+ * @code{c}
+ * MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
+ * @endcode
+ *
+ * Creates a new message buffer using dynamically allocated memory. See
+ * xMessageBufferCreateStatic() for a version that uses statically allocated
+ * memory (memory that is allocated at compile time).
+ *
+ * configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
+ * FreeRTOSConfig.h for xMessageBufferCreate() to be available.
+ *
+ * @param xBufferSizeBytes The total number of bytes (not messages) the message
+ * buffer will be able to hold at any one time. When a message is written to
+ * the message buffer an additional sizeof( size_t ) bytes are also written to
+ * store the message's length. sizeof( size_t ) is typically 4 bytes on a
+ * 32-bit architecture, so on most 32-bit architectures a 10 byte message will
+ * take up 14 bytes of message buffer space.
+ *
+ * @param pxSendCompletedCallback Callback invoked when a send operation to the
+ * message buffer is complete. If the parameter is NULL or xMessageBufferCreate()
+ * is called without the parameter, then it will use the default implementation
+ * provided by sbSEND_COMPLETED macro. To enable the callback,
+ * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
+ *
+ * @param pxReceiveCompletedCallback Callback invoked when a receive operation from
+ * the message buffer is complete. If the parameter is NULL or xMessageBufferCreate()
+ * is called without the parameter, it will use the default implementation provided
+ * by sbRECEIVE_COMPLETED macro. To enable the callback,
+ * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
+ *
+ * @return If NULL is returned, then the message buffer cannot be created
+ * because there is insufficient heap memory available for FreeRTOS to allocate
+ * the message buffer data structures and storage area. A non-NULL value being
+ * returned indicates that the message buffer has been created successfully -
+ * the returned value should be stored as the handle to the created message
+ * buffer.
+ *
+ * Example use:
+ * @code{c}
+ *
+ * void vAFunction( void )
+ * {
+ * MessageBufferHandle_t xMessageBuffer;
+ * const size_t xMessageBufferSizeBytes = 100;
+ *
+ * // Create a message buffer that can hold 100 bytes. The memory used to hold
+ * // both the message buffer structure and the messages themselves is allocated
+ * // dynamically. Each message added to the buffer consumes an additional 4
+ * // bytes which are used to hold the length of the message.
+ * xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes );
+ *
+ * if( xMessageBuffer == NULL )
+ * {
+ * // There was not enough heap memory space available to create the
+ * // message buffer.
+ * }
+ * else
+ * {
+ * // The message buffer was created successfully and can now be used.
+ * }
+ *
+ * @endcode
+ * \defgroup xMessageBufferCreate xMessageBufferCreate
+ * \ingroup MessageBufferManagement
+ */
+#define xMessageBufferCreate( xBufferSizeBytes ) \
+ xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( size_t ) 0, pdTRUE, NULL, NULL )
+
+#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ #define xMessageBufferCreateWithCallback( xBufferSizeBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
+ xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( size_t ) 0, pdTRUE, ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
+#endif
+
+/**
+ * message_buffer.h
+ *
+ * @code{c}
+ * MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes,
+ * uint8_t *pucMessageBufferStorageArea,
+ * StaticMessageBuffer_t *pxStaticMessageBuffer );
+ * @endcode
+ * Creates a new message buffer using statically allocated memory. See
+ * xMessageBufferCreate() for a version that uses dynamically allocated memory.
+ *
+ * @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
+ * pucMessageBufferStorageArea parameter. When a message is written to the
+ * message buffer an additional sizeof( size_t ) bytes are also written to store
+ * the message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
+ * architecture, so on most 32-bit architecture a 10 byte message will take up
+ * 14 bytes of message buffer space. The maximum number of bytes that can be
+ * stored in the message buffer is actually (xBufferSizeBytes - 1).
+ *
+ * @param pucMessageBufferStorageArea Must point to a uint8_t array that is at
+ * least xBufferSizeBytes big. This is the array to which messages are
+ * copied when they are written to the message buffer.
+ *
+ * @param pxStaticMessageBuffer Must point to a variable of type
+ * StaticMessageBuffer_t, which will be used to hold the message buffer's data
+ * structure.
+ *
+ * @param pxSendCompletedCallback Callback invoked when a new message is sent to the message buffer.
+ * If the parameter is NULL or xMessageBufferCreate() is called without the parameter, then it will use the default
+ * implementation provided by sbSEND_COMPLETED macro. To enable the callback,
+ * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
+ *
+ * @param pxReceiveCompletedCallback Callback invoked when a message is read from a
+ * message buffer. If the parameter is NULL or xMessageBufferCreate() is called without the parameter, it will
+ * use the default implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
+ * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
+ *
+ * @return If the message buffer is created successfully then a handle to the
+ * created message buffer is returned. If either pucMessageBufferStorageArea or
+ * pxStaticmessageBuffer are NULL then NULL is returned.
+ *
+ * Example use:
+ * @code{c}
+ *
+ * // Used to dimension the array used to hold the messages. The available space
+ * // will actually be one less than this, so 999.
+ #define STORAGE_SIZE_BYTES 1000
+ *
+ * // Defines the memory that will actually hold the messages within the message
+ * // buffer.
+ * static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
+ *
+ * // The variable used to hold the message buffer structure.
+ * StaticMessageBuffer_t xMessageBufferStruct;
+ *
+ * void MyFunction( void )
+ * {
+ * MessageBufferHandle_t xMessageBuffer;
+ *
+ * xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucStorageBuffer ),
+ * ucStorageBuffer,
+ * &xMessageBufferStruct );
+ *
+ * // As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer
+ * // parameters were NULL, xMessageBuffer will not be NULL, and can be used to
+ * // reference the created message buffer in other message buffer API calls.
+ *
+ * // Other code that uses the message buffer can go here.
+ * }
+ *
+ * @endcode
+ * \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic
+ * \ingroup MessageBufferManagement
+ */
+#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \
+ xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), 0, pdTRUE, ( pucMessageBufferStorageArea ), ( pxStaticMessageBuffer ), NULL, NULL )
+
+#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ #define xMessageBufferCreateStaticWithCallback( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
+ xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), 0, pdTRUE, ( pucMessageBufferStorageArea ), ( pxStaticMessageBuffer ), ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
+#endif
+
+/**
+ * message_buffer.h
+ *
+ * @code{c}
+ * size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
+ * const void *pvTxData,
+ * size_t xDataLengthBytes,
+ * TickType_t xTicksToWait );
+ * @endcode
+ *
+ * Sends a discrete message to the message buffer. The message can be any
+ * length that fits within the buffer's free space, and is copied into the
+ * buffer.
+ *
+ * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
+ * implementation (so also the message buffer implementation, as message buffers
+ * are built on top of stream buffers) assumes there is only one task or
+ * interrupt that will write to the buffer (the writer), and only one task or
+ * interrupt that will read from the buffer (the reader). It is safe for the
+ * writer and reader to be different tasks or interrupts, but, unlike other
+ * FreeRTOS objects, it is not safe to have multiple different writers or
+ * multiple different readers. If there are to be multiple different writers
+ * then the application writer must place each call to a writing API function
+ * (such as xMessageBufferSend()) inside a critical section and set the send
+ * block time to 0. Likewise, if there are to be multiple different readers
+ * then the application writer must place each call to a reading API function
+ * (such as xMessageBufferRead()) inside a critical section and set the receive
+ * block time to 0.
+ *
+ * Use xMessageBufferSend() to write to a message buffer from a task. Use
+ * xMessageBufferSendFromISR() to write to a message buffer from an interrupt
+ * service routine (ISR).
+ *
+ * @param xMessageBuffer The handle of the message buffer to which a message is
+ * being sent.
+ *
+ * @param pvTxData A pointer to the message that is to be copied into the
+ * message buffer.
+ *
+ * @param xDataLengthBytes The length of the message. That is, the number of
+ * bytes to copy from pvTxData into the message buffer. When a message is
+ * written to the message buffer an additional sizeof( size_t ) bytes are also
+ * written to store the message's length. sizeof( size_t ) is typically 4 bytes
+ * on a 32-bit architecture, so on most 32-bit architecture setting
+ * xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
+ * bytes (20 bytes of message data and 4 bytes to hold the message length).
+ *
+ * @param xTicksToWait The maximum amount of time the calling task should remain
+ * in the Blocked state to wait for enough space to become available in the
+ * message buffer, should the message buffer have insufficient space when
+ * xMessageBufferSend() is called. The calling task will never block if
+ * xTicksToWait is zero. The block time is specified in tick periods, so the
+ * absolute time it represents is dependent on the tick frequency. The macro
+ * pdMS_TO_TICKS() can be used to convert a time specified in milliseconds into
+ * a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will cause
+ * the task to wait indefinitely (without timing out), provided
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
+ * CPU time when they are in the Blocked state.
+ *
+ * @return The number of bytes written to the message buffer. If the call to
+ * xMessageBufferSend() times out before there was enough space to write the
+ * message into the message buffer then zero is returned. If the call did not
+ * time out then xDataLengthBytes is returned.
+ *
+ * Example use:
+ * @code{c}
+ * void vAFunction( MessageBufferHandle_t xMessageBuffer )
+ * {
+ * size_t xBytesSent;
+ * uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
+ * char *pcStringToSend = "String to send";
+ * const TickType_t x100ms = pdMS_TO_TICKS( 100 );
+ *
+ * // Send an array to the message buffer, blocking for a maximum of 100ms to
+ * // wait for enough space to be available in the message buffer.
+ * xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
+ *
+ * if( xBytesSent != sizeof( ucArrayToSend ) )
+ * {
+ * // The call to xMessageBufferSend() times out before there was enough
+ * // space in the buffer for the data to be written.
+ * }
+ *
+ * // Send the string to the message buffer. Return immediately if there is
+ * // not enough space in the buffer.
+ * xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
+ *
+ * if( xBytesSent != strlen( pcStringToSend ) )
+ * {
+ * // The string could not be added to the message buffer because there was
+ * // not enough free space in the buffer.
+ * }
+ * }
+ * @endcode
+ * \defgroup xMessageBufferSend xMessageBufferSend
+ * \ingroup MessageBufferManagement
+ */
+#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) \
+ xStreamBufferSend( ( xMessageBuffer ), ( pvTxData ), ( xDataLengthBytes ), ( xTicksToWait ) )
+
+/**
+ * message_buffer.h
+ *
+ * @code{c}
+ * size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer,
+ * const void *pvTxData,
+ * size_t xDataLengthBytes,
+ * BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * Interrupt safe version of the API function that sends a discrete message to
+ * the message buffer. The message can be any length that fits within the
+ * buffer's free space, and is copied into the buffer.
+ *
+ * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
+ * implementation (so also the message buffer implementation, as message buffers
+ * are built on top of stream buffers) assumes there is only one task or
+ * interrupt that will write to the buffer (the writer), and only one task or
+ * interrupt that will read from the buffer (the reader). It is safe for the
+ * writer and reader to be different tasks or interrupts, but, unlike other
+ * FreeRTOS objects, it is not safe to have multiple different writers or
+ * multiple different readers. If there are to be multiple different writers
+ * then the application writer must place each call to a writing API function
+ * (such as xMessageBufferSend()) inside a critical section and set the send
+ * block time to 0. Likewise, if there are to be multiple different readers
+ * then the application writer must place each call to a reading API function
+ * (such as xMessageBufferRead()) inside a critical section and set the receive
+ * block time to 0.
+ *
+ * Use xMessageBufferSend() to write to a message buffer from a task. Use
+ * xMessageBufferSendFromISR() to write to a message buffer from an interrupt
+ * service routine (ISR).
+ *
+ * @param xMessageBuffer The handle of the message buffer to which a message is
+ * being sent.
+ *
+ * @param pvTxData A pointer to the message that is to be copied into the
+ * message buffer.
+ *
+ * @param xDataLengthBytes The length of the message. That is, the number of
+ * bytes to copy from pvTxData into the message buffer. When a message is
+ * written to the message buffer an additional sizeof( size_t ) bytes are also
+ * written to store the message's length. sizeof( size_t ) is typically 4 bytes
+ * on a 32-bit architecture, so on most 32-bit architecture setting
+ * xDataLengthBytes to 20 will reduce the free space in the message buffer by 24
+ * bytes (20 bytes of message data and 4 bytes to hold the message length).
+ *
+ * @param pxHigherPriorityTaskWoken It is possible that a message buffer will
+ * have a task blocked on it waiting for data. Calling
+ * xMessageBufferSendFromISR() can make data available, and so cause a task that
+ * was waiting for data to leave the Blocked state. If calling
+ * xMessageBufferSendFromISR() causes a task to leave the Blocked state, and the
+ * unblocked task has a priority higher than the currently executing task (the
+ * task that was interrupted), then, internally, xMessageBufferSendFromISR()
+ * will set *pxHigherPriorityTaskWoken to pdTRUE. If
+ * xMessageBufferSendFromISR() sets this value to pdTRUE, then normally a
+ * context switch should be performed before the interrupt is exited. This will
+ * ensure that the interrupt returns directly to the highest priority Ready
+ * state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it
+ * is passed into the function. See the code example below for an example.
+ *
+ * @return The number of bytes actually written to the message buffer. If the
+ * message buffer didn't have enough free space for the message to be stored
+ * then 0 is returned, otherwise xDataLengthBytes is returned.
+ *
+ * Example use:
+ * @code{c}
+ * // A message buffer that has already been created.
+ * MessageBufferHandle_t xMessageBuffer;
+ *
+ * void vAnInterruptServiceRoutine( void )
+ * {
+ * size_t xBytesSent;
+ * char *pcStringToSend = "String to send";
+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
+ *
+ * // Attempt to send the string to the message buffer.
+ * xBytesSent = xMessageBufferSendFromISR( xMessageBuffer,
+ * ( void * ) pcStringToSend,
+ * strlen( pcStringToSend ),
+ * &xHigherPriorityTaskWoken );
+ *
+ * if( xBytesSent != strlen( pcStringToSend ) )
+ * {
+ * // The string could not be added to the message buffer because there was
+ * // not enough free space in the buffer.
+ * }
+ *
+ * // If xHigherPriorityTaskWoken was set to pdTRUE inside
+ * // xMessageBufferSendFromISR() then a task that has a priority above the
+ * // priority of the currently executing task was unblocked and a context
+ * // switch should be performed to ensure the ISR returns to the unblocked
+ * // task. In most FreeRTOS ports this is done by simply passing
+ * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
+ * // variables value, and perform the context switch if necessary. Check the
+ * // documentation for the port in use for port specific instructions.
+ * portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+ * }
+ * @endcode
+ * \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR
+ * \ingroup MessageBufferManagement
+ */
+#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) \
+ xStreamBufferSendFromISR( ( xMessageBuffer ), ( pvTxData ), ( xDataLengthBytes ), ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * message_buffer.h
+ *
+ * @code{c}
+ * size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
+ * void *pvRxData,
+ * size_t xBufferLengthBytes,
+ * TickType_t xTicksToWait );
+ * @endcode
+ *
+ * Receives a discrete message from a message buffer. Messages can be of
+ * variable length and are copied out of the buffer.
+ *
+ * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
+ * implementation (so also the message buffer implementation, as message buffers
+ * are built on top of stream buffers) assumes there is only one task or
+ * interrupt that will write to the buffer (the writer), and only one task or
+ * interrupt that will read from the buffer (the reader). It is safe for the
+ * writer and reader to be different tasks or interrupts, but, unlike other
+ * FreeRTOS objects, it is not safe to have multiple different writers or
+ * multiple different readers. If there are to be multiple different writers
+ * then the application writer must place each call to a writing API function
+ * (such as xMessageBufferSend()) inside a critical section and set the send
+ * block time to 0. Likewise, if there are to be multiple different readers
+ * then the application writer must place each call to a reading API function
+ * (such as xMessageBufferRead()) inside a critical section and set the receive
+ * block time to 0.
+ *
+ * Use xMessageBufferReceive() to read from a message buffer from a task. Use
+ * xMessageBufferReceiveFromISR() to read from a message buffer from an
+ * interrupt service routine (ISR).
+ *
+ * @param xMessageBuffer The handle of the message buffer from which a message
+ * is being received.
+ *
+ * @param pvRxData A pointer to the buffer into which the received message is
+ * to be copied.
+ *
+ * @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
+ * parameter. This sets the maximum length of the message that can be received.
+ * If xBufferLengthBytes is too small to hold the next message then the message
+ * will be left in the message buffer and 0 will be returned.
+ *
+ * @param xTicksToWait The maximum amount of time the task should remain in the
+ * Blocked state to wait for a message, should the message buffer be empty.
+ * xMessageBufferReceive() will return immediately if xTicksToWait is zero and
+ * the message buffer is empty. The block time is specified in tick periods, so
+ * the absolute time it represents is dependent on the tick frequency. The
+ * macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
+ * into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will
+ * cause the task to wait indefinitely (without timing out), provided
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
+ * CPU time when they are in the Blocked state.
+ *
+ * @return The length, in bytes, of the message read from the message buffer, if
+ * any. If xMessageBufferReceive() times out before a message became available
+ * then zero is returned. If the length of the message is greater than
+ * xBufferLengthBytes then the message will be left in the message buffer and
+ * zero is returned.
+ *
+ * Example use:
+ * @code{c}
+ * void vAFunction( MessageBuffer_t xMessageBuffer )
+ * {
+ * uint8_t ucRxData[ 20 ];
+ * size_t xReceivedBytes;
+ * const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
+ *
+ * // Receive the next message from the message buffer. Wait in the Blocked
+ * // state (so not using any CPU processing time) for a maximum of 100ms for
+ * // a message to become available.
+ * xReceivedBytes = xMessageBufferReceive( xMessageBuffer,
+ * ( void * ) ucRxData,
+ * sizeof( ucRxData ),
+ * xBlockTime );
+ *
+ * if( xReceivedBytes > 0 )
+ * {
+ * // A ucRxData contains a message that is xReceivedBytes long. Process
+ * // the message here....
+ * }
+ * }
+ * @endcode
+ * \defgroup xMessageBufferReceive xMessageBufferReceive
+ * \ingroup MessageBufferManagement
+ */
+#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) \
+ xStreamBufferReceive( ( xMessageBuffer ), ( pvRxData ), ( xBufferLengthBytes ), ( xTicksToWait ) )
+
+
+/**
+ * message_buffer.h
+ *
+ * @code{c}
+ * size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer,
+ * void *pvRxData,
+ * size_t xBufferLengthBytes,
+ * BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * An interrupt safe version of the API function that receives a discrete
+ * message from a message buffer. Messages can be of variable length and are
+ * copied out of the buffer.
+ *
+ * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
+ * implementation (so also the message buffer implementation, as message buffers
+ * are built on top of stream buffers) assumes there is only one task or
+ * interrupt that will write to the buffer (the writer), and only one task or
+ * interrupt that will read from the buffer (the reader). It is safe for the
+ * writer and reader to be different tasks or interrupts, but, unlike other
+ * FreeRTOS objects, it is not safe to have multiple different writers or
+ * multiple different readers. If there are to be multiple different writers
+ * then the application writer must place each call to a writing API function
+ * (such as xMessageBufferSend()) inside a critical section and set the send
+ * block time to 0. Likewise, if there are to be multiple different readers
+ * then the application writer must place each call to a reading API function
+ * (such as xMessageBufferRead()) inside a critical section and set the receive
+ * block time to 0.
+ *
+ * Use xMessageBufferReceive() to read from a message buffer from a task. Use
+ * xMessageBufferReceiveFromISR() to read from a message buffer from an
+ * interrupt service routine (ISR).
+ *
+ * @param xMessageBuffer The handle of the message buffer from which a message
+ * is being received.
+ *
+ * @param pvRxData A pointer to the buffer into which the received message is
+ * to be copied.
+ *
+ * @param xBufferLengthBytes The length of the buffer pointed to by the pvRxData
+ * parameter. This sets the maximum length of the message that can be received.
+ * If xBufferLengthBytes is too small to hold the next message then the message
+ * will be left in the message buffer and 0 will be returned.
+ *
+ * @param pxHigherPriorityTaskWoken It is possible that a message buffer will
+ * have a task blocked on it waiting for space to become available. Calling
+ * xMessageBufferReceiveFromISR() can make space available, and so cause a task
+ * that is waiting for space to leave the Blocked state. If calling
+ * xMessageBufferReceiveFromISR() causes a task to leave the Blocked state, and
+ * the unblocked task has a priority higher than the currently executing task
+ * (the task that was interrupted), then, internally,
+ * xMessageBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
+ * If xMessageBufferReceiveFromISR() sets this value to pdTRUE, then normally a
+ * context switch should be performed before the interrupt is exited. That will
+ * ensure the interrupt returns directly to the highest priority Ready state
+ * task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
+ * passed into the function. See the code example below for an example.
+ *
+ * @return The length, in bytes, of the message read from the message buffer, if
+ * any.
+ *
+ * Example use:
+ * @code{c}
+ * // A message buffer that has already been created.
+ * MessageBuffer_t xMessageBuffer;
+ *
+ * void vAnInterruptServiceRoutine( void )
+ * {
+ * uint8_t ucRxData[ 20 ];
+ * size_t xReceivedBytes;
+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
+ *
+ * // Receive the next message from the message buffer.
+ * xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer,
+ * ( void * ) ucRxData,
+ * sizeof( ucRxData ),
+ * &xHigherPriorityTaskWoken );
+ *
+ * if( xReceivedBytes > 0 )
+ * {
+ * // A ucRxData contains a message that is xReceivedBytes long. Process
+ * // the message here....
+ * }
+ *
+ * // If xHigherPriorityTaskWoken was set to pdTRUE inside
+ * // xMessageBufferReceiveFromISR() then a task that has a priority above the
+ * // priority of the currently executing task was unblocked and a context
+ * // switch should be performed to ensure the ISR returns to the unblocked
+ * // task. In most FreeRTOS ports this is done by simply passing
+ * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
+ * // variables value, and perform the context switch if necessary. Check the
+ * // documentation for the port in use for port specific instructions.
+ * portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+ * }
+ * @endcode
+ * \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR
+ * \ingroup MessageBufferManagement
+ */
+#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) \
+ xStreamBufferReceiveFromISR( ( xMessageBuffer ), ( pvRxData ), ( xBufferLengthBytes ), ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * message_buffer.h
+ *
+ * @code{c}
+ * void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );
+ * @endcode
+ *
+ * Deletes a message buffer that was previously created using a call to
+ * xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message
+ * buffer was created using dynamic memory (that is, by xMessageBufferCreate()),
+ * then the allocated memory is freed.
+ *
+ * A message buffer handle must not be used after the message buffer has been
+ * deleted.
+ *
+ * @param xMessageBuffer The handle of the message buffer to be deleted.
+ *
+ */
+#define vMessageBufferDelete( xMessageBuffer ) \
+ vStreamBufferDelete( xMessageBuffer )
+
+/**
+ * message_buffer.h
+ * @code{c}
+ * BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer );
+ * @endcode
+ *
+ * Tests to see if a message buffer is full. A message buffer is full if it
+ * cannot accept any more messages, of any size, until space is made available
+ * by a message being removed from the message buffer.
+ *
+ * @param xMessageBuffer The handle of the message buffer being queried.
+ *
+ * @return If the message buffer referenced by xMessageBuffer is full then
+ * pdTRUE is returned. Otherwise pdFALSE is returned.
+ */
+#define xMessageBufferIsFull( xMessageBuffer ) \
+ xStreamBufferIsFull( xMessageBuffer )
+
+/**
+ * message_buffer.h
+ * @code{c}
+ * BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer );
+ * @endcode
+ *
+ * Tests to see if a message buffer is empty (does not contain any messages).
+ *
+ * @param xMessageBuffer The handle of the message buffer being queried.
+ *
+ * @return If the message buffer referenced by xMessageBuffer is empty then
+ * pdTRUE is returned. Otherwise pdFALSE is returned.
+ *
+ */
+#define xMessageBufferIsEmpty( xMessageBuffer ) \
+ xStreamBufferIsEmpty( xMessageBuffer )
+
+/**
+ * message_buffer.h
+ * @code{c}
+ * BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );
+ * @endcode
+ *
+ * Resets a message buffer to its initial empty state, discarding any message it
+ * contained.
+ *
+ * A message buffer can only be reset if there are no tasks blocked on it.
+ *
+ * @param xMessageBuffer The handle of the message buffer being reset.
+ *
+ * @return If the message buffer was reset then pdPASS is returned. If the
+ * message buffer could not be reset because either there was a task blocked on
+ * the message queue to wait for space to become available, or to wait for a
+ * a message to be available, then pdFAIL is returned.
+ *
+ * \defgroup xMessageBufferReset xMessageBufferReset
+ * \ingroup MessageBufferManagement
+ */
+#define xMessageBufferReset( xMessageBuffer ) \
+ xStreamBufferReset( xMessageBuffer )
+
+
+/**
+ * message_buffer.h
+ * @code{c}
+ * size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer );
+ * @endcode
+ * Returns the number of bytes of free space in the message buffer.
+ *
+ * @param xMessageBuffer The handle of the message buffer being queried.
+ *
+ * @return The number of bytes that can be written to the message buffer before
+ * the message buffer would be full. When a message is written to the message
+ * buffer an additional sizeof( size_t ) bytes are also written to store the
+ * message's length. sizeof( size_t ) is typically 4 bytes on a 32-bit
+ * architecture, so if xMessageBufferSpacesAvailable() returns 10, then the size
+ * of the largest message that can be written to the message buffer is 6 bytes.
+ *
+ * \defgroup xMessageBufferSpaceAvailable xMessageBufferSpaceAvailable
+ * \ingroup MessageBufferManagement
+ */
+#define xMessageBufferSpaceAvailable( xMessageBuffer ) \
+ xStreamBufferSpacesAvailable( xMessageBuffer )
+#define xMessageBufferSpacesAvailable( xMessageBuffer ) \
+ xStreamBufferSpacesAvailable( xMessageBuffer ) /* Corrects typo in original macro name. */
+
+/**
+ * message_buffer.h
+ * @code{c}
+ * size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer );
+ * @endcode
+ * Returns the length (in bytes) of the next message in a message buffer.
+ * Useful if xMessageBufferReceive() returned 0 because the size of the buffer
+ * passed into xMessageBufferReceive() was too small to hold the next message.
+ *
+ * @param xMessageBuffer The handle of the message buffer being queried.
+ *
+ * @return The length (in bytes) of the next message in the message buffer, or 0
+ * if the message buffer is empty.
+ *
+ * \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes
+ * \ingroup MessageBufferManagement
+ */
+#define xMessageBufferNextLengthBytes( xMessageBuffer ) \
+ xStreamBufferNextMessageLengthBytes( xMessageBuffer ) PRIVILEGED_FUNCTION;
+
+/**
+ * message_buffer.h
+ *
+ * @code{c}
+ * BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xMessageBuffer, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * For advanced users only.
+ *
+ * The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
+ * data is sent to a message buffer or stream buffer. If there was a task that
+ * was blocked on the message or stream buffer waiting for data to arrive then
+ * the sbSEND_COMPLETED() macro sends a notification to the task to remove it
+ * from the Blocked state. xMessageBufferSendCompletedFromISR() does the same
+ * thing. It is provided to enable application writers to implement their own
+ * version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
+ *
+ * See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
+ * additional information.
+ *
+ * @param xMessageBuffer The handle of the stream buffer to which data was
+ * written.
+ *
+ * @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
+ * initialised to pdFALSE before it is passed into
+ * xMessageBufferSendCompletedFromISR(). If calling
+ * xMessageBufferSendCompletedFromISR() removes a task from the Blocked state,
+ * and the task has a priority above the priority of the currently running task,
+ * then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
+ * context switch should be performed before exiting the ISR.
+ *
+ * @return If a task was removed from the Blocked state then pdTRUE is returned.
+ * Otherwise pdFALSE is returned.
+ *
+ * \defgroup xMessageBufferSendCompletedFromISR xMessageBufferSendCompletedFromISR
+ * \ingroup StreamBufferManagement
+ */
+#define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
+ xStreamBufferSendCompletedFromISR( ( xMessageBuffer ), ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * message_buffer.h
+ *
+ * @code{c}
+ * BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xMessageBuffer, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * For advanced users only.
+ *
+ * The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
+ * data is read out of a message buffer or stream buffer. If there was a task
+ * that was blocked on the message or stream buffer waiting for data to arrive
+ * then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
+ * remove it from the Blocked state. xMessageBufferReceiveCompletedFromISR()
+ * does the same thing. It is provided to enable application writers to
+ * implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
+ * ANY OTHER TIME.
+ *
+ * See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
+ * additional information.
+ *
+ * @param xMessageBuffer The handle of the stream buffer from which data was
+ * read.
+ *
+ * @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
+ * initialised to pdFALSE before it is passed into
+ * xMessageBufferReceiveCompletedFromISR(). If calling
+ * xMessageBufferReceiveCompletedFromISR() removes a task from the Blocked state,
+ * and the task has a priority above the priority of the currently running task,
+ * then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
+ * context switch should be performed before exiting the ISR.
+ *
+ * @return If a task was removed from the Blocked state then pdTRUE is returned.
+ * Otherwise pdFALSE is returned.
+ *
+ * \defgroup xMessageBufferReceiveCompletedFromISR xMessageBufferReceiveCompletedFromISR
+ * \ingroup StreamBufferManagement
+ */
+#define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \
+ xStreamBufferReceiveCompletedFromISR( ( xMessageBuffer ), ( pxHigherPriorityTaskWoken ) )
+
+/* *INDENT-OFF* */
+#if defined( __cplusplus )
+ } /* extern "C" */
+#endif
+/* *INDENT-ON* */
+
+#endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */
diff --git a/source/test/freertos/inc/mpu_prototypes.h b/source/test/freertos/inc/mpu_prototypes.h
new file mode 100644
index 0000000..933794c
--- /dev/null
+++ b/source/test/freertos/inc/mpu_prototypes.h
@@ -0,0 +1,264 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/*
+ * When the MPU is used the standard (non MPU) API functions are mapped to
+ * equivalents that start "MPU_", the prototypes for which are defined in this
+ * header files. This will cause the application code to call the MPU_ version
+ * which wraps the non-MPU version with privilege promoting then demoting code,
+ * so the kernel code always runs will full privileges.
+ */
+
+
+#ifndef MPU_PROTOTYPES_H
+#define MPU_PROTOTYPES_H
+
+/* MPU versions of task.h API functions. */
+BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode,
+ const char * const pcName,
+ const uint16_t usStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ TaskHandle_t * const pxCreatedTask ) FREERTOS_SYSTEM_CALL;
+TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode,
+ const char * const pcName,
+ const uint32_t ulStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ StackType_t * const puxStackBuffer,
+ StaticTask_t * const pxTaskBuffer ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
+ const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
+UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
+eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskGetInfo( TaskHandle_t xTask,
+ TaskStatus_t * pxTaskStatus,
+ BaseType_t xGetFreeStackSpace,
+ eTaskState eState ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskPrioritySet( TaskHandle_t xTask,
+ UBaseType_t uxNewPriority ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskStartScheduler( void ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskSuspendAll( void ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskResumeAll( void ) FREERTOS_SYSTEM_CALL;
+TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL;
+UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL;
+char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) FREERTOS_SYSTEM_CALL;
+TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) FREERTOS_SYSTEM_CALL;
+UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
+configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask,
+ TaskHookFunction_t pxHookFunction ) FREERTOS_SYSTEM_CALL;
+TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
+ BaseType_t xIndex,
+ void * pvValue ) FREERTOS_SYSTEM_CALL;
+void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
+ BaseType_t xIndex ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask,
+ void * pvParameter ) FREERTOS_SYSTEM_CALL;
+TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL;
+UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
+ const UBaseType_t uxArraySize,
+ configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL;
+configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL;
+configRUN_TIME_COUNTER_TYPE MPU_ulTaskGetIdleRunTimePercent( void ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskGetRunTimeStats( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify,
+ UBaseType_t uxIndexToNotify,
+ uint32_t ulValue,
+ eNotifyAction eAction,
+ uint32_t * pulPreviousNotificationValue ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
+ uint32_t ulBitsToClearOnEntry,
+ uint32_t ulBitsToClearOnExit,
+ uint32_t * pulNotificationValue,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
+ BaseType_t xClearCountOnExit,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask,
+ UBaseType_t uxIndexToClear ) FREERTOS_SYSTEM_CALL;
+uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
+ UBaseType_t uxIndexToClear,
+ uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL;
+TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
+ TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL;
+void MPU_vTaskMissedYield( void ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) FREERTOS_SYSTEM_CALL;
+
+/* MPU versions of queue.h API functions. */
+BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue,
+ const void * const pvItemToQueue,
+ TickType_t xTicksToWait,
+ const BaseType_t xCopyPosition ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue,
+ void * const pvBuffer,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue,
+ void * const pvBuffer,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
+UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
+void MPU_vQueueDelete( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
+QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
+QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType,
+ StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
+QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
+ const UBaseType_t uxInitialCount ) FREERTOS_SYSTEM_CALL;
+QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
+ const UBaseType_t uxInitialCount,
+ StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL;
+TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) FREERTOS_SYSTEM_CALL;
+void MPU_vQueueAddToRegistry( QueueHandle_t xQueue,
+ const char * pcName ) FREERTOS_SYSTEM_CALL;
+void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
+const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
+QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength,
+ const UBaseType_t uxItemSize,
+ const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
+QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
+ const UBaseType_t uxItemSize,
+ uint8_t * pucQueueStorage,
+ StaticQueue_t * pxStaticQueue,
+ const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL;
+QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
+ QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
+ QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL;
+QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
+ const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue,
+ BaseType_t xNewQueue ) FREERTOS_SYSTEM_CALL;
+void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue,
+ UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL;
+UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
+uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL;
+
+/* MPU versions of timers.h API functions. */
+TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName,
+ const TickType_t xTimerPeriodInTicks,
+ const UBaseType_t uxAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction ) FREERTOS_SYSTEM_CALL;
+TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName,
+ const TickType_t xTimerPeriodInTicks,
+ const UBaseType_t uxAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction,
+ StaticTimer_t * pxTimerBuffer ) FREERTOS_SYSTEM_CALL;
+void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
+void MPU_vTimerSetTimerID( TimerHandle_t xTimer,
+ void * pvNewID ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
+TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
+ void * pvParameter1,
+ uint32_t ulParameter2,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
+void MPU_vTimerSetReloadMode( TimerHandle_t xTimer,
+ const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL;
+UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
+TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
+TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer,
+ const BaseType_t xCommandID,
+ const TickType_t xOptionalValue,
+ BaseType_t * const pxHigherPriorityTaskWoken,
+ const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+
+/* MPU versions of event_group.h API functions. */
+EventGroupHandle_t MPU_xEventGroupCreate( void ) FREERTOS_SYSTEM_CALL;
+EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) FREERTOS_SYSTEM_CALL;
+EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToWaitFor,
+ const BaseType_t xClearOnExit,
+ const BaseType_t xWaitForAllBits,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL;
+EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToSet ) FREERTOS_SYSTEM_CALL;
+EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToSet,
+ const EventBits_t uxBitsToWaitFor,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) FREERTOS_SYSTEM_CALL;
+UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) FREERTOS_SYSTEM_CALL;
+
+/* MPU versions of message/stream_buffer.h API functions. */
+size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
+ const void * pvTxData,
+ size_t xDataLengthBytes,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
+ void * pvRxData,
+ size_t xBufferLengthBytes,
+ TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
+size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
+void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
+size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
+size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL;
+BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
+ size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL;
+StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes,
+ size_t xTriggerLevelBytes,
+ BaseType_t xIsMessageBuffer,
+ StreamBufferCallbackFunction_t pxSendCompletedCallback,
+ StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) FREERTOS_SYSTEM_CALL;
+StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
+ size_t xTriggerLevelBytes,
+ BaseType_t xIsMessageBuffer,
+ uint8_t * const pucStreamBufferStorageArea,
+ StaticStreamBuffer_t * const pxStaticStreamBuffer,
+ StreamBufferCallbackFunction_t pxSendCompletedCallback,
+ StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) FREERTOS_SYSTEM_CALL;
+
+
+
+#endif /* MPU_PROTOTYPES_H */
diff --git a/source/test/freertos/inc/mpu_wrappers.h b/source/test/freertos/inc/mpu_wrappers.h
new file mode 100644
index 0000000..af06ab3
--- /dev/null
+++ b/source/test/freertos/inc/mpu_wrappers.h
@@ -0,0 +1,184 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef MPU_WRAPPERS_H
+#define MPU_WRAPPERS_H
+
+/* This file redefines API functions to be called through a wrapper macro, but
+ * only for ports that are using the MPU. */
+#if ( portUSING_MPU_WRAPPERS == 1 )
+
+/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
+ * included from queue.c or task.c to prevent it from having an effect within
+ * those files. */
+ #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/*
+ * Map standard (non MPU) API functions to equivalents that start
+ * "MPU_". This will cause the application code to call the MPU_
+ * version, which wraps the non-MPU version with privilege promoting
+ * then demoting code, so the kernel code always runs will full
+ * privileges.
+ */
+
+/* Map standard task.h API functions to the MPU equivalents. */
+ #define xTaskCreate MPU_xTaskCreate
+ #define xTaskCreateStatic MPU_xTaskCreateStatic
+ #define vTaskDelete MPU_vTaskDelete
+ #define vTaskDelay MPU_vTaskDelay
+ #define xTaskDelayUntil MPU_xTaskDelayUntil
+ #define xTaskAbortDelay MPU_xTaskAbortDelay
+ #define uxTaskPriorityGet MPU_uxTaskPriorityGet
+ #define eTaskGetState MPU_eTaskGetState
+ #define vTaskGetInfo MPU_vTaskGetInfo
+ #define vTaskPrioritySet MPU_vTaskPrioritySet
+ #define vTaskSuspend MPU_vTaskSuspend
+ #define vTaskResume MPU_vTaskResume
+ #define vTaskSuspendAll MPU_vTaskSuspendAll
+ #define xTaskResumeAll MPU_xTaskResumeAll
+ #define xTaskGetTickCount MPU_xTaskGetTickCount
+ #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks
+ #define pcTaskGetName MPU_pcTaskGetName
+ #define xTaskGetHandle MPU_xTaskGetHandle
+ #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
+ #define uxTaskGetStackHighWaterMark2 MPU_uxTaskGetStackHighWaterMark2
+ #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
+ #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
+ #define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer
+ #define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer
+ #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
+ #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
+ #define uxTaskGetSystemState MPU_uxTaskGetSystemState
+ #define vTaskList MPU_vTaskList
+ #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats
+ #define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter
+ #define ulTaskGetIdleRunTimePercent MPU_ulTaskGetIdleRunTimePercent
+ #define xTaskGenericNotify MPU_xTaskGenericNotify
+ #define xTaskGenericNotifyWait MPU_xTaskGenericNotifyWait
+ #define ulTaskGenericNotifyTake MPU_ulTaskGenericNotifyTake
+ #define xTaskGenericNotifyStateClear MPU_xTaskGenericNotifyStateClear
+ #define ulTaskGenericNotifyValueClear MPU_ulTaskGenericNotifyValueClear
+ #define xTaskCatchUpTicks MPU_xTaskCatchUpTicks
+
+ #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
+ #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState
+ #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
+ #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
+
+/* Map standard queue.h API functions to the MPU equivalents. */
+ #define xQueueGenericSend MPU_xQueueGenericSend
+ #define xQueueReceive MPU_xQueueReceive
+ #define xQueuePeek MPU_xQueuePeek
+ #define xQueueSemaphoreTake MPU_xQueueSemaphoreTake
+ #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
+ #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable
+ #define vQueueDelete MPU_vQueueDelete
+ #define xQueueCreateMutex MPU_xQueueCreateMutex
+ #define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic
+ #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
+ #define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic
+ #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
+ #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
+ #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
+ #define xQueueGenericCreate MPU_xQueueGenericCreate
+ #define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic
+ #define xQueueCreateSet MPU_xQueueCreateSet
+ #define xQueueAddToSet MPU_xQueueAddToSet
+ #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
+ #define xQueueSelectFromSet MPU_xQueueSelectFromSet
+ #define xQueueGenericReset MPU_xQueueGenericReset
+
+ #if ( configQUEUE_REGISTRY_SIZE > 0 )
+ #define vQueueAddToRegistry MPU_vQueueAddToRegistry
+ #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
+ #define pcQueueGetName MPU_pcQueueGetName
+ #endif
+
+/* Map standard timer.h API functions to the MPU equivalents. */
+ #define pvTimerGetTimerID MPU_pvTimerGetTimerID
+ #define vTimerSetTimerID MPU_vTimerSetTimerID
+ #define xTimerIsTimerActive MPU_xTimerIsTimerActive
+ #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle
+ #define pcTimerGetName MPU_pcTimerGetName
+ #define vTimerSetReloadMode MPU_vTimerSetReloadMode
+ #define uxTimerGetReloadMode MPU_uxTimerGetReloadMode
+ #define xTimerGetPeriod MPU_xTimerGetPeriod
+ #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
+ #define xTimerGenericCommand MPU_xTimerGenericCommand
+
+/* Map standard event_group.h API functions to the MPU equivalents. */
+ #define xEventGroupCreate MPU_xEventGroupCreate
+ #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic
+ #define xEventGroupWaitBits MPU_xEventGroupWaitBits
+ #define xEventGroupClearBits MPU_xEventGroupClearBits
+ #define xEventGroupSetBits MPU_xEventGroupSetBits
+ #define xEventGroupSync MPU_xEventGroupSync
+ #define vEventGroupDelete MPU_vEventGroupDelete
+
+/* Map standard message/stream_buffer.h API functions to the MPU
+ * equivalents. */
+ #define xStreamBufferSend MPU_xStreamBufferSend
+ #define xStreamBufferReceive MPU_xStreamBufferReceive
+ #define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes
+ #define vStreamBufferDelete MPU_vStreamBufferDelete
+ #define xStreamBufferIsFull MPU_xStreamBufferIsFull
+ #define xStreamBufferIsEmpty MPU_xStreamBufferIsEmpty
+ #define xStreamBufferReset MPU_xStreamBufferReset
+ #define xStreamBufferSpacesAvailable MPU_xStreamBufferSpacesAvailable
+ #define xStreamBufferBytesAvailable MPU_xStreamBufferBytesAvailable
+ #define xStreamBufferSetTriggerLevel MPU_xStreamBufferSetTriggerLevel
+ #define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate
+ #define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic
+
+
+/* Remove the privileged function macro, but keep the PRIVILEGED_DATA
+ * macro so applications can place data in privileged access sections
+ * (useful when using statically allocated objects). */
+ #define PRIVILEGED_FUNCTION
+ #define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
+ #define FREERTOS_SYSTEM_CALL
+
+ #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
+
+/* Ensure API functions go in the privileged execution section. */
+ #define PRIVILEGED_FUNCTION __attribute__( ( section( "privileged_functions" ) ) )
+ #define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
+ #define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) )
+
+ #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
+
+#else /* portUSING_MPU_WRAPPERS */
+
+ #define PRIVILEGED_FUNCTION
+ #define PRIVILEGED_DATA
+ #define FREERTOS_SYSTEM_CALL
+
+#endif /* portUSING_MPU_WRAPPERS */
+
+
+#endif /* MPU_WRAPPERS_H */
diff --git a/source/test/freertos/inc/portable.h b/source/test/freertos/inc/portable.h
new file mode 100644
index 0000000..e7ec7bd
--- /dev/null
+++ b/source/test/freertos/inc/portable.h
@@ -0,0 +1,238 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/*-----------------------------------------------------------
+* Portable layer API. Each function must be defined for each port.
+*----------------------------------------------------------*/
+
+#ifndef PORTABLE_H
+#define PORTABLE_H
+
+/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
+ * pre-processor definition was used to ensure the pre-processor found the correct
+ * portmacro.h file for the port being used. That scheme was deprecated in favour
+ * of setting the compiler's include path such that it found the correct
+ * portmacro.h file - removing the need for the constant and allowing the
+ * portmacro.h file to be located anywhere in relation to the port being used.
+ * Purely for reasons of backward compatibility the old method is still valid, but
+ * to make it clear that new projects should not use it, support for the port
+ * specific constants has been moved into the deprecated_definitions.h header
+ * file. */
+#include "deprecated_definitions.h"
+
+/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
+ * did not result in a portmacro.h header file being included - and it should be
+ * included here. In this case the path to the correct portmacro.h header file
+ * must be set in the compiler's include path. */
+#ifndef portENTER_CRITICAL
+ #include "portmacro.h"
+#endif
+
+#if portBYTE_ALIGNMENT == 32
+ #define portBYTE_ALIGNMENT_MASK ( 0x001f )
+#elif portBYTE_ALIGNMENT == 16
+ #define portBYTE_ALIGNMENT_MASK ( 0x000f )
+#elif portBYTE_ALIGNMENT == 8
+ #define portBYTE_ALIGNMENT_MASK ( 0x0007 )
+#elif portBYTE_ALIGNMENT == 4
+ #define portBYTE_ALIGNMENT_MASK ( 0x0003 )
+#elif portBYTE_ALIGNMENT == 2
+ #define portBYTE_ALIGNMENT_MASK ( 0x0001 )
+#elif portBYTE_ALIGNMENT == 1
+ #define portBYTE_ALIGNMENT_MASK ( 0x0000 )
+#else /* if portBYTE_ALIGNMENT == 32 */
+ #error "Invalid portBYTE_ALIGNMENT definition"
+#endif /* if portBYTE_ALIGNMENT == 32 */
+
+#ifndef portUSING_MPU_WRAPPERS
+ #define portUSING_MPU_WRAPPERS 0
+#endif
+
+#ifndef portNUM_CONFIGURABLE_REGIONS
+ #define portNUM_CONFIGURABLE_REGIONS 1
+#endif
+
+#ifndef portHAS_STACK_OVERFLOW_CHECKING
+ #define portHAS_STACK_OVERFLOW_CHECKING 0
+#endif
+
+#ifndef portARCH_NAME
+ #define portARCH_NAME NULL
+#endif
+
+#ifndef configSTACK_ALLOCATION_FROM_SEPARATE_HEAP
+ /* Defaults to 0 for backward compatibility. */
+ #define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
+#endif
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+#include "mpu_wrappers.h"
+
+/*
+ * Setup the stack of a new task so it is ready to be placed under the
+ * scheduler control. The registers have to be placed on the stack in
+ * the order that the port expects to find them.
+ *
+ */
+#if ( portUSING_MPU_WRAPPERS == 1 )
+ #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
+ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
+ StackType_t * pxEndOfStack,
+ TaskFunction_t pxCode,
+ void * pvParameters,
+ BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
+ #else
+ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
+ TaskFunction_t pxCode,
+ void * pvParameters,
+ BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
+ #endif
+#else /* if ( portUSING_MPU_WRAPPERS == 1 ) */
+ #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
+ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
+ StackType_t * pxEndOfStack,
+ TaskFunction_t pxCode,
+ void * pvParameters ) PRIVILEGED_FUNCTION;
+ #else
+ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
+ TaskFunction_t pxCode,
+ void * pvParameters ) PRIVILEGED_FUNCTION;
+ #endif
+#endif /* if ( portUSING_MPU_WRAPPERS == 1 ) */
+
+/* Used by heap_5.c to define the start address and size of each memory region
+ * that together comprise the total FreeRTOS heap space. */
+typedef struct HeapRegion
+{
+ uint8_t * pucStartAddress;
+ size_t xSizeInBytes;
+} HeapRegion_t;
+
+/* Used to pass information about the heap out of vPortGetHeapStats(). */
+typedef struct xHeapStats
+{
+ size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */
+ size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
+ size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
+ size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */
+ size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */
+ size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */
+ size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */
+} HeapStats_t;
+
+/*
+ * Used to define multiple heap regions for use by heap_5.c. This function
+ * must be called before any calls to pvPortMalloc() - not creating a task,
+ * queue, semaphore, mutex, software timer, event group, etc. will result in
+ * pvPortMalloc being called.
+ *
+ * pxHeapRegions passes in an array of HeapRegion_t structures - each of which
+ * defines a region of memory that can be used as the heap. The array is
+ * terminated by a HeapRegions_t structure that has a size of 0. The region
+ * with the lowest start address must appear first in the array.
+ */
+void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
+
+/*
+ * Returns a HeapStats_t structure filled with information about the current
+ * heap state.
+ */
+void vPortGetHeapStats( HeapStats_t * pxHeapStats );
+
+/*
+ * Map to the memory management routines required for the port.
+ */
+void * pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
+void * pvPortCalloc( size_t xNum,
+ size_t xSize ) PRIVILEGED_FUNCTION;
+void vPortFree( void * pv ) PRIVILEGED_FUNCTION;
+void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
+size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
+size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
+
+#if ( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 )
+ void * pvPortMallocStack( size_t xSize ) PRIVILEGED_FUNCTION;
+ void vPortFreeStack( void * pv ) PRIVILEGED_FUNCTION;
+#else
+ #define pvPortMallocStack pvPortMalloc
+ #define vPortFreeStack vPortFree
+#endif
+
+#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
+
+/**
+ * task.h
+ * @code{c}
+ * void vApplicationMallocFailedHook( void )
+ * @endcode
+ *
+ * This hook function is called when allocation failed.
+ */
+ void vApplicationMallocFailedHook( void ); /*lint !e526 Symbol not defined as it is an application callback. */
+#endif
+
+/*
+ * Setup the hardware ready for the scheduler to take control. This generally
+ * sets up a tick interrupt and sets timers for the correct tick frequency.
+ */
+BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
+ * the hardware is left in its original condition after the scheduler stops
+ * executing.
+ */
+void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * The structures and methods of manipulating the MPU are contained within the
+ * port layer.
+ *
+ * Fills the xMPUSettings structure with the memory region information
+ * contained in xRegions.
+ */
+#if ( portUSING_MPU_WRAPPERS == 1 )
+ struct xMEMORY_REGION;
+ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
+ const struct xMEMORY_REGION * const xRegions,
+ StackType_t * pxBottomOfStack,
+ uint32_t ulStackDepth ) PRIVILEGED_FUNCTION;
+#endif
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ }
+#endif
+/* *INDENT-ON* */
+
+#endif /* PORTABLE_H */
diff --git a/source/test/freertos/inc/portmacro.h b/source/test/freertos/inc/portmacro.h
new file mode 100644
index 0000000..bfe0575
--- /dev/null
+++ b/source/test/freertos/inc/portmacro.h
@@ -0,0 +1,128 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+
+#ifndef PORTMACRO_H
+ #define PORTMACRO_H
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #include "chip.h"
+ #include "board.h"
+
+/*-----------------------------------------------------------
+ * Port specific definitions.
+ *
+ * The settings in this file configure FreeRTOS correctly for the
+ * given hardware and compiler.
+ *
+ * These settings should not be altered.
+ *-----------------------------------------------------------
+ */
+
+/* Type definitions. */
+ #define portCHAR char
+ #define portFLOAT float
+ #define portDOUBLE double
+ #define portLONG long
+ #define portSHORT short
+ #define portSTACK_TYPE uint32_t
+ #define portBASE_TYPE long
+
+ typedef portSTACK_TYPE StackType_t;
+ typedef long BaseType_t;
+ typedef unsigned long UBaseType_t;
+
+ #if ( configUSE_16_BIT_TICKS == 1 )
+ typedef uint16_t TickType_t;
+ #define portMAX_DELAY ( TickType_t ) 0xffff
+ #else
+ typedef uint32_t TickType_t;
+ #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
+
+/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
+ * not need to be guarded with a critical section. */
+ #define portTICK_TYPE_IS_ATOMIC 1
+ #endif
+/*-----------------------------------------------------------*/
+
+/* Architecture specifics. */
+ #define portSTACK_GROWTH ( -1 )
+ #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
+ #define portBYTE_ALIGNMENT 8
+ #define portDONT_DISCARD __attribute__( ( used ) )
+/*-----------------------------------------------------------*/
+
+
+/* Scheduler utilities. */
+ extern void vPortYield( void );
+ #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
+ #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
+ #define portYIELD() vPortYield()
+ #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 )
+ #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
+/*-----------------------------------------------------------*/
+
+
+/* Critical section management. */
+ extern void vPortEnterCritical( void );
+ extern void vPortExitCritical( void );
+ extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__( ( naked ) );
+ extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__( ( naked ) );
+
+ #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
+ #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMaskFromISR( x )
+ #define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
+ #define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
+ #define portENTER_CRITICAL() vPortEnterCritical()
+ #define portEXIT_CRITICAL() vPortExitCritical()
+
+/*-----------------------------------------------------------*/
+
+/* Tickless idle/low power functionality. */
+ #ifndef portSUPPRESS_TICKS_AND_SLEEP
+ extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
+ #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
+ #endif
+/*-----------------------------------------------------------*/
+
+/* Task function macros as described on the FreeRTOS.org WEB site. */
+ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
+ #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
+
+ #define portNOP()
+
+ #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+#endif /* PORTMACRO_H */
diff --git a/source/test/freertos/inc/projdefs.h b/source/test/freertos/inc/projdefs.h
new file mode 100644
index 0000000..aa49e59
--- /dev/null
+++ b/source/test/freertos/inc/projdefs.h
@@ -0,0 +1,122 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef PROJDEFS_H
+#define PROJDEFS_H
+
+/*
+ * Defines the prototype to which task functions must conform. Defined in this
+ * file to ensure the type is known before portable.h is included.
+ */
+typedef void (* TaskFunction_t)( void * );
+
+/* Converts a time in milliseconds to a time in ticks. This macro can be
+ * overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
+ * definition here is not suitable for your application. */
+#ifndef pdMS_TO_TICKS
+ #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000U ) )
+#endif
+
+#define pdFALSE ( ( BaseType_t ) 0 )
+#define pdTRUE ( ( BaseType_t ) 1 )
+
+#define pdPASS ( pdTRUE )
+#define pdFAIL ( pdFALSE )
+#define errQUEUE_EMPTY ( ( BaseType_t ) 0 )
+#define errQUEUE_FULL ( ( BaseType_t ) 0 )
+
+/* FreeRTOS error definitions. */
+#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 )
+#define errQUEUE_BLOCKED ( -4 )
+#define errQUEUE_YIELD ( -5 )
+
+/* Macros used for basic data corruption checks. */
+#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES
+ #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0
+#endif
+
+#if ( configUSE_16_BIT_TICKS == 1 )
+ #define pdINTEGRITY_CHECK_VALUE 0x5a5a
+#else
+ #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
+#endif
+
+/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
+ * itself. */
+#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
+#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
+#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
+#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
+#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
+#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
+#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */
+#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */
+#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */
+#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */
+#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */
+#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */
+#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */
+#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */
+#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */
+#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */
+#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */
+#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */
+#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */
+#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */
+#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */
+#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */
+#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */
+#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */
+#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */
+#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
+#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
+#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
+#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
+#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
+#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */
+#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */
+#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */
+#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */
+#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */
+#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */
+#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */
+#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
+#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
+
+/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
+ * itself. */
+#define pdFREERTOS_LITTLE_ENDIAN 0
+#define pdFREERTOS_BIG_ENDIAN 1
+
+/* Re-defining endian values for generic naming. */
+#define pdLITTLE_ENDIAN pdFREERTOS_LITTLE_ENDIAN
+#define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN
+
+
+#endif /* PROJDEFS_H */
diff --git a/source/test/freertos/inc/queue.h b/source/test/freertos/inc/queue.h
new file mode 100644
index 0000000..df572e1
--- /dev/null
+++ b/source/test/freertos/inc/queue.h
@@ -0,0 +1,1722 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h" must appear in source files before "include queue.h"
+#endif
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+#include "task.h"
+
+/**
+ * Type by which queues are referenced. For example, a call to xQueueCreate()
+ * returns an QueueHandle_t variable that can then be used as a parameter to
+ * xQueueSend(), xQueueReceive(), etc.
+ */
+struct QueueDefinition; /* Using old naming convention so as not to break kernel aware debuggers. */
+typedef struct QueueDefinition * QueueHandle_t;
+
+/**
+ * Type by which queue sets are referenced. For example, a call to
+ * xQueueCreateSet() returns an xQueueSet variable that can then be used as a
+ * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc.
+ */
+typedef struct QueueDefinition * QueueSetHandle_t;
+
+/**
+ * Queue sets can contain both queues and semaphores, so the
+ * QueueSetMemberHandle_t is defined as a type to be used where a parameter or
+ * return value can be either an QueueHandle_t or an SemaphoreHandle_t.
+ */
+typedef struct QueueDefinition * QueueSetMemberHandle_t;
+
+/* For internal use only. */
+#define queueSEND_TO_BACK ( ( BaseType_t ) 0 )
+#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 )
+#define queueOVERWRITE ( ( BaseType_t ) 2 )
+
+/* For internal use only. These definitions *must* match those in queue.c. */
+#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U )
+#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U )
+#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U )
+#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U )
+#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U )
+#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U )
+
+/**
+ * queue. h
+ * @code{c}
+ * QueueHandle_t xQueueCreate(
+ * UBaseType_t uxQueueLength,
+ * UBaseType_t uxItemSize
+ * );
+ * @endcode
+ *
+ * Creates a new queue instance, and returns a handle by which the new queue
+ * can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, queues use two blocks of
+ * memory. The first block is used to hold the queue's data structures. The
+ * second block is used to hold items placed into the queue. If a queue is
+ * created using xQueueCreate() then both blocks of memory are automatically
+ * dynamically allocated inside the xQueueCreate() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a queue is created using
+ * xQueueCreateStatic() then the application writer must provide the memory that
+ * will get used by the queue. xQueueCreateStatic() therefore allows a queue to
+ * be created without using any dynamic memory allocation.
+ *
+ * https://www.FreeRTOS.org/Embedded-RTOS-Queues.html
+ *
+ * @param uxQueueLength The maximum number of items that the queue can contain.
+ *
+ * @param uxItemSize The number of bytes each item in the queue will require.
+ * Items are queued by copy, not by reference, so this is the number of bytes
+ * that will be copied for each posted item. Each item on the queue must be
+ * the same size.
+ *
+ * @return If the queue is successfully create then a handle to the newly
+ * created queue is returned. If the queue cannot be created then 0 is
+ * returned.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ * char ucMessageID;
+ * char ucData[ 20 ];
+ * };
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue1, xQueue2;
+ *
+ * // Create a queue capable of containing 10 uint32_t values.
+ * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+ * if( xQueue1 == 0 )
+ * {
+ * // Queue was not created and must not be used.
+ * }
+ *
+ * // Create a queue capable of containing 10 pointers to AMessage structures.
+ * // These should be passed by pointer as they contain a lot of data.
+ * xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ * if( xQueue2 == 0 )
+ * {
+ * // Queue was not created and must not be used.
+ * }
+ *
+ * // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueCreate xQueueCreate
+ * \ingroup QueueManagement
+ */
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
+#endif
+
+/**
+ * queue. h
+ * @code{c}
+ * QueueHandle_t xQueueCreateStatic(
+ * UBaseType_t uxQueueLength,
+ * UBaseType_t uxItemSize,
+ * uint8_t *pucQueueStorage,
+ * StaticQueue_t *pxQueueBuffer
+ * );
+ * @endcode
+ *
+ * Creates a new queue instance, and returns a handle by which the new queue
+ * can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, queues use two blocks of
+ * memory. The first block is used to hold the queue's data structures. The
+ * second block is used to hold items placed into the queue. If a queue is
+ * created using xQueueCreate() then both blocks of memory are automatically
+ * dynamically allocated inside the xQueueCreate() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a queue is created using
+ * xQueueCreateStatic() then the application writer must provide the memory that
+ * will get used by the queue. xQueueCreateStatic() therefore allows a queue to
+ * be created without using any dynamic memory allocation.
+ *
+ * https://www.FreeRTOS.org/Embedded-RTOS-Queues.html
+ *
+ * @param uxQueueLength The maximum number of items that the queue can contain.
+ *
+ * @param uxItemSize The number of bytes each item in the queue will require.
+ * Items are queued by copy, not by reference, so this is the number of bytes
+ * that will be copied for each posted item. Each item on the queue must be
+ * the same size.
+ *
+ * @param pucQueueStorage If uxItemSize is not zero then
+ * pucQueueStorage must point to a uint8_t array that is at least large
+ * enough to hold the maximum number of items that can be in the queue at any
+ * one time - which is ( uxQueueLength * uxItemsSize ) bytes. If uxItemSize is
+ * zero then pucQueueStorage can be NULL.
+ *
+ * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which
+ * will be used to hold the queue's data structure.
+ *
+ * @return If the queue is created then a handle to the created queue is
+ * returned. If pxQueueBuffer is NULL then NULL is returned.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ * char ucMessageID;
+ * char ucData[ 20 ];
+ * };
+ *
+ #define QUEUE_LENGTH 10
+ #define ITEM_SIZE sizeof( uint32_t )
+ *
+ * // xQueueBuffer will hold the queue structure.
+ * StaticQueue_t xQueueBuffer;
+ *
+ * // ucQueueStorage will hold the items posted to the queue. Must be at least
+ * // [(queue length) * ( queue item size)] bytes long.
+ * uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue1;
+ *
+ * // Create a queue capable of containing 10 uint32_t values.
+ * xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
+ * ITEM_SIZE // The size of each item in the queue
+ * &( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
+ * &xQueueBuffer ); // The buffer that will hold the queue structure.
+ *
+ * // The queue is guaranteed to be created successfully as no dynamic memory
+ * // allocation is used. Therefore xQueue1 is now a handle to a valid queue.
+ *
+ * // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueCreateStatic xQueueCreateStatic
+ * \ingroup QueueManagement
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueSendToToFront(
+ * QueueHandle_t xQueue,
+ * const void *pvItemToQueue,
+ * TickType_t xTicksToWait
+ * );
+ * @endcode
+ *
+ * Post an item to the front of a queue. The item is queued by copy, not by
+ * reference. This function must not be called from an interrupt service
+ * routine. See xQueueSendFromISR () for an alternative which may be used
+ * in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full. The call will return immediately if this is set to 0 and the
+ * queue is full. The time is defined in tick periods so the constant
+ * portTICK_PERIOD_MS should be used to convert to real time if this is required.
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ * char ucMessageID;
+ * char ucData[ 20 ];
+ * } xMessage;
+ *
+ * uint32_t ulVar = 10UL;
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue1, xQueue2;
+ * struct AMessage *pxMessage;
+ *
+ * // Create a queue capable of containing 10 uint32_t values.
+ * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+ *
+ * // Create a queue capable of containing 10 pointers to AMessage structures.
+ * // These should be passed by pointer as they contain a lot of data.
+ * xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ *
+ * // ...
+ *
+ * if( xQueue1 != 0 )
+ * {
+ * // Send an uint32_t. Wait for 10 ticks for space to become
+ * // available if necessary.
+ * if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+ * {
+ * // Failed to post the message, even after 10 ticks.
+ * }
+ * }
+ *
+ * if( xQueue2 != 0 )
+ * {
+ * // Send a pointer to a struct AMessage object. Don't block if the
+ * // queue is already full.
+ * pxMessage = & xMessage;
+ * xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+ * }
+ *
+ * // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueSend xQueueSend
+ * \ingroup QueueManagement
+ */
+#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) \
+ xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueSendToBack(
+ * QueueHandle_t xQueue,
+ * const void *pvItemToQueue,
+ * TickType_t xTicksToWait
+ * );
+ * @endcode
+ *
+ * This is a macro that calls xQueueGenericSend().
+ *
+ * Post an item to the back of a queue. The item is queued by copy, not by
+ * reference. This function must not be called from an interrupt service
+ * routine. See xQueueSendFromISR () for an alternative which may be used
+ * in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full. The call will return immediately if this is set to 0 and the queue
+ * is full. The time is defined in tick periods so the constant
+ * portTICK_PERIOD_MS should be used to convert to real time if this is required.
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ * char ucMessageID;
+ * char ucData[ 20 ];
+ * } xMessage;
+ *
+ * uint32_t ulVar = 10UL;
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue1, xQueue2;
+ * struct AMessage *pxMessage;
+ *
+ * // Create a queue capable of containing 10 uint32_t values.
+ * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+ *
+ * // Create a queue capable of containing 10 pointers to AMessage structures.
+ * // These should be passed by pointer as they contain a lot of data.
+ * xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ *
+ * // ...
+ *
+ * if( xQueue1 != 0 )
+ * {
+ * // Send an uint32_t. Wait for 10 ticks for space to become
+ * // available if necessary.
+ * if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+ * {
+ * // Failed to post the message, even after 10 ticks.
+ * }
+ * }
+ *
+ * if( xQueue2 != 0 )
+ * {
+ * // Send a pointer to a struct AMessage object. Don't block if the
+ * // queue is already full.
+ * pxMessage = & xMessage;
+ * xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+ * }
+ *
+ * // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueSend xQueueSend
+ * \ingroup QueueManagement
+ */
+#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \
+ xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueSend(
+ * QueueHandle_t xQueue,
+ * const void * pvItemToQueue,
+ * TickType_t xTicksToWait
+ * );
+ * @endcode
+ *
+ * This is a macro that calls xQueueGenericSend(). It is included for
+ * backward compatibility with versions of FreeRTOS.org that did not
+ * include the xQueueSendToFront() and xQueueSendToBack() macros. It is
+ * equivalent to xQueueSendToBack().
+ *
+ * Post an item on a queue. The item is queued by copy, not by reference.
+ * This function must not be called from an interrupt service routine.
+ * See xQueueSendFromISR () for an alternative which may be used in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full. The call will return immediately if this is set to 0 and the
+ * queue is full. The time is defined in tick periods so the constant
+ * portTICK_PERIOD_MS should be used to convert to real time if this is required.
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ * char ucMessageID;
+ * char ucData[ 20 ];
+ * } xMessage;
+ *
+ * uint32_t ulVar = 10UL;
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue1, xQueue2;
+ * struct AMessage *pxMessage;
+ *
+ * // Create a queue capable of containing 10 uint32_t values.
+ * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+ *
+ * // Create a queue capable of containing 10 pointers to AMessage structures.
+ * // These should be passed by pointer as they contain a lot of data.
+ * xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ *
+ * // ...
+ *
+ * if( xQueue1 != 0 )
+ * {
+ * // Send an uint32_t. Wait for 10 ticks for space to become
+ * // available if necessary.
+ * if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+ * {
+ * // Failed to post the message, even after 10 ticks.
+ * }
+ * }
+ *
+ * if( xQueue2 != 0 )
+ * {
+ * // Send a pointer to a struct AMessage object. Don't block if the
+ * // queue is already full.
+ * pxMessage = & xMessage;
+ * xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+ * }
+ *
+ * // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueSend xQueueSend
+ * \ingroup QueueManagement
+ */
+#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \
+ xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueOverwrite(
+ * QueueHandle_t xQueue,
+ * const void * pvItemToQueue
+ * );
+ * @endcode
+ *
+ * Only for use with queues that have a length of one - so the queue is either
+ * empty or full.
+ *
+ * Post an item on a queue. If the queue is already full then overwrite the
+ * value held in the queue. The item is queued by copy, not by reference.
+ *
+ * This function must not be called from an interrupt service routine.
+ * See xQueueOverwriteFromISR () for an alternative which may be used in an ISR.
+ *
+ * @param xQueue The handle of the queue to which the data is being sent.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @return xQueueOverwrite() is a macro that calls xQueueGenericSend(), and
+ * therefore has the same return values as xQueueSendToFront(). However, pdPASS
+ * is the only value that can be returned because xQueueOverwrite() will write
+ * to the queue even when the queue is already full.
+ *
+ * Example usage:
+ * @code{c}
+ *
+ * void vFunction( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue;
+ * uint32_t ulVarToSend, ulValReceived;
+ *
+ * // Create a queue to hold one uint32_t value. It is strongly
+ * // recommended *not* to use xQueueOverwrite() on queues that can
+ * // contain more than one value, and doing so will trigger an assertion
+ * // if configASSERT() is defined.
+ * xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
+ *
+ * // Write the value 10 to the queue using xQueueOverwrite().
+ * ulVarToSend = 10;
+ * xQueueOverwrite( xQueue, &ulVarToSend );
+ *
+ * // Peeking the queue should now return 10, but leave the value 10 in
+ * // the queue. A block time of zero is used as it is known that the
+ * // queue holds a value.
+ * ulValReceived = 0;
+ * xQueuePeek( xQueue, &ulValReceived, 0 );
+ *
+ * if( ulValReceived != 10 )
+ * {
+ * // Error unless the item was removed by a different task.
+ * }
+ *
+ * // The queue is still full. Use xQueueOverwrite() to overwrite the
+ * // value held in the queue with 100.
+ * ulVarToSend = 100;
+ * xQueueOverwrite( xQueue, &ulVarToSend );
+ *
+ * // This time read from the queue, leaving the queue empty once more.
+ * // A block time of 0 is used again.
+ * xQueueReceive( xQueue, &ulValReceived, 0 );
+ *
+ * // The value read should be the last value written, even though the
+ * // queue was already full when the value was written.
+ * if( ulValReceived != 100 )
+ * {
+ * // Error!
+ * }
+ *
+ * // ...
+ * }
+ * @endcode
+ * \defgroup xQueueOverwrite xQueueOverwrite
+ * \ingroup QueueManagement
+ */
+#define xQueueOverwrite( xQueue, pvItemToQueue ) \
+ xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE )
+
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueGenericSend(
+ * QueueHandle_t xQueue,
+ * const void * pvItemToQueue,
+ * TickType_t xTicksToWait
+ * BaseType_t xCopyPosition
+ * );
+ * @endcode
+ *
+ * It is preferred that the macros xQueueSend(), xQueueSendToFront() and
+ * xQueueSendToBack() are used in place of calling this function directly.
+ *
+ * Post an item on a queue. The item is queued by copy, not by reference.
+ * This function must not be called from an interrupt service routine.
+ * See xQueueSendFromISR () for an alternative which may be used in an ISR.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for space to become available on the queue, should it already
+ * be full. The call will return immediately if this is set to 0 and the
+ * queue is full. The time is defined in tick periods so the constant
+ * portTICK_PERIOD_MS should be used to convert to real time if this is required.
+ *
+ * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the
+ * item at the back of the queue, or queueSEND_TO_FRONT to place the item
+ * at the front of the queue (for high priority messages).
+ *
+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ * char ucMessageID;
+ * char ucData[ 20 ];
+ * } xMessage;
+ *
+ * uint32_t ulVar = 10UL;
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * QueueHandle_t xQueue1, xQueue2;
+ * struct AMessage *pxMessage;
+ *
+ * // Create a queue capable of containing 10 uint32_t values.
+ * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+ *
+ * // Create a queue capable of containing 10 pointers to AMessage structures.
+ * // These should be passed by pointer as they contain a lot of data.
+ * xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ *
+ * // ...
+ *
+ * if( xQueue1 != 0 )
+ * {
+ * // Send an uint32_t. Wait for 10 ticks for space to become
+ * // available if necessary.
+ * if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10, queueSEND_TO_BACK ) != pdPASS )
+ * {
+ * // Failed to post the message, even after 10 ticks.
+ * }
+ * }
+ *
+ * if( xQueue2 != 0 )
+ * {
+ * // Send a pointer to a struct AMessage object. Don't block if the
+ * // queue is already full.
+ * pxMessage = & xMessage;
+ * xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0, queueSEND_TO_BACK );
+ * }
+ *
+ * // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueSend xQueueSend
+ * \ingroup QueueManagement
+ */
+BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
+ const void * const pvItemToQueue,
+ TickType_t xTicksToWait,
+ const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueuePeek(
+ * QueueHandle_t xQueue,
+ * void * const pvBuffer,
+ * TickType_t xTicksToWait
+ * );
+ * @endcode
+ *
+ * Receive an item from a queue without removing the item from the queue.
+ * The item is received by copy so a buffer of adequate size must be
+ * provided. The number of bytes copied into the buffer was defined when
+ * the queue was created.
+ *
+ * Successfully received items remain on the queue so will be returned again
+ * by the next call, or a call to xQueueReceive().
+ *
+ * This macro must not be used in an interrupt service routine. See
+ * xQueuePeekFromISR() for an alternative that can be called from an interrupt
+ * service routine.
+ *
+ * @param xQueue The handle to the queue from which the item is to be
+ * received.
+ *
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for an item to receive should the queue be empty at the time
+ * of the call. The time is defined in tick periods so the constant
+ * portTICK_PERIOD_MS should be used to convert to real time if this is required.
+ * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue
+ * is empty.
+ *
+ * @return pdTRUE if an item was successfully received from the queue,
+ * otherwise pdFALSE.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ * char ucMessageID;
+ * char ucData[ 20 ];
+ * } xMessage;
+ *
+ * QueueHandle_t xQueue;
+ *
+ * // Task to create a queue and post a value.
+ * void vATask( void *pvParameters )
+ * {
+ * struct AMessage *pxMessage;
+ *
+ * // Create a queue capable of containing 10 pointers to AMessage structures.
+ * // These should be passed by pointer as they contain a lot of data.
+ * xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ * if( xQueue == 0 )
+ * {
+ * // Failed to create the queue.
+ * }
+ *
+ * // ...
+ *
+ * // Send a pointer to a struct AMessage object. Don't block if the
+ * // queue is already full.
+ * pxMessage = & xMessage;
+ * xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+ *
+ * // ... Rest of task code.
+ * }
+ *
+ * // Task to peek the data from the queue.
+ * void vADifferentTask( void *pvParameters )
+ * {
+ * struct AMessage *pxRxedMessage;
+ *
+ * if( xQueue != 0 )
+ * {
+ * // Peek a message on the created queue. Block for 10 ticks if a
+ * // message is not immediately available.
+ * if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+ * {
+ * // pcRxedMessage now points to the struct AMessage variable posted
+ * // by vATask, but the item still remains on the queue.
+ * }
+ * }
+ *
+ * // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueuePeek xQueuePeek
+ * \ingroup QueueManagement
+ */
+BaseType_t xQueuePeek( QueueHandle_t xQueue,
+ void * const pvBuffer,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueuePeekFromISR(
+ * QueueHandle_t xQueue,
+ * void *pvBuffer,
+ * );
+ * @endcode
+ *
+ * A version of xQueuePeek() that can be called from an interrupt service
+ * routine (ISR).
+ *
+ * Receive an item from a queue without removing the item from the queue.
+ * The item is received by copy so a buffer of adequate size must be
+ * provided. The number of bytes copied into the buffer was defined when
+ * the queue was created.
+ *
+ * Successfully received items remain on the queue so will be returned again
+ * by the next call, or a call to xQueueReceive().
+ *
+ * @param xQueue The handle to the queue from which the item is to be
+ * received.
+ *
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
+ *
+ * @return pdTRUE if an item was successfully received from the queue,
+ * otherwise pdFALSE.
+ *
+ * \defgroup xQueuePeekFromISR xQueuePeekFromISR
+ * \ingroup QueueManagement
+ */
+BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
+ void * const pvBuffer ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueReceive(
+ * QueueHandle_t xQueue,
+ * void *pvBuffer,
+ * TickType_t xTicksToWait
+ * );
+ * @endcode
+ *
+ * Receive an item from a queue. The item is received by copy so a buffer of
+ * adequate size must be provided. The number of bytes copied into the buffer
+ * was defined when the queue was created.
+ *
+ * Successfully received items are removed from the queue.
+ *
+ * This function must not be used in an interrupt service routine. See
+ * xQueueReceiveFromISR for an alternative that can.
+ *
+ * @param xQueue The handle to the queue from which the item is to be
+ * received.
+ *
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
+ *
+ * @param xTicksToWait The maximum amount of time the task should block
+ * waiting for an item to receive should the queue be empty at the time
+ * of the call. xQueueReceive() will return immediately if xTicksToWait
+ * is zero and the queue is empty. The time is defined in tick periods so the
+ * constant portTICK_PERIOD_MS should be used to convert to real time if this is
+ * required.
+ *
+ * @return pdTRUE if an item was successfully received from the queue,
+ * otherwise pdFALSE.
+ *
+ * Example usage:
+ * @code{c}
+ * struct AMessage
+ * {
+ * char ucMessageID;
+ * char ucData[ 20 ];
+ * } xMessage;
+ *
+ * QueueHandle_t xQueue;
+ *
+ * // Task to create a queue and post a value.
+ * void vATask( void *pvParameters )
+ * {
+ * struct AMessage *pxMessage;
+ *
+ * // Create a queue capable of containing 10 pointers to AMessage structures.
+ * // These should be passed by pointer as they contain a lot of data.
+ * xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+ * if( xQueue == 0 )
+ * {
+ * // Failed to create the queue.
+ * }
+ *
+ * // ...
+ *
+ * // Send a pointer to a struct AMessage object. Don't block if the
+ * // queue is already full.
+ * pxMessage = & xMessage;
+ * xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+ *
+ * // ... Rest of task code.
+ * }
+ *
+ * // Task to receive from the queue.
+ * void vADifferentTask( void *pvParameters )
+ * {
+ * struct AMessage *pxRxedMessage;
+ *
+ * if( xQueue != 0 )
+ * {
+ * // Receive a message on the created queue. Block for 10 ticks if a
+ * // message is not immediately available.
+ * if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+ * {
+ * // pcRxedMessage now points to the struct AMessage variable posted
+ * // by vATask.
+ * }
+ * }
+ *
+ * // ... Rest of task code.
+ * }
+ * @endcode
+ * \defgroup xQueueReceive xQueueReceive
+ * \ingroup QueueManagement
+ */
+BaseType_t xQueueReceive( QueueHandle_t xQueue,
+ void * const pvBuffer,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ * @code{c}
+ * UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
+ * @endcode
+ *
+ * Return the number of messages stored in a queue.
+ *
+ * @param xQueue A handle to the queue being queried.
+ *
+ * @return The number of messages available in the queue.
+ *
+ * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting
+ * \ingroup QueueManagement
+ */
+UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ * @code{c}
+ * UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
+ * @endcode
+ *
+ * Return the number of free spaces available in a queue. This is equal to the
+ * number of items that can be sent to the queue before the queue becomes full
+ * if no items are removed.
+ *
+ * @param xQueue A handle to the queue being queried.
+ *
+ * @return The number of spaces available in the queue.
+ *
+ * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting
+ * \ingroup QueueManagement
+ */
+UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ * @code{c}
+ * void vQueueDelete( QueueHandle_t xQueue );
+ * @endcode
+ *
+ * Delete a queue - freeing all the memory allocated for storing of items
+ * placed on the queue.
+ *
+ * @param xQueue A handle to the queue to be deleted.
+ *
+ * \defgroup vQueueDelete vQueueDelete
+ * \ingroup QueueManagement
+ */
+void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueSendToFrontFromISR(
+ * QueueHandle_t xQueue,
+ * const void *pvItemToQueue,
+ * BaseType_t *pxHigherPriorityTaskWoken
+ * );
+ * @endcode
+ *
+ * This is a macro that calls xQueueGenericSendFromISR().
+ *
+ * Post an item to the front of a queue. It is safe to use this macro from
+ * within an interrupt service routine.
+ *
+ * Items are queued by copy not reference so it is preferable to only
+ * queue small items, especially when called from an ISR. In most cases
+ * it would be preferable to store a pointer to the item being queued.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the data was successfully sent to the queue, otherwise
+ * errQUEUE_FULL.
+ *
+ * Example usage for buffered IO (where the ISR can obtain more than one value
+ * per call):
+ * @code{c}
+ * void vBufferISR( void )
+ * {
+ * char cIn;
+ * BaseType_t xHigherPriorityTaskWoken;
+ *
+ * // We have not woken a task at the start of the ISR.
+ * xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // Loop until the buffer is empty.
+ * do
+ * {
+ * // Obtain a byte from the buffer.
+ * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+ *
+ * // Post the byte.
+ * xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+ *
+ * } while( portINPUT_BYTE( BUFFER_COUNT ) );
+ *
+ * // Now the buffer is empty we can switch context if necessary.
+ * if( xHigherPriorityTaskWoken )
+ * {
+ * taskYIELD ();
+ * }
+ * }
+ * @endcode
+ *
+ * \defgroup xQueueSendFromISR xQueueSendFromISR
+ * \ingroup QueueManagement
+ */
+#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
+ xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT )
+
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueSendToBackFromISR(
+ * QueueHandle_t xQueue,
+ * const void *pvItemToQueue,
+ * BaseType_t *pxHigherPriorityTaskWoken
+ * );
+ * @endcode
+ *
+ * This is a macro that calls xQueueGenericSendFromISR().
+ *
+ * Post an item to the back of a queue. It is safe to use this macro from
+ * within an interrupt service routine.
+ *
+ * Items are queued by copy not reference so it is preferable to only
+ * queue small items, especially when called from an ISR. In most cases
+ * it would be preferable to store a pointer to the item being queued.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the data was successfully sent to the queue, otherwise
+ * errQUEUE_FULL.
+ *
+ * Example usage for buffered IO (where the ISR can obtain more than one value
+ * per call):
+ * @code{c}
+ * void vBufferISR( void )
+ * {
+ * char cIn;
+ * BaseType_t xHigherPriorityTaskWoken;
+ *
+ * // We have not woken a task at the start of the ISR.
+ * xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // Loop until the buffer is empty.
+ * do
+ * {
+ * // Obtain a byte from the buffer.
+ * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+ *
+ * // Post the byte.
+ * xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+ *
+ * } while( portINPUT_BYTE( BUFFER_COUNT ) );
+ *
+ * // Now the buffer is empty we can switch context if necessary.
+ * if( xHigherPriorityTaskWoken )
+ * {
+ * taskYIELD ();
+ * }
+ * }
+ * @endcode
+ *
+ * \defgroup xQueueSendFromISR xQueueSendFromISR
+ * \ingroup QueueManagement
+ */
+#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
+ xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueOverwriteFromISR(
+ * QueueHandle_t xQueue,
+ * const void * pvItemToQueue,
+ * BaseType_t *pxHigherPriorityTaskWoken
+ * );
+ * @endcode
+ *
+ * A version of xQueueOverwrite() that can be used in an interrupt service
+ * routine (ISR).
+ *
+ * Only for use with queues that can hold a single item - so the queue is either
+ * empty or full.
+ *
+ * Post an item on a queue. If the queue is already full then overwrite the
+ * value held in the queue. The item is queued by copy, not by reference.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xQueueOverwriteFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return xQueueOverwriteFromISR() is a macro that calls
+ * xQueueGenericSendFromISR(), and therefore has the same return values as
+ * xQueueSendToFrontFromISR(). However, pdPASS is the only value that can be
+ * returned because xQueueOverwriteFromISR() will write to the queue even when
+ * the queue is already full.
+ *
+ * Example usage:
+ * @code{c}
+ *
+ * QueueHandle_t xQueue;
+ *
+ * void vFunction( void *pvParameters )
+ * {
+ * // Create a queue to hold one uint32_t value. It is strongly
+ * // recommended *not* to use xQueueOverwriteFromISR() on queues that can
+ * // contain more than one value, and doing so will trigger an assertion
+ * // if configASSERT() is defined.
+ * xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
+ * }
+ *
+ * void vAnInterruptHandler( void )
+ * {
+ * // xHigherPriorityTaskWoken must be set to pdFALSE before it is used.
+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ * uint32_t ulVarToSend, ulValReceived;
+ *
+ * // Write the value 10 to the queue using xQueueOverwriteFromISR().
+ * ulVarToSend = 10;
+ * xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+ *
+ * // The queue is full, but calling xQueueOverwriteFromISR() again will still
+ * // pass because the value held in the queue will be overwritten with the
+ * // new value.
+ * ulVarToSend = 100;
+ * xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+ *
+ * // Reading from the queue will now return 100.
+ *
+ * // ...
+ *
+ * if( xHigherPrioritytaskWoken == pdTRUE )
+ * {
+ * // Writing to the queue caused a task to unblock and the unblocked task
+ * // has a priority higher than or equal to the priority of the currently
+ * // executing task (the task this interrupt interrupted). Perform a context
+ * // switch so this interrupt returns directly to the unblocked task.
+ * portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port.
+ * }
+ * }
+ * @endcode
+ * \defgroup xQueueOverwriteFromISR xQueueOverwriteFromISR
+ * \ingroup QueueManagement
+ */
+#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
+ xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE )
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueSendFromISR(
+ * QueueHandle_t xQueue,
+ * const void *pvItemToQueue,
+ * BaseType_t *pxHigherPriorityTaskWoken
+ * );
+ * @endcode
+ *
+ * This is a macro that calls xQueueGenericSendFromISR(). It is included
+ * for backward compatibility with versions of FreeRTOS.org that did not
+ * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR()
+ * macros.
+ *
+ * Post an item to the back of a queue. It is safe to use this function from
+ * within an interrupt service routine.
+ *
+ * Items are queued by copy not reference so it is preferable to only
+ * queue small items, especially when called from an ISR. In most cases
+ * it would be preferable to store a pointer to the item being queued.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xQueueSendFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the data was successfully sent to the queue, otherwise
+ * errQUEUE_FULL.
+ *
+ * Example usage for buffered IO (where the ISR can obtain more than one value
+ * per call):
+ * @code{c}
+ * void vBufferISR( void )
+ * {
+ * char cIn;
+ * BaseType_t xHigherPriorityTaskWoken;
+ *
+ * // We have not woken a task at the start of the ISR.
+ * xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // Loop until the buffer is empty.
+ * do
+ * {
+ * // Obtain a byte from the buffer.
+ * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+ *
+ * // Post the byte.
+ * xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+ *
+ * } while( portINPUT_BYTE( BUFFER_COUNT ) );
+ *
+ * // Now the buffer is empty we can switch context if necessary.
+ * if( xHigherPriorityTaskWoken )
+ * {
+ * // Actual macro used here is port specific.
+ * portYIELD_FROM_ISR ();
+ * }
+ * }
+ * @endcode
+ *
+ * \defgroup xQueueSendFromISR xQueueSendFromISR
+ * \ingroup QueueManagement
+ */
+#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
+ xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueGenericSendFromISR(
+ * QueueHandle_t xQueue,
+ * const void *pvItemToQueue,
+ * BaseType_t *pxHigherPriorityTaskWoken,
+ * BaseType_t xCopyPosition
+ * );
+ * @endcode
+ *
+ * It is preferred that the macros xQueueSendFromISR(),
+ * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place
+ * of calling this function directly. xQueueGiveFromISR() is an
+ * equivalent for use by semaphores that don't actually copy any data.
+ *
+ * Post an item on a queue. It is safe to use this function from within an
+ * interrupt service routine.
+ *
+ * Items are queued by copy not reference so it is preferable to only
+ * queue small items, especially when called from an ISR. In most cases
+ * it would be preferable to store a pointer to the item being queued.
+ *
+ * @param xQueue The handle to the queue on which the item is to be posted.
+ *
+ * @param pvItemToQueue A pointer to the item that is to be placed on the
+ * queue. The size of the items the queue will hold was defined when the
+ * queue was created, so this many bytes will be copied from pvItemToQueue
+ * into the queue storage area.
+ *
+ * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the
+ * item at the back of the queue, or queueSEND_TO_FRONT to place the item
+ * at the front of the queue (for high priority messages).
+ *
+ * @return pdTRUE if the data was successfully sent to the queue, otherwise
+ * errQUEUE_FULL.
+ *
+ * Example usage for buffered IO (where the ISR can obtain more than one value
+ * per call):
+ * @code{c}
+ * void vBufferISR( void )
+ * {
+ * char cIn;
+ * BaseType_t xHigherPriorityTaskWokenByPost;
+ *
+ * // We have not woken a task at the start of the ISR.
+ * xHigherPriorityTaskWokenByPost = pdFALSE;
+ *
+ * // Loop until the buffer is empty.
+ * do
+ * {
+ * // Obtain a byte from the buffer.
+ * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+ *
+ * // Post each byte.
+ * xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
+ *
+ * } while( portINPUT_BYTE( BUFFER_COUNT ) );
+ *
+ * // Now the buffer is empty we can switch context if necessary. Note that the
+ * // name of the yield function required is port specific.
+ * if( xHigherPriorityTaskWokenByPost )
+ * {
+ * portYIELD_FROM_ISR();
+ * }
+ * }
+ * @endcode
+ *
+ * \defgroup xQueueSendFromISR xQueueSendFromISR
+ * \ingroup QueueManagement
+ */
+BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
+ const void * const pvItemToQueue,
+ BaseType_t * const pxHigherPriorityTaskWoken,
+ const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
+ BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+
+/**
+ * queue. h
+ * @code{c}
+ * BaseType_t xQueueReceiveFromISR(
+ * QueueHandle_t xQueue,
+ * void *pvBuffer,
+ * BaseType_t *pxTaskWoken
+ * );
+ * @endcode
+ *
+ * Receive an item from a queue. It is safe to use this function from within an
+ * interrupt service routine.
+ *
+ * @param xQueue The handle to the queue from which the item is to be
+ * received.
+ *
+ * @param pvBuffer Pointer to the buffer into which the received item will
+ * be copied.
+ *
+ * @param pxTaskWoken A task may be blocked waiting for space to become
+ * available on the queue. If xQueueReceiveFromISR causes such a task to
+ * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will
+ * remain unchanged.
+ *
+ * @return pdTRUE if an item was successfully received from the queue,
+ * otherwise pdFALSE.
+ *
+ * Example usage:
+ * @code{c}
+ *
+ * QueueHandle_t xQueue;
+ *
+ * // Function to create a queue and post some values.
+ * void vAFunction( void *pvParameters )
+ * {
+ * char cValueToPost;
+ * const TickType_t xTicksToWait = ( TickType_t )0xff;
+ *
+ * // Create a queue capable of containing 10 characters.
+ * xQueue = xQueueCreate( 10, sizeof( char ) );
+ * if( xQueue == 0 )
+ * {
+ * // Failed to create the queue.
+ * }
+ *
+ * // ...
+ *
+ * // Post some characters that will be used within an ISR. If the queue
+ * // is full then this task will block for xTicksToWait ticks.
+ * cValueToPost = 'a';
+ * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+ * cValueToPost = 'b';
+ * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+ *
+ * // ... keep posting characters ... this task may block when the queue
+ * // becomes full.
+ *
+ * cValueToPost = 'c';
+ * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+ * }
+ *
+ * // ISR that outputs all the characters received on the queue.
+ * void vISR_Routine( void )
+ * {
+ * BaseType_t xTaskWokenByReceive = pdFALSE;
+ * char cRxedChar;
+ *
+ * while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+ * {
+ * // A character was received. Output the character now.
+ * vOutputCharacter( cRxedChar );
+ *
+ * // If removing the character from the queue woke the task that was
+ * // posting onto the queue xTaskWokenByReceive will have been set to
+ * // pdTRUE. No matter how many times this loop iterates only one
+ * // task will be woken.
+ * }
+ *
+ * if( xTaskWokenByReceive != ( char ) pdFALSE;
+ * {
+ * taskYIELD ();
+ * }
+ * }
+ * @endcode
+ * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR
+ * \ingroup QueueManagement
+ */
+BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
+ void * const pvBuffer,
+ BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+
+/*
+ * Utilities to query queues that are safe to use from an ISR. These utilities
+ * should be used only from within an ISR, or within a critical section.
+ */
+BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * The functions defined above are for passing data to and from tasks. The
+ * functions below are the equivalents for passing data to and from
+ * co-routines.
+ *
+ * These functions are called from the co-routine macro implementation and
+ * should not be called directly from application code. Instead use the macro
+ * wrappers defined within croutine.h.
+ */
+BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue,
+ const void * pvItemToQueue,
+ BaseType_t xCoRoutinePreviouslyWoken );
+BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue,
+ void * pvBuffer,
+ BaseType_t * pxTaskWoken );
+BaseType_t xQueueCRSend( QueueHandle_t xQueue,
+ const void * pvItemToQueue,
+ TickType_t xTicksToWait );
+BaseType_t xQueueCRReceive( QueueHandle_t xQueue,
+ void * pvBuffer,
+ TickType_t xTicksToWait );
+
+/*
+ * For internal use only. Use xSemaphoreCreateMutex(),
+ * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling
+ * these functions directly.
+ */
+QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType,
+ StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION;
+QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
+ const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION;
+QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
+ const UBaseType_t uxInitialCount,
+ StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
+TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
+
+/*
+ * For internal use only. Use xSemaphoreTakeMutexRecursive() or
+ * xSemaphoreGiveMutexRecursive() instead of calling these functions directly.
+ */
+BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION;
+
+/*
+ * Reset a queue back to its original empty state. The return value is now
+ * obsolete and is always set to pdPASS.
+ */
+#define xQueueReset( xQueue ) xQueueGenericReset( ( xQueue ), pdFALSE )
+
+/*
+ * The registry is provided as a means for kernel aware debuggers to
+ * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add
+ * a queue, semaphore or mutex handle to the registry if you want the handle
+ * to be available to a kernel aware debugger. If you are not using a kernel
+ * aware debugger then this function can be ignored.
+ *
+ * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the
+ * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0
+ * within FreeRTOSConfig.h for the registry to be available. Its value
+ * does not affect the number of queues, semaphores and mutexes that can be
+ * created - just the number that the registry can hold.
+ *
+ * If vQueueAddToRegistry is called more than once with the same xQueue
+ * parameter, the registry will store the pcQueueName parameter from the
+ * most recent call to vQueueAddToRegistry.
+ *
+ * @param xQueue The handle of the queue being added to the registry. This
+ * is the handle returned by a call to xQueueCreate(). Semaphore and mutex
+ * handles can also be passed in here.
+ *
+ * @param pcQueueName The name to be associated with the handle. This is the
+ * name that the kernel aware debugger will display. The queue registry only
+ * stores a pointer to the string - so the string must be persistent (global or
+ * preferably in ROM/Flash), not on the stack.
+ */
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+ void vQueueAddToRegistry( QueueHandle_t xQueue,
+ const char * pcQueueName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+#endif
+
+/*
+ * The registry is provided as a means for kernel aware debuggers to
+ * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add
+ * a queue, semaphore or mutex handle to the registry if you want the handle
+ * to be available to a kernel aware debugger, and vQueueUnregisterQueue() to
+ * remove the queue, semaphore or mutex from the register. If you are not using
+ * a kernel aware debugger then this function can be ignored.
+ *
+ * @param xQueue The handle of the queue being removed from the registry.
+ */
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+ void vQueueUnregisterQueue( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * The queue registry is provided as a means for kernel aware debuggers to
+ * locate queues, semaphores and mutexes. Call pcQueueGetName() to look
+ * up and return the name of a queue in the queue registry from the queue's
+ * handle.
+ *
+ * @param xQueue The handle of the queue the name of which will be returned.
+ * @return If the queue is in the registry then a pointer to the name of the
+ * queue is returned. If the queue is not in the registry then NULL is
+ * returned.
+ */
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+ const char * pcQueueGetName( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+#endif
+
+/*
+ * Generic version of the function used to create a queue using dynamic memory
+ * allocation. This is called by other functions and macros that create other
+ * RTOS objects that use the queue structure as their base.
+ */
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
+ const UBaseType_t uxItemSize,
+ const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * Generic version of the function used to create a queue using dynamic memory
+ * allocation. This is called by other functions and macros that create other
+ * RTOS objects that use the queue structure as their base.
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
+ const UBaseType_t uxItemSize,
+ uint8_t * pucQueueStorage,
+ StaticQueue_t * pxStaticQueue,
+ const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * Queue sets provide a mechanism to allow a task to block (pend) on a read
+ * operation from multiple queues or semaphores simultaneously.
+ *
+ * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
+ * function.
+ *
+ * A queue set must be explicitly created using a call to xQueueCreateSet()
+ * before it can be used. Once created, standard FreeRTOS queues and semaphores
+ * can be added to the set using calls to xQueueAddToSet().
+ * xQueueSelectFromSet() is then used to determine which, if any, of the queues
+ * or semaphores contained in the set is in a state where a queue read or
+ * semaphore take operation would be successful.
+ *
+ * Note 1: See the documentation on https://www.FreeRTOS.org/RTOS-queue-sets.html
+ * for reasons why queue sets are very rarely needed in practice as there are
+ * simpler methods of blocking on multiple objects.
+ *
+ * Note 2: Blocking on a queue set that contains a mutex will not cause the
+ * mutex holder to inherit the priority of the blocked task.
+ *
+ * Note 3: An additional 4 bytes of RAM is required for each space in a every
+ * queue added to a queue set. Therefore counting semaphores that have a high
+ * maximum count value should not be added to a queue set.
+ *
+ * Note 4: A receive (in the case of a queue) or take (in the case of a
+ * semaphore) operation must not be performed on a member of a queue set unless
+ * a call to xQueueSelectFromSet() has first returned a handle to that set member.
+ *
+ * @param uxEventQueueLength Queue sets store events that occur on
+ * the queues and semaphores contained in the set. uxEventQueueLength specifies
+ * the maximum number of events that can be queued at once. To be absolutely
+ * certain that events are not lost uxEventQueueLength should be set to the
+ * total sum of the length of the queues added to the set, where binary
+ * semaphores and mutexes have a length of 1, and counting semaphores have a
+ * length set by their maximum count value. Examples:
+ * + If a queue set is to hold a queue of length 5, another queue of length 12,
+ * and a binary semaphore, then uxEventQueueLength should be set to
+ * (5 + 12 + 1), or 18.
+ * + If a queue set is to hold three binary semaphores then uxEventQueueLength
+ * should be set to (1 + 1 + 1 ), or 3.
+ * + If a queue set is to hold a counting semaphore that has a maximum count of
+ * 5, and a counting semaphore that has a maximum count of 3, then
+ * uxEventQueueLength should be set to (5 + 3), or 8.
+ *
+ * @return If the queue set is created successfully then a handle to the created
+ * queue set is returned. Otherwise NULL is returned.
+ */
+QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION;
+
+/*
+ * Adds a queue or semaphore to a queue set that was previously created by a
+ * call to xQueueCreateSet().
+ *
+ * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
+ * function.
+ *
+ * Note 1: A receive (in the case of a queue) or take (in the case of a
+ * semaphore) operation must not be performed on a member of a queue set unless
+ * a call to xQueueSelectFromSet() has first returned a handle to that set member.
+ *
+ * @param xQueueOrSemaphore The handle of the queue or semaphore being added to
+ * the queue set (cast to an QueueSetMemberHandle_t type).
+ *
+ * @param xQueueSet The handle of the queue set to which the queue or semaphore
+ * is being added.
+ *
+ * @return If the queue or semaphore was successfully added to the queue set
+ * then pdPASS is returned. If the queue could not be successfully added to the
+ * queue set because it is already a member of a different queue set then pdFAIL
+ * is returned.
+ */
+BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
+ QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
+
+/*
+ * Removes a queue or semaphore from a queue set. A queue or semaphore can only
+ * be removed from a set if the queue or semaphore is empty.
+ *
+ * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
+ * function.
+ *
+ * @param xQueueOrSemaphore The handle of the queue or semaphore being removed
+ * from the queue set (cast to an QueueSetMemberHandle_t type).
+ *
+ * @param xQueueSet The handle of the queue set in which the queue or semaphore
+ * is included.
+ *
+ * @return If the queue or semaphore was successfully removed from the queue set
+ * then pdPASS is returned. If the queue was not in the queue set, or the
+ * queue (or semaphore) was not empty, then pdFAIL is returned.
+ */
+BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
+ QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
+
+/*
+ * xQueueSelectFromSet() selects from the members of a queue set a queue or
+ * semaphore that either contains data (in the case of a queue) or is available
+ * to take (in the case of a semaphore). xQueueSelectFromSet() effectively
+ * allows a task to block (pend) on a read operation on all the queues and
+ * semaphores in a queue set simultaneously.
+ *
+ * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this
+ * function.
+ *
+ * Note 1: See the documentation on https://www.FreeRTOS.org/RTOS-queue-sets.html
+ * for reasons why queue sets are very rarely needed in practice as there are
+ * simpler methods of blocking on multiple objects.
+ *
+ * Note 2: Blocking on a queue set that contains a mutex will not cause the
+ * mutex holder to inherit the priority of the blocked task.
+ *
+ * Note 3: A receive (in the case of a queue) or take (in the case of a
+ * semaphore) operation must not be performed on a member of a queue set unless
+ * a call to xQueueSelectFromSet() has first returned a handle to that set member.
+ *
+ * @param xQueueSet The queue set on which the task will (potentially) block.
+ *
+ * @param xTicksToWait The maximum time, in ticks, that the calling task will
+ * remain in the Blocked state (with other tasks executing) to wait for a member
+ * of the queue set to be ready for a successful queue read or semaphore take
+ * operation.
+ *
+ * @return xQueueSelectFromSet() will return the handle of a queue (cast to
+ * a QueueSetMemberHandle_t type) contained in the queue set that contains data,
+ * or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained
+ * in the queue set that is available, or NULL if no such queue or semaphore
+ * exists before before the specified block time expires.
+ */
+QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
+ const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/*
+ * A version of xQueueSelectFromSet() that can be used from an ISR.
+ */
+QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
+
+/* Not public API functions. */
+void vQueueWaitForMessageRestricted( QueueHandle_t xQueue,
+ TickType_t xTicksToWait,
+ const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION;
+BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
+ BaseType_t xNewQueue ) PRIVILEGED_FUNCTION;
+void vQueueSetQueueNumber( QueueHandle_t xQueue,
+ UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION;
+UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
+
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ }
+#endif
+/* *INDENT-ON* */
+
+#endif /* QUEUE_H */
diff --git a/source/test/freertos/inc/semphr.h b/source/test/freertos/inc/semphr.h
new file mode 100644
index 0000000..d3165d8
--- /dev/null
+++ b/source/test/freertos/inc/semphr.h
@@ -0,0 +1,1193 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef SEMAPHORE_H
+#define SEMAPHORE_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h" must appear in source files before "include semphr.h"
+#endif
+
+#include "queue.h"
+
+typedef QueueHandle_t SemaphoreHandle_t;
+
+#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U )
+#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U )
+#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U )
+
+
+/**
+ * semphr. h
+ * @code{c}
+ * vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore );
+ * @endcode
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a binary semaphore!
+ * https://www.FreeRTOS.org/RTOS-task-notifications.html
+ *
+ * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the
+ * xSemaphoreCreateBinary() function. Note that binary semaphores created using
+ * the vSemaphoreCreateBinary() macro are created in a state such that the
+ * first call to 'take' the semaphore would pass, whereas binary semaphores
+ * created using xSemaphoreCreateBinary() are created in a state such that the
+ * the semaphore must first be 'given' before it can be 'taken'.
+ *
+ * Macro that implements a semaphore by using the existing queue mechanism.
+ * The queue length is 1 as this is a binary semaphore. The data size is 0
+ * as we don't want to actually store any data - we just want to know if the
+ * queue is empty or full.
+ *
+ * This type of semaphore can be used for pure synchronisation between tasks or
+ * between an interrupt and a task. The semaphore need not be given back once
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while
+ * another continuously 'takes' the semaphore. For this reason this type of
+ * semaphore does not use a priority inheritance mechanism. For an alternative
+ * that does use priority inheritance see xSemaphoreCreateMutex().
+ *
+ * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore = NULL;
+ *
+ * void vATask( void * pvParameters )
+ * {
+ * // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+ * // This is a macro so pass the variable in directly.
+ * vSemaphoreCreateBinary( xSemaphore );
+ *
+ * if( xSemaphore != NULL )
+ * {
+ * // The semaphore was created successfully.
+ * // The semaphore can now be used.
+ * }
+ * }
+ * @endcode
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
+ * \ingroup Semaphores
+ */
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define vSemaphoreCreateBinary( xSemaphore ) \
+ { \
+ ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \
+ if( ( xSemaphore ) != NULL ) \
+ { \
+ ( void ) xSemaphoreGive( ( xSemaphore ) ); \
+ } \
+ }
+#endif
+
+/**
+ * semphr. h
+ * @code{c}
+ * SemaphoreHandle_t xSemaphoreCreateBinary( void );
+ * @endcode
+ *
+ * Creates a new binary semaphore instance, and returns a handle by which the
+ * new semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a binary semaphore!
+ * https://www.FreeRTOS.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, binary semaphores use a block
+ * of memory, in which the semaphore structure is stored. If a binary semaphore
+ * is created using xSemaphoreCreateBinary() then the required memory is
+ * automatically dynamically allocated inside the xSemaphoreCreateBinary()
+ * function. (see https://www.FreeRTOS.org/a00111.html). If a binary semaphore
+ * is created using xSemaphoreCreateBinaryStatic() then the application writer
+ * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a
+ * binary semaphore to be created without using any dynamic memory allocation.
+ *
+ * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this
+ * xSemaphoreCreateBinary() function. Note that binary semaphores created using
+ * the vSemaphoreCreateBinary() macro are created in a state such that the
+ * first call to 'take' the semaphore would pass, whereas binary semaphores
+ * created using xSemaphoreCreateBinary() are created in a state such that the
+ * the semaphore must first be 'given' before it can be 'taken'.
+ *
+ * This type of semaphore can be used for pure synchronisation between tasks or
+ * between an interrupt and a task. The semaphore need not be given back once
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while
+ * another continuously 'takes' the semaphore. For this reason this type of
+ * semaphore does not use a priority inheritance mechanism. For an alternative
+ * that does use priority inheritance see xSemaphoreCreateMutex().
+ *
+ * @return Handle to the created semaphore, or NULL if the memory required to
+ * hold the semaphore's data structures could not be allocated.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore = NULL;
+ *
+ * void vATask( void * pvParameters )
+ * {
+ * // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
+ * // This is a macro so pass the variable in directly.
+ * xSemaphore = xSemaphoreCreateBinary();
+ *
+ * if( xSemaphore != NULL )
+ * {
+ * // The semaphore was created successfully.
+ * // The semaphore can now be used.
+ * }
+ * }
+ * @endcode
+ * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary
+ * \ingroup Semaphores
+ */
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#endif
+
+/**
+ * semphr. h
+ * @code{c}
+ * SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer );
+ * @endcode
+ *
+ * Creates a new binary semaphore instance, and returns a handle by which the
+ * new semaphore can be referenced.
+ *
+ * NOTE: In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a binary semaphore!
+ * https://www.FreeRTOS.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, binary semaphores use a block
+ * of memory, in which the semaphore structure is stored. If a binary semaphore
+ * is created using xSemaphoreCreateBinary() then the required memory is
+ * automatically dynamically allocated inside the xSemaphoreCreateBinary()
+ * function. (see https://www.FreeRTOS.org/a00111.html). If a binary semaphore
+ * is created using xSemaphoreCreateBinaryStatic() then the application writer
+ * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a
+ * binary semaphore to be created without using any dynamic memory allocation.
+ *
+ * This type of semaphore can be used for pure synchronisation between tasks or
+ * between an interrupt and a task. The semaphore need not be given back once
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while
+ * another continuously 'takes' the semaphore. For this reason this type of
+ * semaphore does not use a priority inheritance mechanism. For an alternative
+ * that does use priority inheritance see xSemaphoreCreateMutex().
+ *
+ * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the semaphore's data structure, removing the
+ * need for the memory to be allocated dynamically.
+ *
+ * @return If the semaphore is created then a handle to the created semaphore is
+ * returned. If pxSemaphoreBuffer is NULL then NULL is returned.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore = NULL;
+ * StaticSemaphore_t xSemaphoreBuffer;
+ *
+ * void vATask( void * pvParameters )
+ * {
+ * // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
+ * // The semaphore's data structures will be placed in the xSemaphoreBuffer
+ * // variable, the address of which is passed into the function. The
+ * // function's parameter is not NULL, so the function will not attempt any
+ * // dynamic memory allocation, and therefore the function will not return
+ * // return NULL.
+ * xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer );
+ *
+ * // Rest of task code goes here.
+ * }
+ * @endcode
+ * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic
+ * \ingroup Semaphores
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, ( pxStaticSemaphore ), queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+/**
+ * semphr. h
+ * @code{c}
+ * xSemaphoreTake(
+ * SemaphoreHandle_t xSemaphore,
+ * TickType_t xBlockTime
+ * );
+ * @endcode
+ *
+ * Macro to obtain a semaphore. The semaphore must have previously been
+ * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
+ * xSemaphoreCreateCounting().
+ *
+ * @param xSemaphore A handle to the semaphore being taken - obtained when
+ * the semaphore was created.
+ *
+ * @param xBlockTime The time in ticks to wait for the semaphore to become
+ * available. The macro portTICK_PERIOD_MS can be used to convert this to a
+ * real time. A block time of zero can be used to poll the semaphore. A block
+ * time of portMAX_DELAY can be used to block indefinitely (provided
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).
+ *
+ * @return pdTRUE if the semaphore was obtained. pdFALSE
+ * if xBlockTime expired without the semaphore becoming available.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore = NULL;
+ *
+ * // A task that creates a semaphore.
+ * void vATask( void * pvParameters )
+ * {
+ * // Create the semaphore to guard a shared resource.
+ * xSemaphore = xSemaphoreCreateBinary();
+ * }
+ *
+ * // A task that uses the semaphore.
+ * void vAnotherTask( void * pvParameters )
+ * {
+ * // ... Do other things.
+ *
+ * if( xSemaphore != NULL )
+ * {
+ * // See if we can obtain the semaphore. If the semaphore is not available
+ * // wait 10 ticks to see if it becomes free.
+ * if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+ * {
+ * // We were able to obtain the semaphore and can now access the
+ * // shared resource.
+ *
+ * // ...
+ *
+ * // We have finished accessing the shared resource. Release the
+ * // semaphore.
+ * xSemaphoreGive( xSemaphore );
+ * }
+ * else
+ * {
+ * // We could not obtain the semaphore and can therefore not access
+ * // the shared resource safely.
+ * }
+ * }
+ * }
+ * @endcode
+ * \defgroup xSemaphoreTake xSemaphoreTake
+ * \ingroup Semaphores
+ */
+#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )
+
+/**
+ * semphr. h
+ * @code{c}
+ * xSemaphoreTakeRecursive(
+ * SemaphoreHandle_t xMutex,
+ * TickType_t xBlockTime
+ * );
+ * @endcode
+ *
+ * Macro to recursively obtain, or 'take', a mutex type semaphore.
+ * The mutex must have previously been created using a call to
+ * xSemaphoreCreateRecursiveMutex();
+ *
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
+ * macro to be available.
+ *
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
+ * exactly five times.
+ *
+ * @param xMutex A handle to the mutex being obtained. This is the
+ * handle returned by xSemaphoreCreateRecursiveMutex();
+ *
+ * @param xBlockTime The time in ticks to wait for the semaphore to become
+ * available. The macro portTICK_PERIOD_MS can be used to convert this to a
+ * real time. A block time of zero can be used to poll the semaphore. If
+ * the task already owns the semaphore then xSemaphoreTakeRecursive() will
+ * return immediately no matter what the value of xBlockTime.
+ *
+ * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime
+ * expired without the semaphore becoming available.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xMutex = NULL;
+ *
+ * // A task that creates a mutex.
+ * void vATask( void * pvParameters )
+ * {
+ * // Create the mutex to guard a shared resource.
+ * xMutex = xSemaphoreCreateRecursiveMutex();
+ * }
+ *
+ * // A task that uses the mutex.
+ * void vAnotherTask( void * pvParameters )
+ * {
+ * // ... Do other things.
+ *
+ * if( xMutex != NULL )
+ * {
+ * // See if we can obtain the mutex. If the mutex is not available
+ * // wait 10 ticks to see if it becomes free.
+ * if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+ * {
+ * // We were able to obtain the mutex and can now access the
+ * // shared resource.
+ *
+ * // ...
+ * // For some reason due to the nature of the code further calls to
+ * // xSemaphoreTakeRecursive() are made on the same mutex. In real
+ * // code these would not be just sequential calls as this would make
+ * // no sense. Instead the calls are likely to be buried inside
+ * // a more complex call structure.
+ * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+ * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+ *
+ * // The mutex has now been 'taken' three times, so will not be
+ * // available to another task until it has also been given back
+ * // three times. Again it is unlikely that real code would have
+ * // these calls sequentially, but instead buried in a more complex
+ * // call structure. This is just for illustrative purposes.
+ * xSemaphoreGiveRecursive( xMutex );
+ * xSemaphoreGiveRecursive( xMutex );
+ * xSemaphoreGiveRecursive( xMutex );
+ *
+ * // Now the mutex can be taken by other tasks.
+ * }
+ * else
+ * {
+ * // We could not obtain the mutex and can therefore not access
+ * // the shared resource safely.
+ * }
+ * }
+ * }
+ * @endcode
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive
+ * \ingroup Semaphores
+ */
+#if ( configUSE_RECURSIVE_MUTEXES == 1 )
+ #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
+#endif
+
+/**
+ * semphr. h
+ * @code{c}
+ * xSemaphoreGive( SemaphoreHandle_t xSemaphore );
+ * @endcode
+ *
+ * Macro to release a semaphore. The semaphore must have previously been
+ * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
+ * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake().
+ *
+ * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for
+ * an alternative which can be used from an ISR.
+ *
+ * This macro must also not be used on semaphores created using
+ * xSemaphoreCreateRecursiveMutex().
+ *
+ * @param xSemaphore A handle to the semaphore being released. This is the
+ * handle returned when the semaphore was created.
+ *
+ * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred.
+ * Semaphores are implemented using queues. An error can occur if there is
+ * no space on the queue to post a message - indicating that the
+ * semaphore was not first obtained correctly.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore = NULL;
+ *
+ * void vATask( void * pvParameters )
+ * {
+ * // Create the semaphore to guard a shared resource.
+ * xSemaphore = vSemaphoreCreateBinary();
+ *
+ * if( xSemaphore != NULL )
+ * {
+ * if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+ * {
+ * // We would expect this call to fail because we cannot give
+ * // a semaphore without first "taking" it!
+ * }
+ *
+ * // Obtain the semaphore - don't block if the semaphore is not
+ * // immediately available.
+ * if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) )
+ * {
+ * // We now have the semaphore and can access the shared resource.
+ *
+ * // ...
+ *
+ * // We have finished accessing the shared resource so can free the
+ * // semaphore.
+ * if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+ * {
+ * // We would not expect this call to fail because we must have
+ * // obtained the semaphore to get here.
+ * }
+ * }
+ * }
+ * }
+ * @endcode
+ * \defgroup xSemaphoreGive xSemaphoreGive
+ * \ingroup Semaphores
+ */
+#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
+
+/**
+ * semphr. h
+ * @code{c}
+ * xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex );
+ * @endcode
+ *
+ * Macro to recursively release, or 'give', a mutex type semaphore.
+ * The mutex must have previously been created using a call to
+ * xSemaphoreCreateRecursiveMutex();
+ *
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
+ * macro to be available.
+ *
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
+ * exactly five times.
+ *
+ * @param xMutex A handle to the mutex being released, or 'given'. This is the
+ * handle returned by xSemaphoreCreateMutex();
+ *
+ * @return pdTRUE if the semaphore was given.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xMutex = NULL;
+ *
+ * // A task that creates a mutex.
+ * void vATask( void * pvParameters )
+ * {
+ * // Create the mutex to guard a shared resource.
+ * xMutex = xSemaphoreCreateRecursiveMutex();
+ * }
+ *
+ * // A task that uses the mutex.
+ * void vAnotherTask( void * pvParameters )
+ * {
+ * // ... Do other things.
+ *
+ * if( xMutex != NULL )
+ * {
+ * // See if we can obtain the mutex. If the mutex is not available
+ * // wait 10 ticks to see if it becomes free.
+ * if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE )
+ * {
+ * // We were able to obtain the mutex and can now access the
+ * // shared resource.
+ *
+ * // ...
+ * // For some reason due to the nature of the code further calls to
+ * // xSemaphoreTakeRecursive() are made on the same mutex. In real
+ * // code these would not be just sequential calls as this would make
+ * // no sense. Instead the calls are likely to be buried inside
+ * // a more complex call structure.
+ * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+ * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+ *
+ * // The mutex has now been 'taken' three times, so will not be
+ * // available to another task until it has also been given back
+ * // three times. Again it is unlikely that real code would have
+ * // these calls sequentially, it would be more likely that the calls
+ * // to xSemaphoreGiveRecursive() would be called as a call stack
+ * // unwound. This is just for demonstrative purposes.
+ * xSemaphoreGiveRecursive( xMutex );
+ * xSemaphoreGiveRecursive( xMutex );
+ * xSemaphoreGiveRecursive( xMutex );
+ *
+ * // Now the mutex can be taken by other tasks.
+ * }
+ * else
+ * {
+ * // We could not obtain the mutex and can therefore not access
+ * // the shared resource safely.
+ * }
+ * }
+ * }
+ * @endcode
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive
+ * \ingroup Semaphores
+ */
+#if ( configUSE_RECURSIVE_MUTEXES == 1 )
+ #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) )
+#endif
+
+/**
+ * semphr. h
+ * @code{c}
+ * xSemaphoreGiveFromISR(
+ * SemaphoreHandle_t xSemaphore,
+ * BaseType_t *pxHigherPriorityTaskWoken
+ * );
+ * @endcode
+ *
+ * Macro to release a semaphore. The semaphore must have previously been
+ * created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting().
+ *
+ * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
+ * must not be used with this macro.
+ *
+ * This macro can be used from an ISR.
+ *
+ * @param xSemaphore A handle to the semaphore being released. This is the
+ * handle returned when the semaphore was created.
+ *
+ * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+ * @code{c}
+ \#define LONG_TIME 0xffff
+ \#define TICKS_TO_WAIT 10
+ * SemaphoreHandle_t xSemaphore = NULL;
+ *
+ * // Repetitive task.
+ * void vATask( void * pvParameters )
+ * {
+ * for( ;; )
+ * {
+ * // We want this task to run every 10 ticks of a timer. The semaphore
+ * // was created before this task was started.
+ *
+ * // Block waiting for the semaphore to become available.
+ * if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+ * {
+ * // It is time to execute.
+ *
+ * // ...
+ *
+ * // We have finished our task. Return to the top of the loop where
+ * // we will block on the semaphore until it is time to execute
+ * // again. Note when using the semaphore for synchronisation with an
+ * // ISR in this manner there is no need to 'give' the semaphore back.
+ * }
+ * }
+ * }
+ *
+ * // Timer ISR
+ * void vTimerISR( void * pvParameters )
+ * {
+ * static uint8_t ucLocalTickCount = 0;
+ * static BaseType_t xHigherPriorityTaskWoken;
+ *
+ * // A timer tick has occurred.
+ *
+ * // ... Do other time functions.
+ *
+ * // Is it time for vATask () to run?
+ * xHigherPriorityTaskWoken = pdFALSE;
+ * ucLocalTickCount++;
+ * if( ucLocalTickCount >= TICKS_TO_WAIT )
+ * {
+ * // Unblock the task by releasing the semaphore.
+ * xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+ *
+ * // Reset the count so we release the semaphore again in 10 ticks time.
+ * ucLocalTickCount = 0;
+ * }
+ *
+ * if( xHigherPriorityTaskWoken != pdFALSE )
+ * {
+ * // We can force a context switch here. Context switching from an
+ * // ISR uses port specific syntax. Check the demo task for your port
+ * // to find the syntax required.
+ * }
+ * }
+ * @endcode
+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
+ * \ingroup Semaphores
+ */
+#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * semphr. h
+ * @code{c}
+ * xSemaphoreTakeFromISR(
+ * SemaphoreHandle_t xSemaphore,
+ * BaseType_t *pxHigherPriorityTaskWoken
+ * );
+ * @endcode
+ *
+ * Macro to take a semaphore from an ISR. The semaphore must have
+ * previously been created with a call to xSemaphoreCreateBinary() or
+ * xSemaphoreCreateCounting().
+ *
+ * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
+ * must not be used with this macro.
+ *
+ * This macro can be used from an ISR, however taking a semaphore from an ISR
+ * is not a common operation. It is likely to only be useful when taking a
+ * counting semaphore when an interrupt is obtaining an object from a resource
+ * pool (when the semaphore count indicates the number of resources available).
+ *
+ * @param xSemaphore A handle to the semaphore being taken. This is the
+ * handle returned when the semaphore was created.
+ *
+ * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the semaphore was successfully taken, otherwise
+ * pdFALSE
+ */
+#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * semphr. h
+ * @code{c}
+ * SemaphoreHandle_t xSemaphoreCreateMutex( void );
+ * @endcode
+ *
+ * Creates a new mutex type semaphore instance, and returns a handle by which
+ * the new mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, mutex semaphores use a block
+ * of memory, in which the mutex structure is stored. If a mutex is created
+ * using xSemaphoreCreateMutex() then the required memory is automatically
+ * dynamically allocated inside the xSemaphoreCreateMutex() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a mutex is created using
+ * xSemaphoreCreateMutexStatic() then the application writer must provided the
+ * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
+ * without using any dynamic memory allocation.
+ *
+ * Mutexes created using this function can be accessed using the xSemaphoreTake()
+ * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and
+ * xSemaphoreGiveRecursive() macros must not be used.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @return If the mutex was successfully created then a handle to the created
+ * semaphore is returned. If there was not enough heap to allocate the mutex
+ * data structures then NULL is returned.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore;
+ *
+ * void vATask( void * pvParameters )
+ * {
+ * // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+ * // This is a macro so pass the variable in directly.
+ * xSemaphore = xSemaphoreCreateMutex();
+ *
+ * if( xSemaphore != NULL )
+ * {
+ * // The semaphore was created successfully.
+ * // The semaphore can now be used.
+ * }
+ * }
+ * @endcode
+ * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex
+ * \ingroup Semaphores
+ */
+#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_MUTEXES == 1 ) )
+ #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
+#endif
+
+/**
+ * semphr. h
+ * @code{c}
+ * SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );
+ * @endcode
+ *
+ * Creates a new mutex type semaphore instance, and returns a handle by which
+ * the new mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, mutex semaphores use a block
+ * of memory, in which the mutex structure is stored. If a mutex is created
+ * using xSemaphoreCreateMutex() then the required memory is automatically
+ * dynamically allocated inside the xSemaphoreCreateMutex() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a mutex is created using
+ * xSemaphoreCreateMutexStatic() then the application writer must provided the
+ * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
+ * without using any dynamic memory allocation.
+ *
+ * Mutexes created using this function can be accessed using the xSemaphoreTake()
+ * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and
+ * xSemaphoreGiveRecursive() macros must not be used.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will be used to hold the mutex's data structure, removing the need for
+ * the memory to be allocated dynamically.
+ *
+ * @return If the mutex was successfully created then a handle to the created
+ * mutex is returned. If pxMutexBuffer was NULL then NULL is returned.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore;
+ * StaticSemaphore_t xMutexBuffer;
+ *
+ * void vATask( void * pvParameters )
+ * {
+ * // A mutex cannot be used before it has been created. xMutexBuffer is
+ * // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is
+ * // attempted.
+ * xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer );
+ *
+ * // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+ * // so there is no need to check it.
+ * }
+ * @endcode
+ * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic
+ * \ingroup Semaphores
+ */
+#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_MUTEXES == 1 ) )
+ #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) )
+#endif
+
+
+/**
+ * semphr. h
+ * @code{c}
+ * SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void );
+ * @endcode
+ *
+ * Creates a new recursive mutex type semaphore instance, and returns a handle
+ * by which the new recursive mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, recursive mutexes use a block
+ * of memory, in which the mutex structure is stored. If a recursive mutex is
+ * created using xSemaphoreCreateRecursiveMutex() then the required memory is
+ * automatically dynamically allocated inside the
+ * xSemaphoreCreateRecursiveMutex() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a recursive mutex is created using
+ * xSemaphoreCreateRecursiveMutexStatic() then the application writer must
+ * provide the memory that will get used by the mutex.
+ * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to
+ * be created without using any dynamic memory allocation.
+ *
+ * Mutexes created using this macro can be accessed using the
+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The
+ * xSemaphoreTake() and xSemaphoreGive() macros must not be used.
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
+ * exactly five times.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @return xSemaphore Handle to the created mutex semaphore. Should be of type
+ * SemaphoreHandle_t.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore;
+ *
+ * void vATask( void * pvParameters )
+ * {
+ * // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+ * // This is a macro so pass the variable in directly.
+ * xSemaphore = xSemaphoreCreateRecursiveMutex();
+ *
+ * if( xSemaphore != NULL )
+ * {
+ * // The semaphore was created successfully.
+ * // The semaphore can now be used.
+ * }
+ * }
+ * @endcode
+ * \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex
+ * \ingroup Semaphores
+ */
+#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
+ #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
+#endif
+
+/**
+ * semphr. h
+ * @code{c}
+ * SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer );
+ * @endcode
+ *
+ * Creates a new recursive mutex type semaphore instance, and returns a handle
+ * by which the new recursive mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, recursive mutexes use a block
+ * of memory, in which the mutex structure is stored. If a recursive mutex is
+ * created using xSemaphoreCreateRecursiveMutex() then the required memory is
+ * automatically dynamically allocated inside the
+ * xSemaphoreCreateRecursiveMutex() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a recursive mutex is created using
+ * xSemaphoreCreateRecursiveMutexStatic() then the application writer must
+ * provide the memory that will get used by the mutex.
+ * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to
+ * be created without using any dynamic memory allocation.
+ *
+ * Mutexes created using this macro can be accessed using the
+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The
+ * xSemaphoreTake() and xSemaphoreGive() macros must not be used.
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
+ * exactly five times.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the recursive mutex's data structure,
+ * removing the need for the memory to be allocated dynamically.
+ *
+ * @return If the recursive mutex was successfully created then a handle to the
+ * created recursive mutex is returned. If pxMutexBuffer was NULL then NULL is
+ * returned.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore;
+ * StaticSemaphore_t xMutexBuffer;
+ *
+ * void vATask( void * pvParameters )
+ * {
+ * // A recursive semaphore cannot be used before it is created. Here a
+ * // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic().
+ * // The address of xMutexBuffer is passed into the function, and will hold
+ * // the mutexes data structures - so no dynamic memory allocation will be
+ * // attempted.
+ * xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer );
+ *
+ * // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+ * // so there is no need to check it.
+ * }
+ * @endcode
+ * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic
+ * \ingroup Semaphores
+ */
+#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
+ #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, ( pxStaticSemaphore ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+/**
+ * semphr. h
+ * @code{c}
+ * SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount );
+ * @endcode
+ *
+ * Creates a new counting semaphore instance, and returns a handle by which the
+ * new counting semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a counting semaphore!
+ * https://www.FreeRTOS.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, counting semaphores use a
+ * block of memory, in which the counting semaphore structure is stored. If a
+ * counting semaphore is created using xSemaphoreCreateCounting() then the
+ * required memory is automatically dynamically allocated inside the
+ * xSemaphoreCreateCounting() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a counting semaphore is created
+ * using xSemaphoreCreateCountingStatic() then the application writer can
+ * instead optionally provide the memory that will get used by the counting
+ * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting
+ * semaphore to be created without using any dynamic memory allocation.
+ *
+ * Counting semaphores are typically used for two things:
+ *
+ * 1) Counting events.
+ *
+ * In this usage scenario an event handler will 'give' a semaphore each time
+ * an event occurs (incrementing the semaphore count value), and a handler
+ * task will 'take' a semaphore each time it processes an event
+ * (decrementing the semaphore count value). The count value is therefore
+ * the difference between the number of events that have occurred and the
+ * number that have been processed. In this case it is desirable for the
+ * initial count value to be zero.
+ *
+ * 2) Resource management.
+ *
+ * In this usage scenario the count value indicates the number of resources
+ * available. To obtain control of a resource a task must first obtain a
+ * semaphore - decrementing the semaphore count value. When the count value
+ * reaches zero there are no free resources. When a task finishes with the
+ * resource it 'gives' the semaphore back - incrementing the semaphore count
+ * value. In this case it is desirable for the initial count value to be
+ * equal to the maximum count value, indicating that all resources are free.
+ *
+ * @param uxMaxCount The maximum count value that can be reached. When the
+ * semaphore reaches this value it can no longer be 'given'.
+ *
+ * @param uxInitialCount The count value assigned to the semaphore when it is
+ * created.
+ *
+ * @return Handle to the created semaphore. Null if the semaphore could not be
+ * created.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore;
+ *
+ * void vATask( void * pvParameters )
+ * {
+ * SemaphoreHandle_t xSemaphore = NULL;
+ *
+ * // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+ * // The max value to which the semaphore can count should be 10, and the
+ * // initial value assigned to the count should be 0.
+ * xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+ *
+ * if( xSemaphore != NULL )
+ * {
+ * // The semaphore was created successfully.
+ * // The semaphore can now be used.
+ * }
+ * }
+ * @endcode
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting
+ * \ingroup Semaphores
+ */
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
+#endif
+
+/**
+ * semphr. h
+ * @code{c}
+ * SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer );
+ * @endcode
+ *
+ * Creates a new counting semaphore instance, and returns a handle by which the
+ * new counting semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a counting semaphore!
+ * https://www.FreeRTOS.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, counting semaphores use a
+ * block of memory, in which the counting semaphore structure is stored. If a
+ * counting semaphore is created using xSemaphoreCreateCounting() then the
+ * required memory is automatically dynamically allocated inside the
+ * xSemaphoreCreateCounting() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a counting semaphore is created
+ * using xSemaphoreCreateCountingStatic() then the application writer must
+ * provide the memory. xSemaphoreCreateCountingStatic() therefore allows a
+ * counting semaphore to be created without using any dynamic memory allocation.
+ *
+ * Counting semaphores are typically used for two things:
+ *
+ * 1) Counting events.
+ *
+ * In this usage scenario an event handler will 'give' a semaphore each time
+ * an event occurs (incrementing the semaphore count value), and a handler
+ * task will 'take' a semaphore each time it processes an event
+ * (decrementing the semaphore count value). The count value is therefore
+ * the difference between the number of events that have occurred and the
+ * number that have been processed. In this case it is desirable for the
+ * initial count value to be zero.
+ *
+ * 2) Resource management.
+ *
+ * In this usage scenario the count value indicates the number of resources
+ * available. To obtain control of a resource a task must first obtain a
+ * semaphore - decrementing the semaphore count value. When the count value
+ * reaches zero there are no free resources. When a task finishes with the
+ * resource it 'gives' the semaphore back - incrementing the semaphore count
+ * value. In this case it is desirable for the initial count value to be
+ * equal to the maximum count value, indicating that all resources are free.
+ *
+ * @param uxMaxCount The maximum count value that can be reached. When the
+ * semaphore reaches this value it can no longer be 'given'.
+ *
+ * @param uxInitialCount The count value assigned to the semaphore when it is
+ * created.
+ *
+ * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the semaphore's data structure, removing the
+ * need for the memory to be allocated dynamically.
+ *
+ * @return If the counting semaphore was successfully created then a handle to
+ * the created counting semaphore is returned. If pxSemaphoreBuffer was NULL
+ * then NULL is returned.
+ *
+ * Example usage:
+ * @code{c}
+ * SemaphoreHandle_t xSemaphore;
+ * StaticSemaphore_t xSemaphoreBuffer;
+ *
+ * void vATask( void * pvParameters )
+ * {
+ * SemaphoreHandle_t xSemaphore = NULL;
+ *
+ * // Counting semaphore cannot be used before they have been created. Create
+ * // a counting semaphore using xSemaphoreCreateCountingStatic(). The max
+ * // value to which the semaphore can count is 10, and the initial value
+ * // assigned to the count will be 0. The address of xSemaphoreBuffer is
+ * // passed in and will be used to hold the semaphore structure, so no dynamic
+ * // memory allocation will be used.
+ * xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer );
+ *
+ * // No memory allocation was attempted so xSemaphore cannot be NULL, so there
+ * // is no need to check its value.
+ * }
+ * @endcode
+ * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic
+ * \ingroup Semaphores
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+/**
+ * semphr. h
+ * @code{c}
+ * void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
+ * @endcode
+ *
+ * Delete a semaphore. This function must be used with care. For example,
+ * do not delete a mutex type semaphore if the mutex is held by a task.
+ *
+ * @param xSemaphore A handle to the semaphore to be deleted.
+ *
+ * \defgroup vSemaphoreDelete vSemaphoreDelete
+ * \ingroup Semaphores
+ */
+#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
+
+/**
+ * semphr.h
+ * @code{c}
+ * TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
+ * @endcode
+ *
+ * If xMutex is indeed a mutex type semaphore, return the current mutex holder.
+ * If xMutex is not a mutex type semaphore, or the mutex is available (not held
+ * by a task), return NULL.
+ *
+ * Note: This is a good way of determining if the calling task is the mutex
+ * holder, but not a good way of determining the identity of the mutex holder as
+ * the holder may change between the function exiting and the returned value
+ * being tested.
+ */
+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
+ #define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) )
+#endif
+
+/**
+ * semphr.h
+ * @code{c}
+ * TaskHandle_t xSemaphoreGetMutexHolderFromISR( SemaphoreHandle_t xMutex );
+ * @endcode
+ *
+ * If xMutex is indeed a mutex type semaphore, return the current mutex holder.
+ * If xMutex is not a mutex type semaphore, or the mutex is available (not held
+ * by a task), return NULL.
+ *
+ */
+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
+ #define xSemaphoreGetMutexHolderFromISR( xSemaphore ) xQueueGetMutexHolderFromISR( ( xSemaphore ) )
+#endif
+
+/**
+ * semphr.h
+ * @code{c}
+ * UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
+ * @endcode
+ *
+ * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns
+ * its current count value. If the semaphore is a binary semaphore then
+ * uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the
+ * semaphore is not available.
+ *
+ */
+#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) )
+
+/**
+ * semphr.h
+ * @code{c}
+ * UBaseType_t uxSemaphoreGetCountFromISR( SemaphoreHandle_t xSemaphore );
+ * @endcode
+ *
+ * If the semaphore is a counting semaphore then uxSemaphoreGetCountFromISR() returns
+ * its current count value. If the semaphore is a binary semaphore then
+ * uxSemaphoreGetCountFromISR() returns 1 if the semaphore is available, and 0 if the
+ * semaphore is not available.
+ *
+ */
+#define uxSemaphoreGetCountFromISR( xSemaphore ) uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) ( xSemaphore ) )
+
+#endif /* SEMAPHORE_H */
diff --git a/source/test/freertos/inc/stack_macros.h b/source/test/freertos/inc/stack_macros.h
new file mode 100644
index 0000000..2455674
--- /dev/null
+++ b/source/test/freertos/inc/stack_macros.h
@@ -0,0 +1,137 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef STACK_MACROS_H
+#define STACK_MACROS_H
+
+/*
+ * Call the stack overflow hook function if the stack of the task being swapped
+ * out is currently overflowed, or looks like it might have overflowed in the
+ * past.
+ *
+ * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
+ * the current stack state only - comparing the current top of stack value to
+ * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
+ * will also cause the last few stack bytes to be checked to ensure the value
+ * to which the bytes were set when the task was created have not been
+ * overwritten. Note this second test does not guarantee that an overflowed
+ * stack will always be recognised.
+ */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * portSTACK_LIMIT_PADDING is a number of extra words to consider to be in
+ * use on the stack.
+ */
+#ifndef portSTACK_LIMIT_PADDING
+ #define portSTACK_LIMIT_PADDING 0
+#endif
+
+#if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
+
+/* Only the current stack state is to be checked. */
+ #define taskCHECK_FOR_STACK_OVERFLOW() \
+ { \
+ /* Is the currently saved stack pointer within the stack limit? */ \
+ if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \
+ { \
+ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
+ } \
+ }
+
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
+/*-----------------------------------------------------------*/
+
+#if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
+
+/* Only the current stack state is to be checked. */
+ #define taskCHECK_FOR_STACK_OVERFLOW() \
+ { \
+ \
+ /* Is the currently saved stack pointer within the stack limit? */ \
+ if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \
+ { \
+ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
+ } \
+ }
+
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
+/*-----------------------------------------------------------*/
+
+#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
+
+ #define taskCHECK_FOR_STACK_OVERFLOW() \
+ { \
+ const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
+ const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \
+ \
+ if( ( pulStack[ 0 ] != ulCheckValue ) || \
+ ( pulStack[ 1 ] != ulCheckValue ) || \
+ ( pulStack[ 2 ] != ulCheckValue ) || \
+ ( pulStack[ 3 ] != ulCheckValue ) ) \
+ { \
+ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
+ } \
+ }
+
+#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
+/*-----------------------------------------------------------*/
+
+#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
+
+ #define taskCHECK_FOR_STACK_OVERFLOW() \
+ { \
+ int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
+ static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
+ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
+ \
+ \
+ pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
+ \
+ /* Has the extremity of the task stack ever been written over? */ \
+ if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
+ { \
+ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
+ } \
+ }
+
+#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
+/*-----------------------------------------------------------*/
+
+/* Remove stack overflow macro if not being used. */
+#ifndef taskCHECK_FOR_STACK_OVERFLOW
+ #define taskCHECK_FOR_STACK_OVERFLOW()
+#endif
+
+
+
+#endif /* STACK_MACROS_H */
diff --git a/source/test/freertos/inc/stream_buffer.h b/source/test/freertos/inc/stream_buffer.h
new file mode 100644
index 0000000..bf5019e
--- /dev/null
+++ b/source/test/freertos/inc/stream_buffer.h
@@ -0,0 +1,913 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/*
+ * Stream buffers are used to send a continuous stream of data from one task or
+ * interrupt to another. Their implementation is light weight, making them
+ * particularly suited for interrupt to task and core to core communication
+ * scenarios.
+ *
+ * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
+ * implementation (so also the message buffer implementation, as message buffers
+ * are built on top of stream buffers) assumes there is only one task or
+ * interrupt that will write to the buffer (the writer), and only one task or
+ * interrupt that will read from the buffer (the reader). It is safe for the
+ * writer and reader to be different tasks or interrupts, but, unlike other
+ * FreeRTOS objects, it is not safe to have multiple different writers or
+ * multiple different readers. If there are to be multiple different writers
+ * then the application writer must place each call to a writing API function
+ * (such as xStreamBufferSend()) inside a critical section and set the send
+ * block time to 0. Likewise, if there are to be multiple different readers
+ * then the application writer must place each call to a reading API function
+ * (such as xStreamBufferReceive()) inside a critical section section and set the
+ * receive block time to 0.
+ *
+ */
+
+#ifndef STREAM_BUFFER_H
+#define STREAM_BUFFER_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h must appear in source files before include stream_buffer.h"
+#endif
+
+/* *INDENT-OFF* */
+#if defined( __cplusplus )
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+/**
+ * Type by which stream buffers are referenced. For example, a call to
+ * xStreamBufferCreate() returns an StreamBufferHandle_t variable that can
+ * then be used as a parameter to xStreamBufferSend(), xStreamBufferReceive(),
+ * etc.
+ */
+struct StreamBufferDef_t;
+typedef struct StreamBufferDef_t * StreamBufferHandle_t;
+
+/**
+ * Type used as a stream buffer's optional callback.
+ */
+typedef void (* StreamBufferCallbackFunction_t)( StreamBufferHandle_t xStreamBuffer,
+ BaseType_t xIsInsideISR,
+ BaseType_t * const pxHigherPriorityTaskWoken );
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes );
+ * @endcode
+ *
+ * Creates a new stream buffer using dynamically allocated memory. See
+ * xStreamBufferCreateStatic() for a version that uses statically allocated
+ * memory (memory that is allocated at compile time).
+ *
+ * configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 or left undefined in
+ * FreeRTOSConfig.h for xStreamBufferCreate() to be available.
+ *
+ * @param xBufferSizeBytes The total number of bytes the stream buffer will be
+ * able to hold at any one time.
+ *
+ * @param xTriggerLevelBytes The number of bytes that must be in the stream
+ * buffer before a task that is blocked on the stream buffer to wait for data is
+ * moved out of the blocked state. For example, if a task is blocked on a read
+ * of an empty stream buffer that has a trigger level of 1 then the task will be
+ * unblocked when a single byte is written to the buffer or the task's block
+ * time expires. As another example, if a task is blocked on a read of an empty
+ * stream buffer that has a trigger level of 10 then the task will not be
+ * unblocked until the stream buffer contains at least 10 bytes or the task's
+ * block time expires. If a reading task's block time expires before the
+ * trigger level is reached then the task will still receive however many bytes
+ * are actually available. Setting a trigger level of 0 will result in a
+ * trigger level of 1 being used. It is not valid to specify a trigger level
+ * that is greater than the buffer size.
+ *
+ * @param pxSendCompletedCallback Callback invoked when number of bytes at least equal to
+ * trigger level is sent to the stream buffer. If the parameter is NULL, it will use the default
+ * implementation provided by sbSEND_COMPLETED macro. To enable the callback,
+ * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
+ *
+ * @param pxReceiveCompletedCallback Callback invoked when more than zero bytes are read from a
+ * stream buffer. If the parameter is NULL, it will use the default
+ * implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
+ * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
+ *
+ * @return If NULL is returned, then the stream buffer cannot be created
+ * because there is insufficient heap memory available for FreeRTOS to allocate
+ * the stream buffer data structures and storage area. A non-NULL value being
+ * returned indicates that the stream buffer has been created successfully -
+ * the returned value should be stored as the handle to the created stream
+ * buffer.
+ *
+ * Example use:
+ * @code{c}
+ *
+ * void vAFunction( void )
+ * {
+ * StreamBufferHandle_t xStreamBuffer;
+ * const size_t xStreamBufferSizeBytes = 100, xTriggerLevel = 10;
+ *
+ * // Create a stream buffer that can hold 100 bytes. The memory used to hold
+ * // both the stream buffer structure and the data in the stream buffer is
+ * // allocated dynamically.
+ * xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
+ *
+ * if( xStreamBuffer == NULL )
+ * {
+ * // There was not enough heap memory space available to create the
+ * // stream buffer.
+ * }
+ * else
+ * {
+ * // The stream buffer was created successfully and can now be used.
+ * }
+ * }
+ * @endcode
+ * \defgroup xStreamBufferCreate xStreamBufferCreate
+ * \ingroup StreamBufferManagement
+ */
+
+#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) \
+ xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, NULL, NULL )
+
+#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ #define xStreamBufferCreateWithCallback( xBufferSizeBytes, xTriggerLevelBytes, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
+ xStreamBufferGenericCreate( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
+#endif
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes,
+ * size_t xTriggerLevelBytes,
+ * uint8_t *pucStreamBufferStorageArea,
+ * StaticStreamBuffer_t *pxStaticStreamBuffer );
+ * @endcode
+ * Creates a new stream buffer using statically allocated memory. See
+ * xStreamBufferCreate() for a version that uses dynamically allocated memory.
+ *
+ * configSUPPORT_STATIC_ALLOCATION must be set to 1 in FreeRTOSConfig.h for
+ * xStreamBufferCreateStatic() to be available.
+ *
+ * @param xBufferSizeBytes The size, in bytes, of the buffer pointed to by the
+ * pucStreamBufferStorageArea parameter.
+ *
+ * @param xTriggerLevelBytes The number of bytes that must be in the stream
+ * buffer before a task that is blocked on the stream buffer to wait for data is
+ * moved out of the blocked state. For example, if a task is blocked on a read
+ * of an empty stream buffer that has a trigger level of 1 then the task will be
+ * unblocked when a single byte is written to the buffer or the task's block
+ * time expires. As another example, if a task is blocked on a read of an empty
+ * stream buffer that has a trigger level of 10 then the task will not be
+ * unblocked until the stream buffer contains at least 10 bytes or the task's
+ * block time expires. If a reading task's block time expires before the
+ * trigger level is reached then the task will still receive however many bytes
+ * are actually available. Setting a trigger level of 0 will result in a
+ * trigger level of 1 being used. It is not valid to specify a trigger level
+ * that is greater than the buffer size.
+ *
+ * @param pucStreamBufferStorageArea Must point to a uint8_t array that is at
+ * least xBufferSizeBytes big. This is the array to which streams are
+ * copied when they are written to the stream buffer.
+ *
+ * @param pxStaticStreamBuffer Must point to a variable of type
+ * StaticStreamBuffer_t, which will be used to hold the stream buffer's data
+ * structure.
+ *
+ * @param pxSendCompletedCallback Callback invoked when number of bytes at least equal to
+ * trigger level is sent to the stream buffer. If the parameter is NULL, it will use the default
+ * implementation provided by sbSEND_COMPLETED macro. To enable the callback,
+ * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
+ *
+ * @param pxReceiveCompletedCallback Callback invoked when more than zero bytes are read from a
+ * stream buffer. If the parameter is NULL, it will use the default
+ * implementation provided by sbRECEIVE_COMPLETED macro. To enable the callback,
+ * configUSE_SB_COMPLETED_CALLBACK must be set to 1 in FreeRTOSConfig.h.
+ *
+ * @return If the stream buffer is created successfully then a handle to the
+ * created stream buffer is returned. If either pucStreamBufferStorageArea or
+ * pxStaticstreamBuffer are NULL then NULL is returned.
+ *
+ * Example use:
+ * @code{c}
+ *
+ * // Used to dimension the array used to hold the streams. The available space
+ * // will actually be one less than this, so 999.
+ #define STORAGE_SIZE_BYTES 1000
+ *
+ * // Defines the memory that will actually hold the streams within the stream
+ * // buffer.
+ * static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ];
+ *
+ * // The variable used to hold the stream buffer structure.
+ * StaticStreamBuffer_t xStreamBufferStruct;
+ *
+ * void MyFunction( void )
+ * {
+ * StreamBufferHandle_t xStreamBuffer;
+ * const size_t xTriggerLevel = 1;
+ *
+ * xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucStorageBuffer ),
+ * xTriggerLevel,
+ * ucStorageBuffer,
+ * &xStreamBufferStruct );
+ *
+ * // As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer
+ * // parameters were NULL, xStreamBuffer will not be NULL, and can be used to
+ * // reference the created stream buffer in other stream buffer API calls.
+ *
+ * // Other code that uses the stream buffer can go here.
+ * }
+ *
+ * @endcode
+ * \defgroup xStreamBufferCreateStatic xStreamBufferCreateStatic
+ * \ingroup StreamBufferManagement
+ */
+
+#define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) \
+ xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pucStreamBufferStorageArea ), ( pxStaticStreamBuffer ), NULL, NULL )
+
+#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ #define xStreamBufferCreateStaticWithCallback( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer, pxSendCompletedCallback, pxReceiveCompletedCallback ) \
+ xStreamBufferGenericCreateStatic( ( xBufferSizeBytes ), ( xTriggerLevelBytes ), pdFALSE, ( pucStreamBufferStorageArea ), ( pxStaticStreamBuffer ), ( pxSendCompletedCallback ), ( pxReceiveCompletedCallback ) )
+#endif
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
+ * const void *pvTxData,
+ * size_t xDataLengthBytes,
+ * TickType_t xTicksToWait );
+ * @endcode
+ *
+ * Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
+ *
+ * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
+ * implementation (so also the message buffer implementation, as message buffers
+ * are built on top of stream buffers) assumes there is only one task or
+ * interrupt that will write to the buffer (the writer), and only one task or
+ * interrupt that will read from the buffer (the reader). It is safe for the
+ * writer and reader to be different tasks or interrupts, but, unlike other
+ * FreeRTOS objects, it is not safe to have multiple different writers or
+ * multiple different readers. If there are to be multiple different writers
+ * then the application writer must place each call to a writing API function
+ * (such as xStreamBufferSend()) inside a critical section and set the send
+ * block time to 0. Likewise, if there are to be multiple different readers
+ * then the application writer must place each call to a reading API function
+ * (such as xStreamBufferReceive()) inside a critical section and set the receive
+ * block time to 0.
+ *
+ * Use xStreamBufferSend() to write to a stream buffer from a task. Use
+ * xStreamBufferSendFromISR() to write to a stream buffer from an interrupt
+ * service routine (ISR).
+ *
+ * @param xStreamBuffer The handle of the stream buffer to which a stream is
+ * being sent.
+ *
+ * @param pvTxData A pointer to the buffer that holds the bytes to be copied
+ * into the stream buffer.
+ *
+ * @param xDataLengthBytes The maximum number of bytes to copy from pvTxData
+ * into the stream buffer.
+ *
+ * @param xTicksToWait The maximum amount of time the task should remain in the
+ * Blocked state to wait for enough space to become available in the stream
+ * buffer, should the stream buffer contain too little space to hold the
+ * another xDataLengthBytes bytes. The block time is specified in tick periods,
+ * so the absolute time it represents is dependent on the tick frequency. The
+ * macro pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
+ * into a time specified in ticks. Setting xTicksToWait to portMAX_DELAY will
+ * cause the task to wait indefinitely (without timing out), provided
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. If a task times out
+ * before it can write all xDataLengthBytes into the buffer it will still write
+ * as many bytes as possible. A task does not use any CPU time when it is in
+ * the blocked state.
+ *
+ * @return The number of bytes written to the stream buffer. If a task times
+ * out before it can write all xDataLengthBytes into the buffer it will still
+ * write as many bytes as possible.
+ *
+ * Example use:
+ * @code{c}
+ * void vAFunction( StreamBufferHandle_t xStreamBuffer )
+ * {
+ * size_t xBytesSent;
+ * uint8_t ucArrayToSend[] = { 0, 1, 2, 3 };
+ * char *pcStringToSend = "String to send";
+ * const TickType_t x100ms = pdMS_TO_TICKS( 100 );
+ *
+ * // Send an array to the stream buffer, blocking for a maximum of 100ms to
+ * // wait for enough space to be available in the stream buffer.
+ * xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms );
+ *
+ * if( xBytesSent != sizeof( ucArrayToSend ) )
+ * {
+ * // The call to xStreamBufferSend() times out before there was enough
+ * // space in the buffer for the data to be written, but it did
+ * // successfully write xBytesSent bytes.
+ * }
+ *
+ * // Send the string to the stream buffer. Return immediately if there is not
+ * // enough space in the buffer.
+ * xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 );
+ *
+ * if( xBytesSent != strlen( pcStringToSend ) )
+ * {
+ * // The entire string could not be added to the stream buffer because
+ * // there was not enough free space in the buffer, but xBytesSent bytes
+ * // were sent. Could try again to send the remaining bytes.
+ * }
+ * }
+ * @endcode
+ * \defgroup xStreamBufferSend xStreamBufferSend
+ * \ingroup StreamBufferManagement
+ */
+size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
+ const void * pvTxData,
+ size_t xDataLengthBytes,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
+ * const void *pvTxData,
+ * size_t xDataLengthBytes,
+ * BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * Interrupt safe version of the API function that sends a stream of bytes to
+ * the stream buffer.
+ *
+ * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
+ * implementation (so also the message buffer implementation, as message buffers
+ * are built on top of stream buffers) assumes there is only one task or
+ * interrupt that will write to the buffer (the writer), and only one task or
+ * interrupt that will read from the buffer (the reader). It is safe for the
+ * writer and reader to be different tasks or interrupts, but, unlike other
+ * FreeRTOS objects, it is not safe to have multiple different writers or
+ * multiple different readers. If there are to be multiple different writers
+ * then the application writer must place each call to a writing API function
+ * (such as xStreamBufferSend()) inside a critical section and set the send
+ * block time to 0. Likewise, if there are to be multiple different readers
+ * then the application writer must place each call to a reading API function
+ * (such as xStreamBufferReceive()) inside a critical section and set the receive
+ * block time to 0.
+ *
+ * Use xStreamBufferSend() to write to a stream buffer from a task. Use
+ * xStreamBufferSendFromISR() to write to a stream buffer from an interrupt
+ * service routine (ISR).
+ *
+ * @param xStreamBuffer The handle of the stream buffer to which a stream is
+ * being sent.
+ *
+ * @param pvTxData A pointer to the data that is to be copied into the stream
+ * buffer.
+ *
+ * @param xDataLengthBytes The maximum number of bytes to copy from pvTxData
+ * into the stream buffer.
+ *
+ * @param pxHigherPriorityTaskWoken It is possible that a stream buffer will
+ * have a task blocked on it waiting for data. Calling
+ * xStreamBufferSendFromISR() can make data available, and so cause a task that
+ * was waiting for data to leave the Blocked state. If calling
+ * xStreamBufferSendFromISR() causes a task to leave the Blocked state, and the
+ * unblocked task has a priority higher than the currently executing task (the
+ * task that was interrupted), then, internally, xStreamBufferSendFromISR()
+ * will set *pxHigherPriorityTaskWoken to pdTRUE. If
+ * xStreamBufferSendFromISR() sets this value to pdTRUE, then normally a
+ * context switch should be performed before the interrupt is exited. This will
+ * ensure that the interrupt returns directly to the highest priority Ready
+ * state task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it
+ * is passed into the function. See the example code below for an example.
+ *
+ * @return The number of bytes actually written to the stream buffer, which will
+ * be less than xDataLengthBytes if the stream buffer didn't have enough free
+ * space for all the bytes to be written.
+ *
+ * Example use:
+ * @code{c}
+ * // A stream buffer that has already been created.
+ * StreamBufferHandle_t xStreamBuffer;
+ *
+ * void vAnInterruptServiceRoutine( void )
+ * {
+ * size_t xBytesSent;
+ * char *pcStringToSend = "String to send";
+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
+ *
+ * // Attempt to send the string to the stream buffer.
+ * xBytesSent = xStreamBufferSendFromISR( xStreamBuffer,
+ * ( void * ) pcStringToSend,
+ * strlen( pcStringToSend ),
+ * &xHigherPriorityTaskWoken );
+ *
+ * if( xBytesSent != strlen( pcStringToSend ) )
+ * {
+ * // There was not enough free space in the stream buffer for the entire
+ * // string to be written, ut xBytesSent bytes were written.
+ * }
+ *
+ * // If xHigherPriorityTaskWoken was set to pdTRUE inside
+ * // xStreamBufferSendFromISR() then a task that has a priority above the
+ * // priority of the currently executing task was unblocked and a context
+ * // switch should be performed to ensure the ISR returns to the unblocked
+ * // task. In most FreeRTOS ports this is done by simply passing
+ * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
+ * // variables value, and perform the context switch if necessary. Check the
+ * // documentation for the port in use for port specific instructions.
+ * portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+ * }
+ * @endcode
+ * \defgroup xStreamBufferSendFromISR xStreamBufferSendFromISR
+ * \ingroup StreamBufferManagement
+ */
+size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
+ const void * pvTxData,
+ size_t xDataLengthBytes,
+ BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
+ * void *pvRxData,
+ * size_t xBufferLengthBytes,
+ * TickType_t xTicksToWait );
+ * @endcode
+ *
+ * Receives bytes from a stream buffer.
+ *
+ * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer
+ * implementation (so also the message buffer implementation, as message buffers
+ * are built on top of stream buffers) assumes there is only one task or
+ * interrupt that will write to the buffer (the writer), and only one task or
+ * interrupt that will read from the buffer (the reader). It is safe for the
+ * writer and reader to be different tasks or interrupts, but, unlike other
+ * FreeRTOS objects, it is not safe to have multiple different writers or
+ * multiple different readers. If there are to be multiple different writers
+ * then the application writer must place each call to a writing API function
+ * (such as xStreamBufferSend()) inside a critical section and set the send
+ * block time to 0. Likewise, if there are to be multiple different readers
+ * then the application writer must place each call to a reading API function
+ * (such as xStreamBufferReceive()) inside a critical section and set the receive
+ * block time to 0.
+ *
+ * Use xStreamBufferReceive() to read from a stream buffer from a task. Use
+ * xStreamBufferReceiveFromISR() to read from a stream buffer from an
+ * interrupt service routine (ISR).
+ *
+ * @param xStreamBuffer The handle of the stream buffer from which bytes are to
+ * be received.
+ *
+ * @param pvRxData A pointer to the buffer into which the received bytes will be
+ * copied.
+ *
+ * @param xBufferLengthBytes The length of the buffer pointed to by the
+ * pvRxData parameter. This sets the maximum number of bytes to receive in one
+ * call. xStreamBufferReceive will return as many bytes as possible up to a
+ * maximum set by xBufferLengthBytes.
+ *
+ * @param xTicksToWait The maximum amount of time the task should remain in the
+ * Blocked state to wait for data to become available if the stream buffer is
+ * empty. xStreamBufferReceive() will return immediately if xTicksToWait is
+ * zero. The block time is specified in tick periods, so the absolute time it
+ * represents is dependent on the tick frequency. The macro pdMS_TO_TICKS() can
+ * be used to convert a time specified in milliseconds into a time specified in
+ * ticks. Setting xTicksToWait to portMAX_DELAY will cause the task to wait
+ * indefinitely (without timing out), provided INCLUDE_vTaskSuspend is set to 1
+ * in FreeRTOSConfig.h. A task does not use any CPU time when it is in the
+ * Blocked state.
+ *
+ * @return The number of bytes actually read from the stream buffer, which will
+ * be less than xBufferLengthBytes if the call to xStreamBufferReceive() timed
+ * out before xBufferLengthBytes were available.
+ *
+ * Example use:
+ * @code{c}
+ * void vAFunction( StreamBuffer_t xStreamBuffer )
+ * {
+ * uint8_t ucRxData[ 20 ];
+ * size_t xReceivedBytes;
+ * const TickType_t xBlockTime = pdMS_TO_TICKS( 20 );
+ *
+ * // Receive up to another sizeof( ucRxData ) bytes from the stream buffer.
+ * // Wait in the Blocked state (so not using any CPU processing time) for a
+ * // maximum of 100ms for the full sizeof( ucRxData ) number of bytes to be
+ * // available.
+ * xReceivedBytes = xStreamBufferReceive( xStreamBuffer,
+ * ( void * ) ucRxData,
+ * sizeof( ucRxData ),
+ * xBlockTime );
+ *
+ * if( xReceivedBytes > 0 )
+ * {
+ * // A ucRxData contains another xReceivedBytes bytes of data, which can
+ * // be processed here....
+ * }
+ * }
+ * @endcode
+ * \defgroup xStreamBufferReceive xStreamBufferReceive
+ * \ingroup StreamBufferManagement
+ */
+size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
+ void * pvRxData,
+ size_t xBufferLengthBytes,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
+ * void *pvRxData,
+ * size_t xBufferLengthBytes,
+ * BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * An interrupt safe version of the API function that receives bytes from a
+ * stream buffer.
+ *
+ * Use xStreamBufferReceive() to read bytes from a stream buffer from a task.
+ * Use xStreamBufferReceiveFromISR() to read bytes from a stream buffer from an
+ * interrupt service routine (ISR).
+ *
+ * @param xStreamBuffer The handle of the stream buffer from which a stream
+ * is being received.
+ *
+ * @param pvRxData A pointer to the buffer into which the received bytes are
+ * copied.
+ *
+ * @param xBufferLengthBytes The length of the buffer pointed to by the
+ * pvRxData parameter. This sets the maximum number of bytes to receive in one
+ * call. xStreamBufferReceive will return as many bytes as possible up to a
+ * maximum set by xBufferLengthBytes.
+ *
+ * @param pxHigherPriorityTaskWoken It is possible that a stream buffer will
+ * have a task blocked on it waiting for space to become available. Calling
+ * xStreamBufferReceiveFromISR() can make space available, and so cause a task
+ * that is waiting for space to leave the Blocked state. If calling
+ * xStreamBufferReceiveFromISR() causes a task to leave the Blocked state, and
+ * the unblocked task has a priority higher than the currently executing task
+ * (the task that was interrupted), then, internally,
+ * xStreamBufferReceiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE.
+ * If xStreamBufferReceiveFromISR() sets this value to pdTRUE, then normally a
+ * context switch should be performed before the interrupt is exited. That will
+ * ensure the interrupt returns directly to the highest priority Ready state
+ * task. *pxHigherPriorityTaskWoken should be set to pdFALSE before it is
+ * passed into the function. See the code example below for an example.
+ *
+ * @return The number of bytes read from the stream buffer, if any.
+ *
+ * Example use:
+ * @code{c}
+ * // A stream buffer that has already been created.
+ * StreamBuffer_t xStreamBuffer;
+ *
+ * void vAnInterruptServiceRoutine( void )
+ * {
+ * uint8_t ucRxData[ 20 ];
+ * size_t xReceivedBytes;
+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
+ *
+ * // Receive the next stream from the stream buffer.
+ * xReceivedBytes = xStreamBufferReceiveFromISR( xStreamBuffer,
+ * ( void * ) ucRxData,
+ * sizeof( ucRxData ),
+ * &xHigherPriorityTaskWoken );
+ *
+ * if( xReceivedBytes > 0 )
+ * {
+ * // ucRxData contains xReceivedBytes read from the stream buffer.
+ * // Process the stream here....
+ * }
+ *
+ * // If xHigherPriorityTaskWoken was set to pdTRUE inside
+ * // xStreamBufferReceiveFromISR() then a task that has a priority above the
+ * // priority of the currently executing task was unblocked and a context
+ * // switch should be performed to ensure the ISR returns to the unblocked
+ * // task. In most FreeRTOS ports this is done by simply passing
+ * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the
+ * // variables value, and perform the context switch if necessary. Check the
+ * // documentation for the port in use for port specific instructions.
+ * portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+ * }
+ * @endcode
+ * \defgroup xStreamBufferReceiveFromISR xStreamBufferReceiveFromISR
+ * \ingroup StreamBufferManagement
+ */
+size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
+ void * pvRxData,
+ size_t xBufferLengthBytes,
+ BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
+ * @endcode
+ *
+ * Deletes a stream buffer that was previously created using a call to
+ * xStreamBufferCreate() or xStreamBufferCreateStatic(). If the stream
+ * buffer was created using dynamic memory (that is, by xStreamBufferCreate()),
+ * then the allocated memory is freed.
+ *
+ * A stream buffer handle must not be used after the stream buffer has been
+ * deleted.
+ *
+ * @param xStreamBuffer The handle of the stream buffer to be deleted.
+ *
+ * \defgroup vStreamBufferDelete vStreamBufferDelete
+ * \ingroup StreamBufferManagement
+ */
+void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );
+ * @endcode
+ *
+ * Queries a stream buffer to see if it is full. A stream buffer is full if it
+ * does not have any free space, and therefore cannot accept any more data.
+ *
+ * @param xStreamBuffer The handle of the stream buffer being queried.
+ *
+ * @return If the stream buffer is full then pdTRUE is returned. Otherwise
+ * pdFALSE is returned.
+ *
+ * \defgroup xStreamBufferIsFull xStreamBufferIsFull
+ * \ingroup StreamBufferManagement
+ */
+BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
+ * @endcode
+ *
+ * Queries a stream buffer to see if it is empty. A stream buffer is empty if
+ * it does not contain any data.
+ *
+ * @param xStreamBuffer The handle of the stream buffer being queried.
+ *
+ * @return If the stream buffer is empty then pdTRUE is returned. Otherwise
+ * pdFALSE is returned.
+ *
+ * \defgroup xStreamBufferIsEmpty xStreamBufferIsEmpty
+ * \ingroup StreamBufferManagement
+ */
+BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );
+ * @endcode
+ *
+ * Resets a stream buffer to its initial, empty, state. Any data that was in
+ * the stream buffer is discarded. A stream buffer can only be reset if there
+ * are no tasks blocked waiting to either send to or receive from the stream
+ * buffer.
+ *
+ * @param xStreamBuffer The handle of the stream buffer being reset.
+ *
+ * @return If the stream buffer is reset then pdPASS is returned. If there was
+ * a task blocked waiting to send to or read from the stream buffer then the
+ * stream buffer is not reset and pdFAIL is returned.
+ *
+ * \defgroup xStreamBufferReset xStreamBufferReset
+ * \ingroup StreamBufferManagement
+ */
+BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
+ * @endcode
+ *
+ * Queries a stream buffer to see how much free space it contains, which is
+ * equal to the amount of data that can be sent to the stream buffer before it
+ * is full.
+ *
+ * @param xStreamBuffer The handle of the stream buffer being queried.
+ *
+ * @return The number of bytes that can be written to the stream buffer before
+ * the stream buffer would be full.
+ *
+ * \defgroup xStreamBufferSpacesAvailable xStreamBufferSpacesAvailable
+ * \ingroup StreamBufferManagement
+ */
+size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
+ * @endcode
+ *
+ * Queries a stream buffer to see how much data it contains, which is equal to
+ * the number of bytes that can be read from the stream buffer before the stream
+ * buffer would be empty.
+ *
+ * @param xStreamBuffer The handle of the stream buffer being queried.
+ *
+ * @return The number of bytes that can be read from the stream buffer before
+ * the stream buffer would be empty.
+ *
+ * \defgroup xStreamBufferBytesAvailable xStreamBufferBytesAvailable
+ * \ingroup StreamBufferManagement
+ */
+size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel );
+ * @endcode
+ *
+ * A stream buffer's trigger level is the number of bytes that must be in the
+ * stream buffer before a task that is blocked on the stream buffer to
+ * wait for data is moved out of the blocked state. For example, if a task is
+ * blocked on a read of an empty stream buffer that has a trigger level of 1
+ * then the task will be unblocked when a single byte is written to the buffer
+ * or the task's block time expires. As another example, if a task is blocked
+ * on a read of an empty stream buffer that has a trigger level of 10 then the
+ * task will not be unblocked until the stream buffer contains at least 10 bytes
+ * or the task's block time expires. If a reading task's block time expires
+ * before the trigger level is reached then the task will still receive however
+ * many bytes are actually available. Setting a trigger level of 0 will result
+ * in a trigger level of 1 being used. It is not valid to specify a trigger
+ * level that is greater than the buffer size.
+ *
+ * A trigger level is set when the stream buffer is created, and can be modified
+ * using xStreamBufferSetTriggerLevel().
+ *
+ * @param xStreamBuffer The handle of the stream buffer being updated.
+ *
+ * @param xTriggerLevel The new trigger level for the stream buffer.
+ *
+ * @return If xTriggerLevel was less than or equal to the stream buffer's length
+ * then the trigger level will be updated and pdTRUE is returned. Otherwise
+ * pdFALSE is returned.
+ *
+ * \defgroup xStreamBufferSetTriggerLevel xStreamBufferSetTriggerLevel
+ * \ingroup StreamBufferManagement
+ */
+BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
+ size_t xTriggerLevel ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * For advanced users only.
+ *
+ * The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when
+ * data is sent to a message buffer or stream buffer. If there was a task that
+ * was blocked on the message or stream buffer waiting for data to arrive then
+ * the sbSEND_COMPLETED() macro sends a notification to the task to remove it
+ * from the Blocked state. xStreamBufferSendCompletedFromISR() does the same
+ * thing. It is provided to enable application writers to implement their own
+ * version of sbSEND_COMPLETED(), and MUST NOT BE USED AT ANY OTHER TIME.
+ *
+ * See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
+ * additional information.
+ *
+ * @param xStreamBuffer The handle of the stream buffer to which data was
+ * written.
+ *
+ * @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
+ * initialised to pdFALSE before it is passed into
+ * xStreamBufferSendCompletedFromISR(). If calling
+ * xStreamBufferSendCompletedFromISR() removes a task from the Blocked state,
+ * and the task has a priority above the priority of the currently running task,
+ * then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
+ * context switch should be performed before exiting the ISR.
+ *
+ * @return If a task was removed from the Blocked state then pdTRUE is returned.
+ * Otherwise pdFALSE is returned.
+ *
+ * \defgroup xStreamBufferSendCompletedFromISR xStreamBufferSendCompletedFromISR
+ * \ingroup StreamBufferManagement
+ */
+BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
+ BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+
+/**
+ * stream_buffer.h
+ *
+ * @code{c}
+ * BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * For advanced users only.
+ *
+ * The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when
+ * data is read out of a message buffer or stream buffer. If there was a task
+ * that was blocked on the message or stream buffer waiting for data to arrive
+ * then the sbRECEIVE_COMPLETED() macro sends a notification to the task to
+ * remove it from the Blocked state. xStreamBufferReceiveCompletedFromISR()
+ * does the same thing. It is provided to enable application writers to
+ * implement their own version of sbRECEIVE_COMPLETED(), and MUST NOT BE USED AT
+ * ANY OTHER TIME.
+ *
+ * See the example implemented in FreeRTOS/Demo/Minimal/MessageBufferAMP.c for
+ * additional information.
+ *
+ * @param xStreamBuffer The handle of the stream buffer from which data was
+ * read.
+ *
+ * @param pxHigherPriorityTaskWoken *pxHigherPriorityTaskWoken should be
+ * initialised to pdFALSE before it is passed into
+ * xStreamBufferReceiveCompletedFromISR(). If calling
+ * xStreamBufferReceiveCompletedFromISR() removes a task from the Blocked state,
+ * and the task has a priority above the priority of the currently running task,
+ * then *pxHigherPriorityTaskWoken will get set to pdTRUE indicating that a
+ * context switch should be performed before exiting the ISR.
+ *
+ * @return If a task was removed from the Blocked state then pdTRUE is returned.
+ * Otherwise pdFALSE is returned.
+ *
+ * \defgroup xStreamBufferReceiveCompletedFromISR xStreamBufferReceiveCompletedFromISR
+ * \ingroup StreamBufferManagement
+ */
+BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
+ BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+
+/* Functions below here are not part of the public API. */
+StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
+ size_t xTriggerLevelBytes,
+ BaseType_t xIsMessageBuffer,
+ StreamBufferCallbackFunction_t pxSendCompletedCallback,
+ StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
+
+
+StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
+ size_t xTriggerLevelBytes,
+ BaseType_t xIsMessageBuffer,
+ uint8_t * const pucStreamBufferStorageArea,
+ StaticStreamBuffer_t * const pxStaticStreamBuffer,
+ StreamBufferCallbackFunction_t pxSendCompletedCallback,
+ StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
+
+size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+ void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer,
+ UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION;
+ UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
+ uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
+#endif
+
+/* *INDENT-OFF* */
+#if defined( __cplusplus )
+ }
+#endif
+/* *INDENT-ON* */
+
+#endif /* !defined( STREAM_BUFFER_H ) */
diff --git a/source/test/freertos/inc/task.h b/source/test/freertos/inc/task.h
new file mode 100644
index 0000000..ab8eeb8
--- /dev/null
+++ b/source/test/freertos/inc/task.h
@@ -0,0 +1,3118 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+
+#ifndef INC_TASK_H
+#define INC_TASK_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h must appear in source files before include task.h"
+#endif
+
+#include "list.h"
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+/*-----------------------------------------------------------
+* MACROS AND DEFINITIONS
+*----------------------------------------------------------*/
+
+/*
+ * If tskKERNEL_VERSION_NUMBER ends with + it represents the version in development
+ * after the numbered release.
+ *
+ * The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD
+ * values will reflect the last released version number.
+ */
+#define tskKERNEL_VERSION_NUMBER "V10.5.1"
+#define tskKERNEL_VERSION_MAJOR 10
+#define tskKERNEL_VERSION_MINOR 5
+#define tskKERNEL_VERSION_BUILD 1
+
+/* MPU region parameters passed in ulParameters
+ * of MemoryRegion_t struct. */
+#define tskMPU_REGION_READ_ONLY ( 1UL << 0UL )
+#define tskMPU_REGION_READ_WRITE ( 1UL << 1UL )
+#define tskMPU_REGION_EXECUTE_NEVER ( 1UL << 2UL )
+#define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL )
+#define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL )
+
+/* The direct to task notification feature used to have only a single notification
+ * per task. Now there is an array of notifications per task that is dimensioned by
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward compatibility, any use of the
+ * original direct to task notification defaults to using the first index in the
+ * array. */
+#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 )
+
+/**
+ * task. h
+ *
+ * Type by which tasks are referenced. For example, a call to xTaskCreate
+ * returns (via a pointer parameter) an TaskHandle_t variable that can then
+ * be used as a parameter to vTaskDelete to delete the task.
+ *
+ * \defgroup TaskHandle_t TaskHandle_t
+ * \ingroup Tasks
+ */
+struct tskTaskControlBlock; /* The old naming convention is used to prevent breaking kernel aware debuggers. */
+typedef struct tskTaskControlBlock * TaskHandle_t;
+
+/*
+ * Defines the prototype to which the application task hook function must
+ * conform.
+ */
+typedef BaseType_t (* TaskHookFunction_t)( void * );
+
+/* Task states returned by eTaskGetState. */
+typedef enum
+{
+ eRunning = 0, /* A task is querying the state of itself, so must be running. */
+ eReady, /* The task being queried is in a ready or pending ready list. */
+ eBlocked, /* The task being queried is in the Blocked state. */
+ eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */
+ eDeleted, /* The task being queried has been deleted, but its TCB has not yet been freed. */
+ eInvalid /* Used as an 'invalid state' value. */
+} eTaskState;
+
+/* Actions that can be performed when vTaskNotify() is called. */
+typedef enum
+{
+ eNoAction = 0, /* Notify the task without updating its notify value. */
+ eSetBits, /* Set bits in the task's notification value. */
+ eIncrement, /* Increment the task's notification value. */
+ eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */
+ eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */
+} eNotifyAction;
+
+/*
+ * Used internally only.
+ */
+typedef struct xTIME_OUT
+{
+ BaseType_t xOverflowCount;
+ TickType_t xTimeOnEntering;
+} TimeOut_t;
+
+/*
+ * Defines the memory ranges allocated to the task when an MPU is used.
+ */
+typedef struct xMEMORY_REGION
+{
+ void * pvBaseAddress;
+ uint32_t ulLengthInBytes;
+ uint32_t ulParameters;
+} MemoryRegion_t;
+
+/*
+ * Parameters required to create an MPU protected task.
+ */
+typedef struct xTASK_PARAMETERS
+{
+ TaskFunction_t pvTaskCode;
+ const char * pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ configSTACK_DEPTH_TYPE usStackDepth;
+ void * pvParameters;
+ UBaseType_t uxPriority;
+ StackType_t * puxStackBuffer;
+ MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ];
+ #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+ StaticTask_t * const pxTaskBuffer;
+ #endif
+} TaskParameters_t;
+
+/* Used with the uxTaskGetSystemState() function to return the state of each task
+ * in the system. */
+typedef struct xTASK_STATUS
+{
+ TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */
+ const char * pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ UBaseType_t xTaskNumber; /* A number unique to the task. */
+ eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */
+ UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */
+ UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */
+ configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See https://www.FreeRTOS.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
+ StackType_t * pxStackBase; /* Points to the lowest address of the task's stack area. */
+ #if ( ( portSTACK_GROWTH > 0 ) && ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
+ StackType_t * pxTopOfStack; /* Points to the top address of the task's stack area. */
+ StackType_t * pxEndOfStack; /* Points to the end address of the task's stack area. */
+ #endif
+ configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
+} TaskStatus_t;
+
+/* Possible return values for eTaskConfirmSleepModeStatus(). */
+typedef enum
+{
+ eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPRESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */
+ eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */
+ #endif /* INCLUDE_vTaskSuspend */
+} eSleepModeStatus;
+
+/**
+ * Defines the priority used by the idle task. This must not be modified.
+ *
+ * \ingroup TaskUtils
+ */
+#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U )
+
+/**
+ * task. h
+ *
+ * Macro for forcing a context switch.
+ *
+ * \defgroup taskYIELD taskYIELD
+ * \ingroup SchedulerControl
+ */
+#define taskYIELD() portYIELD()
+
+/**
+ * task. h
+ *
+ * Macro to mark the start of a critical code region. Preemptive context
+ * switches cannot occur when in a critical region.
+ *
+ * NOTE: This may alter the stack (depending on the portable implementation)
+ * so must be used with care!
+ *
+ * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
+ * \ingroup SchedulerControl
+ */
+#define taskENTER_CRITICAL() portENTER_CRITICAL()
+#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
+
+/**
+ * task. h
+ *
+ * Macro to mark the end of a critical code region. Preemptive context
+ * switches cannot occur when in a critical region.
+ *
+ * NOTE: This may alter the stack (depending on the portable implementation)
+ * so must be used with care!
+ *
+ * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
+ * \ingroup SchedulerControl
+ */
+#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
+#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
+
+/**
+ * task. h
+ *
+ * Macro to disable all maskable interrupts.
+ *
+ * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS
+ * \ingroup SchedulerControl
+ */
+#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
+
+/**
+ * task. h
+ *
+ * Macro to enable microcontroller interrupts.
+ *
+ * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS
+ * \ingroup SchedulerControl
+ */
+#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
+
+/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is
+ * 0 to generate more optimal code when configASSERT() is defined as the constant
+ * is used in assert() statements. */
+#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 )
+#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 )
+#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 )
+
+
+/*-----------------------------------------------------------
+* TASK CREATION API
+*----------------------------------------------------------*/
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskCreate(
+ * TaskFunction_t pxTaskCode,
+ * const char *pcName,
+ * configSTACK_DEPTH_TYPE usStackDepth,
+ * void *pvParameters,
+ * UBaseType_t uxPriority,
+ * TaskHandle_t *pxCreatedTask
+ * );
+ * @endcode
+ *
+ * Create a new task and add it to the list of tasks that are ready to run.
+ *
+ * Internally, within the FreeRTOS implementation, tasks use two blocks of
+ * memory. The first block is used to hold the task's data structures. The
+ * second block is used by the task as its stack. If a task is created using
+ * xTaskCreate() then both blocks of memory are automatically dynamically
+ * allocated inside the xTaskCreate() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a task is created using
+ * xTaskCreateStatic() then the application writer must provide the required
+ * memory. xTaskCreateStatic() therefore allows a task to be created without
+ * using any dynamic memory allocation.
+ *
+ * See xTaskCreateStatic() for a version that does not use any dynamic memory
+ * allocation.
+ *
+ * xTaskCreate() can only be used to create a task that has unrestricted
+ * access to the entire microcontroller memory map. Systems that include MPU
+ * support can alternatively create an MPU constrained task using
+ * xTaskCreateRestricted().
+ *
+ * @param pxTaskCode Pointer to the task entry function. Tasks
+ * must be implemented to never return (i.e. continuous loop).
+ *
+ * @param pcName A descriptive name for the task. This is mainly used to
+ * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default
+ * is 16.
+ *
+ * @param usStackDepth The size of the task stack specified as the number of
+ * variables the stack can hold - not the number of bytes. For example, if
+ * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes
+ * will be allocated for stack storage.
+ *
+ * @param pvParameters Pointer that will be used as the parameter for the task
+ * being created.
+ *
+ * @param uxPriority The priority at which the task should run. Systems that
+ * include MPU support can optionally create tasks in a privileged (system)
+ * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For
+ * example, to create a privileged task at priority 2 the uxPriority parameter
+ * should be set to ( 2 | portPRIVILEGE_BIT ).
+ *
+ * @param pxCreatedTask Used to pass back a handle by which the created task
+ * can be referenced.
+ *
+ * @return pdPASS if the task was successfully created and added to a ready
+ * list, otherwise an error code defined in the file projdefs.h
+ *
+ * Example usage:
+ * @code{c}
+ * // Task to be created.
+ * void vTaskCode( void * pvParameters )
+ * {
+ * for( ;; )
+ * {
+ * // Task code goes here.
+ * }
+ * }
+ *
+ * // Function that creates a task.
+ * void vOtherFunction( void )
+ * {
+ * static uint8_t ucParameterToPass;
+ * TaskHandle_t xHandle = NULL;
+ *
+ * // Create the task, storing the handle. Note that the passed parameter ucParameterToPass
+ * // must exist for the lifetime of the task, so in this case is declared static. If it was just an
+ * // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
+ * // the new task attempts to access it.
+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+ * configASSERT( xHandle );
+ *
+ * // Use the handle to delete the task.
+ * if( xHandle != NULL )
+ * {
+ * vTaskDelete( xHandle );
+ * }
+ * }
+ * @endcode
+ * \defgroup xTaskCreate xTaskCreate
+ * \ingroup Tasks
+ */
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
+ const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const configSTACK_DEPTH_TYPE usStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
+#endif
+
+/**
+ * task. h
+ * @code{c}
+ * TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
+ * const char *pcName,
+ * uint32_t ulStackDepth,
+ * void *pvParameters,
+ * UBaseType_t uxPriority,
+ * StackType_t *puxStackBuffer,
+ * StaticTask_t *pxTaskBuffer );
+ * @endcode
+ *
+ * Create a new task and add it to the list of tasks that are ready to run.
+ *
+ * Internally, within the FreeRTOS implementation, tasks use two blocks of
+ * memory. The first block is used to hold the task's data structures. The
+ * second block is used by the task as its stack. If a task is created using
+ * xTaskCreate() then both blocks of memory are automatically dynamically
+ * allocated inside the xTaskCreate() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a task is created using
+ * xTaskCreateStatic() then the application writer must provide the required
+ * memory. xTaskCreateStatic() therefore allows a task to be created without
+ * using any dynamic memory allocation.
+ *
+ * @param pxTaskCode Pointer to the task entry function. Tasks
+ * must be implemented to never return (i.e. continuous loop).
+ *
+ * @param pcName A descriptive name for the task. This is mainly used to
+ * facilitate debugging. The maximum length of the string is defined by
+ * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h.
+ *
+ * @param ulStackDepth The size of the task stack specified as the number of
+ * variables the stack can hold - not the number of bytes. For example, if
+ * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes
+ * will be allocated for stack storage.
+ *
+ * @param pvParameters Pointer that will be used as the parameter for the task
+ * being created.
+ *
+ * @param uxPriority The priority at which the task will run.
+ *
+ * @param puxStackBuffer Must point to a StackType_t array that has at least
+ * ulStackDepth indexes - the array will then be used as the task's stack,
+ * removing the need for the stack to be allocated dynamically.
+ *
+ * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will
+ * then be used to hold the task's data structures, removing the need for the
+ * memory to be allocated dynamically.
+ *
+ * @return If neither puxStackBuffer nor pxTaskBuffer are NULL, then the task
+ * will be created and a handle to the created task is returned. If either
+ * puxStackBuffer or pxTaskBuffer are NULL then the task will not be created and
+ * NULL is returned.
+ *
+ * Example usage:
+ * @code{c}
+ *
+ * // Dimensions of the buffer that the task being created will use as its stack.
+ * // NOTE: This is the number of words the stack will hold, not the number of
+ * // bytes. For example, if each stack item is 32-bits, and this is set to 100,
+ * // then 400 bytes (100 * 32-bits) will be allocated.
+ #define STACK_SIZE 200
+ *
+ * // Structure that will hold the TCB of the task being created.
+ * StaticTask_t xTaskBuffer;
+ *
+ * // Buffer that the task being created will use as its stack. Note this is
+ * // an array of StackType_t variables. The size of StackType_t is dependent on
+ * // the RTOS port.
+ * StackType_t xStack[ STACK_SIZE ];
+ *
+ * // Function that implements the task being created.
+ * void vTaskCode( void * pvParameters )
+ * {
+ * // The parameter value is expected to be 1 as 1 is passed in the
+ * // pvParameters value in the call to xTaskCreateStatic().
+ * configASSERT( ( uint32_t ) pvParameters == 1UL );
+ *
+ * for( ;; )
+ * {
+ * // Task code goes here.
+ * }
+ * }
+ *
+ * // Function that creates a task.
+ * void vOtherFunction( void )
+ * {
+ * TaskHandle_t xHandle = NULL;
+ *
+ * // Create the task without using any dynamic memory allocation.
+ * xHandle = xTaskCreateStatic(
+ * vTaskCode, // Function that implements the task.
+ * "NAME", // Text name for the task.
+ * STACK_SIZE, // Stack size in words, not bytes.
+ * ( void * ) 1, // Parameter passed into the task.
+ * tskIDLE_PRIORITY,// Priority at which the task is created.
+ * xStack, // Array to use as the task's stack.
+ * &xTaskBuffer ); // Variable to hold the task's data structure.
+ *
+ * // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
+ * // been created, and xHandle will be the task's handle. Use the handle
+ * // to suspend the task.
+ * vTaskSuspend( xHandle );
+ * }
+ * @endcode
+ * \defgroup xTaskCreateStatic xTaskCreateStatic
+ * \ingroup Tasks
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
+ const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const uint32_t ulStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ StackType_t * const puxStackBuffer,
+ StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION;
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+ * @endcode
+ *
+ * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1.
+ *
+ * xTaskCreateRestricted() should only be used in systems that include an MPU
+ * implementation.
+ *
+ * Create a new task and add it to the list of tasks that are ready to run.
+ * The function parameters define the memory regions and associated access
+ * permissions allocated to the task.
+ *
+ * See xTaskCreateRestrictedStatic() for a version that does not use any
+ * dynamic memory allocation.
+ *
+ * @param pxTaskDefinition Pointer to a structure that contains a member
+ * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
+ * documentation) plus an optional stack buffer and the memory region
+ * definitions.
+ *
+ * @param pxCreatedTask Used to pass back a handle by which the created task
+ * can be referenced.
+ *
+ * @return pdPASS if the task was successfully created and added to a ready
+ * list, otherwise an error code defined in the file projdefs.h
+ *
+ * Example usage:
+ * @code{c}
+ * // Create an TaskParameters_t structure that defines the task to be created.
+ * static const TaskParameters_t xCheckTaskParameters =
+ * {
+ * vATask, // pvTaskCode - the function that implements the task.
+ * "ATask", // pcName - just a text name for the task to assist debugging.
+ * 100, // usStackDepth - the stack size DEFINED IN WORDS.
+ * NULL, // pvParameters - passed into the task function as the function parameters.
+ * ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+ * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+ *
+ * // xRegions - Allocate up to three separate memory regions for access by
+ * // the task, with appropriate access permissions. Different processors have
+ * // different memory alignment requirements - refer to the FreeRTOS documentation
+ * // for full information.
+ * {
+ * // Base address Length Parameters
+ * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE },
+ * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY },
+ * { cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE }
+ * }
+ * };
+ *
+ * int main( void )
+ * {
+ * TaskHandle_t xHandle;
+ *
+ * // Create a task from the const structure defined above. The task handle
+ * // is requested (the second parameter is not NULL) but in this case just for
+ * // demonstration purposes as its not actually used.
+ * xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+ *
+ * // Start the scheduler.
+ * vTaskStartScheduler();
+ *
+ * // Will only get here if there was insufficient memory to create the idle
+ * // and/or timer task.
+ * for( ;; );
+ * }
+ * @endcode
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted
+ * \ingroup Tasks
+ */
+#if ( portUSING_MPU_WRAPPERS == 1 )
+ BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
+ TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION;
+#endif
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+ * @endcode
+ *
+ * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1.
+ *
+ * xTaskCreateRestrictedStatic() should only be used in systems that include an
+ * MPU implementation.
+ *
+ * Internally, within the FreeRTOS implementation, tasks use two blocks of
+ * memory. The first block is used to hold the task's data structures. The
+ * second block is used by the task as its stack. If a task is created using
+ * xTaskCreateRestricted() then the stack is provided by the application writer,
+ * and the memory used to hold the task's data structure is automatically
+ * dynamically allocated inside the xTaskCreateRestricted() function. If a task
+ * is created using xTaskCreateRestrictedStatic() then the application writer
+ * must provide the memory used to hold the task's data structures too.
+ * xTaskCreateRestrictedStatic() therefore allows a memory protected task to be
+ * created without using any dynamic memory allocation.
+ *
+ * @param pxTaskDefinition Pointer to a structure that contains a member
+ * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
+ * documentation) plus an optional stack buffer and the memory region
+ * definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure
+ * contains an additional member, which is used to point to a variable of type
+ * StaticTask_t - which is then used to hold the task's data structure.
+ *
+ * @param pxCreatedTask Used to pass back a handle by which the created task
+ * can be referenced.
+ *
+ * @return pdPASS if the task was successfully created and added to a ready
+ * list, otherwise an error code defined in the file projdefs.h
+ *
+ * Example usage:
+ * @code{c}
+ * // Create an TaskParameters_t structure that defines the task to be created.
+ * // The StaticTask_t variable is only included in the structure when
+ * // configSUPPORT_STATIC_ALLOCATION is set to 1. The PRIVILEGED_DATA macro can
+ * // be used to force the variable into the RTOS kernel's privileged data area.
+ * static PRIVILEGED_DATA StaticTask_t xTaskBuffer;
+ * static const TaskParameters_t xCheckTaskParameters =
+ * {
+ * vATask, // pvTaskCode - the function that implements the task.
+ * "ATask", // pcName - just a text name for the task to assist debugging.
+ * 100, // usStackDepth - the stack size DEFINED IN WORDS.
+ * NULL, // pvParameters - passed into the task function as the function parameters.
+ * ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+ * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+ *
+ * // xRegions - Allocate up to three separate memory regions for access by
+ * // the task, with appropriate access permissions. Different processors have
+ * // different memory alignment requirements - refer to the FreeRTOS documentation
+ * // for full information.
+ * {
+ * // Base address Length Parameters
+ * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE },
+ * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY },
+ * { cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE }
+ * }
+ *
+ * &xTaskBuffer; // Holds the task's data structure.
+ * };
+ *
+ * int main( void )
+ * {
+ * TaskHandle_t xHandle;
+ *
+ * // Create a task from the const structure defined above. The task handle
+ * // is requested (the second parameter is not NULL) but in this case just for
+ * // demonstration purposes as its not actually used.
+ * xTaskCreateRestrictedStatic( &xRegTest1Parameters, &xHandle );
+ *
+ * // Start the scheduler.
+ * vTaskStartScheduler();
+ *
+ * // Will only get here if there was insufficient memory to create the idle
+ * // and/or timer task.
+ * for( ;; );
+ * }
+ * @endcode
+ * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic
+ * \ingroup Tasks
+ */
+#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+ BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition,
+ TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION;
+#endif
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
+ * @endcode
+ *
+ * Memory regions are assigned to a restricted task when the task is created by
+ * a call to xTaskCreateRestricted(). These regions can be redefined using
+ * vTaskAllocateMPURegions().
+ *
+ * @param xTask The handle of the task being updated.
+ *
+ * @param xRegions A pointer to a MemoryRegion_t structure that contains the
+ * new memory region definitions.
+ *
+ * Example usage:
+ * @code{c}
+ * // Define an array of MemoryRegion_t structures that configures an MPU region
+ * // allowing read/write access for 1024 bytes starting at the beginning of the
+ * // ucOneKByte array. The other two of the maximum 3 definable regions are
+ * // unused so set to zero.
+ * static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
+ * {
+ * // Base address Length Parameters
+ * { ucOneKByte, 1024, portMPU_REGION_READ_WRITE },
+ * { 0, 0, 0 },
+ * { 0, 0, 0 }
+ * };
+ *
+ * void vATask( void *pvParameters )
+ * {
+ * // This task was created such that it has access to certain regions of
+ * // memory as defined by the MPU configuration. At some point it is
+ * // desired that these MPU regions are replaced with that defined in the
+ * // xAltRegions const struct above. Use a call to vTaskAllocateMPURegions()
+ * // for this purpose. NULL is used as the task handle to indicate that this
+ * // function should modify the MPU regions of the calling task.
+ * vTaskAllocateMPURegions( NULL, xAltRegions );
+ *
+ * // Now the task can continue its function, but from this point on can only
+ * // access its stack and the ucOneKByte array (unless any other statically
+ * // defined or shared regions have been declared elsewhere).
+ * }
+ * @endcode
+ * \defgroup vTaskAllocateMPURegions vTaskAllocateMPURegions
+ * \ingroup Tasks
+ */
+void vTaskAllocateMPURegions( TaskHandle_t xTask,
+ const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskDelete( TaskHandle_t xTaskToDelete );
+ * @endcode
+ *
+ * INCLUDE_vTaskDelete must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Remove a task from the RTOS real time kernel's management. The task being
+ * deleted will be removed from all ready, blocked, suspended and event lists.
+ *
+ * NOTE: The idle task is responsible for freeing the kernel allocated
+ * memory from tasks that have been deleted. It is therefore important that
+ * the idle task is not starved of microcontroller processing time if your
+ * application makes any calls to vTaskDelete (). Memory allocated by the
+ * task code is not automatically freed, and should be freed before the task
+ * is deleted.
+ *
+ * See the demo application file death.c for sample code that utilises
+ * vTaskDelete ().
+ *
+ * @param xTaskToDelete The handle of the task to be deleted. Passing NULL will
+ * cause the calling task to be deleted.
+ *
+ * Example usage:
+ * @code{c}
+ * void vOtherFunction( void )
+ * {
+ * TaskHandle_t xHandle;
+ *
+ * // Create the task, storing the handle.
+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+ *
+ * // Use the handle to delete the task.
+ * vTaskDelete( xHandle );
+ * }
+ * @endcode
+ * \defgroup vTaskDelete vTaskDelete
+ * \ingroup Tasks
+ */
+void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;
+
+/*-----------------------------------------------------------
+* TASK CONTROL API
+*----------------------------------------------------------*/
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskDelay( const TickType_t xTicksToDelay );
+ * @endcode
+ *
+ * Delay a task for a given number of ticks. The actual time that the
+ * task remains blocked depends on the tick rate. The constant
+ * portTICK_PERIOD_MS can be used to calculate real time from the tick
+ * rate - with the resolution of one tick period.
+ *
+ * INCLUDE_vTaskDelay must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ *
+ * vTaskDelay() specifies a time at which the task wishes to unblock relative to
+ * the time at which vTaskDelay() is called. For example, specifying a block
+ * period of 100 ticks will cause the task to unblock 100 ticks after
+ * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method
+ * of controlling the frequency of a periodic task as the path taken through the
+ * code, as well as other task and interrupt activity, will affect the frequency
+ * at which vTaskDelay() gets called and therefore the time at which the task
+ * next executes. See xTaskDelayUntil() for an alternative API function designed
+ * to facilitate fixed frequency execution. It does this by specifying an
+ * absolute time (rather than a relative time) at which the calling task should
+ * unblock.
+ *
+ * @param xTicksToDelay The amount of time, in tick periods, that
+ * the calling task should block.
+ *
+ * Example usage:
+ *
+ * void vTaskFunction( void * pvParameters )
+ * {
+ * // Block for 500ms.
+ * const TickType_t xDelay = 500 / portTICK_PERIOD_MS;
+ *
+ * for( ;; )
+ * {
+ * // Simply toggle the LED every 500ms, blocking between each toggle.
+ * vToggleLED();
+ * vTaskDelay( xDelay );
+ * }
+ * }
+ *
+ * \defgroup vTaskDelay vTaskDelay
+ * \ingroup TaskCtrl
+ */
+void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
+ * @endcode
+ *
+ * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Delay a task until a specified time. This function can be used by periodic
+ * tasks to ensure a constant execution frequency.
+ *
+ * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will
+ * cause a task to block for the specified number of ticks from the time vTaskDelay () is
+ * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed
+ * execution frequency as the time between a task starting to execute and that task
+ * calling vTaskDelay () may not be fixed [the task may take a different path though the
+ * code between calls, or may get interrupted or preempted a different number of times
+ * each time it executes].
+ *
+ * Whereas vTaskDelay () specifies a wake time relative to the time at which the function
+ * is called, xTaskDelayUntil () specifies the absolute (exact) time at which it wishes to
+ * unblock.
+ *
+ * The macro pdMS_TO_TICKS() can be used to calculate the number of ticks from a
+ * time specified in milliseconds with a resolution of one tick period.
+ *
+ * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the
+ * task was last unblocked. The variable must be initialised with the current time
+ * prior to its first use (see the example below). Following this the variable is
+ * automatically updated within xTaskDelayUntil ().
+ *
+ * @param xTimeIncrement The cycle time period. The task will be unblocked at
+ * time *pxPreviousWakeTime + xTimeIncrement. Calling xTaskDelayUntil with the
+ * same xTimeIncrement parameter value will cause the task to execute with
+ * a fixed interface period.
+ *
+ * @return Value which can be used to check whether the task was actually delayed.
+ * Will be pdTRUE if the task way delayed and pdFALSE otherwise. A task will not
+ * be delayed if the next expected wake time is in the past.
+ *
+ * Example usage:
+ * @code{c}
+ * // Perform an action every 10 ticks.
+ * void vTaskFunction( void * pvParameters )
+ * {
+ * TickType_t xLastWakeTime;
+ * const TickType_t xFrequency = 10;
+ * BaseType_t xWasDelayed;
+ *
+ * // Initialise the xLastWakeTime variable with the current time.
+ * xLastWakeTime = xTaskGetTickCount ();
+ * for( ;; )
+ * {
+ * // Wait for the next cycle.
+ * xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency );
+ *
+ * // Perform action here. xWasDelayed value can be used to determine
+ * // whether a deadline was missed if the code here took too long.
+ * }
+ * }
+ * @endcode
+ * \defgroup xTaskDelayUntil xTaskDelayUntil
+ * \ingroup TaskCtrl
+ */
+BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
+ const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION;
+
+/*
+ * vTaskDelayUntil() is the older version of xTaskDelayUntil() and does not
+ * return a value.
+ */
+#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) \
+ do { \
+ ( void ) xTaskDelayUntil( ( pxPreviousWakeTime ), ( xTimeIncrement ) ); \
+ } while( 0 )
+
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskAbortDelay( TaskHandle_t xTask );
+ * @endcode
+ *
+ * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this
+ * function to be available.
+ *
+ * A task will enter the Blocked state when it is waiting for an event. The
+ * event it is waiting for can be a temporal event (waiting for a time), such
+ * as when vTaskDelay() is called, or an event on an object, such as when
+ * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task
+ * that is in the Blocked state is used in a call to xTaskAbortDelay() then the
+ * task will leave the Blocked state, and return from whichever function call
+ * placed the task into the Blocked state.
+ *
+ * There is no 'FromISR' version of this function as an interrupt would need to
+ * know which object a task was blocked on in order to know which actions to
+ * take. For example, if the task was blocked on a queue the interrupt handler
+ * would then need to know if the queue was locked.
+ *
+ * @param xTask The handle of the task to remove from the Blocked state.
+ *
+ * @return If the task referenced by xTask was not in the Blocked state then
+ * pdFAIL is returned. Otherwise pdPASS is returned.
+ *
+ * \defgroup xTaskAbortDelay xTaskAbortDelay
+ * \ingroup TaskCtrl
+ */
+BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask );
+ * @endcode
+ *
+ * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Obtain the priority of any task.
+ *
+ * @param xTask Handle of the task to be queried. Passing a NULL
+ * handle results in the priority of the calling task being returned.
+ *
+ * @return The priority of xTask.
+ *
+ * Example usage:
+ * @code{c}
+ * void vAFunction( void )
+ * {
+ * TaskHandle_t xHandle;
+ *
+ * // Create a task, storing the handle.
+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+ *
+ * // ...
+ *
+ * // Use the handle to obtain the priority of the created task.
+ * // It was created with tskIDLE_PRIORITY, but may have changed
+ * // it itself.
+ * if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
+ * {
+ * // The task has changed it's priority.
+ * }
+ *
+ * // ...
+ *
+ * // Is our priority higher than the created task?
+ * if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
+ * {
+ * // Our priority (obtained using NULL handle) is higher.
+ * }
+ * }
+ * @endcode
+ * \defgroup uxTaskPriorityGet uxTaskPriorityGet
+ * \ingroup TaskCtrl
+ */
+UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask );
+ * @endcode
+ *
+ * A version of uxTaskPriorityGet() that can be used from an ISR.
+ */
+UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * eTaskState eTaskGetState( TaskHandle_t xTask );
+ * @endcode
+ *
+ * INCLUDE_eTaskGetState must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Obtain the state of any task. States are encoded by the eTaskState
+ * enumerated type.
+ *
+ * @param xTask Handle of the task to be queried.
+ *
+ * @return The state of xTask at the time the function was called. Note the
+ * state of the task might change between the function being called, and the
+ * functions return value being tested by the calling task.
+ */
+eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );
+ * @endcode
+ *
+ * configUSE_TRACE_FACILITY must be defined as 1 for this function to be
+ * available. See the configuration section for more information.
+ *
+ * Populates a TaskStatus_t structure with information about a task.
+ *
+ * @param xTask Handle of the task being queried. If xTask is NULL then
+ * information will be returned about the calling task.
+ *
+ * @param pxTaskStatus A pointer to the TaskStatus_t structure that will be
+ * filled with information about the task referenced by the handle passed using
+ * the xTask parameter.
+ *
+ * @param xGetFreeStackSpace The TaskStatus_t structure contains a member to report
+ * the stack high water mark of the task being queried. Calculating the stack
+ * high water mark takes a relatively long time, and can make the system
+ * temporarily unresponsive - so the xGetFreeStackSpace parameter is provided to
+ * allow the high water mark checking to be skipped. The high watermark value
+ * will only be written to the TaskStatus_t structure if xGetFreeStackSpace is
+ * not set to pdFALSE;
+ *
+ * @param eState The TaskStatus_t structure contains a member to report the
+ * state of the task being queried. Obtaining the task state is not as fast as
+ * a simple assignment - so the eState parameter is provided to allow the state
+ * information to be omitted from the TaskStatus_t structure. To obtain state
+ * information then set eState to eInvalid - otherwise the value passed in
+ * eState will be reported as the task state in the TaskStatus_t structure.
+ *
+ * Example usage:
+ * @code{c}
+ * void vAFunction( void )
+ * {
+ * TaskHandle_t xHandle;
+ * TaskStatus_t xTaskDetails;
+ *
+ * // Obtain the handle of a task from its name.
+ * xHandle = xTaskGetHandle( "Task_Name" );
+ *
+ * // Check the handle is not NULL.
+ * configASSERT( xHandle );
+ *
+ * // Use the handle to obtain further information about the task.
+ * vTaskGetInfo( xHandle,
+ * &xTaskDetails,
+ * pdTRUE, // Include the high water mark in xTaskDetails.
+ * eInvalid ); // Include the task state in xTaskDetails.
+ * }
+ * @endcode
+ * \defgroup vTaskGetInfo vTaskGetInfo
+ * \ingroup TaskCtrl
+ */
+void vTaskGetInfo( TaskHandle_t xTask,
+ TaskStatus_t * pxTaskStatus,
+ BaseType_t xGetFreeStackSpace,
+ eTaskState eState ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
+ * @endcode
+ *
+ * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Set the priority of any task.
+ *
+ * A context switch will occur before the function returns if the priority
+ * being set is higher than the currently executing task.
+ *
+ * @param xTask Handle to the task for which the priority is being set.
+ * Passing a NULL handle results in the priority of the calling task being set.
+ *
+ * @param uxNewPriority The priority to which the task will be set.
+ *
+ * Example usage:
+ * @code{c}
+ * void vAFunction( void )
+ * {
+ * TaskHandle_t xHandle;
+ *
+ * // Create a task, storing the handle.
+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+ *
+ * // ...
+ *
+ * // Use the handle to raise the priority of the created task.
+ * vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
+ *
+ * // ...
+ *
+ * // Use a NULL handle to raise our priority to the same value.
+ * vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
+ * }
+ * @endcode
+ * \defgroup vTaskPrioritySet vTaskPrioritySet
+ * \ingroup TaskCtrl
+ */
+void vTaskPrioritySet( TaskHandle_t xTask,
+ UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskSuspend( TaskHandle_t xTaskToSuspend );
+ * @endcode
+ *
+ * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Suspend any task. When suspended a task will never get any microcontroller
+ * processing time, no matter what its priority.
+ *
+ * Calls to vTaskSuspend are not accumulative -
+ * i.e. calling vTaskSuspend () twice on the same task still only requires one
+ * call to vTaskResume () to ready the suspended task.
+ *
+ * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL
+ * handle will cause the calling task to be suspended.
+ *
+ * Example usage:
+ * @code{c}
+ * void vAFunction( void )
+ * {
+ * TaskHandle_t xHandle;
+ *
+ * // Create a task, storing the handle.
+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+ *
+ * // ...
+ *
+ * // Use the handle to suspend the created task.
+ * vTaskSuspend( xHandle );
+ *
+ * // ...
+ *
+ * // The created task will not run during this period, unless
+ * // another task calls vTaskResume( xHandle ).
+ *
+ * //...
+ *
+ *
+ * // Suspend ourselves.
+ * vTaskSuspend( NULL );
+ *
+ * // We cannot get here unless another task calls vTaskResume
+ * // with our handle as the parameter.
+ * }
+ * @endcode
+ * \defgroup vTaskSuspend vTaskSuspend
+ * \ingroup TaskCtrl
+ */
+void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskResume( TaskHandle_t xTaskToResume );
+ * @endcode
+ *
+ * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Resumes a suspended task.
+ *
+ * A task that has been suspended by one or more calls to vTaskSuspend ()
+ * will be made available for running again by a single call to
+ * vTaskResume ().
+ *
+ * @param xTaskToResume Handle to the task being readied.
+ *
+ * Example usage:
+ * @code{c}
+ * void vAFunction( void )
+ * {
+ * TaskHandle_t xHandle;
+ *
+ * // Create a task, storing the handle.
+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+ *
+ * // ...
+ *
+ * // Use the handle to suspend the created task.
+ * vTaskSuspend( xHandle );
+ *
+ * // ...
+ *
+ * // The created task will not run during this period, unless
+ * // another task calls vTaskResume( xHandle ).
+ *
+ * //...
+ *
+ *
+ * // Resume the suspended task ourselves.
+ * vTaskResume( xHandle );
+ *
+ * // The created task will once again get microcontroller processing
+ * // time in accordance with its priority within the system.
+ * }
+ * @endcode
+ * \defgroup vTaskResume vTaskResume
+ * \ingroup TaskCtrl
+ */
+void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * void xTaskResumeFromISR( TaskHandle_t xTaskToResume );
+ * @endcode
+ *
+ * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be
+ * available. See the configuration section for more information.
+ *
+ * An implementation of vTaskResume() that can be called from within an ISR.
+ *
+ * A task that has been suspended by one or more calls to vTaskSuspend ()
+ * will be made available for running again by a single call to
+ * xTaskResumeFromISR ().
+ *
+ * xTaskResumeFromISR() should not be used to synchronise a task with an
+ * interrupt if there is a chance that the interrupt could arrive prior to the
+ * task being suspended - as this can lead to interrupts being missed. Use of a
+ * semaphore as a synchronisation mechanism would avoid this eventuality.
+ *
+ * @param xTaskToResume Handle to the task being readied.
+ *
+ * @return pdTRUE if resuming the task should result in a context switch,
+ * otherwise pdFALSE. This is used by the ISR to determine if a context switch
+ * may be required following the ISR.
+ *
+ * \defgroup vTaskResumeFromISR vTaskResumeFromISR
+ * \ingroup TaskCtrl
+ */
+BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
+
+/*-----------------------------------------------------------
+* SCHEDULER CONTROL
+*----------------------------------------------------------*/
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskStartScheduler( void );
+ * @endcode
+ *
+ * Starts the real time kernel tick processing. After calling the kernel
+ * has control over which tasks are executed and when.
+ *
+ * See the demo application file main.c for an example of creating
+ * tasks and starting the kernel.
+ *
+ * Example usage:
+ * @code{c}
+ * void vAFunction( void )
+ * {
+ * // Create at least one task before starting the kernel.
+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+ *
+ * // Start the real time kernel with preemption.
+ * vTaskStartScheduler ();
+ *
+ * // Will not get here unless a task calls vTaskEndScheduler ()
+ * }
+ * @endcode
+ *
+ * \defgroup vTaskStartScheduler vTaskStartScheduler
+ * \ingroup SchedulerControl
+ */
+void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskEndScheduler( void );
+ * @endcode
+ *
+ * NOTE: At the time of writing only the x86 real mode port, which runs on a PC
+ * in place of DOS, implements this function.
+ *
+ * Stops the real time kernel tick. All created tasks will be automatically
+ * deleted and multitasking (either preemptive or cooperative) will
+ * stop. Execution then resumes from the point where vTaskStartScheduler ()
+ * was called, as if vTaskStartScheduler () had just returned.
+ *
+ * See the demo application file main. c in the demo/PC directory for an
+ * example that uses vTaskEndScheduler ().
+ *
+ * vTaskEndScheduler () requires an exit function to be defined within the
+ * portable layer (see vPortEndScheduler () in port. c for the PC port). This
+ * performs hardware specific operations such as stopping the kernel tick.
+ *
+ * vTaskEndScheduler () will cause all of the resources allocated by the
+ * kernel to be freed - but will not free resources allocated by application
+ * tasks.
+ *
+ * Example usage:
+ * @code{c}
+ * void vTaskCode( void * pvParameters )
+ * {
+ * for( ;; )
+ * {
+ * // Task code goes here.
+ *
+ * // At some point we want to end the real time kernel processing
+ * // so call ...
+ * vTaskEndScheduler ();
+ * }
+ * }
+ *
+ * void vAFunction( void )
+ * {
+ * // Create at least one task before starting the kernel.
+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+ *
+ * // Start the real time kernel with preemption.
+ * vTaskStartScheduler ();
+ *
+ * // Will only get here when the vTaskCode () task has called
+ * // vTaskEndScheduler (). When we get here we are back to single task
+ * // execution.
+ * }
+ * @endcode
+ *
+ * \defgroup vTaskEndScheduler vTaskEndScheduler
+ * \ingroup SchedulerControl
+ */
+void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskSuspendAll( void );
+ * @endcode
+ *
+ * Suspends the scheduler without disabling interrupts. Context switches will
+ * not occur while the scheduler is suspended.
+ *
+ * After calling vTaskSuspendAll () the calling task will continue to execute
+ * without risk of being swapped out until a call to xTaskResumeAll () has been
+ * made.
+ *
+ * API functions that have the potential to cause a context switch (for example,
+ * xTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler
+ * is suspended.
+ *
+ * Example usage:
+ * @code{c}
+ * void vTask1( void * pvParameters )
+ * {
+ * for( ;; )
+ * {
+ * // Task code goes here.
+ *
+ * // ...
+ *
+ * // At some point the task wants to perform a long operation during
+ * // which it does not want to get swapped out. It cannot use
+ * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+ * // operation may cause interrupts to be missed - including the
+ * // ticks.
+ *
+ * // Prevent the real time kernel swapping out the task.
+ * vTaskSuspendAll ();
+ *
+ * // Perform the operation here. There is no need to use critical
+ * // sections as we have all the microcontroller processing time.
+ * // During this time interrupts will still operate and the kernel
+ * // tick count will be maintained.
+ *
+ * // ...
+ *
+ * // The operation is complete. Restart the kernel.
+ * xTaskResumeAll ();
+ * }
+ * }
+ * @endcode
+ * \defgroup vTaskSuspendAll vTaskSuspendAll
+ * \ingroup SchedulerControl
+ */
+void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskResumeAll( void );
+ * @endcode
+ *
+ * Resumes scheduler activity after it was suspended by a call to
+ * vTaskSuspendAll().
+ *
+ * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks
+ * that were previously suspended by a call to vTaskSuspend().
+ *
+ * @return If resuming the scheduler caused a context switch then pdTRUE is
+ * returned, otherwise pdFALSE is returned.
+ *
+ * Example usage:
+ * @code{c}
+ * void vTask1( void * pvParameters )
+ * {
+ * for( ;; )
+ * {
+ * // Task code goes here.
+ *
+ * // ...
+ *
+ * // At some point the task wants to perform a long operation during
+ * // which it does not want to get swapped out. It cannot use
+ * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+ * // operation may cause interrupts to be missed - including the
+ * // ticks.
+ *
+ * // Prevent the real time kernel swapping out the task.
+ * vTaskSuspendAll ();
+ *
+ * // Perform the operation here. There is no need to use critical
+ * // sections as we have all the microcontroller processing time.
+ * // During this time interrupts will still operate and the real
+ * // time kernel tick count will be maintained.
+ *
+ * // ...
+ *
+ * // The operation is complete. Restart the kernel. We want to force
+ * // a context switch - but there is no point if resuming the scheduler
+ * // caused a context switch already.
+ * if( !xTaskResumeAll () )
+ * {
+ * taskYIELD ();
+ * }
+ * }
+ * }
+ * @endcode
+ * \defgroup xTaskResumeAll xTaskResumeAll
+ * \ingroup SchedulerControl
+ */
+BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION;
+
+/*-----------------------------------------------------------
+* TASK UTILITIES
+*----------------------------------------------------------*/
+
+/**
+ * task. h
+ * @code{c}
+ * TickType_t xTaskGetTickCount( void );
+ * @endcode
+ *
+ * @return The count of ticks since vTaskStartScheduler was called.
+ *
+ * \defgroup xTaskGetTickCount xTaskGetTickCount
+ * \ingroup TaskUtils
+ */
+TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * TickType_t xTaskGetTickCountFromISR( void );
+ * @endcode
+ *
+ * @return The count of ticks since vTaskStartScheduler was called.
+ *
+ * This is a version of xTaskGetTickCount() that is safe to be called from an
+ * ISR - provided that TickType_t is the natural word size of the
+ * microcontroller being used or interrupt nesting is either not supported or
+ * not being used.
+ *
+ * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR
+ * \ingroup TaskUtils
+ */
+TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * uint16_t uxTaskGetNumberOfTasks( void );
+ * @endcode
+ *
+ * @return The number of tasks that the real time kernel is currently managing.
+ * This includes all ready, blocked and suspended tasks. A task that
+ * has been deleted but not yet freed by the idle task will also be
+ * included in the count.
+ *
+ * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks
+ * \ingroup TaskUtils
+ */
+UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * char *pcTaskGetName( TaskHandle_t xTaskToQuery );
+ * @endcode
+ *
+ * @return The text (human readable) name of the task referenced by the handle
+ * xTaskToQuery. A task can query its own name by either passing in its own
+ * handle, or by setting xTaskToQuery to NULL.
+ *
+ * \defgroup pcTaskGetName pcTaskGetName
+ * \ingroup TaskUtils
+ */
+char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+/**
+ * task. h
+ * @code{c}
+ * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );
+ * @endcode
+ *
+ * NOTE: This function takes a relatively long time to complete and should be
+ * used sparingly.
+ *
+ * @return The handle of the task that has the human readable name pcNameToQuery.
+ * NULL is returned if no matching name is found. INCLUDE_xTaskGetHandle
+ * must be set to 1 in FreeRTOSConfig.h for pcTaskGetHandle() to be available.
+ *
+ * \defgroup pcTaskGetHandle pcTaskGetHandle
+ * \ingroup TaskUtils
+ */
+TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+/**
+ * task.h
+ * @code{c}
+ * UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
+ * @endcode
+ *
+ * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for
+ * this function to be available.
+ *
+ * Returns the high water mark of the stack associated with xTask. That is,
+ * the minimum free stack space there has been (in words, so on a 32 bit machine
+ * a value of 1 means 4 bytes) since the task started. The smaller the returned
+ * number the closer the task has come to overflowing its stack.
+ *
+ * uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
+ * same except for their return type. Using configSTACK_DEPTH_TYPE allows the
+ * user to determine the return type. It gets around the problem of the value
+ * overflowing on 8-bit types without breaking backward compatibility for
+ * applications that expect an 8-bit return type.
+ *
+ * @param xTask Handle of the task associated with the stack to be checked.
+ * Set xTask to NULL to check the stack of the calling task.
+ *
+ * @return The smallest amount of free stack space there has been (in words, so
+ * actual spaces on the stack rather than bytes) since the task referenced by
+ * xTask was created.
+ */
+UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
+/**
+ * task.h
+ * @code{c}
+ * configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask );
+ * @endcode
+ *
+ * INCLUDE_uxTaskGetStackHighWaterMark2 must be set to 1 in FreeRTOSConfig.h for
+ * this function to be available.
+ *
+ * Returns the high water mark of the stack associated with xTask. That is,
+ * the minimum free stack space there has been (in words, so on a 32 bit machine
+ * a value of 1 means 4 bytes) since the task started. The smaller the returned
+ * number the closer the task has come to overflowing its stack.
+ *
+ * uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
+ * same except for their return type. Using configSTACK_DEPTH_TYPE allows the
+ * user to determine the return type. It gets around the problem of the value
+ * overflowing on 8-bit types without breaking backward compatibility for
+ * applications that expect an 8-bit return type.
+ *
+ * @param xTask Handle of the task associated with the stack to be checked.
+ * Set xTask to NULL to check the stack of the calling task.
+ *
+ * @return The smallest amount of free stack space there has been (in words, so
+ * actual spaces on the stack rather than bytes) since the task referenced by
+ * xTask was created.
+ */
+configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
+/* When using trace macros it is sometimes necessary to include task.h before
+ * FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined,
+ * so the following two prototypes will cause a compilation error. This can be
+ * fixed by simply guarding against the inclusion of these two prototypes unless
+ * they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration
+ * constant. */
+#ifdef configUSE_APPLICATION_TASK_TAG
+ #if configUSE_APPLICATION_TASK_TAG == 1
+
+/**
+ * task.h
+ * @code{c}
+ * void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
+ * @endcode
+ *
+ * Sets pxHookFunction to be the task hook function used by the task xTask.
+ * Passing xTask as NULL has the effect of setting the calling tasks hook
+ * function.
+ */
+ void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
+ TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION;
+
+/**
+ * task.h
+ * @code{c}
+ * void xTaskGetApplicationTaskTag( TaskHandle_t xTask );
+ * @endcode
+ *
+ * Returns the pxHookFunction value assigned to the task xTask. Do not
+ * call from an interrupt service routine - call
+ * xTaskGetApplicationTaskTagFromISR() instead.
+ */
+ TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
+/**
+ * task.h
+ * @code{c}
+ * void xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask );
+ * @endcode
+ *
+ * Returns the pxHookFunction value assigned to the task xTask. Can
+ * be called from an interrupt service routine.
+ */
+ TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+ #endif /* configUSE_APPLICATION_TASK_TAG ==1 */
+#endif /* ifdef configUSE_APPLICATION_TASK_TAG */
+
+#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
+
+/* Each task contains an array of pointers that is dimensioned by the
+ * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The
+ * kernel does not use the pointers itself, so the application writer can use
+ * the pointers for any purpose they wish. The following two functions are
+ * used to set and query a pointer respectively. */
+ void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
+ BaseType_t xIndex,
+ void * pvValue ) PRIVILEGED_FUNCTION;
+ void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
+ BaseType_t xIndex ) PRIVILEGED_FUNCTION;
+
+#endif
+
+#if ( configCHECK_FOR_STACK_OVERFLOW > 0 )
+
+/**
+ * task.h
+ * @code{c}
+ * void vApplicationStackOverflowHook( TaskHandle_t xTask char *pcTaskName);
+ * @endcode
+ *
+ * The application stack overflow hook is called when a stack overflow is detected for a task.
+ *
+ * Details on stack overflow detection can be found here: https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html
+ *
+ * @param xTask the task that just exceeded its stack boundaries.
+ * @param pcTaskName A character string containing the name of the offending task.
+ */
+ void vApplicationStackOverflowHook( TaskHandle_t xTask,
+ char * pcTaskName );
+
+#endif
+
+#if ( configUSE_TICK_HOOK > 0 )
+
+/**
+ * task.h
+ * @code{c}
+ * void vApplicationTickHook( void );
+ * @endcode
+ *
+ * This hook function is called in the system tick handler after any OS work is completed.
+ */
+ void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an application callback. */
+
+#endif
+
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+/**
+ * task.h
+ * @code{c}
+ * void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
+ * @endcode
+ *
+ * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Idle Task TCB. This function is required when
+ * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION
+ *
+ * @param ppxIdleTaskTCBBuffer A handle to a statically allocated TCB buffer
+ * @param ppxIdleTaskStackBuffer A handle to a statically allocated Stack buffer for the idle task
+ * @param pulIdleTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer
+ */
+ void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
+ StackType_t ** ppxIdleTaskStackBuffer,
+ uint32_t * pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is an application callback. */
+#endif
+
+/**
+ * task.h
+ * @code{c}
+ * BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
+ * @endcode
+ *
+ * Calls the hook function associated with xTask. Passing xTask as NULL has
+ * the effect of calling the Running tasks (the calling task) hook function.
+ *
+ * pvParameter is passed to the hook function for the task to interpret as it
+ * wants. The return value is the value returned by the task hook function
+ * registered by the user.
+ */
+BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
+ void * pvParameter ) PRIVILEGED_FUNCTION;
+
+/**
+ * xTaskGetIdleTaskHandle() is only available if
+ * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h.
+ *
+ * Simply returns the handle of the idle task. It is not valid to call
+ * xTaskGetIdleTaskHandle() before the scheduler has been started.
+ */
+TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for
+ * uxTaskGetSystemState() to be available.
+ *
+ * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in
+ * the system. TaskStatus_t structures contain, among other things, members
+ * for the task handle, task name, task priority, task state, and total amount
+ * of run time consumed by the task. See the TaskStatus_t structure
+ * definition in this file for the full member list.
+ *
+ * NOTE: This function is intended for debugging use only as its use results in
+ * the scheduler remaining suspended for an extended period.
+ *
+ * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures.
+ * The array must contain at least one TaskStatus_t structure for each task
+ * that is under the control of the RTOS. The number of tasks under the control
+ * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function.
+ *
+ * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray
+ * parameter. The size is specified as the number of indexes in the array, or
+ * the number of TaskStatus_t structures contained in the array, not by the
+ * number of bytes in the array.
+ *
+ * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in
+ * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to the
+ * total run time (as defined by the run time stats clock, see
+ * https://www.FreeRTOS.org/rtos-run-time-stats.html) since the target booted.
+ * pulTotalRunTime can be set to NULL to omit the total run time information.
+ *
+ * @return The number of TaskStatus_t structures that were populated by
+ * uxTaskGetSystemState(). This should equal the number returned by the
+ * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed
+ * in the uxArraySize parameter was too small.
+ *
+ * Example usage:
+ * @code{c}
+ * // This example demonstrates how a human readable table of run time stats
+ * // information is generated from raw data provided by uxTaskGetSystemState().
+ * // The human readable table is written to pcWriteBuffer
+ * void vTaskGetRunTimeStats( char *pcWriteBuffer )
+ * {
+ * TaskStatus_t *pxTaskStatusArray;
+ * volatile UBaseType_t uxArraySize, x;
+ * configRUN_TIME_COUNTER_TYPE ulTotalRunTime, ulStatsAsPercentage;
+ *
+ * // Make sure the write buffer does not contain a string.
+ * pcWriteBuffer = 0x00;
+ *
+ * // Take a snapshot of the number of tasks in case it changes while this
+ * // function is executing.
+ * uxArraySize = uxTaskGetNumberOfTasks();
+ *
+ * // Allocate a TaskStatus_t structure for each task. An array could be
+ * // allocated statically at compile time.
+ * pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
+ *
+ * if( pxTaskStatusArray != NULL )
+ * {
+ * // Generate raw status information about each task.
+ * uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
+ *
+ * // For percentage calculations.
+ * ulTotalRunTime /= 100UL;
+ *
+ * // Avoid divide by zero errors.
+ * if( ulTotalRunTime > 0 )
+ * {
+ * // For each populated position in the pxTaskStatusArray array,
+ * // format the raw data as human readable ASCII data
+ * for( x = 0; x < uxArraySize; x++ )
+ * {
+ * // What percentage of the total run time has the task used?
+ * // This will always be rounded down to the nearest integer.
+ * // ulTotalRunTimeDiv100 has already been divided by 100.
+ * ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
+ *
+ * if( ulStatsAsPercentage > 0UL )
+ * {
+ * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
+ * }
+ * else
+ * {
+ * // If the percentage is zero here then the task has
+ * // consumed less than 1% of the total run time.
+ * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
+ * }
+ *
+ * pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
+ * }
+ * }
+ *
+ * // The array is no longer needed, free the memory it consumes.
+ * vPortFree( pxTaskStatusArray );
+ * }
+ * }
+ * @endcode
+ */
+UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
+ const UBaseType_t uxArraySize,
+ configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskList( char *pcWriteBuffer );
+ * @endcode
+ *
+ * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must
+ * both be defined as 1 for this function to be available. See the
+ * configuration section of the FreeRTOS.org website for more information.
+ *
+ * NOTE 1: This function will disable interrupts for its duration. It is
+ * not intended for normal application runtime use but as a debug aid.
+ *
+ * Lists all the current tasks, along with their current state and stack
+ * usage high water mark.
+ *
+ * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or
+ * suspended ('S').
+ *
+ * PLEASE NOTE:
+ *
+ * This function is provided for convenience only, and is used by many of the
+ * demo applications. Do not consider it to be part of the scheduler.
+ *
+ * vTaskList() calls uxTaskGetSystemState(), then formats part of the
+ * uxTaskGetSystemState() output into a human readable table that displays task:
+ * names, states, priority, stack usage and task number.
+ * Stack usage specified as the number of unused StackType_t words stack can hold
+ * on top of stack - not the number of bytes.
+ *
+ * vTaskList() has a dependency on the sprintf() C library function that might
+ * bloat the code size, use a lot of stack, and provide different results on
+ * different platforms. An alternative, tiny, third party, and limited
+ * functionality implementation of sprintf() is provided in many of the
+ * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note
+ * printf-stdarg.c does not provide a full snprintf() implementation!).
+ *
+ * It is recommended that production systems call uxTaskGetSystemState()
+ * directly to get access to raw stats data, rather than indirectly through a
+ * call to vTaskList().
+ *
+ * @param pcWriteBuffer A buffer into which the above mentioned details
+ * will be written, in ASCII form. This buffer is assumed to be large
+ * enough to contain the generated report. Approximately 40 bytes per
+ * task should be sufficient.
+ *
+ * \defgroup vTaskList vTaskList
+ * \ingroup TaskUtils
+ */
+void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskGetRunTimeStats( char *pcWriteBuffer );
+ * @endcode
+ *
+ * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS
+ * must both be defined as 1 for this function to be available. The application
+ * must also then provide definitions for
+ * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE()
+ * to configure a peripheral timer/counter and return the timers current count
+ * value respectively. The counter should be at least 10 times the frequency of
+ * the tick count.
+ *
+ * NOTE 1: This function will disable interrupts for its duration. It is
+ * not intended for normal application runtime use but as a debug aid.
+ *
+ * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total
+ * accumulated execution time being stored for each task. The resolution
+ * of the accumulated time value depends on the frequency of the timer
+ * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro.
+ * Calling vTaskGetRunTimeStats() writes the total execution time of each
+ * task into a buffer, both as an absolute count value and as a percentage
+ * of the total system execution time.
+ *
+ * NOTE 2:
+ *
+ * This function is provided for convenience only, and is used by many of the
+ * demo applications. Do not consider it to be part of the scheduler.
+ *
+ * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part of the
+ * uxTaskGetSystemState() output into a human readable table that displays the
+ * amount of time each task has spent in the Running state in both absolute and
+ * percentage terms.
+ *
+ * vTaskGetRunTimeStats() has a dependency on the sprintf() C library function
+ * that might bloat the code size, use a lot of stack, and provide different
+ * results on different platforms. An alternative, tiny, third party, and
+ * limited functionality implementation of sprintf() is provided in many of the
+ * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note
+ * printf-stdarg.c does not provide a full snprintf() implementation!).
+ *
+ * It is recommended that production systems call uxTaskGetSystemState() directly
+ * to get access to raw stats data, rather than indirectly through a call to
+ * vTaskGetRunTimeStats().
+ *
+ * @param pcWriteBuffer A buffer into which the execution times will be
+ * written, in ASCII form. This buffer is assumed to be large enough to
+ * contain the generated report. Approximately 40 bytes per task should
+ * be sufficient.
+ *
+ * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats
+ * \ingroup TaskUtils
+ */
+void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+/**
+ * task. h
+ * @code{c}
+ * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void );
+ * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void );
+ * @endcode
+ *
+ * configGENERATE_RUN_TIME_STATS, configUSE_STATS_FORMATTING_FUNCTIONS and
+ * INCLUDE_xTaskGetIdleTaskHandle must all be defined as 1 for these functions
+ * to be available. The application must also then provide definitions for
+ * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE()
+ * to configure a peripheral timer/counter and return the timers current count
+ * value respectively. The counter should be at least 10 times the frequency of
+ * the tick count.
+ *
+ * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total
+ * accumulated execution time being stored for each task. The resolution
+ * of the accumulated time value depends on the frequency of the timer
+ * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro.
+ * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total
+ * execution time of each task into a buffer, ulTaskGetIdleRunTimeCounter()
+ * returns the total execution time of just the idle task and
+ * ulTaskGetIdleRunTimePercent() returns the percentage of the CPU time used by
+ * just the idle task.
+ *
+ * Note the amount of idle time is only a good measure of the slack time in a
+ * system if there are no other tasks executing at the idle priority, tickless
+ * idle is not used, and configIDLE_SHOULD_YIELD is set to 0.
+ *
+ * @return The total run time of the idle task or the percentage of the total
+ * run time consumed by the idle task. This is the amount of time the
+ * idle task has actually been executing. The unit of time is dependent on the
+ * frequency configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and
+ * portGET_RUN_TIME_COUNTER_VALUE() macros.
+ *
+ * \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter
+ * \ingroup TaskUtils
+ */
+configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION;
+configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction );
+ * BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Sends a direct to task notification to a task, with an optional value and
+ * action.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t). The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * Events can be sent to a task using an intermediary object. Examples of such
+ * objects are queues, semaphores, mutexes and event groups. Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values. In
+ * that way task notifications can be used to send data to a task, or be used as
+ * light weight and fast binary or counting semaphores.
+ *
+ * A task can use xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() to
+ * [optionally] block to wait for a notification to be pending. The task does
+ * not consume any CPU time while it is in the Blocked state.
+ *
+ * A notification sent to a task will remain pending until it is cleared by the
+ * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their
+ * un-indexed equivalents). If the task was already in the Blocked state to
+ * wait for a notification when the notification arrives then the task will
+ * automatically be removed from the Blocked state (unblocked) and the
+ * notification cleared.
+ *
+ * **NOTE** Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not be
+ * unblocked by a notification sent to any other array index.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array. xTaskNotify() is the original API function, and remains backward
+ * compatible by always operating on the notification value at index 0 in the
+ * array. Calling xTaskNotify() is equivalent to calling xTaskNotifyIndexed()
+ * with the uxIndexToNotify parameter set to 0.
+ *
+ * @param xTaskToNotify The handle of the task being notified. The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param uxIndexToNotify The index within the target task's array of
+ * notification values to which the notification is to be sent. uxIndexToNotify
+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotify() does
+ * not have this parameter and always sends notifications to index 0.
+ *
+ * @param ulValue Data that can be sent with the notification. How the data is
+ * used depends on the value of the eAction parameter.
+ *
+ * @param eAction Specifies how the notification updates the task's notification
+ * value, if at all. Valid values for eAction are as follows:
+ *
+ * eSetBits -
+ * The target notification value is bitwise ORed with ulValue.
+ * xTaskNotifyIndexed() always returns pdPASS in this case.
+ *
+ * eIncrement -
+ * The target notification value is incremented. ulValue is not used and
+ * xTaskNotifyIndexed() always returns pdPASS in this case.
+ *
+ * eSetValueWithOverwrite -
+ * The target notification value is set to the value of ulValue, even if the
+ * task being notified had not yet processed the previous notification at the
+ * same array index (the task already had a notification pending at that index).
+ * xTaskNotifyIndexed() always returns pdPASS in this case.
+ *
+ * eSetValueWithoutOverwrite -
+ * If the task being notified did not already have a notification pending at the
+ * same array index then the target notification value is set to ulValue and
+ * xTaskNotifyIndexed() will return pdPASS. If the task being notified already
+ * had a notification pending at the same array index then no action is
+ * performed and pdFAIL is returned.
+ *
+ * eNoAction -
+ * The task receives a notification at the specified array index without the
+ * notification value at that index being updated. ulValue is not used and
+ * xTaskNotifyIndexed() always returns pdPASS in this case.
+ *
+ * pulPreviousNotificationValue -
+ * Can be used to pass out the subject task's notification value before any
+ * bits are modified by the notify function.
+ *
+ * @return Dependent on the value of eAction. See the description of the
+ * eAction parameter.
+ *
+ * \defgroup xTaskNotifyIndexed xTaskNotifyIndexed
+ * \ingroup TaskNotifications
+ */
+BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
+ UBaseType_t uxIndexToNotify,
+ uint32_t ulValue,
+ eNotifyAction eAction,
+ uint32_t * pulPreviousNotificationValue ) PRIVILEGED_FUNCTION;
+#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \
+ xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL )
+#define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \
+ xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL )
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue );
+ * BaseType_t xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * xTaskNotifyAndQueryIndexed() performs the same operation as
+ * xTaskNotifyIndexed() with the addition that it also returns the subject
+ * task's prior notification value (the notification value at the time the
+ * function is called rather than when the function returns) in the additional
+ * pulPreviousNotifyValue parameter.
+ *
+ * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the
+ * addition that it also returns the subject task's prior notification value
+ * (the notification value as it was at the time the function is called, rather
+ * than when the function returns) in the additional pulPreviousNotifyValue
+ * parameter.
+ *
+ * \defgroup xTaskNotifyAndQueryIndexed xTaskNotifyAndQueryIndexed
+ * \ingroup TaskNotifications
+ */
+#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) \
+ xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) )
+#define xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotifyValue ) \
+ xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) )
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
+ * BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * A version of xTaskNotifyIndexed() that can be used from an interrupt service
+ * routine (ISR).
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t). The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * Events can be sent to a task using an intermediary object. Examples of such
+ * objects are queues, semaphores, mutexes and event groups. Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values. In
+ * that way task notifications can be used to send data to a task, or be used as
+ * light weight and fast binary or counting semaphores.
+ *
+ * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a
+ * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block
+ * to wait for a notification value to have a non-zero value. The task does
+ * not consume any CPU time while it is in the Blocked state.
+ *
+ * A notification sent to a task will remain pending until it is cleared by the
+ * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their
+ * un-indexed equivalents). If the task was already in the Blocked state to
+ * wait for a notification when the notification arrives then the task will
+ * automatically be removed from the Blocked state (unblocked) and the
+ * notification cleared.
+ *
+ * **NOTE** Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not be
+ * unblocked by a notification sent to any other array index.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array. xTaskNotifyFromISR() is the original API function, and remains
+ * backward compatible by always operating on the notification value at index 0
+ * within the array. Calling xTaskNotifyFromISR() is equivalent to calling
+ * xTaskNotifyIndexedFromISR() with the uxIndexToNotify parameter set to 0.
+ *
+ * @param uxIndexToNotify The index within the target task's array of
+ * notification values to which the notification is to be sent. uxIndexToNotify
+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyFromISR()
+ * does not have this parameter and always sends notifications to index 0.
+ *
+ * @param xTaskToNotify The handle of the task being notified. The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param ulValue Data that can be sent with the notification. How the data is
+ * used depends on the value of the eAction parameter.
+ *
+ * @param eAction Specifies how the notification updates the task's notification
+ * value, if at all. Valid values for eAction are as follows:
+ *
+ * eSetBits -
+ * The task's notification value is bitwise ORed with ulValue. xTaskNotify()
+ * always returns pdPASS in this case.
+ *
+ * eIncrement -
+ * The task's notification value is incremented. ulValue is not used and
+ * xTaskNotify() always returns pdPASS in this case.
+ *
+ * eSetValueWithOverwrite -
+ * The task's notification value is set to the value of ulValue, even if the
+ * task being notified had not yet processed the previous notification (the
+ * task already had a notification pending). xTaskNotify() always returns
+ * pdPASS in this case.
+ *
+ * eSetValueWithoutOverwrite -
+ * If the task being notified did not already have a notification pending then
+ * the task's notification value is set to ulValue and xTaskNotify() will
+ * return pdPASS. If the task being notified already had a notification
+ * pending then no action is performed and pdFAIL is returned.
+ *
+ * eNoAction -
+ * The task receives a notification without its notification value being
+ * updated. ulValue is not used and xTaskNotify() always returns pdPASS in
+ * this case.
+ *
+ * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
+ * task to which the notification was sent to leave the Blocked state, and the
+ * unblocked task has a priority higher than the currently running task. If
+ * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should
+ * be requested before the interrupt is exited. How a context switch is
+ * requested from an ISR is dependent on the port - see the documentation page
+ * for the port in use.
+ *
+ * @return Dependent on the value of eAction. See the description of the
+ * eAction parameter.
+ *
+ * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR
+ * \ingroup TaskNotifications
+ */
+BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
+ UBaseType_t uxIndexToNotify,
+ uint32_t ulValue,
+ eNotifyAction eAction,
+ uint32_t * pulPreviousNotificationValue,
+ BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \
+ xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) )
+#define xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \
+ xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken );
+ * BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * xTaskNotifyAndQueryIndexedFromISR() performs the same operation as
+ * xTaskNotifyIndexedFromISR() with the addition that it also returns the
+ * subject task's prior notification value (the notification value at the time
+ * the function is called rather than at the time the function returns) in the
+ * additional pulPreviousNotifyValue parameter.
+ *
+ * xTaskNotifyAndQueryFromISR() performs the same operation as
+ * xTaskNotifyFromISR() with the addition that it also returns the subject
+ * task's prior notification value (the notification value at the time the
+ * function is called rather than at the time the function returns) in the
+ * additional pulPreviousNotifyValue parameter.
+ *
+ * \defgroup xTaskNotifyAndQueryIndexedFromISR xTaskNotifyAndQueryIndexedFromISR
+ * \ingroup TaskNotifications
+ */
+#define xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \
+ xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) )
+#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \
+ xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
+ *
+ * BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
+ * @endcode
+ *
+ * Waits for a direct to task notification to be pending at a given index within
+ * an array of direct to task notifications.
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this
+ * function to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t). The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * Events can be sent to a task using an intermediary object. Examples of such
+ * objects are queues, semaphores, mutexes and event groups. Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values. In
+ * that way task notifications can be used to send data to a task, or be used as
+ * light weight and fast binary or counting semaphores.
+ *
+ * A notification sent to a task will remain pending until it is cleared by the
+ * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their
+ * un-indexed equivalents). If the task was already in the Blocked state to
+ * wait for a notification when the notification arrives then the task will
+ * automatically be removed from the Blocked state (unblocked) and the
+ * notification cleared.
+ *
+ * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a
+ * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block
+ * to wait for a notification value to have a non-zero value. The task does
+ * not consume any CPU time while it is in the Blocked state.
+ *
+ * **NOTE** Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not be
+ * unblocked by a notification sent to any other array index.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array. xTaskNotifyWait() is the original API function, and remains backward
+ * compatible by always operating on the notification value at index 0 in the
+ * array. Calling xTaskNotifyWait() is equivalent to calling
+ * xTaskNotifyWaitIndexed() with the uxIndexToWaitOn parameter set to 0.
+ *
+ * @param uxIndexToWaitOn The index within the calling task's array of
+ * notification values on which the calling task will wait for a notification to
+ * be received. uxIndexToWaitOn must be less than
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyWait() does
+ * not have this parameter and always waits for notifications on index 0.
+ *
+ * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value
+ * will be cleared in the calling task's notification value before the task
+ * checks to see if any notifications are pending, and optionally blocks if no
+ * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if
+ * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have
+ * the effect of resetting the task's notification value to 0. Setting
+ * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged.
+ *
+ * @param ulBitsToClearOnExit If a notification is pending or received before
+ * the calling task exits the xTaskNotifyWait() function then the task's
+ * notification value (see the xTaskNotify() API function) is passed out using
+ * the pulNotificationValue parameter. Then any bits that are set in
+ * ulBitsToClearOnExit will be cleared in the task's notification value (note
+ * *pulNotificationValue is set before any bits are cleared). Setting
+ * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL
+ * (if limits.h is not included) will have the effect of resetting the task's
+ * notification value to 0 before the function exits. Setting
+ * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged
+ * when the function exits (in which case the value passed out in
+ * pulNotificationValue will match the task's notification value).
+ *
+ * @param pulNotificationValue Used to pass the task's notification value out
+ * of the function. Note the value passed out will not be effected by the
+ * clearing of any bits caused by ulBitsToClearOnExit being non-zero.
+ *
+ * @param xTicksToWait The maximum amount of time that the task should wait in
+ * the Blocked state for a notification to be received, should a notification
+ * not already be pending when xTaskNotifyWait() was called. The task
+ * will not consume any processing time while it is in the Blocked state. This
+ * is specified in kernel ticks, the macro pdMS_TO_TICKS( value_in_ms ) can be
+ * used to convert a time specified in milliseconds to a time specified in
+ * ticks.
+ *
+ * @return If a notification was received (including notifications that were
+ * already pending when xTaskNotifyWait was called) then pdPASS is
+ * returned. Otherwise pdFAIL is returned.
+ *
+ * \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed
+ * \ingroup TaskNotifications
+ */
+BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
+ uint32_t ulBitsToClearOnEntry,
+ uint32_t ulBitsToClearOnExit,
+ uint32_t * pulNotificationValue,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+#define xTaskNotifyWait( ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \
+ xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) )
+#define xTaskNotifyWaitIndexed( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \
+ xTaskGenericNotifyWait( ( uxIndexToWaitOn ), ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) )
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify );
+ * BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
+ * @endcode
+ *
+ * Sends a direct to task notification to a particular index in the target
+ * task's notification array in a manner similar to giving a counting semaphore.
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * macros to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t). The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * Events can be sent to a task using an intermediary object. Examples of such
+ * objects are queues, semaphores, mutexes and event groups. Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values. In
+ * that way task notifications can be used to send data to a task, or be used as
+ * light weight and fast binary or counting semaphores.
+ *
+ * xTaskNotifyGiveIndexed() is a helper macro intended for use when task
+ * notifications are used as light weight and faster binary or counting
+ * semaphore equivalents. Actual FreeRTOS semaphores are given using the
+ * xSemaphoreGive() API function, the equivalent action that instead uses a task
+ * notification is xTaskNotifyGiveIndexed().
+ *
+ * When task notifications are being used as a binary or counting semaphore
+ * equivalent then the task being notified should wait for the notification
+ * using the ulTaskNotifyTakeIndexed() API function rather than the
+ * xTaskNotifyWaitIndexed() API function.
+ *
+ * **NOTE** Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not be
+ * unblocked by a notification sent to any other array index.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array. xTaskNotifyGive() is the original API function, and remains backward
+ * compatible by always operating on the notification value at index 0 in the
+ * array. Calling xTaskNotifyGive() is equivalent to calling
+ * xTaskNotifyGiveIndexed() with the uxIndexToNotify parameter set to 0.
+ *
+ * @param xTaskToNotify The handle of the task being notified. The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param uxIndexToNotify The index within the target task's array of
+ * notification values to which the notification is to be sent. uxIndexToNotify
+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyGive()
+ * does not have this parameter and always sends notifications to index 0.
+ *
+ * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the
+ * eAction parameter set to eIncrement - so pdPASS is always returned.
+ *
+ * \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed
+ * \ingroup TaskNotifications
+ */
+#define xTaskNotifyGive( xTaskToNotify ) \
+ xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( 0 ), eIncrement, NULL )
+#define xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ) \
+ xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( 0 ), eIncrement, NULL )
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken );
+ * void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * A version of xTaskNotifyGiveIndexed() that can be called from an interrupt
+ * service routine (ISR).
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro
+ * to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t). The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * Events can be sent to a task using an intermediary object. Examples of such
+ * objects are queues, semaphores, mutexes and event groups. Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values. In
+ * that way task notifications can be used to send data to a task, or be used as
+ * light weight and fast binary or counting semaphores.
+ *
+ * vTaskNotifyGiveIndexedFromISR() is intended for use when task notifications
+ * are used as light weight and faster binary or counting semaphore equivalents.
+ * Actual FreeRTOS semaphores are given from an ISR using the
+ * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses
+ * a task notification is vTaskNotifyGiveIndexedFromISR().
+ *
+ * When task notifications are being used as a binary or counting semaphore
+ * equivalent then the task being notified should wait for the notification
+ * using the ulTaskNotifyTakeIndexed() API function rather than the
+ * xTaskNotifyWaitIndexed() API function.
+ *
+ * **NOTE** Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not be
+ * unblocked by a notification sent to any other array index.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array. xTaskNotifyFromISR() is the original API function, and remains
+ * backward compatible by always operating on the notification value at index 0
+ * within the array. Calling xTaskNotifyGiveFromISR() is equivalent to calling
+ * xTaskNotifyGiveIndexedFromISR() with the uxIndexToNotify parameter set to 0.
+ *
+ * @param xTaskToNotify The handle of the task being notified. The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param uxIndexToNotify The index within the target task's array of
+ * notification values to which the notification is to be sent. uxIndexToNotify
+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ * xTaskNotifyGiveFromISR() does not have this parameter and always sends
+ * notifications to index 0.
+ *
+ * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
+ * task to which the notification was sent to leave the Blocked state, and the
+ * unblocked task has a priority higher than the currently running task. If
+ * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch
+ * should be requested before the interrupt is exited. How a context switch is
+ * requested from an ISR is dependent on the port - see the documentation page
+ * for the port in use.
+ *
+ * \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR
+ * \ingroup TaskNotifications
+ */
+void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
+ UBaseType_t uxIndexToNotify,
+ BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \
+ vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( pxHigherPriorityTaskWoken ) )
+#define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken ) \
+ vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * task. h
+ * @code{c}
+ * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ *
+ * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ * @endcode
+ *
+ * Waits for a direct to task notification on a particular index in the calling
+ * task's notification array in a manner similar to taking a counting semaphore.
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this
+ * function to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t). The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * Events can be sent to a task using an intermediary object. Examples of such
+ * objects are queues, semaphores, mutexes and event groups. Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values. In
+ * that way task notifications can be used to send data to a task, or be used as
+ * light weight and fast binary or counting semaphores.
+ *
+ * ulTaskNotifyTakeIndexed() is intended for use when a task notification is
+ * used as a faster and lighter weight binary or counting semaphore alternative.
+ * Actual FreeRTOS semaphores are taken using the xSemaphoreTake() API function,
+ * the equivalent action that instead uses a task notification is
+ * ulTaskNotifyTakeIndexed().
+ *
+ * When a task is using its notification value as a binary or counting semaphore
+ * other tasks should send notifications to it using the xTaskNotifyGiveIndexed()
+ * macro, or xTaskNotifyIndex() function with the eAction parameter set to
+ * eIncrement.
+ *
+ * ulTaskNotifyTakeIndexed() can either clear the task's notification value at
+ * the array index specified by the uxIndexToWaitOn parameter to zero on exit,
+ * in which case the notification value acts like a binary semaphore, or
+ * decrement the notification value on exit, in which case the notification
+ * value acts like a counting semaphore.
+ *
+ * A task can use ulTaskNotifyTakeIndexed() to [optionally] block to wait for
+ * a notification. The task does not consume any CPU time while it is in the
+ * Blocked state.
+ *
+ * Where as xTaskNotifyWaitIndexed() will return when a notification is pending,
+ * ulTaskNotifyTakeIndexed() will return when the task's notification value is
+ * not zero.
+ *
+ * **NOTE** Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not be
+ * unblocked by a notification sent to any other array index.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array. ulTaskNotifyTake() is the original API function, and remains backward
+ * compatible by always operating on the notification value at index 0 in the
+ * array. Calling ulTaskNotifyTake() is equivalent to calling
+ * ulTaskNotifyTakeIndexed() with the uxIndexToWaitOn parameter set to 0.
+ *
+ * @param uxIndexToWaitOn The index within the calling task's array of
+ * notification values on which the calling task will wait for a notification to
+ * be non-zero. uxIndexToWaitOn must be less than
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyTake() does
+ * not have this parameter and always waits for notifications on index 0.
+ *
+ * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's
+ * notification value is decremented when the function exits. In this way the
+ * notification value acts like a counting semaphore. If xClearCountOnExit is
+ * not pdFALSE then the task's notification value is cleared to zero when the
+ * function exits. In this way the notification value acts like a binary
+ * semaphore.
+ *
+ * @param xTicksToWait The maximum amount of time that the task should wait in
+ * the Blocked state for the task's notification value to be greater than zero,
+ * should the count not already be greater than zero when
+ * ulTaskNotifyTake() was called. The task will not consume any processing
+ * time while it is in the Blocked state. This is specified in kernel ticks,
+ * the macro pdMS_TO_TICKS( value_in_ms ) can be used to convert a time
+ * specified in milliseconds to a time specified in ticks.
+ *
+ * @return The task's notification count before it is either cleared to zero or
+ * decremented (see the xClearCountOnExit parameter).
+ *
+ * \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed
+ * \ingroup TaskNotifications
+ */
+uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
+ BaseType_t xClearCountOnExit,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \
+ ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), ( xClearCountOnExit ), ( xTicksToWait ) )
+#define ulTaskNotifyTakeIndexed( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ) \
+ ulTaskGenericNotifyTake( ( uxIndexToWaitOn ), ( xClearCountOnExit ), ( xTicksToWait ) )
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToCLear );
+ *
+ * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t). The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * If a notification is sent to an index within the array of notifications then
+ * the notification at that index is said to be 'pending' until it is read or
+ * explicitly cleared by the receiving task. xTaskNotifyStateClearIndexed()
+ * is the function that clears a pending notification without reading the
+ * notification value. The notification value at the same array index is not
+ * altered. Set xTask to NULL to clear the notification state of the calling
+ * task.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array. xTaskNotifyStateClear() is the original API function, and remains
+ * backward compatible by always operating on the notification value at index 0
+ * within the array. Calling xTaskNotifyStateClear() is equivalent to calling
+ * xTaskNotifyStateClearIndexed() with the uxIndexToNotify parameter set to 0.
+ *
+ * @param xTask The handle of the RTOS task that will have a notification state
+ * cleared. Set xTask to NULL to clear a notification state in the calling
+ * task. To obtain a task's handle create the task using xTaskCreate() and
+ * make use of the pxCreatedTask parameter, or create the task using
+ * xTaskCreateStatic() and store the returned value, or use the task's name in
+ * a call to xTaskGetHandle().
+ *
+ * @param uxIndexToClear The index within the target task's array of
+ * notification values to act upon. For example, setting uxIndexToClear to 1
+ * will clear the state of the notification at index 1 within the array.
+ * uxIndexToClear must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ * ulTaskNotifyStateClear() does not have this parameter and always acts on the
+ * notification at index 0.
+ *
+ * @return pdTRUE if the task's notification state was set to
+ * eNotWaitingNotification, otherwise pdFALSE.
+ *
+ * \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed
+ * \ingroup TaskNotifications
+ */
+BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
+ UBaseType_t uxIndexToClear ) PRIVILEGED_FUNCTION;
+#define xTaskNotifyStateClear( xTask ) \
+ xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) )
+#define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \
+ xTaskGenericNotifyStateClear( ( xTask ), ( uxIndexToClear ) )
+
+/**
+ * task. h
+ * @code{c}
+ * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear );
+ *
+ * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t). The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * ulTaskNotifyValueClearIndexed() clears the bits specified by the
+ * ulBitsToClear bit mask in the notification value at array index uxIndexToClear
+ * of the task referenced by xTask.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array. ulTaskNotifyValueClear() is the original API function, and remains
+ * backward compatible by always operating on the notification value at index 0
+ * within the array. Calling ulTaskNotifyValueClear() is equivalent to calling
+ * ulTaskNotifyValueClearIndexed() with the uxIndexToClear parameter set to 0.
+ *
+ * @param xTask The handle of the RTOS task that will have bits in one of its
+ * notification values cleared. Set xTask to NULL to clear bits in a
+ * notification value of the calling task. To obtain a task's handle create the
+ * task using xTaskCreate() and make use of the pxCreatedTask parameter, or
+ * create the task using xTaskCreateStatic() and store the returned value, or
+ * use the task's name in a call to xTaskGetHandle().
+ *
+ * @param uxIndexToClear The index within the target task's array of
+ * notification values in which to clear the bits. uxIndexToClear
+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ * ulTaskNotifyValueClear() does not have this parameter and always clears bits
+ * in the notification value at index 0.
+ *
+ * @param ulBitsToClear Bit mask of the bits to clear in the notification value of
+ * xTask. Set a bit to 1 to clear the corresponding bits in the task's notification
+ * value. Set ulBitsToClear to 0xffffffff (UINT_MAX on 32-bit architectures) to clear
+ * the notification value to 0. Set ulBitsToClear to 0 to query the task's
+ * notification value without clearing any bits.
+ *
+ *
+ * @return The value of the target task's notification value before the bits
+ * specified by ulBitsToClear were cleared.
+ * \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear
+ * \ingroup TaskNotifications
+ */
+uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
+ UBaseType_t uxIndexToClear,
+ uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
+#define ulTaskNotifyValueClear( xTask, ulBitsToClear ) \
+ ulTaskGenericNotifyValueClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulBitsToClear ) )
+#define ulTaskNotifyValueClearIndexed( xTask, uxIndexToClear, ulBitsToClear ) \
+ ulTaskGenericNotifyValueClear( ( xTask ), ( uxIndexToClear ), ( ulBitsToClear ) )
+
+/**
+ * task.h
+ * @code{c}
+ * void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut );
+ * @endcode
+ *
+ * Capture the current time for future use with xTaskCheckForTimeOut().
+ *
+ * @param pxTimeOut Pointer to a timeout object into which the current time
+ * is to be captured. The captured time includes the tick count and the number
+ * of times the tick count has overflowed since the system first booted.
+ * \defgroup vTaskSetTimeOutState vTaskSetTimeOutState
+ * \ingroup TaskCtrl
+ */
+void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
+
+/**
+ * task.h
+ * @code{c}
+ * BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait );
+ * @endcode
+ *
+ * Determines if pxTicksToWait ticks has passed since a time was captured
+ * using a call to vTaskSetTimeOutState(). The captured time includes the tick
+ * count and the number of times the tick count has overflowed.
+ *
+ * @param pxTimeOut The time status as captured previously using
+ * vTaskSetTimeOutState. If the timeout has not yet occurred, it is updated
+ * to reflect the current time status.
+ * @param pxTicksToWait The number of ticks to check for timeout i.e. if
+ * pxTicksToWait ticks have passed since pxTimeOut was last updated (either by
+ * vTaskSetTimeOutState() or xTaskCheckForTimeOut()), the timeout has occurred.
+ * If the timeout has not occurred, pxTicksToWait is updated to reflect the
+ * number of remaining ticks.
+ *
+ * @return If timeout has occurred, pdTRUE is returned. Otherwise pdFALSE is
+ * returned and pxTicksToWait is updated to reflect the number of remaining
+ * ticks.
+ *
+ * @see https://www.FreeRTOS.org/xTaskCheckForTimeOut.html
+ *
+ * Example Usage:
+ * @code{c}
+ * // Driver library function used to receive uxWantedBytes from an Rx buffer
+ * // that is filled by a UART interrupt. If there are not enough bytes in the
+ * // Rx buffer then the task enters the Blocked state until it is notified that
+ * // more data has been placed into the buffer. If there is still not enough
+ * // data then the task re-enters the Blocked state, and xTaskCheckForTimeOut()
+ * // is used to re-calculate the Block time to ensure the total amount of time
+ * // spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This
+ * // continues until either the buffer contains at least uxWantedBytes bytes,
+ * // or the total amount of time spent in the Blocked state reaches
+ * // MAX_TIME_TO_WAIT - at which point the task reads however many bytes are
+ * // available up to a maximum of uxWantedBytes.
+ *
+ * size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes )
+ * {
+ * size_t uxReceived = 0;
+ * TickType_t xTicksToWait = MAX_TIME_TO_WAIT;
+ * TimeOut_t xTimeOut;
+ *
+ * // Initialize xTimeOut. This records the time at which this function
+ * // was entered.
+ * vTaskSetTimeOutState( &xTimeOut );
+ *
+ * // Loop until the buffer contains the wanted number of bytes, or a
+ * // timeout occurs.
+ * while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes )
+ * {
+ * // The buffer didn't contain enough data so this task is going to
+ * // enter the Blocked state. Adjusting xTicksToWait to account for
+ * // any time that has been spent in the Blocked state within this
+ * // function so far to ensure the total amount of time spent in the
+ * // Blocked state does not exceed MAX_TIME_TO_WAIT.
+ * if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE )
+ * {
+ * //Timed out before the wanted number of bytes were available,
+ * // exit the loop.
+ * break;
+ * }
+ *
+ * // Wait for a maximum of xTicksToWait ticks to be notified that the
+ * // receive interrupt has placed more data into the buffer.
+ * ulTaskNotifyTake( pdTRUE, xTicksToWait );
+ * }
+ *
+ * // Attempt to read uxWantedBytes from the receive buffer into pucBuffer.
+ * // The actual number of bytes read (which might be less than
+ * // uxWantedBytes) is returned.
+ * uxReceived = UART_read_from_receive_buffer( pxUARTInstance,
+ * pucBuffer,
+ * uxWantedBytes );
+ *
+ * return uxReceived;
+ * }
+ * @endcode
+ * \defgroup xTaskCheckForTimeOut xTaskCheckForTimeOut
+ * \ingroup TaskCtrl
+ */
+BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
+ TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION;
+
+/**
+ * task.h
+ * @code{c}
+ * BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp );
+ * @endcode
+ *
+ * This function corrects the tick count value after the application code has held
+ * interrupts disabled for an extended period resulting in tick interrupts having
+ * been missed.
+ *
+ * This function is similar to vTaskStepTick(), however, unlike
+ * vTaskStepTick(), xTaskCatchUpTicks() may move the tick count forward past a
+ * time at which a task should be removed from the blocked state. That means
+ * tasks may have to be removed from the blocked state as the tick count is
+ * moved.
+ *
+ * @param xTicksToCatchUp The number of tick interrupts that have been missed due to
+ * interrupts being disabled. Its value is not computed automatically, so must be
+ * computed by the application writer.
+ *
+ * @return pdTRUE if moving the tick count forward resulted in a task leaving the
+ * blocked state and a context switch being performed. Otherwise pdFALSE.
+ *
+ * \defgroup xTaskCatchUpTicks xTaskCatchUpTicks
+ * \ingroup TaskCtrl
+ */
+BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION;
+
+
+/*-----------------------------------------------------------
+* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
+*----------------------------------------------------------*/
+
+/*
+ * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY
+ * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS
+ * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+ *
+ * Called from the real time kernel tick (either preemptive or cooperative),
+ * this increments the tick count and checks if any tasks that are blocked
+ * for a finite period required removing from a blocked list and placing on
+ * a ready list. If a non-zero value is returned then a context switch is
+ * required because either:
+ * + A task was removed from a blocked list because its timeout had expired,
+ * or
+ * + Time slicing is in use and there is a task of equal priority to the
+ * currently running task.
+ */
+BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
+ * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+ *
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED.
+ *
+ * Removes the calling task from the ready list and places it both
+ * on the list of tasks waiting for a particular event, and the
+ * list of delayed tasks. The task will be removed from both lists
+ * and replaced on the ready list should either the event occur (and
+ * there be no higher priority tasks waiting on the same event) or
+ * the delay period expires.
+ *
+ * The 'unordered' version replaces the event list item value with the
+ * xItemValue value, and inserts the list item at the end of the list.
+ *
+ * The 'ordered' version uses the existing event list item value (which is the
+ * owning task's priority) to insert the list item into the event list in task
+ * priority order.
+ *
+ * @param pxEventList The list containing tasks that are blocked waiting
+ * for the event to occur.
+ *
+ * @param xItemValue The item value to use for the event list item when the
+ * event list is not ordered by task priority.
+ *
+ * @param xTicksToWait The maximum amount of time that the task should wait
+ * for the event to occur. This is specified in kernel ticks, the constant
+ * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time
+ * period.
+ */
+void vTaskPlaceOnEventList( List_t * const pxEventList,
+ const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
+ const TickType_t xItemValue,
+ const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/*
+ * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
+ * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+ *
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED.
+ *
+ * This function performs nearly the same function as vTaskPlaceOnEventList().
+ * The difference being that this function does not permit tasks to block
+ * indefinitely, whereas vTaskPlaceOnEventList() does.
+ *
+ */
+void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,
+ TickType_t xTicksToWait,
+ const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION;
+
+/*
+ * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
+ * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+ *
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED.
+ *
+ * Removes a task from both the specified event list and the list of blocked
+ * tasks, and places it on a ready queue.
+ *
+ * xTaskRemoveFromEventList()/vTaskRemoveFromUnorderedEventList() will be called
+ * if either an event occurs to unblock a task, or the block timeout period
+ * expires.
+ *
+ * xTaskRemoveFromEventList() is used when the event list is in task priority
+ * order. It removes the list item from the head of the event list as that will
+ * have the highest priority owning task of all the tasks on the event list.
+ * vTaskRemoveFromUnorderedEventList() is used when the event list is not
+ * ordered and the event list items hold something other than the owning tasks
+ * priority. In this case the event list item value is updated to the value
+ * passed in the xItemValue parameter.
+ *
+ * @return pdTRUE if the task being removed has a higher priority than the task
+ * making the call, otherwise pdFALSE.
+ */
+BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION;
+void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
+ const TickType_t xItemValue ) PRIVILEGED_FUNCTION;
+
+/*
+ * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY
+ * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS
+ * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+ *
+ * Sets the pointer to the current TCB to the TCB of the highest priority task
+ * that is ready to run.
+ */
+portDONT_DISCARD void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY
+ * THE EVENT BITS MODULE.
+ */
+TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Return the handle of the calling task.
+ */
+TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Shortcut used by the queue implementation to prevent unnecessary call to
+ * taskYIELD();
+ */
+void vTaskMissedYield( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Returns the scheduler state as taskSCHEDULER_RUNNING,
+ * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED.
+ */
+BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Raises the priority of the mutex holder to that of the calling task should
+ * the mutex holder have a priority less than the calling task.
+ */
+BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
+
+/*
+ * Set the priority of a task back to its proper priority in the case that it
+ * inherited a higher priority while it was holding a semaphore.
+ */
+BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
+
+/*
+ * If a higher priority task attempting to obtain a mutex caused a lower
+ * priority task to inherit the higher priority task's priority - but the higher
+ * priority task then timed out without obtaining the mutex, then the lower
+ * priority task will disinherit the priority again - but only down as far as
+ * the highest priority task that is still waiting for the mutex (if there were
+ * more than one task waiting for the mutex).
+ */
+void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder,
+ UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION;
+
+/*
+ * Get the uxTaskNumber assigned to the task referenced by the xTask parameter.
+ */
+UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
+/*
+ * Set the uxTaskNumber of the task referenced by the xTask parameter to
+ * uxHandle.
+ */
+void vTaskSetTaskNumber( TaskHandle_t xTask,
+ const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION;
+
+/*
+ * Only available when configUSE_TICKLESS_IDLE is set to 1.
+ * If tickless mode is being used, or a low power mode is implemented, then
+ * the tick interrupt will not execute during idle periods. When this is the
+ * case, the tick count value maintained by the scheduler needs to be kept up
+ * to date with the actual execution time by being skipped forward by a time
+ * equal to the idle period.
+ */
+void vTaskStepTick( TickType_t xTicksToJump ) PRIVILEGED_FUNCTION;
+
+/*
+ * Only available when configUSE_TICKLESS_IDLE is set to 1.
+ * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port
+ * specific sleep function to determine if it is ok to proceed with the sleep,
+ * and if it is ok to proceed, if it is ok to sleep indefinitely.
+ *
+ * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only
+ * called with the scheduler suspended, not from within a critical section. It
+ * is therefore possible for an interrupt to request a context switch between
+ * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being
+ * entered. eTaskConfirmSleepModeStatus() should be called from a short
+ * critical section between the timer being stopped and the sleep mode being
+ * entered to ensure it is ok to proceed into the sleep mode.
+ */
+eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * For internal use only. Increment the mutex held count when a mutex is
+ * taken and return the handle of the task that has taken the mutex.
+ */
+TaskHandle_t pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * For internal use only. Same as vTaskSetTimeOutState(), but without a critical
+ * section.
+ */
+void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
+
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ }
+#endif
+/* *INDENT-ON* */
+#endif /* INC_TASK_H */
diff --git a/source/test/freertos/inc/timers.h b/source/test/freertos/inc/timers.h
new file mode 100644
index 0000000..4b73908
--- /dev/null
+++ b/source/test/freertos/inc/timers.h
@@ -0,0 +1,1369 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+
+#ifndef TIMERS_H
+#define TIMERS_H
+
+#ifndef INC_FREERTOS_H
+ #error "include FreeRTOS.h must appear in source files before include timers.h"
+#endif
+
+/*lint -save -e537 This headers are only multiply included if the application code
+ * happens to also be including task.h. */
+#include "task.h"
+/*lint -restore */
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ extern "C" {
+#endif
+/* *INDENT-ON* */
+
+/*-----------------------------------------------------------
+* MACROS AND DEFINITIONS
+*----------------------------------------------------------*/
+
+/* IDs for commands that can be sent/received on the timer queue. These are to
+ * be used solely through the macros that make up the public software timer API,
+ * as defined below. The commands that are sent from interrupts must use the
+ * highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task
+ * or interrupt version of the queue send function should be used. */
+#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 )
+#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 )
+#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 )
+#define tmrCOMMAND_START ( ( BaseType_t ) 1 )
+#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 )
+#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 )
+#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 )
+#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 )
+
+#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 )
+#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 )
+#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 )
+#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 )
+#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 )
+
+
+/**
+ * Type by which software timers are referenced. For example, a call to
+ * xTimerCreate() returns an TimerHandle_t variable that can then be used to
+ * reference the subject timer in calls to other software timer API functions
+ * (for example, xTimerStart(), xTimerReset(), etc.).
+ */
+struct tmrTimerControl; /* The old naming convention is used to prevent breaking kernel aware debuggers. */
+typedef struct tmrTimerControl * TimerHandle_t;
+
+/*
+ * Defines the prototype to which timer callback functions must conform.
+ */
+typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer );
+
+/*
+ * Defines the prototype to which functions used with the
+ * xTimerPendFunctionCallFromISR() function must conform.
+ */
+typedef void (* PendedFunction_t)( void *,
+ uint32_t );
+
+/**
+ * TimerHandle_t xTimerCreate( const char * const pcTimerName,
+ * TickType_t xTimerPeriodInTicks,
+ * BaseType_t xAutoReload,
+ * void * pvTimerID,
+ * TimerCallbackFunction_t pxCallbackFunction );
+ *
+ * Creates a new software timer instance, and returns a handle by which the
+ * created software timer can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, software timers use a block
+ * of memory, in which the timer data structure is stored. If a software timer
+ * is created using xTimerCreate() then the required memory is automatically
+ * dynamically allocated inside the xTimerCreate() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a software timer is created using
+ * xTimerCreateStatic() then the application writer must provide the memory that
+ * will get used by the software timer. xTimerCreateStatic() therefore allows a
+ * software timer to be created without using any dynamic memory allocation.
+ *
+ * Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
+ * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
+ * xTimerChangePeriodFromISR() API functions can all be used to transition a
+ * timer into the active state.
+ *
+ * @param pcTimerName A text name that is assigned to the timer. This is done
+ * purely to assist debugging. The kernel itself only ever references a timer
+ * by its handle, and never by its name.
+ *
+ * @param xTimerPeriodInTicks The timer period. The time is defined in tick
+ * periods so the constant portTICK_PERIOD_MS can be used to convert a time that
+ * has been specified in milliseconds. For example, if the timer must expire
+ * after 100 ticks, then xTimerPeriodInTicks should be set to 100.
+ * Alternatively, if the timer must expire after 500ms, then xPeriod can be set
+ * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or
+ * equal to 1000. Time timer period must be greater than 0.
+ *
+ * @param xAutoReload If xAutoReload is set to pdTRUE then the timer will
+ * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter.
+ * If xAutoReload is set to pdFALSE then the timer will be a one-shot timer and
+ * enter the dormant state after it expires.
+ *
+ * @param pvTimerID An identifier that is assigned to the timer being created.
+ * Typically this would be used in the timer callback function to identify which
+ * timer expired when the same callback function is assigned to more than one
+ * timer.
+ *
+ * @param pxCallbackFunction The function to call when the timer expires.
+ * Callback functions must have the prototype defined by TimerCallbackFunction_t,
+ * which is "void vCallbackFunction( TimerHandle_t xTimer );".
+ *
+ * @return If the timer is successfully created then a handle to the newly
+ * created timer is returned. If the timer cannot be created because there is
+ * insufficient FreeRTOS heap remaining to allocate the timer
+ * structures then NULL is returned.
+ *
+ * Example usage:
+ * @verbatim
+ * #define NUM_TIMERS 5
+ *
+ * // An array to hold handles to the created timers.
+ * TimerHandle_t xTimers[ NUM_TIMERS ];
+ *
+ * // An array to hold a count of the number of times each timer expires.
+ * int32_t lExpireCounters[ NUM_TIMERS ] = { 0 };
+ *
+ * // Define a callback function that will be used by multiple timer instances.
+ * // The callback function does nothing but count the number of times the
+ * // associated timer expires, and stop the timer once the timer has expired
+ * // 10 times.
+ * void vTimerCallback( TimerHandle_t pxTimer )
+ * {
+ * int32_t lArrayIndex;
+ * const int32_t xMaxExpiryCountBeforeStopping = 10;
+ *
+ * // Optionally do something if the pxTimer parameter is NULL.
+ * configASSERT( pxTimer );
+ *
+ * // Which timer expired?
+ * lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer );
+ *
+ * // Increment the number of times that pxTimer has expired.
+ * lExpireCounters[ lArrayIndex ] += 1;
+ *
+ * // If the timer has expired 10 times then stop it from running.
+ * if( lExpireCounters[ lArrayIndex ] == xMaxExpiryCountBeforeStopping )
+ * {
+ * // Do not use a block time if calling a timer API function from a
+ * // timer callback function, as doing so could cause a deadlock!
+ * xTimerStop( pxTimer, 0 );
+ * }
+ * }
+ *
+ * void main( void )
+ * {
+ * int32_t x;
+ *
+ * // Create then start some timers. Starting the timers before the scheduler
+ * // has been started means the timers will start running immediately that
+ * // the scheduler starts.
+ * for( x = 0; x < NUM_TIMERS; x++ )
+ * {
+ * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel.
+ * ( 100 * ( x + 1 ) ), // The timer period in ticks.
+ * pdTRUE, // The timers will auto-reload themselves when they expire.
+ * ( void * ) x, // Assign each timer a unique id equal to its array index.
+ * vTimerCallback // Each timer calls the same callback when it expires.
+ * );
+ *
+ * if( xTimers[ x ] == NULL )
+ * {
+ * // The timer was not created.
+ * }
+ * else
+ * {
+ * // Start the timer. No block time is specified, and even if one was
+ * // it would be ignored because the scheduler has not yet been
+ * // started.
+ * if( xTimerStart( xTimers[ x ], 0 ) != pdPASS )
+ * {
+ * // The timer could not be set into the Active state.
+ * }
+ * }
+ * }
+ *
+ * // ...
+ * // Create tasks here.
+ * // ...
+ *
+ * // Starting the scheduler will start the timers running as they have already
+ * // been set into the active state.
+ * vTaskStartScheduler();
+ *
+ * // Should not reach here.
+ * for( ;; );
+ * }
+ * @endverbatim
+ */
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const TickType_t xTimerPeriodInTicks,
+ const BaseType_t xAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION;
+#endif
+
+/**
+ * TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,
+ * TickType_t xTimerPeriodInTicks,
+ * BaseType_t xAutoReload,
+ * void * pvTimerID,
+ * TimerCallbackFunction_t pxCallbackFunction,
+ * StaticTimer_t *pxTimerBuffer );
+ *
+ * Creates a new software timer instance, and returns a handle by which the
+ * created software timer can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, software timers use a block
+ * of memory, in which the timer data structure is stored. If a software timer
+ * is created using xTimerCreate() then the required memory is automatically
+ * dynamically allocated inside the xTimerCreate() function. (see
+ * https://www.FreeRTOS.org/a00111.html). If a software timer is created using
+ * xTimerCreateStatic() then the application writer must provide the memory that
+ * will get used by the software timer. xTimerCreateStatic() therefore allows a
+ * software timer to be created without using any dynamic memory allocation.
+ *
+ * Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
+ * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
+ * xTimerChangePeriodFromISR() API functions can all be used to transition a
+ * timer into the active state.
+ *
+ * @param pcTimerName A text name that is assigned to the timer. This is done
+ * purely to assist debugging. The kernel itself only ever references a timer
+ * by its handle, and never by its name.
+ *
+ * @param xTimerPeriodInTicks The timer period. The time is defined in tick
+ * periods so the constant portTICK_PERIOD_MS can be used to convert a time that
+ * has been specified in milliseconds. For example, if the timer must expire
+ * after 100 ticks, then xTimerPeriodInTicks should be set to 100.
+ * Alternatively, if the timer must expire after 500ms, then xPeriod can be set
+ * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or
+ * equal to 1000. The timer period must be greater than 0.
+ *
+ * @param xAutoReload If xAutoReload is set to pdTRUE then the timer will
+ * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter.
+ * If xAutoReload is set to pdFALSE then the timer will be a one-shot timer and
+ * enter the dormant state after it expires.
+ *
+ * @param pvTimerID An identifier that is assigned to the timer being created.
+ * Typically this would be used in the timer callback function to identify which
+ * timer expired when the same callback function is assigned to more than one
+ * timer.
+ *
+ * @param pxCallbackFunction The function to call when the timer expires.
+ * Callback functions must have the prototype defined by TimerCallbackFunction_t,
+ * which is "void vCallbackFunction( TimerHandle_t xTimer );".
+ *
+ * @param pxTimerBuffer Must point to a variable of type StaticTimer_t, which
+ * will be then be used to hold the software timer's data structures, removing
+ * the need for the memory to be allocated dynamically.
+ *
+ * @return If the timer is created then a handle to the created timer is
+ * returned. If pxTimerBuffer was NULL then NULL is returned.
+ *
+ * Example usage:
+ * @verbatim
+ *
+ * // The buffer used to hold the software timer's data structure.
+ * static StaticTimer_t xTimerBuffer;
+ *
+ * // A variable that will be incremented by the software timer's callback
+ * // function.
+ * UBaseType_t uxVariableToIncrement = 0;
+ *
+ * // A software timer callback function that increments a variable passed to
+ * // it when the software timer was created. After the 5th increment the
+ * // callback function stops the software timer.
+ * static void prvTimerCallback( TimerHandle_t xExpiredTimer )
+ * {
+ * UBaseType_t *puxVariableToIncrement;
+ * BaseType_t xReturned;
+ *
+ * // Obtain the address of the variable to increment from the timer ID.
+ * puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer );
+ *
+ * // Increment the variable to show the timer callback has executed.
+ * ( *puxVariableToIncrement )++;
+ *
+ * // If this callback has executed the required number of times, stop the
+ * // timer.
+ * if( *puxVariableToIncrement == 5 )
+ * {
+ * // This is called from a timer callback so must not block.
+ * xTimerStop( xExpiredTimer, staticDONT_BLOCK );
+ * }
+ * }
+ *
+ *
+ * void main( void )
+ * {
+ * // Create the software time. xTimerCreateStatic() has an extra parameter
+ * // than the normal xTimerCreate() API function. The parameter is a pointer
+ * // to the StaticTimer_t structure that will hold the software timer
+ * // structure. If the parameter is passed as NULL then the structure will be
+ * // allocated dynamically, just as if xTimerCreate() had been called.
+ * xTimer = xTimerCreateStatic( "T1", // Text name for the task. Helps debugging only. Not used by FreeRTOS.
+ * xTimerPeriod, // The period of the timer in ticks.
+ * pdTRUE, // This is an auto-reload timer.
+ * ( void * ) &uxVariableToIncrement, // A variable incremented by the software timer's callback function
+ * prvTimerCallback, // The function to execute when the timer expires.
+ * &xTimerBuffer ); // The buffer that will hold the software timer structure.
+ *
+ * // The scheduler has not started yet so a block time is not used.
+ * xReturned = xTimerStart( xTimer, 0 );
+ *
+ * // ...
+ * // Create tasks here.
+ * // ...
+ *
+ * // Starting the scheduler will start the timers running as they have already
+ * // been set into the active state.
+ * vTaskStartScheduler();
+ *
+ * // Should not reach here.
+ * for( ;; );
+ * }
+ * @endverbatim
+ */
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const TickType_t xTimerPeriodInTicks,
+ const BaseType_t xAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction,
+ StaticTimer_t * pxTimerBuffer ) PRIVILEGED_FUNCTION;
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+/**
+ * void *pvTimerGetTimerID( TimerHandle_t xTimer );
+ *
+ * Returns the ID assigned to the timer.
+ *
+ * IDs are assigned to timers using the pvTimerID parameter of the call to
+ * xTimerCreated() that was used to create the timer, and by calling the
+ * vTimerSetTimerID() API function.
+ *
+ * If the same callback function is assigned to multiple timers then the timer
+ * ID can be used as time specific (timer local) storage.
+ *
+ * @param xTimer The timer being queried.
+ *
+ * @return The ID assigned to the timer being queried.
+ *
+ * Example usage:
+ *
+ * See the xTimerCreate() API function example usage scenario.
+ */
+void * pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
+
+/**
+ * void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID );
+ *
+ * Sets the ID assigned to the timer.
+ *
+ * IDs are assigned to timers using the pvTimerID parameter of the call to
+ * xTimerCreated() that was used to create the timer.
+ *
+ * If the same callback function is assigned to multiple timers then the timer
+ * ID can be used as time specific (timer local) storage.
+ *
+ * @param xTimer The timer being updated.
+ *
+ * @param pvNewID The ID to assign to the timer.
+ *
+ * Example usage:
+ *
+ * See the xTimerCreate() API function example usage scenario.
+ */
+void vTimerSetTimerID( TimerHandle_t xTimer,
+ void * pvNewID ) PRIVILEGED_FUNCTION;
+
+/**
+ * BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer );
+ *
+ * Queries a timer to see if it is active or dormant.
+ *
+ * A timer will be dormant if:
+ * 1) It has been created but not started, or
+ * 2) It is an expired one-shot timer that has not been restarted.
+ *
+ * Timers are created in the dormant state. The xTimerStart(), xTimerReset(),
+ * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and
+ * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the
+ * active state.
+ *
+ * @param xTimer The timer being queried.
+ *
+ * @return pdFALSE will be returned if the timer is dormant. A value other than
+ * pdFALSE will be returned if the timer is active.
+ *
+ * Example usage:
+ * @verbatim
+ * // This function assumes xTimer has already been created.
+ * void vAFunction( TimerHandle_t xTimer )
+ * {
+ * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )"
+ * {
+ * // xTimer is active, do something.
+ * }
+ * else
+ * {
+ * // xTimer is not active, do something else.
+ * }
+ * }
+ * @endverbatim
+ */
+BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
+
+/**
+ * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void );
+ *
+ * Simply returns the handle of the timer service/daemon task. It it not valid
+ * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started.
+ */
+TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
+
+/**
+ * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
+ *
+ * Timer functionality is provided by a timer service/daemon task. Many of the
+ * public FreeRTOS timer API functions send commands to the timer service task
+ * through a queue called the timer command queue. The timer command queue is
+ * private to the kernel itself and is not directly accessible to application
+ * code. The length of the timer command queue is set by the
+ * configTIMER_QUEUE_LENGTH configuration constant.
+ *
+ * xTimerStart() starts a timer that was previously created using the
+ * xTimerCreate() API function. If the timer had already been started and was
+ * already in the active state, then xTimerStart() has equivalent functionality
+ * to the xTimerReset() API function.
+ *
+ * Starting a timer ensures the timer is in the active state. If the timer
+ * is not stopped, deleted, or reset in the mean time, the callback function
+ * associated with the timer will get called 'n' ticks after xTimerStart() was
+ * called, where 'n' is the timers defined period.
+ *
+ * It is valid to call xTimerStart() before the scheduler has been started, but
+ * when this is done the timer will not actually start until the scheduler is
+ * started, and the timers expiry time will be relative to when the scheduler is
+ * started, not relative to when xTimerStart() was called.
+ *
+ * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart()
+ * to be available.
+ *
+ * @param xTimer The handle of the timer being started/restarted.
+ *
+ * @param xTicksToWait Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the start command to be successfully
+ * sent to the timer command queue, should the queue already be full when
+ * xTimerStart() was called. xTicksToWait is ignored if xTimerStart() is called
+ * before the scheduler is started.
+ *
+ * @return pdFAIL will be returned if the start command could not be sent to
+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
+ * timer service/daemon task relative to other tasks in the system, although the
+ * timers expiry time is relative to when xTimerStart() is actually called. The
+ * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
+ * configuration constant.
+ *
+ * Example usage:
+ *
+ * See the xTimerCreate() API function example usage scenario.
+ *
+ */
+#define xTimerStart( xTimer, xTicksToWait ) \
+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
+
+/**
+ * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );
+ *
+ * Timer functionality is provided by a timer service/daemon task. Many of the
+ * public FreeRTOS timer API functions send commands to the timer service task
+ * through a queue called the timer command queue. The timer command queue is
+ * private to the kernel itself and is not directly accessible to application
+ * code. The length of the timer command queue is set by the
+ * configTIMER_QUEUE_LENGTH configuration constant.
+ *
+ * xTimerStop() stops a timer that was previously started using either of the
+ * The xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(),
+ * xTimerChangePeriod() or xTimerChangePeriodFromISR() API functions.
+ *
+ * Stopping a timer ensures the timer is not in the active state.
+ *
+ * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStop()
+ * to be available.
+ *
+ * @param xTimer The handle of the timer being stopped.
+ *
+ * @param xTicksToWait Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the stop command to be successfully
+ * sent to the timer command queue, should the queue already be full when
+ * xTimerStop() was called. xTicksToWait is ignored if xTimerStop() is called
+ * before the scheduler is started.
+ *
+ * @return pdFAIL will be returned if the stop command could not be sent to
+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
+ * timer service/daemon task relative to other tasks in the system. The timer
+ * service/daemon task priority is set by the configTIMER_TASK_PRIORITY
+ * configuration constant.
+ *
+ * Example usage:
+ *
+ * See the xTimerCreate() API function example usage scenario.
+ *
+ */
+#define xTimerStop( xTimer, xTicksToWait ) \
+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) )
+
+/**
+ * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,
+ * TickType_t xNewPeriod,
+ * TickType_t xTicksToWait );
+ *
+ * Timer functionality is provided by a timer service/daemon task. Many of the
+ * public FreeRTOS timer API functions send commands to the timer service task
+ * through a queue called the timer command queue. The timer command queue is
+ * private to the kernel itself and is not directly accessible to application
+ * code. The length of the timer command queue is set by the
+ * configTIMER_QUEUE_LENGTH configuration constant.
+ *
+ * xTimerChangePeriod() changes the period of a timer that was previously
+ * created using the xTimerCreate() API function.
+ *
+ * xTimerChangePeriod() can be called to change the period of an active or
+ * dormant state timer.
+ *
+ * The configUSE_TIMERS configuration constant must be set to 1 for
+ * xTimerChangePeriod() to be available.
+ *
+ * @param xTimer The handle of the timer that is having its period changed.
+ *
+ * @param xNewPeriod The new period for xTimer. Timer periods are specified in
+ * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time
+ * that has been specified in milliseconds. For example, if the timer must
+ * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively,
+ * if the timer must expire after 500ms, then xNewPeriod can be set to
+ * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than
+ * or equal to 1000.
+ *
+ * @param xTicksToWait Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the change period command to be
+ * successfully sent to the timer command queue, should the queue already be
+ * full when xTimerChangePeriod() was called. xTicksToWait is ignored if
+ * xTimerChangePeriod() is called before the scheduler is started.
+ *
+ * @return pdFAIL will be returned if the change period command could not be
+ * sent to the timer command queue even after xTicksToWait ticks had passed.
+ * pdPASS will be returned if the command was successfully sent to the timer
+ * command queue. When the command is actually processed will depend on the
+ * priority of the timer service/daemon task relative to other tasks in the
+ * system. The timer service/daemon task priority is set by the
+ * configTIMER_TASK_PRIORITY configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // This function assumes xTimer has already been created. If the timer
+ * // referenced by xTimer is already active when it is called, then the timer
+ * // is deleted. If the timer referenced by xTimer is not active when it is
+ * // called, then the period of the timer is set to 500ms and the timer is
+ * // started.
+ * void vAFunction( TimerHandle_t xTimer )
+ * {
+ * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )"
+ * {
+ * // xTimer is already active - delete it.
+ * xTimerDelete( xTimer );
+ * }
+ * else
+ * {
+ * // xTimer is not active, change its period to 500ms. This will also
+ * // cause the timer to start. Block for a maximum of 100 ticks if the
+ * // change period command cannot immediately be sent to the timer
+ * // command queue.
+ * if( xTimerChangePeriod( xTimer, 500 / portTICK_PERIOD_MS, 100 ) == pdPASS )
+ * {
+ * // The command was successfully sent.
+ * }
+ * else
+ * {
+ * // The command could not be sent, even after waiting for 100 ticks
+ * // to pass. Take appropriate action here.
+ * }
+ * }
+ * }
+ * @endverbatim
+ */
+#define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) \
+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) )
+
+/**
+ * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );
+ *
+ * Timer functionality is provided by a timer service/daemon task. Many of the
+ * public FreeRTOS timer API functions send commands to the timer service task
+ * through a queue called the timer command queue. The timer command queue is
+ * private to the kernel itself and is not directly accessible to application
+ * code. The length of the timer command queue is set by the
+ * configTIMER_QUEUE_LENGTH configuration constant.
+ *
+ * xTimerDelete() deletes a timer that was previously created using the
+ * xTimerCreate() API function.
+ *
+ * The configUSE_TIMERS configuration constant must be set to 1 for
+ * xTimerDelete() to be available.
+ *
+ * @param xTimer The handle of the timer being deleted.
+ *
+ * @param xTicksToWait Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the delete command to be
+ * successfully sent to the timer command queue, should the queue already be
+ * full when xTimerDelete() was called. xTicksToWait is ignored if xTimerDelete()
+ * is called before the scheduler is started.
+ *
+ * @return pdFAIL will be returned if the delete command could not be sent to
+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
+ * timer service/daemon task relative to other tasks in the system. The timer
+ * service/daemon task priority is set by the configTIMER_TASK_PRIORITY
+ * configuration constant.
+ *
+ * Example usage:
+ *
+ * See the xTimerChangePeriod() API function example usage scenario.
+ */
+#define xTimerDelete( xTimer, xTicksToWait ) \
+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) )
+
+/**
+ * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );
+ *
+ * Timer functionality is provided by a timer service/daemon task. Many of the
+ * public FreeRTOS timer API functions send commands to the timer service task
+ * through a queue called the timer command queue. The timer command queue is
+ * private to the kernel itself and is not directly accessible to application
+ * code. The length of the timer command queue is set by the
+ * configTIMER_QUEUE_LENGTH configuration constant.
+ *
+ * xTimerReset() re-starts a timer that was previously created using the
+ * xTimerCreate() API function. If the timer had already been started and was
+ * already in the active state, then xTimerReset() will cause the timer to
+ * re-evaluate its expiry time so that it is relative to when xTimerReset() was
+ * called. If the timer was in the dormant state then xTimerReset() has
+ * equivalent functionality to the xTimerStart() API function.
+ *
+ * Resetting a timer ensures the timer is in the active state. If the timer
+ * is not stopped, deleted, or reset in the mean time, the callback function
+ * associated with the timer will get called 'n' ticks after xTimerReset() was
+ * called, where 'n' is the timers defined period.
+ *
+ * It is valid to call xTimerReset() before the scheduler has been started, but
+ * when this is done the timer will not actually start until the scheduler is
+ * started, and the timers expiry time will be relative to when the scheduler is
+ * started, not relative to when xTimerReset() was called.
+ *
+ * The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset()
+ * to be available.
+ *
+ * @param xTimer The handle of the timer being reset/started/restarted.
+ *
+ * @param xTicksToWait Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the reset command to be successfully
+ * sent to the timer command queue, should the queue already be full when
+ * xTimerReset() was called. xTicksToWait is ignored if xTimerReset() is called
+ * before the scheduler is started.
+ *
+ * @return pdFAIL will be returned if the reset command could not be sent to
+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will
+ * be returned if the command was successfully sent to the timer command queue.
+ * When the command is actually processed will depend on the priority of the
+ * timer service/daemon task relative to other tasks in the system, although the
+ * timers expiry time is relative to when xTimerStart() is actually called. The
+ * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
+ * configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass
+ * // without a key being pressed, then the LCD back-light is switched off. In
+ * // this case, the timer is a one-shot timer.
+ *
+ * TimerHandle_t xBacklightTimer = NULL;
+ *
+ * // The callback function assigned to the one-shot timer. In this case the
+ * // parameter is not used.
+ * void vBacklightTimerCallback( TimerHandle_t pxTimer )
+ * {
+ * // The timer expired, therefore 5 seconds must have passed since a key
+ * // was pressed. Switch off the LCD back-light.
+ * vSetBacklightState( BACKLIGHT_OFF );
+ * }
+ *
+ * // The key press event handler.
+ * void vKeyPressEventHandler( char cKey )
+ * {
+ * // Ensure the LCD back-light is on, then reset the timer that is
+ * // responsible for turning the back-light off after 5 seconds of
+ * // key inactivity. Wait 10 ticks for the command to be successfully sent
+ * // if it cannot be sent immediately.
+ * vSetBacklightState( BACKLIGHT_ON );
+ * if( xTimerReset( xBacklightTimer, 100 ) != pdPASS )
+ * {
+ * // The reset command was not executed successfully. Take appropriate
+ * // action here.
+ * }
+ *
+ * // Perform the rest of the key processing here.
+ * }
+ *
+ * void main( void )
+ * {
+ * int32_t x;
+ *
+ * // Create then start the one-shot timer that is responsible for turning
+ * // the back-light off if no keys are pressed within a 5 second period.
+ * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel.
+ * ( 5000 / portTICK_PERIOD_MS), // The timer period in ticks.
+ * pdFALSE, // The timer is a one-shot timer.
+ * 0, // The id is not used by the callback so can take any value.
+ * vBacklightTimerCallback // The callback function that switches the LCD back-light off.
+ * );
+ *
+ * if( xBacklightTimer == NULL )
+ * {
+ * // The timer was not created.
+ * }
+ * else
+ * {
+ * // Start the timer. No block time is specified, and even if one was
+ * // it would be ignored because the scheduler has not yet been
+ * // started.
+ * if( xTimerStart( xBacklightTimer, 0 ) != pdPASS )
+ * {
+ * // The timer could not be set into the Active state.
+ * }
+ * }
+ *
+ * // ...
+ * // Create tasks here.
+ * // ...
+ *
+ * // Starting the scheduler will start the timer running as it has already
+ * // been set into the active state.
+ * vTaskStartScheduler();
+ *
+ * // Should not reach here.
+ * for( ;; );
+ * }
+ * @endverbatim
+ */
+#define xTimerReset( xTimer, xTicksToWait ) \
+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )
+
+/**
+ * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer,
+ * BaseType_t *pxHigherPriorityTaskWoken );
+ *
+ * A version of xTimerStart() that can be called from an interrupt service
+ * routine.
+ *
+ * @param xTimer The handle of the timer being started/restarted.
+ *
+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most
+ * of its time in the Blocked state, waiting for messages to arrive on the timer
+ * command queue. Calling xTimerStartFromISR() writes a message to the timer
+ * command queue, so has the potential to transition the timer service/daemon
+ * task out of the Blocked state. If calling xTimerStartFromISR() causes the
+ * timer service/daemon task to leave the Blocked state, and the timer service/
+ * daemon task has a priority equal to or greater than the currently executing
+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will
+ * get set to pdTRUE internally within the xTimerStartFromISR() function. If
+ * xTimerStartFromISR() sets this value to pdTRUE then a context switch should
+ * be performed before the interrupt exits.
+ *
+ * @return pdFAIL will be returned if the start command could not be sent to
+ * the timer command queue. pdPASS will be returned if the command was
+ * successfully sent to the timer command queue. When the command is actually
+ * processed will depend on the priority of the timer service/daemon task
+ * relative to other tasks in the system, although the timers expiry time is
+ * relative to when xTimerStartFromISR() is actually called. The timer
+ * service/daemon task priority is set by the configTIMER_TASK_PRIORITY
+ * configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // This scenario assumes xBacklightTimer has already been created. When a
+ * // key is pressed, an LCD back-light is switched on. If 5 seconds pass
+ * // without a key being pressed, then the LCD back-light is switched off. In
+ * // this case, the timer is a one-shot timer, and unlike the example given for
+ * // the xTimerReset() function, the key press event handler is an interrupt
+ * // service routine.
+ *
+ * // The callback function assigned to the one-shot timer. In this case the
+ * // parameter is not used.
+ * void vBacklightTimerCallback( TimerHandle_t pxTimer )
+ * {
+ * // The timer expired, therefore 5 seconds must have passed since a key
+ * // was pressed. Switch off the LCD back-light.
+ * vSetBacklightState( BACKLIGHT_OFF );
+ * }
+ *
+ * // The key press interrupt service routine.
+ * void vKeyPressEventInterruptHandler( void )
+ * {
+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // Ensure the LCD back-light is on, then restart the timer that is
+ * // responsible for turning the back-light off after 5 seconds of
+ * // key inactivity. This is an interrupt service routine so can only
+ * // call FreeRTOS API functions that end in "FromISR".
+ * vSetBacklightState( BACKLIGHT_ON );
+ *
+ * // xTimerStartFromISR() or xTimerResetFromISR() could be called here
+ * // as both cause the timer to re-calculate its expiry time.
+ * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was
+ * // declared (in this function).
+ * if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS )
+ * {
+ * // The start command was not executed successfully. Take appropriate
+ * // action here.
+ * }
+ *
+ * // Perform the rest of the key processing here.
+ *
+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch
+ * // should be performed. The syntax required to perform a context switch
+ * // from inside an ISR varies from port to port, and from compiler to
+ * // compiler. Inspect the demos for the port you are using to find the
+ * // actual syntax required.
+ * if( xHigherPriorityTaskWoken != pdFALSE )
+ * {
+ * // Call the interrupt safe yield function here (actual function
+ * // depends on the FreeRTOS port being used).
+ * }
+ * }
+ * @endverbatim
+ */
+#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) \
+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )
+
+/**
+ * BaseType_t xTimerStopFromISR( TimerHandle_t xTimer,
+ * BaseType_t *pxHigherPriorityTaskWoken );
+ *
+ * A version of xTimerStop() that can be called from an interrupt service
+ * routine.
+ *
+ * @param xTimer The handle of the timer being stopped.
+ *
+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most
+ * of its time in the Blocked state, waiting for messages to arrive on the timer
+ * command queue. Calling xTimerStopFromISR() writes a message to the timer
+ * command queue, so has the potential to transition the timer service/daemon
+ * task out of the Blocked state. If calling xTimerStopFromISR() causes the
+ * timer service/daemon task to leave the Blocked state, and the timer service/
+ * daemon task has a priority equal to or greater than the currently executing
+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will
+ * get set to pdTRUE internally within the xTimerStopFromISR() function. If
+ * xTimerStopFromISR() sets this value to pdTRUE then a context switch should
+ * be performed before the interrupt exits.
+ *
+ * @return pdFAIL will be returned if the stop command could not be sent to
+ * the timer command queue. pdPASS will be returned if the command was
+ * successfully sent to the timer command queue. When the command is actually
+ * processed will depend on the priority of the timer service/daemon task
+ * relative to other tasks in the system. The timer service/daemon task
+ * priority is set by the configTIMER_TASK_PRIORITY configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // This scenario assumes xTimer has already been created and started. When
+ * // an interrupt occurs, the timer should be simply stopped.
+ *
+ * // The interrupt service routine that stops the timer.
+ * void vAnExampleInterruptServiceRoutine( void )
+ * {
+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // The interrupt has occurred - simply stop the timer.
+ * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined
+ * // (within this function). As this is an interrupt service routine, only
+ * // FreeRTOS API functions that end in "FromISR" can be used.
+ * if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS )
+ * {
+ * // The stop command was not executed successfully. Take appropriate
+ * // action here.
+ * }
+ *
+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch
+ * // should be performed. The syntax required to perform a context switch
+ * // from inside an ISR varies from port to port, and from compiler to
+ * // compiler. Inspect the demos for the port you are using to find the
+ * // actual syntax required.
+ * if( xHigherPriorityTaskWoken != pdFALSE )
+ * {
+ * // Call the interrupt safe yield function here (actual function
+ * // depends on the FreeRTOS port being used).
+ * }
+ * }
+ * @endverbatim
+ */
+#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) \
+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U )
+
+/**
+ * BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer,
+ * TickType_t xNewPeriod,
+ * BaseType_t *pxHigherPriorityTaskWoken );
+ *
+ * A version of xTimerChangePeriod() that can be called from an interrupt
+ * service routine.
+ *
+ * @param xTimer The handle of the timer that is having its period changed.
+ *
+ * @param xNewPeriod The new period for xTimer. Timer periods are specified in
+ * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time
+ * that has been specified in milliseconds. For example, if the timer must
+ * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively,
+ * if the timer must expire after 500ms, then xNewPeriod can be set to
+ * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than
+ * or equal to 1000.
+ *
+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most
+ * of its time in the Blocked state, waiting for messages to arrive on the timer
+ * command queue. Calling xTimerChangePeriodFromISR() writes a message to the
+ * timer command queue, so has the potential to transition the timer service/
+ * daemon task out of the Blocked state. If calling xTimerChangePeriodFromISR()
+ * causes the timer service/daemon task to leave the Blocked state, and the
+ * timer service/daemon task has a priority equal to or greater than the
+ * currently executing task (the task that was interrupted), then
+ * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the
+ * xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets
+ * this value to pdTRUE then a context switch should be performed before the
+ * interrupt exits.
+ *
+ * @return pdFAIL will be returned if the command to change the timers period
+ * could not be sent to the timer command queue. pdPASS will be returned if the
+ * command was successfully sent to the timer command queue. When the command
+ * is actually processed will depend on the priority of the timer service/daemon
+ * task relative to other tasks in the system. The timer service/daemon task
+ * priority is set by the configTIMER_TASK_PRIORITY configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // This scenario assumes xTimer has already been created and started. When
+ * // an interrupt occurs, the period of xTimer should be changed to 500ms.
+ *
+ * // The interrupt service routine that changes the period of xTimer.
+ * void vAnExampleInterruptServiceRoutine( void )
+ * {
+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // The interrupt has occurred - change the period of xTimer to 500ms.
+ * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined
+ * // (within this function). As this is an interrupt service routine, only
+ * // FreeRTOS API functions that end in "FromISR" can be used.
+ * if( xTimerChangePeriodFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS )
+ * {
+ * // The command to change the timers period was not executed
+ * // successfully. Take appropriate action here.
+ * }
+ *
+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch
+ * // should be performed. The syntax required to perform a context switch
+ * // from inside an ISR varies from port to port, and from compiler to
+ * // compiler. Inspect the demos for the port you are using to find the
+ * // actual syntax required.
+ * if( xHigherPriorityTaskWoken != pdFALSE )
+ * {
+ * // Call the interrupt safe yield function here (actual function
+ * // depends on the FreeRTOS port being used).
+ * }
+ * }
+ * @endverbatim
+ */
+#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) \
+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U )
+
+/**
+ * BaseType_t xTimerResetFromISR( TimerHandle_t xTimer,
+ * BaseType_t *pxHigherPriorityTaskWoken );
+ *
+ * A version of xTimerReset() that can be called from an interrupt service
+ * routine.
+ *
+ * @param xTimer The handle of the timer that is to be started, reset, or
+ * restarted.
+ *
+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most
+ * of its time in the Blocked state, waiting for messages to arrive on the timer
+ * command queue. Calling xTimerResetFromISR() writes a message to the timer
+ * command queue, so has the potential to transition the timer service/daemon
+ * task out of the Blocked state. If calling xTimerResetFromISR() causes the
+ * timer service/daemon task to leave the Blocked state, and the timer service/
+ * daemon task has a priority equal to or greater than the currently executing
+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will
+ * get set to pdTRUE internally within the xTimerResetFromISR() function. If
+ * xTimerResetFromISR() sets this value to pdTRUE then a context switch should
+ * be performed before the interrupt exits.
+ *
+ * @return pdFAIL will be returned if the reset command could not be sent to
+ * the timer command queue. pdPASS will be returned if the command was
+ * successfully sent to the timer command queue. When the command is actually
+ * processed will depend on the priority of the timer service/daemon task
+ * relative to other tasks in the system, although the timers expiry time is
+ * relative to when xTimerResetFromISR() is actually called. The timer service/daemon
+ * task priority is set by the configTIMER_TASK_PRIORITY configuration constant.
+ *
+ * Example usage:
+ * @verbatim
+ * // This scenario assumes xBacklightTimer has already been created. When a
+ * // key is pressed, an LCD back-light is switched on. If 5 seconds pass
+ * // without a key being pressed, then the LCD back-light is switched off. In
+ * // this case, the timer is a one-shot timer, and unlike the example given for
+ * // the xTimerReset() function, the key press event handler is an interrupt
+ * // service routine.
+ *
+ * // The callback function assigned to the one-shot timer. In this case the
+ * // parameter is not used.
+ * void vBacklightTimerCallback( TimerHandle_t pxTimer )
+ * {
+ * // The timer expired, therefore 5 seconds must have passed since a key
+ * // was pressed. Switch off the LCD back-light.
+ * vSetBacklightState( BACKLIGHT_OFF );
+ * }
+ *
+ * // The key press interrupt service routine.
+ * void vKeyPressEventInterruptHandler( void )
+ * {
+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ *
+ * // Ensure the LCD back-light is on, then reset the timer that is
+ * // responsible for turning the back-light off after 5 seconds of
+ * // key inactivity. This is an interrupt service routine so can only
+ * // call FreeRTOS API functions that end in "FromISR".
+ * vSetBacklightState( BACKLIGHT_ON );
+ *
+ * // xTimerStartFromISR() or xTimerResetFromISR() could be called here
+ * // as both cause the timer to re-calculate its expiry time.
+ * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was
+ * // declared (in this function).
+ * if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS )
+ * {
+ * // The reset command was not executed successfully. Take appropriate
+ * // action here.
+ * }
+ *
+ * // Perform the rest of the key processing here.
+ *
+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch
+ * // should be performed. The syntax required to perform a context switch
+ * // from inside an ISR varies from port to port, and from compiler to
+ * // compiler. Inspect the demos for the port you are using to find the
+ * // actual syntax required.
+ * if( xHigherPriorityTaskWoken != pdFALSE )
+ * {
+ * // Call the interrupt safe yield function here (actual function
+ * // depends on the FreeRTOS port being used).
+ * }
+ * }
+ * @endverbatim
+ */
+#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) \
+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )
+
+
+/**
+ * BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend,
+ * void *pvParameter1,
+ * uint32_t ulParameter2,
+ * BaseType_t *pxHigherPriorityTaskWoken );
+ *
+ *
+ * Used from application interrupt service routines to defer the execution of a
+ * function to the RTOS daemon task (the timer service task, hence this function
+ * is implemented in timers.c and is prefixed with 'Timer').
+ *
+ * Ideally an interrupt service routine (ISR) is kept as short as possible, but
+ * sometimes an ISR either has a lot of processing to do, or needs to perform
+ * processing that is not deterministic. In these cases
+ * xTimerPendFunctionCallFromISR() can be used to defer processing of a function
+ * to the RTOS daemon task.
+ *
+ * A mechanism is provided that allows the interrupt to return directly to the
+ * task that will subsequently execute the pended callback function. This
+ * allows the callback function to execute contiguously in time with the
+ * interrupt - just as if the callback had executed in the interrupt itself.
+ *
+ * @param xFunctionToPend The function to execute from the timer service/
+ * daemon task. The function must conform to the PendedFunction_t
+ * prototype.
+ *
+ * @param pvParameter1 The value of the callback function's first parameter.
+ * The parameter has a void * type to allow it to be used to pass any type.
+ * For example, unsigned longs can be cast to a void *, or the void * can be
+ * used to point to a structure.
+ *
+ * @param ulParameter2 The value of the callback function's second parameter.
+ *
+ * @param pxHigherPriorityTaskWoken As mentioned above, calling this function
+ * will result in a message being sent to the timer daemon task. If the
+ * priority of the timer daemon task (which is set using
+ * configTIMER_TASK_PRIORITY in FreeRTOSConfig.h) is higher than the priority of
+ * the currently running task (the task the interrupt interrupted) then
+ * *pxHigherPriorityTaskWoken will be set to pdTRUE within
+ * xTimerPendFunctionCallFromISR(), indicating that a context switch should be
+ * requested before the interrupt exits. For that reason
+ * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
+ * example code below.
+ *
+ * @return pdPASS is returned if the message was successfully sent to the
+ * timer daemon task, otherwise pdFALSE is returned.
+ *
+ * Example usage:
+ * @verbatim
+ *
+ * // The callback function that will execute in the context of the daemon task.
+ * // Note callback functions must all use this same prototype.
+ * void vProcessInterface( void *pvParameter1, uint32_t ulParameter2 )
+ * {
+ * BaseType_t xInterfaceToService;
+ *
+ * // The interface that requires servicing is passed in the second
+ * // parameter. The first parameter is not used in this case.
+ * xInterfaceToService = ( BaseType_t ) ulParameter2;
+ *
+ * // ...Perform the processing here...
+ * }
+ *
+ * // An ISR that receives data packets from multiple interfaces
+ * void vAnISR( void )
+ * {
+ * BaseType_t xInterfaceToService, xHigherPriorityTaskWoken;
+ *
+ * // Query the hardware to determine which interface needs processing.
+ * xInterfaceToService = prvCheckInterfaces();
+ *
+ * // The actual processing is to be deferred to a task. Request the
+ * // vProcessInterface() callback function is executed, passing in the
+ * // number of the interface that needs processing. The interface to
+ * // service is passed in the second parameter. The first parameter is
+ * // not used in this case.
+ * xHigherPriorityTaskWoken = pdFALSE;
+ * xTimerPendFunctionCallFromISR( vProcessInterface, NULL, ( uint32_t ) xInterfaceToService, &xHigherPriorityTaskWoken );
+ *
+ * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context
+ * // switch should be requested. The macro used is port specific and will
+ * // be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
+ * // the documentation page for the port being used.
+ * portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+ *
+ * }
+ * @endverbatim
+ */
+BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend,
+ void * pvParameter1,
+ uint32_t ulParameter2,
+ BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
+
+/**
+ * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
+ * void *pvParameter1,
+ * uint32_t ulParameter2,
+ * TickType_t xTicksToWait );
+ *
+ *
+ * Used to defer the execution of a function to the RTOS daemon task (the timer
+ * service task, hence this function is implemented in timers.c and is prefixed
+ * with 'Timer').
+ *
+ * @param xFunctionToPend The function to execute from the timer service/
+ * daemon task. The function must conform to the PendedFunction_t
+ * prototype.
+ *
+ * @param pvParameter1 The value of the callback function's first parameter.
+ * The parameter has a void * type to allow it to be used to pass any type.
+ * For example, unsigned longs can be cast to a void *, or the void * can be
+ * used to point to a structure.
+ *
+ * @param ulParameter2 The value of the callback function's second parameter.
+ *
+ * @param xTicksToWait Calling this function will result in a message being
+ * sent to the timer daemon task on a queue. xTicksToWait is the amount of
+ * time the calling task should remain in the Blocked state (so not using any
+ * processing time) for space to become available on the timer queue if the
+ * queue is found to be full.
+ *
+ * @return pdPASS is returned if the message was successfully sent to the
+ * timer daemon task, otherwise pdFALSE is returned.
+ *
+ */
+BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
+ void * pvParameter1,
+ uint32_t ulParameter2,
+ TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+/**
+ * const char * const pcTimerGetName( TimerHandle_t xTimer );
+ *
+ * Returns the name that was assigned to a timer when the timer was created.
+ *
+ * @param xTimer The handle of the timer being queried.
+ *
+ * @return The name assigned to the timer specified by the xTimer parameter.
+ */
+const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+/**
+ * void vTimerSetReloadMode( TimerHandle_t xTimer, const BaseType_t xAutoReload );
+ *
+ * Updates a timer to be either an auto-reload timer, in which case the timer
+ * automatically resets itself each time it expires, or a one-shot timer, in
+ * which case the timer will only expire once unless it is manually restarted.
+ *
+ * @param xTimer The handle of the timer being updated.
+ *
+ * @param xAutoReload If xAutoReload is set to pdTRUE then the timer will
+ * expire repeatedly with a frequency set by the timer's period (see the
+ * xTimerPeriodInTicks parameter of the xTimerCreate() API function). If
+ * xAutoReload is set to pdFALSE then the timer will be a one-shot timer and
+ * enter the dormant state after it expires.
+ */
+void vTimerSetReloadMode( TimerHandle_t xTimer,
+ const BaseType_t xAutoReload ) PRIVILEGED_FUNCTION;
+
+/**
+ * BaseType_t xTimerGetReloadMode( TimerHandle_t xTimer );
+ *
+ * Queries a timer to determine if it is an auto-reload timer, in which case the timer
+ * automatically resets itself each time it expires, or a one-shot timer, in
+ * which case the timer will only expire once unless it is manually restarted.
+ *
+ * @param xTimer The handle of the timer being queried.
+ *
+ * @return If the timer is an auto-reload timer then pdTRUE is returned, otherwise
+ * pdFALSE is returned.
+ */
+BaseType_t xTimerGetReloadMode( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
+
+/**
+ * UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer );
+ *
+ * Queries a timer to determine if it is an auto-reload timer, in which case the timer
+ * automatically resets itself each time it expires, or a one-shot timer, in
+ * which case the timer will only expire once unless it is manually restarted.
+ *
+ * @param xTimer The handle of the timer being queried.
+ *
+ * @return If the timer is an auto-reload timer then pdTRUE is returned, otherwise
+ * pdFALSE is returned.
+ */
+UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
+
+/**
+ * TickType_t xTimerGetPeriod( TimerHandle_t xTimer );
+ *
+ * Returns the period of a timer.
+ *
+ * @param xTimer The handle of the timer being queried.
+ *
+ * @return The period of the timer in ticks.
+ */
+TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
+
+/**
+ * TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer );
+ *
+ * Returns the time in ticks at which the timer will expire. If this is less
+ * than the current tick count then the expiry time has overflowed from the
+ * current time.
+ *
+ * @param xTimer The handle of the timer being queried.
+ *
+ * @return If the timer is running then the time in ticks at which the timer
+ * will next expire is returned. If the timer is not running then the return
+ * value is undefined.
+ */
+TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
+
+/*
+ * Functions beyond this part are not part of the public API and are intended
+ * for use by the kernel only.
+ */
+BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION;
+BaseType_t xTimerGenericCommand( TimerHandle_t xTimer,
+ const BaseType_t xCommandID,
+ const TickType_t xOptionalValue,
+ BaseType_t * const pxHigherPriorityTaskWoken,
+ const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+ void vTimerSetTimerNumber( TimerHandle_t xTimer,
+ UBaseType_t uxTimerNumber ) PRIVILEGED_FUNCTION;
+ UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
+#endif
+
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+/**
+ * task.h
+ * @code{c}
+ * void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
+ * @endcode
+ *
+ * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Timer Task TCB. This function is required when
+ * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION
+ *
+ * @param ppxTimerTaskTCBBuffer A handle to a statically allocated TCB buffer
+ * @param ppxTimerTaskStackBuffer A handle to a statically allocated Stack buffer for the idle task
+ * @param pulTimerTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer
+ */
+ void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
+ StackType_t ** ppxTimerTaskStackBuffer,
+ uint32_t * pulTimerTaskStackSize );
+
+#endif
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+ }
+#endif
+/* *INDENT-ON* */
+#endif /* TIMERS_H */
diff --git a/source/test/freertos/src/FreeRTOSCommonHooks.c b/source/test/freertos/src/FreeRTOSCommonHooks.c
new file mode 100644
index 0000000..11cd74c
--- /dev/null
+++ b/source/test/freertos/src/FreeRTOSCommonHooks.c
@@ -0,0 +1,94 @@
+/*
+ * @brief Common FreeRTOS functions shared among platforms
+ *
+ * @note
+ * Copyright(C) NXP Semiconductors, 2012
+ * All rights reserved.
+ *
+ * @par
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * LPC products. This software is supplied "AS IS" without any warranties of
+ * any kind, and NXP Semiconductors and its licensor disclaim any and
+ * all warranties, express or implied, including all implied warranties of
+ * merchantability, fitness for a particular purpose and non-infringement of
+ * intellectual property rights. NXP Semiconductors assumes no responsibility
+ * or liability for the use of the software, conveys no license or rights under any
+ * patent, copyright, mask work right, or any other intellectual property rights in
+ * or to any products. NXP Semiconductors reserves the right to make changes
+ * in the software without notification. NXP Semiconductors also makes no
+ * representation or warranty that such application will be suitable for the
+ * specified use without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under NXP Semiconductors' and its
+ * licensor's relevant copyrights in the software, without fee, provided that it
+ * is used in conjunction with NXP Semiconductors microcontrollers. This
+ * copyright, permission, and disclaimer notice must appear in all copies of
+ * this code.
+ */
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "portable.h"
+
+#include "chip.h"
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+
+/* Delay for the specified number of milliSeconds */
+void FreeRTOSDelay(uint32_t ms)
+{
+ portTickType xDelayTime;
+
+ xDelayTime = xTaskGetTickCount();
+ vTaskDelayUntil(&xDelayTime, ms);
+}
+
+/* FreeRTOS malloc fail hook */
+void vApplicationMallocFailedHook(void)
+{
+ DEBUGSTR("DIE:ERROR:FreeRTOS: Malloc Failure!\r\n");
+ taskDISABLE_INTERRUPTS();
+ for (;; ) {}
+}
+
+/* FreeRTOS application idle hook */
+void vApplicationIdleHook(void)
+{
+ /* Best to sleep here until next systick */
+ __WFI();
+}
+
+/* FreeRTOS stack overflow hook */
+void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName)
+{
+ (void) pxTask;
+ (void) pcTaskName;
+
+ DEBUGOUT("DIE:ERROR:FreeRTOS: Stack overflow in task %s\r\n", pcTaskName);
+ /* Run time stack overflow checking is performed if
+ configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
+ function is called if a stack overflow is detected. */
+ taskDISABLE_INTERRUPTS();
+ for (;; ) {}
+}
+
+/* FreeRTOS application tick hook */
+void vApplicationTickHook(void)
+{}
diff --git a/source/test/freertos/src/croutine.c b/source/test/freertos/src/croutine.c
new file mode 100644
index 0000000..aa5ea6f
--- /dev/null
+++ b/source/test/freertos/src/croutine.c
@@ -0,0 +1,363 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "croutine.h"
+
+/* Remove the whole file is co-routines are not being used. */
+#if ( configUSE_CO_ROUTINES != 0 )
+
+/*
+ * Some kernel aware debuggers require data to be viewed to be global, rather
+ * than file scope.
+ */
+ #ifdef portREMOVE_STATIC_QUALIFIER
+ #define static
+ #endif
+
+
+/* Lists for ready and blocked co-routines. --------------------*/
+ static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
+ static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */
+ static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
+ static List_t * pxDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used. */
+ static List_t * pxOverflowDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
+ static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
+
+/* Other file private variables. --------------------------------*/
+ CRCB_t * pxCurrentCoRoutine = NULL;
+ static UBaseType_t uxTopCoRoutineReadyPriority = 0;
+ static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
+
+/* The initial state of the co-routine when it is created. */
+ #define corINITIAL_STATE ( 0 )
+
+/*
+ * Place the co-routine represented by pxCRCB into the appropriate ready queue
+ * for the priority. It is inserted at the end of the list.
+ *
+ * This macro accesses the co-routine ready lists and therefore must not be
+ * used from within an ISR.
+ */
+ #define prvAddCoRoutineToReadyQueue( pxCRCB ) \
+ { \
+ if( ( pxCRCB )->uxPriority > uxTopCoRoutineReadyPriority ) \
+ { \
+ uxTopCoRoutineReadyPriority = ( pxCRCB )->uxPriority; \
+ } \
+ vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ ( pxCRCB )->uxPriority ] ), &( ( pxCRCB )->xGenericListItem ) ); \
+ }
+
+/*
+ * Utility to ready all the lists used by the scheduler. This is called
+ * automatically upon the creation of the first co-routine.
+ */
+ static void prvInitialiseCoRoutineLists( void );
+
+/*
+ * Co-routines that are readied by an interrupt cannot be placed directly into
+ * the ready lists (there is no mutual exclusion). Instead they are placed in
+ * in the pending ready list in order that they can later be moved to the ready
+ * list by the co-routine scheduler.
+ */
+ static void prvCheckPendingReadyList( void );
+
+/*
+ * Macro that looks at the list of co-routines that are currently delayed to
+ * see if any require waking.
+ *
+ * Co-routines are stored in the queue in the order of their wake time -
+ * meaning once one co-routine has been found whose timer has not expired
+ * we need not look any further down the list.
+ */
+ static void prvCheckDelayedList( void );
+
+/*-----------------------------------------------------------*/
+
+ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode,
+ UBaseType_t uxPriority,
+ UBaseType_t uxIndex )
+ {
+ BaseType_t xReturn;
+ CRCB_t * pxCoRoutine;
+
+ /* Allocate the memory that will store the co-routine control block. */
+ pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
+
+ if( pxCoRoutine )
+ {
+ /* If pxCurrentCoRoutine is NULL then this is the first co-routine to
+ * be created and the co-routine data structures need initialising. */
+ if( pxCurrentCoRoutine == NULL )
+ {
+ pxCurrentCoRoutine = pxCoRoutine;
+ prvInitialiseCoRoutineLists();
+ }
+
+ /* Check the priority is within limits. */
+ if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
+ {
+ uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
+ }
+
+ /* Fill out the co-routine control block from the function parameters. */
+ pxCoRoutine->uxState = corINITIAL_STATE;
+ pxCoRoutine->uxPriority = uxPriority;
+ pxCoRoutine->uxIndex = uxIndex;
+ pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
+
+ /* Initialise all the other co-routine control block parameters. */
+ vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
+ vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
+
+ /* Set the co-routine control block as a link back from the ListItem_t.
+ * This is so we can get back to the containing CRCB from a generic item
+ * in a list. */
+ listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
+ listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
+
+ /* Event lists are always in priority order. */
+ listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
+
+ /* Now the co-routine has been initialised it can be added to the ready
+ * list at the correct priority. */
+ prvAddCoRoutineToReadyQueue( pxCoRoutine );
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+ }
+
+ return xReturn;
+ }
+/*-----------------------------------------------------------*/
+
+ void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay,
+ List_t * pxEventList )
+ {
+ TickType_t xTimeToWake;
+
+ /* Calculate the time to wake - this may overflow but this is
+ * not a problem. */
+ xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
+
+ /* We must remove ourselves from the ready list before adding
+ * ourselves to the blocked list as the same list item is used for
+ * both lists. */
+ ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
+
+ /* The list item will be inserted in wake time order. */
+ listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
+
+ if( xTimeToWake < xCoRoutineTickCount )
+ {
+ /* Wake time has overflowed. Place this item in the
+ * overflow list. */
+ vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
+ }
+ else
+ {
+ /* The wake time has not overflowed, so we can use the
+ * current block list. */
+ vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
+ }
+
+ if( pxEventList )
+ {
+ /* Also add the co-routine to an event list. If this is done then the
+ * function must be called with interrupts disabled. */
+ vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
+ }
+ }
+/*-----------------------------------------------------------*/
+
+ static void prvCheckPendingReadyList( void )
+ {
+ /* Are there any co-routines waiting to get moved to the ready list? These
+ * are co-routines that have been readied by an ISR. The ISR cannot access
+ * the ready lists itself. */
+ while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
+ {
+ CRCB_t * pxUnblockedCRCB;
+
+ /* The pending ready list can be accessed by an ISR. */
+ portDISABLE_INTERRUPTS();
+ {
+ pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyCoRoutineList ) );
+ ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
+ }
+ portENABLE_INTERRUPTS();
+
+ ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
+ prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
+ }
+ }
+/*-----------------------------------------------------------*/
+
+ static void prvCheckDelayedList( void )
+ {
+ CRCB_t * pxCRCB;
+
+ xPassedTicks = xTaskGetTickCount() - xLastTickCount;
+
+ while( xPassedTicks )
+ {
+ xCoRoutineTickCount++;
+ xPassedTicks--;
+
+ /* If the tick count has overflowed we need to swap the ready lists. */
+ if( xCoRoutineTickCount == 0 )
+ {
+ List_t * pxTemp;
+
+ /* Tick count has overflowed so we need to swap the delay lists. If there are
+ * any items in pxDelayedCoRoutineList here then there is an error! */
+ pxTemp = pxDelayedCoRoutineList;
+ pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
+ pxOverflowDelayedCoRoutineList = pxTemp;
+ }
+
+ /* See if this tick has made a timeout expire. */
+ while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
+ {
+ pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
+
+ if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
+ {
+ /* Timeout not yet expired. */
+ break;
+ }
+
+ portDISABLE_INTERRUPTS();
+ {
+ /* The event could have occurred just before this critical
+ * section. If this is the case then the generic list item will
+ * have been moved to the pending ready list and the following
+ * line is still valid. Also the pvContainer parameter will have
+ * been set to NULL so the following lines are also valid. */
+ ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
+
+ /* Is the co-routine waiting on an event also? */
+ if( pxCRCB->xEventListItem.pxContainer )
+ {
+ ( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
+ }
+ }
+ portENABLE_INTERRUPTS();
+
+ prvAddCoRoutineToReadyQueue( pxCRCB );
+ }
+ }
+
+ xLastTickCount = xCoRoutineTickCount;
+ }
+/*-----------------------------------------------------------*/
+
+ void vCoRoutineSchedule( void )
+ {
+ /* Only run a co-routine after prvInitialiseCoRoutineLists() has been
+ * called. prvInitialiseCoRoutineLists() is called automatically when a
+ * co-routine is created. */
+ if( pxDelayedCoRoutineList != NULL )
+ {
+ /* See if any co-routines readied by events need moving to the ready lists. */
+ prvCheckPendingReadyList();
+
+ /* See if any delayed co-routines have timed out. */
+ prvCheckDelayedList();
+
+ /* Find the highest priority queue that contains ready co-routines. */
+ while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
+ {
+ if( uxTopCoRoutineReadyPriority == 0 )
+ {
+ /* No more co-routines to check. */
+ return;
+ }
+
+ --uxTopCoRoutineReadyPriority;
+ }
+
+ /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
+ * of the same priority get an equal share of the processor time. */
+ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
+
+ /* Call the co-routine. */
+ ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
+ }
+ }
+/*-----------------------------------------------------------*/
+
+ static void prvInitialiseCoRoutineLists( void )
+ {
+ UBaseType_t uxPriority;
+
+ for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
+ {
+ vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
+ }
+
+ vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
+ vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
+ vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
+
+ /* Start with pxDelayedCoRoutineList using list1 and the
+ * pxOverflowDelayedCoRoutineList using list2. */
+ pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
+ pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
+ }
+/*-----------------------------------------------------------*/
+
+ BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList )
+ {
+ CRCB_t * pxUnblockedCRCB;
+ BaseType_t xReturn;
+
+ /* This function is called from within an interrupt. It can only access
+ * event lists and the pending ready list. This function assumes that a
+ * check has already been made to ensure pxEventList is not empty. */
+ pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
+ ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
+ vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
+
+ if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_CO_ROUTINES == 0 */
diff --git a/source/test/freertos/src/event_groups.c b/source/test/freertos/src/event_groups.c
new file mode 100644
index 0000000..f3e6aff
--- /dev/null
+++ b/source/test/freertos/src/event_groups.c
@@ -0,0 +1,778 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/* Standard includes. */
+#include
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+ * all the API functions to use the MPU wrappers. That should only be done when
+ * task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "timers.h"
+#include "event_groups.h"
+
+/* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
+ * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
+ * for the header files above, but not in this file, in order to generate the
+ * correct privileged Vs unprivileged linkage and placement. */
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */
+
+/* The following bit fields convey control information in a task's event list
+ * item value. It is important they don't clash with the
+ * taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
+#if configUSE_16_BIT_TICKS == 1
+ #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
+ #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
+ #define eventWAIT_FOR_ALL_BITS 0x0400U
+ #define eventEVENT_BITS_CONTROL_BYTES 0xff00U
+#else
+ #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
+ #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
+ #define eventWAIT_FOR_ALL_BITS 0x04000000UL
+ #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
+#endif
+
+typedef struct EventGroupDef_t
+{
+ EventBits_t uxEventBits;
+ List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxEventGroupNumber;
+ #endif
+
+ #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
+ #endif
+} EventGroup_t;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Test the bits set in uxCurrentEventBits to see if the wait condition is met.
+ * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
+ * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
+ * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
+ * wait condition is met if any of the bits set in uxBitsToWait for are also set
+ * in uxCurrentEventBits.
+ */
+static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
+ const EventBits_t uxBitsToWaitFor,
+ const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
+
+/*-----------------------------------------------------------*/
+
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+ EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer )
+ {
+ EventGroup_t * pxEventBits;
+
+ /* A StaticEventGroup_t object must be provided. */
+ configASSERT( pxEventGroupBuffer );
+
+ #if ( configASSERT_DEFINED == 1 )
+ {
+ /* Sanity check that the size of the structure used to declare a
+ * variable of type StaticEventGroup_t equals the size of the real
+ * event group structure. */
+ volatile size_t xSize = sizeof( StaticEventGroup_t );
+ configASSERT( xSize == sizeof( EventGroup_t ) );
+ } /*lint !e529 xSize is referenced if configASSERT() is defined. */
+ #endif /* configASSERT_DEFINED */
+
+ /* The user has provided a statically allocated event group - use it. */
+ pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 !e9087 EventGroup_t and StaticEventGroup_t are deliberately aliased for data hiding purposes and guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
+
+ if( pxEventBits != NULL )
+ {
+ pxEventBits->uxEventBits = 0;
+ vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
+
+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ {
+ /* Both static and dynamic allocation can be used, so note that
+ * this event group was created statically in case the event group
+ * is later deleted. */
+ pxEventBits->ucStaticallyAllocated = pdTRUE;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+ traceEVENT_GROUP_CREATE( pxEventBits );
+ }
+ else
+ {
+ /* xEventGroupCreateStatic should only ever be called with
+ * pxEventGroupBuffer pointing to a pre-allocated (compile time
+ * allocated) StaticEventGroup_t variable. */
+ traceEVENT_GROUP_CREATE_FAILED();
+ }
+
+ return pxEventBits;
+ }
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+
+ EventGroupHandle_t xEventGroupCreate( void )
+ {
+ EventGroup_t * pxEventBits;
+
+ /* Allocate the event group. Justification for MISRA deviation as
+ * follows: pvPortMalloc() always ensures returned memory blocks are
+ * aligned per the requirements of the MCU stack. In this case
+ * pvPortMalloc() must return a pointer that is guaranteed to meet the
+ * alignment requirements of the EventGroup_t structure - which (if you
+ * follow it through) is the alignment requirements of the TickType_t type
+ * (EventBits_t being of TickType_t itself). Therefore, whenever the
+ * stack alignment requirements are greater than or equal to the
+ * TickType_t alignment requirements the cast is safe. In other cases,
+ * where the natural word size of the architecture is less than
+ * sizeof( TickType_t ), the TickType_t variables will be accessed in two
+ * or more reads operations, and the alignment requirements is only that
+ * of each individual read. */
+ pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
+
+ if( pxEventBits != NULL )
+ {
+ pxEventBits->uxEventBits = 0;
+ vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
+
+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ /* Both static and dynamic allocation can be used, so note this
+ * event group was allocated statically in case the event group is
+ * later deleted. */
+ pxEventBits->ucStaticallyAllocated = pdFALSE;
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
+
+ traceEVENT_GROUP_CREATE( pxEventBits );
+ }
+ else
+ {
+ traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */
+ }
+
+ return pxEventBits;
+ }
+
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToSet,
+ const EventBits_t uxBitsToWaitFor,
+ TickType_t xTicksToWait )
+{
+ EventBits_t uxOriginalBitValue, uxReturn;
+ EventGroup_t * pxEventBits = xEventGroup;
+ BaseType_t xAlreadyYielded;
+ BaseType_t xTimeoutOccurred = pdFALSE;
+
+ configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
+ configASSERT( uxBitsToWaitFor != 0 );
+ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+ {
+ configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+ }
+ #endif
+
+ vTaskSuspendAll();
+ {
+ uxOriginalBitValue = pxEventBits->uxEventBits;
+
+ ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
+
+ if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
+ {
+ /* All the rendezvous bits are now set - no need to block. */
+ uxReturn = ( uxOriginalBitValue | uxBitsToSet );
+
+ /* Rendezvous always clear the bits. They will have been cleared
+ * already unless this is the only task in the rendezvous. */
+ pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
+
+ xTicksToWait = 0;
+ }
+ else
+ {
+ if( xTicksToWait != ( TickType_t ) 0 )
+ {
+ traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
+
+ /* Store the bits that the calling task is waiting for in the
+ * task's event list item so the kernel knows when a match is
+ * found. Then enter the blocked state. */
+ vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
+
+ /* This assignment is obsolete as uxReturn will get set after
+ * the task unblocks, but some compilers mistakenly generate a
+ * warning about uxReturn being returned without being set if the
+ * assignment is omitted. */
+ uxReturn = 0;
+ }
+ else
+ {
+ /* The rendezvous bits were not set, but no block time was
+ * specified - just return the current event bit value. */
+ uxReturn = pxEventBits->uxEventBits;
+ xTimeoutOccurred = pdTRUE;
+ }
+ }
+ }
+ xAlreadyYielded = xTaskResumeAll();
+
+ if( xTicksToWait != ( TickType_t ) 0 )
+ {
+ if( xAlreadyYielded == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* The task blocked to wait for its required bits to be set - at this
+ * point either the required bits were set or the block time expired. If
+ * the required bits were set they will have been stored in the task's
+ * event list item, and they should now be retrieved then cleared. */
+ uxReturn = uxTaskResetEventItemValue();
+
+ if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
+ {
+ /* The task timed out, just return the current event bit value. */
+ taskENTER_CRITICAL();
+ {
+ uxReturn = pxEventBits->uxEventBits;
+
+ /* Although the task got here because it timed out before the
+ * bits it was waiting for were set, it is possible that since it
+ * unblocked another task has set the bits. If this is the case
+ * then it needs to clear the bits before exiting. */
+ if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
+ {
+ pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ xTimeoutOccurred = pdTRUE;
+ }
+ else
+ {
+ /* The task unblocked because the bits were set. */
+ }
+
+ /* Control bits might be set as the task had blocked should not be
+ * returned. */
+ uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
+ }
+
+ traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
+
+ /* Prevent compiler warnings when trace macros are not used. */
+ ( void ) xTimeoutOccurred;
+
+ return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToWaitFor,
+ const BaseType_t xClearOnExit,
+ const BaseType_t xWaitForAllBits,
+ TickType_t xTicksToWait )
+{
+ EventGroup_t * pxEventBits = xEventGroup;
+ EventBits_t uxReturn, uxControlBits = 0;
+ BaseType_t xWaitConditionMet, xAlreadyYielded;
+ BaseType_t xTimeoutOccurred = pdFALSE;
+
+ /* Check the user is not attempting to wait on the bits used by the kernel
+ * itself, and that at least one bit is being requested. */
+ configASSERT( xEventGroup );
+ configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
+ configASSERT( uxBitsToWaitFor != 0 );
+ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+ {
+ configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+ }
+ #endif
+
+ vTaskSuspendAll();
+ {
+ const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
+
+ /* Check to see if the wait condition is already met or not. */
+ xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
+
+ if( xWaitConditionMet != pdFALSE )
+ {
+ /* The wait condition has already been met so there is no need to
+ * block. */
+ uxReturn = uxCurrentEventBits;
+ xTicksToWait = ( TickType_t ) 0;
+
+ /* Clear the wait bits if requested to do so. */
+ if( xClearOnExit != pdFALSE )
+ {
+ pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else if( xTicksToWait == ( TickType_t ) 0 )
+ {
+ /* The wait condition has not been met, but no block time was
+ * specified, so just return the current value. */
+ uxReturn = uxCurrentEventBits;
+ xTimeoutOccurred = pdTRUE;
+ }
+ else
+ {
+ /* The task is going to block to wait for its required bits to be
+ * set. uxControlBits are used to remember the specified behaviour of
+ * this call to xEventGroupWaitBits() - for use when the event bits
+ * unblock the task. */
+ if( xClearOnExit != pdFALSE )
+ {
+ uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ if( xWaitForAllBits != pdFALSE )
+ {
+ uxControlBits |= eventWAIT_FOR_ALL_BITS;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Store the bits that the calling task is waiting for in the
+ * task's event list item so the kernel knows when a match is
+ * found. Then enter the blocked state. */
+ vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
+
+ /* This is obsolete as it will get set after the task unblocks, but
+ * some compilers mistakenly generate a warning about the variable
+ * being returned without being set if it is not done. */
+ uxReturn = 0;
+
+ traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
+ }
+ }
+ xAlreadyYielded = xTaskResumeAll();
+
+ if( xTicksToWait != ( TickType_t ) 0 )
+ {
+ if( xAlreadyYielded == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* The task blocked to wait for its required bits to be set - at this
+ * point either the required bits were set or the block time expired. If
+ * the required bits were set they will have been stored in the task's
+ * event list item, and they should now be retrieved then cleared. */
+ uxReturn = uxTaskResetEventItemValue();
+
+ if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
+ {
+ taskENTER_CRITICAL();
+ {
+ /* The task timed out, just return the current event bit value. */
+ uxReturn = pxEventBits->uxEventBits;
+
+ /* It is possible that the event bits were updated between this
+ * task leaving the Blocked state and running again. */
+ if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
+ {
+ if( xClearOnExit != pdFALSE )
+ {
+ pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ xTimeoutOccurred = pdTRUE;
+ }
+ taskEXIT_CRITICAL();
+ }
+ else
+ {
+ /* The task unblocked because the bits were set. */
+ }
+
+ /* The task blocked so control bits may have been set. */
+ uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
+ }
+
+ traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
+
+ /* Prevent compiler warnings when trace macros are not used. */
+ ( void ) xTimeoutOccurred;
+
+ return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToClear )
+{
+ EventGroup_t * pxEventBits = xEventGroup;
+ EventBits_t uxReturn;
+
+ /* Check the user is not attempting to clear the bits used by the kernel
+ * itself. */
+ configASSERT( xEventGroup );
+ configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
+
+ taskENTER_CRITICAL();
+ {
+ traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
+
+ /* The value returned is the event group value prior to the bits being
+ * cleared. */
+ uxReturn = pxEventBits->uxEventBits;
+
+ /* Clear the bits. */
+ pxEventBits->uxEventBits &= ~uxBitsToClear;
+ }
+ taskEXIT_CRITICAL();
+
+ return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
+
+ BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToClear )
+ {
+ BaseType_t xReturn;
+
+ traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
+ xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */
+
+ return xReturn;
+ }
+
+#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
+{
+ UBaseType_t uxSavedInterruptStatus;
+ EventGroup_t const * const pxEventBits = xEventGroup;
+ EventBits_t uxReturn;
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ uxReturn = pxEventBits->uxEventBits;
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return uxReturn;
+} /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */
+/*-----------------------------------------------------------*/
+
+EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToSet )
+{
+ ListItem_t * pxListItem;
+ ListItem_t * pxNext;
+ ListItem_t const * pxListEnd;
+ List_t const * pxList;
+ EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
+ EventGroup_t * pxEventBits = xEventGroup;
+ BaseType_t xMatchFound = pdFALSE;
+
+ /* Check the user is not attempting to set the bits used by the kernel
+ * itself. */
+ configASSERT( xEventGroup );
+ configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
+
+ pxList = &( pxEventBits->xTasksWaitingForBits );
+ pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
+ vTaskSuspendAll();
+ {
+ traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
+
+ pxListItem = listGET_HEAD_ENTRY( pxList );
+
+ /* Set the bits. */
+ pxEventBits->uxEventBits |= uxBitsToSet;
+
+ /* See if the new bit value should unblock any tasks. */
+ while( pxListItem != pxListEnd )
+ {
+ pxNext = listGET_NEXT( pxListItem );
+ uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
+ xMatchFound = pdFALSE;
+
+ /* Split the bits waited for from the control bits. */
+ uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
+ uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
+
+ if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
+ {
+ /* Just looking for single bit being set. */
+ if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
+ {
+ xMatchFound = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
+ {
+ /* All bits are set. */
+ xMatchFound = pdTRUE;
+ }
+ else
+ {
+ /* Need all bits to be set, but not all the bits were set. */
+ }
+
+ if( xMatchFound != pdFALSE )
+ {
+ /* The bits match. Should the bits be cleared on exit? */
+ if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
+ {
+ uxBitsToClear |= uxBitsWaitedFor;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Store the actual event flag value in the task's event list
+ * item before removing the task from the event list. The
+ * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
+ * that is was unblocked due to its required bits matching, rather
+ * than because it timed out. */
+ vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
+ }
+
+ /* Move onto the next list item. Note pxListItem->pxNext is not
+ * used here as the list item may have been removed from the event list
+ * and inserted into the ready/pending reading list. */
+ pxListItem = pxNext;
+ }
+
+ /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
+ * bit was set in the control word. */
+ pxEventBits->uxEventBits &= ~uxBitsToClear;
+ }
+ ( void ) xTaskResumeAll();
+
+ return pxEventBits->uxEventBits;
+}
+/*-----------------------------------------------------------*/
+
+void vEventGroupDelete( EventGroupHandle_t xEventGroup )
+{
+ EventGroup_t * pxEventBits = xEventGroup;
+ const List_t * pxTasksWaitingForBits;
+
+ configASSERT( pxEventBits );
+
+ pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
+
+ vTaskSuspendAll();
+ {
+ traceEVENT_GROUP_DELETE( xEventGroup );
+
+ while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
+ {
+ /* Unblock the task, returning 0 as the event list is being deleted
+ * and cannot therefore have any bits set. */
+ configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
+ vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
+ }
+ }
+ ( void ) xTaskResumeAll();
+
+ #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
+ {
+ /* The event group can only have been allocated dynamically - free
+ * it again. */
+ vPortFree( pxEventBits );
+ }
+ #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+ {
+ /* The event group could have been allocated statically or
+ * dynamically, so check before attempting to free the memory. */
+ if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
+ {
+ vPortFree( pxEventBits );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+}
+/*-----------------------------------------------------------*/
+
+/* For internal use only - execute a 'set bits' command that was pended from
+ * an interrupt. */
+void vEventGroupSetBitsCallback( void * pvEventGroup,
+ const uint32_t ulBitsToSet )
+{
+ ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
+}
+/*-----------------------------------------------------------*/
+
+/* For internal use only - execute a 'clear bits' command that was pended from
+ * an interrupt. */
+void vEventGroupClearBitsCallback( void * pvEventGroup,
+ const uint32_t ulBitsToClear )
+{
+ ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
+ const EventBits_t uxBitsToWaitFor,
+ const BaseType_t xWaitForAllBits )
+{
+ BaseType_t xWaitConditionMet = pdFALSE;
+
+ if( xWaitForAllBits == pdFALSE )
+ {
+ /* Task only has to wait for one bit within uxBitsToWaitFor to be
+ * set. Is one already set? */
+ if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
+ {
+ xWaitConditionMet = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* Task has to wait for all the bits in uxBitsToWaitFor to be set.
+ * Are they set already? */
+ if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
+ {
+ xWaitConditionMet = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ return xWaitConditionMet;
+}
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
+
+ BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
+ const EventBits_t uxBitsToSet,
+ BaseType_t * pxHigherPriorityTaskWoken )
+ {
+ BaseType_t xReturn;
+
+ traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
+ xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */
+
+ return xReturn;
+ }
+
+#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
+ {
+ UBaseType_t xReturn;
+ EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
+
+ if( xEventGroup == NULL )
+ {
+ xReturn = 0;
+ }
+ else
+ {
+ xReturn = pxEventBits->uxEventGroupNumber;
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ void vEventGroupSetNumber( void * xEventGroup,
+ UBaseType_t uxEventGroupNumber )
+ {
+ ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
diff --git a/source/test/freertos/src/heap_3.c b/source/test/freertos/src/heap_3.c
new file mode 100644
index 0000000..dd5f502
--- /dev/null
+++ b/source/test/freertos/src/heap_3.c
@@ -0,0 +1,95 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+
+/*
+ * Implementation of pvPortMalloc() and vPortFree() that relies on the
+ * compilers own malloc() and free() implementations.
+ *
+ * This file can only be used if the linker is configured to to generate
+ * a heap memory area.
+ *
+ * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the
+ * memory management pages of https://www.FreeRTOS.org for more information.
+ */
+
+#include
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+ * all the API functions to use the MPU wrappers. That should only be done when
+ * task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "portable.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
+#endif
+
+/*-----------------------------------------------------------*/
+
+void * pvPortMalloc( size_t xWantedSize )
+{
+ void * pvReturn;
+
+ vTaskSuspendAll();
+ {
+ pvReturn = malloc( xWantedSize );
+ traceMALLOC( pvReturn, xWantedSize );
+ }
+ ( void ) xTaskResumeAll();
+
+ #if ( configUSE_MALLOC_FAILED_HOOK == 1 )
+ {
+ if( pvReturn == NULL )
+ {
+ vApplicationMallocFailedHook();
+ }
+ }
+ #endif
+
+ return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void * pv )
+{
+ if( pv != NULL )
+ {
+ vTaskSuspendAll();
+ {
+ free( pv );
+ traceFREE( pv, 0 );
+ }
+ ( void ) xTaskResumeAll();
+ }
+}
diff --git a/source/test/freertos/src/list.c b/source/test/freertos/src/list.c
new file mode 100644
index 0000000..0f4f42e
--- /dev/null
+++ b/source/test/freertos/src/list.c
@@ -0,0 +1,226 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+
+#include
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+ * all the API functions to use the MPU wrappers. That should only be done when
+ * task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "list.h"
+
+/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
+ * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be
+ * defined for the header files above, but not in this file, in order to
+ * generate the correct privileged Vs unprivileged linkage and placement. */
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
+
+/*-----------------------------------------------------------
+* PUBLIC LIST API documented in list.h
+*----------------------------------------------------------*/
+
+void vListInitialise( List_t * const pxList )
+{
+ /* The list structure contains a list item which is used to mark the
+ * end of the list. To initialise the list the list end is inserted
+ * as the only list entry. */
+ pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
+
+ listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
+
+ /* The list end value is the highest possible value in the list to
+ * ensure it remains at the end of the list. */
+ pxList->xListEnd.xItemValue = portMAX_DELAY;
+
+ /* The list end next and previous pointers point to itself so we know
+ * when the list is empty. */
+ pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
+ pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
+
+ /* Initialize the remaining fields of xListEnd when it is a proper ListItem_t */
+ #if ( configUSE_MINI_LIST_ITEM == 0 )
+ {
+ pxList->xListEnd.pvOwner = NULL;
+ pxList->xListEnd.pxContainer = NULL;
+ listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
+ }
+ #endif
+
+ pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
+
+ /* Write known values into the list if
+ * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+ listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
+ listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
+}
+/*-----------------------------------------------------------*/
+
+void vListInitialiseItem( ListItem_t * const pxItem )
+{
+ /* Make sure the list item is not recorded as being on a list. */
+ pxItem->pxContainer = NULL;
+
+ /* Write known values into the list item if
+ * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
+ listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
+ listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
+}
+/*-----------------------------------------------------------*/
+
+void vListInsertEnd( List_t * const pxList,
+ ListItem_t * const pxNewListItem )
+{
+ ListItem_t * const pxIndex = pxList->pxIndex;
+
+ /* Only effective when configASSERT() is also defined, these tests may catch
+ * the list data structures being overwritten in memory. They will not catch
+ * data errors caused by incorrect configuration or use of FreeRTOS. */
+ listTEST_LIST_INTEGRITY( pxList );
+ listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
+
+ /* Insert a new list item into pxList, but rather than sort the list,
+ * makes the new list item the last item to be removed by a call to
+ * listGET_OWNER_OF_NEXT_ENTRY(). */
+ pxNewListItem->pxNext = pxIndex;
+ pxNewListItem->pxPrevious = pxIndex->pxPrevious;
+
+ /* Only used during decision coverage testing. */
+ mtCOVERAGE_TEST_DELAY();
+
+ pxIndex->pxPrevious->pxNext = pxNewListItem;
+ pxIndex->pxPrevious = pxNewListItem;
+
+ /* Remember which list the item is in. */
+ pxNewListItem->pxContainer = pxList;
+
+ ( pxList->uxNumberOfItems )++;
+}
+/*-----------------------------------------------------------*/
+
+void vListInsert( List_t * const pxList,
+ ListItem_t * const pxNewListItem )
+{
+ ListItem_t * pxIterator;
+ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
+
+ /* Only effective when configASSERT() is also defined, these tests may catch
+ * the list data structures being overwritten in memory. They will not catch
+ * data errors caused by incorrect configuration or use of FreeRTOS. */
+ listTEST_LIST_INTEGRITY( pxList );
+ listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
+
+ /* Insert the new list item into the list, sorted in xItemValue order.
+ *
+ * If the list already contains a list item with the same item value then the
+ * new list item should be placed after it. This ensures that TCBs which are
+ * stored in ready lists (all of which have the same xItemValue value) get a
+ * share of the CPU. However, if the xItemValue is the same as the back marker
+ * the iteration loop below will not end. Therefore the value is checked
+ * first, and the algorithm slightly modified if necessary. */
+ if( xValueOfInsertion == portMAX_DELAY )
+ {
+ pxIterator = pxList->xListEnd.pxPrevious;
+ }
+ else
+ {
+ /* *** NOTE ***********************************************************
+ * If you find your application is crashing here then likely causes are
+ * listed below. In addition see https://www.FreeRTOS.org/FAQHelp.html for
+ * more tips, and ensure configASSERT() is defined!
+ * https://www.FreeRTOS.org/a00110.html#configASSERT
+ *
+ * 1) Stack overflow -
+ * see https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html
+ * 2) Incorrect interrupt priority assignment, especially on Cortex-M
+ * parts where numerically high priority values denote low actual
+ * interrupt priorities, which can seem counter intuitive. See
+ * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html and the definition
+ * of configMAX_SYSCALL_INTERRUPT_PRIORITY on
+ * https://www.FreeRTOS.org/a00110.html
+ * 3) Calling an API function from within a critical section or when
+ * the scheduler is suspended, or calling an API function that does
+ * not end in "FromISR" from an interrupt.
+ * 4) Using a queue or semaphore before it has been initialised or
+ * before the scheduler has been started (are interrupts firing
+ * before vTaskStartScheduler() has been called?).
+ * 5) If the FreeRTOS port supports interrupt nesting then ensure that
+ * the priority of the tick interrupt is at or below
+ * configMAX_SYSCALL_INTERRUPT_PRIORITY.
+ **********************************************************************/
+
+ for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */
+ {
+ /* There is nothing to do here, just iterating to the wanted
+ * insertion position. */
+ }
+ }
+
+ pxNewListItem->pxNext = pxIterator->pxNext;
+ pxNewListItem->pxNext->pxPrevious = pxNewListItem;
+ pxNewListItem->pxPrevious = pxIterator;
+ pxIterator->pxNext = pxNewListItem;
+
+ /* Remember which list the item is in. This allows fast removal of the
+ * item later. */
+ pxNewListItem->pxContainer = pxList;
+
+ ( pxList->uxNumberOfItems )++;
+}
+/*-----------------------------------------------------------*/
+
+UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
+{
+/* The list item knows which list it is in. Obtain the list from the list
+ * item. */
+ List_t * const pxList = pxItemToRemove->pxContainer;
+
+ pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
+ pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
+
+ /* Only used during decision coverage testing. */
+ mtCOVERAGE_TEST_DELAY();
+
+ /* Make sure the index is left pointing to a valid item. */
+ if( pxList->pxIndex == pxItemToRemove )
+ {
+ pxList->pxIndex = pxItemToRemove->pxPrevious;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ pxItemToRemove->pxContainer = NULL;
+ ( pxList->uxNumberOfItems )--;
+
+ return pxList->uxNumberOfItems;
+}
+/*-----------------------------------------------------------*/
diff --git a/source/test/freertos/src/port.c b/source/test/freertos/src/port.c
new file mode 100644
index 0000000..3a93cea
--- /dev/null
+++ b/source/test/freertos/src/port.c
@@ -0,0 +1,633 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/*-----------------------------------------------------------
+* Implementation of functions defined in portable.h for the ARM CM0 port.
+*----------------------------------------------------------*/
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* Constants required to manipulate the NVIC. */
+#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
+#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
+#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
+#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
+#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
+#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
+#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
+#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
+#define portNVIC_PEND_SYSTICK_SET_BIT ( 1UL << 26UL )
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
+#define portMIN_INTERRUPT_PRIORITY ( 255UL )
+#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
+#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
+
+/* Constants required to set up the initial stack. */
+#define portINITIAL_XPSR ( 0x01000000 )
+
+/* The systick is a 24-bit counter. */
+#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
+
+/* A fiddle factor to estimate the number of SysTick counts that would have
+ * occurred while the SysTick counter is stopped during tickless idle
+ * calculations. */
+#ifndef portMISSED_COUNTS_FACTOR
+ #define portMISSED_COUNTS_FACTOR ( 94UL )
+#endif
+
+/* Let the user override the default SysTick clock rate. If defined by the
+ * user, this symbol must equal the SysTick clock rate when the CLK bit is 0 in the
+ * configuration register. */
+#ifndef configSYSTICK_CLOCK_HZ
+ #define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ )
+ /* Ensure the SysTick is clocked at the same frequency as the core. */
+ #define portNVIC_SYSTICK_CLK_BIT_CONFIG ( portNVIC_SYSTICK_CLK_BIT )
+#else
+ /* Select the option to clock SysTick not at the same frequency as the core. */
+ #define portNVIC_SYSTICK_CLK_BIT_CONFIG ( 0 )
+#endif
+
+/* Let the user override the pre-loading of the initial LR with the address of
+ * prvTaskExitError() in case it messes up unwinding of the stack in the
+ * debugger. */
+#ifdef configTASK_RETURN_ADDRESS
+ #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
+#else
+ #define portTASK_RETURN_ADDRESS prvTaskExitError
+#endif
+
+/*
+ * Setup the timer to generate the tick interrupts. The implementation in this
+ * file is weak to allow application writers to change the timer used to
+ * generate the tick interrupt.
+ */
+void vPortSetupTimerInterrupt( void );
+
+/*
+ * Exception handlers.
+ */
+void xPortPendSVHandler( void ) __attribute__( ( naked ) );
+void xPortSysTickHandler( void );
+void vPortSVCHandler( void );
+
+/*
+ * Start first task is a separate function so it can be tested in isolation.
+ */
+static void vPortStartFirstTask( void ) __attribute__( ( naked ) );
+
+/*
+ * Used to catch tasks that attempt to return from their implementing function.
+ */
+static void prvTaskExitError( void );
+
+/*-----------------------------------------------------------*/
+
+/* Each task maintains its own interrupt status in the critical nesting
+ * variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The number of SysTick increments that make up one tick period.
+ */
+#if ( configUSE_TICKLESS_IDLE == 1 )
+ static uint32_t ulTimerCountsForOneTick = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The maximum number of tick periods that can be suppressed is limited by the
+ * 24 bit resolution of the SysTick timer.
+ */
+#if ( configUSE_TICKLESS_IDLE == 1 )
+ static uint32_t xMaximumPossibleSuppressedTicks = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Compensate for the CPU cycles that pass while the SysTick is stopped (low
+ * power functionality only.
+ */
+#if ( configUSE_TICKLESS_IDLE == 1 )
+ static uint32_t ulStoppedTimerCompensation = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
+ TaskFunction_t pxCode,
+ void * pvParameters )
+{
+ /* Simulate the stack frame as it would be created by a context switch
+ * interrupt. */
+ pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */
+ pxTopOfStack--;
+ *pxTopOfStack = ( StackType_t ) pxCode; /* PC */
+ pxTopOfStack--;
+ *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
+ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
+ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
+ pxTopOfStack -= 8; /* R11..R4. */
+
+ return pxTopOfStack;
+}
+/*-----------------------------------------------------------*/
+
+static void prvTaskExitError( void )
+{
+ volatile uint32_t ulDummy = 0UL;
+
+ /* A function that implements a task must not exit or attempt to return to
+ * its caller as there is nothing to return to. If a task wants to exit it
+ * should instead call vTaskDelete( NULL ).
+ *
+ * Artificially force an assert() to be triggered if configASSERT() is
+ * defined, then stop here so application writers can catch the error. */
+ configASSERT( uxCriticalNesting == ~0UL );
+ portDISABLE_INTERRUPTS();
+
+ while( ulDummy == 0 )
+ {
+ /* This file calls prvTaskExitError() after the scheduler has been
+ * started to remove a compiler warning about the function being defined
+ * but never called. ulDummy is used purely to quieten other warnings
+ * about code appearing after this function is called - making ulDummy
+ * volatile makes the compiler think the function could return and
+ * therefore not output an 'unreachable code' warning for code that appears
+ * after it. */
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vPortSVCHandler( void )
+{
+ /* This function is no longer used, but retained for backward
+ * compatibility. */
+}
+/*-----------------------------------------------------------*/
+
+void vPortStartFirstTask( void )
+{
+ /* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector
+ * table offset register that can be used to locate the initial stack value.
+ * Not all M0 parts have the application vector table at address 0. */
+ __asm volatile (
+ " .syntax unified \n"
+ " ldr r2, pxCurrentTCBConst2 \n"/* Obtain location of pxCurrentTCB. */
+ " ldr r3, [r2] \n"
+ " ldr r0, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */
+ " adds r0, #32 \n"/* Discard everything up to r0. */
+ " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
+ " movs r0, #2 \n"/* Switch to the psp stack. */
+ " msr CONTROL, r0 \n"
+ " isb \n"
+ " pop {r0-r5} \n"/* Pop the registers that are saved automatically. */
+ " mov lr, r5 \n"/* lr is now in r5. */
+ " pop {r3} \n"/* Return address is now in r3. */
+ " pop {r2} \n"/* Pop and discard XPSR. */
+ " cpsie i \n"/* The first task has its context and interrupts can be enabled. */
+ " bx r3 \n"/* Finally, jump to the user defined task code. */
+ " \n"
+ " .align 4 \n"
+ "pxCurrentTCBConst2: .word pxCurrentTCB "
+ );
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+BaseType_t xPortStartScheduler( void )
+{
+ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */
+ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+ portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+
+ /* Start the timer that generates the tick ISR. Interrupts are disabled
+ * here already. */
+ vPortSetupTimerInterrupt();
+
+ /* Initialise the critical nesting count ready for the first task. */
+ uxCriticalNesting = 0;
+
+ /* Start the first task. */
+ vPortStartFirstTask();
+
+ /* Should never get here as the tasks will now be executing! Call the task
+ * exit error function to prevent compiler warnings about a static function
+ * not being called in the case that the application writer overrides this
+ * functionality by defining configTASK_RETURN_ADDRESS. Call
+ * vTaskSwitchContext() so link time optimisation does not remove the
+ * symbol. */
+ vTaskSwitchContext();
+ prvTaskExitError();
+
+ /* Should not get here! */
+ return 0;
+}
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler( void )
+{
+ /* Not implemented in ports where there is nothing to return to.
+ * Artificially force an assert. */
+ configASSERT( uxCriticalNesting == 1000UL );
+}
+/*-----------------------------------------------------------*/
+
+void vPortYield( void )
+{
+ /* Set a PendSV to request a context switch. */
+ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+
+ /* Barriers are normally not required but do ensure the code is completely
+ * within the specified behaviour for the architecture. */
+ __asm volatile ( "dsb" ::: "memory" );
+ __asm volatile ( "isb" );
+}
+/*-----------------------------------------------------------*/
+
+void vPortEnterCritical( void )
+{
+ portDISABLE_INTERRUPTS();
+ uxCriticalNesting++;
+ __asm volatile ( "dsb" ::: "memory" );
+ __asm volatile ( "isb" );
+}
+/*-----------------------------------------------------------*/
+
+void vPortExitCritical( void )
+{
+ configASSERT( uxCriticalNesting );
+ uxCriticalNesting--;
+
+ if( uxCriticalNesting == 0 )
+ {
+ portENABLE_INTERRUPTS();
+ }
+}
+/*-----------------------------------------------------------*/
+
+uint32_t ulSetInterruptMaskFromISR( void )
+{
+ __asm volatile (
+ " mrs r0, PRIMASK \n"
+ " cpsid i \n"
+ " bx lr "
+ ::: "memory"
+ );
+}
+/*-----------------------------------------------------------*/
+
+void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask )
+{
+ __asm volatile (
+ " msr PRIMASK, r0 \n"
+ " bx lr "
+ ::: "memory"
+ );
+}
+/*-----------------------------------------------------------*/
+
+void xPortPendSVHandler( void )
+{
+ /* This is a naked function. */
+
+ __asm volatile
+ (
+ " .syntax unified \n"
+ " mrs r0, psp \n"
+ " \n"
+ " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */
+ " ldr r2, [r3] \n"
+ " \n"
+ " subs r0, r0, #32 \n"/* Make space for the remaining low registers. */
+ " str r0, [r2] \n"/* Save the new top of stack. */
+ " stmia r0!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
+ " mov r4, r8 \n"/* Store the high registers. */
+ " mov r5, r9 \n"
+ " mov r6, r10 \n"
+ " mov r7, r11 \n"
+ " stmia r0!, {r4-r7} \n"
+ " \n"
+ " push {r3, r14} \n"
+ " cpsid i \n"
+ " bl vTaskSwitchContext \n"
+ " cpsie i \n"
+ " pop {r2, r3} \n"/* lr goes in r3. r2 now holds tcb pointer. */
+ " \n"
+ " ldr r1, [r2] \n"
+ " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */
+ " adds r0, r0, #16 \n"/* Move to the high registers. */
+ " ldmia r0!, {r4-r7} \n"/* Pop the high registers. */
+ " mov r8, r4 \n"
+ " mov r9, r5 \n"
+ " mov r10, r6 \n"
+ " mov r11, r7 \n"
+ " \n"
+ " msr psp, r0 \n"/* Remember the new top of stack for the task. */
+ " \n"
+ " subs r0, r0, #32 \n"/* Go back for the low registers that are not automatically restored. */
+ " ldmia r0!, {r4-r7} \n"/* Pop low registers. */
+ " \n"
+ " bx r3 \n"
+ " \n"
+ " .align 4 \n"
+ "pxCurrentTCBConst: .word pxCurrentTCB "
+ );
+}
+/*-----------------------------------------------------------*/
+
+void xPortSysTickHandler( void )
+{
+ uint32_t ulPreviousMask;
+
+ ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ /* Increment the RTOS tick. */
+ if( xTaskIncrementTick() != pdFALSE )
+ {
+ /* Pend a context switch. */
+ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Setup the systick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
+{
+ /* Calculate the constants required to configure the tick interrupt. */
+ #if ( configUSE_TICKLESS_IDLE == 1 )
+ {
+ ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
+ xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
+ ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
+ }
+ #endif /* configUSE_TICKLESS_IDLE */
+
+ /* Stop and reset the SysTick. */
+ portNVIC_SYSTICK_CTRL_REG = 0UL;
+ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+
+ /* Configure SysTick to interrupt at the requested rate. */
+ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TICKLESS_IDLE == 1 )
+
+ __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
+ {
+ uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft;
+ TickType_t xModifiableIdleTime;
+
+ /* Make sure the SysTick reload value does not overflow the counter. */
+ if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
+ {
+ xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
+ }
+
+ /* Enter a critical section but don't use the taskENTER_CRITICAL()
+ * method as that will mask interrupts that should exit sleep mode. */
+ __asm volatile ( "cpsid i" ::: "memory" );
+ __asm volatile ( "dsb" );
+ __asm volatile ( "isb" );
+
+ /* If a context switch is pending or a task is waiting for the scheduler
+ * to be unsuspended then abandon the low power entry. */
+ if( eTaskConfirmSleepModeStatus() == eAbortSleep )
+ {
+ /* Re-enable interrupts - see comments above the cpsid instruction
+ * above. */
+ __asm volatile ( "cpsie i" ::: "memory" );
+ }
+ else
+ {
+ /* Stop the SysTick momentarily. The time the SysTick is stopped for
+ * is accounted for as best it can be, but using the tickless mode will
+ * inevitably result in some tiny drift of the time maintained by the
+ * kernel with respect to calendar time. */
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT );
+
+ /* Use the SysTick current-value register to determine the number of
+ * SysTick decrements remaining until the next tick interrupt. If the
+ * current-value register is zero, then there are actually
+ * ulTimerCountsForOneTick decrements remaining, not zero, because the
+ * SysTick requests the interrupt when decrementing from 1 to 0. */
+ ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+ if( ulSysTickDecrementsLeft == 0 )
+ {
+ ulSysTickDecrementsLeft = ulTimerCountsForOneTick;
+ }
+
+ /* Calculate the reload value required to wait xExpectedIdleTime
+ * tick periods. -1 is used because this code normally executes part
+ * way through the first tick period. But if the SysTick IRQ is now
+ * pending, then clear the IRQ, suppressing the first tick, and correct
+ * the reload value to reflect that the second tick period is already
+ * underway. The expected idle time is always at least two ticks. */
+ ulReloadValue = ulSysTickDecrementsLeft + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
+
+ if( ( portNVIC_INT_CTRL_REG & portNVIC_PEND_SYSTICK_SET_BIT ) != 0 )
+ {
+ portNVIC_INT_CTRL_REG = portNVIC_PEND_SYSTICK_CLEAR_BIT;
+ ulReloadValue -= ulTimerCountsForOneTick;
+ }
+
+ if( ulReloadValue > ulStoppedTimerCompensation )
+ {
+ ulReloadValue -= ulStoppedTimerCompensation;
+ }
+
+ /* Set the new reload value. */
+ portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
+
+ /* Clear the SysTick count flag and set the count value back to
+ * zero. */
+ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+
+ /* Restart SysTick. */
+ portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+ /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
+ * set its parameter to 0 to indicate that its implementation contains
+ * its own wait for interrupt or wait for event instruction, and so wfi
+ * should not be executed again. However, the original expected idle
+ * time variable must remain unmodified, so a copy is taken. */
+ xModifiableIdleTime = xExpectedIdleTime;
+ configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
+
+ if( xModifiableIdleTime > 0 )
+ {
+ __asm volatile ( "dsb" ::: "memory" );
+ __asm volatile ( "wfi" );
+ __asm volatile ( "isb" );
+ }
+
+ configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
+
+ /* Re-enable interrupts to allow the interrupt that brought the MCU
+ * out of sleep mode to execute immediately. See comments above
+ * the cpsid instruction above. */
+ __asm volatile ( "cpsie i" ::: "memory" );
+ __asm volatile ( "dsb" );
+ __asm volatile ( "isb" );
+
+ /* Disable interrupts again because the clock is about to be stopped
+ * and interrupts that execute while the clock is stopped will increase
+ * any slippage between the time maintained by the RTOS and calendar
+ * time. */
+ __asm volatile ( "cpsid i" ::: "memory" );
+ __asm volatile ( "dsb" );
+ __asm volatile ( "isb" );
+
+ /* Disable the SysTick clock without reading the
+ * portNVIC_SYSTICK_CTRL_REG register to ensure the
+ * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
+ * the time the SysTick is stopped for is accounted for as best it can
+ * be, but using the tickless mode will inevitably result in some tiny
+ * drift of the time maintained by the kernel with respect to calendar
+ * time*/
+ portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT );
+
+ /* Determine whether the SysTick has already counted to zero. */
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ {
+ uint32_t ulCalculatedLoadValue;
+
+ /* The tick interrupt ended the sleep (or is now pending), and
+ * a new tick period has started. Reset portNVIC_SYSTICK_LOAD_REG
+ * with whatever remains of the new tick period. */
+ ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
+
+ /* Don't allow a tiny value, or values that have somehow
+ * underflowed because the post sleep hook did something
+ * that took too long or because the SysTick current-value register
+ * is zero. */
+ if( ( ulCalculatedLoadValue <= ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
+ {
+ ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
+ }
+
+ portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
+
+ /* As the pending tick will be processed as soon as this
+ * function exits, the tick value maintained by the tick is stepped
+ * forward by one less than the time spent waiting. */
+ ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
+ }
+ else
+ {
+ /* Something other than the tick interrupt ended the sleep. */
+
+ /* Use the SysTick current-value register to determine the
+ * number of SysTick decrements remaining until the expected idle
+ * time would have ended. */
+ ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG;
+ #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG != portNVIC_SYSTICK_CLK_BIT )
+ {
+ /* If the SysTick is not using the core clock, the current-
+ * value register might still be zero here. In that case, the
+ * SysTick didn't load from the reload register, and there are
+ * ulReloadValue decrements remaining in the expected idle
+ * time, not zero. */
+ if( ulSysTickDecrementsLeft == 0 )
+ {
+ ulSysTickDecrementsLeft = ulReloadValue;
+ }
+ }
+ #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */
+
+ /* Work out how long the sleep lasted rounded to complete tick
+ * periods (not the ulReload value which accounted for part
+ * ticks). */
+ ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - ulSysTickDecrementsLeft;
+
+ /* How many complete tick periods passed while the processor
+ * was waiting? */
+ ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
+
+ /* The reload value is set to whatever fraction of a single tick
+ * period remains. */
+ portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
+ }
+
+ /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again,
+ * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If
+ * the SysTick is not using the core clock, temporarily configure it to
+ * use the core clock. This configuration forces the SysTick to load
+ * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next
+ * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready
+ * to receive the standard value immediately. */
+ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+ portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
+ #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT )
+ {
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+ }
+ #else
+ {
+ /* The temporary usage of the core clock has served its purpose,
+ * as described above. Resume usage of the other clock. */
+ portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
+
+ if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+ {
+ /* The partial tick period already ended. Be sure the SysTick
+ * counts it only once. */
+ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0;
+ }
+
+ portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+ portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
+ }
+ #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */
+
+ /* Step the tick to account for any tick periods that elapsed. */
+ vTaskStepTick( ulCompleteTickPeriods );
+
+ /* Exit with interrupts enabled. */
+ __asm volatile ( "cpsie i" ::: "memory" );
+ }
+ }
+
+#endif /* configUSE_TICKLESS_IDLE */
diff --git a/source/test/freertos/src/queue.c b/source/test/freertos/src/queue.c
new file mode 100644
index 0000000..e76e7ff
--- /dev/null
+++ b/source/test/freertos/src/queue.c
@@ -0,0 +1,3087 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#include
+#include
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+ * all the API functions to use the MPU wrappers. That should only be done when
+ * task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+#if ( configUSE_CO_ROUTINES == 1 )
+ #include "croutine.h"
+#endif
+
+/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
+ * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
+ * for the header files above, but not in this file, in order to generate the
+ * correct privileged Vs unprivileged linkage and placement. */
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
+
+
+/* Constants used with the cRxLock and cTxLock structure members. */
+#define queueUNLOCKED ( ( int8_t ) -1 )
+#define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 )
+#define queueINT8_MAX ( ( int8_t ) 127 )
+
+/* When the Queue_t structure is used to represent a base queue its pcHead and
+ * pcTail members are used as pointers into the queue storage area. When the
+ * Queue_t structure is used to represent a mutex pcHead and pcTail pointers are
+ * not necessary, and the pcHead pointer is set to NULL to indicate that the
+ * structure instead holds a pointer to the mutex holder (if any). Map alternative
+ * names to the pcHead and structure member to ensure the readability of the code
+ * is maintained. The QueuePointers_t and SemaphoreData_t types are used to form
+ * a union as their usage is mutually exclusive dependent on what the queue is
+ * being used for. */
+#define uxQueueType pcHead
+#define queueQUEUE_IS_MUTEX NULL
+
+typedef struct QueuePointers
+{
+ int8_t * pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
+ int8_t * pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */
+} QueuePointers_t;
+
+typedef struct SemaphoreData
+{
+ TaskHandle_t xMutexHolder; /*< The handle of the task that holds the mutex. */
+ UBaseType_t uxRecursiveCallCount; /*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */
+} SemaphoreData_t;
+
+/* Semaphores do not actually store or copy data, so have an item size of
+ * zero. */
+#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 )
+#define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U )
+
+#if ( configUSE_PREEMPTION == 0 )
+
+/* If the cooperative scheduler is being used then a yield should not be
+ * performed just because a higher priority task has been woken. */
+ #define queueYIELD_IF_USING_PREEMPTION()
+#else
+ #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
+#endif
+
+/*
+ * Definition of the queue used by the scheduler.
+ * Items are queued by copy, not reference. See the following link for the
+ * rationale: https://www.FreeRTOS.org/Embedded-RTOS-Queues.html
+ */
+typedef struct QueueDefinition /* The old naming convention is used to prevent breaking kernel aware debuggers. */
+{
+ int8_t * pcHead; /*< Points to the beginning of the queue storage area. */
+ int8_t * pcWriteTo; /*< Points to the free next place in the storage area. */
+
+ union
+ {
+ QueuePointers_t xQueue; /*< Data required exclusively when this structure is used as a queue. */
+ SemaphoreData_t xSemaphore; /*< Data required exclusively when this structure is used as a semaphore. */
+ } u;
+
+ List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
+ List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
+
+ volatile UBaseType_t uxMessagesWaiting; /*< The number of items currently in the queue. */
+ UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
+ UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */
+
+ volatile int8_t cRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
+ volatile int8_t cTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */
+
+ #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
+ #endif
+
+ #if ( configUSE_QUEUE_SETS == 1 )
+ struct QueueDefinition * pxQueueSetContainer;
+ #endif
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxQueueNumber;
+ uint8_t ucQueueType;
+ #endif
+} xQUEUE;
+
+/* The old xQUEUE name is maintained above then typedefed to the new Queue_t
+ * name below to enable the use of older kernel aware debuggers. */
+typedef xQUEUE Queue_t;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The queue registry is just a means for kernel aware debuggers to locate
+ * queue structures. It has no other purpose so is an optional component.
+ */
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+
+/* The type stored within the queue registry array. This allows a name
+ * to be assigned to each queue making kernel aware debugging a little
+ * more user friendly. */
+ typedef struct QUEUE_REGISTRY_ITEM
+ {
+ const char * pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ QueueHandle_t xHandle;
+ } xQueueRegistryItem;
+
+/* The old xQueueRegistryItem name is maintained above then typedefed to the
+ * new xQueueRegistryItem name below to enable the use of older kernel aware
+ * debuggers. */
+ typedef xQueueRegistryItem QueueRegistryItem_t;
+
+/* The queue registry is simply an array of QueueRegistryItem_t structures.
+ * The pcQueueName member of a structure being NULL is indicative of the
+ * array position being vacant. */
+ PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
+
+#endif /* configQUEUE_REGISTRY_SIZE */
+
+/*
+ * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
+ * prevent an ISR from adding or removing items to the queue, but does prevent
+ * an ISR from removing tasks from the queue event lists. If an ISR finds a
+ * queue is locked it will instead increment the appropriate queue lock count
+ * to indicate that a task may require unblocking. When the queue in unlocked
+ * these lock counts are inspected, and the appropriate action taken.
+ */
+static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * Uses a critical section to determine if there is any data in a queue.
+ *
+ * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
+ */
+static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * Uses a critical section to determine if there is any space in a queue.
+ *
+ * @return pdTRUE if there is no space, otherwise pdFALSE;
+ */
+static BaseType_t prvIsQueueFull( const Queue_t * pxQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * Copies an item into the queue, either at the front of the queue or the
+ * back of the queue.
+ */
+static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
+ const void * pvItemToQueue,
+ const BaseType_t xPosition ) PRIVILEGED_FUNCTION;
+
+/*
+ * Copies an item out of a queue.
+ */
+static void prvCopyDataFromQueue( Queue_t * const pxQueue,
+ void * const pvBuffer ) PRIVILEGED_FUNCTION;
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+/*
+ * Checks to see if a queue is a member of a queue set, and if so, notifies
+ * the queue set that the queue contains data.
+ */
+ static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * Called after a Queue_t structure has been allocated either statically or
+ * dynamically to fill in the structure's members.
+ */
+static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
+ const UBaseType_t uxItemSize,
+ uint8_t * pucQueueStorage,
+ const uint8_t ucQueueType,
+ Queue_t * pxNewQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * Mutexes are a special type of queue. When a mutex is created, first the
+ * queue is created, then prvInitialiseMutex() is called to configure the queue
+ * as a mutex.
+ */
+#if ( configUSE_MUTEXES == 1 )
+ static void prvInitialiseMutex( Queue_t * pxNewQueue ) PRIVILEGED_FUNCTION;
+#endif
+
+#if ( configUSE_MUTEXES == 1 )
+
+/*
+ * If a task waiting for a mutex causes the mutex holder to inherit a
+ * priority, but the waiting task times out, then the holder should
+ * disinherit the priority - but only down to the highest priority of any
+ * other tasks that are waiting for the same mutex. This function returns
+ * that priority.
+ */
+ static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
+#endif
+/*-----------------------------------------------------------*/
+
+/*
+ * Macro to mark a queue as locked. Locking a queue prevents an ISR from
+ * accessing the queue event lists.
+ */
+#define prvLockQueue( pxQueue ) \
+ taskENTER_CRITICAL(); \
+ { \
+ if( ( pxQueue )->cRxLock == queueUNLOCKED ) \
+ { \
+ ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \
+ } \
+ if( ( pxQueue )->cTxLock == queueUNLOCKED ) \
+ { \
+ ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \
+ } \
+ } \
+ taskEXIT_CRITICAL()
+
+/*
+ * Macro to increment cTxLock member of the queue data structure. It is
+ * capped at the number of tasks in the system as we cannot unblock more
+ * tasks than the number of tasks in the system.
+ */
+#define prvIncrementQueueTxLock( pxQueue, cTxLock ) \
+ { \
+ const UBaseType_t uxNumberOfTasks = uxTaskGetNumberOfTasks(); \
+ if( ( UBaseType_t ) ( cTxLock ) < uxNumberOfTasks ) \
+ { \
+ configASSERT( ( cTxLock ) != queueINT8_MAX ); \
+ ( pxQueue )->cTxLock = ( int8_t ) ( ( cTxLock ) + ( int8_t ) 1 ); \
+ } \
+ }
+
+/*
+ * Macro to increment cRxLock member of the queue data structure. It is
+ * capped at the number of tasks in the system as we cannot unblock more
+ * tasks than the number of tasks in the system.
+ */
+#define prvIncrementQueueRxLock( pxQueue, cRxLock ) \
+ { \
+ const UBaseType_t uxNumberOfTasks = uxTaskGetNumberOfTasks(); \
+ if( ( UBaseType_t ) ( cRxLock ) < uxNumberOfTasks ) \
+ { \
+ configASSERT( ( cRxLock ) != queueINT8_MAX ); \
+ ( pxQueue )->cRxLock = ( int8_t ) ( ( cRxLock ) + ( int8_t ) 1 ); \
+ } \
+ }
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
+ BaseType_t xNewQueue )
+{
+ BaseType_t xReturn = pdPASS;
+ Queue_t * const pxQueue = xQueue;
+
+ configASSERT( pxQueue );
+
+ if( ( pxQueue != NULL ) &&
+ ( pxQueue->uxLength >= 1U ) &&
+ /* Check for multiplication overflow. */
+ ( ( SIZE_MAX / pxQueue->uxLength ) >= pxQueue->uxItemSize ) )
+ {
+ taskENTER_CRITICAL();
+ {
+ pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */
+ pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;
+ pxQueue->pcWriteTo = pxQueue->pcHead;
+ pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - 1U ) * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */
+ pxQueue->cRxLock = queueUNLOCKED;
+ pxQueue->cTxLock = queueUNLOCKED;
+
+ if( xNewQueue == pdFALSE )
+ {
+ /* If there are tasks blocked waiting to read from the queue, then
+ * the tasks will remain blocked as after this function exits the queue
+ * will still be empty. If there are tasks blocked waiting to write to
+ * the queue, then one should be unblocked as after this function exits
+ * it will be possible to write to it. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ queueYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* Ensure the event queues start in the correct state. */
+ vListInitialise( &( pxQueue->xTasksWaitingToSend ) );
+ vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );
+ }
+ }
+ taskEXIT_CRITICAL();
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+
+ configASSERT( xReturn != pdFAIL );
+
+ /* A value is returned for calling semantic consistency with previous
+ * versions. */
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+ QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
+ const UBaseType_t uxItemSize,
+ uint8_t * pucQueueStorage,
+ StaticQueue_t * pxStaticQueue,
+ const uint8_t ucQueueType )
+ {
+ Queue_t * pxNewQueue = NULL;
+
+ /* The StaticQueue_t structure and the queue storage area must be
+ * supplied. */
+ configASSERT( pxStaticQueue );
+
+ if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&
+ ( pxStaticQueue != NULL ) &&
+
+ /* A queue storage area should be provided if the item size is not 0, and
+ * should not be provided if the item size is 0. */
+ ( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ) &&
+ ( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ) )
+ {
+ #if ( configASSERT_DEFINED == 1 )
+ {
+ /* Sanity check that the size of the structure used to declare a
+ * variable of type StaticQueue_t or StaticSemaphore_t equals the size of
+ * the real queue and semaphore structures. */
+ volatile size_t xSize = sizeof( StaticQueue_t );
+
+ /* This assertion cannot be branch covered in unit tests */
+ configASSERT( xSize == sizeof( Queue_t ) ); /* LCOV_EXCL_BR_LINE */
+ ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */
+ }
+ #endif /* configASSERT_DEFINED */
+
+ /* The address of a statically allocated queue was passed in, use it.
+ * The address of a statically allocated storage area was also passed in
+ * but is already set. */
+ pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
+
+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ {
+ /* Queues can be allocated wither statically or dynamically, so
+ * note this queue was allocated statically in case the queue is
+ * later deleted. */
+ pxNewQueue->ucStaticallyAllocated = pdTRUE;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+ prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
+ }
+ else
+ {
+ configASSERT( pxNewQueue );
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return pxNewQueue;
+ }
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+
+ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
+ const UBaseType_t uxItemSize,
+ const uint8_t ucQueueType )
+ {
+ Queue_t * pxNewQueue = NULL;
+ size_t xQueueSizeInBytes;
+ uint8_t * pucQueueStorage;
+
+ if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&
+ /* Check for multiplication overflow. */
+ ( ( SIZE_MAX / uxQueueLength ) >= uxItemSize ) &&
+ /* Check for addition overflow. */
+ ( ( SIZE_MAX - sizeof( Queue_t ) ) >= ( uxQueueLength * uxItemSize ) ) )
+ {
+ /* Allocate enough space to hold the maximum number of items that
+ * can be in the queue at any time. It is valid for uxItemSize to be
+ * zero in the case the queue is used as a semaphore. */
+ xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ /* Allocate the queue and storage area. Justification for MISRA
+ * deviation as follows: pvPortMalloc() always ensures returned memory
+ * blocks are aligned per the requirements of the MCU stack. In this case
+ * pvPortMalloc() must return a pointer that is guaranteed to meet the
+ * alignment requirements of the Queue_t structure - which in this case
+ * is an int8_t *. Therefore, whenever the stack alignment requirements
+ * are greater than or equal to the pointer to char requirements the cast
+ * is safe. In other cases alignment requirements are not strict (one or
+ * two bytes). */
+ pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */
+
+ if( pxNewQueue != NULL )
+ {
+ /* Jump past the queue structure to find the location of the queue
+ * storage area. */
+ pucQueueStorage = ( uint8_t * ) pxNewQueue;
+ pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */
+
+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ /* Queues can be created either statically or dynamically, so
+ * note this task was created dynamically in case it is later
+ * deleted. */
+ pxNewQueue->ucStaticallyAllocated = pdFALSE;
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
+
+ prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
+ }
+ else
+ {
+ traceQUEUE_CREATE_FAILED( ucQueueType );
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ configASSERT( pxNewQueue );
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return pxNewQueue;
+ }
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
+ const UBaseType_t uxItemSize,
+ uint8_t * pucQueueStorage,
+ const uint8_t ucQueueType,
+ Queue_t * pxNewQueue )
+{
+ /* Remove compiler warnings about unused parameters should
+ * configUSE_TRACE_FACILITY not be set to 1. */
+ ( void ) ucQueueType;
+
+ if( uxItemSize == ( UBaseType_t ) 0 )
+ {
+ /* No RAM was allocated for the queue storage area, but PC head cannot
+ * be set to NULL because NULL is used as a key to say the queue is used as
+ * a mutex. Therefore just set pcHead to point to the queue as a benign
+ * value that is known to be within the memory map. */
+ pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
+ }
+ else
+ {
+ /* Set the head to the start of the queue storage area. */
+ pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;
+ }
+
+ /* Initialise the queue members as described where the queue type is
+ * defined. */
+ pxNewQueue->uxLength = uxQueueLength;
+ pxNewQueue->uxItemSize = uxItemSize;
+ ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ pxNewQueue->ucQueueType = ucQueueType;
+ }
+ #endif /* configUSE_TRACE_FACILITY */
+
+ #if ( configUSE_QUEUE_SETS == 1 )
+ {
+ pxNewQueue->pxQueueSetContainer = NULL;
+ }
+ #endif /* configUSE_QUEUE_SETS */
+
+ traceQUEUE_CREATE( pxNewQueue );
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+ static void prvInitialiseMutex( Queue_t * pxNewQueue )
+ {
+ if( pxNewQueue != NULL )
+ {
+ /* The queue create function will set all the queue structure members
+ * correctly for a generic queue, but this function is creating a
+ * mutex. Overwrite those members that need to be set differently -
+ * in particular the information required for priority inheritance. */
+ pxNewQueue->u.xSemaphore.xMutexHolder = NULL;
+ pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
+
+ /* In case this is a recursive mutex. */
+ pxNewQueue->u.xSemaphore.uxRecursiveCallCount = 0;
+
+ traceCREATE_MUTEX( pxNewQueue );
+
+ /* Start with the semaphore in the expected state. */
+ ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );
+ }
+ else
+ {
+ traceCREATE_MUTEX_FAILED();
+ }
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+
+ QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
+ {
+ QueueHandle_t xNewQueue;
+ const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
+
+ xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
+ prvInitialiseMutex( ( Queue_t * ) xNewQueue );
+
+ return xNewQueue;
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+ QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType,
+ StaticQueue_t * pxStaticQueue )
+ {
+ QueueHandle_t xNewQueue;
+ const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
+
+ /* Prevent compiler warnings about unused parameters if
+ * configUSE_TRACE_FACILITY does not equal 1. */
+ ( void ) ucQueueType;
+
+ xNewQueue = xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType );
+ prvInitialiseMutex( ( Queue_t * ) xNewQueue );
+
+ return xNewQueue;
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
+
+ TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore )
+ {
+ TaskHandle_t pxReturn;
+ Queue_t * const pxSemaphore = ( Queue_t * ) xSemaphore;
+
+ configASSERT( xSemaphore );
+
+ /* This function is called by xSemaphoreGetMutexHolder(), and should not
+ * be called directly. Note: This is a good way of determining if the
+ * calling task is the mutex holder, but not a good way of determining the
+ * identity of the mutex holder, as the holder may change between the
+ * following critical section exiting and the function returning. */
+ taskENTER_CRITICAL();
+ {
+ if( pxSemaphore->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ pxReturn = pxSemaphore->u.xSemaphore.xMutexHolder;
+ }
+ else
+ {
+ pxReturn = NULL;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return pxReturn;
+ } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */
+
+#endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
+
+ TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore )
+ {
+ TaskHandle_t pxReturn;
+
+ configASSERT( xSemaphore );
+
+ /* Mutexes cannot be used in interrupt service routines, so the mutex
+ * holder should not change in an ISR, and therefore a critical section is
+ * not required here. */
+ if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ pxReturn = ( ( Queue_t * ) xSemaphore )->u.xSemaphore.xMutexHolder;
+ }
+ else
+ {
+ pxReturn = NULL;
+ }
+
+ return pxReturn;
+ } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */
+
+#endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_RECURSIVE_MUTEXES == 1 )
+
+ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
+ {
+ BaseType_t xReturn;
+ Queue_t * const pxMutex = ( Queue_t * ) xMutex;
+
+ configASSERT( pxMutex );
+
+ /* If this is the task that holds the mutex then xMutexHolder will not
+ * change outside of this task. If this task does not hold the mutex then
+ * pxMutexHolder can never coincidentally equal the tasks handle, and as
+ * this is the only condition we are interested in it does not matter if
+ * pxMutexHolder is accessed simultaneously by another task. Therefore no
+ * mutual exclusion is required to test the pxMutexHolder variable. */
+ if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() )
+ {
+ traceGIVE_MUTEX_RECURSIVE( pxMutex );
+
+ /* uxRecursiveCallCount cannot be zero if xMutexHolder is equal to
+ * the task handle, therefore no underflow check is required. Also,
+ * uxRecursiveCallCount is only modified by the mutex holder, and as
+ * there can only be one, no mutual exclusion is required to modify the
+ * uxRecursiveCallCount member. */
+ ( pxMutex->u.xSemaphore.uxRecursiveCallCount )--;
+
+ /* Has the recursive call count unwound to 0? */
+ if( pxMutex->u.xSemaphore.uxRecursiveCallCount == ( UBaseType_t ) 0 )
+ {
+ /* Return the mutex. This will automatically unblock any other
+ * task that might be waiting to access the mutex. */
+ ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ /* The mutex cannot be given because the calling task is not the
+ * holder. */
+ xReturn = pdFAIL;
+
+ traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_RECURSIVE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_RECURSIVE_MUTEXES == 1 )
+
+ BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex,
+ TickType_t xTicksToWait )
+ {
+ BaseType_t xReturn;
+ Queue_t * const pxMutex = ( Queue_t * ) xMutex;
+
+ configASSERT( pxMutex );
+
+ /* Comments regarding mutual exclusion as per those within
+ * xQueueGiveMutexRecursive(). */
+
+ traceTAKE_MUTEX_RECURSIVE( pxMutex );
+
+ if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() )
+ {
+ ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait );
+
+ /* pdPASS will only be returned if the mutex was successfully
+ * obtained. The calling task may have entered the Blocked state
+ * before reaching here. */
+ if( xReturn != pdFAIL )
+ {
+ ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
+ }
+ else
+ {
+ traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
+ }
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_RECURSIVE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+ QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
+ const UBaseType_t uxInitialCount,
+ StaticQueue_t * pxStaticQueue )
+ {
+ QueueHandle_t xHandle = NULL;
+
+ if( ( uxMaxCount != 0 ) &&
+ ( uxInitialCount <= uxMaxCount ) )
+ {
+ xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
+
+ if( xHandle != NULL )
+ {
+ ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
+
+ traceCREATE_COUNTING_SEMAPHORE();
+ }
+ else
+ {
+ traceCREATE_COUNTING_SEMAPHORE_FAILED();
+ }
+ }
+ else
+ {
+ configASSERT( xHandle );
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xHandle;
+ }
+
+#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+
+ QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
+ const UBaseType_t uxInitialCount )
+ {
+ QueueHandle_t xHandle = NULL;
+
+ if( ( uxMaxCount != 0 ) &&
+ ( uxInitialCount <= uxMaxCount ) )
+ {
+ xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
+
+ if( xHandle != NULL )
+ {
+ ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
+
+ traceCREATE_COUNTING_SEMAPHORE();
+ }
+ else
+ {
+ traceCREATE_COUNTING_SEMAPHORE_FAILED();
+ }
+ }
+ else
+ {
+ configASSERT( xHandle );
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xHandle;
+ }
+
+#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
+ const void * const pvItemToQueue,
+ TickType_t xTicksToWait,
+ const BaseType_t xCopyPosition )
+{
+ BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired;
+ TimeOut_t xTimeOut;
+ Queue_t * const pxQueue = xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
+ configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
+ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+ {
+ configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+ }
+ #endif
+
+ /*lint -save -e904 This function relaxes the coding standard somewhat to
+ * allow return statements within the function itself. This is done in the
+ * interest of execution time efficiency. */
+ for( ; ; )
+ {
+ taskENTER_CRITICAL();
+ {
+ /* Is there room on the queue now? The running task must be the
+ * highest priority task wanting to access the queue. If the head item
+ * in the queue is to be overwritten then it does not matter if the
+ * queue is full. */
+ if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
+ {
+ traceQUEUE_SEND( pxQueue );
+
+ #if ( configUSE_QUEUE_SETS == 1 )
+ {
+ const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
+
+ xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
+
+ if( pxQueue->pxQueueSetContainer != NULL )
+ {
+ if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) )
+ {
+ /* Do not notify the queue set as an existing item
+ * was overwritten in the queue so the number of items
+ * in the queue has not changed. */
+ mtCOVERAGE_TEST_MARKER();
+ }
+ else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
+ {
+ /* The queue is a member of a queue set, and posting
+ * to the queue set caused a higher priority task to
+ * unblock. A context switch is required. */
+ queueYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* If there was a task waiting for data to arrive on the
+ * queue then unblock it now. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The unblocked task has a priority higher than
+ * our own so yield immediately. Yes it is ok to
+ * do this from within the critical section - the
+ * kernel takes care of that. */
+ queueYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else if( xYieldRequired != pdFALSE )
+ {
+ /* This path is a special case that will only get
+ * executed if the task was holding multiple mutexes
+ * and the mutexes were given back in an order that is
+ * different to that in which they were taken. */
+ queueYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ #else /* configUSE_QUEUE_SETS */
+ {
+ xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
+
+ /* If there was a task waiting for data to arrive on the
+ * queue then unblock it now. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The unblocked task has a priority higher than
+ * our own so yield immediately. Yes it is ok to do
+ * this from within the critical section - the kernel
+ * takes care of that. */
+ queueYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else if( xYieldRequired != pdFALSE )
+ {
+ /* This path is a special case that will only get
+ * executed if the task was holding multiple mutexes and
+ * the mutexes were given back in an order that is
+ * different to that in which they were taken. */
+ queueYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_QUEUE_SETS */
+
+ taskEXIT_CRITICAL();
+ return pdPASS;
+ }
+ else
+ {
+ if( xTicksToWait == ( TickType_t ) 0 )
+ {
+ /* The queue was full and no block time is specified (or
+ * the block time has expired) so leave now. */
+ taskEXIT_CRITICAL();
+
+ /* Return to the original privilege level before exiting
+ * the function. */
+ traceQUEUE_SEND_FAILED( pxQueue );
+ return errQUEUE_FULL;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ /* The queue was full and a block time was specified so
+ * configure the timeout structure. */
+ vTaskInternalSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
+ else
+ {
+ /* Entry time was already set. */
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ /* Interrupts and other tasks can send to and receive from the queue
+ * now the critical section has been exited. */
+
+ vTaskSuspendAll();
+ prvLockQueue( pxQueue );
+
+ /* Update the timeout state to see if it has expired yet. */
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+ {
+ if( prvIsQueueFull( pxQueue ) != pdFALSE )
+ {
+ traceBLOCKING_ON_QUEUE_SEND( pxQueue );
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
+
+ /* Unlocking the queue means queue events can effect the
+ * event list. It is possible that interrupts occurring now
+ * remove this task from the event list again - but as the
+ * scheduler is suspended the task will go onto the pending
+ * ready list instead of the actual ready list. */
+ prvUnlockQueue( pxQueue );
+
+ /* Resuming the scheduler will move tasks from the pending
+ * ready list into the ready list - so it is feasible that this
+ * task is already in the ready list before it yields - in which
+ * case the yield will not cause a context switch unless there
+ * is also a higher priority task in the pending ready list. */
+ if( xTaskResumeAll() == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ }
+ else
+ {
+ /* Try again. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ }
+ }
+ else
+ {
+ /* The timeout has expired. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+
+ traceQUEUE_SEND_FAILED( pxQueue );
+ return errQUEUE_FULL;
+ }
+ } /*lint -restore */
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
+ const void * const pvItemToQueue,
+ BaseType_t * const pxHigherPriorityTaskWoken,
+ const BaseType_t xCopyPosition )
+{
+ BaseType_t xReturn;
+ UBaseType_t uxSavedInterruptStatus;
+ Queue_t * const pxQueue = xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
+ configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
+
+ /* RTOS ports that support interrupt nesting have the concept of a maximum
+ * system call (or maximum API call) interrupt priority. Interrupts that are
+ * above the maximum system call priority are kept permanently enabled, even
+ * when the RTOS kernel is in a critical section, but cannot make any calls to
+ * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
+ * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ * failure if a FreeRTOS API function is called from an interrupt that has been
+ * assigned a priority above the configured maximum system call priority.
+ * Only FreeRTOS functions that end in FromISR can be called from interrupts
+ * that have been assigned a priority at or (logically) below the maximum
+ * system call interrupt priority. FreeRTOS maintains a separate interrupt
+ * safe API to ensure interrupt entry is as fast and as simple as possible.
+ * More information (albeit Cortex-M specific) is provided on the following
+ * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ /* Similar to xQueueGenericSend, except without blocking if there is no room
+ * in the queue. Also don't directly wake a task that was blocked on a queue
+ * read, instead return a flag to say whether a context switch is required or
+ * not (i.e. has a task with a higher priority than us been woken by this
+ * post). */
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
+ {
+ const int8_t cTxLock = pxQueue->cTxLock;
+ const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
+
+ traceQUEUE_SEND_FROM_ISR( pxQueue );
+
+ /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a
+ * semaphore or mutex. That means prvCopyDataToQueue() cannot result
+ * in a task disinheriting a priority and prvCopyDataToQueue() can be
+ * called here even though the disinherit function does not check if
+ * the scheduler is suspended before accessing the ready lists. */
+ ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
+
+ /* The event list is not altered if the queue is locked. This will
+ * be done when the queue is unlocked later. */
+ if( cTxLock == queueUNLOCKED )
+ {
+ #if ( configUSE_QUEUE_SETS == 1 )
+ {
+ if( pxQueue->pxQueueSetContainer != NULL )
+ {
+ if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) )
+ {
+ /* Do not notify the queue set as an existing item
+ * was overwritten in the queue so the number of items
+ * in the queue has not changed. */
+ mtCOVERAGE_TEST_MARKER();
+ }
+ else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
+ {
+ /* The queue is a member of a queue set, and posting
+ * to the queue set caused a higher priority task to
+ * unblock. A context switch is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority so
+ * record that a context switch is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ #else /* configUSE_QUEUE_SETS */
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority so record that a
+ * context switch is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Not used in this path. */
+ ( void ) uxPreviousMessagesWaiting;
+ }
+ #endif /* configUSE_QUEUE_SETS */
+ }
+ else
+ {
+ /* Increment the lock count so the task that unlocks the queue
+ * knows that data was posted while it was locked. */
+ prvIncrementQueueTxLock( pxQueue, cTxLock );
+ }
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
+ xReturn = errQUEUE_FULL;
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
+ BaseType_t * const pxHigherPriorityTaskWoken )
+{
+ BaseType_t xReturn;
+ UBaseType_t uxSavedInterruptStatus;
+ Queue_t * const pxQueue = xQueue;
+
+ /* Similar to xQueueGenericSendFromISR() but used with semaphores where the
+ * item size is 0. Don't directly wake a task that was blocked on a queue
+ * read, instead return a flag to say whether a context switch is required or
+ * not (i.e. has a task with a higher priority than us been woken by this
+ * post). */
+
+ configASSERT( pxQueue );
+
+ /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR()
+ * if the item size is not 0. */
+ configASSERT( pxQueue->uxItemSize == 0 );
+
+ /* Normally a mutex would not be given from an interrupt, especially if
+ * there is a mutex holder, as priority inheritance makes no sense for an
+ * interrupts, only tasks. */
+ configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) );
+
+ /* RTOS ports that support interrupt nesting have the concept of a maximum
+ * system call (or maximum API call) interrupt priority. Interrupts that are
+ * above the maximum system call priority are kept permanently enabled, even
+ * when the RTOS kernel is in a critical section, but cannot make any calls to
+ * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
+ * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ * failure if a FreeRTOS API function is called from an interrupt that has been
+ * assigned a priority above the configured maximum system call priority.
+ * Only FreeRTOS functions that end in FromISR can be called from interrupts
+ * that have been assigned a priority at or (logically) below the maximum
+ * system call interrupt priority. FreeRTOS maintains a separate interrupt
+ * safe API to ensure interrupt entry is as fast and as simple as possible.
+ * More information (albeit Cortex-M specific) is provided on the following
+ * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
+
+ /* When the queue is used to implement a semaphore no data is ever
+ * moved through the queue but it is still valid to see if the queue 'has
+ * space'. */
+ if( uxMessagesWaiting < pxQueue->uxLength )
+ {
+ const int8_t cTxLock = pxQueue->cTxLock;
+
+ traceQUEUE_SEND_FROM_ISR( pxQueue );
+
+ /* A task can only have an inherited priority if it is a mutex
+ * holder - and if there is a mutex holder then the mutex cannot be
+ * given from an ISR. As this is the ISR version of the function it
+ * can be assumed there is no mutex holder and no need to determine if
+ * priority disinheritance is needed. Simply increase the count of
+ * messages (semaphores) available. */
+ pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;
+
+ /* The event list is not altered if the queue is locked. This will
+ * be done when the queue is unlocked later. */
+ if( cTxLock == queueUNLOCKED )
+ {
+ #if ( configUSE_QUEUE_SETS == 1 )
+ {
+ if( pxQueue->pxQueueSetContainer != NULL )
+ {
+ if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
+ {
+ /* The semaphore is a member of a queue set, and
+ * posting to the queue set caused a higher priority
+ * task to unblock. A context switch is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority so
+ * record that a context switch is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ #else /* configUSE_QUEUE_SETS */
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority so record that a
+ * context switch is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_QUEUE_SETS */
+ }
+ else
+ {
+ /* Increment the lock count so the task that unlocks the queue
+ * knows that data was posted while it was locked. */
+ prvIncrementQueueTxLock( pxQueue, cTxLock );
+ }
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
+ xReturn = errQUEUE_FULL;
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueReceive( QueueHandle_t xQueue,
+ void * const pvBuffer,
+ TickType_t xTicksToWait )
+{
+ BaseType_t xEntryTimeSet = pdFALSE;
+ TimeOut_t xTimeOut;
+ Queue_t * const pxQueue = xQueue;
+
+ /* Check the pointer is not NULL. */
+ configASSERT( ( pxQueue ) );
+
+ /* The buffer into which data is received can only be NULL if the data size
+ * is zero (so no data is copied into the buffer). */
+ configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
+
+ /* Cannot block if the scheduler is suspended. */
+ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+ {
+ configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+ }
+ #endif
+
+ /*lint -save -e904 This function relaxes the coding standard somewhat to
+ * allow return statements within the function itself. This is done in the
+ * interest of execution time efficiency. */
+ for( ; ; )
+ {
+ taskENTER_CRITICAL();
+ {
+ const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
+
+ /* Is there data in the queue now? To be running the calling task
+ * must be the highest priority task wanting to access the queue. */
+ if( uxMessagesWaiting > ( UBaseType_t ) 0 )
+ {
+ /* Data available, remove one item. */
+ prvCopyDataFromQueue( pxQueue, pvBuffer );
+ traceQUEUE_RECEIVE( pxQueue );
+ pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;
+
+ /* There is now space in the queue, were any tasks waiting to
+ * post to the queue? If so, unblock the highest priority waiting
+ * task. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ queueYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ taskEXIT_CRITICAL();
+ return pdPASS;
+ }
+ else
+ {
+ if( xTicksToWait == ( TickType_t ) 0 )
+ {
+ /* The queue was empty and no block time is specified (or
+ * the block time has expired) so leave now. */
+ taskEXIT_CRITICAL();
+ traceQUEUE_RECEIVE_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ /* The queue was empty and a block time was specified so
+ * configure the timeout structure. */
+ vTaskInternalSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
+ else
+ {
+ /* Entry time was already set. */
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ /* Interrupts and other tasks can send to and receive from the queue
+ * now the critical section has been exited. */
+
+ vTaskSuspendAll();
+ prvLockQueue( pxQueue );
+
+ /* Update the timeout state to see if it has expired yet. */
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+ {
+ /* The timeout has not expired. If the queue is still empty place
+ * the task on the list of tasks waiting to receive from the queue. */
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+ {
+ traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+ prvUnlockQueue( pxQueue );
+
+ if( xTaskResumeAll() == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* The queue contains data again. Loop back to try and read the
+ * data. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ }
+ }
+ else
+ {
+ /* Timed out. If there is no data in the queue exit, otherwise loop
+ * back and attempt to read the data. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+ {
+ traceQUEUE_RECEIVE_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ } /*lint -restore */
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
+ TickType_t xTicksToWait )
+{
+ BaseType_t xEntryTimeSet = pdFALSE;
+ TimeOut_t xTimeOut;
+ Queue_t * const pxQueue = xQueue;
+
+ #if ( configUSE_MUTEXES == 1 )
+ BaseType_t xInheritanceOccurred = pdFALSE;
+ #endif
+
+ /* Check the queue pointer is not NULL. */
+ configASSERT( ( pxQueue ) );
+
+ /* Check this really is a semaphore, in which case the item size will be
+ * 0. */
+ configASSERT( pxQueue->uxItemSize == 0 );
+
+ /* Cannot block if the scheduler is suspended. */
+ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+ {
+ configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+ }
+ #endif
+
+ /*lint -save -e904 This function relaxes the coding standard somewhat to allow return
+ * statements within the function itself. This is done in the interest
+ * of execution time efficiency. */
+ for( ; ; )
+ {
+ taskENTER_CRITICAL();
+ {
+ /* Semaphores are queues with an item size of 0, and where the
+ * number of messages in the queue is the semaphore's count value. */
+ const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;
+
+ /* Is there data in the queue now? To be running the calling task
+ * must be the highest priority task wanting to access the queue. */
+ if( uxSemaphoreCount > ( UBaseType_t ) 0 )
+ {
+ traceQUEUE_RECEIVE( pxQueue );
+
+ /* Semaphores are queues with a data size of zero and where the
+ * messages waiting is the semaphore's count. Reduce the count. */
+ pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1;
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ /* Record the information required to implement
+ * priority inheritance should it become necessary. */
+ pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_MUTEXES */
+
+ /* Check to see if other tasks are blocked waiting to give the
+ * semaphore, and if so, unblock the highest priority such task. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ queueYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ taskEXIT_CRITICAL();
+ return pdPASS;
+ }
+ else
+ {
+ if( xTicksToWait == ( TickType_t ) 0 )
+ {
+ /* The semaphore count was 0 and no block time is specified
+ * (or the block time has expired) so exit now. */
+ taskEXIT_CRITICAL();
+ traceQUEUE_RECEIVE_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ /* The semaphore count was 0 and a block time was specified
+ * so configure the timeout structure ready to block. */
+ vTaskInternalSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
+ else
+ {
+ /* Entry time was already set. */
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ /* Interrupts and other tasks can give to and take from the semaphore
+ * now the critical section has been exited. */
+
+ vTaskSuspendAll();
+ prvLockQueue( pxQueue );
+
+ /* Update the timeout state to see if it has expired yet. */
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+ {
+ /* A block time is specified and not expired. If the semaphore
+ * count is 0 then enter the Blocked state to wait for a semaphore to
+ * become available. As semaphores are implemented with queues the
+ * queue being empty is equivalent to the semaphore count being 0. */
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+ {
+ traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ taskENTER_CRITICAL();
+ {
+ xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder );
+ }
+ taskEXIT_CRITICAL();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* if ( configUSE_MUTEXES == 1 ) */
+
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+ prvUnlockQueue( pxQueue );
+
+ if( xTaskResumeAll() == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* There was no timeout and the semaphore count was not 0, so
+ * attempt to take the semaphore again. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ }
+ }
+ else
+ {
+ /* Timed out. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+
+ /* If the semaphore count is 0 exit now as the timeout has
+ * expired. Otherwise return to attempt to take the semaphore that is
+ * known to be available. As semaphores are implemented by queues the
+ * queue being empty is equivalent to the semaphore count being 0. */
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+ {
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ /* xInheritanceOccurred could only have be set if
+ * pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to
+ * test the mutex type again to check it is actually a mutex. */
+ if( xInheritanceOccurred != pdFALSE )
+ {
+ taskENTER_CRITICAL();
+ {
+ UBaseType_t uxHighestWaitingPriority;
+
+ /* This task blocking on the mutex caused another
+ * task to inherit this task's priority. Now this task
+ * has timed out the priority should be disinherited
+ * again, but only as low as the next highest priority
+ * task that is waiting for the same mutex. */
+ uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue );
+ vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority );
+ }
+ taskEXIT_CRITICAL();
+ }
+ }
+ #endif /* configUSE_MUTEXES */
+
+ traceQUEUE_RECEIVE_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ } /*lint -restore */
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueuePeek( QueueHandle_t xQueue,
+ void * const pvBuffer,
+ TickType_t xTicksToWait )
+{
+ BaseType_t xEntryTimeSet = pdFALSE;
+ TimeOut_t xTimeOut;
+ int8_t * pcOriginalReadPosition;
+ Queue_t * const pxQueue = xQueue;
+
+ /* Check the pointer is not NULL. */
+ configASSERT( ( pxQueue ) );
+
+ /* The buffer into which data is received can only be NULL if the data size
+ * is zero (so no data is copied into the buffer. */
+ configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
+
+ /* Cannot block if the scheduler is suspended. */
+ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+ {
+ configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+ }
+ #endif
+
+ /*lint -save -e904 This function relaxes the coding standard somewhat to
+ * allow return statements within the function itself. This is done in the
+ * interest of execution time efficiency. */
+ for( ; ; )
+ {
+ taskENTER_CRITICAL();
+ {
+ const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
+
+ /* Is there data in the queue now? To be running the calling task
+ * must be the highest priority task wanting to access the queue. */
+ if( uxMessagesWaiting > ( UBaseType_t ) 0 )
+ {
+ /* Remember the read position so it can be reset after the data
+ * is read from the queue as this function is only peeking the
+ * data, not removing it. */
+ pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom;
+
+ prvCopyDataFromQueue( pxQueue, pvBuffer );
+ traceQUEUE_PEEK( pxQueue );
+
+ /* The data is not being removed, so reset the read pointer. */
+ pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition;
+
+ /* The data is being left in the queue, so see if there are
+ * any other tasks waiting for the data. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority than this task. */
+ queueYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ taskEXIT_CRITICAL();
+ return pdPASS;
+ }
+ else
+ {
+ if( xTicksToWait == ( TickType_t ) 0 )
+ {
+ /* The queue was empty and no block time is specified (or
+ * the block time has expired) so leave now. */
+ taskEXIT_CRITICAL();
+ traceQUEUE_PEEK_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ else if( xEntryTimeSet == pdFALSE )
+ {
+ /* The queue was empty and a block time was specified so
+ * configure the timeout structure ready to enter the blocked
+ * state. */
+ vTaskInternalSetTimeOutState( &xTimeOut );
+ xEntryTimeSet = pdTRUE;
+ }
+ else
+ {
+ /* Entry time was already set. */
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ /* Interrupts and other tasks can send to and receive from the queue
+ * now that the critical section has been exited. */
+
+ vTaskSuspendAll();
+ prvLockQueue( pxQueue );
+
+ /* Update the timeout state to see if it has expired yet. */
+ if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+ {
+ /* Timeout has not expired yet, check to see if there is data in the
+ * queue now, and if not enter the Blocked state to wait for data. */
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+ {
+ traceBLOCKING_ON_QUEUE_PEEK( pxQueue );
+ vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+ prvUnlockQueue( pxQueue );
+
+ if( xTaskResumeAll() == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* There is data in the queue now, so don't enter the blocked
+ * state, instead return to try and obtain the data. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+ }
+ }
+ else
+ {
+ /* The timeout has expired. If there is still no data in the queue
+ * exit, otherwise go back and try to read the data again. */
+ prvUnlockQueue( pxQueue );
+ ( void ) xTaskResumeAll();
+
+ if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+ {
+ traceQUEUE_PEEK_FAILED( pxQueue );
+ return errQUEUE_EMPTY;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ } /*lint -restore */
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
+ void * const pvBuffer,
+ BaseType_t * const pxHigherPriorityTaskWoken )
+{
+ BaseType_t xReturn;
+ UBaseType_t uxSavedInterruptStatus;
+ Queue_t * const pxQueue = xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
+
+ /* RTOS ports that support interrupt nesting have the concept of a maximum
+ * system call (or maximum API call) interrupt priority. Interrupts that are
+ * above the maximum system call priority are kept permanently enabled, even
+ * when the RTOS kernel is in a critical section, but cannot make any calls to
+ * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
+ * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ * failure if a FreeRTOS API function is called from an interrupt that has been
+ * assigned a priority above the configured maximum system call priority.
+ * Only FreeRTOS functions that end in FromISR can be called from interrupts
+ * that have been assigned a priority at or (logically) below the maximum
+ * system call interrupt priority. FreeRTOS maintains a separate interrupt
+ * safe API to ensure interrupt entry is as fast and as simple as possible.
+ * More information (albeit Cortex-M specific) is provided on the following
+ * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
+
+ /* Cannot block in an ISR, so check there is data available. */
+ if( uxMessagesWaiting > ( UBaseType_t ) 0 )
+ {
+ const int8_t cRxLock = pxQueue->cRxLock;
+
+ traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
+
+ prvCopyDataFromQueue( pxQueue, pvBuffer );
+ pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;
+
+ /* If the queue is locked the event list will not be modified.
+ * Instead update the lock count so the task that unlocks the queue
+ * will know that an ISR has removed data while the queue was
+ * locked. */
+ if( cRxLock == queueUNLOCKED )
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority than us so
+ * force a context switch. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* Increment the lock count so the task that unlocks the queue
+ * knows that data was removed while it was locked. */
+ prvIncrementQueueRxLock( pxQueue, cRxLock );
+ }
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
+ void * const pvBuffer )
+{
+ BaseType_t xReturn;
+ UBaseType_t uxSavedInterruptStatus;
+ int8_t * pcOriginalReadPosition;
+ Queue_t * const pxQueue = xQueue;
+
+ configASSERT( pxQueue );
+ configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
+ configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */
+
+ /* RTOS ports that support interrupt nesting have the concept of a maximum
+ * system call (or maximum API call) interrupt priority. Interrupts that are
+ * above the maximum system call priority are kept permanently enabled, even
+ * when the RTOS kernel is in a critical section, but cannot make any calls to
+ * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
+ * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ * failure if a FreeRTOS API function is called from an interrupt that has been
+ * assigned a priority above the configured maximum system call priority.
+ * Only FreeRTOS functions that end in FromISR can be called from interrupts
+ * that have been assigned a priority at or (logically) below the maximum
+ * system call interrupt priority. FreeRTOS maintains a separate interrupt
+ * safe API to ensure interrupt entry is as fast and as simple as possible.
+ * More information (albeit Cortex-M specific) is provided on the following
+ * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ /* Cannot block in an ISR, so check there is data available. */
+ if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
+ {
+ traceQUEUE_PEEK_FROM_ISR( pxQueue );
+
+ /* Remember the read position so it can be reset as nothing is
+ * actually being removed from the queue. */
+ pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom;
+ prvCopyDataFromQueue( pxQueue, pvBuffer );
+ pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition;
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
+{
+ UBaseType_t uxReturn;
+
+ configASSERT( xQueue );
+
+ taskENTER_CRITICAL();
+ {
+ uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;
+ }
+ taskEXIT_CRITICAL();
+
+ return uxReturn;
+} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
+/*-----------------------------------------------------------*/
+
+UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )
+{
+ UBaseType_t uxReturn;
+ Queue_t * const pxQueue = xQueue;
+
+ configASSERT( pxQueue );
+
+ taskENTER_CRITICAL();
+ {
+ uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;
+ }
+ taskEXIT_CRITICAL();
+
+ return uxReturn;
+} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
+/*-----------------------------------------------------------*/
+
+UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )
+{
+ UBaseType_t uxReturn;
+ Queue_t * const pxQueue = xQueue;
+
+ configASSERT( pxQueue );
+ uxReturn = pxQueue->uxMessagesWaiting;
+
+ return uxReturn;
+} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
+/*-----------------------------------------------------------*/
+
+void vQueueDelete( QueueHandle_t xQueue )
+{
+ Queue_t * const pxQueue = xQueue;
+
+ configASSERT( pxQueue );
+ traceQUEUE_DELETE( pxQueue );
+
+ #if ( configQUEUE_REGISTRY_SIZE > 0 )
+ {
+ vQueueUnregisterQueue( pxQueue );
+ }
+ #endif
+
+ #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
+ {
+ /* The queue can only have been allocated dynamically - free it
+ * again. */
+ vPortFree( pxQueue );
+ }
+ #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+ {
+ /* The queue could have been allocated statically or dynamically, so
+ * check before attempting to free the memory. */
+ if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
+ {
+ vPortFree( pxQueue );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #else /* if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) */
+ {
+ /* The queue must have been statically allocated, so is not going to be
+ * deleted. Avoid compiler warnings about the unused parameter. */
+ ( void ) pxQueue;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue )
+ {
+ return ( ( Queue_t * ) xQueue )->uxQueueNumber;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ void vQueueSetQueueNumber( QueueHandle_t xQueue,
+ UBaseType_t uxQueueNumber )
+ {
+ ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ uint8_t ucQueueGetQueueType( QueueHandle_t xQueue )
+ {
+ return ( ( Queue_t * ) xQueue )->ucQueueType;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+ static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue )
+ {
+ UBaseType_t uxHighestPriorityOfWaitingTasks;
+
+ /* If a task waiting for a mutex causes the mutex holder to inherit a
+ * priority, but the waiting task times out, then the holder should
+ * disinherit the priority - but only down to the highest priority of any
+ * other tasks that are waiting for the same mutex. For this purpose,
+ * return the priority of the highest priority task that is waiting for the
+ * mutex. */
+ if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0U )
+ {
+ uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) );
+ }
+ else
+ {
+ uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY;
+ }
+
+ return uxHighestPriorityOfWaitingTasks;
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
+ const void * pvItemToQueue,
+ const BaseType_t xPosition )
+{
+ BaseType_t xReturn = pdFALSE;
+ UBaseType_t uxMessagesWaiting;
+
+ /* This function is called from a critical section. */
+
+ uxMessagesWaiting = pxQueue->uxMessagesWaiting;
+
+ if( pxQueue->uxItemSize == ( UBaseType_t ) 0 )
+ {
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+ {
+ /* The mutex is no longer being held. */
+ xReturn = xTaskPriorityDisinherit( pxQueue->u.xSemaphore.xMutexHolder );
+ pxQueue->u.xSemaphore.xMutexHolder = NULL;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_MUTEXES */
+ }
+ else if( xPosition == queueSEND_TO_BACK )
+ {
+ ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */
+ pxQueue->pcWriteTo += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */
+
+ if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
+ {
+ pxQueue->pcWriteTo = pxQueue->pcHead;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ ( void ) memcpy( ( void * ) pxQueue->u.xQueue.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e9087 !e418 MISRA exception as the casts are only redundant for some ports. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. Assert checks null pointer only used when length is 0. */
+ pxQueue->u.xQueue.pcReadFrom -= pxQueue->uxItemSize;
+
+ if( pxQueue->u.xQueue.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
+ {
+ pxQueue->u.xQueue.pcReadFrom = ( pxQueue->u.xQueue.pcTail - pxQueue->uxItemSize );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ if( xPosition == queueOVERWRITE )
+ {
+ if( uxMessagesWaiting > ( UBaseType_t ) 0 )
+ {
+ /* An item is not being added but overwritten, so subtract
+ * one from the recorded number of items in the queue so when
+ * one is added again below the number of recorded items remains
+ * correct. */
+ --uxMessagesWaiting;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static void prvCopyDataFromQueue( Queue_t * const pxQueue,
+ void * const pvBuffer )
+{
+ if( pxQueue->uxItemSize != ( UBaseType_t ) 0 )
+ {
+ pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */
+
+ if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
+ {
+ pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvUnlockQueue( Queue_t * const pxQueue )
+{
+ /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
+
+ /* The lock counts contains the number of extra data items placed or
+ * removed from the queue while the queue was locked. When a queue is
+ * locked items can be added or removed, but the event lists cannot be
+ * updated. */
+ taskENTER_CRITICAL();
+ {
+ int8_t cTxLock = pxQueue->cTxLock;
+
+ /* See if data was added to the queue while it was locked. */
+ while( cTxLock > queueLOCKED_UNMODIFIED )
+ {
+ /* Data was posted while the queue was locked. Are any tasks
+ * blocked waiting for data to become available? */
+ #if ( configUSE_QUEUE_SETS == 1 )
+ {
+ if( pxQueue->pxQueueSetContainer != NULL )
+ {
+ if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE )
+ {
+ /* The queue is a member of a queue set, and posting to
+ * the queue set caused a higher priority task to unblock.
+ * A context switch is required. */
+ vTaskMissedYield();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* Tasks that are removed from the event list will get
+ * added to the pending ready list as the scheduler is still
+ * suspended. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority so record that a
+ * context switch is required. */
+ vTaskMissedYield();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ #else /* configUSE_QUEUE_SETS */
+ {
+ /* Tasks that are removed from the event list will get added to
+ * the pending ready list as the scheduler is still suspended. */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority so record that
+ * a context switch is required. */
+ vTaskMissedYield();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ #endif /* configUSE_QUEUE_SETS */
+
+ --cTxLock;
+ }
+
+ pxQueue->cTxLock = queueUNLOCKED;
+ }
+ taskEXIT_CRITICAL();
+
+ /* Do the same for the Rx lock. */
+ taskENTER_CRITICAL();
+ {
+ int8_t cRxLock = pxQueue->cRxLock;
+
+ while( cRxLock > queueLOCKED_UNMODIFIED )
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ vTaskMissedYield();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ --cRxLock;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ pxQueue->cRxLock = queueUNLOCKED;
+ }
+ taskEXIT_CRITICAL();
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue )
+{
+ BaseType_t xReturn;
+
+ taskENTER_CRITICAL();
+ {
+ if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )
+{
+ BaseType_t xReturn;
+ Queue_t * const pxQueue = xQueue;
+
+ configASSERT( pxQueue );
+
+ if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+
+ return xReturn;
+} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvIsQueueFull( const Queue_t * pxQueue )
+{
+ BaseType_t xReturn;
+
+ taskENTER_CRITICAL();
+ {
+ if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )
+{
+ BaseType_t xReturn;
+ Queue_t * const pxQueue = xQueue;
+
+ configASSERT( pxQueue );
+
+ if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+
+ return xReturn;
+} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+ BaseType_t xQueueCRSend( QueueHandle_t xQueue,
+ const void * pvItemToQueue,
+ TickType_t xTicksToWait )
+ {
+ BaseType_t xReturn;
+ Queue_t * const pxQueue = xQueue;
+
+ /* If the queue is already full we may have to block. A critical section
+ * is required to prevent an interrupt removing something from the queue
+ * between the check to see if the queue is full and blocking on the queue. */
+ portDISABLE_INTERRUPTS();
+ {
+ if( prvIsQueueFull( pxQueue ) != pdFALSE )
+ {
+ /* The queue is full - do we want to block or just leave without
+ * posting? */
+ if( xTicksToWait > ( TickType_t ) 0 )
+ {
+ /* As this is called from a coroutine we cannot block directly, but
+ * return indicating that we need to block. */
+ vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
+ portENABLE_INTERRUPTS();
+ return errQUEUE_BLOCKED;
+ }
+ else
+ {
+ portENABLE_INTERRUPTS();
+ return errQUEUE_FULL;
+ }
+ }
+ }
+ portENABLE_INTERRUPTS();
+
+ portDISABLE_INTERRUPTS();
+ {
+ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
+ {
+ /* There is room in the queue, copy the data into the queue. */
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
+ xReturn = pdPASS;
+
+ /* Were any co-routines waiting for data to become available? */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ /* In this instance the co-routine could be placed directly
+ * into the ready list as we are within a critical section.
+ * Instead the same pending ready list mechanism is used as if
+ * the event were caused from within an interrupt. */
+ if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The co-routine waiting has a higher priority so record
+ * that a yield might be appropriate. */
+ xReturn = errQUEUE_YIELD;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ xReturn = errQUEUE_FULL;
+ }
+ }
+ portENABLE_INTERRUPTS();
+
+ return xReturn;
+ }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+ BaseType_t xQueueCRReceive( QueueHandle_t xQueue,
+ void * pvBuffer,
+ TickType_t xTicksToWait )
+ {
+ BaseType_t xReturn;
+ Queue_t * const pxQueue = xQueue;
+
+ /* If the queue is already empty we may have to block. A critical section
+ * is required to prevent an interrupt adding something to the queue
+ * between the check to see if the queue is empty and blocking on the queue. */
+ portDISABLE_INTERRUPTS();
+ {
+ if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )
+ {
+ /* There are no messages in the queue, do we want to block or just
+ * leave with nothing? */
+ if( xTicksToWait > ( TickType_t ) 0 )
+ {
+ /* As this is a co-routine we cannot block directly, but return
+ * indicating that we need to block. */
+ vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
+ portENABLE_INTERRUPTS();
+ return errQUEUE_BLOCKED;
+ }
+ else
+ {
+ portENABLE_INTERRUPTS();
+ return errQUEUE_FULL;
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ portENABLE_INTERRUPTS();
+
+ portDISABLE_INTERRUPTS();
+ {
+ if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
+ {
+ /* Data is available from the queue. */
+ pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize;
+
+ if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail )
+ {
+ pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ --( pxQueue->uxMessagesWaiting );
+ ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
+
+ xReturn = pdPASS;
+
+ /* Were any co-routines waiting for space to become available? */
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ /* In this instance the co-routine could be placed directly
+ * into the ready list as we are within a critical section.
+ * Instead the same pending ready list mechanism is used as if
+ * the event were caused from within an interrupt. */
+ if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ xReturn = errQUEUE_YIELD;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+ }
+ portENABLE_INTERRUPTS();
+
+ return xReturn;
+ }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+ BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue,
+ const void * pvItemToQueue,
+ BaseType_t xCoRoutinePreviouslyWoken )
+ {
+ Queue_t * const pxQueue = xQueue;
+
+ /* Cannot block within an ISR so if there is no space on the queue then
+ * exit without doing anything. */
+ if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
+ {
+ prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
+
+ /* We only want to wake one co-routine per ISR, so check that a
+ * co-routine has not already been woken. */
+ if( xCoRoutinePreviouslyWoken == pdFALSE )
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ return pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xCoRoutinePreviouslyWoken;
+ }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_CO_ROUTINES == 1 )
+
+ BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue,
+ void * pvBuffer,
+ BaseType_t * pxCoRoutineWoken )
+ {
+ BaseType_t xReturn;
+ Queue_t * const pxQueue = xQueue;
+
+ /* We cannot block from an ISR, so check there is data available. If
+ * not then just leave without doing anything. */
+ if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )
+ {
+ /* Copy the data from the queue. */
+ pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize;
+
+ if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail )
+ {
+ pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ --( pxQueue->uxMessagesWaiting );
+ ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
+
+ if( ( *pxCoRoutineWoken ) == pdFALSE )
+ {
+ if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+ {
+ if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+ {
+ *pxCoRoutineWoken = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_CO_ROUTINES */
+/*-----------------------------------------------------------*/
+
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+
+ void vQueueAddToRegistry( QueueHandle_t xQueue,
+ const char * pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ {
+ UBaseType_t ux;
+ QueueRegistryItem_t * pxEntryToWrite = NULL;
+
+ configASSERT( xQueue );
+
+ if( pcQueueName != NULL )
+ {
+ /* See if there is an empty space in the registry. A NULL name denotes
+ * a free slot. */
+ for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )
+ {
+ /* Replace an existing entry if the queue is already in the registry. */
+ if( xQueue == xQueueRegistry[ ux ].xHandle )
+ {
+ pxEntryToWrite = &( xQueueRegistry[ ux ] );
+ break;
+ }
+ /* Otherwise, store in the next empty location */
+ else if( ( pxEntryToWrite == NULL ) && ( xQueueRegistry[ ux ].pcQueueName == NULL ) )
+ {
+ pxEntryToWrite = &( xQueueRegistry[ ux ] );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+
+ if( pxEntryToWrite != NULL )
+ {
+ /* Store the information on this queue. */
+ pxEntryToWrite->pcQueueName = pcQueueName;
+ pxEntryToWrite->xHandle = xQueue;
+
+ traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName );
+ }
+ }
+
+#endif /* configQUEUE_REGISTRY_SIZE */
+/*-----------------------------------------------------------*/
+
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+
+ const char * pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ {
+ UBaseType_t ux;
+ const char * pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+ configASSERT( xQueue );
+
+ /* Note there is nothing here to protect against another task adding or
+ * removing entries from the registry while it is being searched. */
+
+ for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )
+ {
+ if( xQueueRegistry[ ux ].xHandle == xQueue )
+ {
+ pcReturn = xQueueRegistry[ ux ].pcQueueName;
+ break;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ return pcReturn;
+ } /*lint !e818 xQueue cannot be a pointer to const because it is a typedef. */
+
+#endif /* configQUEUE_REGISTRY_SIZE */
+/*-----------------------------------------------------------*/
+
+#if ( configQUEUE_REGISTRY_SIZE > 0 )
+
+ void vQueueUnregisterQueue( QueueHandle_t xQueue )
+ {
+ UBaseType_t ux;
+
+ configASSERT( xQueue );
+
+ /* See if the handle of the queue being unregistered in actually in the
+ * registry. */
+ for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )
+ {
+ if( xQueueRegistry[ ux ].xHandle == xQueue )
+ {
+ /* Set the name to NULL to show that this slot if free again. */
+ xQueueRegistry[ ux ].pcQueueName = NULL;
+
+ /* Set the handle to NULL to ensure the same queue handle cannot
+ * appear in the registry twice if it is added, removed, then
+ * added again. */
+ xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0;
+ break;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
+
+#endif /* configQUEUE_REGISTRY_SIZE */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TIMERS == 1 )
+
+ void vQueueWaitForMessageRestricted( QueueHandle_t xQueue,
+ TickType_t xTicksToWait,
+ const BaseType_t xWaitIndefinitely )
+ {
+ Queue_t * const pxQueue = xQueue;
+
+ /* This function should not be called by application code hence the
+ * 'Restricted' in its name. It is not part of the public API. It is
+ * designed for use by kernel code, and has special calling requirements.
+ * It can result in vListInsert() being called on a list that can only
+ * possibly ever have one item in it, so the list will be fast, but even
+ * so it should be called with the scheduler locked and not from a critical
+ * section. */
+
+ /* Only do anything if there are no messages in the queue. This function
+ * will not actually cause the task to block, just place it on a blocked
+ * list. It will not block until the scheduler is unlocked - at which
+ * time a yield will be performed. If an item is added to the queue while
+ * the queue is locked, and the calling task blocks on the queue, then the
+ * calling task will be immediately unblocked when the queue is unlocked. */
+ prvLockQueue( pxQueue );
+
+ if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U )
+ {
+ /* There is nothing in the queue, block for the specified period. */
+ vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ prvUnlockQueue( pxQueue );
+ }
+
+#endif /* configUSE_TIMERS */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+
+ QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )
+ {
+ QueueSetHandle_t pxQueue;
+
+ pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET );
+
+ return pxQueue;
+ }
+
+#endif /* configUSE_QUEUE_SETS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
+ QueueSetHandle_t xQueueSet )
+ {
+ BaseType_t xReturn;
+
+ taskENTER_CRITICAL();
+ {
+ if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
+ {
+ /* Cannot add a queue/semaphore to more than one queue set. */
+ xReturn = pdFAIL;
+ }
+ else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 )
+ {
+ /* Cannot add a queue/semaphore to a queue set if there are already
+ * items in the queue/semaphore. */
+ xReturn = pdFAIL;
+ }
+ else
+ {
+ ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
+ xReturn = pdPASS;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+ }
+
+#endif /* configUSE_QUEUE_SETS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
+ QueueSetHandle_t xQueueSet )
+ {
+ BaseType_t xReturn;
+ Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore;
+
+ if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
+ {
+ /* The queue was not a member of the set. */
+ xReturn = pdFAIL;
+ }
+ else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 )
+ {
+ /* It is dangerous to remove a queue from a set when the queue is
+ * not empty because the queue set will still hold pending events for
+ * the queue. */
+ xReturn = pdFAIL;
+ }
+ else
+ {
+ taskENTER_CRITICAL();
+ {
+ /* The queue is no longer contained in the set. */
+ pxQueueOrSemaphore->pxQueueSetContainer = NULL;
+ }
+ taskEXIT_CRITICAL();
+ xReturn = pdPASS;
+ }
+
+ return xReturn;
+ } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */
+
+#endif /* configUSE_QUEUE_SETS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
+ TickType_t const xTicksToWait )
+ {
+ QueueSetMemberHandle_t xReturn = NULL;
+
+ ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); /*lint !e961 Casting from one typedef to another is not redundant. */
+ return xReturn;
+ }
+
+#endif /* configUSE_QUEUE_SETS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet )
+ {
+ QueueSetMemberHandle_t xReturn = NULL;
+
+ ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */
+ return xReturn;
+ }
+
+#endif /* configUSE_QUEUE_SETS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_QUEUE_SETS == 1 )
+
+ static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue )
+ {
+ Queue_t * pxQueueSetContainer = pxQueue->pxQueueSetContainer;
+ BaseType_t xReturn = pdFALSE;
+
+ /* This function must be called form a critical section. */
+
+ /* The following line is not reachable in unit tests because every call
+ * to prvNotifyQueueSetContainer is preceded by a check that
+ * pxQueueSetContainer != NULL */
+ configASSERT( pxQueueSetContainer ); /* LCOV_EXCL_BR_LINE */
+ configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
+
+ if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
+ {
+ const int8_t cTxLock = pxQueueSetContainer->cTxLock;
+
+ traceQUEUE_SET_SEND( pxQueueSetContainer );
+
+ /* The data copied is the handle of the queue that contains data. */
+ xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, queueSEND_TO_BACK );
+
+ if( cTxLock == queueUNLOCKED )
+ {
+ if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
+ {
+ if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
+ {
+ /* The task waiting has a higher priority. */
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ prvIncrementQueueTxLock( pxQueueSetContainer, cTxLock );
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_QUEUE_SETS */
diff --git a/source/test/freertos/src/stream_buffer.c b/source/test/freertos/src/stream_buffer.c
new file mode 100644
index 0000000..fed7eb8
--- /dev/null
+++ b/source/test/freertos/src/stream_buffer.c
@@ -0,0 +1,1427 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/* Standard includes. */
+#include
+#include
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+ * all the API functions to use the MPU wrappers. That should only be done when
+ * task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "stream_buffer.h"
+
+#if ( configUSE_TASK_NOTIFICATIONS != 1 )
+ #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c
+#endif
+
+#if ( INCLUDE_xTaskGetCurrentTaskHandle != 1 )
+ #error INCLUDE_xTaskGetCurrentTaskHandle must be set to 1 to build stream_buffer.c
+#endif
+
+/* Lint e961, e9021 and e750 are suppressed as a MISRA exception justified
+ * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
+ * for the header files above, but not in this file, in order to generate the
+ * correct privileged Vs unprivileged linkage and placement. */
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
+
+/* If the user has not provided application specific Rx notification macros,
+ * or #defined the notification macros away, then provide default implementations
+ * that uses task notifications. */
+/*lint -save -e9026 Function like macros allowed and needed here so they can be overridden. */
+#ifndef sbRECEIVE_COMPLETED
+ #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \
+ vTaskSuspendAll(); \
+ { \
+ if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \
+ { \
+ ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToSend, \
+ ( uint32_t ) 0, \
+ eNoAction ); \
+ ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \
+ } \
+ } \
+ ( void ) xTaskResumeAll();
+#endif /* sbRECEIVE_COMPLETED */
+
+/* If user has provided a per-instance receive complete callback, then
+ * invoke the callback else use the receive complete macro which is provided by default for all instances.
+ */
+#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ #define prvRECEIVE_COMPLETED( pxStreamBuffer ) \
+ { \
+ if( ( pxStreamBuffer )->pxReceiveCompletedCallback != NULL ) \
+ { \
+ ( pxStreamBuffer )->pxReceiveCompletedCallback( ( pxStreamBuffer ), pdFALSE, NULL ); \
+ } \
+ else \
+ { \
+ sbRECEIVE_COMPLETED( ( pxStreamBuffer ) ); \
+ } \
+ }
+#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
+ #define prvRECEIVE_COMPLETED( pxStreamBuffer ) sbRECEIVE_COMPLETED( ( pxStreamBuffer ) )
+#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
+
+#ifndef sbRECEIVE_COMPLETED_FROM_ISR
+ #define sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, \
+ pxHigherPriorityTaskWoken ) \
+ { \
+ UBaseType_t uxSavedInterruptStatus; \
+ \
+ uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \
+ { \
+ if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \
+ { \
+ ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend, \
+ ( uint32_t ) 0, \
+ eNoAction, \
+ ( pxHigherPriorityTaskWoken ) ); \
+ ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \
+ } \
+ } \
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
+ }
+#endif /* sbRECEIVE_COMPLETED_FROM_ISR */
+
+#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ #define prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, \
+ pxHigherPriorityTaskWoken ) \
+ { \
+ if( ( pxStreamBuffer )->pxReceiveCompletedCallback != NULL ) \
+ { \
+ ( pxStreamBuffer )->pxReceiveCompletedCallback( ( pxStreamBuffer ), pdTRUE, ( pxHigherPriorityTaskWoken ) ); \
+ } \
+ else \
+ { \
+ sbRECEIVE_COMPLETED_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) ); \
+ } \
+ }
+#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
+ #define prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
+ sbRECEIVE_COMPLETED_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) )
+#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
+
+/* If the user has not provided an application specific Tx notification macro,
+ * or #defined the notification macro away, then provide a default
+ * implementation that uses task notifications.
+ */
+#ifndef sbSEND_COMPLETED
+ #define sbSEND_COMPLETED( pxStreamBuffer ) \
+ vTaskSuspendAll(); \
+ { \
+ if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \
+ { \
+ ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToReceive, \
+ ( uint32_t ) 0, \
+ eNoAction ); \
+ ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \
+ } \
+ } \
+ ( void ) xTaskResumeAll();
+#endif /* sbSEND_COMPLETED */
+
+/* If user has provided a per-instance send completed callback, then
+ * invoke the callback else use the send complete macro which is provided by default for all instances.
+ */
+#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ #define prvSEND_COMPLETED( pxStreamBuffer ) \
+ { \
+ if( ( pxStreamBuffer )->pxSendCompletedCallback != NULL ) \
+ { \
+ pxStreamBuffer->pxSendCompletedCallback( ( pxStreamBuffer ), pdFALSE, NULL ); \
+ } \
+ else \
+ { \
+ sbSEND_COMPLETED( ( pxStreamBuffer ) ); \
+ } \
+ }
+#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
+ #define prvSEND_COMPLETED( pxStreamBuffer ) sbSEND_COMPLETED( ( pxStreamBuffer ) )
+#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
+
+
+#ifndef sbSEND_COMPLETE_FROM_ISR
+ #define sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
+ { \
+ UBaseType_t uxSavedInterruptStatus; \
+ \
+ uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \
+ { \
+ if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \
+ { \
+ ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, \
+ ( uint32_t ) 0, \
+ eNoAction, \
+ ( pxHigherPriorityTaskWoken ) ); \
+ ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \
+ } \
+ } \
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
+ }
+#endif /* sbSEND_COMPLETE_FROM_ISR */
+
+
+#if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ #define prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
+ { \
+ if( ( pxStreamBuffer )->pxSendCompletedCallback != NULL ) \
+ { \
+ ( pxStreamBuffer )->pxSendCompletedCallback( ( pxStreamBuffer ), pdTRUE, ( pxHigherPriorityTaskWoken ) ); \
+ } \
+ else \
+ { \
+ sbSEND_COMPLETE_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) ); \
+ } \
+ }
+#else /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
+ #define prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \
+ sbSEND_COMPLETE_FROM_ISR( ( pxStreamBuffer ), ( pxHigherPriorityTaskWoken ) )
+#endif /* if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) */
+
+/*lint -restore (9026) */
+
+/* The number of bytes used to hold the length of a message in the buffer. */
+#define sbBYTES_TO_STORE_MESSAGE_LENGTH ( sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) )
+
+/* Bits stored in the ucFlags field of the stream buffer. */
+#define sbFLAGS_IS_MESSAGE_BUFFER ( ( uint8_t ) 1 ) /* Set if the stream buffer was created as a message buffer, in which case it holds discrete messages rather than a stream. */
+#define sbFLAGS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 2 ) /* Set if the stream buffer was created using statically allocated memory. */
+
+/*-----------------------------------------------------------*/
+
+/* Structure that hold state information on the buffer. */
+typedef struct StreamBufferDef_t /*lint !e9058 Style convention uses tag. */
+{
+ volatile size_t xTail; /* Index to the next item to read within the buffer. */
+ volatile size_t xHead; /* Index to the next item to write within the buffer. */
+ size_t xLength; /* The length of the buffer pointed to by pucBuffer. */
+ size_t xTriggerLevelBytes; /* The number of bytes that must be in the stream buffer before a task that is waiting for data is unblocked. */
+ volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */
+ volatile TaskHandle_t xTaskWaitingToSend; /* Holds the handle of a task waiting to send data to a message buffer that is full. */
+ uint8_t * pucBuffer; /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */
+ uint8_t ucFlags;
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */
+ #endif
+
+ #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ StreamBufferCallbackFunction_t pxSendCompletedCallback; /* Optional callback called on send complete. sbSEND_COMPLETED is called if this is NULL. */
+ StreamBufferCallbackFunction_t pxReceiveCompletedCallback; /* Optional callback called on receive complete. sbRECEIVE_COMPLETED is called if this is NULL. */
+ #endif
+} StreamBuffer_t;
+
+/*
+ * The number of bytes available to be read from the buffer.
+ */
+static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION;
+
+/*
+ * Add xCount bytes from pucData into the pxStreamBuffer's data storage area.
+ * This function does not update the buffer's xHead pointer, so multiple writes
+ * may be chained together "atomically". This is useful for Message Buffers where
+ * the length and data bytes are written in two separate chunks, and we don't want
+ * the reader to see the buffer as having grown until after all data is copied over.
+ * This function takes a custom xHead value to indicate where to write to (necessary
+ * for chaining) and returns the the resulting xHead position.
+ * To mark the write as complete, manually set the buffer's xHead field with the
+ * returned xHead from this function.
+ */
+static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer,
+ const uint8_t * pucData,
+ size_t xCount,
+ size_t xHead ) PRIVILEGED_FUNCTION;
+
+/*
+ * If the stream buffer is being used as a message buffer, then reads an entire
+ * message out of the buffer. If the stream buffer is being used as a stream
+ * buffer then read as many bytes as possible from the buffer.
+ * prvReadBytesFromBuffer() is called to actually extract the bytes from the
+ * buffer's data storage area.
+ */
+static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer,
+ void * pvRxData,
+ size_t xBufferLengthBytes,
+ size_t xBytesAvailable ) PRIVILEGED_FUNCTION;
+
+/*
+ * If the stream buffer is being used as a message buffer, then writes an entire
+ * message to the buffer. If the stream buffer is being used as a stream
+ * buffer then write as many bytes as possible to the buffer.
+ * prvWriteBytestoBuffer() is called to actually send the bytes to the buffer's
+ * data storage area.
+ */
+static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
+ const void * pvTxData,
+ size_t xDataLengthBytes,
+ size_t xSpace,
+ size_t xRequiredSpace ) PRIVILEGED_FUNCTION;
+
+/*
+ * Copies xCount bytes from the pxStreamBuffer's data storage area to pucData.
+ * This function does not update the buffer's xTail pointer, so multiple reads
+ * may be chained together "atomically". This is useful for Message Buffers where
+ * the length and data bytes are read in two separate chunks, and we don't want
+ * the writer to see the buffer as having more free space until after all data is
+ * copied over, especially if we have to abort the read due to insufficient receiving space.
+ * This function takes a custom xTail value to indicate where to read from (necessary
+ * for chaining) and returns the the resulting xTail position.
+ * To mark the read as complete, manually set the buffer's xTail field with the
+ * returned xTail from this function.
+ */
+static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer,
+ uint8_t * pucData,
+ size_t xCount,
+ size_t xTail ) PRIVILEGED_FUNCTION;
+
+/*
+ * Called by both pxStreamBufferCreate() and pxStreamBufferCreateStatic() to
+ * initialise the members of the newly created stream buffer structure.
+ */
+static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
+ uint8_t * const pucBuffer,
+ size_t xBufferSizeBytes,
+ size_t xTriggerLevelBytes,
+ uint8_t ucFlags,
+ StreamBufferCallbackFunction_t pxSendCompletedCallback,
+ StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
+
+/*-----------------------------------------------------------*/
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
+ size_t xTriggerLevelBytes,
+ BaseType_t xIsMessageBuffer,
+ StreamBufferCallbackFunction_t pxSendCompletedCallback,
+ StreamBufferCallbackFunction_t pxReceiveCompletedCallback )
+ {
+ uint8_t * pucAllocatedMemory;
+ uint8_t ucFlags;
+
+ /* In case the stream buffer is going to be used as a message buffer
+ * (that is, it will hold discrete messages with a little meta data that
+ * says how big the next message is) check the buffer will be large enough
+ * to hold at least one message. */
+ if( xIsMessageBuffer == pdTRUE )
+ {
+ /* Is a message buffer but not statically allocated. */
+ ucFlags = sbFLAGS_IS_MESSAGE_BUFFER;
+ configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
+ }
+ else
+ {
+ /* Not a message buffer and not statically allocated. */
+ ucFlags = 0;
+ configASSERT( xBufferSizeBytes > 0 );
+ }
+
+ configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
+
+ /* A trigger level of 0 would cause a waiting task to unblock even when
+ * the buffer was empty. */
+ if( xTriggerLevelBytes == ( size_t ) 0 )
+ {
+ xTriggerLevelBytes = ( size_t ) 1;
+ }
+
+ /* A stream buffer requires a StreamBuffer_t structure and a buffer.
+ * Both are allocated in a single call to pvPortMalloc(). The
+ * StreamBuffer_t structure is placed at the start of the allocated memory
+ * and the buffer follows immediately after. The requested size is
+ * incremented so the free space is returned as the user would expect -
+ * this is a quirk of the implementation that means otherwise the free
+ * space would be reported as one byte smaller than would be logically
+ * expected. */
+ if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) )
+ {
+ xBufferSizeBytes++;
+ pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */
+ }
+ else
+ {
+ pucAllocatedMemory = NULL;
+ }
+
+ if( pucAllocatedMemory != NULL )
+ {
+ prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pucAllocatedMemory, /* Structure at the start of the allocated memory. */ /*lint !e9087 Safe cast as allocated memory is aligned. */ /*lint !e826 Area is not too small and alignment is guaranteed provided malloc() behaves as expected and returns aligned buffer. */
+ pucAllocatedMemory + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */
+ xBufferSizeBytes,
+ xTriggerLevelBytes,
+ ucFlags,
+ pxSendCompletedCallback,
+ pxReceiveCompletedCallback );
+
+ traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pucAllocatedMemory ), xIsMessageBuffer );
+ }
+ else
+ {
+ traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer );
+ }
+
+ return ( StreamBufferHandle_t ) pucAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */
+ }
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+ StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
+ size_t xTriggerLevelBytes,
+ BaseType_t xIsMessageBuffer,
+ uint8_t * const pucStreamBufferStorageArea,
+ StaticStreamBuffer_t * const pxStaticStreamBuffer,
+ StreamBufferCallbackFunction_t pxSendCompletedCallback,
+ StreamBufferCallbackFunction_t pxReceiveCompletedCallback )
+ {
+ StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer; /*lint !e740 !e9087 Safe cast as StaticStreamBuffer_t is opaque Streambuffer_t. */
+ StreamBufferHandle_t xReturn;
+ uint8_t ucFlags;
+
+ configASSERT( pucStreamBufferStorageArea );
+ configASSERT( pxStaticStreamBuffer );
+ configASSERT( xTriggerLevelBytes <= xBufferSizeBytes );
+
+ /* A trigger level of 0 would cause a waiting task to unblock even when
+ * the buffer was empty. */
+ if( xTriggerLevelBytes == ( size_t ) 0 )
+ {
+ xTriggerLevelBytes = ( size_t ) 1;
+ }
+
+ if( xIsMessageBuffer != pdFALSE )
+ {
+ /* Statically allocated message buffer. */
+ ucFlags = sbFLAGS_IS_MESSAGE_BUFFER | sbFLAGS_IS_STATICALLY_ALLOCATED;
+ }
+ else
+ {
+ /* Statically allocated stream buffer. */
+ ucFlags = sbFLAGS_IS_STATICALLY_ALLOCATED;
+ }
+
+ /* In case the stream buffer is going to be used as a message buffer
+ * (that is, it will hold discrete messages with a little meta data that
+ * says how big the next message is) check the buffer will be large enough
+ * to hold at least one message. */
+ configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH );
+
+ #if ( configASSERT_DEFINED == 1 )
+ {
+ /* Sanity check that the size of the structure used to declare a
+ * variable of type StaticStreamBuffer_t equals the size of the real
+ * message buffer structure. */
+ volatile size_t xSize = sizeof( StaticStreamBuffer_t );
+ configASSERT( xSize == sizeof( StreamBuffer_t ) );
+ } /*lint !e529 xSize is referenced is configASSERT() is defined. */
+ #endif /* configASSERT_DEFINED */
+
+ if( ( pucStreamBufferStorageArea != NULL ) && ( pxStaticStreamBuffer != NULL ) )
+ {
+ prvInitialiseNewStreamBuffer( pxStreamBuffer,
+ pucStreamBufferStorageArea,
+ xBufferSizeBytes,
+ xTriggerLevelBytes,
+ ucFlags,
+ pxSendCompletedCallback,
+ pxReceiveCompletedCallback );
+
+ /* Remember this was statically allocated in case it is ever deleted
+ * again. */
+ pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED;
+
+ traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer );
+
+ xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer; /*lint !e9087 Data hiding requires cast to opaque type. */
+ }
+ else
+ {
+ xReturn = NULL;
+ traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer );
+ }
+
+ return xReturn;
+ }
+#endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
+/*-----------------------------------------------------------*/
+
+void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer )
+{
+ StreamBuffer_t * pxStreamBuffer = xStreamBuffer;
+
+ configASSERT( pxStreamBuffer );
+
+ traceSTREAM_BUFFER_DELETE( xStreamBuffer );
+
+ if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE )
+ {
+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ {
+ /* Both the structure and the buffer were allocated using a single call
+ * to pvPortMalloc(), hence only one call to vPortFree() is required. */
+ vPortFree( ( void * ) pxStreamBuffer ); /*lint !e9087 Standard free() semantics require void *, plus pxStreamBuffer was allocated by pvPortMalloc(). */
+ }
+ #else
+ {
+ /* Should not be possible to get here, ucFlags must be corrupt.
+ * Force an assert. */
+ configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 );
+ }
+ #endif
+ }
+ else
+ {
+ /* The structure and buffer were not allocated dynamically and cannot be
+ * freed - just scrub the structure so future use will assert. */
+ ( void ) memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) );
+ }
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer )
+{
+ StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ BaseType_t xReturn = pdFAIL;
+ StreamBufferCallbackFunction_t pxSendCallback = NULL, pxReceiveCallback = NULL;
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxStreamBufferNumber;
+ #endif
+
+ configASSERT( pxStreamBuffer );
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ /* Store the stream buffer number so it can be restored after the
+ * reset. */
+ uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber;
+ }
+ #endif
+
+ /* Can only reset a message buffer if there are no tasks blocked on it. */
+ taskENTER_CRITICAL();
+ {
+ if( ( pxStreamBuffer->xTaskWaitingToReceive == NULL ) && ( pxStreamBuffer->xTaskWaitingToSend == NULL ) )
+ {
+ #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ {
+ pxSendCallback = pxStreamBuffer->pxSendCompletedCallback;
+ pxReceiveCallback = pxStreamBuffer->pxReceiveCompletedCallback;
+ }
+ #endif
+
+ prvInitialiseNewStreamBuffer( pxStreamBuffer,
+ pxStreamBuffer->pucBuffer,
+ pxStreamBuffer->xLength,
+ pxStreamBuffer->xTriggerLevelBytes,
+ pxStreamBuffer->ucFlags,
+ pxSendCallback,
+ pxReceiveCallback );
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
+ }
+ #endif
+
+ traceSTREAM_BUFFER_RESET( xStreamBuffer );
+
+ xReturn = pdPASS;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer,
+ size_t xTriggerLevel )
+{
+ StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ BaseType_t xReturn;
+
+ configASSERT( pxStreamBuffer );
+
+ /* It is not valid for the trigger level to be 0. */
+ if( xTriggerLevel == ( size_t ) 0 )
+ {
+ xTriggerLevel = ( size_t ) 1;
+ }
+
+ /* The trigger level is the number of bytes that must be in the stream
+ * buffer before a task that is waiting for data is unblocked. */
+ if( xTriggerLevel < pxStreamBuffer->xLength )
+ {
+ pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel;
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer )
+{
+ const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ size_t xSpace;
+ size_t xOriginalTail;
+
+ configASSERT( pxStreamBuffer );
+
+ /* The code below reads xTail and then xHead. This is safe if the stream
+ * buffer is updated once between the two reads - but not if the stream buffer
+ * is updated more than once between the two reads - hence the loop. */
+ do
+ {
+ xOriginalTail = pxStreamBuffer->xTail;
+ xSpace = pxStreamBuffer->xLength + pxStreamBuffer->xTail;
+ xSpace -= pxStreamBuffer->xHead;
+ } while( xOriginalTail != pxStreamBuffer->xTail );
+
+ xSpace -= ( size_t ) 1;
+
+ if( xSpace >= pxStreamBuffer->xLength )
+ {
+ xSpace -= pxStreamBuffer->xLength;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xSpace;
+}
+/*-----------------------------------------------------------*/
+
+size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer )
+{
+ const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ size_t xReturn;
+
+ configASSERT( pxStreamBuffer );
+
+ xReturn = prvBytesInBuffer( pxStreamBuffer );
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
+ const void * pvTxData,
+ size_t xDataLengthBytes,
+ TickType_t xTicksToWait )
+{
+ StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ size_t xReturn, xSpace = 0;
+ size_t xRequiredSpace = xDataLengthBytes;
+ TimeOut_t xTimeOut;
+ size_t xMaxReportedSpace = 0;
+
+ configASSERT( pvTxData );
+ configASSERT( pxStreamBuffer );
+
+ /* The maximum amount of space a stream buffer will ever report is its length
+ * minus 1. */
+ xMaxReportedSpace = pxStreamBuffer->xLength - ( size_t ) 1;
+
+ /* This send function is used to write to both message buffers and stream
+ * buffers. If this is a message buffer then the space needed must be
+ * increased by the amount of bytes needed to store the length of the
+ * message. */
+ if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
+ {
+ xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
+
+ /* Overflow? */
+ configASSERT( xRequiredSpace > xDataLengthBytes );
+
+ /* If this is a message buffer then it must be possible to write the
+ * whole message. */
+ if( xRequiredSpace > xMaxReportedSpace )
+ {
+ /* The message would not fit even if the entire buffer was empty,
+ * so don't wait for space. */
+ xTicksToWait = ( TickType_t ) 0;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* If this is a stream buffer then it is acceptable to write only part
+ * of the message to the buffer. Cap the length to the total length of
+ * the buffer. */
+ if( xRequiredSpace > xMaxReportedSpace )
+ {
+ xRequiredSpace = xMaxReportedSpace;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ if( xTicksToWait != ( TickType_t ) 0 )
+ {
+ vTaskSetTimeOutState( &xTimeOut );
+
+ do
+ {
+ /* Wait until the required number of bytes are free in the message
+ * buffer. */
+ taskENTER_CRITICAL();
+ {
+ xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
+
+ if( xSpace < xRequiredSpace )
+ {
+ /* Clear notification state as going to wait for space. */
+ ( void ) xTaskNotifyStateClear( NULL );
+
+ /* Should only be one writer. */
+ configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL );
+ pxStreamBuffer->xTaskWaitingToSend = xTaskGetCurrentTaskHandle();
+ }
+ else
+ {
+ taskEXIT_CRITICAL();
+ break;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer );
+ ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
+ pxStreamBuffer->xTaskWaitingToSend = NULL;
+ } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ if( xSpace == ( size_t ) 0 )
+ {
+ xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
+
+ if( xReturn > ( size_t ) 0 )
+ {
+ traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn );
+
+ /* Was a task waiting for the data? */
+ if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
+ {
+ prvSEND_COMPLETED( pxStreamBuffer );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer );
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
+ const void * pvTxData,
+ size_t xDataLengthBytes,
+ BaseType_t * const pxHigherPriorityTaskWoken )
+{
+ StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ size_t xReturn, xSpace;
+ size_t xRequiredSpace = xDataLengthBytes;
+
+ configASSERT( pvTxData );
+ configASSERT( pxStreamBuffer );
+
+ /* This send function is used to write to both message buffers and stream
+ * buffers. If this is a message buffer then the space needed must be
+ * increased by the amount of bytes needed to store the length of the
+ * message. */
+ if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
+ {
+ xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer );
+ xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace );
+
+ if( xReturn > ( size_t ) 0 )
+ {
+ /* Was a task waiting for the data? */
+ if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes )
+ {
+ prvSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
+ const void * pvTxData,
+ size_t xDataLengthBytes,
+ size_t xSpace,
+ size_t xRequiredSpace )
+{
+ size_t xNextHead = pxStreamBuffer->xHead;
+ configMESSAGE_BUFFER_LENGTH_TYPE xMessageLength;
+
+ if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
+ {
+ /* This is a message buffer, as opposed to a stream buffer. */
+
+ /* Convert xDataLengthBytes to the message length type. */
+ xMessageLength = ( configMESSAGE_BUFFER_LENGTH_TYPE ) xDataLengthBytes;
+
+ /* Ensure the data length given fits within configMESSAGE_BUFFER_LENGTH_TYPE. */
+ configASSERT( ( size_t ) xMessageLength == xDataLengthBytes );
+
+ if( xSpace >= xRequiredSpace )
+ {
+ /* There is enough space to write both the message length and the message
+ * itself into the buffer. Start by writing the length of the data, the data
+ * itself will be written later in this function. */
+ xNextHead = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xMessageLength ), sbBYTES_TO_STORE_MESSAGE_LENGTH, xNextHead );
+ }
+ else
+ {
+ /* Not enough space, so do not write data to the buffer. */
+ xDataLengthBytes = 0;
+ }
+ }
+ else
+ {
+ /* This is a stream buffer, as opposed to a message buffer, so writing a
+ * stream of bytes rather than discrete messages. Plan to write as many
+ * bytes as possible. */
+ xDataLengthBytes = configMIN( xDataLengthBytes, xSpace );
+ }
+
+ if( xDataLengthBytes != ( size_t ) 0 )
+ {
+ /* Write the data to the buffer. */
+ pxStreamBuffer->xHead = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes, xNextHead ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alignment and access. */
+ }
+
+ return xDataLengthBytes;
+}
+/*-----------------------------------------------------------*/
+
+size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
+ void * pvRxData,
+ size_t xBufferLengthBytes,
+ TickType_t xTicksToWait )
+{
+ StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
+
+ configASSERT( pvRxData );
+ configASSERT( pxStreamBuffer );
+
+ /* This receive function is used by both message buffers, which store
+ * discrete messages, and stream buffers, which store a continuous stream of
+ * bytes. Discrete messages include an additional
+ * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
+ * message. */
+ if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
+ {
+ xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
+ }
+ else
+ {
+ xBytesToStoreMessageLength = 0;
+ }
+
+ if( xTicksToWait != ( TickType_t ) 0 )
+ {
+ /* Checking if there is data and clearing the notification state must be
+ * performed atomically. */
+ taskENTER_CRITICAL();
+ {
+ xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
+
+ /* If this function was invoked by a message buffer read then
+ * xBytesToStoreMessageLength holds the number of bytes used to hold
+ * the length of the next discrete message. If this function was
+ * invoked by a stream buffer read then xBytesToStoreMessageLength will
+ * be 0. */
+ if( xBytesAvailable <= xBytesToStoreMessageLength )
+ {
+ /* Clear notification state as going to wait for data. */
+ ( void ) xTaskNotifyStateClear( NULL );
+
+ /* Should only be one reader. */
+ configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL );
+ pxStreamBuffer->xTaskWaitingToReceive = xTaskGetCurrentTaskHandle();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ if( xBytesAvailable <= xBytesToStoreMessageLength )
+ {
+ /* Wait for data to be available. */
+ traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer );
+ ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
+ pxStreamBuffer->xTaskWaitingToReceive = NULL;
+
+ /* Recheck the data available after blocking. */
+ xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
+ }
+
+ /* Whether receiving a discrete message (where xBytesToStoreMessageLength
+ * holds the number of bytes used to store the message length) or a stream of
+ * bytes (where xBytesToStoreMessageLength is zero), the number of bytes
+ * available must be greater than xBytesToStoreMessageLength to be able to
+ * read bytes from the buffer. */
+ if( xBytesAvailable > xBytesToStoreMessageLength )
+ {
+ xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable );
+
+ /* Was a task waiting for space in the buffer? */
+ if( xReceivedLength != ( size_t ) 0 )
+ {
+ traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength );
+ prvRECEIVE_COMPLETED( xStreamBuffer );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer );
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xReceivedLength;
+}
+/*-----------------------------------------------------------*/
+
+size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer )
+{
+ StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ size_t xReturn, xBytesAvailable;
+ configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
+
+ configASSERT( pxStreamBuffer );
+
+ /* Ensure the stream buffer is being used as a message buffer. */
+ if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
+ {
+ xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
+
+ if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH )
+ {
+ /* The number of bytes available is greater than the number of bytes
+ * required to hold the length of the next message, so another message
+ * is available. */
+ ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, pxStreamBuffer->xTail );
+ xReturn = ( size_t ) xTempReturn;
+ }
+ else
+ {
+ /* The minimum amount of bytes in a message buffer is
+ * ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is
+ * less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid
+ * value is 0. */
+ configASSERT( xBytesAvailable == 0 );
+ xReturn = 0;
+ }
+ }
+ else
+ {
+ xReturn = 0;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
+ void * pvRxData,
+ size_t xBufferLengthBytes,
+ BaseType_t * const pxHigherPriorityTaskWoken )
+{
+ StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
+
+ configASSERT( pvRxData );
+ configASSERT( pxStreamBuffer );
+
+ /* This receive function is used by both message buffers, which store
+ * discrete messages, and stream buffers, which store a continuous stream of
+ * bytes. Discrete messages include an additional
+ * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the
+ * message. */
+ if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
+ {
+ xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
+ }
+ else
+ {
+ xBytesToStoreMessageLength = 0;
+ }
+
+ xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
+
+ /* Whether receiving a discrete message (where xBytesToStoreMessageLength
+ * holds the number of bytes used to store the message length) or a stream of
+ * bytes (where xBytesToStoreMessageLength is zero), the number of bytes
+ * available must be greater than xBytesToStoreMessageLength to be able to
+ * read bytes from the buffer. */
+ if( xBytesAvailable > xBytesToStoreMessageLength )
+ {
+ xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable );
+
+ /* Was a task waiting for space in the buffer? */
+ if( xReceivedLength != ( size_t ) 0 )
+ {
+ prvRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength );
+
+ return xReceivedLength;
+}
+/*-----------------------------------------------------------*/
+
+static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer,
+ void * pvRxData,
+ size_t xBufferLengthBytes,
+ size_t xBytesAvailable )
+{
+ size_t xCount, xNextMessageLength;
+ configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
+ size_t xNextTail = pxStreamBuffer->xTail;
+
+ if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
+ {
+ /* A discrete message is being received. First receive the length
+ * of the message. */
+ xNextTail = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, sbBYTES_TO_STORE_MESSAGE_LENGTH, xNextTail );
+ xNextMessageLength = ( size_t ) xTempNextMessageLength;
+
+ /* Reduce the number of bytes available by the number of bytes just
+ * read out. */
+ xBytesAvailable -= sbBYTES_TO_STORE_MESSAGE_LENGTH;
+
+ /* Check there is enough space in the buffer provided by the
+ * user. */
+ if( xNextMessageLength > xBufferLengthBytes )
+ {
+ /* The user has provided insufficient space to read the message. */
+ xNextMessageLength = 0;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* A stream of bytes is being received (as opposed to a discrete
+ * message), so read as many bytes as possible. */
+ xNextMessageLength = xBufferLengthBytes;
+ }
+
+ /* Use the minimum of the wanted bytes and the available bytes. */
+ xCount = configMIN( xNextMessageLength, xBytesAvailable );
+
+ if( xCount != ( size_t ) 0 )
+ {
+ /* Read the actual data and update the tail to mark the data as officially consumed. */
+ pxStreamBuffer->xTail = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) pvRxData, xCount, xNextTail ); /*lint !e9079 Data storage area is implemented as uint8_t array for ease of sizing, indexing and alignment. */
+ }
+
+ return xCount;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer )
+{
+ const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ BaseType_t xReturn;
+ size_t xTail;
+
+ configASSERT( pxStreamBuffer );
+
+ /* True if no bytes are available. */
+ xTail = pxStreamBuffer->xTail;
+
+ if( pxStreamBuffer->xHead == xTail )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer )
+{
+ BaseType_t xReturn;
+ size_t xBytesToStoreMessageLength;
+ const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+
+ configASSERT( pxStreamBuffer );
+
+ /* This generic version of the receive function is used by both message
+ * buffers, which store discrete messages, and stream buffers, which store a
+ * continuous stream of bytes. Discrete messages include an additional
+ * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */
+ if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
+ {
+ xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH;
+ }
+ else
+ {
+ xBytesToStoreMessageLength = 0;
+ }
+
+ /* True if the available space equals zero. */
+ if( xStreamBufferSpacesAvailable( xStreamBuffer ) <= xBytesToStoreMessageLength )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
+ BaseType_t * pxHigherPriorityTaskWoken )
+{
+ StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ BaseType_t xReturn;
+ UBaseType_t uxSavedInterruptStatus;
+
+ configASSERT( pxStreamBuffer );
+
+ uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL )
+ {
+ ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive,
+ ( uint32_t ) 0,
+ eNoAction,
+ pxHigherPriorityTaskWoken );
+ ( pxStreamBuffer )->xTaskWaitingToReceive = NULL;
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
+ BaseType_t * pxHigherPriorityTaskWoken )
+{
+ StreamBuffer_t * const pxStreamBuffer = xStreamBuffer;
+ BaseType_t xReturn;
+ UBaseType_t uxSavedInterruptStatus;
+
+ configASSERT( pxStreamBuffer );
+
+ uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL )
+ {
+ ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend,
+ ( uint32_t ) 0,
+ eNoAction,
+ pxHigherPriorityTaskWoken );
+ ( pxStreamBuffer )->xTaskWaitingToSend = NULL;
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer,
+ const uint8_t * pucData,
+ size_t xCount,
+ size_t xHead )
+{
+ size_t xFirstLength;
+
+ configASSERT( xCount > ( size_t ) 0 );
+
+ /* Calculate the number of bytes that can be added in the first write -
+ * which may be less than the total number of bytes that need to be added if
+ * the buffer will wrap back to the beginning. */
+ xFirstLength = configMIN( pxStreamBuffer->xLength - xHead, xCount );
+
+ /* Write as many bytes as can be written in the first write. */
+ configASSERT( ( xHead + xFirstLength ) <= pxStreamBuffer->xLength );
+ ( void ) memcpy( ( void * ) ( &( pxStreamBuffer->pucBuffer[ xHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */
+
+ /* If the number of bytes written was less than the number that could be
+ * written in the first write... */
+ if( xCount > xFirstLength )
+ {
+ /* ...then write the remaining bytes to the start of the buffer. */
+ configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength );
+ ( void ) memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ xHead += xCount;
+
+ if( xHead >= pxStreamBuffer->xLength )
+ {
+ xHead -= pxStreamBuffer->xLength;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xHead;
+}
+/*-----------------------------------------------------------*/
+
+static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer,
+ uint8_t * pucData,
+ size_t xCount,
+ size_t xTail )
+{
+ size_t xFirstLength;
+
+ configASSERT( xCount != ( size_t ) 0 );
+
+ /* Calculate the number of bytes that can be read - which may be
+ * less than the number wanted if the data wraps around to the start of
+ * the buffer. */
+ xFirstLength = configMIN( pxStreamBuffer->xLength - xTail, xCount );
+
+ /* Obtain the number of bytes it is possible to obtain in the first
+ * read. Asserts check bounds of read and write. */
+ configASSERT( xFirstLength <= xCount );
+ configASSERT( ( xTail + xFirstLength ) <= pxStreamBuffer->xLength );
+ ( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */
+
+ /* If the total number of wanted bytes is greater than the number
+ * that could be read in the first read... */
+ if( xCount > xFirstLength )
+ {
+ /* ...then read the remaining bytes from the start of the buffer. */
+ ( void ) memcpy( ( void * ) &( pucData[ xFirstLength ] ), ( void * ) ( pxStreamBuffer->pucBuffer ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Move the tail pointer to effectively remove the data read from the buffer. */
+ xTail += xCount;
+
+ if( xTail >= pxStreamBuffer->xLength )
+ {
+ xTail -= pxStreamBuffer->xLength;
+ }
+
+ return xTail;
+}
+/*-----------------------------------------------------------*/
+
+static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer )
+{
+/* Returns the distance between xTail and xHead. */
+ size_t xCount;
+
+ xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead;
+ xCount -= pxStreamBuffer->xTail;
+
+ if( xCount >= pxStreamBuffer->xLength )
+ {
+ xCount -= pxStreamBuffer->xLength;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xCount;
+}
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
+ uint8_t * const pucBuffer,
+ size_t xBufferSizeBytes,
+ size_t xTriggerLevelBytes,
+ uint8_t ucFlags,
+ StreamBufferCallbackFunction_t pxSendCompletedCallback,
+ StreamBufferCallbackFunction_t pxReceiveCompletedCallback )
+{
+ /* Assert here is deliberately writing to the entire buffer to ensure it can
+ * be written to without generating exceptions, and is setting the buffer to a
+ * known value to assist in development/debugging. */
+ #if ( configASSERT_DEFINED == 1 )
+ {
+ /* The value written just has to be identifiable when looking at the
+ * memory. Don't use 0xA5 as that is the stack fill value and could
+ * result in confusion as to what is actually being observed. */
+ const BaseType_t xWriteValue = 0x55;
+ configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer );
+ } /*lint !e529 !e438 xWriteValue is only used if configASSERT() is defined. */
+ #endif
+
+ ( void ) memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); /*lint !e9087 memset() requires void *. */
+ pxStreamBuffer->pucBuffer = pucBuffer;
+ pxStreamBuffer->xLength = xBufferSizeBytes;
+ pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes;
+ pxStreamBuffer->ucFlags = ucFlags;
+ #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
+ {
+ pxStreamBuffer->pxSendCompletedCallback = pxSendCompletedCallback;
+ pxStreamBuffer->pxReceiveCompletedCallback = pxReceiveCompletedCallback;
+ }
+ #else
+ {
+ ( void ) pxSendCompletedCallback;
+ ( void ) pxReceiveCompletedCallback;
+ }
+ #endif
+}
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer )
+ {
+ return xStreamBuffer->uxStreamBufferNumber;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer,
+ UBaseType_t uxStreamBufferNumber )
+ {
+ xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer )
+ {
+ return( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER );
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
diff --git a/source/test/freertos/src/tasks.c b/source/test/freertos/src/tasks.c
new file mode 100644
index 0000000..0cc948f
--- /dev/null
+++ b/source/test/freertos/src/tasks.c
@@ -0,0 +1,5429 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/* Standard includes. */
+#include
+#include
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+ * all the API functions to use the MPU wrappers. That should only be done when
+ * task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "timers.h"
+#include "stack_macros.h"
+
+/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
+ * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
+ * for the header files above, but not in this file, in order to generate the
+ * correct privileged Vs unprivileged linkage and placement. */
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
+
+/* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
+ * functions but without including stdio.h here. */
+#if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
+
+/* At the bottom of this file are two optional functions that can be used
+ * to generate human readable text from the raw data generated by the
+ * uxTaskGetSystemState() function. Note the formatting functions are provided
+ * for convenience only, and are NOT considered part of the kernel. */
+ #include
+#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
+
+#if ( configUSE_PREEMPTION == 0 )
+
+/* If the cooperative scheduler is being used then a yield should not be
+ * performed just because a higher priority task has been woken. */
+ #define taskYIELD_IF_USING_PREEMPTION()
+#else
+ #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
+#endif
+
+/* Values that can be assigned to the ucNotifyState member of the TCB. */
+#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */
+#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
+#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )
+
+/*
+ * The value used to fill the stack of a task when the task is created. This
+ * is used purely for checking the high water mark for tasks.
+ */
+#define tskSTACK_FILL_BYTE ( 0xa5U )
+
+/* Bits used to record how a task's stack and TCB were allocated. */
+#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
+#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
+#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
+
+/* If any of the following are set then task stacks are filled with a known
+ * value so the high water mark can be determined. If none of the following are
+ * set then don't fill the stack so there is no unnecessary dependency on memset. */
+#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
+ #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1
+#else
+ #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0
+#endif
+
+/*
+ * Macros used by vListTask to indicate which state a task is in.
+ */
+#define tskRUNNING_CHAR ( 'X' )
+#define tskBLOCKED_CHAR ( 'B' )
+#define tskREADY_CHAR ( 'R' )
+#define tskDELETED_CHAR ( 'D' )
+#define tskSUSPENDED_CHAR ( 'S' )
+
+/*
+ * Some kernel aware debuggers require the data the debugger needs access to to
+ * be global, rather than file scope.
+ */
+#ifdef portREMOVE_STATIC_QUALIFIER
+ #define static
+#endif
+
+/* The name allocated to the Idle task. This can be overridden by defining
+ * configIDLE_TASK_NAME in FreeRTOSConfig.h. */
+#ifndef configIDLE_TASK_NAME
+ #define configIDLE_TASK_NAME "IDLE"
+#endif
+
+#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
+
+/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
+ * performed in a generic way that is not optimised to any particular
+ * microcontroller architecture. */
+
+/* uxTopReadyPriority holds the priority of the highest priority ready
+ * state task. */
+ #define taskRECORD_READY_PRIORITY( uxPriority ) \
+ { \
+ if( ( uxPriority ) > uxTopReadyPriority ) \
+ { \
+ uxTopReadyPriority = ( uxPriority ); \
+ } \
+ } /* taskRECORD_READY_PRIORITY */
+
+/*-----------------------------------------------------------*/
+
+ #define taskSELECT_HIGHEST_PRIORITY_TASK() \
+ { \
+ UBaseType_t uxTopPriority = uxTopReadyPriority; \
+ \
+ /* Find the highest priority queue that contains ready tasks. */ \
+ while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
+ { \
+ configASSERT( uxTopPriority ); \
+ --uxTopPriority; \
+ } \
+ \
+ /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
+ * the same priority get an equal share of the processor time. */ \
+ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
+ uxTopReadyPriority = uxTopPriority; \
+ } /* taskSELECT_HIGHEST_PRIORITY_TASK */
+
+/*-----------------------------------------------------------*/
+
+/* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
+ * they are only required when a port optimised method of task selection is
+ * being used. */
+ #define taskRESET_READY_PRIORITY( uxPriority )
+ #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
+
+#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
+
+/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
+ * performed in a way that is tailored to the particular microcontroller
+ * architecture being used. */
+
+/* A port optimised version is provided. Call the port defined macros. */
+ #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( ( uxPriority ), uxTopReadyPriority )
+
+/*-----------------------------------------------------------*/
+
+ #define taskSELECT_HIGHEST_PRIORITY_TASK() \
+ { \
+ UBaseType_t uxTopPriority; \
+ \
+ /* Find the highest priority list that contains ready tasks. */ \
+ portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
+ configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
+ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
+ } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
+
+/*-----------------------------------------------------------*/
+
+/* A port optimised version is provided, call it only if the TCB being reset
+ * is being referenced from a ready list. If it is referenced from a delayed
+ * or suspended list then it won't be in a ready list. */
+ #define taskRESET_READY_PRIORITY( uxPriority ) \
+ { \
+ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
+ { \
+ portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
+ } \
+ }
+
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
+
+/*-----------------------------------------------------------*/
+
+/* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
+ * count overflows. */
+#define taskSWITCH_DELAYED_LISTS() \
+ { \
+ List_t * pxTemp; \
+ \
+ /* The delayed tasks list should be empty when the lists are switched. */ \
+ configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
+ \
+ pxTemp = pxDelayedTaskList; \
+ pxDelayedTaskList = pxOverflowDelayedTaskList; \
+ pxOverflowDelayedTaskList = pxTemp; \
+ xNumOfOverflows++; \
+ prvResetNextTaskUnblockTime(); \
+ }
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Place the task represented by pxTCB into the appropriate ready list for
+ * the task. It is inserted at the end of the list.
+ */
+#define prvAddTaskToReadyList( pxTCB ) \
+ traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
+ taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
+ listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
+ tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
+/*-----------------------------------------------------------*/
+
+/*
+ * Several functions take a TaskHandle_t parameter that can optionally be NULL,
+ * where NULL is used to indicate that the handle of the currently executing
+ * task should be used in place of the parameter. This macro simply checks to
+ * see if the parameter is NULL and returns a pointer to the appropriate TCB.
+ */
+#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )
+
+/* The item value of the event list item is normally used to hold the priority
+ * of the task to which it belongs (coded to allow it to be held in reverse
+ * priority order). However, it is occasionally borrowed for other purposes. It
+ * is important its value is not updated due to a task priority change while it is
+ * being used for another purpose. The following bit definition is used to inform
+ * the scheduler that the value should not be changed - in which case it is the
+ * responsibility of whichever module is using the value to ensure it gets set back
+ * to its original value when it is released. */
+#if ( configUSE_16_BIT_TICKS == 1 )
+ #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
+#else
+ #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
+#endif
+
+/*
+ * Task control block. A task control block (TCB) is allocated for each task,
+ * and stores task state information, including a pointer to the task's context
+ * (the task's run time environment, including register values)
+ */
+typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */
+{
+ volatile StackType_t * pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
+
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
+ #endif
+
+ ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
+ ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
+ UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
+ StackType_t * pxStack; /*< Points to the start of the stack. */
+ char pcTaskName[ configMAX_TASK_NAME_LEN ]; /*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+ #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
+ StackType_t * pxEndOfStack; /*< Points to the highest valid address for the stack. */
+ #endif
+
+ #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+ UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
+ #endif
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
+ UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
+ #endif
+
+ #if ( configUSE_MUTEXES == 1 )
+ UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
+ UBaseType_t uxMutexesHeld;
+ #endif
+
+ #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+ TaskHookFunction_t pxTaskTag;
+ #endif
+
+ #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
+ void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
+ #endif
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
+ #endif
+
+ #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
+ configTLS_BLOCK_TYPE xTLSBlock; /*< Memory block used as Thread Local Storage (TLS) Block for the task. */
+ #endif
+
+ #if ( configUSE_TASK_NOTIFICATIONS == 1 )
+ volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
+ volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
+ #endif
+
+ /* See the comments in FreeRTOS.h with the definition of
+ * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
+ #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
+ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
+ #endif
+
+ #if ( INCLUDE_xTaskAbortDelay == 1 )
+ uint8_t ucDelayAborted;
+ #endif
+
+ #if ( configUSE_POSIX_ERRNO == 1 )
+ int iTaskErrno;
+ #endif
+} tskTCB;
+
+/* The old tskTCB name is maintained above then typedefed to the new TCB_t name
+ * below to enable the use of older kernel aware debuggers. */
+typedef tskTCB TCB_t;
+
+/*lint -save -e956 A manual analysis and inspection has been used to determine
+ * which static variables must be declared volatile. */
+portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
+
+/* Lists for ready and blocked tasks. --------------------
+ * xDelayedTaskList1 and xDelayedTaskList2 could be moved to function scope but
+ * doing so breaks some kernel aware debuggers and debuggers that rely on removing
+ * the static qualifier. */
+PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */
+PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
+PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
+PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
+PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
+PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
+
+#if ( INCLUDE_vTaskDelete == 1 )
+
+ PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
+ PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
+
+#endif
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
+
+#endif
+
+/* Global POSIX errno. Its value is changed upon context switching to match
+ * the errno of the currently running task. */
+#if ( configUSE_POSIX_ERRNO == 1 )
+ int FreeRTOS_errno = 0;
+#endif
+
+/* Other file private variables. --------------------------------*/
+PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
+PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
+PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
+PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
+PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U;
+PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
+PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
+PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
+PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
+PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
+
+/* Improve support for OpenOCD. The kernel tracks Ready tasks via priority lists.
+ * For tracking the state of remote threads, OpenOCD uses uxTopUsedPriority
+ * to determine the number of priority lists to read back from the remote target. */
+const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U;
+
+/* Context switches are held pending while the scheduler is suspended. Also,
+ * interrupts must not manipulate the xStateListItem of a TCB, or any of the
+ * lists the xStateListItem can be referenced from, if the scheduler is suspended.
+ * If an interrupt needs to unblock a task while the scheduler is suspended then it
+ * moves the task's event list item into the xPendingReadyList, ready for the
+ * kernel to move the task from the pending ready list into the real ready list
+ * when the scheduler is unsuspended. The pending ready list itself can only be
+ * accessed from a critical section. */
+PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+/* Do not move these variables to function scope as doing so prevents the
+ * code working with debuggers that need to remove the static qualifier. */
+ PRIVILEGED_DATA static configRUN_TIME_COUNTER_TYPE ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
+ PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
+
+#endif
+
+/*lint -restore */
+
+/*-----------------------------------------------------------*/
+
+/* File private functions. --------------------------------*/
+
+/**
+ * Utility task that simply returns pdTRUE if the task referenced by xTask is
+ * currently in the Suspended state, or pdFALSE if the task referenced by xTask
+ * is in any other state.
+ */
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
+#endif /* INCLUDE_vTaskSuspend */
+
+/*
+ * Utility to ready all the lists used by the scheduler. This is called
+ * automatically upon the creation of the first task.
+ */
+static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * The idle task, which as all tasks is implemented as a never ending loop.
+ * The idle task is automatically created and added to the ready lists upon
+ * creation of the first user task.
+ *
+ * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
+ * language extensions. The equivalent prototype for this function is:
+ *
+ * void prvIdleTask( void *pvParameters );
+ *
+ */
+static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION;
+
+/*
+ * Utility to free all memory allocated by the scheduler to hold a TCB,
+ * including the stack pointed to by the TCB.
+ *
+ * This does not free memory allocated by the task itself (i.e. memory
+ * allocated by calls to pvPortMalloc from within the tasks application code).
+ */
+#if ( INCLUDE_vTaskDelete == 1 )
+
+ static void prvDeleteTCB( TCB_t * pxTCB ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * Used only by the idle task. This checks to see if anything has been placed
+ * in the list of tasks waiting to be deleted. If so the task is cleaned up
+ * and its TCB deleted.
+ */
+static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * The currently executing task is entering the Blocked state. Add the task to
+ * either the current or the overflow delayed task list.
+ */
+static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
+ const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
+
+/*
+ * Fills an TaskStatus_t structure with information on each task that is
+ * referenced from the pxList list (which may be a ready list, a delayed list,
+ * a suspended list, etc.).
+ *
+ * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
+ * NORMAL APPLICATION CODE.
+ */
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
+ List_t * pxList,
+ eTaskState eState ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * Searches pxList for a task with name pcNameToQuery - returning a handle to
+ * the task if it is found, or NULL if the task is not found.
+ */
+#if ( INCLUDE_xTaskGetHandle == 1 )
+
+ static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
+ const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * When a task is created, the stack of the task is filled with a known value.
+ * This function determines the 'high water mark' of the task stack by
+ * determining how much of the stack remains at the original preset value.
+ */
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
+
+ static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * Return the amount of time, in ticks, that will pass before the kernel will
+ * next move a task from the Blocked state to the Running state.
+ *
+ * This conditional compilation should use inequality to 0, not equality to 1.
+ * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
+ * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
+ * set to a value other than 1.
+ */
+#if ( configUSE_TICKLESS_IDLE != 0 )
+
+ static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * Set xNextTaskUnblockTime to the time at which the next Blocked state task
+ * will exit the Blocked state.
+ */
+static void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION;
+
+#if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
+
+/*
+ * Helper function used to pad task names with spaces when printing out
+ * human readable tables of task information.
+ */
+ static char * prvWriteNameToBuffer( char * pcBuffer,
+ const char * pcTaskName ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * Called after a Task_t structure has been allocated either statically or
+ * dynamically to fill in the structure's members.
+ */
+static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
+ const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const uint32_t ulStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ TaskHandle_t * const pxCreatedTask,
+ TCB_t * pxNewTCB,
+ const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
+
+/*
+ * Called after a new task has been created and initialised to place the task
+ * under the control of the scheduler.
+ */
+static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
+
+/*
+ * freertos_tasks_c_additions_init() should only be called if the user definable
+ * macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro
+ * called by the function.
+ */
+#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
+
+ static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*-----------------------------------------------------------*/
+
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
+ const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const uint32_t ulStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ StackType_t * const puxStackBuffer,
+ StaticTask_t * const pxTaskBuffer )
+ {
+ TCB_t * pxNewTCB;
+ TaskHandle_t xReturn;
+
+ configASSERT( puxStackBuffer != NULL );
+ configASSERT( pxTaskBuffer != NULL );
+
+ #if ( configASSERT_DEFINED == 1 )
+ {
+ /* Sanity check that the size of the structure used to declare a
+ * variable of type StaticTask_t equals the size of the real task
+ * structure. */
+ volatile size_t xSize = sizeof( StaticTask_t );
+ configASSERT( xSize == sizeof( TCB_t ) );
+ ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
+ }
+ #endif /* configASSERT_DEFINED */
+
+ if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
+ {
+ /* The memory used for the task's TCB and stack are passed into this
+ * function - use them. */
+ pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
+ memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
+ pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
+
+ #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
+ {
+ /* Tasks can be created statically or dynamically, so note this
+ * task was created statically in case the task is later deleted. */
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
+ }
+ #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
+
+ prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
+ prvAddNewTaskToReadyList( pxNewTCB );
+ }
+ else
+ {
+ xReturn = NULL;
+ }
+
+ return xReturn;
+ }
+
+#endif /* SUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+ BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition,
+ TaskHandle_t * pxCreatedTask )
+ {
+ TCB_t * pxNewTCB;
+ BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+
+ configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
+ configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
+
+ if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )
+ {
+ /* Allocate space for the TCB. Where the memory comes from depends
+ * on the implementation of the port malloc function and whether or
+ * not static allocation is being used. */
+ pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;
+ memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
+
+ /* Store the stack location in the TCB. */
+ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
+
+ #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+ {
+ /* Tasks can be created statically or dynamically, so note this
+ * task was created statically in case the task is later deleted. */
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
+ }
+ #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
+
+ prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
+ pxTaskDefinition->pcName,
+ ( uint32_t ) pxTaskDefinition->usStackDepth,
+ pxTaskDefinition->pvParameters,
+ pxTaskDefinition->uxPriority,
+ pxCreatedTask, pxNewTCB,
+ pxTaskDefinition->xRegions );
+
+ prvAddNewTaskToReadyList( pxNewTCB );
+ xReturn = pdPASS;
+ }
+
+ return xReturn;
+ }
+
+#endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
+/*-----------------------------------------------------------*/
+
+#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+
+ BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
+ TaskHandle_t * pxCreatedTask )
+ {
+ TCB_t * pxNewTCB;
+ BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+
+ configASSERT( pxTaskDefinition->puxStackBuffer );
+
+ if( pxTaskDefinition->puxStackBuffer != NULL )
+ {
+ /* Allocate space for the TCB. Where the memory comes from depends
+ * on the implementation of the port malloc function and whether or
+ * not static allocation is being used. */
+ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
+
+ if( pxNewTCB != NULL )
+ {
+ memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
+
+ /* Store the stack location in the TCB. */
+ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
+
+ #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+ {
+ /* Tasks can be created statically or dynamically, so note
+ * this task had a statically allocated stack in case it is
+ * later deleted. The TCB was allocated dynamically. */
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
+ }
+ #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
+
+ prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
+ pxTaskDefinition->pcName,
+ ( uint32_t ) pxTaskDefinition->usStackDepth,
+ pxTaskDefinition->pvParameters,
+ pxTaskDefinition->uxPriority,
+ pxCreatedTask, pxNewTCB,
+ pxTaskDefinition->xRegions );
+
+ prvAddNewTaskToReadyList( pxNewTCB );
+ xReturn = pdPASS;
+ }
+ }
+
+ return xReturn;
+ }
+
+#endif /* portUSING_MPU_WRAPPERS */
+/*-----------------------------------------------------------*/
+
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+
+ BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
+ const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const configSTACK_DEPTH_TYPE usStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ TaskHandle_t * const pxCreatedTask )
+ {
+ TCB_t * pxNewTCB;
+ BaseType_t xReturn;
+
+ /* If the stack grows down then allocate the stack then the TCB so the stack
+ * does not grow into the TCB. Likewise if the stack grows up then allocate
+ * the TCB then the stack. */
+ #if ( portSTACK_GROWTH > 0 )
+ {
+ /* Allocate space for the TCB. Where the memory comes from depends on
+ * the implementation of the port malloc function and whether or not static
+ * allocation is being used. */
+ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
+
+ if( pxNewTCB != NULL )
+ {
+ memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
+
+ /* Allocate space for the stack used by the task being created.
+ * The base of the stack memory stored in the TCB so the task can
+ * be deleted later if required. */
+ pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ if( pxNewTCB->pxStack == NULL )
+ {
+ /* Could not allocate the stack. Delete the allocated TCB. */
+ vPortFree( pxNewTCB );
+ pxNewTCB = NULL;
+ }
+ }
+ }
+ #else /* portSTACK_GROWTH */
+ {
+ StackType_t * pxStack;
+
+ /* Allocate space for the stack used by the task being created. */
+ pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
+
+ if( pxStack != NULL )
+ {
+ /* Allocate space for the TCB. */
+ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
+
+ if( pxNewTCB != NULL )
+ {
+ memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
+
+ /* Store the stack location in the TCB. */
+ pxNewTCB->pxStack = pxStack;
+ }
+ else
+ {
+ /* The stack cannot be used as the TCB was not created. Free
+ * it again. */
+ vPortFreeStack( pxStack );
+ }
+ }
+ else
+ {
+ pxNewTCB = NULL;
+ }
+ }
+ #endif /* portSTACK_GROWTH */
+
+ if( pxNewTCB != NULL )
+ {
+ #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
+ {
+ /* Tasks can be created statically or dynamically, so note this
+ * task was created dynamically in case it is later deleted. */
+ pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
+ }
+ #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
+
+ prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
+ prvAddNewTaskToReadyList( pxNewTCB );
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+ }
+
+ return xReturn;
+ }
+
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
+ const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const uint32_t ulStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ TaskHandle_t * const pxCreatedTask,
+ TCB_t * pxNewTCB,
+ const MemoryRegion_t * const xRegions )
+{
+ StackType_t * pxTopOfStack;
+ UBaseType_t x;
+
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ /* Should the task be created in privileged mode? */
+ BaseType_t xRunPrivileged;
+
+ if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
+ {
+ xRunPrivileged = pdTRUE;
+ }
+ else
+ {
+ xRunPrivileged = pdFALSE;
+ }
+ uxPriority &= ~portPRIVILEGE_BIT;
+ #endif /* portUSING_MPU_WRAPPERS == 1 */
+
+ /* Avoid dependency on memset() if it is not required. */
+ #if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
+ {
+ /* Fill the stack with a known value to assist debugging. */
+ ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
+ }
+ #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
+
+ /* Calculate the top of stack address. This depends on whether the stack
+ * grows from high memory to low (as per the 80x86) or vice versa.
+ * portSTACK_GROWTH is used to make the result positive or negative as required
+ * by the port. */
+ #if ( portSTACK_GROWTH < 0 )
+ {
+ pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );
+ pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. Checked by assert(). */
+
+ /* Check the alignment of the calculated top of stack is correct. */
+ configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+
+ #if ( configRECORD_STACK_HIGH_ADDRESS == 1 )
+ {
+ /* Also record the stack's high address, which may assist
+ * debugging. */
+ pxNewTCB->pxEndOfStack = pxTopOfStack;
+ }
+ #endif /* configRECORD_STACK_HIGH_ADDRESS */
+ }
+ #else /* portSTACK_GROWTH */
+ {
+ pxTopOfStack = pxNewTCB->pxStack;
+
+ /* Check the alignment of the stack buffer is correct. */
+ configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+
+ /* The other extreme of the stack space is required if stack checking is
+ * performed. */
+ pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
+ }
+ #endif /* portSTACK_GROWTH */
+
+ /* Store the task name in the TCB. */
+ if( pcName != NULL )
+ {
+ for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
+ {
+ pxNewTCB->pcTaskName[ x ] = pcName[ x ];
+
+ /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
+ * configMAX_TASK_NAME_LEN characters just in case the memory after the
+ * string is not accessible (extremely unlikely). */
+ if( pcName[ x ] == ( char ) 0x00 )
+ {
+ break;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ /* Ensure the name string is terminated in the case that the string length
+ * was greater or equal to configMAX_TASK_NAME_LEN. */
+ pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* This is used as an array index so must ensure it's not too large. */
+ configASSERT( uxPriority < configMAX_PRIORITIES );
+
+ if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
+ {
+ uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ pxNewTCB->uxPriority = uxPriority;
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ pxNewTCB->uxBasePriority = uxPriority;
+ }
+ #endif /* configUSE_MUTEXES */
+
+ vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
+ vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
+
+ /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get
+ * back to the containing TCB from a generic item in a list. */
+ listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
+
+ /* Event lists are always in priority order. */
+ listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
+
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ {
+ vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
+ }
+ #else
+ {
+ /* Avoid compiler warning about unreferenced parameter. */
+ ( void ) xRegions;
+ }
+ #endif
+
+ #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
+ {
+ /* Allocate and initialize memory for the task's TLS Block. */
+ configINIT_TLS_BLOCK( pxNewTCB->xTLSBlock );
+ }
+ #endif
+
+ /* Initialize the TCB stack to look as if the task was already running,
+ * but had been interrupted by the scheduler. The return address is set
+ * to the start of the task function. Once the stack has been initialised
+ * the top of stack variable is updated. */
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ {
+ /* If the port has capability to detect stack overflow,
+ * pass the stack end address to the stack initialization
+ * function as well. */
+ #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
+ {
+ #if ( portSTACK_GROWTH < 0 )
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged );
+ }
+ #else /* portSTACK_GROWTH */
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged );
+ }
+ #endif /* portSTACK_GROWTH */
+ }
+ #else /* portHAS_STACK_OVERFLOW_CHECKING */
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
+ }
+ #endif /* portHAS_STACK_OVERFLOW_CHECKING */
+ }
+ #else /* portUSING_MPU_WRAPPERS */
+ {
+ /* If the port has capability to detect stack overflow,
+ * pass the stack end address to the stack initialization
+ * function as well. */
+ #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
+ {
+ #if ( portSTACK_GROWTH < 0 )
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters );
+ }
+ #else /* portSTACK_GROWTH */
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters );
+ }
+ #endif /* portSTACK_GROWTH */
+ }
+ #else /* portHAS_STACK_OVERFLOW_CHECKING */
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
+ }
+ #endif /* portHAS_STACK_OVERFLOW_CHECKING */
+ }
+ #endif /* portUSING_MPU_WRAPPERS */
+
+ if( pxCreatedTask != NULL )
+ {
+ /* Pass the handle out in an anonymous way. The handle can be used to
+ * change the created task's priority, delete the created task, etc.*/
+ *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
+{
+ /* Ensure interrupts don't access the task lists while the lists are being
+ * updated. */
+ taskENTER_CRITICAL();
+ {
+ uxCurrentNumberOfTasks++;
+
+ if( pxCurrentTCB == NULL )
+ {
+ /* There are no other tasks, or all the other tasks are in
+ * the suspended state - make this the current task. */
+ pxCurrentTCB = pxNewTCB;
+
+ if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
+ {
+ /* This is the first task to be created so do the preliminary
+ * initialisation required. We will not recover if this call
+ * fails, but we will report the failure. */
+ prvInitialiseTaskLists();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* If the scheduler is not already running, make this task the
+ * current task if it is the highest priority task to be created
+ * so far. */
+ if( xSchedulerRunning == pdFALSE )
+ {
+ if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
+ {
+ pxCurrentTCB = pxNewTCB;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ uxTaskNumber++;
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ /* Add a counter into the TCB for tracing only. */
+ pxNewTCB->uxTCBNumber = uxTaskNumber;
+ }
+ #endif /* configUSE_TRACE_FACILITY */
+ traceTASK_CREATE( pxNewTCB );
+
+ prvAddTaskToReadyList( pxNewTCB );
+
+ portSETUP_TCB( pxNewTCB );
+ }
+ taskEXIT_CRITICAL();
+
+ if( xSchedulerRunning != pdFALSE )
+ {
+ /* If the created task is of a higher priority than the current task
+ * then it should run now. */
+ if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
+ {
+ taskYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+}
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelete == 1 )
+
+ void vTaskDelete( TaskHandle_t xTaskToDelete )
+ {
+ TCB_t * pxTCB;
+
+ taskENTER_CRITICAL();
+ {
+ /* If null is passed in here then it is the calling task that is
+ * being deleted. */
+ pxTCB = prvGetTCBFromHandle( xTaskToDelete );
+
+ /* Remove task from the ready/delayed list. */
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
+ {
+ taskRESET_READY_PRIORITY( pxTCB->uxPriority );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Is the task waiting on an event also? */
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Increment the uxTaskNumber also so kernel aware debuggers can
+ * detect that the task lists need re-generating. This is done before
+ * portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
+ * not return. */
+ uxTaskNumber++;
+
+ if( pxTCB == pxCurrentTCB )
+ {
+ /* A task is deleting itself. This cannot complete within the
+ * task itself, as a context switch to another task is required.
+ * Place the task in the termination list. The idle task will
+ * check the termination list and free up any memory allocated by
+ * the scheduler for the TCB and stack of the deleted task. */
+ vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
+
+ /* Increment the ucTasksDeleted variable so the idle task knows
+ * there is a task that has been deleted and that it should therefore
+ * check the xTasksWaitingTermination list. */
+ ++uxDeletedTasksWaitingCleanUp;
+
+ /* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
+ * portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */
+ traceTASK_DELETE( pxTCB );
+
+ /* The pre-delete hook is primarily for the Windows simulator,
+ * in which Windows specific clean up operations are performed,
+ * after which it is not possible to yield away from this task -
+ * hence xYieldPending is used to latch that a context switch is
+ * required. */
+ portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
+ }
+ else
+ {
+ --uxCurrentNumberOfTasks;
+ traceTASK_DELETE( pxTCB );
+
+ /* Reset the next expected unblock time in case it referred to
+ * the task that has just been deleted. */
+ prvResetNextTaskUnblockTime();
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ /* If the task is not deleting itself, call prvDeleteTCB from outside of
+ * critical section. If a task deletes itself, prvDeleteTCB is called
+ * from prvCheckTasksWaitingTermination which is called from Idle task. */
+ if( pxTCB != pxCurrentTCB )
+ {
+ prvDeleteTCB( pxTCB );
+ }
+
+ /* Force a reschedule if it is the currently running task that has just
+ * been deleted. */
+ if( xSchedulerRunning != pdFALSE )
+ {
+ if( pxTCB == pxCurrentTCB )
+ {
+ configASSERT( uxSchedulerSuspended == 0 );
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+
+#endif /* INCLUDE_vTaskDelete */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskDelayUntil == 1 )
+
+ BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
+ const TickType_t xTimeIncrement )
+ {
+ TickType_t xTimeToWake;
+ BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
+
+ configASSERT( pxPreviousWakeTime );
+ configASSERT( ( xTimeIncrement > 0U ) );
+ configASSERT( uxSchedulerSuspended == 0 );
+
+ vTaskSuspendAll();
+ {
+ /* Minor optimisation. The tick count cannot change in this
+ * block. */
+ const TickType_t xConstTickCount = xTickCount;
+
+ /* Generate the tick time at which the task wants to wake. */
+ xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
+
+ if( xConstTickCount < *pxPreviousWakeTime )
+ {
+ /* The tick count has overflowed since this function was
+ * lasted called. In this case the only time we should ever
+ * actually delay is if the wake time has also overflowed,
+ * and the wake time is greater than the tick time. When this
+ * is the case it is as if neither time had overflowed. */
+ if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
+ {
+ xShouldDelay = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* The tick time has not overflowed. In this case we will
+ * delay if either the wake time has overflowed, and/or the
+ * tick time is less than the wake time. */
+ if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
+ {
+ xShouldDelay = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ /* Update the wake time ready for the next call. */
+ *pxPreviousWakeTime = xTimeToWake;
+
+ if( xShouldDelay != pdFALSE )
+ {
+ traceTASK_DELAY_UNTIL( xTimeToWake );
+
+ /* prvAddCurrentTaskToDelayedList() needs the block time, not
+ * the time to wake, so subtract the current tick count. */
+ prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ xAlreadyYielded = xTaskResumeAll();
+
+ /* Force a reschedule if xTaskResumeAll has not already done so, we may
+ * have put ourselves to sleep. */
+ if( xAlreadyYielded == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xShouldDelay;
+ }
+
+#endif /* INCLUDE_xTaskDelayUntil */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelay == 1 )
+
+ void vTaskDelay( const TickType_t xTicksToDelay )
+ {
+ BaseType_t xAlreadyYielded = pdFALSE;
+
+ /* A delay time of zero just forces a reschedule. */
+ if( xTicksToDelay > ( TickType_t ) 0U )
+ {
+ configASSERT( uxSchedulerSuspended == 0 );
+ vTaskSuspendAll();
+ {
+ traceTASK_DELAY();
+
+ /* A task that is removed from the event list while the
+ * scheduler is suspended will not get placed in the ready
+ * list or removed from the blocked list until the scheduler
+ * is resumed.
+ *
+ * This task cannot be in an event list as it is the currently
+ * executing task. */
+ prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
+ }
+ xAlreadyYielded = xTaskResumeAll();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Force a reschedule if xTaskResumeAll has not already done so, we may
+ * have put ourselves to sleep. */
+ if( xAlreadyYielded == pdFALSE )
+ {
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+#endif /* INCLUDE_vTaskDelay */
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )
+
+ eTaskState eTaskGetState( TaskHandle_t xTask )
+ {
+ eTaskState eReturn;
+ List_t const * pxStateList;
+ List_t const * pxDelayedList;
+ List_t const * pxOverflowedDelayedList;
+ const TCB_t * const pxTCB = xTask;
+
+ configASSERT( pxTCB );
+
+ if( pxTCB == pxCurrentTCB )
+ {
+ /* The task calling this function is querying its own state. */
+ eReturn = eRunning;
+ }
+ else
+ {
+ taskENTER_CRITICAL();
+ {
+ pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
+ pxDelayedList = pxDelayedTaskList;
+ pxOverflowedDelayedList = pxOverflowDelayedTaskList;
+ }
+ taskEXIT_CRITICAL();
+
+ if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) )
+ {
+ /* The task being queried is referenced from one of the Blocked
+ * lists. */
+ eReturn = eBlocked;
+ }
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ else if( pxStateList == &xSuspendedTaskList )
+ {
+ /* The task being queried is referenced from the suspended
+ * list. Is it genuinely suspended or is it blocked
+ * indefinitely? */
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
+ {
+ #if ( configUSE_TASK_NOTIFICATIONS == 1 )
+ {
+ BaseType_t x;
+
+ /* The task does not appear on the event list item of
+ * and of the RTOS objects, but could still be in the
+ * blocked state if it is waiting on its notification
+ * rather than waiting on an object. If not, is
+ * suspended. */
+ eReturn = eSuspended;
+
+ for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
+ {
+ if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
+ {
+ eReturn = eBlocked;
+ break;
+ }
+ }
+ }
+ #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
+ {
+ eReturn = eSuspended;
+ }
+ #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
+ }
+ else
+ {
+ eReturn = eBlocked;
+ }
+ }
+ #endif /* if ( INCLUDE_vTaskSuspend == 1 ) */
+
+ #if ( INCLUDE_vTaskDelete == 1 )
+ else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
+ {
+ /* The task being queried is referenced from the deleted
+ * tasks list, or it is not referenced from any lists at
+ * all. */
+ eReturn = eDeleted;
+ }
+ #endif
+
+ else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
+ {
+ /* If the task is not in any other state, it must be in the
+ * Ready (including pending ready) state. */
+ eReturn = eReady;
+ }
+ }
+
+ return eReturn;
+ } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
+
+#endif /* INCLUDE_eTaskGetState */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_uxTaskPriorityGet == 1 )
+
+ UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
+ {
+ TCB_t const * pxTCB;
+ UBaseType_t uxReturn;
+
+ taskENTER_CRITICAL();
+ {
+ /* If null is passed in here then it is the priority of the task
+ * that called uxTaskPriorityGet() that is being queried. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+ uxReturn = pxTCB->uxPriority;
+ }
+ taskEXIT_CRITICAL();
+
+ return uxReturn;
+ }
+
+#endif /* INCLUDE_uxTaskPriorityGet */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_uxTaskPriorityGet == 1 )
+
+ UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )
+ {
+ TCB_t const * pxTCB;
+ UBaseType_t uxReturn, uxSavedInterruptState;
+
+ /* RTOS ports that support interrupt nesting have the concept of a
+ * maximum system call (or maximum API call) interrupt priority.
+ * Interrupts that are above the maximum system call priority are keep
+ * permanently enabled, even when the RTOS kernel is in a critical section,
+ * but cannot make any calls to FreeRTOS API functions. If configASSERT()
+ * is defined in FreeRTOSConfig.h then
+ * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ * failure if a FreeRTOS API function is called from an interrupt that has
+ * been assigned a priority above the configured maximum system call
+ * priority. Only FreeRTOS functions that end in FromISR can be called
+ * from interrupts that have been assigned a priority at or (logically)
+ * below the maximum system call interrupt priority. FreeRTOS maintains a
+ * separate interrupt safe API to ensure interrupt entry is as fast and as
+ * simple as possible. More information (albeit Cortex-M specific) is
+ * provided on the following link:
+ * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ /* If null is passed in here then it is the priority of the calling
+ * task that is being queried. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+ uxReturn = pxTCB->uxPriority;
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );
+
+ return uxReturn;
+ }
+
+#endif /* INCLUDE_uxTaskPriorityGet */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskPrioritySet == 1 )
+
+ void vTaskPrioritySet( TaskHandle_t xTask,
+ UBaseType_t uxNewPriority )
+ {
+ TCB_t * pxTCB;
+ UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
+ BaseType_t xYieldRequired = pdFALSE;
+
+ configASSERT( uxNewPriority < configMAX_PRIORITIES );
+
+ /* Ensure the new priority is valid. */
+ if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
+ {
+ uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ taskENTER_CRITICAL();
+ {
+ /* If null is passed in here then it is the priority of the calling
+ * task that is being changed. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ uxCurrentBasePriority = pxTCB->uxBasePriority;
+ }
+ #else
+ {
+ uxCurrentBasePriority = pxTCB->uxPriority;
+ }
+ #endif
+
+ if( uxCurrentBasePriority != uxNewPriority )
+ {
+ /* The priority change may have readied a task of higher
+ * priority than the calling task. */
+ if( uxNewPriority > uxCurrentBasePriority )
+ {
+ if( pxTCB != pxCurrentTCB )
+ {
+ /* The priority of a task other than the currently
+ * running task is being raised. Is the priority being
+ * raised above that of the running task? */
+ if( uxNewPriority >= pxCurrentTCB->uxPriority )
+ {
+ xYieldRequired = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* The priority of the running task is being raised,
+ * but the running task must already be the highest
+ * priority task able to run so no yield is required. */
+ }
+ }
+ else if( pxTCB == pxCurrentTCB )
+ {
+ /* Setting the priority of the running task down means
+ * there may now be another task of higher priority that
+ * is ready to execute. */
+ xYieldRequired = pdTRUE;
+ }
+ else
+ {
+ /* Setting the priority of any other task down does not
+ * require a yield as the running task must be above the
+ * new priority of the task being modified. */
+ }
+
+ /* Remember the ready list the task might be referenced from
+ * before its uxPriority member is changed so the
+ * taskRESET_READY_PRIORITY() macro can function correctly. */
+ uxPriorityUsedOnEntry = pxTCB->uxPriority;
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ /* Only change the priority being used if the task is not
+ * currently using an inherited priority. */
+ if( pxTCB->uxBasePriority == pxTCB->uxPriority )
+ {
+ pxTCB->uxPriority = uxNewPriority;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* The base priority gets set whatever. */
+ pxTCB->uxBasePriority = uxNewPriority;
+ }
+ #else /* if ( configUSE_MUTEXES == 1 ) */
+ {
+ pxTCB->uxPriority = uxNewPriority;
+ }
+ #endif /* if ( configUSE_MUTEXES == 1 ) */
+
+ /* Only reset the event list item value if the value is not
+ * being used for anything else. */
+ if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
+ {
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* If the task is in the blocked or suspended list we need do
+ * nothing more than change its priority variable. However, if
+ * the task is in a ready list it needs to be removed and placed
+ * in the list appropriate to its new priority. */
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
+ {
+ /* The task is currently in its ready list - remove before
+ * adding it to its new ready list. As we are in a critical
+ * section we can do this even if the scheduler is suspended. */
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
+ {
+ /* It is known that the task is in its ready list so
+ * there is no need to check again and the port level
+ * reset macro can be called directly. */
+ portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ prvAddTaskToReadyList( pxTCB );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ if( xYieldRequired != pdFALSE )
+ {
+ taskYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Remove compiler warning about unused variables when the port
+ * optimised task selection is not being used. */
+ ( void ) uxPriorityUsedOnEntry;
+ }
+ }
+ taskEXIT_CRITICAL();
+ }
+
+#endif /* INCLUDE_vTaskPrioritySet */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ void vTaskSuspend( TaskHandle_t xTaskToSuspend )
+ {
+ TCB_t * pxTCB;
+
+ taskENTER_CRITICAL();
+ {
+ /* If null is passed in here then it is the running task that is
+ * being suspended. */
+ pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
+
+ traceTASK_SUSPEND( pxTCB );
+
+ /* Remove task from the ready/delayed list and place in the
+ * suspended list. */
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
+ {
+ taskRESET_READY_PRIORITY( pxTCB->uxPriority );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Is the task waiting on an event also? */
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
+
+ #if ( configUSE_TASK_NOTIFICATIONS == 1 )
+ {
+ BaseType_t x;
+
+ for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
+ {
+ if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
+ {
+ /* The task was blocked to wait for a notification, but is
+ * now suspended, so no notification was received. */
+ pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION;
+ }
+ }
+ }
+ #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
+ }
+ taskEXIT_CRITICAL();
+
+ if( xSchedulerRunning != pdFALSE )
+ {
+ /* Reset the next expected unblock time in case it referred to the
+ * task that is now in the Suspended state. */
+ taskENTER_CRITICAL();
+ {
+ prvResetNextTaskUnblockTime();
+ }
+ taskEXIT_CRITICAL();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ if( pxTCB == pxCurrentTCB )
+ {
+ if( xSchedulerRunning != pdFALSE )
+ {
+ /* The current task has just been suspended. */
+ configASSERT( uxSchedulerSuspended == 0 );
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ /* The scheduler is not running, but the task that was pointed
+ * to by pxCurrentTCB has just been suspended and pxCurrentTCB
+ * must be adjusted to point to a different task. */
+ if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */
+ {
+ /* No other tasks are ready, so set pxCurrentTCB back to
+ * NULL so when the next task is created pxCurrentTCB will
+ * be set to point to it no matter what its relative priority
+ * is. */
+ pxCurrentTCB = NULL;
+ }
+ else
+ {
+ vTaskSwitchContext();
+ }
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+#endif /* INCLUDE_vTaskSuspend */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
+ {
+ BaseType_t xReturn = pdFALSE;
+ const TCB_t * const pxTCB = xTask;
+
+ /* Accesses xPendingReadyList so must be called from a critical
+ * section. */
+
+ /* It does not make sense to check if the calling task is suspended. */
+ configASSERT( xTask );
+
+ /* Is the task being resumed actually in the suspended list? */
+ if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
+ {
+ /* Has the task already been resumed from within an ISR? */
+ if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
+ {
+ /* Is it in the suspended list because it is in the Suspended
+ * state, or because is is blocked with no timeout? */
+ if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961. The cast is only redundant when NULL is used. */
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xReturn;
+ } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
+
+#endif /* INCLUDE_vTaskSuspend */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+ void vTaskResume( TaskHandle_t xTaskToResume )
+ {
+ TCB_t * const pxTCB = xTaskToResume;
+
+ /* It does not make sense to resume the calling task. */
+ configASSERT( xTaskToResume );
+
+ /* The parameter cannot be NULL as it is impossible to resume the
+ * currently executing task. */
+ if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )
+ {
+ taskENTER_CRITICAL();
+ {
+ if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
+ {
+ traceTASK_RESUME( pxTCB );
+
+ /* The ready list can be accessed even if the scheduler is
+ * suspended because this is inside a critical section. */
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
+ prvAddTaskToReadyList( pxTCB );
+
+ /* A higher priority task may have just been resumed. */
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
+ {
+ /* This yield may not cause the task just resumed to run,
+ * but will leave the lists in the correct state for the
+ * next yield. */
+ taskYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ taskEXIT_CRITICAL();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+#endif /* INCLUDE_vTaskSuspend */
+
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
+
+ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
+ {
+ BaseType_t xYieldRequired = pdFALSE;
+ TCB_t * const pxTCB = xTaskToResume;
+ UBaseType_t uxSavedInterruptStatus;
+
+ configASSERT( xTaskToResume );
+
+ /* RTOS ports that support interrupt nesting have the concept of a
+ * maximum system call (or maximum API call) interrupt priority.
+ * Interrupts that are above the maximum system call priority are keep
+ * permanently enabled, even when the RTOS kernel is in a critical section,
+ * but cannot make any calls to FreeRTOS API functions. If configASSERT()
+ * is defined in FreeRTOSConfig.h then
+ * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ * failure if a FreeRTOS API function is called from an interrupt that has
+ * been assigned a priority above the configured maximum system call
+ * priority. Only FreeRTOS functions that end in FromISR can be called
+ * from interrupts that have been assigned a priority at or (logically)
+ * below the maximum system call interrupt priority. FreeRTOS maintains a
+ * separate interrupt safe API to ensure interrupt entry is as fast and as
+ * simple as possible. More information (albeit Cortex-M specific) is
+ * provided on the following link:
+ * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
+ {
+ traceTASK_RESUME_FROM_ISR( pxTCB );
+
+ /* Check the ready lists can be accessed. */
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
+ {
+ /* Ready lists can be accessed so move the task from the
+ * suspended list to the ready list directly. */
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
+ {
+ xYieldRequired = pdTRUE;
+
+ /* Mark that a yield is pending in case the user is not
+ * using the return value to initiate a context switch
+ * from the ISR using portYIELD_FROM_ISR. */
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
+ prvAddTaskToReadyList( pxTCB );
+ }
+ else
+ {
+ /* The delayed or ready lists cannot be accessed so the task
+ * is held in the pending ready list until the scheduler is
+ * unsuspended. */
+ vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xYieldRequired;
+ }
+
+#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+void vTaskStartScheduler( void )
+{
+ BaseType_t xReturn;
+
+ /* Add the idle task at the lowest priority. */
+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ StaticTask_t * pxIdleTaskTCBBuffer = NULL;
+ StackType_t * pxIdleTaskStackBuffer = NULL;
+ uint32_t ulIdleTaskStackSize;
+
+ /* The Idle task is created using user provided RAM - obtain the
+ * address of the RAM then create the idle task. */
+ vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
+ xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,
+ configIDLE_TASK_NAME,
+ ulIdleTaskStackSize,
+ ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */
+ portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
+ pxIdleTaskStackBuffer,
+ pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
+
+ if( xIdleTaskHandle != NULL )
+ {
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+ }
+ #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
+ {
+ /* The Idle task is being created using dynamically allocated RAM. */
+ xReturn = xTaskCreate( prvIdleTask,
+ configIDLE_TASK_NAME,
+ configMINIMAL_STACK_SIZE,
+ ( void * ) NULL,
+ portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
+ &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
+
+ #if ( configUSE_TIMERS == 1 )
+ {
+ if( xReturn == pdPASS )
+ {
+ xReturn = xTimerCreateTimerTask();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_TIMERS */
+
+ if( xReturn == pdPASS )
+ {
+ /* freertos_tasks_c_additions_init() should only be called if the user
+ * definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is
+ * the only macro called by the function. */
+ #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
+ {
+ freertos_tasks_c_additions_init();
+ }
+ #endif
+
+ /* Interrupts are turned off here, to ensure a tick does not occur
+ * before or during the call to xPortStartScheduler(). The stacks of
+ * the created tasks contain a status word with interrupts switched on
+ * so interrupts will automatically get re-enabled when the first task
+ * starts to run. */
+ portDISABLE_INTERRUPTS();
+
+ #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
+ {
+ /* Switch C-Runtime's TLS Block to point to the TLS
+ * block specific to the task that will run first. */
+ configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
+ }
+ #endif
+
+ xNextTaskUnblockTime = portMAX_DELAY;
+ xSchedulerRunning = pdTRUE;
+ xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
+
+ /* If configGENERATE_RUN_TIME_STATS is defined then the following
+ * macro must be defined to configure the timer/counter used to generate
+ * the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS
+ * is set to 0 and the following line fails to build then ensure you do not
+ * have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
+ * FreeRTOSConfig.h file. */
+ portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
+
+ traceTASK_SWITCHED_IN();
+
+ /* Setting up the timer tick is hardware specific and thus in the
+ * portable interface. */
+ xPortStartScheduler();
+
+ /* In most cases, xPortStartScheduler() will not return. If it
+ * returns pdTRUE then there was not enough heap memory available
+ * to create either the Idle or the Timer task. If it returned
+ * pdFALSE, then the application called xTaskEndScheduler().
+ * Most ports don't implement xTaskEndScheduler() as there is
+ * nothing to return to. */
+ }
+ else
+ {
+ /* This line will only be reached if the kernel could not be started,
+ * because there was not enough FreeRTOS heap to create the idle task
+ * or the timer task. */
+ configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
+ }
+
+ /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
+ * meaning xIdleTaskHandle is not used anywhere else. */
+ ( void ) xIdleTaskHandle;
+
+ /* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority
+ * from getting optimized out as it is no longer used by the kernel. */
+ ( void ) uxTopUsedPriority;
+}
+/*-----------------------------------------------------------*/
+
+void vTaskEndScheduler( void )
+{
+ /* Stop the scheduler interrupts and call the portable scheduler end
+ * routine so the original ISRs can be restored if necessary. The port
+ * layer must ensure interrupts enable bit is left in the correct state. */
+ portDISABLE_INTERRUPTS();
+ xSchedulerRunning = pdFALSE;
+ vPortEndScheduler();
+}
+/*----------------------------------------------------------*/
+
+void vTaskSuspendAll( void )
+{
+ /* A critical section is not required as the variable is of type
+ * BaseType_t. Please read Richard Barry's reply in the following link to a
+ * post in the FreeRTOS support forum before reporting this as a bug! -
+ * https://goo.gl/wu4acr */
+
+ /* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that
+ * do not otherwise exhibit real time behaviour. */
+ portSOFTWARE_BARRIER();
+
+ /* The scheduler is suspended if uxSchedulerSuspended is non-zero. An increment
+ * is used to allow calls to vTaskSuspendAll() to nest. */
+ ++uxSchedulerSuspended;
+
+ /* Enforces ordering for ports and optimised compilers that may otherwise place
+ * the above increment elsewhere. */
+ portMEMORY_BARRIER();
+}
+/*----------------------------------------------------------*/
+
+#if ( configUSE_TICKLESS_IDLE != 0 )
+
+ static TickType_t prvGetExpectedIdleTime( void )
+ {
+ TickType_t xReturn;
+ UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
+
+ /* uxHigherPriorityReadyTasks takes care of the case where
+ * configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
+ * task that are in the Ready state, even though the idle task is
+ * running. */
+ #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
+ {
+ if( uxTopReadyPriority > tskIDLE_PRIORITY )
+ {
+ uxHigherPriorityReadyTasks = pdTRUE;
+ }
+ }
+ #else
+ {
+ const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
+
+ /* When port optimised task selection is used the uxTopReadyPriority
+ * variable is used as a bit map. If bits other than the least
+ * significant bit are set then there are tasks that have a priority
+ * above the idle priority that are in the Ready state. This takes
+ * care of the case where the co-operative scheduler is in use. */
+ if( uxTopReadyPriority > uxLeastSignificantBit )
+ {
+ uxHigherPriorityReadyTasks = pdTRUE;
+ }
+ }
+ #endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) */
+
+ if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
+ {
+ xReturn = 0;
+ }
+ else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
+ {
+ /* There are other idle priority tasks in the ready state. If
+ * time slicing is used then the very next tick interrupt must be
+ * processed. */
+ xReturn = 0;
+ }
+ else if( uxHigherPriorityReadyTasks != pdFALSE )
+ {
+ /* There are tasks in the Ready state that have a priority above the
+ * idle priority. This path can only be reached if
+ * configUSE_PREEMPTION is 0. */
+ xReturn = 0;
+ }
+ else
+ {
+ xReturn = xNextTaskUnblockTime - xTickCount;
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_TICKLESS_IDLE */
+/*----------------------------------------------------------*/
+
+BaseType_t xTaskResumeAll( void )
+{
+ TCB_t * pxTCB = NULL;
+ BaseType_t xAlreadyYielded = pdFALSE;
+
+ /* If uxSchedulerSuspended is zero then this function does not match a
+ * previous call to vTaskSuspendAll(). */
+ configASSERT( uxSchedulerSuspended );
+
+ /* It is possible that an ISR caused a task to be removed from an event
+ * list while the scheduler was suspended. If this was the case then the
+ * removed task will have been added to the xPendingReadyList. Once the
+ * scheduler has been resumed it is safe to move all the pending ready
+ * tasks from this list into their appropriate ready list. */
+ taskENTER_CRITICAL();
+ {
+ --uxSchedulerSuspended;
+
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
+ {
+ if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
+ {
+ /* Move any readied tasks from the pending list into the
+ * appropriate ready list. */
+ while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
+ {
+ pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+ listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
+ portMEMORY_BARRIER();
+ listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
+ prvAddTaskToReadyList( pxTCB );
+
+ /* If the moved task has a priority higher than or equal to
+ * the current task then a yield must be performed. */
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
+ {
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ if( pxTCB != NULL )
+ {
+ /* A task was unblocked while the scheduler was suspended,
+ * which may have prevented the next unblock time from being
+ * re-calculated, in which case re-calculate it now. Mainly
+ * important for low power tickless implementations, where
+ * this can prevent an unnecessary exit from low power
+ * state. */
+ prvResetNextTaskUnblockTime();
+ }
+
+ /* If any ticks occurred while the scheduler was suspended then
+ * they should be processed now. This ensures the tick count does
+ * not slip, and that any delayed tasks are resumed at the correct
+ * time. */
+ {
+ TickType_t xPendedCounts = xPendedTicks; /* Non-volatile copy. */
+
+ if( xPendedCounts > ( TickType_t ) 0U )
+ {
+ do
+ {
+ if( xTaskIncrementTick() != pdFALSE )
+ {
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ --xPendedCounts;
+ } while( xPendedCounts > ( TickType_t ) 0U );
+
+ xPendedTicks = 0;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ if( xYieldPending != pdFALSE )
+ {
+ #if ( configUSE_PREEMPTION != 0 )
+ {
+ xAlreadyYielded = pdTRUE;
+ }
+ #endif
+ taskYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xAlreadyYielded;
+}
+/*-----------------------------------------------------------*/
+
+TickType_t xTaskGetTickCount( void )
+{
+ TickType_t xTicks;
+
+ /* Critical section required if running on a 16 bit processor. */
+ portTICK_TYPE_ENTER_CRITICAL();
+ {
+ xTicks = xTickCount;
+ }
+ portTICK_TYPE_EXIT_CRITICAL();
+
+ return xTicks;
+}
+/*-----------------------------------------------------------*/
+
+TickType_t xTaskGetTickCountFromISR( void )
+{
+ TickType_t xReturn;
+ UBaseType_t uxSavedInterruptStatus;
+
+ /* RTOS ports that support interrupt nesting have the concept of a maximum
+ * system call (or maximum API call) interrupt priority. Interrupts that are
+ * above the maximum system call priority are kept permanently enabled, even
+ * when the RTOS kernel is in a critical section, but cannot make any calls to
+ * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
+ * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ * failure if a FreeRTOS API function is called from an interrupt that has been
+ * assigned a priority above the configured maximum system call priority.
+ * Only FreeRTOS functions that end in FromISR can be called from interrupts
+ * that have been assigned a priority at or (logically) below the maximum
+ * system call interrupt priority. FreeRTOS maintains a separate interrupt
+ * safe API to ensure interrupt entry is as fast and as simple as possible.
+ * More information (albeit Cortex-M specific) is provided on the following
+ * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
+ {
+ xReturn = xTickCount;
+ }
+ portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+UBaseType_t uxTaskGetNumberOfTasks( void )
+{
+ /* A critical section is not required because the variables are of type
+ * BaseType_t. */
+ return uxCurrentNumberOfTasks;
+}
+/*-----------------------------------------------------------*/
+
+char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+{
+ TCB_t * pxTCB;
+
+ /* If null is passed in here then the name of the calling task is being
+ * queried. */
+ pxTCB = prvGetTCBFromHandle( xTaskToQuery );
+ configASSERT( pxTCB );
+ return &( pxTCB->pcTaskName[ 0 ] );
+}
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskGetHandle == 1 )
+
+ static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
+ const char pcNameToQuery[] )
+ {
+ TCB_t * pxNextTCB;
+ TCB_t * pxFirstTCB;
+ TCB_t * pxReturn = NULL;
+ UBaseType_t x;
+ char cNextChar;
+ BaseType_t xBreakLoop;
+
+ /* This function is called with the scheduler suspended. */
+
+ if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
+ {
+ listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+
+ do
+ {
+ listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+
+ /* Check each character in the name looking for a match or
+ * mismatch. */
+ xBreakLoop = pdFALSE;
+
+ for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
+ {
+ cNextChar = pxNextTCB->pcTaskName[ x ];
+
+ if( cNextChar != pcNameToQuery[ x ] )
+ {
+ /* Characters didn't match. */
+ xBreakLoop = pdTRUE;
+ }
+ else if( cNextChar == ( char ) 0x00 )
+ {
+ /* Both strings terminated, a match must have been
+ * found. */
+ pxReturn = pxNextTCB;
+ xBreakLoop = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ if( xBreakLoop != pdFALSE )
+ {
+ break;
+ }
+ }
+
+ if( pxReturn != NULL )
+ {
+ /* The handle has been found. */
+ break;
+ }
+ } while( pxNextTCB != pxFirstTCB );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return pxReturn;
+ }
+
+#endif /* INCLUDE_xTaskGetHandle */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskGetHandle == 1 )
+
+ TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ {
+ UBaseType_t uxQueue = configMAX_PRIORITIES;
+ TCB_t * pxTCB;
+
+ /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
+ configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
+
+ vTaskSuspendAll();
+ {
+ /* Search the ready lists. */
+ do
+ {
+ uxQueue--;
+ pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
+
+ if( pxTCB != NULL )
+ {
+ /* Found the handle. */
+ break;
+ }
+ } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ /* Search the delayed lists. */
+ if( pxTCB == NULL )
+ {
+ pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
+ }
+
+ if( pxTCB == NULL )
+ {
+ pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
+ }
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ {
+ if( pxTCB == NULL )
+ {
+ /* Search the suspended list. */
+ pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
+ }
+ }
+ #endif
+
+ #if ( INCLUDE_vTaskDelete == 1 )
+ {
+ if( pxTCB == NULL )
+ {
+ /* Search the deleted list. */
+ pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
+ }
+ }
+ #endif
+ }
+ ( void ) xTaskResumeAll();
+
+ return pxTCB;
+ }
+
+#endif /* INCLUDE_xTaskGetHandle */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
+ const UBaseType_t uxArraySize,
+ configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
+ {
+ UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
+
+ vTaskSuspendAll();
+ {
+ /* Is there a space in the array for each task in the system? */
+ if( uxArraySize >= uxCurrentNumberOfTasks )
+ {
+ /* Fill in an TaskStatus_t structure with information on each
+ * task in the Ready state. */
+ do
+ {
+ uxQueue--;
+ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
+ } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ /* Fill in an TaskStatus_t structure with information on each
+ * task in the Blocked state. */
+ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
+ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
+
+ #if ( INCLUDE_vTaskDelete == 1 )
+ {
+ /* Fill in an TaskStatus_t structure with information on
+ * each task that has been deleted but not yet cleaned up. */
+ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
+ }
+ #endif
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ {
+ /* Fill in an TaskStatus_t structure with information on
+ * each task in the Suspended state. */
+ uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
+ }
+ #endif
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ {
+ if( pulTotalRunTime != NULL )
+ {
+ #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
+ portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
+ #else
+ *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
+ #endif
+ }
+ }
+ #else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
+ {
+ if( pulTotalRunTime != NULL )
+ {
+ *pulTotalRunTime = 0;
+ }
+ }
+ #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ ( void ) xTaskResumeAll();
+
+ return uxTask;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
+
+ TaskHandle_t xTaskGetIdleTaskHandle( void )
+ {
+ /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
+ * started, then xIdleTaskHandle will be NULL. */
+ configASSERT( ( xIdleTaskHandle != NULL ) );
+ return xIdleTaskHandle;
+ }
+
+#endif /* INCLUDE_xTaskGetIdleTaskHandle */
+/*----------------------------------------------------------*/
+
+/* This conditional compilation should use inequality to 0, not equality to 1.
+ * This is to ensure vTaskStepTick() is available when user defined low power mode
+ * implementations require configUSE_TICKLESS_IDLE to be set to a value other than
+ * 1. */
+#if ( configUSE_TICKLESS_IDLE != 0 )
+
+ void vTaskStepTick( TickType_t xTicksToJump )
+ {
+ /* Correct the tick count value after a period during which the tick
+ * was suppressed. Note this does *not* call the tick hook function for
+ * each stepped tick. */
+ configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
+
+ if( ( xTickCount + xTicksToJump ) == xNextTaskUnblockTime )
+ {
+ /* Arrange for xTickCount to reach xNextTaskUnblockTime in
+ * xTaskIncrementTick() when the scheduler resumes. This ensures
+ * that any delayed tasks are resumed at the correct time. */
+ configASSERT( uxSchedulerSuspended );
+ configASSERT( xTicksToJump != ( TickType_t ) 0 );
+
+ /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
+ taskENTER_CRITICAL();
+ {
+ xPendedTicks++;
+ }
+ taskEXIT_CRITICAL();
+ xTicksToJump--;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ xTickCount += xTicksToJump;
+ traceINCREASE_TICK_COUNT( xTicksToJump );
+ }
+
+#endif /* configUSE_TICKLESS_IDLE */
+/*----------------------------------------------------------*/
+
+BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )
+{
+ BaseType_t xYieldOccurred;
+
+ /* Must not be called with the scheduler suspended as the implementation
+ * relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */
+ configASSERT( uxSchedulerSuspended == 0 );
+
+ /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when
+ * the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */
+ vTaskSuspendAll();
+
+ /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
+ taskENTER_CRITICAL();
+ {
+ xPendedTicks += xTicksToCatchUp;
+ }
+ taskEXIT_CRITICAL();
+ xYieldOccurred = xTaskResumeAll();
+
+ return xYieldOccurred;
+}
+/*----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskAbortDelay == 1 )
+
+ BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
+ {
+ TCB_t * pxTCB = xTask;
+ BaseType_t xReturn;
+
+ configASSERT( pxTCB );
+
+ vTaskSuspendAll();
+ {
+ /* A task can only be prematurely removed from the Blocked state if
+ * it is actually in the Blocked state. */
+ if( eTaskGetState( xTask ) == eBlocked )
+ {
+ xReturn = pdPASS;
+
+ /* Remove the reference to the task from the blocked list. An
+ * interrupt won't touch the xStateListItem because the
+ * scheduler is suspended. */
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
+
+ /* Is the task waiting on an event also? If so remove it from
+ * the event list too. Interrupts can touch the event list item,
+ * even though the scheduler is suspended, so a critical section
+ * is used. */
+ taskENTER_CRITICAL();
+ {
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
+
+ /* This lets the task know it was forcibly removed from the
+ * blocked state so it should not re-evaluate its block time and
+ * then block again. */
+ pxTCB->ucDelayAborted = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ /* Place the unblocked task into the appropriate ready list. */
+ prvAddTaskToReadyList( pxTCB );
+
+ /* A task being unblocked cannot cause an immediate context
+ * switch if preemption is turned off. */
+ #if ( configUSE_PREEMPTION == 1 )
+ {
+ /* Preemption is on, but a context switch should only be
+ * performed if the unblocked task has a priority that is
+ * higher than the currently executing task. */
+ if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
+ {
+ /* Pend the yield to be performed when the scheduler
+ * is unsuspended. */
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_PREEMPTION */
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+ }
+ ( void ) xTaskResumeAll();
+
+ return xReturn;
+ }
+
+#endif /* INCLUDE_xTaskAbortDelay */
+/*----------------------------------------------------------*/
+
+BaseType_t xTaskIncrementTick( void )
+{
+ TCB_t * pxTCB;
+ TickType_t xItemValue;
+ BaseType_t xSwitchRequired = pdFALSE;
+
+ /* Called by the portable layer each time a tick interrupt occurs.
+ * Increments the tick then checks to see if the new tick value will cause any
+ * tasks to be unblocked. */
+ traceTASK_INCREMENT_TICK( xTickCount );
+
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
+ {
+ /* Minor optimisation. The tick count cannot change in this
+ * block. */
+ const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
+
+ /* Increment the RTOS tick, switching the delayed and overflowed
+ * delayed lists if it wraps to 0. */
+ xTickCount = xConstTickCount;
+
+ if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
+ {
+ taskSWITCH_DELAYED_LISTS();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* See if this tick has made a timeout expire. Tasks are stored in
+ * the queue in the order of their wake time - meaning once one task
+ * has been found whose block time has not expired there is no need to
+ * look any further down the list. */
+ if( xConstTickCount >= xNextTaskUnblockTime )
+ {
+ for( ; ; )
+ {
+ if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
+ {
+ /* The delayed list is empty. Set xNextTaskUnblockTime
+ * to the maximum possible value so it is extremely
+ * unlikely that the
+ * if( xTickCount >= xNextTaskUnblockTime ) test will pass
+ * next time through. */
+ xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ break;
+ }
+ else
+ {
+ /* The delayed list is not empty, get the value of the
+ * item at the head of the delayed list. This is the time
+ * at which the task at the head of the delayed list must
+ * be removed from the Blocked state. */
+ pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+ xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
+
+ if( xConstTickCount < xItemValue )
+ {
+ /* It is not time to unblock this item yet, but the
+ * item value is the time at which the task at the head
+ * of the blocked list must be removed from the Blocked
+ * state - so record the item value in
+ * xNextTaskUnblockTime. */
+ xNextTaskUnblockTime = xItemValue;
+ break; /*lint !e9011 Code structure here is deemed easier to understand with multiple breaks. */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* It is time to remove the item from the Blocked state. */
+ listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
+
+ /* Is the task waiting on an event also? If so remove
+ * it from the event list. */
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Place the unblocked task into the appropriate ready
+ * list. */
+ prvAddTaskToReadyList( pxTCB );
+
+ /* A task being unblocked cannot cause an immediate
+ * context switch if preemption is turned off. */
+ #if ( configUSE_PREEMPTION == 1 )
+ {
+ /* Preemption is on, but a context switch should
+ * only be performed if the unblocked task's
+ * priority is higher than the currently executing
+ * task.
+ * The case of equal priority tasks sharing
+ * processing time (which happens when both
+ * preemption and time slicing are on) is
+ * handled below.*/
+ if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
+ {
+ xSwitchRequired = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_PREEMPTION */
+ }
+ }
+ }
+
+ /* Tasks of equal priority to the currently running task will share
+ * processing time (time slice) if preemption is on, and the application
+ * writer has not explicitly turned time slicing off. */
+ #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
+ {
+ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
+ {
+ xSwitchRequired = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
+
+ #if ( configUSE_TICK_HOOK == 1 )
+ {
+ /* Guard against the tick hook being called when the pended tick
+ * count is being unwound (when the scheduler is being unlocked). */
+ if( xPendedTicks == ( TickType_t ) 0 )
+ {
+ vApplicationTickHook();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_TICK_HOOK */
+
+ #if ( configUSE_PREEMPTION == 1 )
+ {
+ if( xYieldPending != pdFALSE )
+ {
+ xSwitchRequired = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_PREEMPTION */
+ }
+ else
+ {
+ ++xPendedTicks;
+
+ /* The tick hook gets called at regular intervals, even if the
+ * scheduler is locked. */
+ #if ( configUSE_TICK_HOOK == 1 )
+ {
+ vApplicationTickHook();
+ }
+ #endif
+ }
+
+ return xSwitchRequired;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+ void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
+ TaskHookFunction_t pxHookFunction )
+ {
+ TCB_t * xTCB;
+
+ /* If xTask is NULL then it is the task hook of the calling task that is
+ * getting set. */
+ if( xTask == NULL )
+ {
+ xTCB = ( TCB_t * ) pxCurrentTCB;
+ }
+ else
+ {
+ xTCB = xTask;
+ }
+
+ /* Save the hook function in the TCB. A critical section is required as
+ * the value can be accessed from an interrupt. */
+ taskENTER_CRITICAL();
+ {
+ xTCB->pxTaskTag = pxHookFunction;
+ }
+ taskEXIT_CRITICAL();
+ }
+
+#endif /* configUSE_APPLICATION_TASK_TAG */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+ TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
+ {
+ TCB_t * pxTCB;
+ TaskHookFunction_t xReturn;
+
+ /* If xTask is NULL then set the calling task's hook. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ /* Save the hook function in the TCB. A critical section is required as
+ * the value can be accessed from an interrupt. */
+ taskENTER_CRITICAL();
+ {
+ xReturn = pxTCB->pxTaskTag;
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+ }
+
+#endif /* configUSE_APPLICATION_TASK_TAG */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+ TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask )
+ {
+ TCB_t * pxTCB;
+ TaskHookFunction_t xReturn;
+ UBaseType_t uxSavedInterruptStatus;
+
+ /* If xTask is NULL then set the calling task's hook. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ /* Save the hook function in the TCB. A critical section is required as
+ * the value can be accessed from an interrupt. */
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ xReturn = pxTCB->pxTaskTag;
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+ }
+
+#endif /* configUSE_APPLICATION_TASK_TAG */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+ BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
+ void * pvParameter )
+ {
+ TCB_t * xTCB;
+ BaseType_t xReturn;
+
+ /* If xTask is NULL then we are calling our own task hook. */
+ if( xTask == NULL )
+ {
+ xTCB = pxCurrentTCB;
+ }
+ else
+ {
+ xTCB = xTask;
+ }
+
+ if( xTCB->pxTaskTag != NULL )
+ {
+ xReturn = xTCB->pxTaskTag( pvParameter );
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_APPLICATION_TASK_TAG */
+/*-----------------------------------------------------------*/
+
+void vTaskSwitchContext( void )
+{
+ if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
+ {
+ /* The scheduler is currently suspended - do not allow a context
+ * switch. */
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ xYieldPending = pdFALSE;
+ traceTASK_SWITCHED_OUT();
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ {
+ #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
+ portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
+ #else
+ ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
+ #endif
+
+ /* Add the amount of time the task has been running to the
+ * accumulated time so far. The time the task started running was
+ * stored in ulTaskSwitchedInTime. Note that there is no overflow
+ * protection here so count values are only valid until the timer
+ * overflows. The guard against negative values is to protect
+ * against suspect run time stat counter implementations - which
+ * are provided by the application, not the kernel. */
+ if( ulTotalRunTime > ulTaskSwitchedInTime )
+ {
+ pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ ulTaskSwitchedInTime = ulTotalRunTime;
+ }
+ #endif /* configGENERATE_RUN_TIME_STATS */
+
+ /* Check for stack overflow, if configured. */
+ taskCHECK_FOR_STACK_OVERFLOW();
+
+ /* Before the currently running task is switched out, save its errno. */
+ #if ( configUSE_POSIX_ERRNO == 1 )
+ {
+ pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
+ }
+ #endif
+
+ /* Select a new task to run using either the generic C or port
+ * optimised asm code. */
+ taskSELECT_HIGHEST_PRIORITY_TASK(); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+ traceTASK_SWITCHED_IN();
+
+ /* After the new task is switched in, update the global errno. */
+ #if ( configUSE_POSIX_ERRNO == 1 )
+ {
+ FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
+ }
+ #endif
+
+ #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
+ {
+ /* Switch C-Runtime's TLS Block to point to the TLS
+ * Block specific to this task. */
+ configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
+ }
+ #endif
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vTaskPlaceOnEventList( List_t * const pxEventList,
+ const TickType_t xTicksToWait )
+{
+ configASSERT( pxEventList );
+
+ /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
+ * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
+
+ /* Place the event list item of the TCB in the appropriate event list.
+ * This is placed in the list in priority order so the highest priority task
+ * is the first to be woken by the event.
+ *
+ * Note: Lists are sorted in ascending order by ListItem_t.xItemValue.
+ * Normally, the xItemValue of a TCB's ListItem_t members is:
+ * xItemValue = ( configMAX_PRIORITIES - uxPriority )
+ * Therefore, the event list is sorted in descending priority order.
+ *
+ * The queue that contains the event list is locked, preventing
+ * simultaneous access from interrupts. */
+ vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
+
+ prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
+}
+/*-----------------------------------------------------------*/
+
+void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
+ const TickType_t xItemValue,
+ const TickType_t xTicksToWait )
+{
+ configASSERT( pxEventList );
+
+ /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
+ * the event groups implementation. */
+ configASSERT( uxSchedulerSuspended != 0 );
+
+ /* Store the item value in the event list item. It is safe to access the
+ * event list item here as interrupts won't access the event list item of a
+ * task that is not in the Blocked state. */
+ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
+
+ /* Place the event list item of the TCB at the end of the appropriate event
+ * list. It is safe to access the event list here because it is part of an
+ * event group implementation - and interrupts don't access event groups
+ * directly (instead they access them indirectly by pending function calls to
+ * the task level). */
+ listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
+
+ prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TIMERS == 1 )
+
+ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,
+ TickType_t xTicksToWait,
+ const BaseType_t xWaitIndefinitely )
+ {
+ configASSERT( pxEventList );
+
+ /* This function should not be called by application code hence the
+ * 'Restricted' in its name. It is not part of the public API. It is
+ * designed for use by kernel code, and has special calling requirements -
+ * it should be called with the scheduler suspended. */
+
+
+ /* Place the event list item of the TCB in the appropriate event list.
+ * In this case it is assume that this is the only task that is going to
+ * be waiting on this event list, so the faster vListInsertEnd() function
+ * can be used in place of vListInsert. */
+ listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
+
+ /* If the task should block indefinitely then set the block time to a
+ * value that will be recognised as an indefinite delay inside the
+ * prvAddCurrentTaskToDelayedList() function. */
+ if( xWaitIndefinitely != pdFALSE )
+ {
+ xTicksToWait = portMAX_DELAY;
+ }
+
+ traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
+ prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
+ }
+
+#endif /* configUSE_TIMERS */
+/*-----------------------------------------------------------*/
+
+BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
+{
+ TCB_t * pxUnblockedTCB;
+ BaseType_t xReturn;
+
+ /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
+ * called from a critical section within an ISR. */
+
+ /* The event list is sorted in priority order, so the first in the list can
+ * be removed as it is known to be the highest priority. Remove the TCB from
+ * the delayed list, and add it to the ready list.
+ *
+ * If an event is for a queue that is locked then this function will never
+ * get called - the lock count on the queue will get modified instead. This
+ * means exclusive access to the event list is guaranteed here.
+ *
+ * This function assumes that a check has already been made to ensure that
+ * pxEventList is not empty. */
+ pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+ configASSERT( pxUnblockedTCB );
+ listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) );
+
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
+ {
+ listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
+ prvAddTaskToReadyList( pxUnblockedTCB );
+
+ #if ( configUSE_TICKLESS_IDLE != 0 )
+ {
+ /* If a task is blocked on a kernel object then xNextTaskUnblockTime
+ * might be set to the blocked task's time out time. If the task is
+ * unblocked for a reason other than a timeout xNextTaskUnblockTime is
+ * normally left unchanged, because it is automatically reset to a new
+ * value when the tick count equals xNextTaskUnblockTime. However if
+ * tickless idling is used it might be more important to enter sleep mode
+ * at the earliest possible time - so reset xNextTaskUnblockTime here to
+ * ensure it is updated at the earliest possible time. */
+ prvResetNextTaskUnblockTime();
+ }
+ #endif
+ }
+ else
+ {
+ /* The delayed and ready lists cannot be accessed, so hold this task
+ * pending until the scheduler is resumed. */
+ listINSERT_END( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
+ }
+
+ if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
+ {
+ /* Return true if the task removed from the event list has a higher
+ * priority than the calling task. This allows the calling task to know if
+ * it should force a context switch now. */
+ xReturn = pdTRUE;
+
+ /* Mark that a yield is pending in case the user is not using the
+ * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
+ const TickType_t xItemValue )
+{
+ TCB_t * pxUnblockedTCB;
+
+ /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
+ * the event flags implementation. */
+ configASSERT( uxSchedulerSuspended != pdFALSE );
+
+ /* Store the new item value in the event list. */
+ listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
+
+ /* Remove the event list form the event flag. Interrupts do not access
+ * event flags. */
+ pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+ configASSERT( pxUnblockedTCB );
+ listREMOVE_ITEM( pxEventListItem );
+
+ #if ( configUSE_TICKLESS_IDLE != 0 )
+ {
+ /* If a task is blocked on a kernel object then xNextTaskUnblockTime
+ * might be set to the blocked task's time out time. If the task is
+ * unblocked for a reason other than a timeout xNextTaskUnblockTime is
+ * normally left unchanged, because it is automatically reset to a new
+ * value when the tick count equals xNextTaskUnblockTime. However if
+ * tickless idling is used it might be more important to enter sleep mode
+ * at the earliest possible time - so reset xNextTaskUnblockTime here to
+ * ensure it is updated at the earliest possible time. */
+ prvResetNextTaskUnblockTime();
+ }
+ #endif
+
+ /* Remove the task from the delayed list and add it to the ready list. The
+ * scheduler is suspended so interrupts will not be accessing the ready
+ * lists. */
+ listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
+ prvAddTaskToReadyList( pxUnblockedTCB );
+
+ if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
+ {
+ /* The unblocked task has a priority above that of the calling task, so
+ * a context switch is required. This function is called with the
+ * scheduler suspended so xYieldPending is set so the context switch
+ * occurs immediately that the scheduler is resumed (unsuspended). */
+ xYieldPending = pdTRUE;
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
+{
+ configASSERT( pxTimeOut );
+ taskENTER_CRITICAL();
+ {
+ pxTimeOut->xOverflowCount = xNumOfOverflows;
+ pxTimeOut->xTimeOnEntering = xTickCount;
+ }
+ taskEXIT_CRITICAL();
+}
+/*-----------------------------------------------------------*/
+
+void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
+{
+ /* For internal use only as it does not use a critical section. */
+ pxTimeOut->xOverflowCount = xNumOfOverflows;
+ pxTimeOut->xTimeOnEntering = xTickCount;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
+ TickType_t * const pxTicksToWait )
+{
+ BaseType_t xReturn;
+
+ configASSERT( pxTimeOut );
+ configASSERT( pxTicksToWait );
+
+ taskENTER_CRITICAL();
+ {
+ /* Minor optimisation. The tick count cannot change in this block. */
+ const TickType_t xConstTickCount = xTickCount;
+ const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
+
+ #if ( INCLUDE_xTaskAbortDelay == 1 )
+ if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE )
+ {
+ /* The delay was aborted, which is not the same as a time out,
+ * but has the same result. */
+ pxCurrentTCB->ucDelayAborted = pdFALSE;
+ xReturn = pdTRUE;
+ }
+ else
+ #endif
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ if( *pxTicksToWait == portMAX_DELAY )
+ {
+ /* If INCLUDE_vTaskSuspend is set to 1 and the block time
+ * specified is the maximum block time then the task should block
+ * indefinitely, and therefore never time out. */
+ xReturn = pdFALSE;
+ }
+ else
+ #endif
+
+ if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
+ {
+ /* The tick count is greater than the time at which
+ * vTaskSetTimeout() was called, but has also overflowed since
+ * vTaskSetTimeOut() was called. It must have wrapped all the way
+ * around and gone past again. This passed since vTaskSetTimeout()
+ * was called. */
+ xReturn = pdTRUE;
+ *pxTicksToWait = ( TickType_t ) 0;
+ }
+ else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
+ {
+ /* Not a genuine timeout. Adjust parameters for time remaining. */
+ *pxTicksToWait -= xElapsedTime;
+ vTaskInternalSetTimeOutState( pxTimeOut );
+ xReturn = pdFALSE;
+ }
+ else
+ {
+ *pxTicksToWait = ( TickType_t ) 0;
+ xReturn = pdTRUE;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vTaskMissedYield( void )
+{
+ xYieldPending = pdTRUE;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
+ {
+ UBaseType_t uxReturn;
+ TCB_t const * pxTCB;
+
+ if( xTask != NULL )
+ {
+ pxTCB = xTask;
+ uxReturn = pxTCB->uxTaskNumber;
+ }
+ else
+ {
+ uxReturn = 0U;
+ }
+
+ return uxReturn;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ void vTaskSetTaskNumber( TaskHandle_t xTask,
+ const UBaseType_t uxHandle )
+ {
+ TCB_t * pxTCB;
+
+ if( xTask != NULL )
+ {
+ pxTCB = xTask;
+ pxTCB->uxTaskNumber = uxHandle;
+ }
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+
+/*
+ * -----------------------------------------------------------
+ * The Idle task.
+ * ----------------------------------------------------------
+ *
+ * The portTASK_FUNCTION() macro is used to allow port/compiler specific
+ * language extensions. The equivalent prototype for this function is:
+ *
+ * void prvIdleTask( void *pvParameters );
+ *
+ */
+static portTASK_FUNCTION( prvIdleTask, pvParameters )
+{
+ /* Stop warnings. */
+ ( void ) pvParameters;
+
+ /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
+ * SCHEDULER IS STARTED. **/
+
+ /* In case a task that has a secure context deletes itself, in which case
+ * the idle task is responsible for deleting the task's secure context, if
+ * any. */
+ portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE );
+
+ for( ; ; )
+ {
+ /* See if any tasks have deleted themselves - if so then the idle task
+ * is responsible for freeing the deleted task's TCB and stack. */
+ prvCheckTasksWaitingTermination();
+
+ #if ( configUSE_PREEMPTION == 0 )
+ {
+ /* If we are not using preemption we keep forcing a task switch to
+ * see if any other task has become available. If we are using
+ * preemption we don't need to do this as any task becoming available
+ * will automatically get the processor anyway. */
+ taskYIELD();
+ }
+ #endif /* configUSE_PREEMPTION */
+
+ #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
+ {
+ /* When using preemption tasks of equal priority will be
+ * timesliced. If a task that is sharing the idle priority is ready
+ * to run then the idle task should yield before the end of the
+ * timeslice.
+ *
+ * A critical region is not required here as we are just reading from
+ * the list, and an occasional incorrect value will not matter. If
+ * the ready list at the idle priority contains more than one task
+ * then a task other than the idle task is ready to execute. */
+ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
+ {
+ taskYIELD();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
+
+ #if ( configUSE_IDLE_HOOK == 1 )
+ {
+ extern void vApplicationIdleHook( void );
+
+ /* Call the user defined function from within the idle task. This
+ * allows the application designer to add background functionality
+ * without the overhead of a separate task.
+ * NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
+ * CALL A FUNCTION THAT MIGHT BLOCK. */
+ vApplicationIdleHook();
+ }
+ #endif /* configUSE_IDLE_HOOK */
+
+ /* This conditional compilation should use inequality to 0, not equality
+ * to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
+ * user defined low power mode implementations require
+ * configUSE_TICKLESS_IDLE to be set to a value other than 1. */
+ #if ( configUSE_TICKLESS_IDLE != 0 )
+ {
+ TickType_t xExpectedIdleTime;
+
+ /* It is not desirable to suspend then resume the scheduler on
+ * each iteration of the idle task. Therefore, a preliminary
+ * test of the expected idle time is performed without the
+ * scheduler suspended. The result here is not necessarily
+ * valid. */
+ xExpectedIdleTime = prvGetExpectedIdleTime();
+
+ if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
+ {
+ vTaskSuspendAll();
+ {
+ /* Now the scheduler is suspended, the expected idle
+ * time can be sampled again, and this time its value can
+ * be used. */
+ configASSERT( xNextTaskUnblockTime >= xTickCount );
+ xExpectedIdleTime = prvGetExpectedIdleTime();
+
+ /* Define the following macro to set xExpectedIdleTime to 0
+ * if the application does not want
+ * portSUPPRESS_TICKS_AND_SLEEP() to be called. */
+ configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );
+
+ if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
+ {
+ traceLOW_POWER_IDLE_BEGIN();
+ portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
+ traceLOW_POWER_IDLE_END();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ ( void ) xTaskResumeAll();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_TICKLESS_IDLE */
+ }
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TICKLESS_IDLE != 0 )
+
+ eSleepModeStatus eTaskConfirmSleepModeStatus( void )
+ {
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ /* The idle task exists in addition to the application tasks. */
+ const UBaseType_t uxNonApplicationTasks = 1;
+ #endif /* INCLUDE_vTaskSuspend */
+
+ eSleepModeStatus eReturn = eStandardSleep;
+
+ /* This function must be called from a critical section. */
+
+ if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
+ {
+ /* A task was made ready while the scheduler was suspended. */
+ eReturn = eAbortSleep;
+ }
+ else if( xYieldPending != pdFALSE )
+ {
+ /* A yield was pended while the scheduler was suspended. */
+ eReturn = eAbortSleep;
+ }
+ else if( xPendedTicks != 0 )
+ {
+ /* A tick interrupt has already occurred but was held pending
+ * because the scheduler is suspended. */
+ eReturn = eAbortSleep;
+ }
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ else if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
+ {
+ /* If all the tasks are in the suspended list (which might mean they
+ * have an infinite block time rather than actually being suspended)
+ * then it is safe to turn all clocks off and just wait for external
+ * interrupts. */
+ eReturn = eNoTasksWaitingTimeout;
+ }
+ #endif /* INCLUDE_vTaskSuspend */
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return eReturn;
+ }
+
+#endif /* configUSE_TICKLESS_IDLE */
+/*-----------------------------------------------------------*/
+
+#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
+
+ void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
+ BaseType_t xIndex,
+ void * pvValue )
+ {
+ TCB_t * pxTCB;
+
+ if( ( xIndex >= 0 ) &&
+ ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
+ {
+ pxTCB = prvGetTCBFromHandle( xTaskToSet );
+ configASSERT( pxTCB != NULL );
+ pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
+ }
+ }
+
+#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
+/*-----------------------------------------------------------*/
+
+#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
+
+ void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
+ BaseType_t xIndex )
+ {
+ void * pvReturn = NULL;
+ TCB_t * pxTCB;
+
+ if( ( xIndex >= 0 ) &&
+ ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
+ {
+ pxTCB = prvGetTCBFromHandle( xTaskToQuery );
+ pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
+ }
+ else
+ {
+ pvReturn = NULL;
+ }
+
+ return pvReturn;
+ }
+
+#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
+/*-----------------------------------------------------------*/
+
+#if ( portUSING_MPU_WRAPPERS == 1 )
+
+ void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify,
+ const MemoryRegion_t * const xRegions )
+ {
+ TCB_t * pxTCB;
+
+ /* If null is passed in here then we are modifying the MPU settings of
+ * the calling task. */
+ pxTCB = prvGetTCBFromHandle( xTaskToModify );
+
+ vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
+ }
+
+#endif /* portUSING_MPU_WRAPPERS */
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseTaskLists( void )
+{
+ UBaseType_t uxPriority;
+
+ for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
+ {
+ vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
+ }
+
+ vListInitialise( &xDelayedTaskList1 );
+ vListInitialise( &xDelayedTaskList2 );
+ vListInitialise( &xPendingReadyList );
+
+ #if ( INCLUDE_vTaskDelete == 1 )
+ {
+ vListInitialise( &xTasksWaitingTermination );
+ }
+ #endif /* INCLUDE_vTaskDelete */
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ {
+ vListInitialise( &xSuspendedTaskList );
+ }
+ #endif /* INCLUDE_vTaskSuspend */
+
+ /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
+ * using list2. */
+ pxDelayedTaskList = &xDelayedTaskList1;
+ pxOverflowDelayedTaskList = &xDelayedTaskList2;
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckTasksWaitingTermination( void )
+{
+ /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
+
+ #if ( INCLUDE_vTaskDelete == 1 )
+ {
+ TCB_t * pxTCB;
+
+ /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()
+ * being called too often in the idle task. */
+ while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
+ {
+ taskENTER_CRITICAL();
+ {
+ pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+ ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
+ --uxCurrentNumberOfTasks;
+ --uxDeletedTasksWaitingCleanUp;
+ }
+ taskEXIT_CRITICAL();
+
+ prvDeleteTCB( pxTCB );
+ }
+ }
+ #endif /* INCLUDE_vTaskDelete */
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ void vTaskGetInfo( TaskHandle_t xTask,
+ TaskStatus_t * pxTaskStatus,
+ BaseType_t xGetFreeStackSpace,
+ eTaskState eState )
+ {
+ TCB_t * pxTCB;
+
+ /* xTask is NULL then get the state of the calling task. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;
+ pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName[ 0 ] );
+ pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
+ pxTaskStatus->pxStackBase = pxTCB->pxStack;
+ #if ( ( portSTACK_GROWTH > 0 ) && ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
+ pxTaskStatus->pxTopOfStack = pxTCB->pxTopOfStack;
+ pxTaskStatus->pxEndOfStack = pxTCB->pxEndOfStack;
+ #endif
+ pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
+
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
+ }
+ #else
+ {
+ pxTaskStatus->uxBasePriority = 0;
+ }
+ #endif
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ {
+ pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
+ }
+ #else
+ {
+ pxTaskStatus->ulRunTimeCounter = ( configRUN_TIME_COUNTER_TYPE ) 0;
+ }
+ #endif
+
+ /* Obtaining the task state is a little fiddly, so is only done if the
+ * value of eState passed into this function is eInvalid - otherwise the
+ * state is just set to whatever is passed in. */
+ if( eState != eInvalid )
+ {
+ if( pxTCB == pxCurrentTCB )
+ {
+ pxTaskStatus->eCurrentState = eRunning;
+ }
+ else
+ {
+ pxTaskStatus->eCurrentState = eState;
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ {
+ /* If the task is in the suspended list then there is a
+ * chance it is actually just blocked indefinitely - so really
+ * it should be reported as being in the Blocked state. */
+ if( eState == eSuspended )
+ {
+ vTaskSuspendAll();
+ {
+ if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+ {
+ pxTaskStatus->eCurrentState = eBlocked;
+ }
+ }
+ ( void ) xTaskResumeAll();
+ }
+ }
+ #endif /* INCLUDE_vTaskSuspend */
+ }
+ }
+ else
+ {
+ pxTaskStatus->eCurrentState = eTaskGetState( pxTCB );
+ }
+
+ /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
+ * parameter is provided to allow it to be skipped. */
+ if( xGetFreeStackSpace != pdFALSE )
+ {
+ #if ( portSTACK_GROWTH > 0 )
+ {
+ pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
+ }
+ #else
+ {
+ pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
+ }
+ #endif
+ }
+ else
+ {
+ pxTaskStatus->usStackHighWaterMark = 0;
+ }
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+ static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
+ List_t * pxList,
+ eTaskState eState )
+ {
+ configLIST_VOLATILE TCB_t * pxNextTCB;
+ configLIST_VOLATILE TCB_t * pxFirstTCB;
+ UBaseType_t uxTask = 0;
+
+ if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
+ {
+ listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+
+ /* Populate an TaskStatus_t structure within the
+ * pxTaskStatusArray array for each task that is referenced from
+ * pxList. See the definition of TaskStatus_t in task.h for the
+ * meaning of each TaskStatus_t structure member. */
+ do
+ {
+ listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+ vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
+ uxTask++;
+ } while( pxNextTCB != pxFirstTCB );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return uxTask;
+ }
+
+#endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
+
+ static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
+ {
+ uint32_t ulCount = 0U;
+
+ while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
+ {
+ pucStackByte -= portSTACK_GROWTH;
+ ulCount++;
+ }
+
+ ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
+
+ return ( configSTACK_DEPTH_TYPE ) ulCount;
+ }
+
+#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
+
+/* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
+ * same except for their return type. Using configSTACK_DEPTH_TYPE allows the
+ * user to determine the return type. It gets around the problem of the value
+ * overflowing on 8-bit types without breaking backward compatibility for
+ * applications that expect an 8-bit return type. */
+ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
+ {
+ TCB_t * pxTCB;
+ uint8_t * pucEndOfStack;
+ configSTACK_DEPTH_TYPE uxReturn;
+
+ /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are
+ * the same except for their return type. Using configSTACK_DEPTH_TYPE
+ * allows the user to determine the return type. It gets around the
+ * problem of the value overflowing on 8-bit types without breaking
+ * backward compatibility for applications that expect an 8-bit return
+ * type. */
+
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ #if portSTACK_GROWTH < 0
+ {
+ pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
+ }
+ #else
+ {
+ pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
+ }
+ #endif
+
+ uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack );
+
+ return uxReturn;
+ }
+
+#endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
+
+ UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
+ {
+ TCB_t * pxTCB;
+ uint8_t * pucEndOfStack;
+ UBaseType_t uxReturn;
+
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ #if portSTACK_GROWTH < 0
+ {
+ pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
+ }
+ #else
+ {
+ pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
+ }
+ #endif
+
+ uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
+
+ return uxReturn;
+ }
+
+#endif /* INCLUDE_uxTaskGetStackHighWaterMark */
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelete == 1 )
+
+ static void prvDeleteTCB( TCB_t * pxTCB )
+ {
+ /* This call is required specifically for the TriCore port. It must be
+ * above the vPortFree() calls. The call is also used by ports/demos that
+ * want to allocate and clean RAM statically. */
+ portCLEAN_UP_TCB( pxTCB );
+
+ #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
+ {
+ /* Free up the memory allocated for the task's TLS Block. */
+ configDEINIT_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
+ }
+ #endif
+
+ #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
+ {
+ /* The task can only have been allocated dynamically - free both
+ * the stack and TCB. */
+ vPortFreeStack( pxTCB->pxStack );
+ vPortFree( pxTCB );
+ }
+ #elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
+ {
+ /* The task could have been allocated statically or dynamically, so
+ * check what was statically allocated before trying to free the
+ * memory. */
+ if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
+ {
+ /* Both the stack and TCB were allocated dynamically, so both
+ * must be freed. */
+ vPortFreeStack( pxTCB->pxStack );
+ vPortFree( pxTCB );
+ }
+ else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
+ {
+ /* Only the stack was statically allocated, so the TCB is the
+ * only memory that must be freed. */
+ vPortFree( pxTCB );
+ }
+ else
+ {
+ /* Neither the stack nor the TCB were allocated dynamically, so
+ * nothing needs to be freed. */
+ configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB );
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+ }
+
+#endif /* INCLUDE_vTaskDelete */
+/*-----------------------------------------------------------*/
+
+static void prvResetNextTaskUnblockTime( void )
+{
+ if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
+ {
+ /* The new current delayed list is empty. Set xNextTaskUnblockTime to
+ * the maximum possible value so it is extremely unlikely that the
+ * if( xTickCount >= xNextTaskUnblockTime ) test will pass until
+ * there is an item in the delayed list. */
+ xNextTaskUnblockTime = portMAX_DELAY;
+ }
+ else
+ {
+ /* The new current delayed list is not empty, get the value of
+ * the item at the head of the delayed list. This is the time at
+ * which the task at the head of the delayed list should be removed
+ * from the Blocked state. */
+ xNextTaskUnblockTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxDelayedTaskList );
+ }
+}
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
+
+ TaskHandle_t xTaskGetCurrentTaskHandle( void )
+ {
+ TaskHandle_t xReturn;
+
+ /* A critical section is not required as this is not called from
+ * an interrupt and the current TCB will always be the same for any
+ * individual execution thread. */
+ xReturn = pxCurrentTCB;
+
+ return xReturn;
+ }
+
+#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+
+ BaseType_t xTaskGetSchedulerState( void )
+ {
+ BaseType_t xReturn;
+
+ if( xSchedulerRunning == pdFALSE )
+ {
+ xReturn = taskSCHEDULER_NOT_STARTED;
+ }
+ else
+ {
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
+ {
+ xReturn = taskSCHEDULER_RUNNING;
+ }
+ else
+ {
+ xReturn = taskSCHEDULER_SUSPENDED;
+ }
+ }
+
+ return xReturn;
+ }
+
+#endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+ BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
+ {
+ TCB_t * const pxMutexHolderTCB = pxMutexHolder;
+ BaseType_t xReturn = pdFALSE;
+
+ /* If the mutex was given back by an interrupt while the queue was
+ * locked then the mutex holder might now be NULL. _RB_ Is this still
+ * needed as interrupts can no longer use mutexes? */
+ if( pxMutexHolder != NULL )
+ {
+ /* If the holder of the mutex has a priority below the priority of
+ * the task attempting to obtain the mutex then it will temporarily
+ * inherit the priority of the task attempting to obtain the mutex. */
+ if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )
+ {
+ /* Adjust the mutex holder state to account for its new
+ * priority. Only reset the event list item value if the value is
+ * not being used for anything else. */
+ if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
+ {
+ listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* If the task being modified is in the ready state it will need
+ * to be moved into a new list. */
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )
+ {
+ if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
+ {
+ /* It is known that the task is in its ready list so
+ * there is no need to check again and the port level
+ * reset macro can be called directly. */
+ portRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority, uxTopReadyPriority );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Inherit the priority before being moved into the new list. */
+ pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
+ prvAddTaskToReadyList( pxMutexHolderTCB );
+ }
+ else
+ {
+ /* Just inherit the priority. */
+ pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
+ }
+
+ traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );
+
+ /* Inheritance occurred. */
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )
+ {
+ /* The base priority of the mutex holder is lower than the
+ * priority of the task attempting to take the mutex, but the
+ * current priority of the mutex holder is not lower than the
+ * priority of the task attempting to take the mutex.
+ * Therefore the mutex holder must have already inherited a
+ * priority, but inheritance would have occurred if that had
+ * not been the case. */
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+ BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
+ {
+ TCB_t * const pxTCB = pxMutexHolder;
+ BaseType_t xReturn = pdFALSE;
+
+ if( pxMutexHolder != NULL )
+ {
+ /* A task can only have an inherited priority if it holds the mutex.
+ * If the mutex is held by a task then it cannot be given from an
+ * interrupt, and if a mutex is given by the holding task then it must
+ * be the running state task. */
+ configASSERT( pxTCB == pxCurrentTCB );
+ configASSERT( pxTCB->uxMutexesHeld );
+ ( pxTCB->uxMutexesHeld )--;
+
+ /* Has the holder of the mutex inherited the priority of another
+ * task? */
+ if( pxTCB->uxPriority != pxTCB->uxBasePriority )
+ {
+ /* Only disinherit if no other mutexes are held. */
+ if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
+ {
+ /* A task can only have an inherited priority if it holds
+ * the mutex. If the mutex is held by a task then it cannot be
+ * given from an interrupt, and if a mutex is given by the
+ * holding task then it must be the running state task. Remove
+ * the holding task from the ready list. */
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
+ {
+ portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Disinherit the priority before adding the task into the
+ * new ready list. */
+ traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
+ pxTCB->uxPriority = pxTCB->uxBasePriority;
+
+ /* Reset the event list item value. It cannot be in use for
+ * any other purpose if this task is running, and it must be
+ * running to give back the mutex. */
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ prvAddTaskToReadyList( pxTCB );
+
+ /* Return true to indicate that a context switch is required.
+ * This is only actually required in the corner case whereby
+ * multiple mutexes were held and the mutexes were given back
+ * in an order different to that in which they were taken.
+ * If a context switch did not occur when the first mutex was
+ * returned, even if a task was waiting on it, then a context
+ * switch should occur when the last mutex is returned whether
+ * a task is waiting on it or not. */
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xReturn;
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+ void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder,
+ UBaseType_t uxHighestPriorityWaitingTask )
+ {
+ TCB_t * const pxTCB = pxMutexHolder;
+ UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;
+ const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;
+
+ if( pxMutexHolder != NULL )
+ {
+ /* If pxMutexHolder is not NULL then the holder must hold at least
+ * one mutex. */
+ configASSERT( pxTCB->uxMutexesHeld );
+
+ /* Determine the priority to which the priority of the task that
+ * holds the mutex should be set. This will be the greater of the
+ * holding task's base priority and the priority of the highest
+ * priority task that is waiting to obtain the mutex. */
+ if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )
+ {
+ uxPriorityToUse = uxHighestPriorityWaitingTask;
+ }
+ else
+ {
+ uxPriorityToUse = pxTCB->uxBasePriority;
+ }
+
+ /* Does the priority need to change? */
+ if( pxTCB->uxPriority != uxPriorityToUse )
+ {
+ /* Only disinherit if no other mutexes are held. This is a
+ * simplification in the priority inheritance implementation. If
+ * the task that holds the mutex is also holding other mutexes then
+ * the other mutexes may have caused the priority inheritance. */
+ if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )
+ {
+ /* If a task has timed out because it already holds the
+ * mutex it was trying to obtain then it cannot of inherited
+ * its own priority. */
+ configASSERT( pxTCB != pxCurrentTCB );
+
+ /* Disinherit the priority, remembering the previous
+ * priority to facilitate determining the subject task's
+ * state. */
+ traceTASK_PRIORITY_DISINHERIT( pxTCB, uxPriorityToUse );
+ uxPriorityUsedOnEntry = pxTCB->uxPriority;
+ pxTCB->uxPriority = uxPriorityToUse;
+
+ /* Only reset the event list item value if the value is not
+ * being used for anything else. */
+ if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
+ {
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* If the running task is not the task that holds the mutex
+ * then the task that holds the mutex could be in either the
+ * Ready, Blocked or Suspended states. Only remove the task
+ * from its current state list if it is in the Ready state as
+ * the task's priority is going to change and there is one
+ * Ready list per priority. */
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
+ {
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
+ {
+ /* It is known that the task is in its ready list so
+ * there is no need to check again and the port level
+ * reset macro can be called directly. */
+ portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ prvAddTaskToReadyList( pxTCB );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+
+ void vTaskEnterCritical( void )
+ {
+ portDISABLE_INTERRUPTS();
+
+ if( xSchedulerRunning != pdFALSE )
+ {
+ ( pxCurrentTCB->uxCriticalNesting )++;
+
+ /* This is not the interrupt safe version of the enter critical
+ * function so assert() if it is being called from an interrupt
+ * context. Only API functions that end in "FromISR" can be used in an
+ * interrupt. Only assert if the critical nesting count is 1 to
+ * protect against recursive calls if the assert function also uses a
+ * critical section. */
+ if( pxCurrentTCB->uxCriticalNesting == 1 )
+ {
+ portASSERT_IF_IN_ISR();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+#endif /* portCRITICAL_NESTING_IN_TCB */
+/*-----------------------------------------------------------*/
+
+#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+
+ void vTaskExitCritical( void )
+ {
+ if( xSchedulerRunning != pdFALSE )
+ {
+ if( pxCurrentTCB->uxCriticalNesting > 0U )
+ {
+ ( pxCurrentTCB->uxCriticalNesting )--;
+
+ if( pxCurrentTCB->uxCriticalNesting == 0U )
+ {
+ portENABLE_INTERRUPTS();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+#endif /* portCRITICAL_NESTING_IN_TCB */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
+
+ static char * prvWriteNameToBuffer( char * pcBuffer,
+ const char * pcTaskName )
+ {
+ size_t x;
+
+ /* Start by copying the entire string. */
+ strcpy( pcBuffer, pcTaskName );
+
+ /* Pad the end of the string with spaces to ensure columns line up when
+ * printed out. */
+ for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ )
+ {
+ pcBuffer[ x ] = ' ';
+ }
+
+ /* Terminate. */
+ pcBuffer[ x ] = ( char ) 0x00;
+
+ /* Return the new end of string. */
+ return &( pcBuffer[ x ] );
+ }
+
+#endif /* ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+
+ void vTaskList( char * pcWriteBuffer )
+ {
+ TaskStatus_t * pxTaskStatusArray;
+ UBaseType_t uxArraySize, x;
+ char cStatus;
+
+ /*
+ * PLEASE NOTE:
+ *
+ * This function is provided for convenience only, and is used by many
+ * of the demo applications. Do not consider it to be part of the
+ * scheduler.
+ *
+ * vTaskList() calls uxTaskGetSystemState(), then formats part of the
+ * uxTaskGetSystemState() output into a human readable table that
+ * displays task: names, states, priority, stack usage and task number.
+ * Stack usage specified as the number of unused StackType_t words stack can hold
+ * on top of stack - not the number of bytes.
+ *
+ * vTaskList() has a dependency on the sprintf() C library function that
+ * might bloat the code size, use a lot of stack, and provide different
+ * results on different platforms. An alternative, tiny, third party,
+ * and limited functionality implementation of sprintf() is provided in
+ * many of the FreeRTOS/Demo sub-directories in a file called
+ * printf-stdarg.c (note printf-stdarg.c does not provide a full
+ * snprintf() implementation!).
+ *
+ * It is recommended that production systems call uxTaskGetSystemState()
+ * directly to get access to raw stats data, rather than indirectly
+ * through a call to vTaskList().
+ */
+
+
+ /* Make sure the write buffer does not contain a string. */
+ *pcWriteBuffer = ( char ) 0x00;
+
+ /* Take a snapshot of the number of tasks in case it changes while this
+ * function is executing. */
+ uxArraySize = uxCurrentNumberOfTasks;
+
+ /* Allocate an array index for each task. NOTE! if
+ * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
+ * equate to NULL. */
+ pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */
+
+ if( pxTaskStatusArray != NULL )
+ {
+ /* Generate the (binary) data. */
+ uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
+
+ /* Create a human readable table from the binary data. */
+ for( x = 0; x < uxArraySize; x++ )
+ {
+ switch( pxTaskStatusArray[ x ].eCurrentState )
+ {
+ case eRunning:
+ cStatus = tskRUNNING_CHAR;
+ break;
+
+ case eReady:
+ cStatus = tskREADY_CHAR;
+ break;
+
+ case eBlocked:
+ cStatus = tskBLOCKED_CHAR;
+ break;
+
+ case eSuspended:
+ cStatus = tskSUSPENDED_CHAR;
+ break;
+
+ case eDeleted:
+ cStatus = tskDELETED_CHAR;
+ break;
+
+ case eInvalid: /* Fall through. */
+ default: /* Should not get here, but it is included
+ * to prevent static checking errors. */
+ cStatus = ( char ) 0x00;
+ break;
+ }
+
+ /* Write the task name to the string, padding with spaces so it
+ * can be printed in tabular form more easily. */
+ pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
+
+ /* Write the rest of the string. */
+ sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
+ pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
+ }
+
+ /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
+ * is 0 then vPortFree() will be #defined to nothing. */
+ vPortFree( pxTaskStatusArray );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
+/*----------------------------------------------------------*/
+
+#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) )
+
+ void vTaskGetRunTimeStats( char * pcWriteBuffer )
+ {
+ TaskStatus_t * pxTaskStatusArray;
+ UBaseType_t uxArraySize, x;
+ configRUN_TIME_COUNTER_TYPE ulTotalTime, ulStatsAsPercentage;
+
+ /*
+ * PLEASE NOTE:
+ *
+ * This function is provided for convenience only, and is used by many
+ * of the demo applications. Do not consider it to be part of the
+ * scheduler.
+ *
+ * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
+ * of the uxTaskGetSystemState() output into a human readable table that
+ * displays the amount of time each task has spent in the Running state
+ * in both absolute and percentage terms.
+ *
+ * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
+ * function that might bloat the code size, use a lot of stack, and
+ * provide different results on different platforms. An alternative,
+ * tiny, third party, and limited functionality implementation of
+ * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
+ * a file called printf-stdarg.c (note printf-stdarg.c does not provide
+ * a full snprintf() implementation!).
+ *
+ * It is recommended that production systems call uxTaskGetSystemState()
+ * directly to get access to raw stats data, rather than indirectly
+ * through a call to vTaskGetRunTimeStats().
+ */
+
+ /* Make sure the write buffer does not contain a string. */
+ *pcWriteBuffer = ( char ) 0x00;
+
+ /* Take a snapshot of the number of tasks in case it changes while this
+ * function is executing. */
+ uxArraySize = uxCurrentNumberOfTasks;
+
+ /* Allocate an array index for each task. NOTE! If
+ * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
+ * equate to NULL. */
+ pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */
+
+ if( pxTaskStatusArray != NULL )
+ {
+ /* Generate the (binary) data. */
+ uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
+
+ /* For percentage calculations. */
+ ulTotalTime /= 100UL;
+
+ /* Avoid divide by zero errors. */
+ if( ulTotalTime > 0UL )
+ {
+ /* Create a human readable table from the binary data. */
+ for( x = 0; x < uxArraySize; x++ )
+ {
+ /* What percentage of the total run time has the task used?
+ * This will always be rounded down to the nearest integer.
+ * ulTotalRunTime has already been divided by 100. */
+ ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
+
+ /* Write the task name to the string, padding with
+ * spaces so it can be printed in tabular form more
+ * easily. */
+ pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
+
+ if( ulStatsAsPercentage > 0UL )
+ {
+ #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
+ {
+ sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
+ }
+ #else
+ {
+ /* sizeof( int ) == sizeof( long ) so a smaller
+ * printf() library can be used. */
+ sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
+ }
+ #endif
+ }
+ else
+ {
+ /* If the percentage is zero here then the task has
+ * consumed less than 1% of the total run time. */
+ #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
+ {
+ sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );
+ }
+ #else
+ {
+ /* sizeof( int ) == sizeof( long ) so a smaller
+ * printf() library can be used. */
+ sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
+ }
+ #endif
+ }
+
+ pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
+ * is 0 then vPortFree() will be #defined to nothing. */
+ vPortFree( pxTaskStatusArray );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
+/*-----------------------------------------------------------*/
+
+TickType_t uxTaskResetEventItemValue( void )
+{
+ TickType_t uxReturn;
+
+ uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
+
+ /* Reset the event list item to its normal value - so it can be used with
+ * queues and semaphores. */
+ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+ TaskHandle_t pvTaskIncrementMutexHeldCount( void )
+ {
+ /* If xSemaphoreCreateMutex() is called before any tasks have been created
+ * then pxCurrentTCB will be NULL. */
+ if( pxCurrentTCB != NULL )
+ {
+ ( pxCurrentTCB->uxMutexesHeld )++;
+ }
+
+ return pxCurrentTCB;
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+ uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait,
+ BaseType_t xClearCountOnExit,
+ TickType_t xTicksToWait )
+ {
+ uint32_t ulReturn;
+
+ configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
+
+ taskENTER_CRITICAL();
+ {
+ /* Only block if the notification count is not already non-zero. */
+ if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
+ {
+ /* Mark this task as waiting for a notification. */
+ pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
+
+ if( xTicksToWait > ( TickType_t ) 0 )
+ {
+ prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
+ traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait );
+
+ /* All ports are written to allow a yield in a critical
+ * section (some will yield immediately, others wait until the
+ * critical section exits) - but it is not something that
+ * application code should ever do. */
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ taskENTER_CRITICAL();
+ {
+ traceTASK_NOTIFY_TAKE( uxIndexToWait );
+ ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
+
+ if( ulReturn != 0UL )
+ {
+ if( xClearCountOnExit != pdFALSE )
+ {
+ pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL;
+ }
+ else
+ {
+ pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1;
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
+ }
+ taskEXIT_CRITICAL();
+
+ return ulReturn;
+ }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait,
+ uint32_t ulBitsToClearOnEntry,
+ uint32_t ulBitsToClearOnExit,
+ uint32_t * pulNotificationValue,
+ TickType_t xTicksToWait )
+ {
+ BaseType_t xReturn;
+
+ configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
+
+ taskENTER_CRITICAL();
+ {
+ /* Only block if a notification is not already pending. */
+ if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
+ {
+ /* Clear bits in the task's notification value as bits may get
+ * set by the notifying task or interrupt. This can be used to
+ * clear the value to zero. */
+ pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;
+
+ /* Mark this task as waiting for a notification. */
+ pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
+
+ if( xTicksToWait > ( TickType_t ) 0 )
+ {
+ prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
+ traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait );
+
+ /* All ports are written to allow a yield in a critical
+ * section (some will yield immediately, others wait until the
+ * critical section exits) - but it is not something that
+ * application code should ever do. */
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ taskENTER_CRITICAL();
+ {
+ traceTASK_NOTIFY_WAIT( uxIndexToWait );
+
+ if( pulNotificationValue != NULL )
+ {
+ /* Output the current notification value, which may or may not
+ * have changed. */
+ *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
+ }
+
+ /* If ucNotifyValue is set then either the task never entered the
+ * blocked state (because a notification was already pending) or the
+ * task unblocked because of a notification. Otherwise the task
+ * unblocked because of a timeout. */
+ if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
+ {
+ /* A notification was not received. */
+ xReturn = pdFALSE;
+ }
+ else
+ {
+ /* A notification was already pending or a notification was
+ * received while the task was waiting. */
+ pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit;
+ xReturn = pdTRUE;
+ }
+
+ pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+ }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
+ UBaseType_t uxIndexToNotify,
+ uint32_t ulValue,
+ eNotifyAction eAction,
+ uint32_t * pulPreviousNotificationValue )
+ {
+ TCB_t * pxTCB;
+ BaseType_t xReturn = pdPASS;
+ uint8_t ucOriginalNotifyState;
+
+ configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
+ configASSERT( xTaskToNotify );
+ pxTCB = xTaskToNotify;
+
+ taskENTER_CRITICAL();
+ {
+ if( pulPreviousNotificationValue != NULL )
+ {
+ *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
+ }
+
+ ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
+
+ pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
+
+ switch( eAction )
+ {
+ case eSetBits:
+ pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
+ break;
+
+ case eIncrement:
+ ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
+ break;
+
+ case eSetValueWithOverwrite:
+ pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
+ break;
+
+ case eSetValueWithoutOverwrite:
+
+ if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
+ {
+ pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
+ }
+ else
+ {
+ /* The value could not be written to the task. */
+ xReturn = pdFAIL;
+ }
+
+ break;
+
+ case eNoAction:
+
+ /* The task is being notified without its notify value being
+ * updated. */
+ break;
+
+ default:
+
+ /* Should not get here if all enums are handled.
+ * Artificially force an assert by testing a value the
+ * compiler can't assume is const. */
+ configASSERT( xTickCount == ( TickType_t ) 0 );
+
+ break;
+ }
+
+ traceTASK_NOTIFY( uxIndexToNotify );
+
+ /* If the task is in the blocked state specifically to wait for a
+ * notification then unblock it now. */
+ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
+ {
+ listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
+ prvAddTaskToReadyList( pxTCB );
+
+ /* The task should not have been on an event list. */
+ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
+
+ #if ( configUSE_TICKLESS_IDLE != 0 )
+ {
+ /* If a task is blocked waiting for a notification then
+ * xNextTaskUnblockTime might be set to the blocked task's time
+ * out time. If the task is unblocked for a reason other than
+ * a timeout xNextTaskUnblockTime is normally left unchanged,
+ * because it will automatically get reset to a new value when
+ * the tick count equals xNextTaskUnblockTime. However if
+ * tickless idling is used it might be more important to enter
+ * sleep mode at the earliest possible time - so reset
+ * xNextTaskUnblockTime here to ensure it is updated at the
+ * earliest possible time. */
+ prvResetNextTaskUnblockTime();
+ }
+ #endif
+
+ if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
+ {
+ /* The notified task has a priority above the currently
+ * executing task so a yield is required. */
+ taskYIELD_IF_USING_PREEMPTION();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+ }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
+ UBaseType_t uxIndexToNotify,
+ uint32_t ulValue,
+ eNotifyAction eAction,
+ uint32_t * pulPreviousNotificationValue,
+ BaseType_t * pxHigherPriorityTaskWoken )
+ {
+ TCB_t * pxTCB;
+ uint8_t ucOriginalNotifyState;
+ BaseType_t xReturn = pdPASS;
+ UBaseType_t uxSavedInterruptStatus;
+
+ configASSERT( xTaskToNotify );
+ configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
+
+ /* RTOS ports that support interrupt nesting have the concept of a
+ * maximum system call (or maximum API call) interrupt priority.
+ * Interrupts that are above the maximum system call priority are keep
+ * permanently enabled, even when the RTOS kernel is in a critical section,
+ * but cannot make any calls to FreeRTOS API functions. If configASSERT()
+ * is defined in FreeRTOSConfig.h then
+ * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ * failure if a FreeRTOS API function is called from an interrupt that has
+ * been assigned a priority above the configured maximum system call
+ * priority. Only FreeRTOS functions that end in FromISR can be called
+ * from interrupts that have been assigned a priority at or (logically)
+ * below the maximum system call interrupt priority. FreeRTOS maintains a
+ * separate interrupt safe API to ensure interrupt entry is as fast and as
+ * simple as possible. More information (albeit Cortex-M specific) is
+ * provided on the following link:
+ * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ pxTCB = xTaskToNotify;
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ if( pulPreviousNotificationValue != NULL )
+ {
+ *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
+ }
+
+ ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
+ pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
+
+ switch( eAction )
+ {
+ case eSetBits:
+ pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
+ break;
+
+ case eIncrement:
+ ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
+ break;
+
+ case eSetValueWithOverwrite:
+ pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
+ break;
+
+ case eSetValueWithoutOverwrite:
+
+ if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
+ {
+ pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
+ }
+ else
+ {
+ /* The value could not be written to the task. */
+ xReturn = pdFAIL;
+ }
+
+ break;
+
+ case eNoAction:
+
+ /* The task is being notified without its notify value being
+ * updated. */
+ break;
+
+ default:
+
+ /* Should not get here if all enums are handled.
+ * Artificially force an assert by testing a value the
+ * compiler can't assume is const. */
+ configASSERT( xTickCount == ( TickType_t ) 0 );
+ break;
+ }
+
+ traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify );
+
+ /* If the task is in the blocked state specifically to wait for a
+ * notification then unblock it now. */
+ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
+ {
+ /* The task should not have been on an event list. */
+ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
+
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
+ {
+ listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
+ prvAddTaskToReadyList( pxTCB );
+ }
+ else
+ {
+ /* The delayed and ready lists cannot be accessed, so hold
+ * this task pending until the scheduler is resumed. */
+ listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
+ }
+
+ if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
+ {
+ /* The notified task has a priority above the currently
+ * executing task so a yield is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+
+ /* Mark that a yield is pending in case the user is not
+ * using the "xHigherPriorityTaskWoken" parameter to an ISR
+ * safe FreeRTOS function. */
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ return xReturn;
+ }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+ void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
+ UBaseType_t uxIndexToNotify,
+ BaseType_t * pxHigherPriorityTaskWoken )
+ {
+ TCB_t * pxTCB;
+ uint8_t ucOriginalNotifyState;
+ UBaseType_t uxSavedInterruptStatus;
+
+ configASSERT( xTaskToNotify );
+ configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
+
+ /* RTOS ports that support interrupt nesting have the concept of a
+ * maximum system call (or maximum API call) interrupt priority.
+ * Interrupts that are above the maximum system call priority are keep
+ * permanently enabled, even when the RTOS kernel is in a critical section,
+ * but cannot make any calls to FreeRTOS API functions. If configASSERT()
+ * is defined in FreeRTOSConfig.h then
+ * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
+ * failure if a FreeRTOS API function is called from an interrupt that has
+ * been assigned a priority above the configured maximum system call
+ * priority. Only FreeRTOS functions that end in FromISR can be called
+ * from interrupts that have been assigned a priority at or (logically)
+ * below the maximum system call interrupt priority. FreeRTOS maintains a
+ * separate interrupt safe API to ensure interrupt entry is as fast and as
+ * simple as possible. More information (albeit Cortex-M specific) is
+ * provided on the following link:
+ * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
+
+ pxTCB = xTaskToNotify;
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
+ pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
+
+ /* 'Giving' is equivalent to incrementing a count in a counting
+ * semaphore. */
+ ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
+
+ traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify );
+
+ /* If the task is in the blocked state specifically to wait for a
+ * notification then unblock it now. */
+ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
+ {
+ /* The task should not have been on an event list. */
+ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
+
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
+ {
+ listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
+ prvAddTaskToReadyList( pxTCB );
+ }
+ else
+ {
+ /* The delayed and ready lists cannot be accessed, so hold
+ * this task pending until the scheduler is resumed. */
+ listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
+ }
+
+ if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
+ {
+ /* The notified task has a priority above the currently
+ * executing task so a yield is required. */
+ if( pxHigherPriorityTaskWoken != NULL )
+ {
+ *pxHigherPriorityTaskWoken = pdTRUE;
+ }
+
+ /* Mark that a yield is pending in case the user is not
+ * using the "xHigherPriorityTaskWoken" parameter in an ISR
+ * safe FreeRTOS function. */
+ xYieldPending = pdTRUE;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+ }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+ BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
+ UBaseType_t uxIndexToClear )
+ {
+ TCB_t * pxTCB;
+ BaseType_t xReturn;
+
+ configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
+
+ /* If null is passed in here then it is the calling task that is having
+ * its notification state cleared. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ taskENTER_CRITICAL();
+ {
+ if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED )
+ {
+ pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION;
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+ }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+ uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
+ UBaseType_t uxIndexToClear,
+ uint32_t ulBitsToClear )
+ {
+ TCB_t * pxTCB;
+ uint32_t ulReturn;
+
+ /* If null is passed in here then it is the calling task that is having
+ * its notification state cleared. */
+ pxTCB = prvGetTCBFromHandle( xTask );
+
+ taskENTER_CRITICAL();
+ {
+ /* Return the notification as it was before the bits were cleared,
+ * then clear the bit mask. */
+ ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
+ pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
+ }
+ taskEXIT_CRITICAL();
+
+ return ulReturn;
+ }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
+
+ configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void )
+ {
+ return xIdleTaskHandle->ulRunTimeCounter;
+ }
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
+
+ configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void )
+ {
+ configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
+
+ ulTotalTime = portGET_RUN_TIME_COUNTER_VALUE();
+
+ /* For percentage calculations. */
+ ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
+
+ /* Avoid divide by zero errors. */
+ if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
+ {
+ ulReturn = xIdleTaskHandle->ulRunTimeCounter / ulTotalTime;
+ }
+ else
+ {
+ ulReturn = 0;
+ }
+
+ return ulReturn;
+ }
+
+#endif /* if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
+ const BaseType_t xCanBlockIndefinitely )
+{
+ TickType_t xTimeToWake;
+ const TickType_t xConstTickCount = xTickCount;
+
+ #if ( INCLUDE_xTaskAbortDelay == 1 )
+ {
+ /* About to enter a delayed list, so ensure the ucDelayAborted flag is
+ * reset to pdFALSE so it can be detected as having been set to pdTRUE
+ * when the task leaves the Blocked state. */
+ pxCurrentTCB->ucDelayAborted = pdFALSE;
+ }
+ #endif
+
+ /* Remove the task from the ready list before adding it to the blocked list
+ * as the same list item is used for both lists. */
+ if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
+ {
+ /* The current task must be in a ready list, so there is no need to
+ * check, and the port reset macro can be called directly. */
+ portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); /*lint !e931 pxCurrentTCB cannot change as it is the calling task. pxCurrentTCB->uxPriority and uxTopReadyPriority cannot change as called with scheduler suspended or in a critical section. */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ #if ( INCLUDE_vTaskSuspend == 1 )
+ {
+ if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
+ {
+ /* Add the task to the suspended task list instead of a delayed task
+ * list to ensure it is not woken by a timing event. It will block
+ * indefinitely. */
+ listINSERT_END( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
+ }
+ else
+ {
+ /* Calculate the time at which the task should be woken if the event
+ * does not occur. This may overflow but this doesn't matter, the
+ * kernel will manage it correctly. */
+ xTimeToWake = xConstTickCount + xTicksToWait;
+
+ /* The list item will be inserted in wake time order. */
+ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
+
+ if( xTimeToWake < xConstTickCount )
+ {
+ /* Wake time has overflowed. Place this item in the overflow
+ * list. */
+ vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
+ }
+ else
+ {
+ /* The wake time has not overflowed, so the current block list
+ * is used. */
+ vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
+
+ /* If the task entering the blocked state was placed at the
+ * head of the list of blocked tasks then xNextTaskUnblockTime
+ * needs to be updated too. */
+ if( xTimeToWake < xNextTaskUnblockTime )
+ {
+ xNextTaskUnblockTime = xTimeToWake;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ }
+ #else /* INCLUDE_vTaskSuspend */
+ {
+ /* Calculate the time at which the task should be woken if the event
+ * does not occur. This may overflow but this doesn't matter, the kernel
+ * will manage it correctly. */
+ xTimeToWake = xConstTickCount + xTicksToWait;
+
+ /* The list item will be inserted in wake time order. */
+ listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
+
+ if( xTimeToWake < xConstTickCount )
+ {
+ /* Wake time has overflowed. Place this item in the overflow list. */
+ vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
+ }
+ else
+ {
+ /* The wake time has not overflowed, so the current block list is used. */
+ vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
+
+ /* If the task entering the blocked state was placed at the head of the
+ * list of blocked tasks then xNextTaskUnblockTime needs to be updated
+ * too. */
+ if( xTimeToWake < xNextTaskUnblockTime )
+ {
+ xNextTaskUnblockTime = xTimeToWake;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+
+ /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
+ ( void ) xCanBlockIndefinitely;
+ }
+ #endif /* INCLUDE_vTaskSuspend */
+}
+
+/* Code below here allows additional code to be inserted into this source file,
+ * especially where access to file scope functions and data is needed (for example
+ * when performing module tests). */
+
+#ifdef FREERTOS_MODULE_TEST
+ #include "tasks_test_access_functions.h"
+#endif
+
+
+#if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
+
+ #include "freertos_tasks_c_additions.h"
+
+ #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
+ static void freertos_tasks_c_additions_init( void )
+ {
+ FREERTOS_TASKS_C_ADDITIONS_INIT();
+ }
+ #endif
+
+#endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */
diff --git a/source/test/freertos/src/timers.c b/source/test/freertos/src/timers.c
new file mode 100644
index 0000000..800a2b8
--- /dev/null
+++ b/source/test/freertos/src/timers.c
@@ -0,0 +1,1124 @@
+/*
+ * FreeRTOS Kernel V10.5.1
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/* Standard includes. */
+#include
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+ * all the API functions to use the MPU wrappers. That should only be done when
+ * task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "timers.h"
+
+#if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 )
+ #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available.
+#endif
+
+/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
+ * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
+ * for the header files above, but not in this file, in order to generate the
+ * correct privileged Vs unprivileged linkage and placement. */
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e9021 !e961 !e750. */
+
+
+/* This entire source file will be skipped if the application is not configured
+ * to include software timer functionality. This #if is closed at the very bottom
+ * of this file. If you want to include software timer functionality then ensure
+ * configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
+#if ( configUSE_TIMERS == 1 )
+
+/* Misc definitions. */
+ #define tmrNO_DELAY ( ( TickType_t ) 0U )
+ #define tmrMAX_TIME_BEFORE_OVERFLOW ( ( TickType_t ) -1 )
+
+/* The name assigned to the timer service task. This can be overridden by
+ * defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */
+ #ifndef configTIMER_SERVICE_TASK_NAME
+ #define configTIMER_SERVICE_TASK_NAME "Tmr Svc"
+ #endif
+
+/* Bit definitions used in the ucStatus member of a timer structure. */
+ #define tmrSTATUS_IS_ACTIVE ( ( uint8_t ) 0x01 )
+ #define tmrSTATUS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 0x02 )
+ #define tmrSTATUS_IS_AUTORELOAD ( ( uint8_t ) 0x04 )
+
+/* The definition of the timers themselves. */
+ typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */
+ {
+ const char * pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */
+ TickType_t xTimerPeriodInTicks; /*<< How quickly and often the timer expires. */
+ void * pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */
+ TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */
+ #endif
+ uint8_t ucStatus; /*<< Holds bits to say if the timer was statically allocated or not, and if it is active or not. */
+ } xTIMER;
+
+/* The old xTIMER name is maintained above then typedefed to the new Timer_t
+ * name below to enable the use of older kernel aware debuggers. */
+ typedef xTIMER Timer_t;
+
+/* The definition of messages that can be sent and received on the timer queue.
+ * Two types of message can be queued - messages that manipulate a software timer,
+ * and messages that request the execution of a non-timer related callback. The
+ * two message types are defined in two separate structures, xTimerParametersType
+ * and xCallbackParametersType respectively. */
+ typedef struct tmrTimerParameters
+ {
+ TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */
+ Timer_t * pxTimer; /*<< The timer to which the command will be applied. */
+ } TimerParameter_t;
+
+
+ typedef struct tmrCallbackParameters
+ {
+ PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */
+ void * pvParameter1; /* << The value that will be used as the callback functions first parameter. */
+ uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */
+ } CallbackParameters_t;
+
+/* The structure that contains the two message types, along with an identifier
+ * that is used to determine which message type is valid. */
+ typedef struct tmrTimerQueueMessage
+ {
+ BaseType_t xMessageID; /*<< The command being sent to the timer service task. */
+ union
+ {
+ TimerParameter_t xTimerParameters;
+
+ /* Don't include xCallbackParameters if it is not going to be used as
+ * it makes the structure (and therefore the timer queue) larger. */
+ #if ( INCLUDE_xTimerPendFunctionCall == 1 )
+ CallbackParameters_t xCallbackParameters;
+ #endif /* INCLUDE_xTimerPendFunctionCall */
+ } u;
+ } DaemonTaskMessage_t;
+
+/*lint -save -e956 A manual analysis and inspection has been used to determine
+ * which static variables must be declared volatile. */
+
+/* The list in which active timers are stored. Timers are referenced in expire
+ * time order, with the nearest expiry time at the front of the list. Only the
+ * timer service task is allowed to access these lists.
+ * xActiveTimerList1 and xActiveTimerList2 could be at function scope but that
+ * breaks some kernel aware debuggers, and debuggers that reply on removing the
+ * static qualifier. */
+ PRIVILEGED_DATA static List_t xActiveTimerList1;
+ PRIVILEGED_DATA static List_t xActiveTimerList2;
+ PRIVILEGED_DATA static List_t * pxCurrentTimerList;
+ PRIVILEGED_DATA static List_t * pxOverflowTimerList;
+
+/* A queue that is used to send commands to the timer service task. */
+ PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
+ PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
+
+/*lint -restore */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Initialise the infrastructure used by the timer service task if it has not
+ * been initialised already.
+ */
+ static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * The timer service task (daemon). Timer functionality is controlled by this
+ * task. Other tasks communicate with the timer service task using the
+ * xTimerQueue queue.
+ */
+ static portTASK_FUNCTION_PROTO( prvTimerTask, pvParameters ) PRIVILEGED_FUNCTION;
+
+/*
+ * Called by the timer service task to interpret and process a command it
+ * received on the timer queue.
+ */
+ static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Insert the timer into either xActiveTimerList1, or xActiveTimerList2,
+ * depending on if the expire time causes a timer counter overflow.
+ */
+ static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer,
+ const TickType_t xNextExpiryTime,
+ const TickType_t xTimeNow,
+ const TickType_t xCommandTime ) PRIVILEGED_FUNCTION;
+
+/*
+ * Reload the specified auto-reload timer. If the reloading is backlogged,
+ * clear the backlog, calling the callback for each additional reload. When
+ * this function returns, the next expiry time is after xTimeNow.
+ */
+ static void prvReloadTimer( Timer_t * const pxTimer,
+ TickType_t xExpiredTime,
+ const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;
+
+/*
+ * An active timer has reached its expire time. Reload the timer if it is an
+ * auto-reload timer, then call its callback.
+ */
+ static void prvProcessExpiredTimer( const TickType_t xNextExpireTime,
+ const TickType_t xTimeNow ) PRIVILEGED_FUNCTION;
+
+/*
+ * The tick count has overflowed. Switch the timer lists after ensuring the
+ * current timer list does not still reference some timers.
+ */
+ static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE
+ * if a tick count overflow occurred since prvSampleTimeNow() was last called.
+ */
+ static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION;
+
+/*
+ * If the timer list contains any active timers then return the expire time of
+ * the timer that will expire first and set *pxListWasEmpty to false. If the
+ * timer list does not contain any timers then return 0 and set *pxListWasEmpty
+ * to pdTRUE.
+ */
+ static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION;
+
+/*
+ * If a timer has expired, process it. Otherwise, block the timer service task
+ * until either a timer does expire or a command is received.
+ */
+ static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime,
+ BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION;
+
+/*
+ * Called after a Timer_t structure has been allocated either statically or
+ * dynamically to fill in the structure's members.
+ */
+ static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const TickType_t xTimerPeriodInTicks,
+ const BaseType_t xAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction,
+ Timer_t * pxNewTimer ) PRIVILEGED_FUNCTION;
+/*-----------------------------------------------------------*/
+
+ BaseType_t xTimerCreateTimerTask( void )
+ {
+ BaseType_t xReturn = pdFAIL;
+
+ /* This function is called when the scheduler is started if
+ * configUSE_TIMERS is set to 1. Check that the infrastructure used by the
+ * timer service task has been created/initialised. If timers have already
+ * been created then the initialisation will already have been performed. */
+ prvCheckForValidListAndQueue();
+
+ if( xTimerQueue != NULL )
+ {
+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ StaticTask_t * pxTimerTaskTCBBuffer = NULL;
+ StackType_t * pxTimerTaskStackBuffer = NULL;
+ uint32_t ulTimerTaskStackSize;
+
+ vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );
+ xTimerTaskHandle = xTaskCreateStatic( prvTimerTask,
+ configTIMER_SERVICE_TASK_NAME,
+ ulTimerTaskStackSize,
+ NULL,
+ ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
+ pxTimerTaskStackBuffer,
+ pxTimerTaskTCBBuffer );
+
+ if( xTimerTaskHandle != NULL )
+ {
+ xReturn = pdPASS;
+ }
+ }
+ #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
+ {
+ xReturn = xTaskCreate( prvTimerTask,
+ configTIMER_SERVICE_TASK_NAME,
+ configTIMER_TASK_STACK_DEPTH,
+ NULL,
+ ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
+ &xTimerTaskHandle );
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ configASSERT( xReturn );
+ return xReturn;
+ }
+/*-----------------------------------------------------------*/
+
+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+
+ TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const TickType_t xTimerPeriodInTicks,
+ const BaseType_t xAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction )
+ {
+ Timer_t * pxNewTimer;
+
+ pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of Timer_t is always a pointer to the timer's mame. */
+
+ if( pxNewTimer != NULL )
+ {
+ /* Status is thus far zero as the timer is not created statically
+ * and has not been started. The auto-reload bit may get set in
+ * prvInitialiseNewTimer. */
+ pxNewTimer->ucStatus = 0x00;
+ prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
+ }
+
+ return pxNewTimer;
+ }
+
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
+ TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const TickType_t xTimerPeriodInTicks,
+ const BaseType_t xAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction,
+ StaticTimer_t * pxTimerBuffer )
+ {
+ Timer_t * pxNewTimer;
+
+ #if ( configASSERT_DEFINED == 1 )
+ {
+ /* Sanity check that the size of the structure used to declare a
+ * variable of type StaticTimer_t equals the size of the real timer
+ * structure. */
+ volatile size_t xSize = sizeof( StaticTimer_t );
+ configASSERT( xSize == sizeof( Timer_t ) );
+ ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */
+ }
+ #endif /* configASSERT_DEFINED */
+
+ /* A pointer to a StaticTimer_t structure MUST be provided, use it. */
+ configASSERT( pxTimerBuffer );
+ pxNewTimer = ( Timer_t * ) pxTimerBuffer; /*lint !e740 !e9087 StaticTimer_t is a pointer to a Timer_t, so guaranteed to be aligned and sized correctly (checked by an assert()), so this is safe. */
+
+ if( pxNewTimer != NULL )
+ {
+ /* Timers can be created statically or dynamically so note this
+ * timer was created statically in case it is later deleted. The
+ * auto-reload bit may get set in prvInitialiseNewTimer(). */
+ pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED;
+
+ prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, xAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );
+ }
+
+ return pxNewTimer;
+ }
+
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+ static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ const TickType_t xTimerPeriodInTicks,
+ const BaseType_t xAutoReload,
+ void * const pvTimerID,
+ TimerCallbackFunction_t pxCallbackFunction,
+ Timer_t * pxNewTimer )
+ {
+ /* 0 is not a valid value for xTimerPeriodInTicks. */
+ configASSERT( ( xTimerPeriodInTicks > 0 ) );
+
+ /* Ensure the infrastructure used by the timer service task has been
+ * created/initialised. */
+ prvCheckForValidListAndQueue();
+
+ /* Initialise the timer structure members using the function
+ * parameters. */
+ pxNewTimer->pcTimerName = pcTimerName;
+ pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;
+ pxNewTimer->pvTimerID = pvTimerID;
+ pxNewTimer->pxCallbackFunction = pxCallbackFunction;
+ vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );
+
+ if( xAutoReload != pdFALSE )
+ {
+ pxNewTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;
+ }
+
+ traceTIMER_CREATE( pxNewTimer );
+ }
+/*-----------------------------------------------------------*/
+
+ BaseType_t xTimerGenericCommand( TimerHandle_t xTimer,
+ const BaseType_t xCommandID,
+ const TickType_t xOptionalValue,
+ BaseType_t * const pxHigherPriorityTaskWoken,
+ const TickType_t xTicksToWait )
+ {
+ BaseType_t xReturn = pdFAIL;
+ DaemonTaskMessage_t xMessage;
+
+ configASSERT( xTimer );
+
+ /* Send a message to the timer service task to perform a particular action
+ * on a particular timer definition. */
+ if( xTimerQueue != NULL )
+ {
+ /* Send a command to the timer service task to start the xTimer timer. */
+ xMessage.xMessageID = xCommandID;
+ xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
+ xMessage.u.xTimerParameters.pxTimer = xTimer;
+
+ if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )
+ {
+ if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING )
+ {
+ xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
+ }
+ else
+ {
+ xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY );
+ }
+ }
+ else
+ {
+ xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
+ }
+
+ traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ return xReturn;
+ }
+/*-----------------------------------------------------------*/
+
+ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void )
+ {
+ /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been
+ * started, then xTimerTaskHandle will be NULL. */
+ configASSERT( ( xTimerTaskHandle != NULL ) );
+ return xTimerTaskHandle;
+ }
+/*-----------------------------------------------------------*/
+
+ TickType_t xTimerGetPeriod( TimerHandle_t xTimer )
+ {
+ Timer_t * pxTimer = xTimer;
+
+ configASSERT( xTimer );
+ return pxTimer->xTimerPeriodInTicks;
+ }
+/*-----------------------------------------------------------*/
+
+ void vTimerSetReloadMode( TimerHandle_t xTimer,
+ const BaseType_t xAutoReload )
+ {
+ Timer_t * pxTimer = xTimer;
+
+ configASSERT( xTimer );
+ taskENTER_CRITICAL();
+ {
+ if( xAutoReload != pdFALSE )
+ {
+ pxTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD;
+ }
+ else
+ {
+ pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_AUTORELOAD );
+ }
+ }
+ taskEXIT_CRITICAL();
+ }
+/*-----------------------------------------------------------*/
+
+ BaseType_t xTimerGetReloadMode( TimerHandle_t xTimer )
+ {
+ Timer_t * pxTimer = xTimer;
+ BaseType_t xReturn;
+
+ configASSERT( xTimer );
+ taskENTER_CRITICAL();
+ {
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0 )
+ {
+ /* Not an auto-reload timer. */
+ xReturn = pdFALSE;
+ }
+ else
+ {
+ /* Is an auto-reload timer. */
+ xReturn = pdTRUE;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+ }
+
+ UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer )
+ {
+ return ( UBaseType_t ) xTimerGetReloadMode( xTimer );
+ }
+/*-----------------------------------------------------------*/
+
+ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer )
+ {
+ Timer_t * pxTimer = xTimer;
+ TickType_t xReturn;
+
+ configASSERT( xTimer );
+ xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) );
+ return xReturn;
+ }
+/*-----------------------------------------------------------*/
+
+ const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+ {
+ Timer_t * pxTimer = xTimer;
+
+ configASSERT( xTimer );
+ return pxTimer->pcTimerName;
+ }
+/*-----------------------------------------------------------*/
+
+ static void prvReloadTimer( Timer_t * const pxTimer,
+ TickType_t xExpiredTime,
+ const TickType_t xTimeNow )
+ {
+ /* Insert the timer into the appropriate list for the next expiry time.
+ * If the next expiry time has already passed, advance the expiry time,
+ * call the callback function, and try again. */
+ while( prvInsertTimerInActiveList( pxTimer, ( xExpiredTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xExpiredTime ) != pdFALSE )
+ {
+ /* Advance the expiry time. */
+ xExpiredTime += pxTimer->xTimerPeriodInTicks;
+
+ /* Call the timer callback. */
+ traceTIMER_EXPIRED( pxTimer );
+ pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
+ }
+ }
+/*-----------------------------------------------------------*/
+
+ static void prvProcessExpiredTimer( const TickType_t xNextExpireTime,
+ const TickType_t xTimeNow )
+ {
+ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
+
+ /* Remove the timer from the list of active timers. A check has already
+ * been performed to ensure the list is not empty. */
+
+ ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
+
+ /* If the timer is an auto-reload timer then calculate the next
+ * expiry time and re-insert the timer in the list of active timers. */
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )
+ {
+ prvReloadTimer( pxTimer, xNextExpireTime, xTimeNow );
+ }
+ else
+ {
+ pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_ACTIVE );
+ }
+
+ /* Call the timer callback. */
+ traceTIMER_EXPIRED( pxTimer );
+ pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
+ }
+/*-----------------------------------------------------------*/
+
+ static portTASK_FUNCTION( prvTimerTask, pvParameters )
+ {
+ TickType_t xNextExpireTime;
+ BaseType_t xListWasEmpty;
+
+ /* Just to avoid compiler warnings. */
+ ( void ) pvParameters;
+
+ #if ( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 )
+ {
+ extern void vApplicationDaemonTaskStartupHook( void );
+
+ /* Allow the application writer to execute some code in the context of
+ * this task at the point the task starts executing. This is useful if the
+ * application includes initialisation code that would benefit from
+ * executing after the scheduler has been started. */
+ vApplicationDaemonTaskStartupHook();
+ }
+ #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */
+
+ for( ; ; )
+ {
+ /* Query the timers list to see if it contains any timers, and if so,
+ * obtain the time at which the next timer will expire. */
+ xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty );
+
+ /* If a timer has expired, process it. Otherwise, block this task
+ * until either a timer does expire, or a command is received. */
+ prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty );
+
+ /* Empty the command queue. */
+ prvProcessReceivedCommands();
+ }
+ }
+/*-----------------------------------------------------------*/
+
+ static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime,
+ BaseType_t xListWasEmpty )
+ {
+ TickType_t xTimeNow;
+ BaseType_t xTimerListsWereSwitched;
+
+ vTaskSuspendAll();
+ {
+ /* Obtain the time now to make an assessment as to whether the timer
+ * has expired or not. If obtaining the time causes the lists to switch
+ * then don't process this timer as any timers that remained in the list
+ * when the lists were switched will have been processed within the
+ * prvSampleTimeNow() function. */
+ xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
+
+ if( xTimerListsWereSwitched == pdFALSE )
+ {
+ /* The tick count has not overflowed, has the timer expired? */
+ if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )
+ {
+ ( void ) xTaskResumeAll();
+ prvProcessExpiredTimer( xNextExpireTime, xTimeNow );
+ }
+ else
+ {
+ /* The tick count has not overflowed, and the next expire
+ * time has not been reached yet. This task should therefore
+ * block to wait for the next expire time or a command to be
+ * received - whichever comes first. The following line cannot
+ * be reached unless xNextExpireTime > xTimeNow, except in the
+ * case when the current timer list is empty. */
+ if( xListWasEmpty != pdFALSE )
+ {
+ /* The current timer list is empty - is the overflow list
+ * also empty? */
+ xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList );
+ }
+
+ vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty );
+
+ if( xTaskResumeAll() == pdFALSE )
+ {
+ /* Yield to wait for either a command to arrive, or the
+ * block time to expire. If a command arrived between the
+ * critical section being exited and this yield then the yield
+ * will not cause the task to block. */
+ portYIELD_WITHIN_API();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ }
+ else
+ {
+ ( void ) xTaskResumeAll();
+ }
+ }
+ }
+/*-----------------------------------------------------------*/
+
+ static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty )
+ {
+ TickType_t xNextExpireTime;
+
+ /* Timers are listed in expiry time order, with the head of the list
+ * referencing the task that will expire first. Obtain the time at which
+ * the timer with the nearest expiry time will expire. If there are no
+ * active timers then just set the next expire time to 0. That will cause
+ * this task to unblock when the tick count overflows, at which point the
+ * timer lists will be switched and the next expiry time can be
+ * re-assessed. */
+ *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList );
+
+ if( *pxListWasEmpty == pdFALSE )
+ {
+ xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
+ }
+ else
+ {
+ /* Ensure the task unblocks when the tick count rolls over. */
+ xNextExpireTime = ( TickType_t ) 0U;
+ }
+
+ return xNextExpireTime;
+ }
+/*-----------------------------------------------------------*/
+
+ static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched )
+ {
+ TickType_t xTimeNow;
+ PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */
+
+ xTimeNow = xTaskGetTickCount();
+
+ if( xTimeNow < xLastTime )
+ {
+ prvSwitchTimerLists();
+ *pxTimerListsWereSwitched = pdTRUE;
+ }
+ else
+ {
+ *pxTimerListsWereSwitched = pdFALSE;
+ }
+
+ xLastTime = xTimeNow;
+
+ return xTimeNow;
+ }
+/*-----------------------------------------------------------*/
+
+ static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer,
+ const TickType_t xNextExpiryTime,
+ const TickType_t xTimeNow,
+ const TickType_t xCommandTime )
+ {
+ BaseType_t xProcessTimerNow = pdFALSE;
+
+ listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime );
+ listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );
+
+ if( xNextExpiryTime <= xTimeNow )
+ {
+ /* Has the expiry time elapsed between the command to start/reset a
+ * timer was issued, and the time the command was processed? */
+ if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ {
+ /* The time between a command being issued and the command being
+ * processed actually exceeds the timers period. */
+ xProcessTimerNow = pdTRUE;
+ }
+ else
+ {
+ vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) );
+ }
+ }
+ else
+ {
+ if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) )
+ {
+ /* If, since the command was issued, the tick count has overflowed
+ * but the expiry time has not, then the timer must have already passed
+ * its expiry time and should be processed immediately. */
+ xProcessTimerNow = pdTRUE;
+ }
+ else
+ {
+ vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );
+ }
+ }
+
+ return xProcessTimerNow;
+ }
+/*-----------------------------------------------------------*/
+
+ static void prvProcessReceivedCommands( void )
+ {
+ DaemonTaskMessage_t xMessage;
+ Timer_t * pxTimer;
+ BaseType_t xTimerListsWereSwitched;
+ TickType_t xTimeNow;
+
+ while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */
+ {
+ #if ( INCLUDE_xTimerPendFunctionCall == 1 )
+ {
+ /* Negative commands are pended function calls rather than timer
+ * commands. */
+ if( xMessage.xMessageID < ( BaseType_t ) 0 )
+ {
+ const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters );
+
+ /* The timer uses the xCallbackParameters member to request a
+ * callback be executed. Check the callback is not NULL. */
+ configASSERT( pxCallback );
+
+ /* Call the function. */
+ pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* INCLUDE_xTimerPendFunctionCall */
+
+ /* Commands that are positive are timer commands rather than pended
+ * function calls. */
+ if( xMessage.xMessageID >= ( BaseType_t ) 0 )
+ {
+ /* The messages uses the xTimerParameters member to work on a
+ * software timer. */
+ pxTimer = xMessage.u.xTimerParameters.pxTimer;
+
+ if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) /*lint !e961. The cast is only redundant when NULL is passed into the macro. */
+ {
+ /* The timer is in a list, remove it. */
+ ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue );
+
+ /* In this case the xTimerListsWereSwitched parameter is not used, but
+ * it must be present in the function call. prvSampleTimeNow() must be
+ * called after the message is received from xTimerQueue so there is no
+ * possibility of a higher priority task adding a message to the message
+ * queue with a time that is ahead of the timer daemon task (because it
+ * pre-empted the timer daemon task after the xTimeNow value was set). */
+ xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
+
+ switch( xMessage.xMessageID )
+ {
+ case tmrCOMMAND_START:
+ case tmrCOMMAND_START_FROM_ISR:
+ case tmrCOMMAND_RESET:
+ case tmrCOMMAND_RESET_FROM_ISR:
+ /* Start or restart a timer. */
+ pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE;
+
+ if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE )
+ {
+ /* The timer expired before it was added to the active
+ * timer list. Process it now. */
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 )
+ {
+ prvReloadTimer( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow );
+ }
+ else
+ {
+ pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_ACTIVE );
+ }
+
+ /* Call the timer callback. */
+ traceTIMER_EXPIRED( pxTimer );
+ pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ break;
+
+ case tmrCOMMAND_STOP:
+ case tmrCOMMAND_STOP_FROM_ISR:
+ /* The timer has already been removed from the active list. */
+ pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_ACTIVE );
+ break;
+
+ case tmrCOMMAND_CHANGE_PERIOD:
+ case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR:
+ pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE;
+ pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue;
+ configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) );
+
+ /* The new period does not really have a reference, and can
+ * be longer or shorter than the old one. The command time is
+ * therefore set to the current time, and as the period cannot
+ * be zero the next expiry time can only be in the future,
+ * meaning (unlike for the xTimerStart() case above) there is
+ * no fail case that needs to be handled here. */
+ ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow );
+ break;
+
+ case tmrCOMMAND_DELETE:
+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ {
+ /* The timer has already been removed from the active list,
+ * just free up the memory if the memory was dynamically
+ * allocated. */
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) 0 )
+ {
+ vPortFree( pxTimer );
+ }
+ else
+ {
+ pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_ACTIVE );
+ }
+ }
+ #else /* if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
+ {
+ /* If dynamic allocation is not enabled, the memory
+ * could not have been dynamically allocated. So there is
+ * no need to free the memory - just mark the timer as
+ * "not active". */
+ pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_ACTIVE );
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+ break;
+
+ default:
+ /* Don't expect to get here. */
+ break;
+ }
+ }
+ }
+ }
+/*-----------------------------------------------------------*/
+
+ static void prvSwitchTimerLists( void )
+ {
+ TickType_t xNextExpireTime;
+ List_t * pxTemp;
+
+ /* The tick count has overflowed. The timer lists must be switched.
+ * If there are any timers still referenced from the current timer list
+ * then they must have expired and should be processed before the lists
+ * are switched. */
+ while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE )
+ {
+ xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
+
+ /* Process the expired timer. For auto-reload timers, be careful to
+ * process only expirations that occur on the current list. Further
+ * expirations must wait until after the lists are switched. */
+ prvProcessExpiredTimer( xNextExpireTime, tmrMAX_TIME_BEFORE_OVERFLOW );
+ }
+
+ pxTemp = pxCurrentTimerList;
+ pxCurrentTimerList = pxOverflowTimerList;
+ pxOverflowTimerList = pxTemp;
+ }
+/*-----------------------------------------------------------*/
+
+ static void prvCheckForValidListAndQueue( void )
+ {
+ /* Check that the list from which active timers are referenced, and the
+ * queue used to communicate with the timer service, have been
+ * initialised. */
+ taskENTER_CRITICAL();
+ {
+ if( xTimerQueue == NULL )
+ {
+ vListInitialise( &xActiveTimerList1 );
+ vListInitialise( &xActiveTimerList2 );
+ pxCurrentTimerList = &xActiveTimerList1;
+ pxOverflowTimerList = &xActiveTimerList2;
+
+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ /* The timer queue is allocated statically in case
+ * configSUPPORT_DYNAMIC_ALLOCATION is 0. */
+ PRIVILEGED_DATA static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */
+ PRIVILEGED_DATA static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */
+
+ xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue );
+ }
+ #else
+ {
+ xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );
+ }
+ #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
+
+ #if ( configQUEUE_REGISTRY_SIZE > 0 )
+ {
+ if( xTimerQueue != NULL )
+ {
+ vQueueAddToRegistry( xTimerQueue, "TmrQ" );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configQUEUE_REGISTRY_SIZE */
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ taskEXIT_CRITICAL();
+ }
+/*-----------------------------------------------------------*/
+
+ BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
+ {
+ BaseType_t xReturn;
+ Timer_t * pxTimer = xTimer;
+
+ configASSERT( xTimer );
+
+ /* Is the timer in the list of active timers? */
+ taskENTER_CRITICAL();
+ {
+ if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 )
+ {
+ xReturn = pdFALSE;
+ }
+ else
+ {
+ xReturn = pdTRUE;
+ }
+ }
+ taskEXIT_CRITICAL();
+
+ return xReturn;
+ } /*lint !e818 Can't be pointer to const due to the typedef. */
+/*-----------------------------------------------------------*/
+
+ void * pvTimerGetTimerID( const TimerHandle_t xTimer )
+ {
+ Timer_t * const pxTimer = xTimer;
+ void * pvReturn;
+
+ configASSERT( xTimer );
+
+ taskENTER_CRITICAL();
+ {
+ pvReturn = pxTimer->pvTimerID;
+ }
+ taskEXIT_CRITICAL();
+
+ return pvReturn;
+ }
+/*-----------------------------------------------------------*/
+
+ void vTimerSetTimerID( TimerHandle_t xTimer,
+ void * pvNewID )
+ {
+ Timer_t * const pxTimer = xTimer;
+
+ configASSERT( xTimer );
+
+ taskENTER_CRITICAL();
+ {
+ pxTimer->pvTimerID = pvNewID;
+ }
+ taskEXIT_CRITICAL();
+ }
+/*-----------------------------------------------------------*/
+
+ #if ( INCLUDE_xTimerPendFunctionCall == 1 )
+
+ BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend,
+ void * pvParameter1,
+ uint32_t ulParameter2,
+ BaseType_t * pxHigherPriorityTaskWoken )
+ {
+ DaemonTaskMessage_t xMessage;
+ BaseType_t xReturn;
+
+ /* Complete the message with the function parameters and post it to the
+ * daemon task. */
+ xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR;
+ xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
+ xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
+ xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
+
+ xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
+
+ tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn );
+
+ return xReturn;
+ }
+
+ #endif /* INCLUDE_xTimerPendFunctionCall */
+/*-----------------------------------------------------------*/
+
+ #if ( INCLUDE_xTimerPendFunctionCall == 1 )
+
+ BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
+ void * pvParameter1,
+ uint32_t ulParameter2,
+ TickType_t xTicksToWait )
+ {
+ DaemonTaskMessage_t xMessage;
+ BaseType_t xReturn;
+
+ /* This function can only be called after a timer has been created or
+ * after the scheduler has been started because, until then, the timer
+ * queue does not exist. */
+ configASSERT( xTimerQueue );
+
+ /* Complete the message with the function parameters and post it to the
+ * daemon task. */
+ xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK;
+ xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend;
+ xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1;
+ xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2;
+
+ xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
+
+ tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn );
+
+ return xReturn;
+ }
+
+ #endif /* INCLUDE_xTimerPendFunctionCall */
+/*-----------------------------------------------------------*/
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+
+ UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer )
+ {
+ return ( ( Timer_t * ) xTimer )->uxTimerNumber;
+ }
+
+ #endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+
+ void vTimerSetTimerNumber( TimerHandle_t xTimer,
+ UBaseType_t uxTimerNumber )
+ {
+ ( ( Timer_t * ) xTimer )->uxTimerNumber = uxTimerNumber;
+ }
+
+ #endif /* configUSE_TRACE_FACILITY */
+/*-----------------------------------------------------------*/
+
+/* This entire source file will be skipped if the application is not configured
+ * to include software timer functionality. If you want to include software timer
+ * functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
+#endif /* configUSE_TIMERS == 1 */
diff --git a/source/test/src/FreeRTOSCPP/EventGroups.hpp b/source/test/src/FreeRTOSCPP/EventGroups.hpp
new file mode 100644
index 0000000..6aa7a1b
--- /dev/null
+++ b/source/test/src/FreeRTOSCPP/EventGroups.hpp
@@ -0,0 +1,503 @@
+/*
+ * FreeRTOS-Cpp
+ * Copyright (C) 2021 Jon Enz. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://github.com/jonenz/FreeRTOS-Cpp
+ */
+
+#ifndef FREERTOS_EVENTGROUPS_HPP
+#define FREERTOS_EVENTGROUPS_HPP
+
+#include
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+
+namespace FreeRTOS {
+
+/**
+ * @class EventGroupBase EventGroupBase.hpp
+ *
+ * @brief Base class that provides the standard event group interface to
+ * FreeRTOS::EventGroup and FreeRTOS::StaticEventGroup.
+ *
+ * @note This class is not intended to be instantiated by the user. Use
+ * FreeRTOS::EventGroup or FreeRTOS::StaticEventGroup.
+ */
+class EventGroupBase {
+ public:
+ friend class EventGroup;
+ friend class StaticEventGroup;
+
+ EventGroupBase(const EventGroupBase&) = delete;
+ EventGroupBase& operator=(const EventGroupBase&) = delete;
+
+ static void* operator new(size_t, void* ptr) { return ptr; }
+ static void* operator new[](size_t, void* ptr) { return ptr; }
+ static void* operator new(size_t) = delete;
+ static void* operator new[](size_t) = delete;
+
+ // NOLINTNEXTLINE
+ using EventBits = std::bitset<((configUSE_16_BIT_TICKS == 1) ? 8 : 24)>;
+
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Function that checks if the underlying event group handle is not
+ * NULL. This should be used to ensure an event group has been created
+ * correctly.
+ *
+ * @retval true the handle is not NULL.
+ * @retval false the handle is NULL.
+ */
+ inline bool isValid() const { return (handle != NULL); }
+
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Function that calls EventBits_t xEventGroupWaitBits( const
+ * EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const
+ * BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t
+ * xTicksToWait )
+ *
+ * @see
+ *
+ * Read bits within an RTOS event group, optionally entering the Blocked state
+ * (with a timeout) to wait for a bit or group of bits to become set.
+ *
+ * @warning This function cannot be called from an interrupt.
+ *
+ * @param bitsToWaitFor A bitwise value that indicates the bit or bits to test
+ * inside the event group. bitsToWaitFor must not be set to 0.
+ * @param clearOnExit If clearOnExit is set to true then any bits set in the
+ * value passed as the bitsToWaitFor parameter will be cleared in the event
+ * group before wait() returns if wait() returns for any reason other than a
+ * timeout. The timeout value is set by the ticksToWait parameter. If
+ * clearOnExit is set to false then the bits set in the event group are not
+ * altered when the call to wait() returns.
+ * @param waitForAllBits waitForAllBits is used to create either a logical AND
+ * test (where all bits must be set) or a logical OR test (where one or more
+ * bits must be set) as follows: If waitForAllBits is set to true then wait()
+ * will return when either all the bits set in the value passed as the
+ * bitsToWaitFor parameter are set in the event group or the specified block
+ * time expires. If waitForAllBits is set to false then wait() will return
+ * when any of the bits set in the value passed as the bitsToWaitFor parameter
+ * are set in the event group or the specified block time expires.
+ * @param ticksToWait The maximum amount of time (specified in 'ticks') to
+ * wait for one/all (depending on the waitForAllBits value) of the bits
+ * specified by bitsToWaitFor to become set.
+ * @return EventBits The value of the event group at the time either the event
+ * bits being waited for became set, or the block time expired. The current
+ * value of the event bits in an event group will be different to the returned
+ * value if a higher priority task or interrupt changed the value of an event
+ * bit between the calling task leaving the Blocked state and exiting the
+ * wait() function. Test the return value to know which bits were set. If
+ * wait() returned because its timeout expired then not all the bits being
+ * waited for will be set. If wait() returned because the bits it was waiting
+ * for were set then the returned value is the event group value before any
+ * bits were automatically cleared because the clearOnExit parameter was set
+ * to true.
+ *
+ * Example Usage
+ * @include EventGroups/wait.cpp
+ */
+ inline EventBits wait(const EventBits& bitsToWaitFor = 0,
+ const bool clearOnExit = false,
+ const bool waitForAllBits = false,
+ const TickType_t ticksToWait = portMAX_DELAY) const {
+ return EventBits(xEventGroupWaitBits(
+ handle, bitsToWaitFor.to_ulong(), (clearOnExit ? pdTRUE : pdFALSE),
+ (waitForAllBits ? pdTRUE : pdFALSE), ticksToWait));
+ }
+
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Function that calls EventBits_t xEventGroupSetBits(
+ * EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
+ *
+ * @see
+ *
+ * Set bits (flags) within an RTOS event group. This function cannot be called
+ * from an interrupt. setFromISR() is a version that can be called from an
+ * interrupt.
+ *
+ * Setting bits in an event group will automatically unblock tasks that are
+ * blocked waiting for the bits.
+ *
+ * @param bitsToSet A bitwise value that indicates the bit or bits to set in
+ * the event group.
+ * @return EventBits The value of the event group at the time the call to
+ * set() returns. There are two reasons why the returned value might have the
+ * bits specified by the uxBitsToSet parameter cleared:
+ * 1. If setting a bit results in a task that was waiting for the bit leaving
+ * the blocked state then it is possible the bit will have been cleared
+ * automatically (see the clearOnExit parameter of wait()).
+ * 2. Any unblocked (or otherwise Ready state) task that has a priority above
+ * that of the task that called set() will execute and may change the event
+ * group value before the call to set() returns.
+ *
+ * Example Usage
+ * @include EventGroups/set.cpp
+ */
+ inline EventBits set(const EventBits& bitsToSet) const {
+ return EventBits(xEventGroupSetBits(handle, bitsToSet.to_ulong()));
+ }
+
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Function that calls BaseType_t xEventGroupSetBitsFromISR(
+ * EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t
+ * *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * Set bits (flags) within an RTOS event group. A version of set() that can be
+ * called from an interrupt service routine (ISR).
+ *
+ * Setting bits in an event group will automatically unblock tasks that are
+ * blocked waiting for the bits.
+ *
+ * Setting bits in an event group is not a deterministic operation because
+ * there are an unknown number of tasks that may be waiting for the bit or
+ * bits being set. FreeRTOS does not allow non-deterministic operations to be
+ * performed in interrupts or from critical sections. Therefore
+ * xEventGroupSetBitFromISR() sends a message to the RTOS daemon task to have
+ * the set operation performed in the context of the daemon task - where a
+ * scheduler lock is used in place of a critical section.
+ *
+ * @note As mentioned in the paragraph above, setting bits from an ISR will
+ * defer the set operation to the RTOS daemon task (also known as the timer
+ * service task). The RTOS daemon task is scheduled according to its priority,
+ * just like any other RTOS task. Therefore, if it is essential the set
+ * operation completes immediately (before a task created by the application
+ * executes) then the priority of the RTOS daemon task must be higher than the
+ * priority of any application task that uses the event group. The priority of
+ * the RTOS daemon task is set by the configTIMER_TASK_PRIORITY definition in
+ * FreeRTOSConfig.h.
+ *
+ * @param higherPriorityTaskWoken As mentioned above, calling this function
+ * will result in a message being sent to the RTOS daemon task. If the
+ * priority of the daemon task is higher than the priority of the currently
+ * running task (the task the interrupt interrupted) then
+ * higherPriorityTaskWoken will be set to true by setFromISR(), indicating
+ * that a context switch should be requested before the interrupt exits. For
+ * that reason higherPriorityTaskWoken must be initialised to false. See the
+ * example code below.
+ * @param bitsToSet A bitwise value that indicates the bit or bits to set in
+ * the event group.
+ * @retval true If the message was sent to the RTOS daemon task.
+ * @retval false Otherwise or if the timer service queue was full
+ *
+ * Example Usage
+ * @include EventGroups/setFromISR.cpp
+ */
+ inline bool setFromISR(bool& higherPriorityTaskWoken,
+ const EventBits& bitsToSet) const {
+ BaseType_t taskWoken = pdFALSE;
+ bool result = (xEventGroupSetBitsFromISR(handle, bitsToSet.to_ulong(),
+ &taskWoken) == pdPASS);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Function that calls BaseType_t xEventGroupSetBitsFromISR(
+ * EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t
+ * *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline bool setFromISR(const EventBits& bitsToSet) const {
+ return (xEventGroupSetBitsFromISR(handle, bitsToSet.to_ulong(), NULL) ==
+ pdPASS);
+ }
+
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Function that calls EventBits_t xEventGroupClearBits(
+ * EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
+ *
+ * @see
+ *
+ * Clear bits (flags) within an RTOS event group. This function cannot be
+ * called from an interrupt. See clearFromISR() for a version that can be
+ * called from an interrupt.
+ *
+ * @param bitsToClear A bitwise value that indicates the bit or bits to clear
+ * in the event group.
+ * @return EventBits The value of the event group before the specified bits
+ * were cleared.
+ *
+ * Example Usage
+ * @include EventGroups/clear.cpp
+ */
+ inline EventBits clear(const EventBits& bitsToClear) const {
+ return EventBits(xEventGroupClearBits(handle, bitsToClear.to_ulong()));
+ }
+
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Function that calls BaseType_t xEventGroupClearBitsFromISR(
+ * EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
+ *
+ * @see
+ *
+ * A version of clear() that can be called from an interrupt. The clear
+ * operation is deferred to the RTOS daemon task which is also known as the
+ * timer service task. The priority of the daemon task is set by the
+ * configTIMER_TASK_PRIORITY setting in FreeRTOSConfig.h.
+ *
+ * @param bitsToClear A bitwise value that indicates the bit or bits to clear
+ * in the event group.
+ * @return true If the operation was successfully deferred to the RTOS daemon
+ * task.
+ * @return false If the timer command queue is full.
+ *
+ * Example Usage
+ * @include EventGroups/clearFromISR.cpp
+ */
+ inline bool clearFromISR(const EventBits& bitsToClear) const {
+ return (xEventGroupClearBitsFromISR(handle, bitsToClear.to_ulong()) ==
+ pdPASS);
+ }
+
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Function that calls EventBits_t xEventGroupGetBits(
+ * EventGroupHandle_t xEventGroup )
+ *
+ * @see
+ *
+ * Returns the current value of the event bits (event flags) in an RTOS event
+ * group. This function cannot be used from an interrupt. See getFromISR() for
+ * a version that can be used in an interrupt.
+ *
+ * @return EventBits The value of the event bits in the event group at the
+ * time get() was called.
+ */
+ inline EventBits get() const { return EventBits(xEventGroupGetBits(handle)); }
+
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Function that calls EventBits_t xEventGroupGetBitsFromISR(
+ * EventGroupHandle_t xEventGroup )
+ *
+ * @see
+ *
+ * A version of get() that can be called from an interrupt.
+ *
+ * @return EventBits The value of the event bits in the event group at the
+ * time getFromISR() was called.
+ */
+ inline EventBits getFromISR() const {
+ return EventBits(xEventGroupGetBitsFromISR(handle));
+ }
+
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Function that calls EventBits_t xEventGroupSync(
+ * EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const
+ * EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
+ *
+ * @see
+ *
+ * Atomically set bits (flags) within an RTOS event group, then wait for a
+ * combination of bits to be set within the same event group. This
+ * functionality is typically used to synchronize multiple tasks (often called
+ * a task rendezvous), where each task has to wait for the other tasks to
+ * reach a synchronization point before proceeding.
+ *
+ * This function cannot be used from an interrupt.
+ *
+ * The function will return before its block time expires if the bits
+ * specified by the bitsToWait parameter are set, or become set within that
+ * time. In this case all the bits specified by bitsToWait will be
+ * automatically cleared before the function returns.
+ *
+ * @param bitsToSet The bit or bits to set in the event group before
+ * determining if (and possibly waiting for), all the bits specified by the
+ * bitsToWait parameter are set.
+ * @param bitsToWaitFor A bitwise value that indicates the bit or bits to test
+ * inside the event group.
+ * @param ticksToWait The maximum amount of time (specified in 'ticks') to
+ * wait for all the bits specified by the uxBitsToWaitFor parameter value to
+ * become set.
+ * @return EventBits
+ *
+ * Example Usage
+ * @include EventGroups/sync.cpp
+ */
+ inline EventBits sync(const EventBits& bitsToSet = 0,
+ const EventBits& bitsToWaitFor = 0,
+ const TickType_t ticksToWait = portMAX_DELAY) const {
+ return EventBits(xEventGroupSync(handle, bitsToSet.to_ulong(),
+ bitsToWaitFor.to_ulong(), ticksToWait));
+ }
+
+ private:
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Construct a new EventGroupBase object.
+ *
+ * @note Default constructor is deliberately private as this class is not
+ * intended to be instantiated or derived from by the user. Use
+ * FreeRTOS::EventGroup or FreeRTOS::StaticEventGroup.
+ */
+ EventGroupBase() = default;
+
+ /**
+ * EventGroup.hpp
+ *
+ * @brief Destroy the EventGroupBase object by calling void
+ * vEventGroupDelete( EventGroupHandle_t xEventGroup )
+ *
+ * @see
+ *
+ * Delete an event group.
+ *
+ * Tasks that are blocked on the event group being deleted will be unblocked,
+ * and report an event group value of 0.
+ */
+ ~EventGroupBase() { vEventGroupDelete(this->handle); };
+
+ EventGroupBase(EventGroupBase&&) noexcept = default;
+ EventGroupBase& operator=(EventGroupBase&&) noexcept = default;
+
+ /**
+ * @brief Handle used to refer to the event group when using the FreeRTOS
+ * interface.
+ */
+ EventGroupHandle_t handle = NULL;
+};
+
+#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+
+/**
+ * @class EventGroup EventGroups.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS event group.
+ *
+ * Each event group requires a [very] small amount of RAM that is used to hold
+ * the event group's state. If an event group is created using this class then
+ * the required RAM is automatically allocated from the FreeRTOS heap. If an
+ * event group is created using FreeRTOS::StaticEventGroup then the RAM is
+ * provided by the application writer, which requires an additional parameter,
+ * but allows the RAM to be statically allocated at compile time. See the Static
+ * Vs Dynamic allocation page for more information.
+ */
+class EventGroup : public EventGroupBase {
+ public:
+ /**
+ * EventGroup.hpp
+ *
+ * @brief Construct a new EventGroup object by calling EventGroupHandle_t
+ * xEventGroupCreate( void )
+ *
+ * @see
+ *
+ * @warning The user should call isValid() on this object to verify that the
+ * queue was created successfully in case the memory required to create the
+ * queue could not be allocated.
+ *
+ * Example Usage
+ * @include EventGroups/eventGroup.cpp
+ */
+ EventGroup() { this->handle = xEventGroupCreate(); }
+ ~EventGroup() = default;
+
+ EventGroup(const EventGroup&) = delete;
+ EventGroup& operator=(const EventGroup&) = delete;
+
+ EventGroup(EventGroup&&) noexcept = default;
+ EventGroup& operator=(EventGroup&&) noexcept = default;
+};
+
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+#if (configSUPPORT_STATIC_ALLOCATION == 1)
+
+/**
+ * @class StaticEventGroup EventGroups.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS event group.
+ *
+ * Each event group requires a [very] small amount of RAM that is used to hold
+ * the event group's state. If an event group is created using
+ * FreeRTOS::EventGroup then the required RAM is automatically allocated from
+ * the FreeRTOS heap. If an event group is created using this class then the RAM
+ * is provided by the application writer, which requires an additional
+ * parameter, but allows the RAM to be statically allocated at compile time. See
+ * the Static Vs Dynamic allocation page for more information.
+ */
+class StaticEventGroup : public EventGroupBase {
+ public:
+ /**
+ * EventGroups.hpp
+ *
+ * @brief Construct a new StaticEventGroup object by calling
+ * EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t
+ * *pxEventGroupBuffer )
+ *
+ * @see
+ *
+ * @warning This class contains the storage buffer for the event group, so the
+ * user should create this object as a global object or with the static
+ * storage specifier so that the object instance is not on the stack.
+ *
+ * Example Usage
+ * @include EventGroups/staticEventGroup.cpp
+ */
+ StaticEventGroup() {
+ this->handle = xEventGroupCreateStatic(&staticEventGroup);
+ }
+ ~StaticEventGroup() = default;
+
+ StaticEventGroup(const StaticEventGroup&) = delete;
+ StaticEventGroup& operator=(const StaticEventGroup&) = delete;
+
+ StaticEventGroup(StaticEventGroup&&) noexcept = default;
+ StaticEventGroup& operator=(StaticEventGroup&&) noexcept = default;
+
+ private:
+ StaticEventGroup_t staticEventGroup;
+};
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+} // namespace FreeRTOS
+
+#endif // FREERTOS_EVENTGROUPS_HPP
diff --git a/source/test/src/FreeRTOSCPP/Kernel.hpp b/source/test/src/FreeRTOSCPP/Kernel.hpp
new file mode 100644
index 0000000..0f28646
--- /dev/null
+++ b/source/test/src/FreeRTOSCPP/Kernel.hpp
@@ -0,0 +1,409 @@
+/*
+ * FreeRTOS-Cpp
+ * Copyright (C) 2021 Jon Enz. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://github.com/jonenz/FreeRTOS-Cpp
+ */
+
+#ifndef FREERTOS_KERNEL_HPP
+#define FREERTOS_KERNEL_HPP
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+namespace FreeRTOS {
+
+/**
+ * @brief Kernel namespace that provides an interface to kernel functions.
+ *
+ */
+namespace Kernel {
+enum class SchedulerState : BaseType_t {
+ Suspended = taskSCHEDULER_SUSPENDED,
+ NotStarted = taskSCHEDULER_NOT_STARTED,
+ Running = taskSCHEDULER_RUNNING,
+};
+
+/**
+ * @brief If versionNumber ends with + it represents the version in development
+ * after the numbered release.
+ */
+inline constexpr char versionNumber[] = tskKERNEL_VERSION_NUMBER;
+inline constexpr BaseType_t versionMajor = tskKERNEL_VERSION_MAJOR;
+inline constexpr BaseType_t versionMinor = tskKERNEL_VERSION_MINOR;
+inline constexpr BaseType_t versionBuild = tskKERNEL_VERSION_BUILD;
+
+#if (INCLUDE_xTaskGetSchedulerState == 1)
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls xTaskGetSchedulerState()
+ *
+ * @see
+ *
+ * @retval SchedulerState Returns the scheduler state as Running, NotStarted, or
+ * Suspended.
+ */
+inline SchedulerState getSchedulerState() {
+ return static_cast(xTaskGetSchedulerState());
+}
+#endif /* INCLUDE_xTaskGetSchedulerState */
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls uxTaskGetNumberOfTasks()
+ *
+ * @see
+ *
+ * @retval UBaseType_t The number of tasks that the real time kernel is
+ * currently managing. This includes all ready, blocked and suspended tasks. A
+ * task that has been deleted but not yet freed by the idle task will also be
+ * included in the count.
+ */
+inline UBaseType_t getNumberOfTasks() { return uxTaskGetNumberOfTasks(); }
+
+#if (INCLUDE_xTaskGetIdleTaskHandle == 1 && configGENERATE_RUN_TIME_STATS == 1)
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls xTaskGetIdleRunTimeCounter()
+ *
+ * @see
+ *
+ * @retval TickType_t The run-time counter for the Idle task.
+ *
+ * This function can be used to determine how much CPU time the idle task
+ * receives. See the Run Time Stats page for a full description of the
+ * run-time-stats feature.
+ *
+ * configGENERATE_RUN_TIME_STATS and INCLUDE_xTaskGetIdleTaskHandle must both be
+ * defined as 1 for this function to be available. The application must also
+ * then provide definitions for portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and
+ * portGET_RUN_TIME_COUNTER_VALUE to configure a peripheral timer/counter and
+ * return the timer's current count value respectively. It is recommended to
+ * make the timer at least 10 times the frequency of the tick count.
+ */
+inline TickType_t getIdleRunTimeCounter() {
+ return xTaskGetIdleRunTimeCounter();
+}
+#endif /* INCLUDE_xTaskGetIdleTaskHandle && configGENERATE_RUN_TIME_STATS*/
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls xTaskGetTickCount()
+ *
+ * @see
+ *
+ * @retval TickType_t The count of ticks since
+ * FreeRTOS::Kernel::startScheduler() was called.
+ */
+inline TickType_t getTickCount() { return xTaskGetTickCount(); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls xTaskGetTickCountFromISR()
+ *
+ * @see
+ *
+ * @retval TickType_t The count of ticks since
+ * FreeRTOS::Kernel::startScheduler() was called.
+ *
+ * This is a version of FreeRTOS::Kernel::getTickCount() that is safe to be
+ * called from an ISR - provided that TickType_t is the natural word size of the
+ * microcontroller being used or interrupt nesting is either not supported or
+ * not being used.
+ */
+inline TickType_t getTickCountFromISR() { return xTaskGetTickCountFromISR(); }
+
+/**
+ *Kernel.hpp
+ *
+ * @brief Function that calls taskYIELD()
+ *
+ * @see
+ *
+ * FreeRTOS::Kernel::yield() is used to request a context switch to another
+ *task. However, if there are no other tasks at a higher or equal priority to
+ *the task that calls FreeRTOS::Kernel::yield() then the RTOS scheduler will
+ *simply select the task that called FreeRTOS::Kernel::yield() to run again.
+ */
+inline void yield() { taskYIELD(); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls taskENTER_CRITICAL()
+ *
+ * @see
+ *
+ * Function to mark the start of a critical code region. Preemptive context
+ * switches cannot occur when in a critical region.
+ *
+ * @note This may alter the stack (depending on the portable implementation) so
+ * must be used with care!
+ *
+ * Example Usage
+ * @include Kernel/enterExitCritical.cpp
+ */
+inline void enterCritical() { taskENTER_CRITICAL(); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls taskENTER_CRITICAL_FROM_ISR()
+ *
+ * @see
+ *
+ *
+ * @retval uint32_t the interrupt mask state as it was before the macro was
+ * called. The value returned by FreeRTOS::Kernel::enterCriticalFromISR() must
+ * be used as the interruptStatus parameter in the matching call to
+ * FreeRTOS::Kernel::exitCriticalFromISR().
+ *
+ * Function to mark the start of a critical code region. Preemptive context
+ * switches cannot occur when in a critical region.
+ *
+ * @note This may alter the stack (depending on the portable implementation) so
+ * must be used with care!
+ *
+ * Example Usage
+ * @include Kernel/enterExitCriticalFromISR.cpp
+ */
+inline uint32_t enterCriticalFromISR() { return taskENTER_CRITICAL_FROM_ISR(); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls taskEXIT_CRITICAL()
+ *
+ * @see
+ *
+ * Function to mark the end of a critical code region. Preemptive context
+ * switches cannot occur when in a critical region.
+ *
+ * @note This may alter the stack (depending on the portable implementation) so
+ * must be used with care!
+ *
+ * Example Usage
+ * @include Kernel/enterExitCritical.cpp
+ */
+inline void exitCritical() { taskEXIT_CRITICAL(); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls taskEXIT_CRITICAL_FROM_ISR()
+ *
+ * @see
+ *
+ *
+ * @param interruptStatus The value used as the interruptStatus parameter must
+ * be the value returned from the matching call to
+ * FreeRTOS::Kernel::enterCriticalFromISR().
+ *
+ * Function to mark the end of a critical code region. Preemptive context
+ * switches cannot occur when in a critical region.
+ *
+ * @note This may alter the stack (depending on the portable implementation) so
+ * must be used with care!
+ *
+ * Example Usage
+ * @include Kernel/enterExitCriticalFromISR.cpp
+ */
+inline void exitCriticalFromISR(const uint32_t interruptStatus) {
+ taskEXIT_CRITICAL_FROM_ISR(interruptStatus);
+}
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls taskDISABLE_INTERRUPTS()
+ *
+ * @see
+ *
+ * Function to disable all maskable interrupts.
+ */
+inline void disableInterrupts() { taskDISABLE_INTERRUPTS(); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls taskENABLE_INTERRUPTS()
+ *
+ * @see
+ *
+ * Function to enable microcontroller interrupts.
+ */
+inline void enableInterrupts() { taskENABLE_INTERRUPTS(); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls vTaskStartScheduler()
+ *
+ * @see
+ *
+ * Starts the real time kernel tick processing. After calling the kernel has
+ * control over which tasks are executed and when.
+ *
+ * Example Usage
+ * @include Kernel/startScheduler.cpp
+ */
+inline void startScheduler() { vTaskStartScheduler(); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls vTaskEndScheduler()
+ *
+ * @see
+ *
+ * @note At the time of writing only the x86 real mode port, which runs on a PC
+ * in place of DOS, implements this function.
+ *
+ * Stops the real time kernel tick. All created tasks will be automatically
+ * deleted and multitasking (either preemptive or cooperative) will stop.
+ * Execution then resumes from the point where
+ * FreeRTOS::Kernel::startScheduler() was called, as if
+ * FreeRTOS::Kernel::startScheduler() had just returned.
+ *
+ * See the demo application file main. c in the demo/PC directory for an example
+ * that uses FreeRTOS::Kernel::endScheduler().
+ *
+ * FreeRTOS::Kernel::endScheduler() requires an exit function to be defined
+ * within the portable layer (see vPortEndScheduler () in port. c for the PC
+ * port). This performs hardware specific operations such as stopping the
+ * kernel tick.
+ *
+ * FreeRTOS::Kernel::endScheduler() will cause all of the resources allocated by
+ * the kernel to be freed - but will not free resources allocated by application
+ * tasks.
+ *
+ * Example Usage
+ * @include Kernel/endScheduler.cpp
+ */
+inline void endScheduler() { vTaskEndScheduler(); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls vTaskSuspendAll()
+ *
+ * @see
+ *
+ * Suspends the scheduler without disabling interrupts. Context switches will
+ * not occur while the scheduler is suspended.
+ *
+ * After calling FreeRTOS::Kernel::suspendAll() the calling task will continue
+ * to execute without risk of being swapped out until a call to
+ * FreeRTOS::Kernel::resumeAll() has been made.
+ *
+ * API functions that have the potential to cause a context switch (for example,
+ * FreeRTOS::Task::delayUntil(), FreeRTOS::Queue::send(), etc.) must not be
+ * called while the scheduler is suspended.
+ *
+ * Example Usage
+ * @include Kernel/suspendAll.cpp
+ */
+inline void suspendAll() { vTaskSuspendAll(); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls xTaskResumeAll()
+ *
+ * @see
+ *
+ * Resumes scheduler activity after it was suspended by a call to
+ * FreeRTOS::Kernel::suspendAll().
+ *
+ * FreeRTOS::Kernel::resumeAll() only resumes the scheduler. It does not
+ * unsuspend tasks that were previously suspended by a call to
+ * FreeRTOS::Task::suspend().
+ *
+ * @retval true If resuming the scheduler caused a context switch.
+ * @retval false Otherwise.
+ *
+ * Example Usage
+ * @include Kernel/resumeAll.cpp
+ */
+inline bool resumeAll() { return (xTaskResumeAll() == pdTRUE); }
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls vTaskStepTick( const TickType_t xTicksToJump
+ * )
+ *
+ * @see
+ *
+ * Only available when configUSE_TICKLESS_IDLE is set to 1. If tickless mode is
+ * being used, or a low power mode is implemented, then the tick interrupt will
+ * not execute during idle periods. When this is the case, the tick count value
+ * maintained by the scheduler needs to be kept up to date with the actual
+ * execution time by being skipped forward by a time equal to the idle period.
+ *
+ * @param ticksToJump The number of RTOS ticks that have passed since the tick
+ * interrupt was stopped.
+ */
+inline void stepTick(const TickType_t ticksToJump) {
+ vTaskStepTick(ticksToJump);
+}
+
+/**
+ * Kernel.hpp
+ *
+ * @brief Function that calls xTaskCatchUpTicks( TickType_t xTicksToCatchUp
+ * )
+ *
+ * @see
+ *
+ * This function corrects the tick count value after the application code has
+ * held interrupts disabled for an extended period resulting in tick interrupts
+ * having been missed.
+ *
+ * This function is similar to FreeRTOS::Kernel::stepTick(), however, unlike
+ * FreeRTOS::Kernel::stepTick(), FreeRTOS::Kernel::catchUpTicks() may move the
+ * tick count forward past a time at which a task should be removed from the
+ * blocked state. That means tasks may have to be removed from the blocked
+ * state as the tick count is moved.
+ *
+ * @param ticksToCatchUp The number of tick interrupts that have been missed due
+ * to interrupts being disabled. Its value is not computed automatically, so
+ * must be computed by the application writer.
+ *
+ * @retval true If moving the tick count forward resulted in a task leaving the
+ * blocked state and a context switch being performed.
+ * @retval false Otherwise.
+ */
+inline bool catchUpTicks(const TickType_t ticksToCatchUp) {
+ return (xTaskCatchUpTicks(ticksToCatchUp) == pdTRUE);
+}
+} // namespace Kernel
+
+} // namespace FreeRTOS
+
+#endif // FREERTOS_KERNEL_HPP
diff --git a/source/test/src/FreeRTOSCPP/MessageBuffer.hpp b/source/test/src/FreeRTOSCPP/MessageBuffer.hpp
new file mode 100644
index 0000000..0e9fdad
--- /dev/null
+++ b/source/test/src/FreeRTOSCPP/MessageBuffer.hpp
@@ -0,0 +1,518 @@
+/*
+ * FreeRTOS-Cpp
+ * Copyright (C) 2021 Jon Enz. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://github.com/jonenz/FreeRTOS-Cpp
+ */
+
+#ifndef FREERTOS_MESSAGEBUFFER_HPP
+#define FREERTOS_MESSAGEBUFFER_HPP
+
+#include "FreeRTOS.h"
+#include "message_buffer.h"
+
+namespace FreeRTOS {
+
+/**
+ * @class MessageBufferBase MessageBuffer.hpp
+ *
+ * @brief Base class that provides the standard message buffer interface to
+ * FreeRTOS::MessageBuffer and FreeRTOS::StaticMessageBuffer.
+ *
+ * @note This class is not intended to be instantiated by the user. Use
+ * FreeRTOS::MessageBuffer or FreeRTOS::StaticMessageBuffer.
+ *
+ * @warning Uniquely among FreeRTOS objects, the stream buffer implementation
+ * (so also the message buffer implementation, as message buffers are built on
+ * top of stream buffers) assumes there is only one task or interrupt that will
+ * write to the buffer (the writer), and only one task or interrupt that will
+ * read from the buffer (the reader). It is safe for the writer and reader to
+ * be different tasks or interrupts, but, unlike other FreeRTOS objects, it is
+ * not safe to have multiple different writers or multiple different readers. If
+ * there are to be multiple different writers then the application writer must
+ * place each call to a writing API function (such as send()) inside a critical
+ * section and set the send block time to 0. Likewise, if there are to be
+ * multiple different readers then the application writer must place each call
+ * to a reading API function (such as read()) inside a critical section and set
+ * the receive block time to 0.
+ */
+class MessageBufferBase {
+ public:
+ friend class MessageBuffer;
+ template
+ friend class StaticMessageBuffer;
+
+ MessageBufferBase(const MessageBufferBase&) = delete;
+ MessageBufferBase& operator=(const MessageBufferBase&) = delete;
+
+ static void* operator new(size_t, void* ptr) { return ptr; }
+ static void* operator new[](size_t, void* ptr) { return ptr; }
+ static void* operator new(size_t) = delete;
+ static void* operator new[](size_t) = delete;
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that checks if the underlying message buffer handle is not
+ * NULL. This should be used to ensure a message buffer has been created
+ * correctly.
+ *
+ * @retval true If the handle is not NULL.
+ * @retval false If the handle is NULL.
+ */
+ inline bool isValid() const { return (handle != NULL); }
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that calls size_t xMessageBufferSend(
+ * MessageBufferHandle_t xMessageBuffer, const void *pvTxData, size_t
+ * xDataLengthBytes, TickType_t xTicksToWait )
+ *
+ * @see
+ *
+ * Sends a discrete message to the message buffer. The message can be any
+ * length that fits within the buffer's free space, and is copied into the
+ * buffer.
+ *
+ * Use send() to write to a message buffer from a task. Use sendFromISR() to
+ * write to a message buffer from an interrupt service routine (ISR).
+ *
+ * @param data A pointer to the message that is to be copied into the message
+ * buffer.
+ * @param length The length of the message. That is, the number of bytes to
+ * copy from data into the message buffer. When a message is written to the
+ * message buffer an additional sizeof( size_t ) bytes are also written to
+ * store the message's length. sizeof( size_t ) is typically 4 bytes on a
+ * 32-bit architecture, so on most 32-bit architecture setting length to 20
+ * will reduce the free space in the message buffer by 24 bytes (20 bytes of
+ * message data and 4 bytes to hold the message length).
+ * @param ticksToWait The maximum amount of time the calling task should
+ * remain in the Blocked state to wait for enough space to become available in
+ * the message buffer, should the message buffer have insufficient space when
+ * send() is called. The calling task will never block if ticksToWait is
+ * zero. The block time is specified in tick periods, so the absolute time it
+ * represents is dependent on the tick frequency. The macro pdMS_TO_TICKS()
+ * can be used to convert a time specified in milliseconds into a time
+ * specified in ticks. Setting ticksToWait to portMAX_DELAY will cause the
+ * task to wait indefinitely (without timing out), provided
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
+ * CPU time when they are in the Blocked state.
+ * @return size_t The number of bytes written to the message buffer. If the
+ * call to send() times out before there was enough space to write the message
+ * into the message buffer then zero is returned. If the call did not time
+ * out then length is returned.
+ *
+ * Example Usage
+ * @include MessageBuffer/send.cpp
+ */
+ inline size_t send(const void* data, const size_t length,
+ const TickType_t ticksToWait = portMAX_DELAY) const {
+ return xMessageBufferSend(handle, data, length, ticksToWait);
+ }
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that calls size_t xMessageBufferSendFromISR(
+ * MessageBufferHandle_t xMessageBuffer, const void *pvTxData, size_t
+ * xDataLengthBytes, BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * Interrupt safe version of the API function that sends a discrete message to
+ * the message buffer. The message can be any length that fits within the
+ * buffer's free space, and is copied into the buffer.
+ *
+ * Use send() to write to a message buffer from a task. Use sendFromISR() to
+ * write to a message buffer from an interrupt service routine (ISR).
+ *
+ * @param higherPriorityTaskWoken It is possible that a message buffer will
+ * have a task blocked on it waiting for data. Calling sendFromISR() can make
+ * data available, and so cause a task that was waiting for data to leave the
+ * Blocked state. If calling sendFromISR() causes a task to leave the Blocked
+ * state, and the unblocked task has a priority higher than the currently
+ * executing task (the task that was interrupted), then, internally,
+ * sendFromISR() will set higherPriorityTaskWoken to true. If sendFromISR()
+ * sets this value to true, then normally a context switch should be performed
+ * before the interrupt is exited. This will ensure that the interrupt returns
+ * directly to the highest priority Ready state task. higherPriorityTaskWoken
+ * should be set to false before it is passed into the function. See the code
+ * example below for an example.
+ * @param data A pointer to the message that is to be copied into the message
+ * buffer.
+ * @param length The length of the message. That is, the number of bytes to
+ * copy from data into the message buffer. When a message is written to the
+ * message buffer an additional sizeof( size_t ) bytes are also written to
+ * store the message's length. sizeof( size_t ) is typically 4 bytes on a
+ * 32-bit architecture, so on most 32-bit architecture setting length to 20
+ * will reduce the free space in the message buffer by 24 bytes (20 bytes of
+ * message data and 4 bytes to hold the message length).
+ * @return size_t The number of bytes actually written to the message buffer.
+ * If the message buffer didn't have enough free space for the message to be
+ * stored then 0 is returned, otherwise length is returned.
+ *
+ * Example Usage
+ * @include MessageBuffer/sendFromISR.cpp
+ */
+ inline size_t sendFromISR(bool& higherPriorityTaskWoken, const void* data,
+ const size_t length) const {
+ BaseType_t taskWoken = pdFALSE;
+ size_t result = xMessageBufferSendFromISR(handle, data, length, &taskWoken);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that calls size_t xMessageBufferSendFromISR(
+ * MessageBufferHandle_t xMessageBuffer, const void *pvTxData, size_t
+ * xDataLengthBytes, BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline size_t sendFromISR(const void* data, const size_t length) const {
+ return xMessageBufferSendFromISR(handle, data, length, NULL);
+ }
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that calls size_t xMessageBufferReceive(
+ * MessageBufferHandle_t xMessageBuffer, void *pvRxData, size_t
+ * xBufferLengthBytes, TickType_t xTicksToWait )
+ *
+ * @see
+ *
+ * Use receive() to read from a message buffer from a task.
+ * UsereceiveFromISR() to read from a message buffer from an interrupt service
+ * routine (ISR).
+ *
+ * @param buffer A pointer to the buffer into which the received message is to
+ * be copied.
+ * @param bufferLength The length of the buffer pointed to by the buffer
+ * parameter. This sets the maximum length of the message that can be
+ * received. If bufferLength is too small to hold the next message then the
+ * message will be left in the message buffer and 0 will be returned.
+ * @param ticksToWait The maximum amount of time the task should remain in the
+ * Blocked state to wait for a message, should the message buffer be empty.
+ * receive() will return immediately if ticksToWait is zero and the message
+ * buffer is empty. The block time is specified in tick periods, so the
+ * absolute time it represents is dependent on the tick frequency. The macro
+ * pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
+ * into a time specified in ticks. Setting ticksToWait to portMAX_DELAY will
+ * cause the task to wait indefinitely (without timing out), provided
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. Tasks do not use any
+ * CPU time when they are in the Blocked state.
+ * @return size_t The length, in bytes, of the message read from the message
+ * buffer, if any. If receive() times out before a message became available
+ * then zero is returned. If the length of the message is greater than
+ * bufferLength then the message will be left in the message buffer and zero
+ * is returned.
+ *
+ * Example Usage
+ * @include MessageBuffer/receive.cpp
+ */
+ inline size_t receive(void* buffer, const size_t bufferLength,
+ const TickType_t ticksToWait = portMAX_DELAY) const {
+ return xMessageBufferReceive(handle, buffer, bufferLength, ticksToWait);
+ }
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that calls size_t xMessageBufferReceiveFromISR(
+ * MessageBufferHandle_t xMessageBuffer, void *pvRxData, size_t
+ * xBufferLengthBytes, BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * Use receive() to read from a message buffer from a task.
+ * UsereceiveFromISR() to read from a message buffer from an interrupt service
+ * routine (ISR).
+ *
+ * @param higherPriorityTaskWoken It is possible that a message buffer will
+ * have a task blocked on it waiting for space to become available. Calling
+ * receiveFromISR() can make space available, and so cause a task that is
+ * waiting for space to leave the Blocked state. If calling receiveFromISR()
+ * causes a task to leave the Blocked state, and the unblocked task has a
+ * priority higher than the currently executing task (the task that was
+ * interrupted), then, internally, receiveFromISR() will set
+ * higherPriorityTaskWoken to true. If receiveFromISR() sets this value to
+ * true, then normally a context switch should be performed before the
+ * interrupt is exited. That will ensure the interrupt returns directly to the
+ * highest priority Ready state task. higherPriorityTaskWoken should be set
+ * to false before it is passed into the function. See the code example below
+ * for an example.
+ * @param buffer A pointer to the buffer into which the received message is to
+ * be copied.
+ * @param bufferLength The length of the buffer pointed to by the buffer
+ * parameter. This sets the maximum length of the message that can be
+ * received. If bufferLength is too small to hold the next message then the
+ * message will be left in the message buffer and 0 will be returned.
+ * @return size_t The length, in bytes, of the message read from the message
+ * buffer, if any.
+ *
+ * Example Usage
+ * @include MessageBuffer/receiveFromISR.cpp
+ */
+ inline size_t receiveFromISR(bool& higherPriorityTaskWoken, void* buffer,
+ const size_t bufferLength) const {
+ BaseType_t taskWoken = pdFALSE;
+ size_t result =
+ xMessageBufferReceiveFromISR(handle, buffer, bufferLength, &taskWoken);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that calls size_t xMessageBufferReceiveFromISR(
+ * MessageBufferHandle_t xMessageBuffer, void *pvRxData, size_t
+ * xBufferLengthBytes, BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline size_t receiveFromISR(void* buffer, const size_t bufferLength) const {
+ return xMessageBufferReceiveFromISR(handle, buffer, bufferLength, NULL);
+ }
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that calls size_t xMessageBufferSpacesAvailable(
+ * MessageBufferHandle_t xMessageBuffer )
+ *
+ * @see
+ *
+ * Queries a message buffer to see how much free space it contains, which is
+ * equal to the amount of data that can be sent to the message buffer before
+ * it is full. The returned value is 4 bytes larger than the maximum message
+ * size that can be sent to the message buffer.
+ *
+ * @return size_t The number of bytes that can be written to the message
+ * buffer before the message buffer would be full. When a message is written
+ * to the message buffer an additional sizeof( size_t ) bytes are also written
+ * to store the message's length. sizeof( size_t ) is typically 4 bytes on a
+ * 32-bit architecture, so if spacesAvailable() returns 10, then the size of
+ * the largest message that can be written to the message buffer is 6 bytes.
+ */
+ inline size_t spacesAvailable() const {
+ return xMessageBufferSpacesAvailable(handle);
+ }
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that calls BaseType_t xMessageBufferReset(
+ * MessageBufferHandle_t xMessageBuffer )
+ *
+ * @see
+ *
+ * Resets a message buffer to its initial, empty, state. Any data that was in
+ * the message buffer is discarded. A message buffer can only be reset if
+ * there are no tasks blocked waiting to either send to or receive from the
+ * message buffer.
+ *
+ * @retval true If the message buffer is reset.
+ * @retval false If there was a task blocked waiting to send to or read from
+ * the message buffer then the message buffer will not be reset.
+ */
+ inline bool reset() const { return (xMessageBufferReset(handle) == pdPASS); }
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that calls BaseType_t xMessageBufferIsEmpty(
+ * MessageBufferHandle_t xMessageBuffer )
+ *
+ * @see
+ *
+ * Queries a message buffer to see if it is empty. A message buffer is empty
+ * if it does not contain any messages.
+ *
+ * @retval true If the message buffer is empty.
+ * @retval false Otherwise.
+ */
+ inline bool isEmpty() const {
+ return (xMessageBufferIsEmpty(handle) == pdTRUE);
+ }
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Function that calls BaseType_t xMessageBufferIsFull(
+ * MessageBufferHandle_t xMessageBuffer )
+ *
+ * @see
+ *
+ * Queries a message buffer to see if it is full. A message buffer is full if
+ * it cannot accept any more messages, of any size, until space is made
+ * available by a message being removed from the message buffer.
+ *
+ * @retval true If the message buffer is full.
+ * @retval false Otherwise.
+ */
+ inline bool isFull() const {
+ return (xMessageBufferIsFull(handle) == pdTRUE);
+ }
+
+ private:
+ MessageBufferBase() = default;
+
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Destroy the MessageBufferBase object by calling void
+ * vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer )
+ *
+ * @see
+ *
+ * Delete a queue - freeing all the memory allocated for storing of items
+ * placed on the queue.
+ */
+ ~MessageBufferBase() { vMessageBufferDelete(this->handle); }
+
+ MessageBufferBase(MessageBufferBase&&) noexcept = default;
+ MessageBufferBase& operator=(MessageBufferBase&&) noexcept = default;
+
+ MessageBufferHandle_t handle = NULL;
+};
+
+#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+
+/**
+ * @class MessageBuffer MessageBuffer.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS message
+ * buffer.
+ *
+ * A message buffer using dynamically allocated memory from the FreeRTOS heap.
+ * See FreeRTOS::StaticMessageBuffer for a version that uses statically
+ * allocated memory (memory that is allocated at compile time).
+ */
+class MessageBuffer : public MessageBufferBase {
+ public:
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Construct a new MessageBuffer object by calling
+ * MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes
+ * )
+ *
+ * @see
+ *
+ * @warning The user should call isValid() on this object to verify that the
+ * message buffer was created successfully in case the memory required to
+ * create the message buffer could not be allocated.
+ *
+ * @param size The total number of bytes (not messages) the message buffer
+ * will be able to hold at any one time. When a message is written to the
+ * message buffer an additional sizeof( size_t ) bytes are also written to
+ * store the message's length. sizeof( size_t ) is typically 4 bytes on a
+ * 32-bit architecture, so on most 32-bit architectures a 10 byte message will
+ * take up 14 bytes of message buffer space.
+ *
+ * Example Usage
+ * @include MessageBuffer/messageBuffer.cpp
+ */
+ explicit MessageBuffer(size_t size) {
+ this->handle = xMessageBufferCreate(size);
+ }
+ ~MessageBuffer() = default;
+
+ MessageBuffer(const MessageBuffer&) = delete;
+ MessageBuffer& operator=(const MessageBuffer&) = delete;
+
+ MessageBuffer(MessageBuffer&&) noexcept = default;
+ MessageBuffer& operator=(MessageBuffer&&) noexcept = default;
+};
+
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+#if (configSUPPORT_STATIC_ALLOCATION == 1)
+
+/**
+ * @class StaticMessageBuffer MessageBuffer.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS message
+ * buffer.
+ *
+ * If a message buffer is created using this class then the RAM is provided by
+ * the application writer as part of the object instance and allows the RAM to
+ * be statically allocated at compile time.
+ *
+ * @tparam N The size, in bytes, of the storage for the message buffer.
+ */
+template
+class StaticMessageBuffer : public MessageBufferBase {
+ public:
+ /**
+ * MessageBuffer.hpp
+ *
+ * @brief Construct a new StaticMessageBuffer object by calling
+ * MessageBufferHandle_t xMessageBufferCreateStatic( size_t
+ * xBufferSizeBytes, uint8_t *pucMessageBufferStorageArea,
+ * StaticMessageBuffer_t *pxStaticMessageBuffer )
+ *
+ * @see
+ *
+ * @warning This class contains the storage buffer for the message buffer, so
+ * the user should create this object as a global object or with the static
+ * storage specifier so that the object instance is not on the stack.
+ *
+ * Example Usage
+ * @include MessageBuffer/staticMessageBuffer.cpp
+ */
+ StaticMessageBuffer() : MessageBufferBase() {
+ this->handle = xMessageBufferCreateStatic(sizeof(storage), storage,
+ &staticMessageBuffer);
+ }
+ ~StaticMessageBuffer() = default;
+
+ StaticMessageBuffer(const StaticMessageBuffer&) = delete;
+ StaticMessageBuffer& operator=(const StaticMessageBuffer&) = delete;
+
+ StaticMessageBuffer(StaticMessageBuffer&&) noexcept = default;
+ StaticMessageBuffer& operator=(StaticMessageBuffer&&) noexcept = default;
+
+ private:
+ StaticMessageBuffer_t staticMessageBuffer;
+ uint8_t storage[N] = {0};
+};
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+} // namespace FreeRTOS
+
+#endif // FREERTOS_MESSAGEBUFFER_HPP
\ No newline at end of file
diff --git a/source/test/src/FreeRTOSCPP/Mutex.hpp b/source/test/src/FreeRTOSCPP/Mutex.hpp
new file mode 100644
index 0000000..e045324
--- /dev/null
+++ b/source/test/src/FreeRTOSCPP/Mutex.hpp
@@ -0,0 +1,495 @@
+/*
+ * FreeRTOS-Cpp
+ * Copyright (C) 2021 Jon Enz. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://github.com/jonenz/FreeRTOS-Cpp
+ */
+
+#ifndef FREERTOS_MUTEX_HPP
+#define FREERTOS_MUTEX_HPP
+
+#include "FreeRTOS.h"
+#include "semphr.h"
+
+namespace FreeRTOS {
+
+/**
+ * @class MutexBase Mutex.hpp
+ *
+ * @brief Base class that provides the standard mutex interface to
+ * FreeRTOS::Mutex, FreeRTOS::StaticMutex, FreeRTOS::RecursiveMutex, and
+ * FreeRTOS::StaticRecursiveMutex.
+ *
+ * @note This class is not intended to be instantiated by the user. Use
+ * FreeRTOS::Mutex, FreeRTOS::StaticMutex, FreeRTOS::RecursiveMutex, and
+ * FreeRTOS::StaticRecursiveMutex.
+ */
+class MutexBase {
+ public:
+ friend class Mutex;
+ friend class StaticMutex;
+ friend class RecursiveMutexBase;
+ friend class RecursiveMutex;
+ friend class StaticRecursiveMutex;
+
+ MutexBase(const MutexBase&) = delete;
+ MutexBase& operator=(const MutexBase&) = delete;
+
+ static void* operator new(size_t, void* ptr) { return ptr; }
+ static void* operator new[](size_t, void* ptr) { return ptr; }
+ static void* operator new(size_t) = delete;
+ static void* operator new[](size_t) = delete;
+
+ /**
+ * Mutex.hpp
+ *
+ * @brief Function that checks if the underlying semaphore handle is not NULL.
+ * This should be used to ensure a semaphore has been created correctly.
+ *
+ * @retval true the handle is not NULL.
+ * @retval false the handle is NULL.
+ */
+ inline bool isValid() const { return (handle != NULL); }
+
+ /**
+ * Mutex.hpp
+ *
+ * @brief Function that calls xSemaphoreTake( SemaphoreHandle_t
+ * xSemaphore, TickType_t xTicksToWait )
+ *
+ * @see
+ *
+ * @param ticksToWait The time in ticks to wait for the mutex to become
+ * available. The macro portTICK_PERIOD_MS can be used to convert this to a
+ * real time. A block time of zero can be used to poll the mutex.
+ * @retval true If the mutex was locked.
+ * @retval false If ticksToWait expired without the mutex becoming available.
+ *
+ * Example Usage
+ * @include Mutex/lock.cpp
+ */
+ inline bool lock(const TickType_t ticksToWait = portMAX_DELAY) const {
+ return (xSemaphoreTake(handle, ticksToWait) == pdTRUE);
+ }
+
+ /**
+ * Mutex.hpp
+ *
+ * @brief Function that calls xSemaphoreTakeFromISR ( SemaphoreHandle_t
+ * xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @param higherPriorityTaskWoken It is possible (although unlikely, and
+ * dependent on the semaphore type) that a mutex will have one or more tasks
+ * blocked on it waiting to give the mutex. Calling lockFromISR() will make a
+ * task that was blocked waiting to give the mutex leave the Blocked state. If
+ * calling the API function causes a task to leave the Blocked state, and the
+ * unblocked task has a priority equal to or higher than the currently
+ * executing task (the task that was interrupted), then, internally, the API
+ * function will set higherPriorityTaskWoken to true.
+ * @return true If the mutex was successfully locked.
+ * @return false If the mutex was not successfully locked because it was not
+ * available.
+ */
+ inline bool lockFromISR(bool& higherPriorityTaskWoken) const {
+ BaseType_t taskWoken = pdFALSE;
+ bool result = (xSemaphoreTakeFromISR(handle, &taskWoken) == pdTRUE);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * Mutex.hpp
+ *
+ * @brief Function that calls xSemaphoreTakeFromISR ( SemaphoreHandle_t
+ * xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline bool lockFromISR() const {
+ return (xSemaphoreTakeFromISR(handle, NULL) == pdTRUE);
+ }
+
+ /**
+ * Mutex.hpp
+ *
+ * @brief Function that calls xSemaphoreGive( SemaphoreHandle_t xSemaphore
+ * )
+ *
+ * @see
+ *
+ * @warning This must not be used from an ISR.
+ *
+ * @return true If the mutex was unlocked.
+ * @return false If an error occurred. Mutexes (semaphores) are implemented
+ * using queues. An error can occur if there is no space on the queue to post
+ * a message indicating that the mutex was not first locked correctly.
+ *
+ * Example Usage
+ * @include Mutex/unlock.cpp
+ */
+ inline bool unlock() const { return (xSemaphoreGive(handle) == pdTRUE); }
+
+ private:
+ MutexBase() = default;
+
+ /**
+ * Mutex.hpp
+ *
+ * @brief Destroy the MutexBase object by calling void vSemaphoreDelete(
+ * SemaphoreHandle_t xSemaphore )
+ *
+ * @see
+ *
+ * @note Do not delete a mutex that has tasks blocked on it (tasks that are in
+ * the Blocked state waiting for the mutex to become available).
+ */
+ ~MutexBase() { vSemaphoreDelete(this->handle); }
+
+ MutexBase(MutexBase&&) noexcept = default;
+ MutexBase& operator=(MutexBase&&) noexcept = default;
+
+ /**
+ * @brief Handle used to refer to the semaphore when using the FreeRTOS
+ * interface.
+ */
+ SemaphoreHandle_t handle = NULL;
+};
+
+/**
+ * @class RecursiveMutexBase Mutex.hpp
+ *
+ * @brief Base class that provides the recursive mutex interface to
+ * FreeRTOS::RecursiveMutex and FreeRTOS::StaticRecursiveMutex. This class
+ * exists to override the lock() and unlock() functions which require different
+ * underlying functions from what is used in FreeRTOS::MutexBase.
+ *
+ * @note This class is not intended to be instantiated by the user. Use
+ * FreeRTOS::RecursiveMutex or FreeRTOS::StaticRecursiveMutex.
+ */
+class RecursiveMutexBase : public MutexBase {
+ public:
+ friend class RecursiveMutex;
+ friend class StaticRecursiveMutex;
+
+ RecursiveMutexBase(const RecursiveMutexBase&) = delete;
+ RecursiveMutexBase& operator=(const RecursiveMutexBase&) = delete;
+
+ static void* operator new(size_t, void*);
+ static void* operator new[](size_t, void*);
+ static void* operator new(size_t) = delete;
+ static void* operator new[](size_t) = delete;
+
+ /**
+ * Mutex.hpp
+ *
+ * @brief Function that calls xSemaphoreTakeRecursive( SemaphoreHandle_t
+ * xMutex, TickType_t xTicksToWait )
+ *
+ * @see
+ *
+ * @param ticksToWait The time in ticks to wait for the mutex to become
+ * available. The macro portTICK_PERIOD_MS can be used to convert this to a
+ * real time. A block time of zero can be used to poll the mutex. If the task
+ * already owns the mutex then take() will return immediately no matter what
+ * the value of ticksToWait.
+ * @retval true If the mutex was locked.
+ * @retval false If ticksToWait expired without the mutex becoming available.
+ *
+ * Example Usage
+ * @include Mutex/recursiveLock.cpp
+ */
+ inline bool lock(const TickType_t ticksToWait = portMAX_DELAY) const {
+ return (xSemaphoreTakeRecursive(handle, ticksToWait) == pdTRUE);
+ }
+
+ /**
+ * Mutex.hpp
+ *
+ * @brief Function that calls xSemaphoreGiveRecursive( SemaphoreHandle_t
+ * xSemaphore )
+ *
+ * @see
+ *
+ * A mutex used recursively can be locked repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called unlock() for each
+ * successful lock request. For example, if a task successfully locks the
+ * same mutex 5 times then the mutex will not be available to any other task
+ * until it has also unlocked the mutex back exactly five times.
+ *
+ * @return true If the mutex was unlocked.
+ * @return false Otherwise.
+ *
+ * Example Usage
+ * @include Mutex/recursiveLock.cpp
+ */
+ inline bool unlock() const {
+ return (xSemaphoreGiveRecursive(handle) == pdTRUE);
+ }
+
+ private:
+ RecursiveMutexBase() = default;
+ ~RecursiveMutexBase() = default;
+
+ RecursiveMutexBase(RecursiveMutexBase&&) noexcept = default;
+ RecursiveMutexBase& operator=(RecursiveMutexBase&&) noexcept = default;
+};
+
+#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+
+/**
+ * @class Mutex Mutex.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS mutex.
+ *
+ * Each mutex require a small amount of RAM that is used to hold the mutex's
+ * state. If a mutex is created using FreeRTOS::Mutex then the required RAM is
+ * automatically allocated from the FreeRTOS heap. If a mutex is created using
+ * FreeRTOS::StaticMutex then the RAM is provided by the application writer and
+ * allows the RAM to be statically allocated at compile time. See the Static Vs
+ * Dynamic allocation page for more information.
+ *
+ * Mutexes and binary semaphores are very similar but have some subtle
+ * differences: Mutexes include a priority inheritance mechanism, binary
+ * semaphores do not. This makes binary semaphores the better choice for
+ * implementing synchronisation (between tasks or between tasks and an
+ * interrupt), and mutexes the better choice for implementing simple mutual
+ * exclusion.
+ *
+ * The priority of a task that locks a mutex will be temporarily raised if
+ * another task of higher priority attempts to obtain the same mutex. The task
+ * that owns the mutex 'inherits' the priority of the task attempting to lock
+ * the same mutex. This means the mutex must always be unlocked back otherwise
+ * the higher priority task will never be able to lock the mutex, and the lower
+ * priority task will never 'disinherit' the priority.
+ */
+class Mutex : public MutexBase {
+ public:
+ /**
+ * Mutex.hpp
+ *
+ * @brief Construct a new Mutex object by calling SemaphoreHandle_t
+ * xSemaphoreCreateMutex( void )
+ *
+ * @see
+ *
+ * @warning The user should call isValid() on this object to verify that the
+ * mutex was created successfully in case the memory required to create the
+ * queue could not be allocated.
+ *
+ * Example Usage
+ * @include Mutex/mutex.cpp
+ */
+ Mutex() { this->handle = xSemaphoreCreateMutex(); }
+ ~Mutex() = default;
+
+ Mutex(const Mutex&) = delete;
+ Mutex& operator=(const Mutex&) = delete;
+
+ Mutex(Mutex&&) noexcept = default;
+ Mutex& operator=(Mutex&&) noexcept = default;
+};
+
+/**
+ * @class RecursiveMutex Mutex.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS recursive
+ * mutex.
+ *
+ * Each recursive mutex require a small amount of RAM that is used to hold the
+ * recursive mutex's state. If a mutex is created using FreeRTOS::RecursiveMutex
+ * then the required RAM is automatically allocated from the FreeRTOS heap. If a
+ * recursive mutex is created using FreeRTOS::StaticRecursiveMutex then the RAM
+ * is provided by the application writer, which requires an additional
+ * parameter, but allows the RAM to be statically allocated at compile time. See
+ * the Static Vs Dynamic allocation page for more information.
+ *
+ * Contrary to non-recursive mutexes, a task can lock a recursive mutex multiple
+ * times, and the recursive mutex will only be returned after the holding task
+ * has unlocked the mutex the same number of times it locked the mutex.
+ *
+ * Like non-recursive mutexes, recursive mutexes implement a priority
+ * inheritance algorithm. The priority of a task that locks a mutex will be
+ * temporarily raised if another task of higher priority attempts to obtain the
+ * same mutex. The task that owns the mutex 'inherits' the priority of the task
+ * attempting to lock the same mutex. This means the mutex must always be
+ * unlocked otherwise the higher priority task will never be able to obtain the
+ * mutex, and the lower priority task will never 'disinherit' the priority.
+ */
+class RecursiveMutex : public RecursiveMutexBase {
+ public:
+ /**
+ * Mutex.hpp
+ *
+ * @brief Construct a new RecursiveMutex object by calling
+ * SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )
+ *
+ * @see
+ *
+ * @warning The user should call isValid() on this object to verify that the
+ * recursive mutex was created successfully in case the memory required to
+ * create the queue could not be allocated.
+ *
+ * Example Usage
+ * @include Mutex/recursiveMutex.cpp
+ */
+ RecursiveMutex() { this->handle = xSemaphoreCreateRecursiveMutex(); }
+ ~RecursiveMutex() = default;
+
+ RecursiveMutex(const RecursiveMutex&) = delete;
+ RecursiveMutex& operator=(const RecursiveMutex&) = delete;
+
+ RecursiveMutex(RecursiveMutex&&) noexcept = default;
+ RecursiveMutex& operator=(RecursiveMutex&&) noexcept = default;
+};
+
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+#if (configSUPPORT_STATIC_ALLOCATION == 1)
+
+/**
+ * @class StaticMutex Mutex.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS mutex.
+ *
+ * Each mutex require a small amount of RAM that is used to hold the mutex's
+ * state. If a mutex is created using FreeRTOS::Mutex then the required RAM is
+ * automatically allocated from the FreeRTOS heap. If a mutex is created using
+ * FreeRTOS::StaticMutex then the RAM is provided by the application writer and
+ * allows the RAM to be statically allocated at compile time. See the Static Vs
+ * Dynamic allocation page for more information.
+ *
+ * Mutexes and binary semaphores are very similar but have some subtle
+ * differences: Mutexes include a priority inheritance mechanism, binary
+ * semaphores do not. This makes binary semaphores the better choice for
+ * implementing synchronisation (between tasks or between tasks and an
+ * interrupt), and mutexes the better choice for implementing simple mutual
+ * exclusion.
+ *
+ * The priority of a task that locks a mutex will be temporarily raised if
+ * another task of higher priority attempts to obtain the same mutex. The task
+ * that owns the mutex 'inherits' the priority of the task attempting to lock
+ * the same mutex. This means the mutex must always be unlocked back otherwise
+ * the higher priority task will never be able to lock the mutex, and the lower
+ * priority task will never 'disinherit' the priority.
+ */
+class StaticMutex : public MutexBase {
+ public:
+ /**
+ * Mutex.hpp
+ *
+ * @brief Construct a new StaticMutex object by calling
+ * SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t
+ * *pxMutexBuffer )
+ *
+ * @see
+ *
+ * @warning This class contains the storage buffer for the mutex, so the user
+ * should create this object as a global object or with the static storage
+ * specifier so that the object instance is not on the stack.
+ *
+ * Example Usage
+ * @include Mutex/staticMutex.cpp
+ */
+ StaticMutex() { this->handle = xSemaphoreCreateMutexStatic(&staticMutex); }
+ ~StaticMutex() = default;
+
+ StaticMutex(const StaticMutex&) = delete;
+ StaticMutex& operator=(const StaticMutex&) = delete;
+
+ StaticMutex(StaticMutex&&) noexcept = default;
+ StaticMutex& operator=(StaticMutex&&) noexcept = default;
+
+ private:
+ StaticSemaphore_t staticMutex;
+};
+
+/**
+ * @class StaticRecursiveMutex Mutex.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS recursive
+ * mutex.
+ *
+ * Each recursive mutex require a small amount of RAM that is used to hold the
+ * recursive mutex's state. If a mutex is created using FreeRTOS::RecursiveMutex
+ * then the required RAM is automatically allocated from the FreeRTOS heap. If a
+ * recursive mutex is created using FreeRTOS::StaticRecursiveMutex then the RAM
+ * is provided by the application writer, which requires an additional
+ * parameter, but allows the RAM to be statically allocated at compile time. See
+ * the Static Vs Dynamic allocation page for more information.
+ *
+ * Contrary to non-recursive mutexes, a task can lock a recursive mutex multiple
+ * times, and the recursive mutex will only be returned after the holding task
+ * has unlocked the mutex the same number of times it locked the mutex.
+ *
+ * Like non-recursive mutexes, recursive mutexes implement a priority
+ * inheritance algorithm. The priority of a task that locks a mutex will be
+ * temporarily raised if another task of higher priority attempts to obtain the
+ * same mutex. The task that owns the mutex 'inherits' the priority of the task
+ * attempting to lock the same mutex. This means the mutex must always be
+ * unlocked otherwise the higher priority task will never be able to obtain the
+ * mutex, and the lower priority task will never 'disinherit' the priority.
+ */
+class StaticRecursiveMutex : public RecursiveMutexBase {
+ public:
+ /**
+ * Mutex.hpp
+ *
+ * @brief Construct a new StaticRecursiveMutex object by calling
+ * SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic(
+ * StaticSemaphore_t *pxMutexBuffer )
+ *
+ * @see
+ *
+ * @warning This class contains the storage buffer for the recursive mutex, so
+ * the user should create this object as a global object or with the static
+ * storage specifier so that the object instance is not on the stack.
+ *
+ * Example Usage
+ * @include Mutex/staticRecursiveMutex.cpp
+ */
+ StaticRecursiveMutex() {
+ this->handle = xSemaphoreCreateRecursiveMutexStatic(&staticRecursiveMutex);
+ }
+ ~StaticRecursiveMutex() = default;
+
+ StaticRecursiveMutex(const StaticRecursiveMutex&) = delete;
+ StaticRecursiveMutex& operator=(const StaticRecursiveMutex&) = delete;
+
+ StaticRecursiveMutex(StaticRecursiveMutex&&) noexcept = default;
+ StaticRecursiveMutex& operator=(StaticRecursiveMutex&&) noexcept = default;
+
+ private:
+ StaticSemaphore_t staticRecursiveMutex;
+};
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+} // namespace FreeRTOS
+
+#endif // FREERTOS_MUTEX_HPP
diff --git a/source/test/src/FreeRTOSCPP/Queue.hpp b/source/test/src/FreeRTOSCPP/Queue.hpp
new file mode 100644
index 0000000..fe6cc31
--- /dev/null
+++ b/source/test/src/FreeRTOSCPP/Queue.hpp
@@ -0,0 +1,737 @@
+/*
+ * FreeRTOS-Cpp
+ * Copyright (C) 2021 Jon Enz. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://github.com/jonenz/FreeRTOS-Cpp
+ */
+
+#ifndef FREERTOS_QUEUE_HPP
+#define FREERTOS_QUEUE_HPP
+
+#include
+
+#include "FreeRTOS.h"
+#include "queue.h"
+
+namespace FreeRTOS {
+
+/**
+ * @class QueueBase Queue.hpp
+ *
+ * @brief Base class that provides the standard queue interface to
+ * FreeRTOS::Queue and FreeRTOS::StaticQueue.
+ *
+ * @note This class is not intended to be instantiated by the user. Use
+ * FreeRTOS::Queue or FreeRTOS::StaticQueue.
+ *
+ * @tparam T Type to be stored in the queue.
+ */
+template
+class QueueBase {
+ public:
+ template
+ friend class Queue;
+
+ template
+ friend class StaticQueue;
+
+ QueueBase(const QueueBase&) = delete;
+ QueueBase& operator=(const QueueBase&) = delete;
+
+ static void* operator new(size_t, void* ptr) { return ptr; }
+ static void* operator new[](size_t, void* ptr) { return ptr; }
+ static void* operator new(size_t) = delete;
+ static void* operator new[](size_t) = delete;
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that checks if the underlying queue handle is not NULL.
+ * This should be used to ensure a queue has been created correctly.
+ *
+ * @retval true the handle is not NULL.
+ * @retval false the handle is NULL.
+ */
+ inline bool isValid() const { return (handle != NULL); }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls xQueueSendToBack( xQueue, pvItemToQueue,
+ * xTicksToWait )
+ *
+ * @see
+ *
+ * Post an item to the back of a queue. The item is queued by copy, not by
+ * reference. This function must not be called from an interrupt service
+ * routine. See FreeRTOS::Queue::sendToBackFromISR() for an alternative which
+ * may be used in an ISR.
+ *
+ * @param item A reference to the item that is to be placed on the queue.
+ * @param ticksToWait The maximum amount of time the task should block waiting
+ * for space to become available on the queue, should it already be full. The
+ * call will return immediately if this is set to 0 and the queue is full. The
+ * time is defined in tick periods so the constant portTICK_PERIOD_MS should
+ * be used to convert to real time if this is required.
+ * @retval true if the item was successfully posted.
+ * @retval false otherwise.
+ *
+ * Example Usage
+ * @include Queue/sendToBack.cpp
+ */
+ inline bool sendToBack(const T& item,
+ const TickType_t ticksToWait = portMAX_DELAY) const {
+ return (xQueueSendToBack(handle, &item, ticksToWait) == pdTRUE);
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls xQueueSendToBackFromISR( xQueue,
+ * pvItemToQueue, pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @param higherPriorityTaskWoken A reference that will be set to true if
+ * sending to the queue caused a task to unblock, and the unblocked task has a
+ * priority higher than the currently running task.
+ * @param item A reference to the item that is to be placed on the queue.
+ * @retval true if the item was successfully posted
+ * @retval false otherwise.
+ *
+ * Example Usage
+ * @include Queue/sendToBackFromISR.cpp
+ */
+ inline bool sendToBackFromISR(bool& higherPriorityTaskWoken,
+ const T& item) const {
+ BaseType_t taskWoken = pdFALSE;
+ bool result =
+ (xQueueSendToBackFromISR(handle, &item, &taskWoken) == pdPASS);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls xQueueSendToBackFromISR( xQueue,
+ * pvItemToQueue, pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline bool sendToBackFromISR(const T& item) const {
+ return (xQueueSendToBackFromISR(handle, &item, NULL) == pdPASS);
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls xQueueSendToFront( xQueue, pvItemToQueue,
+ * xTicksToWait )
+ *
+ * @see
+ *
+ * @param item A reference to the item that is to be placed on the queue.
+ * @param ticksToWait The maximum amount of time the task should block waiting
+ * for space to become available on the queue, should it already be full. The
+ * call will return immediately if this is set to 0 and the queue is full. The
+ * time is defined in tick periods so the constant portTICK_PERIOD_MS should
+ * be used to convert to real time if this is required.
+ * @retval true if the item was successfully posted.
+ * @retval false otherwise.
+ *
+ * Example Usage
+ * @include Queue/sendToFront.cpp
+ */
+ inline bool sendToFront(const T& item,
+ const TickType_t ticksToWait = portMAX_DELAY) const {
+ return (xQueueSendToFront(handle, &item, ticksToWait) == pdTRUE);
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls xQueueSendToFrontFromISR( xQueue,
+ * pvItemToQueue, pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @param higherPriorityTaskWoken A reference that will be set to true if
+ * sending to the queue caused a task to unblock, and the unblocked task has a
+ * priority higher than the currently running task.
+ * @param item A reference to the item that is to be placed on the queue.
+ * @retval true if the item was successfully posted
+ * @retval false otherwise.
+ *
+ * Example Usage
+ * @include Queue/sendToFrontFromISR.cpp
+ */
+ inline bool sendToFrontFromISR(bool& higherPriorityTaskWoken,
+ const T& item) const {
+ BaseType_t taskWoken = pdFALSE;
+ bool result =
+ (xQueueSendToFrontFromISR(handle, &item, &taskWoken) == pdPASS);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls xQueueSendToFrontFromISR( xQueue,
+ * pvItemToQueue, pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline bool sendToFrontFromISR(const T& item) const {
+ return (xQueueSendToFrontFromISR(handle, &item, NULL) == pdPASS);
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueueReceive( QueueHandle_t
+ * xQueue, void *pvBuffer, TickType_t xTicksToWait )
+ *
+ * @see
+ *
+ * Receive an item from a queue. This function must not be used in an
+ * interrupt service routine. See receiveFromISR() for an alternative that
+ * can.
+ *
+ * @param ticksToWait The maximum amount of time the task should block waiting
+ * for an item to receive should the queue be empty at the time of the call.
+ * Setting ticksToWait to 0 will cause the function to return immediately if
+ * the queue is empty. The time is defined in tick periods so the constant
+ * portTICK_PERIOD_MS should be used to convert to real time if this is
+ * required.
+ * @return std::optional Object from the queue. User should check that the
+ * value is present.
+ *
+ * Example Usage
+ * @include Queue/receive.cpp
+ */
+ inline std::optional receive(
+ const TickType_t ticksToWait = portMAX_DELAY) const {
+ T buffer;
+ return (xQueueReceive(handle, &buffer, ticksToWait) == pdTRUE)
+ ? std::optional(buffer)
+ : std::nullopt;
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueueReceiveFromISR(
+ * QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxHigherPriorityTaskWoken
+ * )
+ *
+ * @see
+ *
+ * Receive an item from a queue. It is safe to use this function from within
+ * an interrupt service routine.
+ *
+ * @param higherPriorityTaskWoken A reference that will be set to true if
+ * sending to the queue caused a task to unblock, and the unblocked task has a
+ * priority higher than the currently running task.
+ * @return std::optional Object from the queue. User should check that the
+ * value is present.
+ *
+ * Example Usage
+ * @include Queue/receiveFromISR.cpp
+ */
+ inline std::optional receiveFromISR(bool& higherPriorityTaskWoken) const {
+ T buffer;
+ BaseType_t taskWoken = pdFALSE;
+ bool result = (xQueueReceiveFromISR(handle, &buffer, &taskWoken) == pdTRUE);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result ? std::optional(buffer) : std::nullopt;
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueueReceiveFromISR(
+ * QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxHigherPriorityTaskWoken
+ * )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline std::optional receiveFromISR() const {
+ T buffer;
+ return (xQueueReceiveFromISR(handle, &buffer, NULL) == pdTRUE)
+ ? std::optional(buffer)
+ : std::nullopt;
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls UBaseType_t uxQueueMessagesWaiting(
+ * QueueHandle_t xQueue )
+ *
+ * @see
+ *
+ * Return the number of messages stored in a queue.
+ *
+ * @retval UBaseType_t The number of messages available in the queue.
+ */
+ inline UBaseType_t messagesWaiting() const {
+ return uxQueueMessagesWaiting(handle);
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls UBaseType_t uxQueueMessagesWaitingFromISR(
+ * QueueHandle_t xQueue )
+ *
+ * @see
+ *
+ * A version of messagesWaiting() that can be called from an ISR. Return the
+ * number of messages stored in a queue.
+ *
+ * @retval UBaseType_t The number of messages available in the queue.
+ */
+ inline UBaseType_t messagesWaitingFromISR() const {
+ return uxQueueMessagesWaitingFromISR(handle);
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls UBaseType_t uxQueueSpacesAvailable(
+ * QueueHandle_t xQueue )
+ *
+ * @see
+ *
+ * Return the number of free spaces in a queue.
+ *
+ * @retval UBaseType_t The number of free spaces available in the queue.
+ */
+ inline UBaseType_t spacesAvailable() const {
+ return uxQueueSpacesAvailable(handle);
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueueReset( QueueHandle_t xQueue
+ * )
+ *
+ * @see
+ *
+ * Resets a queue to its original empty state.
+ */
+ inline void reset() const { xQueueReset(handle); }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueueOverwrite( QueueHandle_t
+ * xQueue, const void * pvItemToQueue )
+ *
+ * @see
+ *
+ * Only for use with queues that have a length of one - so the queue is either
+ * empty or full.
+ *
+ * Post an item on a queue. If the queue is already full then overwrite the
+ * value held in the queue. The item is queued by copy, not by reference.
+ *
+ * This function must not be called from an interrupt service routine. See
+ * overwriteFromISR() for an alternative which may be used in an ISR.
+ *
+ * @param item A reference to the item that is to be placed on the queue.
+ *
+ * Example Usage
+ * @include Queue/overwrite.cpp
+ */
+ inline void overwrite(const T& item) const { xQueueOverwrite(handle, &item); }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueueOverwriteFromISR(
+ * QueueHandle_t xQueue, const void * pvItemToQueue, BaseType_t
+ * *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * A version of overwrite() that can be used in an interrupt service routine
+ * (ISR).
+ *
+ * Only for use with queues that can hold a single item - so the queue is
+ * either empty or full.
+ *
+ * Post an item on a queue. If the queue is already full then overwrite the
+ * value held in the queue. The item is queued by copy, not by reference.
+ *
+ * @param higherPriorityTaskWoken A reference that will be set to true if
+ * sending to the queue caused a task to unblock, and the unblocked task has a
+ * priority higher than the currently running task.
+ * @param item A reference to the item that is to be placed on the queue.
+ *
+ * Example Usage
+ * @include Queue/overwriteFromISR.cpp
+ */
+ inline void overwriteFromISR(bool& higherPriorityTaskWoken,
+ const T& item) const {
+ BaseType_t taskWoken = pdFALSE;
+ xQueueOverwriteFromISR(handle, &item, &taskWoken);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueueOverwriteFromISR(
+ * QueueHandle_t xQueue, const void * pvItemToQueue, BaseType_t
+ * *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline void overwriteFromISR(const T& item) const {
+ xQueueOverwriteFromISR(handle, &item, NULL);
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueuePeek( QueueHandle_t xQueue,
+ * void * const pvBuffer, TickType_t xTicksToWait )
+ *
+ * @see
+ *
+ * Receive an item from a queue without removing the item from the queue.
+ *
+ * Successfully received items remain on the queue so will be returned again
+ * by the next call, or a call to receive().
+ *
+ * This function must not be used in an interrupt service routine. See
+ * peekFromISR() for an alternative that can be called from an interrupt
+ * service routine.
+ *
+ * @param ticksToWait The maximum amount of time the task should block waiting
+ * for an item to receive should the queue be empty at the time of the call.
+ * Setting ticksToWait to 0 will cause the function to return immediately if
+ * the queue is empty. The time is defined in tick periods so the constant
+ * portTICK_PERIOD_MS should be used to convert to real time if this is
+ * required.
+ * @return std::optional Object from the queue. User should check that the
+ * value is present.
+ *
+ * Example Usage
+ * @include Queue/peek.cpp
+ */
+ inline std::optional peek(
+ const TickType_t ticksToWait = portMAX_DELAY) const {
+ T buffer;
+ return (xQueuePeek(handle, &buffer, ticksToWait) == pdTRUE)
+ ? std::optional(buffer)
+ : std::nullopt;
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueuePeekFromISR( QueueHandle_t
+ * xQueue, void *pvBuffer )
+ *
+ * @see
+ *
+ * A version of peek() that can be called from an interrupt service routine
+ * (ISR).
+ *
+ * Receive an item from a queue without removing the item from the queue.
+ *
+ * Successfully received items remain on the queue so will be returned again
+ * by the next call, or a call to receive().
+ *
+ * @return std::optional Object from the queue. User should check that the
+ * value is present.
+ */
+ inline std::optional peekFromISR() const {
+ T buffer;
+ return (xQueuePeekFromISR(handle, &buffer) == pdTRUE)
+ ? std::optional(buffer)
+ : std::nullopt;
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls void vQueueAddToRegistry( QueueHandle_t
+ * xQueue, char *pcQueueName )
+ *
+ * @see
+ *
+ * The registry is provided as a means for kernel aware debuggers to locate
+ * queues, semaphores and mutexes. Call addToRegistry() add a queue,
+ * semaphore or mutex handle to the registry if you want the handle to be
+ * available to a kernel aware debugger. If you are not using a kernel aware
+ * debugger then this function can be ignored.
+ *
+ * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the
+ * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 within
+ * FreeRTOSConfig.h for the registry to be available. Its value does not
+ * effect the number of queues, semaphores and mutexes that can be created -
+ * just the number that the registry can hold.
+ *
+ * If addToRegistry() is called more than once for the same queue, the
+ * registry will store the name parameter from the most recent call to
+ * addToRegistry().
+ *
+ * @param name The name to be associated with the handle. This is the name
+ * that the kernel aware debugger will display. The queue registry only
+ * stores a pointer to the string - so the string must be persistent (global
+ * or preferably in ROM/Flash), not on the stack.
+ */
+ inline void addToRegistry(const char* name) const {
+ vQueueAddToRegistry(handle, name);
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls void vQueueUnregisterQueue( QueueHandle_t
+ * xQueue )
+ *
+ * @see
+ *
+ * The registry is provided as a means for kernel aware debuggers to locate
+ * queues, semaphores and mutexes. Call addToRegistry() add a queue,
+ * semaphore or mutex handle to the registry if you want the handle to be
+ * available to a kernel aware debugger, and unregister() to remove the queue,
+ * semaphore or mutex from the register. If you are not using a kernel aware
+ * debugger then this function can be ignored.
+ */
+ inline void unregister() const { vQueueUnregisterQueue(handle); }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls const char *pcQueueGetName( QueueHandle_t
+ * xQueue )
+ *
+ * @see
+ *
+ * The queue registry is provided as a means for kernel aware debuggers to
+ * locate queues, semaphores and mutexes. Call getName() to look up and return
+ * the name of a queue in the queue registry from the queue's handle.
+ *
+ * @return If the queue referenced by the queue is in the queue registry, then
+ * the text name of the queue is returned, otherwise NULL is returned.
+ */
+ inline const char* getName() const { return pcQueueGetName(handle); }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueueIsQueueFullFromISR( const
+ * QueueHandle_t xQueue )
+ *
+ * @see
+ *
+ * Queries a queue to determine if the queue is empty. This function should
+ * only be used in an ISR.
+ *
+ * @return true if the queue is full.
+ * @return false if the queue is not full.
+ */
+ inline bool isFullFromISR() const {
+ return (xQueueIsQueueFullFromISR(handle) == pdTRUE);
+ }
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Function that calls BaseType_t xQueueIsQueueEmptyFromISR( const
+ * QueueHandle_t xQueue )
+ *
+ * @see
+ *
+ * Queries a queue to determine if the queue is empty. This function should
+ * only be used in an ISR.
+ *
+ * @retval true if the queue is empty.
+ * @retval false if the queue is not empty.
+ */
+ inline bool isEmptyFromISR() const {
+ return (xQueueIsQueueEmptyFromISR(handle) == pdTRUE);
+ }
+
+ private:
+ /**
+ * Queue.hpp
+ *
+ * @brief Construct a new QueueBase object.
+ *
+ * @note Default constructor is deliberately private as this class is not
+ * intended to be instantiated or derived from by the user. Use
+ * FreeRTOS::Queue or FreeRTOS::StaticQueue.
+ */
+ QueueBase() = default;
+
+ /**
+ * Queue.hpp
+ *
+ * @brief Destroy the QueueBase object by calling void vQueueDelete(
+ * QueueHandle_t xQueue )
+ *
+ * @see
+ *
+ * Delete a queue - freeing all the memory allocated for storing of items
+ * placed on the queue.
+ */
+ ~QueueBase() { vQueueDelete(this->handle); }
+
+ QueueBase(QueueBase&&) noexcept = default;
+ QueueBase& operator=(QueueBase&&) noexcept = default;
+
+ /**
+ * @brief Handle used to refer to the queue when using the FreeRTOS interface.
+ */
+ QueueHandle_t handle = NULL;
+};
+
+#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+
+/**
+ * @class Queue Queue.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS queue.
+ *
+ * Each queue requires RAM that is used to hold the queue state, and to hold the
+ * items that are contained in the queue (the queue storage area). If a queue is
+ * created using this class then the required RAM is automatically allocated
+ * from the FreeRTOS heap.
+ *
+ * @tparam T Type to be stored in the queue.
+ */
+template
+class Queue : public QueueBase {
+ public:
+ /**
+ * Queue.hpp
+ *
+ * @brief Construct a new Queue object by calling QueueHandle_t
+ * xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize )
+ *
+ * @see
+ *
+ * @warning The user should call isValid() on this object to verify that the
+ * queue was created successfully in case the memory required to create the
+ * queue could not be allocated.
+ *
+ * @param length The maximum number of items the queue can hold at any one
+ * time.
+ *
+ * Example Usage
+ * @include Queue/queue.cpp
+ */
+ explicit Queue(const UBaseType_t length) {
+ this->handle = xQueueCreate(length, sizeof(T));
+ }
+ ~Queue() = default;
+
+ Queue(const Queue&) = delete;
+ Queue& operator=(const Queue&) = delete;
+
+ Queue(Queue&&) noexcept = default;
+ Queue& operator=(Queue&&) noexcept = default;
+};
+
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+#if (configSUPPORT_STATIC_ALLOCATION == 1)
+
+/**
+ * @class StaticQueue Queue.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS queue.
+ *
+ * If a queue is created using this class then the RAM is provided by the
+ * application writer as part of the object instance and allows the RAM to be
+ * statically allocated at compile time.
+ *
+ * @tparam T Type to be stored in the queue.
+ * @tparam N The maximum number of items the queue can hold at any one time.
+ */
+template
+class StaticQueue : public QueueBase {
+ public:
+ /**
+ * Queue.hpp
+ *
+ * @brief Construct a new StaticQueue object by calling
+ * QueueHandle_t xQueueCreateStatic( UBaseType_t uxQueueLength,
+ * UBaseType_t uxItemSize, uint8_t *pucQueueStorageBuffer, StaticQueue_t
+ * *pxQueueBuffer )
+ *
+ * @see
+ *
+ * @warning This class contains the storage buffer for the queue, so the user
+ * should create this object as a global object or with the static storage
+ * specifier so that the object instance is not on the stack.
+ *
+ * Example Usage
+ * @include Queue/staticQueue.cpp
+ */
+ StaticQueue() {
+ this->handle = xQueueCreateStatic(N, sizeof(T), storage, &staticQueue);
+ }
+ ~StaticQueue() = default;
+
+ StaticQueue(const StaticQueue&) = delete;
+ StaticQueue& operator=(const StaticQueue&) = delete;
+
+ StaticQueue(StaticQueue&&) noexcept = default;
+ StaticQueue& operator=(StaticQueue&&) noexcept = default;
+
+ private:
+ StaticQueue_t staticQueue;
+ uint8_t storage[N * sizeof(T)];
+};
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+} // namespace FreeRTOS
+
+#endif // FREERTOS_QUEUE_HPP
diff --git a/source/test/src/FreeRTOSCPP/Semaphore.hpp b/source/test/src/FreeRTOSCPP/Semaphore.hpp
new file mode 100644
index 0000000..63d7bfa
--- /dev/null
+++ b/source/test/src/FreeRTOSCPP/Semaphore.hpp
@@ -0,0 +1,523 @@
+/*
+ * FreeRTOS-Cpp
+ * Copyright (C) 2021 Jon Enz. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://github.com/jonenz/FreeRTOS-Cpp
+ */
+
+#ifndef FREERTOS_SEMAPHORE_HPP
+#define FREERTOS_SEMAPHORE_HPP
+
+#include "FreeRTOS.h"
+#include "semphr.h"
+
+namespace FreeRTOS {
+
+/**
+ * @class SemaphoreBase Semaphore.hpp
+ *
+ * @brief Base class that provides the standard semaphore interface to
+ * FreeRTOS::BinarySemaphore, FreeRTOS::StaticBinarySemaphore,
+ * FreeRTOS::CountingSemaphore, and FreeRTOS::StaticCountingSemaphore.
+ *
+ * @note This class is not intended to be instantiated by the user. Use
+ * FreeRTOS::BinarySemaphore, FreeRTOS::StaticBinarySemaphore,
+ * FreeRTOS::CountingSemaphore, or FreeRTOS::StaticCountingSemaphore.
+ */
+class SemaphoreBase {
+ public:
+ friend class BinarySemaphore;
+ friend class StaticBinarySemaphore;
+ friend class CountingSemaphore;
+ friend class StaticCountingSemaphore;
+
+ SemaphoreBase(const SemaphoreBase&) = delete;
+ SemaphoreBase& operator=(const SemaphoreBase&) = delete;
+
+ static void* operator new(size_t, void* ptr) { return ptr; }
+ static void* operator new[](size_t, void* ptr) { return ptr; }
+ static void* operator new(size_t) = delete;
+ static void* operator new[](size_t) = delete;
+
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Function that checks if the underlying semaphore handle is not NULL.
+ * This should be used to ensure a semaphore has been created correctly.
+ *
+ * @retval true the handle is not NULL.
+ * @retval false the handle is NULL.
+ */
+ inline bool isValid() const { return (handle != NULL); }
+
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Function that calls UBaseType_t uxSemaphoreGetCount(
+ * SemaphoreHandle_t xSemaphore )
+ *
+ * @see
+ *
+ * Returns the count of a semaphore.
+ *
+ * @return UBaseType_t If the semaphore is a counting semaphore then the
+ * semaphores current count value is returned. If the semaphore is a binary
+ * semaphore then 1 is returned if the semaphore is available, and 0 is
+ * returned if the semaphore is not available.
+ */
+ inline UBaseType_t getCount() const { return uxSemaphoreGetCount(handle); }
+
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Function that calls xSemaphoreTake( SemaphoreHandle_t
+ * xSemaphore, TickType_t xTicksToWait )
+ *
+ * @see
+ *
+ * Function to obtain a semaphore.
+ *
+ * This macro must not be called from an ISR. takeFromISR() can be used to
+ * take a semaphore from within an interrupt if required, although this would
+ * not be a normal operation. Semaphores use queues as their underlying
+ * mechanism, so functions are to some extent interoperable.
+ *
+ * @param ticksToWait The time in ticks to wait for the semaphore to become
+ * available. The macro portTICK_PERIOD_MS can be used to convert this to a
+ * real time. A block time of zero can be used to poll the semaphore.
+ * @retval true If the semaphore was obtained.
+ * @retval false If xTicksToWait expired without the semaphore becoming
+ * available.
+ *
+ * Example Usage
+ * @include Semaphore/take.cpp
+ */
+ inline bool take(const TickType_t ticksToWait = portMAX_DELAY) const {
+ return (xSemaphoreTake(handle, ticksToWait) == pdTRUE);
+ }
+
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Function that calls xSemaphoreTakeFromISR( SemaphoreHandle_t
+ * xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken)
+ *
+ * @see
+ *
+ * A version of take() that can be called from an ISR. Unlike take(),
+ * takeFromISR() does not permit a block time to be specified.
+ *
+ * @param higherPriorityTaskWoken It is possible (although unlikely, and
+ * dependent on the semaphore type) that a semaphore will have one or more
+ * tasks blocked on it waiting to give the semaphore. Calling takeFromISR()
+ * will make a task that was blocked waiting to give the semaphore leave the
+ * Blocked state. If calling the API function causes a task to leave the
+ * Blocked state, and the unblocked task has a priority equal to or higher
+ * than the currently executing task (the task that was interrupted), then,
+ * internally, the API function will set higherPriorityTaskWoken to true. If
+ * takeFromISR() sets higherPriorityTaskWoken to true, then a context switch
+ * should be performed before the interrupt is exited. This will ensure that
+ * the interrupt returns directly to the highest priority Ready state task.
+ * The mechanism is identical to that used in the FreeRTOS::receiveFromISR()
+ * function, and readers are referred to the FreeRTOS::receiveFromISR()
+ * documentation for further explanation.
+ * @retval true If the semaphore was successfully taken.
+ * @retval false If the semaphore was not successfully taken because it was
+ * not available.
+ */
+ inline bool takeFromISR(bool& higherPriorityTaskWoken) const {
+ BaseType_t taskWoken = pdFALSE;
+ bool result = (xSemaphoreTakeFromISR(handle, &taskWoken) == pdTRUE);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Function that calls xSemaphoreTakeFromISR( SemaphoreHandle_t
+ * xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken)
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline bool takeFromISR() const {
+ return (xSemaphoreTakeFromISR(handle, NULL) == pdTRUE);
+ }
+
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Function that calls xSemaphoreGive( SemaphoreHandle_t xSemaphore
+ * )
+ *
+ * @see
+ *
+ * Function to release a semaphore.
+ *
+ * This must not be used from an ISR. See giveFromISR() for an alternative
+ * which can be used from an ISR.
+ *
+ * @retval true If the semaphore was released.
+ * @retval false If an error occurred. Semaphores are implemented using
+ * queues. An error can occur if there is no space on the queue to post a
+ * message indicating that the semaphore was not first obtained correctly.
+ *
+ * Example Usage
+ * @include Semaphore/give.cpp
+ */
+ inline bool give() const { return (xSemaphoreGive(handle) == pdTRUE); }
+
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Function that calls xSemaphoreGiveFromISR( SemaphoreHandle_t
+ * xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * Function to release a semaphore.
+ *
+ * This macro can be used from an ISR.
+ *
+ * @param higherPriorityTaskWoken giveFromISR() will set
+ * higherPriorityTaskWoken to true if giving the semaphore caused a task to
+ * unblock, and the unblocked task has a priority higher than the currently
+ * running task. If giveFromISR() sets this value to true then a context
+ * switch should be requested before the interrupt is exited.
+ * @retval true If the semaphore was successfully given.
+ * @retval false Otherwise.
+ *
+ * Example Usage
+ * @include Semaphore/giveFromISR.cpp
+ */
+ inline bool giveFromISR(bool& higherPriorityTaskWoken) const {
+ BaseType_t taskWoken = pdFALSE;
+ bool result = (xSemaphoreGiveFromISR(handle, &taskWoken) == pdTRUE);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Function that calls xSemaphoreGiveFromISR( SemaphoreHandle_t
+ * xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline bool giveFromISR() const {
+ return (xSemaphoreGiveFromISR(handle, NULL) == pdTRUE);
+ }
+
+ private:
+ SemaphoreBase() = default;
+
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Destroy the SemaphoreBase object by calling void
+ * vSemaphoreDelete( SemaphoreHandle_t xSemaphore )
+ *
+ * @see
+ *
+ * @note Do not delete a semaphore that has tasks blocked on it (tasks that
+ * are in the Blocked state waiting for the semaphore to become available).
+ */
+ ~SemaphoreBase() { vSemaphoreDelete(this->handle); }
+
+ SemaphoreBase(SemaphoreBase&&) noexcept = default;
+ SemaphoreBase& operator=(SemaphoreBase&&) noexcept = default;
+
+ /**
+ * @brief Handle used to refer to the semaphore when using the FreeRTOS
+ * interface.
+ */
+ SemaphoreHandle_t handle = NULL;
+};
+
+#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+
+/**
+ * @class BinarySemaphore Semaphore.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS binary
+ * semaphore.
+ *
+ * Each binary semaphore require a small amount of RAM that is used to hold the
+ * semaphore's state. If a binary semaphore is created using
+ * FreeRTOS::BinarySemaphore then the required RAM is automatically allocated
+ * from the FreeRTOS heap. If a binary semaphore is created using
+ * FreeRTOS::StaticBinarySemaphore then the RAM is provided by the application
+ * writer as part of the class and allows the RAM to be statically allocated at
+ * compile time. See the Static Vs Dynamic allocation page for more information.
+ *
+ * The semaphore is created in the 'empty' state, meaning the semaphore must
+ * first be given using the give() API function before it can subsequently be
+ * taken (obtained) using the take() function.
+ *
+ * Binary semaphores and mutexes are very similar but have some subtle
+ * differences: Mutexes include a priority inheritance mechanism, binary
+ * semaphores do not. This makes binary semaphores the better choice for
+ * implementing synchronisation (between tasks or between tasks and an
+ * interrupt), and mutexes the better choice for implementing simple mutual
+ * exclusion.
+ *
+ * A binary semaphore need not be given back once obtained, so task
+ * synchronisation can be implemented by one task/interrupt continuously
+ * 'giving' the semaphore while another continuously 'takes' the semaphore. This
+ * is demonstrated by the sample code on the giveFromISR() documentation page.
+ * Note the same functionality can often be achieved in a more efficient way
+ * using a direct to task notification.
+ *
+ * The priority of a task that 'takes' a mutex can potentially be raised if
+ * another task of higher priority attempts to obtain the same mutex. The task
+ * that owns the mutex 'inherits' the priority of the task attempting to 'take'
+ * the same mutex. This means the mutex must always be 'given' back - otherwise
+ * the higher priority task will never be able to obtain the mutex, and the
+ * lower priority task will never 'disinherit' the priority. An example of a
+ * mutex being used to implement mutual exclusion is provided on the take()
+ * documentation page.
+ */
+class BinarySemaphore : public SemaphoreBase {
+ public:
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Construct a new BinarySemaphore object by calling
+ * SemaphoreHandle_t xSemaphoreCreateBinary( void )
+ *
+ * @see
+ *
+ * @warning The user should call isValid() on this object to verify that the
+ * binary semaphore was created successfully in case the memory required to
+ * create the queue could not be allocated.
+ *
+ * Example Usage
+ * @include Semaphore/binarySemaphore.cpp
+ */
+ BinarySemaphore() { this->handle = xSemaphoreCreateBinary(); }
+ ~BinarySemaphore() = default;
+
+ BinarySemaphore(const BinarySemaphore&) = delete;
+ BinarySemaphore& operator=(const BinarySemaphore&) = delete;
+
+ BinarySemaphore(BinarySemaphore&&) noexcept = default;
+ BinarySemaphore& operator=(BinarySemaphore&&) noexcept = default;
+};
+
+/**
+ * @class CountingSemaphore Semaphore.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS counting
+ * semaphore.
+ *
+ * Each counting semaphore require a small amount of RAM that is used to hold
+ * the semaphore's state. If a counting semaphore is created using
+ * FreeRTOS::CountingSemaphore then the required RAM is automatically allocated
+ * from the FreeRTOS heap. If a counting semaphore is created using
+ * FreeRTOS::StaticCountingSemaphore then the RAM is provided by the application
+ * writer as part of the class and allows the RAM to be statically allocated at
+ * compile time. See the Static Vs Dynamic allocation page for more information.
+ *
+ * Counting semaphores are typically used for two things:
+ * 1. Counting Events:
+ * In this usage scenario an event handler will 'give' a semaphore each time an
+ * event occurs (incrementing the semaphore count value), and a handler task
+ * will 'take' a semaphore each time it processes an event (decrementing the
+ * semaphore count value). The count value is therefore the difference between
+ * the number of events that have occurred and the number that have been
+ * processed. In this case it is desirable for the initial count value to be
+ * zero. Note the same functionality can often be achieved in a more efficient
+ * way using a direct to task notification.
+ *
+ * 2. Resource Management:
+ * In this usage scenario the count value indicates the number of resources
+ * available. To obtain control of a resource a task must first obtain a
+ * semaphore - decrementing the semaphore count value. When the count value
+ * reaches zero there are no free resources. When a task finishes with the
+ * resource it 'gives' the semaphore back - incrementing the semaphore count
+ * value. In this case it is desirable for the initial count value to be equal
+ * to the maximum count value, indicating that all resources are free.
+ */
+class CountingSemaphore : public SemaphoreBase {
+ public:
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Construct a new CountingSemaphore by calling
+ * SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount,
+ * UBaseType_t uxInitialCount)
+ *
+ * @warning The user should call isValid() on this object to verify that the
+ * binary semaphore was created successfully in case the memory required to
+ * create the queue could not be allocated.
+ *
+ * @param maxCount The maximum count value that can be reached. When the
+ * semaphore reaches this value it can no longer be 'given'.
+ * @param initialCount The count value assigned to the semaphore when
+ * it is created.
+ */
+ explicit CountingSemaphore(const UBaseType_t maxCount,
+ const UBaseType_t initialCount = 0) {
+ this->handle = xSemaphoreCreateCounting(maxCount, initialCount);
+ }
+ ~CountingSemaphore() = default;
+
+ CountingSemaphore(const CountingSemaphore&) = delete;
+ CountingSemaphore& operator=(const CountingSemaphore&) = delete;
+
+ CountingSemaphore(CountingSemaphore&&) noexcept = default;
+ CountingSemaphore& operator=(CountingSemaphore&&) noexcept = default;
+};
+
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+#if (configSUPPORT_STATIC_ALLOCATION == 1)
+
+/**
+ * @class StaticBinarySemaphore Semaphore.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS binary
+ * semaphore.
+ *
+ * Each binary semaphore require a small amount of RAM that is used to hold the
+ * semaphore's state. If a binary semaphore is created using
+ * FreeRTOS::BinarySemaphore then the required RAM is automatically allocated
+ * from the FreeRTOS heap. If a binary semaphore is created using
+ * FreeRTOS::StaticBinarySemaphore then the RAM is provided by the application
+ * writer as part of the class and allows the RAM to be statically allocated at
+ * compile time. See the Static Vs Dynamic allocation page for more information.
+ *
+ * The semaphore is created in the 'empty' state, meaning the semaphore must
+ * first be given using the give() API function before it can subsequently be
+ * taken (obtained) using the take() function.
+ *
+ * Binary semaphores and mutexes are very similar but have some subtle
+ * differences: Mutexes include a priority inheritance mechanism, binary
+ * semaphores do not. This makes binary semaphores the better choice for
+ * implementing synchronisation (between tasks or between tasks and an
+ * interrupt), and mutexes the better choice for implementing simple mutual
+ * exclusion.
+ *
+ * A binary semaphore need not be given back once obtained, so task
+ * synchronisation can be implemented by one task/interrupt continuously
+ * 'giving' the semaphore while another continuously 'takes' the semaphore. This
+ * is demonstrated by the sample code on the giveFromISR() documentation page.
+ * Note the same functionality can often be achieved in a more efficient way
+ * using a direct to task notification.
+ *
+ * The priority of a task that 'takes' a mutex can potentially be raised if
+ * another task of higher priority attempts to obtain the same mutex. The task
+ * that owns the mutex 'inherits' the priority of the task attempting to 'take'
+ * the same mutex. This means the mutex must always be 'given' back - otherwise
+ * the higher priority task will never be able to obtain the mutex, and the
+ * lower priority task will never 'disinherit' the priority. An example of a
+ * mutex being used to implement mutual exclusion is provided on the take()
+ * documentation page.
+ */
+class StaticBinarySemaphore : public SemaphoreBase {
+ public:
+ /**
+ * Semaphore.hpp
+ *
+ * @brief Construct a new StaticBinarySemaphore object by calling
+ * SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t
+ * *pxSemaphoreBuffer )
+ *
+ * @see
+ *
+ * @warning This class contains the storage buffer for the binary semaphore,
+ * so the user should create this object as a global object or with the static
+ * storage specifier so that the object instance is not on the stack.
+ *
+ * Example Usage
+ * @include Semaphore/staticBinarySemaphore.cpp
+ */
+ StaticBinarySemaphore() {
+ this->handle = xSemaphoreCreateBinaryStatic(&staticBinarySemaphore);
+ }
+ ~StaticBinarySemaphore() = default;
+
+ StaticBinarySemaphore(const StaticBinarySemaphore&) = delete;
+ StaticBinarySemaphore& operator=(const StaticBinarySemaphore&) = delete;
+
+ StaticBinarySemaphore(StaticBinarySemaphore&&) noexcept = default;
+ StaticBinarySemaphore& operator=(StaticBinarySemaphore&&) noexcept = default;
+
+ private:
+ StaticSemaphore_t staticBinarySemaphore;
+};
+
+class StaticCountingSemaphore : public SemaphoreBase {
+ public:
+ /**
+ * @brief Construct a new StaticCountingSemaphore object by calling
+ * SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t
+ * uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t
+ * *pxSemaphoreBuffer )
+ *
+ * @see
+ *
+ * @warning This class contains the storage buffer for the counting semaphore,
+ * so the user should create this object as a global object or with the static
+ * storage specifier so that the object instance is not on the stack.
+ *
+ * @param maxCount The maximum count value that can be reached. When the
+ * semaphore reaches this value it can no longer be 'given'.
+ * @param initialCount The count value assigned to the semaphore when it is
+ * created.
+ *
+ * Example Usage
+ * @include Semaphore/staticCountingSemaphore.cpp
+ */
+ explicit StaticCountingSemaphore(const UBaseType_t maxCount,
+ const UBaseType_t initialCount = 0) {
+ this->handle = xSemaphoreCreateCountingStatic(maxCount, initialCount,
+ &staticCountingSemaphore);
+ }
+ ~StaticCountingSemaphore() = default;
+
+ StaticCountingSemaphore(const StaticCountingSemaphore&) = delete;
+ StaticCountingSemaphore& operator=(const StaticCountingSemaphore&) = delete;
+
+ StaticCountingSemaphore(StaticCountingSemaphore&&) noexcept = default;
+ StaticCountingSemaphore& operator=(StaticCountingSemaphore&&) noexcept =
+ default;
+
+ private:
+ StaticSemaphore_t staticCountingSemaphore;
+};
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+} // namespace FreeRTOS
+
+#endif // FREERTOS_SEMAPHORE_HPP
\ No newline at end of file
diff --git a/source/test/src/FreeRTOSCPP/StreamBuffer.hpp b/source/test/src/FreeRTOSCPP/StreamBuffer.hpp
new file mode 100644
index 0000000..c87a734
--- /dev/null
+++ b/source/test/src/FreeRTOSCPP/StreamBuffer.hpp
@@ -0,0 +1,566 @@
+/*
+ * FreeRTOS-Cpp
+ * Copyright (C) 2021 Jon Enz. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://github.com/jonenz/FreeRTOS-Cpp
+ */
+
+#ifndef FREERTOS_STREAMBUFFER_HPP
+#define FREERTOS_STREAMBUFFER_HPP
+
+#include "FreeRTOS.h"
+#include "stream_buffer.h"
+
+namespace FreeRTOS {
+
+/**
+ * @class StreamBufferBase StreamBuffer.hpp
+ *
+ * @brief Base class that provides the standard stream buffer interface to
+ * FreeRTOS::StreamBuffer and FreeRTOS::StaticStreamBuffer.
+ *
+ * @note This class is not intended to be instantiated by the user. Use
+ * FreeRTOS::StreamBuffer or FreeRTOS::StaticStreamBuffer.
+ *
+ * @warning Uniquely among FreeRTOS objects, the stream buffer implementation
+ * (so also the message buffer implementation, as message buffers are built on
+ * top of stream buffers) assumes there is only one task or interrupt that will
+ * write to the buffer (the writer), and only one task or interrupt that will
+ * read from the buffer (the reader). It is safe for the writer and reader to
+ * be different tasks or interrupts, but, unlike other FreeRTOS objects, it is
+ * not safe to have multiple different writers or multiple different readers. If
+ * there are to be multiple different writers then the application writer must
+ * place each call to a writing API function (such as send()) inside a critical
+ * section and set the send block time to 0. Likewise, if there are to be
+ * multiple different readers then the application writer must place each call
+ * to a reading API function (such as read()) inside a critical section and set
+ * the receive block time to 0.
+ */
+class StreamBufferBase {
+ public:
+ friend class StreamBuffer;
+ template
+ friend class StaticStreamBuffer;
+
+ StreamBufferBase(const StreamBufferBase&) = delete;
+ StreamBufferBase& operator=(const StreamBufferBase&) = delete;
+
+ static void* operator new(size_t, void* ptr) { return ptr; }
+ static void* operator new[](size_t, void* ptr) { return ptr; }
+ static void* operator new(size_t) = delete;
+ static void* operator new[](size_t) = delete;
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that checks if the underlying stream buffer handle is not
+ * NULL. This should be used to ensure a stream buffer has been created
+ * correctly.
+ *
+ * @retval true If the handle is not NULL.
+ * @retval false If the handle is NULL.
+ */
+ inline bool isValid() const { return (handle != NULL); }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls size_t xStreamBufferSend(
+ * StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t
+ * xDataLengthBytes, TickType_t xTicksToWait )
+ *
+ * @see
+ *
+ * Sends bytes to a stream buffer. The bytes are copied into the stream
+ * buffer.
+ *
+ * Use send() to write to a stream buffer from a task. Use sendFromISR() to
+ * write to a stream buffer from an interrupt service routine (ISR).
+ *
+ * @param data A pointer to the buffer that holds the bytes to be copied into
+ * the stream buffer.
+ * @param length The maximum number of bytes to copy from data into the stream
+ * buffer.
+ * @param ticksToWait The maximum amount of time the task should remain in the
+ * Blocked state to wait for enough space to become available in the stream
+ * buffer, should the stream buffer contain too little space to hold the
+ * another length bytes. The block time is specified in tick periods, so the
+ * absolute time it represents is dependent on the tick frequency. The macro
+ * pdMS_TO_TICKS() can be used to convert a time specified in milliseconds
+ * into a time specified in ticks. Setting ticksToWait to portMAX_DELAY will
+ * cause the task to wait indefinitely (without timing out), provided
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. If a task times out
+ * before it can write all length into the buffer it will still write as many
+ * bytes as possible. A task does not use any CPU time when it is in the
+ * blocked state.
+ * @return size_t The number of bytes written to the stream buffer. If a task
+ * times out before it can write all length into the buffer it will still
+ * write as many bytes as possible.
+ *
+ * Example Usage
+ * @include StreamBuffer/send.cpp
+ */
+ inline size_t send(const void* data, const size_t length,
+ const TickType_t ticksToWait = portMAX_DELAY) const {
+ return xStreamBufferSend(handle, data, length, ticksToWait);
+ }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls size_t xStreamBufferSendFromISR(
+ * StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t
+ * xDataLengthBytes, BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * Interrupt safe version of the API function that sends a stream of bytes to
+ * the stream buffer.
+ *
+ * Use send() to write to a stream buffer from a task. Use sendFromISR() to
+ * write to a stream buffer from an interrupt service routine (ISR).
+ *
+ * @param higherPriorityTaskWoken It is possible that a stream buffer will
+ * have a task blocked on it waiting for data. Calling sendFromISR() can make
+ * data available, and so cause a task that was waiting for data to leave the
+ * Blocked state. If calling sendFromISR() causes a task to leave the Blocked
+ * state, and the unblocked task has a priority higher than the currently
+ * executing task (the task that was interrupted), then, internally,
+ * sendFromISR() will set higherPriorityTaskWoken to true. If sendFromISR()
+ * sets this value to true, then normally a context switch should be performed
+ * before the interrupt is exited. This will ensure that the interrupt
+ * returns directly to the highest priority Ready state task.
+ * higherPriorityTaskWoken should be set to false before it is passed into the
+ * function. See the example code below for an example.
+ * @param data A pointer to the buffer that holds the bytes to be copied into
+ * the stream buffer.
+ * @param length The maximum number of bytes to copy from data into the stream
+ * buffer.
+ * @return size_t The number of bytes written to the stream buffer. If a task
+ * times out before it can write all length into the buffer it will still
+ * write as many bytes as possible.
+ *
+ * Example Usage
+ * @include StreamBuffer/sendFromISR.cpp
+ */
+ inline size_t sendFromISR(bool& higherPriorityTaskWoken, const void* data,
+ const size_t length) const {
+ BaseType_t taskWoken = pdFALSE;
+ size_t result = xStreamBufferSendFromISR(handle, data, length, &taskWoken);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls size_t xStreamBufferSendFromISR(
+ * StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t
+ * xDataLengthBytes, BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline size_t sendFromISR(const void* data, const size_t length) const {
+ return xStreamBufferSendFromISR(handle, data, length, NULL);
+ }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls size_t xStreamBufferReceive(
+ * StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t
+ * xBufferLengthBytes, TickType_t xTicksToWait )
+ *
+ * @see
+ *
+ * Receives bytes from a stream buffer.
+ *
+ * Use receive() to read from a stream buffer from a task. Use
+ * receiveFromISR() to read from a stream buffer from an interrupt service
+ * routine (ISR).
+ *
+ * @param buffer A pointer to the buffer into which the received bytes will be
+ * copied.
+ * @param bufferLength The length of the buffer pointed to by the data
+ * parameter. This sets the maximum number of bytes to receive in one call.
+ * receive() will return as many bytes as possible up to a maximum set by
+ * length.
+ * @param ticksToWait The maximum amount of time the task should remain in the
+ * Blocked state to wait for data to become available if the stream buffer is
+ * empty. receive() will return immediately if ticksToWait is zero. The block
+ * time is specified in tick periods, so the absolute time it represents is
+ * dependent on the tick frequency. The macro pdMS_TO_TICKS() can be used to
+ * convert a time specified in milliseconds into a time specified in ticks.
+ * Setting ticksToWait to portMAX_DELAY will cause the task to wait
+ * indefinitely (without timing out), provided INCLUDE_vTaskSuspend is set to
+ * 1 in FreeRTOSConfig.h. A task does not use any CPU time when it is in the
+ * Blocked state.
+ * @return size_t The number of bytes read from the stream buffer. This will
+ * be the number of bytes available up to a maximum of length.
+ *
+ * Example Usage
+ * @include StreamBuffer/receive.cpp
+ */
+ inline size_t receive(void* buffer, const size_t bufferLength,
+ const TickType_t ticksToWait = portMAX_DELAY) const {
+ return xStreamBufferReceive(handle, buffer, bufferLength, ticksToWait);
+ }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls size_t xStreamBufferReceiveFromISR(
+ * StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t
+ * xBufferLengthBytes, BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * An interrupt safe version of the API function that receives bytes from a
+ * stream buffer.
+ *
+ * Use receive() to read from a stream buffer from a task. Use
+ * receiveFromISR() to read from a stream buffer from an interrupt service
+ * routine (ISR).
+ *
+ * @param higherPriorityTaskWoken It is possible that a stream buffer will
+ * have a task blocked on it waiting for space to become available. Calling
+ * receiveFromISR() can make space available, and so cause a task that is
+ * waiting for space to leave the Blocked state. If calling receiveFromISR()
+ * causes a task to leave the Blocked state, and the unblocked task has a
+ * priority higher than the currently executing task (the task that was
+ * interrupted), then, internally, receiveFromISR() will set
+ * higherPriorityTaskWoken to true. If receiveFromISR() sets this value to
+ * true, then normally a context switch should be performed before the
+ * interrupt is exited. That will ensure the interrupt returns directly to the
+ * highest priority Ready state task. higherPriorityTaskWoken should be set to
+ * false before it is passed into the function. See the code example below for
+ * an example.
+ * @param buffer A pointer to the buffer into which the received bytes will be
+ * copied.
+ * @param bufferLength The length of the buffer pointed to by the buffer
+ * parameter. This sets the maximum number of bytes to receive in one call.
+ * receive() will return as many bytes as possible up to a maximum set by
+ * length.
+ * @return size_t The number of bytes read from the stream buffer, if any.
+ *
+ * Example Usage
+ * @include StreamBuffer/receiveFromISR.cpp
+ */
+ inline size_t receiveFromISR(bool& higherPriorityTaskWoken, void* buffer,
+ const size_t bufferLength) const {
+ BaseType_t taskWoken = pdFALSE;
+ size_t result =
+ xStreamBufferReceiveFromISR(handle, buffer, bufferLength, &taskWoken);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls size_t xStreamBufferReceiveFromISR(
+ * StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t
+ * xBufferLengthBytes, BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline size_t receiveFromISR(void* buffer, const size_t bufferLength) const {
+ return xStreamBufferReceiveFromISR(handle, buffer, bufferLength, NULL);
+ }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls size_t xStreamBufferBytesAvailable(
+ * StreamBufferHandle_t xStreamBuffer )
+ *
+ * @see
+ *
+ * Queries the stream buffer to see how much data it contains, which is equal
+ * to the number of bytes that can be read from the stream buffer before the
+ * stream buffer would be empty.
+ *
+ * @return size_t The number of bytes that can be read from the stream buffer
+ * before the stream buffer would be empty.
+ */
+ inline size_t bytesAvailable() const {
+ return xStreamBufferBytesAvailable(handle);
+ }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls size_t xStreamBufferSpacesAvailable(
+ * StreamBufferHandle_t xStreamBuffer )
+ *
+ * @see
+ *
+ * Queries a stream buffer to see how much free space it contains, which is
+ * equal to the amount of data that can be sent to the stream buffer before it
+ * is full.
+ *
+ * @return size_t The number of bytes that can be written to the stream buffer
+ * before the stream buffer would be full.
+ */
+ inline size_t spacesAvailable() const {
+ return xStreamBufferSpacesAvailable(handle);
+ }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls BaseType_t xStreamBufferSetTriggerLevel(
+ * StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel )
+ *
+ * @see
+ *
+ * A stream buffer's trigger level is the number of bytes that must be in the
+ * stream buffer before a task that is blocked on the stream buffer to wait
+ * for data is moved out of the blocked state. For example, if a task is
+ * blocked on a read of an empty stream buffer that has a trigger level of 1
+ * then the task will be unblocked when a single byte is written to the buffer
+ * or the task's block time expires. As another example, if a task is blocked
+ * on a read of an empty stream buffer that has a trigger level of 10 then the
+ * task will not be unblocked until the stream buffer contains at least 10
+ * bytes or the task's block time expires. If a reading task's block time
+ * expires before the trigger level is reached then the task will still
+ * receive however many bytes are actually available. Setting a trigger level
+ * of 0 will result in a trigger level of 1 being used. It is not valid to
+ * specify a trigger level that is greater than the buffer size.
+ *
+ * @param triggerLevel The new trigger level for the stream buffer.
+ * @retval true If triggerLevel was less than or equal to the stream buffer's
+ * length then the trigger level was updated.
+ * @retval false Otherwise.
+ */
+ inline bool setTriggerLevel(const size_t triggerLevel = 0) const {
+ return (xStreamBufferSetTriggerLevel(handle, triggerLevel) == pdTRUE);
+ }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls BaseType_t xStreamBufferReset(
+ * StreamBufferHandle_t xStreamBuffer )
+ *
+ * @see
+ *
+ * Resets a stream buffer to its initial, empty, state. Any data that was in
+ * the stream buffer is discarded. A stream buffer can only be reset if there
+ * are no tasks blocked waiting to either send to or receive from the stream
+ * buffer.
+ *
+ * @return true If the stream buffer is reset.
+ * @return false If there was a task blocked waiting to send to or read from
+ * the stream buffer then the stream buffer was not reset.
+ */
+ inline bool reset() const { return (xStreamBufferReset(handle) == pdPASS); }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls BaseType_t xStreamBufferIsEmpty(
+ * StreamBufferHandle_t xStreamBuffer )
+ *
+ * @see
+ *
+ * Queries a stream buffer to see if it is empty. A stream buffer is empty if
+ * it does not contain any data.
+ *
+ * @return true If the stream buffer is empty.
+ * @return false Otherwise.
+ */
+ inline bool isEmpty() const {
+ return (xStreamBufferIsEmpty(handle) == pdTRUE);
+ }
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Function that calls BaseType_t xStreamBufferIsFull(
+ * StreamBufferHandle_t xStreamBuffer )
+ *
+ * @see
+ *
+ * Queries a stream buffer to see if it is full. A stream buffer is full if it
+ * does not have any free space, and therefore cannot accept any more data.
+ *
+ * @return true If the stream buffer is full.
+ * @return false Otherwise.
+ */
+ inline bool isFull() const { return (xStreamBufferIsFull(handle) == pdTRUE); }
+
+ private:
+ StreamBufferBase() = default;
+
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Destroy the StreamBufferBase object by calling
+ * void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer )
+ *
+ * @see
+ *
+ * Deletes a stream buffer and free the allocated memory.
+ */
+ ~StreamBufferBase() { vStreamBufferDelete(this->handle); }
+
+ StreamBufferBase(StreamBufferBase&&) noexcept = default;
+ StreamBufferBase& operator=(StreamBufferBase&&) noexcept = default;
+
+ StreamBufferHandle_t handle = NULL;
+};
+
+#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
+
+/**
+ * @class StreamBuffer StreamBuffer.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS stream buffer.
+ *
+ * A stream buffer using dynamically allocated memory from the FreeRTOS heap.
+ * See FreeRTOS::StaticStreamBuffer for a version that uses statically allocated
+ * memory (memory that is allocated at compile time).
+ */
+class StreamBuffer : public StreamBufferBase {
+ public:
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Construct a new StreamBuffer object by calling
+ * StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes,
+ * size_t xTriggerLevelBytes )
+ *
+ * @see
+ *
+ * @warning The user should call isValid() on this object to verify that the
+ * stream buffer was created successfully in case the memory required to
+ * create the message buffer could not be allocated.
+ *
+ * @param size The total number of bytes the stream buffer will be able to
+ * hold at any one time.
+ * @param triggerLevel The number of bytes that must be in the stream
+ * buffer before a task that is blocked on the stream buffer to wait for data
+ * is moved out of the blocked state. For example, if a task is blocked on a
+ * read of an empty stream buffer that has a trigger level of 1 then the task
+ * will be unblocked when a single byte is written to the buffer or the task's
+ * block time expires. As another example, if a task is blocked on a read of
+ * an empty stream buffer that has a trigger level of 10 then the task will
+ * not be unblocked until the stream buffer contains at least 10 bytes or the
+ * task's block time expires. If a reading task's block time expires before
+ * the trigger level is reached then the task will still receive however many
+ * bytes are actually available. Setting a trigger level of 0 will result in a
+ * trigger level of 1 being used. It is not valid to specify a trigger level
+ * that is greater than the buffer size.
+ *
+ * Example Usage
+ * @include StreamBuffer/streamBuffer.cpp
+ */
+ explicit StreamBuffer(const size_t size, const size_t triggerLevel = 0) {
+ this->handle = xStreamBufferCreate(size, triggerLevel);
+ }
+ ~StreamBuffer() = default;
+
+ StreamBuffer(const StreamBuffer&) = delete;
+ StreamBuffer& operator=(const StreamBuffer&) = delete;
+
+ StreamBuffer(StreamBuffer&&) noexcept = default;
+ StreamBuffer& operator=(StreamBuffer&&) noexcept = default;
+};
+
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+#if (configSUPPORT_STATIC_ALLOCATION == 1)
+
+/**
+ * @class StaticStreamBuffer StreamBuffer.hpp
+ *
+ * @brief Class that encapsulates the functionality of a FreeRTOS stream buffer.
+ *
+ * If a stream buffer is created using this class then the RAM is provided by
+ * the application writer as part of the object instance and allows the RAM to
+ * be statically allocated at compile time.
+ *
+ * @tparam N The size, in bytes, of the storage buffer for the stream buffer.
+ */
+template
+class StaticStreamBuffer : public StreamBufferBase {
+ public:
+ /**
+ * StreamBuffer.hpp
+ *
+ * @brief Construct a new StaticStreamBuffer object by calling
+ * StreamBufferHandle_t xStreamBufferCreateStatic( size_t
+ * xBufferSizeBytes, size_t xTriggerLevelBytes, uint8_t
+ * *pucStreamBufferStorageArea, StaticStreamBuffer_t *pxStaticStreamBuffer
+ * )
+ *
+ * @see
+ *
+ * @param triggerLevel The number of bytes that must be in the stream
+ * buffer before a task that is blocked on the stream buffer to wait for data
+ * is moved out of the blocked state. For example, if a task is blocked on a
+ * read of an empty stream buffer that has a trigger level of 1 then the task
+ * will be unblocked when a single byte is written to the buffer or the task's
+ * block time expires. As another example, if a task is blocked on a read of
+ * an empty stream buffer that has a trigger level of 10 then the task will
+ * not be unblocked until the stream buffer contains at least 10 bytes or the
+ * task's block time expires. If a reading task's block time expires before
+ * the trigger level is reached then the task will still receive however many
+ * bytes are actually available. Setting a trigger level of 0 will result in a
+ * trigger level of 1 being used. It is not valid to specify a trigger level
+ * that is greater than the buffer size.
+ *
+ * Example Usage
+ * @include StreamBuffer/staticStreamBuffer.cpp
+ */
+ explicit StaticStreamBuffer(const size_t triggerLevel = 0) {
+ this->handle = xStreamBufferCreateStatic(sizeof(storage), triggerLevel,
+ storage, &staticStreamBuffer);
+ }
+ ~StaticStreamBuffer() = default;
+
+ StaticStreamBuffer(const StaticStreamBuffer&) = delete;
+ StaticStreamBuffer& operator=(const StaticStreamBuffer&) = delete;
+
+ StaticStreamBuffer(StaticStreamBuffer&&) noexcept = default;
+ StaticStreamBuffer& operator=(StaticStreamBuffer&&) noexcept = default;
+
+ private:
+ StaticStreamBuffer_t staticStreamBuffer;
+ uint8_t storage[N];
+};
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+
+} // namespace FreeRTOS
+
+#endif // FREERTOS_STREAMBUFFER_HPP
\ No newline at end of file
diff --git a/source/test/src/FreeRTOSCPP/Task.hpp b/source/test/src/FreeRTOSCPP/Task.hpp
new file mode 100644
index 0000000..7da36ab
--- /dev/null
+++ b/source/test/src/FreeRTOSCPP/Task.hpp
@@ -0,0 +1,1480 @@
+/*
+ * FreeRTOS-Cpp
+ * Copyright (C) 2021 Jon Enz. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * 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.
+ *
+ * https://github.com/jonenz/FreeRTOS-Cpp
+ */
+
+#ifndef FREERTOS_TASK_HPP
+#define FREERTOS_TASK_HPP
+
+#include
+#include
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "../FreeRTOSCPP/Kernel.hpp"
+
+/**
+ * @brief C function that is used to interface this class with the FreeRTOS
+ * kernel.
+ *
+ * @note This function should not be called or referenced by the user.
+ *
+ * @param task Pointer to an instance of FreeRTOS::TaskBase.
+ */
+void callTaskFunction(void* task);
+
+namespace FreeRTOS {
+
+/**
+ * @class TaskBase Task.hpp
+ *
+ * @brief Base class that provides the standard task interface to FreeRTOS::Task
+ * and FreeRTOS::StaticTask.
+ *
+ * @note This class is not intended to be instantiated or derived from by the
+ * user. Use FreeRTOS::Task or FreeRTOS::StaticTask as a base class for a user
+ * implemented task.
+ */
+class TaskBase {
+ public:
+ friend class Task;
+ template
+ friend class StaticTask;
+
+ TaskBase(const TaskBase&) = delete;
+ TaskBase& operator=(const TaskBase&) = delete;
+
+ static void* operator new(size_t, void* ptr) { return ptr; }
+ static void* operator new[](size_t, void* ptr) { return ptr; }
+ static void* operator new(size_t) = delete;
+ static void* operator new[](size_t) = delete;
+
+ enum class State {
+ Running = eRunning,
+ Ready = eReady,
+ Blocked = eBlocked,
+ Suspended = eSuspended,
+ Deleted = eDeleted,
+ Invalid = eInvalid,
+ };
+
+ enum class NotifyAction {
+ NoAction = eNoAction,
+ SetBits = eSetBits,
+ Increment = eIncrement,
+ SetValueWithOverwrite = eSetValueWithOverwrite,
+ SetValueWithoutOverwrite = eSetValueWithoutOverwrite,
+ };
+
+ // NOLINTNEXTLINE
+ using NotificationBits = std::bitset<32>;
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that acts as the entry point of the task instance. This
+ * function initializes the previous wake time of the task and calls the user
+ * implemented taskFunction().
+ *
+ * @note This function is only public so that it can be accessed by the C
+ * interface function callTaskFunction() and should not be called or
+ * referenced by the user.
+ */
+ virtual inline void taskEntry() final {
+ previousWakeTime = FreeRTOS::Kernel::getTickCount();
+ taskFunction();
+ };
+
+#if (INCLUDE_uxTaskPriorityGet == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls UBaseType_t uxTaskPriorityGet( TaskHandle_t
+ * xTask )
+ *
+ * @see
+ *
+ * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be
+ * available. See the RTOS Configuration documentation for more information.
+ *
+ * Obtain the priority of any task.
+ *
+ * @return UBaseType_t The priority of the task.
+ *
+ * Example Usage
+ * @include Task/getPriority.cpp
+ */
+ inline UBaseType_t getPriority() const { return uxTaskPriorityGet(handle); }
+#endif /* INCLUDE_uxTaskPriorityGet */
+
+#if (INCLUDE_vTaskPrioritySet == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls void vTaskPrioritySet( TaskHandle_t xTask,
+ * UBaseType_t uxNewPriority )
+ *
+ * @see
+ *
+ * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be
+ * available. See the configuration section for more information.
+ *
+ * Set the priority of the task.
+ *
+ * A context switch will occur before the function returns if the priority
+ * being set is higher than the currently executing task.
+ *
+ * @param newPriority The priority to which the task will be set.
+ *
+ * Example Usage
+ * @include Task/setPriority.cpp
+ */
+ inline void setPriority(const UBaseType_t newPriority) const {
+ vTaskPrioritySet(handle, newPriority);
+ }
+#endif /* INCLUDE_vTaskPrioritySet */
+
+#if (INCLUDE_vTaskSuspend == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls void vTaskSuspend( TaskHandle_t
+ * xTaskToSuspend )
+ *
+ * @see
+ *
+ * INCLUDE_vTaskSuspend must be defined as 1 for this function to be
+ * available. See the RTOS Configuration documentation for more information.
+ *
+ * Suspend a task. When suspended a task will never get any microcontroller
+ * processing time, no matter what its priority.
+ *
+ * Calls to suspend() are not accumulative - i.e. calling suspend() twice on
+ * the same task still only requires one call to resume() to ready the
+ * suspended task.
+ *
+ * Example Usage
+ * @include Task/suspend.cpp
+ */
+ inline void suspend() const { vTaskSuspend(handle); }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls void vTaskResume( TaskHandle_t xTaskToResume
+ * )
+ *
+ * @see
+ *
+ * INCLUDE_vTaskSuspend must be defined as 1 for this function to be
+ * available. See the RTOS Configuration documentation for more information.
+ *
+ * Resumes a suspended task.
+ *
+ * A task that has been suspended by one or more calls to suspend() will be
+ * made available for running again by a single call to resume().
+ *
+ * Example Usage
+ * @include Task/resume.cpp
+ */
+ inline void resume() const { vTaskResume(handle); }
+
+#if (INCLUDE_xTaskResumeFromISR == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t xTaskResumeFromISR( TaskHandle_t
+ * xTaskToResume )
+ *
+ * @see
+ *
+ * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be
+ * available. See the configuration section for more information.
+ *
+ * An implementation of resume() that can be called from within an ISR.
+ *
+ * A task that has been suspended by one or more calls to suspend() will be
+ * made available for running again by a single call to resumeFromISR().
+ *
+ * resumeFromISR() should not be used to synchronize a task with an interrupt
+ * if there is a chance that the interrupt could arrive prior to the task
+ * being suspended - as this can lead to interrupts being missed. Use of a
+ * semaphore as a synchronisation mechanism would avoid this eventuality.
+ *
+ * @retval true If resuming the task should result in a context switch. This
+ * is used by the ISR to determine if a context switch may be required
+ * following the ISR.
+ * @retval false Otherwise.
+ *
+ * Example Usage
+ * @include Task/resumeFromISR.cpp
+ */
+ inline bool resumeFromISR() const {
+ return (xTaskResumeFromISR(handle) == pdTRUE);
+ }
+#endif /* INCLUDE_xTaskResumeFromISR */
+#endif /* INCLUDE_vTaskSuspend */
+
+#if (INCLUDE_xTaskAbortDelay == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t xTaskAbortDelay( TaskHandle_t
+ * xTask )
+ *
+ * @see
+ *
+ * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this
+ * function to be available.
+ *
+ * A task will enter the Blocked state when it is waiting for an event. The
+ * event it is waiting for can be a temporal event (waiting for a time), such
+ * as when delay() is called, or an event on an object, such as when
+ * FreeRTOS::Queue::receive() or notifyTake() is called. If the handle of a
+ * task that is in the Blocked state is used in a call to abortDelay() then
+ * the task will leave the Blocked state, and return from whichever function
+ * call placed the task into the Blocked state.
+ *
+ * There is no 'FromISR' version of this function as an interrupt would need
+ * to know which object a task was blocked on in order to know which actions
+ * to take. For example, if the task was blocked on a queue the interrupt
+ * handler would then need to know if the queue was locked.
+ *
+ * @retval true Otherwise.
+ * @retval false If the task was not in the Blocked state.
+ */
+ inline bool abortDelay() const { return (xTaskAbortDelay(handle) == pdPASS); }
+#endif /* INCLUDE_xTaskAbortDelay */
+
+#if (INCLUDE_xTaskGetIdleTaskHandle == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls TaskHandle_t xTaskGetIdleTaskHandle( void
+ * )
+ *
+ * @see
+ *
+ * getIdleTaskHandle() is only available if INCLUDE_xTaskGetIdleTaskHandle is
+ * set to 1 in FreeRTOSConfig.h.
+ *
+ * Simply returns the handle of the idle task. It is not valid to call
+ * getIdleTaskHandle() before the scheduler has been started.
+ *
+ * @return TaskHandle_t The task handle associated with the Idle task. The
+ * Idle task is created automatically when the RTOS scheduler is started.
+ */
+ inline static TaskHandle_t getIdleHandle() {
+ return xTaskGetIdleTaskHandle();
+ }
+#endif /* INCLUDE_xTaskGetIdleTaskHandle */
+
+#if (INCLUDE_uxTaskGetStackHighWaterMark == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls UBaseType_t uxTaskGetStackHighWaterMark(
+ * TaskHandle_t xTask )
+ *
+ * @see
+ *
+ * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h
+ * for this function to be available.
+ *
+ * Returns the high water mark of the stack. That is, the minimum free stack
+ * space there has been (in words, so on a 32 bit machine a value of 1 means 4
+ * bytes) since the task started. The smaller the returned number the closer
+ * the task has come to overflowing its stack.
+ *
+ * getStackHighWaterMark() and getStackHighWaterMark2() are the same except
+ * for their return type. Using configSTACK_DEPTH_TYPE allows the user to
+ * determine the return type. It gets around the problem of the value
+ * overflowing on 8-bit types without breaking backward compatibility for
+ * applications that expect an 8-bit return type.
+ *
+ * @return BaseType_t The smallest amount of free stack space there has been
+ * (in words, so actual spaces on the stack rather than bytes) since the task
+ * was created.
+ */
+ inline UBaseType_t getStackHighWaterMark() const {
+ return uxTaskGetStackHighWaterMark(handle);
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls UBaseType_t uxTaskGetStackHighWaterMark2(
+ * TaskHandle_t xTask )
+ *
+ * @see
+ *
+ * Returns the high water mark of the stack. That is, the minimum free stack
+ * space there has been (in words, so on a 32 bit machine a value of 1 means 4
+ * bytes) since the task started. The smaller the returned number the closer
+ * the task has come to overflowing its stack.
+ *
+ * getStackHighWaterMark() and getStackHighWaterMark2() are the same except
+ * for their return type. Using configSTACK_DEPTH_TYPE allows the user to
+ * determine the return type. It gets around the problem of the value
+ * overflowing on 8-bit types without breaking backward compatibility for
+ * applications that expect an 8-bit return type.
+ *
+ * @return configSTACK_DEPTH_TYPE The smallest amount of free stack space
+ * there has been (in words, so actual spaces on the stack rather than bytes)
+ * since the task was created.
+ */
+ inline configSTACK_DEPTH_TYPE getStackHighWaterMark2() const {
+ return uxTaskGetStackHighWaterMark2(handle);
+ }
+#endif /* INCLUDE_uxTaskGetStackHighWaterMark */
+
+#if (INCLUDE_eTaskGetState == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls UBaseType_t uxTaskGetStackHighWaterMark2(
+ * TaskHandle_t xTask )
+ *
+ * @see
+ *
+ * @see getInfo()
+ *
+ * INCLUDE_eTaskGetState must be defined as 1 for this function to be
+ * available. See the configuration section for more information.
+ *
+ * Obtain the state of any task. States are encoded by the
+ * FreeRTOS::Task::State enumerated class type.
+ *
+ * @return State The state of the task at the time the function was called.
+ * Note the state of the task might change between the function being called,
+ * and the functions return value being tested by the calling task.
+ */
+ inline State getState() const {
+ return static_cast(eTaskGetState(handle));
+ }
+#endif /* INCLUDE_eTaskGetState */
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls char *pcTaskGetName( TaskHandle_t
+ * xTaskToQuery )
+ *
+ * @see
+ *
+ * Looks up the name of a task.
+ *
+ * @return const char* The text (human readable) name of the task. A pointer
+ * to the subject task's name, which is a standard NULL terminated C string.
+ */
+ inline const char* getName() const { return pcTaskGetName(handle); }
+
+#if (INCLUDE_xTaskGetHandle == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls TaskHandle_t xTaskGetHandle( const char
+ * *pcNameToQuery )
+ *
+ * @see
+ *
+ * @note This function takes a relatively long time to complete and should be
+ * used sparingly.
+ *
+ * @param name The text name (as a standard C NULL terminated string) of the
+ * task for which the handle will be returned.
+ * @return TaskHandle_t The handle of the task that has the human readable
+ * name. NULL is returned if no matching name is found.
+ * INCLUDE_xTaskGetHandle must be set to 1 in FreeRTOSConfig.h for getHandle()
+ * to be available.
+ */
+ inline static TaskHandle_t getHandle(const char* name) {
+ return xTaskGetHandle(name);
+ }
+#endif /* INCLUDE_xTaskGetHandle */
+
+#if (configUSE_TASK_NOTIFICATIONS == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t xTaskNotifyGiveIndexed(
+ * TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify )
+ *
+ * @see
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Each task has a private array of "notification values" (or
+ * 'notifications'), each of which is a 32-bit unsigned integer (uint32_t).
+ * The constant configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of
+ * indexes in the array, and (for backward compatibility) defaults to 1 if
+ * left undefined. Prior to FreeRTOS V10.4.0 there was only one notification
+ * value per task.
+ *
+ * Events can be sent to a task using an intermediary object. Examples of
+ * such objects are queues, semaphores, mutexes and event groups. Task
+ * notifications are a method of sending an event directly to a task without
+ * the need for such an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values. In
+ * that way task notifications can be used to send data to a task, or be used
+ * as light weight and fast binary or counting semaphores.
+ *
+ * notifyGive() indicies is are intended for use when task notifications are
+ * used as light weight and faster binary or counting semaphore equivalents.
+ * Actual FreeRTOS semaphores are given using the FreeRTOS::Semaphore API, the
+ * equivalent action that instead uses a task notification is notifyGive().
+ *
+ * When task notifications are being used as a binary or counting semaphore
+ * equivalent then the task being notified should wait for the notification
+ * using the notificationTake() API function rather than the
+ * notifyWaitIndexed() API function.
+ *
+ * @note Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not
+ * be unblocked by a notification sent to any other array index.
+ *
+ * @param index The index within the target task's array of notification
+ * values to which the notification is to be sent. index must be less than
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ *
+ * Example Usage
+ * @include Task/notifyGive.cpp
+ */
+ inline void notifyGive(const UBaseType_t index = 0) const {
+ xTaskNotifyGiveIndexed(handle, index);
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls void vTaskNotifyGiveIndexedFromISR(
+ * TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t
+ * *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * Version of notifyGive() that can be used from an interrupt service routine
+ * (ISR). See the documentation page for the notifyGive() API function for a
+ * description of their operation and the necessary configuration parameters.
+ *
+ * @param higherPriorityTaskWoken A reference that will be set to true if
+ * sending the notification caused a task to unblock, and the unblocked task
+ * has a priority higher than the currently running task. If
+ * higherPriorityTaskWoken is set to true, then a context switch should be
+ * requested before the interrupt is exited.
+ * @param index The index within the target task's array of notification
+ * values to which the notification is to be sent. index must be less than
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ *
+ * Example Usage
+ * @include Task/notifyGiveFromISR.cpp
+ */
+ inline void notifyGiveFromISR(bool& higherPriorityTaskWoken,
+ const UBaseType_t index = 0) const {
+ BaseType_t taskWoken = pdFALSE;
+ vTaskNotifyGiveIndexedFromISR(handle, index, &taskWoken);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls void vTaskNotifyGiveIndexedFromISR(
+ * TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t
+ * *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline void notifyGiveFromISR(const UBaseType_t index = 0) const {
+ vTaskNotifyGiveIndexedFromISR(handle, index, NULL);
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t xTaskNotifyIndexed( TaskHandle_t
+ * xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction
+ * eAction )
+ *
+ * @see
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Each task has a private array of "notification values" (or
+ * 'notifications'), each of which is a 32-bit unsigned integer (uint32_t).
+ * The constant configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of
+ * indexes in the array, and (for backward compatibility) defaults to 1 if
+ * left undefined. Prior to FreeRTOS V10.4.0 there was only one notification
+ * value per task.
+ *
+ * Events can be sent to a task using an intermediary object. Examples of
+ * such objects are queues, semaphores, mutexes and event groups. Task
+ * notifications are a method of sending an event directly to a task without
+ * the need for such an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values. In
+ * that way task notifications can be used to send data to a task, or be used
+ * as light weight and fast binary or counting semaphores.
+ *
+ * A task can use notifyWait() or notifyTake() to [optionally] block to wait
+ * for a notification to be pending. The task does not consume any CPU time
+ * while it is in the Blocked state.
+ *
+ * A notification sent to a task will remain pending until it is cleared by
+ * the task calling notifyWait() or notifyTake(). If the task was already in
+ * the Blocked state to wait for a notification when the notification arrives
+ * then the task will automatically be removed from the Blocked state
+ * (unblocked) and the notification cleared.
+ *
+ * @note Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not
+ * be unblocked by a notification sent to any other array index.
+ *
+ * @param action Specifies how the notification updates the task's
+ * notification value, if at all. Valid values for action are as follows:
+ *
NotifyAction Setting
Action Performed
+ *
NoAction
The target task receives the event,
+ * but its notification value is not updated. In this case value is not used.
+ *
SetBits
The notification value of the target
+ * task will be bitwise ORed with value. For example, if value is set to 0x01,
+ * then bit 0 will get set within the target task's notification value.
+ * Likewise if value is 0x04 then bit 2 will get set in the target task's
+ * notification value. In this way the RTOS task notification mechanism can be
+ * used as a light weight alternative to an event group.
Increment
+ *
The notification value of the target task will be incremented by one,
+ * making the call to notify() equivalent to a call to notifyGive(). In this
+ * case value is not used.
SetValueWithOverwrite
The
+ * notification value of the target task is unconditionally set to value. In
+ * this way the RTOS task notification mechanism is being used as a light
+ * weight alternative to FreeRTOS::Queue::Overwrite().
+ *
SetValueWithoutOverwrite
If the target task does not already
+ * have a notification pending then its notification value will be set to
+ * value. If the target task already has a notification pending then its
+ * notification value is not updated as to do so would overwrite the previous
+ * value before it was used. In this case the call to notify() fails and false
+ * is returned. In this way the RTOS task notification mechanism is being
+ * used as a light weight alternative to FreeRTOS::Queue::send() on a queue of
+ * length 1.
+ * @param value Data that can be sent with the notification. How the data is
+ * used depends on the value of the action parameter.
+ * @param index The index within the target task's array of notification
+ * values to which the notification is to be sent. index must be less than
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ *
+ * @return false If action is set to SetValueWithoutOverwrite and the task's
+ * notification value cannot be updated because the target task already had a
+ * notification pending.
+ * @return true Otherwise.
+ *
+ * Example Usage
+ * @include Task/notify.cpp
+ */
+ inline bool notify(const NotifyAction action,
+ const NotificationBits value = 0,
+ const UBaseType_t index = 0) const {
+ return (xTaskNotifyIndexed(handle, index, value.to_ulong(),
+ static_cast(action)) == pdPASS);
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t xTaskNotifyAndQueryIndexed(
+ * TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue,
+ * eNotifyAction eAction, uint32_t *pulPreviousNotifyValue )
+ *
+ * @see
+ *
+ * notifyAndQuery() performs the same operation as notify() with the addition
+ * that it also returns the target task's prior notification value (the
+ * notification value at the time the function is called rather than when the
+ * function returns).
+ *
+ * @param action An enumerated type that can take one of the values documented
+ * in the table below in order to perform the associated action.
+ *
NotifyAction Setting
Action Performed
+ *
NoAction
The target task receives the event,
+ * but its notification value is not updated. In this case value is not used.
+ *
SetBits
The notification value of the target
+ * task will be bitwise ORed with value. For example, if value is set to 0x01,
+ * then bit 0 will get set within the target task's notification value.
+ * Likewise if value is 0x04 then bit 2 will get set in the target task's
+ * notification value. In this way the RTOS task notification mechanism can be
+ * used as a light weight alternative to an event group.
Increment
+ *
The notification value of the target task will be incremented by one,
+ * making the call to notify() equivalent to a call to notifyGive(). In this
+ * case value is not used.
SetValueWithOverwrite
The
+ * notification value of the target task is unconditionally set to value. In
+ * this way the RTOS task notification mechanism is being used as a light
+ * weight alternative to FreeRTOS::Queue::Overwrite().
+ *
SetValueWithoutOverwrite
If the target task does not already
+ * have a notification pending then its notification value will be set to
+ * value. If the target task already has a notification pending then its
+ * notification value is not updated as to do so would overwrite the previous
+ * value before it was used. In this case the call to notify() fails and false
+ * is returned. In this way the RTOS task notification mechanism is being
+ * used as a light weight alternative to FreeRTOS::Queue::send() on a queue of
+ * length 1.
+ * @param value Used to update the notification value of the task. See the
+ * description of the action parameter below.
+ * @param index The index within the target task's array of notification
+ * values to which the notification is to be sent. index must be less than
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ *
+ * @return false If action is set to SetValueWithoutOverwrite and the task's
+ * notification value cannot be updated because the target task already had a
+ * notification pending.
+ * @return true Otherwise.
+ *
+ * Example Usage
+ * @include Task/notifyAndQuery.cpp
+ */
+ inline std::pair notifyAndQuery(
+ const NotifyAction action, const NotificationBits value = 0,
+ const UBaseType_t index = 0) const {
+ uint32_t pulNotificationValue;
+ bool result =
+ (xTaskNotifyAndQueryIndexed(handle, index, value.to_ulong(),
+ static_cast(action),
+ &pulNotificationValue) == pdPASS);
+
+ return std::make_pair(result, NotificationBits(pulNotificationValue));
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t
+ xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify,
+ * UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction,
+ uint32_t *pulPreviousNotifyValue,
+ * BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * notifyAndQueryFromISR() performs the same operation as notifyFromISR() with
+ the addition that it also returns the
+ * target task's prior notification value (the notification value at the time
+ the function is called rather than at
+ * the time the function returns).
+
+ * @param higherPriorityTaskWoken A reference that will be set to true if
+ sending the notification caused a task to
+ * unblock, and the unblocked task has a priority higher than the currently
+ running task. If higherPriorityTaskWoken
+ * is set to true, then a context switch should be requested before the
+ interrupt is exited.
+ * @param action An enumerated type that can take one of the values documented
+ in the table below in order to perform
+ * the associated action.
+ *
NotifyAction Setting
Action Performed
+ *
NoAction
The target task receives the event,
+ but its notification value is not updated.
+ * In this case value is not used.
+ *
SetBits
The notification value of the target
+ task will be bitwise ORed with value. For
+ * example, if value is set to 0x01, then bit 0 will get set within the target
+ task's notification value. Likewise if
+ * value is 0x04 then bit 2 will get set in the target task's notification
+ value. In this way the RTOS task
+ * notification mechanism can be used as a light weight alternative to an
+ event group.
+ *
Increment
The notification value of the target
+ task will be incremented by one, making
+ * the call to notify() equivalent to a call to notifyGive(). In this case
+ value is not used.
+ *
SetValueWithOverwrite
The notification value of the target
+ task is unconditionally set to value. In
+ * this way the RTOS task notification mechanism is being used as a light
+ weight alternative to
+ * FreeRTOS::Queue::Overwrite().
+ *
SetValueWithoutOverwrite
If the target task does not already
+ have a notification pending then its
+ * notification value will be set to value. If the target task already has a
+ notification pending then its
+ * notification value is not updated as to do so would overwrite the previous
+ value before it was used. In this case
+ * the call to notify() fails and false is returned. In this way the RTOS
+ task notification mechanism is being used
+ * as a light weight alternative to FreeRTOS::Queue::send() on a queue of
+ length 1.
+ * @param value Used to update the notification value of the task. See the
+ description of the action parameter below.
+ * @param index The index within the target task's array of notification
+ values to which the notification is to be
+ * sent. index must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ *
+ * @retval false If action is set to SetValueWithoutOverwrite and the task's
+ notification value cannot be updated
+ * because the target task already had a notification pending.
+ * @retval true Otherwise.
+ * @return NotificationBits The task's notification value before any bits are
+ modified.
+ *
+ * Example Usage
+ * @include Task/notifyAndQueryFromISR.cpp
+ */
+ inline std::pair notifyAndQueryFromISR(
+ bool& higherPriorityTaskWoken, const NotifyAction action,
+ const NotificationBits value = 0, const UBaseType_t index = 0) const {
+ BaseType_t taskWoken = pdFALSE;
+ uint32_t pulNotificationValue;
+ bool result = (xTaskNotifyAndQueryIndexedFromISR(
+ handle, index, value.to_ulong(),
+ static_cast(action),
+ &pulNotificationValue, &taskWoken) == pdPASS);
+
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+
+ return std::make_pair(result, NotificationBits(pulNotificationValue));
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t
+ xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify,
+ * UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction,
+ uint32_t *pulPreviousNotifyValue,
+ * BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline std::pair notifyAndQueryFromISR(
+ const NotifyAction action, const NotificationBits value = 0,
+ const UBaseType_t index = 0) const {
+ uint32_t pulNotificationValue;
+ bool result = (xTaskNotifyAndQueryIndexedFromISR(
+ handle, index, value.to_ulong(),
+ static_cast(action),
+ &pulNotificationValue, NULL) == pdPASS);
+
+ return std::make_pair(result, NotificationBits(pulNotificationValue));
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t xTaskNotifyIndexedFromISR(
+ * TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue,
+ * eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * Version of notify() that can be used from an interrupt service routine
+ * (ISR). See the documentation page for the notify() API function for a
+ * description of their operation and the necessary configuration parameters,
+ * as well as backward compatibility information.
+ *
+ * @param higherPriorityTaskWoken A reference that will be set to true if
+ * sending the notification caused a task to unblock, and the unblocked task
+ * has a priority higher than the currently running task. If
+ * higherPriorityTaskWoken is set to true, then a context switch should be
+ * requested before the interrupt is exited.
+ * @param action An enumerated type that can take one of the values documented
+ * in the table below in order to perform the associated action.
+ *
NotifyAction Setting
Action Performed
+ *
NoAction
The target task receives the event,
+ * but its notification value is not updated. In this case value is not used.
+ *
SetBits
The notification value of the target
+ * task will be bitwise ORed with value. For example, if value is set to 0x01,
+ * then bit 0 will get set within the target task's notification value.
+ * Likewise if value is 0x04 then bit 2 will get set in the target task's
+ * notification value. In this way the RTOS task notification mechanism can be
+ * used as a light weight alternative to an event group.
Increment
+ *
The notification value of the target task will be incremented by one,
+ * making the call to notify() equivalent to a call to notifyGive(). In this
+ * case value is not used.
SetValueWithOverwrite
The
+ * notification value of the target task is unconditionally set to value. In
+ * this way the RTOS task notification mechanism is being used as a light
+ * weight alternative to FreeRTOS::Queue::Overwrite().
+ *
SetValueWithoutOverwrite
If the target task does not already
+ * have a notification pending then its notification value will be set to
+ * value. If the target task already has a notification pending then its
+ * notification value is not updated as to do so would overwrite the previous
+ * value before it was used. In this case the call to notify() fails and false
+ * is returned. In this way the RTOS task notification mechanism is being
+ * used as a light weight alternative to FreeRTOS::Queue::send() on a queue of
+ * length 1.
+ * @param value Used to update the notification value of the task. See the
+ * description of the action parameter below.
+ * @param index The index within the target task's array of notification
+ * values to which the notification is to be sent. index must be less than
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ *
+ * @retval false If action is set to SetValueWithoutOverwrite and the task's
+ * notification value cannot be updated because the target task already had a
+ * notification pending.
+ * @retval true Otherwise.
+ *
+ * Example Usage
+ * This example demonstrates how to use notifyFromISR() with the SetBits
+ * action. See the notify() API documentation page for examples showing how to
+ * use the NoAction, SetValueWithOverwrite and SetValueWithoutOverwrite
+ * actions.
+ * @include Task/notifyFromISR.cpp
+ */
+ inline bool notifyFromISR(bool& higherPriorityTaskWoken,
+ const NotifyAction action,
+ const NotificationBits value = 0,
+ const UBaseType_t index = 0) const {
+ BaseType_t taskWoken = pdFALSE;
+ bool result = (xTaskNotifyIndexedFromISR(handle, index, value.to_ulong(),
+ static_cast(action),
+ &taskWoken) == pdPASS);
+ if (taskWoken == pdTRUE) {
+ higherPriorityTaskWoken = true;
+ }
+ return result;
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t xTaskNotifyIndexedFromISR(
+ * TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue,
+ * eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )
+ *
+ * @see
+ *
+ * @overload
+ */
+ inline bool notifyFromISR(const NotifyAction action,
+ const NotificationBits value = 0,
+ const UBaseType_t index = 0) const {
+ return (xTaskNotifyIndexedFromISR(handle, index, value.to_ulong(),
+ static_cast(action),
+ NULL) == pdPASS);
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t xTaskNotifyWaitIndexed(
+ * UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t
+ * ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t
+ * xTicksToWait )
+ *
+ * @see
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Each task has an array of 'task notifications' (or just 'notifications'),
+ * each of which has a state and a 32-bit value. A direct to task notification
+ * is an event sent directly to a task that can unblock the receiving task,
+ * and optionally update one of the receiving task’s notification values in a
+ * number of different ways. For example, a notification may overwrite one of
+ * the receiving task’s notification values, or just set one or more bits in
+ * one of the receiving task’s notification values.
+ *
+ * notifyWait() waits, with an optional timeout, for the calling task to
+ * receive a notification. If the receiving RTOS task was already Blocked
+ * waiting for a notification when the notification it is waiting for arrives
+ * the receiving RTOS task will be removed from the Blocked state and the
+ * notification cleared.
+ *
+ * @note Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not
+ * be unblocked by a notification sent to any other array index.
+ *
+ * notifyGive() must not be called from an interrupt service routine. Use
+ * notifyGiveFromISR() instead.
+ *
+ * @param ticksToWait The maximum time to wait in the Blocked state for a
+ * notification to be received if a notification is not already pending when
+ * notifyWait() is called.
+ *
+ * The RTOS task does not consume any CPU time when it is in the Blocked
+ * state.
+ *
+ * The time is specified in RTOS tick periods. The pdMS_TO_TICKS() macro can
+ * be used to convert a time specified in milliseconds into a time specified
+ * in ticks.
+ *
+ * @param bitsToClearOnEntry Any bits set in bitsToClearOnEntry will be
+ * cleared in the calling RTOS task's notification value on entry to the
+ * notifyWait() function (before the task waits for a new notification)
+ * provided a notification is not already pending when notifyWait() is called.
+ *
+ * For example, if bitsToClearOnEntry is 0x01, then bit 0 of the task's
+ * notification value will be cleared on entry to the function.
+ *
+ * Setting bitsToClearOnEntry to 0xffffffff (ULONG_MAX) will clear all the
+ * bits in the task's notification value, effectively clearing the value to 0.
+ *
+ * @param bitsToClearOnExit Any bits set in bitsToClearOnExit will be cleared
+ * in the calling RTOS task's notification value before notifyWait() function
+ * exits if a notification was received.
+ *
+ * The bits are cleared after the RTOS task's notification value are returned.
+ *
+ * For example, if bitsToClearOnExit is 0x03, then bit 0 and bit 1 of the
+ * task's notification value will be cleared before the function exits.
+ *
+ * Setting bitsToClearOnExit to 0xffffffff (ULONG_MAX) will clear all the bits
+ * in the task's notification value, effectively clearing the value to 0.
+ *
+ * @param index The index within the calling task's array of notification
+ * values on which the calling task will wait for a notification to be
+ * received. index must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ *
+ * @retval true If a notification was received, or a notification was already
+ * pending when notifyWait() was called.
+ * @retval false If the call to notifyWait() timed out before a notification
+ * was received.
+ * @return The RTOS task's notification value as it was before any bits were
+ * cleared due to the bitsToClearOnExit setting.
+ *
+ * Example Usage
+ * @include Task/notifyWait.cpp
+ */
+ inline static std::pair notifyWait(
+ const TickType_t ticksToWait = portMAX_DELAY,
+ const NotificationBits bitsToClearOnEntry = 0,
+ const NotificationBits bitsToClearOnExit = 0,
+ const UBaseType_t index = 0) {
+ uint32_t pulNotificationValue;
+ bool result =
+ (xTaskNotifyWaitIndexed(index, bitsToClearOnEntry.to_ulong(),
+ bitsToClearOnExit.to_ulong(),
+ &pulNotificationValue, ticksToWait) == pdTRUE);
+ return std::make_pair(result, NotificationBits(pulNotificationValue));
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t xTaskNotifyStateClearIndexed(
+ * TaskHandle_t xTask, UBaseType_t uxIndexToClear )
+ *
+ * @see
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Each RTOS task has an array of task notifications. Each task notification
+ * has a notification state that can be either ‘pending’ or ‘not pending’, and
+ * a 32-bit notification value.
+ *
+ * If a notification is sent to an index within the array of notifications
+ * then the notification at that index is said to be 'pending' until the task
+ * reads its notification value or explicitly clears the notification state to
+ * 'not pending' by calling notifyStateClear().
+ *
+ * @param index The index within the target task's array of notification
+ * values to act upon. For example, setting index to 1 will clear the state of
+ * the notification at index 1 within the array.
+ *
+ * index must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ *
+ * notifyStateClear() does not have this parameter and always acts on the
+ * notification at index 0.
+ *
+ * @retval true If the task had a notification pending, and the notification
+ * was cleared.
+ * @retval false If the task didn't have a notification pending.
+ *
+ * Example Usage
+ * @include Task/notifyStateClear.cpp
+ */
+ inline bool notifyStateClear(const UBaseType_t index = 0) const {
+ return (xTaskNotifyStateClearIndexed(handle, index) == pdTRUE);
+ }
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls uint32_t ulTaskNotifyValueClearIndexed(
+ * TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear
+ * )
+ *
+ * @see
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Each RTOS task has an array of task notifications. Each task notification
+ * has a notification state that can be either ‘pending’ or ‘not pending’, and
+ * a 32-bit notification value.
+ *
+ * notifyValueClear() clears the bits specified by the bitsToClear bit mask in
+ * the notification value at array index index of the task.
+ *
+ * @param bitsToClear Bit mask of the bits to clear in the notification value
+ * of the task. Set a bit to 1 to clear the corresponding bits in the task's
+ * notification value. Set bitsToClear to 0xffffffff (UINT_MAX on 32-bit
+ * architectures) to clear the notification value to 0. Set bitsToClear to 0
+ * to query the task's notification value without clearing any bits.
+ * @param index The index within the target task's array of notification
+ * values in which to clear the bits. index must be less than
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ * @return NotificationBits The value of the target task's notification value
+ * before the bits specified by bitsToClear were cleared.
+ *
+ * Example Usage
+ * @include Task/notifyValueClear.cpp
+ */
+ inline NotificationBits notifyValueClear(
+ const NotificationBits bitsToClear = 0,
+ const UBaseType_t index = 0) const {
+ return NotificationBits(
+ ulTaskNotifyValueClearIndexed(handle, index, bitsToClear.to_ulong()));
+ }
+#endif /* configUSE_TASK_NOTIFICATIONS */
+
+ protected:
+ /**
+ * Task.hpp
+ *
+ * @brief Abstraction function that acts as the entry point of the task for
+ * the user.
+ */
+ virtual void taskFunction() = 0;
+
+#if (INCLUDE_vTaskDelay == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls void vTaskDelay( const TickType_t
+ * xTicksToDelay )
+ *
+ * @see
+ *
+ * INCLUDE_vTaskDelay must be defined as 1 for this function to be available.
+ * See the configuration section for more information.
+ *
+ * Delay a task for a given number of ticks. The actual time that the task
+ * remains blocked depends on the tick rate. The constant portTICK_PERIOD_MS
+ * can be used to calculate real time from the tick rate - with the resolution
+ * of one tick period.
+ *
+ * delay() specifies a time at which the task wishes to unblock relative to
+ * the time at which delay() is called. For example, specifying a block
+ * period of 100 ticks will cause the task to unblock 100 ticks after delay()
+ * is called. delay() does not therefore provide a good method of controlling
+ * the frequency of a periodic task as the path taken through the code, as
+ * well as other task and interrupt activity, will affect the frequency at
+ * which delay() gets called and therefore the time at which the task next
+ * executes. See delayUntil() for an alternative API function designed to
+ * facilitate fixed frequency execution. It does this by specifying an
+ * absolute time (rather than a relative time) at which the calling task
+ * should unblock.
+ *
+ * @param ticksToDelay The amount of time, in tick periods, that the task
+ * should block.
+ *
+ * Example Usage
+ * @include Task/delay.cpp
+ */
+ inline static void delay(const TickType_t ticksToDelay = 0) {
+ vTaskDelay(ticksToDelay);
+ }
+#endif /* INCLUDE_vTaskDelay */
+
+#if (INCLUDE_xTaskDelayUntil == 1)
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls BaseType_t xTaskDelayUntil( TickType_t
+ * *pxPreviousWakeTime, const TickType_t xTimeIncrement )
+ *
+ * @see
+ *
+ * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be
+ * available. See the configuration section for more information.
+ *
+ * Delay a task until a specified time. This function can be used by periodic
+ * tasks to ensure a constant execution frequency.
+ *
+ * This function differs from delay() in one important aspect: delay() will
+ * cause a task to block for the specified number of ticks from the time delay
+ * () is called. It is therefore difficult to use delay() by itself to
+ * generate a fixed execution frequency as the time between a task starting to
+ * execute and that task calling delay() may not be fixed [the task may take a
+ * different path though the code between calls, or may get interrupted or
+ * preempted a different number of times each time it executes].
+ *
+ * Whereas delay() specifies a wake time relative to the time at which the
+ * function is called, delayUntil() specifies the absolute (exact) time at
+ * which it wishes to unblock.
+ *
+ * The function pdMS_TO_TICKS() can be used to calculate the number of ticks
+ * from a time specified in milliseconds with a resolution of one tick period.
+ *
+ * @param timeIncrement The cycle time period. The task will be unblocked at
+ * time (previousWakeTime + timeIncrement). Calling delayUntil() with the same
+ * timeIncrement parameter value will cause the task to execute with a fixed
+ * interval period.
+ * @return true If the task way delayed.
+ * @return false Otherwise. A task will not be delayed if the next expected
+ * wake time is in the past.
+ *
+ * Example Usage
+ * @include Task/delayUntil.cpp
+ */
+ inline bool delayUntil(const TickType_t timeIncrement = 0) {
+ return (xTaskDelayUntil(&previousWakeTime, timeIncrement) == pdTRUE);
+ }
+#endif /* INCLUDE_xTaskDelayUntil */
+
+ /**
+ * Task.hpp
+ *
+ * @brief Function that calls uint32_t ulTaskNotifyTakeIndexed(
+ * UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t
+ * xTicksToWait )
+ *
+ * @see
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Each task has a private array of "notification values" (or
+ * 'notifications'), each of which is a 32-bit unsigned integer (uint32_t).
+ * The constant configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of
+ * indexes in the array, and (for backward compatibility) defaults to 1 if
+ * left undefined. Prior to FreeRTOS V10.4.0 there was only one notification
+ * value per task.
+ *
+ * Events can be sent to a task using an intermediary object. Examples of
+ * such objects are queues, semaphores, mutexes and event groups. Task
+ * notifications are a method of sending an event directly to a task without
+ * the need for such an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values. In
+ * that way task notifications can be used to send data to a task, or be used
+ * as light weight and fast binary or counting semaphores.
+ *
+ * notifyTake() is intended for use when a task notification is used as a
+ * faster and lighter weight binary or counting semaphore alternative. Actual
+ * FreeRTOS semaphores are taken using the FreeRTOS::Semaphore::take() API
+ * function, the equivalent action that instead uses a task notification is
+ * notifyTake().
+ *
+ * When task notifications are being used as a binary or counting semaphore
+ * equivalent then the task being notified should wait for the notification
+ * using the notificationTake() API function rather than the notifyWait() API
+ * function.
+ *
+ * notifyTake() can either clear the task's notification value at the array
+ * index specified by the indexToWaitOn parameter to zero on exit, in which
+ * case the notification value acts like a binary semaphore, or decrement the
+ * notification value on exit, in which case the notification value acts like
+ * a counting semaphore.
+ *
+ * A task can use notifyTake() to [optionally] block to wait for a
+ * notification. The task does not consume any CPU time while it is in the
+ * Blocked state.
+ *
+ * Where as notifyWait() will return when a notification is pending,
+ * notifyTake() will return when the task's notification value is not zero.
+ *
+ * @note Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not
+ * be unblocked by a notification sent to any other array index.
+ *
+ * @param ticksToWait The maximum time to wait in the Blocked state for a
+ * notification to be received if a notification is not already pending when
+ * notifyTake() is called. The RTOS task does not consume any CPU time when
+ * it is in the Blocked state. The time is specified in RTOS tick periods.
+ * The pdMS_TO_TICKS() macro can be used to convert a time specified in
+ * milliseconds into a time specified in ticks.
+ *
+ * @param clearCountOnExit If an RTOS task notification is received and
+ * clearCountOnExit is set to false then the RTOS task's notification value is
+ * decremented before notifyTake() exits. This is equivalent to the value of a
+ * counting semaphore being decremented by a successful call to
+ * FreeRTOS::Semaphore::Take(). If an RTOS task notification is received and
+ * clearCountOnExit is set to true then the RTOS task's notification value is
+ * reset to 0 before notifyTake() exits. This is equivalent to the value of a
+ * binary semaphore being left at zero (or empty, or 'not available') after a
+ * successful call to FreeRTOS::Semaphore::Take().
+ *
+ * @param index The index within the calling task's array of notification
+ * values on which the calling task will wait for a notification to be
+ * non-zero. index must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ *
+ * @return NotificationBits The value of the task's notification value before
+ * it is decremented or cleared (see the description of clearCountOnExit)
+ *
+ * Example Usage
+ * @include Task/notifyTake.cpp
+ */
+ inline static NotificationBits notifyTake(
+ const TickType_t ticksToWait = portMAX_DELAY,
+ const bool clearCountOnExit = true, const UBaseType_t index = 0) {
+ return NotificationBits(
+ ulTaskNotifyTakeIndexed(index, clearCountOnExit, ticksToWait));
+ }
+
+ private:
+ /**
+ * @brief Construct a new TaskBase object. This default constructor is
+ * deliberately private as this class is not intended to be instantiated or
+ * derived from by the user. Use FreeRTOS::Task or FreeRTOS::StaticTask as a
+ * base class for creating a task.
+ */
+ TaskBase() = default;
+
+ TaskBase(TaskBase&&) noexcept = default;
+ TaskBase& operator=(TaskBase&&) noexcept = default;
+
+ /**
+ * Task.hpp
+ *
+ * @brief Destroy the Task object.
+ *
+ * @see
+ *
+ * If INCLUDE_vTaskDelete is defined as 1 and the task handle is not NULL,
+ * then the destructor will call