C语言 微型代码转储闪存

mtb9vblg  于 2023-04-05  发布在  其他
关注(0)|答案(2)|浏览(172)

我正在尝试编写尽可能小的代码来提取英飞凌XMC4500微控制器的固件。
该代码必须适合到一个30字节的缓冲区,使我有15个机器指令使用拇指16位指令集。
从C开始,我尝试通过一个GPIO引脚(see original question)来转储闪存,下面是这个漂亮的技巧。
基本上我在做的是:
1.设置GPIO引脚输出方向

  1. LED1(引脚1.1) Flink ,带有时钟(SPI串行时钟)
  2. Flink LED2(引脚1.0),带数据位(SPI MOSI)
    1.用逻辑分析仪嗅探引脚

编辑:

1.更新C代码块
1.添加装配代码块

#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)

但是代码的大小仍然太大,无法满足我的要求。
有什么我可以做的来进一步缩减我的代码吗?有什么可以优化或省略的吗?

gab6jxml

gab6jxml1#

如果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);
}

这将删除三个端口读取、一个端口写入和一个条件。
在一个函数中完成所有这些以避免任何调用开销。我将从为此生成的程序集开始,看看您可以做些什么来改进它。

6gpjuf90

6gpjuf902#

16条指令并不多我不期望C编译器能够产生足够有效的代码来进行内存转储。如果你对输出位模式不太挑剔,我认为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个可能为高或低的位时间(取决于数据读取),随后是始终为零的位时间,以确保下一个高脉冲的上升沿可见。基本上类似于异步串行通信,但电平相反。

相关问题