Advertisement
njama267

simple multitask preemption example

Feb 23rd, 2012
1,708
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.77 KB | None | 0 0
  1. /*
  2. primitive multitasking example for NXP's LPC1788 using IAR IDE
  3.  
  4. it contains only two tasks.
  5. Both tasks are only simple LED flashes in infinite loops.
  6. tasks are preemted always from one to the other
  7. it is done by SysTick interrupt handler which switches the context
  8.  
  9. 1/ interrupt is set up
  10. 2/ stack for task 2 created
  11. 3/ main enters task 1 so task 1 uses stack originally used by main program
  12.  
  13. 4/the tasks are regulary interupted and switched to the other one
  14.  
  15. */
  16. #include <nxp/iolpc1788.h>
  17.  
  18.  
  19. #define LED1 (1<<13)
  20. #define LED2 (1<<18)
  21.  
  22. #define STACK_SIZE 50
  23.  
  24. unsigned int *task1SP;
  25. unsigned int *task2SP;
  26. unsigned int current_task;
  27.  
  28. //stack for task 2
  29. unsigned int stack2 [STACK_SIZE];
  30.  
  31. /*change LED state at given IO pin*/
  32. void flash_LED(unsigned int led){
  33.  
  34.   //check pin state and change it
  35.   if(FIO1PIN & led){
  36.     FIO1CLR = led;
  37.   }
  38.   else{
  39.     FIO1SET = led;
  40.   }
  41.  
  42. }
  43.  
  44. /*demo task 1 flash LED1 */
  45. void task1(){
  46.  
  47.   while(1){
  48.    
  49.     //wait
  50.     for(int i=0;i<1000000;i++){
  51.     }
  52.    
  53.     flash_LED(LED1);
  54.  
  55.   }
  56. }
  57.  
  58. /*demo task 2 flash LED2 */
  59. void task2(){
  60.  
  61.   while(1){
  62.    
  63.     //wait
  64.     for(int i=0;i<1000000;i++){
  65.     }
  66.    
  67.     flash_LED(LED2);
  68.   }
  69. }
  70.  
  71. /*basic hw setup */
  72. void hw_init(){
  73.   // diodes at P1.13 a 15 as output
  74.   FIO1DIR = (1<<13|1<<18);
  75.  
  76.   //SYSTICK set up
  77.   //enable + interupt + cpu freq
  78.   STCTRL = (0x7);
  79.  
  80.   // value to count-down for systick reloadREG = (fcpu * T) - 1
  81.   STRELOAD = 0x1D31D;//0xFFFFFE 0xB67753 0x123F22 0x1D31D //max 1s 100ms 10ms
  82.  
  83. }
  84.  
  85. /*this function sets up a stack for task2. This is the most difficult part.
  86.  
  87. contents of the stack from the top adress
  88.  
  89. PSR - manual copy from stack of task 1 ;) (Program Status Register)
  90. PC - adress of task2 (Program Counter)
  91. LR - to be poped into LR (Link Register)
  92. R12 - to be poped into
  93. (R3 to R0) - to be poped into
  94. EXC_RETURN value - so processor knows that it returns from an interrupt
  95. 0x0 - from top to this point values are pushed autmatically when entering an
  96.       interrupt and poped back when leaving interrupt
  97.  
  98. (R4 to R11) - values to be pushed after context switch
  99.  
  100. */
  101. void create_task2(){
  102.  
  103.   //init whole array to zeros
  104.   for(int i=0;i<STACK_SIZE;i++){
  105.     stack2[i]=0;
  106.   }
  107.   //target task2SP to end of array stack2
  108.   //so it can grow downwards
  109.   task2SP = &stack2[STACK_SIZE-1];
  110.  
  111.   //set the stack formation all registers with correct values of PC LR etc
  112.   //comment out =0 (already set)
  113.   *task2SP = 0x81000000; //PSR ?
  114.   task2SP--;
  115.   *task2SP = (unsigned int) ((void *) task2); //PC task2()
  116.  
  117.   task2SP = task2SP-7;
  118.   *task2SP = 0xFFFFFFF9; //EXC_RETURN
  119.  
  120.   task2SP = task2SP-9;
  121.   //now task2SP targets to end of stack of task 2
  122.   //ready to be switched into
  123. }
  124.  
  125. void main(){
  126.  
  127.   //create stack formation for task 2
  128.   create_task2();
  129.  
  130.   //start with task 1
  131.   current_task = 1;
  132.  
  133.   //set up systick and other hw
  134.   hw_init();
  135.  
  136.   //and go into the first task
  137.   task1();
  138.  
  139. }
  140.  
  141.  
  142. /* set Stack Pointer */
  143. void set_sp(void *x){
  144.  
  145.   asm("MOV SP, R0");
  146.  
  147. }
  148. /* get Stack Pointer */
  149. void* get_sp(){
  150.  
  151.   asm("MOV R0, SP");
  152.  
  153.   //return value is in R0
  154. }
  155.  
  156. //SysTick_Handler function run by the interrupt
  157. //my simple scheduler
  158. //switch between task 1 and 2
  159. void SysTick_Handler(){
  160.  
  161.   //1 stack what is not automatically stacked
  162.   asm("PUSH {R4-R11}");
  163.  
  164.   switch (current_task){
  165.    
  166.   case 1:
  167.     //2 save current stack pointer
  168.     task1SP = get_sp();
  169.    
  170.     //3 get SP of another task
  171.     set_sp(task2SP);
  172.     current_task=2;
  173.     break;
  174.    
  175.   case 2:
  176.     //2 save current stack pointer
  177.     task2SP = get_sp();
  178.    
  179.     //3 get SP of another task
  180.     set_sp(task1SP);
  181.     current_task=1;
  182.     break;
  183.   }
  184.  
  185.   //4 restore the stack
  186.   asm("POP {R4-R11}");
  187.  
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement