📄 my_os.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 + -