Está en la página 1de 227

UNIVERSIDAD SIMÓN BOLÍVAR

DECANATO DE ESTUDIOS PROFESIONALES


COORDINACIÓN DE TECNOLOGÍA E INGENIERÍA
ELECTRÓNICA

ELECTROCARDIÓGRAFO PORTATIL BASADO EN


ARQUITECTURA DE PROCESADORES
HETEROGÉNEOS

Por:
Rommel Aser Jesús Contreras Figueroa

Realizado con la asesorı́a de:


Prof. Guillermo Villegas

PROYECTO DE GRADO
Presentado ante la Ilustre Universidad Simón Bolı́var
como requisito parcial para optar al tı́tulo de
Ingeniero Electrónico

Sartenejas, Octubre del 2023


UNIVERSIDAD SIMÓN BOLÍVAR
DECANATO DE ESTUDIOS PROFESIONALES
COORDINACIÓN DE TECNOLOGÍA E INGENIERÍA
ELECTRÓNICA
ELECTROCARDIÓGRAFO PORTATIL BASADO EN
ARQUITECTURA DE PROCESADORES HETEROGÉNEOS
PROYECTO DE GRADO
PRESENTADO POR:
Rommel Aser Jesús Contreras Figueroa, 14-10242

RESUMEN

La presente investigación por un lado se centra en el estudio y la implementación


del funcionamiento en detalle de la plataforma de desarrollo PICO-PI-IMX7 de la
empresa TechNexion. Esta plataforma utiliza el SoC (System on Chip) i.MX7D
de NXP Semiconductors que utiliza multiprocesamiento heterogéneo: dual ARM
Cortex-A7 Core para la ejecución de un sistema operativo Linux y un ARM Cortex-
M4 Core, que se dedica a la adquisición y al procesamiento en tiempo real. De
esta manera, se pueden desarrollar aplicaciones electrocardiográficas que aprove-
chen los beneficios del procesamiento heterogéneo posibilitando una adquisición
sin pérdida de datos y evitando el uso de un driver (Linux) de tiempo real. Como
sensores para la adquisición del electrocardiograma se consideraron dos cabeceras
analógicas (Analog Front End, AFE): ADS1298 de Texas Instruments y BMD101
de NeuroSky. Se estudiaron e implementaron las primitivas de código tanto en
firmware como en software, para cubrir la funcionalidad de los diferentes com-
ponentes del sistema que comprende la plataforma de desarrollo PICO-PI-IMX7
y los AFE. A partir de estas primitivas se implementaron aplicaciones (electro-
cardiógrafos) para capturar, procesar y graficar la data en tiempo real y además
permite consultarla vı́a Internet.

Palabras clave: System on Chip, multiprocesamiento heterogéneo, procesamiento


en tiempo real, electrocardiograma, AFE, electrocardiógrafo.

i
Agradecimientos
A mis abuelos, gracias por todo el cariño que me dieron y por regalarme unos
padres tan excepcionales, preocupados y amorosos, llevo conmigo su recuerdo y
están presente en todos mis logros.
A mi madre Fidia Figueroa, gracias por su amor incondicional y tu abnegación
como madre, la sociedad suele agradecerles el regalo de la vida, pero yo le agradezco
más que a diario, llena mi vida de amor y felicidad. Te amo mamá, a veces siento
que no te lo digo lo suficiente.
A mi padre Rommel Contreras, gracias por todo el cariño, el amor y la forma-
ción que junto a mi madre me brindas, gracias por haber hecho de mi la persona
que hoy soy, por desde muy pequeño mostrarme la ciencia y llenar mi vida de
luces. Te amo papá.
A mi hermanita Stephanie Contreras, gracias por llenarme todos los dı́as de
orgullo, por cuidarme y amarme incondicionalmente, gracias por estar siempre ahı́
para mı́ y ser un ejemplo a seguir. Te amo hermanita, no dudo que tengo la mejor
hermana de todas.
A Jhon Campos, no sabes cuanto me alegró conocerte cuñado eres una persona
muy amable, cariñosa y de buen corazón. doy gracias de saber que mi hermana
tiene una persona tan especial a su lado.
A mi hermano, por los buenos momentos compartidos y por los que nos faltan
por vivir. Espero que el futuro nos permita acercarnos más.
A todos mis tı́os y tı́as en especial a: Gloria Figueroa, Angel Contreras, Raisa
Contreras, Alirio Cardoza, Rita Contreras y Raquel Contreras, por todo su cariño,
apoyo y preocupación.
A mis primos Angel Contreras, Dayana Mendoza ,Jose Cardoza, Yajariyu Car-
doza y Daniela Cardoza por todo el amor y cariño que me has demostrado desde
bebé, gracias por todo el apoyo primo.
A la Sra Alicia Peñaloza por hacer de su casa un hogar para mı́ durante mi
aventura universitaria, agradezco mucho su cariño y consejos a lo largo de todos
estos años. De igual modo agradezco el haber tenido compañeros y amigos como
Maylis Rivero, Alejandro Guevara y Luis Vargas.
A Todos mis amigos de la orquesta, me encantarı́a que de nuevo pudiéramos ha-
cer música juntos, atesoro y valoro con mucho cariño los buenos momentos hemos

ii
iii

vivido. En especial gracias a: Andreina Moreno, Letmi Escobar, Luis Rodriguez,


Edgar Barón, José Contreras, Gian Rega y Patricia Marval.
A todos mis amigos de la universidad en especial a: Pedro Fanega, Julio Barrios,
Luis Flores, Sofı́a Vega, Hillany Rodriguez, Naulymar Morillo, José Danglad, al
delegado (Andrés Bustamante), José Coa, David Bellorin, Rafaella Martinez, Car-
lo Márquez, Yvan León, Xavier Bracho, Said Alvarado, Yeiskel Cisneros, Marco
Arroyo y Sabrina Rodriguez, por todo su cariño y apoyo durante todos estos años.
Haberlos conocidos es uno de los regalos más grandes que me dió la universidad.
A mis amigos de biomecatrónica en especial a: Marı́a Parilli, Juan Nuñez, Marı́a
Bohorquez (la maracucha), los años que compartimos juntos en esta agrupación
son muy preciados para mı́.
A mis amigos de la salita de electrónica, por toda la alegrı́a, calidez que me
hicieron sentir.
A mis amigos de fı́sica; a veces siento que nunca hubiera dejado la carrera,
gracias por todo el cariño y aprecio que me tienen. Me llenan de orgullo como
personas y como profesionales.
A mi tutor Guillermo Villegas, usted ha sido uno de los profesores que más a
marcado mi desarrollo profesional, gracias por haber compartido su conocimiento
conmigo y todo el apoyo durante estos años, le doy las gracias en mi nombre y en
el de todos los compañeros que han tenido la suerte de tenerlo como profesor.
A la profesora Marı́a Isabel, gracias por confiar en mı́ y haberme dado la opor-
tunidad de haber estudiado una carrera tan maravillosa. Espero no decepcionarla
nunca.
A mis profesores, a todos los niveles, de formación y en especial a: Edgar Barón,
Gaudi Morantes, Gerardo Fernandez, Angel Terrones, Shunichi Watanabe y Lin
Song. Gracias por haberme enseñado de la manera que lo hicieron, ustedes son y
serán pilares fundamentales en mi desarrollo como persona y como profesional.
Índice general

Resumen I

Agradecimientos II

Índice de Figuras VIII

Lista de Tablas XII

Lista de Acrónimos XIII

1. Marco teórico 5
1.1. Microcontrolador . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2. Microprocesador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3. Procesadores Heterogéneos . . . . . . . . . . . . . . . . . . . . . . . 6
1.4. SoC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.5. SoM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.6. SiP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.7. Imagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.7.1. Bootloader . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.7.2. Aplicaciones BareMetal . . . . . . . . . . . . . . . . . . . . . 8
1.7.3. kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.7.4. Sistema Operativo . . . . . . . . . . . . . . . . . . . . . . . 9
1.7.5. Sistemas Operativos en Tiempo Real (RTOS) . . . . . . . . 9
1.8. IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.9. Electrocardiografia . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.10. Electrocardiógrafo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.11. Interfaces de Comunicación . . . . . . . . . . . . . . . . . . . . . . 17
1.11.1. UART . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.11.2. Interfaz Periférica en Serie . . . . . . . . . . . . . . . . . . . 19
1.11.3. Bus Serial Universal . . . . . . . . . . . . . . . . . . . . . . 21
1.11.4. OTG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.11.5. Circuito Inter-Integrado I2C . . . . . . . . . . . . . . . . . . 24
1.11.6. Comunicación Inter-procesadores IPC . . . . . . . . . . . . . 26
iv
Índice general v

1.12. Shell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.12.1. SSH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

2. Descripción de las Plataformas de Desarrollo 30


2.1. Plataforma Principal . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.1.1. SoC i.MX7D . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.1.2. SoM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.1.3. Carrier Baserboard . . . . . . . . . . . . . . . . . . . . . . . 40
2.1.4. Pantalla LCD Táctil de 5 pulgadas . . . . . . . . . . . . . . 42
2.1.5. Analog Frontend AFE . . . . . . . . . . . . . . . . . . . . . 43
2.1.6. Hub Slim de 4 Puertos USB 3.0 . . . . . . . . . . . . . . . . 47
2.1.7. USB TO UART Bridge . . . . . . . . . . . . . . . . . . . . . 48
2.2. Plataforma de desarrollo Auxiliar . . . . . . . . . . . . . . . . . . . 49
2.2.1. PICDEM Z Demonstration Kit . . . . . . . . . . . . . . . . 49
2.3. Herramientas de Depuración y Laboratorio . . . . . . . . . . . . . . 52
2.3.1. NI myDAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
2.3.2. In Circuit Debbugger 3 (ICD3) . . . . . . . . . . . . . . . . 52
2.3.3. Analizador Lógico . . . . . . . . . . . . . . . . . . . . . . . . 53
2.3.4. Divisor de Voltaje para Señales de mV . . . . . . . . . . . . 54
2.4. Plataforma de Laboratorio . . . . . . . . . . . . . . . . . . . . . . . 55
2.5. Software de la Plataforma Principal . . . . . . . . . . . . . . . . . . 56
2.6. Firmware PIC18F4620 . . . . . . . . . . . . . . . . . . . . . . . . . 58
2.7. Softwares Auxiliares para Interactuar con las Plataformas . . . . . 58
2.7.1. ARM DS IDE . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.7.2. Visual Studio Code . . . . . . . . . . . . . . . . . . . . . . . 59
2.7.3. MPLAB X . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.7.4. Kst2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.7.5. PuTTY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
2.7.6. NI ELVISmx Instrument . . . . . . . . . . . . . . . . . . . . 60
2.7.7. DSO Monitor Controller . . . . . . . . . . . . . . . . . . . . 60
2.7.8. Universal Update Utility (UUU) . . . . . . . . . . . . . . . . 60

3. Configuración de las Plataformas y Desarrollo Experimental 61


3.1. Experiencia 1: Carga de la imagen mediante UUU en Windows . . . 63
3.2. Experiencia 2: Carga de la imagen con UUU en Linux . . . . . . . . 64
3.3. Experiencia 3: Carga de la imagen con Bootbomb . . . . . . . . . . 64
3.4. Experiencia 4: Carga de la imagen en Linux usando el comando dd
y Bootbomb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3.5. Experiencia 5: Carga de la imagen con el comando ums de U-Boot . 68
3.6. Experiencia 6: Carga de la imagen con BalenaEtcher . . . . . . . . 68
3.7. Problemas corregidos de las imagenes . . . . . . . . . . . . . . . . . 69
3.8. Creación de una imagen para la plataforma de trabajo . . . . . . . 70
3.9. Compendio de métodos de carga de imagen . . . . . . . . . . . . . . 70
3.9.1. Compilando el U-Boot . . . . . . . . . . . . . . . . . . . . . 71
Índice general vi

3.10. Optimización del Sistema Operativo (Ubuntu) . . . . . . . . . . . . 72


3.10.1. Expansión del Almacenamiento . . . . . . . . . . . . . . . . 72
3.10.2. Inicio de programas después del arranque en Ubuntu . . . . 73
3.10.3. Implementación de mecanismos de Acceso Remoto . . . . . . 75
3.10.4. Optimización General . . . . . . . . . . . . . . . . . . . . . 81
3.11. Cadena de compilación para FreeRTOS en Terminal . . . . . . . . . 84
3.11.1. Carga de una Imagen Firmware en el núcleo M4 . . . . . . . 85
3.11.2. ARM Develop Studio IDE . . . . . . . . . . . . . . . . . . . 86
3.11.3. Modulos del Kernel Linux . . . . . . . . . . . . . . . . . . . 87
3.12. Árbol de dispositivos . . . . . . . . . . . . . . . . . . . . . . . . . . 88
3.12.1. Árbol de dispositivos Linux . . . . . . . . . . . . . . . . . . 88
3.12.2. Árbol de dispositivos: Archivos BSP FreeRTOS y aplicacio-
nes BareMetal . . . . . . . . . . . . . . . . . . . . . . . . . . 90
3.13. Primitivas básicas implementadas con el núcleo M4 . . . . . . . . . 91
3.13.1. Control de GPIO y LEDs con el núcleo M4 . . . . . . . . . . 91
3.13.2. Control de la interfaz UART . . . . . . . . . . . . . . . . . . 93
3.13.3. Manejo de la interfaz I2C . . . . . . . . . . . . . . . . . . . 94
3.14. Primitivas básicas implementadas para el núcleo A7 . . . . . . . . . 95
3.14.1. Manipulación de GPIO . . . . . . . . . . . . . . . . . . . . . 96
3.14.2. Control de la Backlight del LCD . . . . . . . . . . . . . . . . 102
3.14.3. Manejo del UART . . . . . . . . . . . . . . . . . . . . . . . 102
3.14.4. Manejo de la interfaz SPI . . . . . . . . . . . . . . . . . . . 103
3.14.5. Instalación de Processing en Ubuntu sobre i.MX7D . . . . . 105
3.14.6. Ejecución de programas desarrollados en Processing . . . . . 105
3.15. RPMsg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
3.16. Primitivas básicas asociadas a RPMsg . . . . . . . . . . . . . . . . 118
3.16.1. Ecos de caracteres con RPMsg . . . . . . . . . . . . . . . . . 118
3.16.2. RPMsg PingPong . . . . . . . . . . . . . . . . . . . . . . . . 122
3.17. Implementación del Driver para controlar el AFE ADS1298 usando
la plataforma auxiliar . . . . . . . . . . . . . . . . . . . . . . . . . . 125
3.17.1. Configuración del PICDEM Z Demostration Kit . . . . . . . 126
3.17.1.1. Registro de Configuración 1 . . . . . . . . . . . . . 127
3.17.2. Ciclo de operación descrito por el fabricante . . . . . . . . . 135
3.17.3. Elaboración del Driver . . . . . . . . . . . . . . . . . . . . . 144
3.18. Implementación de un Driver para Controlar el BMD101 mediante
la PICO-PI-IMX7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
3.18.1. BMD101 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
3.18.2. Driver implementado . . . . . . . . . . . . . . . . . . . . . . 147
3.18.3. Módulo kernel Linux A7 . . . . . . . . . . . . . . . . . . . . 159
3.19. Página Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
3.20. Sistema X Window . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

4. Resultados 187
4.1. Resultados driver AFE ADS1298 . . . . . . . . . . . . . . . . . . . 187
Índice general vii

4.1.1. Análisis de los resultados . . . . . . . . . . . . . . . . . . . . 188


4.2. Resultados Driver AFE BMD101 . . . . . . . . . . . . . . . . . . . 189
4.2.1. Determinación experimental de la tasa de muestreo . . . . . 190
4.2.2. Determinación experimental de la ganancia . . . . . . . . . . 190
4.2.3. Comportamiento en frecuencia del AFE . . . . . . . . . . . 191
4.2.4. Graficación de los datos usando Kst2 . . . . . . . . . . . . . 192
4.2.5. Análisis de los resultados . . . . . . . . . . . . . . . . . . . . 196
4.3. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
4.4. Recomendaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Índice de figuras

1.1. Señal ECG [10]. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10


1.2. Componentes de la forma de onda ECG [11]. . . . . . . . . . . . . . 11
1.3. Triangulo de Einthoven [10]. . . . . . . . . . . . . . . . . . . . . . . 13
1.4. Electrodos Precordiales V1 a V6. . . . . . . . . . . . . . . . . . . . 14
1.5. Wilson Central Terminal [10]. . . . . . . . . . . . . . . . . . . . . . 14
1.6. Diagrama propuesto por Maxim Integrated en la nota de aplica-
ción AN4693 para la implementación completa de un dispositivo
electrocardiógrafo [14]. . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.7. Conexión de la interfaz UART [15]. . . . . . . . . . . . . . . . . . . 18
1.8. Interfaz UART modificado de [15]. . . . . . . . . . . . . . . . . . . 19
1.9. Conexión de la interfaz SPI para múltiples dispositivos esclavos [16]. 20
1.10. Ejemplo de actividad en la interfaz SPI bajo el modo de configura-
ción SPI1 [16]. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.11. Hilos que componen el cable USB. . . . . . . . . . . . . . . . . . . . 21
1.12. Estandar de conectores en el protocolo USB. . . . . . . . . . . . . . 23
1.13. Esquema de conexión de la interfaz I2C [20]. . . . . . . . . . . . . . 24
1.14. Trama de datos generico dentro del protocolo I2C [20]. . . . . . . . 25
1.15. Comportamiento de la interfaz I2C bajo diferentes escenarios A)
Escritura de un byte; B) Escritura de más de un byte; C)Lectura de
un byte; D) Lectura de más de un byte [21]. . . . . . . . . . . . . . 26
1.16. Diagrama conceptual de comunicación inter-procesadores mediante
memoria compartidas [22]. . . . . . . . . . . . . . . . . . . . . . . . 26
1.17. Diagrama conceptual handshaking SSH [23]. . . . . . . . . . . . . . 28

2.1. Diagrama General de la Plataforma Principal. . . . . . . . . . . . . 31


2.2. Montaje Plataforma Principal. . . . . . . . . . . . . . . . . . . . . . 32
2.3. Módulos de la Plataforma Principal. . . . . . . . . . . . . . . . . . 32
2.4. Topologı́a de bus compartido [24]. . . . . . . . . . . . . . . . . . . . 34
2.5. Controlador de dominio de recursos (RDC) del SoC i.MX7D [25]. . 35
2.6. Sistema de reloj del SoC i.MX7D [25]. . . . . . . . . . . . . . . . . 36
2.7. Messaging Unit del SoC i.MX7D [25]. . . . . . . . . . . . . . . . . . 37
2.8. Unidad de manejo de energı́a [25]. . . . . . . . . . . . . . . . . . . . 39
2.9. Diagrama de bloques del SoM PICO- IMX7 EMMC[26]. . . . . . . 39
2.10. Vista superior de la PICO-PI-IMX7 Carrier Baserboard GL [27]. . . 40
2.11. Diagrama de puertos e interfaces de la PICO-PI-IMX7: Carrier Ba-
serboard PICO-PI-GL, SoM PICO-IMX7-EMMC. . . . . . . . . . . 40

viii
Índice de figuras ix

2.12. Conectores tipo header JP1, JP2 y JP8 de la PICO-PI-GL [30]. . . 41


2.13. Configuración de los jumpers J1 y J2, para alternar entre los modos:
Descarga Serial e Inicio desde la eMMC [30]. . . . . . . . . . . . . . 42
2.14. Modo de descarga serial (izquierda), modo de inicio desde la eMMC
(derecha) [26]. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
2.15. Pantalla LCD touch screen de 5 pulgadas TDP0500T800480PCAP . 43
2.16. Módulo de adquisición ECG basado en ADS1298. . . . . . . . . . . 44
2.17. Diagrama de bloques del ADS1298 [31]. . . . . . . . . . . . . . . . . 44
2.18. Módulo ECG 4 Click de MikroElektronika [32]. . . . . . . . . . . . 46
2.19. Diagrama de bloques del BMD101 [32]. . . . . . . . . . . . . . . . . 47
2.20. 4-Port Ultra Slim USB 3.0 Data Hub. . . . . . . . . . . . . . . . . . 47
2.21. Módulo USB to Serial GPIO Breakout - CP2103 de Sparkfun. . . . 48
2.22. Diagrama del módulo USB to Serial GPIO Breakout - CP2103 de
Sparkfun [33]. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
2.23. Diagrama general de la plataforma Auxiliar. . . . . . . . . . . . . . 49
2.24. Vista superior de la plataforma PICDEM Z Demostration Kit[27]. . 50
2.25. Pinout del PIC18F4620. [34]. . . . . . . . . . . . . . . . . . . . . . 50
2.26. Plataforma de adquisición de datos NI myDAQ [35]. . . . . . . . . . 52
2.27. Esquema de conexión del ICD3 [36] . . . . . . . . . . . . . . . . . . 53
2.28. Analizador lógico HiLetgo [37]. . . . . . . . . . . . . . . . . . . . . 53
2.29. Ejemplo entorno Logic 2 [38]. . . . . . . . . . . . . . . . . . . . . . 54
2.30. Divisor de Voltaje para Señales de mV . . . . . . . . . . . . . . . . 54
2.31. Plataforma de Laboratorio . . . . . . . . . . . . . . . . . . . . . . . 55
2.32. Señal Cardiac generada con el generador de funciones. . . . . . . . . 56
2.33. Flujo de operación del Boot ROM [25]. . . . . . . . . . . . . . . . . 57

3.1. Configuración realizada en PuTTY. . . . . . . . . . . . . . . . . . . 63


3.2. Salida del comando usando UUU [47]. . . . . . . . . . . . . . . . . . 64
3.3. Esquema de carga de la imagen con el comando ums (U-Boot) y
comando dd (Linux Host [49]). . . . . . . . . . . . . . . . . . . . . 68
3.4. Carga de la imagen mediante BalenaEtcher. . . . . . . . . . . . . . 69
3.5. Salida de la consola del procesador auxiliar imagen con problema
override reserved memory. . . . . . . . . . . . . . . . . . . . . . . . 69
3.6. Elección de método de carga de imagen [55]. . . . . . . . . . . . . . 71
3.7. Conectar unidad de red en Windows. . . . . . . . . . . . . . . . . . 78
3.8. Salida de df -h luego de la optimizan realizada. . . . . . . . . . . . . 84
3.9. Salida de la compilación por terminal de Hello World. . . . . . . . . 85
3.10. Ejecución de los comandos en la consola de U-Boot. . . . . . . . . . 86
3.11. Salida del ejemplo Hello World. . . . . . . . . . . . . . . . . . . . . 86
3.12. Ejemplo para dispositivo UART mapeado en memoria. . . . . . . . 89
3.13. Arbol de dispositivos de alto nivel [68]. . . . . . . . . . . . . . . . . 89
3.14. Relación de los archivos que integran el árbol de Dispositivos que
integran el árbol de dispositivos de la PICO-PI-I.MX7D. . . . . . . 90
3.15. Árbol de directorio BSP FreeRTOS. . . . . . . . . . . . . . . . . . . 91
3.16. Señal de salida del GPIO o LED configurado. . . . . . . . . . . . . 92
Índice de figuras x

3.17. Salida en consola del programa blinking imx demo. . . . . . . . . . 93


3.18. Modificación de la configuración para el funcionamiento de I2C. . . 94
3.19. Modificación de la interfaz I2C. . . . . . . . . . . . . . . . . . . . . 94
3.20. Modificación de la interfaz I2C. . . . . . . . . . . . . . . . . . . . . 95
3.21. Actividad de la interfaz I2C. . . . . . . . . . . . . . . . . . . . . . . 95
3.22. Salida del comando de visualización del archivo /sys/kernel/debu-
g/gpio. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
3.23. Salida del comando gpiodetect. . . . . . . . . . . . . . . . . . . . . 97
3.24. Salida del comando gpioinfo. . . . . . . . . . . . . . . . . . . . . . . 98
3.25. Señal PWM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
3.26. Actividad en el puerto SPI generada desde Processing, visualizada
desde Logic2 mediante el analizador lógico. . . . . . . . . . . . . . . 104
3.27. Ejecución de la aplicación Visor Sismómetro [73] en la plataforma
de desarrollo PICO-PI-IMX7. . . . . . . . . . . . . . . . . . . . . . 107
3.28. Modelo de la comunicación entre procesadores IPC RPMsg [74]. . . 109
3.29. Analogı́a VirtIO [75]. . . . . . . . . . . . . . . . . . . . . . . . . . . 110
3.30. Implementacı́on de Virtio [74]. . . . . . . . . . . . . . . . . . . . . . 111
3.31. Mecanismo de comunicación de RPMsg. . . . . . . . . . . . . . . . 112
3.32. Mecanismo de comunicación de RPMsg modificado [74]. . . . . . . . 115
3.33. Mecanismo de Desconección de RPMsg modificado por [74]. . . . . 116
3.34. Comunicación rpmsg A7-M4 [76]. . . . . . . . . . . . . . . . . . . . 119
3.35. Salida consola serial auxiliar M4 esclavo en la espera del maestro. . 120
3.36. Mensaje enviado desde el maestro Cortex-A7 con Linux y su eco
retornado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
3.37. Mensaje recibido en el esclavo Cortex-M4 con FreeRTOS. . . . . . . 122
3.38. Mecanı́smo de interacción. . . . . . . . . . . . . . . . . . . . . . . . 123
3.39. Salida terminal de depuración del ARM Cortex-M4 (FreeRTOS). . . 124
3.40. Salida terminal del shell Linux ARM Cortex-A7. . . . . . . . . . . . 124
3.41. Módulo de adquisición ECG, vista superior. . . . . . . . . . . . . . 125
3.42. Módulo de adquisición ECG, vista inferior. . . . . . . . . . . . . . . 125
3.43. Etiquetas de definición, PIC18F4620 (Izq.) PIC18F46K22 (Der.). . 126
3.44. Modo 1 comunicación SPI Microchip Technology [81]. . . . . . . . . 127
3.45. Modo 1 comunicación SPI para ADS1298 Texas Instruments [31]. . 127
3.46. Estructura del registro de CONFIG1 [31]. . . . . . . . . . . . . . . 128
3.47. Configuración detallada del registro CONFIG1 [31]. . . . . . . . . . 128
3.48. Estructura del registro de CONFIG2 [31]. . . . . . . . . . . . . . . 128
3.49. Configuración detallada del registro CONFIG2 [31]. . . . . . . . . . 129
3.50. Estructura del registro de CONFIG3 [31]. . . . . . . . . . . . . . . 129
3.51. Configuración detallada del registro CONFIG3 [31]. . . . . . . . . . 130
3.52. Estructura de los registros asociados a la configuración de los cana-
les de adquisición CHnSET [31]. . . . . . . . . . . . . . . . . . . . . 130
3.53. Configuración detallada de los registros CHnSET [31]. . . . . . . . . 131
3.54. Comportamiento de la interfaz SPI bajo la acción del comando
RDATAC [31]. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Índice de figuras xi

3.55. Comportamiento de la interfaz SPI bajo la acción del comando


RDATA [31]. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
3.56. Comportamiento de la interfaz SPI bajo la acción del comando
RREG [31]. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
3.57. Comportamiento de la interfaz SPI bajo la acción del comando
WREG [31]. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
3.58. Flujograma de captura y operación del ADS1298 [31]. . . . . . . . . 135
3.59. Plataforma auxiliar. . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
3.60. Registros configurados del ADS1298 vistos desde MPLAB mediante
el ICD3 activando la depuración en circuito. . . . . . . . . . . . . . 141
3.61. Registros configurados del ADS1298 vistos desde Logic2 mediante
el analizador lógico. . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
3.62. Lectura y captura de datos a partir de la consola serial de RealTerm
mediante la interfaz serial. . . . . . . . . . . . . . . . . . . . . . . . 144
3.63. Señales utilizadas para la elaboración del driver, configuradas en
Logic2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
3.64. Módulo ECG 4 Click Vista Superior [32]. . . . . . . . . . . . . . . . 146
3.65. Módulo ECG 4 Click Vista Inferior [32]. . . . . . . . . . . . . . . . 147
3.66. Estructura de la salida de datos del BMD101 [32]. . . . . . . . . . . 148
3.67. Estructura del payload del BMD101 [32]. . . . . . . . . . . . . . . . 149
3.68. Diagrama de flujo del algoritmo Driver. . . . . . . . . . . . . . . . . 151
3.69. Estructura cliente servidor de X. . . . . . . . . . . . . . . . . . . . . 184
3.70. Salida en pantalla del programa xeyes. . . . . . . . . . . . . . . . . 186
3.71. Ejemplo de salida en pantalla de Kst2 mediante X. . . . . . . . . . 186

4.1. Señal capturada. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188


4.2. Determinación experimental frecuencia de muestreo mediante gra-
ficación en Kst2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
4.3. Bode de Magnitud resultante del barrido de frecuencias. . . . . . . 192
4.4. Señal Senoidal 1mV @ 1Hz visualización en la patalla de la plata-
forma de desarrrollo. . . . . . . . . . . . . . . . . . . . . . . . . . . 193
4.5. Señal Senoidal 1mV @ 20Hz visualización en la patalla de la plata-
forma de desarrrollo. . . . . . . . . . . . . . . . . . . . . . . . . . . 194
4.6. Señal Senoidal 1mV @ 20Hz visualización en la patalla de un orde-
nador remoto mediante SSHFS. . . . . . . . . . . . . . . . . . . . . 194
4.7. Señal Cardiac, visualización en la página web de visualización. . . . 195
4.8. Señal Cardiac, visualización en la página web de visualización. . . . 195
9. Diagrama esquemático de la PICDEM Z [27]. . . . . . . . . . . . . 208
Índice de tablas

1.1. Caracterı́sticas de la señal ECG (Adultos). . . . . . . . . . . . . . . 11


1.2. Caracterı́sticas Generales de las plataformas AFE [14]. . . . . . . . 16
1.3. Tipos de AFE para ECG [14]. . . . . . . . . . . . . . . . . . . . . . 17
1.4. Funcionamiento de los pines de la interfaz SPI. . . . . . . . . . . . . 20
1.5. Modos de configuración de la interfaz SPI. . . . . . . . . . . . . . . 21
1.6. Descripción de las lı́neas que componen la interfaz I2C. . . . . . . . 24
1.7. Las señales que integran un marco de datos en la comunicación I2C. 25

3.1. Caracterı́sticas de la comunicación serial con la plataforma de de-


sarrollo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.2. Tipos de datos de salida BMD101 [32] . . . . . . . . . . . . . . . . 149

1. Datos usada para la determinación experimental de la cantidad de


muestras por segundo Parte 1 . . . . . . . . . . . . . . . . . . . . . 209
2. Datos usada para la determinación experimental de la cantidad de
muestras por segundo Parte 2 . . . . . . . . . . . . . . . . . . . . . 210

xii
Lista de Acrónimos

A7 ARM Cortex A7 Core, Núcleo A7.


AC Alternating Current, Corriente Alterna.
ACK Acknowledge, Reconocimiento (I2C).
ADC Analog-to-Digital Converter, Convertidor Análogo Digital.
AC97 Audio Codec 97, Códec de Audio 97.
AFE Analog Front End, Cabecera Analógica.
AED Automated External Defibrillator, Desfibrilador Externo Au-
tomático.
aVR Augmented Vector Right, Derivación aVR.
aVL Augmented Vector Left, Derivación aVL.
aVF Augmented Vector Foot, Derivación aVF.
ASIC Application Specific Integrated Circuit, Circuito Integrado de Apli-
cación Especı́fica.
BOM Bill of Materials, Lista de Materiales.
CAN Controller Area Network, Red de Área de Controlador.
CCGR Control Clock Gating Register, Registro de Control y Bloqueo del
Reloj.
CCM Clock Control Module, Módulo de Control de Reloj.
COM Communications Port, Puerto de Comunicaciones.
CPHA Clock Phase, Fase del Reloj (SPI).
GPC General Power Control, Control General de Energı́a.
CPOL Clock Polarity, Polaridad del Reloj (SPI).
CPU Central Processing Unit, Unidad de Procesamiento Central.
CRC Cycling Redundancy Code, Código de Redundancia Cı́clica.

xiii
Lista de Acrónimos xiv

CSI Camera Serial Interface, Interfaz Serial de Cámara.


DAQ Data Acquisition, Adquisición de Datos.
DC Direct Current, Corriente Directa.
eMMC embebbed Multimedia Card, Tarjeta embebida multimedia
DDR3 Double Data Rate 3, Memoria de Tasa Doble de Datos 3 .
ECG Electrocardiogram, Electrocardiograma.
GND Ground, Tierra.
GPIO General-Purpose Input/Output, Entrada/Salida de Propósito Ge-
neral.
HMP Heterogeneous Multi-Processor, Multiprocesador Heterogéneo.
I2C Inter-Integrated Circuit, Interfaz de Circuito Inter-Integrado.
ID Identifier, Identificador.
IDM Integrated Device Manufacturer, Fabricante de Dispositivos Inte-
grados.
IPC Inter-Processor Communication, Comunicación Interprocesado-
res.
LED Light Emitting Diode, Diodo Emisor de Luz.
LOFF Lead-Off Detection, Detección de Desconexión de Electrodos.
LPCG Low Power Clock Gating, Activador/desactivador de Reloj de Ba-
jo Consumo.
LPDDR2 Low Power Double Data Rate 2, Tasa de Doble Datos de Bajo
Consumo 2.
LPDDR3 Low Power Double Data Rate 3, Tasa de Doble Datos de Bajo
Consumo 3.
M4 ARM Cortex M4 Core, Núcleo M4.
MCU Micro-controller Unit, Unidad de Micro-controlador.
MIPS Microprocessor without Interlocked Pipeline Stages, Microprocesa-
dor sin Etapas de Pipeline Interconectadas.
MPU Microprocessor Unit, Unidad de Microprocesador.
NACK Not Acknowledge, No Reconocimiento (I2C).
OS Operating System, Sistema Operativo.
Lista de Acrónimos xv

OSC Oscillator, Oscilador.


P Stop Condition, Condición de Parada (I2C).
PCB Printed Circuit Board, Tarjeta de circuito impreso.
PCM Pulse Code Modulation, Modulación por Codificación de Pulsos.
PCIe Peripheral Component Interconnect Express, Interconexión de
Componentes Periféricos Express.
PFD Phase Frequency Detector, Detector de Fase y Frecuencia.
PIC Peripheral Interface Controller, Controlador de Interfaz Periféri-
ca.
PFD Phase Frequency Detector, Detector de Fase y Frecuencia.
PLL Phase-Locked Loop, Bucle de Enganche de Fase.
PMIC Power Management Integrated Circuit, Circuito Integrado de Ges-
tión de Energı́a.
PMU Power Management Unit, Unidad de Gestión de Energı́a.
RA Right Arm, Brazo Derecho.
RA Repeated Start Condition, Condición de Inicio Repetida (I2C).
RAM Random Access Memory, Memoria de Acceso Aleatorio.
RF Radio Frequency, Frecuencia de Radio.
RL Right Leg, Pierna Derecha.
RLD Right Leg Drive, Impulsor de la Pierna Derecha.
ROM Read Only Memory, Memoria de Solo Lectura.
RPMsg Remote Processor Message, Mensajes entre Procesadores Remo-
tos.
RTOS Real Time Operating System, Sistema Operativo en Tiempo Real.
RX Receive, Receptor (UART).
S Start Condition, Condición de Inicio (I2C).
SCP Secure Copy Protocol, Protocolo de Copia Segura.
SDP Secure Device Provisioning, Provisión Segura de Dispositivos.
SFTP SSH File Transfer Protocol, Protocolo de Transferencia de Archi-
vos sobre SSH.
SiP System in Package, Sistema en paquete.
Lista de Acrónimos xvi

SMP Symmetric Multi-Processor, Multiprocesador Simétrico.


SoC System on a Chip, Sistema en Chip.
SoM System on Module, Sistema en Módulo.
SPI Serial Peripheral Interface, Interfaz Periférica en Serie.
SSH Secure Shell, Capa de seguridad para conexiones de red.
SSHFS SSH Filesystem, Sistema de Archivos sobre SSH.
SS o CS Slave Selector o Chip Selector, Selector de Esclavo o Selector de
Chip (SPI).
TX Transmit, Transmisor (UART).
TTY Terminal Type, Tipo de Terminal (Consola serial o similar en en-
torno Linux).
UART Universal Asynchronous Receiver/Transmitter, Receptor Trans-
misor Universal Ası́ncrono.
UMS USB Mass Storage, Almacenamiento Masivo USB.
USB Universal Serial Bus, Bus Universal en Serie.
UUU Universal Update Utility, Utilidad de Actualización Universal.
VBUS Voltage Bus, Bus de Voltaje.
V1 Chest Lead V1, Derivación V1.
V2 Chest Lead V2, Derivación V2.
V3 Chest Lead V3, Derivación V3.
V4 Chest Lead V4, Derivación V4.
V5 Chest Lead V5, Derivación V5.
V6 Chest Lead V6, Derivación V6.
W Write, Escritura (I2C).
Wi-Fi Wireless Fidelity, Fidelidad Inalámbrica.
Introducción

Este proyecto está enmarcado en el área de investigación de instrumentación


biomédica de signos vitales, especı́ficamente en el área de electrocardiografı́a estu-
diando los aspectos de la implementación de un electrocardiógrafo portátil.
En el Grupo de Bioingenierı́a y Biofı́sica Aplicada (GBBA) en la Universidad
Simón Bolı́var se han desarrollado varios proyectos y aplicaciones relacionadas
con la electrocardiografı́a: en 1998 se desarrolló una aplicación cliente servidor
para la transmisión de ECG vı́a Internet [1], en el año 2001 se realizó un estudio
sobre la transmisión de señales ECG en “tiempo real” para aplicaciones no clı́nicas
[2] y también un sistema telemétrico de electrocardiografı́a basado en Internet
embebido [3], en 2006 un monitor electrocardiográfico con Bluetooth y capacidades
de Holter para aplicaciones de telemedicina [4]. No obstante, hasta ahora no se
ha incluido la tecnologı́a de multiprocesamiento heterogéneo a nivel de la unidad
de controladora/procesador en la implementación de las aplicaciones, por lo que
este trabajo se plantea como un aporte para el uso de esta tecnologı́a en nuevas
investigaciones.
Elegir un Microprocessor Unit (MPU) ejecutando Linux para el diseño de un
dispositivo portátil médico puede ofrecer enormes ventajas. Sin embargo, es res-
ponsabilidad del diseñador del sistema garantizar que se mantenga la seguridad del
paciente, y la exactitud y seguridad de los datos. La exactitud de los datos tiene
que ver con la adquisición y procesamiento en tiempo real, y esto se puede lograr
incluyendo un Microcontroller Unit (MCU). La coexistencia de MPU y MCU es
lo que se conoce como multiprocesamiento heterogéneo.
La plataforma de desarrollo PICO-PI-IMX7 de TechNexion, está integrada por
dos tarjetas conectadas en piggyback (tarjeta superpuesta): un SoM y una ca-
rrier baseboard. (placa base). El SoM (PICO-IMX7-EMMC) integra el procesador
heterogéneo i.MX7D (SoC) e incluye elementos como memoria DDR3, almacena-
miento eMMC, circuito integrado de gestión de energı́a (PMIC), SIP (System in

1
Introducción 2

Package) para conexiones inalámbricas (Wi-Fi / Bluetooth), conectores board-to-


board y otros elementos. La carrier baseboard (PICO-PI-GL) dispone de conectores
board-to-board e interfaces para comunicarse e interactuar con el mundo real: au-
dio, Ethernet, USB y conectores pin headers (conectores de pines machos) para
un gran número de señales.
Como sensores para la adquisición del electrocardiograma se consideraron dos
cabeceras analógicas (Analog Front End, AFE): ADS1298 de Texas Instruments y
BMD101 de NeuroSky. Además, el dispositivo incluye una pantalla táctil LCD de 5
pulgadas que sirve como interfaz hombre-máquina para visualizar la información.
El i.MX7 (DUAL) de NXP Semiconductors es un System on Chip (SoC) de pro-
cesador heterogéneo que integra dos núcleos MPU ARM Cortex-A7 y un núcleo
MCU ARM Cortex-M4. El núcleo ARM Cortex-M4 se encarga del control del AFE
y de la adquisición de datos. Una vez adquiridos, los datos se transfieren mediante
un protocolo de comunicación inter procesadores a los núcleos ARM Cortex-A7,
donde se ejecuta el sistema operativo Linux. Esta arquitectura garantiza una ope-
ración sin pérdida de datos y elimina la necesidad de utilizar un driver de tiempo
real en el sistema operativo (Linux). La comunicación de datos a plataformas re-
motas se puede implementar de forma inalámbrica, permitiendo la transferencia
de información a una estación central de monitoreo de manera efectiva.
Se estudiaron e implementaron las primitivas de código tanto en firmware para
el ARM Cortex-M4 Core, como en software para el ARM Cortex-A7 Core, para
cubrir la funcionalidad de los diferentes componentes del sistema que comprende la
plataforma de desarrollo PICO-PI-IMX7 y los AFE. A partir de estas primitivas
se implementaron aplicaciones (electrocardiográficas) para capturar, procesar y
graficar los datos en tiempo real en la pantalla LCD del dispositivo y con la
posibilidad consultar esta data vı́a Internet.
Con este nuevo dispositivo se cubren aplicaciones electrocardiográficas donde se
requiere un dispositivo portátil (portable y hand held ) y de bajo consumo, para el
área de la instrumentación biomédica en los siguientes ámbitos: salud en el hogar
(Home Health Care), cuidados paliativos (Hospice Care), residencias geriátricas
(Nursing Homes) y la oficina de doctor (Physician Office).
Los beneficios y aplicaciones de los procesadores heterogéneos no han sido ex-
plotados en el ámbito académico venezolano, esta tesis pretende ser un trabajo
pionero que abra paso a futuras investigaciones en este campo, tanto para la Uni-
versidad Simón Bolı́var como para el resto del paı́s.
Introducción 3

Objetivos

Objetivo general
Estudio e implementación en detalle de las primitivas de firmware y software
necesarias para realizar una aplicación de electrocardiografı́a, capaz de capturar,
procesar y desplegar datos en tiempo real mediante la plataforma de desarrollo de
arquitectura heterogénea PICO-PI-IMX7 de TechNexion y de cabeceras analógicas
para electrocardiografı́a.

Objetivos especı́ficos
Estudiar los procesos necesarios para configurar las platformas de trabajo.

Estudiar el estado del arte referente a los procesadores heterogéneos.

Realizar un driver para el control de un dispositivo AFE.

Utilizar un protocolo de comunicación inter procesadores para transferir la


data entre los núcleos del SoC i.MX7D de NXP Semiconductors.

Capturar, procesar y graficar la data proveniente del AFE para su visuali-


zación y/o posterior consulta.

Estudiar e implementar mecanismos de comunicación con la plataforma de


desarrollo, que permitan acceder a los datos de manera remota.

Estructura del trabajo


Esta investigación está dividida en cuatro capı́tulos que se desarrollan de la
siguiente manera:
Capı́tulo 1 Marco Teórico: Expone los fundamentos teóricos significativos
para la investigación y necesarios para realizar la descripción de la plataforma.
Capı́tulo 2 Descripción de las Plataformas: En este capı́tulo se describe
el hardware, instrumentos y herramientas de software utilizadas a lo largo de la
investigación.
Capı́tulo 3 Configuración de la Plataforma y Desarrollo Experimen-
tal: Presenta las primitivas elaboradas a lo largo de la investigación necesarias
para la configuración de la plataforma y el desarrollo de los objetivos planteados.
Introducción 4

Capı́tulo 4. Resultados: eEpone los resultados obtenidos a partir de las


primitivas implementadas.
Capı́tulo 5 Conclusiones y Recomendaciones: Expone las conclusiones
obtenidas a partir de la investigación y las recomendaciones para desarrollos futu-
ros que sigan esta lı́nea de investigación.
Capı́tulo 1

Marco teórico

Este Capı́tulo presenta una revisión de los antecedentes y fundamentos teóricos


de la investigación, con el fin de facilitar la comprensión del contenido que se
desarrolla a lo largo de la investigación. Se exponen las definiciones generales
de las tecnologı́as que conforman las plataformas utilizadas en el proyecto y los
aspectos teóricos de la aplicación y las señales en estudio.

1.1. Microcontrolador
Un microcontrolador es un dispositivo implementado en un solo circuito in-
tegrado que combina una unidad central de procesamiento, memoria (RAM y
ROM/Flash), periféricos de entrada/salida (E/S), en muchos casos, convertido-
res analógico-digitales (ADC) y otros componentes en un paquete compacto. Los
microcontroladores están diseñados para aplicaciones especı́ficas, como el control
de dispositivos electrónicos, monitoréo de variables fı́sicas a través de sensores, y
un amplio rango de aplicaciones. Suelen tener estar incluidas tareas de control en
tiempo real y bajo consumo de energı́a.

1.2. Microprocesador
En el contexto actual, el termino microprocesador ha cambiado debido al auge
de los procesadores “multi-núcleo” los cuales están integrados por varias unidades
de computo conocidas como núcleos [5]. El concepto original de un microprocesa-
dor corresponde al de un núcleo de procesamiento individual, estos son similares

5
Capı́tulo 1. Marco teórico 6

a los microcontroladores en el sentido de integrar diferentes elementos de hardwa-


re como: CPU, memorias RAM y ROM, periféricos, unidades de procesamiento
gráfico, entre otros. Sin embargo, están diseñados como unidades con altas capa-
cidades de cómputo y procesamiento; son utilizados en aplicaciones generales que
involucren sistemas operativos, como: televisores, teléfonos inteligentes, tabletas,
servidores y una amplia variedad de dispositivos.

1.3. Procesadores Heterogéneos


Los sistemas multi-núcleo heterogéneos, son sistemas que combinan dos o más
núcleos con diferentes especificaciones entre MCU y MPU [6]. En la industria de
sistemas embebidos para aplicaciones en tiempo real, los sistemas heterogéneos
multi-núcleo se han convertido en arquitecturas populares y ampliamente utiliza-
das. Los sistemas embebidos que incorporan una arquitectura heterogénea, per-
miten un mejor manejo de la disposición de los recursos de computo, permitiendo
asignar más o menos recursos a un determinado problema.
Esto implica, que al trabajar con procesadores heterogéneos debemos implemen-
tar una arquitectura de software, adaptadas a las caracterı́sticas del procesador.
Estos sistemas suelen combinar entornos de software diferentes. Los MPU suelen
trabajar con un sistema operativo de uso general, mientras que las MCU pueden
correr sistemas operativos en tiempo real (RTOS) como aplicaciones BareMetal.

1.4. SoC
Un SoC (System on Chip) es un circuito integrado de un solo die (sustrato
semiconductor) que contiene la mayorı́a o todos los componentes de una compu-
tadora o sistema electrónico. Estos componentes incluyen: una o varias unidades
de procesamiento, memorias, puertos de entrada y salida, interfaces periféricas y
dispositivos de almacenamiento secundario. Frecuentemente también pueden estar
incluidos otros componentes como módems de radio y unidades de procesamiento
gráfico (GPU).
Capı́tulo 1. Marco teórico 7

1.5. SoM
Un SoM (System on Module), es un tipo de placa electrónica que integra diver-
sos componentes esenciales de un sistema informático en un solo módulo compacto
en un PCB. Estos componentes suelen incluir procesadores, memoria, almacena-
miento y otros elementos como controladores de periféricos, interfaces de comuni-
cación y circuitos de alimentación.
La principal ventaja de un SoM es facilitar el diseño y desarrollo de sistemas
embebidos, ya que gran parte del hardware esencial y su acondicionamiento se
encuentra integrado en el módulo. Esto reduce el tiempo y la complejidad del
diseño de la placa base, permitiendo a los diseñadores centrarse en la funcionalidad
especı́fica de su producto en lugar de tener que diseñar y construir todo el sistema
desde cero.

1.6. SiP
Un SiP (System in Package), es una manera de empaquetar dos o más circuitos
integrados dentro de un solo paquete. Esto es en contraste al SoC donde las funcio-
nes de los integrados están implementadas en un mismo substrato semiconductor.
En vez de colocar circuitos integrados en un circuito impreso (PCB), estos pueden
ser combinados en un mismo paquete para reducir costos o para acortar distancias
que las señales deben viajar.

1.7. Imagen
En el entorno de los SoC el termino imagen refiere a una copia de un sistema
operativo y su entorno, configurados especı́ficamente para funcionar en un circuito
integrado o en un conjunto de circuitos integrados. Una imagen en este sentido
contiene todo lo necesario para arrancar y ejecutar un sistema en un SoC.
Una imagen SoC incluye componentes como:

ˆ Bootloader

ˆ Sistemas Operativos

ˆ kernel
Capı́tulo 1. Marco teórico 8

ˆ Sistema de archivos

ˆ Configuraciones

ˆ Aplicaciones y software adicional

1.7.1. Bootloader
El iniciador de arranque o bootloader es el programa que se ejecuta al encender
o reiniciar un dispositivo. Su función principal es preparar la carga de un sistema
operativo (OS). El bootloader se encuentra en una memoria de arranque especı́fica;
como la memoria ROM o la memoria flash, y es responsable de varias tareas
importantes, como:

ˆ Inicialización del hardware: Como es el programa de inicio de un sistema


embebido, realiza la conexión entre el hardware del dispositivo y el sistema
operativo [7].

ˆ Selección del sistema operativo: El bootloader permite la selección del


sistema operativo que se debe cargar.

ˆ Verificación de integridad: Verificar la integridad y autenticidad del OS


antes de cargarlo para evitar la ejecución del software no autorizado o mo-
dificado.

ˆ Carga del sistema operativo.

1.7.2. Aplicaciones BareMetal


Una aplicación BareMetal se ejecuta como software privilegiado de bajo nivel
con acceso directo al procesador y periféricos, sin la intervención de ninguna capa
de sistema operativo. Estas aplicaciones garantizan tiempos de ejecución estrictos
en plataformas de hardware con recursos muy limitados [8].

1.7.3. kernel
El kernel es el núcleo central de un sistema operativo que administra los recur-
sos del hardware y facilita la interacción entre el software y el hardware en una
computadora.
Capı́tulo 1. Marco teórico 9

1.7.4. Sistema Operativo


Un sistema operativo es un software fundamental que actúa como intermediario
entre el hardware de una computadora y las aplicaciones de software. Proporciona
una interfaz y servicios para que los programas puedan ejecutarse en la máquina.
En esencia, el sistema operativo es el núcleo del funcionamiento de una compu-
tadora, gestionando recursos y permitiendo la interacción entre los componentes
fı́sicos y los usuarios.

1.7.5. Sistemas Operativos en Tiempo Real (RTOS)


Los sistemas operativos de tiempo real o RTOS (Real Time Operative Sistem)
son sistemas operativos diseñados para administrar y controlar sistemas y aplica-
ciones que requieren respuestas en tiempo real. A diferencia de los sitemas opera-
tivos de propósito general, que están orientados a tareas generales de cómputo los
RTOS están diseñados para garantizar la ejecución de tareas crı́ticas en tiempo
real. Estos se clasifican en: Hard RTOS donde el cumplimiento de los plazos de
respuesta puede tener consecuencias graves para la datos (estos pueden resultar
inútiles para un instante de tiempo posterior al esperado) y Soft RTOS donde solo
se requieren garantı́as de rendimiento [9].

1.8. IDE
Los entornos de desarrollo integrados (IDE) son herramientas de software que
proporciona un conjunto integrado de caracterı́sticas y utilidades para facilitar el
desarrollo de aplicaciones de software en un solo entorno.
Los IDE generalmente incluyen:

ˆ Editor de código: Un editor que permite escribir, editar y formatear el


código fuente del programa en varios lenguajes de programación.

ˆ Compilador o Interprete: Un compilador o intérprete integrado que con-


vierte el código fuente escrito por el desarrollo en código ejecutable.

ˆ Depurador: Una herramienta que ayuda a los desarrolladores a identificar


y corregir errores.
Capı́tulo 1. Marco teórico 10

ˆ Plantillas y asistentes: Proporciona plantillas de código o asistentes para


agilizar la creación agilizar la creación de proyectos y estructuras de código
comunes.

ˆ Administración de proyectos: Facilita la gestión de proyectos, permitien-


do o organizar archivos, recursos y bibliotecas en una estructura coherente.

1.9. Electrocardiografia
El corazón es el responsable de mantener un flujo adecuado de sangre a través
del cuerpo, con la finalidad de entregar oxı́geno y nutrientes mientras se remueve
dióxido de carbono y desperdicios. Durante cada latido cardı́aco, el corazón se
contrae en una secuencia especı́fica y en un orden preciso para garantizar que la
sangre fluya en la dirección adecuada. Este flujo se da a través de las distintas
cámaras del corazón: las aurı́culas y los ventrı́culos. Cada segmento del corazón
se contrae debido a su propia señal eléctrica (onda de depolarización), y la suma
de estas señal es en la superficie del cuerpo del paciente da como resultado el
electrocardiograma que tiene una forma de onda caracterı́stica. Ver las Figuras 1.1
y 1.2.

Figura 1.1: Señal ECG [10].


Capı́tulo 1. Marco teórico 11

Figura 1.2: Componentes de la forma de onda ECG [11].

La tabla 1.1 Resume las caracterı́sticas de la señal ECG:


Tabla 1.1: Caracterı́sticas de la señal ECG (Adultos).

Onda Amplitud (mV) Duración seg


P 0.25 0.12 - 0.22 (Intervalo PR)
R 1.06 0.07 - 0.1
T 0.1 - 0.5 0.05 - 0.15 (Segmento S T)
Complejo QRS - 0.09

El ECG tiene caracterı́sticas únicas que son altamente identificables incluso


para no profesionales, por ejemplo observando el perı́odo entre segmentos repe-
tidos podemos determinar la frecuencia cardı́aca. Como cada porción de la onda
corresponde a un segmento especı́fico del ciclo cardı́aco; los cardiólogos expertos
pueden utilizar estas ondas para diagnosticar un gran número de enfermedades
y afecciones cardı́acas. El rango de información posible a partir del ECG es la
razón por la que un amplio número de aplicaciones relacionadas a la salud pueden
requerir medidas de ECG.
La electrocardiografı́a es una técnica de medida de la actividad eléctrica del co-
razón. Un electrocardiograma (ECG) es una representación gráfica de las señales
Capı́tulo 1. Marco teórico 12

eléctricas del corazón en función del tiempo. Los ECG recogen las señales cardı́acas
mediante electrodos ubicados en la piel en áreas especı́ficas del cuerpo, que regis-
tran la actividad eléctrica generada por el corazón. Estos electrodos permiten
estudiar el comportamiento del corazón desde diferentes ángulos, representados
como canales. Cada canal refleja la diferencia de voltaje entre dos electrodos, o
entre un electrodo y la medida promedio de varios.
Los canales se denomina derivaciones (leads), por lo que un ECG de 12 deri-
vaciones tiene 12 canales separados que se muestran gráficamente. El número de
derivaciones varı́a de 1 a 12 según la aplicación. Desafortunadamente, los cables
que van a los electrodos ocasionalmente también se denominan leads. Esto puede
crear confusión, ya que un ECG de 12 derivaciones (12 canales) solo requiere 10
electrodos y 10 cables dado que algunas medidas son tomadas de manera indirecta
mediante cálculo, a partir de la data registrada por otros canales. En resumen,
tenemos 8 canales diferenciales independientes y 4 canales se obtienen a partir de
otras derivaciones.
Los electrocardiógrafos son capaces de detectar señales como: la señal de los
marcapasos denominada como pace y la señal de lead-off que ocurre cuando un
electrodo tiene mal contacto eléctrico con la piel. Muchos dispositivos son capaces
de generar una señal de alerta indicando este mal contacto. En algunos dispositivos
la frecuencia respiratoria también se detecta mediante el análisis de la medida
indirecta de la impedancia del torax.

Derivaciones
Se llaman electrodos primarios a los tres vertices que conforman el triángulo de
Einthoven (Figura 1.3). Estos están ubicados en el brazo izquierdo, brazo derecho
y pierna izquierda y son conocidos como LA, RA, LL (por sus siglas en Inglés),
a partir de estos electrodos podemos obtener las tres primeras derivaciones, las
cuales son:

ˆ Lead I: V LA − V RA

ˆ Lead II: V LL − V RA

ˆ Lead III: V LL − V LA
Capı́tulo 1. Marco teórico 13

Figura 1.3: Triangulo de Einthoven [10].

Ley de Einthoven
Cualquiera de las derivaciones primarias puede ser calculada a partir de las
otras dos. Por lo que solo se necesitan medir dos de las tres derivaciones, en el
caso particular de la derivación III la ecuación 1.1 queda como:

Lead III = Lead II- Lead I (1.1)

Además de los tres electrodos primarios, un cuarto electrodo llamado Right-Leg


(RL) es utilizado para reducir el voltaje de modo común (interferencia) realimen-
tado a la Right Leg (pierna derecha) el voltaje de modo común sensado, invertido
y amplificado.

Derivaciones precordiales
Los electrodos precordiales o pectorales, proveen información respecto a los
ventrı́culos del corazón en múltiples ángulos transversales. Estos se numeran desde
V1 a V6 (Figura 1.4).
Capı́tulo 1. Marco teórico 14

Figura 1.4: Electrodos Precordiales V1 a V6.

Estas derivaciones están referenciadas respecto al centro del triángulo de Eintho-


ven; punto que también es conocido como Wilson Central Terminal (WCT). Ver
Figura 1.5
Asumiendo:
RRA = RLA = RLL (1.2)

RA + LA + LL
VW ilson = (1.3)
3

Figura 1.5: Wilson Central Terminal [10].

Esta señal es utilizada como la referencia negativa de las derivaciones precor-


diales.
Capı́tulo 1. Marco teórico 15

Derivaciones aumentadas
Proveen información que mejora el vector de información para determinar el eje
eléctrico del corazón. aVR, aVL y aVF se determinan a partir del punto medio
de las extremidades.

LL + LA
aVR = RA − (1.4)
2

LL + RA
aVL = LA − (1.5)
2

LA + RA
aVF = LL − (1.6)
2

1.10. Electrocardiógrafo
En 1887, el fisiólogo e ingeniero británico Augustus Waller fue el primero en
en utilizar un galvanómetro para registrar la actividad eléctrica del corazón, lo-
grando registrar un ECG muy rudimentario utilizando un par de electrodos y un
galvanómetro [12]. El primer monitor diseñado para observar estas señales es el de
Willem Eithoven en 1906 quien desarrolló el primer electrocardiógrafo, un instru-
mento más sensible y preciso para medir la actividad eléctrica del corazón. Fue el
primero en utilizar los términos P, Q, R, S y T para describir las diferentes ondas
que conforman la señal de ECG [13].
Con las evolución de la electrónica, la tecnologı́a ha llevado a la implementa-
ción de monitores especializados, en clı́nicas y hospitales. Ahora, no solo adquie-
ren diferentes derivaciones de los biopotenciales cardı́acos, si no que, también son
capaces de monitorear otros signos vitales como: saturación de oxı́geno, presión
arterial; temperatura, entre otros parámetros. Obteniendo más información para
el diagnóstico y monitoreo de pacientes, pero implicando sistemas de control y pro-
cesamiento digital más sofisticados. Estos dispositivos varı́an en costo y tamaño,
desde unidades portátiles hasta equipos clı́nicos complejos. [14].
La implementación de un electrocardiógrafo, se puede dividir en dos partes:
el AFE, que adquiere y digitaliza las señales, y el resto del sistema, que analiza,
muestra, almacena y transmite los datos; según las capacidades del dispositivo
en cuestión. Los AFE comparten requisitos básicos, pero varı́an en número de
derivaciones, fidelidad de la señal, rechazo a las interferencias, entre otros. El
Capı́tulo 1. Marco teórico 16

resto del sistema difiere según la presencia de caracterı́sticas como la inclusión


de: pantalla, impresión, conexión en radio frecuencias (RF) y baterı́as recargables
(Figura 1.6).

Figura 1.6: Diagrama propuesto por Maxim Integrated en la nota de aplicación


AN4693 para la implementación completa de un dispositivo electrocardiógrafo
[14].

En la tabla 1.2 se tienen las caracterı́sticas de los electrocardiógrafos según su


aplicación.

Tabla 1.2: Caracterı́sticas Generales de las plataformas AFE [14].

Caracteristicas Telemetrı́a Holter Consumidor AED Diagnóstico Monitoreo de pacientes


Alimentación
Lı́nea N N N N A A
Recargable S S S S U A
Disposable U U U U S S
Comunicación
RF A S S S S S
RS-232/RS485 N S S S S S
Ethernet S S S S S S
USB N S S S S S
Modem N S S S S S
Data card N U S S S S
Graphic display S U A S S A
Printer N N N N A S
Capı́tulo 1. Marco teórico 17

Analog Frontend (AFE) para ECG


La función principal de estos AFE es adquirir las señales eléctricas del corazón.
Este proceso se complica debido a la necesidad de rechazar interferencias de fuentes
de RF fuertes, señales de marcapaso, señales de lead-off, voltaje de modo común
de la lı́nea de frecuencia, señales electromiográficas y ruido eléctrico. Además,
la señal de ECG a nivel de milivoltios puede estar superpuesta a un voltaje de
offset DC que puede ser de alrrededor 200 mV normalmente relacionado con la
interfaz electrodo piel. Las conexiones eléctricas al paciente no deben crear un
riesgo de descarga eléctrica ni interferir con otros equipos médicos que puedan
estar conectados al paciente. El rango de frecuencia de interés para el ECG varı́a
según la aplicación. Para el caso de ECG de reposo de 12 derivaciones (resting
12-lead electrocardiography) es de 0.05Hz a 100Hz.
Además, la mayorı́a de los electrocardiógrafos deben recuperarse rápidamente
de un evento de desfibrilación, que puede saturar el AFE y cargar los capacitores
asociados al mecanismo de sampling and hold 1 .

Tipos de AFE para ECG


La Tabla 1.3 los clasifica según sus caracterı́sticas y arquitecturas:

Tabla 1.3: Tipos de AFE para ECG [14].

Caracterı́sticas Monitor de pacientes Diagnostico Telemetrı́a Holter AED Consumidor


Alta inmunidad a RF U U S S S N
Frecuencia min [Hz] 0.05 0.05 50 150 40 40
Frecuencia de Muestreo [Sps] 1k -100k 1k -100k 1024 1024 250+ 250+
Resolución [bits] 12 - 20 12 - 20 12 - 20 12 - 20 12 10 - 12
Right led drive A A S S N S
Pace (marcapasos) A A U U U S
Detección de Lead-off A A U U A S
Compatible con Defibrilación A U A U A S

1.11. Interfaces de Comunicación


Las plataformas de desarrollos utilizadas durante esta investigación cuentan
con diversas interfaces de comunicación como: SPI, UART, I2C, entre otras. Esta
sección pretende describir el funcionamiento general de las interfaces utilizadas.
1
Muestreo y retención, proceso en el que una señal analógica es muestreada (capturada) en
intervalos de tiempo discretos y luego se mantiene constante durante el proceso de conversión.
Capı́tulo 1. Marco teórico 18

1.11.1. UART
El protocolo UART (Universal Asynchronous Receiver-Transmitter ) es un pro-
tocolo de comunicación serial ampliamente utilizado para transmitir datos entre
dispositivos. El protocolo UART es ası́ncrono, lo que significa que no se requiere
una señal de reloj compartida para sincronizar los datos entre los dispositivos. En
cambio, se envı́a un flujo de bits a través de dos lı́neas: una para transmitir (TX)
y otra para recibir (RX). La comunicación puede ser Full Duplex 2 o Half Duplex 3
(Figura 1.7).

Figura 1.7: Conexión de la interfaz UART [15].

El proceso de transmisión UART incluye los siguientes elementos:

Bit de Inicio: Cada trama de datos comienza con un bit de inicio, que
es un nivel lógico bajo (0). El bit de inicio señala al receptor que se está
iniciando una nueva trama. En estado de inactividad la señal normalmente
se encuentra en alto (1).

Bit de Datos: Los datos se envı́an en forma de bit. La cantidad de bit de


datos en cada trama se configura previamente, generalmente en 7 u 8 bit.

Bit de Paridad (Opcional): Si se habilita, puede incluirse un bit de pa-


ridad después de los bit de datos. El bit de paridad puede ser par o impar y
ayuda a detectar errores en la transmisión.
2
Full Duplex permite la comunicación bidireccional simultánea, con lı́neas separadas para
transmitir y recibir datos.
3
Half Duplex significa que la comunicación se realiza en ambos sentidos, pero no de manera
simultánea. Los dispositivos alternan entre transmitir y recibir en una única lı́nea de comunica-
ción.
Capı́tulo 1. Marco teórico 19

Bit de Parada: Después de los bit de datos y si está habilitado el bit de


paridad, se envı́an uno o más bit de parada. Los bit de parada son niveles
lógicos altos (1) que indican el final de la trama Figura (1.8).

Figura 1.8: Interfaz UART modificado de [15].

A pesar de que los dispositivos no comparten una señal de reloj, se estandariza


una velocidad de transmisión conocida como baud rate para asegurar una comu-
nicación confiable. El baud rate se mide en bit por segundo (bps) y determina la
velocidad a la que se transmiten los bit. Ambos dispositivos deben configurarse
con el mismo baud rate para garantizar una comunicación adecuada.

1.11.2. Interfaz Periférica en Serie


La interfaz SPI (Serial Peripheral Interface) es un protocolo de comunicación
sı́ncrono ampliamente utilizado en electrónica para la transferencia de datos en-
tre un dispositivo maestro y uno o varios dispositivos esclavos. Este protocolo es
especialmente útil en aplicaciones donde se requiere una alta velocidad de transmi-
sión y recepción de datos, ası́ como una comunicación confiable entre componentes
electrónicos.
En la Figura 1.9 se puede observar conexión de la interfaz SPI configurada para
interactuar con múltiples nodos:
Capı́tulo 1. Marco teórico 20

Figura 1.9: Conexión de la interfaz SPI para múltiples dispositivos esclavos


[16].

La comunicación en la interfaz SPI se basa en cuatro lı́neas principales:

Tabla 1.4: Funcionamiento de los pines de la interfaz SPI.

Lı́nea Función
SCLK Señal de Reloj, es dispuesta por el maestro para la sincronización con dispositivos esclavos
MOSI Salida de datos del maestro, entrada de datos de los dispositivos esclavos
MISO Entrada de datos del maestro, salida de datos de los dispositivos esclavos
SS o CS Selector de chip o selector de esclavo

Además de las lineas que componen la interfaz, se deben tomar en cuenta los
modos de configuración de la interfaz estos varı́an según:

CPOL: determina el estado inicial de la lı́nea SCLK cuando no está en uso.


En algunas configuraciones, el estado inicial es bajo (CPOL = 0), mientras
que en otras es alto (CPOL = 1). Esto afecta cómo se interpretan los datos
en los flancos de subida o bajada de la señal SCLK.

CPHA: determina en qué momento los datos se capturan y se transmiten en


relación con la señal SCLK. En el caso de CPHA = 0, los datos se capturan
en el flanco de bajada y se transmiten en el flanco de subida de SCLK. En
el caso de CPHA = 1, ocurre lo contrario: los datos se capturan en el flanco
de subida y se transmiten en el flanco de bajada de SCLK.

En la siguiente tabla se listan los modos de operación de la interfaz SPI y sus


distintas configuraciones:
Capı́tulo 1. Marco teórico 21

Tabla 1.5: Modos de configuración de la interfaz SPI.

Modo SPI CPOL CPHA Fase de SCLK utilizada para muestrear y/o correr la data
0 0 0 Data muestreada en el flanco de subida y corrida en el flanco de bajada.
1 0 1 Data muestreada en el eje de bajada y corrida en el flanco de bajada.
2 1 0 Data muestreada en el eje de subida y corrida en el eje de bajada.
3 1 1 Data muestreada en el eje de bajada y corrida en el eje de subida.

A continuación se muestra un ejemplo con el modo de configuración SPI1:

Figura 1.10: Ejemplo de actividad en la interfaz SPI bajo el modo de confi-


guración SPI1 [16].

1.11.3. Bus Serial Universal


El USB (Universal Serial Bus) es un protocolo de comunicación que estable-
ce un estándar para conectar periféricos y dispositivos a una computadora [17].
Destaca por su facilidad de uso gracias a la función Plug-and-Play, que permite
conectar y desconectar dispositivos sin reiniciar la computadora. Con diferentes
velocidades de transferencia y tipos de conexiones, el USB se ha convertido en
el estándar predominante en los ordenadores y otros dispositivos, facilitando la
conexión y transferencia de datos entre dispositivos electrónicos.
La Figura 1.11 muestra los hilos que componen el cable USB para los stándares
más tı́picos.

Figura 1.11: Hilos que componen el cable USB.


Capı́tulo 1. Marco teórico 22

El protocolo emplea cuatro hilos y sigue una topologı́a de red con un único
maestro y múltiples esclavos. La arquitectura del USB se compone de tres elemen-
tos principales: el anfitrión USB, el dispositivo USB y la interconexión USB.
El anfitrión USB opera como maestro en la comunicación y es único en la red.
Su función principal es gestionar las transferencias de datos entre sı́ mismo y los
periféricos conectados. Por otro lado, el dispositivo USB actúa como esclavo en la
conexión. La red USB puede soportar hasta 127 dispositivos conectados al mismo
anfitrión, lo que contribuye a su versatilidad.
La interconexión USB se basa en tres componentes esenciales. La lı́nea de ali-
mentación (VBUS) proporciona 5V para la energı́a, la lı́nea de tierra (GND) esta-
blece una referencia común y un par trenzado transmite señales de datos D+ y D-.
Esta configuración garantiza una comunicación confiable entre los dispositivos.
La orientación del flujo de datos en el contexto del anfitrión USB determina
que la información de entrada se desplaza desde el dispositivo hacia el anfitrión,
mientras que los datos de salida se transmiten desde el anfitrión hacia el dispositivo.
Las transferencias USB suelen adoptar un enfoque isócrono y para el caso USB
2.0 proporcionan tres rangos de velocidad de transmisión: uno de baja velocidad
de hasta 1.5 Mbps, otro de velocidad media de hasta 12.5 Mbps y, por último, uno
de alta velocidad que alcanza hasta 480 Mbps.
La arquitectura del protocolo USB se desglosa en cuatro categorı́as principales
para la transferencia de datos. Inicialmente, las transferencias de control se utilizan
para la configuración de dispositivos recién conectados, estableciendo parámetros
iniciales. En segundo lugar, las transferencias de bulto permiten la transmisión de
grandes volúmenes de datos, con capacidad para detectar errores y retransmitir
tramas, y asignan un ancho de banda variable en función de la actividad del bus.
Por otro lado, las transferencias por interrupción agilizan el envı́o de tramas de
datos breves con latencia limitada, otorgándoles cierta prioridad en el bus, pero
sucediendo con menos frecuencia.
Finalmente, las transferencias isócronas siguen un enfoque similar al de las
transferencias de bulto, pero aseguran una latencia acotada en el bus, garantizan un
ancho de banda completo y no permiten la retransmisión de datos. Cada categorı́a
de transferencia juega un papel vital en el funcionamiento del protocolo USB,
posibilitando la configuración de dispositivos, la transmisión eficiente de datos y la
gestión de prioridades, adecuándose a las exigencias de los dispositivos conectados
al bus.
Las diferencias entre las variantes Mini y Micro se reflejan en la configuración
Capı́tulo 1. Marco teórico 23

del cuarto pin (ID), conectado a tierra en los modelos de tipo A y dejado des-
conectado en los modelos de tipo B. En contraste, el conector USB tipo C [18]
representa una arquitectura más moderna dentro de este estándar. Caracterizado
por su reversibilidad, este conector alberga 24 pines dispuestos simétricamente en
ambos lados, lo que elimina la necesidad de una orientación especı́fica al inser-
tarlo. Además de esta ventaja, el USB tipo C admite tasas de transferencia más
veloces y una mayor capacidad de suministro de energı́a en comparación con sus
predecesores.

1.11.4. OTG
USB OTG4 es una especificación de la tecnologı́a USB que permite que los
dispositivos USB actúen como anfitriones o como dispositivos esclavos según sea
necesario[19].
En la Figura 1.12 se muestran los diferentes conectores junto con su estándar
de pines.

Figura 1.12: Estandar de conectores en el protocolo USB.


4
Por sus siglas en On the Go, (sobre la marcha en español).
Capı́tulo 1. Marco teórico 24

1.11.5. Circuito Inter-Integrado I2C


Es un protocolo de comunicación serial serial sı́ncrono y Full Dupex de dos
hilos desarrollado por Philips en la decada de 1980 (ahora NXP Semiconductors).
Al igual que el protocolo SPI esta interfaz es utilizada para comunicar varios
dispositivos utilizando una filosofı́a maestro - esclavo, donde un dispositivo actúa
como maestro de la comunicación para interactuar con uno o varios dispositivos
esclavos. En el caso de protocolo I2C cada dispositivo esclavo posee un número
de identificación único, y la comunicación del o los dispositivos maestros hacia los
esclavos se realiza mediante el uso de ese identificador; que permite seleccionar el
dispositivo con el cual se requiera establecer comunicación. Los dispositivos pueden
actuar como transmisores o receptores.

Tabla 1.6: Descripción de las lı́neas que componen la interfaz I2C.

Pin Función
SDA Es la vı́a de transmisión y recepción de datos entre el
maestro y los dispositivos esclavos.
SCL Es la lı́nea que porta la señal de reloj generada por el
maestro.

Las lı́neas que conforman la interfaz son drenador-abierto5 ; por lo que es nece-
sario colocar resistencias de polarización pull-upps 6 .

Figura 1.13: Esquema de conexión de la interfaz I2C [20].


5
Configuración de salida en la que un dispositivo drena corriente hacia un nivel de voltaje
más bajo como “tierra”, permitiendo usar rangos de voltaje para la señal de salida.
6
Son resistencias utilizadas para establecer un nivel lógico alto en una lı́nea de señal cuando
no se encuentra activamente en uso.
Capı́tulo 1. Marco teórico 25

Dado que la comunicación a través de I2C se fundamenta en direccionamientos


y acceso a regiones de memoria, resulta primordial comprender en primer lugar la
dirección de identificación o identificador asignado a cada dispositivo esclavo, esto
con el propósito de establecer comunicación efectiva con dichos dispositivos. Cada
dispositivo esclavo está equipado con un identificador, que puede ser de 7 u 10 bit
según el modo de operación que se esté utilizando.
Un tramo de datos I2C mantiene la siguiente estructura:

Figura 1.14: Trama de datos generico dentro del protocolo I2C [20].

Las señales que integran un marco de datos en la comunicación I2C se listan a


continuación:

Tabla 1.7: Las señales que integran un marco de datos en la comunicación


I2C.

Componente Descripción
S Condición de parada
AD Dirección del esclavo ID
W bit de escritura (0)
R bit de lectura (1)
ACK Reconocimiento
NACK No Reconocimiento
RA Dirección del registro interno
DATA Datos a transmitir o a recibir
P Condición de parada

A continuación se muestra el comportamiento de la interfaz bajo diferentes


escenarios:
Capı́tulo 1. Marco teórico 26

Figura 1.15: Comportamiento de la interfaz I2C bajo diferentes escenarios A)


Escritura de un byte; B) Escritura de más de un byte; C)Lectura de un byte; D)
Lectura de más de un byte [21].

1.11.6. Comunicación Inter-procesadores IPC


La Comunicación Inter-procesadores (IPC) se refiere al intercambio de infor-
mación y datos entre diferentes procesadores en de un sistema computacional. Los
cuales pueden estar en un mismo sistema multi-núcleo. El IPC es esencial para la
coordinación, la sincronización y el intercambio de información entre estos proce-
sadores, permitiendo la colaboración y la ejecución eficiente de tareas en paralelo.
Puede involucrar diversos mecanismos y protocolos, como colas de mensajes, me-
moria compartida, señales y pipelines, entre otros, con el objetivo de garantizar
una comunicación efectiva y segura entre los procesos involucrados (Figura 1.16).

Figura 1.16: Diagrama conceptual de comunicación inter-procesadores me-


diante memoria compartidas [22].
Capı́tulo 1. Marco teórico 27

1.12. Shell
En el contexto de la informática “shell ” se refiere a una interfaz de lı́nea de co-
mandos que permite a los usuarios interactuar con un sistema operativo mediante
la entrada y ejecución de comandos.

1.12.1. SSH
SSH, o Secure Shell, es un protocolo de red utilizado para establecer conexiones
seguras y cifradas entre dispositivos a través de una red no segura, como Internet.
SSH proporciona una forma segura de acceder y administrar sistemas remotos
y transferir datos de manera confiable, ya que cifra la información transmitida,
protegiéndola de posibles ataques y accesos no autorizados.
El protocolo SSH permite la autenticación y la comunicación cifrada entre un
cliente y un servidor. Se utiliza comúnmente para el acceso a servidores remotos a
través de una lı́nea de comandos, pero también puede ser utilizado para transferir
archivos de manera segura utilizando herramientas como SFTP (SSH File Transfer
Protocol ) o SCP (Secure Copy Protocol ). SSH reemplaza a protocolos más antiguos
y menos seguros, como Telnet y rlogin, que transmitı́an información en texto plano
sin cifrado, lo que los hacı́a vulnerables a ataques y escuchas no autorizadas.
El funcionamiento de SSH es el siguiente:

1. Autenticación: Cuando un cliente se conecta a un servidor a través de


SSH, el servidor verifica la identidad del cliente solicitando credenciales de
autenticación, como una contraseña o una clave pública. Esto asegura que el
cliente tiene permiso para acceder al servidor.

2. Generación de Claves: Para una mayor seguridad, SSH utiliza un sistema


de claves criptográficas. El cliente y el servidor generan un par de claves (una
pública y otra privada) que se utilizan para el cifrado y la autenticación.

3. Intercambio de Claves: El cliente envı́a su clave pública al servidor du-


rante el proceso de autenticación. El servidor utiliza esta clave para cifrar
un desafı́o que envı́a al cliente.

4. Respuesta del Cliente: El cliente recibe el desafı́o cifrado y lo descifra


utilizando su clave privada. Luego, envı́a de vuelta al servidor una respuesta
cifrada utilizando la clave pública del servidor.
Capı́tulo 1. Marco teórico 28

5. Establecimiento del Canal Seguro: Una vez que la autenticación es exi-


tosa, SSH establece un canal seguro entre el cliente y el servidor. Toda la
comunicación que ocurre a través de este canal, incluyendo comandos y da-
tos, se cifra para proteger la confidencialidad.

6. Sesión Interactiva o Transferencia de Archivos: Una vez establecido


el canal seguro, el cliente puede interactuar con el servidor de manera remo-
ta, ejecutando comandos en la lı́nea de comandos, transfiriendo archivos o
realizando otras operaciones (Figura 1.17).

Figura 1.17: Diagrama conceptual handshaking SSH [23].

SSHFS

SSHFS (Secure Shell File System) es una herramienta que permite montar sis-
temas de archivos remotos a través de SSH (Secure Shell ) en un sistema local.
Proporciona una forma de acceder y administrar archivos y directorios en un ser-
vidor remoto como si estuvieran en el sistema local, a través de una conexión
segura encriptada.
SSHFS utiliza el protocolo SSH para establecer una conexión segura entre el
sistema local y el servidor remoto. Una vez que la conexión está establecida, SSHFS
monta el sistema de archivos remoto en una ubicación local, lo que permite a los
usuarios acceder a los archivos y directorios en el servidor remoto como si fueran
parte del sistema local.
Capı́tulo 1. Marco teórico 29

Esta tecnologı́a es especialmente útil para acceder a archivos y recursos en ser-


vidores remotos de manera segura y conveniente, ya que proporciona encriptación
y autenticación de alto nivel a través de SSH.
Capı́tulo 2

Descripción de las Plataformas de


Desarrollo

En el capı́tulo previo, se exploraron los fundamentos teóricos y los antecedentes


que contextualizan el proyecto. En esta sección, se ofrece una descripción en detalle
de las plataformas utilizadas, a fin de dar un panorama general de los recursos
usados en la investigación.
El objetivo de este trabajo es el desarrollo e implementación de las primitivas
de código en firmware y software necesarias para implementar una aplicación de
electrocardiografı́a, mediante el uso de un AFE para electrocardiografı́a controlado
por una plataforma de desarrollo que incorpora una arquitectura de procesadores
heterogéneos.
La investigación involucró dos plataformas de desarrollo: la plataforma principal
de arquitectura heterogénea donde se implementa la aplicación definitiva y una
plataforma auxiliar donde se realizó el diseño del firmware para el control de una
de las cabeceras analógicas estudiadas.
Para realizar las primitivas desarrolladas con las plataformas se utilizó herra-
mientas de depuración y de laboratorio, y los softwares para las plataformas e
instrumentos correspondientes.

2.1. Plataforma Principal


Esta plataforma principal está conformada por un development kit (kit de desa-
rrollo) PICO-PI-IMX7 de Technexion, un AFE de electrocardiografia, una pantalla
LCD de 5 pulgadas y accesorios de comunicacón.

30
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 31

La plataforma de desarrollo PICO-PI-IMX7 de TechNexion, está integrada por


dos tarjetas conectadas en piggyback (tarjeta superpuesta): un SoM y una Carrier
Baserboard (placa base). El SoM (PICO-IMX7-EMMC) integra el procesador hete-
rogéneo i.MX7D (SoC) e incluye elementos como memoria DDR3, almacenamiento
eMMC, circuito integrado de gestión de energı́a (PMIC), SIP (System in Packa-
ge) para conexiones inalámbricas (Wi-Fi / Bluetooth), conectores board-to-board
y otros elementos. La Carrier Baserboard (PICO-PI-GL) dispone de conectores
board-to-board e interfaces para comunicarse e interactuar con el mundo real: au-
dio, Ethernet, USB y conectores pin headers (conectores de pines machos) para
un gran número de señales.
El i.MX7 (DUAL) de NXP Semiconductors es un System on Chip (SoC) de pro-
cesador heterogéneo que integra dos núcleos (MPU) ARM Cortex-A7 y un núcleo
(MCU) ARM Cortex-M4. El núcleo ARM Cortex-M4 se encarga del control del
AFE y de la adquisición de datos. Una vez adquiridos, los datos se transfieren
mediante un protocolo de comunicación inter procesadores a los núcleos ARM
Cortex-A7, donde se ejecuta el sistema operativo Linux. Esta arquitectura garan-
tiza una operación sin pérdida de datos y elimina la necesidad de utilizar un driver
de tiempo real en el sistema operativo (Linux).
La Figura 2.1 expone un diagrama general de la plataforma principal y en la
Figura 2.2 se presenta el montaje implementado.

Figura 2.1: Diagrama General de la Plataforma Principal.


Capı́tulo 2. Descripción de las Plataformas de Desarrollo 32

Figura 2.2: Montaje Plataforma Principal.

2.1.1. SoC i.MX7D


En el SoM se tiene el SoC i.MX7D de NXP Semiconductors (Figura 2.3), es
un procesador de aplicaciones altamente integrado y de bajo consumo de energı́a,
diseñado para una amplia gama de aplicaciones embebidas. Cuenta con una ar-
quitectura heterogénea que combina dos tipos de núcleos:

ˆ ARM Cortex-A7 Core: Dos núcleos A7; microprocesadores de aplica-


ciónes generales de alto rendimiento y eficiencia energética.

ˆ ARM Cortex-M4 Core: Un microcontrolador diseñado para aplicaciones


en “tiempo real”, y de bajo consumo energético, está optimizado para realizar
tareas de control y procesamiento de señales en sistemas embebidos.

Figura 2.3: Módulos de la Plataforma Principal.


Capı́tulo 2. Descripción de las Plataformas de Desarrollo 33

El SoC cuenta con la posibilidad de hacer procesamiento multimedia y gráfico


2D y 3D de alto rendimiento, dispone capacidades avanzadas de reproducción de
video, gráficos y visualización, admite resoluciones de pantalla de alta definición y
proporciona aceleración de hardware para formatos de video populares (incluidos
H.264, H.265, VP8 y VP9). También, ofrece soporte para interfaces gráficas avan-
zadas como OpenGL ES 2.0 y OpenVG 1.1, lo que permite una experiencia visual
rica en aplicaciones multimedia y de usuario.
Incluye una amplia gama de interfaces y periféricos integrados para conectivi-
dad. Soporta Fast Ethernet 10/100Mbps, interfaces de bus: USB 2.0, UART, SPI,
I2C y GPIO; que permiten la conexión de una variedad de dispositivos y senso-
res externos. También, incluye controladores integrados para interfaces comunes
(PCIe, CAN, LCD, SPI, CSI, LCD y MIPI-DSI), lo que proporciona flexibilidad
de conexión y expansión.
Incorpora una unidad de procesamiento seguro (SPU) dedicada que proporciona
un entorno seguro para la gestión de claves, la generación de números aleatorios
y otras operaciones criptográficas sensibles. Mediante la cual se incluye carac-
terı́sticas de seguridad avanzadas para proteger la integridad y confidencialidad de
los datos. Cuenta con un motor de cifrado y descifrado de hardware que acelera
operaciones criptográficas, como AES y SHA.
Soporta tecnologı́as de seguridad de nivel de sistema (TrustZone), que permite
la separación de aplicaciones y la ejecución segura de código en entornos aislados
y secure Boot; lo que garantiza que solo se cargue y ejecute el software auténtico
y no modificado, brindando protección contra ataques de software malicioso o no
autorizado.
Admite múltiples interfaces de audio, como: PCM, I2S, AC97 y TDM, que
permiten la conexión de diferentes dispositivos de audio y Codec1 . Ofrece soporte
para una amplia gama de formatos de audio, incluidos PCM (lineal y comprimido),
y proporciona capacidades de procesamiento de audio; como mezcla, filtrado y
equalización.
Permite el uso de una amplia gama de opciones de memoria, incluida: DDR3 y
LPDDR2/LPDDR32 , también ofrece interfaces de almacenamiento, como, eMMC
y NAND Flash, para el almacenamiento de datos y el acceso rápido.
1
Codec “codificador-decodificador”. Se refiere a algoritmos o programas utilizados para com-
primir y descomprimir datos digitales, como archivos de audio o video.
2
LP: Low Power de baja potencia
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 34

Es compatible con diferentes tecnologı́as de comunicación inalámbrica, como


Wi-Fi y Bluetooth, a través de interfaces y controladores integrados, esto permite
la conectividad inalámbrica para aplicaciones como IoT, dispositivos médicos y
automatización del hogar (sin embargo, bajo las opciones de software ofrecidos
por el fabricante no se consideran los drivers para el integrado SoC que se encarga
de las conexiones inalámbricas).
Es compatible con una gran variedad de sistemas operativos, incluidos: Ubun-
tu, Yocto, Android Things (descontinuado), Qt, para correr en los núcleos A7,
Además, es compatible con FreeRTOS en su núcleo M4, en este núcleo también se
pueden correr aplicaciones BareMetal.

Memoria Compartida

Los diferentes núcleos del SoC i.MX7D tienen acceso a las mismas conexiones
(compartidas) y por tanto, disponen de periféricos y de la memoria3 . Cabe destacar
que no todos los recursos del SoC están disponibles a su vez en los niveles de
hardware de las plataformas subs secuentes (SoM, Carrier Baserboard ). La Figura
2.4 muestra la topologı́a de bus compartida utilizada en la plataforma de trabajo
principal.

Figura 2.4: Topologı́a de bus compartido [24].


3
topologı́a de bus compartido
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 35

Resource Domain Controller (RDC)

El controlador de dominio de recursos mostrado en la Figura 2.5 provee una


asistencia robusta para el aislamiento de la sección de memoria objetivo: asig-
nando segmentos como los periféricos y memoria a un único núcleo, bus maestro,
o un conjunto de núcleos y buses maestros. Muchos de los procesadores actua-
les tienen multiples núcleos para incrementar su desempeño y flexibilidad. Los
núcleos pueden desarrollar diferentes funciones que requieran el acceso a recursos
por distintos procesadores como: periféricos y memoria. El compartir recursos en-
tre procesos independientes posibilita la ocurrencia de colisiones de datos donde
la información almacenada por un proceso (en periféricos o memoria), es sobres-
crita por un programa corriendo en otro núcleo. Una colaboración poco cuidadosa
entre dos sistemas puede generar errores, inadvertencia de mal funcionamiento o
disminuciones de desempeño.

Figura 2.5: Controlador de dominio de recursos (RDC) del SoC i.MX7D [25].

El RDC consiste en un mecanismo que permite establecer dominios para los


recursos, asignando: núcleos, administradores de bus, periféricos y regiones de me-
moria a identificadores de dominio4 . Una vez configurado las transacciones del bus,
son monitoreadas para restringir el acceso a elementos como periféricos o memoria
que estén asociados a un un dominio exclusivo.
4
Etiqueta o código único asignado a un dominio especı́fico dentro de un sistema, permite
identificar y gestionar de manera única los recursos y dispositivos asociados a ese dominio en
particular.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 36

Para compartir periféricos, el RDC provee un mecanismo basado en semáforos5


para dar exclusividad por tiempo limitado mientras el programa dominante utiliza
el periférico. Cuando las operaciones de un dominio ha terminado de utilizar el
periférico, entonces es liberado por el semáforo permitiendo que el periférico quede
disponible para otro dominio.

Clock

Como se muestra en el diagrama de la Figura 2.6, los OSCs (Oscillators), PLLs


(Phase Locked Loops), PFDs (Phase Frequency Detectors) y pre-divisores, generan
las fuentes de reloj con frecuencias fijas o variables. Luego la lógica de generación
de reloj fundamental dentro del Módulo de Control de Reloj (CCM) genera varias
señales de reloj fundamentales para el núcleo, bus y bloques periféricos. Estas
señales de reloj fundamentales son enviadas a cada módulo de bloqueo de reloj
de bajo consumo (LPCG6 ), módulos donde está contenida la lógica de activación
y desactivación de cada reloj. La señal de control para los registros de control y
bloqueo del reloj (CCGR) en el CCM será la fuente de reloj para habilitar señales.
Algunos de los relojes necesitan ser desactivados durante el reinicio, el módulo
de control de recursos del sistema (SRC) también enviará señales de control de
activación/desactivación de reloj al LPCG.

Figura 2.6: Sistema de reloj del SoC i.MX7D [25].


5
Semáforo: herramienta de sincronización que permite controlar el acceso a recursos compar-
tidos entre diferentes procesos o hilos.
6
LPCG Low Power Clock Gating.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 37

Posteriormente, el CCM habilitará la activación/desactivación de reloj en fun-


ción de la configuración. Al mismo tiempo, el CCM también puede desactivar las
señales de habilitación para los PLL y los PFD, de modo que estos módulos puedan
apagarse durante el modo de bajo consumo. Cuando el SoC entra en el modo de
parada, el GPC puede desactivar la señal de habilitación del OSC para apagarlo,
y también puede activar la señal de modo de parada para poner al OSC en modo
de bajo consumo.

Messaging Unit

La unidad de mensajerı́a permite que dos procesadores dentro del SoC se co-
muniquen y coordinen mediante mensajes (por ejemplo, datos, estados, interrup-
ciones, etc.) a través de la unidad de mensajerı́a (MU).
Debido a que la MU gestiona la mensajerı́a entre procesadores, utiliza relojes
diferentes, por lo tanto la MU debe sincronizar los accesos de un lado al otro.
La MU logra esta sincronización mediante dos conjuntos de registros coincidentes
uno orientado hacia el procesador A y otro orientado hacia el procesador B. Este
módulo es fundamental para permitir la comunicación y la coordinación entre los
procesadores del SoC.

Figura 2.7: Messaging Unit del SoC i.MX7D [25].

La Unidad de Mensajerı́a (MU) incluye las siguientes caracterı́sticas:

ˆ Control de mensajerı́a mediante interrupciones o mediante sondeo (polling).


Capı́tulo 2. Descripción de las Plataformas de Desarrollo 38

ˆ El procesador B puede sacar al procesador A de los modos de bajo consu-


mo al activar una de las interrupciones mencionadas anteriormente hacia el
procesador A, y viceversa.

ˆ Interfaces de procesador simétricas, con cada lado admitiendo lo siguiente:

ˆ Cuatro solicitudes de interrupción de propósito general reflejadas hacia


el otro lado.
ˆ Tres banderas de propósito general reflejadas en el otro lado.

ˆ Cuatro registros de recepción con interrupción enmascarable.

ˆ Cuatro registros de transmisión con interrupción enmascarable.

Para más información sobre esta unidad consultar el manual de referencia del
SoC i.MX7D [25].

Power Management Unit PMU

La unidad de manejo de energı́a (Figura 2.8) está integrado por: PMU, GPC,
CCM y SRC:

ˆ Unidad de manejo de enegı́a (PMU): se encarga de generar los rieles


de alimentación utilizando reguladores de caida de voltaje lineal (LDOs) o
interruptores de potencia a partir de una entrada de energı́a externa.

ˆ Controlador general de energı́a (GPC): es el controlador central de


todo el sistema de energı́a. Sus funciones claves incluyen el control del modo
de energı́a del SoC y la gestión de los dominios de energı́a.

ˆ Módulo de control de reloj (CCM): genera la señal de reloj para los


módulos en cada dominio de energı́a y también habilita/deshabilita los relo-
jes en función del modo de energı́a establecido por el GPC.

ˆ Control de reinicio del sistema (SRC): genera la señal de reinicio (reset)


para cada dominio de energı́a durante el encendido de dicho dominio.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 39

Figura 2.8: Unidad de manejo de energı́a [25].

2.1.2. SoM
El SoM PICO-IMX7-EMMC (Figura 2.9) es un módulo diseñado para comple-
mentar las capacidades del SoC, este cuenta con las siguientes caracterı́sticas:

Figura 2.9: Diagrama de bloques del SoM PICO- IMX7 EMMC[26].

ˆ Memoria: El módulo dispone de una memoria RAM de 512 MB DDR3L y


una memoria flash de 4 GB eMMC (Embebed MultiMediaCard ).

ˆ Conectividad: Incluye Ethernet, Wi-Fi y Bluetooth mediante el SIP AP6335


de AMPAK (TechNexion no proporciona los drivers para este dispositivo).
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 40

ˆ Conectores: el modulo utiliza conectores Hirose de 70 pines para conectarse


a la Carrier Baseboard, donde estaran el resto de conectores asociados a los
protocolos seriales, pines de propósito general y señales.

ˆ PMIC: PMIC (Power Management Integrated Circuit) para regular y con-


trolar el suministro de energı́a a los diferentes componentes del módulo.

2.1.3. Carrier Baserboard


La Carrier Baserboard PICO-PI-GL (Figura 2.10) es una tarjeta en la que se
conecta el SoM a través de los conectores Hirose de alta velocidad. Esta provee
las interfaces con el mundo real; es decir señales externas al SoM como: audio,
network, USB, GPIO y protocolos seriales.

Figura 2.10: Vista superior de la PICO-PI-IMX7 Carrier Baserboard GL [27].

El esquema general de puertos e interfaces de la PICO-IMX7 se muestra en la


imagen a continuación en la Figura 2.11.

Figura 2.11: Diagrama de puertos e interfaces de la PICO-PI-IMX7: Carrier


Baserboard PICO-PI-GL, SoM PICO-IMX7-EMMC.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 41

La Carrier Baserboard dispone de un mikroBus [28] en los conectores tipo


header JP1 y JP2, que puede usarse para conectar dispositivos que utilicen este
estándar de conexión (como el AFE), y un conector tipo header de cuarenta pines
(JP8) con el cual se tiene acceso a distintos periféricos. A continuación en la Figura
2.12 se tiene la descripción de los conectores elaborada a partir de los esquemáticos
de Technexion [29],[30].

Figura 2.12: Conectores tipo header JP1, JP2 y JP8 de la PICO-PI-GL [30].

Los jumpers J1 y J2, se utilizan para cambiar la configuración de inicio de la


plataforma. Es decir, cambiar entre el modo de inicio desde la eMMC (eMMC
Boot) que es la configuración de inicio normal de la plataforma o el modo de des-
carga serial que es utilizado para hacer la carga de imágenes mediante la conexión
serial con un ordenador host. La plataforma utilizada no cuenta con tarjeta SD;
pero Technexion distribuye plataformas con esta caracterı́stica. En la Figura 2.13
se observa la configuración, tanto para el modo de descarga serial como para el
modo de inicio desde la eMMC:
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 42

Figura 2.13: Configuración de los jumpers J1 y J2, para alternar entre los
modos: Descarga Serial e Inicio desde la eMMC [30].

Para la plataforma de trabajo utilizada, las configuraciones de los pines según


el modo de trabajo deseado se pueden ver en la Figura 2.14:

Figura 2.14: Modo de descarga serial (izquierda), modo de inicio desde la


eMMC (derecha) [26].

En conjunto con los jumpers la plataforma dispone de un puerto USB OTG que
permite programarla cuando los jumpers J1 y J2 están en el modo de descarga
serial. La programación se hace mediante el protocolo SDP (Serial Downloader
Protocol ), el cual es el utilizado en los i.MX SoCs de NXP y proporciona los medios
para descargar una imagen de programa a la eMMC; a través de una conexión
serial USB y UART. En condiciones de inicio desde eMMC esta conexión también
es utilizada para alimentar la plataforma.

2.1.4. Pantalla LCD Táctil de 5 pulgadas


El kit de desarrollo suministrado por Technexion dispone de una pantalla LCD
touch screen de 5 pulgadas (TechNexion TDP0500T800480PCAP [26]) donde se
puede visualizar el ambiente gráfico del sistema operativo instalado, ademas de
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 43

información referente al arranque, al boot y a su modo de descarga serial. La


pantalla utilizada se muestra en la Figura 2.15.

Figura 2.15: Pantalla LCD touch screen de 5 pulgadas


TDP0500T800480PCAP

2.1.5. Analog Frontend AFE


Inicialmente se considero como AFE el ADS1298 de Texas Instruments. Durante
el transcurso del proyecto al profundizar el estudio de la plataforma principal se
concluyó que el núcleo M4 no tiene acceso a una interfaz SPI, la cual es la usada
por este AFE. Para sustituir este AFE, se escogió el BMD101 de NeuroSky con
interfaz UART que es soportada por núcleo M4. Este punto se desarrollará con
detalle en el Capı́tulo 3.

AFE ADS1298

Se utizó un módulo de adquisición basado en el AFE ADS1298 (Figura 3.41).


El AFE cuenta con 8 canales de conversión análogo digital simultanea bajo la
tecnologı́a delta sigma (∆Σ), incluye ganancia programable (PGA), referencias de
voltaje internas y osciladores. Combina las caracterı́sticas requeridas para aplica-
ciones de electrocardiografı́a y electroencefalografı́a con altos niveles de integración
y rendimiento. El diagrama en bloques del ADS1298 se en cuentra en la Figura
2.17.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 44

Figura 2.16: Módulo de adquisición ECG basado en ADS1298.

Figura 2.17: Diagrama de bloques del ADS1298 [31].

Amplificadores de instrumentación y configuración de ganancia

ˆ Cada canal del ADS1298 incluye un amplificador de instrumentación de alta


impedancia y bajo ruido.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 45

ˆ El amplificador de instrumentación proporciona ganancia programable, es-


to permite que se adapte a diferentes amplitudes de señal y requisitos de
aplicación.

ˆ La ganancia se puede configurar en pasos de 6dB en especı́fico x1, x2 ,x6, x8,


x12, mediante los registros de configuración. Esto proporciona una amplia
gama de opciones de ganancia para amplificar y acondicionar las señales
bioeléctricas.

Tasa de muestreo y resolución

ˆ Ofrece una alta resolución de hasta 24 bits, lo que permite una adquisisción
precisa de las señales bioeléctricas.

ˆ La tasa de muestreo es cofigurable y puede alcanzar hasta 32 KSs (muestras


por segundo), sin embargo para alcanzar las tasas de muestreo de 16 y 32
KSps se disminuye la resolución de 24 bits a 16 bits por canal; para todas
las demas configuraciones la resolución se mantiene en 24 bits de datos por
canal.

Interfaz de comunicación y registros de configuración

El ADS1298 se comunica con un dispositivo de control a través de una interfaz


SPI (Serial Perispheral Interface) de alta velocidad. Se pueden configurar los dife-
rentes parámetros del ADS1298, cargando valores a sus registros de configuración
a través de la interfaz SPI. Los registros nos permiten ajustar parámetros tales co-
mo: ganancia, frecuencia de muestreo, configuración de los canales y multiplexores
para seleccionar las diferentes opciones para cada canal, entre otras opciones.

Alimentación y consumo de energı́a

El dispositivo es compatible con una amplia gama de voltajes de alimentación,


lo que permite su integración en diferentes entornos, ofrece modos de trabajo
en bajo consumo de energı́a y funciones de ahorro de energı́a para optimizar la
duración de la baterı́a en aplicaciones portátiles y dispositivos médicos.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 46

Caracterı́sticas de seguridad y protección

Incorpora caracterı́sticas de seguridad, como protección contra descargas elec-


trostáticas (ESD) en los pines de entrada y protección contra sobretenciones. Cuen-
ta con una función de detección de electrodo desconectado (LOFF) para identificar
y notificar la desconexión de los electrodos y garantiar una adquisición de señal
confiable y precisa.

AFE BMD101

Se utilizó el ECG 4 Click de mikroElektronika, que incluye el BMD101 de


NeuroSky [32], que viene con interfaz UART y con el conector MikroBus (Figura
2.18).

Figura 2.18: Módulo ECG 4 Click de MikroElektronika [32].

El BMD101 es la tercera generación de dispositivos SoC NeuroSky para detec-


ción y procesamiento de biopotenciales cardı́acos. El módulo posee las siguientes
caracterı́sticas:

ˆ Detección de LOFF: Cualquier resistencia entre las dos entradas del sensor
que exceda impedancia de la piel activará la detección del LOFF.

ˆ Low Dropout: contiene internamente un LDO, que consiste en una banda


potencial interna que genera una referencia de 1.2V, seguida por dos buffers
de ganancia unitaria para la alimentación analógica y digital.

ˆ Oscilador de control digital: Incluye un DCO (Digital Control Oscilator )


el cual provee un reloj de 22.1MHz completamente integrado como señal de
referencia.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 47

ˆ Ganancia: Cuenta con una ganancia de x128 en el bloque del amplificador


de instrumentación, veces la entrada según el datasheet [32].

ˆ UART: cuenta con interfaz UART de 57600 bauds, 8 bits de datos, sin
paridad.

El diagrama de bloques del AFE se muestra a continuación:

Figura 2.19: Diagrama de bloques del BMD101 [32].

2.1.6. Hub Slim de 4 Puertos USB 3.0


Para extender los puertos disponibles de la plataforma fue necesario utilizar
un hub de puertos USB. Se utilizó el módulo 4-Port Ultra Slim USB 3.0 Data
Hub de Anker (Figura 2.20), que permitió conectar hasta 4 periféricos USB, como:
teclados, mouse, unidades de almacenamiento masivo, Bluetooth para interactuar
o utilizar con la PICO-PI i.MX7.

Figura 2.20: 4-Port Ultra Slim USB 3.0 Data Hub.


Capı́tulo 2. Descripción de las Plataformas de Desarrollo 48

Nota: recordar que el USB 2.0 tiene un fanout 7 de 500mA; las 4 salidas del hub
no deben superar esa corriente.

2.1.7. USB TO UART Bridge


Para leer la salida de la consola serial de debug del núcleo M4, ubicada en el
puerto UART6 de la Carrier Baserboard (pines 8 y 10 del conector J8), se utilizó
el módulo de SparkFun USB to Serial GPIO Breakout - CP2103 (Figura 2.21),
este permite añadir esta interfaz como un puerto serial visible para la PC utilizada
durante la depuración.

Figura 2.21: Módulo USB to Serial GPIO Breakout - CP2103 de Sparkfun.

El diagrama general del módulo se muestra en la Figura 2.22 a continuación.

Figura 2.22: Diagrama del módulo USB to Serial GPIO Breakout - CP2103
de Sparkfun [33].
7
Fanout, se refiere a la capacidad de una fuente de corriente para alimentar varios componentes
o circuitos sin comprometer su capacidad para suministrar la corriente requerida de manera
estable y confiable.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 49

2.2. Plataforma de desarrollo Auxiliar


Además de la plataforma de desarrollo principal se cuenta con una plataforma
de desarrollo auxiliar que comprende: PICDEM Z Demonstration Kit de Microchip
Technology y el AFE ADS1298 de Texas instruments y accesorios de depuración
(Figura 2.23).

Figura 2.23: Diagrama general de la plataforma Auxiliar.

2.2.1. PICDEM Z Demonstration Kit


Este kit (Figura 2.24) fue utilizado para desarrollar los algoritmos en firmware
necesarios para realizar adquisición con la cabecera analógica ADS1298, mientras
se implementaba la plataforma principal.
El kit cuenta con una MCU de 8 bits PIC18F4620, proporcionando a los usua-
rios una plataforma para explorar y familiarizarse con los microcontroladores de
la familia PIC18 de Microchip Technology [34].
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 50

Figura 2.24: Vista superior de la plataforma PICDEM Z Demostration Kit[27].

El diagrama esquemático está disponibles en el Apéndice A1 de este documento.

El PIC18F4620

Para este proyecto se usó la versión en encapsulado de 40 pines, conocido como


PDIP (Plastic Dual Inline Package). El pintout del microcontrolador se muestra
en la Figura 2.25

Figura 2.25: Pinout del PIC18F4620. [34].

A continuación, se proporciona una descripción general de las caracterı́sticas


principales del PIC18F4620:

1. Arquitectura y velocidad de reloj: Utiliza una arquitectura RISC de 8 bits


mejorada, lo que significa que utiliza un conjunto reducido de instrucciones
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 51

para un procesamiento más eficiente. La velocidad de reloj máxima del dis-


positivo es de 40 MHz, mediante reloj externos y hasta 32 MHz habilitado
los PLL internos.

2. Memoria: El microcontrolador tiene una memoria flash de programa de hasta


64 KB, que permite almacenar el código ejecutable. Además, dispone de 3.8
KB de memoria RAM para almacenar datos y variables temporales.

3. Periféricos integrados: Cuenta con una amplia gama de periféricos integrados


para facilitar la implementación de diversas funcionalidades. Estos periféricos
incluyen múltiples módulos para comunicación serial (UART, SPI y I2C,
CAN), módulos de temporización y contadores (timers), módulos PWM para
generación de señales de pulsos, convertidores analógico-digitales (ADC) de
10 bits de resolución, comparadores con multiplexor de entrada y muchos
otros.

4. Puertos de E/S: El microcontrolador dispone de varios puertos de uso ge-


neral de entrada/salida (GPIO) que permiten la conexión de dispositivos
externos y la interacción con el entorno. Estos puertos se pueden configurar
individualmente como entradas o salidas digitales y algunos de ellos también
pueden funcionar como entradas analógicas.

5. Interrupciones: Cuenta con un sistema de interrupciones flexible que permite


al procesador responder rápidamente a eventos externos. Esto permite eje-
cutar rutinas especı́ficas cuando se produce una interrupción, lo cual resulta
útil para manejar eventos en tiempo real y tareas crı́ticas.

6. Bajo consumo de energı́a: Ofrece opciones de bajo consumo de energı́a para


maximizar la eficiencia y prolongar la duración de la baterı́a en aplicaciones
con requisitos energéticos limitados. Esto incluye modos de bajo consumo
y caracterı́sticas de administración de energı́a para minimizar el consumo
cuando el dispositivo no está en pleno funcionamiento.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 52

2.3. Herramientas de Depuración y Laboratorio

2.3.1. NI myDAQ
La plataforma de adquisición NI my DAQ (Figura 2.26) es un dispositivo de
adquisición de datos que proporciona ocho instrumentos de laboratorio plug-and-
play basados en LabVIEW. incluye un multı́metro digital (DMM), osciloscopio,
generador de funciones, datalogger entre otros como: Provee instrumentos de soft-
ware para realizar experimentos y ejercicios con analizador de Bode, generador de
forma de onda arbitraria, analizador de señal dinámica (transformada rápida de
Fourier), entrada y salida digital; dispositivos que permiten realizar ingenierı́a real
cuando se combinan con software LabVIEW y NI Multisim.

Figura 2.26: Plataforma de adquisición de datos NI myDAQ [35].

2.3.2. In Circuit Debbugger 3 (ICD3)


ICD3 es una herramienta desarrollada por Microchip Technology para depurar
y programar microcontroladores PIC. Forma parte de la serie de herramientas
MPLAB de Microchip Technology, orientada a facilitar la creación de sistemas
embebidos con microcontroladores PIC. El ICD3 permite cargar, programar y
depurar firmware en microcontroladores in circuit (directamente en la PCB). Esto
agiliza la depuración en sistemas embebidos, posibilitando pruebas en condiciones
reales sin programadores externos.
Permite hacer la carga de los binarios pre-compilados de las aplicaciones Bare-
Metal para el PIC18F4620; a travéz del conector RJ(11). Además se usó para la
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 53

depuración de los algoritmos desarrollados para el control del AFE ADS1298, per-
mitiendo verificar las configuraciones y rutinas de control a nivel de los registros
del microcontrolador.
En la Figura 2.27 a continuación de muestra el esquema de conexión del ICD3.

Figura 2.27: Esquema de conexión del ICD3 [36]

2.3.3. Analizador Lógico


Un analizador lógico es un instrumento para capturar, mostrar y medir múlti-
ples señales digitales; muestra la relación y el tiempo entre muchas señales diferen-
tes y analiza protocolos de comunicación digital como: I2C, SPI y UART. Tienen
como ventaja su capacidad para registrar una gran cantidad de señales digitales
simultáneamente. Los osciloscopios también pueden registrar datos digitales, pero
normalmente tienen limitaciones respecto al número de canales y la duración de
la grabación debido a los requisitos de memoria. Para este trabajo se utilizaron
el analizador lógico de Hiletgo 24MHz 8CH USB Logic Analyzer 8 Channel y el
software Logic 2 asociado al dispositivo (Figuras 2.28 y 2.29).

Figura 2.28: Analizador lógico HiLetgo [37].


Capı́tulo 2. Descripción de las Plataformas de Desarrollo 54

Figura 2.29: Ejemplo entorno Logic 2 [38].

2.3.4. Divisor de Voltaje para Señales de mV


Se utilizó un divisor de voltaje para llevar las señales del generador de funciones
a los niveles de voltaje adecuado y conectar de una manera fácil los electrodos de
las derivaciones en un montaje experimental.

Figura 2.30: Divisor de Voltaje para Señales de mV

En la parte superior de la Figura 2.30 podemos observar los valores teóricos de


resistencia utilizados para el divisor de voltaje, se utilizaron resistencias 1 % de
tolerancia, a partir de este divisor se pueden estudiar las siguientes derivaciones:

ˆ I: LA-RA =0.971mV ∼ 1 mV

ˆ II: LL-RA =1.942mV ∼ 2 mV

ˆ III: LL-LA =0.971mV ∼ 1 mV


Capı́tulo 2. Descripción de las Plataformas de Desarrollo 55

2.4. Plataforma de Laboratorio


Se utilizaron diferentes instrumentos para generar señales o medir señales eléctri-
cas a lo largo del proyecto, en este inciso se describen los tres dispositivos básicos
que conforma la plataforma de laboratorio utilizada osciloscópio, generador de
funciones y multı́metro:

ˆ Oscilocópio: Se utilizó el UNI-T UTED2102CEX Figura 2.31a para poder


visualizar de manera precisa las señales de voltaje. Este sirvió como herra-
mienta de depuración y monitoreo, para las diversas etapas del proyecto.
El dispositivo cuenta con la posibilidad de conectarse con un ordenador me-
diante un cable USB tipo A a tipo A. Existen dos aplicaciones de UNI-T que
permiten configurar y observar las señales desde el computador, o capturar
y analizar la información de las señales, DSO Monitor y Wave Analysis.

ˆ Generador de funciones: Se utilizó el Generador de Funciones 33120A de


Agilent (Figura 2.31b) para hacer pruebas con diferentes tipos de señales:
onda cuadrada, senoidal y señal Cardiac (señal ECG simulada).

ˆ Multı́metro: UNI-T UT805A Figura 2.31c que cuenta con diferentes he-
rramientas como ohmimetro, verificador de continuidad, medidor de voltaje
entre otros.

(b) Generador de
(a) Osciloscopio funciones Agilent (c) Multimetro
UNI-T UTD2102. 331202A UNI-T UT805A.

Figura 2.31: Plataforma de Laboratorio

A continuación se muestra un ejemplo de forma de onda de la señal Cardiac ge-


nerada utilizado el generador de funciones Agilent 331202A y visualizada mediante
el osciloscopio UNI-T UTD2102 Figura 2.32.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 56

Figura 2.32: Señal Cardiac generada con el generador de funciones.

2.5. Software de la Plataforma Principal


El software de la plataforma principal se fiere a la imagen configurada, en
este apartado se describe el proceso de carga y los elementos utilizados en la
composición de la imagen.

Boot ROM y SPL

La Boot ROM es una memoria On-Chip (SoC) donde están las instrucciones
de inicio del procesador. El proceso de inicio en el procesador i.MX7D es de la
siguiente manera: Al encender la tarjeta de desarrollo se verifica el identificador
del CPU 0 (uno de los núcleos A7), luego se verifica el tipo de arranque; es decir,
si se carga directamente el bootloader o el SPL (Second Program Loader ). Esta es
una etapa temprana del proceso de arranque, en los sistemas embebidos se utiliza
en combinación con un bootloader principal, como U-Boot.
La imagen SPL es la responsable de cargar el bootloader. Para un proceso de
arranque seguro, y continuar la cadena de confianza, la imagen SPL verifica la
imagen del U-Boot usado justo antes de pasarle el control.
La Figura 2.33 expone un esquema general del proceso de arranque del SoC.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 57

Figura 2.33: Flujo de operación del Boot ROM [25].

Bootloader

En este proyecto se utiliza como bootloader el U-Boot, este es un bootloader de


código abierto altamente personalizable que se puede adaptar para admitir una
amplia gama de sistemas y arquitecturas.

Sistema Operativo

En la imagen cargada al SoC se utilizan dos tipos de sistemas operativos8 :


uno es una distribución de Linux de uso general llamada Ubuntu (este opera en
el entorno de los núcleos A7) y el otro es un sistema operativo en tiempo real
(RTOS), llamado FreeRTOS (este opera en el entorno del núcleo M4).

FreeRTOS

Es un kernel de RTOS para sistemas embebidos con mucha popularidad entre


diferentes plataformas de hardware, donde pueden elaborarse aplicaciones embe-
bidas bajo los requerimientos de “tiempo real” que puedan ser necesitados o per-
mitiendo que las aplicaciones se organicen como una colección de diferentes hilos
8
sistema operativo y una aplicación /textitfirmware FreeRTOS para el núcleo M4.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 58

o tareas de ejecución [39].


En un procesador que dispone de un solo núcleo, solo podemos ejecutar una
tarea a la vez, el RTOS decidirá cual hilo deberá ser ejecutado examinando su nivel
de prioridad asignada por el diseñador de la aplicación. En el caso más simple el
diseñador de la aplicación podrı́a asignar prioridades más altas a las tareas que
requieran caracterı́sticas Hard-RTOS e hilos de menor prioridad a las que requieran
Soft-RTOS, garantizando que los requerimientos Hard-RTOS siempre se ejecuten
por delante a los Soft RTOS, sin embargo estos métodos de diseño no son siempre
tan simplistas.

BSP de FreeRtos

Un BSP es un conjunto de archivos y drivers que proporcionan una capa de


abstracción entre el sistema operativo (en este caso, FreeRTOS) y el hardware
especı́fico de una placa o dispositivo. En el contexto de FreeRTOS, BSP significa
Board Support Package (Paquete de Soporte para la Placa).
El BSP contiene implementaciones especı́ficas de bajo nivel (drivers) que per-
miten que FreeRTOS interactúe con la memoria, los periféricos, puertos de E/S,
temporizadores y otros componentes de hardware del sistema.

2.6. Firmware PIC18F4620


El microcontrolador PIC18F4620 trabaja a partir de binarios pre compilados
de aplicaciones BareMetal. Para generar estas aplicaciones se utilizó el IDE de
Microchip Technology MPLAB X ID V6, y el compilador Microchip C18.

2.7. Softwares Auxiliares para Interactuar con


las Plataformas
Ademas de los instrumentos ya mencionados fueron necesarios una serie diversa
de programas durante el desarrollo e implementación de la aplicación, estos se
describen a continuación.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 59

2.7.1. ARM DS IDE


El IDE de ARM, es una solución integrada para el desarrollo de software
(C/C++) para los núcleos de arquitectura Cortex-A, Cortex-M y otras. ARM
Development Studio ayuda a compilar, codificar, depurar y optimizar rápidamen-
te proyectos basados en ARM. La versión utilizada es un IDE sobre una base
gráfica que usa el marco de referencia de Eclipse; que se puede integrar a desarro-
llos con FreeRTOS. La herramienta y su cadena de compilación fue instalada en
Windows.

2.7.2. Visual Studio Code


Visual Studio Code es un IDE de código abierto desarrollado por Microsoft. Este
fue utilizado para emular aplicaciones FreeRTOS directamente en un ordenador,
antes de hacer la configuración adecuada de la plataforma de desarrollo principal.
Otra aplicación conveniente de este IDE resultó en el la compilación de módulos
para el kernel Linux. Permitiendo desarrollar el módulo encargado de la recepción
de la data en el entorno de los núcleos A7.

2.7.3. MPLAB X
MPLAB X es un entorno de desarrollo integrado (IDE) desarrollado por Micro-
chip Technology, MPLAB X es compatible con una amplia gama de microcontro-
ladores y microprocesadores de Microchip, lo que abarca desde dispositivos básicos
hasta soluciones más avanzadas.
Esta herramienta fue fundamental para el desarrollo del driver para controlar el
ADS1298 desde el microcontrolador PIC18F4620, utilizando el compilador C-18.

2.7.4. Kst2
Es un visualizador y analizador de data en tiempo real. Fue creado por el
equipo de desarrolladores del proyecto KDE (K Desktop Environment)[40], que
es un entorno de escritorio de software libre para sistemas basadas en Unix. Kst2
está disponible tanto para Linux como para Windows.
Esta herramienta fue utilizada para generar las gráficas a partir de la data
cruda obtenida de los AFE tanto en la plataforma principal como en la auxiliar.
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 60

2.7.5. PuTTY
PuTTY [41] programa de código abierto que se utiliza para emular terminales,
a partir: de interfaces seriales o remotas mediante SSH, Telnet o rlogin.

2.7.6. NI ELVISmx Instrument


NI ELVISmx es un software y hardware diseñado por National Instruments
(NI), en conjunto con el hardware asociado (en este caso NI myDAQ) dispone una
plataforma de instrumentos de medición con una componente visual basada en
LabVIEW.

2.7.7. DSO Monitor Controller


DSO monitor Controler es una interfaz de control para los Osciloscópios UNI-T,
que permite controlar el osciloscópio desde el ordenador, realizar capturas imagenes
de las señales medidas y guardar la data cruda de las mismas como un data logger
para su posterior análisis.

2.7.8. Universal Update Utility (UUU)


Es una utilidad de implementación de imágenes para la eMMC desarrollada por
NXP Semiconductors [42], debido a la necesidad de una utilidad de actualización
portátil para Linux y Windows. UUU tiene el mismo uso tanto en Windows como
en Linux, es decir que los mismo scripts funcionan para ambos sitemas operativos.
Capı́tulo 3

Configuración de las Plataformas


y Desarrollo Experimental

En el Capı́tulo anterior se hizo la descripción en detalle de los distintos elemen-


tos de software, hardware, firmeware que integran la plataforma, y el instrumental
de laboratorio utilizado para la depuración de las aplicaciones.
En este Capı́tulo se describen las distintas experiencias realizadas, en primer
lugar la puesta a punto de la plataforma de desarrollo principal que implica: la
descripción de la configuración de la imagen cargada a la plataforma principal y los
métodos utilizados para realizar la carga. Se describen también, las diferentes pri-
mitivas y experimentos que fueron llevados acabo con las plataformas como: el uso
de las interfaces periféricas mediante el núcleo M4 y los núcleos A7, implementa-
ción del mecanismo de comunicación interprocesadores, los drivers implementados
para trabajar con el AFE ADS1298 (plataforma de desarrollo auxiliar) y el AFE
BMD101 (plataforma de desarrollo principal).
La implementación de la imagen para la plataforma consiste en disponer de
una configuración donde se dispone de las herramientas necesarias para cumplir
los objetivos del proyecto, para esto es necesario generar una imagen que contenga
tanto el bootloader como el sistema operativo, permitiendo cargar firmware en
el núcleo M4 (procesador auxiliar) a la vez ejecutar programas en los núcleos
principales A7; garantizando la comunicación entre ellos mediante el protocolo
RPMsg. Lo que implicó llevar acabo varias tareas:

ˆ Disponer de las herramientas de compilación

ˆ Compilar y disponer el bootloader para operar

61
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 62

ˆ Cargar el bootloader

ˆ Carga de una imagen firmware en el núcleo M4

ˆ Carga del sistema operativo Linux/Ubuntu en los núcleos A7

ˆ Optimización del sistema operativo

ˆ Implementación del ambiente para desarrollar y compilar código para la


plataforma (Ubuntu, OS y aplicaciones BareMetal)

ˆ Operación simultánea de los núcleos A7/M4

ˆ Trabajar con módulos en kernel Linux

ˆ Establecer la comunicación inter-procesadores

Por defecto la plataforma principal viene con Android (Things 8.1) instalado
como sistema operativo, sin embargo, este sistema actualmente se encuentra des-
continuado, y no es el más adecuado para los objetivos del proyecto; a pesar de
compartir el kernel Linux, por lo que fue necesario considerar otra imagen con un
sistema operativo Linux de uso general como Ubuntu.
Antes de cargar una imagen es recomendable verificar la versión de bootloader
disponible en la imagen, para ver si U-Boot dispone del comando ums (este co-
mando facilita el proceso de carga de la imagen). Para verificarlo se debe utilizar
un programa de consola serial, un programa que nos permita tener una interfaz
serial en nuestra computadora. Se recomienda PuTTY, por lo fácil que resulta
configurarlo y está disponible para Windows y para Linux.
Para asegurar que el ordenador reconoce la interfaz serial de la PICO-PI-IMX7
y le asocia un puerto COM. En Windows se puede revisar el administrador de
dispositivos y observar si se agrega un nuevo puerto COM en la lista de dispositivos.
En caso de que no se agregue, se requiere de un driver adecuado [43]. Una vez
asegurado el acceso con PuTTY a la interfaz serial de la plataforma de desarrollo,
se debe seleccionar la interfaz y configurar los parametros de la comunicación que
se muestran en la Tabla 3.1 y en la Figura 3.1.

Tabla 3.1: Caracterı́sticas de la comunicación serial con la plataforma de de-


sarrollo.

Baud Rate [Bps] Paridad Bits de datos Stop Bits


115200 Ninguna 8 1
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 63

Figura 3.1: Configuración realizada en PuTTY.

Nota: Se puede crear un perfil con la configuración mencionada en PuTTY


y evitando repetir el proceso cada vez que se requiera establecer este tipo de
conexión.

3.1. Experiencia 1: Carga de la imagen mediante


UUU en Windows
Mediante la documentación dispuesta por TechNexion [44], [45] se experimentó
hacer la carga de las imágenes demo de Ubuntu (disponibles en el repositorio de
TechNexion [46]), sin embargo, se presentaron problemas con los drivers para
detectar la plataforma de desarrollo en el modo de descarga serial, los cuales
no permitieron hacer la carga de la imagen, con esta versión de la utilidad y
la plataforma de desarrollo utilizada.
TechNexion subió una nueva versión del binario pre-compilado de UUU a su ser-
vidor FTP [46] el dı́a 8-04-2023. Con esta versión no ocurre el error para Windows
11.
Con la versión adecuada de la utilidad se puede realizar la carga de la imagen
siguiendo el video dispuesto por TechNexion [45].
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 64

3.2. Experiencia 2: Carga de la imagen con UUU


en Linux
Este procedimiento es básicamente el mismo, con la diferencia de que las ins-
trucciones que se usan en el terminal van con las sintaxis adecuada para Linux:
$ sudo ./ uuu -b emmc_imx7_img ../../ imx / pico - im7 / imx7 -
,→ SPL ../../ pico - imx7 / imx7 -u - boot . img < imagen a
,→ cargar >

La salida se muestra en la Figura 3.2:

Figura 3.2: Salida del comando usando UUU [47].

3.3. Experiencia 3: Carga de la imagen con Boot-


bomb
El i.MX USB Loader es una herramienta de Boundary Devices, que permite
instalar U-Boot sin un depurador JTAG, usando el modo de arranque USB (es un
remplazo para el método anterior con UUU). Con la imagen bootbomb, se puede
interactuar con la eMMC cuando no se tiene instalado el bootloader (U-Boot),
cuando no está presente el SPL o cuando el U-Boot no tiene el comando ums.
El U-Boot utiliza el dispositivo de descarga serial para proporcionar una im-
plementación SPD (protocolo de descarga serial) a través de USB. Esto permite
descargar imágenes de programas a la eMMC, utilizando el mismo protocolo y
herramientas que el mecanismo de recuperación del SoC.
El procedimiento para llevar a cabo la carga de esta forma se describe a conti-
nuación:
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 65

1. Descargar el binario pre-compilado, disponible en el servidor FTP de Tech-


Nexion. Se usó la version:

pico-imx7-imx6ul-imx6ull_otg-installer_20170112.zip

Este archivo admite la instalación desde plataformas Windows y Linux. En


caso de tener descargado el archivo, omitir, pero es recomendable verificar
si existe una nueva versión.

2. Se puede descargar y compilar i.MX USB Loader: del Github de TechNexion


o del branch de sus creadores Boundarys Devices y compilar el U-Boot, puede
encontrar información en la bitácora en lı́nea [48].

3. Configurar la tarjeta de desarrollo en el modo de descarga serial como se


muestra en la Figura 2.14.

4. Conectar un cable USB micro B al UART de depuración para la consola


serial y un cable USB C entre la ordenador host y el puerto USB OTG de
la PICO-PI-IMX7.

5. Activar PuTTY con la configuración descrita anteriormente. Si está en Linux,


el dispositivo se agrega como /dev/tty/USB0. En Windows como el puerto
COM que se le asigna.

6. En Linux, ubicarse en el directorio que se muestra a continuación y ejecutar


lo siguiente:
$ ~/ pico - imx7 - imx6ul - imx6ull_otg - installer_20170112 /
,→ linux $ sudo ./ imx_usb ../ pico -
,→ imx7d_bootbomb_20170112 . imx

Tambien puede utilizar el siguiente script disponible en el directorio descar-


gado.
$ ./ imx7d . sh

En Windows demora alrededor de un minuto en activarse y encender la


pantalla LCD.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 66

.\ sb_loader . exe -f ..\..\ pico -


,→ imx7d_bootbomb_20170112 . imx ~\ pico - imx7 imx6ul
,→ - imx6ull_otg - installer_20170112 \ windows \
,→ sb_loader > .\ sb_loader . exe -f ..\..\ pico -
,→ imx7d_bootbomb_20170112 . imx

ˆ Nota 1: Este archivo e imagen solo son para recuperar el boot (arranque
inicial), luego debe actualizarse el U-Boot e instalar el Ubuntu con la imagen
adecuada.

ˆ Nota 2: Si la salida despliega error: err 3 o Could not open device vid=0x15a2
... necesita privilegios de administrador.

7. Se debe encender la pantalla LCD de la tarjeta de desarrollo y se instala


en la ordenador host Ubuntu, dos dispositivos USB, que son las particiones
(volumen) de la memoria eMMC de la tarjeta de desarrollo. Una de apro-
ximadamente 21MB que se corresponde al boot y otra de 3,7GB donde se
localiza el sistema operativo y el árbol de directorio del Ubuntu. La eMMC,
ahora está disponible para interactuar con ella.
Nota: En el terminal abierto PuTTY se observará el despliegue de informa-
ción (el dmesg tı́pico de Linux).

3.4. Experiencia 4: Carga de la imagen en Linux


usando el comando dd y Bootbomb
Luego de que el dispositivo es reconocido, se debe cargar la imagen, a la me-
moria eMMC, para esto se puede utilizar el comando dd (duplicador de datos).
Esta herramienta permite la transferencia de datos ası́ como la conversión de co-
dificación y caracteres preestablecidos.

1. Primero verificar si el driver del puerto OTG ha sido reconocido por Linux,
se puede utilizar este comando:
$ lsusb | grep Freescale
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 67

La salida de este comando muestra:


Bus
00 x Device 00 y : ID 15 a2 :0076 Freescale Semiconductor
,→ , Inc . i . MX 7 Solo /7 Dual
SystemOnChip in RecoveryMode

2. Verificado que el sistema operativo reconoce el dispositivo, seguir la sección


3.3; carga de la imagen con Bootbomb.

3. Usar el comando lsblk (List Blocks Devices); este comando se utiliza para
listar los bloques de memoria.

4. Ubicado el bloque asociado al dispositivo, desmontarlo utilizando:


$ sudo umount / dev / sdx

siendo x la letra asociada al directorio de archivos del bloque que se requiera


desmontar.

5. Exportar el directorio y cargar el contenido de esa unidad (la memoria de la


eMMC) con 0, ası́ se asegura el borrado de todo el contenido incluyendo el
árbol de particiones. Este proceso es delicado, no equivocar en la letra que
identifica el directorio se pueden borrar archivos importantes. Las instruc-
ciones que deben usar se muestran a continuación:
$ export DISK =/ dev / sdX
$ sudo dd if =/ dev / zero of = $ { DISK } bs =1 M count =10

6. Se ejecuta el siguiente comando para cargar la imagen de sistema operativo


a la plataforma de desarrollo principal, desde directorio donde se encuentra
la imagen de Ubuntu (mismo procedimiento para Android Things, QT y
Yocto).
$ sudo dd if =./ imagen_ubuntu . img of = $ { DISK } bs =1 M
,→ oflag = dsync status = progress

7. Terminado el proceso anterior, desconectar la tarjeta, cambiar la configu-


ración a el modo de inicio desde la eMMC como se muestra en la Figura
2.14.

8. La tarjeta de desarrollo, debe iniciar con el sistema cargado.


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 68

3.5. Experiencia 5: Carga de la imagen con el


comando ums de U-Boot
El comando ums, significa almacenamiento masivo USB. Lo que hace el coman-
do ums, es exportar un dispositivo de bloque (eMMC o SD) como un dispositivo de
almacenamiento masivo en la computadora host. El proceso de carga de la imagen
utilizando este comando se muestra en la Figura 3.3.

Figura 3.3: Esquema de carga de la imagen con el comando ums (U-Boot) y


comando dd (Linux Host [49]).

3.6. Experiencia 6: Carga de la imagen con Ba-


lenaEtcher
BalenaEtcher es un programa que permite cargar una imagen de sistema ope-
rativo a una unidad de memoria, este programa facilita la carga de las imágenes
a la plataforma de trabajo. Se debe montar la memoria eMMC como un bloque
de memoria visible para el sistema operativo por cualquiera de los métodos discu-
tidos sin embargo se recomienda tener previamente cargada en la plataforma una
version de U-boot que disponga del comando ums. Luego de seleccionar el bloque
de memoria donde se va a cargar la imagen se ejecuta el proceso de carga como se
ve en la Figura 3.4.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 69

Figura 3.4: Carga de la imagen mediante BalenaEtcher.

TechNexion sugiere la posibilidad de usar esta herramienta en el video infor-


mativo donde muestran la carga de la imagen mediante UUU [45].

3.7. Problemas corregidos de las imagenes


Para el desarrollo de la imagen requerida fue necesario adecuarla, a través de
la resolución de problemas;que fueron resueltos progresivamente para cumplir con
las necesidades requeridas para desarrollar. A continuación se listan los problemas
que fueron corregidos:

ˆ Override reserved memory : Este problema no permitı́a cargar una ima-


gen firmware para ejecutar en el procesador auxiliar, siempre que se trataba
de hacer la carga de la imagen aparecı́a este error, Figura 3.5.

Figura 3.5: Salida de la consola del procesador auxiliar imagen con problema
override reserved memory.

La corrección a este problema puede encontrarse en esta entrada del material


en lı́nea [50].

ˆ Ausencia del comando UMS en U-Boot: Este problema puede resolver-


se de dos maneras. Compilando U-Boot y agregando este comando, a partir
de una imagen de U-Boot que ya disponga del comando. Esta última es la
opción recomendada.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 70

ˆ Comunicación inter-procesadores y operación en simultaneo: La


solución a esto es la integración de la solución de varios problemas, se creó
una imagen con el SPL de la version 2021.04, se utilizó U-Boot 2018.03
publicada el 23 de octubre del 2022 y se hizo la compilación de Linux para
activar remoteproc. En el material en linea se puede observar mejor estos
procedimientos [51], [52].

3.8. Creación de una imagen para la plataforma


de trabajo
Como resultado de las distintas experiencias desarrolladas, se realizó una ima-
gen configurada con las diferentes, optimizada y configurada bajo los requerimien-
tos del proyecto. El proceso de creación de la misma está disponible en la bitácora
en lı́nea, como también la imagen utilizada en la versión final de este proyecto [53].

3.9. Compendio de métodos de carga de imagen


Las experiencias descritas anteriormente respecto a los diferentes métodos estu-
diados para la carga de la imagen a la plataforma, permitieron realizar el siguiente
flujograma instructivo para el proceso de carga de imágenes en la plataforma de
desarrollo (Figura 3.6), presentando soluciones de carga para los diferentes estados
en que se pueda encontrar la plataforma. En el diagrama estos se denotan como
“casos”.
Este esquema se puede consultar con más detalles y vinculos con asistencia a
la información en la bitácora digital asociada a esta investigación [54].
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 71

Figura 3.6: Elección de método de carga de imagen [55].

3.9.1. Compilando el U-Boot


Es posible realizar la compilación del U-Boot y no depender de los binarios
pre-compilados de TechNexion, sin embargo este procedimiento requiere más ex-
periencia y documentación. Solo serı́a necesario para agregar o quitar alguna ca-
racterı́stica que tenga el bootloader y que no pueda configurarse a partir de las
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 72

variables de entorno de U-Boot.


El proceso de compilación de U-Boot se puede encontrar en la bittácora digital
de este trabajo [48]. También se necesitarán herramientas anexas (como Linaro)
para relizar la compilación cruzada, es decir compilar desde nuestro ordenador
para la plataforma de desarrollo. La información necesaria se encuentra disponible
en el blog [48].

3.10. Optimización del Sistema Operativo (Ubun-


tu)
Dependiendo del objetivo del proyecto que se pretenda elaborar en la platafor-
ma, puede ser conveniente expandir el almacenamiento disponible para el sistema
operativo mediante alguna unidad de almacenamiento externo, en caso de ser ne-
cesario más espacio de almacenamiento.
Se elaboró una optimización del almacenamiento de la imagen para que ocupe
menos espacio de la memoria eMMC. Se redujo al 49 % de su capacidad de almace-
namiento. También se modificaron algunos servicios para montar almacenamiento
externo a la plataforma permitiendo tener más espacio de almacenamiento para
la unidad.
El proceso de optimización se puede dividir en 3 etapas:

Aumento del espacio de trabajo en disco.

Inicio de programas después del arranque en Ubuntu.

Optimización del Sistema Operativo (Ubuntu).

Las etapas que conforman el proceso de optimización del optimización se des-


criben a continuación:

3.10.1. Expansión del Almacenamiento


La imagen de Ubuntu utiliza gran parte de esta memoria eMMC de la plata-
forma para instalarse. No quedando casi recursos disponibles para trabajar con
alguna aplicación que requiera de un espacio significativos de memoria. Además,
la escasa cantidad de memoria RAM, limita las posibilidades de la aplicación. Por
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 73

lo que se vuelve un aspecto a considerar, el uso de dispositivos USB de almacena-


miento masivo para paliar ambas carencias.
Requerimientos: Una unidad de almacenamiento masivo y un replicador de
puerto USB.
Se particiona el pendrive en las partes que considere (por ejemplo se sugiere
4 particiones: 3 particiones ext4 y una swap). Esto es conveniente hacerlo con la
utilidad gparted; con la misma utilidad se pueden montar las particiones creadas.
La utilidad gparted debe ser instalada previamente con:
$ apt - get install gparted .

Como root, se crea un directorio de nombre varios (o el de preferencia) en:


/home/ubuntu/
$ sudo mkdir / home / ubuntu / varios

Se debe dar permiso de escritura y lectura al directorio creado:


$ sudo chmod 777 / home / ubuntu / varios

Se montan las particiones.


$ sudo mount / dev / sda1 / home / ubuntu / varios

Para montar la partición swap creada en el pendrive, se utiliza el comando


swapon:
$ swapon / dev / sda4

Nota: se debe verificar la letra identificadora asignada por Ubuntu a la unidad


de almacenamiento.

3.10.2. Inicio de programas después del arranque en Ubun-


tu
Desde antes de la versión 22.04 de Ubuntu, el archivo /etc/rc.local no viene
instalado por defecto. Por lo que hay que crearlo en forma manual, antes de poder
utilizarlo [56].
Tradicionalmente el script de shell /etc/rc.local es usado para llamar a más
scripts o comandos una vez que se han cargado todos los servicios. Cuando Li-
nux init cambia a un nivel de ejecución multiusuario, generalmente se llama /et-
c/rc.local al final de toda la operación de inicio.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 74

El servicio systemd rc-local.service siempre existe, y si rc.local reside y es ejecu-


table, se extrae inmediatamente en multi-user.target. En systemd, la sincronización
con /etc/rc.local se proporciona mediante el uso de un servicio especı́fico llama-
do rc-local.service. Sin embargo, en systemd, la funcionalidad /etc/rc.local está
deshabilitada de forma predeterminada. Por lo que hay que configurar y ejecutar
algunas cosas antes de poder utilizarlo.
Crear (o editar) el archivo /etc/rc.local
Agregar permiso de ejecución:
$ sudo chmod + x / etc / rc . local

Verificar que el contenido de este archivo contenga las siguientes lı́neas de en-
cabezado y final, y los comando que quiere que se ejecuten automáticamente.
# !/ bin / sh
#
# This script will be executed * after * all the other
,→ init scripts .
# You can put your own initialization stuff in here if
,→ you don ’ t
# want to do the full Sys V style init stuff .

swapon / dev / sda4


mount / dev / sda1 / home / ubuntu / varios
mount / dev / sda2 / home / ubuntu / otros

Editar el archivo /etc/systemd/system/rc-local.service


[ Unit ]
Description =/ etc / rc . local Compatibility
ConditionPathExists =/ etc / rc . local
After = network . target

[ Service ]
Type = forking
ExecStart =/ etc / rc . local start
TimeoutSec =0
StandardOutput = tty
RemainAfterExit = yes
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 75

GuessMainPID = no

[ Install ]
WantedBy = user . target

Se habilita el servicio en el arranque del sistema:


$ sudo systemctl enable rc - local

Seguidamente arrancar el servicio con:


$ sudo systemctl start rc - local . service

Y verificar el funcionamiento del servicio, observando su status:


$ sudo systemctl status rc - local . service

Reiniciar el dispositivo.
Nota 1: En el siguiente inicio, se ejecutarán lo contemplado en el archivo /etc-
rc/local, el ejemplo montará dos particiones: una swap y otra de trabajo. Es ne-
cesario verificar la existencia de los recursos mencionados en este apartado.
Nota 2: Si se considera retardar la ejecución de algún comando en el archivo
/etc/rc.local, considere usar un tiempo de espera:
# wait for 60 seconds
sleep 60

3.10.3. Implementación de mecanismos de Acceso Remoto


Hay situaciones donde resulta favorable acceder a la información de la platafor-
ma de desarrollo principal de manera remota, esto puede servir para consultar la
data almacenada en la plataforma, para cargar datos o archivos o modificar estos.
Se evaluaron diferentes métodos para implementar el acceso remoto:
Samba
Samba es un protocolo de compartición de archivos que permite compartir ar-
chivos y recursos entre sistemas Windows y sistemas basados en Unix/Linux. Pro-
porciona una mayor compatibilidad con sistemas Windows y ofrece caracterı́sticas
avanzadas de integración con dominios de Windows. Sin embargo, en términos de
rendimiento, NFS y SSHFS suelen ser más eficientes en entornos de red local. Esto
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 76

se debe a que Samba tiene una mayor sobrecarga debido a su enfoque en la compa-
tibilidad con Windows y la implementación de varios protocolos y caracterı́sticas
adicionales.
Para implementar Samba en la plataforma se siguieron los pasos listados a
continuación:

1. Instalar el paquete Samba con apt-get.


$ sudo apt - get install samba

2. Se comprueba que está instalado correctamente:


$ sudo systemctl status nmbd

3. Configurar Samba: Crear un directorio donde se ubicarán los archivos a com-


partir en la red:
$ sudo mkdir / samba

Editar y configurar el archivo /etc/samba/smb.conf:


$ sudo nano / etc / samba / smb . conf

Agregar las siguientes lı́neas de configuración:


[ samba - share ]
comment = Samba on Ubuntu
path = / samba
read only = no
browsable = yes

Agregar un usuario Samba al sistema, para poder acceder a los recursos


compartidos de forma remota:
$ useradd [ nombre - usuario ; ejemplo samba ]

Agregar el usuario creado del sistema al servidor Samba, al ejecutar el si-


guiente comando se le pedirá una contraseña; que será también la que se
pida en forma remota cuando se acceda a los recursos del sistema:
$ useradd [ nombre - usuario ; ejemplo samba ]
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 77

4. Crear una carpeta pública, que estará disponible para los usuarios remotos:
$ sudo mkdir / samba / public

5. Asignar los permisos necesarios para los usuarios que se conecten al servidor:
$ sudo mkdir / samba / public

$ sudo chown -R nobody : nogroup / samba / public


$ sudo chmod -R 0777 / samba / public
$ sudo chgrp sambashare / samba / public

Reiniciar el servidor Samba para aplicar los cambios:


$ sudo systemctl restart smbd . service

6. Conectarse en forma remota al servidor Samba:

ˆ Desde Windows: Pulsar la combinación de tecla Windows + r y es-


criba dentro del campo
\\192.168.88.20 samba - share

ˆ Desde Linux (Ubuntu): El recurso disponible se visualiza en el Ex-


plorador de Archivo > Red; aparecerá una carpeta con el nombre de su
usuario.

SSHFS
El protocolo SSHFS (Secure Shell File System) permite montar un directorio
remoto a través de una conexión SSH. Esto permite acceder y trabajar con los
archivos en tiempo real como si estuvieran en su ordenador. SSHFS proporciona
una forma segura de compartir archivos y es compatible tanto con Windows como
con Ubuntu. SSHFS brinda una capa de seguridad adicional al cifrar los datos
durante la transferencia; pero hay que tener en cuenta que esto representa una
carga adicional (de cifrado).
Para implementar el protocolo en la ordenador Auxiliar:

Instalar la última versión de WinFsp.

Instalar la última versión de SSHFS-Win.


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 78

Nota: Elegir el instalador x64 o x86 según la arquitectura de su ordenador.


Ambas aplicaciones se pueden instalar fácilmente con WinGet desde una con-
sola power shell:
> winget install WinFsp . WinFsp ; winget install SSHFS - Win
,→ . SSHFS - Win

Uso básico de SSHFS desde Windows (10 u 11): Una vez que haya instalado
WinFsp y SSHFS-Win, puede asignar una unidad de red a un directorio en un
host SSHFS utilizando el Explorador de Windows o el comando net use.
En el Explorador de Windows, seleccionar Esta PC → Asignar unidad de red
(Figura 3.7) e ingresar la letra de la unidad deseada y la ruta SSHFS usando la
siguiente sintaxis UNC:

Figura 3.7: Conectar unidad de red en Windows.

Ejemplo : > \\ sshfs \ ubuntu@192 .168.88.20

La primera vez que se asigne una ruta SSHFS en particular, se le solicitará


el nombre de usuario y la contraseña de SSHFS. Puede optar por guardar estas
credenciales con el Administrador de credenciales de Windows, en cuyo caso no se
le volverá a solicitar.
Para desasignar la unidad, hacer click con el botón derecho en el icono de la
unidad en el Explorador de Windows y seleccione Desconectar.
Uso básico de SSHFS desde Linux (Ubuntu 22.04):

1. Instalar los paquetes necesarios: Tanto como el ordenador auxiliar como


la plataforma de desarrollo principal hay que tener instalados los paquetes
openssh-server y openssh-client. Para instalar estos paquetes en Ubuntu hay
que abrir una terminal y ejecutar el siguiente comando:
$ sudo apt - get install openssh - server openssh - client

En el ordenador que actúa como cliente tenemos que asegurarnos que los
paquetes sshfs y fuse están instalados. Para ello el siguiente comando en la
terminal:
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 79

$ sudo apt - get install sshfs fuse

2. Activar el módulo Fuse en el ordenador que actúa como cliente


Para que el sistema de archivos remoto se pueda montar hay que hacer uso
de un módulo del kernel conocido como Fuse. Para ver si este módulo está
activado tenemos que teclear el siguiente comando en la terminal:
$ lsmod | grep fuse

Si el comando arroja un resultado del tipo “fuse 86016 3” podemos tener


la seguridad que el módulo Fuse está activado y podemos pasar al siguiente
apartado.
Si por lo contrario el comando no devuelve ningún resultado pueden pasar
dos cosas. La primera es que el módulo esté desactivado. La segunda es que
el módulo Fuse se haya compilado directamente en el kernel y por lo tanto
no haga falta cargar ningún módulo.
Para comprobar si el módulo Fuse se ha compilado directamente en el Kernel
ejecutamos el siguiente comando en la terminal:
$ grep -i fuse / lib / modules / $ ( uname -r ) / modules .
,→ builtin

Si el comando nos devuelve un resultado similar del tipo “kernel/fs/fuse/-


fuse.ko” podemos tener la seguridad que Fuse está activo y por lo tanto
podemos pasar al siguiente apartado.
Finalmente, en el caso que el comando no devuelva ningún resultado signifi-
cará que el módulo no está cargado en el kernel. Para cargarlo tan solo hay
que ejecutar el siguiente comando en la terminal:
$ modprobe fuse

3. Asegurar que el usuario forme parte del grupo Fuse


Una vez activado el módulo Fuse, en el ordenador que actúa como cliente
tenemos que comprobar que nuestro usuario forme parte del grupo Fuse.
Para ello instalamos el paquete members ejecutando el siguiente comando
en la terminal:
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 80

$ sudo apt - get install members

Justo después de instalar el paquete ejecutamos el siguiente comando en la


terminal:
$ members fuse

Si la salida del comando no muestra el nombre de nuestro usuario, entonces


es que nuestro usuario no pertenece al grupo Fuse. Si es este el caso, para
que nuestro usuario pertenezca al grupo Fuse hay que ejecutar el siguiente
comando en la terminal:
$ sudo gpasswd -a rajcf fuse

Una vez ejecutado el comando, el usuario se habrá añadido dentro del grupo
Fuse. Si queremos lo podemos comprobar ejecutando de nuevo el siguiente
comando en la terminal:
$ members fuse

4. Montar el sistema de archivos remotos


Montar el sistema de archivos de forma manual para comprobar si todo está
funcionando correctamente.
En el ordenador local. que actuará como cliente ejecutaremos el comando:
$ sshfs rajcf@192 .168.88.20:/ home / ubuntu / otros / home
,→ / ubuntu / varios

Después de ejecutar el comando con el explorador de archivos tendremos


acceso a la totalidad de contenido de la partición compartida del equipo
remoto que actúa como servidor.

5. Crear la carpeta donde se montará el sistema de archivos SSHFS


Seguidamente en el ordenador que actúa como cliente crearemos la carpe-
ta en la que montaremos el sistema de archivos remoto SSHFS. Para ello
ejecutamos el siguiente comando en la terminal:
$ mkdir / home / ubuntu / varios /
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 81

En este caso, el sistema de archivos remotos se montará en una carpeta


llamada otros que está ubicada /home/ubuntu/.
Si se requiere desmontar el volumen que se acaba de montar, tan solo se
ejecuta el siguiente comando:
$ fusermount -u / home / ubuntu / varios

Nota: Si queremos montar el sistema de archivo remoto SSHFS automática-


mente en cada arranque, ver indicaciones en el enlace a las fuentes consulta-
das.

Página Web
Otra estratégia utilizada para la visualización de datos fue implementar una
página web con la información que se requerı́a consultar utilizando la plataforma
de desarrollo principal como un servidor. El servidor web utilizado fue Apache,
instalado en el SO Ubuntu de la PICO-PI-IMX7, de esta manera se puede elaborar,
una página web simple index pi.html, con un código javascript para leer el archivo
de datos adquiridos y graficarlos.
El servidor apache se configuró en el directorio:
/ var / wwww / html

Es necesario generar un enlace simbólico de /samba/public/datos rpmsg.txt


archivo de salida del módulo kernel donde se recoge la adquisición de los biopo-
tenciales. El enlace se genera con el siguiente comando:
$ sudo ln -f / samba / public / datos_rpmsg . txt ./ datos . txt

Port Forwarding
Para utilizar este método se necesita una IP pública en caso de que la consulta
venga de un cliente externo a la red. Se debe configurar port forwarding en el
router para hacer que las consultas que lleguen a esa IP por un puerto especificado
(en este caso puerto 80) sean dirigidos al servidor web Apache configurado en la
plataforma de desarrollo, el servidor web dispone la página consultada.

3.10.4. Optimización General


La optimización de un Sistema Operativo como el Linux Ubuntu, es una tarea
meticulosa que puede abarcar muchos otros procedimientos que los descritos en
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 82

este apartado. Es necesario partir de alguna base o umbral desde donde ir evaluan-
do el comportamiento del SO. Entre ellas: memoria RAM, SWAP, CPU y usos de
memoria de almacenamiento.
En el caso de la tarjeta de desarrollo PICO-PI-IMX7D, con memoria fı́sica
RAM 512MB DDR3L, no es posible aumentar fı́sicamente la memoria RAM.
Una vez creada la partición swap como se menciona en el apartado anterior se
puede optimizar el uso de la memoria RAM mediate la configuración del uso de la
memoria SWAP. La imagen suministrada por TechNexion, utiliza un disco swap
creado en memoria virtual (RAM DISK); memoria de intercambio comprimida
directamente en RAM, en lo que se conoce como ZRAM swap. Por defecto Ubuntu
22.04 viene configurado para que siempre intente utilizar el 60 % de la memoria
virtual disponible en dicho disco. Lo que se puede verificar con:
$ cat / proc / sys / vm / swapppiness

Este parámetro se puede cambiar, por ejemplo, a 10 %, con:


$ sudo sysctl -w vm . swappiness =10

Nota 1: Modificar el swappiness a un valor minimizado, no siempre será lo más


conveniente, ya que eso implica mayor uso de las capacidades de CPU. El valor
adecuado siempre se obtendrá de un estudio detallado del comportamiento del
sistema; dependiendo de las aplicaciones y servicios que se ejecuten, en relación
con el valor de la swappiness configurada.
Nota 2: Este valor se puede fijar, editando /etc/sysctl.conf y agregando al final:
vm . swappiness =10

Optimizar la configuración de discos virtuales y memoria compar-


tida: El dispositivo /dev/shm, que aparece cuando listamos el espacio en disco
disponible con:
$ df - h $

No es más que la implementación del concepto de “memoria compartida” para


los procesos ejecutados en Linux Ubuntu. Permitiendo que los datos sean com-
partidos entre diferentes programas que corren en Linux de una manera eficiente.
Esto se puede reconfigurar con:
$ mount -o remount , size =100 M / dev / shm

Lo que se puede verificar con estas utilidades del sistema:


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 83

$ df -h
$ top
$ swapon
$ free -m
$ wath -n 1 free -m ( informa sobre el almacenamiento
,→ disponible y lo lista cada segundo )

$ systemctl disable ModemManager . service


$ systemctl stop ModemManager . service

También se puede intentar:


$ sudo apt - get purge modemmanager .

Servicio que se puede volver a instalar con:


$ sudo apt - get install modemmanager

Limitar el tamaño de los journal es el diario del sistema. Estos logs se ubican
en /var/log/journal y pueden ocupar un gran espacio de la eMMC.
Para verificar el espacio utilizado:
$ journalctl -- disk - usage

Salida > journal take up 352.0 M en hie system , pero al


,→ momento solo ha utilizado : 125 M

Para delimitar el tamaño usado por journal en disco a por ejemplo 50M:
$ sudo journalctl -- vacuum - size =50 M

Para reiniciar el servicio de journal:


$ sudo service systemd - journald restart

Se puede igual, delimitar el número de archivos journal a crear (en dı́as conse-
cutivos):
$ sudo journalctl -- vacuum - files =2

Al final se puede verificar la integridad del sistema de journal, con:


$ journalctl -- verify
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 84

Instalar las aplicaciones en ruta alterna especificada. Como una partición de


un dispositivo USB tipo pendrive, para que apt lo utilice de repositorio y otros
fines. Por ejemplo, para instalar, la utilidad mc (comandante norton: explorador
y editor de archivo desde consola o terminal):
$ sudo apt - get install -o = dir :: cache =/ home / ubuntu / varios
,→ / Aplicaciones mc

Nota: Previamente hay que desinstalar y borrar completamente la instalación


del paquete que se quiere “mudar”, con:
$ sudo apt - get purge ( nombre de la herramienta )

Siempre es conveniente asegurarse de que el gestor de los paquetes de soft-


ware (APT), auto remueva y limpie su base de datos y archivos temporales de
instalación:
$ sudo apt - get autoremove
$ sudo apt - get autoclean

Después de haber removido las aplicaciones no necesitadas e instalado las per-


tinentes obtenemos:
Evitar el uso de la RAM por parte de aplicaciones y servicios no esenciales.
Ejemplo: desinstalar el servicio Modem Manager si no tiene previsto el uso de esa
aplicación Figura 3.8.

Figura 3.8: Salida de df -h luego de la optimizan realizada.

3.11. Cadena de compilación para FreeRTOS en


Terminal
Para compilar una imagen firmware o BareMetal para el núcleo M4, es ne-
cesaria una cadena de compilación comprendida por utilidades como: GCC 5.4.1
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 85

(arm-none-eabi), Make 4.3, Cmake version 3.24.2 y MinGW 2.37. Los últimos tres
pueden ser descargados de forma rápida mendiante el repositorio de paquetes para
Windows Chocolatey [29],[57],[58],[59],[60],[61]. El crosscompiler GCC se puede
bajar desde el repositorio de ARM [62].
Para probar la cadena de compilación se utilizaron los recursos dispuestos por
TechNexion en su repositorio github [63], una vez expandidos se debe ubicar en la
carpeta de ejemplo que se requiera correr en particular en el subdirectorio armgcc,
en la Figura 3.9 se muestra el comando para el ejemplo hello world.
C :\ Users \14 -10\ OneDrive \ Documents \ Tesis \ freertos - tn -
,→ freertos_1 .0.1 _imx7d \ examples \ imx7d_pico_m4 \
,→ demo_apps \ hello_world \ armgcc > build_all . bat

Figura 3.9: Salida de la compilación por terminal de Hello World.

3.11.1. Carga de una Imagen Firmware en el núcleo M4


El código fuente actual de U-Boot (para los procesadores de aplicaciones i.MX7D
/ 7S e i.Mx 6SX) proporciona comandos como bootaux y fatload que ayudan a los
usuarios a cargar el código en el núcleo Cortex-M4 y activarlo.
Por ejemplo, para cargar la imagen resultante de la compilación del ejemplo
hello world para ejecutarse (una vez cargada mediante U-Boot a la eMMC) se
tendrı́a el siguiente proceso:
fatload mmc 0 0 x7f8000 hello_world . bin
dcache flush
bootaux 0 x7f8000

La Figura 3.10 se muestra la ejecución de estos comandos en la consola de in-


teracción con la de debug. U-Boot y su respectiva salida en la consola de debugging
Figura 3.10.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 86

Figura 3.10: Ejecución de los comandos en la consola de U-Boot.

Figura 3.11: Salida del ejemplo Hello World.

Nota: cabe destacar que estas mismas utilidades están disponibles para Linux,
sin embargo estas pruebas fueron hechas solo para Windows.
No es necesario seguir estas instrucciones para cada nueva ejecución de una
imagen firmware, se puede configurar la imagen por defecto que tomará el núcleo
M4 al arrancar el SO esta información puede ser consultada en la bitácora [29].

3.11.2. ARM Develop Studio IDE


Tener que compilar desde el terminal y editar de manera aislada, sin las ventajas
de un IDE, no es una manera cómoda de trabajar, ası́ que se decidió trabajar con
ARM Develop Studio IDE. El proceso de configuración detallado del entorno puede
encontrarse en [29].
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 87

A partir del entorno es posible ordenar los archivos que componen los proyectos
con los que se generan las imágenes firmware cargadas al núcleo M4, permite
“navegar” cómodamente entre los archivos para buscar las implementaciones de
las diferentes secciones de código y cuenta con herramientas de depuración.
Nota: En el material en lı́nea, tambien se puede encontrar la implementación
de FreeRTOS en diferentes entornos: en el ordenador desde Visual Studio [64],
usando un microcontrolador PIC [65], compilando y corriendo el código para el
núcleo M4 de la plataforma de desarrollo.

3.11.3. Modulos del Kernel Linux


El SoC de la tarjeta de desarrollo PICO-PI-IMX7; fue diseñado para el trabajo
conjunto y colaborativo de sus distintos núcleos: los Cortex-A7 para correr un
OS como Ubuntu y el Cortex-M4, para ejecutar imágenes firmware BareMetal
o un sistema operativo en tiempo real como FreeRTOS. El SoC i.MX7D es un
procesador MPU heterogéneo que combina distintos núcleos, lo que implica un
necesario mecanismo y protocolo para comunicar los núcleos.
Linux posee un núcleo o kernel monolı́tico hı́brido. Los controladores de dispo-
sitivos y las extensiones del núcleo normalmente se ejecutan en un espacio privile-
giado conocido como anillo 0, con acceso pleno a los recursos de hardware, aunque
algunos se ejecutan en espacio de usuario.
Los controladores de dispositivos y las extensiones al núcleo se pueden cargar
y descargar fácilmente como módulos, mientras el sistema continúa funcionando
sin interrupciones. Los controladores de estos SoC, también pueden ser detenidos
momentáneamente por actividades más importantes bajo ciertas condiciones. Esta
habilidad fue agregada para gestionar correctamente interrupciones de hardware
y para mejorar el soporte de multiprocesamiento simétrico.
Las versiones posteriores del kernel de Linux (≥ 5.x) implementan el marco
RPROC en la sección (proc remoto) del repositorio de drivers remote proc del
kernel de Linux. Por defecto remoteproc viene desactivada, su activación implica
compilar el kernel, los módulos, el árbol de dispositivvos e instalar cada uno en su
respectivo lugar. El marco RPROC se configura cuando se compila el kernel de
Linux, con el menuconfig (Device Drivers ⇒ Remote proc drivers) [66].
En el siguiente enlace [67] puede observarse el proceso de compilación del kernel
para esta aplicación. Sin embargo, a pesar que se pueden activar los drivers para
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 88

el SoC i.MX7D no está disponible el remoteproc en todas sus funciones para la


plataforma utilizada, solo se contempla para permitir el uso de RPMsg.
A nivel de FreeRTOS, la mensajerı́a de procesador remoto (RPMsg) es un
bus de mensajerı́a basado en VirtIO que permite la comunicación de procesado-
res (IPC) entre contextos de software independientes que se ejecutan en núcleos
homogéneos o heterogéneos presentes en un sistema de procesamiento múltiple
asimétrico (AMP). El código fuente del componente RPMsg se ha publicado como
parte del marco de procesamiento múltiple asimétrico abierto (OpenAMP).

3.12. Árbol de dispositivos


Es una estructura de árbol, con nodos que describen los dispositivos fı́sicos del
sistema que el software no puede detectar de forma dinámica. Los nodos están
organizados en una relación jerárquica. En el contexto de este proyecto resultan
importantes dos estructuras de este tipo: el árbol de dispositivos del kernel Linux
y el árbol de dispositivos de los archivos BSP de FreeRTOS o las definiciones del
board en las imágenes BareMetal.

3.12.1. Árbol de dispositivos Linux


Antes de que se implementara en Linux el árbol de dispositivosm el kernel
contenı́a codigo especı́fico para cada dispositivo. Un pequeño cambio, como la mo-
dificación de la dirección de un periférico I2C, obligaba a ejecutar una recopilación
de la imagen del kernel. El cargador de arranque (por ejemplo, U-Boot) cargaba
un único binario, la imagen del núcleo y lo ejecutaba.
Con la implementación de los árboles de dispositivos, el propio núcleo ya no
necesita un código especı́fico para cada versión de hardware. En su lugar, el código
se encuentra en un binario separado: el BLOB (Binary Large Object) del árbol de
dispositivos (archivos de extensión .dtb). Esto permite usar diferentes hardware
con la misma imagen de kernel ; simplemente se requiere cambiar el archivo con el
binario del árbol de dispositivos.
El árbol de dispositivos se puede pasar al kernel agregándolo a la imagen del
kernel o mediante el gestor de arranque. El tipo de máquina ahora está defi-
nida en el propio árbol de dispositivos. El cargador de arranque puede agregar
dinámicamente alguna información (por ejemplo, frecuencias de reloj) al árbol de
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 89

dispositivos y luego pasa un puntero al árbol, ubicado en la memoria del sistema.


Luego, el núcleo analiza el árbol de dispositivos.
La Figura 3.13 es una representación de un árbol de dispositivos simple, que
describe el tipo de plataforma, la CPU y la memoria. Los nodos están organiza-
dos en una jerarquı́a con una colección de tokens de una propiedad y valor. Un
dispositivo UART mapeado en memoria se muestra en la Figura 3.12.

Figura 3.12: Ejemplo para dispositivo UART mapeado en memoria.

Los subnodos definen la relación de los dispositivos dentro de la jeraquı́a, por


ejemplo los dispositivos I2C son hijos de un nodo de controlador I2C.

Figura 3.13: Arbol de dispositivos de alto nivel [68].

El proceso de compilación del kernel Linux descrito en [67], incluye un aparte


para construir el árbol de dispositivos de la plataforma de desarrollo. Esta parte del
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 90

proceso se puede repetir sin necesidad de recompilar el kernel. La compilación del


árbol de dispositivos es un proceso independiente con su propio makefile y archivos
fuente. Existe un orden de prelación del árbol de dispositivos que va desde lo más
fundamental: los núcleos del SoC, pasando por el SoM y sus módulos hasta la
Carrier Baseboard. Todos los dispositivos y módulos de hardware quedan descritos
y preconfigurados en el árbol de dispositivos. Básicamente Linux comprende de:
boot, kernel, árbol de dispositivos y el sistema de archivos; a ello se le añade las
utilidades y programas de los usuarios.

Figura 3.14: Relación de los archivos que integran el árbol de Dispositivos que
integran el árbol de dispositivos de la PICO-PI-I.MX7D.

3.12.2. Árbol de dispositivos: Archivos BSP FreeRTOS y


aplicaciones BareMetal
Los directorios BSP de FreeRTOS (Figura 3.15), son archivos que contienen
definiciones con los recursos de hardware que componen la plataforma de trabajo.
Estos archivos complementan el código para la aplicación que ejecuta el núcleo M4,
señalando las configuraciones y definiciones de los diferentes periféricos, puertos y
pines de uso general que la aplicación podrı́a requerir. Además contienen los drivers
asociados a estos dispositivos, la información y configuración de los elementos de
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 91

la plataforma que están bajo el control del núcleo M4 que se encuentran definidos
en el directorio board.

Figura 3.15: Árbol de directorio BSP FreeRTOS.

Lo mismo pasa con las aplicaciones BareMetal, estas no cuentan con un mane-
jador de recursos o sistema operativo como en el caso de FreeRTOS, sin embargo,
se deben contemplar los drivers y definiciones necesarias al compilar la imagen
que ejecute el dispositivo.

3.13. Primitivas básicas implementadas con el


núcleo M4
Las primitivas básicas implementadas para el núcleo M7, consistieron en la
prueba y modificación, de los ejemplos disponibles en el material de TechNexion
[63], en particular si probaron el uso de GPIO, el control de los LEDs disponibles
en la plataforma, el uso de la interfaz UART y la interfaz I2C. Este ultimo se tuvo
que adaptar ya que estaba implementado para una plataforma de desarrollo con
una Carrie Baseboard distinta el modelo DWARF.

3.13.1. Control de GPIO y LEDs con el núcleo M4


Para desarrollar estas primitivas se parte del ejemplo blinking imx demo del
conjunto de ejemplos de FreeRTOS, el ejemplo genera el parpadeo de un LED y
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 92

varı́a el perı́odo de encendido y apagado del mismo, ademas imprime en la terminal


este perı́odo.
La configuración y selección del LED o GPIO se hace modificando los archivos:
gpio pins.c, gpio pins.h, board.h y el código asociado en main.c con la manipula-
ción que se desee para el pin.
gpio_config_t gpioLed = {
" USER LED " , /* name */
& IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA06 , /* muxReg */
5, /* muxConfig */
& IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA06 , /* padReg */
0, /* padConfig */
GPIO2 , /* base */
6 /* pin */
};

De esta manera se define la configuración del pin, para cambiar el pin se debe
ubicar el chipset del GPIO que se desea utilizar e indicar el pin, la configuración,
para la configuración de los multiplexores se tomó la que venı́a por defecto en el
ejemplo. La Figuras 3.16 y 3.17, muestran las salidas de voltaje del pin y de la
consola serial de debugging.

Figura 3.16: Señal de salida del GPIO o LED configurado.


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 93

Figura 3.17: Salida en consola del programa blinking imx demo.

3.13.2. Control de la interfaz UART


El la primitiva comentada anteriormente ya manipulaba la interfaz UART pa-
ra “imprimir” información mediante la consola serial. Para la lectura de datos
utilizando esta interfaz se estudio el ejemplo hello world, en este ejemplo luego
de desplegar el mensaje de “hello world´´ funciona como un loopback donde los
datos escritos por el usuario en la consola serial, son re-impresos por el núcleo M4
utilizando la interfaz serial.
void HelloTask ( void * pvParameters ) {
uint8_t receiveBuff ;
// Print the initial banner
PRINTF ( " \ r \ nHello World !\ n \ n \ r " ) ;

while (1) {
// Main routine that simply echoes received
,→ characters forever
// First , get character
receiveBuff = GETCHAR () ;
// Now echo the received character
PUTCHAR ( receiveBuff ) ;
}
}
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 94

3.13.3. Manejo de la interfaz I2C


Este ejemplo no estaba implementado para la plataforma de desarrollo utilizada
en este proyecto si no para el modelo DWARF. Esta comparte el SoC i.MX7D y
SoM, pero difiere en la Carrier Baseboard. Para hacer que compile el ejemplo de
FreeRTOS sensor demo como primer paso debemos cambiar las definiciones que
hacen para la DWARF Carrier Baseboard, y hacer que estas definiciones no estén
condicionadas a esa plataforma:

Figura 3.18: Modificación de la configuración para el funcionamiento de I2C.

Basta con comentar los if ( DWARF BOARD=1) y los endif. en particular


para esta sección debemos modificar la numeración de la interfaz I2C utilizada por
defecto viene configurada para I2C1 pero para la PICO-PI-GL Carrier Baseboard
no tenemos disponible esta interfaz.

Figura 3.19: Modificación de la interfaz I2C.

En el archivo gpio pins.c se sigue el mismo procedimiento de comentar las


definiciones para la plataforma DWARF.
Para los otros gpios configurados asociados a los sensores se debe elegir con cui-
dado pines que tengan sentido de acuerdo al pinout de la Carrier Baseboard que
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 95

estamos utilizado, sin embargo en la DWARF cuenta con esos sensores embebidos
en la board. Como primera aproximación en la adaptación de este ejemplo se deja-
ron las definiciones que estaban por defecto con el objetivo de que compile luego
deberan ser ajustadas a los sensores o periféricos I2C a utilizar. En gpio pins.h:

Figura 3.20: Modificación de la interfaz I2C.

Una vez que se realizan los cambios sugeridos se logra que el programa compile y
se puede ver actividad en los pines 28 y 27 del conector J8 de la Carrier Baseboard
PICO-PI-GL que conforman la interfaz I2C seleccionada. Ver Figura 3.21.

Figura 3.21: Actividad de la interfaz I2C.

Se puede encontrar más detalles de estas experiencias en la documentación


asociada a los ejemplos disponibles en el contenido descargado del repositorio de
TechNexion.

3.14. Primitivas básicas implementadas para el


núcleo A7
TechNexion usa para la PICO-PI-IMX7D y modelos semejantes, la librerı́a libg-
piod; igual uso hace Raspberry PI. La API de esta librerı́a permite manipular los
puertos y GPIO disponibles en los conectores de expansion (JP1, JP2 y J8) [69].
Tambien se realizaron pruebas utilizando el lenguaje de programación Processing
para correr aplicaciones de ejemplo y acceder a los dispositivos periférico disponi-
bles para Ubuntu.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 96

3.14.1. Manipulación de GPIO


En el caso del SoC i.MX7D, los GPIO están asociadas a siete modulos o chipsets
(0 a 6) con capacidad de interrupción. Cada banco puede contener hasta 32 lı́neas
GPIO (0-31). Cuando se configura como una salida, es posible escribir en un
registro interno para controlar el estado activado en el pin de salida. Cuando se
configura como entrada, es posible detectar el estado de la entrada leyendo el
estado de un registro interno. Se puede producir una interrupción core, mediante
un GPIO a partir de un periférico. El GPIO es uno de los bloques que controla
el IOMUX (*) del SoC. EN las MPU de la serie iMX (iMX5, iMX6, iMX6SX,
iMX6UL, iMX7D, iMX8M, ...) se refieren a GPIO utilizando dos parámetros: un
número de banco y un número de IO (pin).
Para obtener la información del GPIO correspondiente a un pin se puede con-
sultar el manual correspondiente a la plataforma. En el caso de las referencias a
los GPIO del i.MX7D publicadas por TechNexion, en la tabla de descripción de
los conectores (anexa a los esquemáticos y diagramas de conexión), no se corres-
ponden con la configuración real para la i.MX7D (al parecer la tabla se refiere a
lo correspondiente para la i.MX6D). Lo que se puede verificar, usando el comando
gpioinfo o listando el archivo que tiene la configuración para el kernel /sys/kerne-
l/debug/gpio. Como se muestra en la Figura 3.22.
$ cat / sys / kernel / debug / gpio

Figura 3.22: Salida del comando de visualización del archivo /sys/kernel/de-


bug/gpio.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 97

En ese archivo se listan los GPIO por su nombre y número con que fue exportado
(de acuedo a la fórmula; N = (BANK – 1) * 32 + IO), ese es el número que le
asigna la librerı́a libgpiod al momento de ser exportado; y es que se debe usar desde
los sketches o aplicaciones Java exportadas en Processing. Processing Foundation
utiliza libgpiod junto con la suya nativa Hardware I/O.
Normalmente se puede acceder a los GPIO en el directorio: /sys/class/gpio
$ ls - la / sys / class / gpio /

Cada GPIO tiene su propio directorio. Por ejemplo, GPIO 5 usará una carpe-
ta llamada /sys/class/gpio/gpio5. Si la carpeta no está presente, el GPIO debe
exportarse primero. Esto se puede hacer con:
$ echo 5 > / sys / class / gpio / export

y de manera similar, cuando ya no se requiera, no exportados con:


$ echo 5 > / sys / class / gpio / unexport

Para facilitar el acceso a los GPIO a través de scripts y de lı́nea de comandos,


existen herramientas de lı́nea de comandos disponibles.
Se probaron 6 herramientas de linea de comandos para esta primitiva:
gpiodetect: enumera todos los gpiochips presentes en el sistema (Figura 3.23),
sus nombres, etiquetas y número de lı́neas GPIO.

Figura 3.23: Salida del comando gpiodetect.

gpioinfo: enumera todas las lı́neas de gpiochips especificados, sus nombres,


consumidores, dirección, estado activo y banderas adicionales (Figura 3.24).
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 98

Figura 3.24: Salida del comando gpioinfo.

gpioget: lee valores de GPIO especificado lı́neas.


Leer el valor de una sola linea GPIO .
$ gpioget gpiochip1 23
0

# Leer dos valores al mismo tiempo . Establezca el estado


,→ activo de las lineas en bajo .
$ gpioget -- active - low gpiochip1 23 24
1 1

gpioset: establezce los valores de las lı́neas GPIO especificadas.


# Cambia un GPIO por nombre , luego espera a que el
,→ usuario presione ENTER .
$ gpioset -- mode = wait ‘ gpiofind " USR - LED -2 " ‘=1
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 99

Establecer valores de dos lineas , luego demonizar y


,→ esperar una senal ( SIGINT o SIGTERM ) antes de
,→ liberarlos .
$ gpioset -- mode = signal -- background gpiochip1 23=1 24=0

# Establece el valor de una sola linea , luego sal


,→ inmediatamente . Esto es util
# para pines flotantes .
$ gpioset gpiochip1 23=1

gpiofind: encuentra el nombre de gpiochip y el desplazamiento de lı́nea dado


el nombre de la lı́nea.
Encuentra una linea GPIO por nombre .
gpiofind " USR - LED -2 "
Salida : > gpiochip1 23

gpiomon: espera eventos en las lı́neas GPIO, se especifican qué eventos detec-
tar, cuántos eventos procesar antes de salir o si los eventos deben informarse a la
consola.
Espere tres eventos de flanco ascendente en una sola
,→ linea GPIO , luego salga .
$ gpiomon -- num - events =3 -- rising - edge gpiochip2 3
event : RISING EDGE offset : 3 timestamp : [
,→ 1151.814356387]
event : RISING EDGE offset : 3 timestamp : [
,→ 1151.815449803]
evento : RISING EDGE offset : 3 timestamp : [
,→ 1152.091556803]

# Espere un solo evento de flanco descendente . Con


,→ formato de salida personalizado .
$ gpiomon -- format = " %e %o %s %n " -- falling - edge
,→ gpiochip1 4
0 4 1156 615459801

Pausa la ejecucion hasta que ocurra un solo evento de


,→ cualquier tipo . No imprimir
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 100

# nada . Encuentra la linea por su nombre .


$ gpiomon -- num - events =1 -- silent ‘ gpiofind " USR - IN " ‘
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 101

Supervisar varias lineas , salir despues del primer


,→ evento .
$ gpiomon -- silent -- num - events =1 gpiochip0 2 3 5

PWM

Los controladores de software que manejan los PWM disponibles en el i.MX7D,


están definidos en la carpeta /sys/class/pwm, y allı́ deben de estar visibles como:
pwmchip0, pwmchip1 sucesivamente [70].
$ ls - la / sys / class / pwm

Los controladores que maneja los PWM declarados en los esquemáticos y dia-
gramas de conexión publicados por TechNexion, son: PWM1 (J8 PIN12), PWM2
(J8 PIN33) y PWM3 (J8 PIN15); todos trabajando a 3V.
Para PWM1 (J8 PIN12), se debe ubicar en pwmchip1, y desde allı́ declarar
(EXPORTAR) el pwm0, luego se tiene acceso (desde el shell de Linux), a ese
controlador exportado y ya es disponible para configurarlo, como sigue:
Primero se debe de exportar el controlador a utilizar, ubicándonos en el direc-
torio: /sys/class/pwmchip1
$ echo 0 > export

Luego, desde la carpeta de ese controlador, se configura el PWM, en este caso


pwm0:
$ cd pwm0 /

$ echo 10000 > period

$ echo 6000 > duty_cycle

$ echo 1 > enable

Con comandos y definiciones se ha configurado el PWM0, con la frecuencia


PWM en 10 kHz y el ciclo de trabajo igual a 6 kHz (Figura 3.25).
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 102

Figura 3.25: Señal PWM.

3.14.2. Control de la Backlight del LCD


El brillo de la retroiluminación de la pantalla LCD que acompaña a la PICO-
PI-IMX7, se puede controlar leyendo y escribiendo /sys/class/backlight/backlight;
filesystem (sysfs)[71].
$ cd / sys / class / backlight / backlight
$ cat max_brightness
7

El archivo max brightness contiene un valor que se refiere al brillo máximo de


la luz de fondo. El nivel de brillo se puede controlar escribiendo un número entre
0 y max brightness en el archivo de brillo.
Ejemplo, para apagar o oscurecer totalmente:
$ echo 0 > brightness

Máximo brillo:
$ echo 100 > brightness

3.14.3. Manejo del UART


Los UART a menudo se denominan “UART1” o “UART2”, etc. (por lo general,
no hay ÜART0”). El software, por otro lado, normalmente enumera los dispositivos
de puerto serie comenzando con el número 0.
La PICO-PI-IMX7 de TechNexion, tiene un puerto serie expuesto, en los pines
8 (TXD), 10 (RXD), pin 7 (RTS) y pin 11 (CTS), todos ellos se corresponden al
UART6 fı́sico del conector J8. También replicado en el conector JP2; solo TXD
y RXD. Estos pines, operan en niveles TTL de 3.3V, en lugar de los niveles de
voltaje RS-232; que normalmente se esperan del “puerto serial” en una ordenador.
Debe de utilizar un dispositivo que trabaje a 3.3V.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 103

Los parámetros UART se leen y configuran con el comando stty. Por ejemplo,
para configurar la tasa de baudios en UART3 a 115200, se usa el comando:
A continuación se listan las primitivas de control probadas:
Configuración de la tasa baudios:
$ stty -F / dev / ttymxc2 115200

Habilitar el control de flujo:


$ stty -F / dev / ttymxc2 crtscts

Desactivar el control de flujo


$ stty -F / dev / ttymxc2 - crtscts

Revisar el estado actual de la interfaz


$ stty -a -F / dev / ttymxc2

Envı́o y recepción de datos por un puerto UART: El envı́o se realiza escribiendo


datos al del dispositivo; como si fuera un “archivo”:
$ echo " Hello world " > / dev / ttymxc2
y para recibir se debe de leer el dispositivo ; el "
,→ archivo " :
$ cat / dev / ttymxc2

3.14.4. Manejo de la interfaz SPI


El siguiente conjunto de primitivas está referido al uso de la interfaz SPI desde
la consola shell de Ubuntu y desde Processing [72].
Para verificar que Ubuntu tiene control de la interfaz SPI, se puede utilizar el
siguiente comando:
$ ls / dev / spidev *

Si el dispositivo está disponible se observa una salida como esta:


/ dev / spidev2 .0

El archivo /dev/spidev2.0 es un dispositivo especial en Linux que representa


una conexión a un bus SPI. El número 2 en el nombre del archivo corresponde
al número del bus SPI en el sistema, y el 0 representa el número del dispositivo
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 104

en ese bus. Cuando se abre el archivo /dev/spidev2.0, se establece una conexión


con el dispositivo SPI correspondiente, y se pueden enviar y recibir datos a través
de este archivo utilizando llamadas al sistema, como read() y write(). El archivo
actúa como una interfaz para el bus SPI, permitiendo que las aplicaciones accedan
a los dispositivos conectados a través del bus.
En Processing la librerı́a “processing.io” incluye la clase ”SPI”, que proporciona
una interfaz para comunicarse con dispositivos a través del protocolo SPI. Esta
clase utiliza el dispositivo SPI definido en el sistema operativo subyacente (por
ejemplo, /dev/spidev2.0 en Linux) para transferir datos. La clase “SPI” tiene
varios métodos útiles para trabajar con dispositivos SPI, como:
beginTransaction(): Iniciar una transacción de comunicación con un dispo-
sitivo SPI. Este método configura la velocidad del reloj, el orden de bits y el modo
de datos del bus SPI.
endTransaction(): finaliza una transacción de comunicación con un disposi-
tivo SPI. Este método restaura la configuración original del bus SPI.
setBitOrder(): establece el orden de bits (MSB o LSB) utilizado en la trans-
ferencia de datos.
setDataMode(): Configura el modo SPI (SPI MODE0, SPI MODE1, SPI MODE2
o SPI MODE3) utilizado en la transferencia de datos.
setClockDivider(): Para establecer la velocidad del reloj utilizado en la trans-
ferencia de datos.
transfer(): para enviar y recibir datos a través del bus SPI. Este método toma
un arreglo de bytes que contiene los datos a enviar y devuelve un arreglo de bytes
que contiene los datos recibidos.

Figura 3.26: Actividad en el puerto SPI generada desde Processing, visuali-


zada desde Logic2 mediante el analizador lógico.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 105

3.14.5. Instalación de Processing en Ubuntu sobre i.MX7D


1. Como super usuario, desde una consola o terminal de Ubuntu, se descarga la
versión de Processing para ARM (Raspberry Pi 32 bit); página de descarga
de Processing Org.

2. Expanda el archivo .tgz descargado, en el lugar donde va a quedar instalado


Processing.
$ tar - xzvf [ nombre del archivo ]

3. Verifique que se tiene instalado el Java adecuado en la versión de Ubuntu de


su sistema.
$ java -- version )

4. Ejecute el script de instalación:


$ sudo ./ install . sh

5. Verifique con uno de los ejemplos (del menu de ejemplos) que el intérprete
del PDE funciona.

3.14.6. Ejecución de programas desarrollados en Proces-


sing
Processing es un entorno de programación y lenguaje diseñado para facilitar la
creación de obras visuales y interactivas en el ámbito de la programación artı́stica
y la computación creativa. Desarrollado en 2001 por Casey Reas y Ben Fry. Pro-
cessing combina elementos de programación con la expresión visual, permitiendo
a artistas, diseñadores y programadores crear piezas visuales dinámicas, anima-
ciones, instalaciones interactivas y mucho más. Basado en Java, Processing ofrece
una abstracción amigable para trabajar con gráficos, permitiendo a los usuarios
enfocarse en la creatividad y la experimentación visual, sin la necesidad de su-
mergirse en detalles técnicos complejos. Desde su creación, Processing ha ganado
popularidad en la comunidad de artistas digitales y educadores, proporcionando
una plataforma versátil para explorar la convergencia entre arte, tecnologı́a y pro-
gramación. El entorno de desarrollo de procesamiento (PDE), incluye un editor de
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 106

texto, un compilador y una ventana de visualización. En Processing, los programas


son nombrados bocetos (sketches).
La biblioteca de E/S de hardware (Hardware I/O) permite el acceso a los pe-
riféricos hardware de una computadora, como entradas y salidas digitales (GPIO,
PWM) o busses seriales (UART, SPI, I2C). Esta biblioteca solo está disponible
para arquitecturas que corran Linux integradas con los controladores de kernel
necesarios, como Raspberry Pi; o Ubuntu corriendo sobre un ARM Cortex-A7.
Los programas o sketches de Processing, se interpretan en el PDE y se con-
vierten a Java, desde donde son ejecutadas. Igual pueden exportarse los sketches
(como aplicaciones Java) hacia otras plataformas: Linux, Android, macOS y Win-
dows. Lo que se exporta es un JAR (Java ARchive), especı́fico para la plataforma
seleccionada; el cual ya no necesita del PDE. Ese resultado incluso puede ser empo-
trado en una aplicación mayor desarrollada en Java o C++. Lo contrario también
es posible: desarrollar en C++ o Java y usar una librerı́a core de Processing para
utilizar todos sus recursos. También se pueden desarrollar un sketch de Processing
utilizando otros lenguajes como Java, Python, JavaScript y R.
La siguiente imagen, es un ejemplo de una aplicación Visor Sismómetro [73]
desarrollada en Processing para Windows. Se ejecutó en el PDE de Processing
Ubuntu en la PICO-PI-IMX7; y luego se exportó a Java, desde donde se ejecutó
para capturar la imagen. La aplicación guarda y gráfica la data de un geófono SM-
6 (proveniente del conversor A/D de un PIC 18) desplegándola en pantalla con el
auxilio de la interactividad de un menú. La gráfica es producto del despliegue de
los datos almacenados en un archivo.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 107

Figura 3.27: Ejecución de la aplicación Visor Sismómetro [73] en la plataforma


de desarrollo PICO-PI-IMX7.

Es importante señalar que aunque es posible ejecutar aplicaciones de alto nivel


en la plataforma, no es recomendable para un producto final utilizar, una interfaz
gráfica elaborada con una herramienta de alto nivel, ya que se tiene menos control
de los tiempos de ejecución, lo más recomendable serı́a realizar una aplicación
adaptada al proyecto en un lenguaje de bajo nivel como C.

3.15. RPMsg
Para el contexto de esta investigación, existen dos kernels diferentes de Linux:
el upstream o mainline, que proviene del repositorio de Linus Torvalds, y el downs-
tream, que proviene de NXP (modificado por TechNexion). La versión descenden-
te tiene muchas modificaciones para admitir algunos periféricos NXP/TechNexion
que aún no están disponibles o que fueron rechazados en la lı́nea principal. Un
buen ejemplo es el RPMSG.
El kernel de la lı́nea principal usa la implementación de OpenAMP (Open
Asymmetric Multi-Processing), que es un esfuerzo por hacer que HMP (multipro-
cesamiento heterogéneo) sea más fácil para los dispositivos Linux, mientras que
el downstream usa RPMSG-Lite, que es un protocolo creado por NXP y no está
disponible en el kernel de la lı́nea principal (debido a que fue adoptado el modelo
OpenAMP).
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 108

RPMsg es un bus de mensajerı́a basado en VirtIO, que permite que los contro-
ladores del kernel se comuniquen con los procesadores remotos disponibles en el
sistema. A su vez, los controladores podrı́an exponer las interfaces de espacio de
usuario adecuadas si fuera necesario.
Cada dispositivo RPMsg es un canal de comunicación con un procesador re-
moto por lo que los dispositivos RPMsg se denominan canales. Los canales se
identifican con un nombre textual y tienen una dirección RPMsg local (“origen”)
y una dirección RPMsg remota (“destino”).
RPMsg permite una comunicación de bajo costo y baja latencia entre proce-
sadores, lo que es esencial para aplicaciones en tiempo real y de alto rendimiento.
Facilita la transferencia de datos y comandos entre los procesadores, lo que permite
la coordinación y la colaboración entre los diferentes componentes del sistema.
Estos otros procesadores remotos suelen ser adecuados para manejar tareas es-
pecı́ficas, como la aceleración de hardware multimedia o una pantalla LCD. Con
marco genérico de AMP/IPC, es posible controlar estos procesadores AMP re-
motos (encender, apagar, arrancar) y comunicar (enviar/recibir) mensajes. Los
controladores reales de este marco deben exponer la interfaz del espacio del usua-
rio. La otra parte de la ecuación es remoteproc, que es un controlador genérico
para mantener el estado de los procesadores remotos. Este controlador abstrae las
diferencias de hardware con el soporte para por ejemplo los procesadores en el SoC
NXP i.MX7D: 2 procesadores ARM Cortex-A7 de 32 bits (doble núcleo de bajo
consumo, con una frecuencia de hasta 1 GHz) y el coprocesador ARM Cortex-M4
(a 200MHz) Figura 3.28.
El controlador de caracteres RPMsg presenta los extremos de RPMsg a los pro-
cesos del espacio de usuario. Múltiples aplicaciones del espacio de usuario pueden
usar un canal RPMsg; presentando solicitudes diferentes de interacciones con el
servicio remoto. El controlador de caracteres RPMSg admite la creación de múlti-
ples puntos finales para cada dispositivo RPMsg, lo que permite el uso del mismo
canal para diferentes propósitos. Cada dispositivo de punto final creado se muestra
como un dispositivo de un solo carácter (/dev). Los derechos de acceso se pueden
configurar de forma independiente para cada punto final individual; esto es válido
para un kernel de Linux; con soporte para RPMsg.

ˆ ioctl: llamada de sistema en Unix-Linux que permite a una aplicación con-


trolar o comunicarse con un driver de dispositivo.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 109

ˆ sysfs: es la función encargada en el kernel de Linux de exportar información


sobre los dispositivos y sus controladores desde el modelo de dispositivos del
núcleo hacia el espacio del usuario.

ˆ udev: es el gestor de dispositivos que usa el núcleo Linux. Su función es


controlar los archivos de dispositivo en /dev.

Figura 3.28: Modelo de la comunicación entre procesadores IPC RPMsg [74].

En el modelo RPMsg, el bus VirtIO está debajo del bus RPMsg. Cada mensaje
de anuncio de servicio de nombres de VirtIO crea un nuevo dispositivo RPMsg, que
se supone debe vincularse a un controlador RPMsg; que se crea dinámicamente:

ˆ El dispositivo remoto anuncia la existencia de un servicio RPMsg remoto


mediante el envı́o de un mensaje de anuncio de servicio de nombre que con-
tiene el nombre del servicio (es decir, el nombre del canal), las direcciones
de origen y de destino.

ˆ El mensaje es manejado por el bus RPMsg, que crea y registra dinámica-


mente un canal RPMsg que representa el servicio remoto.

ˆ Tan pronto como se registra un controlador RPMsg relevante, el bus lo prue-


ba de inmediato y las dos partes pueden comenzar a intercambiar mensajes

VirtIO RPMsg se implementó antes del API RPMsg FreeRTOS aware; y no


se hizo para trabajar a la par con el controlador de caracteres mensajes RPMsg.
La siguiente abstracción (Figura 3.29) [75] sirve para dar una idea general del
funcionamiento de esta tecnologı́a.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 110

Figura 3.29: Analogı́a VirtIO [75].

1. VM: Quiero ir a google.com. Hola VirtIO-net, ¿puedes decirle al host que


recupere esta página web por mı́?

2. VirtIO-net: Está bien. Hola host, ¿puedes abrir esta página web para noso-
tros?

3. Host: Está bien. Estoy tomando los datos de la página web ahora.

4. Host: Aquı́ están los datos de la página web solicitada.

5. VirtIO-net: Gracias. Hola VM, aquı́ está la página web que solicitaste.

Aunque este ejemplo es demasiado simplificado, la idea central permanece in-


tacta. Es decir, hacer que el hardware del host haga la mayor parte del trabajo
posible y dejar que VirtIO maneje el envı́o y la recepción de datos. La descarga de
la mayor parte del trabajo al host hace que la ejecución en la VM sea más rápida
y eficiente en comparación con si estuviera emulando un dispositivo [75].
Cada controlador RPMsg puede vincularse a un controlador RPMsg sı́mple o
al controlador de caracteres RPMsg. Originalmente RPMsg, se implementó como
un parche con los siguientes objetivos:

1. El dispositivo RPMsg se crea cuando se prueba el controlador VirtIO RPMsg.

2. Cuando se anuncia un servicio remoto, se mantiene en la lista de servicios


remotos de VirtIO proc.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 111

3. Cuando se registra un controlador RPMsg relevante, el bus RPMsg lo prueba


inmediatamente.

Los siguientes diagramas (Figuras 3.30 y 3.31) muestran la implementación actual


del marco RPMsg en Linux, y las funcionalidades del controlador de caracteres
RPMsg.

Figura 3.30: Implementacı́on de Virtio [74].


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 112

Figura 3.31: Mecanismo de comunicación de RPMsg.

En el procesador maestro:

1. Cuando el módulo se carga o se instala en el kernel del sistema operativo


Linux (utilizando el comando insmod o modprobe), se realiza una exploración
de los dispositivos conectados para detectar si hay algún dispositivo RPMsg
disponible. Si se encuentra un nuevo dispositivo RPMsg, automáticamente
se invoca la función rpmsg tty probe para inicializar y registrar el controlador
TTY correspondiente a ese dispositivo.

2. La función rpmsg tty probe se encarga de realizar las configuraciones necesa-


rias para permitir la comunicación con el dispositivo a través de la interfaz
TTY. Esto incluye la inicialización de estructuras de datos, la asignación de
recursos y la configuración del controlador de terminal TTY. Después de que
rpmsg tt probe ha sido ejecutada con éxito, el dispositivo RPMsg está listo
para la comunicación bidireccional entre el procesador maestro y el procesa-
dor remoto. Se pueden enviar y recibir mensajes a través de los canales de
comunicación RPMsg establecidos.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 113

3. La función rpmsg tty write se utiliza para iniciar y administrar el envı́o de


datos desde el procesador maestro al procesador remoto a través de la co-
municación RPMsg. Esta proporciona un buffer de datos y su tamaño como
argumentos; la función toma los datos del buffer y los envı́a al procesador
remoto a través del canal de comunicación RPMsg establecido usando la
función rpmsg send.

ˆ La función rpmsg send se utiliza para enviar mensajes a través del canal
de comunicación RPMsg establecido entre el procesador maestro y el
procesador remoto, toma como argumento un puntero al contexto de
RPMsg, el identificador del canal RPMsg, un puntero al buffer de datos
que se va a enviar y el tamaño de los datos.

En el procesador remoto

1. El código del remoto inicializa el sistema, configura las interrupciones MU


y realiza la inicialización del RPMsg. Luego, entra en un bucle infinito para
esperar recibir mensajes del maestro; esto lo hace con: while (msg count ==
0).

2. En el peor de los casos, el maestro enviará tres mensajes consecutivos que el


remoto no procesará. La sincronización entre el remoto y el maestro se logra
debido a que cada vez que se devuelve la llamada al punto final, la inte-
rrupción de recepción MU se desactiva temporalmente. Hasta que el remoto
consuma el mensaje, la interrupción no se habilitará nuevamente. Cuando la
interrupción no está habilitada, el maestro no puede enviar la notificación,
se bloqueará allı́ y no puede enviar más mensajes. El maestro envı́a el pri-
mer mensaje, dispara el ISR en el lado remoto, ISR remoto borra el bit de
estado MU para que el maestro pueda enviar el segundo mensaje y notifique
nuevamente y el maestro puede continuar enviando el tercer mensaje, pero
lo bloqueará al intentar notificarlo. Mientras tanto, el lado remoto todavı́a
está en el primer ISR que tiene un bucle para recibir los tres mensajes. El
maestro está bloqueado y no puede enviar el cuarto mensaje, el ISR del lado
remoto almacena estos tres mensajes en el buffer de la aplicación e informa
a la capa de la aplicación para consumirlos. Después se consumen tres men-
sajes, se habilita nuevamente el ISR y se recibe la segunda notificación. Esto
desbloquea al maestro para completar la tercera notificación y enviar el cuar-
to mensaje. La situación continúa y podemos ver que la capa de aplicación
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 114

necesita un tamaño máximo de tres buffers para contener los mensajes no


consumidos. Por lo tanto, el contador STRING BUFFER CNT se establece
en tres. El término slot se refiere a un ı́ndice o posición en un buffer utilizado
para almacenar mensajes recibidos. En particular, el código utiliza un array
de estructuras app message t llamado app msg, tiene un tamaño definido
por STRING BUFFER CNT. Cada elemento en este array representa un
slot que puede contener un mensaje recibido.
El propósito de utilizar múltiples slots es permitir el almacenamiento y proce-
samiento concurrente de varios mensajes recibidos. Cuando se recibe un nue-
vo mensaje, se almacena en el siguiente slot disponible en el array app msg,
y se incrementa el ı́ndice app idx para apuntar al siguiente slot. Esto permite
que los mensajes se almacenen y procesen de manera secuencial en los dife-
rentes slots, lo que evita la pérdida de mensajes y garantiza que se procesen
en el orden en que se recibieron. Al utilizar múltiples slots, el código pue-
de manejar correctamente la recepción de nuevos mensajes mientras aún se
están procesando los mensajes anteriores. Esto es especialmente importante
en sistemas en los que la velocidad de recepción de mensajes es mayor que
la velocidad de procesamiento de los mismos.

3. Luego que llega un mensaje, se activa la función de devolución de llamada


rpmsg read cb. Esta función se llama cuando se recibe un mensaje a través
del canal RPMsg. En esta función, se deshabilita temporalmente la interrup-
ción de recepción MU para evitar que el maestro envı́e demasiados mensajes
y el remoto no pueda mantener el ritmo para consumirlos. El mensaje reci-
bido se almacena en un buffer local y se guarda información sobre su origen,
longitud y datos.

4. Después de guardar el mensaje recibido en un buffer local; también guardar


la información relevante en la estructura app msg, se habilita nuevamente la
interrupción de recepción MU y se espera a que lleguen más mensajes.

5. Una vez que se ha procesado un mensaje, se prepara un buffer de transmisión


de RPMsg para enviar una respuesta al maestro.

6. La función UART SendDataPolling se utiliza para enviar los datos recibidos


desde el terminal desde el puerto UART al maestro a través de RPMsg; este
proceso se repite para cada bloque de datos recibido.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 115

7. Una vez que se ha enviado la respuesta al maestro, se libera el buffer de


recepción RPMsg y se repite el ciclo esperando nuevos mensajes del maestro.
Se llama a RPMsg release rx buffer para indicar que el buffer de recepción
puede ser liberado y reutilizado.

Mecanismo de envı́o y recepción RPMsg

En las Figura 3.32 tenemos el flujograma mecanismo de comunicación RPMsg


y en la Figura 3.33 tenemos el flujograma Mecanismo de Desconección de RPMsg.

Figura 3.32: Mecanismo de comunicación de RPMsg modificado [74].


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 116

Figura 3.33: Mecanismo de Desconección de RPMsg modificado por [74].

La interfaz de control: El controlador de caracteres RPMsg proporciona una


interfaz de control (en forma de un dispositivo de caracteres en /dev/rpmsg ctrlX),
lo que permite que el espacio del usuario exporte una interfaz de punto final
para cada punto final expuesto. A través de la función rpmsg create ept (en
rpmsg rtos.c), se crea un endpoint (punto final) para comunicación bidireccional
mediante la librerı́a RPMsg; pasándole varios parámetros:

ˆ rp chnl: es el canal de comunicación asociado al endpoint que se está crean-


do.

ˆ rpmsg read rtos cb: es el puntero a la función de callback que se llamará


cada vez que se reciba un mensaje en este endpoint.

ˆ (void ∗)q: es un puntero a la cola en la que se almacenarán los mensajes


entrantes.

ˆ addr: es un puntero a la dirección que se asignará al endpoint creado.


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 117

Se crea un canal de comunicación RPMsg, ejecutando:


retval = rpmsg_create_ept ( rp_chnl , rpmsg_read_rtos_cb , (
,→ void *) q , addr ) ;

El ioctl recibe la información (declarado en rpmsg.h):


* channel_info - channel info
* @name : channel name
* @src : local address
* @dst : destination address
*/
struct channel_info {
char name [ RPMSG_NAME_SIZE ];
unsigned long src ;
unsigned long dest

El backend RPMsg utiliza los tres campos para crear el punto final real y
el controlador char RPMsg para crear un dispositivo de punto final RPMsg (en
/dev/rpmsgX), junto con los mismos tres parámetros en sysfs para el uso de udev.
Se pueden crear múltiples puntos finales usando la interfaz de control. A cada
dispositivo de punto final creado se le asigna un número secuencial, para que se
distingan entre sı́.
La interfaz de punto final: Para cada punto final, el controlador de caracteres
RPMsg utiliza una cola de buffer de socket para almacenar los datos recibidos en
el canal destinado a ese punto final. Cuando los datos del dispositivo remoto llegan
al canal RPMsg, el controlador de caracteres RPMsg asigna un buffer de socket
para contener los datos recibidos y los pone en cola en la cola de buffer de socket
del punto final de destino.
Las aplicaciones del espacio de usuario pueden interactuar con el servicio remoto
leyendo/escribiendo datos hacia/desde el punto final, a través de la interfaz del
punto final en /dev/rpmsgX (X indica el número del punto final):

ˆ Lectura: cuando se solicita una operación de lectura en un dispositivo de


punto final, el backend saca de la cola un buffer de socket de la cola de buffer
de socket asociada a ese punto final (si no está vacı́o) y copia los datos en el
buffer del usuario.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 118

ˆ Escritura: cuando se solicita una operación de escritura en un dispositivo


de punto final, el backend copia el buffer del usuario en un buffer del kernel
y envı́a un mensaje RPMsg con el contenido del buffer al dispositivo remoto.

La interfaz del punto final proporciona un ioctl para destruir el punto final
(rpmsg rtos.c):
/*!
* @brief / como comando : does not need to write data to
,→ kernel space
* This function deletes rpmsg endpoint and performs
,→ cleanup . RTOS aware version .
*
* @param [ in ] rp_ept Pointer to endpoint to destroy //
,→ magic number to differentiate the set of ioctl
*
* @see rpmsg_rtos_create_ept // number assigned to the
,→ ioctl operation to distinguish commands from one
,→ another
*/

void rpmsg_rtos_destroy_ept ( struct rpmsg_endpoint *


,→ rp_ept ) // (0 xb5 , 0 x2 )

El extremo de RPMsg se creará y destruirá después de abrir y cerrar el dispo-


sitivo de extremo, lo que permitirá que los backends de RPMsg abran y cierren el
canal fı́sico, donde sea compatible.

3.16. Primitivas básicas asociadas a RPMsg

3.16.1. Ecos de caracteres con RPMsg


Esta aplicación de demostración muestra cómo funciona la pila de pares remotos
de RPMsg en el sistema operativo FreeRTOS con la extensión API de RTOS de
RPMsg. Funciona con Linux RPMsg master peer para transferir contenido de
cadena de un lado a otro.
El objetivo del ejemplo RPMsg String Echo FreeRTOS Demo with RTOS API:
El protocolo de enlace del servicio de nombres se realiza primero para crear los
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 119

canales de comunicación. A continuación, el sistema operativo Linux espera la


entrada del usuario en el TTY virtual de RPMsg. Todo lo que se recibe se envı́a
al núcleo ARM Cortex-M4. El núcleo ARM Cortex-M4 muestra lo que se recibe
y repite el mismo mensaje como confirmación. El lector tty en el núcleo ARM
Cortex-A7 puede recibir el mensaje e iniciar otra transacción. La demostración
demuestra la capacidad de RPMsg para enviar contenido arbitrario de un lado a
otro.
La extensión RPMsg RTOS API es un conjunto de API fáciles de usar que
admiten la recepción/envı́o de mensajes multitarea. El módulo pluggable del lado
Linux, se crea con el programa: imx rpmsg tty.c y el programa para el esclavo
Cortex-M4, con: str echo freertos.c. Ambos establecen el canal de comunicación y
los buffers necesarios (Figura 3.34).

Figura 3.34: Comunicación rpmsg A7-M4 [76].

Requerimientos de Hardware

ˆ Tarjeta de desarrollo PICO-PI-IMX7D con Linux (RPMsg activado)

Cable micro-USB (para consola de debugging y consola auxiliar) y otro tipo


C-USB (para alimentación y consola OTG)

ˆ Ordenador con puertos USB

ˆ Un software terminal Serial como PuTTY, configurado de la manera mos-


trada anteriormente en este trabajo
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 120

Preparando y ejecutando la demostración:

1. Abra dos terminales seriales en la computadora con la configuración Figura


3.1.

2. Compile y cargue el archivo binario del ejemplo demostracióin en la memoria


TCM mediante el mini shell de U-Boot, usando el comando ums mmc 0
puede montar la memoria como una unidad de almacenamiento visible para
el ordenador y copiar el archivo:
rpmsg_str_echo_freertos_example . bin

3. Inicie la parte esclava del ejemplo, en el núcleo ARM Cotex M4 auxiliar para
comenzar a ejecutar la demostración.
= > datload mmc 0 0 x7f8000
,→ rpmsg_str_echo_freertos_example . bin
59683 bytes read in 23 ms (2.5 MiB / s )
= > dcache flush
bootaux 0 x7f8000
U - Boot : # # Starting auxiliary core at 0 x0007f8000 ...
,→ ( Consola de debug )

Salida por la consola auxiliar (M4 FreeRTOS) Figura 3.35:

Figura 3.35: Salida consola serial auxiliar M4 esclavo en la espera del maestro.

4. Luego continuamos con el proceso de boot, escribimos el comando boot en la


consola de U-Boot para que el proceso de boot inicie el kernel del sistema
operativo Linux.

5. Desde el shell de Linux, habilitar todos los niveles de mensajes del kernel
por la consola (esta salida queda igual registrada como la última entrada de
demsg):
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 121

$ echo 8 > / proc / sys / kernel / printk

6. Desde el shell de Linux, instalar el módulo maestro del ejemplo imx rpmsg tty
para que sea ejecutado por los ARM Cortex-A7.
Si no recuerda el nombre del módulo a instalar puede usar el siguiente co-
mando:
$ ls / dev / | grep RPMSG

7. Luego se carga el módulo con:


$ modprobe imx_rpmsg_tty

8. El usuario puede ingresar una cadena de caracteres en el RPMsg tty virtual


usando el siguiente comando

ˆ Primero debe verificar la existencia del dispositivo tty asociado a RPMsg

$ ls / dev /| grep RPMSG

ˆ Luego de conocer el nombre del dispositivo puede enviar mensajes a la


consola del Cortex-M4 a través de ese tty virtual:
$ echo " Rommel Contreras " > / dev / ttyRPMSG0

ˆ En los terminales del ARM Cortex-M4, se emite el contenido de la


cadena recibida y su longitud. En el del ARM Cortex-A7 se recibe el
eco de lo enviado:

Figura 3.36: Mensaje enviado desde el maestro Cortex-A7 con Linux y su eco
retornado.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 122

Figura 3.37: Mensaje recibido en el esclavo Cortex-M4 con FreeRTOS.

RPMsg master (Cortex-A7 Linux OS) y remote (M4 FreeRTOS OS) realizan
el protocolo de enlace del servicio de nombres para crear el canal de comunicación.
La dirección del canal M4 es 1 y la dirección del canal A7 es 1024. El núcleo A7
luego espera la entrada del usuario a RPMsg virtual TTY y envı́a el contenido al
núcleo M4. Al recibir los datos, el núcleo M4 genera el contenido y su longitud
en el terminal y devuelve el mismo mensaje al núcleo A7. Si alguna aplicación
está leyendo desde /dev/ttyRPMSG en el núcleo A7, podrı́a recibir el mensaje de
eco. El ciclo continúa demostrando la capacidad de RPMsg para enviar contenido
arbitrario.
Note que el eco retornado en el terminal del Cortex-A7, se divide en partes
de 16 caracteres máximos, si la longitud del mensaje enviado es mayor a 16; esto
es debido a la configuración inicial del módulo imx rpmsg tty. La implementación
de la API RTOS cuenta con una cola para almacenar los mensajes recibidos, de
modo que todos los mensajes del núcleo A7 puedan almacenarse en el buffer para
recibirlos a continuación del procesado.

3.16.2. RPMsg PingPong


Una segunda experiencia realizada utilizando el API de RPMsg para FreeR-
TOS, fue la ejecución y carga del ejemplo “rpmsg pingpong”. Funciona con Linux
RPMsg master peer para transferir valores enteros de un lado a otro.
El programa de ejemplo opera de la siguiente manera. El protocolo de enlace
del servicio de nombres se carga primero para crear los canales de comunicación.
A continuación, el Cortex-A7 con el sistema operativo Linux transfiere el primer
entero (0) al Cortex-M4 con el sistema operativo FreeRTOS, el cual suma 1 al
número entero enviado y lo devuelve al master; repitiendo esto 100 veces.
Nota: Al igual que el ejemplo mensionado en la primitiva anterior remoteproc
support debe de estar activado.
Apartando, la configuración previa de las variables y el establecimiento del
canal el proceso de comunicación se resume a las rutinas señaladas en la Figura
3.38.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 123

Figura 3.38: Mecanı́smo de interacción.

Ejecución

Se carga la imagen del ejemplo al núcleo M4 con el procedimiento mostrado


en la sección anterior pero con el nombre correspondiente a la imagen del ejemplo
rpmsg pingpong freertos example.bin. Luego se continua el arranque del sistema
operativo, en la terminal se ejecuta:
$ echo 8 > / proc / sys / kernel / printk

Para habilitar todos los niveles de mensajes del kernel a salir por la consola
(esta salida queda igual registrada como la última entrada de dmsesg):
Desde el shell de Linux, instale el módulo maestro del ejemplo ping-pong, para
que sea ejecutado por los ARM Cortex-A7.
$ modprobe imx_rpmsg_pingpong

Las Figura 3.39 y 3.40 muestran las salidas en ambas consolas (la del shell de
Linux y la del terminal de depuración del núcleo M4):
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 124

Figura 3.39: Salida terminal de depuración del ARM Cortex-M4 (FreeRTOS).

Figura 3.40: Salida terminal del shell Linux ARM Cortex-A7.


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 125

3.17. Implementación del Driver para controlar


el AFE ADS1298 usando la plataforma au-
xiliar
Al momento de iniciar este trabajo de investigación, se elaboró en paralelo, un
driver para el AFE ADS1298 usando la plataforma auxiliar que utiliza un kit de
desarrollo más simple como lo es el PICDEM Z Demostration Kit de Microchip
Technology, para facilitar el proceso de migración de código y el desarrollo del
mismo sin tener que afrontar las dificultades del desconocimiento de la plataforma
principal.
Varios trabajos similares en diferentes plataformas PICs, Raspberry y Arduino
[77],[78],[79] y principalmente en el trabajo de Meng [80] debido a que la plataforma
de trabajo de la cual se partı́a era muy similar a la elegida, permitió adaptar y
modificar el código a las necesidades del proyecto, pasando de adquirir datos de 8
bits (como en el caso de la implementación de Meng) a adquirir 24 bits de datos
por canal.
Se trabajo con un módulo aislada de adquisición de ECG de 12 derivaciones,
basado en el ADS1298 de Texas Instruments, con 8 canales de adquisición, comuni-
cación SPI y conector mikroBus; desarrollada por el Ingeniero Cruz (no publicado)
(Figuras 2.16 y 3.42).

Figura 3.41: Módulo de adquisición ECG, vista superior.

Figura 3.42: Módulo de adquisición ECG, vista inferior.


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 126

3.17.1. Configuración del PICDEM Z Demostration Kit


Realizar esta implementación implicó revisar los controladores realizados para
el ADS1298 en diferentes plataformas. De los trabajos revisados fueron notables
por su estructuración los recursos de software disponibles por Analog Devices Inc.
para el control de AFE y otro driver desarrollado por Meng en C18 (a partir
de las rutinas de Analog Devices, Inc.). Estas simplificaban algunas opciones del
anterior, tenı́an una implementación más sencilla adecuada para los objetivos del
proyecto, por lo que se tomó como punto de partida para el diseño del controlador.
Se decidió utilizar es compilador MPLAB C18 luego de revisar el código para
controlar el ADS1298 a través de un microcontrolador PIC18F46K22 realizado por
Meng, [80], debido a que se disponı́a de los microcontroladores PIC18F4620 y el
PIC18F25K20.
Entre los dos microcontroladores disponibles se eligió utilizar el PIC18F4620
porque compartia el mismo empaquetado y layout que el PIC18F46K22. Sin em-
bargo, a pesar de sus similitudes las etiquetas asociadas a su definición en código
diferian significativamente (Figura 3.43); podemos ver un ejemplo de esto en la
imagen siguiente:

Figura 3.43: Etiquetas de definición, PIC18F4620 (Izq.) PIC18F46K22 (Der.).

Explicación del protocolo SPI

El ADS1298 es un dispositivo de conversión analógico a digital (ADC) que está


diseñado especı́ficamente para la adquisición de señales de ECG y otras aplicacio-
nes biomédicas. Utiliza una interfaz SPI para la comunicación con el microcontro-
lador o procesador que lo controla.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 127

El modo de operación para la comunicación del AFE coincide con el modo 0


de la comunicación SPI planteada por Microchip Technology [81] como se ve en
las Figuras 3.44 y 3.45:

Figura 3.44: Modo 1 comunicación SPI Microchip Technology [81].

Figura 3.45: Modo 1 comunicación SPI para ADS1298 Texas Instruments [31].

El ADS1298 utiliza registros de configuración de 8 bits para ajustar y controlar


diferentes parámetros como la ganancia de los canales, las referencias de voltaje, el
tipo de adquisición, entre otros. Estos registros son accesibles a través de la interfaz
SPI y se utilizan cargando determinados valores dependiendo de la configuración
que se espera lograr. A continuación, se describen algunos de los registros de
configuración claves para el desarrollo del driver.

3.17.1.1. Registro de Configuración 1

En este registro (Figuras 3.46 y 3.47) se configura la resolución con la que


el dispositivo va adquirir los datos, si se habilitará la entrada de datos bajo el
protocolo DAISY, si estará o no disponible la salida de reloj, y la frecuencia con
la que se van a tomar muestras de la data.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 128

Figura 3.46: Estructura del registro de CONFIG1 [31].

Figura 3.47: Configuración detallada del registro CONFIG1 [31].

Registro de Configuración 2
En este registro (Figuras 3.48 y 3.49) se configura si la frecuencia de muestreo
del Wilson Central Terminal WCT es variable o fija, se puede configurar el uso de
una señal de prueba para que sea generada de manera interna o que sea tomada
de manera externa, además se puede configurar la amplitud de la señal de prueba
generada internamente, ası́ como la frecuencia de la misma.

Figura 3.48: Estructura del registro de CONFIG2 [31].


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 129

Figura 3.49: Configuración detallada del registro CONFIG2 [31].

Registro de Configuración 3
En este registro (Figuras 3.50 y 3.51) se configura el estado del buffer de re-
ferencia del powerdown, la referencia de voltaje de la medición y varias opciones
asociadas a la señal del Righ Leg Drive (RLD).

Figura 3.50: Estructura del registro de CONFIG3 [31].


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 130

Figura 3.51: Configuración detallada del registro CONFIG3 [31].

Registro de configuración 4
Este registro se encarga de la configuración del control del Lead Off o detección
de mala conexión del lead, aunque está considerada su escritura en el código, el
driver no considera esta detección de Lead Off.
Registros de configuración de los canales CHnSET[1-8]
Para configurar los canales, existe un registro asociado a cada canal, en estos
registros tenemos: la opción de encender o apagar un canal, configurar su ganancia,
configurar el tipo de señal que tendremos en ese canal (señal externa, señal de
prueba, temperatura, medición de los niveles de voltaje de alimentación).

Figura 3.52: Estructura de los registros asociados a la configuración de los


canales de adquisición CHnSET [31].
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 131

Figura 3.53: Configuración detallada de los registros CHnSET [31].

Existen muchos otros registros de configuración en el AFE sin embargo estos


no forman parte de las rutinas desarrolladas para el control del AFE. A pesar de
que estos pueden ser configurados desde la aplicación no serán detallados en este
documento, pero se puede consultar estas y otras caracterı́sticas en [31].
Comandos Opcode
El ADS1298 se controla y configura a partir de comandos opcode o códigos
de operación sencillos para las ordenes como: RESET, START, STOP ... o com-
puestos en el caso de las operaciones de lectura y escritura. Los comandos son
enviados desde el dispositivo de control (en este caso el PIC18F4620) por medio
de la interfaz SPI hasta el AFE. Estos se listan y explican a continuación:

ˆ WAKEUP: Hace que el dispositivo salga del modo de reposo o standby.

ˆ STANDBY: Hace que el dispositivo entre en el modo STANDBY, en este


modo todas las partes del circuito son apagadas exceptuando las asociadas
a las referencias de voltaje.

RESET: Este comando resetea el ciclo de filtrado de, hace que todos los
registros de configuración vuelvan a sus valores por defecto.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 132

ˆ START: Este comando inicia la conversión de datos. El pin de START debe


estar en low para controlar las conversiones por comando. Si la conversión
esta en progreso este comando no tiene efecto.

ˆ STOP: Este comando detiene la conversión la señal de inicio debe estar en


bajo para controlar las conversiones por medio de este comando. Cuando es
enviado las conversiones en progreso se completan y las futuras conversiones
son detenidas hasta que se envie una señal de inicio.

ˆ RDATAC: Este comando habilita la lectura de data de manera continua


como se muestra en la Figura 3.54. Los datos son capturados cada vez que
la señal DRDY baja (cuando hay datos disponibles) sin necesidad del en-
vió consecutivo de comandos de lectura, para detener la adquisición de data
continua podemos usar el comando STOP o SDATAC (detención de la ad-
quisición continua).

Figura 3.54: Comportamiento de la interfaz SPI bajo la acción del comando


RDATAC [31].

ˆ SDATAC: Detiene la adquisición de datos de manera continua.

ˆ RDATA: Con este comando se hace la adquisición de un único bloque de


datos, luego de que la señal DRDY baja indicando cando la conversión del
bloque de datos se detiene la adquisición (como si se hubiera enviado el
comando SDATAC) como se observa en la figura 3.55.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 133

Figura 3.55: Comportamiento de la interfaz SPI bajo la acción del comando


RDATA [31].

Comandos compuestos: La decodificación de cada comando enviado al AFE


tarda 4tclk (ciclos de reloj) en decodificar y ejecutar, al enviarse comandos com-
puestos por varios bytes se requieren 4tclk por cada bytes u opcode si la frecuencia
de reloj es 2.048MHz el tiempo de decodificación serian 1.96µs.

ˆ RREG: Este comando efectua la lectura de la data contenida en un registro,


este es un comando compuesto por dos bytes. El primero contiene el comando
y la dirección del registro a leer y el segundo la cantidad de registros a leer
a continuación del anterior. La estructura es la siguiente:

Primer byte del opcode 001 x xxxx


donde x xxxx es el registro inicial de lectura .
Segundo byte del opcode 000 y yyyy
donde y yyyy es el numero de registros a leer a
,→ partir del primero - 1.

En la Figura 3.56 se puede observar el comportamiento de la interfaz SPI


bajo este comando:
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 134

Figura 3.56: Comportamiento de la interfaz SPI bajo la acción del comando


RREG [31].

ˆ WREG: Comando de escritura de datos en un registro. El comando WREG


es un comando de dos bytes, el primer byte contiene el comando y el registro
inicial, el segundo byte contiene la cantidad de registros subsecuentes a ser
escritos (contados desde 0).

Primer byte del opcode 010 x xxxx


donde x xxxx es el registro inicial de
,→ escritura .
Segundo byte del opcode 000 y yyyy
donde y yyyy es el numero de registros a
,→ escribir a partir del primero - 1.

A continuación se puede observar el comportamiento de la interfaz SPI bajo


este comando:

Figura 3.57: Comportamiento de la interfaz SPI bajo la acción del comando


WREG [31].
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 135

3.17.2. Ciclo de operación descrito por el fabricante


En la hoja de datos del ADS1298 se muestra un diagrama de flujos que describe
la configuración básica para el AFE para capturar datos, como el que se muestra
en la Figura 3.58:

Figura 3.58: Flujograma de captura y operación del ADS1298 [31].


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 136

El montaje utilizado para el desarrollo del driver está implementado como se


muestra en las Figuras y 3.59:

Figura 3.59: Plataforma auxiliar.

El proceso de captura de datos mediante el ADS1298 puede ser dividido en 4


etapas claves las cuales se describen a continuación:

ˆ Secuencia de reinicio: Al efectuar la secuencia de reinicio nos aseguramos


de llevar el AFE a una configuración por defecto y eliminar cualquier con-
figuración remanente cargada a los registros de configuración. En el manual
del ADS1298 [31] se describe el procedimiento; a continuación se muestra la
implantación de esta secuencia a nivel de código:
unsigned char ADS1298_PowerUp () {
unsigned int i = 0;

/* Bring the PWR pin HIGH to turn on the


,→ device */
ADS1298_PWR_PIN = 1;
for ( i = 0; i < 50000; i ++) {}

/* Reset the device by toggling the RESET pin */


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 137

ADS1298_RESET_PIN = 0;
for ( i = 0; i < 500; i ++) {} // wait at least 18
,→ shift clock cycles
ADS1298_RESET_PIN = 1;
for ( i = 0; i < 500; i ++) {} // wait at least 18
,→ shift clock cycles

/* Reset the device by issuing the RESET


,→ opcode */
/* change */
CommADS1298_CS1_PIN = 0;
ADS1298_WriteSingleOpCode ( ADS1298_RESET ) ;
CommADS1298_CS1_PIN = 1;
for ( i = 0; i < 500; i ++) {} // wait at least 18
,→ shift clock cycles

/* Stop the read data continuously mode ( SDATAC )


,→ */
/* change */
CommADS1298_CS1_PIN = 0;
ADS1298_WriteSingleOpCode ( ADS1298_SDATAC ) ;
CommADS1298_CS1_PIN = 1;
for ( i = 0; i < 50; i ++) {} // wait at least 4
,→ shift clock cycles

/* Stop the data conversion ( STOP ) */


ADS1298_START_PIN = 0;
for ( i = 0; i < 50; i ++) {} // wait at least 4
,→ shift clock cycles

return 1;
}
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 138

ˆ Ajuste de los registros de configuración: Los registros de configuración


deben ser cargados de manera que coincida con la configuración deseada. En
este caso usaremos una señal externa, que será muestreada en el modo de
alta resolución a 1KS/s, la referencia de voltaje VREFP se configura a 4V
y no se utiliza ninguna configuración para RLD, WCT o LOFF.
unsigned char ADS1298_RegistersForTesting ( unsigned
,→ char * channels ) {
unsigned char writeVals [25] = {0 , 0 , 0 , 0 ,
,→ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
,→ 0 , 0 , 0 , 0 , 0 , 0};

/* Define the common register values to


,→ write */
/* CONFIG1 */ writeVals [0] = 0 x86 ; //
,→ ADS1298_CONFIG1_HR | ADS1298_CONFIG1_DR_1K ; //
,→ 0 x83
/* CONFIG2 */ writeVals [1] = 0 x00 ; //
,→ ADS1298_CONFIG2_WCTCHOPCONST |
,→ ADS1298_CONFIG2_INTTEST |
,→ ADS1298_CONFIG2_TESTAMP |
,→ ADS1298_CONFIG2_TESTFREQ_AC20 ;//35
/* CONFIG3 */ writeVals [2] = 0 xC0 ; //
,→ ADS1298_CONFIG3_INTREFEN | (0 b1u << 6) ;
/* LOFF */ writeVals [3] = 0 x00 ;
/* CHXSET */ // channel settings in
,→ index values 4 to 11
/* RLD_SENSP */ writeVals [12] = 0 x00 ;
/* RLD_SENSN */ writeVals [13] = 0 x00 ;
/* LOFF_SENSP */ writeVals [14] = 0 x00 ;
/* LOFF_SENSN */ writeVals [15] = 0 x00 ;
/* LOFF_FLIP */ writeVals [16] = 0 x00 ;
/* LOFF_STATP */ writeVals [17] = 0 x00 ;
/* LOFF_STATN */ writeVals [18] = 0 x00 ;
/* GPIO */ writeVals [19] = 0 x00 ;
/* PACE */ writeVals [20] = 0 x00 ;
/* RESP */ writeVals [21] = 0 x00 ;
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 139

/* CONFIG4 */ writeVals [22] = 0 x00 ;


/* WCT1 */ writeVals [23] = 0 x00 ;
/* WCT2 */ writeVals [24] = 0 x00 ;

/* Write the standard configuration registers */


ADS1298_WriteRegisters (1 , ADS1298_CONFIG1 , 4 ,
,→ writeVals ) ;
// ADS1298_WriteRegisters (2 , ADS1298_CONFIG1 , 4 ,
,→ writeVals ) ;

/* Set the channels */


ADS1298_SetChannels ( channels ) ;

return 1;
}

Para configurar los registros se utiliza la variable channels[0]. Es una variable


unsigned char que nos permite seleccionar los canales que deseamos encender
o apagar, en este caso de ejemplo, se utiliza un solo canal para seleccionarlo
y configurar la variable channels[0] = 0b01000000 indicando que se utilizara
el canal 2. El canal 1 en el montaje de la plataforma elaborado por Cruz va
a la derivación V6 de los electrodos pectorales y al no haberse configurado
WCT la data del canal 1 no tendrı́a sentido.
void ADS1298_SetChannels ( unsigned char *
,→ channels ) {
unsigned char writeVals [8] = {0 , 0 , 0 , 0 , 0 , 0 ,
,→ 0 , 0};
unsigned char j ;

/* Iterate through the 8 channels of one


,→ device */
for ( j = 0; j < 8; j = j + 1) {
/* Define the register values for
,→ the channel settings */
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 140

if ((( channels [0] >> (7 - j ) ) & 0 x01


,→ ) == 0 x01 ) { // turn channel on
// writeVals [ j ] =
,→ ADS1298_CHSET_GAIN_12 | ADS1298_CHSET_MUX_TEST
,→ ;
writeVals [ j ] = ADS1298_CHSET_GAIN_8 |
,→ ADS1298_CHSET_MUX_ELEC ;

}
else { // turn channel off
writeVals [ j ] =
,→ ADS1298_CHSET_PD | ADS1298_CHSET_MUX_SHORT ;
}
}

/* Send the register values */


ADS1298_WriteRegisters (1 , ADS1298_CH1SET , 8 ,
,→ writeVals ) ;

/* Compute the new frame size */


ADS1298_ComputeFrameSize () ;
}

Una vez cargados los registros con los valores necesarios se pueden verifi-
car haciendo una lectura de los mismos, o mediante el analizador lógico al
momento que son cargados. Las Figuras 3.60 y 3.61 muestran los valores
cargados mediantes ambos métodos.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 141

Figura 3.60: Registros configurados del ADS1298 vistos desde MPLAB me-
diante el ICD3 activando la depuración en circuito.

Figura 3.61: Registros configurados del ADS1298 vistos desde Logic2 mediante
el analizador lógico.

ˆ Inicio de la adquisición: El programa de Meng sólo toma los primeros


8 bits de data de un único canal (descartando el status) haciendo que la
resolución de la data pasara de 24 a 8 bits y los enviaba a un analizador
lógico. En la versión elaborada para este proyecto se aprovechan los 24 bits
de la data de los 2 canales (en caso de estar activos ambos a la vez) que no
dependen del la señal WCT.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 142

C18 cuenta con unas librerı́as para el manejo de números flotantes sin embar-
go algunas funciones como printf no funcionan adecuadamente con este tipo
de datos. Como en principio el objetivo de hacer este driver era el conoci-
miento en detalle ADS1298 para una futura implementación en la plataforma
de desarrollo principal (PICO-PI-IMX7D), no se reparó en la salida de los
datos si no en el funcionamiento; de hecho para valores decimales menores
a 0.01 el programa puede presentar problemas en la representación. Una se-
gunda aproximación a considerar fue el envı́o de data cruda para su posterior
conversión e impresión. Las funciones utilizadas se muestran a continuación.

ˆ Rutina de formateo de data en flotantes


unsigned char dataframe ( unsigned char * dummy ,
,→ unsigned float * data , int length , unsigned
,→ char * channels , unsigned char ALG ) {
if ( channels [0]==0 b01000000 ) {
unsigned char i =9;
unsigned short long aux [3];
aux [0]= (0 x000000 | dummy [i -3]) ;
aux [0]=(( aux [0]) < <16) ;
aux [1]=(0 x000000 | dummy [i -2]) ;
aux [1]=( aux [1] < <8) ;
aux [2]= dummy [i -1];
aux [0]= aux [0]| aux [1]| aux [2];
aux [0]= aux [0] ^ 0 x800000 ;
data [0]= (( aux [0] -0 b1 ) * Vref * LSB ) / GAIN ;
return 1;
}
if ( channels [0]==0 b01100000 ) {
unsigned char i =12;
unsigned short long aux [6];
aux [0]= (0 x000000 | dummy [i -6]) ;
aux [0]=(( aux [0]) < <16) ;
aux [1]=(0 x000000 | dummy [i -5]) ;
aux [1]=( aux [1] < <8) ;
aux [2]= dummy [i -4];
aux [0]= aux [0]| aux [1]| aux [2];
aux [0]= aux [0] ^ 0 x800000 ;
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 143

data [0]= (( aux [0] -0 b1 ) * Vref * LSB ) / GAIN ;


aux [3]= (0 x000000 | dummy [i -3]) ;
aux [3]=(( aux [3]) < <16) ;
aux [4]=(0 x000000 | dummy [i -2]) ;
aux [4]=( aux [4] < <8) ;
aux [5]= dummy [i -1];
aux [3]= aux [3]| aux [4]| aux [5];
aux [3]= aux [3] ^ 0 x800000 ;
data [1]= (( aux [3] -0 b1 ) * Vref * LSB ) / GAIN ;
if ( ALG ) {
data [2]= data [1] - data [0];
return 3;
}
else {
return 2;
}
}

ˆ Rutina de formateo data cruda

void data_print ( unsigned char * data , int dl ) {


int i =0 , j =0;
long int entero , decimal ;

printf ( " %u %u %u \ r \ n " , data [6] , data [7] , data [8])


,→ ;
}

ˆ Manejo de la data capturada: La data capturada es enviada por la in-


terfaz UART del microcontrolador al ordenador y mediante el programa de
captura serial RealTerm (Figura 3.62) es almacenada en un archivo de tex-
to, con un formato CSV (valores separados por comas). Luego la data es
graficada con alguna herramienta de como Excel o Kst2.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 144

Figura 3.62: Lectura y captura de datos a partir de la consola serial de Real-


Term mediante la interfaz serial.

3.17.3. Elaboración del Driver


Para el desarrollo del driver se tuvieron que tomar en cuenta un conjunto
de señales involucradas en el proceso de control del dispositivo (Figura 3.63).
Estas fueron a su vez configuradas en la interfaz de captura del analizador lógico;
instrumento que fue sumamente útil para observar en detalle como operaba el
código sirviendo como herramienta de depuración. Las señales utilizadas fueron
configuradas en la herramienta [37] bajo los siguientes nombres y colores:

Figura 3.63: Señales utilizadas para la elaboración del driver, configuradas en


Logic2.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 145

La PICDEM Z cuenta con un sensor de temperatura TC77 que envı́a datos de


manera continua mediante la interfaz SPI. La señal del CS para este integrado
debe ser tomada en cuenta en el desarrollo del driver debido a que en caso de no
poner en alto, el pin RA2 del microcontrolador durante la ejecución del driver este
dispositivo siempre ocuparı́a la interfaz SPI.
En el manejo de la señal de DRDY no fue detectada de manera correcta por el
microcontrolador y por lo tanto la lectura de data no se hacı́a, dado a que el pro-
grama entraba en un bucle “infinito”, esperando que la señal cambiara al estado
debido. El problema ocurrı́a debido a que el pin tomaba por defecto la configura-
ción analógica a pesar de haber configurado previamente el pin como una entrada
digital. Se trabajo sobre la hipotesis de que el problema se debı́a a los pull ups,
sin embargo, el problema se solucionó haciendo el registro ADCON 1 = 0X0F ;
forzando a todos los pins análogo digitales del microcontrolador a comportarse
como digitales.
La velocidad del reloj del microcontrolador resultó otra limitante, debido a
que la rutina de adquisición se ejecutaba en tiempos muchos mayores que los
necesarios para las frecuencias de muestreo esperadas. Por ejemplo, para obtener
un muestreo de mil muestras por segundo es necesario que cada dato sea procesado
en un intervalo de tiempo 1ms > tadquisicion , sin embargo aun con los PLL activos
para llevar la frecuencia de trabajo 32 MHz las rutina se ejecutaba en tiempos
cercanos a los 3 ms.
Por otro lado, activar los PLL inplicó cambiar la tasa de baudios de la interfaz
UART ya que esta configuración depende de la frecuencia de reloj del microcon-
trolador, pasando de 115200 baudios a 38400 baudios. Lo que para transmitir la
información de todos los canales (si este fuera el caso) se tendrı́an problemas de
transmisión.
Se observaron también diferencias entre los marcos de data obtenidos en el
modo de adquisición continua, entre: los registrados por el debugger y los obser-
vados con el simulador lógico; la solución a esto queda pendiente para una futura
investigación.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 146

3.18. Implementación de un Driver para Con-


trolar el BMD101 mediante la PICO-PI-
IMX7
Dado al hecho de que no se podrı́a utilizar la interfaz SPI de la plataforma de
trabajo principal de la manera que se pretendı́a en el plateamiento inicial (con el
núcleo M4), se optó por una alternativa de AFE que permitiera utilizar otra de
las interfaces de comunicación disponibles para el ARM Cortex-M4, por lo que se
decidió utilizar un dispositivo serial. Ya que se determinó en la adquisición de data
utilizando la interfaz serial, resultarı́a en una complementación sencilla a nivel de
código.

3.18.1. BMD101
El módulo ECG 4 Click de MikroeEktronika basado en el AFE BMD101 de
Neurosky es un dispositivo que permite efectuar la adquisición de un canal ECG
con una resolución de 16 bits a una frecuencia de muestreo de 512 S/s. Este
dispositivo una vez energizado y con sus señales de control (Reset y LDO) en
su estado de operación empieza a adquirir la señal que tenga a su entrada. La
comunicación con el dispositivo de control es a partir de una interfaz UART con
una tasa de 57600 bps.
En las Figuras 3.64 y 3.65 se muestran la vista superior e inferior del dispositivo:

Figura 3.64: Módulo ECG 4 Click Vista Superior [32].


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 147

Figura 3.65: Módulo ECG 4 Click Vista Inferior [32].

El driver de este dispositivo no cuenta con una etapa que configure los paráme-
tros de operación del dispositivo como en el caso estudiado en la sección anterior.
El driver diseñado puede verse como un driver de dos entornos o también como
dos drivers independientes trabajando en conjunto. La imagen firmware cargada
al núcleo M4 recoge la data emitida por el AFE, la formatea y la envı́a mediante
RPMsg (a través de la memoria compartida) al segundo entorno (el entorno de
los ARM Cortex-A7). La data será recibida por un módulo imx rpmsg tty.ko que
opera en el espacio de kernel, este crea un archivo con los valores recibidos, luego
con alguna aplicación en el espacio de usuario como Kst2 se pueden graficar estos
datos en tiempo real, o se puede utilizar la plataforma como un servidor desde el
cual distintos usuarios puedan consultar la data.

3.18.2. Driver implementado


El driver que se implementó para el núcleo M4 espera un mensaje del lado
master (entorno de operación de los núcleos A7) para empezar a procesar datos
del AFE. Luego este, según el tipo de datos (si es data de los electrodos, data de
la frecuencia cardı́aca o la calidad de la conexión de los electrodos), envı́a la data
capturada al entorno Linux donde es atendida por el módulo imx rpmsg tty.ko, o
desplega información por la consola serial de debugging.
El AFE BMD101 de Neurosky tiene una salida de datos que se estructura como
en la Figura 3.66:
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 148

Figura 3.66: Estructura de la salida de datos del BMD101 [32].

Los paquetes son enviados como un stream serial de bytes. Cada paquete inicia
y termina con un header, seguido con su carga útil de datos y terminando con
un CRC (check sum byte). El encabezado del paquete consiste de 3 bytes; 2 de
sincronización SYNC (0xAA, 0xAA), seguidos por la longitud de la carga útil
PLENGTH. Los 2 SYNC bytes son utilizados para señalar la nueva llegada de
paquetes, el byte de PLENGTH indica la longitud en bytes de la carga útil del
paquete.
La carga útil de datos no debe ser interpretada hasta que no se verifique la
integridad de los paquetes, esto se hace mediante el CRC. La verificación se realiza
de la siguiente manera:

1. Se suman todos los bytes de la carga util (payload ).

2. Se toman los 8 bits inferiores de la suma.

3. Se realiza una inversión o complemento a uno de estos bits.

4. Se compara el valor obtenido con este algoritmo con el presente en el bloque


de datos.

5. Si el CRC calculado no coincide con el valor contenido en el bloque, el bloque


deberá ser descartado.

Formato del payload o carga útil

La carga útil de datos consiste en una serie continua de datos, convertir la


carga útil de datos implica convertir cada una de esas hileras de datos hasta que
todos los bytes de carga útil sean convertidos. Una fila de datos consiste de bytes
dispuestos en el formato mostrado en la Figura 3.67.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 149

Figura 3.67: Estructura del payload del BMD101 [32].

La fila de datos empieza con cero o con valores EXCODE. Estos son bytes con
valor 0x55, su presencia indica el nivel de código extendido; mientras más valores
0x55 sean recibidos es mayor el nivel de código extendido. El nivel de código
extendido se utiliza en conjunto con el byte de CODE para determinar el tipo de
datos de esa hilera.
El byte de CODE indica el tipo de data codificada en la hilera de datos, en la
Tabla 3.2 a continuación se exponen los diferentes valores posibles, y la longitud
vLength en cada caso.

Tabla 3.2: Tipos de datos de salida BMD101 [32]

Nivel de código Extendido [CODE] [vLength] Tipo de dato recibido


0 0x02 N/A SQ; 0=LOFF ;200 =OK
0 0x03 N/A Frecuencia Cardı́aca
0 0x08 N/A X
0 0x80 2 16 bits ECG data C2
0 0x84 5 X
0 0x85 3 X

Nota: C2 es usado para expresar que la data está en su complemento a 2, SQ


=Signal Quality.
El algoritmo de conversión de un paquete se describe a continuación:

1. Mantener las lecturas de byte desde el stream hasta un byte de SYNC (0xAA)
es encontrado.

2. Leer el siguiente byte y asegurarse de que esté también un byte de SYNC (si
no, volver al paso 1).
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 150

3. Leer el byte PLENGTH.

4. Se chequea la integridad de los datos mediante el algoritmo de checksum co-


mentado previamente. Si el check sum calculado no coincide con el capturado
en el bloque regresar al punto 1.

5. Analizar uno a uno los bytes de la carga útil:

a) Analizar el primer byte del payload, esto puede ser un EXCODE o


CODE.
b) En caso de ser un CODE debemos analizar el tipo de datos del que se
trata y manejarlo de la manera correspondiente.

Firmware del núcleo M4

Una vez analizado el algoritmo ser realizó su implementación, para esto se


partió del ejemplo str echo freertos de los ejemplos de TechNexion para el uso de
FreeRTOS en sus plataformas [63]. El cual se modificó, para capturar los bloques
de datos de la salida del BMD101, en la Figura 3.68 se puede observar un diagrama
de flujos que describe la operación del driver que opera en el núcleo M4.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 151

Figura 3.68: Diagrama de flujo del algoritmo Driver.


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 152

La señal de inicio que envı́a el lado master es transmitida mediante el terminal


de Ubuntu al igual que la señal que permite cambiar el estado del GPIO asociado a
la señal de Reset del BMD101. El código implementado se muestra a continuación
y se puede en contrar en [82].
Inclusión de librerias
# include " rpmsg / rpmsg_rtos . h "
# include " FreeRTOS . h "
# include " task . h "
# include " semphr . h "
# include " string . h "
# include " board . h "
# include " mu_imx . h "
# include " debug_console_imx . h "
# include " uart_imx . h "
# include < stdio .h >
# include < stdlib .h >

Aquı́ se incluyen las librerı́as necesarias para el funcionamiento del programa.


Estas librerı́as proporcionan funciones y definiciones para el uso de RPMsg: FreeR-
TOS, manejo de tareas, semáforos, manipulación de strings, configuración de los
recursos asociados al núcleo M4, manejo del hardware UART y otras utilidades
estándar. Estas forman parte de la estructura BSP.
Definición de constantes y variables globales

Definiciones par RTOS


# define APP_TASK_STACK_SIZE 256
# define APP_MU_IRQ_PRIORITY 3

// Definiciones para RPMsg


static char app_buf [512];
# define BUFFER_SIZE 16
uint8_t dataBuffer [ BUFFER_SIZE ];

// Definiciones para el driver


# define SYNC_BYTE 0 xAA
# define EXCODE_BYTE 0 x55
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 153

unsigned char receivedByte ;


unsigned char payload [256];
int payloadLength ;
unsigned char checksum ;
unsigned char crc ;
unsigned char excodeCount ;
unsigned char code ;
unsigned char length ;
unsigned char data [256];
int dataIndex ;

En esta sección se definen constantes, como el tamaño de la pila de tareas


APP TASK STACK SIZE de FreeRTOS, la prioridad de la interrupción APP
MU IRQ PRIORITY, para trabajar con el protocolo RPMsg. Se define también
el tamaño del buffer de aplicación y de datos al igual que los arreglos con los que
se implementan estos buffers, y por último variables globales y constantes que son
necesarias para el manejo de la salida del AFE BMD101.
Prototipos de funciones
static void UART_ReceiveDataPolling ( void * base , uint8_t
,→ * rxBuff , uint32_t rxSize ) ;
unsigned char calculateChecksum ( unsigned char * data , int
,→ length ) ;
char * handleData ( unsigned char excodeCount , unsigned
,→ char code , unsigned char length , unsigned char *
,→ data ) ;

En esta sección se declaran prototipos de funciones que serán utilizadas más


adelante, como las funciones de envió y recepción por la interfaz UART, la función
que realiza el cálculo del checksum (mediante el algoritmo explicado anteriormente)
y la función handleData que analiza y maneja los datos enviados por el módulo
AFE.
Luego tenemos la función StrEchoTask(∗pvParameters). Esta es la función prin-
cipal del programa, y es la tarea que se ejecutará cuando se inicie el sistema opera-
tivo FreeRTOS. Es aquı́ donde ocurre el procesamiento de los datos recibidos por
la interfaz UART y se envı́an las respuestas adecuadas al master y a la consola de
debugging (en la etapa de depuración).
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 154

static void StrEchoTask ( void * pvParameters )


{
int result ;
struct remote_device * rdev = NULL ;
struct rpmsg_channel * app_chnl = NULL ;
void * rx_buf ;
int len ;
unsigned long src ;
unsigned long size ;
void * tx_buf ;
PRINTF ( " \ r \ nUniversidad Simon Bolivar \ r \ n " ) ;
PRINTF ( " \ r \ nPor : Rommel Contreras / USB 14 -10242\ r \ n
,→ " ) ;
PRINTF ( " \ r \ nDriver Serial BMD101 \ r \ n " ) ;
...

Esta primera sección de la función crea algunas variables locales necesarias para
el funcionamiento de la comunicación IPC RPMsg, y presenta la información de
la aplicación en la consola de debugging.
result = rpmsg_rtos_init (0 , & rdev , RPMSG_MASTER , &
,→ app_chnl ) ;
assert ( result == 0) ;

result = rpmsg_rtos_recv_nocopy ( app_chnl - > rp_ept , &


,→ rx_buf , & len , & src , 0 xFFFFFFFF ) ;
assert ( result == 0) ;

assert ( len < sizeof ( app_buf ) ) ;


memcpy ( app_buf , rx_buf , len ) ;
app_buf [ len ] = 0;

En esta sección se hace la inicialización del protocolo RPMsg y se sincroniza


con el núcleo opuesto. En este caso el núcleo M4 actúa como esclavo dejando al
procesador A7 opuesto como master, estableciéndose un canal de comunicación
RPMsg (app chn1 ). Luego el programa espera recibir un mensaje mediante la
función rpmsg rtos recv nocopy, en el momento que se reciba un mensaje, se copia
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 155

en el buffer app buf, este mensaje en el diagrama de flujo del algoritmo driver
(Figura 3.68) es marcado como la señal de inicio.
El siguiente proceso se corresponde al búcle infinito donde ocurre la recepción
y procesamiento de datos, siguiendo los pasos descritos en el algoritmo.
for (;;) {
do {
UART_ReceiveDataPolling (
,→ BOARD_DEBUG_UART_BASEADDR , & receivedByte , 1) ;
} while ( receivedByte != SYNC_BYTE ) ;

UART_ReceiveDataPolling ( BOARD_DEBUG_UART_BASEADDR , &


,→ receivedByte , 1) ;
if ( receivedByte != SYNC_BYTE ) {
continue ;
}

UART_ReceiveDataPolling ( BOARD_DEBUG_UART_BASEADDR , &


,→ receivedByte , 1) ;
payloadLength = receivedByte ;

for ( int i = 0; i < payloadLength ; i ++) {


UART_ReceiveDataPolling (
,→ BOARD_DEBUG_UART_BASEADDR , & receivedByte , 1) ;
payload [ i ] = receivedByte ;
}

checksum = calculateChecksum ( payload , payloadLength )


,→ ;

UART_ReceiveDataPolling ( BOARD_DEBUG_UART_BASEADDR , &


,→ receivedByte , 1) ;
crc = receivedByte ;
if ( crc != checksum ) {
continue ;
}
...
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 156

En esta sección del bucle el programa realiza las siguientes acciones:

ˆ Espera recibir dos SYNC BYTE consecutivos para sincronizar la comunica-


ción UART.

ˆ Lee el byte siguiente, que representa la longitud del payload que se va a


recibir (payloadLength).

ˆ Lee el payload completo a través de UART y lo almacena en el arreglo


payload.

ˆ Calcula el checksum de los datos recibidos y lo compara con el byte CRC


recibido para verificar la integridad de los datos.

Una vez verificada la integridad de los datos, el programa procede a procesar


el resto de los datos recibidos.
Procesamiento de los datos recibidos
int index = 0;
while ( index < payloadLength ) {
excodeCount = 0;
while ( payload [ index ] == EXCODE_BYTE ) {
excodeCount ++;
index ++;
}

code = & payload [ index ];


index ++;

length = 0;
if (* code == 0 x80 ) {
length = payload [ index ];
index ++;
dataIndex = 0;
for ( int i = 0; i < length ; i ++) {
data [ dataIndex ] = payload [ index ];
dataIndex ++;
index ++;
}
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 157

} else if (* code == 0 x03 ) {


data [0] = payload [ index ];
index ++;
PRINTF ( " \ r \ nHEART RATE : %d Bpm \ r \ n " , data
,→ [0]) ;
} else if (* code == 0 x02 ) {
data [0] = payload [ index ];
index ++;
unsigned char signalQuality = data [0];
PRINTF ( " \ r \ n ** Calidad de la senal **\ r \ n " ) ;
PRINTF ( " \ r \ nSQ= %d \ n \ r " , data [0]) ;
if ( signalQuality == 200) {
PRINTF ( " \ n \ rSensor ON \ n \ r " ) ;
}
if ( signalQuality == 0) {
PRINTF ( " \ n \ rSensor OFF LOFF \ n \ r " ) ;
}
}
}
...

En esta parte, el programa interpreta los datos recibidos desde el dispositi-


vo BMD101 que se encuentran en el payload. Los datos están estructurados en
paquetes con diferentes códigos (code) y longitudes (length).
El bucle while en el bloque anterior procesa los datos y actualiza las variables
excodeCount, code, length, y data con la información correspondiente. Estos datos
serán utilizados más adelante para generar una respuesta adecuada a través de
RPMsg.
Función handelData:
char * frame = handleData ( excodeCount , code , length ,
,→ data ) ;
tx_buf = rpmsg_rtos_alloc_tx_buffer ( app_chnl - > rp_ept
,→ , & size ) ;
assert ( tx_buf ) ;

len = strlen ( frame ) ;


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 158

memcpy ( tx_buf , frame , len ) ;

result = rpmsg_rtos_send_nocopy ( app_chnl - > rp_ept ,


,→ tx_buf , len , src ) ;
assert ( result == 0) ;

free ( frame ) ;
}

En esta parte, se llama a la función handleData para procesar los datos recibidos
y generar una respuesta adecuada en forma de una cadena de caracteres (frame).
Luego, se asigna un buffer de transmisión (tx buf) para enviar la respuesta a través
de RPMsg. Finalmente, se envı́a la respuesta utilizando rpmsg rtos send nocopy
y se libera el almacenamiento de frame.
A continuación puede observarse la implementación de la función handleData
basada en el algoritmo de conversión de datos del AFE BMD101 discutido ante-
riormente:
char * handleData ( unsigned char excodeCount , unsigned
,→ char * code , unsigned char length , unsigned char *
,→ data ) {
// Data de los Electrodos
if (* code == 0 x80 ) {

// Combine the two bytes of data into a 16 - bit


,→ signed integer
short int rawValue = ( data [0] << 8) | data [1];

// Convert the raw value to its two ’s complement


,→ representation if necessary

char * string = ( char *) malloc (10 * sizeof ( char ) ) ;


sprintf ( string , " %d \ r \ n " , rawValue ) ;
return string ;

}
}
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 159

En el código, no se listan los directorios asociados al BSP, estos pueden ser


consultados accediendo a alguno de los ejemplos comentados anteriormente.
Luego de hacer la inclusión de las librerı́as, las variables, constantes y prototi-
pos de funciones necesarias, está la función StrEchoTask. Dicha función, luego de
definir ciertos elementos que serán utilizados a lo largo de su ejecución, imprime
los diálogos de presentación de la aplicación; estos aparecen una vez que se ejecuta
el programa. Luego al instalar el módulo, que servirá de driver en el entorno del
master se desplega la siguiente información:
El reconocimiento del servicio de nombre se ha
,→ completado , el Cortex - M4 ha configurado un canal
,→ rpmsg channel [1 ---> 1024]

Al desplegarse esta lı́nea hemos establecido un canal de comunicación entre el


entorno Linux y FreeRTOS.

3.18.3. Módulo kernel Linux A7


La contraparte de este código es atendida por el módulo que instalamos en el
sistema operativo Ubuntu. El módulo desarrollado es una modificación del módulo
imx rpmsg tty adaptada para recibir los datos formateados por el núcleo M4 y
guardarlos en un archivo para su posterior consulta o graficación. El archivo tiene
una capacidad máxima y funciona como un buffer circular al alcanzar su capacidad
máxima.
# include < linux / slab .h >
# include < linux / delay .h >
# include < linux / kernel .h >
# include < linux / module .h >
# include < linux / rpmsg .h >
# include < linux / tty .h >
# include < linux / tty_driver .h >
# include < linux / tty_flip .h >
# include < linux / virtio .h >
# include < linux / fs .h >
# include < linux / file .h >
# include < linux / fcntl .h >
# define MAX_FILE_SIZE (2 * 1024 * 1024)
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 160

# define RPMSG_MAX_SIZE 256


# define MSG " hello world ! "

Esta sección incluye los encabezados necesarios para el desarrollo de un con-


trolador de dispositivo para comunicación a través de RPMsg utilizando TTY.
Además, se definen constantes, como MAX FILE SIZE, RPMSG MAX SIZE y
MSG.
struct rpmsgtty_port {
struct tty_port port ;
spinlock_t rx_lock ;
struct rpmsg_device * rpdev ;
struct tty_driver * rpmsgtty_driver ;
};

Se define una estructura llamada rpmsgtty port, que actúa como un envoltorio o
contenedor para un puerto TTY relacionado con el protocolo RPMsg en un entorno
especı́fico. Esta estructura encapsula los componentes necesarios para administrar
un puerto TTY basado en RPMsg.
static int rpmsg_tty_cb ( struct rpmsg_device * rpdev , void
,→ * data , int len ,
void *
,→ priv , u32 src )
{
struct rpmsgtty_port * cport = dev_get_drvdata (&
,→ rpdev - > dev ) ;
char * filename = " / samba / public / datos_rpmsg . txt "
,→ ;
struct file * file ;
mm_segment_t old_fs ;
loff_t pos ;
ssize_t written ;
loff_t file_size ;

if ( len == 0)
return 0;

spin_lock_bh (& cport - > rx_lock ) ;


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 161

file = filp_open ( filename , O_WRONLY | O_CREAT |


,→ O_APPEND , 0644) ;
if ( IS_ERR ( file ) ) {
dev_err (& rpdev - > dev , " Failed to open
,→ file : %s \ n " , filename ) ;
return PTR_ERR ( file ) ;
}

old_fs = get_fs () ;
set_fs ( KERNEL_DS ) ;

pos = 0;
written = kernel_write ( file , data , len , & pos ) ;
if ( written < 0) {
dev_err (& rpdev - > dev , " Failed to write to
,→ file : %s \ n " , filename ) ;
filp_close ( file , NULL ) ;
return written ;
}

set_fs ( old_fs ) ;
filp_close ( file , NULL ) ;

file = filp_open ( filename , O_RDONLY , 0) ;


if ( IS_ERR ( file ) ) {
dev_err (& rpdev - > dev , " Failed to open
,→ file : %s \ n " , filename ) ;
return PTR_ERR ( file ) ;
}

file_size = vfs_llseek ( file , 0 , SEEK_END ) ;


filp_close ( file , NULL ) ;

if ( file_size >= MAX_FILE_SIZE ) {


file = filp_open ( filename , O_WRONLY |
,→ O_CREAT | O_TRUNC , 0644) ;
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 162

if ( IS_ERR ( file ) ) {
dev_err (& rpdev - > dev , " Failed to
,→ open file : %s \ n " , filename ) ;
return PTR_ERR ( file ) ;
}
filp_close ( file , NULL ) ;
}

tty_flip_buffer_push (& cport - > port ) ;


spin_unlock_bh (& cport - > rx_lock ) ;

return 0;
}

Aquı́ comienza la implementación de la función rpmsg tty cb, que es el callback


que se llama cuando llega un mensaje a través del canal RPMsg establecido en el
controlador rpmsg tty driver. Esta función se encarga de guardar el contenido del
mensaje en un archivo llamado “datos rpmsg.txt”. La función opera de la siguiente
manera:

1. Se obtiene la estructura rpmsgtty port asociada al dispositivo RPMsg.

2. Se define la ruta del archivo donde se guardarán los datos recibidos a través
del canal RPMsg.

3. Se abre el archivo en modo escritura con la bandera O APPEND para agregar


datos al final. Si el archivo no existe, se crea con permisos 0644.

4. Se cambia el segmento de espacio de archivos.

5. Se cambia el segmento de espacio de archivos al espacio de datos del kernel


para permitir la escritura en el archivo.

6. Se utiliza kernel write para escribir los datos recibidos en el archivo.

7. Se restaura el valor del segmento de espacio de archivos a su estado original.

8. Se cierra el archivo después de escribir los datos.

9. Se abre el archivo en modo lectura para obtener su tamaño actual.


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 163

10. Si el archivo ha alcanzado o superado el tamaño máximo definido en MAX


FILE SIZE, se sobrescribe.

11. Se libera el mensaje del buffer del puerto TTY utilizando tty flip buffer push.

12. Se libera el bloqueo del puerto serie para permitir que otros procesos accedan
al puerto.

Se define una estructura llamada rpmsgtty port ops, que contiene las operacio-
nes para el puerto TTY relacionadas con el controlador RPMsg.
static struct tty_port_operations rpmsgtty_port_ops = {
,→ };
static int rpmsgtty_install ( struct tty_driver *
,→ driver , struct tty_struct * tty )
{
struct rpmsgtty_port * cport = driver - > driver_state ;
return tty_port_install (& cport - > port , driver , tty ) ;
}

static int rpmsgtty_open ( struct tty_struct * tty , struct


,→ file * filp )
{
return tty_port_open ( tty - > port , tty , filp ) ;
}

static void rpmsgtty_close ( struct tty_struct * tty ,


,→ struct file * filp )
{
return tty_port_close ( tty - > port , tty , filp ) ;
}

Se obtiene el puerto rpmsgtty port asociado con el dispositivo. TTY y el canal


RPMsg asignado; rpdev. Verifica que el buffer de entrada buf no sea nulo. Luego,
se envı́an los datos dividiéndolos en mensajes de tamaño fijo utilizando la función
rpmsg send. Si rpmsg send falla, la función devolverá el valor de retorno no nulo
de la llamada. Finalmente, la función devuelve el número total de bytes escritos.
Las siguientes son funciones auxiliares para la apertura y cierre del puerto TTY
en el controlador.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 164

static int rpmsgtty_write ( struct tty_struct * tty , const


,→ unsigned char * buf ,
int total )
{
int count , ret = 0;
const unsigned char * tbuf ;
struct rpmsgtty_port * rptty_port = container_of ( tty
,→ - > port ,

,→ struct rpmsgtty_port , port ) ;


struct rpmsg_device * rpdev = rptty_port - > rpdev ;

if ( buf == NULL ) {
pr_err ( " buf shouldn ’t be null .\ n " ) ;
return - ENOMEM ;
}

count = total ;
tbuf = buf ;
do {
ret = rpmsg_send ( rpdev - > ept , ( void *) tbuf ,
count > RPMSG_MAX_SIZE ?
,→ RPMSG_MAX_SIZE : count ) ;
if ( ret ) {
dev_err (& rpdev - > dev , " rpmsg_send failed : %d \
,→ n " , ret ) ;
return ret ;
}

if ( count > RPMSG_MAX_SIZE ) {


count -= RPMSG_MAX_SIZE ;
tbuf += RPMSG_MAX_SIZE ;
} else {
count = 0;
}
} while ( count > 0) ;
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 165

return total ;
}

1. La función recibe un puntero a la estructura tty struct que representa la


terminal TTY, un puntero al buffer de datos buf y el tamaño total total de
los datos a escribir.

2. Se verifica si el puntero buf es nulo. Si es ası́, se imprime un mensaje de error


y se devuelve el código de error ENOMEM, que indica un error de falta de
memoria.

3. Se inicializan las variables count y ret; count se utiliza para rastrear la canti-
dad de datos que quedan por enviar, y ret se utiliza para rastrear el resultado
de la llamada a rpmsg send.

4. Se obtiene un puntero al objeto rpmsgtty port que contiene la estructura


tty port y otros detalles relacionados con el puerto TTY. Esto se hace utili-
zando la macro container of para obtener el puntero rpmsgtty port a partir
del punto tty->port

5. Se obtiene el puntero al dispositivo RPMsg (rpdev) asociado al puerto TTY.

6. Se verifica si el puntero buf es nulo. Si es nulo, se devuelve un código de error


ENOMEM indicando que no hay suficiente memoria.

7. Se inicializa count con el valor total, que representa la cantidad total de


datos a escribir, tbuf se inicializa con el puntero buf para rastrear la posición
actual en el buffer de datos.

8. Se inicia un bucle do-while para enviar los datos a través del canal RPMsg
en fragmentos.

9. Se utiliza la función rpmsg send para enviar un mensaje al dispositivo remoto


a través del canal RPMsg. Se envı́a como máximo RPMSG MAX SIZE bytes
de datos en cada llamada a rpmsg send.

10. Si la llamada a rpmsg send tiene éxito, se disminuye la cantidad count por la
cantidad de bytes enviados y se avanza el puntero tbuf en la misma cantidad.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 166

11. Si la cantidad restante en count es mayor que RPMSG MAX SIZE, el bucle
continuará. Si es menor o igual, se establece count en cero para finalizar el
bucle.

12. El bucle continúa hasta que se hayan enviado todos los datos.

En resumen, la función rpmsgtty write se encarga de enviar los datos proporcio-


nados a través del canal RPMsg en fragmentos de tamaño máximo RPMSG MAX
SIZE. Utiliza la función rpmsg send para enviar cada fragmento y realiza un se-
guimiento del progreso utilizando las variables count y tbuf.
En la sección que se lista a continuación se defines las operaciones relacionadas
con el puerto TTY para el controlador. La función rpmsgtty write room simple-
mente devuelve el tamaño máximo del buffer de escritura, que en este caso es
RPMSG MAX SIZE. También se crea la estructura imxrpmsgtty ops que contine
las operaciones para instalar, abrir, cerrar y escribir en el puerto TTY, ası́ como
la función para obtener el espacio disponible en el buffer de escritura.
static int rpmsgtty_write_room ( struct tty_struct * tty )
{
return RPMSG_MAX_SIZE ;
}

static const struct tty_operations imxrpmsgtty_ops = {


. install = rpmsgtty_install ,
. open = rpmsgtty_open ,
. close = rpmsgtty_close ,
. write = rpmsgtty_write ,
. write_room = rpmsgtty_write_room ,
};

Le sigue la función rpmsg tty probe se llama cuando se detecta un nuevo dis-
positivo compatible con el controlador. cuyos pasos clave, son:
static int rpmsg_tty_probe ( struct rpmsg_device * rpdev )
{
int ret ;
struct rpmsgtty_port * cport ;
struct tty_driver * rpmsgtty_driver ;
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 167

dev_info (& rpdev - > dev , " new channel : 0 x %x -> 0 x %x !\ n "
,→ , rpdev - > src , rpdev - > dst ) ;

cport = devm_kzalloc (& rpdev - > dev , sizeof (* cport ) ,


,→ GFP_KERNEL ) ;
if (! cport )
return - ENOMEM ;

rpmsgtty_driver = tty_alloc_driver (1 ,
,→ TTY_DRIVER_UNNUMBERED_NODE ) ;
if ( IS_ERR ( rpmsgtty_driver ) ) {
kfree ( cport ) ;
return PTR_ERR ( rpmsgtty_driver ) ;
}

rpmsgtty_driver - > driver_name = " rpmsg_tty " ;


rpmsgtty_driver - > name = kasprintf ( GFP_KERNEL , "
,→ ttyRPMSG %d " , rpdev - > dst ) ;
rpmsgtty_driver - > major = UNNAMED_MAJOR ;
rpmsgtty_driver - > minor_start = 0;
rpmsgtty_driver - > type = TTY_DRIVER_TYPE_CONSOLE ;
rpmsgtty_driver - > init_termios = tty_std_termios ;

tty_set_operations ( rpmsgtty_driver , & imxrpmsgtty_ops


,→ ) ;

tty_port_init (& cport - > port ) ;


cport - > port . ops = & rpmsgtty_port_ops ;
spin_lock_init (& cport - > rx_lock ) ;
cport - > rpdev = rpdev ;
dev_set_drvdata (& rpdev - > dev , cport ) ;
rpmsgtty_driver - > driver_state = cport ;
cport - > rpmsgtty_driver = rpmsgtty_driver ;

ret = tty_register_driver ( cport - > rpmsgtty_driver ) ;


if ( ret < 0) {
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 168

pr_err ( " Couldn ’t install rpmsg tty driver : ret %


,→ d \ n " , ret ) ;
goto error1 ;
} else {
pr_info ( " Install rpmsg tty driver !\ n " ) ;
}

ret = rpmsg_send ( rpdev - > ept , MSG , strlen ( MSG ) ) ;


if ( ret ) {
dev_err (& rpdev - > dev , " rpmsg_send failed : %d \ n " ,
,→ ret ) ;
goto error ;
}

return 0;

error :
tty_unregister_driver ( cport - > rpmsgtty_driver ) ;
error1 :
tty_driver_kref_put ( cport - > rpmsgtty_driver ) ;
tty_port_destroy (& cport - > port ) ;
cport - > rpmsgtty_driver = NULL ;
kfree ( cport ) ;

return ret ;
}

1. Se imprime un mensaje de información que indica el nuevo canal RPMsg


detectado (origen y destino).

2. Se reserva memoria para una estructura rpmsgtty port utilizando devm kzalloc
esta estructura contendrá la información dobre el puerto TTY y otros deta-
lles relacionados.

3. Se asigna memoria para un controlador ca sin numeración utilizando tty allo


driver.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 169

4. Se configuran varios parámetros del controlador TTY, como el nombre del


controlador, el nombre del dispositivo, el tipo (en este caso, TTY DRIVER
TYPE CONSOLE para una consola) y las operaciones del controlador.

5. Se inicializa el puerto TTY utilizando tty port init, se configuran las opera-
ciones del puerto y se inicializa un bloqueo de hilos para gestionar la exclusión
mutua en el acceso a los datos de recepción.

6. Se obtiene un puntero al dispositivo RPMsg asociado a través de rpdev.

7. Se registra el controlador TTY utilizando tty register driver. Si la llamada


falla, se realiza una limpieza de recursos y se devuelve el código de error.

8. Se envı́a un mensaje al dispositivo remoto a través del canal RPMsg utili-


zando rpmsg send. Si esta llamada también falla, se deshace la configuración
realizada y se devuelve el código de error.

9. Si todo esto es exitoso, la función retorna 0.

Luego esta la función rpmsg tty remove la cual se llama cuando se elimina un
dispositivo compatible; la implementación se muestra a continuación:
static void rpmsg_tty_remove ( struct rpmsg_device * rpdev )
{
struct rpmsgtty_port * cport = dev_get_drvdata (& rpdev
,→ - > dev ) ;

dev_info (& rpdev - > dev , " rpmsg tty driver is removed \ n
,→ " ) ;

tty_unregister_driver ( cport - > rpmsgtty_driver ) ;


kfree ( cport - > rpmsgtty_driver - > name ) ;
tty_driver_kref_put ( cport - > rpmsgtty_driver ) ;
tty_port_destroy (& cport - > port ) ;
cport - > rpmsgtty_driver = NULL ;
}

La función opera de la siguiente manera:

1. Se obtiene un puntero a la estructura rpmsgtty port utilizando dev get drvdata.


Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 170

2. Se imprime un mensaje de información indicando que el controlador se está


eliminando.

3. Se desintegra el controlador TTY utilizando tty unregister driver.

4. Se imprime un mensaje de información indicando que el controlador se está


eliminando.

5. Se desregistra el controlador TTY utilizando tty unregister driver.

6. Se libera la memoria asignada al nombre del controlador utilizando kfree.

7. Se decrementa la referencia al controlador TTY utilizando tty driver kref put.

8. Se destruye el puerto TTY utilizando tty port destroy.

9. Finalmente, se establece el puntero rpmsgtty driver en la estructura rpmsgtty


port como nulo.

Luego se define la estructura rpmsg driver tty id table, en esta sección se define
una lista de identificadores de dispositivos para los canales RPMsg que serán com-
patibles con este controlador. Se espera que el controlador detecte los dispositivos
basados en estos identificadores.
static struct rpmsg_device_id rpmsg_driver_tty_id_table
,→ [] = {
{ . name = " rpmsg - virtual - tty - channel -1 " } ,
{ . name = " rpmsg - virtual - tty - channel " } ,
{ . name = " rpmsg - openamp - demo - channel " } ,
{} ,
};

En estas últimas secciones, se define la estructura del controlador rpmsg tty


driver que contiene información sobre el nombre del controlador, la función de
sonda probe para detectar dispositivos compatibles, la función de callback para
manejar mensajes entrantes y las funciones de eliminación (remove) para limpiar
cuando un dispositivo es eliminado.
Luego, las funciones init y fini, se utilizan para registrar y desmontar el con-
trolador de dispositivo RPMsg. El controlador se registra con la función regis-
ter rpmsg driver, lo que permite que el kernel asocie el controlador con los dis-
positivos compatibles detectados. Cuando el módulo se carga (module init) y se
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 171

descarga (module exit), estas funciones se utilizan para iniciar y finalizar el con-
trolador respectivamente.

3.19. Página Web


Como ejemplo simple de presentación externa, se implementó un servidor web
en la plataforma de desarrollo principal, el cual permite graficar los datos ad-
quiridos y consultarlos desde un ordenador remoto; ofrece información sobre la
frecuencia cardiaca, la opción de descargar un archivo con las muestras que se
consultan, ademas de ajustar la cantidad de muestras desplegadas y los intervalos
de tiempo en los que estas muestras son mostradas en pantalla.
Usando un servidor Apache instalado en el Ubuntu de la plataforma de desarro-
llo se puede desplegar la página web https://ip_plataforma_de_desarrollo/
index_pi.html. El algoritmo implementado index pi.html, es el siguiente:
Encabezado HTML:
<! DOCTYPE html >
< html >
< head >
< meta charset = " UTF -8 " >
< title > Demo data ECG via RPMsg </ title >
< style >
# myChartContainer {
width : 80 %;
margin : auto ;
}

# optionsContainer {
text - align : center ;
margin - bottom : 20 px ;
}

# numSamplesInput , # lineThicknessInput , #
,→ intervalInput , # colorSelect {
width : 6 em ;
}
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 172

# heartRateContainer {
position : absolute ;
bottom : 10 px ;
right : 10 px ;
padding : 10 px ;
background - color : # f0f0f0 ;
}
</ style >
< script src = " https :// cdn . jsdelivr . net / npm / chart . js " >
,→ </ script >
</ head >

ˆ Se define la codificación de caracteres como UTF-8.

ˆ Se establece el tı́tulo de la página como “Demo data ECG vı́a RPMsg”.

ˆ Se incluye un bloque <style> para definir estilos CSS que afectarán la apa-
riencia de la página.

ˆ Define estilos para varios elementos de la página, como contenedores, campos


de entrada, botones y más. Estos estilos controlan la apariencia y disposición
de los elementos.

ˆ Se carga la librerı́a chart.js

Cuerpo HTML:
< body >
< h1 style = " text - align : center ; " > Demo data ECG via
,→ RPMsg </ h1 >
< div id = " myChartContainer " >
< canvas id = " myChart " > </ canvas >
</ div >
< div id = " optionsContainer " >
< label for = " numSamplesInput " > Numero de Muestras :
,→ </ label >
< input type = " number " id = " numSamplesInput " value =
,→ " 2048 " >
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 173

< label for = " lineThicknessInput " > Grosor de la


,→ Linea y Puntos : </ label >
< input type = " number " id = " lineThicknessInput "
,→ value = " 1 " >
< label for = " intervalInput " > Intervalo de
,→ Actualizacion ( ms ) : </ label >
< input type = " number " id = " intervalInput " value = "
,→ 3000 " >
< label for = " colorSelect " > Color : </ label >
< select id = " colorSelect " >
< option value = " rgb (75 , 192 , 192) " > Verde </
,→ option >
< option value = " rgb (255 , 99 , 132) " > Rojo </
,→ option >
< option value = " rgb (54 , 162 , 235) " > Azul </
,→ option >
< option value = " rgb (255 , 205 , 86) " > Amarillo </
,→ option >
</ select >
< button id = " downloadButton " > Guarda Datos </ button >
< label for = " standardizeDataCheckbox " > Datos
,→ Reales : </ label >
< input type = " checkbox " id = "
,→ standardizeDataCheckbox " >
</ div >
< div id = " heartRateContainer " style = " display : none ; " >
< h2 id = " heartRateLabel " > Ritmo Cardiaco </ h2 >
<p id = " heartRate " > </ p >
</ div >
< script >
Aqui va el script .
.
.
</ script >
</ body >
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 174

El cuerpo de la página contiene el contenido principal de la página, que incluye


un tı́tulo, un contenedor para el gráfico, opciones para personalizar el gráfico, un
botón para descargar datos y un contenedor para mostrar el ritmo cardı́aco.
Java Script

var ctx =
,→ document . getElementById ( ’ myChart ’) . getContext ( ’2 d ’) ;
var chart ;
var dataURL = " datos . txt " ;

var downloadButton =
,→ document . getElementById ( ’ downloadButton ’) ;
downloadButton . addEventListener ( ’ click ’ ,
,→ downloadData ) ;

var numSamplesInput =
,→ document . getElementById ( ’ numSamplesInput ’) ;
var lineThicknessInput =
,→ document . getElementById ( ’ lineThicknessInput ’) ;
var intervalInput =
,→ document . getElementById ( ’ intervalInput ’) ;
var colorSelect =
,→ document . getElementById ( ’ colorSelect ’) ;
var standardizeDataCheckbox =
,→ document . getElementById ( ’ standardizeDataCheckbox ’) ;
var heartRateDisplay =
,→ document . getElementById ( ’ heartRate ’) ;
var heartRateLabel =
,→ document . getElementById ( ’ heartRateLabel ’) ;

var numSamples =
,→ parseInt ( numSamplesInput . value ) ;
var lineThickness =
,→ parseInt ( lineThicknessInput . value ) ;
var interval = parseInt ( intervalInput . value ) ;
var color = colorSelect . value ;
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 175

var standardizeData =
,→ standardizeDataCheckbox . checked ;
var lastHeartRate = 0;

var lastValues = [];


for ( var i = 0; i < numSamples ; i ++) {
lastValues . push (0) ;
}

numSamplesInput . addEventListener ( ’ change ’ ,


,→ updateChart ) ;
lineThicknessInput . addEventListener ( ’ change ’ ,
,→ updateChart ) ;
intervalInput . addEventListener ( ’ change ’ ,
,→ updateInterval ) ;
colorSelect . addEventListener ( ’ change ’ ,
,→ updateColor ) ;

,→ standardizeDataCheckbox . addEventListener ( ’ change ’ ,


,→ updateData ) ;

function createChart () {
var data = {
labels : Array . from ({ length : numSamples
,→ } , (_ , i ) = > ( standardizeData ? (( i * 1000) /
,→ 1024) . toFixed (1) : ( i + 1) . toString () ) ) ,
datasets : [{
data : lastValues ,
fill : false ,
borderColor : color ,
tension : 0.1 ,
borderWidth : lineThickness ,
pointRadius : lineThickness
}]
};
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 176

var options = {
responsive : true ,
scales : {
x: {
display : true ,
title : {
display : true ,
text : standardizeData ?
,→ ’ Tiempo ( ms ) ’ : ’ Tiempo (1024 Muestras / s ) ’
},
ticks : {
callback : function ( value ,
,→ index , values ) {
if ( standardizeData ) {
return ( index *
,→ (1000 / 1024) ) . toFixed (1) ;
} else {
return value ;
}
}
}
},
y: {
display : true ,
title : {
display : true ,
text : standardizeData ?
,→ ’ Valor ( mV ) ’ : ’ Valor Original ’
},
ticks : {
callback : function ( value ,
,→ index , values ) {
if ( standardizeData ) {
return value ;
<! - - ’ (( value * 2) - 1) . toFixed (1) ; ’
,→ -->
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 177

} else {
return value ;
}
},
min : standardizeData ? -8 :
,→ undefined ,
max : standardizeData ? 8 :
,→ undefined
}
}
},
plugins : {
legend : {
display : false
},
tooltip : {
callbacks : {
label : function ( context ) {
var label =
,→ context . dataset . label || ’ ’;

if ( label ) {
label += ’: ’;
}
label +=
,→ context . parsed . y + ( standardizeData ? " mV " : " " ) ;

return label ;
}
}
}
}
};

chart = new Chart ( ctx , {


type : ’ line ’ ,
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 178

data : data ,
options : options
}) ;
}

function updateChart () {
numSamples =
,→ parseInt ( numSamplesInput . value ) ;
lineThickness =
,→ parseInt ( lineThicknessInput . value ) ;

lastValues = lastValues . slice ( - numSamples ) ;

chart . data . labels = Array . from ({ length :


,→ numSamples } , (_ , i ) = > ( standardizeData ? (( i *
,→ 1000) / 1024) . toFixed (1) : ( i + 1) . toString () ) ) ;
chart . data . datasets [0]. data = lastValues ;
chart . data . datasets [0]. borderWidth =
,→ lineThickness ;
chart . data . datasets [0]. pointRadius =
,→ lineThickness ;
chart . options . scales . x . title . text =
,→ standardizeData ? ’ Tiempo ( ms ) ’ : ’ Tiempo (1024
,→ Muestras / s ) ’;
chart . options . scales . y . title . text =
,→ standardizeData ? ’ Valor ( mV ) ’ : ’ Valor Original ’;
chart . options . scales . y . ticks . min =
,→ standardizeData ? -8 : undefined ;
chart . options . scales . y . ticks . max =
,→ standardizeData ? 8 : undefined ;

chart . update () ;
}

function updateInterval () {
interval = parseInt ( intervalInput . value ) ;
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 179

clearInterval ( intervalId ) ;
intervalId = setInterval ( cargarDatos ,
,→ interval ) ;
}

function updateColor () {
color = colorSelect . value ;
chart . data . datasets [0]. borderColor = color ;
chart . update () ;
}

function updateData () {
standardizeData =
,→ standardizeDataCheckbox . checked ;
updateChart () ;
updateHeartRate () ;
}

function updateHeartRate () {

if ( standardizeData &&
,→ standardizeDataCheckbox . checked ) {
lastHeartRate = heartRate ;
heartRateDisplay . textContent =
,→ heartRate . toString () ;
heartRateContainer . style . display =
,→ ’ block ’;
heartRateLabel . innerHTML = ’ Ritmo
,→ <br > Cardiaco ’;
heartRateLabel . style . whiteSpace = ’pre - line ’;
} else {
lastHeartRate = 0;
heartRateContainer . style . display =
,→ ’ none ’;
}
}
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 180

function calculateThreshold ( ecgSignal ,


,→ thresholdFraction ) {
var maxValue = Math . max (... ecgSignal ) ;
var threshold = maxValue * thresholdFraction ;
return threshold ;
}
// Funcion para encontrar picos R en la senal de ECG
function findRPeaks ( ecgSignal , threshold ) {
var peaks = [];
for ( var i = 1; i < ecgSignal . length - 1; i ++) {
if ( ecgSignal [ i ] > threshold && ecgSignal [ i ] >
,→ ecgSignal [ i - 1] && ecgSignal [ i ] > ecgSignal [ i +
,→ 1]) {
peaks . push ( i ) ;
}
}
return peaks ;
}

// Funcion para calcular el ritmo cardiaco a


,→ partir de los picos R detectados
function calculateHeartRate ( peaks , interval ) {
if ( peaks . length < 2) {
return 0;
}

var sumOfRRIntervals =
,→ peaks . slice (1) . reduce (( sum , peak , index ) = > sum +
,→ ( peak - peaks [ index ]) , 0) ;
var averageRRInterval = sumOfRRIntervals /
,→ ( peaks . length - 1) ;

var heartRate = Math . round (0.5*60 /


,→ ( averageRRInterval / 1000) ) ;
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 181

return heartRate ;
}

// Funcion para actualizar el ritmo cardiaco en


,→ la interfaz
function updateHeartRateDisplay ( heartRate ) {
if ( standardizeData &&
,→ standardizeDataCheckbox . checked ) {
lastHeartRate = heartRate ;
heartRateDisplay . textContent =
,→ heartRate . toString () ;
heartRateContainer . style . display =
,→ ’ block ’;
} else {
lastHeartRate = 0;
heartRateContainer . style . display =
,→ ’ none ’;
}
}

// Luego , en tu funcion cargarDatos , calcula el


,→ umbral antes de detectar los picos R :

function cargarDatos () {
fetch ( dataURL )
. then ( response = > response . text () )
. then ( data = > {
var lines = data . trim () . split ( ’\ n ’) ;
var values = lines . map ( line = >
,→ parseFloat ( line ) ) ;
lastValues =
,→ values . slice ( - numSamples ) ;

if ( standardizeData ) {
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 182

lastValues =
,→ lastValues . map ( value = > (1000 * 1.2 * value ) /
,→ (122.46 * Math . pow (2 , 15) ) ) ;
}

chart . data . datasets [0]. data =


,→ lastValues ;
chart . update () ;
var threshold =
,→ calculateThreshold ( lastValues , 0.7) ; // Ajusta el
,→ valor de thresholdFraction segun tus datos
var peaks = findRPeaks ( lastValues ,
,→ threshold ) ;
var heartRate =
,→ calculateHeartRate ( peaks , interval ) ;

updateHeartRateDisplay ( heartRate ) ;
})
. catch ( error = > {
console . log ( ’ Error al cargar los
,→ datos : ’ , error ) ;
}) ;
}

function downloadData () {
var data = lastValues . join ( ’\ n ’) ;
var blob = new Blob ([ data ] , { type :
,→ ’ text / plain ’ }) ;
var url = URL . createObjectURL ( blob ) ;
var a = document . createElement ( ’a ’) ;
a . href = url ;
a . download = ’ datos . txt ’;
a . click () ;
URL . revokeObjectURL ( url ) ;
}
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 183

createChart () ;
cargarDatos () ;
var intervalId = setInterval ( cargarDatos ,
,→ interval ) ;

Se inicia JavaScript en el bloque <script>. Este script interactúa con la página


web y maneja la creación y actualización del gráfico, ası́ como la carga de datos
y el cálculo del ritmo cardı́aco. Las variables se definen para manejar elemen-
tos de la página web, configuración de gráfico, datos y más. Se definen funciones
como: createChart(), updateChart(), updateInterval(), updateColor(), updateDa-
ta(), updateHeartRate(), calculateThreshold(), findRPeaks(), calculateHeartRa-
te(), updateHeartRateDisplay(), cargarDatos(), y downloadData().
createChart(): Inicializa el gráfico utilizando la biblioteca chart.js y lo alma-
cena en la variable chart. Las funciones como updateChart(), updateInterval(),
etc., se utilizan para actualizar el gráfico y gestionar las opciones del usuario.
cargarDatos(): carga datos desde un archivo externo (”datos.txt”), proce-
sa los datos y actualiza el gráfico. downloadData() permite descargar los datos
actuales en un archivo de texto.
Al final del script, se llama a createChart(), cargarDatos(), y se configura un
intervalo para actualizar automáticamente los datos del gráfico.

3.20. Sistema X Window


El software X Window System (en adelante X) se puede utilizar para propor-
cionar una interfaz gráfica de usuario (GUI) para las plataformas que ejecutan
sistemas operativos UNIX y Linux. El protocolo X, se inicia en el MIT a media-
dos de la década de los 80; como una interfaz gráfica para el novedoso sistema
operativo UNIX. La version vigente (X11), permite la presentación gráfica entre
computadores en un entorno de red cliente-servidor; independientemente del OS.
X usa el modelo cliente-servidor: un servidor X se comunica con varios pro-
gramas cliente. El servidor acepta los pedidos para la salida gráfica (ventanas) y
devuelve la entrada del usuario como se observa en la Figura 3.69 (desde el teclado,
el ratón, o la pantalla táctil).
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 184

Figura 3.69: Estructura cliente servidor de X.

En X, el terminal de usuario serı́a el servidor y las aplicaciones por consiguiente


los clientes; aunque los términos parezcan invertidos. X toma la perspectiva de la
aplicación, en vez de la del usuario final: X proporciona la exhibición por pantalla
y los servicios de entrada/salida a las aplicaciones, ası́ que es un servidor; las
aplicaciones usan estos servicios, por lo tanto, son los clientes.
El servidor X provee servicios para acceder a la pantalla, teclado y ratón, mien-
tras que los clientes son las aplicaciones que utilizan estos recursos para interacción
con el usuario. De este modo mientras el servidor se ejecuta de manera local, las
aplicaciones pueden ejecutarse remotamente desde otras máquinas, proporcionan-
do ası́ el concepto de transparencia de red.
Existen algunos requisitos previos para ejecutar una aplicación X en un sistema
Ubuntu y mostrarla en otro computador corriendo otro SO. El sistema en el que
se mostrará la aplicación debe ejecutar un servidor X; el modo gráfico de Linux
supone el servidor X; contrario a Windows o Mac. Para Windows es recomendable
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 185

el sistema VcXsrv Windows X Server (instalar VcXsrv con Chocolatey) o usar el


servidor Xming X Server.
Para permitir acceder a la ordenador o estación de trabajo del usuario, a cual-
quier maquina remota (o una especı́fica), usando el protocolo X; para permitir
cualquier solicitud de cliente se usa:
$ xhost +

Nota: puede especificar un ip o máscara de red, usando; xhost <ip>; el comando


permitirá la conexión de remota al usuario que otorga el permiso.
Conectarse al sistema remoto donde se ejecuta la aplicación que se necesite
visualizar en la estación de trabajo. Usando el protocolo SSH (nombre de usua-
rio@IP):
$ ssh ubuntu@ < IP remoto >

Exportamos la salida gráfica o display desde la maquina remota especificando


el IP de la estación de trabajo local, con el comando:
$ export DISPLAY = < IP local >:0.0

Verifique con:
$ echo $ DISPLAY

Ahora se puede ejecutar en la ordenador remota, la aplicación que se requiere


que el servidor X instalado en la máquina local (Windows o Linux) despliegue en
la pantalla para el uso e interacción; por ejemplo se puede probar con:
$ xeyes &

Nota: El carácter ampersand (&), indica que la aplicación se debe ejecutar,


pero liberando el prompt de comando del terminal donde se opera.
Si todo está correcto, en la computadora local se debe de desplegar la aplicación
que ejecutamos en la computadora remota; la aplicación remota serı́a un cliente
del servidor X instalado en la máquina local.
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 186

Figura 3.70: Salida en pantalla del programa xeyes.

Este método se puede usar para consultar y graficar los datos con la aplicación
de Kst2; pero utilizando un ordenador remoto.

Figura 3.71: Ejemplo de salida en pantalla de Kst2 mediante X.


Capı́tulo 4

Resultados

En este Capı́tulo se presentan y analizan los resultados más relevantes obte-


nidos durante este trabajo de investigación, los resultados son divididos en tres
grupos de primitivas, resultados: implementación del driver para el control del
AFE ADS1298 utilizando la plataforma de desarrollo auxiliar, resultados obteni-
dos a partir de la implementación del driver para el control del AFE BMD101
utilizando la plataforma de desarrollo principal PICO-PI-IMX7, resultados aso-
ciados a la configuración de la imagen y los elementos que la conforman.

4.1. Resultados driver AFE ADS1298


El código que se implementó con la plataforma auxiliar controlando el AFE
ADS1298 fue exitoso en cierta medida, al graficar el archivo de captura con el
programa Kst2. Sin embargo, la velocidad de reloj son limitantes dado a que de-
berı́an poderse apreciar muchas más muestras; si no existieran las limitaciones en
la frecuencia de trabajo del dispositivo de control. Esto debido a que se tienen que
manejar los resultados para representar los valores decimales retrasando las con-
versiones y perdiendo resolución debido al algoritmo de conversión implementado.
A continuación podemos ver un ejemplo para una señal de entrada sinusoidal
que pasa por el simulador de ECG descrito en el Capı́tulo 2, haciendo que la
derivación tenga una diferencia de potencial de alrrededor de 2mV.

187
Capı́tulo 4. Resultados 188

Figura 4.1: Señal capturada.

4.1.1. Análisis de los resultados


A pesar de que se logró implementar un driver que cumple con la lógica de
control básica para el manejo del ADS1298, existen un conjunto de motivos que
evidencian que la elección del microcontrolador PIC18F4620 como plataforma de
desarrollo base, no es la mejor elección para atender los requerimientos del dispo-
sitivo.
La velocidad del microcontrolador es una limitante, incluso para el control de
un solo canal de datos, debido a que las rutinas de adquisición no alcanzan los
tiempos mı́nimos necesarios para muestrear y capturar la data de manera que se
recojan la cantidad de muestras que el AFE realmente captura en la configuración
de sus registros.
Investigaciones posteriores en la plataforma de desarrollo principal arrojaron
que la interfaz SPI no es un elemento disponible para el ARM Cortex-M4 en el
marco de la carrier baseboard PICO-PI-IMX7D, Esta posibilidad no fue considera-
da al inicio del proyecto debido a que la información suministrada por la compañı́a
que elaboró la plataforma (Technexion) no especificaba de manera explı́cita este
detalle. El dispositivo SoC si cuenta con una interfaz SPI a nivel de la carrier
baseboard ; sin embargo solo está disponible para los ARM Cortex-A7. Este pro-
blema fue apreciado al visitar las entradas dedicadas a la PICO-PI-IMX7D en la
página del sistema operativo para sistemas embebidos Zephyr [83]. A demas que
en los ejemplos dispuestos por Technexion para el aprendizaje, y en los archivos
Capı́tulo 4. Resultados 189

de configuración del board en FreeRTOS BSP, no existe información para el uso


de la interfaz SPI en esta plataforma; lo que cambia para plataformas diferentes
con el mismo SoC.
Se podrı́a implementar la comunicación SPI, desarrollando el protocolo a nivel
de GPIO; implementando las primitivas de este protocolo con los GPIO disponibles
para el núcleo ARM Cortex-M4. Sin embargo, esta implementación escapa de los
objetivos planteados por la tesis y se desvı́a del objetivo principal que es el uso de
la arquitectura heterogénea bajo una aplicación.
Esto ultimo, conllevó a desarrollar un segundo driver pero no con el ADS1298 si
no con un módulo basado en un AFE para ECG, basado en el BMD101 Neurosky,
El módulo es el ECG 4-Click de MikroElektronica, que cuenta con una interfaz
de comunicación serial y el estándar mikroBus para conectarse a la interfaz de
control.

4.2. Resultados Driver AFE BMD101


La documentación suministrada por Neurosky para el AFE BMD101 no es muy
rigurosa, en la descripción del dispositivo y omiten información que suele ser útil
considerar como: la cantidad de muestras por segundo que se obtienen al adquirir
la data, el comportamiento de la ganancia del dispositivo, el orden del filtrado que
se realiza a la data.
Se pudo encontrar un documento con los siguientes datos:

ˆ Frecuencia de muestreo: 512 S/s (16 bits).

ˆ Filtrado: 0.5 Hz - 100 Hz, filtro notch @ 50 Hz y 60 Hz.

ˆ El orden de los filtros pasa alto y pasa bajos no está documentado.

En el datasheet tenemos que la ganancia diferencial antes del filtrado es 128.


Se puede calcular que la ganancia después del filtrado @ 20 Hz deberı́a ser 128
aproximadamente, sin embargo, luego de analizar experimental el comportamiento
en frecuencia del dispositivo y partiendo de que los algoritmos presentados en este
trabajo están correctos, se sospecha que este valor no incluye la etapa de filtrado,
por las diferencias obtenidas al realizar en las mediciones.
Hay que considerar también que el divisor de voltaje para mVp genera 0.971
mVp como una aproximación a 1 mVp.
Capı́tulo 4. Resultados 190

Si se considera el peor caso para los valores de las resistencias el error es 0.98.
O sea el error de las resistencia en el numerador del divisor -1 % y las resistencias
del denominador del divisor +1 %.
Para clarificar estos datos fueron realizados una serie de experimentos descritos
a continuación:

4.2.1. Determinación experimental de la tasa de muestreo


Para confirmar la robustes de la adquisición se midió la cantidad de muestras
que se obtienen de una señal conocida en este caso se utiliza una señal cuadrada
de 1 Hz @ 1 mVp, posteriormente mediante el uso del programa Kst2, se estudio
cuantas muestras se correspondı́an a un perı́odo de la señal. El sampling rate queda
como 512 S/s. Que confirma que el código está correcto.

Figura 4.2: Determinación experimental frecuencia de muestreo mediante gra-


ficación en Kst2.

Los datos usados para generar este gráfico pueden verse en el Apendice B 4.4.

4.2.2. Determinación experimental de la ganancia


Para confirmar la robustes del código se determino la ganancia analizando una
onda sinusoidal de 20 Hz (mitad del ancho de banda según el fabricante), y se
determinó que el valor de la ganancia, reportado en la hoja de datos del dispositivo,
no incluye la ganancia asociada al filtrado, dado a que los valores obtenidos al
realizar el gráfico utilizando el valor de 128 reportado en la hoja de datos dentro
Capı́tulo 4. Resultados 191

de la ecuación de conversión no se obtenı́an los valores esperados para la mitad


de banda. Para obtener mediciones más confiables se debe considerar un factor de
1.825 asociado a la ganancia de esta etapa, lo que implica considerar este termino
como un factor de escalamiento.
También hay que tener en cuenta que para el montaje se utilizó el divisor de
voltaje que está implementado con resistencias de 1 % de tolerancia como error
asociado a la medida.
De esta medición se confirmo que el código que genera la data está correcto
por la similitud de la ganancia esperada con la ganancia obtenida, además los
resultados muestran que la adqusición se realiza sin perdidas.

4.2.3. Comportamiento en frecuencia del AFE


Se realiza un barrido punto a punto de frecuencias para hacer mediciones de
la data a travéz del puerto serial en un rango 0.1 Hz a 130 Hz a partir de estas
mediciones se pudo construir el diagrama de Bode de Magnitud mostrado en la
Figura 4.3:
La ecuación usada para obtener los valores RTO es la siguiente:

V RT I · 1,825 · 128
V alorRT O = · [V ] (4.1)
1000

Vo V RT I · 1,825 · 128 [V ]
Gain = = · (4.2)
Vi 1000 · 10 · (−exp3) [V ]
Según los resultados del Bode de Magnitud, se comprueba un ancho de banda
que corresponde a lo esperado.
Capı́tulo 4. Resultados 192

Figura 4.3: Bode de Magnitud resultante del barrido de frecuencias.

Del comportamiento en frecuencia se puede observar que la zona más “plana”


del gráfico o la que aparenta un comportamiento más lineal ocurre más a la iz-
quierda del gráfico alrededor de los 5 Hz, por lo que podrı́a esta zona ser una mejor
candidata para tomar el factor de escalamiento para normalizar los datos, sin em-
bargo por la falta de información se decidió utilizar la frecuencia media reportada
en el datasheet para tomar el valor de normalización.
Por las pendientes que se pueden observar del gráfico el filtro parece tener
un comportamiento de segundo orden, ya que caen aproximadamente 6 dB a los
extremos de las frecuencias de corte.

4.2.4. Graficación de los datos usando Kst2


A partir del valor de la ganancia determinado y la tasa de muestreo, se realiza
el ajuste de los ejes de la aplicación de graficación Kst2 [40] , para esto los valores
del eje ordenado se les aplica la siguiente ecuación de conversión.

1,2 · ADCcode
V alorRT I = · 1000 · [mV ] (4.3)
1,825 · 128 · 215
La escala temporal (eje de las abscisas) queda como un producto del número de
muestras por el tiempo en segundos en el que se adquiere una muestra. Se obtienen
512 muestras en cada segundo por lo que la ecuación de ajuste para el eje queda
como:
Capı́tulo 4. Resultados 193

1
GT = Nmuestra · [s] (4.4)
512

GT = Nmuestra · 1,953125[ms] (4.5)

Con los parámetros de muestreo y ganancia configurados en los ajustes del


programa de gratificación se realizan las gráficas para los datos recogidos 4.4.

Figura 4.4: Señal Senoidal 1mV @ 1Hz visualización en la patalla de la pla-


taforma de desarrrollo.

Se observa que el valor de voltaje RTI obtenido para este caso cae debido a la
atenuación a 1 Hz debido al pasa alto.
En contraste en la Figura 4.5 se muestra el comportamiento del gráfico con una
estrada senoidal, con frecuencia 20 Hz (ancho de banda reportado en la hoja de
datos).
Capı́tulo 4. Resultados 194

Figura 4.5: Señal Senoidal 1mV @ 20Hz visualización en la patalla de la


plataforma de desarrrollo.

Como era de esperarse el valor obtenido para este caso se aproxima mucho a 1
mV, ya que es la frecuencia utilizada para el valor de normalización.
Otra manera de visualizar estos datos es mediante un ordenador remoto (Figura
4.6) por medio de SSHFS.

Figura 4.6: Señal Senoidal 1mV @ 20Hz visualización en la patalla de un


ordenador remoto mediante SSHFS.
Capı́tulo 4. Resultados 195

Es posible consultar y graficar estos datos, tanto en la plataforma de desarrollo


principal, como en un ordenador que actúe como cliente para consultar el archivo
de salida. Se estudiaron diferentes métodos para la conexión remota de un disposi-
tivo cliente dentro de una red local. Se puede encontrar información de los métodos
y configuraciones utilizadas en la bitácora en lı́nea asociada a este trabajo [84].
Otro objetivo alcanzado la disposición del archivo de datos capturados en un
página web, situada en la plataforma de desarrollo, mediante port forwarding de
una IP pública, es posible visualizar esta data en un ordenador remoto fuera de la
red local; se muestra a continuación el resultado de esta página web:

Figura 4.7: Señal Cardiac, visualización en la página web de visualización.

Figura 4.8: Señal Cardiac, visualización en la página web de visualización.

Cabe destacar que no se desarrolló una aplicación robusta para este caso que
garantice la transmisión de datos sin perdidas.
Capı́tulo 4. Resultados 196

4.2.5. Análisis de los resultados


Los resultados obtenidos obtenidos son los esperados. Por la cantidad de mues-
tras recibidas y la forma de onda, se puede observar que no ocurren perdidas
de datos, discontinuidades o alteraciones inesperadas en la adquisición, ni existen
inconvenientes en el despliegue de datos de manera local. para el caso de la pla-
taforma de desarrollo. Esto no es igual para el caso de clientes dentro y fuera de
la red local, debido a los retrasos asociados al envió de paquetes y la implementa-
ción de la página Web de visualización. la cual aún se encuentra en una etapa de
desarrollo, con un amplio margen de mejora.
La consola de debugging es una herramienta bastante útil para el desarrollo
permitiendo ver mensajes que facilitan el proceso de depuración del algoritmo, sin
embargo, el uso de la consola de debugging bajo el esquema implementado impo-
sibilita el uso del conector mikroBus incorporado a la plataforma de desarrollo. Al
conectar AFE en este bus se compartirı́an las lineas seriales entre la salida del M4
y la aalida del BMD101, ocasionando colisiones entre las lineas, razón por la que
la interfaz de debug no es empleada en la aplicación final.
Conclusiones y Recomendaciones

A lo largo de este trabajo se han presentado las distintas etapas de desarrollo


de esta investigación: un estudio de antecedentes significativos para el desarrollo
de la aplicación, elaboración y estructuración de un marco teórico con conceptos
y definiciones necesarias para elaborar soluciones de los objetivos planteados. La
configuración y puesta apunto de la plataforma de desarrollo, la implementación de
dos drivers de control para dos módulos AFE de ECG, presentando los resultados
al igual que el análisis de los resultados obtenidos. En este capı́tulo, se presentan
las conclusiones derivadas de los resultados obtenidos de esta investigación, junto
con las recomendaciones e ideas para los futuros trabajos que puedan realizarse a
partir de este trabajo.

4.3. Conclusiones
Con este trabajo se avanza la compresión de los procesadores heterogéneos,
al presentar una aplicación funcional de esta tecnologı́a y los pasos seguidos a lo
largo de su desarrollo. Se pretende que este trabajo sirva como referencia para
futuros desarrollos y aplicaciones similares, facilitando soluciones y estrategias
para disminuir la curva de aprendizaje que tienen estos dispositivos.
Como se mencionó previamente en este trabajo, el uso y aplicación de estas
tecnologı́as, ha sido trabajado durante años y cada dı́a su presencia se hace más
notoria en una amplia gama de aplicaciones de tiempo real. Es importante que se
sigan desarrollando trabajos utilizando procesadores heterogéneos debido a que el
desempeño de estos en un amplio rango de aplicaciones mejora significativamente
al de los procesadores simétricos.
La aplicación de electrocardiógrafo implementada en el marco de este trabajo
es solo una demostración de las primitivas de firmware y software correspondientes
al hardware considerado que incluye procesadores heterogéneos como dispositivos

197
Capı́tulo 4. Resultados 198

de control. Ademas la aplicación permite almacenar archivos como un holter para


su posterior análisis.
El driver implementado utilizando el microcontrolador PIC18F4620 permite
concluir que no se deben utilizar microcontroladores de rango médio para el de-
sarrollo de este tipo de aplicaciones, sobre todo en el sector médico debido a la
complejidad que suelen tener los instrumentos de medición en este campo. Se ob-
serva que la frecuencia de trabajo máxima de este dispositivo se queda corta para
el procesamiento de la data del AFE ADS1298, lo cual se comprueba al pasar de
la implementación con 8 MHz a 32 MHz los tiempos de conversión de un dato
pasa de alrededor de 15 ms a 3 ms, pero aún es insuficiente para establecer una
adquisición de 1 KHz. Lo que sugiere una implementación con un procesador con
mayores prestaciones como las de un núcleo M4 que opera a 200 MHz.
La investigación permite concluir que no se podı́a acceder a la interfaz SPI de
la plataforma mediante el núcleo M4, información que al momento de iniciar este
trabajo no estaba verificada. Sin embargo, es posible utilizar la comunicación SPI
desde el entorno de los núcleos A7 como demuestran las pruebas realizadas con el
shell de Linux [85]. Pero esto implicarı́a el uso de un driver de Linux para asegurar
una adquisición sin perdida de datos.
Las experiencias realizadas al configurar la plataforma proveen un flujograma
que contempla los distintos escenarios en los se puede encontrar la plataforma al
momento de hacer su configuración, y los métodos recomendados para hacer la
carga de una imagen a la eMMC en cada caso. Se implementó también la imagen
optimizada de la plataforma de desarrollo del proyecto, para facilitar el desarrollo
de investigaciones futuras, la cual se encuentra disponible en disponible en [53].
El driver implementado para al aplicación heterogénea es un ejemplo del funcio-
namiento de la tecnologı́a de comunicación inter-procesadores. Este es un ejemplo
del trabajo de dos aplicaciones independientes, en procesadores independientes
con distintas frecuencias de trabajo, compartiendo datos y operando de manera
simultánea.
La bitácora digital anexa a este trabajo [29] estuvo pública desde octubre del
2022 hasta abril de este año alcanzando 6832 visitas lo que implica en una buena
medida del valor y la utilidad de este trabajo. Se pretende que esto quede como
un material de consulta para la comunidad universitaria y mejorar este material
en el futuro.
Capı́tulo 4. Resultados 199

4.4. Recomendaciones
Existen muchas formas de dar continuidad a este trabajo, por lo que en esta
sección se plantearán varios posibles trabajos futuros.
En primer lugar, a pesar de que la plataforma no puede manejar la interfaz SPI
por medio del núcleo M4 en la configuración dispuesta por Technexion, esto no es
ası́ para otras plataformas de distintas compañias dado a que el SoC y el SOM si
disponen de otras interfaces SPI distinta a la que llega a la Carrier Baseboard que
no es accesible por el núcleo M4. Una solución a esto podrı́a ser la migración a otra
plataforma como: la Colibri de Toradex Colibri IMX7D 1GB o alguna plataforma
con mayores prestaciones.
Tambien se podrı́a implementar un módulo driver en el kernel Linux para
adquirir la data con los núcleos A6 o A8. Pero esta solución por supuesto va
encontra de las premisas del uso de procesadores heterogéneos.
La aplicación web cliente servidor diseñada como objetivo adicional de este
trabajo tiene un gran marco de mejora que van desde el manejo de la data hasta
la implantación de códigos robustos para la presentación de datos que pueden ser
explorados en un trabajo posterior.
Se recomienda desarrollar una interfaz gráfica independiente en lenguaje C para
la aplicación que permita una interacción robusta la para el usuario final.
Evaluar el uso de un AFE con una documentación más explicita para un desa-
rrollo más firme de la aplicación, o consultar con la compañı́a Neurosky el com-
portamiento en frecuencia y la ganancia de la etapa de filtrado del dispositivo
BMD101.
Adicionalmente se podrin realizar pruebas para medir el máximo throughput
de datos posible utilizando los mecanismos de comunicación inter-procesadores
disponibles en esta arquitectura.
Bibliografı́a

[1] C. Garcı́a, “Desarrollo de una aplicación cliente-servidor para la transmi-


sión de ecg vı́a internet,” Trabajo de Grado de Maestrı́a, Universidad Simón
Bolı́var, 1998.

[2] A. I. Hernandez, F. Mora, M. Villegas, G. Passariello, and G. Carrault,


“Real-time ecg transmission via internet for nonclinical applications,” IEEE
Transactions on information technology in biomedicine, vol. 5, no. 3, pp. 253–
257, 2001.

[3] J. Cruz, G. Villegas, J. Uyá, A. Hernández, G. Passariello, and F. Mora,


“Sistema telemédico de electrocardiografı́a basado en internet embebido,”
Memorias del Taller de Telemedicina e Informática Medica (CD). Mérida.
Venezuela, 2001.

[4] D. Lucani, G. Cataldo, J. Cruz, G. Villegas, and S. Wong, “A portable ecg


monitoring device with bluetooth and holter capabilities for telemedicine ap-
plications,” IEEE, pp. 5244–5247, 2006.

[5] S. Furber, “Microprocessors: The engines of the digital age,” Proceedings


of the Royal Society A: Mathematical, Physical and Engineering Sciences,
vol. 473, no. 2199, p. 20160893, 2017, erratum in: Proceedings of the
Royal Society A: Mathematical, Physical and Engineering Sciences. 2017
May;473(2201):20170304. [Online]. Available: https://doi.org/10.1098/rspa.
2016.0893

[6] F. Baum and A. Raghuraman, “Making Full use of Emerging ARM-based


Heterogeneous Multicore SoCs,” in 8th European Congress on Embedded Real
Time Software and Systems (ERTS 2016), TOULOUSE, France, Jan. 2016.
[Online]. Available: https://hal.science/hal-01292325

200
Capı́tulo 4. Resultados 201

[7] Y. Kang, J. Chen, and B. Li, “Generic bootloader architecture based on


automatic update mechanism,” in 2018 IEEE 3rd International Conference
on Signal and Image Processing (ICSIP). IEEE, 2018, pp. 586–590.

[8] A. A. Clements, N. S. Almakhdhub, K. S. Saab, P. Srivastava, J. Koo, S. Bag-


chi, and M. Payer, “Protecting bare-metal embedded systems with privilege
overlays,” in 2017 IEEE Symposium on Security and Privacy (SP), 2017, pp.
289–303.

[9] A. Murikipudi, V. Prakash, and T. Vigneswaran, “Performance analysis of


real time operating system with general purpose operating system for mobile
robotic system,” Indian Journal of Science and Technology, vol. 8, no. 19, pp.
1–6, 2015.

[10] Texas Instruments, “How to measure ecg: A guide to the sig-


nals, system blocks and solutions,” https://www.ti.com/video/series/
how-to-measure-ecg--a-guide-to-the-signals--system-blocks-and-so.html?
keyMatch=ECG#tab-1, 5 2017.

[11] A. A. Atkielski) and atom, “Schematic diagram of normal sinus rhythm for
a human heart as seen on ecg (with english labels),” Retrieved from https:
//commons.wikimedia.org/wiki/File:SinusRhythmLabels.svg, January 2007.

[12] D. B. Geselowitz, “On the theory of the electrocardiogram,” Proceedings of


the IEEE, vol. 77, no. 6, pp. 857–876, 1989.

[13] P. Kligfield, “Derivation of the correct waveform of the human electrocardio-


gram by willem einthoven, 1890-1895,” Cardiology Journal, vol. 17, no. 1, pp.
109–113, 2010.

[14] Maxim Integrated, “Introduction to electrocardiographs,” May 2010,


application Note No. 4693. [Online]. Available: https://www.analog.com/en/
technical-articles/introduction-to-electrocardiographs.html

[15] E. Peña and M. G. Legaspi, “Uart: A hardware communication protocol un-


derstanding universal asynchronous receiver/transmitter,” Analog Dialogue,
vol. 54, no. 4, December 2020. [Online]. Available: https://www.analog.com/
en/analog-dialogue/articles/uart-a-hardware-communication-protocol.html
Capı́tulo 4. Resultados 202

[16] P. Dhaker, “Introduction to spi interface,” Analog Dialogue, vol. 52,


no. 9, pp. 52–09, 2018. [Online]. Available: https://www.analog.com/en/
analog-dialogue/articles/introduction-to-spi-interface.html

[17] J. Axelson, “Serial port complete second edition: Com ports, usb virtual com
ports, and ports for embedded systems,” Lakeview Research LLC, 2007.

[18] N. Enos and B. Gosselin, “A primer on usb type-c and power delivery appli-
cations and requirements,” Texas Instruments, 2016.

[19] J. Axelson, USB complete: the developer’s guide. Lakeview research LLC,
2015.

[20] M. G. Legaspi and E. Peña, “I2c communication protocol: Understanding i2c


primer, pmbus, and smbus,” Analog Dialogue, vol. 55, no. 4, November 2021.
[Online]. Available: https://www.analog.com/en/analog-dialogue/articles/
i2c-communication-protocol-understanding-i2c-primer-pmbus-and-smbus.
html

[21] J. L. Marin Marcano, “Diseño e implementación de un sistema embebido de


telemetrı́a para vehı́culos baja sae,” 2012.

[22] N. Y. Gelvez Garcia, H. Espitia, and J. Bayona, “Testing of a virtualized


distributed processing system for the execution of bio-inspired optimization
algorithms,” Symmetry, vol. 12, p. 1192, 07 2020.

[23] A. Stec, “Ssl vs. ssh,” last updated: July 26, 2023. [Online]. Available:
https://www.baeldung.com/cs/ssl-vs-ssh

[24] T. D. Resources, “Freertos on the cortex-m4 of a colibri imx7,”


2021. [Online]. Available: https://developer.toradex.com/software/real-time/
freertos/freertos-on-the-cortex-m4-of-a-colibri-imx7/

[25] NXP, i.MX 7Dual Applications Processor Reference Manual Rev. 1. NXP,
2018.

[26] ——, “Pico i.mx7 development kit for android things hardware manual rev
b1,” 2017. [Online]. Available: https://www.nxp.com/docs/en/user-guide/
PICO-IMX7UL-USG.pdf

[27] Microchip Technology Inc., “Demonstration kit users guide,” Microchip Tech-
nology Inc., Document ID: DS51524C, 2008.
Capı́tulo 4. Resultados 203

[28] MikroElektronika, “Mikrobus - click boards — how does it work?” 2023.


[Online]. Available: https://www.mikroe.com/mikrobus

[29] R. Contreras, “Bitácora de tesis rajcf,” Blog, septiembre 2022, disponible en:
https://compilando-pico-pi-imx7.blogspot.com/.

[30] ——, “Conectores jp1, jp2, jp8 de la pico pi carrier board gl,” Imagen, octubre
2022, disponible en: https://compilando-pico-pi-imx7.blogspot.com/search?
q=pico+pi.

[31] T. Instruments, “Low-power, 8-channel, 24-bit analog front-end for biopoten-


tial measurements,” ADS1298 datasheet, 2012.

[32] NeuroSky, “Bmd101 datasheet,” https://download.mikroe.com/documents/


datasheets/BMD101.pdf, Fecha de acceso: julio 2023.

[33] Silicon Laboratories, “Single-chip usb to uart bridge,” 2010. [Online].


Available: https://www.silabs.com/documents/public/data-sheets/CP2103.
pdf

[34] Microchip Technology Inc., “PIC18F4620 data sheet,” [Online]. Availa-


ble: http://ww1.microchip.com/downloads/en/devicedoc/39626e.pdf, 2007,
accessed: July 5, 2023.

[35] National Instruments, “mydaq - dispositivo de adquisición de datos para


estudiantes,” 2023. [Online]. Available: https://www.ni.com/es-cr/shop/
hardware/products/mydaq-student-data-acquisition-device.html

[36] M. T. Inc., MPLAB ® ICD 3 In-Circuit Debugger User’s Guide For MPLAB
X IDE, 2012. [Online]. Available: https://ww1.microchip.com/downloads/
en/DeviceDoc/50002081B.pdf

[37] HiLetgo, “24mhz 8ch usb logic analyzer 8 channel logic analyzer
compatible to saleae,” website, 2023. [Online]. Available: https://hiletgo.
com/ProductDetail/1915369.html

[38] Saleae, “Saleae support spi analizer, user guide,” website, 2023. [Online]. Avai-
lable: https://support.saleae.com/protocol-analyzers/analyzer-user-guides/
using-spi

[39] B. Richard, “Freertos,” 9 2020. [Online]. Available: http//:www.freertos.org


Capı́tulo 4. Resultados 204

[40] R. P. Netterfield B., Chern R., “The kst handbook,” website, 2017. [Online].
Available: https://kst-plot.kde.org/docbook/html/index.html

[41] S. Tatham, “Putty,” Build platform: 64-bit x86 Windows, 2020, release 0.74.
[Online]. Available: https://www.chiark.greenend.org.uk/∼sgtatham/putty/

[42] NXP Semiconductors, “Universal Update Utility (UUU) User Gui-


de,” https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/
imx-processors/140261/1/UUU.pdf, Jan. 2019.

[43] ——, “Google cloud iot quick start guide,” https://www.nxp.com/docs/en/


user-guide/GOOGLE-CLOUD-IOT-iMX7-QSG.pdf, Fecha de acceso: julio
2023.

[44] Technexion, “Using ’uuu’ to flash e.mmc,” https://developer.technexion.com/


docs/using-uuu-to-flash-emmc, abril 2022.

[45] Technexion, “Using ’uuu’ to flash e.mmc,” YouTube video, 2022. [Online].
Available: https://www.youtube.com/watch?v=PcROg80aTYI

[46] Technexion, “Index of demo software pico imx7 pico imx7


emmc diskimage,” Repositorio de descarga de Technexion. [Online].
Available: https://download.technexion.com/demo software/PICO/IMX7/
pico-imx7-emmc/DiskImage/

[47] R. Contreras, “uuu-tool,” Artı́culo, abril 2022, disponible en: https://


compilando-pico-pi-imx7.blogspot.com/2023/04/uuu-tool.html.

[48] ——, “Compilando el u-boot,” Artı́culo, octubre 2022, disponible en: https://
compilando-pico-pi-imx7.blogspot.com/2022/10/compilando-el-u-boot.html.

[49] ——, “ums u-boot,” artı́culo, octubre 2022, disponible


en: https://compilando-pico-pi-imx7.blogspot.com/2022/11/
el-comando-ums-de-u-boot.html.

[50] ——, “Override reserved memory,” Blog, abril 2023, disponi-


ble en: https://compilando-pico-pi-imx7.blogspot.com/2023/04/
override-reserved-memory.html.

[51] ——, “Imágenes fallidas,” artı́culo, junio 2023, disponible en: https://
compilando-pico-pi-imx7.blogspot.com/2023/06/imagenes-fallidas.html.
Capı́tulo 4. Resultados 205

[52] ——, “Copia de la emmc,” artı́culo, junio 2023, disponible en: https://
compilando-pico-pi-imx7.blogspot.com/2022/11/copia-de-la-emmc.html.

[53] ——, “Salvavidas emmc,” Artı́culo, mayo 2023. [Online]. Available: https:
//compilando-pico-pi-imx7.blogspot.com/2023/05/salvavidas-emmc.html

[54] ——, “Boot y so, pico-pi-i.mx7d,” Blog, abril 2023, disponi-


ble en: https://compilando-pico-pi-imx7.blogspot.com/2023/04/
booteo-de-la-pico-pi-imx7d.html.

[55] ——, “Boot y so, pico-pi-i.mx7d,” Artı́culo, abril 2023, dispo-


nible en: https://compilando-pico-pi-imx7.blogspot.com/2023/04/
booteo-de-la-pico-pi-imx7d.html.

[56] ——, “Aumentando el tamaño del espacio de trabajo en disco,” Artı́cu-


lo, enero 2023, disponible en: https://compilando-pico-pi-imx7.blogspot.com/
2023/02/optimizando-el-ubuntu-instalado-en-la.html.

[57] ——, “Instalando chocolatey, make y cmake y mingw (para windows),”


octubre 2022. [Online]. Available: https://compilando-pico-pi-imx7.blogspot.
com/2022/10/instalando-chocolate-make-y-cmake-y.html

[58] ——, “Instalando make,” octubre 2022. [Online]. Available: https:


//compilando-pico-pi-imx7.blogspot.com/2022/10/instalando-make.html

[59] ——, “Instalando cmake,” octubre 2022. [Online]. Available: https:


//compilando-pico-pi-imx7.blogspot.com/2022/10/instalando-cmake.html

[60] ——, “Instalando mingw,” octubre 2022. [Online]. Available: https:


//compilando-pico-pi-imx7.blogspot.com/2022/10/instalando-minggw.html

[61] ——, “Exportando la ubicación de la variable del entorno,” octubre


2022, variable de entorno para la cadena de compilación de FreeRTOS.
[Online]. Available: https://compilando-pico-pi-imx7.blogspot.com/2022/10/
exportando-la-ubicacion-de-la-variable.html

[62] Arm, “Gnu-a downloads,” Sı́tio de descarga. [Online]. Available: https:


//developer.arm.com/downloads/-/gnu-a

[63] Technexion, “freertos-tn,” Repositorio Github, 2017, disponible en:


OptimizandoelUbuntuinstaladoenlaPico-Pi-i.MX7D.
Capı́tulo 4. Resultados 206

[64] R. Contreras, “Freertos en visual studio code,” Artı́culo, Noviembre


2022, disponible en: Ohttps://compilando-pico-pi-imx7.blogspot.com/2022/
11/freertos-en-visual-code.html.

[65] ——, “Freertos en pic18,” Artı́culo, Noviembre 2022, disponible en: https:
//compilando-pico-pi-imx7.blogspot.com/2022/11/freertos-en-pic18.html.

[66] ——, “Kernel linux y remoteproc,” Artı́culo, abril 2023. [On-


line]. Available: https://compilando-pico-pi-imx7.blogspot.com/2023/04/
kernel-de-linux-y-remoteproc.html

[67] ——, “Compilando el kernel linux,” Artı́culo, abril 2023. [On-


line]. Available: https://compilando-pico-pi-imx7.blogspot.com/2023/04/
compilando-el-kernel-linux.html

[68] Freescale Semiconductors, “Introduction to Device Trees,” NXP Se-


miconductors, Application Note, 2015. [Online]. Available: https:
//www.nxp.com/docs/en/application-note/AN5125.pdf

[69] R. Contreras, “Gpio desde el shell de linux,” Artı́culo, Febrero 2023.


[Online]. Available: https://compilando-pico-pi-imx7.blogspot.com/2023/
02/gpio-desde-el-shell-de-linux.html

[70] ——, “Pwm desde el shell de linux,” Artı́culo, Febrero 2023. [Online]. Availa-
ble: https://compilando-pico-pi-imx7.blogspot.com/2023/02/entrada-1.html

[71] ——, “Controlando backlight del lcd,” Artı́culo, Febrero 2023. [On-
line]. Available: https://compilando-pico-pi-imx7.blogspot.com/2023/02/
controlando-la-intensidad-de-la-luz.html

[72] ——, “Spi desde el shell de linux,” Artı́culo, Febrero 2023. [Online]. Available:
https://compilando-pico-pi-imx7.blogspot.com/2023/02/blog-post.html

[73] ——, “VISOR SISMÓMETRO,” 2019. [Online]. Available: https://doi.org/


10.7910/DVN/1JXSYT

[74] N. Semiconductors, “Rpmsg rtos layer user’s guide, rev1,” 07/2016.

[75] J. Palmer, “Introduction to virtio,” 5 2022. [Online]. Available: https:


//blogs.oracle.com/linux/post/introduction-to-virtio
Bibliografı́a 207

[76] R. Contreras, “Ecos de caracteres con rpmsg y rtos api,” Artı́culo, abril
2023. [Online]. Available: https://compilando-pico-pi-imx7.blogspot.com/
2023/04/ecos-de-caracteres-con-rpmsg-y-rtos-api.html

[77] M. A. B. Neto, “Desenvolvimento de um eletrocardiógrafo holter com ta-


manho e custo reduzidos,” 2012.

[78] J. C. Montoya Cardona et al., “Sistema de adquisición de biopotenciales para


entornos académicos,” 2013.

[79] Á. P. Guerrero Castillo, “Diseño de un dispositivo para la adquisición de una


señal eeg que incluya la reducción de artefactos oculares.” Ph.D. dissertation,
Escuela Colombiana de Ingenierı́a Julio Garavito, 2017.

[80] J. Meng, “Ads1298 ecg monitoring,” Repositorio Github, diciembre 2020. [On-
line]. Available: https://github.com/YessyeM/ADS1298 ECG Monitoring

[81] Microchip Technology Inc., “Getting started with spi using mssp
on pic18,” https://ww1.microchip.com/downloads/en/Appnotes/
Getting-Started-With-SPI-Using-MSSP-on-PIC18-90003265B.pdf, 2020.

[82] R. Contreras, “Pico-pi-i.mx7d-bmd101,” https://github.com/Rommelaser/


PICO-PI-i.MX7D BMD101.git, Agosto 2023.

[83] Z. Project, “Zephyr project documentation - pico pi m4 board,”


2023. [Online]. Available: https://docs.zephyrproject.org/latest/boards/
arm/pico pi m4/doc/index.html

[84] R. Contreras, “Acceso remoto,” Blog, junio 2023. [Online]. Available:


https://compilando-pico-pi-imx7.blogspot.com/2023/06/acceso-remoto.html

[85] ——, “Spi desde el shell de linux,” Blog, 2 2023. [Online]. Available:
https://compilando-pico-pi-imx7.blogspot.com/2023/02/blog-post.html
Apéndice A

A1. Esquemático PICDEM Z

Figura 9: Diagrama esquemático de la PICDEM Z [27].

208
Apéndice B

Tabla 1: Datos usada para la determinación experimental de la cantidad de


muestras por segundo Parte 1

1-32 3-64 65-96 97-128 129-160 161-193 194-225 226-258


422 -8307 -4301 -2286 -1247 -696 -398 -233
175 -8272 -4214 -2245 -1225 -682 -388 -225
-1871 -8079 -4128 -2205 -1203 -669 -379 -219
-5007 -7763 -4044 -2163 -1185 -657 -373 -215
-7528 -7410 -3963 -2117 -1167 -645 -369 -212
-8562 -7107 -3885 -2072 -1149 -632 -364 -208
-8960 -6910 -3810 -2032 -1128 -617 -358 -204
-10147 -6822 -3736 -1996 -1105 -603 -350 -199
-12337 -6804 -3663 -1963 -1080 -593 -343 -195
-14275 -6797 -3592 -1929 -1058 -585 -337 -192
-14692 -6751 -3523 -1892 -1039 -577 -332 -188
-13632 -6639 -3457 -1856 -1021 -569 -325 -185
-12192 -6468 -3389 -1821 -1003 -558 -317 -183
-11266 -6267 -3320 -1788 -986 -547 -312 -182
-10873 -6073 -3249 -1753 -969 -538 -311 -183
-10598 -5913 -3181 -1718 -953 -530 -310 -182
-10271 -5795 -3120 -1684 -936 -522 -305 -179
-10034 -5710 -3064 -1654 -918 -513 -297 -175
-9982 -5639 -3008 -1625 -899 -503 -288 -198
-10002 -5565 -2951 -1597 -881 -494 -285 -193
-9981 -5476 -2893 -1568 -864 -486 -284 -63
-9948 -5370 -2839 -1537 -848 -478 -281 101
-10006 -5251 -2786 -1507 -831 -469 -274 150
-10096 -5127 -2733 -1477 -813 -462 -267 64
-10018 -5010 -2678 -1449 -796 -456 -264 39
-9707 -4903 -2622 -1422 -782 -449 -263 229
-9222 -4809 -2571 -1394 -771 -441 -261 467
-8705 -4722 -2525 -1366 -761 -431 -256 436
-8306 -4640 -2480 -1338 -752 -421 -250 155
-8112 -4558 -2432 -1312 -740 -415 -246 52
-8114 -4474 -2381 -1289 -727 -411 -244 363
-8221 -4388 -2331 -1268 -712 -406 -240 655

209
Apéndice B. 210

Tabla 2: Datos usada para la determinación experimental de la cantidad de


muestras por segundo Parte 2

259-291 292-323 324-355 356-387 388-419 420-451 452-484 485-512


337 8441 4593 2489 1353 753 411 239
-327 8531 4503 2441 1327 741 406 237
-119 8501 4415 2397 1301 728 400 234
1855 8315 4330 2354 1277 713 394 230
4960 8006 4247 2310 1257 697 388 225
7523 7657 4164 2262 1238 681 382 218
8622 7352 4082 2216 1217 668 375 212
9037 7151 4005 2173 1194 657 368 208
10182 7059 3933 2132 1172 647 362 206
12333 7040 3866 2092 1151 636 355 204
14293 7032 3798 2052 1132 625 347 200
14779 6984 3727 2012 1113 614 339 198
13777 6870 3654 1975 1093 602 332 228
12351 6700 3581 1941 1072 588 326 199
11413 6502 3510 1906 1053 576 321 50
11015 6309 3442 1870 1036 566 316 -105
10751 6147 3377 1833 1018 559 310 -120
10435 6024 3315 1798 1000 551 305 -22
10200 5935 3255 1765 982 539 301 -31
10147 5865 3194 1734 964 525 296 -258
10172 5793 3133 1703 947 515 290 -471
10163 5705 3072 1673 928 508 284 -372
10140 5598 3013 1643 910 501 279 -77
10199 5477 2956 1613 892 490 276 -47
10294 5352 2900 1583 876 476 272 -409
10225 5234 2843 1554 861 463 268 -622
9926 5125 2787 1524 847 456 263 -166
9452 5028 2733 1495 832 450 258 474
8941 4938 2683 1464 816 442 255 -7
8539 4853 2636 1434 800 432 252 -2293
8338 4768 2589 1405 783 422 247 -5450
8335 4682 2539 1379 767 416 243 -7774

También podría gustarte