0% encontró este documento útil (0 votos)
155 vistas20 páginas

Tareas en Un RTOS

En esta práctica se codificó un programa sobre el sistema operativo freeRTOS capaz de ejecutar dos tareas simultáneas asignándoles una prioridad, un tiempo y una función.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
155 vistas20 páginas

Tareas en Un RTOS

En esta práctica se codificó un programa sobre el sistema operativo freeRTOS capaz de ejecutar dos tareas simultáneas asignándoles una prioridad, un tiempo y una función.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 20

CENTRO DE ENSEÑANZA TÉCNICA INDUSTRIAL

TECNÓLOGO EN SISTEMAS ELECTRÓNICOS Y TELECOMUNICACIONES

Sistemas Embebidos
Reporte de práctica
PRÁCTICA 8: TAREAS EN UN SISTEMA OPERATIVO

Alumno:
MIGUEL ANGEL MÁRQUEZ HERNÁNDEZ
Registro:
18100170
Profesor:
MARISCAL GUTIÉRREZ LUIS ALEJANDRO

Fecha:
11 de junio de 2022
Resumen
En esta práctica se codificó un programa sobre el sistema operativo freeRTOS capaz de ejecutar dos tareas
simultáneas, asignándoles una prioridad, un tiempo y una función.

Objetivos Generales:
• Conocer las bases de los sistemas operativos en tiempo real.
• Comprender el funcionamiento de las tareas en sistemas operativos de tiempo real.
Objetivos Específicos:
• Utilizar FreeRTOS para realizar un proceso en la tarjeta de desarrollo KL25z.
• Implementar dos tareas en un programa de FreeRTOS.
Marco Teórico:
SISTEMAS OPERATIVOS:
El sistema operativo de una computadora es el programa que se encarga de administrar el hardware y el resto
de las aplicaciones que corren en el equipo. Sin un sistema operativo, cada aplicación tendría que incluir su GUI
propia, así como todo el código necesario para controlar las funciones de bajo nivel de la computadora, como
el uso de disco, interfaces de red, periféricos, etc.

En vez de hacer eso, muchas tareas comunes como enviar un paquete de red o mostrar texto en algún
dispositivo de salida pueden ser delegadas al sistema operativo que sirve como intermediario entre las
aplicaciones y el hardware. El sistema operativo provee un método consistente y repetible para que las
aplicaciones interactúen con el hardware.

KERNEL:
El kernel es el núcleo de un sistema operativo y la interfaz entre el software y el hardware. Controla todos los
accesos al procesador y a la memoria, es el responsable de los drivers y puede acceder directamente al
hardware.

SHELL:
El shell o intérprete de comandos es el programa informático que provee una interfaz de usuario para acceder
a los servicios del sistema operativo.
Dependiendo del tipo de interfaz que empleen, los shells pueden ser:
• De líneas texto (CLI, Command-Line Interface, interfaz de línea de comandos),
• Gráficos (GUI, Graphical User Interface, interfaz gráfica de usuario),
• De lenguaje natural (NUI, Natural User Interface, interfaz natural de usuario).

SISTEMA OPERATIVO DE TIEMPO REAL (RTOS):


Los sistemas operativos de tiempo real son un tipo concreto de sistema desarrollado para ejecutar aplicaciones
que disponen de algún tipo de restricción temporal. Estas aplicaciones se caracterizan por poseer unos
requisitos específicos de ejecución y tiempo de respuesta, ya sea la de ejecutar las acciones en menos de un
tiempo predefinido o la de ejecutarlas a intervalos determinados.
CARACTERÍSTICAS DE UN RTOS:
Determinismo: Realizan acciones dentro de un intervalo de tiempo acotado.
Sensibilidad: Es el tiempo que se tarda el sistema operativo en reconocer una interrupción e iniciar la ISR, los
RTOS son altamente sensibles
Control del usuario: Los usuarios tienen mayor control sobre los procesos
Fiabilidad: En los RTOS una falla puede ser catastrófica, por lo que no pueden permitirse como en los sistemas
normales.
Scheduling basado en prioridad: Las tareas de más alta prioridad se ejecutan primero, lo que garantiza que los
RTOS siempre ejecuten la tarea más importante.

FREERTOS:
Es un sistema operativo de tiempo real para sistemas embebidos. FreeRTOS tiene un tamaño relativamente
pequeño. El núcleo mínimo de FreeRTOS consiste en tres archivos .c y un puñado de archivos .h. Que suman
aproximadamente 9000 líneas de código.

