⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 my_os.c

📁 avr Rtos 255 Task avr Rtos 255 Task
💻 C
字号:
#include "my_os.h"
#include "ma_tgt.h"
//#include "global.h"
#include <stdlib.h>
#include <inavr.h>

//externe
extern unsigned char t_sph;
extern unsigned char t_spl;
extern unsigned char t_r29;
extern unsigned char t_r28;
extern unsigned char task_time;
extern unsigned char ig,jg,kg,lg,mg,ng;
extern unsigned int global_inc_g;
extern unsigned int global_inc;
extern unsigned int inc;
extern unsigned char temp_g;
extern unsigned char b_start_so;
extern S8 lcd_sem;
extern unsigned char lcd_coada[NR_MAX_TASK];


//variabile folosite sistem operare
//pointer catre task-ul curent
//kernel *p_taskcurent;
 S8 task_curent;
//poiter catre task-ul coada
//kernel *p_taskcoada;
 S8 task_coada;
//poiter catre task-ul varf
//kernel *p_taskvarf;
 S8 task_varf;
//task-ul care se va activa in lista de asteptare
// S8 task_wait;
//variabila locala folosita la preluarea adresei si la alte stocari temporare
unsigned int tem;



task rtos[NR_MAX_TASK];

unsigned char coada [NR_MAX_TASK];

//declaratii de functii
//functia initializeaza sistemul de operare
void start_so(void)
{
 //initializeaza vectorul de taskuri
/* unsigned char i;
 task_curent=0;
 task_ultim=0;
 task_time=0;
 for(i=0;i<NR_MAX_TASK;i++)
 {
  v_task[i].nr_timpi=0;
  v_task[i].activ=FALSE;
 }
 */
// p_taskvarf=p_taskcoada=p_taskcurent=NULL;//toata lista este invalida
  task_varf=task_coada=task_curent=-1;//initializeaza index vector taskuri
//initializare semafoare resurse hard
  lcd_sem = -1;//o sigura resursa pentru LCD (toate resursele hard sunt accesate o singura data!)
}

//functia creaza un task
unsigned char creaza_task(void (*taskf)(void),unsigned char numar)
{

  //  task temp;
    unsigned int i;

//1.pozitionarea taskului in lista
    if(task_varf==-1)//daca lista este vida
    {
/*      task_varf=temp;
      p_taskcurent=p_taskvarf;//task-ul curent este initial primul task
      p_taskcoada=p_taskvarf;*/
      if(task_coada>=NR_MAX_TASK-1)//daca indexul nu este mai mare decat numarul de task-uri
        return T_EROARE;
      task_coada++;//incrementeaza indexul coada
      task_curent=task_varf=task_coada;
//      rtos[task_coada]=temp;
//initializare
    }
    else//daca lista are cel putin un element
    {
//      p_taskcoada->t_urm=temp;
//      p_taskcoada=temp;
      if(task_coada>=NR_MAX_TASK-1)
        return T_EROARE;
      task_coada++;
//        rtos[task_coada]=temp;
    }

//
//    temp=malloc (sizeof(kernel));
//    if(temp==NULL) return T_EROARE;

//    temp.t_urm=NULL;//initializare element urmator task
    rtos[task_coada].nr_timpi=numar;//initializare timpi task
    rtos[task_coada].activ=1;//initializare task on/off
    for(i=0;i<OSTaskStkSize;i++)
      rtos[task_coada].adr_task[i]=(unsigned char)i;//initializare stiva in total
//salvarea pointer functie
    i = (unsigned int) taskf;
    rtos[task_coada].adr_task[OSTaskStkSizeHard-1]=(unsigned char)i&0x0ff;//ocmps functie
    rtos[task_coada].adr_task[OSTaskStkSizeHard-2]=(unsigned char)((i>>8)&0x0ff);//ocms functie
//initializarea stivei
    i = (unsigned int) rtos[task_coada].adr_task+OSTaskStkSizeHard-3;
    rtos[task_coada].adr_task[OSTaskStkSize-1]=(unsigned char)i&0xff;
    rtos[task_coada].adr_task[OSTaskStkSize-2]=(unsigned char)(i>>8)&0xff;
//initialiarea pointer y
    i = (unsigned int) rtos[task_coada].adr_task+62;
    rtos[task_coada].adr_task[OSTaskStkSize-3]=(unsigned char)i&0xff;
    rtos[task_coada].adr_task[OSTaskStkSize-4]=(unsigned char)(i>>8)&0xff;

    return T_OK;
}

