Desarrollado en La-Tecnologia: a veces todo lo que necesitas son pocas banderas

El desarrollo de la contraseña sin conexión de la comunidad de La-Tecnologia está tardando un poco menos de un año. Desde julio, nuestros probadores beta han estado trabajando duro para brindarnos sugerencias constantes sobre las funciones que les gustaría realizar y las mejoras que el equipo de desarrollo podría realizar. Esto llevó a más de 1100 compromisos de GitHub y diez mil líneas de código. Como puede adivinar, nuestro microcontrolador de bolsillo de 8 bits comenzó a llenarse con bastante rapidez.

Uno de nuestros colaboradores, [Miguel], descubrió recientemente una compilación y un enlace que nos hizo ahorrar alrededor de 3 KB de almacenamiento Flash en nuestro firmware de 26 KB con poco procesamiento adicional. Mantén tus sombreros puestos, esta entrada se volverá técnica ...

Muchos codificadores de todo el mundo están trabajando en el firmware de Mooltipass al mismo tiempo. Dependiendo de la funcionalidad que quieran implementar, se les asigna un directorio dedicado para que funcionen. Lógicamente, el código que producen se divide en muchas funciones en C dependiendo de la tarea requerida. Esto agrega muchas características que el compilador GCC generalmente usa con el LLAMADA maestro de asamblea.

Esta instrucción particular de 8 bits utiliza un valor de 22 bits que contiene la dirección absoluta de la función de llamada. Por lo tanto, se usa un total de 4 bytes de relámpago para una llamada de función (sin pasar argumentos). Sin embargo, las instrucciones del AVR también contienen otra forma de llamar a funciones usando direccionamiento relativo. Esta instrucción es RCALL y utiliza un valor largo de 11 bits que contiene el desplazamiento entre el contador del programa actual y la función a llamar. Esto reduce la llamada funcional a 2 bytes y dura un ciclo de reloj menos. La bandera -mrelax, por lo tanto, nos hizo ahorrar 1KB al tener el enlace LLAMADA con RCALL instrucciones siempre que sea posible.

Finalmente, el -mcall prólogos El indicador del compilador liberó 2 KB de almacenamiento Flash. Crea rutinas principales de prólogo / epílogo que se llaman al principio y al final de las rutinas de programación. Para simplificar las cosas, prepara la pila AVR y registra de la misma manera antes de realizar cualquier función. Por lo tanto, esto desperdiciará algo de tiempo de ejecución y ahorrará mucho espacio en el código.

Se pueden encontrar más técnicas de ahorro haciendo clic en este enlace. ¿Quieres estar atento a la fecha de lanzamiento de Mooltipass? ¡Suscríbete a nuestros Grupos de Google oficiales!

  • canon dice:

    No olvide incluir funciones que solo se utilizan una vez.

    • Mathieu Stephan dice:

      ¡sí! lo hemos hecho varias veces.
      También comparamos funciones de declaración de ahorro de espacio flash como en línea según la cantidad de veces que se llamaron.

  • el gancho dice:

    ¿Los bucles de desenrollado son solo una escena de demostración de 6502?

    • Hombre sin marcar dice:

      No, pero el desenrollado de bucles es una optimización rápida que cuesta espacio en el código. A Mooltipass le falta espacio de código.

  • Depositar dice:

    No soy un experto en estas cosas, pero me pregunto si su desarrollo lleva un tiempo inusualmente largo. Con las indies escuché que es muy rápido y necesitas las finanzas rápidamente para sostener un esfuerzo general. Tal vez su versión beta se lance como un producto si la desarrolla alguien que trabaja solo en ella. O tal vez sea un trabajo a tiempo parcial. De todos modos, curioso. Muy bien, estás hablando de desarrollarlo.

    ¿Alguna razón en particular para optimizar su mcu en lugar de comenzar con una más grande?

    • Mathieu Stephan dice:

      Bueno, también hay mucho desarrollo en el lado del software (complementos adicionales, scripts de Python para generar paquetes), y ahora que tenemos probadores beta, también estamos cambiando algunas cosas.
      Todos nos desarrollamos en nuestro tiempo libre.
      La razón principal por la que nos quedamos con este MCU es la compatibilidad con arduino. De todos modos, hasta ahora ha sido lo suficientemente bueno para nuestro uso.

  • Tyler dice:

    Ahorré mucho espacio cambiando:
    conjunto vacío (bool activado) {
    visto) {
    P1OUT | = 1;
    } otro {
    P1OUT & = ~ 1;
    }
    }

    En dos convocatorias:

    setLEDOn vacío () {
    P1OUT | = 1;
    }

    setLEDOff vacío () {
    P1OUT & = ~ 1;
    }

    El primero no suele aparecer en la lista y debe pasar arg. El segundo siempre estaba en la fila. Esto depende del uso de setLED, por supuesto, en mi código siempre pone el LED en un estado estático; ya sea verdadero o falso. ¡A veces más es menos!

  • Ralph Doncaster (Nerdo Ralph) dice:

    El uso de la optimización de enlaces (-flto) debería reducir el tamaño aún más.
    http://nerdralph.blogspot.ca/2014/04/gcc-link-time-optimization-can-fix-bad.html

    • Mathieu Stephan dice:

      Guardar código con esta bandera parece ser una buena métrica para saber si un codificador es bueno: para nuestra solución, ¡en realidad aumenta la velocidad del rayo en 24 bytes!

      • Ralph Doncaster (Nerdo Ralph) dice:

        Eso es un poco sorprendente. Con 4.8.3 y 4.9.1 todavía no he visto un ejemplo en el que lto, cuando se usa con todas las bibliotecas vinculadas al elf, aumenta de tamaño.
        ¿Qué versión de gcc estás usando?

        • Mathieu Stephan dice:

          para mí sería 4.8.1, les pediré a los demás contribuyentes que prueben la bandera y me hagan saber sus ahorros

      • Ralph Doncaster (Nerdo Ralph) dice:

        Solo mira el gitube y parece que estás usando el IDE de Arduino.
        Arduino crea librerías de una manera original, lo que puede provocar problemas con lto.
        http://nerdralph.blogspot.ca/2014/07/gcc-lto-call-graph-generation.html

        Usar Ino (inotool.org) le daría más control sobre el proceso de construcción. Y sería más fácil usar gcc 4.9.1 en contra de intentar integrarlo con el IDE de Arduino. Estoy seguro de que las versiones nocturnas de Arduino 1.5 beta todavía funcionan con 4.8.1 (tal vez con algunos parches).

        • Mathieu Stephan dice:

          no usamos Arduino IDE para fw dev.
          Algunos colaboradores usan avrstudio, otros makefile

  • charliex dice:

    Me sorprende que esta no sea una optimización predeterminada, el código relativo a la computadora es extremadamente común. aunque es gcc, no me sorprende mucho.

    • daid303 dice:

      No todos los códigos funcionarán con -mrelax (consulte el manual de gcc para obtener más detalles)

      • charliex dice:

        sí, estaba más relacionado con la naturaleza relativa de la computadora del gen de código vs relax, que no es también el artículo al que se alude. Asumiría que el código no funcional está demasiado lejos para un salto relativo y, sin embargo, sería una advertencia. De lo contrario, no veo ninguna especificación en el manual de gcc, sin embargo, podría haber algunos errores relacionados. agregue más pragma / atributos, etc.que no he visto.

  • charliex dice:

    si a nadie le importa un poco de golf de código (ja, ja) ... si tuviera que estresarme por el espacio de código / datos, aquí hay algunas cosas que consideraría después de la optimización prematura, cada una es caso por caso con pruebas cuidadosas para ver si más o menos, no solo cambió globalmente sin verificar (como en la codificación en línea) y solo eché un vistazo a fragmentos de código leyendo café y ordenando 80/20, sino que también son consejos generales.

    conjunto de indicadores de verdadero / falso en 8 bits, utilice campos de bits en su lugar cuando sea posible.
    muchos búferes de tiempo cuando sea posible y las condiciones de reingreso / carrera no ocurrirán, considere un búfer global con accesos indirectos, esto es doble porque reduce el uso de la pila y puede reducir el tamaño del código si se implementa correctamente, si puede usar funciones desnudas sin diseño de pila, por ejemplo, quizás algunas ganancias de dirección relativas
    mueva globos individuales en estructuras, esto le dará una dirección relativa.
    volátil puede ser costoso, muchos optimizadores solo se detendrán prematuramente cuando vean uno, así que considere esto
    static no es constante, asegúrese de que los datos estén listos para que su constante (a menos que tenga más RAM que espacio de código) sea igualmente válida para punteros o matrices de puntos, a menudo la gente se olvida de hacer que ambos lados de los punteros sean const

    • Mathieu Stephan dice:

      Hola Charliex,

      De hecho, hablamos sobre el uso de un búfer global, pero por ahora preferimos usar búferes de tiempo porque tenemos una función dedicada que controla el uso de la pila y preferimos la claridad del código :).
      ¿Tiene alguna literatura sobre las ventajas de los bienes persistentes en las llamadas funcionales? Ese es un tema bastante interesante.

      • charliex dice:

        const vars es un nombre inapropiado, solo tomo datos legibles (error tipográfico solo en mi publicación anterior)
        así que si tiene una estructura de datos rellena y simplemente legible, marcarla estáticamente solo cambia su alcance, no la saca de la RAM, volviendo a lo que es más costoso para su RAM o rom.

        so static const versus static para bases de datos de RO predefinidas, para conjuntos de punteros const * const ptr; vs const * ptr;

        No estoy de acuerdo con la claridad del código de usar un búfer dividido contra las horas locales, puede mantener la legibilidad del código, porque en lugar de una matriz automática local fija, es solo un puntero de alias que todos los enfoques tienen el mismo aspecto. También es tan simple como agregar guardias de reemplazo a un búfer global contra una pila automática, porque si mata la pila, mata la ejecución y la recuperación limitada.

        Puede seguir utilizando la monitorización, pero también considere cuánto espacio automático necesita, los dispositivos integrados obviamente funcionan en un espacio limitado, por lo que desea que todos sus datos sean de tamaños fijos, porque tal es el caso que puede pre-distribuir en el búfer global, sin embargo, no puede exceder el máximo.

        Hace que sea difícil asegurarse de que pueda volver a ingresar o enhebrar varios, etc., pero si es un código completamente simple, no es un problema, agregar protectores de código se encarga de eso.

        la mayor parte, si no todo, de esto (incluida la relajación) se aborda en las notas avr-gcc.

        http://www.atmel.com/images/doc8453.pdf

        http://www.tty1.net/blog/2008/avr-gcc-optimisations_en.html

        • Mathieu Stephan dice:

          Hola charliex,

          De hecho, la mayoría de los datos de solo lectura se almacenan en PROGMEM o en la memoria flash externa (gráficos, consulte dir bitmaps).
          Eres bueno en el búfer común ... ¡Reiniciaré una discusión con el equipo!

          Gracias

          • charliex dice:

            anim.c era un lugar, en mi opinión, miré la inconsistencia estática que parecía ser usado RO y no en PROGMEM. ¿A qué se sitúa la alineación estructural?

          • arlequín dice:

            El código anim.c se está procesando y no representa el resto del código. Estas estructuras estáticas se convertirán en medios en el relámpago SPI.

            El AVR se alinea a 8 bits.

          • arlequín dice:

            Además, en el AVR, la creación de una estructura const no la mueve al espacio de código. Debe colocarlo explícitamente en la sección del programa para lograr esto y luego usar funciones especiales para acceder a él.

            Consulte http://www.nongnu.org/avr-libc/user-manual/pgmspace.html para obtener más detalles.

  • Galane dice:

    ¿Puede almacenar cada función solo una vez en el código y luego usar tokens mucho más cortos que muestren la ubicación de cada función? Para cualquier función utilizada dos o más veces, se ahorraría espacio.

    Texas Instruments utilizó este método en su Extended BASIC.

  • RobHeffo dice:

    Si el proyecto alcanza los límites de los recursos disponibles en la MCU al desarrollar el firmware de suministro, dificultará las actualizaciones y las correcciones.

    Además, al ser un dispositivo diseñado para ser abierto y pirateable, casi bloqueará a aquellos que quieran agregar sus propias funciones al firmware original porque no tienen un espacio flash para que lo usen.

    Definitivamente necesito una MCU más grande.

    • Mathieu Stephan dice:

      Pues bien, el punto principal de este artículo fue decir que ahora tenemos mucho espacio para los usuarios que quieran realizar sus propias funciones ...

Ricardo Prieto
Ricardo Prieto

Deja una respuesta

Tu dirección de correo electrónico no será publicada.