Modulo 07 Diapo
Modulo 07 Diapo
14/09/2018
Drivers LPCOpen
Hasta hace algunos años, la forma de trabajo con microcontroladores se basaba en el conocimiento
de la arquitectura y, a partir de esta se configuraban diferentes aspectos del microcontrolador
escribiendo en direcciones de memoria particular.
Si bien esta forma de trabajo sigue utilizándose en algunos casos, con el advenimiento de mi-
crocontroladores más complejos y núcleos de terceros, se ha vuelto común que los fabricantes de
microcontroladores proporcionen drivers implementados como funciones que permiten controlar
diferentes aspectos del dispositivo.
En general, para dispositivos basados en núcleos ARM, la estructura de drivers contiene dos partes:
Una vez establecida la frecuencia de reloj del sistema (y siempre que esta se modifique) es con-
veniente invocar a la función SystemCoreClockUpdate, que actualiza el valor de la variable global
SystemCoreClock al valor de la frecuencia de trabajo configurada en el núcleo.
Configuración de periféricos
Cada periférico presente en el lpc4337 debe ser configurado según las especificaciones de la hoja
de datos del mismo (documento UM10503.pdf).
Más allá de las opciones particulares de cada periférico, existe cierto comportamiento general.
Cada uno tiene asociada una estructura de configuración, la cuál debe ser utilizada como argu-
mento en la invocación a las diferentes funciones de configuración. El nombre de algunas de es-
tas estructuras es LPC USART0, LPC USART2, LPC TIMER0, LPC DAC, LPC ADC0, LPC GPIO PORT,
etc.
Cada periférico cuenta con una función de inicialización y de ‘des inicialización’. Por ejemplo:
Chip GPIO Init y Chip GPIO DeInit, Chip I2C Init y Chip I2C DeInit, Chip TIMER Init
y Chip TIMER DeInit, etc.
Configuración de periféricos
Cada periférico presente en el lpc4337 debe ser configurado según las especificaciones de la hoja
de datos del mismo (documento UM10503.pdf).
Más allá de las opciones particulares de cada periférico, existe cierto comportamiento general.
Cada uno tiene asociada una estructura de configuración, la cuál debe ser utilizada como argu-
mento en la invocación a las diferentes funciones de configuración. El nombre de algunas de es-
tas estructuras es LPC USART0, LPC USART2, LPC TIMER0, LPC DAC, LPC ADC0, LPC GPIO PORT,
etc.
Cada periférico cuenta con una función de inicialización y de ‘des inicialización’. Por ejemplo:
Chip GPIO Init y Chip GPIO DeInit, Chip I2C Init y Chip I2C DeInit, Chip TIMER Init
y Chip TIMER DeInit, etc.
La definición e implementación de las funciones de cada periférico se encuentran en un archivo
con el mismo nombre (gpio 18xx 43xx.c, gpio 18xx 43xx.h)
Configuración de periféricos
Cada periférico presente en el lpc4337 debe ser configurado según las especificaciones de la hoja
de datos del mismo (documento UM10503.pdf).
Más allá de las opciones particulares de cada periférico, existe cierto comportamiento general.
Cada uno tiene asociada una estructura de configuración, la cuál debe ser utilizada como argu-
mento en la invocación a las diferentes funciones de configuración. El nombre de algunas de es-
tas estructuras es LPC USART0, LPC USART2, LPC TIMER0, LPC DAC, LPC ADC0, LPC GPIO PORT,
etc.
Cada periférico cuenta con una función de inicialización y de ‘des inicialización’. Por ejemplo:
Chip GPIO Init y Chip GPIO DeInit, Chip I2C Init y Chip I2C DeInit, Chip TIMER Init
y Chip TIMER DeInit, etc.
La definición e implementación de las funciones de cada periférico se encuentran en un archivo
con el mismo nombre (gpio 18xx 43xx.c, gpio 18xx 43xx.h)
Configuración GPIO
El primer paso es identificar el conexionado en el esquema de la EDU-CIAA y, a partir de este, los
números de pin asociados.
Configuración GPIO
El primer paso es identificar el conexionado en el esquema de la EDU-CIAA y, a partir de este, los
números de pin asociados.
Configuración GPIO
Luego, a partir de la identificación del pin a configurar, determinar el valor de configuración que se
corresponde con la función de interés.
Configuración GPIO
Luego, a partir de la identificación del pin a configurar, determinar el valor de configuración que se
corresponde con la función de interés.
Configuración GPIO
Luego, a partir de la identificación del pin a configurar, determinar el valor de configuración que se
corresponde con la función de interés.
Configuración GPIO
La configuración de los pines de entrada salida digitales requiere establecer el modo de funciona-
miento de los pines para luego configurarlos a través del módulo GPIO.
Notar la relación entre el puerto P2 10 y el GPIO0[14].
/* E s t a b l e c e m o s la funci ó n del pin */
C hi p _S CU _ Pi nM u xS e t (0 x02 , 0 x0A , SCU_MODE_FUNC0 );
/* I n i c i a l i z a m o s el m ó dulo GPIO */
Chip_GPIO_Init ( LPC_GPIO_PORT );
/* E s t a b l e c e m o s su direcci ó n */
C h i p _ G P I O _ S e t P i n D I R O u t p u t ( LPC_GPIO_PORT , 0 , 14);
/* Ponemos la salida en 1 */
C h i p _ G P I O _ S e t P i n O u t H i g h ( LPC_GPIO_PORT , 0 , 14);
Configuración GPIO
Además de establecer la configuración de multiplexación de un pin, la función Chip SCU PinMuxSet
permite establecer opciones particulares del mismo. La combinación de diferentes valores puede
establecerse utilizando el operador or (¦). Algunos valores posibles son:
SCU MODE PULLUP: habilita resistencias de pullup.
SCU MODE REPEATER: habilita resistencias de pullup y pulldown.
SCU MODE INACT: desactiva resistencias de pullup y pulldown.
SCU MODE PULLDOWN: habilita resistencias de pulldown.
SCU MODE ZIF DIS: desactiva el filtro de glitch, debe desactivarse para trabajar con frecuencias
mayores o iguales a 30 Mhz.
SCU MODE INBUFF EN: activa el buffer de entrada digital. Si un pin será configurado como
entrada digital deberá activarse. Si constituirá una entrada analógica, debe desactivarse.
SCU MODE 4MA DRIVESTR, SCU MODE 8MA DRIVESTR, SCU MODE 14MA DRIVESTR,
SCU MODE 20MA DRIVESTR: configura la corriente de salida máxima (soportado en algu-
nos pines).
SCU MODE FUNCX: establece la función de un pin. Los valores posibles de X van de 0 a 7.
Configuración GPIO
En lo que respecta a las funciones de trabajo sobre los GPIO, se incorporan definiciones que permiten
configurar la dirección, realizar operaciones de escritura o lectura. Tanto a nivel de pin como a nivel
de puerto.
Un particularidad del módulo GPIO es que cuenta con un registro de enmascaramiento. Este permite
establecer, a través de la función Chip GPIO SetPortMask, un valor de máscara asociada a un puerto
particular.
Si un bit de esta máscara toma valor 0, permite realizar operaciones de lectura y escritura a través
de las funciones Chip GPIO SetMaskedPortValue y Chip GPIO GetMaskedPortValue.
Si la máscara toma valor 1, los bits correspondientes de ese puerto no serán afectados por las
operaciones de lectura y escritura anteriores. En el caso de las operaciones de lectura, los bits
enmascarados serán leı́dos como 0.
Interrupciones y el NVIC
El núcleo Cortex-M4, presente en el LPC4337, incorpora un controlador de interrupciones (NVIC)
a través del cual se realiza la configuración y gestión de las interrupciones.
Entre las caracterı́sticas que incorpora se encuentran:
Capacidad para gestionar hasta 240 interrupciones.
Asignación de prioridades de 0 a 255 a cada interrupción (0 mayor prioridad - 255 menor
prioridad).
Configuración de disparo por nivel o flanco.
Desde el punto de vista del procesador, al dispararse una interrupción, automáticamente se guarda
su estado en el stack, restableciéndose al momento de finalizar la rutina asociada al procesamiento
de la misma.
Interrupciones y el NVIC
En lo que respecta a la configuración del controlador de interrupciones, este puede gestionarse
ya sea a través del acceso directo a los registros de configuración o a través de las funciones
incorporadas en CMSIS.
void NVIC EnableIRQ(IRQn Type IRQn) y void NVIC DisableIRQ(IRQn Type IRQn)
Habilitan y deshabilitan una interrupción. El argumento es el número de interrupción de interés.
La primer interrupción asociada a un periférico es la 0 y la cantidad depende del fabricante del
microcontrolador. Las identificaciones de -14 a -1 corresponden con excepciones del núcleo.
uint32 t NVIC GetPendingIRQ(IRQn Type IRQn)
Permite saber si una interrupción o excepción se encuentra pendiente de ser atendida.
void NVIC ClearPendingIRQ(IRQn Type IRQn) y void NVIC SetPendingIRQ(IRQn Type
IRQn)
Permiten establecer o eliminar el indicador de estado de una interrupción.
void NVIC SetPriority(IRQn Type IRQn, uint32 t priority) y
uint32 t NVIC GetPriority(IRQn Type IRQn)
Permiten establecer o acceder a la prioridad configurada para una interrupción o excepción.
Excepciones en Cortex-M4
El vector de interrupciones contiene en las primeras 15 posiciones, direcciones asociadas a las
excepciones del núcleo. Algunas de ellas son de uso reservado. Para el núcleo Cortex-M4 estas
excepciones son:
Reset: rutina inicialización.
NMI: excepción no enmascarable.
HardFault: se genera ante un error durante el procesamiento de una excepción.
MemManage: asociada a un error de protección de memoria.
BusFault: se origina al detectar un error en el bus de memoria del sistema. Se puede originar
debido errores al ejecutar una instrucción o transacción sobre el área de memoria de datos.
UsageFault: está asociada a errores durante la ejecución de instrucciones. Puede producirse
ante la ejecución de instrucciones indefinidas.
SVCall: Supervisor Call, se produce al ejecutarse la instrucción SVC
PendSV: disparada a través del NVIC, suele utilizar para la realización de cambios de contexto
o para la separación del procesamiento de ISR.
SysTick: se dispara cuando el módulo SysTick alcanza el valor cero.
ISR e interrupciones
El vector de interrupciones se configura inicializando cada una de sus posiciones con la dirección
de memoria de una función (startUp.c). Las excepciones del núcleo asociadas a las primeras 14
posiciones suelen tener implementaciones particulares pero se las define utilizando el atributo weak
(débil).
En el compilador GCC, una sı́mbolo definido como débil será automáticamente sobre escrito si se
encuentra otro sı́mbolo con el mismo nombre. Por esto, si se inicializa el vector de interrupciones
utilizando como nombre de ISR asociada al SysTick el identificador SysTick Handler, de encon-
trarse una función con este nombre en otro archivo, se utilizará la nueva definición en vez de la
débil.
Las ISR asociadas a los periféricos suelen vincularse a una única función. De modo similar al
caso anterior se utiliza la directiva weak pero junto a alias. El conjunto logra que se cree una
definición débil de una función y vincularla a través del alias con una implementación real. Al igual
que en el caso anterior, el sı́mbolo definido de este modo será sobre escrito si se encuentra una
implementación con el mismo nombre en otro archivo.
Interrupciones y GPIO
Los periféricos que soportan el uso de interrupciones se encuentran conectados al NVIC. En función
del tipo de periférico son los orı́genes de interrupciones que puede generar.
Para el caso del módulo GPIO, puede configurarse para generar dos tipos de interrupciones:
Interrupciones basadas en el estado de pines
Se pueden configurar hasta 8 pines pertenecientes a diferentes puertos como disparadores de
interrupciones. Cada uno configurado por nivel o flanco y se encuentra asociado a una ISR
diferente.
Interrupciones basadas en el estado de grupos de pines
Permite configurar pines de diferentes puertos asociados a un grupo para generar una única
interrupción. Es posible configurar el disparo de la interrupción cuando todos los pines del
conjunto han sido excitados o solo uno. Pueden definirse dos grupos.
Interrupciones y GPIO
Los periféricos que soportan el uso de interrupciones se encuentran conectados al NVIC. En función
del tipo de periférico son los orı́genes de interrupciones que puede generar.
Para el caso del módulo GPIO, puede configurarse para generar dos tipos de interrupciones:
Interrupciones basadas en el estado de pines
Se pueden configurar hasta 8 pines pertenecientes a diferentes puertos como disparadores de
interrupciones. Cada uno configurado por nivel o flanco y se encuentra asociado a una ISR
diferente.
Interrupciones basadas en el estado de grupos de pines
Permite configurar pines de diferentes puertos asociados a un grupo para generar una única
interrupción. Es posible configurar el disparo de la interrupción cuando todos los pines del
conjunto han sido excitados o solo uno. Pueden definirse dos grupos.
Gestión de tiempo
Existen diferentes formas de trabajo en lo que a medición de tiempo y retardos se refiere. En el
caso de la CIAA podemos utilizar:
SysTick: módulo incorporado en el núcleo Cortex-M4. Permite establecer un valor de cuenta,
disparando una interrupción cada vez que se alcanza el valor cero. También es posible acceder
al registro de cuenta.
SysTick
Las estructuras de control del SysTick son proporcionadas por la librerı́a CMSIS. Incorpora una
función y la declaración de una estructura para el acceso al valor de sus registros.
La función SysTick Config toma como argumento el valor de carga automática que utilizará el reloj
expresado en ciclos de reloj (ticks). Esta función también habilita la interrupción asociada e inicia
el ciclo de cuenta decremental. Cada vez que se alcanza el valor cero se disparará la interrupción
asociada y se cargará nuevamente con el valor configurado. Es importante considerar que el registro
de carga tiene un tamaño de 24 bits, lo que limita el valor de inicialización.
Una vez configurado, el SysTick generará interrupciones hasta que se lo detenga. Para esto es
necesario modificar su registro de control:
SysTick->CTRL = SysTick->CTRL & (~SysTick CTRL ENABLE Msk);
SysTick
stopwatch
Utiliza el timer0 para generar tiempos muertos. Una vez inicializada es posible llamar diferentes fun-
ciones determinar el tiempo transcurrido o generar retardos. Algunas de las funciones que incorpora
son:
void StopWatch Init(void)
Inicializa la librerı́a, configurando el timer utilizado. Debe ser invocada previa a cualquier otra
llamada de la librerı́a.
void StopWatch DelayUs(uint32 t uS)
Detiene la ejecución de la aplicación durante la cantidad de micro segundos indicados como
argumento.
void StopWatch DelayMs(uint32 t mS)
Detiene la ejecución de la aplicación durante la cantidad indicada de milisegundos.
uint32 t StopWatch Start(void)
Retorna el valor actual del contador asociado al timer utilizado.
uint32 t StopWatch Elapsed(uint32 t startTime)
Retorna la cantidad de ticks que han pasado entre el valor actual del contador y el argumento
dado.
USART y UART
Se incorporan 3 módulos USART (0, 2 y 3) y 1 módulo UART (1), este último con incluye lı́neas
de señalización full modem y soporte RS485.
Caracterı́sticas USART:
FIFO de 16 bytes, configurable para generar disparos con diferentes niveles de almacenamiento
(1, 4, 8 y 14 bytes).
En modo UART permite generar lı́neas de control por software.
Modos RS-485/EIA-485 de 9 bit con habilitación de salida.
IrDA en USART3.
Soporte de DMA.
Modo auto baud rate.
En la EDU-CIAA NXP el módulo USART2 está conectado al FT2232, por lo que puede ser accedido
como un puerto serie virtual a través del puerto USB.
# include " chip . h " Ch ip_ UART _Se tBa ud ( LPC_USART2 , 115200);
# include < string .h > C hi p_ U AR T _T XE n a b l e ( LPC_USART2 );
Buffer circulares
La comunicación con dispositivos externos en sistemas embebidos, por ejemplo a través de un
módulo USART, es un medio pero no un fin. El sistema se diseña para la realización de una
tarea y además se soportan comunicaciones de diferente tipo, por lo que no es una alternativa de
implementación válida centrar el diseño de la aplicación a partir de las comunicaciones.
El uso de la memoria FIFO asociada a la USART puede ser una solución pero solo cubre el caso
en el que se acumule hasta 16 bytes.
Una solución más general es el uso de colas
circulares, estas agregan información de forma
cı́clica en un extremo mientras la quitan desde
el otro.
La librerı́a lpcOpen incorpora una implementa-
ción de colas circulares, entre sus caracterı́sticas
se encuentran:
Almacenamiento estático basado en vecto-
res.
Tamaño de los elementos configurable.
Posibilidad de agregar y quitar un elemento
o varios en una sola operación.
Colas circulares
En la implementación provista por lpcOpen, cada cola circular se encontrará asociada a dos varia-
bles. Por un lado tendremos una variable de tipo RINGBUFF T, la cuál contiene los datos significativos
respecto del estado y configuración del buffer.
Por otro, un arreglo de tantos elementos como se deseen, que contendrá la información del buffer
circular. No existe restricción respecto del tamaño que puede contener cada elemento en el buffer,
pero si se debe guardar consistencia en la configuración de modo que la cantidad de elementos
esté acorde al tamaño del arreglo.