RTOS para PIC16 y PIC18

Hola,

Les comparto un Codigo generico para que puedan usar como un Sistema RTOS,
Lo he probado una y otra vez para asegurar que funcione, con este codigo de ejemplo es para que se den una idea de como realizar un RTOS, hasta eso pueden cambiar algunas cosas para usarlo para sus proyectos.

Subiré mas codigos con la misma estructura para empezar a crear nuestro propio RTOS, Aunque actualmente ya existe el Free Rtos, entre varios mas, solo hice por curiosidad, aunque si tienen alguna idea mejor para hacerlo mas dinamico, adelante.

El codigo es para un PIC16F648A, aunque los siguientes codigos seran para el PIC18F4520.

Saludos!

Código:
/* 
 * File:   Main.c
 * Author: jorge rodriguez
 *
 * Created on 12 de noviembre de 2014, 04:44 PM
 *
 * Brief: Codigo de ejemplo de un RTOS a una velocidad de 1mS de interrupcion
 */

/*
 Incluimos Librerias
 */

#include    <htc.h>
#include    <stdio.h>
#include    <stdlib.h>

/*
 Configuramos los Fuses del Microcontrolador
 */
#pragma config WDTE=OFF,PWRTE=ON,CP=OFF,BOREN=OFF,MCLRE=ON,CPD=OFF,FOSC=HS
/*
 Configuramos La velocidad de trabajo del Microcontrolador
 */
#define __XTAL_FREQ 20000000

/*
 Definiciones Globales
 */

#define Int_OFF PIE1bits.TMR1IE = 0
#define Int_ON PIE1bits.TMR1IE = 1
#define TimeRTOS    64911


/*
 Variables del Sistema RTOS
 */
int TasksCounter=0;
unsigned int ProcessTaskFlags=0;
unsigned char flagInter=0;

/*
 Variables Globales para Usuario
 */




/*
 Punteros de funciones en una estructura, Aqui debe de crear tus funciones o estructuras que vas a usar en tus codigos
 */
struct Led_Control{

    void (*ptr_blink) (unsigned char* port,unsigned char _nbit,int _time);
    void (*ptr_Shift_Led) (unsigned char *port,int _time);
    void (*Init)(void);

}Led_Control;




/*
 Funciones de Escribir y Leer del Timer 1 para Sistema RTOS
 */

unsigned int ReadTimer1(){

    return (unsigned int)(TMR1H<<8)|(TMR1L);

}

void WriteTimer1(unsigned int _load){

    TMR1H = (unsigned int) (_load>>8)&0xFF;
    TMR1L = (_load&0xFF);

}

/*
 Interrupcion por Timer 1 a una velocidad de 1mS para el Sistema RTOS
 */

static void interrupt isr(){


    if(PIR1bits.TMR1IF){

        PIR1bits.TMR1IF=0;
        flagInter = 1;

        TasksCounter++;

        WriteTimer1(TimeRTOS);

    }


}

/*
 Funciones de Usuario
 */


void blink(unsigned char* port,unsigned char _nbit,int _time){

    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        /*
         Siempre Apage la interrupcion del Sistema RTOS antes de empezar su codigo
         */
        Int_OFF;

         /*
          Codigo del Usuario
          * Inicio
         */

        (*port) ^= (1<<_nbit);
        
         /*
          Codigo del Usuario
          * Final
         */
         /*
         Siempre Inicie la interrupción del Sistema RTOS despues de terminar su codigo
         */
        Int_ON;

    }
}

void Shift_LED(unsigned char *port,int _time){

    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        /*
         Siempre Apage la interrupcion del Sistema RTOS antes de empezar su codigo
         */
        Int_OFF;

         /*
          Codigo del Usuario
          * Inicio
         */
        for(unsigned char _shift=0;_shift<7;_shift++){
            (*port) ^= (1<<_shift);
            for(unsigned int _t=10000;_t>0;_t--);
            (*port) ^= (1<<_shift);
            for(unsigned int _t=10000;_t>0;_t--);
        }


         /*
          Codigo del Usuario
          * Final
         */
         /*
         Siempre Inicie la interrupcion del Sistema RTOS despues de terminar su codigo
         */
        Int_ON;

    }


}


/*
 Funcion de Empezar las Tareas del Sistema RTOS
 */


void Tasks_Start(void){

    Int_ON;

    while(1){

        if(flagInter){
            flagInter=0;
            
            /*
             Aqui llama las funciones del Usuario
             */

            Led_Control.ptr_blink(&PORTB,5,50); //Cada 50mS se ejecutara esta funcion
            Led_Control.ptr_blink(&PORTB,0,1000); //Cada 1s se ejecutara esta funcion
            Led_Control.ptr_Shift_Led(&PORTA,600);    //Cada 600mS se ejecutara esta Funcion
        }

    }
}