• Tareas: casi la mitad del núcleo de FreeRTOS está orientado al manejo de tareas.
• Comunicación: Las tareas e interrupciones utilizan colas para intercambiar información.
• Gestión del hardware: 6% del código núcleo de FreeRTOS permite que el sistema operativo interactúe
con el hardware.

REGISTROS UTILIZADOS:

PIN CONTROL REGISTER N PORTX->PCRN


PORT DATA DIRECTION REGISTER GPIO-> PDDR

GPIO-> PCOR

GPIO-> PSOR
FUNCIONES UTILIZADAS:
xTaskCreate();
Crea una nueva tarea y la añade a la lista de tareas que están listas para ejecutarse.
Ejemplo:

void vTaskCode( void * pvParameters )


{
/* The parameter value is expected to be 1 as 1 is passed in the
pvParameters value in the call to xTaskCreate() below.
configASSERT( ( ( uint32_t ) pvParameters ) == 1 );

for( ;; )
{
/* Task code goes here. */
}
}
/* Function that creates a task. */
void vOtherFunction( void )
{
BaseType_t xReturned;
TaskHandle_t xHandle = NULL;

/* Create the task, storing the handle. */


xReturned = xTaskCreate(
vTaskCode, /* Function that implements the task.
*/
"NAME", /* Text name for the task. */
STACK_SIZE, /* Stack size in words, not bytes. */
( void * ) 1, /* Parameter passed into the task. */
tskIDLE_PRIORITY,/* Priority at which the task is
created. */
&xHandle ); /* Used to pass out the created
task's handle. */

if( xReturned == pdPASS )


{
/* The task was created. Use the task's handle to delete the
task. */
vTaskDelete( xHandle );
}
}

vTaskStartScheduler();
Habilita el secuenciador de tareas.
Ejemplo:
void vAFunction( void )
{
// Tasks can be created before or after starting the RTOS
scheduler
xTaskCreate( vTaskCode,
"NAME",
STACK_SIZE,
NULL,
tskIDLE_PRIORITY,
NULL );
// Start the real time scheduler.
vTaskStartScheduler();
// Will not get here unless there is insufficient RAM.
}

vTaskDelay();
Bloquea una tarea por el número de ticks especificado como parámetro.
Ejemplo:
void vTaskFunction( void * pvParameters )
{
/* Block for 500ms. */
const TickType_t xDelay = 500 / portTICK_PERIOD_MS;

for( ;; )
{
/* Simply toggle the LED every 500ms, blocking between each
toggle. */
vToggleLED();
vTaskDelay( xDelay );
}
}
Desarrollo Teórico:
FUNCIÓN PRINCIPAL:
DIAGRAMA DE FLUJO:

PSEUDOCÓDIGO:
FUNCION PRINCIPAL
CREAR TAREA 1
CREAR TAREA 2
INICIALIZAR SCHEDULER
FIN
TAREA 1 (MOSTRAR IMAGEN):
DIAGRAMA DE FLUJO:
PSEUDOCÓDIGO:
TAREA 1
INICIALIZAR MATRIZ
LIMPIAR MATRIZ
IMPRIMIR “ESTA ES MI PRIMER TAREA”

SI CONTADOR == 0
PARA I = 1; I<= 8; I++
ROW_DATA = 0
PARA j = 0; j< 8; j++
ROW_DATA = |= (mono2[i-1][j]<< j)
FIN PARA

ROW_SET(I)
COL_WRITE(ROW_DATA)
VTASKDELAY(2)
MATRIX_CLEAR()
FIN PARA

SI CONTADOR == 1
PARA I = 1; I<= 8; I++
ROW_DATA = 0
PARA j = 0; j< 8; j++
ROW_DATA = |= (mono1[i-1][j]<< j)
FIN PARA

ROW_SET(I)
COL_WRITE(ROW_DATA)
VTASKDELAY(2)
MATRIX_CLEAR()
FIN PARA
FIN TAREA 1
TAREA 2 (LEER PUSH BUTTON):
DIAGRAMA DE FLUJO:
PSEUDOCÓDIGO:

TAREA 2
INICIALIZAR SWITCH
IMPRIMIR “ESTA ES MI SEGUNDA TAREA”
PREV_SWITCHSTATE = CURR_SWITCHSTATE
CURR_SWITCHSTATE = PTE21
RISING_EDGE = 0
SI CURR_SWITCHSTATE != PREV_SWITCHSTATE && CURR_SWITCHSTATE == 1
RISING EDGE = 1
COUNTER++
SI COUNTER == 2
COUNTER = 0
FIN SI
FIN SI
VTASKDELAY(50)
FIN TAREA 2

