portable/GCC/Posix: add new port for Posix (Linux) applications

This is similar to the Windows port, allowing FreeRTOS kernel
applications to run as regular applications on Posix (Linux) systems.

You can use this in a 32-bit or 64-bit application (although there are
dynamic memory allocation trace points that do not support 64-bit
addresses).

Many of the same caveats of running an RTOS on a non-real-time system
apply, but this is still very useful for easy debugging/testing
applications in a simulated environment. In particular, it allows easy
use of tools such as valgrind.

You can call standard library functions from tasks but care must be
taken with any that internally take mutexes or block. This includes
malloc()/free() and many stdio functions (e.g., printf()).

Replacement malloc(), free(), realloc(), and calloc() functions are
provided which are safe. printf() needs to be called with a FreeRTOS
mutex help (or called from only a single task).

Each task is run in its own pthread, which makes debugging with
standard tools (such as GDB) easier backtraces for individual tasks
are available. Threads for non-running tasks are blocked in sigwait().

The stack for each task (thread) is allocated when the thread is
created, and the stack provided during task creation is not used. This
is so the stack has guard pages, to help with detecting stack
overflows.

Task switch is done by resuming the thread for the next task by
sending it the resume signal (SIGUSR1) and then suspending the current
thread.

The timer interrupt uses SIGALRM and care is taken to ensure that the
signal handler runs only on the thread for the current task.

The additional data needed per-thread is stored at the top on the
task's stack.

When a running task is being deleted, its thread is marked it as dying
so when we switch away from it it exits instead of suspending. This
ensures that even if the idle task doesn't run, threads are deleted
which allows for more threads to be created (if many tasks are being
created and deleted in rapid succession).

To further aid debugging, SIGINT (^C) is not blocked inside critical
sections. This allows it to be used break into GDB while in a critical
section. This means that care must be taken with any custom SIGINT
handlers as these are like NMIs.