void Init(void){
    //Instancias de Funciones a Usar
    Led_Control.ptr_blink       = &blink;
    Led_Control.ptr_Shift_Led   = &Shift_LED;
}
/*
 * 
 */
void main(void) {


    //Configuracion de Puertos y Perifericos
    TRISB = 0x00;
    TRISA = 0x00;
    CMCON = 0x07;
    T1CON = 0b00110001;
    

    //Configuracion Timer1 para el Sistema RTOS a 1mS
    WriteTimer1(TimeRTOS);

    Led_Control.Init=&Init;
    
    Led_Control.Init();


    PORTB = 0x00;
    PORTA = 0x00;

    //Activa las Interrupciones Globales
    INTCONbits.GIE = 1;
    INTCONbits.PEIE = 1;

    //Inicia Las Tareas
    Tasks_Start();


}
 
Hola,

Subo otro Codigo que es parecido al anterior, pero la unica diferencia es que he eliminado las
lineas 'Int_OFF y Int_ON', he agregado una funcion que me diga el tiempo actual que ha transcurrido, y tambien puse mas funciones para haber como se comporta y tambien visualizar el tiempo que tarda en ejecutar todas las funciones.

RTOS CODE:

Código:
/* 
 * File:   Main.c
 * Author: jorge rodriguez
 *
 * Created on 12 de noviembre de 2014, 04:44 PM
 *
 * Brief: Codigo de ejemplo de un RTOS a una velocidad de 1mS de interrupcion
 */

/*
 Incluimos Librerias
 */

#include    <htc.h>
#include    <stdio.h>
#include    <stdlib.h>

/*
 Configuramos los Fuses del Microcontrolador
 */
#pragma config WDTE=OFF,PWRTE=ON,CP=OFF,BOREN=OFF,MCLRE=ON,CPD=OFF,FOSC=HS
/*
 Configuramos La velocidad de trabajo del Microcontrolador
 */
#define __XTAL_FREQ 20000000

/*
 Definiciones Globales
 */

#define Int_OFF PIE1bits.TMR1IE = 0
#define Int_ON PIE1bits.TMR1IE = 1
#define TimeRTOS    64911


/*
 Variables del Sistema RTOS
 */
int TasksCounter=0;
int StartTime=0,EndTime=0,DiffTime=0;
unsigned int ProcessTaskFlags=0;
unsigned char flagInter=0;

/*
 Variables Globales para Usuario
 */




/*
 Punteros de funciones en una estructura, Aqui debe de crear tus funciones o estructuras que vas a usar en tus codigos
 */
struct Led_Control{

    void (*ptr_blink) (unsigned char* port,unsigned char _nbit,int _time);
    void (*ptr_Shift_Led) (unsigned char *port,int _time);
    void (*Init)(void);

}Led_Control;


/*
 Para Funcion de printf
 */
void putch(char _data){

    while(!TXSTAbits.TRMT);
    TXREG = _data;


}


/*
 Funciones de Escribir y Leer del Timer 1 para Sistema RTOS
 */

unsigned int ReadTimer1(){

    return (unsigned int)(TMR1H<<8)|(TMR1L);

}

void WriteTimer1(unsigned int _load){

    TMR1H = (unsigned int) (_load>>8)&0xFF;
    TMR1L = (_load&0xFF);

}

/*
 Interrupcion por Timer 1 a una velocidad de 1mS para el Sistema RTOS
 */

static void interrupt isr(){


    if(PIR1bits.TMR1IF){

        PIR1bits.TMR1IF=0;
        flagInter = 1;

        TasksCounter++;

        WriteTimer1(TimeRTOS);

    }


}



/*
 Funciones de Usuario
 */

void Datos_screen(int _time){


    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        printf("CurrentTime = %u\r\n",TasksCounter);

    }




}


void blink(unsigned char* port,unsigned char _nbit,int _time){

    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

         /*
          Codigo del Usuario
          * Inicio
         */

        (*port) ^= (1<<_nbit);
        
         /*
          Codigo del Usuario
          * Final
         */
    }
}

void Shift_LED(unsigned char *port,int _time){

    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

         /*
          Codigo del Usuario
          * Inicio
         */
        for(unsigned char _shift=0;_shift<8;_shift++){
            (*port) ^= (1<<_shift);
            for(unsigned long _t=1000;_t>0;_t--);
        }


         /*
          Codigo del Usuario
          * Final
         */

    }


}



/*
 Funcion de Empezar las Tareas del Sistema RTOS
 */


void Tasks_Start(void){

    Int_ON;

    while(1){

        if(flagInter==1){
            flagInter=0;
            
            /*
             Aqui llama las funciones del Usuario
             */
            StartTime = TasksCounter;
            Led_Control.ptr_blink(&PORTB,0,50);     //Cada 50mS se ejecutara esta funcion
            Led_Control.ptr_blink(&PORTB,3,55);     //Cada 55mS se ejecutara esta funcion
            Led_Control.ptr_blink(&PORTB,4,60);     //Cada 60mS se ejecutara esta funcion
            Led_Control.ptr_blink(&PORTB,5,65);     //Cada 65mS se ejecutara esta funcion
            Led_Control.ptr_Shift_Led(&PORTA,70);   //Cada 70mS se ejecutara esta Funcion
            Led_Control.ptr_Shift_Led(&PORTB,75);   //Cada 75mS se ejecutara esta Funcion
            Datos_screen(80);                       //Cada 80mS se ejecutara esta Funcion
            EndTime = TasksCounter;

            DiffTime = EndTime - StartTime;

            if(DiffTime!=0)
                printf("TimeElapsed = %u mS\r\n",DiffTime);

            StartTime = EndTime = DiffTime = 0;


        }

    }
}

void Init(void){
    //Instancias de Funciones a Usar
    Led_Control.ptr_blink       = &blink;
    Led_Control.ptr_Shift_Led   = &Shift_LED;
}

/*
 * 
 */
void main(void) {


    //Configuracion de Puertos y Perifericos
    TRISB = 0x02;
    TRISA = 0x00;
    CMCON = 0x07;
    T1CON = 0b00110001;
    TXSTA = 0b00110100;
    RCSTA = 0b10010000;
    SPBRG = 9;

    //Configuracion Timer1 para el Sistema RTOS a 1mS
    WriteTimer1(TimeRTOS);

    Led_Control.Init=&Init;

    Led_Control.Init();


    PORTB = 0x00;
    PORTA = 0x00;

    //Activa las Interrupciones Globales
    INTCONbits.GIE = 1;
    INTCONbits.PEIE = 1;

    printf("Start Threads Here!!!\r\n");
    //Inicia Las Tareas
    Tasks_Start();


}

Resultado:

Código:
Start Threads Here!!!
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
CurrentTime = 480
TimeElapsed = 2 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 57 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
CurrentTime = 960
TimeElapsed = 2 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
CurrentTime = 1040
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
CurrentTime = 1600
TimeElapsed = 2 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 1 mS
TimeElapsed = 56 mS
TimeElapsed = 1 mS
TimeElapsed =

Como hemos visto algunas funciones retardan el RTOS a 56mS y otras solo 1mS,
mientras tanto el 'CurrentTime' sube cada 80 mS.

Saludos!
 
Hola,

He utilizado aun el mismo el código para modificarlo y poder sacar el tiempo que consume cada función cuando es ejecutada, con la ayuda del TIMER0 con un Preescalar de 32 , si nuestro PIC16F648A tiene una velocidad de 0.2uS por instrucción entonces, 0.2uS * 32 = 6.4 uS, entonces El timer0 incrementara cada 6.4uS el tiempo Maximo es de:

Código:
TiempoMaximo = 6.4uS * 256 = 1.6384 mS

He realizado un arreglo de tiempo donde se guardaran temporalmente el tiempo transcurrido en cada funcion que se ejecute.
Antes que se imprima por el Serial lo que he realizado es la multiplicacion del valor del Timer0 por 6.4 para obtener el valor entero los microsegundos que tardo en ejecutar la funcion.

Por Ejemplo:

Código:
TimeBuffer[0]=Function(50);  //Se ejecuta funcion cada 50mS

Si nuestro valor del TimerBuffer fue de 100 entonces al ser multiplicado por 6.4 es igual a 640.
Entonces sabemos que 640 es un valor entero que corresponde a 640 uS.

¿Porque?

Si 100 lo multiplicamos por 0.0000064 s (Incremento de Timer0) es igual a 0.000640 S.

Entonces solo lo visualizamos como un valor entero y solo especificamos que seas 'uS'.

printf("TimeBuffer[0] = %u uS\r\n",_y,(unsigned int)(TimeBuffer[0]*6.4));


Codigo:

