Skip to main content
replaced http://electronics.stackexchange.com/ with https://electronics.stackexchange.com/
Source Link

Edit: Code is changed. Please refer to older versionsolder versions of this post for the previous code.

Edit: Code is changed. Please refer to older versions of this post for the previous code.

Edit: Code is changed. Please refer to older versions of this post for the previous code.

added older versions link
Source Link

Below is the way to do it with in-line assembly using XC8 compiler, and it works now! However, I need to add develop more code for saving and restoring the STATUSregister, which seems a little trickier than it is for a normal register.

Posted on PasteBin for better viewing:Edit: Code is changed. Please refer to main.colder versions of this post for the previous code.

/* * File: main.c * Author: abdullah * * Created on 10 Haziran 2012 Pazar, 14:43 */ #include <xc.h> // Include the header file needed by the compiler #include "RTOS.h" // Include the header for co-operative RTOS. __CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CP_OFF & IOSCFS_4MHZ & BOREN_ON); unsigned char OS_currentTask; // This register holds the current task's place in the array OS_tasks unsigned char OS_tasks[4]; // This array holds PCL and PCLATH for tasks. This array will have.. // .. (number of tasks)*2 elements, since every task occupies 2 places. void fTask1(void); // Prototype the function for task1. void fTask2(void); // Prototype the function for task2. void main(void) @ 0x0001 { TRISA = 0; // Set all of the PORTA pins as outputs. TRISC = 0; // Set all of the PORTC pins as outputs. ANSEL = 0; // Set all of the analog input pins as digital i/o. PORTA = 0; // Clear PORTA bits. PORTC = 0; // Clear PORTC bits. OS_currentTask = 0; // Current task is first task. fTask1(); // Call task to initialize it. OS_currentTask += 2; // Increment task pointer by two since every task occupies 2 places in the array. fTask2(); // Call task to initialize it. OS_runTasks(4); // Run the tasks in order. The argument of this macro takes is: (Number of tasks) * 2 } void fTask1(void) { OS_initializeTask(); // Initialize the task so that task runner can get its ingredients. while (1) { PORTC = 0xAA; OS_yield(); // Yield CPU to other tasks. PORTC = 0x55; OS_yield(); // Yield CPU to other tasks. } } void fTask2(void) { OS_initializeTask(); // Initialize the task so that task runner can get its ingredients. while (1) { PORTC = 0xFF; OS_yield(); // Yield CPU to other tasks. PORTC = 0x00; OS_yield(); // Yield CPU to other tasks. } } 
/* * File: RTOS.h * Author: abdullah * * Created on 21 Haziran 2012 Perşembe, 10:51 */ #ifndef RTOS_H #define RTOS_H #define OS_yieldasm("OS_yield MACRO"); asm("local {\OS_tmp"); asm("movlw _OS_tasks ; Store the address of tasks, which is the start address of our task 'array'."); \ asm("addwf _OS_currentTask, w ; Add current task's index to the start address."); \ asm("movwf fsr ; We have the index of current task in W. Copy it to FSR"); \ asm("movf pclath, w"movlw high(OS_tmp) ; Copy PCLATH register's contents for the label, to W register."); \ asm("movwf indf ; Copy W to current task's first item. We now store PCLATH of the current state of the task."); \ asm("incf fsr, f ; Increment index, so that we will point to the next item of current task."); \ asm("movlw low($+3OS_tmp) ; Copy PCL ;of Copythe PCL+3label to W register. This will let us save the PCL of the current state of the task."); \ asm("movwf indf ; Copy W to task's next item. With that, we will initialize the current task."); \ asm("goto _OS_taskswitcherOS_taskswitcher"); asm("OS_tmp: ; Yield the CPU to the awaiting task by going ; We will use this label to taskgather switcherthe PC of the return point."); asm("ENDM"); \ } #define OS_initializeTaskOS_yield(); {\asm("OS_yield");  asm("OS_initializeTask MACRO"); asm("local OS_tmp"); asm("movlw _OS_tasks ; Store the address of tasks, which is the start address of our task 'array'."); \ asm("addwf _OS_currentTask, w ; Add current task's index to the start address."); \ asm("movwf fsr ; We have the index of current task in W. Copy it to FSR"); \ asm("movf pclath, w "movlw high(OS_tmp) ; Copy PCLATH register's contents for the label, to W register."); \ asm("movwf indf ; Copy W to current task's first item. We now store PCLATH."); \ asm("incf fsr,f ; Increment index, so that we will point to the next item of current task."); \ asm("movlw low($+3OS_tmp)  ; Copy PCL ;of Copythe PCL+3label to W register. This will let us save the PCL of the startcurrent state of the task."); \ asm("movwf indf ; Copy W to task's next item. With that, we will initialize the current task."); \ asm("return ; We have gathered our initialazation information. Return back to main."); \ }asm("OS_tmp ; We will use this label to gather the PC of the return point."); asm("ENDM");  #define OS_runTasksOS_initializeTask(numberOfTasks); {\asm("OS_initializeTask");  asm("_OS_taskswitcher""OS_runTasks MACRO numberOfTasks"); asm("global \OS_taskswitcher"); asm("OS_taskswitcher:"); asm("CLRWDT"); asm("movlw 0x02 ; W = 2"); \ asm("addwf _OS_currentTask, f ; Add 2 to currentTask, store it in currentTask."); \ asm("movlw "#numberOfTasks"numberOfTasks  ; W = numOfTasks"); \ asm("subwf _OS_currentTask, w ; w= f - w"); \ asm("btfsc status, 0 ; If currentTask >= numOfTasks"); \ asm("clrf _OS_currentTask ; Clear currentTask"); \ asm("movlw _OS_tasks ; Store the address of tasks, which is the start address of our task 'array'."); \ asm("addwf _OS_currentTask, w ; Add current task's index to the start address."); \ asm("movwf fsr ; We have the index of current task in W. Copy it to FSR"); \ asm("movf indf, w ; Copy the contents of current task's first item to W"); \ asm("movwf pclath ; Copy W to PCLATH. As a result, current task's PCLATH will be in PCLATH register."); \ asm("incf fsr, f ; Increment index, so that we will point to the next item of current task."); \ asm("movf indf, w ; Copy the contents of current task's second item to W."); \ asm("movwf pcl ; Copy W to PCL. Finally, current task's PCL will be in PCL register."); \ }asm("ENDM"); #define OS_runTasks(numberOfTasks); asm("OS_runTasks "#numberOfTasks); #endif /* RTOS_H */ 

