Fundamentos de Programación de Sistemas Embebidos Punteros ...

24
Punteros Arreglos Estructuras Uniones Fundamentos de Programaci´ on de Sistemas Embebidos Punteros y estructuras de datos Mg. Ing. E. Sergio Burgos Universidad Nacional de Entre R´ ıos Facultad de Ingenier´ ıa Especializaci´ on en Sistemas Embebidos 14/09/2018 1 / 24 Punteros y estructuras de datos

Transcript of Fundamentos de Programación de Sistemas Embebidos Punteros ...

Page 1: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Fundamentos de Programacion de Sistemas EmbebidosPunteros y estructuras de datos

Mg. Ing. E. Sergio Burgos

Universidad Nacional de Entre RıosFacultad de Ingenierıa

Especializacion en Sistemas Embebidos

14/09/2018

1 / 24 Punteros y estructuras de datos

Page 2: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Punteros

Un puntero es una variable definida de modo tal de contener una direccion de memoria. En lenguajeC la definicion de este tipo de variables se realiza a traves del uso del operador *. De esto, lassiguientes son definiciones de punteros validos:

uint8 t * punteroByte;

float * punteroReal;

void * punteroVoid;

Debido a que contienen una direccion de memoria y no un valor del tipo indicado, todos los punterostendran el mismo espacio de almacenamiento.

2 / 24 Punteros y estructuras de datos

Page 3: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Punteros

Una vez definida una variable de tipo puntero, el valor contenido por la misma puede ser:

NULL

Valor cero, que considerando la estructura de los sistemas, es una direccion de memoriainvalida.

La direccion de un identificadorSi se trata de una variable, la direccion de memoria de esta puede ser obtenida utilizando eloperador &. Por ejemplo:

uint8 t * pValor;

uint8 t valor;

pValor = &valor;

Una direccion de memoria absolutaEn sistemas embebidos registros y perifericos utilizan valores absolutos en el espacio de di-reccionamiento, por lo que es posible utilizar un puntero para acceder a los registros de unperiferico particular.Ademas, debido a que es posible controlar las direcciones de memoria utilizadas por la apli-cacion, un puntero puede asociarse a un area de memoria que se halle fuera del espacio dedireccionamiento indicado en el linker script.

3 / 24 Punteros y estructuras de datos

Page 4: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Punteros

Un puntero puede utilizarse para manipular el contenido de la direccion de memoria que almacena.Para lograr este efecto se utiliza el operador de des referencia (*):

uint8 t valor;

uint8 t *pValor;

pValor = &valor;

*pValor = 0x32; /* Se modifica el contenido */

/* de la variable valor */

4 / 24 Punteros y estructuras de datos

Page 5: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Algebra de punteros

Cuando se utilizan punteros con tipo (no punteros de tipo void), los operadores aritmeticos (+ y-) pueden utilizarse para realizar desplazamientos sobre las direcciones asociadas a los punteros.En este ejemplo, consideraremos que la direccion de memoria utilizada se encuentra fuera delespacio de direccionamiento utilizado en el proceso de enlazado y existe fısicamente.

uint8 t i;

uint8 t * pByte; /* Define un puntero */

pByte = (uint8 t *)0x10080000; /* Vincula el puntero

a una direccion absoluta */

for(i = 0; i < 4; i++) /* i tomara valores de 0 a 3 */

*(pByte + i) = 0; /* Modifica las direcciones: */

/* 0x10080000, 0x10080001, */

/* 0x10080002 y 0x10080003 */

Al definirse el puntero de tipo uint8 t se establece que cada direccion de memoria estara asociadaa un espacio de almacenamiento de tamano 1 byte.

5 / 24 Punteros y estructuras de datos

Page 6: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Algebra de punteros

Cuando se utilizan punteros con tipo (no punteros de tipo void), los operadores aritmeticos (+ y-) pueden utilizarse para realizar desplazamientos sobre las direcciones asociadas a los punteros.En este ejemplo, consideraremos que la direccion de memoria utilizada se encuentra fuera delespacio de direccionamiento utilizado en el proceso de enlazado y existe fısicamente.

uint8 t i;

uint8 t * pByte; /* Define un puntero */

pByte = (uint8 t *)0x10080000; /* Vincula el puntero

a una direccion absoluta */

for(i = 0; i < 4; i++) /* i tomara valores de 0 a 3 */

*(pByte + i) = 0; /* Modifica las direcciones: */

/* 0x10080000, 0x10080001, */

/* 0x10080002 y 0x10080003 */

