2mp.conae.gov.ar i [email protected] - comisión nacional de … · 2016-02-24 · tabla de...
TRANSCRIPT
2mp.conae.gov.ar I [email protected]
Manual Misión SAE CIAA POSIX. VERSION 1.1
Tabla de contenidos
1. [ Introducción ] .................................................................................................................................... 4
2. [POSIX ] ................................................................................................................................................ 4
3. [CIAA POSIX ] ....................................................................................................................................... 4
1.1. ciaaPOSIX_open ........................................................................................................................... 4
1.1.1. Ejemplo de aplicación ............................................................................................................... 5
1.2. ciaaPOSIX_ioctl............................................................................................................................. 6
1.2.1. UART ......................................................................................................................................... 6
1.2.2. I2C ............................................................................................................................................. 7
1.2.3. Entradas y salidas digitales ....................................................................................................... 7
1.2.4. Ejemplo de aplicación ............................................................................................................... 7
1.3. ciaaPOSIX_read y ciaaPOSIX_write .............................................................................................. 8
1.3.1. Ejemplo de aplicación ............................................................................................................... 8
1.4. ciaaPOSIX_close ........................................................................................................................... 8
1.5. Ejemplos de aplicación ................................................................................................................. 9
1.5.1. Ejemplo 1 - GPIO salidas ........................................................................................................... 9
1.5.2. Ejemplo 2 - GPIO entradas ...................................................................................................... 12
1.5.3. Ejemplo 3 - UART .................................................................................................................... 14
Manual POSIX Versión 1.0
4
1. [ Introducción ] En los ejemplos de CIAA-Frimware se utilizan funciones con el prefijo “ciaaPOSIX_”, está guía pretende explicar el funcionamiento de cada una de esas instrucciones.
2. [POSIX ] El nombre POSIX es un acrónimo de “Portable Operating System Interface”, en donde la X proviene de UNIX, dando un marco de pertenencia. POSIX es una norma que especifica nomenclatura, funciones, servicios y demás recursos que sean necesarios para facilitar la portabilidad de las aplicaciones entre distintos sistemas operativos.
3. [CIAA POSIX ] El CIAA Firmware adopta algunos conceptos de POSIX para facilitar al programador de aplicaciones un acceso a los recursos de hardware fácil y principalmente portable. Por este motivo es posible compilar las aplicaciones tanto para arquitectura x86 y ejecutarlas en la PC como para Cortex M4 y ejecutarlas en la ECU-CIAA-NXP. Como no se adopto de forma completa el estándar POSIX se dice que CIAA- Firmware es “POSIX Like”. Dentro de las funcionalidad del entorno CIAA, podemos encontrar cinco funciones para realizar el control total sobre cualquier tipo de periférico incorporado al Firmware. Las funciones son:
ciaaPOSIX_open
ciaaPOSIX_ioctl
ciaaPOISX_read
ciaaPOSIX_write
ciaaPOSIX_close La definición de los prototipos de las funciones se encuentra en el archivo “ciaaPOSIX_stdio.h” dentro de la carpeta “Firmware\modules\posix\inc\”. A continuación se detallarán cada una de ellas
1.1. ciaaPOSIX_open Prototipo de la función:
int32_t ciaaPOSIX_open(char const * path, uint8_t oflag);
Recibe como parámetro:
path: la dirección del periférico.
oflag: el modo de apertura del periférico. Retorna un número negativo si falla y en caso de éxito un numero que identifica al descriptor del periférico seleccionado, a este número se lo llama “file descriptor”.
Manual POSIX Versión 1.0
5
A continuación se listan los periféricos presentes en EDU-CIAA-NXP, sus paths y sus ubicaciónes.
Periférico Path Ubicación
entradas digitales /dev/dio/in/0 Teclas
salidas digitales /dev/dio/out/0 LEDs
UART 1 /dev/serial/uart/1 UART USB
UART 2 /dev/serial/uart/2 UART slot expansión
I2C * /dev/i2c/0 I2C slot expansión
* Solo presente en el Firmware distribuido para MISIÓN SAE Las opciones de apertura y sus valores son:
Solo lectura O_RDONLY
Solo Escritura O_WRONLY
Lectura y escritura O_RDWR
Interfaz no bloqueante O_NONBLOCK
1.1.1. Ejemplo de aplicación Ejemplo de apertura de periféricos:
int32_t teclado;
int32_t display;
int32_t uartUSB;
int32_t i2cExpansion;
teclado = ciaaPOSIX_open("/dev/dio/in/0", O_RDONLY);
display = ciaaPOSIX_open("/dev/dio/out/0", O_RDWR);
uartUSB = ciaaPOSIX_open("/dev/serial/uart/1", O_RDWR | O_NONBLOCK);
i2cExpansion = ciaaPOSIX_open("/dev/i2c/0", O_RDWR);
En el código presentado se abrieron los siguientes periféricos:
Periférico Configuración File descriptor
Entrada digital Solo lectura teclado
Salidas digitales Lectura y escritura display
UART 1 Lectura y escritura no bloqueante uartUSB
I2C Lectura y escritura i2cExpansion
Manual POSIX Versión 1.0
6
1.2. ciaaPOSIX_ioctl Prototipo de la función:
int32_t ciaaPOSIX_ioctl(int32_t fildes, int32_t request, void* param);
Recibe como parámetro:
fildes: el número de file descriptor devuelto por la función ciaaPOSIX_open.
request: el código de configuración que se desea modificar (depende del dispositivo).
param: el valor de configuración. Retorna un -1 si falla y en caso de éxito otro número. A continuación se listan los códigos “request” más utilizados para cada periférico y sus posibles valores.
1.2.1. UART
Codigo Valores Detalle
ciaaPOSIX_IOCTL_SET_BAUDRATE ciaaBAUDRATE_300 ciaaBAUDRATE_600 ciaaBAUDRATE_1200 ciaaBAUDRATE_1800 ciaaBAUDRATE_2400 ciaaBAUDRATE_4800 ciaaBAUDRATE_9600 ciaaBAUDRATE_14400 ciaaBAUDRATE_19200 ciaaBAUDRATE_38400 ciaaBAUDRATE_57600 ciaaBAUDRATE_115200 ciaaBAUDRATE_230400 ciaaBAUDRATE_460800 ciaaBAUDRATE_921600
Selecciona la tasa de transferencia de bits de la UART.
ciaaPOSIX_IOCTL_SET_FIFO_TRIGGER_LEVEL ciaaFIFO_TRIGGER_LEVEL0 ciaaFIFO_TRIGGER_LEVEL1 ciaaFIFO_TRIGGER_LEVEL2 ciaaFIFO_TRIGGER_LEVEL3
Selecciona la cantidad de bytes recibidos antes de producir una interrupción (depende del hardware)
Estas configuración están detalladas en el archivo “ciaaPOSIX_ioctl_serial.h”
Manual POSIX Versión 1.0
7
1.2.2. I2C
Codigo Valores Detalle
ciaaPOSIX_IOCTL_SET_CLOCKRATE ciaaCLOCKRATE_100000 ciaaCLOCKRATE_400000
Selecciona la tasa de transferencia de bits del I2C.
ciaaPOSIX_IOCTL_SET_SLAVEADD <valor dirección del esclavo> Configura la dirección del esclavo
ciaaPOSIX_IOCTL_SET_REGISTERADD <valor dirección de registro del dispositivo esclavo>
Configura el número de registro interno del esclavo.
ciaaPOSIX_IOCTL_SET_REGISTERADDWIDTH ciaaREGISTERADDWIDTH_0bits ciaaREGISTERADDWIDTH_8bits ciaaREGISTERADDWIDTH_16bits ciaaREGISTERADDWIDTH_24bits ciaaREGISTERADDWIDTH_32bits
Cantidad de bits de dirección de los registros del dispositivo esclavo
Estas configuración están detalladas en el archivo “ciaaPOSIX_ioctl_i2c.h”
1.2.3. Entradas y salidas digitales Entradas y salidas digitales: No poseen parámetros de configuración
1.2.4. Ejemplo de aplicación Ejemplo de configuración de UART:
static int32_t fd_uart1;
fd_uart1 = ciaaPOSIX_open("/dev/serial/uart/1", ciaaPOSIX_O_RDWR);
ciaaPOSIX_ioctl(fd_uart1, ciaaPOSIX_IOCTL_SET_BAUDRATE, (void
*)ciaaBAUDRATE_115200);
ciaaPOSIX_ioctl(fd_uart1, ciaaPOSIX_IOCTL_SET_FIFO_TRIGGER_LEVEL, (void
*)ciaaFIFO_TRIGGER_LEVEL3);
Manual POSIX Versión 1.0
8
1.3. ciaaPOSIX_read y ciaaPOSIX_write Prototipo de las funciones:
ssize_t ciaaPOSIX_read(int32_t fildes, void * buf, size_t nbyte);
ssize_t ciaaPOSIX_write(int32_t fildes, void const * buf, size_t nbyte);
Recibe como parámetro:
fildes: el número de file descriptor devuelto por la función ciaaPOSIX_open.
buf: el puntero a la dirección de memoria en donde se almacenarán los datos recibidos (read) o los datos para ser enviados (write).
nbyte: el numero de bytes a recibir (read) o enviar (write) Retorna un -1 si falla y en caso de éxito el valor de bytes recibidos o enviados.
1.3.1. Ejemplo de aplicación Un ejemplo de utilización de las funciones read y write
static int32_t fd_in;
static int32_t fd_out;
uint8_t inputs = 0;
fd_in = ciaaPOSIX_open("/dev/dio/in/0", ciaaPOSIX_O_RDONLY);
fd_out = ciaaPOSIX_open("/dev/dio/out/0", ciaaPOSIX_O_RDWR);
ciaaPOSIX_read(fd_in, &inputs, 1);
ciaaPOSIX_write(fd_out, &inputs, 1);
En este ejemplo se escriben (ciaaPOSIX_write) en los pines de salida del puerto 0 (fd_out) los mismos valores de los pines de entrada del puerto 0 (fd_in).
1.4. ciaaPOSIX_close Prototipo de las funciones:
int32_t ciaaPOSIX_close(int32_t fildes);
Recibe como parámetro:
fildes: el número de file descriptor devuelto por la función ciaaPOSIX_open. Retorna un -1 si falla y en caso de éxito 0.
Manual POSIX Versión 1.0
9
1.5. Ejemplos de aplicación
1.5.1. Ejemplo 1 - GPIO salidas Nombre del proyecto: ejemplo_01_GPIO_out Esta aplicación se controla el estado de los LEDs provistos en la placa EDU-CIAA-NXP y se introducen conceptos de arquitetura de firmware. El ejemplo comienza en la función main, inicializando el sistema operativo y el ciaa kernel. La primer tarea que ejecuta el sistema operativo es “InitTask” en donde se cargan los drivers de GPIOs y UARTs. Además se configura la UART USB con un baudrate de 115200 bit/s. Por último se activa el ciclo de ejecución de la tarea “PeriodicTask” al ejecutar la línea:
SetRelAlarm(ActivatePeriodicTask, BASETIEMPO, BASETIEMPO);
En donde se indica que la tarea PeriodicTask tendrá un ciclo de ejecución permanente, con su base de tiempo definida en un valor de 10ms (en el archivo main.h se puede encontrar que el valor de BASETIEMPO). La tarea periódica tiene la siguiente estructura:
TASK(PeriodicTask)
{
if ( Es_la_primera_vez_que_se_ejecuta ) {
// hacer algo la primera vez que se ejecuta la tarea
} else {
// hace algo en en cada ciclo
}
TerminateTask();
}
Es necesario avisarle al SO que termino el ciclo de ejecución, para eso se utiliza la función:
TerminateTask();
Manual POSIX Versión 1.0
10
Muchas veces es necesario inicializar valores de variables o dispositivos externos, para eso se utiliza una pequeña sección del programa que se ejecutará por única vez al inicio del programa. Por ejemplo se puede utilizar el siguiente:
static sistema_inicializado = NO;
if (sistema_inicializado == NO ) {
// rutina de inicialización
if ( finalizo_la_rutina_de_inicilizacion ) {
sistema_inicializado = SI;
}
}
El atributo static de la variable HW_inicializado significa que se guardara el valor de tal variable aún cuando se salga y se vuelva a entrar en la función (se guarda el valor como si fuera una variable global, pero se accede solamente dentro de la función). En el ciclo de ejecución permanente de la tarea se realiza acciones cada cierto periodo, se utilizan contadores y una estructura como la siguiente para ejecutar parte del código en momentos determinados:
static int contador = 0;
contador++;
if ( !( contador % (500/BASETIEMPO)) ) {
//accion que se ejecutara cada 500 ms
}
De debe resetear el contador cuando el mismo alcance su valor final, en este caso cada 1 segundo.
contador++;
if ( contador >= (1000/BASETIEMPO) ){
contador = 0;
}
Manual POSIX Versión 1.0
11
Para facilitar las operaciones con los leds, se utilizan máscaras. En las mascaras cada bit representa la posición del bit de estado de un LED. Por ejemplo la máscara del LED 1 de la ED-CIAA-NXP (ver cuadro) es igual a 0x08, siendo que el estado del led se indica en el bit número 3 del byte. Pines de entrada
bits 7 6 5 4 3 2 1 0
tecla 4 3 2 1
Pines de salida
bits 7 6 5 4 3 2 1 0
LEDs 3 2 1 B G R
Operaciones con máscaras:
Poner en 1 el bit 0 del byte estado
mascara = 0x01
estado |= mascara
Poner en 0 el bit 1 del byte estado
mascara = 0x02
estado &= mascara
Invertir estado de los bits 1 y 0 del byte estado
mascara = 0x03
estado ^= mascara
Manual POSIX Versión 1.0
12
1.5.2. Ejemplo 2 - GPIO entradas Nombre del proyecto: ejemplo_02_GPIO_in El ejemplos es idéntico al programa anterior, con algunas modificaciones orientadas a ordenar el código. Principalmente la diferencia está en implementar 3 etapas para resolver un problema, sean: leer los datos de entrada, procesarlos y generar las salidas correspondientes. Ahora en la tarea periódica están las funciones:
TASK(PeriodicTask) {
LeerEntradas();
Procesar();
EscribirSalidas();
TerminateTask();
}
De esta forma solo existe un lugar en el programa principal que tiene acceso a leer el hardware y otro lugar con acceso a escribir el hardware. Esto hace que sea más fácil testearlo. Se detallan a continuación las funciones presentadas:
int LeerEntradas(void) {
ciaaPOSIX_read(fd_teclado, &estado_teclas, 1);
ciaaPOSIX_read(fd_leds, &estado_leds, 1);
return 1;
}
Hace una lectura del estado de los LEDs y de las teclas
int EscribirSalidas(void) {
ciaaPOSIX_write(fd_leds, &estado_leds, 1);
return 1;
}
Escribe el estado de LEDs deseado
Manual POSIX Versión 1.0
13
int Procesar(void) {
static int contador = 0;
contador++;
if ( GPIO_GET(estado_teclas, TECLA_2) )
GPIO_SET(estado_leds, LED_1);
else
GPIO_CLEAR(estado_leds, LED_1);
return 1;
}
La función que proceso el estado de las entradas digitales actúa sobre los LEDs.
Manual POSIX Versión 1.0
14
1.5.3. Ejemplo 3 - UART Nombre del proyecto: ejemplo_03_UART En este caso se propone enviar un mensaje predefinido en el programa, y de forma repetitiva interceptar los caracteres recibidos por el puerto serie USB y retransmitirlos por el mismo, haciendo un eco de los datos recibidos. Envió de mensaje predefinido:
char mensaje[] = "Mensaje enviado por UART\n";
ciaaPOSIX_write(fd_uart_usd, mensaje, ciaaPOSIX_strlen(mensaje));
Retransmisión del mensaje recibido:
int8_t buf[20];
int32_t ret;
while(1)
{
ret = ciaaPOSIX_read(fd_uart_usd, buf, 20);
if(ret > 0) {
ciaaPOSIX_write(fd_uart_usd, buf, ret);
}
}
En este ejemplo se presentaron 2 tipos de tarea, una periódica de mayor prioridad y una de ejecución continua de menor prioridad. Los detalles y características de las mismas se explicarán en profundidad en el manual de FreeOSEK.