Código:
/* 
 * File:   Main.c
 * Author: jorge rodriguez
 *
 * Created on 12 de noviembre de 2014, 04:44 PM
 *
 * Brief: Codigo de ejemplo de un RTOS a una velocidad de 1mS de interrupcion
 */

/*
 Incluimos Librerias
 */

#include    <htc.h>
#include    <stdio.h>
#include    <stdlib.h>

/*
 Configuramos los Fuses del Microcontrolador
 */
#pragma config WDTE=OFF,PWRTE=ON,CP=OFF,BOREN=OFF,MCLRE=ON,CPD=OFF,FOSC=HS
/*
 Configuramos La velocidad de trabajo del Microcontrolador
 */
#define __XTAL_FREQ 20000000

/*
 Definiciones Globales
 */

#define Int_OFF PIE1bits.TMR1IE = 0
#define Int_ON PIE1bits.TMR1IE = 1
#define TimeRTOS    64911


/*
 Variables del Sistema RTOS
 */
int TasksCounter=0;
int StartTime=0,EndTime=0,DiffTime=0;
unsigned int ProcessTaskFlags=0;
unsigned char flagInter=0;

/*
 Variables Globales para Usuario
 */


unsigned char TimeBuffer[7];

/*
 Punteros de funciones en una estructura, Aqui debe de crear tus funciones o estructuras que vas a usar en tus codigos
 */
struct Led_Control{

    unsigned char (*ptr_blink) (unsigned char* port,unsigned char _nbit,int _time);
    unsigned char (*ptr_Shift_Led) (unsigned char *port,int _time);
    void (*Init)(void);

}Led_Control;


/*
 Para Funcion de printf
 */
void putch(char _data){

    while(!TXSTAbits.TRMT);
    TXREG = _data;


}


/*
 Funciones de Escribir y Leer del Timer 1 para Sistema RTOS
 */

unsigned int ReadTimer1(){

    return (unsigned int)(TMR1H<<8)|(TMR1L);

}

void WriteTimer1(unsigned int _load){

    TMR1H = (unsigned int) (_load>>8)&0xFF;
    TMR1L = (_load&0xFF);

}

/*
 Interrupcion por Timer 1 a una velocidad de 1mS para el Sistema RTOS
 */

static void interrupt isr(){


    if(PIR1bits.TMR1IF){

        PIR1bits.TMR1IF=0;
        flagInter = 1;

        TasksCounter++;

        WriteTimer1(TimeRTOS);

    }


}



/*
 Funciones de Usuario
 */

unsigned char Datos_screen(int _time){


    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        TMR0 = 0;

        printf("CT = %u\r\n",TasksCounter);

        DiffTime = TMR0;
        
        if(DiffTime!=0)
            return DiffTime;

    }


    return 0;

}


unsigned char blink(unsigned char* port,unsigned char _nbit,int _time){

    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        TMR0 = 0;
         /*
          Codigo del Usuario
          * Inicio
         */

        (*port) ^= (1<<_nbit);

         /*
          Codigo del Usuario
          * Final
         */
        DiffTime = TMR0;

        if(DiffTime!=0)
            return DiffTime;
    }

    return 0;
}

unsigned char Shift_LED(unsigned char *port,int _time){

    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        TMR0 = 0;



         /*
          Codigo del Usuario
          * Inicio
         */
        for(unsigned char _shift=0;_shift<8;_shift++){
            (*port) ^= (1<<_shift);
        }

         /*
          Codigo del Usuario
          * Final
         */
        DiffTime = TMR0;

        if(DiffTime!=0)
            return DiffTime;
    }

    return 0;

}



/*
 Funcion de Empezar las Tareas del Sistema RTOS
 */


void Tasks_Start(void){

    Int_ON;

    while(1){

        if(flagInter==1){
            flagInter=0;
            
            /*
             Aqui llama las funciones del Usuario
             */

            TimeBuffer[0]=Led_Control.ptr_blink(&PORTB,0,50);     //Cada 50mS se ejecutara esta funcion
            TimeBuffer[1]=Led_Control.ptr_blink(&PORTB,3,55);     //Cada 55mS se ejecutara esta funcion
            TimeBuffer[2]=Led_Control.ptr_blink(&PORTB,4,60);     //Cada 60mS se ejecutara esta funcion
            TimeBuffer[3]=Led_Control.ptr_blink(&PORTB,5,65);     //Cada 65mS se ejecutara esta funcion
            TimeBuffer[4]=Led_Control.ptr_Shift_Led(&PORTA,70);   //Cada 70mS se ejecutara esta Funcion
            TimeBuffer[5]=Led_Control.ptr_Shift_Led(&PORTB,75);   //Cada 75mS se ejecutara esta Funcion
            TimeBuffer[6]=Datos_screen(80);                       //Cada 80mS se ejecutara esta Funcion




            for(unsigned char _y=0;_y<sizeof(TimeBuffer);_y++)
                if(TimeBuffer[_y]!=0)
                    printf("TimeBuffer[%u] = %u uS\r\n",_y,(unsigned int)(TimeBuffer[_y]*6.4));

            for(unsigned char _y=0;_y<sizeof(TimeBuffer);_y++)
                TimeBuffer[_y]=0;

        }

    }
}