unsigned char comuta_task(void)
{
    if(task_varf==-1)//test daca este goala lista
      return T_EROARE;
    //  return T_EROARE;

//nou: task-ul este comutat numai daca este activat!
    do
    {
     if(task_curent>=task_coada)
       task_curent=task_varf-1;
     task_curent++;
     tem++;
    }while(!(rtos[task_curent].activ));

//    p_taskcurent=p_taskcurent->t_urm;//daca nu comuta intre taskuri
//    if(p_taskcurent==NULL)
//      p_taskcurent=p_taskvarf;

    task_time=rtos[task_curent].nr_timpi;
//initializare stiva (unde se gaseste adresa stivei)
    tem = (unsigned int) ((rtos[task_curent].adr_task)+OSTaskStkSize)>>8;
    t_sph=(unsigned char)(tem&0x00ff);
    t_spl=(unsigned char)((rtos[task_curent].adr_task)+OSTaskStkSize)&0xff;
//initializarea pointer y (unde se gaseste adresa registrilor r29 si r28)
    tem = (unsigned int) ((rtos[task_curent].adr_task)+OSTaskStkSize-2)>>8;
    t_r29=(unsigned char)(tem&0x00ff);
    t_r28=(unsigned char)((rtos[task_curent].adr_task)+OSTaskStkSize-2)&0xff;

    return T_OK;
}

//folosita pentru initializarea t_sp si t_r in rutina timer
void get_tsp(void)
{
//initializare stiva (unde se gaseste adresa stivei)
    tem = (unsigned int) ((rtos[task_curent].adr_task)+OSTaskStkSize)>>8;
    t_sph=(unsigned char)(tem&0x00ff);
    t_spl=(unsigned char)((rtos[task_curent].adr_task)+OSTaskStkSize)&0xff;
//initializarea adresa pointer y
    tem = (unsigned int) ((rtos[task_curent].adr_task)+OSTaskStkSize-2)>>8;
    t_r29=(unsigned char)(tem&0x00ff);
    t_r28=(unsigned char)((rtos[task_curent].adr_task)+OSTaskStkSize-2)&0xff;
}

//folosita pentru initializarea t_sp si t_r pentru primul task care se va executa
void init_task(void)
{
 //initializare stiva (unde se gaseste adresa stivei)
    task_time=rtos[task_curent].nr_timpi;
    tem = (unsigned int) ((rtos[task_curent].adr_task)+OSTaskStkSize)>>8;
    t_sph=(unsigned char)(tem&0x00ff);
    t_spl=(unsigned char)((rtos[task_curent].adr_task)+OSTaskStkSize)&0xff;
//initializarea pointer y
    tem = (unsigned int) ((rtos[task_curent].adr_task)+OSTaskStkSize-2)>>8;
    t_r29=(unsigned char)(tem&0x00ff);
    t_r28=(unsigned char)((rtos[task_curent].adr_task)+OSTaskStkSize-2)&0xff;
//initialiarea pointer y - la primul task stiva software este pregatita pentru incarcare valori registrii!
    tem = (unsigned int) rtos[task_curent].adr_task+80;
    rtos[task_curent].adr_task[OSTaskStkSize-3]=(unsigned char)tem&0xff;
    rtos[task_curent].adr_task[OSTaskStkSize-4]=(unsigned char)(tem>>8)&0xff;
}