Desarrollo Práctico:
CÓDIGO FUENTE:
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of NXP Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**
* @file MKL25Z4_Task.c
* @brief Application entry point.
*/
#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "MKL25Z4.h"
#include "fsl_debug_console.h"
#include <stdbool.h>

/* FreeRTOS kernel includes. */


#include "FreeRTOS.h"
#include "task.h"
#define C1 5
#define C2 10
#define C3 11
#define C4 0
#define C5 3
#define C6 3
#define C7 10
#define C8 11

#define F1 7
#define F2 6
#define F3 5
#define F4 4
#define F5 8
#define F6 4
#define F7 9
#define F8 2

void matrix_init(void);
void test_pixel(uint8_t row, uint8_t col);
void matrix_clear(void);
void matrix_set(void);

void row_set(uint8_t);
void row_clear(uint8_t data);
void col_write(uint8_t data);
void switch_init(void);

// filas, columnas
bool heart[8][8] = {
{0,1,1,0,0,1,1,0},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1},
{1,1,1,1,1,1,1,1},
{0,1,1,1,1,1,1,0},
{0,0,1,1,1,1,0,0},
{0,0,0,1,1,0,0,0},
{0,0,0,0,0,0,0,0}
};

bool square[8][8] = {
{0,0,0,0,0,0,0,0},
{0,1,1,1,1,1,1,0},
{0,1,1,1,1,1,1,0},
{0,1,1,1,1,1,1,0},
{0,1,1,1,1,1,1,0},
{0,1,1,1,1,1,1,0},
{0,1,1,1,1,1,1,0},
{0,0,0,0,0,0,0,0}
};

bool weird[8][8] = {
{0,0,0,0,0,0,0,0},
{0,1,1,1,0,0,0,0},
{0,1,1,1,0,0,0,0},
{0,1,1,1,0,0,0,0},
{0,0,0,0,1,1,1,0},
{0,0,0,0,1,1,1,0},
{0,0,0,0,1,1,1,0},
{0,0,0,0,0,0,0,0}
};

bool diana[8][8] = {
{0,0,0,0,0,0,0,0},
{0,1,1,1,0,0,0,0},
{0,1,1,0,1,0,0,0},
{0,1,1,0,0,1,0,0},
{0,1,1,0,0,1,0,0},
{0,1,1,0,0,1,0,0},
{0,1,1,1,1,0,0,0},
{0,0,0,0,0,0,0,0}
};

bool mono1[8][8] = {
{0,0,1,1,1,0,0,0},
{0,0,1,1,1,0,0,0},
{0,0,0,1,0,0,0,0},
{0,0,1,1,1,0,0,0},
{0,1,0,1,0,1,0,0},
{0,0,0,1,0,0,0,0},
{0,0,1,0,1,0,0,0},
{0,0,1,0,1,0,0,0}
};

bool mono2[8][8] = {
{0,0,1,1,1,0,0,0},
{0,0,1,1,1,0,0,0},
{0,1,0,1,0,1,0,0},
{0,0,1,1,1,0,0,0},
{0,0,0,1,0,0,0,0},
{0,0,1,1,1,0,0,0},
{0,1,0,0,0,1,0,0},
{1,0,0,0,0,0,1,0}
};

bool pene[8][8] = {
{0,0,0,1,1,0,0,0},
{0,0,1,1,1,1,0,0},
{0,0,0,1,1,0,0,0},
{0,0,0,1,1,0,0,0},
{0,0,0,1,1,0,0,0},
{0,1,1,1,1,1,1,0},
{1,1,1,1,1,1,1,1},
{1,1,1,0,0,1,1,1}
};

bool switch_ispressed = 0;
bool curr_switchstate = 0;
bool prev_switchstate = 0;
bool rising_edge = 0;
int counter = 0;

/*
* @brief Application entry point.
*/
/* Task priorities. */

#define my_task_PRIORITY_1 (configMAX_PRIORITIES - 1)


#define my_task_PRIORITY_2 (configMAX_PRIORITIES - 2)

/***************************
* Prototypes
**************************/
static void my_First_task(void *pvParameters);
static void my_Second_task(void *pvParameters);