void Init(void){
    //Instancias de Funciones a Usar
    Led_Control.ptr_blink       = &blink;
    Led_Control.ptr_Shift_Led   = &Shift_LED;
}

/*
 * 
 */
void main(void) {


    //Configuracion de Puertos y Perifericos
    TRISB = 0x02;
    TRISA = 0x00;
    CMCON = 0x07;
    T1CON = 0b00110001;
    OPTION_REG = 0b00000100;
    TXSTA = 0b00110100;
    RCSTA = 0b10010000;
    SPBRG = 9;
    TMR0 = 0;

    //Configuracion Timer1 para el Sistema RTOS a 1mS
    WriteTimer1(TimeRTOS);

    Led_Control.Init=&Init;

    Led_Control.Init();


    PORTB = 0x00;
    PORTA = 0x00;

    //Activa las Interrupciones Globales
    INTCONbits.GIE = 1;
    INTCONbits.PEIE = 1;

    printf("Start Threads Here!!!\r\n");
    //Inicia Las Tareas
    Tasks_Start();


}


Resultado:

Código:
Start Threads Here!!!
TimeBuffer[1] = 6 uS
TimeBuffer[2] = 6 uS
TimeBuffer[3] = 6 uS
TimeBuffer[4] = 70 uS
TimeBuffer[5] = 70 uS
CT = 80
TimeBuffer[6] = 595 uS
TimeBuffer[1] = 6 uS
TimeBuffer[2] = 6 uS
TimeBuffer[3] = 6 uS
TimeBuffer[4] = 70 uS
TimeBuffer[5] = 70 uS
CT = 160
TimeBuffer[6] = 800 uS
TimeBuffer[1] = 6 uS
TimeBuffer[2] = 6 uS
TimeBuffer[3] = 6 uS
TimeBuffer[4] = 70 uS
TimeBuffer[1] = 6 uS
TimeBuffer[5] = 70 uS
CT = 240
TimeBuffer[2] = 6 uS
TimeBuffer[6] = 806 uS
TimeBuffer[3] = 6 uS
TimeBuffer[1] = 6 uS
TimeBuffer[4] = 70 uS
TimeBuffer[2] = 6 uS
TimeBuffer[5] = 70 uS
CT = 320
TimeBuffer[6] = 806 uS
TimeBuffer[3] = 6 uS
TimeBuffer[1] = 6 uS
TimeBuffer[4] = 70 uS
TimeBuffer[2] = 6 uS
TimeBuffer[5] = 70 uS
TimeBuffer[1] = 6 uS
TimeBuffer[3] = 6 uS
CT = 400
TimeBuffer[6] = 806 uS
TimeBuffer[2] = 6 uS
TimeBuffer[4] = 70 uS
TimeBuffer[1] = 6 uS
TimeBuffer[5] = 70 uS
TimeBuffer[3] = 6 uS
CT = 480
TimeBuffer[2] = 6 uS
TimeBuffer[6] = 806 uS
TimeBuffer[4] = 70 uS
TimeBuffer[1] = 6 uS
TimeBuffer[3] = 6 uS
TimeBuffer[5] = 70 uS
TimeBuffer[2] = 6 uS
TimeBuffer[1] = 6 uS
CT = 560

Entonces, la funcion que esta la posicion numero 2 del buffer, se tarda solo 6uS, mientras la funcion que esta en la posicion 6 se tarda en ejecutarla por completo es 806uS.

Al fin y acabo lo que tenemos solo es un debug de tiempo en cada funcion.

Saludos!
 
Hola,

Siguiendo con el Tema del RTOS para PIC, he migrado exitosamente el código que estaba para el PIC16F628A, al PIC18F4520.

Los procesos que esta realizando el Microcontrolador son los siguientes:

Código:
TimeBuffer[0]=Led_Control.ptr_blink(&PORTB,0,250);     //Cada 250mS se ejecutara esta funcion
TimeBuffer[1]=Led_Control.ptr_blink(&PORTB,1,500);     //Cada 500mS se ejecutara esta funcion
TimeBuffer[2]=Datos_screen(750);                       //Cada 750mS se ejecutara esta Funcion
TimeBuffer[3]=Math_Calculation(180,1000);               //Cada 1000mS se ejecutara esta Funcion
 TimeBuffer[4]=Save_Data(1250);                          //Cada 1250mS se ejecutara esta Funcion


Estas 5 funciones se están ejecutando con el tiempo definido, explico:

TimeBuffer[0]=Led_Control.ptr_blink(&PORTB,0,250);

Esta función se ejecuta cada 250 milisegundos, si llega el TasksCounter (Esta variable se incrementa cada 1mS usando el timer 0) si llegara a 250 mS la función se ejecuta.
¿Pero que pasa si llega a 500 milisegundos?

TimeBuffer[0]=Led_Control.ptr_blink(&PORTB,0,250);
TimeBuffer[1]=Led_Control.ptr_blink(&PORTB,1,500);

Estas dos funciones se ejecutarían, ya que ha pasado dos veces 250 mS es decir se ejecuta dos veces la primera función y una sola vez la función dos.

Y asi cuando llegue a 1250 mS, se ejecutara todas las funciones.

Utilizando el algoritmo del timer 1 para obtener el tiempo de retraso de cada función, esto sirve para debugear las funciones.

Codigo:

Código:
/* 
 * File:   Main.c
 * Author: jorge
 *
 * Created on 9 de noviembre de 2014, 01:43 PM
 */

#include <htc.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#pragma config IESO=OFF,OSC=HS,FCMEN=OFF
#pragma config BOREN=OFF,BORV=3,PWRT=ON
#pragma config WDTPS=128,WDT=OFF
#pragma config CCP2MX=PORTC,PBADEN=OFF,LPT1OSC=OFF,MCLRE=ON
#pragma config DEBUG=OFF,LVP=OFF,STVREN=OFF,XINST=OFF
#pragma config CP0=OFF,CP1=OFF,CP2=OFF,CP3=OFF,CPD=OFF,CPB=OFF
#pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF,WRT3=OFF,WRTB=OFF,WRTC=OFF,WRTD=OFF
#pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTR3=OFF,EBTRB=OFF

#define _XTAL_FREQ 20000000

/*
 Definiciones Globales
 */

#define Int_OFF     INTCONbits.TMR0IE = 0
#define Int_ON      INTCONbits.TMR0IE = 1
#define TimeRTOS    65516

#define DesActiveSSP0	PORTCbits.RC2=1
#define ActiveSSP0	PORTCbits.RC2=0


/*
 Variables del Sistema RTOS
 */
int TasksCounter=0;
unsigned int StartTime=0,EndTime=0,DiffTime=0;
unsigned int ProcessTaskFlags=0;
unsigned char flagInter=0;

/*
 Variables Globales para Usuario
 */


unsigned int TimeBuffer[5];

const char data[]="Primera Prueba con Memorias SRAM con PIC\r\n";

/*
 Punteros de funciones en una estructura, Aqui debe de crear tus funciones o estructuras que vas a usar en tus codigos
 */
struct Led_Control{

    unsigned int (*ptr_blink) (unsigned char* port,unsigned char _nbit,int _time);
    unsigned int (*ptr_Shift_Led) (unsigned char *port,int _time);
    void (*Init)(void);

}Led_Control;

//////////////////////////////////////////////
//Para usar el printf
//////////////////////////////////////////////
void putch(unsigned char byte) {
/* Salida de un byte */
    while(!TXIF) /* Estbalece que el regitro esta vacio*/
     continue;
    TXREG = byte;
}

unsigned char AT45DBXX_write(unsigned int adr_,unsigned char data_){

	unsigned char rdata;

	ActiveSSP0;
	rdata=WriteSPI(0x84);
	rdata=WriteSPI(0xff);
	rdata=WriteSPI((unsigned char)(adr_>>8));
	rdata=WriteSPI((unsigned char)adr_);
	rdata=WriteSPI(data_);
	DesActiveSSP0;

	return rdata;


}


unsigned char AT45DBXX_read(unsigned int adr_){

	unsigned char rdata;

	ActiveSSP0;
	rdata=WriteSPI(0xD4);
	rdata=WriteSPI(0xff);
	rdata=WriteSPI((unsigned char)(adr_>>8));
	rdata=WriteSPI((unsigned char)adr_);
	rdata=ReadSPI();
	rdata=ReadSPI();
	DesActiveSSP0;

	return rdata;

}

