Autor Tema: Manejando tareas en KL46Z  (Leído 3615 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado mojo

  • PIC10
  • *
  • Mensajes: 23
Manejando tareas en KL46Z
« en: 14 de Diciembre de 2016, 19:19:31 »
¡Hola!

Para tratar de aprender a manejar tareas en una placa KL46Z, he hecho el siguiente código:

Código: C
  1. #include <MKL46Z4.H>
  2. #include "RTL.h"
  3. #include "helper.h"
  4.  
  5. OS_TID t_task1;
  6. OS_TID t_task2;
  7.  
  8. long n = 0;
  9.  
  10. OS_MUT UartLock;
  11.  
  12. __task void task1 (void) {
  13.         while(1) {
  14.                 setLedR(1);
  15.         }
  16. }
  17.  
  18. __task void task2 (void) {
  19.         while (1) {
  20.                 setLedG(1);
  21.         }
  22. }
  23.  
  24. __task void init (void) {
  25.         t_task1 = os_tsk_create (task1, 1);
  26.         t_task2 = os_tsk_create (task2, 1);
  27.        
  28.         os_tsk_delete_self ();
  29. }
  30.  
  31. int main () {
  32.         SystemInit();
  33.         initLed('E',29);
  34.         initLed('D',5);
  35.         os_sys_init(init);
  36. }

Con él, pretendo asegurarme de que se ejecuta tanto task1 como task2. Las funciones de encendido y de inicialización de los LEDs funcionan perfectamente, pero ninguno de ellos se enciende...  :5]

¿Qué estoy haciendo mal?


Saludos  :mrgreen:

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Manejando tareas en KL46Z
« Respuesta #1 en: 14 de Diciembre de 2016, 19:52:17 »
Por lo que vi en algunos codigos, creo que seria algo asi... Nuevamente no tengo la menor idea de este RTOS.

Código: C
  1. #include <stdint.h>
  2.  
  3. OS_TID t_task1, t_task2;
  4.  
  5. long n = 0;
  6. uint32_t k,j;
  7.  
  8. __task void task1 (void) {
  9.  
  10.         //Como es la primera en ejecutarse esta debe crear las demas
  11.  
  12.         t_task1 = os_tsk_self();                // ID de task1
  13.         t_task2 = os_tsk_create(task2,0)        // Creacion e ID de task2
  14.        
  15.         while(1)
  16.         {
  17.                 toggleLedR();                           // Cambio el estado del led
  18.                 for(k=0;k<100000;k++);  // Delay
  19.         }
  20. }
  21.  
  22. __task void task2 (void)
  23. {
  24.         while (1)
  25.         {
  26.                 toggleLedG();                           //Cambio el estado del led
  27.                 for(j=0;j<70000;j++);           // Delay
  28.         }
  29. }
  30.  
  31.  
  32. int main (void)
  33. {
  34.         SystemInit();           // ¿?
  35.         initLed('E',29);        // ¿?
  36.         initLed('D',5);         // ¿?
  37.  
  38.         os_sys_init(task1);     // Nos aseguramos que siempre comienze al menos con una tarea
  39.  
  40.         while(1)
  41.         {
  42.                 /* No deberia llegar nunca aca pero nos aseguramos con un while */
  43.         }
  44.  
  45.         retun 0;                // return obligatorio si es int
  46.  
  47. }

Desconectado Carl47D

  • PIC16
  • ***
  • Mensajes: 160
Re:Manejando tareas en KL46Z
« Respuesta #2 en: 15 de Diciembre de 2016, 00:51:56 »
Hola,
No conozco mucho sobre los micros de NXP/Freescale pero este blog me parece muy bueno y trata muchos temas sobre ellos: MCU on Eclipse.
El RTOS es el MQX?

EDIT:
Acabo de ver tu otra pregunta, la versión del RTOS RTX que usas es el 1 o la 2?

Saludos