//salvarea variabilelor globale
void push_var(void)
{
//unsigned char ig,jg,kg,lg,mg,ng;
  rtos[task_curent].adr_task[OSTaskStkSize-5]=ig;
  rtos[task_curent].adr_task[OSTaskStkSize-6]=jg;
  rtos[task_curent].adr_task[OSTaskStkSize-7]=kg;
  rtos[task_curent].adr_task[OSTaskStkSize-8]=lg;
  rtos[task_curent].adr_task[OSTaskStkSize-9]=mg;
  rtos[task_curent].adr_task[OSTaskStkSize-10]=ng;
//  rtos[task_curent].adr_task[OSTaskStkSize-11]=(unsigned char)(global_inc_g&0x0ff);
//  rtos[task_curent].adr_task[OSTaskStkSize-12]=(unsigned char)((global_inc_g>>8)&0x0ff);

  rtos[task_curent].adr_task[OSTaskStkSize-11]=temp_g;
 // rtos[task_curent].adr_task[OSTaskStkSize-12]=init_t;
}

//restaurarea noilor variabile locale
void pop_var(void)
{
//unsigned char ig,jg,kg,lg,mg,ng;
  ig=rtos[task_curent].adr_task[OSTaskStkSize-5];
  jg=rtos[task_curent].adr_task[OSTaskStkSize-6];
  kg=rtos[task_curent].adr_task[OSTaskStkSize-7];
  lg=rtos[task_curent].adr_task[OSTaskStkSize-8];
  mg=rtos[task_curent].adr_task[OSTaskStkSize-9];
  ng=rtos[task_curent].adr_task[OSTaskStkSize-10];
//  global_inc_g=rtos[task_curent].adr_task[OSTaskStkSize-11];
//  tem=rtos[task_curent].adr_task[OSTaskStkSize-12];
//  global_inc_g+=((tem<<8)&0xff00);
  temp_g=rtos[task_curent].adr_task[OSTaskStkSize-11];
 // init_t=rtos[task_curent].adr_task[OSTaskStkSize-12];
}


void PopSP(void)
{
  __disable_interrupt();
  asm("  LDS R29,t_sph");
  asm("  LDS R28,t_spl");
  asm("  LD R16,-Y");
  asm("  OUT 0x3d,R16");
  asm("  LD R16,-Y");
  asm("  OUT 0x3e,R16");

//in plus setare pointer y pentru stiva soft!
  asm("  LDS R30,t_r28");
  asm("  LDS R31,t_r29");
  asm("  LD R28,-Z");
  asm("  LD R29,-Z");

  b_start_so=1;
  __enable_interrupt();
}

