title: Dump Flash Memory through a single GPIO pin
body: <p>I'm working with Infineon's XMC4500 Relax Kit and I'm trying to extract the firmware through a single GPIO pin.</p>
  
  <p>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.</p>
  
  <p>Pseudocode:</p>
  
  <pre><code>while(word by word memory copy hasn't finished)
    ...
    register = value;
    temp_value = value AND 0x1;
    pin = temp_value;
    value = value &gt;&gt; 1;
    ...
  </code></pre>
  
  <p>Am I on the right track? Does anybody have a better/nicer idea how to archive this?</p>
  
  <p><strong>### EDIT ###</strong></p>
  
  <p>Actually a requirement of my (shell)code would be that it needs to be really tiny. I found <a href="http://conference.hitb.org/hitbsecconf2013ams/materials/D1T1%20-%20Travis%20Goodspeed%20-%20Nifty%20Tricks%20and%20Sage%20Advice%20for%20Shellcode%20on%20Embedded%20Systems.pdf#page=36" rel="nofollow">this</a> nifty trick on how to 
  dump firmware by blinking the LEDs.</p>
  
  <p>However I'm struggling to receive correct values with Saleae Logic Analyzer.</p>
  
  <p>Basically what I'm doing is:</p>
  
  <ol>
  <li>Setup the GPIO pin directions to output</li>
  <li>Blink LED1 (pin 1.1) with a clock (SPI serial clock)</li>
  <li>Blink LED2 (pin 1.0) with data bits (SPI MOSI)</li>
  <li>Sniff pins with a logic analyzer</li>
  </ol>
  
  <p>Here's my C code:
  </p>
  
  <pre><code>#include "XMC4500.h"
  
  #define DEL 1260
  
  void init() 
  {
    // P1.0 output, push pull
    PORT1-&gt;IOCR0 = 0x80UL &lt;&lt; 0;
    // P1.1 output, push pull
    PORT1-&gt;IOCR0 |= 0x80UL &lt;&lt; 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-&gt;OUT |= 0x1UL;  
    }
  
    // P1.1 high
    if(i == 1) {
      PORT1-&gt;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-&gt;OUT &amp;= (~0x1UL);
    }
  
    // P1.1 low
    if(i == 1) {
      PORT1-&gt;OUT &amp;= (~0x2UL);
    }
  }
  
  // SPI bit banging
  void spi_send_byte(unsigned char data)
  {
    int i;
  
    // Send bits 7..0
    for (i = 0; i &lt; 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 &amp; 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 &lt;&lt;= 1;
    }
  }
  
  int main() {
    init();
  
    while(1) {
      spi_send_byte('t');
      spi_send_byte('e');
      spi_send_byte('s');
      spi_send_byte('t');
    }
  
    return 0;
  }
  </code></pre>
  
  <p><strong>### 2nd EDIT ###</strong></p>
  
  <p>Dumping flash memory is working fine with the following code:</p>
  
  <pre class="lang-c prettyprint-override"><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 &lt; 32; i++)
    {
      // set pin 1.1 to low (SPI clock)
      PORT1-&gt;OUT &amp;= (~0x2UL);
  
      // set line high if bit is 1, low if bit is 0
      if (data &amp; 0x1) {
        // set pin 1.0 to high (SPI MOSI)
        PORT1-&gt;OUT |= 0x1UL;
      }
      else {
        // set pin 1.0 to low (SPI MOSI)
        PORT1-&gt;OUT &amp;= (~0x1UL);   
      }
  
      // set pin 1.1 to high (SPI clock)
      PORT1-&gt;OUT |= 0x2UL;
  
      data &gt;&gt;= 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-&gt;IOCR0 = 0x8080UL;
  
    while(1) {
      spi_send_word(*p);
      p++;
    }
  }
  </code></pre>