/*
 Funciones de Usuario
 */

unsigned int Save_Data(int _time){

    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        WriteTimer1(0);

        for(unsigned char _g=0;_g<sizeof(data)-1;_g++)
            AT45DBXX_write(_g,data[_g]);

        printf("Data Saved = ");
        for(unsigned char _g=0;_g<sizeof(data)-1;_g++)
            putch(AT45DBXX_read(_g));

        DiffTime = ReadTimer1();

        if(DiffTime!=0)
            return DiffTime;

    }


    return 0;



}


unsigned int Math_Calculation(double _grad,int _time){


    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        WriteTimer1(0);

        double _z3,_rad;

        for(unsigned char _g=0;_g<_grad;_g++){
            _rad = ((double)_g * 3.14592654) / 180;
            _z3 = sin(_rad);
        }

        DiffTime = ReadTimer1();

        
        if(DiffTime!=0)
            return DiffTime;

    }


    return 0;



}

unsigned int Datos_screen(int _time){


    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        WriteTimer1(0);

        printf("CT = %u\r\n",TasksCounter);

        DiffTime = ReadTimer1();

        if(DiffTime!=0)
            return DiffTime;

    }


    return 0;

}


unsigned int blink(unsigned char* port,unsigned char _nbit,int _time){

    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        WriteTimer1(0);
         /*
          Codigo del Usuario
          * Inicio
         */

        (*port) ^= (1<<_nbit);

         /*
          Codigo del Usuario
          * Final
         */
        DiffTime = ReadTimer1();

        if(DiffTime!=0)
            return DiffTime;
         

    }

    return 0;
}

unsigned int Shift_LED(unsigned char *port,int _time){

    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        WriteTimer1(0);



         /*
          Codigo del Usuario
          * Inicio
         */
        for(unsigned char _shift=0;_shift<8;_shift++){
            (*port) ^= (1<<_shift);
        }

         /*
          Codigo del Usuario
          * Final
         */
        DiffTime = ReadTimer1();

        if(DiffTime!=0)
            return DiffTime;
    }

    return 0;

}


/*
 Funcion de Empezar las Tareas del Sistema RTOS
 */


void Tasks_Start(void){

    Int_ON;

    while(1){

        if(flagInter==1){
            
            flagInter=0;
            Int_OFF;
            /*
             Aqui llama las funciones del Usuario
             */

            TimeBuffer[0]=Led_Control.ptr_blink(&PORTB,0,250);     //Cada 250mS se ejecutara esta funcion
            TimeBuffer[1]=Led_Control.ptr_blink(&PORTB,1,500);     //Cada 500mS se ejecutara esta funcion
            TimeBuffer[2]=Datos_screen(750);                       //Cada 750mS se ejecutara esta Funcion
            TimeBuffer[3]=Math_Calculation(180,1000);               //Cada 1000mS se ejecutara esta Funcion
            TimeBuffer[4]=Save_Data(1250);                          //Cada 1250mS se ejecutara esta Funcion

            for(unsigned char _y=0;_y<sizeof(TimeBuffer);_y++){

                if(TimeBuffer[_y]!=0){
                    printf("TimeBuffer[%u] = %u uS\r\n",_y,(unsigned int)((float)TimeBuffer[_y]*1.6));
                }
            
            }

            for(unsigned char _y=0;_y<sizeof(TimeBuffer);_y++)
                TimeBuffer[_y]=0;

            Int_ON;
        }

    }
}

void Init(void){
    //Instancias de Funciones a Usar
    Led_Control.ptr_blink       = &blink;
    Led_Control.ptr_Shift_Led   = &Shift_LED;
}

static void interrupt isr(){

    if(INTCONbits.T0IF){

        INTCONbits.T0IF=0;

        flagInter = 1;

        TasksCounter++;

        WriteTimer0(TimeRTOS);

    }

}



/*
 * 
 */
void main(void){

    TRISC = 0x80;
    TRISB = 0x00;
    CMCON = 0x07;

    OpenUSART(USART_TX_INT_OFF  &
              USART_RX_INT_OFF  &
              USART_ASYNCH_MODE &
              USART_EIGHT_BIT   &
              USART_CONT_RX     &
              USART_BRGH_HIGH   &
              USART_ADDEN_OFF,
              10);

    OpenTimer0(T0_SOURCE_INT &
               T0_16BIT      &
               T0_EDGE_RISE  &
               T0_PS_1_256   &
               TIMER_INT_ON);

    OpenTimer1(T1_SOURCE_INT &
               T1_16BIT_RW   &
               T1_OSC1EN_ON  &
               T1_PS_1_8     &
               TIMER_INT_OFF);

    OpenSPI(SPI_FOSC_16,
            MODE_00,
            SMPEND);

    WriteTimer1(0);
    WriteTimer0(TimeRTOS);
    __delay_ms(10);

    Led_Control.Init=&Init;

    Led_Control.Init();

    INTCONbits.GIE=1;
    INTCONbits.PEIE=1;

    printf("Start Threads Here!!!\r\n");
    //Inicia Las Tareas
    Tasks_Start();

}