Debido a que el puntero tiene ‘tipo’, la direccion de memoria asignada en este caso debe sercongruente con la declaracion del tipo de puntero. Para esto se utiliza un cast. Esto indica alcompilador que debe entender la expresion (o en este caso valor) indicado de un modo particular.

6 / 24 Punteros y estructuras de datos

Page 7: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Algebra de punteros

Cuando se utilizan punteros con tipo (no punteros de tipo void), los operadores aritmeticos (+ y-) pueden utilizarse para realizar desplazamientos sobre las direcciones asociadas a los punteros.En este ejemplo, consideraremos que la direccion de memoria utilizada se encuentra fuera delespacio de direccionamiento utilizado en el proceso de enlazado y existe fısicamente.

uint8 t i;

uint8 t * pByte; /* Define un puntero */

pByte = (uint8 t *)0x10080000; /* Vincula el puntero

a una direccion absoluta */

for(i = 0; i < 4; i++) /* i tomara valores de 0 a 3 */

*(pByte + i) = 0; /* Modifica las direcciones: */

/* 0x10080000, 0x10080001, */

/* 0x10080002 y 0x10080003 */

Al sumarle diferentes valores a la direccion de base y utilizarse el operador de des referencia, sealtera las direcciones de memoria siguientes, en este caso, los 4 bytes siguientes a la direccion0x10080000.

7 / 24 Punteros y estructuras de datos

Page 8: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Algebra de punteros

Cuando se utilizan punteros con tipo (no punteros de tipo void), los operadores aritmeticos (+ y-) pueden utilizarse para realizar desplazamientos sobre las direcciones asociadas a los punteros.En este ejemplo, consideraremos que la direccion de memoria utilizada se encuentra fuera delespacio de direccionamiento utilizado en el proceso de enlazado y existe fısicamente.

uint8 t i;

uint32 t * pDw; /* Define un puntero */

pDw = (uint32 t *)0x10080000; /* Vincula el puntero

a una direccion absoluta */

for(i = 0; i < 4; i++) /* i tomara valores de 0 a 3 */

*(pDw + i) = 0; /* Modifica las direcciones: */

/* 0x10080000, 0x10080004, */

/* 0x10080008 y 0x1008000C */

Ahora, debido al cambio del tipo de puntero utilizado, al sumar los mismos valores que en el casoanterior, se modificaran otras direcciones de memoria, en total 16 bytes.

8 / 24 Punteros y estructuras de datos

Page 9: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Algebra de punteros

Un caso valido y particularmente util, es el uso de un tipo de puntero vinculado a una variable deotro tipo.

float pi = 3.1415; /* Variable de tipo real */

unsigned int tmpV; /* Auxiliar temporal */

int i; /* Contador */

uint8 t *pByte; /* Puntero para mapeo */

pByte = (uint8 t *)&pi; /* cast para asignacion */

for(i=0; i < sizeof(float); i++)

{tmpV = *(pByte + i); /* Acceso a cada byte */

printf("%02x ", tmpV);

}

Si bien en este caso el acceso es de lectura, bien podrıa utilizarse para realizar acceso de escritura.El uso mas comun de este tipo de acceso es la serializacion y des serializacion de informacion almomento de trabajar con perifericos donde la unidad de transferencia sea de menor tamano que launidad de informacion.

9 / 24 Punteros y estructuras de datos

Page 10: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Arreglos: concepto y definicion

Los arreglos son conjuntos homogeneos, finitos y ordenados de datos.

homogeneos implica que todos los valores del conjunto deberan ser del mismo tipo.

finito por ser una cantidad determinada de elementos.

ordenado por existir una relacion de orden en lo que a posicionamiento respecta.

Definiciones validas de arreglos son:

#define MAXSIZE 20

int v[MAXSIZE]; /* Declara un vector de MAXSIZE elementos */

uint32 t m[4][8]; /* Declara una matriz de 4 filas y 8 columnas */

La cantidad de dimensiones asociadas al arreglo esta dada por la cantidad de corchetes utilizadasen su definicion. El tamano de cada dimension esta dada por el valor entre corchetes. El primerelemento siempre estara asociado al ındice 0 y el ultimo al tamano de definicion menos uno.A diferencia de otros lenguajes, en el lenguaje C, no se guarda informacion sobre la cantidad deelementos indicada a la hora de la declaracion del arreglo.

10 / 24 Punteros y estructuras de datos

Page 11: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Arreglos: inicializacion

En sistemas embebidos los arreglos son una forma de implementacion de tablas de consulta. Enestos casos los arreglos se inicializan en su definicion. En estos casos no es imprescindible indicarla cantidad de elementos que lo constituyen.

#define LEN 16

