Advertisement
abdullahkahraman

Microchip Forums: RTOS implementation

Jun 12th, 2012
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.01 KB | None | 0 0
  1. /*
  2.  * File:   main.c
  3.  * Author: abdullah
  4.  *
  5.  * Created on 10 Haziran 2012 Pazar, 14:43
  6.  */
  7. #include <xc.h> // Include the header file needed by the compiler
  8. __CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CP_OFF & IOSCFS_4MHZ & BOREN_ON);
  9. /*
  10.  * INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN
  11.  * WDT disabled and can be enabled by SWDTEN bit of the WDTCON register
  12.  * PWRT enabled
  13.  * MCLR pin function is digital input, MCLR internally tied to VDD
  14.  * Program memory code protection is disabled
  15.  * Internal Oscillator Frequency Select bit : 4MHz
  16.  * Brown-out Reset Selection bits : BOR enabled
  17.  */
  18.  
  19. /*
  20.  * OS_initializeTask(); definition will copy the PCLATH register to the task's PCLATH  , which is held in taskx.pch
  21.  * This will help us hold the PCLATH at the point we yield.
  22.  * After that, it will copy the (PCL register + 8) to current task's PCL which is held in taskx.pcl.
  23.  * 8 is added to PCL because this line plus the "return" takes 8 instructions.
  24.  * We will set the PCL after these instructions, because
  25.  * we want to be in the point after OS_initializeTask when we come back to this task.
  26.  * After all, the function returns without doing anything more. This will initialize the task's PCLATH and PCL.
  27.  */
  28. #define numberOfTasks 2
  29. #define OS_initializeTask(x); tasks[x].pch = PCLATH;\
  30.                              tasks[x].pcl = PCL + 6;\
  31.                              asm("return");
  32.  
  33. /*
  34.  * OS_yield(); definition will do the same stuff that OS_initializeTask(); definition do, however
  35.  * it will return to "taskswitcher" label, which is the start of OS_runTasks(); definition.
  36.  */
  37.  
  38. #define OS_yield(x);         tasks[x].pch = PCLATH;\
  39.                              tasks[x].pcl = PCL + 6;\
  40.                              asm("goto _taskswitcher");
  41.  
  42. /*
  43.  * OS_runTasks(); definition will set the "taskswitcher" label. After that it will change the
  44.  * current task to the next task, by pointing the next item in the linked list of "TCB"s.
  45.  * After that, it will change the PCLATH and PCL registers with the current task's. That will
  46.  * make the program continue the next task from the place it left last time.
  47.  */
  48.  
  49. #define OS_runTasks();       asm("_taskswitcher");\
  50.                              ++currentTask;\
  51. if (currentTask > (numberOfTasks - 1))currentTask = 0;  \
  52.                              PCLATH = tasks[currentTask].pch;  \
  53.                              PCL = tasks[currentTask].pcl;
  54.  
  55. typedef struct _TCB // Create task control block and type define it as "TCB"
  56. {
  57.     unsigned char pch; // pch register will hold the PCLATH value of the task after the last yield.
  58.     unsigned char pcl; // pcl register will hold the PCL value of the task after the last yield.
  59. } TCB;
  60.  
  61. unsigned char currentTask = 0; // This TCB pointer will point to the current task's TCB.
  62.  
  63. TCB tasks[2]; // Define the TCB for task1 and task2.
  64.  
  65. void fTask1(void); // Prototype the function for task1.
  66. void fTask2(void); // Prototype the function for task2.
  67.  
  68. void main(void) @ 0x0099
  69. {
  70.     TRISA = 0; // Set all of the PORTA pins as outputs.
  71.     TRISC = 0; // Set all of the PORTC pins as outputs.
  72.     ANSEL = 0; // Set all of the analog input pins as digital i/o.
  73.     PORTA = 0; // Clear PORTA bits.
  74.     PORTC = 0; // Clear PORTC bits.
  75.  
  76.     /*
  77.      * Before running the tasks, we should initialize the PCL and PCLATH registers for the tasks.
  78.      * In order to do this, we could have looked up the absolute address with a function pointer.
  79.      * However, it seems like this is not possible with this compiler (or all the x16 PICs?)
  80.      * What this compiler creates is a table of the addresses of the functions and a bunch of GOTOs.
  81.      * This will not let us get the absolute address of the function by doing something like:
  82.      * "currentTask->pcl=low(functionpointer);"
  83.      */
  84.     fTask1(); // Run task1 so that we get the address of it and initialize pch and pcl registers.
  85.     currentTask = currentTask++; // Point the currentTask pointer to the next pointer which
  86.     fTask2(); // is task2. And run task2 so that we get the correct pch and pcl.
  87.  
  88.     //OS_runTasks(); // Task switcher. See the comments in the definitions above.
  89.     asm("_taskswitcher");
  90.     ++currentTask;
  91.     if (currentTask == 2)currentTask = 0;
  92.     PCLATH = tasks[currentTask].pch;
  93.     PCL = tasks[currentTask].pcl;
  94. }
  95.  
  96. void fTask1(void)
  97. {
  98.     //OS_initializeTask(0); // Initialize the task
  99.     tasks[0].pch = PCLATH;
  100.     tasks[0].pcl = PCL + 6;
  101.     asm("return");
  102.  
  103.     while (1)
  104.     {
  105.         PORTA = 0xAA; // Toggle PORTA.0
  106.         //OS_yield(0); // Yield
  107.         tasks[0].pch = PCLATH;
  108.         tasks[0].pcl = PCL + 6;
  109.         asm("goto _taskswitcher");
  110.  
  111.         PORTA = 0x55; // Toggle PORTA.0
  112.     }
  113. }
  114.  
  115. void fTask2(void)
  116. {
  117.     //OS_initializeTask(1); // Initialize the task
  118.     tasks[1].pch = PCLATH;
  119.     tasks[1].pcl = PCL + 6;
  120.     asm("return");
  121.  
  122.     while (1)
  123.     {
  124.         PORTC = 0xAA; // Toggle PORTA.1
  125.         OS_yield(1); // Yield
  126.         PORTC = 0x55; // Toggle PORTA.1
  127.     }
  128. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement