La cirugía en el IDE de Arduino aumenta los búferes de serie Deja un comentario

Es bastante conocido que no soy un gran admirador de la infraestructura de Arduino. Por supuesto, en estos días tienes más opciones con pro IDE y Platform IO, por ejemplo. Pero el IDE original siempre me da ardor de estómago. Me di cuenta de cuánto ardor de estómago el otro día cuando quería algo muy simple: aumentar el búfer de recepción en un puerto serie ATmega32. La solución a la que llegué podría ayudarlo a hacer otras cosas, por lo que incluso si no necesita esa función exacta, aún puede resultarle útil ver lo que hice.

Después de esta experiencia, estoy realmente desgarrado. Por un lado, desprecio al editor mediocre por ocultarme demasiados detalles y proporcionar muy pocas herramientas útiles. Por otro lado, me impresionó lo extensible que era si se podían extraer los detalles de cómo funciona internamente.

Primero, te preguntarás por qué uso el IDE. La respuesta corta es que no. Pero cuando produce cosas para que otras personas las usen, casi no puede ignorarlas. No importa cómo cree su entorno personal, en el momento en que su código llegue a Internet, alguien intentará usarlo en el IDE. Hace un tiempo escribí sobre computadora Z80 de $ 4 por [Just4Fun] . Raramente tengo tiempo para construir cosas sobre las que escribo, pero realmente quería probar esta pequeña computadora. Las partes permanecieron parcialmente ensambladas por un tiempo y luego salió un PCB. Obtuve el PCB y, lo adivinaste, se sentó un poco más, parcialmente ensamblado. Pero finalmente encontré tiempo para terminarlo y puse en marcha CP / M.

El único problema era que no había muchas buenas opciones para transferir datos de un lado a otro a la PC. Parecía que la mejor opción era hacer archivos hexadecimales de Intel y transferirlos copiar y pegar a través del terminal. Quería algo mejor, y eso me envió a una madriguera de conejos el sábado por la mañana. Lo que terminé con es una forma de hacer sus propios menús en el IDE de Arduino para establecer opciones de compilación basadas en el hardware de destino para el proyecto. Es un truco que vale la pena conocer, ya que será útil más allá de este único problema.

El problema: Límite de tamaño del búfer serie Arduino

No te aburriré con los detalles sobre cómo hacer que el tablero funcione, ya que solo te importará si tienes uno. Los detalles están disponibles en una discusión en Hackaday.io , si realmente quieres seguirlo. Pero el resultado fue que para las transferencias XModem, [Just4Fun] sintió que el búfer serie Arduino predeterminado no era lo suficientemente grande como para ser confiable. Parecía funcionar con el búfer de 64 bytes predeterminado, pero XModem envía más datos que eso y sería fácil imaginar que se desborde.

¿Qué tan difícil puede ser actualizar el búfer? En cierto sentido, es trivial. De otra manera, es muy difícil porque las herramientas quieren ayudarte mucho.

Cadena de herramientas

El pequeño proyecto de computadora usa un chip Z80 real y usa un ATMega32A para casi todas las funciones de soporte. Genera el reloj, actúa como un puerto serie, actúa como una unidad de disco, etc. Sin embargo, ATMega32 no cuenta directamente con soporte Arduino IDE, por lo que debe instalar una cadena de herramientas. El proyecto requería MightyCore, así que eso es lo que usé.

Las bibliotecas para la serie de hardware se configuraron utilizando #definir declaraciones para permitirle ajustar los tamaños del búfer. De forma predeterminada, si no ha configurado nada, obtendrá un valor predeterminado basado en la cantidad de RAM que proporciona su procesador:

#if! definido (SERIAL_TX_BUFFER_SIZE)
#if ((RAMEND - RAMSTART) & lt; 1023)
#define SERIAL_TX_BUFFER_SIZE 16
#más
#define SERIAL_TX_BUFFER_SIZE 64
#terminara si
#terminara si
#if! definido (SERIAL_RX_BUFFER_SIZE)
#if ((RAMEND - RAMSTART) & lt; 1023)
#define SERIAL_RX_BUFFER_SIZE 16
#más
#define SERIAL_RX_BUFFER_SIZE 64
#terminara si
#terminara si

Haciendo el cambio

Entonces esto es fácil, ¿verdad? Simplemente defina esos símbolos antes de cargar HardwareSerial.h . UH oh. Ese archivo es cargado por Arduino.h . El IDE quiere agregar eso a su programa y lo obliga a ser el primero. Parece que hay algunas versiones de IDE que comprueban si ya lo incluiste para que no lo incluyan dos veces, pero la versión 1.8.5 no parecía hacer eso. Tal vez pueda agregar algunas opciones en las preferencias para pasar al compilador. No No a través del IDE, de todos modos.

No es que no haya intentado muchas cosas. Era tentador, por supuesto, simplemente cambiar las bibliotecas principales. Pero eso es malo. Es posible que desee los valores predeterminados más tarde. Si actualiza la cadena de herramientas, perderá sus actualizaciones. Quería evitar eso. Algunas personas en Internet sugirieron hacer una copia de los archivos de la plataforma y modificarlos. Todavía no es lo ideal.

Pruebe sus suposiciones con informes de errores personalizados

Podría decir que las cosas que intenté no funcionaban porque pondría #if declaraciones y #error declaraciones temporalmente en HardwareSerial.cpp . Por ejemplo:

#if SERIAL_RX_BUFFER_SIZE == 256
#error 256
#terminara si

Ahora, si una compilación causa un error 256, sé que pude establecer el tamaño. Si no, entonces el sistema se resistía a mis cambios.

Compromiso: Agregar opciones de menú a nivel de placa

Realmente quería una forma de hacer un cambio solo en mi proyecto y establecer los tamaños del búfer en serie. Fallé en eso. Lo que hice fue hacer una modificación en los tableros .txt proporcionado por Mighty Core. Sí, tendré que estar atento a las actualizaciones que sobrescriban mis cambios, pero son simples y será obvio que faltan.

La razón por la que será obvio es que creé un menú para el IDE que solo aparece cuando uso ATMega32 para Mighty Core. Este menú le permite seleccionar algunos tamaños de búfer preestablecidos.

Había tres partes para hacer que esto funcionara:

  1. Tienes que decirle al IDE que tienes un elemento de menú y cómo se ve.
  2. El nuevo elemento necesita establecer algunas opciones del compilador.
  3. Debido a que el sistema existente también establece algunas opciones de compilación, debe asegurarse de no golpearlas.

La primera parte es fácil. El archivo boards.txt estaba (para mí) en ~ / .arduino15 / packages / MightyCore / hardware / avr / 2.0.5 / boards.txt . Cerca de la parte superior hay una lista de teclas de menú y agregué las mías al final:

# Opciones de menú
menu.clock = Reloj
menu.BOD = BOD
menu.LTO = Compilador LTO
menu.variant = Variante
menu.pinout = Pinout
menu.bootloader = Bootloader
menu.SerialBuf = Búferes de puerto serie (RX / TX)

Luego, bajé el archivo y agregué mi menú antes de la opción de menú LTO existente para ATMega32:

32.menu.SerialBuf.disabled = Predeterminado
32.menu.SerialBuf.disabled.compilerSB.c.extra_flags =
32.menu.SerialBuf.disabled.compilerSB.cpp.extra_flags =

32.menu.SerialBuf.SB64 = 64/64
32.menu.SerialBuf.SB64.compilerSB.c.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 64 -DSERIAL_TX_BUFFER_SIZE = 64
32.menu.SerialBuf.SB64.compilerSB.cpp.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 64 -DSERIAL_TX_BUFFER_SIZE = 64

32.menu.SerialBuf.SB128 = 128/128
32.menu.SerialBuf.SB128.compilerSB.c.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 128 -DSERIAL_TX_BUFFER_SIZE = 128
32.menu.SerialBuf.SB128.compilerSB.cpp.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 128 -DSERIAL_TX_BUFFER_SIZE = 128

32.menu.SerialBuf.SB12864 = 128/64
32.menu.SerialBuf.SB12864.compilerSB.c.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 128 -DSERIAL_TX_BUFFER_SIZE = 64
32.menu.SerialBuf.SB12864.compilerSB.cpp.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 128 -DSERIAL_TX_BUFFER_SIZE = 64

32.menu.SerialBuf.SB256 = 256/256
32.menu.SerialBuf.SB256.compilerSB.c.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 256 -DSERIAL_TX_BUFFER_SIZE = 256
32.menu.SerialBuf.SB256.compilerSB.cpp.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 256 -DSERIAL_TX_BUFFER_SIZE = 256