const char hex[LEN] = {‘0’, ‘1’, ‘2’, ‘3’,

‘4’, ‘5’, ‘6’, ‘7’,

‘8’, ‘9’, ‘A’, ‘B’,

‘C’, ‘D’, ‘E’, ‘F’};

const uint32 t msk[2][2] = {{0x000000FF, 0x00FF0000},{0xFF000000, 0x0000FF00}};

const uint8 t f1[] = {1};const uint8 t f2[] = {1, 2};const uint8 t * const m[] = {f1, f2};

Una practica util, cuando se trabaja con tablas de consulta de diferentes longitudes es marcar elultimo elemento del arreglo utilizando el caracter NULL. De este modo, multiples tablas de consulta(arreglos) pueden ser utilizados por el mismo algoritmo sin requerir cuidados especiales respectodel tamano de definicion del mismo.

11 / 24 Punteros y estructuras de datos

Page 12: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Arreglos: uso

Cuando se utilizan arreglos como contenedores de informacion, se aprovecha el acceso indexado alos elementos para realizar el mismo procesamiento a todos los elementos. En estos casos se sueletener una estructura iterativas vinculada a cada dimension del arreglo.

#define VLEN 50

int main(void)

{

int v[VLEN];

int i;

. . .

for(i = 0; i < VLEN; i++)

v[i] = 0;

. . .

}

#define MXF 5

#define MXC 7

int main(void)

{

float m[MXF][MXC];

int f, c;

. . .

for(f = 0; f < MXF; f++)

for(c = 0; c < MXC; c++)

m[f][c] = 0;

. . .

}

El hecho que la cantidad de elementos es constante, constituye una limitacion en terminos degeneralidad del algoritmo de procesamiento. Por esto, el uso de arreglos, deberıa limitarse a casosdonde su uso es imprescindible.

12 / 24 Punteros y estructuras de datos

Page 13: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Arreglos: uso

En lenguaje C existe similitud entre los punteros y los arreglos. Esto esta dado en dos sentidos, porun lado debido a que el identificador de un arreglo almacena la direccion del primer elemento. Porotro lado, puede utilizarse la sintaxis de vectores (corchetes) cuando se utiliza un puntero.

int i;

uint8_t *pDatos;

float pi = 3.141596;

unsigned int tmp;

pDatos = (uint8_t *)&pi;

for(i=0; i < sizeof(pi); i++)

{

tmp = pDatos[i];

printf(" %02x ", tmp);

}

De este modo se tiene un comportamiento similar al uso de algebra de punteros pero utilizandonotacion de arreglos.

13 / 24 Punteros y estructuras de datos

Page 14: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Arreglos: cadenas

La forma de implementacion de cadenas de caracteres en lenguaje C es utilizando vectores decaracteres (char), cuyos valores numericos se representan a traves de equivalencias con la tablaASCII (American Standard Code for Information Interchange).

Una particularidad de la tabla ASCII es el hecho que los sımbolos ’A’, ’a’ y ’0’ tienen menor valorque ’Z’, ’z’ y ’9’. Manteniendo orden los valores intermedios de los sımbolos alfabeticos y numericos.

En este tipo de implementaciones de cadenas se trabaja sobredimensionando los arreglos y marcandoel fin de las cadenas de caracteres contenidas con el valor NULL, que se representa con el valor 0 ocomo el caracter ‘\0’.

Debido a que suele ser necesario realizar aplicar algunos algoritmos de forma recurrente, la librerıaestandar de c incorpora diferentes funciones para simplificar el procesamiento de cadenas.

14 / 24 Punteros y estructuras de datos

Page 15: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Funciondes de cadenas de caracteres

A continuacion se listan algunas funciones utiles para el procesamiento de cadenas definidas en elheader string.h

char * strcpy(char * dest, const char * src );

Copia en dest la cadena src.

char * strcat (char * dest, const char * src);Agrega, a continuacion del contenido de dest, el contenido de src.

int strcmp (const char * a, const char * b);

Compara las cadenas a y b, retornando 0 si tienen el mismo contenido, un valor negativo si lacadena a se ubica antes de la cadena b o un valor positivo en caso contrario.

char * strchr (char * str, int chr);Retorna la direccion de la primera ocurrencia de chr en str. En caso de no encontrar coinci-dencia retorna NULL.

char * strstr (const char * pajar, const char * aguja);

Retorna la direccion de la primera ocurrencia de aguja en pajar o NULL si no existe coinci-dencia.

size t strlen(const char * str);

Retorna la longitud de la cadena str, no el tamano establecido en su definicion.

15 / 24 Punteros y estructuras de datos

