/*  FreeRTOS for the PIC 18F8520 in the Innovation First VEX Micro Controller                           */
/*                                                                                                      */
/*  Copyright (c) 2008 by Paul A. Murphy                                                                */
/*                                                                                                      */
/*  The author hereby grants permission to use, copy, modify, distribute, and license this              */
/*  documentation for any purpose, provided that existing copyright notices are retained in all copies  */
/*  and that this notice and the following disclaimer are included verbatim in any distributions.  No   */
/*  written agreement, license, or royalty fee is required for any of the authorized uses.              */
/*  Modifications to this documentation may be copyrighted by their authors and need not follow the     */
/*  licensing terms described here, provided that the new terms are clearly indicated on the first page */
/*  of each section where they apply.  All unmodified material remains subject to the original terms.   */
/*                                                                                                      */
/*  IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, */
/*  INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS DOCUMENTATION, OR ANY           */
/*  DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.       */
/*                                                                                                      */
/*  THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,   */
/*  THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.   */
/*  THIS DOCUMENTATION IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO        */
/*  OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.                */                                                                                                   */
/*                                                                                                      */
/*                                                                                                      */
/*                                                                                                      */
/*  Introduction                                                                                        */
/*                                                                                                      */
/*  This port of FreeRTOS was developed for robotic systems that are built from the prototyping kits    */
/*  known collectively as the VEX Robotics Design System.                                               */
/*                                                                                                      */
/*  These kits include various motors, sensors, and mechanical components; as well as a control module  */
/*  known as the VEX Micro Controller.  These components are made by Innovation First Incorporated, and */
/*  can be purchased at " http://www.vexrobotics.com " as of 23 November 2008.                          */
/*                                                                                                      */
/*  The VEX Micro Controller is the target platform for this port of FreeRTOS.  This unit contains two  */
/*  PIC 18F8520 microcontrollers, which are respectively called the "User" processor and the "Master"   */
/*  processor.  The User processor executes code that is loaded into it by the user, including this     */
/*  port of FreeRTOS and the demonstration code that accompanies it.  In the remainder of this          */
/*  discussion, the VEX Micro Controller will be referred to simply as the "controller".  The PIC       */
/*  18F8520 microcontroller chips themselves are manufactured by Microchip Technologies, Incorporated.  */
/*                                                                                                      */
/*  The purpose of the Master processor is to provide a master clock tick for the controller and to     */
/*  support various functions that are executed in the User processor.  For example, the Master         */
/*  processor accepts data from the VEX radio-control receiver that is connected to the controller.     */
/*  Every 18.5 milliseconds, these data are sent to the User by way of a synchronous serial port        */
/*  interface (SPI) using a proprietary protocol.  In the User processor, user-compiled code is then    */
/*  called upon to read these data and to subsequently drive the MOTORS ports on the controller.        */
/*                                                                                                      */
/*  It is assumed that the user of this port will have a working familiarity with the controller and    */
/*  the VEX software that is used to support its operation.  An elementary familiarity with the setting */
/*  up of electronic hardware in general will be helpful as well.  This port of FreeRTOS was developed  */
/*  using a programming environment called "Eclipse", although MPLAB and other comparable tools should  */
/*  be fine.  Eclipse is an "open-source" product that served this author's needs quite well in most    */
/*  respects.  A major shortcoming was its lack of debugging facilities for the PIC 18F8520; debugging  */
/*  was performed using various hardware and software techniques developed by the author as needed.     */
/*                                                                                                      */
/*                                                                                                      */
/*  Demonstration                                                                                       */
/*                                                                                                      */
/*  The handling of two user-generated tasks is demonstrated, in which the first task reads an analog   */
/*  signal and the second task sends a modified version of this signal to a motor.                      */
/*                                                                                                      */
/*  The creation and handling of the FreeRTOS queues is also demonstrated, as queues are used to handle */
/*  the serial communications.                                                                          */
/*                                                                                                      */
/*  In addition to the analog signal, the first task also reads a signal from a VEX radio-control       */
/*  receiver.  The first task also reads the controller's serial port.  In addition to sending a        */
/*  command to the motor, the second task sends that command out over the controller's serial port.     */
/*                                                                                                      */
/*  The demonstration requires that a VEX radio-control receiver be connected to the controller's Rx1   */
/*  jack (Rx2 also works), and that it be receiving signals from a VEX radio-control transmitter.       */
/*  These units are included with a controller in each VEX Robotics Design System kit, and they are     */
/*  also available  separately.  Although it may be possible to create a comparable demonstration that  */
/*  will run without the radio-control link, this option was not explored due to time constraints.      */
/*                                                                                                      */
/*  For the analog signal, a potentiometer with a resistance of the order of 10 kilohms is needed.      */
/*  This is connected to Port 1 in the "ANALOG/DIGITAL" group of ports on the controller.  The voltage  */
/*  on its wiper arm is read by the command "Get_Analog_Value (0x00)" in the first task.  The voltage   */
/*  on this or any of the other inputs should be kept to between 0 and + 5 volts.                       */
/*                                                                                                      */
/*  For the serial communications, the "RX" and "TX" ports, which are also in the "ANALOG/DIGITAL"      */
/*  group of ports, are used.  For RS-232 communications with a computer, a level shifting adapter      */
/*  is needed.                                                                                          */
/*                                                                                                      */
/*  For the output, a VEX motor was used, although any comparable hobby motor can be used.  This        */
/*  demonstration expects that it be connected to Port 1 in the "MOTORS" group of ports.                */
/*                                                                                                      */
/*  These connections are shown in "system_for_demo_of_freertos_in_vex_controller.pdf".  The            */
/*  controller ports themselves are shown in detail in "vex_controller_interfaces.pdf".  These files    */
/*  are included with this port.                                                                        */
/*                                                                                                      */
/*  Connection to the controller's ports is done using parts that closely resemble those used in hobby  */
/*  radio-control systems, although wires that are pushed into the contact openings are sufficient for  */
/*  a demonstration on a bench if care is used.  This author prefers not to recommend specific          */
/*  connector parts, as the connectors used by VEX for their motors and other peripherals appear to use */
/*  a configuration that was a source of confusion with parts vendors, despite the best of intentions.  */
/*                                                                                                      */
/*  The connection jacks on the end of the controller have names that may be confusing.  The jack       */
/*  labeled "SERIAL" is a serial connection; however, it is for the Programming Module and is not       */
/*  intended for elementary user prototyping.  Similarly, the jacks labeled "Rx1" and "Rx2" are also    */
/*  serial links, which are for connection to the VEX radio-control receiver(s); they have no relation  */
/*  to the "RX" serial input port in the "ANALOG / DIGITAL" group of ports.                             */                                                                                                    */
/*                                                                                                      */
/*                                                                                                      */
/*  Compiling, Linking, Downloading, and Power                                                          */
/*                                                                                                      */
/*  Compilation and linking was performed using a subset of the Microchip MCC18 suite of Windows PC     */
/*  based tools, called the "MPLAB CBOT COMPILER", which was purchased from Innovation First in 2006.   */
/*  Downloading to the VEX controller was handled using what is called the VEX Programming Module, a    */
/*  cable-and-interface assembly that was included with the CBOT compiler.  As of 23 November 2008,     */
/*  comparable packages are at " http://www.vexrobotics.com/vex-robotics-programming-kit.shtml ".       */
/*                                                                                                      */
/*  Power to the controller was provided by a power supply set to 7.2 volts and connected to the        */
/*  controller using a Molex 35141-0201 connector with 35727-0201 pins.  Power to the radio-control     */
/*  transmitter was provided by a power source set to 9.6 volts, also using a Molex 35141-0201          */
/*  connector with 35727-0201 pins.  The 7.2 volt source should be capable of delivering at least two   */
/*  amperes, to easily allow driving at least one motor; the source for the transmitter should be       */
/*  capable of at least 250 milliamperes.  This approach was found to be more convenient than VEX       */
/*  batteries as it obviated the need for frequent re-charging.                                         */
/*                                                                                                      */
/*  The desktop PC software that was used for downloading is called "IFI_Loader.exe".  This is          */
/*  available free of charge at " http://www.vexrobotics.com/vex-robotics-downloads.shtml ".  As of     */
/*  23 November 2008, the direct link is " http://www.vexrobotics.com/docs/ifi_loader-4vex.zip ".  For  */
/*  downloading to the VEX controller, the INHX32 hex format is required.                               */
/*                                                                                                      */
/*                                                                                                      */
/*  Supporting Code                                                                                     */
/*                                                                                                      */
/*  The functioning of the controller, as it is intended to be used in the VEX Robotics Design System,  */
/*  requires that a library called "Vex_library.lib" be linked into user code.  In addition, certain    */
/*  library files in the MCC18 compiler suite are needed.  Vex_library.lib is available directly from   */
/*  Innovation First in several of their user-code packages.  These packages are available free of      */
/*  charge from Innovation First at " http://www.vexrobotics.com/vex-robotics-downloads.shtml ", as of  */
/*  23 November 2008.  For the convenience of the user, a copy of Vex_library.lib is included with this */
/*  port, with permission from Innovation First.                                                        */
/*                                                                                                      */
/*  The user-code packages from Innovation First include several files of source code that support the  */
/*  handling of the controller's input and output interfaces, as well as initialization of the User     */
/*  processor.  Also included is a file containing startup code for the User processor, a linker        */
/*  command file, and a header file that contains definitions for the 18F8520 registers.  (This last is */
/*  a slightly modified version of the definition file provided by Microchip.)                          */
/*                                                                                                      */
/*  These files, called "ifi_aliases.h", "ifi_default.h", "ifi_picdefs.h", "ifi_startup.c",             */
/*  "ifi_utilities.c", "ifi_utilities.h", "user_routines.c", "user_routines.h", and "18f8520user.lkr",  */
/*  are included in this port for the convenience of the user.  None of these files was found to have   */
/*  any kind of copyright declaration, and they can also be found at many locations online, such as     */
/*  information-sharing fora dedicated to the VEX products.  In this port, a Public Domain Dedication   */
/*  has been added to each of these files.  Per a verbal request from a representative of Innovation    */
/*  First, all references to "VEX" have been removed from these files, to emphasize that Innovation     */
/*  First cannot support them as they are used in the present context.                                  */
/*                                                                                                      */
/*  There may be unusual situations in which the code in the Master processor should be updated, as     */
/*  discussed in the VEX and other websites.  This code is available, as a file in the INHX32 hex       */
/*  format, at Innovation First at " http://www.vexrobotics.com/vex-robotics-downloads.shtml ", as of   */
/*  23 November 2008.  It is called "VEX Master Code ver 6" and its download unzips a file called       */
/*  "VEX_MASTER_V6.BIN", and it is downloaded to the Master processor using IFI_Loader.  Accompanying   */
/*  the download is a .pdf file that instructs the user in the particular steps needed.                 */
/*                                                                                                      */
/*                                                                                                      */
/*  Code Development Environment                                                                        */
/*                                                                                                      */
/*  This port of FreeRTOS was developed using the open-source Eclipse Platform, version 3.4.0.  The     */
/*  user interface to the MCC18 compiler and linker was provided by a dedicated "plugin" for the        */
/*  Eclipse environment, which was modified (slightly) for use in this project.  The name of the zipped */
/*  download file for this plugin is " org.eclipse.cdt.mcc18.toolchain_1.2.0.zip ", and it is available */
/*  at " http://www.chiefdelphi.com/forums/showthread.php?t=62127 " as of 23 November 2008.  This site  */
/*  is part of the forum known as "Chief Delphi".                                                       */
/*                                                                                                      */
/*  For this project, several minor modifications were made to this plugin.  These consist of changes   */
/*  to the name of the target controller to reflect its present use with the VEX controller, the        */
/*  addition of " ../" in the library search path so that the MCC18 suite can access Vex_library.lib,   */
/*  and the removal of items not needed in regards to programming the VEX controller.  This modified    */
/*  plugin has been included with this port, and a Public Domain Dedication has been added.  If any     */
/*  problems with this plugin are suspected, the user should download the original from the Chief       */
/*  Delphi website, install it, and use it as reference against which changes can be tested.            */
/*                                                                                                      */
/*                                                                                                      */
/*  FreeRTOS Operation: General                                                                         */
/*                                                                                                      */
/*  The functioning of FreeRTOS is based on the scheduling and switching of multiple tasks so that all  */
/*  tasks get to share the processor's resources over some interval of time and thus present the        */
/*  appearance of running concurrently.  The source file called "port.c" contains the low level code    */
/*  that supports this switching function.                                                              */
/*                                                                                                      */
/*  FreeRTOS uses a periodic interrupt to handle the switching of the tasks, which is referred to as    */
/*  the RTOS tick interrupt.  When this interrupt occurs, the task that has been running is suspended   */
/*  and the data that are associated with that task are saved so that it can be resumed later with no   */
/*  loss of integrity.  Then, the decision is made as to which task to run next by invoking the         */
/*  FreeRTOS vTaskSwitchContext function, and the data associated with that task are retrieved.         */
/*  Finally, upon the exit from the interrupt, this task is run.  FreeRTOS can also perform the task    */
/*  switch outside of the RTOS tick interrupt using the vPortYield function, which makes its own call   */
/*  to vTaskSwitchContext.  The process of saving the data associated with a given task is referred to  */
/*  as the task context save, and the corresponding retrieval is referred to as the task context        */
/*  restore.  These are handled by macros, which are respectively named "portSAVE_CONTEXT" and          */
/*  "portRESTORE_CONTEXT".  The interrupt service routine that handles the RTOS tick interrupt is       */
/*  called "prvTickISR".                                                                                */
/*                                                                                                      */
/*  The RTOS tick interrupt occurs when the count of a particular timer in the processor reaches a      */
/*  preset capture value.  In the generic FreeRTOS, this capture value is used to set the time rate at  */
/*  which the RTOS tick interrupt occurs.  This rate is defined in FreeRTOSConfig.h by the user setting */
/*  called "configTICK_RATE_HZ".                                                                        */
/*                                                                                                      */
/*  In the Vex controller application presented here, the RTOS tick interrupt is synchronized to the    */
/*  action of proprietary VEX Robotics code that is run in the Master processor and proprietary         */
/*  Vex_library.lib code that is run in the User processor.  The code in the Master forces the time     */
/*  rate of the RTOS tick interrupt to be 18.5 milliseconds or approximately 54 Hz.  It follows that    */
/*  the configTICK_RATE_HZ user setting in FreeRTOSConfig.h is ignored in this port.                    */
/*                                                                                                      */
/*  The interrupts used by FreeRTOS are low priority interrupts, and the handler for these is called    */
/*  "LowPriorityInterruptHandler".  When a low level interrupt takes place, this handler checks the     */
/*  interrupt flags and calls the appropriate interrupt service routine.  The high level interrupt is   */
/*  declared and handled by code in Vex_library.lib and is available to the user only indirectly.  The  */
/*  method by which this access is made is described later.                                             */
/*                                                                                                      */
/*  The code module that handles the starting up of the processor is located in the file called         */
/*  "ifi_startup.c".  This is based on Microchip's startup file called "c018iz.c", with some changes    */
/*  made by VEX.  The reset vector is set to 0x000800 in order to accommodate the bootloader mechanism  */
/*  that is used to load code into the processor.                                                       */
/*                                                                                                      */
/*                                                                                                      */
/*  FreeRTOS Operation: Task Creation, Context Saving, Context Switching, and Context Restoration       */
/*                                                                                                      */
/*  The tasks that are to be handled by FreeRTOS are written as functions.  A requirement of this       */
/*  function is that it have an endless for loop, so that once the task is started, it will continue to */
/*  run until it gets suspended in either an RTOS tick interrupt or a call to vPortYield.  Most of the  */
/*  task specific code that the user writes will likely be placed within this endless loop.  Because of */
/*  the continuous looping operation of the function, it cannot return anything; in other words, the    */
/*  function must be declared as returning void.                                                        */
/*                                                                                                      */
/*  The user instructs FreeRTOS to handle a given task by invoking the xTaskCreate function on that     */
/*  task.  This is typically done in the main() function.  After all user tasks are set up, FreeRTOS    */
/*  automatically sets up an idle task by making its own call to xTaskCreate.                           */
/*                                                                                                      */
/*  For each call to xTaskCreate, a task control block ("TCB") and a block for data are allocated in    */
/*  data memory.  This allocation is performed by the pvPortMalloc function in heap_1.c, which places   */
/*  them in the array called "ucHeap[ configTOTAL_HEAP_SIZE ]".  They are placed next to each other,    */
/*  with the start of the data block being one address higher than the last byte in the TCB.  Together, */
/*  the TCB and the data block form a package that completely defines the state of the task.            */
/*                                                                                                      */
/*  The TCB holds data on the relationship of the task to the other tasks, and it includes two members  */
/*  that are used for the accessing of its associated data block.  One is named "*pxStack", which is a  */
/*  pointer to the byte in the data block that is at the lowest address in the block, and the other is  */
/*  "*pxTopOfStack", which is used as an indexing pointer to the block.  In deference to the name       */
/*  "pxStack" and to minimize confusion, the data block is referred to as the "px stack".               */
/*                                                                                                      */
/*  When either the RTOS tick interrupt takes place or the vPortYield function is called, the task that */
/*  has been running is suspended, and the portSAVE_CONTEXT macro is then used to populate the px stack */
/*  with a copy of the values in those registers and memory locations that the task was or could have   */
/*  been using at the time.  The particular registers and memory locations that are saved are those     */
/*  that could be used by other code before the task is resumed.  The next task to be run is then       */
/*  chosen by invoking vTaskSwitchContext.  At the conclusion of the RTOS tick interrupt or vPortYield  */
/*  function call, the portRESTORE_CONTEXT macro is used to copy the values in the px stack, for the    */
/*  newly chosen task, back to those respective registers and memory locations.  Finally, when the RTOS */
/*  interrupt or vPortYield exits, this newly chosen task is run.                                       */
/*                                                                                                      */
/*  When a task is first set up to run, an initial set of values needs to be placed in the px stack for */
/*  that task.  This is handled by the pxPortInitializeStack function, which is called from             */
/*  xTaskCreate.  The pxPortInitializeStack function can be thought of as the first portCONTEXT_SAVE    */
/*  operation, with the difference being that some of the values being saved are initial, predetermined */
/*  values rather than actual register and data memory values.                                          */
/*                                                                                                      */
/*                                                                                                      */
/*  FreeRTOS Operation: Return Address Stack                                                            */
/*                                                                                                      */
/*  The PIC 18F8520 uses a block of registers called the "Return Address Stack" to facilitate the       */
/*  management of interrupts and functions.  This block is a separate group of registers, completely    */
/*  independent of program and data memory.  When an interrupt takes place or a function call is made,  */
/*  the value of the program counter is pushed (placed) on this stack.  Later, upon returning from that */
/*  interrupt or function, that value is popped (removed) and copied back to the program counter so     */
/*  that the interrupted function can resume.                                                           */
/*                                                                                                      */
/*  The Return Address Stack has multiple entries so that a function or interrupt can call a second     */
/*  function, and that second function can call a third function, and so on.  Later on, the returns can */
/*  be made in the reverse order.  This action is known as "nesting".                                   */
/*                                                                                                      */
/*  The pointer, or indexer, to the Return Address Stack is called "STKPTR".  When a new program        */
/*  counter value is pushed onto this stack, STKPTR is incremented, and when one is popped, STKPTR is   */
/*  decremented.  When STKPTR is zero, the Return Address Stack is considered empty, even though it     */
/*  appears to be pointing to a zero address entry.  Thus, STKPTR indicates the number of entries that  */
/*  are on the Return Address Stack at any given time.  As a point of detail, only the lowest 5 bits in */
/*  STKPTR are used for this number, which limits the number of entries to 31.  One of the higher bits  */
/*  is a STKPTR overflow flag and another is an underflow flag.  The code will not allow an underflow,  */
/*  and it is assumed that no attempt will be made to have more than 31 entries on the Return Address   */
/*  Stack at a time.                                                                                    */
/*                                                                                                      */
/*  The context switching mechanism of the operating system is based on the fact that the program       */
/*  counter values in the Return Address Stack can be changed inside the interrupting function, so that */
/*  when the return takes place, a function that is different from the one that was interrupted will be */
/*  run.  The process of switching a task begins when the RTOS tick interrupt, handled by prvTickISR,   */
/*  takes place, or when the vPortYield function is called.  First, the portSAVE_CONTEXT macro captures */
/*  the value of STKPTR so that it knows how many entries there are on the Return Address Stack.  Then, */
/*  it copies the contents of the Return Address Stack to the px stack.  Next, the captured value of    */
/*  STKPTR is saved to the px stack.                                                                    */
/*                                                                                                      */
/*  The vTaskContextSwitch function is then called, and it decides which task shall be run when         */
/*  prvTickISR or vPortYield concludes.  When this decision is made, vTaskSwitchContext selects the     */
/*  task control block (TCB) for the chosen task.  This becomes the "current" TCB.                      */
/*                                                                                                      */
/*  Next, the portRESTORE_CONTEXT macro populates the Return Address Stack with the corresponding       */
/*  values from the px stack that is associated with the current TCB.  It looks at the value of STKPTR  */
/*  that is saved in the px stack to know how many entries to restore.                                  */
/*                                                                                                      */
/*  Finally, when the return is made from prvTickISR or vPortYield, the entry that is on the top of the */
/*  Return Address Stack is popped and copied to the program counter, and the task associated with that */
/*  value is run.  Since the portRESTORE_CONTXT macro restores all entries in the Return Address Stack, */
/*  the nesting of functions or interrupts will be handled properly.                                    */
/*                                                                                                      */
/*                                                                                                      */
/*  FreeRTOS Operation: Task Communication                                                              */
/*                                                                                                      */
/*  A convenient means of exchanging data with a given task is provided by a pointer called "pvParam",  */
/*  which can be used to point to a data structure that the user has created.  While pvParam is itself  */
/*  a global variable, the particular value that it has at any given time depends on the task that is   */
/*  presently running.  When a given task is run, the value of pvParam that is associated with that     */
/*  task is retrieved from the px stack for that task, and when the task is suspended it is saved back. */
/*  For each task, the initial value of pvParam is set by the "pvParameters" parameter in the           */
/*  xTaskCreate function.  It should be emphasized that pvParam is a sixteen bit number and is intended */
/*  to be treated primarily as a pointer to data memory.                                                */
/*                                                                                                      */
/*  An example of the use of pvParam would be two tasks that share data using a common structure that   */
/*  has been type defined as "MYSTRUCT".  In main(), one would have " MYSTRUCT myStruct ", and in the   */
/*  call to xTaskCreate for each of the two tasks, one would have "&myStruct" for pvParameters.  Thus,  */
/*  in this situation, both tasks are getting the same value for pvParam, namely the address in data    */
/*  memory for the structure called "myStruct".                                                         */
/*                                                                                                      */
/*  To access myStruct, each task needs to have a pointer to MYSTRUCT and then have the actual value of */
/*  that pointer assigned to the value of pvParam.  This could be done by having the declaration        */
/*  "static MYSTRUCT * s1" and the assignment " s1 = ( MYSTRUCT * ) pvParam " in the first task, and    */
/*  "static MYSTRUCT * s2" and " s2 = ( MYSTRUCT * ) pvParam " in the second task.  With these, the     */
/*  first task could have "s1 -> memberX = somethingToPut" and the second task could get the value of   */
/*  somethingToPut through "somethingToGet = s2 -> memberX".  The "( MYSTRUCT * )" cast is necessary    */
/*  because pvParam was declared as a pointer to void by default.                                       */
/*                                                                                                      */
/*                                                                                                      */
/*  Integration of VEX Controller Interrupt Events with FreeRTOS Interrupt Events                       */
/*                                                                                                      */
/*  In the this port of FreeRTOS for the VEX controller, the RTOS tick interrupt is synchronized to the */
/*  action of proprietary VEX Robotics code that is run in the Master processor and proprietary         */
/*  Vex_library.lib code that is run in the User processor.                                             */
/*                                                                                                      */
/*  The RTOS tick interrupt cycle begins with the "INT0" hardware interrupt input on the User processor */
/*  being asserted by the Master processor.  This hardware interrupt is configured as a high priority   */
/*  interrupt by code in Vex_library.lib and is not available to the user.                              */
/*                                                                                                      */
/*  Shortly after the INT0 interrupt occurs, at approximately 25 microseconds, communication between    */
/*  the Master and User begins, using a proprietary protocol over a synchronous serial peripheral       */
/*  interface (SPI) connection between the two processors.  This communication ends at approximately    */
/*  590 microseconds.                                                                                   */
/*                                                                                                      */
/*  At 500 microseconds, code in Vex_libary.lib causes Timer 0 to be set to 0x7747 or 30535 decimal.    */
/*  This feature appears to have been provided by VEX so that users can synchronize their own code to   */
/*  the cycling of the VEX (INT0) interrupt, and it is used here for that purpose.                      */
/*                                                                                                      */
/*  At 600 microseconds, the "NEW_SPI_DATA" flag is set, at which point the user can read the updated   */
/*  data from the Master through the rx_data structure, as in other VEX robotics applications.          */
/*                                                                                                      */
/*  Shortly after 600 microseconds, the RTOS tick interrupt reads the data from the Master using a call */
/*  to "Getdata" (in Vex_library.lib), and outputs the appropriate data to the PWM output terminals     */
/*  using "Putdata".  The timing of when the RTOS tick interrupt actually fires is fine-tuned so that   */
/*  it will start looking for NEW_SPI_DATA just before it is expected to be set at 600 microseconds.    */
/*  In this way, a balance is made between starting the interrupt too early and having it wait too long */
/*  (in a loop) for NEW_SPI_DATA to be set, and having it start so late that the data are missed.       */
/*                                                                                                      */
/*  At 14500 microseconds, the Timer 0 counter overflows.  This event is used to fire a Timer 0         */
/*  Overflow interrupt.                                                                                 */
/*                                                                                                      */
/*  Here, the Timer 0 Overflow interrupt is used to set Timer 0 to zero and then start it.  This is the */
/*  timing link between the VEX robotics code and FreeRTOS.                                             */
/*                                                                                                      */
/*  At 17900 microseconds, Timer 1 reaches a set capture value, and the RTOS tick interrupt fires.      */
/*  This particular time was chosen so that the interrupt will be ready to read data from the Master    */
/*  just before the NEW_SPI_DATA flag is set in time for the next cycle, as discussed above.  This      */
/*  amount of advanced timing is needed especially to allow the portSAVE_CONTEXT macro in the interrupt */
/*  service routine to finish.  The Timer 1 capture value is set to 17000.  This corresponds to 3400    */
/*  microseconds, which means that when Timer 0 overflows at 14500 microseconds, the Timer 1 count will */
/*  reach 17000 at 17900 microseconds.                                                                  */
/*                                                                                                      */
/*  Note: If insufficient time is allowed, the result will be crashes.  If, for example, the RTOS tick  */
/*  interrupt is made to fire at 18300 microseconds, a system crash can often be produced by flipping   */
/*  one of the joysticks on the radio control transmitter.                                              */
/*                                                                                                      */
/*  At 18500 microseconds, the next INT0 hardware interrupt is set off by the Master processor, and the */
/*  cycle repeats.                                                                                      */
/*                                                                                                      */
/*  The timing of calls to the Getdata function is critical.  In order to prevent crashes, it was found */
/*  necessary to include the following instructions in the "xPortStartScheduler" function that is in    */
/*  this file: " while(statusflag.NEW_SPI_DATA != 1); Getdata(&rxdata); Putdata(&txdata);".  It was     */
/*  also necessory to comment out the same set of instructions in the VEX file, "user_routines.c",      */
/*  at lines 230, 231, and 232.  These changes begin just after the "else" that immediately follows     */
/*  " #ifdef _SIMULATOR statusflag.NEW_SPI_DATA = 1; " in that file.                                    */
/*                                                                                                      */
/*                                                                                                      */
/*  Memory Requirements                                                                                 */
/*                                                                                                      */
/*  The amount of data memory in the PIC 18F8520 presents challenges for any application that uses more */
/*  than a few tasks.  Consequently, great care is necessary in adjusting the linker command file,      */
/*  setting the heap size, the size of queues, and in how many bytes are set aside for each task's TCB  */
/*  and px stack.                                                                                       */
/*                                                                                                      */
/*  The number of bytes needed for each task control block (TCB) is 28 plus the number of characters    */
/*  set aside for the task designation name.  This number is set by configMAX_TASK_NAME_LEN in          */
/*  FreeRTOSConfig.h.                                                                                   */
/*                                                                                                      */
/*  In other words:                                                                                     */
/*                                                                                                      */
/*  Mtcb = 28 +  configMAX_TASK_NAME_LEN                                                                */
/*                                                                                                      */
/*  It should noted that the task designation name is not the same as the name of the function that     */
/*  constitutes the task.  For example, FreeRTOS automatically sets up an idle task called              */
/*  "prvIdleTask".  The task designation name given to this task is "IDLE".  Since "IDLE" has four      */
/*  characters, it follows that the user should set configMAX_TASK_NAME_LEN to at least 4 in order to   */
/*  avoid having to change "IDLE" to a shorter name.                                                    */
/*                                                                                                      */
/*  The number of bytes needed for each px stack is 21 plus the number of bytes set aside for the       */
/*  uc block, plus 3 times the number of entries one decides to allow on the Return Address Stack.      */
/*  The uc block is set aside nominally for temporary and math data that are used by code created by    */
/*  the compiler.  It starts at address zero in data memory and its size in bytes is given by           */
/*  "portCOMPILER_MANAGED_MEMORY_SIZE", which is defined in this file.                                  */
/*                                                                                                      */
/*  In other words:                                                                                     */
/*                                                                                                      */
/*  Mpx = 21 + portCOMPILER_MANAGED_MEMORY_SIZE + ( 3 * Nras )                                          */
/*                                                                                                      */
/*  where Nras is the number of entries on the return address stack.                                    */
/*                                                                                                      */
/*  It should be clear that the actual size of the px stack at any given time will be determined by the */
/*  the number of functions or interrupts whose progam count values are on the return address stack.    */
/*  While the maximum value would be difficult to determine (although the physical maximum is 31),      */
/*  FreeRTOS provides a means of judiciously choosing a working maximum value for the entire px stack,  */
/*  through the setting called "configMINIMAL_STACK_SIZE" in FreeFTOSConfig.h.                          */
/*                                                                                                      */
/*  This setting imposes the following:                                                                 */
/*                                                                                                      */
/*  21 + portCOMPILER_MANAGED_MEMORY_SIZE + ( 3 * Nras ) <= configMINIMAL_STACK_SIZE                    */
/*                                                                                                      */
/*  where Mqueues is the number of bytes set aside for whatever queues the user sets up                 */
/*                                                                                                      */
/*  and where Nras is always less than or equal to 31                                                   */
/*                                                                                                      */
/*  Given that configMINIMAL_STACK_SIZE sets the maximum size for the px stack, it follows that the     */
/*  amount of memory needed for all tasks (user tasks plus the idle task) is given by                   */
/*                                                                                                      */
/*  Mtotal = Mqueues + Ntasks * ( Mpx + configMINIMAL_STACK_SIZE )                                      */
/*                                                                                                      */
/*  where Ntasks is the number of user tasks plus 1 (for the idle task)                                 */
/*                                                                                                      */
/*  The amount of memory that is actually allocated for all of this is set by "configTOTAL_HEAP_SIZE"   */
/*  in FreeRTOSConfig.h.  Therefore, it is required that                                                */
/*                                                                                                      */
/*  configTOTAL_HEAP_SIZE >= Mtotal                                                                     */
/*                                                                                                      */
/*  For this demonstration, it was found that the following settings worked:                            */
/*                                                                                                      */
/*   configTOTAL_HEAP_SIZE            = 0x2F0                                                           */
/*                                                                                                      */
/*   configMINIMAL_STACK_SIZE         = 88 decimal                                                      */
/*                                                                                                      */
/*   portCOMPILER_MANAGED_MEMORY_SIZE = 50 decimal                                                      */
/*                                                                                                      */
/*   configMAX_TASK_NAME_LEN          = 10                                                              */
/*                                                                                                      */
/*                                                                                                      */
/*  In order to accommodate a heap size of 0x2F0, the linker file, 18f8520user.lkr,  was modified by    */
/*  commenting out sections and expanding the remainder to provide a stretch of at least 0x2F0 bytes.   */
/*                                                                                                      */
/*                                                                                                      */
/*  External User Interrupt                                                                             */
/*                                                                                                      */
/*  An external interrupt handling capability was included, consisting of an interrupt service routine  */
/*  that handles an a positive going edge on Pin 1 of the INTERRUPTS terminal.  This maps to the INT2   */
/*  pin on the User processor.  This interrupt can be used for the timing of pulses from a sensor as,   */
/*  for example, the VEX Range Finder sonar sensor or motor position encoders.                          */
/*                                                                                                      */
/*                                                                                                      */
/*  Limitations                                                                                         */
/*                                                                                                      */
/*  This port of FreeRTOS provides an elementary demonstration of the task switching function and the   */
/*  exchange of data between the tasks, and a rudimentary serial communications functionality, in       */
/*  conjunction with the radio control capabilities provided by VEX Robotics.  In the course of         */
/*  handling the serial communications, the functioning of queues is also demonstrated.                 */
/*                                                                                                      */
/*  The method by which tasks are scheduled in this port is known as "pre-emptive" scheduling.  The     */
/*  potential capability for handling cooprative scheduling is provided through the FreeRTOS "croutine" */
/*  module; however, this capability has not been attempted in this port as of this time.               */
/*                                                                                                      */
/*                                                                                                      */
/*  References                                                                                          */
/*                                                                                                      */
/*                                                                                                      */
/*  For the fundamentals of FreeRTOS:                                                                   */
/*                                                                                                      */
/*                                                                                                      */
/*  "RTOS Fundamentals"                                                                                 */
/*                                                                                                      */
/*      by Richard Barry                                                                                */
/*                                                                                                      */
/*      at " http://www.freertos.org/implementation/a00002.html " as of 23 November 2008                */
/*                                                                                                      */
/*      A .pdf of this was once available online, but that is apparently gone as of 08 October 2008     */
/*                                                                                                      */
/*                                                                                                      */
/*  "An Analysis and Description of the Inner Workings of the FreeRTOS Kernel                           */
/*                                                                                                      */
/*      by Rich Goyette                                                                                 */
/*                                                                                                      */
/*      Carleton University Department of Systems and Computer Engineering                              */
/*                                                                                                      */
/*      Document SYSC5701: Operating System Methods for Real-Time Applications                          */
/*                                                                                                      */
/*      at " http://richardgoyette.com/AcademicMain.html " as of 08 October 2008                        */
/*                                                                                                      */
/*                                                                                                      */
/*  For integrating one's code with VEX Robotics code:                                                  */
/*                                                                                                      */
/*      Background information on using the Timer 0 Overflow to "hook" into the VEX high priority       */
/*      interrupt is available                                                                          */
/*                                                                                                      */
/*      at " http://www.vexforum.com/showthread.php?t=30 ".                                             */
/*                                                                                                      */
/*                                                                                                      */
/*                                                                                                      */
/*  Additional Credits                                                                                  */
/*                                                                                                      */
/*     Eclipse "plugin" code module:                                                                    */
/*                                                                                                      */
/*     An inspection of the manifest file that accompanied the plugin that was obtained at              */
/*     "http://www.chiefdelphi.com/forums/showthread.php?t=62127" suggests that its originator          */
/*     was a Ben Cherian.  This file is assumed to be in the public domain, and this author             */
/*     attached a Public Domain Dedication to the copy included in this port.                           */
/*                                                                                                      */
