commit dba0b2b6c6af99451986c8703fd6a0b3931cba5a
parent b96a32ad6862a3b6ba423d573da690bcd1620454
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date: Mon, 29 Sep 2025 12:23:02 -0300
update `README.md`
Diffstat:
| M | README.md | | | 73 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
1 file changed, 51 insertions(+), 22 deletions(-)
diff --git a/README.md b/README.md
@@ -1,5 +1,12 @@
# Taller de Sistemas Embebidos
+Este proyecto ejecuta una aplicación no bloqueante la cual se actualiza en cada
+milisegundo. A su vez esta aplicación incluye 3 tareas `task_sensor`,
+`task_system` y `task_actuator` las cuales se modelan mediante maquinas de
+estado. De estas 3 tareas solo se ha implementado la maquina de estados de la
+primer primera `task_sensor`, de las restantes solo se ha implementado lo
+suficiente como para que la aplicación se ejecute, pero no son funcionales.
+
```console
.
|-- app
@@ -66,13 +73,14 @@
## Archivo `Core/Startup/startup_stm32f103rbtx.s`
-Esta escrito en arm assembly y se ejecuta al resetear el microcontrolador, el
+Esta escrito en arm assembly y se ejecuta al inicializar el microcontrolador, el
propósito es inicializar los registros principales (como el stack pointer o el
program counter) la memoria y periféricos, para finalmente transferir el
control a la aplicación principal, la cual el punto de entrada es la función
-`main()`, esto se puede ver en la linea 100 del archivo, en la cual se ejecuta
-una instrucción `bl` (branch with link) y luego el símbolo `main`. El único tipo
-de dato utilizado es `word` que representa una variable de 4 bytes (o 32 bits).
+`main` (definida en el archivo `Core/Src/main.c`) esto se puede ver en la linea
+100 del archivo de inicialización, en la cual se ejecuta una instrucción `bl`
+(branch with link) y luego el símbolo `main`. El único tipo de dato utilizado es
+`word` que representa una variable de 4 bytes (o 32 bits).
## Archivo `Core/Src/main.c`
@@ -87,25 +95,46 @@ Los métodos que se encuentran en este archivo además de la (función principal
`MX_GPIO_Init`, `MX_USART2_UART_Init`, `app_init`, `app_update` y
`Error_Handler`.
-La funcion o metodo `initialise_monitor_handles` se encarga de inicializar o
+La función o método `initialise_monitor_handles` se encarga de inicializar o
configurar como se manipula la entrada y salida, por ejemplo con `printf` al
-momento de depurar el codigo, en particular se utiliza UART para comunicarse con
-la computadora, es por esto que se inicializa tambien con `MX_USART2_UART_Init`.
-La funcion `HAL_Init` iniciliza los estados internos de la libreria HAL
-(Hardware Abstraction Layer). `SystemClock_Config` como se indica en el nombre
-configura los relojes internos del microprocesador, como ser las fuentes y los
-preescaladores. La funcion `Error_Handler` se ejecuta en caso de error pero no
-tiene una funcionalidad definida. Por ultimo en la funcion `main` se
-inicializa la aplicacion con `app_init` y en cada ciclo se actualiza el estado
-de la aplicación con `app_update`.
+momento de depurar el código, en particular se utiliza el protocolo UART para
+comunicarse con la computadora, es por esto que se inicializa con la función
+`MX_USART2_UART_Init`.
+
+La función `SystemClock_Config` como se indica en el nombre configura los
+relojes internos del microprocesador, como ser las fuentes y los pre-escaladores
+de los buses y los timers. La velocidad del microprocesador se almacena en la
+variable global `SystemCoreClock`, esta variable se debe actualizar si se cambia
+la velocidad del microprocesador.
+
+Cuando se ejecuta la función `HAL_Init` se inicializa los estados internos de la
+librería HAL (Hardware Abstraction Layer) lo que incluye el timer `SysTick`,
+cuyo estado se almacena en la estructura global del mismo nombre. `SysTick` se
+utiliza para generar una interrupción por cada milisegundo, para esto cuenta
+desde `SystemCoreClock/1000` hasta 0, por ejemplo, para una frecuencia de 64MHz,
+el el timer cuenta desde 64000 hasta 0, lo que produce una interrupción exacta
+por milisegundo.
+
+La función `Error_Handler` se ejecuta en caso de error pero no tiene una
+funcionalidad definida. Por ultimo en la función `main` se inicializa la
+aplicación con `app_init` y en cada ciclo se actualiza el estado de la
+aplicación con `app_update`.
## Archivo `Core/app/app.c`
-En este archivo se definen las funciones `app_init`,`app_update` que se invocan
-en la función `main`, y el callback `HAL_SYSTICK_Callback`, este ultimo es
-una funcion definida de manera debil en la libreria HAL, y se inicializa al
-invocar `HAL_Init` en la función `main`, este callback se ejecuta cada 1 ms, y
-al estar definido de manera debil se puede sobreescribir, que es lo que se hace
-en el archivo. Se puede ver que el callback se sobreescribe para que en cada
-milisegundo incremente el contador global de la aplicacion y el interno de cada
-tarea.
+En este archivo se definen las funciones `app_init` y `app_update` que se
+invocan en la función `main`, y se define el callback `HAL_SYSTICK_Callback`,
+este ultimo es una función que previamente ya estaba definida pero de manera
+débil en la librería HAL, y se inicializa al momento de invocar `HAL_Init`, esta
+función se ejecuta cada 1 milisegundo debido a una interrupción generada por un
+timer. El callback se define de manera tal de incrementar el contador global de
+ticks de la aplicación y el interno de cada tarea, de esta manera, cada vez que
+el contador de cada tarea y de la aplicación dejan de ser nulos (en cada
+milisegundo) la aplicación y las tareas se deben actualizar.
+
+Cada vez que se ejecutan las tareas se mide el tiempo de ejecución contando los
+microsegundos que se tarde en ejecutar esa tarea, el pero de los tiempos de
+ejecución se guarda en el dato `WCET` de cada tarea. La aplicación también lleva
+un registro del tiempo de ejecución en microsegundos que se tarda en ejecutar
+todas las tareas, y resulta de la suma del tiempo de ejecución cada tarea, el
+resultado se guarda en la variable global `g_app_runtime_us`.