Desconectado mojo

  • PIC10
  • *
  • Mensajes: 23
Re:Manejando tareas en KL46Z
« Respuesta #3 en: 15 de Diciembre de 2016, 06:17:34 »
KILLERJC

Buenos días,

te pongo el código tal y como lo tengo... Según lo que sé, debería funcionar:

Código: C
  1. #include <rtl.h>
  2.  
  3. #include <stdint.h>
  4.  
  5.  
  6. OS_TID t_task1;
  7.  
  8. uint32_t j;
  9.  
  10.  
  11. __task void task1 (void) {
  12.  
  13.         os_evt_wait_and(0x0001, 0xffff);     //Espero por la señal (0x0001) de la tarea 'init'
  14.  
  15.                                              //Una vez recibida la señal, continúo
  16.  
  17.         for(;;) {                                          
  18.  
  19.                 for (j = 0; j < 1000000; j++);     //Delay
  20.  
  21.                 toggleLedR();                      //Cambio el estado del LED (on - off)
  22.  
  23.         }
  24.  
  25. }
  26.  
  27. __task void init (void) {
  28.  
  29.         t_task1 = os_tsk_create(task1, 1);     //Crea la tarea 'task1' y guarda su ID en 't_task1'
  30.  
  31.         os_evt_set (0x0001, t_task1);          //Le envío a la tarea 'task1' un señal (0x0001)
  32.  
  33.         os_tsk_delete_self();                  //Borro esta tarea 'init' ya que no la voy a utilizar más
  34.  
  35. }
  36.  
  37. int main (void) {
  38.  
  39.         os_sys_init(init);  //Inicializa el RTOS
  40.  
  41. }

Pero no funciona... Ahora voy a hablar con mi profesora y cuando salga te cuento.


Carl47D


Buenos días,

soy nuevo en esto de los microcontroladores y la terminología aún no la domino, pero me imagino que con RTOS te refieres al sistema operativo que tengo cargado en la placa. Si es así, estoy usando un RTOS que se llama Keil RTX Real-Time Kernel, pero con respecto a la versión que estoy utilizando no tengo ni idea... Ni siquiera sé donde puedo mirar eso.

Muchas gracias por decirme sobre el blog ese. Acabo de entrar y vi que hablan de la KL46Z en algún post así que seguramente me pueda ser útil.

Saludos  :-)

Desconectado Carl47D

  • PIC16
  • ***
  • Mensajes: 160
Re:Manejando tareas en KL46Z
« Respuesta #4 en: 16 de Diciembre de 2016, 00:27:19 »
Que tal mojo,

Así es, RTOS es el acrónimo de Real Time Operating System o Sistema Operativo de Tiempo Real. Con respecto a la versión de RTX no hay tanto problema, me parece que en el Keil más reciente, 5 creo, trae la versión 2.

Y sobre el blog si esta muy bueno, el link al que te manda el hipervínculo es al resultado de buscar KL46Z pero hay mucha más información, aunque creo que el RTOS que utiliza es FreeRTOS, los conceptos deberían ser parecidos entre RTX y FreeRTOS.

Saludos

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re:Manejando tareas en KL46Z
« Respuesta #5 en: 16 de Diciembre de 2016, 11:47:12 »
Yo creo que si nunca usaste un RTOS, entonces sería más aconsejable usar freeRTOS que hay muchísima informacion de como implementarlo en diversas plataformas.

Saludos!
-
Leonardo Garberoglio

Desconectado mojo

  • PIC10
  • *
  • Mensajes: 23
Re:Manejando tareas en KL46Z
« Respuesta #6 en: 16 de Diciembre de 2016, 16:17:33 »
¡Buenas a todos!

Carl47D


Por requisitos de la Universidad estoy usando Keil uVision4, no el 5 , así que quizás no sea esa versión de RTOS. En todo caso ya solucioné el problema, lo que estaba haciendo mal era inicializar los LEDs dentro de una tarea del sistema operativo, cuando en realidad deberían inicializarse dentro del main, antes de iniciar el RTOS.

