我尝试编写尽可能小的代码来提取英飞凌XMC4500微控制器的固件。
代码必须适合 30 字节缓冲区,这允许我使用Thumb 16位指令集获得15条机器指令。
从C开始,我的尝试是在(see original question) nifty技巧之后通过单个GPIO引脚this转储闪存。
基本上我正在做的是:
修改
#include "XMC4500.h"
void main() {
// start dumping at memory address 0x00000000
unsigned int* p = (uint32_t *)(0x0u);
// configure port1 output (push-pull)
PORT1->IOCR0 = 0x8080u;
for(;;) {
int i = 32;
int data = *(p++);
do {
// clock low
PORT1->OUT = 0x0;
// clock high with data bits
PORT1->OUT = 0x2u | data;
data >>= 1;
} while (--i > 0);
}
}
main:
; PORT1->IOCR0 = 0x8080UL
ldr r1, =0x48028100 ; load port1 base address to R1
movw r2, #0x8080 ; move 0x8080 to R2
str r2, [r1, #0x10]
main_1:
; start copying at address 0x00000000
; R12 is known to be zeroed
ldr.w r2, [r12], #0x4 ; int data = *(p++)
movs r3, #32 ; int i = 32
main_2:
; PORT1->OUT = 0x0
; clock low
; R12 is known to be zeroed
str r12, [r1]
; PORT1->OUT = 0x2 | data
; clock high with data bits
orr r4, r2, #0x2
str r4, [r1]
asrs r2, r2, #0x1 ; data >>= 1
subs r3, r3, #0x1 ; i--
bne.n main_2 ; while (--i > 0)
b.n main_1 ; while(true)
但是代码大小仍然太大,无法满足我的要求。
我可以采取哪些措施来进一步缩减我的代码吗?什么可以优化或遗漏?
答案 0 :(得分:3)
如果在此过程中Port1的高位没有改变,并且你可以确保在时钟变高后稍微读取数据位,你可以尝试这样的事情:
#define P1_DEFAULT = ?//constant high bits of port 1, zeros in low two bits
int* dp=0; //maybe use a register which is known to be zeroed.
PORT1->IOCR0 = 0x8080; //should be 3 ins
for(;;){
int i=32; //
int data=*(dp++); //LDMIA instruction may do load and increment in 1 step.
do{
PORT1->OUT = P1_DEFAULT #clock low
PORT1->OUT = P1_DEFAULT + 2+ (data&1); #clock high with data
data>>=1;
} while (--i>0);
}
这应该删除三个端口读取,一个端口写入和一个条件 在一个函数中完成所有操作以避免任何调用开销。我将从生成的程序集开始,看看你可以做些什么来改进它。
答案 1 :(得分:2)
十六条指令不是很多;我不希望C编译器能够生成足够高效的代码来对内存转储进行bit-bang。如果你对输出位模式不太挑剔,我认为使用类似的东西32个字节就足够了:
ldr r1,=Port1 ; Address of IO Port
mov r3,#1
str r3,[r1+IOCR0]
lsl r0,r3,#27
bytes:
mov r5,#9
strb r5,[r1+OUT]
add r0,#1
ldrb r4,[r0]
bits:
strb r4,[r1+OUT]
lsr r4,#1
sub r5,#1
bne bits
b bytes
每个字节将作为高脉冲输出,然后是8位可能为高或低(取决于数据读取),然后是位时间,该位时间始终为零,以确保下一个高脉冲的上升沿将是可见的。基本上类似于异步串行通信,但水平相反。