32.menu.SerialBuf.SB25664 = 256/64
32.menu.SerialBuf.SB25664.compilerSB.c.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 256 -DSERIAL_TX_BUFFER_SIZE = 64
32.menu.SerialBuf.SB25664.compilerSB.cpp.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 256 -DSERIAL_TX_BUFFER_SIZE = 64

32.menu.SerialBuf.SB25632 = 256/32
32.menu.SerialBuf.SB25632.compilerSB.c.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 256 -DSERIAL_TX_BUFFER_SIZE = 32
32.menu.SerialBuf.SB25632.compilerSB.cpp.extra_flags = -DSERIAL_RX_BUFFER_SIZE = 256 -DSERIAL_TX_BUFFER_SIZE = 32

Estructura del menú

Puede ver que el objeto 32.menu agrupa todos los elementos para este procesador. La siguiente parte es nuestra tecla de menú ( SerialBuf ). Después de eso, hay una clave única para cada elemento de memoria. Es importante que no reutilices estos. Entonces, por ejemplo, si tiene dos teclas SB64 , solo una funcionará.

Si se detiene en esa tecla y pone un signo igual, puede asignar al elemento del menú el texto que desea mostrar. Por ejemplo, “Predeterminado” o “64/64”. También puede extender la clave con una propiedad y esa propiedad se establecerá si la opción está activa.

Entonces, por ejemplo, si selecciona 256/256, se establecerá la propiedad compilerSB.c.extra_flags . He inventado ese nombre, por cierto, y verás por qué en un minuto.

Convivencia pacífica

No hay ninguna propiedad llamada compilerSB.c.extra_flags . La propiedad correcta es compiler.c.extra_flags . Sin embargo, la opción Mighty Core LTO usa la misma clave. Por eso es importante que el nuevo menú aparezca primero y también que establezca una propiedad falsa. Entonces el código LTO necesita una ligera modificación:

# Optimización del tiempo de enlace del compilador
32.menu.LTO.Os = LTO deshabilitado
32.menu.LTO.Os.compiler.c.extra_flags = {compilerSB.c.extra_flags}
32.menu.LTO.Os.compiler.c.elf.extra_flags =
32.menu.LTO.Os.compiler.cpp.extra_flags = {compilerSB.cpp.extra_flags}
32.menu.LTO.Os.ltoarcmd = avr-ar

32.menu.LTO.Os_flto = LTO habilitado
32.menu.LTO.Os_flto.compiler.c.extra_flags = {compiladorSB.c.extra_flags} -Wextra -flto -g
32.menu.LTO.Os_flto.compiler.c.elf.extra_flags = -w -flto -g
32.menu.LTO.Os_flto.compiler.cpp.extra_flags = {compilerSB.cpp.extra_flags} -Wextra -flto -g
32.menu.LTO.Os_flto.ltoarcmd = avr-gcc-ar

El gran cambio es que cada conjunto de banderas se agrega a cualquier conjunto de menú nuevo en su propiedad personalizada. De esta manera, todas las banderas se colocan en la propiedad correcta, compiler.c.extra_flags .

Configuré trampas de error para detectar todos los casos y asegurarme de que estaban siendo corregidos. Además, después de eliminar esas trampas, pude ver que el uso de mi memoria aumentaba en consecuencia.

Personalizar

Por supuesto, puede modificar los parámetros si desea algo diferente. También podría usar este truco para establecer otros parámetros antes de que el archivo Arduino.h se haga cargo. Hay documentación sobre cómo configurar las definiciones de la plataforma, incluyendo boards.txt .

Probablemente hubiera sido mejor para mí hacer un archivo personalizado boards.txt con la misma información, pero luego tendría que llevar el resto de Mighty Core conmigo. En cambio, solo guardo una copia del archivo llamado boards.txt.custom y si mi menú desaparece, solo tengo que comparar ese archivo con el archivo boards.txt para ver qué cambió.

Por supuesto, si no tiene que apoyar a las personas que usan el IDE, tal vez simplemente renuncie. El Pro IDE es mejor, incluso si tiene algunas deficiencias. Además, siempre hay Platform.io .

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Enviar Whatsapp
Hola 👋
¿En qué podemos ayudarte?