elgarbe

El problema es que no puedo usar otro sistema operativo, ya que es un trabajo para la Universidad y como requisito nos ponen utilizar RTX. Pero gracias por el consejo igualmente, lo tendré en cuenta si más adelante hago algo por mi cuenta.

Finalmente el código quedaría así:


   
Código: C
  1. #include <rtl.h>
  2.      
  3.     #include <stdint.h>
  4.      
  5.      
  6.     OS_TID t_task1;
  7.      
  8.     uint32_t j;
  9.      
  10.      
  11.     __task void task1 (void) {
  12.      
  13.             os_evt_wait_and(0x0001, 0xffff);     //Espero por la señal (0x0001) de la tarea 'init'
  14.      
  15.                                                  //Una vez recibida la señal, continúo
  16.      
  17.             for(;;) {                                          
  18.      
  19.                     for (j = 0; j < 1000000; j++);     //Delay
  20.      
  21.                     toggleLedR();                      //Cambio el estado del LED (on - off)
  22.      
  23.             }
  24.      
  25.     }
  26.      
  27.     __task void init (void) {
  28.      
  29.             t_task1 = os_tsk_create(task1, 1);     //Crea la tarea 'task1' y guarda su ID en 't_task1'
  30.      
  31.             os_evt_set (0x0001, t_task1);          //Le envío a la tarea 'task1' un señal (0x0001)
  32.      
  33.             os_tsk_delete_self();                  //Borro esta tarea 'init' ya que no la voy a utilizar más
  34.      
  35.     }
  36.      
  37.     int main (void) {
  38.      
  39.             initLedG(); //Activar relojes de los puertos, activar los bits que correspondan, etc
  40.             initLedR(); //Activar relojes de los puertos, activar los bits que correspondan, etc
  41.  
  42.             os_sys_init(init);  //Inicializa el RTOS
  43.      
  44.     }

La diferencia con el anterior código que subí está en el main, inicializo los LEDs antes de llamar al sistema operativo. Ahora mismo no puedo probar este código, debería de funcionar así, pero quizás se me esté colando algo... ;-)

En todo caso, lo importante es inicializar los LEDs desde el main, antes de llamar al RTOS.

Saludos  8)
« Última modificación: 16 de Diciembre de 2016, 16:21:08 por mojo »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Manejando tareas en KL46Z
« Respuesta #7 en: 16 de Diciembre de 2016, 17:32:56 »
Pero es correcto entonces lo que pase xD.. Lo que yo no entiendo, es que necesidad hay de usar 1 tarea mas, luego borrarla, cuando podrias directamente iniciar la tarea task1 como hice. Y siendo el task1 quien cree el task2, total luego el task1 queda encerrado en el while como toda tarea y no va a ejecutarse mas la parte que esta fuera del while, simplemente cuando vuelva al task1 sigue dentro del while
Ya que dependiendo del manejo de memoria que posee el RTOS y que pueden ser de varios tipos y formas, podrias llegar a "inutilizar" una parte de la RAM.
(Este formato, lo encontre en la pagina de ARM, es decir el de iniciar el task1 y dentro de ese el task2 )

Y las demas es usar los:

os_evt_wait_and
os_evt_wait_or
os_evt_set

Ya que si tenes ciertas tareas, directamente dejas que corran y que sea el mismo RTOS que se encargue de cambiarlas cada tick, y nada de bloquear una tarea por completo hasta que termine y luego cambiar a la otra. Por esto es que di el ejemplo de 2 leds en el cual se hace toggle en cada uno.
Ahora si decidis hacer que al final de la tarea se devuelva el poder al RTOS deberia haber una especie de instruccion que lo haga, me refiero a que lo haga antes de que se le termine el tiempo de esa tarea. De esa forma apenas termina, que comienze la tarea que sea que este en orden, sin tener uno que seguir esperando por una tarea que no hace nada de nada.

