tdse-tp3_04-interactive_menu

Index Commits Files Refs
app/gemini_03.txt (7539B)
   1 ### **Análisis de `board.h` (Abstracción de Hardware)**
   2 
   3 Este archivo es un encabezado (header) de configuración que actúa como una
   4 **Capa de Abstracción de Hardware (Hardware Abstraction Layer - HAL)** a nivel
   5 de placa. Su principal objetivo es centralizar y abstraer las definiciones de
   6 hardware específicas de la placa (pines, puertos, lógica de activación),
   7 permitiendo que el resto del código sea más portable y legible.
   8 
   9 #### **Funcionamiento Detallado:**
  10 
  11 1.  **Selección de Placa (Board Selection):**
  12     * Se define una macro `BOARD` que especifica la placa de desarrollo para la
  13       cual se está compilando el código. En este caso, está configurada para la
  14       `NUCLEO_F103RC`.
  15     * `#define BOARD (NUCLEO_F103RC)`
  16 
  17 2.  **Compilación Condicional:**
  18     * El archivo utiliza directivas de preprocesador (`#if`, `#endif`) para
  19       incluir bloques de definiciones que solo son válidos para la placa
  20       seleccionada.
  21     * El bloque que se compilará es el que corresponde a `((BOARD ==
  22       NUCLEO_F103RC) || ...)`.
  23 
  24 3.  **Mapeo de Pines y Puertos:**
  25     * Dentro del bloque condicional, se asignan nombres simbólicos y legibles
  26       (ej. `BTN_ENT_PIN`, `LED_A_PORT`) a las definiciones de pines y puertos
  27       específicos del hardware, que provienen de las librerías de STM32Cube (ej.
  28       `D10_Pin`, `LD2_GPIO_Port`).
  29     * Por ejemplo, en lugar de escribir `HAL_GPIO_ReadPin(D10_GPIO_Port,
  30       D10_Pin)`, el programador puede usar `HAL_GPIO_ReadPin(BTN_ENT_PORT,
  31       BTN_ENT_PIN)`, lo cual es más claro.
  32 
  33 4.  **Abstracción de la Lógica Eléctrica:**
  34     * Define el estado eléctrico que corresponde a una acción lógica. Por
  35       ejemplo, `BTN_ENT_PRESSED` se define como `GPIO_PIN_RESET`. Esto significa
  36       que el botón "Enter" se considera presionado cuando el pin correspondiente
  37       está en estado bajo (LOW). Esto es muy útil porque abstrae si el botón es
  38       activo-alto o activo-bajo.
  39     * De manera similar, `LED_A_ON` se define como `GPIO_PIN_SET`, indicando que
  40       el LED se enciende con un nivel de voltaje alto (HIGH).
  41 
  42 **En resumen, este archivo permite que el resto del código fuente se refiera a
  43 los botones y LEDs por nombres lógicos (como "Enter" o "LED A") sin preocuparse
  44 por los detalles físicos de qué pin específico o qué nivel de voltaje se utiliza
  45 en la placa NUCLEO-F103RC.** Si se quisiera portar el código a otra placa, solo
  46 sería necesario modificar este archivo.
  47 
  48 ---
  49 
  50 ### **Análisis de `dwt.h` (Contador de Ciclos de Alta Precisión)**
  51 
  52 Este archivo de encabezado proporciona un conjunto de funciones para medir
  53 tiempos de ejecución con una resolución muy alta (a nivel de ciclos de reloj del
  54 CPU). Para ello, utiliza el periférico **DWT (Data Watchpoint and Trace)** del
  55 núcleo ARM Cortex-M.
  56 
  57 #### **Funcionamiento Detallado:**
  58 
  59 El archivo define una serie de funciones `static inline`, lo que sugiere al
  60 compilador que inserte el código de la función directamente en el lugar de la
  61 llamada, eliminando la sobrecarga de una llamada a función y haciéndolas muy
  62 eficientes.
  63 
  64 1.  **`cycle_counter_init(void)`:**
  65     * Esta función inicializa el contador de ciclos del DWT.
  66     * `CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;`: Habilita el bloque de
  67       hardware de traza y depuración, que es necesario para que el DWT funcione.
  68     * `DWT->CYCCNT = 0;`: Reinicia el registro del contador de ciclos a cero.
  69     * `DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;`: Activa el contador para que
  70       empiece a contar los ciclos de reloj del CPU.
  71 
  72 2.  **`cycle_counter_reset(void)`:**
  73     * Simplemente reinicia el contador de ciclos a cero. Es útil para empezar a
  74       medir un intervalo de tiempo desde cero.
  75 
  76 3.  **`cycle_counter_get(void)`:**
  77     * Devuelve el valor actual del contador de ciclos, es decir, cuántos ciclos
  78       de reloj han transcurrido desde la última vez que se reinició.
  79 
  80 4.  **`cycle_counter_get_time_us(void)`:**
  81     * Esta es la función más útil para la medición de rendimiento. Convierte el
  82       número de ciclos de reloj a microsegundos ($µs$).
  83     * La fórmula utilizada es: `DWT->CYCCNT / (SystemCoreClock / 1000000)`.
  84     * **Explicación de la fórmula:**
  85         * `SystemCoreClock` es una variable global que contiene la frecuencia
  86           del CPU en Hercios (ciclos por segundo).
  87         * `(SystemCoreClock / 1000000)` calcula cuántos ciclos de reloj ocurren
  88           en un microsegundo.
  89         * Al dividir el número total de ciclos transcurridos (`DWT->CYCCNT`) por
  90           los ciclos por microsegundo, se obtiene el tiempo total transcurrido
  91           en microsegundos.
  92 
  93 **En resumen, este archivo es una herramienta de *profiling* o medición de
  94 rendimiento. Permite medir con gran precisión cuánto tiempo tarda en ejecutarse
  95 un bloque de código, lo cual es fundamental para calcular variables como el
  96 `WCET` (Worst-Case Execution Time) en el archivo `app.c`.**
  97 
  98 ---
  99 
 100 ### **Análisis de `systick.c` (Retardo Bloqueante por SysTick)**
 101 
 102 Este archivo implementa una función de retardo (delay) bloqueante con precisión
 103 de microsegundos, utilizando el temporizador del sistema **(SysTick)** del
 104 núcleo ARM Cortex-M.
 105 
 106 #### **Funcionamiento Detallado:**
 107 
 108 La única función, `systick_delay_us(uint32_t delay_us)`, funciona de la
 109 siguiente manera:
 110 
 111 1.  **Cálculo de Ticks Necesarios:**
 112     * Calcula el número total de "ticks" o ciclos de reloj del SysTick que se
 113       necesitan para alcanzar el retardo deseado en microsegundos (`delay_us`).
 114     * La fórmula `target = delay_us * (SystemCoreClock / 1000000UL)` es la misma
 115       que se usa en `dwt.h` para determinar el número de ciclos de CPU
 116       equivalentes al tiempo deseado.
 117 
 118 2.  **Bucle de Espera (Bloqueo):**
 119     * La función entra en un bucle infinito `while(1)` que es el núcleo del
 120       bloqueo. El microcontrolador no ejecutará ninguna otra instrucción de la
 121       aplicación principal mientras esté dentro de este bucle.
 122     * Dentro del bucle, lee continuamente el valor actual del contador SysTick
 123       (`SysTick->VAL`), que es un contador que cuenta hacia abajo.
 124 
 125 3.  **Manejo del "Wrap-Around" (Reinicio del Contador):**
 126     * El código maneja correctamente el caso en que el contador SysTick llega a
 127       cero y se recarga.
 128     * **Caso normal (`current <= start`):** Si el valor actual es menor que el
 129       inicial, el tiempo transcurrido es simplemente la resta `start - current`.
 130     * **Caso de reinicio (`current > start`):** Si el contador se reinició, el
 131       valor actual será mayor que el inicial. El tiempo transcurrido se calcula
 132       como `SysTick->LOAD + start - current`, donde `SysTick->LOAD` es el valor
 133       desde el que se recarga el contador. Esto asegura que el tiempo se mida
 134       correctamente incluso si el retardo abarca un reinicio del temporizador.
 135 
 136 4.  **Condición de Salida:**
 137     * En cada iteración del bucle, se comprueba si el tiempo transcurrido
 138       (`elapsed`) ha alcanzado o superado el objetivo (`target`).
 139     * Cuando `elapsed >= target`, el bucle se rompe con `break` y la función
 140       termina, completando el retardo.
 141 
 142 **En resumen, este archivo ofrece una función de espera precisa pero
 143 *bloqueante*. Es utilizada por el driver del display (`display.c`) para generar
 144 los pequeños retardos necesarios para la comunicación con la pantalla LCD. El
 145 término "bloqueante" es clave, ya que significa que mientras la función se
 146 ejecuta, el microcontrolador no puede realizar ninguna otra tarea en el bucle
 147 principal de la aplicación.**