Below is the way to do it with in-line assembly using XC8 compiler.

Posted on PasteBin for better viewing: main.c

/* * File: main.c * Author: abdullah * * Created on 10 Haziran 2012 Pazar, 14:43 */ #include <xc.h> // Include the header file needed by the compiler #include "RTOS.h" // Include the header for co-operative RTOS. __CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CP_OFF & IOSCFS_4MHZ & BOREN_ON); unsigned char OS_currentTask; // This register holds the current task's place in the array OS_tasks unsigned char OS_tasks[4]; // This array holds PCL and PCLATH for tasks. This array will have.. // .. (number of tasks)*2 elements, since every task occupies 2 places. void fTask1(void); // Prototype the function for task1. void fTask2(void); // Prototype the function for task2. void main(void) @ 0x0001 { TRISA = 0; // Set all of the PORTA pins as outputs. TRISC = 0; // Set all of the PORTC pins as outputs. ANSEL = 0; // Set all of the analog input pins as digital i/o. PORTA = 0; // Clear PORTA bits. PORTC = 0; // Clear PORTC bits. OS_currentTask = 0; // Current task is first task. fTask1(); // Call task to initialize it. OS_currentTask += 2; // Increment task pointer by two since every task occupies 2 places in the array. fTask2(); // Call task to initialize it. OS_runTasks(4); // Run the tasks in order. The argument of this macro takes is: (Number of tasks) * 2 } void fTask1(void) { OS_initializeTask(); // Initialize the task so that task runner can get its ingredients. while (1) { PORTC = 0xAA; OS_yield(); // Yield CPU to other tasks. PORTC = 0x55; OS_yield(); // Yield CPU to other tasks. } } void fTask2(void) { OS_initializeTask(); // Initialize the task so that task runner can get its ingredients. while (1) { PORTC = 0xFF; OS_yield(); // Yield CPU to other tasks. PORTC = 0x00; OS_yield(); // Yield CPU to other tasks. } } 
/* * File: RTOS.h * Author: abdullah * * Created on 21 Haziran 2012 Perşembe, 10:51 */ #ifndef RTOS_H #define RTOS_H #define OS_yield(); {\ asm("movlw _OS_tasks ; Store the address of tasks, which is the start address of our task 'array'."); \ asm("addwf _OS_currentTask, w ; Add current task's index to the start address."); \ asm("movwf fsr ; We have the index of current task in W. Copy it to FSR"); \ asm("movf pclath, w ; Copy PCLATH register's contents to W register."); \ asm("movwf indf ; Copy W to current task's first item. We now store PCLATH of the current state of the task."); \ asm("incf fsr, f ; Increment index, so that we will point to the next item of current task."); \ asm("movlw low($+3) ; Copy PCL+3 to W register. This will let us save the PCL of the current state of the task."); \ asm("movwf indf ; Copy W to task's next item. With that, we will initialize the current task."); \ asm("goto _OS_taskswitcher ; Yield the CPU to the awaiting task by going to task switcher."); \ } #define OS_initializeTask(); {\ asm("movlw _OS_tasks ; Store the address of tasks, which is the start address of our task 'array'."); \ asm("addwf _OS_currentTask, w ; Add current task's index to the start address."); \ asm("movwf fsr ; We have the index of current task in W. Copy it to FSR"); \ asm("movf pclath, w  ; Copy PCLATH register's contents to W register."); \ asm("movwf indf ; Copy W to current task's first item. We now store PCLATH."); \ asm("incf fsr,f ; Increment index, so that we will point to the next item of current task."); \ asm("movlw low($+3)  ; Copy PCL+3 to W register. This will let us save the PCL of the start of the task."); \ asm("movwf indf ; Copy W to task's next item. With that, we will initialize the current task."); \ asm("return ; We have gathered our initialazation information. Return back to main."); \ } #define OS_runTasks(numberOfTasks); {\ asm("_OS_taskswitcher"); \ asm("movlw 0x02 ; W = 2"); \ asm("addwf _OS_currentTask, f ; Add 2 to currentTask, store it in currentTask."); \ asm("movlw "#numberOfTasks" ; W = numOfTasks"); \ asm("subwf _OS_currentTask, w ; w= f - w"); \ asm("btfsc status, 0 ; If currentTask >= numOfTasks"); \ asm("clrf _OS_currentTask ; Clear currentTask"); \ asm("movlw _OS_tasks ; Store the address of tasks, which is the start address of our task 'array'."); \ asm("addwf _OS_currentTask, w ; Add current task's index to the start address."); \ asm("movwf fsr ; We have the index of current task in W. Copy it to FSR"); \ asm("movf indf, w ; Copy the contents of current task's first item to W"); \ asm("movwf pclath ; Copy W to PCLATH. As a result, current task's PCLATH will be in PCLATH register."); \ asm("incf fsr, f ; Increment index, so that we will point to the next item of current task."); \ asm("movf indf, w ; Copy the contents of current task's second item to W."); \ asm("movwf pcl ; Copy W to PCL. Finally, current task's PCL will be in PCL register."); \ } #endif /* RTOS_H */ 

