我正在使用英飞凌的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;
...
我是否在正确的轨道上?有没有人有更好/更好的想法如何存档?
###编辑###
实际上我的(shell)代码的要求是它需要非常小。我找到了this如何做的好玩法 通过闪烁LED来转储固件。
然而,我很难通过Saleae Logic Analyzer获得正确的数值。
基本上我正在做的是:
这是我的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;
}
### 2nd EDIT ###
使用以下代码转储闪存工作正常:
#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++;
}
}
答案 0 :(得分:4)
您的解决方案的最大问题是恢复时间信息 - 知道一个单词的开始位置和另一个单词的结束位置。在UART tx引脚上输出数据会更简单 - UART会为您添加启动和停止位并管理时序,并且可以通过常规PC串行端口直接读取输出。
如果你不能使用UART,那么通过用UART定时对GPIO进行位冲击来模拟UART仍然可以使用传统的串行端口来直接接收数据。
可以找到示例软件UART 实现here。在您的情况下,您当然只需要传输功能。
答案 1 :(得分:2)
根据您的要求,这可能会有所体现。需要考虑的是,如果在循环读取数据时存在任何时序变化,例如闪存读取时间变化,缓存等等,您将遇到一个问题,找出字节开始和停止的位置。您可能想看看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;
...