Citar
En todo caso, lo importante es inicializar los LEDs desde el main, antes de llamar al RTOS.

Crei que era de comun conocimiento, que primero debes configurar todo el microcontrolador y sus modulos, y luego procedes a darle arranque a todo. Incluso es lo que habias realizado al comienzo con tu Systeminit() y lo de esas otras funciones que no se que eran y les puse un ¿? como comentario al no poder ver el codigo.

Desconectado Carl47D

  • PIC16
  • ***
  • Mensajes: 160
Re:Manejando tareas en KL46Z
« Respuesta #8 en: 16 de Diciembre de 2016, 17:41:10 »
Carl47D

Por requisitos de la Universidad estoy usando Keil uVision4, no el 5 , así que quizás no sea esa versión de RTOS. En todo caso ya solucioné el problema, lo que estaba haciendo mal era inicializar los LEDs dentro de una tarea del sistema operativo, cuando en realidad deberían inicializarse dentro del main, antes de iniciar el RTOS.

Finalmente el código quedaría así:
   
Código: C
  1. #include <rtl.h>
  2.      
  3.     #include <stdint.h>
  4.      
  5.      
  6.     OS_TID t_task1;
  7.      
  8.     uint32_t j;
  9.      
  10.      
  11.     __task void task1 (void) {
  12.      
  13.             os_evt_wait_and(0x0001, 0xffff);     //Espero por la señal (0x0001) de la tarea 'init'
  14.      
  15.                                                  //Una vez recibida la señal, continúo
  16.      
  17.             for(;;) {                                          
  18.      
  19.                     for (j = 0; j < 1000000; j++);     //Delay
  20.      
  21.                     toggleLedR();                      //Cambio el estado del LED (on - off)
  22.      
  23.             }
  24.      
  25.     }
  26.      
  27.     __task void init (void) {
  28.      
  29.             t_task1 = os_tsk_create(task1, 1);     //Crea la tarea 'task1' y guarda su ID en 't_task1'
  30.      
  31.             os_evt_set (0x0001, t_task1);          //Le envío a la tarea 'task1' un señal (0x0001)
  32.      
  33.             os_tsk_delete_self();                  //Borro esta tarea 'init' ya que no la voy a utilizar más
  34.      
  35.     }
  36.      
  37.     int main (void) {
  38.      
  39.             initLedG(); //Activar relojes de los puertos, activar los bits que correspondan, etc
  40.             initLedR(); //Activar relojes de los puertos, activar los bits que correspondan, etc
  41.  
  42.             os_sys_init(init);  //Inicializa el RTOS
  43.      
  44.     }


Que bueno que pudiste resolver el problema, la única parte que cambiaría es el delay que tienes en el for de task1, ese tiempo se podría utilizar para más tareas (en caso de que las tuvieras), en FreeRTOS hay una función que se llama vTaskDelay que sirve para lo mismo pero manda la tarea a estado bloqueado y la desbloquea al finalizar el tiempo que le indicas, mientras la tarea esta bloqueada se pueden despachar las demás tareas.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Manejando tareas en KL46Z
« Respuesta #9 en: 16 de Diciembre de 2016, 18:22:54 »
En ese RTOS tenes:

http://www.keil.com/support/man/docs/rlarm/rlarm_os_dly_wait.htm
http://www.keil.com/support/man/docs/rlarm/rlarm_os_itv_wait.htm

los cuales esperan cierta cantidad de ticks.

Pero para iniciar en el tema de los RTOS yo habia realizado ese delay en mi codigo xD.
Si habia problemas con iniciar las tareas, menos problemas nos ibamos a hacer metiendo mas funciones :P

Desconectado mojo

  • PIC10
  • *
  • Mensajes: 23
Re:Manejando tareas en KL46Z
« Respuesta #10 en: 16 de Diciembre de 2016, 19:46:32 »
KILLERJC

