mgleria / OMXRealTime

0 stars 0 forks source link

Alignment and padding memory #7

Open mgleria opened 6 years ago

mgleria commented 6 years ago

Al migrar código desde una arquitectura menor (8bits) a esta de 16bits surge una dificultad en cuanto a la definición de tipos de datos y uso de la memoria. Es sabido que en cualquier arquitectura acceder a una posición de memoria impar es un problema a sortear. De lograrse, requiere muchas más intrucciones de código lo que impacta de lleno en la performance, y depende cómo se resuelva puede derivar en excepciones en tiempo de ejecución. Por este motivo, el compilador se toma el trabajo de alinear al tamaño WORD de la arquitectura todos los tipos de datos menores a esta, agregando bytes de relleno (padding) para que no existan accesos de datos en direcciones que no sean múltiplos de WORD (direcciones impares). Esto trae como consecuencia un aumento en la utilización de la memoria, pero una ganancia importante en la performance y una reducción en la cantidad de código máquina compilado. El problema que surge es en la generación e interpretación de las tramas que deben enviarse a través del MODEM al servidor. Con las optimizaciones realizadas por el compilador, la trama es algunos bytes mayor (3 en el caso de _trama_muestrat) y eso desplaza los campos que parsea el server cuando interpreta los datos recibidos. Posibles soluciones:

  1. El camino más directo a seguir desde mi perspectiva, es dejar al compilador que haga su trabajo, y adaptar del lado del servidor la interpretación de la nueva trama recibida. Esto podría llegar a ser compatible con el nuevo sistema que se está deslegando del lado del servidor.

  2. La segunda alternativa es enfocar el esfuerzo en tratar de lograr la equivalencia de las tramas, en detrimento de la performance y a riesgo de provocar excepciones en runtime. La ventaja de este enfoque es que para el servidor es transparente. Punto de partida

  3. Una tercera posibilidad podría ser, detectar los bytes de padding de alguna manera, y removerlos de bufferGPRS, que es el array donde codifico los datos en hexadecimal de la trama a enviar en ascii. De esta forma, desde el MCU gestiono la memoria de forma apropiada y no tengo que realizar cambios del lado del servidor. De ser viable la detección de los bytes de padding algoritmicamente sería el enfoque más apropiado.

Fuentes consultadas:

  1. http://www.microchip.com/forums/m965626.aspx
  2. https://stackoverflow.com/questions/38635235/explanation-of-packed-attribute-in-c
  3. http://c-faq.com/struct/align.esr.html
  4. https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member
  5. MPLAB® XC16 C Compiler User’s Guide (pág. 153 - packed attribute)
  6. https://stackoverflow.com/questions/4306186/structure-padding-and-packing
mgleria commented 6 years ago

Una posible línea de trabajo podría ser que el padding introducido por el compilador tenga un valor conocido. Luego analizar la estructura byte a byte en busca de ese valor padding para removerlo del buffer final a enviar. Primero hay que ver si el compilador me ofrece esa posibilidad, y luego si existe algún valor que pueda utilizar sin que se confunda con un dato real. Se puede hacer la búsqueda luego de confirmar que la estructura asociada tiene padding, de esta forma se reduce la posibilidad de un falso positivo.

mgleria commented 6 years ago

Comencé una prueba para entender:

  1. ¿Cómo se están almacenando las estructuras muestra, trama_muestra y bufferGPRS en memoria?
  2. ¿Cómo se están convirtiendo los datos desde las estructuras nativas al bufferGPRS (ASCII)?

Tengo por analizar una planilla con un dump de las 3 estructuras de datos extraidos de la interfaz de debug de MPLAB y un archivo de texto plano con un dump de la memoria completa. Por otra parte, está la planilla de documentación de las tramas (150402_Decodificacion_Trama_Estaciones 00.xlsx), puede ser útil también para entender como funciona para el PIC18 (8bits).

Cruzando estos datos, más la inicialización de las variables debería tener un panorama más claro de qué está pasando a nivel memoria.

mgleria commented 6 years ago

[EDITAR]

Por lo pronto lo que descubrí es que interpretaba mal el almacenamiento del float presion (IEEE-754) y localicé por el momento un sólo byte de padding luego de clima.viento.direccionP = 0x15; con un valor 0xFF.

Hay algún tema también con los char, revisar.

El último código me provoca un halt, revisar los cambios:

  1. Presion
  2. nullE
  3. reserved