Código minúsculo para descargar memoria Flash

2

Estoy tratando de escribir el código más pequeño posible para extraer el firmware de microcontrolador XMC4500 de Infineon .

El código debe caber en un búfer de bytes 30 que me permite tener 15 instrucciones de la máquina usando el conjunto de instrucciones del pulgar de 16 bits.

Comenzando con C, mi intento es volcar la memoria flash a través de un solo pin GPIO (vea la pregunta original) siguiendo este truco ingenioso.

Básicamente, lo que estoy haciendo es:

  1. Configure las direcciones de los pines GPIO para la salida
  2. Blink LED1 (pin 1.1) con un reloj (reloj serial SPI)
  3. Blink LED2 (pin 1.0) con bits de datos (SPI MOSI)
  4. Olfatear pines con un analizador lógico

EDIT:

  1. ACTUALIZAR BLOQUE DE CÓDIGO C
  2. AGREGAR EL BLOQUE DEL CÓDIGO DE ASAMBLEA
#include "XMC4500.h"

void main() {
  // start dumping at memory address 0x00000000
  unsigned int* p = (uint32_t *)(0x0u);

  // configure port1 output (push-pull)
  PORT1->IOCR0 = 0x8080u;

  for(;;) {
    int i = 32;

    int data = *(p++);

    do {
      // clock low
      PORT1->OUT = 0x0;

      // clock high with data bits
      PORT1->OUT = 0x2u | data;

      data >>= 1;

    } while (--i > 0);
  }
}
main:
    ; PORT1->IOCR0 = 0x8080UL
    ldr r1, =0x48028100 ; load port1 base address to R1
    movw r2, #0x8080 ; move 0x8080 to R2
    str r2, [r1, #0x10]

main_1:
    ; start copying at address 0x00000000
    ; R12 is known to be zeroed
    ldr.w r2, [r12], #0x4 ; int data = *(p++)
    movs r3, #32 ; int i = 32

main_2:
    ; PORT1->OUT = 0x0
    ; clock low
    ; R12 is known to be zeroed
    str r12, [r1]

    ; PORT1->OUT = 0x2 | data
    ; clock high with data bits
    orr r4, r2, #0x2
    str r4, [r1]

    asrs r2, r2, #0x1 ; data >>= 1

    subs r3, r3, #0x1 ; i--
    bne.n main_2 ; while (--i > 0)
    b.n main_1 ; while(true)

Sin embargo, el tamaño del código sigue siendo demasiado grande para cumplir mis requisitos.

¿Hay algo que pueda hacer para reducir aún más mi código? ¿Algo que pueda optimizarse o dejarse fuera?

    
pregunta user3696425

2 respuestas

4

No estoy acostumbrado a programar para procesadores ARM y no sé qué compilador usas, así que quizás los cambios propuestos no hagan nada en absoluto, pero bueno, ¡al menos intentemos!

1-Inline tus funciones:

Un buen compilador ya debería incluir una función en línea si las optimizaciones están bien configuradas, pero vale la pena integrarlo para que elimines las llamadas y las rets

2-Evitar la ramificación:

En algunas arquitecturas, un IF se puede traducir en: cargar, probar, ramificar, tres instrucciones, si puedes hacerlo sin ramificar, puedes usar menos instrucciones.

Por lo tanto, el código propuesto es:

    int main() 
    {
      // start dumping at memory address 0x08000000
      unsigned int *p;
      int i;

      p = (uint32_t *)(0x08000000u);

      // configure pin 1.0 and pin 1.1 as output (push-pull)
      PORT1->IOCR0 = 0x8080UL;

      do
      {
        for (i = 0; i < 32; i++)
        {
          // set pin 1.1 to low (SPI clock)
          PORT1->OUT &= (~0x2UL);
          PORT1->OUT = (PORT1->OUT & 0xFFFE) | (data & 0x01)
          PORT1->OUT |= 0x2UL;
          data >>= 1;
        }

      }while(p++)
    }

Inténtalo y comenta los resultados.

    
respondido por el Gusman
1

Esto supone que su programa de 32 bytes es el único código disponible en el chip. No se permiten llamadas externas.

Una preocupación con su código C sería la inclusión y el uso del encabezado "XMC4500.h". Aunque solo está utilizando la estructura "PORT1" para que el resto se optimice, todavía creo que puede obtener un acceso de registro GPIO más eficiente que eso.

Segundo, por su ausencia de información sobre la "configuración del proyecto" , asumo que no ha tomado ninguna medida para forzar a su vinculador a que exprima su código a una ubicación específica, para omitir la tabla de interrupciones , código de inicialización, etc. Es posible que desee ver aquí . Básicamente, lo que dice es que al modificar los archivos .ld / .lds puede forzar al vinculador a colocar secciones específicas de código en direcciones específicas.
Tal script podría verse así:

SECTIONS {
        . = YOUR_DESIRED_ADDRESS; 
        .text : { * (.text); }
}

Editaré la respuesta a medida que surjan nuevas ideas.

    
respondido por el Dzarda

Lea otras preguntas en las etiquetas