Dump Flash Memory through a single GPIO pin

喜你入骨 提交于 2019-12-10 16:06:00

问题


I'm working with Infineon's XMC4500 Relax Kit and I'm trying to extract the firmware through a single GPIO pin.

My very naive idea is to dump one bit at a time through the GPIO pin and somehow "sniff" the data with a logic analyzer.

Pseudocode:

while(word by word memory copy hasn't finished)
  ...
  register = value;
  temp_value = value AND 0x1;
  pin = temp_value;
  value = value >> 1;
  ...

Am I on the right track? Does anybody have a better/nicer idea how to archive this?

### EDIT ###

Actually a requirement of my (shell)code would be that it needs to be really tiny. I found this nifty trick on how to dump firmware by blinking the LEDs.

However I'm struggling to receive correct values with Saleae Logic Analyzer.

Basically what I'm doing is:

  1. Setup the GPIO pin directions to output
  2. Blink LED1 (pin 1.1) with a clock (SPI serial clock)
  3. Blink LED2 (pin 1.0) with data bits (SPI MOSI)
  4. Sniff pins with a logic analyzer

Here's my C code:

#include "XMC4500.h"

#define DEL 1260

void init() 
{
  // P1.0 output, push pull
  PORT1->IOCR0 = 0x80UL << 0;
  // P1.1 output, push pull
  PORT1->IOCR0 |= 0x80UL << 8;
}

void delay(int i) { 
  while(--i) { 
    asm("nop\n"); 
    asm("nop\n"); 
  } 
}

// Sets a pin to high
// P1.0 = SPI MOSI
// P1.1 = SPI CLOCK
void output_high(int i) {
  // P1.0 high
  if(i == 0) {
    PORT1->OUT |= 0x1UL;  
  }

  // P1.1 high
  if(i == 1) {
    PORT1->OUT |= 0x2UL;
  } 
}

// Sets a pin to low
// P1.0 = SPI MOSI
// P1.1 = SPI CLOCK
void output_low(int i) {
  // P1.0 low
  if(i == 0) {
    PORT1->OUT &= (~0x1UL);
  }

  // P1.1 low
  if(i == 1) {
    PORT1->OUT &= (~0x2UL);
  }
}

// SPI bit banging
void spi_send_byte(unsigned char data)
{
  int i;

  // Send bits 7..0
  for (i = 0; i < 8; i++)
  {
    // Sets P1.1 to low (serial clock)
    output_low(1);

    // Consider leftmost bit
    // Set line high if bit is 1, low if bit is 0
    if (data & 0x80)
      // Sets P1.0 to high (MOSI)
      output_high(0);
    else
      // Sets P1.0 to low (MOSI)
      output_low(0);

    delay(DEL);

    // Sets P1.1 to high (Serial Clock)
    output_high(1);

    // Shift byte left so next bit will be leftmost
    data <<= 1;
  }
}

int main() {
  init();

  while(1) {
    spi_send_byte('t');
    spi_send_byte('e');
    spi_send_byte('s');
    spi_send_byte('t');
  }

  return 0;
}

### 2nd EDIT ###

Dumping flash memory is working fine with the following code:

#include "XMC4500.h"

// SPI bit banging
void spi_send_word(uint32_t data)
{
  int i;

  // LSB first, 32 bits per transfer
  for (i = 0; i < 32; i++)
  {
    // set pin 1.1 to low (SPI clock)
    PORT1->OUT &= (~0x2UL);

    // set line high if bit is 1, low if bit is 0
    if (data & 0x1) {
      // set pin 1.0 to high (SPI MOSI)
      PORT1->OUT |= 0x1UL;
    }
    else {
      // set pin 1.0 to low (SPI MOSI)
      PORT1->OUT &= (~0x1UL);   
    }

    // set pin 1.1 to high (SPI clock)
    PORT1->OUT |= 0x2UL;

    data >>= 1;
  }
}

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

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

  while(1) {
    spi_send_word(*p);
    p++;
  }
}

回答1:


The biggest problem with your solution is recovering the timing information - knowing where one word starts and another ends. It would be simpler to output the data on a UART tx pin - the UART adds start and stop bits and manages timing for you, and the output can be read directly via a regular PC serial port.

If you cannot use a UART, emulating a UART by bit-banging the GPIO with UART timing will still allow a conventional serial port to be used to receive the data directly.

An example software UART implementation can be found here. In your case of course you need only the transmit capability.




回答2:


That might work decently depending on your requirements. Something to consider will be if there are any timing variations at all while looping through the data such as flash read times varying, cache stuff, etc you will run into a problem figuring out where bytes start and stop. You might want to take a look at the 1-Wire protocol:

http://en.wikipedia.org/wiki/1-Wire

You don't have to implement it to spec or anything, just take a look at it for an idea. If you implement something like that your logic is just as simple:

while(word by word memory copy hasn't finished)
  ...
  register = value;
  temp_value = value AND 0x1;
  one_wire_send(temp_value);
  value = value >> 1;
  ...


来源:https://stackoverflow.com/questions/23978691/dump-flash-memory-through-a-single-gpio-pin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!