Manejo de GPIOs en ARM Cortex-M
Analicemos en detalle la operatoria para mover un pin de I/O.
La cantidad mínima de instrucciones mediante bit banding es de tres:
- un registro del micro debe apuntar al registro de I/O
- otro contendrá el valor a escribir
- una instrucción de escritura indexada efectúa la operación propiamente dicha
Las operaciones siguientes que realicemos sobre el mismo port pueden hacerse con dos instrucciones, o incluso una si reutilizamos el registro que contiene el valor (0 ó 1).
Las operaciones de modificación de varios bits simultáneamente requieren de una lectura del port de I/O a un registro, modificación del registro, y escritura al port de I/O (excepto que el microcontrolador específicamente disponga de un hardware ad hoc como por ejemplo algunos STM32, pero hablemos del procesador Cortex-M en sí).
Cualquier operación que deseemos realizar sobre cualquier periférico, responderá en esencia a una de estas dos consideraciones vistas. Este proceso analizado demora muy poco tiempo en lo que respecta al procesador. Debido a la estructura interna de buses, el timing para acciones sucesivas sobre I/O viene dado por las transacciones en el bus AHB y luego el APB, sumado al tiempo del procesador para ordenar el cambio (ejecución de las instrucciones). Si bien cada micro tiene sus propios periféricos determinados por su fabricante, es común encontrarnos con tiempos de acceso de varios cientos de nanosegundos, debido a que el tiempo mínimo de conmutación en uno y otro sentido de un pin de I/O corresponde a la máxima velocidad de transferencia en estos buses, que es de dos ciclos de clock en cada uno.
Es posible que el procesador realice otras actividades en este tiempo, pero no que opere sobre el mismo port, en cuyo caso la ejecución de la segunda orden se demora hasta la finalización de la primera.
Por ejemplo, en un microcontrolador como el HT32F125x de Holtek, un Cortex-M3, el clock del bus AHB y el bus APB es configurable por el usuario, 72MHz como máximo y por defecto. A esto sumamos el tiempo de ejecución del procesador. Así, deducimos que el tiempo mínimo posible de latencia es de cuatro ciclos de clock (∼ 50ns), correspondiente al pasaje de la información de mover el pin desde la finalización de la instrucción hasta que pasa por el bus AHB y luego por el bus APB.
Como analizamos, es posible que el procesador realice otras actividades en este tiempo, pero no que opere sobre el mismo port, en cuyo caso la ejecución de la segunda orden se demora hasta la finalización de la primera, obteniendo un período de ocho ciclos de clock (∼ 100ns), como podemos apreciar en la figura, que corresponde al desarrollo de un driver para un display color:
Otra posibilidad es que la implementación interna del bus AHB permita realizar pipelining de sucesivas operaciones, con lo cual se reduce en algunos ciclos el tiempo total.
Por ejemplo para el TMPM330 de Toshiba, otro Cortex-M3, el clock del bus AHB y el bus APB es configurable por el usuario, 40MHz como máximo y por defecto. Al parecer este micro incorporaría pipelining en el bus AHB, pues en la misma aplicación hemos obtenido un período mínimo de seis ciclos de clock (150ns), como podemos apreciar en la figura:
Lo visto hasta aquí es válido también para Cortex-M4 y para Cortex-M0.
El procesador Cortex-M0+ incorpora de manera opcional en su Bus Matrix la conexión a un periférico que permite acceder a operaciones de entrada y salida en un solo ciclo: Single-cycle I/O. Dicho periférico está mapeado en memoria y puede ser accedido por las instrucciones corrientes de transferencia de datos, sólo que éstas se ejecutan en sólo un ciclo, en vez de dos.
La imagen siguiente muestra el movimiento de un par de GPIOs en un STM32G071 operando a 64MHz. En el trazo inferior observamos que un set y reset sucesivos se producen en unos 15ns:
En lo que al proceso de manejo de I/O se refiere, y dado que para operar sobre un pin es necesario copiar el contenido de un registro a memoria, la operación real en sólo un ciclo se limitaría a los casos en que es posible mantener los valores en sendos registros y utilizar sólo instrucciones de transferencia a memoria una tras otra. La imagen siguiente muestra el resultado de ejecutar dos operaciones de lectura-modificación-escritura sucesivas, seguidas por dos de escritura, dentro de un loop (para poder observarlo fácilmente), en un Holtek HT32F52231, Cortex-M0+ de 40MHz. El primer reset de la señal, al momento del disparo, incluye el seteo de los registros necesarios; por eso el tiempo en estado alto es considerablemente más largo. El primer set ya puede ejecutarse en tres ciclos (lectura, modificación, escritura). El segundo reset se ejecuta a los dos ciclos (carga de registro y escritura), mientras que el set siguiente se ejecuta en un ciclo dado que el optimizador del compilador ha podido reutilizar un registro cargado con anterioridad:
Este post contiene algunos extractos del libro “Desarrollo con microcontroladores ARM Cortex-M3“, con permiso del autor.