Efectivamente, tenías razón cuando me indicaste que debía inicializar los LEDs antes de iniciar el sistema operativo, pero por algún otro motivo me estaba fallando el programa y esto hizo que yo pensase que ese código no era válido :lol:

Reconozco la inutilidad de la tarea 'init'...  La pongo por inercia en verdad, ya que en los ejemplos que me han pasado hacen así.

Y con respecto a lo de inicializar todos los módulos, leds, etc...  Para mi no era tan obvio que había que hacerlo antes de entrar en el RTOS, ya que no tengo ninguna experiencia con esto prácticamente...  A partir de ahora ya lo tendré en cuenta xD

Carl47D

Como dice KILLERJC en su último mensaje, tienes esas funciones para dejar pasar los ciclos de reloj que a ti te interese mientras puedes ejecutar otras tareas sin problema.

Este RTOS creo que también tiene mutex implementados, con los que imagino que se podría bloquear el acceso a ciertas áreas de memoria y dejar esperando una tarea a que otra le permita el paso.



P.D. Creo que en algún sitio leí que no se puede utilizar 'os_dly_wait' y 'os_itv_wait' dentro de la misma tarea, pero no me hagais mucho caso... A lo mejor lo soñé xD

Saludos  :-)
« Última modificación: 16 de Diciembre de 2016, 19:51:45 por mojo »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Manejando tareas en KL46Z
« Respuesta #11 en: 16 de Diciembre de 2016, 19:54:48 »
P.D. Creo que en algún sitio leí que no se puede utilizar 'os_dly_wait' y 'os_itv_wait' dentro de la misma tarea, pero no me hagais mucho caso... A lo mejor lo soñé xD

En los links que pase:

Citar
You cannot mix the wait method os_itv_wait and os_dly_wait (or any other wait with a timeout) in the same task. RL-RTX maintains only one timer per task. It is used either for interval or delay waits.

Desconectado mojo

  • PIC10
  • *
  • Mensajes: 23
Re:Manejando tareas en KL46Z
« Respuesta #12 en: 16 de Diciembre de 2016, 20:02:46 »
Entonces es cierto... XD

¡¡ Gracias por vuestra ayuda !!  :mrgreen:

Desconectado Carl47D

  • PIC16
  • ***
  • Mensajes: 160
Re:Manejando tareas en KL46Z
« Respuesta #13 en: 16 de Diciembre de 2016, 21:16:25 »
En ese RTOS tenes:

http://www.keil.com/support/man/docs/rlarm/rlarm_os_dly_wait.htm
http://www.keil.com/support/man/docs/rlarm/rlarm_os_itv_wait.htm

los cuales esperan cierta cantidad de ticks.

Pero para iniciar en el tema de los RTOS yo habia realizado ese delay en mi codigo xD.
Si habia problemas con iniciar las tareas, menos problemas nos ibamos a hacer metiendo mas funciones :P
Disculpa xD, pensé que estaba en el código del primer post xD. No se si se note mucha diferencia usar el vTaskDelay (o equivalentes en RTX) en esta aplicación de una sola tarea, a menos que pongas a dormir al micro mientras no tenga tareas que despachar.

Citar
Carl47D

Como dice KILLERJC en su último mensaje, tienes esas funciones para dejar pasar los ciclos de reloj que a ti te interese mientras puedes ejecutar otras tareas sin problema.

Este RTOS creo que también tiene mutex implementados, con los que imagino que se podría bloquear el acceso a ciertas áreas de memoria y dejar esperando una tarea a que otra le permita el paso.

P.D. Creo que en algún sitio leí que no se puede utilizar 'os_dly_wait' y 'os_itv_wait' dentro de la misma tarea, pero no me hagais mucho caso... A lo mejor lo soñé xD

Gracias por los links, voy a Revisarlos a ver cual función se parece mas a la TaskDelay de FreeRTOS.

Saludos


 

anything