Below is the way to do it with in-line assembly using XC8 compiler, and it works now! However, I need to add develop more code for saving and restoring the STATUSregister, which seems a little trickier than it is for a normal register.

Edit: Code is changed. Please refer to older versions of this post for the previous code.

/* * File: main.c * Author: abdullah * * Created on 10 Haziran 2012 Pazar, 14:43 */ #include <xc.h> // Include the header file needed by the compiler #include "RTOS.h" // Include the header for co-operative RTOS. __CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CP_OFF & IOSCFS_4MHZ & BOREN_ON); unsigned char OS_currentTask; // This register holds the current task's place in the array OS_tasks unsigned char OS_tasks[4]; // This array holds PCL and PCLATH for tasks. This array will have.. // .. (number of tasks)*2 elements, since every task occupies 2 places. void fTask1(void); // Prototype the function for task1. void fTask2(void); // Prototype the function for task2. void main(void) { TRISA = 0; // Set all of the PORTA pins as outputs. TRISC = 0; // Set all of the PORTC pins as outputs. ANSEL = 0; // Set all of the analog input pins as digital i/o. PORTA = 0; // Clear PORTA bits. PORTC = 0; // Clear PORTC bits. OS_currentTask = 0; // Current task is first task. fTask1(); // Call task to initialize it. OS_currentTask += 2; // Increment task pointer by two since every task occupies 2 places in the array. fTask2(); // Call task to initialize it. OS_runTasks(4); // Run the tasks in order. The argument of this macro takes is: (Number of tasks) * 2 } void fTask1(void) { OS_initializeTask(); // Initialize the task so that task runner can get its ingredients. while (1) { PORTC = 0xAA; OS_yield(); // Yield CPU to other tasks. PORTC = 0x55; OS_yield(); // Yield CPU to other tasks. } } void fTask2(void) { OS_initializeTask(); // Initialize the task so that task runner can get its ingredients. while (1) { PORTC = 0xFF; OS_yield(); // Yield CPU to other tasks. PORTC = 0x00; OS_yield(); // Yield CPU to other tasks. } } 
/* * File: RTOS.h * Author: abdullah * * Created on 21 Haziran 2012 Perşembe, 10:51 */ #ifndef RTOS_H #define RTOS_H asm("OS_yield MACRO"); asm("local OS_tmp"); asm("movlw _OS_tasks ; Store the address of tasks, which is the start address of our task 'array'."); asm("addwf _OS_currentTask, w ; Add current task's index to the start address."); asm("movwf fsr ; We have the index of current task in W. Copy it to FSR"); asm("movlw high(OS_tmp) ; Copy PCLATH register's contents for the label, to W register."); asm("movwf indf ; Copy W to current task's first item. We now store PCLATH of the current state of the task."); asm("incf fsr, f ; Increment index, so that we will point to the next item of current task."); asm("movlw low(OS_tmp) ; Copy PCL of the label to W register. This will let us save the PCL of the current state of the task."); asm("movwf indf ; Copy W to task's next item. With that, we will initialize the current task."); asm("goto OS_taskswitcher"); asm("OS_tmp:  ; We will use this label to gather the PC of the return point."); asm("ENDM"); #define OS_yield(); asm("OS_yield");  asm("OS_initializeTask MACRO"); asm("local OS_tmp"); asm("movlw _OS_tasks ; Store the address of tasks, which is the start address of our task 'array'."); asm("addwf _OS_currentTask, w ; Add current task's index to the start address."); asm("movwf fsr ; We have the index of current task in W. Copy it to FSR"); asm("movlw high(OS_tmp) ; Copy PCLATH register's contents for the label, to W register."); asm("movwf indf ; Copy W to current task's first item. We now store PCLATH."); asm("incf fsr,f ; Increment index, so that we will point to the next item of current task."); asm("movlw low(OS_tmp) ; Copy PCL of the label to W register. This will let us save the PCL of the current state of the task."); asm("movwf indf ; Copy W to task's next item. With that, we will initialize the current task."); asm("return ; We have gathered our initialazation information. Return back to main."); asm("OS_tmp ; We will use this label to gather the PC of the return point."); asm("ENDM");  #define OS_initializeTask(); asm("OS_initializeTask");  asm("OS_runTasks MACRO numberOfTasks"); asm("global OS_taskswitcher"); asm("OS_taskswitcher:"); asm("CLRWDT"); asm("movlw 0x02 ; W = 2"); asm("addwf _OS_currentTask, f ; Add 2 to currentTask, store it in currentTask."); asm("movlw numberOfTasks  ; W = numOfTasks"); asm("subwf _OS_currentTask, w ; w= f - w"); asm("btfsc status, 0 ; If currentTask >= numOfTasks"); asm("clrf _OS_currentTask ; Clear currentTask"); asm("movlw _OS_tasks ; Store the address of tasks, which is the start address of our task 'array'."); asm("addwf _OS_currentTask, w ; Add current task's index to the start address."); asm("movwf fsr ; We have the index of current task in W. Copy it to FSR"); asm("movf indf, w ; Copy the contents of current task's first item to W"); asm("movwf pclath ; Copy W to PCLATH. As a result, current task's PCLATH will be in PCLATH register."); asm("incf fsr, f ; Increment index, so that we will point to the next item of current task."); asm("movf indf, w ; Copy the contents of current task's second item to W."); asm("movwf pcl ; Copy W to PCL. Finally, current task's PCL will be in PCL register."); asm("ENDM"); #define OS_runTasks(numberOfTasks); asm("OS_runTasks "#numberOfTasks); #endif /* RTOS_H */ 
added PasteBin link
Source Link

HereBelow is the way to do it with in-line assembly using XC8 compiler.

Posted on PasteBin for better viewing: main.c

Here is the way to do it with in-line assembly using XC8 compiler.

Below is the way to do it with in-line assembly using XC8 compiler.

Posted on PasteBin for better viewing: main.c

Source Link
Loading