Resultado:

Código:
Start Threads Here!!!
TimeBuffer[0] = 3 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
CT = 750
TimeBuffer[0] = 3 uS
TimeBuffer[2] = 803 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[3] = 36682 uS
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[4] = 7112 uS
CT = 1500
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[2] = 904 uS
TimeBuffer[0] = 3 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[3] = 36682 uS
CT = 2250
TimeBuffer[0] = 3 uS
TimeBuffer[2] = 910 uS
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[4] = 7120 uS
TimeBuffer[0] = 3 uS
CT = 3000
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[2] = 908 uS
TimeBuffer[3] = 36682 uS
TimeBuffer[0] = 3 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
CT = 3750
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[2] = 913 uS
TimeBuffer[4] = 7116 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[3] = 36682 uS
TimeBuffer[0] = 3 uS
CT = 4500
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[2] = 908 uS
TimeBuffer[0] = 3 uS
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[3] = 36682 uS
TimeBuffer[4] = 7118 uS
CT = 5250
TimeBuffer[0] = 3 uS
TimeBuffer[2] = 904 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[0] = 3 uS
CT = 6000
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[2] = 908 uS
TimeBuffer[3] = 36682 uS
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[4] = 7118 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
CT = 6750
TimeBuffer[0] = 3 uS
TimeBuffer[2] = 905 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[3] = 36682 uS
TimeBuffer[0] = 3 uS
CT = 7500
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[2] = 915 uS
TimeBuffer[4] = 7116 uS
TimeBuffer[0] = 3 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[3] = 36682 uS
CT = 8250
TimeBuffer[0] = 3 uS
TimeBuffer[2] = 908 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[4] = 7115 uS
CT = 9000
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[2] = 902 uS
TimeBuffer[3] = 36682 uS
TimeBuffer[0] = 3 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
CT = 9750
TimeBuffer[0] = 3 uS
TimeBuffer[2] = 913 uS
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[3] = 36682 uS
TimeBuffer[4] = 7120 uS
TimeBuffer[0] = 3 uS
CT = 10500
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[2] = 995 uS
TimeBuffer[0] = 3 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[3] = 36682 uS
CT = 11250
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[2] = 993 uS
TimeBuffer[4] = 7116 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[0] = 3 uS
CT = 12000
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[2] = 996 uS
TimeBuffer[3] = 36682 uS
TimeBuffer[0] = 3 uS
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[4] = 7116 uS
CT = 12750
TimeBuffer[0] = 3 uS
TimeBuffer[2] = 1000 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[3] = 36682 uS
TimeBuffer[0] = 3 uS
CT = 13500
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[2] = 993 uS
Data Saved = Primera Prueba con Memorias SRAM con PIC
TimeBuffer[0] = 3 uS
TimeBuffer[4] = 7116 uS
TimeBuffer[0] = 3 uS
TimeBuffer[1] = 4 uS
TimeBuffer[3] = 36682 uS

Como vemos la función en la posición 4 se tarda en ejecutarla 7.116mS, mientras la que mas se tarda en ejecutar es la función en la posición numero 3 que tiene hasta 36.682mS.

La función numero 3 que pertenece al algoritmo de 'Math_calculation', el tiempo es razonable ya que realiza un calculo de una media onda sonoidal.

Código:
unsigned int Math_Calculation(double _grad,int _time){


    /*
     Dentro de cada Funcion debe de existir una Variable _time para
     * darle tiempo de ejecucion de la tarea.
     * La sentencia IF, if((TasksCounter%_time) == 0) siempre debe de estar
     */
    if((TasksCounter%_time) == 0){

        WriteTimer1(0);

        double _z3,_rad;

        for(unsigned char _g=0;_g<_grad;_g++){
            _rad = ((double)_g * 3.14592654) / 180;
            _z3 = sin(_rad);
        }

        DiffTime = ReadTimer1();

        
        if(DiffTime!=0)
            return DiffTime;

    }


    return 0;

}


Saludos!
 
Atrás
Arriba