Page 16: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Otras funciones de utilidad

Ademas de las funciones especıficas del procesamiento de cadenas, existe otro conjunto de funcionesde utilidad definidas en el header ctype.h.

int isdigit(int chr);

Comprueba si chr es un dıgito (0, 1, 2, 3, 4, 5, 6, 7, 8 o 9). En caso afirmativo retorna unvalor diferente de cero o cero en caso contrario.

int isalpha(int chr);

Retorna un valor diferente de cero si chr se encuentra en el intervalo [’A’,’Z’] o [’a’, ’z’] o ceroen caso contrario.

int isspace(int chr);

Retorna un valor diferente de cero si chr se corresponde con la representacion de un espacio,entendiendo como tales: ‘ ’, ‘\t’, ‘\n’, ‘\v’, ‘\f’ o ‘\r’. Cero en caso contrario.

int islower (int chr); y int isupper(int chr);Retornan un valor diferente de cero si el argumento se corresponde con una letra minuscula(islower) o mayuscula (isupper), o cero en caso contrario.

int tolower(int c); y int toupper(int c);

Retornan, si es posible, la representacion en minuscula (tolower) o en mayuscula (toupper)del caracter dado como argumento.

16 / 24 Punteros y estructuras de datos

Page 17: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Arreglos: cadenas

Un caso de interes se da a traves de los argumentos de la funcion main, especıficamente el argumentoargv. Si bien esto no se utiliza en sistemas embebidos, su definicion es un caso de aplicacion quepuede extenderse a otras aplicaciones.

int main(int argc, char * argv[])

En este caso, el vector de punteros argv, contiene en cada posicion un puntero a char. Siendo estala declaracion utilizada para cadenas, se obtiene una matriz escalonada o asimetrica.

17 / 24 Punteros y estructuras de datos

Page 18: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Estructura: generalidades

Las estructuras permiten definir una unidad de informacion a partir de la creacion de un nuevo tipode dato que incluye campos.

Cada campo puede ser del mismo o diferente tipo. El acceso a cada elemento se da utilizando eloperador ‘.’ o flecha si se trata de un puntero ‘->’.

/* Declaraci on del tipo de

dato digialIO. No tese el

uso de typedef

*/

typedef struct

{

uint8_t hwPort;

uint8_t hwPin;

uint8_t gpioPort;

uint8_t gpioPint;

uint16_t modo;

} digitalIO;

digitalIO P20; /* Declaraci on de una

variable de tipo

digitalIO */

digitalIO *pP20; /* Puntero a estructura */

pP20 = &P20;

p20.hwPort = 2; /* Asignaci on de valores */

p20.hwPin = 0; /* campos */

(*pP20). hwPort = 20;/* Asignaciones */

(*pP20).hwPin = 0; /* equivalentes */

pP20 ->hwPort = 20; /* Asignaciones */

p20 ->hwPin = 0; /* equivalentes */

18 / 24 Punteros y estructuras de datos

Page 19: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Estructuras: generalidades

Tal como los arreglos, las estructuras pueden inicializarse en su definicion.

/* inicializaci on standard C90 */

const digitalIO

led1 =

{

0x02 ,

0x0A ,

0x00 ,

0x1E ,

SCU_MODE_INACT |

SCU_MODE_FUNC0

};

/* ISO C99 soportado como

extensi on en GCC */

const digitalIO

led1 =

{

.hwPort = 0x02 ,

.hwPin = 0x0A ,

.gpioPort = 0x00 ,

.gpioPint = 0x1E ,

.modo = SCU_MODE_INACT |

SCU_MODE_FUNC0

};

Cuando se utilizan designators para inicializar algunos campos de una estructura, aquellos noindicados, seran inicializados del mismo modo que los entidades estaticas.

19 / 24 Punteros y estructuras de datos

Page 20: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Estructuras: generalidades

Al igual que con cualquier otro tipo de dato es posible definir arreglos de estructuras e inicializarlasen su definicion. En este caso, cada valor de inicializacion de cada estructura es encerrado entrellaves.

const digitalIO

leds[] =

{

{0x02 , 0x00 , 0x05 , 0x00 , SCU_MODE_INACT | SCU_MODE_FUNC4},

{0x02 , 0x0A , 0x00 , 0x0E , SCU_MODE_INACT | SCU_MODE_FUNC0},

{0x02 , 0x0B , 0x01 , 0x0B , SCU_MODE_INACT | SCU_MODE_FUNC0},

{0x02 , 0x0C , 0x01 , 0x0C , SCU_MODE_INACT | SCU_MODE_FUNC0},

{0x02 , 0x01 , 0x05 , 0x01 , SCU_MODE_INACT | SCU_MODE_FUNC4},

{0x02 , 0x02 , 0x05 , 0x02 , SCU_MODE_INACT | SCU_MODE_FUNC4}

};

