通过单个 GPIO 引脚转储闪存

use*_*425 5 c embedded reverse-engineering firmware gpio

我正在使用 Infineon 的 XMC4500 Relax Kit,我正在尝试通过单个 GPIO 引脚提取固件。

我非常天真的想法是通过 GPIO 引脚一次转储一位,然后用逻辑分析仪以某种方式“嗅探”数据。

伪代码:

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

我在正确的轨道上吗?有没有人有更好/更好的想法如何存档?

### 编辑 ###

实际上我的(shell)代码的一个要求是它需要非常小。我发现了这个关于如何通过闪烁 LED 转储固件的绝妙技巧。

但是,我正在努力使用 Saleae Logic Analyzer 接收正确的值。

基本上我正在做的是:

  1. 设置GPIO引脚方向输出
  2. 用时钟(SPI 串行时钟)闪烁 LED1(引脚 1.1)
  3. 用数据位 (SPI MOSI) 闪烁 LED2(引脚 1.0)
  4. 使用逻辑分析仪嗅探引脚

这是我的 C 代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

###第二次编辑###

使用以下代码转储闪存工作正常:

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

Cli*_*ord 5

您的解决方案的最大问题是恢复时间信息 - 知道一个词从哪里开始,另一个词在哪里结束。在 UART tx 引脚上输出数据会更简单 - UART 添加开始和停止位并为您管理时序,并且可以通过常规 PC 串行端口直接读取输出。

如果您不能使用 UART,通过使用 UART 时序对 GPIO 进行位组合来模拟 UART 仍将允许使用传统的串行端口直接接收数据。

可以在此处找到示例软件 UART实现。在您的情况下,您当然只需要传输功能。


The*_*sey 3

根据您的要求,这可能会正常工作。需要考虑的是,在循环数据时是否存在任何时序变化,例如闪存读取时间变化、缓存内容等,您将遇到确定字节开始和停止位置的问题。您可能想看一下 1-Wire 协议:

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

您不必按照规范或其他方式实现它,只需看一下它就可以了。如果你实现类似的东西,你的逻辑就很简单:

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