Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Por:
Rommel Aser Jesús Contreras Figueroa
PROYECTO DE GRADO
Presentado ante la Ilustre Universidad Simón Bolı́var
como requisito parcial para optar al tı́tulo de
Ingeniero Electrónico
RESUMEN
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
Resumen I
Agradecimientos II
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
4. Resultados 187
4.1. Resultados driver AFE ADS1298 . . . . . . . . . . . . . . . . . . . 187
Índice general vii
viii
Índice de figuras ix
xii
Lista de Acrónimos
xiii
Lista de Acrónimos xiv
1
Introducción 2
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.
Marco teórico
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
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
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:
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.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:
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.
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
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:
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
RA + LA + LL
VW ilson = (1.3)
3
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
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).
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).
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:
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.
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.
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.14: Trama de datos generico dentro del protocolo I2C [20].
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
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:
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
30
Capı́tulo 2. Descripción de las Plataformas de Desarrollo 31
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.5: Controlador de dominio de recursos (RDC) del SoC i.MX7D [25].
Clock
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.
Para más información sobre esta unidad consultar el manual de referencia del
SoC i.MX7D [25].
La unidad de manejo de energı́a (Figura 2.8) está integrado por: PMU, GPC,
CCM y SRC:
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.12: Conectores tipo header JP1, JP2 y JP8 de la PICO-PI-GL [30].
Figura 2.13: Configuración de los jumpers J1 y J2, para alternar entre los
modos: Descarga Serial e Inicio desde la eMMC [30].
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.
AFE ADS1298
Ofrece una alta resolución de hasta 24 bits, lo que permite una adquisisción
precisa de las señales bioeléctricas.
AFE BMD101
Detección de LOFF: Cualquier resistencia entre las dos entradas del sensor
que exceda impedancia de la piel activará la detección del LOFF.
UART: cuenta con interfaz UART de 57600 bauds, 8 bits de datos, sin
paridad.
Nota: recordar que el USB 2.0 tiene un fanout 7 de 500mA; las 4 salidas del hub
no deben superar esa corriente.
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
El PIC18F4620
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.
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.
I: LA-RA =0.971mV ∼ 1 mV
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.
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
Bootloader
Sistema Operativo
FreeRTOS
BSP de FreeRtos
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.
61
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 62
Cargar el bootloader
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.
pico-imx7-imx6ul-imx6ull_otg-installer_20170112.zip
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.
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
3. Usar el comando lsblk (List Blocks Devices); este comando se utiliza para
listar los bloques de memoria.
Figura 3.5: Salida de la consola del procesador auxiliar imagen con problema
override reserved memory.
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 .
[ 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
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
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:
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
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:
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:
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
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
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
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.
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
$ df -h
$ top
$ swapon
$ free -m
$ wath -n 1 free -m ( informa sobre el almacenamiento
,→ disponible y lo lista cada segundo )
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
Para delimitar el tamaño usado por journal en disco a por ejemplo 50M:
$ sudo journalctl -- vacuum - size =50 M
Se puede igual, delimitar el número de archivos journal a crear (en dı́as conse-
cutivos):
$ sudo journalctl -- vacuum - files =2
(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
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].
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.
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.
la plataforma que están bajo el control del núcleo M4 que se encuentran definidos
en el directorio board.
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.
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.
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
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:
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.
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
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]
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
Máximo brillo:
$ echo 100 > brightness
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
5. Verifique con uno de los ejemplos (del menu de ejemplos) que el intérprete
del PDE funciona.
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.
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:
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.
5. VirtIO-net: Gracias. Hola VM, aquı́ está la página web que solicitaste.
En el procesador maestro:
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
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):
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
*/
Requerimientos de Hardware
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 )
Figura 3.35: Salida consola serial auxiliar M4 esclavo en la espera del maestro.
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
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
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
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.
Ejecución
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.45: Modo 1 comunicación SPI para ADS1298 Texas Instruments [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.
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).
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).
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
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
return 1;
}
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 138
return 1;
}
}
else { // turn channel off
writeVals [ j ] =
,→ ADS1298_CHSET_PD | ADS1298_CHSET_MUX_SHORT ;
}
}
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.
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.
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:
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.
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:
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.
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
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) ;
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 ) ;
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
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 ) {
}
}
Capı́tulo 3. Configuración de las Plataforma y Desarrollo Experimental 159
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;
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 ) ;
if ( IS_ERR ( file ) ) {
dev_err (& rpdev - > dev , " Failed to
,→ open file : %s \ n " , filename ) ;
return PTR_ERR ( file ) ;
}
filp_close ( file , NULL ) ;
}
return 0;
}
2. Se define la ruta del archivo donde se guardarán los datos recibidos a través
del canal RPMsg.
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 ) ;
}
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 ;
}
return total ;
}
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.
8. Se inicia un bucle do-while para enviar los datos a través del canal RPMsg
en fragmentos.
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.
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 ) ;
rpmsgtty_driver = tty_alloc_driver (1 ,
,→ TTY_DRIVER_UNNUMBERED_NODE ) ;
if ( IS_ERR ( rpmsgtty_driver ) ) {
kfree ( cport ) ;
return PTR_ERR ( rpmsgtty_driver ) ;
}
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 ;
}
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.
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.
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
,→ " ) ;
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 " } ,
{} ,
};
descarga (module exit), estas funciones se utilizan para iniciar y finalizar el con-
trolador respectivamente.
# 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 incluye un bloque <style> para definir estilos CSS que afectarán la apa-
riencia de la página.
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
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;
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 ;
}
}
}
}
};
data : data ,
options : options
}) ;
}
function updateChart () {
numSamples =
,→ parseInt ( numSamplesInput . value ) ;
lineThickness =
,→ parseInt ( lineThicknessInput . value ) ;
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
var sumOfRRIntervals =
,→ peaks . slice (1) . reduce (( sum , peak , index ) = > sum +
,→ ( peak - peaks [ index ]) , 0) ;
var averageRRInterval = sumOfRRIntervals /
,→ ( peaks . length - 1) ;
return heartRate ;
}
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) ) ) ;
}
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 ) ;
Verifique con:
$ echo $ DISPLAY
Este método se puede usar para consultar y graficar los datos con la aplicación
de Kst2; pero utilizando un ordenador remoto.
Resultados
187
Capı́tulo 4. Resultados 188
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:
Los datos usados para generar este gráfico pueden verse en el Apendice B 4.4.
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
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
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
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.
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.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
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
200
Capı́tulo 4. Resultados 201
[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.
[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.
[23] A. Stec, “Ssl vs. ssh,” last updated: July 26, 2023. [Online]. Available:
https://www.baeldung.com/cs/ssl-vs-ssh
[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
[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.
[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
[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/
[45] Technexion, “Using ’uuu’ to flash e.mmc,” YouTube video, 2022. [Online].
Available: https://www.youtube.com/watch?v=PcROg80aTYI
[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.
[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
[65] ——, “Freertos en pic18,” Artı́culo, Noviembre 2022, disponible en: https:
//compilando-pico-pi-imx7.blogspot.com/2022/11/freertos-en-pic18.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
[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
[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.
[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
208
Apéndice B
209
Apéndice B. 210