转储闪存通过单一GPIO引脚

转储闪存通过单一GPIO引脚

本文介绍了转储闪存通过单一GPIO引脚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我与英飞凌XMC4500工作放松Kit和我试图通过一个单一GPIO引脚提取的固件。

我很天真的想法就是通过GPIO引脚并以某种方式嗅用逻辑分析仪中的数据。转储一次一个位

伪code:

 而(由单词记忆副本字尚未完成)
  ...
  注册=价值;
  temp_value =价值和0x1;
  引脚= temp_value;
  值=价值>> 1;
  ...

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

###编辑###

其实我的(壳)code的要求是,它需要真正的小。我发现<一个href=\"http://conference.hitb.org/hitbsecconf2013ams/materials/D1T1%20-%20Travis%20Goodspeed%20-%20Nifty%20Tricks%20and%20Sage%20Advice%20for%20Shell$c$c%20on%20Embedded%20Systems.pdf#page=36\"相对=nofollow>这的如何漂亮的绝招
通过闪烁的指示灯转储固件。

不过我挣扎与Saleae逻辑分析仪获得正确的值。

基本上我做的是:


  1. 设置的GPIO引脚方向输出

  2. 闪烁LED1(引脚1.1)与时钟(SPI串行时钟)

  3. 闪烁LED2(引脚1.0)数据位(SPI MOSI)

  4. 嗅嗅引脚与逻辑分析仪

下面是我的C code:

 的#includeXMC4500.h#定义DEL 1260无效的init()
{
  // P1.0输出,推挽
  PORT1-&GT; IOCR0 = 0x80UL&LT;&LT; 0;
  // P1.1输出,推挽
  PORT1-&GT; IOCR0 | = 0x80UL&LT;&LT; 8;
}无效延迟(int i)以{
  当我) {
    ASM(NOP \\ n);
    ASM(NOP \\ n);
  }
}//设置一个端口为高
// P1.0 = SPI MOSI
// P1.1 = SPI时钟
无效output_high(int i)以{
  // P1.0高
  如果(我== 0){
    PORT1-&GT; OUT | = 0x1UL;
  }  // P1.1高
  如果(ⅰ== 1){
    PORT1-&GT; OUT | = 0x2UL;
  }
}//设置引脚为低
// P1.0 = SPI MOSI
// P1.1 = SPI时钟
无效output_low(int i)以{
  // P1.0低
  如果(我== 0){
    PORT1-&GT;&OUT功放=(〜0x1UL);
  }  // P1.1低
  如果(ⅰ== 1){
    PORT1-&GT;&OUT功放=(〜0x2UL);
  }
}// SPI位拆裂
无效spi_send_byte(unsigned char型数据)
{
  INT I;  //发送位7..0
  对于(i = 0; I&LT; 8;我++)
  {
    //设置P1.1为低(串行时钟)
    output_low(1);    //考虑最左边的位
    //设置行高,如果位是1,如果较低位为0
    如果(数据&安培; 0x80的)
      //设置P1.0为高(MOSI)
      output_high(0);
    其他
      //设置P1.0为低(MOSI)
      output_low(0);    延迟(DEL);    //设置P1.1为高(串行时钟)
    output_high(1);    //左Shift字节,从而在下位将最左面
    数据&LT;&LT; = 1;
  }
}诠释主(){
  在里面();  而(1){
    spi_send_byte('T');
    spi_send_byte('E');
    spi_send_byte('S');
    spi_send_byte('T');
  }  返回0;
}

###第二编辑###

倾销闪存做工精细用下面的code:

的#includeXMC4500.h// SPI位拆裂
无效spi_send_word(uint32_t的数据)
{
  INT I;  // LSB第一,32%的传送比特
  对于(i = 0; I&LT; 32;我++)
  {
    //设置引脚1.1为低(SPI时钟)
    PORT1-&GT;&OUT功放=(〜0x2UL);    //设置行高,如果位是1,如果较低位为0
    如果(数据&安培;为0x1){
      //设置引脚1.0高(SPI MOSI)
      PORT1-&GT; OUT | = 0x1UL;
    }
    其他{
      //设置引脚1.0为低(SPI MOSI)
      PORT1-&GT;&OUT功放=(〜0x1UL);
    }    //设置引脚1.1高(SPI时钟)
    PORT1-&GT; OUT | = 0x2UL;    数据&GT;&GT; = 1;
  }
}诠释主(){
  //开始在内存地址0x08000000倾销
  无符号整型* P;
  p值=(uint32_t的*)(0x08000000u);  //将引脚配置1.0和1.1脚为输出(推挽)
  PORT1-&GT; IOCR0 = 0x8080UL;  而(1){
    spi_send_word(* P);
    p ++;
  }
}


解决方案

与您的解决方案是恢复定时信息的最大问题 - 知道其中一个字的开始和另一端。这将是简单输出一个UART TX引脚数据 - 的UART添加开始和停止位和管理时间为您,并且输出可直接通过普通PC的串行端口读取。

如果您不能使用UART,通过模拟一个UART位敲打GPIO与UART时机仍然允许使用传统的串行端口直接接收数据。

一个例子的软件UART 的实施可以发现这里。在你的课程情况下,你只需要传输能力。

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 todump 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++;
  }
}
解决方案

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.

这篇关于转储闪存通过单一GPIO引脚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 14:14