text: /*
      FreeRTOS V7.6.0 - 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 <stdlib.h>
  #include <bitthunder.h>
  
  /* Scheduler includes. */
  #include <FreeRTOS.h>
  #include <task.h>
  
  struct _BT_OPAQUE_HANDLE {
  	BT_HANDLE_HEADER h;
  };
  
  /* A critical section is exited when the critical section nesting count reaches
  this value. */
  #define portNO_CRITICAL_NESTING			( ( unsigned long ) 0 )
  
  /* In all GICs 255 can be written to the priority mask register to unmask all
  (but the lowest) interrupt priority. */
  #define portUNMASK_VALUE				( 0xFF )
  
  /* Tasks are not created with a floating point context, but can be given a
  floating point context after they have been created.  A variable is stored as
  part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
  does not have an FPU context, or any other value if the task does have an FPU
  context. */
  #define portNO_FLOATING_POINT_CONTEXT	( ( portSTACK_TYPE ) 0 )
  
  
  /* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
  point is zero. */
  #define portBINARY_POINT_BITS			( ( unsigned char ) 0x03 )
  
  /* Constants required to setup the initial task context. */
  #define portINITIAL_SPSR				( ( portSTACK_TYPE ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
  #define portTHUMB_MODE_BIT				( ( portSTACK_TYPE ) 0x20 )
  #define portINTERRUPT_ENABLE_BIT		( 0x80UL )
  #define portTHUMB_MODE_ADDRESS			( 0x01UL )
  
  /* Masks all bits in the APSR other than the mode bits. */
  #define portAPSR_MODE_BITS_MASK			( 0x1F )
  
  /* The value of the mode bits in the APSR when the CPU is executing in user
  mode. */
  #define portAPSR_USER_MODE				( 0x10 )
  
  /*-----------------------------------------------------------*/
  
  /*
   * Starts the first task executing.  This function is necessarily written in
   * assembly code so is implemented in portASM.s.
   */
  extern void vPortRestoreTaskContext( void );
  
  /*-----------------------------------------------------------*/
  
  /* A variable is used to keep track of the critical section nesting.  This
  variable has to be stored as part of the task context and must be initialised to
  a non zero value to ensure interrupts don't inadvertently become unmasked before
  the scheduler starts.  As it is stored as part of the task context it will
  automatically be set to 0 when the first task is started. */
  volatile unsigned long ulCriticalNesting = 9999UL;
  
  /* Saved as part of the task context.  If ulPortTaskHasFPUContext is non-zero then
  a floating point context must be saved and restored for the task. */
  unsigned long ulPortTaskHasFPUContext = pdFALSE;
  
  /* Set to 1 to pend a context switch from an ISR. */
  unsigned long ulPortYieldRequired = pdFALSE;
  
  /* Counts the interrupt nesting depth.  A context switch is only performed if
  if the nesting depth is 0. */
  unsigned long ulPortInterruptNesting = 0UL;
  
  /*-----------------------------------------------------------*/
  
  /*
   * See header file for description.
   */
  portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
  {
  	/* Setup the initial stack of the task.  The stack is set exactly as
  	expected by the portRESTORE_CONTEXT() macro.
  
  	The fist real value on the stack is the status register, which is set for
  	system mode, with interrupts enabled.  A few NULLs are added first to ensure
  	GDB does not try decoding a non-existent return address. */
  	*pxTopOfStack = 0;
  	pxTopOfStack--;
  	*pxTopOfStack = 0;
  	pxTopOfStack--;
  	*pxTopOfStack = 0;
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) portINITIAL_SPSR;
  
  	if( ( ( unsigned long ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
  	{
  		/* The task will start in THUMB mode. */
  		*pxTopOfStack |= portTHUMB_MODE_BIT;
  	}
  
  	pxTopOfStack--;
  
  	/* Next the return address, which in this case is the start of the task. */
  	*pxTopOfStack = ( portSTACK_TYPE ) pxCode;
  	pxTopOfStack--;
  
  	/* Next all the registers other than the stack pointer. */
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x00000000;	/* R14 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x12121212;	/* R12 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x11111111;	/* R11 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x10101010;	/* R10 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x09090909;	/* R9 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x08080808;	/* R8 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x07070707;	/* R7 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x06060606;	/* R6 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x05050505;	/* R5 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x04040404;	/* R4 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x03030303;	/* R3 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x02020202;	/* R2 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) 0x01010101;	/* R1 */
  	pxTopOfStack--;
  	*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
  	pxTopOfStack--;
  
  	/* The task will start with a critical nesting count of 0 as interrupts are
  	enabled. */
  	*pxTopOfStack = portNO_CRITICAL_NESTING;
  
  #ifdef BT_CONFIG_TOOLCHAIN_FLOAT_HARD
  	pxTopOfStack--;
  	pxTopOfStack -= 64;			// Space for the floating point context.
  	*pxTopOfStack = 0x40000000;	// Initial FPEXC value (FPU enabled).
  	pxTopOfStack--;
  	*pxTopOfStack = 0;			// Initial FPSCR value.
  #endif
  
  	return pxTopOfStack;
  }
  
  /*-----------------------------------------------------------*/
  
  
  static BT_ERROR bt_tick_handler(BT_u32 ulIRQ, void *pParam)
  {
  
  	vTaskIncrementTick();
  #if configUSE_PREEMPTION == 1
  	//vTaskSwitchContext();
  	ulPortYieldRequired = pdTRUE;
  #endif
  	/* Increment the RTOS tick. */
  	/*if( xTaskIncrementTick() != pdFALSE )
  	{
  		ulPortYieldRequired = pdTRUE;
  		}*/
  
  	return BT_ERR_NONE;
  }
  
  
  portBASE_TYPE xPortStartScheduler( void )
  {
  	/* Change from System to IRQ mode.
  	 * portRESTORE_CONTEXT sets the desired CPSR by modifying SPSR, which
  	 * requires that the processor be in an Exception mode to actually
  	 * do anything by leaving that mode.
  	 */
  	__asm volatile (
  		"LDR    R0, =0x1D2       \n\t"
  		"MSR    CPSR, R0         \n\t"
  		:::"r0" \
  	);
  
  	//enable_irq();
  
  	BT_ERROR Error;
  	BT_MACHINE_DESCRIPTION *pMachine = BT_GetMachineDescription(&Error);
  	if(!pMachine) {
  		return 0;
  	}
  
  	const BT_INTEGRATED_DRIVER *pDriver;
  	BT_HANDLE hTimer = NULL;
  
  	pDriver = BT_GetIntegratedDriverByName(pMachine->pSystemTimer->name);
  	if(!pDriver) {
  		return 0;
  	}
  
  	hTimer = pDriver->pfnProbe(pMachine->pSystemTimer, &Error);
  	if(!hTimer) {
  		return 0;
  	}
  
  	BT_SetSystemTimerHandle(hTimer);
  
  	const BT_DEV_IF_SYSTIMER *pTimerOps = hTimer->h.pIf->oIfs.pDevIF->unConfigIfs.pSysTimerIF;
  	pTimerOps->pfnSetFrequency(hTimer, configTICK_RATE_HZ);
  	pTimerOps->pfnRegisterInterrupt(hTimer, bt_tick_handler, NULL);
  	pTimerOps->pfnEnableInterrupt(hTimer);
  	pTimerOps->pfnStart(hTimer);
  
  	BT_EnableInterrupts();
  
  	/* Simply start the scheduler.  This is included here as it can only be
  	called from ARM mode. */
  
  	vPortRestoreTaskContext();
  	return 0;
  }
  /*-----------------------------------------------------------*/
  
  void vPortEndScheduler( void )
  {
  	/* Not implemented in ports where there is nothing to return to.
  	Artificially force an assert. */
  	configASSERT( ulCriticalNesting == 1000UL );
  }
  /*-----------------------------------------------------------*/
  
  void vPortEnterCritical( void )
  {
  	portDISABLE_INTERRUPTS();
  	/* Now interrupts are disabled ulCriticalNesting can be accessed
  	directly.  Increment ulCriticalNesting to keep a count of how many times
  	portENTER_CRITICAL() has been called. */
  	ulCriticalNesting++;
  }
  /*-----------------------------------------------------------*/
  
  void vPortExitCritical( void )
  {
  	if( ulCriticalNesting > portNO_CRITICAL_NESTING )
  	{
  		/* Decrement the nesting count as the critical section is being
  		exited. */
  		ulCriticalNesting--;
  
  		/* If the nesting level has reached zero then all interrupt
  		priorities must be re-enabled. */
  		if( ulCriticalNesting == portNO_CRITICAL_NESTING )
  		{
  	         portENABLE_INTERRUPTS();
  		}
  	}
  }
  /*-----------------------------------------------------------*/
  
  /*-----------------------------------------------------------*/
  