int main(void) {

/* Init board hardware. */


BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
BOARD_InitDebugConsole();

if (xTaskCreate(my_First_task, "The_first_task", configMINIMAL_STACK_SIZE + 10, NULL, my_task_PRIORITY_1, NULL) !=


pdPASS)
{
PRINTF("First Task creation failed!.\r\n");
while (1)
;
}
if (xTaskCreate(my_Second_task, "The_Second_task", configMINIMAL_STACK_SIZE + 10, NULL, my_task_PRIORITY_2, NULL) !=
pdPASS)
{
PRINTF("Second task creation failed!.\r\n");
while (1)
;
}
vTaskStartScheduler();
while(1)
{
}
return 0 ;
}

static void my_First_task(void *pvParameters)


{
for (;;)
{
PRINTF("Hello This is my First Task\r\n");

int row_data = 0;
matrix_init();

matrix_clear();
if (counter == 0){
for(int i = 1; i <= 8; i++){
row_data = 0;
for(int j = 0; j < 8; j++){
row_data |= (mono2[i-1][j]) << (j);
}
row_set(i);
col_write(row_data);
vTaskDelay(2);
matrix_clear();
}
}
else if (counter == 1){
for(int i = 1; i <= 8; i++){
row_data = 0;
for(int j = 0; j < 8; j++){
row_data |= (mono1[i-1][j]) << (j);
}
row_set(i);
col_write(row_data);
vTaskDelay(2);
matrix_clear();
}
}
else if (counter == 2){
for(int i = 1; i <= 8; i++){
row_data = 0;
for(int j = 0; j < 8; j++){
row_data |= (pene[i-1][j]) << (j);
}
row_set(i);
col_write(row_data);
vTaskDelay(2);
matrix_clear();
}
}
else if (counter == 3){
for(int i = 1; i <= 8; i++){
row_data = 0;
for(int j = 0; j < 8; j++){
row_data |= (heart[i-1][j]) << (j);
}
row_set(i);
col_write(row_data);
vTaskDelay(2);
matrix_clear();

}
}
else if (counter == 4){
for(int i = 1; i <= 8; i++){
row_data = 0;
for(int j = 0; j < 8; j++){
row_data |= (square[i-1][j]) << (j);
}
row_set(i);
col_write(row_data);
vTaskDelay(2);
matrix_clear();

}
}
else if (counter == 5){
for(int i = 1; i <= 8; i++){
row_data = 0;
for(int j = 0; j < 8; j++){
row_data |= (weird[i-1][j]) << (j);
}
row_set(i);
col_write(row_data);
vTaskDelay(2);
matrix_clear();

}
}

static void my_Second_task(void *pvParameters)


{
for (;;)
{
PRINTF("Hello This is my Second Task\r\n");
switch_init();

prev_switchstate = curr_switchstate;
curr_switchstate = !(GPIOE -> PDIR & (1<<21));
rising_edge = 0;

if (curr_switchstate != prev_switchstate && curr_switchstate == 0 ){

// flanco de bajada
}
else if (curr_switchstate == prev_switchstate){

// no hay cambio

}
else if(curr_switchstate != prev_switchstate && curr_switchstate == 1){

rising_edge = 1;
counter++;
if (counter == 6){
counter = 0;
}

}
// if(switch_ispressed){
// PRINTF("Switch presionado\r\n");
// }

vTaskDelay(50);
}
}
//pte21

void matrix_init(void){

/*
* PTC
* 11 10 6 5 4 3 0 7
* C8 C7 F2 C1 F4 C6 C4 F1
*
* PTB
* 8 9 10 11
* F5 F7 C2 C3
*
* PTE
* 2 3 4 5
* F8 C5 F6 F3
*/

/*
*
* F1 F2 F3 F4 F5 F6 F7 F8
* PTC7 PTC6 PTE5 PTC4 PTB8 PTE4 PTB9 PTE2
*
* C1 C2 C3 C4 C5 C6 C7 C8
* PTC5 PTB10 PTB11 PTC0 PTE3 PTC3 PTC10 PTC11
*/

SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK|SIM_SCGC5_PORTB_MASK|SIM_SCGC5_PORTE_MASK;

PORTC -> PCR[C8] |= PORT_PCR_MUX(1);


PORTC -> PCR[C7] |= PORT_PCR_MUX(1);
PORTC -> PCR[F2] |= PORT_PCR_MUX(1);
PORTC -> PCR[C1] |= PORT_PCR_MUX(1);
PORTC -> PCR[F4] |= PORT_PCR_MUX(1);
PORTC -> PCR[C6] |= PORT_PCR_MUX(1);
PORTC -> PCR[C4] |= PORT_PCR_MUX(1);
PORTC -> PCR[F1] |= PORT_PCR_MUX(1);

PORTB -> PCR[F5] |= PORT_PCR_MUX(1);


PORTB -> PCR[F7] |= PORT_PCR_MUX(1);
PORTB -> PCR[C2] |= PORT_PCR_MUX(1);
PORTB -> PCR[C3] |= PORT_PCR_MUX(1);

PORTE -> PCR[F8] |= PORT_PCR_MUX(1);


PORTE -> PCR[C5] |= PORT_PCR_MUX(1);
PORTE -> PCR[F6] |= PORT_PCR_MUX(1);
PORTE -> PCR[F3] |= PORT_PCR_MUX(1);

GPIOC-> PDDR |= (1<<C8)|(1<<C7)|


(1<<F2)|(1<<C1)|
(1<<F4)|(1<<C6)|
(1<<C4)|(1<<F1);

GPIOB-> PDDR |= (1<<F5)|(1<<F7)|


(1<<C2)|(1<<C3);

GPIOE-> PDDR |= (1<<F8)|(1<<C5)|


(1<<F6)|(1<<F3);
}

void row_set(uint8_t data){


switch (data){
case 1:
GPIOC-> PSOR |= (1<<F1);
break;
case 2:
GPIOC-> PSOR |= (1<<F2);
break;
case 3:
GPIOE-> PSOR |= (1<<F3);
break;
case 4:
GPIOC-> PSOR |= (1<<F4);
break;
case 5:
GPIOB-> PSOR |= (1<<F5);
break;
case 6:
GPIOE-> PSOR |= (1<<F6);
break;
case 7:
GPIOB-> PSOR |= (1<<F7);
break;
case 8:
GPIOE-> PSOR |= (1<<F8);
break;
}
}

void matrix_clear(void){
// FILAS A 0
GPIOC-> PCOR |= (1<<F1)|(1<<F2)|
(1<<F4);

GPIOB-> PCOR |= (1<<F5)|(1<<F7);


GPIOE-> PCOR |= (1<<F8)|(1<<F6)|
(1<<F3);

// COLUMNAS A 0
GPIOC-> PSOR |= (1<<C8)|(1<<C7)|(1<<C1)|(1<<C6)|(1<<C4);

GPIOB-> PSOR |= (1<<C2)|(1<<C3);

GPIOE-> PSOR |= (1<<C5);

void col_write(uint8_t data){

if (data & 0x01){


GPIOC-> PCOR |= (1<<C1);
}
if (data & 0x02){
GPIOB-> PCOR |= (1<<C2);
}
if (data & 0x04){
GPIOB-> PCOR |= (1<<C3);
}
if (data & 0x08){
GPIOC-> PCOR |= (1<<C4);
}
if (data & 0x10){
GPIOE-> PCOR |= (1<<C5);
}
if (data & 0x20){
GPIOC-> PCOR |= (1<<C6);
}
if (data & 0x40){
GPIOC-> PCOR |= (1<<C7);
}
if (data & 0x80){
GPIOC-> PCOR |= (1<<C8);
}
}

void switch_init(void){

// CONFIGURAR PINES COMO GPIO


PORTE -> PCR[21] |= (1<<8);

// CONFIGURAR PINES COMO ENTRADA


GPIOE-> PDDR &=~ (1<<21);

// HABILITAR PULL
PORTE -> PCR[21] |= (1<<1);

// SELECCIONAR PULL UP
PORTE -> PCR[21] |= (1<<0);
}
Ejecución:
MONO 1:

MONO 2:
CONSOLA:
Conclusiones:
Los datos obtenidos de la ejecución en físico y del log de la consola indican que la práctica fue realizada con
éxito ya que se pudo lograr que dos tareas corrieran de manera simultánea en la KL25Z. En la práctica se
utilizaron conocimientos adquiridos a lo largo de la carrera como lo son el manejo de arreglos, pines de gpio,
configuración de registros, así como conocimientos nuevos (RTOS, tareas) para codificar un programa que
realizara dos tareas simultáneas. La tarea 1 se encarga de mostrar un arreglo de 8x8 en la matriz de leds,
mientras que la tarea 2 se encarga de detectar los flancos de subida de un interruptor conectado a PTE21. Cada
que la tarea 2 detecta que se presiona el switch, la tarea 1 cambia la imagen que se muestra en la matriz de
leds.

Al finalizar la práctica aprendí a configurar el entorno de desarrollo para trabajar con freeRTOS, así como a crear
tareas y asignarles una prioridad y un proceso.

REFERENCIAS:
FREERTOS. (s.f.). Real time operating system for microcontrollers. Obtenido de
https://www.freertos.org/index.html

Apéndice:
FIRMA:

También podría gustarte