text: /*
   * FreeRTOS Kernel V10.0.0
   * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy of
   * this software and associated documentation files (the "Software"), to deal in
   * the Software without restriction, including without limitation the rights to
   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
   * the Software, and to permit persons to whom the Software is furnished to do so,
   * subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in all
   * copies or substantial portions of the Software. If you wish to use our Amazon
   * FreeRTOS name, please do so in a fair use way that does not cause confusion.
   *
   * 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!
   */
  
  /*-----------------------------------------------------------
   * 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 )
  #endif
  
  #if portBYTE_ALIGNMENT == 16
  	#define portBYTE_ALIGNMENT_MASK ( 0x000f )
  #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 <avr/wdt.h>
  
  /**
      Enable the watchdog timer, configuring it for expire after
      (value) timeout (which is a combination of the WDP0
      through WDP3 bits).
  
      This function is derived from <avr/wdt.h> but enables only
      the interrupt bit (WDIE), rather than the reset bit (WDE).
  
      Can't find it documented but the WDT, once enabled,
      rolls over and fires a new interrupt each time.
  
      See also the symbolic constants WDTO_15MS et al.
  
      Updated to match avr-libc 2.0.0
  */
  
  static __inline__
  __attribute__ ((__always_inline__))
  void wdt_interrupt_enable (const uint8_t value)
  {
      if (_SFR_IO_REG_P (_WD_CONTROL_REG))
      {
          __asm__ __volatile__ (
                  "in __tmp_reg__,__SREG__"   "\n\t"
                  "cli"                       "\n\t"
                  "wdr"                       "\n\t"
                  "out %0, %1"                "\n\t"
                  "out __SREG__,__tmp_reg__"  "\n\t"
                  "out %0, %2"                "\n\t"
                  : /* no outputs */
                  : "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)),
                  "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))),
                  "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) |
                          _BV(WDIF) | _BV(WDIE) | (value & 0x07)) )
                  : "r0"
          );
      }
      else
      {
          __asm__ __volatile__ (
                  "in __tmp_reg__,__SREG__"   "\n\t"
                  "cli"                       "\n\t"
                  "wdr"                       "\n\t"
                  "sts %0, %1"                "\n\t"
                  "out __SREG__,__tmp_reg__"  "\n\t"
                  "sts %0, %2"                "\n\t"
                  : /* no outputs */
                  : "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)),
                  "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))),
                  "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) |
                          _BV(WDIF) | _BV(WDIE) | (value & 0x07)) )
                  : "r0"
          );
      }
  }
  
  /*-----------------------------------------------------------*/
  /**
      Enable the watchdog timer, configuring it for expire after
      (value) timeout (which is a combination of the WDP0
      through WDP3 bits).
  
      This function is derived from <avr/wdt.h> but enables both
      the reset bit (WDE), and the interrupt bit (WDIE).
  
      This will ensure that if the interrupt is not serviced
      before the second timeout, the AVR will reset.
  
      Servicing the interrupt automatically clears it,
      and ensures the AVR does not reset.
  
      Can't find it documented but the WDT, once enabled,
      rolls over and fires a new interrupt each time.
  
      See also the symbolic constants WDTO_15MS et al.
  
      Updated to match avr-libc 2.0.0
  */
  
  static __inline__
  __attribute__ ((__always_inline__))
  void wdt_interrupt_reset_enable (const uint8_t value)
  {
      if (_SFR_IO_REG_P (_WD_CONTROL_REG))
      {
          __asm__ __volatile__ (
                  "in __tmp_reg__,__SREG__"   "\n\t"
                  "cli"                       "\n\t"
                  "wdr"                       "\n\t"
                  "out %0, %1"                "\n\t"
                  "out __SREG__,__tmp_reg__"  "\n\t"
                  "out %0, %2"                "\n\t"
                  : /* no outputs */
                  : "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)),
                  "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))),
                  "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) |
                          _BV(WDIF) | _BV(WDIE) | _BV(WDE) | (value & 0x07)) )
                  : "r0"
          );
      }
      else
      {
          __asm__ __volatile__ (
                  "in __tmp_reg__,__SREG__"   "\n\t"
                  "cli"                       "\n\t"
                  "wdr"                       "\n\t"
                  "sts %0, %1"                "\n\t"
                  "out __SREG__,__tmp_reg__"  "\n\t"
                  "sts %0, %2"                "\n\t"
                  : /* no outputs */
                  : "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)),
                  "r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))),
                  "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) |
                          _BV(WDIF) | _BV(WDIE) | _BV(WDE) | (value & 0x07)) )
                  : "r0"
          );
      }
  }
  
  /*-----------------------------------------------------------*/
  
  #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 )
  	StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
  #else
  	StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
  #endif
  
  /* Used by heap_5.c. */
  typedef struct HeapRegion
  {
  	uint8_t *pucStartAddress;
  	size_t xSizeInBytes;
  } HeapRegion_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;
  
  
  /*
   * 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;
  size_t xPortGetMinimumEverFreeHeapSize( 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.
   */
  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, configSTACK_DEPTH_TYPE ulStackDepth ) PRIVILEGED_FUNCTION;
  #endif
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* PORTABLE_H */
  
  