This is somewhat inspired by an existing port by William Davy
(https://www.freertos.org/FreeRTOS-simulator-for-Linux.html) but it
takes a number of different approaches to make it switch tasks
reliableand there's little similarly with the original implementation.

- Critical sections block scheduling/"interrupts" by blocking signals
  using pthread_sigmask(). This is more expensive than attempting to
  use flags but works reliably and is analogous to the interrupt
  enable/disable on real hardware.

- Care is take to ensure that the SIGALRM handler (for the timer tick)
  is runnable only on the pthread for the running task. This makes
  tasks switches more straight-forward and reliable as we can suspend
  the thread while in the signal handler.

- Task switches save/restore the critical nesting on the stack.

- Only uses a single (SIGUSR1) signal which is ignored and thus GDB's
  default signal handling options won't trap/print on this signal.

- Extra per-thread data is stored on the task's stack, making it
  accessible in O(1) instead of performing a O(n) lookup of the array.

- Uses the task create/delete hooks in a similar way to the Windows
  port, rather than overloading trace points.
diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c
new file mode 100644
index 0000000..bae6e2f
--- /dev/null
+++ b/portable/ThirdParty/GCC/Posix/port.c
@@ -0,0 +1,601 @@
+/*
+ * FreeRTOS Kernel V10.3.0
+ * Copyright (C) 2020 Cambridge Consultants Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+/*-----------------------------------------------------------
+ * Implementation of functions defined in portable.h for the Posix port.
+ *
+ * Each task has a pthread which eases use of standard debuggers
+ * (allowing backtraces of tasks etc). Threads for tasks that are not
+ * running are blocked in sigwait().
+ *
+ * Task switch is done by resuming the thread for the next task by
+ * sending it the resume signal (SIGUSR1) and then suspending the
+ * current thread.
+ *
+ * The timer interrupt uses SIGALRM and care is taken to ensure that
+ * the signal handler runs only on the thread for the current task.
+ *
+ * Use of part of the standard C library requires care as some
+ * functions can take pthread mutexes internally which can result in
+ * deadlocks as the FreeRTOS kernel can switch tasks while they're
+ * holding a pthread mutex.
+ *
+ * Replacement malloc(), free(), calloc(), and realloc() are provided
+ * for glibc (see below for more information).
+ *
+ * stdio (printf() and friends) should be called from a single task
+ * only or serialized with a FreeRTOS primitive such as a binary
+ * semaphore or mutex.
+ *----------------------------------------------------------*/
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <time.h>
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+/*-----------------------------------------------------------*/
+
+#define SIG_RESUME SIGUSR1
+
+typedef struct THREAD
+{
+	pthread_t pthread;
+	pdTASK_CODE pxCode;
+	void *pvParams;
+	BaseType_t xDying;
+} Thread_t;
+
+/*
+ * The additional per-thread data is stored at the beginning of the
+ * task's stack.
+ */
+static inline Thread_t *prvGetThreadFromTask(TaskHandle_t xTask)
+{
+StackType_t *pxTopOfStack = *(StackType_t **)xTask;
+
+	return (Thread_t *)(pxTopOfStack + 1);
+}
+
+/*-----------------------------------------------------------*/
+
+static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT;
+static sigset_t xResumeSignals;
+static sigset_t xAllSignals;
+static sigset_t xSchedulerOriginalSignalMask;
+static pthread_t hMainThread = ( pthread_t )NULL;
+static volatile portBASE_TYPE uxCriticalNesting;
+/*-----------------------------------------------------------*/
+
+static portBASE_TYPE xSchedulerEnd = pdFALSE;
+/*-----------------------------------------------------------*/
+
+static void prvSetupSignalsAndSchedulerPolicy( void );
+static void prvSetupTimerInterrupt( void );
+static void *prvWaitForStart( void * pvParams );
+static void prvSwitchThread( Thread_t *xThreadToResume, Thread_t *xThreadToSuspend );
+static void prvSuspendSelf( void );
+static void prvResumeThread( pthread_t xThreadId );
+static void vPortSystemTickHandler( int sig );
+static void vPortStartFirstTask( void );
+/*-----------------------------------------------------------*/
+
+/*
+ * The standard glibc malloc(), free() etc. take an internal lock so
+ * it is not safe to switch tasks while calling them.
+ *
+ * Requiring the application use the safe xPortMalloc() and
+ * vPortFree() is not sufficient as malloc() is used internally by
+ * glibc (e.g., by strdup() and the pthread library.)
+ *
+ * To further complicate things malloc() and free() may be called
+ * outside of task context during pthread destruction so using
+ * vTaskSuspend() and xTaskResumeAll() cannot be used.
+ * vPortEnterCritical() and vPortExitCritical() cannot be used either
+ * as they use global state for the critical section nesting (this
+ * cannot be fixed by using TLS as pthread destruction needs to free
+ * the TLS).
+ *
+ * Explicitly save/disable and restore the signal mask to block the
+ * timer (SIGALRM) and other signals.
+ */
+
+extern void *__libc_malloc(size_t);
+extern void __libc_free(void *);
+extern void *__libc_calloc(size_t, size_t);
+extern void *__libc_realloc(void *ptr, size_t);
+
+void *malloc(size_t size)
+{
+sigset_t xSavedSignals;
+void *ptr;
+
+	pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
+	ptr = __libc_malloc( size );
+	pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
+
+	return ptr;
+}
+
+void free(void *ptr)
+{
+sigset_t xSavedSignals;
+
+	pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
+	__libc_free( ptr );
+	pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
+}
+
+void *calloc(size_t nmemb, size_t size)
+{
+sigset_t xSavedSignals;
+void *ptr;
+
+	pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
+	ptr = __libc_calloc( nmemb, size );
+	pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
+
+	return ptr;
+}
+
+void *realloc(void *ptr, size_t size)
+{
+sigset_t xSavedSignals;
+
+	pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
+	ptr = __libc_realloc( ptr, size );
+	pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
+
+	return ptr;
+}
+
+static void prvFatalError( const char *pcCall, int iErrno )
+{
+	fprintf( stderr, "%s: %s\n", pcCall, strerror( iErrno ) );
+	abort();
+}
+
+/*
+ * See header file for description.
+ */
+portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack,
+                                       portSTACK_TYPE *pxEndOfStack,
+                                       pdTASK_CODE pxCode, void *pvParameters )
+{
+Thread_t *thread;
+pthread_attr_t xThreadAttributes;
+size_t ulStackSize;
+int iRet;
+
+	(void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy );
+
+	/*
+	 * Store the additional thread data at the start of the stack.
+	 */
+	thread = (Thread_t *)(pxTopOfStack + 1) - 1;
+	pxTopOfStack = (portSTACK_TYPE *)thread - 1;
+	ulStackSize = (pxTopOfStack + 1 - pxEndOfStack) * sizeof(*pxTopOfStack);
+
+	thread->pxCode = pxCode;
+	thread->pvParams = pvParameters;
+	thread->xDying = pdFALSE;
+
+	pthread_attr_init( &xThreadAttributes );
+	pthread_attr_setstack( &xThreadAttributes, pxEndOfStack, ulStackSize );
+
+	vPortEnterCritical();
+
+	iRet = pthread_create( &thread->pthread, &xThreadAttributes,
+						   prvWaitForStart, thread );
+	if ( iRet )
+	{
+		prvFatalError( "pthread_create", iRet );
+	}
+
+	vPortExitCritical();
+
+	return pxTopOfStack;
+}
+/*-----------------------------------------------------------*/
+
+void vPortStartFirstTask( void )
+{
+Thread_t *pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
+
+	/* Start the first task. */
+	prvResumeThread( pxFirstThread->pthread );
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+portBASE_TYPE xPortStartScheduler( void )
+{
+int iSignal;
+sigset_t xSignals;
+
+	hMainThread = pthread_self();
+
+	/* Start the timer that generates the tick ISR.  Interrupts are disabled
+	here already. */
+	prvSetupTimerInterrupt();
+
+	/* Start the first task. */
+	vPortStartFirstTask();
+
+	/* Wait until signaled by vPortEndScheduler(). */
+	sigemptyset( &xSignals );
+	sigaddset( &xSignals, SIG_RESUME );
+
+	while ( !xSchedulerEnd )
+	{
+		sigwait( &xSignals, &iSignal );
+	}
+
+	/* Restore original signal mask. */
+	(void)pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask,  NULL );
+
+	return 0;
+}
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler( void )
+{
+struct itimerval itimer;
+struct sigaction sigtick;
+
+	/* Stop the timer and ignore any pending SIGALRMs that would end
+	 * up running on the main thread when it is resumed. */
+	itimer.it_value.tv_sec = 0;
+	itimer.it_value.tv_usec = 0;
+	(void)setitimer( ITIMER_REAL, &itimer, NULL );
+
+	sigtick.sa_flags = 0;
+	sigtick.sa_handler = SIG_IGN;
+	sigaction( SIGALRM, &sigtick, NULL );
+
+	/* Signal the scheduler to exit its loop. */
+	xSchedulerEnd = pdTRUE;
+	(void)pthread_kill( hMainThread, SIG_RESUME );
+
+	prvSuspendSelf();
+}
+/*-----------------------------------------------------------*/
+
+void vPortEnterCritical( void )
+{
+	if ( uxCriticalNesting == 0 )
+	{
+		vPortDisableInterrupts();
+	}
+	uxCriticalNesting++;
+}
+/*-----------------------------------------------------------*/
+
+void vPortExitCritical( void )
+{
+	uxCriticalNesting--;
+
+	/* If we have reached 0 then re-enable the interrupts. */
+	if( uxCriticalNesting == 0 )
+	{
+		vPortEnableInterrupts();
+	}
+}
+/*-----------------------------------------------------------*/
+
+void vPortYieldFromISR( void )
+{
+Thread_t *xThreadToSuspend;
+Thread_t *xThreadToResume;
+
+	xThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
+
+	vTaskSwitchContext();
+
+	xThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
+
+	prvSwitchThread( xThreadToResume, xThreadToSuspend );
+}
+/*-----------------------------------------------------------*/
+
+void vPortYield( void )
+{
+	vPortEnterCritical();
+
+	vPortYieldFromISR();
+
+	vPortExitCritical();
+}
+/*-----------------------------------------------------------*/
+
+void vPortDisableInterrupts( void )
+{
+	pthread_sigmask( SIG_BLOCK, &xAllSignals, NULL );
+}
+/*-----------------------------------------------------------*/
+
+void vPortEnableInterrupts( void )
+{
+	pthread_sigmask( SIG_UNBLOCK, &xAllSignals, NULL );
+}
+/*-----------------------------------------------------------*/
+
+portBASE_TYPE xPortSetInterruptMask( void )
+{
+	/* Interrupts are always disabled inside ISRs (signals
+	   handlers). */
+	return pdTRUE;
+}
+/*-----------------------------------------------------------*/
+
+void vPortClearInterruptMask( portBASE_TYPE xMask )
+{
+}
+/*-----------------------------------------------------------*/
+
+static uint64_t prvGetTimeNs(void)
+{
+struct timespec t;
+
+	clock_gettime(CLOCK_MONOTONIC, &t);
+
+	return t.tv_sec * 1000000000ull + t.tv_nsec;
+}
+
+static uint64_t prvStartTimeNs;
+static uint64_t prvTickCount;
+
+/*
+ * Setup the systick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+void prvSetupTimerInterrupt( void )
+{
+struct itimerval itimer;
+int iRet;
+
+	/* Initialise the structure with the current timer information. */
+	iRet = getitimer( ITIMER_REAL, &itimer );
+	if ( iRet )
+	{
+		prvFatalError( "getitimer", errno );
+	}
+
+	/* Set the interval between timer events. */
+	itimer.it_interval.tv_sec = 0;
+	itimer.it_interval.tv_usec = portTICK_RATE_MICROSECONDS;
+
+	/* Set the current count-down. */
+	itimer.it_value.tv_sec = 0;
+	itimer.it_value.tv_usec = portTICK_RATE_MICROSECONDS;
+
+	/* Set-up the timer interrupt. */
+	iRet = setitimer( ITIMER_REAL, &itimer, NULL );
+	if ( iRet )
+	{
+		prvFatalError( "setitimer", errno );
+	}
+
+	prvStartTimeNs = prvGetTimeNs();
+}
+/*-----------------------------------------------------------*/
+
+static void vPortSystemTickHandler( int sig )
+{
+Thread_t *pxThreadToSuspend;
+Thread_t *pxThreadToResume;
+uint64_t xExpectedTicks;
+
+	uxCriticalNesting++; /* Signals are blocked in this signal handler. */
+
+	pxThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
+
+	/* Tick Increment, accounting for any lost signals or drift in
+	 * the timer. */
+	xExpectedTicks = (prvGetTimeNs() - prvStartTimeNs)
+		/ (portTICK_RATE_MICROSECONDS * 1000);
+	do {
+		xTaskIncrementTick();
+		prvTickCount++;
+	} while (prvTickCount < xExpectedTicks);
+
+#if ( configUSE_PREEMPTION == 1 )
+	/* Select Next Task. */
+	vTaskSwitchContext();
+
+	pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
+
+	prvSwitchThread(pxThreadToResume, pxThreadToSuspend);
+#endif
+
+	uxCriticalNesting--;
+}
+/*-----------------------------------------------------------*/
+
+void vPortThreadDying( void *pxTaskToDelete, volatile BaseType_t *pxPendYield )
+{
+Thread_t *pxThread = prvGetThreadFromTask( pxTaskToDelete );
+
+	pxThread->xDying = pdTRUE;
+}
+
+void vPortCancelThread( void *pxTaskToDelete )
+{
+Thread_t *pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete );
+
+	/*
+	 * The thread has already been suspended so it can be safely
+	 * cancelled.
+	 */
+	pthread_cancel( pxThreadToCancel->pthread );
+	pthread_join( pxThreadToCancel->pthread, NULL );
+}
+/*-----------------------------------------------------------*/
+
+static void *prvWaitForStart( void * pvParams )
+{
+Thread_t *pxThread = pvParams;
+
+	prvSuspendSelf();
+
+	/* Resumed for the first time, unblocks all signals. */
+	uxCriticalNesting = 0;
+	vPortEnableInterrupts();
+
+	/* Call the task's entry point. */
+	pxThread->pxCode( pxThread->pvParams );
+
+	return NULL;
+}
+/*-----------------------------------------------------------*/
+
+static void prvSwitchThread( Thread_t *pxThreadToResume,
+							 Thread_t *pxThreadToSuspend )
+{
+BaseType_t uxSavedCriticalNesting;
+
+	if ( pxThreadToSuspend != pxThreadToResume )
+	{
+		/*
+		 * Switch tasks.
+		 *
+		 * The critical section nesting is per-task, so save it on the
+		 * stack of the current (suspending thread), restoring it when
+		 * we switch back to this task.
+		 */
+		uxSavedCriticalNesting = uxCriticalNesting;
+
+		prvResumeThread( pxThreadToResume->pthread );
+		if ( pxThreadToSuspend->xDying )
+		{
+			pthread_exit( NULL );
+		}
+		prvSuspendSelf();
+
+		uxCriticalNesting = uxSavedCriticalNesting;
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvSuspendSelf( void )
+{
+int iSig;
+
+	/*
+	 * Suspend this thread by waiting for a SIG_RESUME signal.
+	 *
+	 * A suspended thread must not handle signals (interrupts) so
+	 * all signals must be blocked by calling this from:
+	 *
+	 * - Inside a critical section (vPortEnterCritical() /
+	 *   vPortExitCritical()).
+	 *
+	 * - From a signal handler that has all signals masked.
+	 *
+	 * - A thread with all signals blocked with pthread_sigmask().
+	 */
+	sigwait( &xResumeSignals, &iSig );
+}
+
+/*-----------------------------------------------------------*/
+
+static void prvResumeThread( pthread_t xThreadId )
+{
+	if ( pthread_self() != xThreadId )
+	{
+		pthread_kill( xThreadId, SIG_RESUME );
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvSetupSignalsAndSchedulerPolicy( void )
+{
+struct sigaction sigresume, sigtick;
+int iRet;
+
+	hMainThread = pthread_self();
+
+	/* Initialise common signal masks. */
+	sigemptyset( &xResumeSignals );
+	sigaddset( &xResumeSignals, SIG_RESUME );
+	sigfillset( &xAllSignals );
+	/* Don't block SIGINT so this can be used to break into GDB while
+	 * in a critical section. */
+	sigdelset( &xAllSignals, SIGINT );
+
+	/*
+	 * Block all signals in this thread so all new threads
+	 * inherits this mask.
+	 *
+	 * When a thread is resumed for the first time, all signals
+	 * will be unblocked.
+	 */
+	(void)pthread_sigmask( SIG_SETMASK, &xAllSignals,
+						   &xSchedulerOriginalSignalMask );
+
+	/* SIG_RESUME is only used with sigwait() so doesn't need a
+	   handler. */
+	sigresume.sa_flags = 0;
+	sigresume.sa_handler = SIG_IGN;
+	sigfillset( &sigresume.sa_mask );
+
+	sigtick.sa_flags = 0;
+	sigtick.sa_handler = vPortSystemTickHandler;
+	sigfillset( &sigtick.sa_mask );
+
+	iRet = sigaction( SIG_RESUME, &sigresume, NULL );
+	if ( iRet )
+	{
+		prvFatalError( "sigaction", errno );
+	}
+
+	iRet = sigaction( SIGALRM, &sigtick, NULL );
+	if ( iRet )
+	{
+		prvFatalError( "sigaction", errno );
+	}
+}
+/*-----------------------------------------------------------*/
+
+unsigned long ulPortGetRunTime( void )
+{
+struct tms xTimes;
+
+	times( &xTimes );
+
+	return ( unsigned long ) xTimes.tms_utime;
+}
+/*-----------------------------------------------------------*/
diff --git a/portable/ThirdParty/GCC/Posix/portmacro.h b/portable/ThirdParty/GCC/Posix/portmacro.h
new file mode 100644
index 0000000..8046cbc
--- /dev/null
+++ b/portable/ThirdParty/GCC/Posix/portmacro.h
@@ -0,0 +1,134 @@
+/*
+ * FreeRTOS Kernel V10.3.0
+ * Copyright 2020 Cambridge Consultants Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <limits.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	unsigned long
+#define portBASE_TYPE	long
+#define portPOINTER_SIZE_TYPE intptr_t
+
+typedef portSTACK_TYPE StackType_t;
+typedef long BaseType_t;
+typedef unsigned long UBaseType_t;
+
+typedef unsigned long TickType_t;
+#define portMAX_DELAY ( TickType_t ) ULONG_MAX
+
+#define portTICK_TYPE_IS_ATOMIC 1
+
+/*-----------------------------------------------------------*/
+
+/* Architecture specifics. */
+#define portSTACK_GROWTH			( -1 )
+#define portHAS_STACK_OVERFLOW_CHECKING	( 1 )
+#define portTICK_PERIOD_MS			( ( TickType_t ) 1000 / configTICK_RATE_HZ )
+#define portTICK_RATE_MICROSECONDS	( ( portTickType ) 1000000 / configTICK_RATE_HZ )
+#define portBYTE_ALIGNMENT			8
+/*-----------------------------------------------------------*/
+
+/* Scheduler utilities. */
+extern void vPortYield( void );
+
+#define portYIELD() vPortYield()
+
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) vPortYield()
+#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
+/*-----------------------------------------------------------*/
+
+/* Critical section management. */
+extern void vPortDisableInterrupts( void );
+extern void vPortEnableInterrupts( void );
+#define portSET_INTERRUPT_MASK()        ( vPortDisableInterrupts() )
+#define portCLEAR_INTERRUPT_MASK()      ( vPortEnableInterrupts() )
+
+extern portBASE_TYPE xPortSetInterruptMask( void );
+extern void vPortClearInterruptMask( portBASE_TYPE xMask );
+
+extern void vPortEnterCritical( void );
+extern void vPortExitCritical( void );
+#define portSET_INTERRUPT_MASK_FROM_ISR()		xPortSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	vPortClearInterruptMask(x)
+#define portDISABLE_INTERRUPTS()				portSET_INTERRUPT_MASK()
+#define portENABLE_INTERRUPTS()					portCLEAR_INTERRUPT_MASK()
+#define portENTER_CRITICAL()					vPortEnterCritical()
+#define portEXIT_CRITICAL()						vPortExitCritical()
+
+/*-----------------------------------------------------------*/
+
+extern void vPortThreadDying( void *pxTaskToDelete, volatile BaseType_t *pxPendYield );
+extern void vPortCancelThread( void *pxTaskToDelete );
+#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) vPortThreadDying( ( pvTaskToDelete ), ( pxPendYield ) )
+#define portCLEAN_UP_TCB( pxTCB )	vPortCancelThread( pxTCB )
+/*-----------------------------------------------------------*/
+
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
+/*-----------------------------------------------------------*/
+
+/*
+ * Tasks run in their own pthreads and context switches between them
+ * are always a full memory barrier. ISRs are emulated as signals
+ * which also imply a full memory barrier.
+ *
+ * Thus, only a compilier barrier is needed to prevent the compiler
+ * reordering.
+ */
+#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
+
+extern unsigned long ulPortGetRunTime( void );
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* no-op */
+#define portGET_RUN_TIME_COUNTER_VALUE()         ulPortGetRunTime()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTMACRO_H */