void sysInit(void)

{

int i;

Chip_GPIO_Init(LPC_GPIO_PORT );

for(i = 0; i < sizeof(leds)/ sizeof(digitalIO ); i++)

{

Chip_SCU_PinMuxSet(leds[i].hwPort , leds[i].hwPin , leds[i].modo);

Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT , leds[i].gpioPort , leds[i]. gpioPin );

Chip_GPIO_SetPortOutLow(LPC_GPIO_PORT , leds[i].gpioPort , leds[i]. gpioPin );

}

}

20 / 24 Punteros y estructuras de datos

Page 21: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Campos de bits

Los campos de bits son casos particulares de estructuras en los cuales los campos se definenindicando el tamano de los bits a utilizar.

Los campos pueden definirse utilizando un tipo de entero como contenedor, pero se prefiere el usode tipos enteros sin signo, ya que el objetivo de uso no es el almacenamiento sino la manipulacionde la informacion.

typedef struct

{

uint8_t cmd :4;

uint8_t data :8;

uint8_t :1;

uint8_t f0 :1;

uint8_t f1 :1;

uint8_t f2 :1;

} bitFileds;

Un campo particular no tiene direcciones de memoria asociada. Esto se debe a que puedenformar parte de un byte y no se direccionable.

El compilador agrega operaciones para lograr la manipulacion necesaria, por lo que puedelograrse un codigo mas complejo.

21 / 24 Punteros y estructuras de datos

Page 22: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Estructuras y almacenamiento

Al definir una estructura, el orden en el que se declaren los campos sera el or-den en el que se almacenara los valores en memoria. Pero puede suceder que el ta-mano de almacenamiento no sea exactamente la suma de los tamanos de cada campo.

typedef struct

{

uint8_t f1; /* 0x10007fac */

uint32_t f2; /* 0x10007fb0 */

uint8_t f3; /* 0x10007fb4 */

uint16_t f4; /* 0x10007fb6 */

} testNoAlign; /* size = 12B */

typedef struct

{

uint8_t f1; /* 0x10007fa0 */

uint32_t f2; /* 0x10007fa4 */

uint8_t f3; /* 0x10007fa8 */

uint16_t f4; /* 0x10007faa */

} __attribute__ (( aligned (4)))

testStructAlign; /* size = 12B */

typedef struct

{

/* 0x10007f90 */

uint8_t f1 __attribute__ (( aligned (4)));

/* 0x10007f94 */

uint32_t f2 __attribute__ (( aligned (4)));

/* 0x10007f98 */

uint8_t f3 __attribute__ (( aligned (4)));

/* 0x10007f9c */

uint16_t f4 __attribute__ (( aligned (4)));

} testFieldAlign; /* size = 16B */

typedef struct

{

/* 0x10007f88 */

uint8_t f1;

/* 0x10007f89 */

uint32_t f2;

/* 0x10007f8d */

uint8_t f3;

/* 0x10007f8e */

uint16_t f4;

} __attribute__ (( packed ))

testPack; /* size = 8B */

22 / 24 Punteros y estructuras de datos

Page 23: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Uniones

Las uniones, al igual que las estructuras, trabajan con campos que pueden ser del mismo o di-ferente tipo. La diferencia entre ambas radica en que las uniones utilizan el mismo espacio dealmacenamiento para todos los campos.

Por esto, el tamano de una union lo determina el tipo de dato que utiliza mayor espacio dealmacenamiento.

#include <stdio.h>

typedef struct

{

uint8_t bh:4;

uint8_t bl:4;

} byte;

typedef union

{

uint32_t val;

byte b[4];

} UnValor;

const char

hex [16] = {'0', '1', '2', '3','4', '5', '6', '7','8', '9', 'A', 'B','C', 'D', 'E', 'F'};

int main(int argc , char * argv [])

{

UnValor x;

int i;

printf("Ingrese un valor decimal:");

scanf("%u", &x.val);

printf("\n");

for(i=3; i>=0;i--)

{

printf(" %c", hex[x.b[i].bl]);

printf("%c ", hex[x.b[i].bh]);

}

printf("\n");

return 0;

}

23 / 24 Punteros y estructuras de datos

Page 24: Fundamentos de Programación de Sistemas Embebidos Punteros ...

Punteros Arreglos Estructuras Uniones

Fin Modulo 8

24 / 24 Punteros y estructuras de datos