SAE-MAN-0008-B - Manual POSIX

Anuncio
2mp.conae.gov.ar I sae.2mp@conae.gov.a
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
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”.
4
Manual POSIX
Versión 1.0
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
Solo Escritura
Lectura y escritura
Interfaz no bloqueante
O_RDONLY
O_WRONLY
O_RDWR
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
Entrada digital
Solo lectura
Salidas digitales
Lectura y escritura
UART 1
Lectura y escritura no bloqueante
I2C
Lectura y escritura
File descriptor
teclado
display
uartUSB
i2cExpansion
5
Manual POSIX
Versión 1.0
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
ciaaPOSIX_IOCTL_SET_BAUDRATE
Valores
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
ciaaPOSIX_IOCTL_SET_FIFO_TRIGGER_LEVEL ciaaFIFO_TRIGGER_LEVEL0
ciaaFIFO_TRIGGER_LEVEL1
ciaaFIFO_TRIGGER_LEVEL2
ciaaFIFO_TRIGGER_LEVEL3
Estas configuración están detalladas en el archivo “ciaaPOSIX_ioctl_serial.h”
Detalle
Selecciona la tasa de
transferencia de bits de la
UART.
Selecciona la cantidad de
bytes recibidos antes de
producir una interrupción
(depende del hardware)
6
Manual POSIX
Versión 1.0
1.2.2. I2C
Codigo
ciaaPOSIX_IOCTL_SET_CLOCKRATE
Valores
ciaaCLOCKRATE_100000
ciaaCLOCKRATE_400000
<valor dirección del esclavo>
ciaaPOSIX_IOCTL_SET_SLAVEADD
ciaaPOSIX_IOCTL_SET_REGISTERADD
ciaaPOSIX_IOCTL_SET_REGISTERADDWIDTH
<valor dirección de registro del
dispositivo esclavo>
ciaaREGISTERADDWIDTH_0bits
ciaaREGISTERADDWIDTH_8bits
ciaaREGISTERADDWIDTH_16bits
ciaaREGISTERADDWIDTH_24bits
ciaaREGISTERADDWIDTH_32bits
Detalle
Selecciona la tasa de
transferencia de bits del I2C.
Configura la dirección del
esclavo
Configura el número de
registro interno del esclavo.
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,
*)ciaaBAUDRATE_115200);
ciaaPOSIX_ioctl(fd_uart1,
*)ciaaFIFO_TRIGGER_LEVEL3);
ciaaPOSIX_IOCTL_SET_BAUDRATE,
(void
ciaaPOSIX_IOCTL_SET_FIFO_TRIGGER_LEVEL,
(void
7
Manual POSIX
Versión 1.0
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.
8
Manual POSIX
Versión 1.0
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();
9
Manual POSIX
Versión 1.0
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;
}
10
Manual POSIX
Versión 1.0
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
tecla
3
2
1
0
4
3
2
1
Pines de salida
bits
7
LEDs
6
5
4
3
2
1
0
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
11
Manual POSIX
Versión 1.0
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
12
Manual POSIX
Versión 1.0
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.
13
Manual POSIX
Versión 1.0
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.
14
Manual POSIX
Versión 1.0
Descargar