//functia trebuie incadrata intre disable si enable interrupt!
//comutare task-uri apelata (nu ISR)
void comuta(void)
{
   __disable_interrupt();
  asm("ST      -Y,R27");
  asm("ST      -Y,R26");
  asm("ST      -Y,R25");
  asm("ST      -Y,R24");
  asm("ST      -Y,R31");
  asm("ST      -Y,R30");
  asm("ST      -Y,R3");
  asm("ST      -Y,R2");
  asm("ST      -Y,R1");
  asm("ST      -Y,R0");
  asm("ST      -Y,R23");
  asm("ST      -Y,R22");
  asm("ST      -Y,R21");
  asm("ST      -Y,R20");
  asm("ST      -Y,R19");
  asm("ST      -Y,R18");
  asm("ST      -Y,R17");
  asm("ST      -Y,R16");
  asm("IN      R26,0x3F");
  asm("IN      R27,0x3B");
  asm("  ST -Y, R4");
  asm("  ST -Y, R5");
  asm("  ST -Y, R6");
  asm("  ST -Y, R7");
  asm("  ST -Y, R8");
  asm("  ST -Y, R9");
  asm("  ST -Y, R10");
  asm("  ST -Y, R11");
  asm("  ST -Y, R12");
  asm("  ST -Y, R13");
  asm("  ST -Y, R14");
  asm("  ST -Y, R15");
  asm("  ST -Y, R26");

    global_inc=0;
    t_sph=0;
    t_spl=0;
    t_r29=0;
    t_r28=0;
    get_tsp();//initializare variabile t_sp si t_r

//salvare adrese - folosit pointer-ul X  (este deja salvat)
    asm("  LDS R30,t_r28");//R26 <- t_r28
    asm("  LDS R31,t_r29");//R27 <- t_r29
    asm("  ST -Z, R28");//salvare pointer Y
    asm("  ST -Z, R29");

//salvare stiva
    asm("  LDS R30,t_spl");//salvarea stivei se face folosind pointer-ul Y
    asm("  LDS R31,t_sph");
    asm("  IN R16,0x3d");//salvare SPH
    asm("  ST -Z,R16");
    asm("  IN R16,0x3e");//salvare SPL
    asm("  ST -Z,R16");

    push_var();//salveaza variabilele
    comuta_task();//comuta task-ul urmator
    pop_var();//restaureaza noile variabile


  asm("  LDS R28,t_spl");
  asm("  LDS R29,t_sph");
  asm("  LD R16,-Y");
  asm("  OUT 0x3d,R16");
  asm("  LD R16,-Y");
  asm("  OUT 0x3e,R16");

//in plus setare pointer y pentru stiva soft!
//restaurare adrese - folosit pointer-ul X  (va fi si el restaurat)

  asm("  LDS R30,t_r28");
  asm("  LDS R31,t_r29");
  asm("  LD R28,-Z");
  asm("  LD R29,-Z");


    //intfunct();
//reactualizeaza pointerii noi calculati
  asm("  LD R26,Y+");
  asm("  LD R15,Y+");
  asm("  LD R14,Y+");
  asm("  LD R13,Y+");
  asm("  LD R12,Y+");
  asm("  LD R11,Y+");
  asm("  LD R10,Y+");
  asm("  LD R9,Y+");
  asm("  LD R8,Y+");
  asm("  LD R7,Y+");
  asm("  LD R6,Y+");
  asm("  LD R5,Y+");
  asm("  LD R4,Y+");

  asm("OUT     0x3B,R27");
  asm("OUT     0x3F,R26");
  asm("LD      R16,Y+");
  asm("LD      R17,Y+");
  asm("LD      R18,Y+");
  asm("LD      R19,Y+");
  asm("LD      R20,Y+");
  asm("LD      R21,Y+");
  asm("LD      R22,Y+");
  asm("LD      R23,Y+");
asm("LD      R0,Y+");
asm("LD      R1,Y+");
asm("LD      R2,Y+");
asm("LD      R3,Y+");
asm("LD      R30,Y+");
asm("LD      R31,Y+");
asm("LD      R24,Y+");
asm("LD      R25,Y+");
asm("LD      R26,Y+");
asm("LD      R27,Y+");
   __enable_interrupt();
}
//
void lcd_req(void)
{
//testeaza starea cererii
  if(lcd_sem>=0)//resursa ocupata?
  {
    lcd_coada[lcd_sem]=task_curent;//adauga task/ul curent in lista cereri acces LCD
    rtos[task_curent].activ = 0;//task-ul curent devine din acest moment inactiv
  }
  lcd_sem++;//incrementeaza starea cererii
  if(lcd_sem>=NR_MAX_TASK)//limita maxima in mod normal nu ar trebui sa ajunga
    lcd_sem=0;
}

void lcd_release(void)
{
 if(lcd_sem>0)//daca exista vreun task in coada de asteptare
 {
  rtos[lcd_coada[0]].activ = 1; //activeaza primul task din coada de asteptare
//sterge primul task din coada de asteptare
  for(ig=0;ig<lcd_sem-1;ig++)
   lcd_coada[ig]=lcd_coada[ig+1];
  lcd_coada[lcd_sem-1]=0;
 }
 lcd_sem--;//decrementeaza semaforul
 if(lcd_sem<-1)//limita minima in mod normal nu ar trebui sa ajunga
  lcd_sem=-1;
}

void delay_1_ms(unsigned int time)
{
 unsigned int in;
// for(temp=0;temp<time;temp++)
// {
//  global_inc_g=0;
  in  = global_inc_g;
  for(;;)
  {
   if(in>global_inc_g)
   {
    if(((0xffff-in)+global_inc_g)>=(time*21))
     break;
   }
   else
   {
    if((global_inc_g-in)>=(time*21))
     break;
   }
  }
// }
}

/*void control_on(void)
{
 b_start_so=0;
}

void control_off
{
 b_start_so=1;
}
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -