请问 2.5.0 bootloader 版本的CH552是不是取消了直接跳入bootloader的功能?

你好,我使用2.5.0版本的CH552,似乎调用__asm__ ("lcall #0x3800"); 只会重启。但是之前2.4.0以前的芯片是可以进入bootloader的。

请问新版本的芯片是去除了这一功能还是修改了使用方式?

boot中存在10秒左右的超时退出时间,看现象这个过程应该是跳进boot,然后退出了。


我没有办法确认是不是进入了boot,但是根据波形,上电后50ms左右程序就开始执行,lcall 0x3800后20ms左右程序就又开始了。和10秒的超时应该没关系。


icon_jpg.gifScreen Shot 2022-04-04 at 11.00.53 PM.png

void setup() {
  P1_4=0;
  pinMode(14, OUTPUT);

  USB_CTRL = 0;
  EA = 0;                     //Disabling all interrupts is required.
  delayMicroseconds(50000);
  delayMicroseconds(50000);

  P1_4=1;

  __asm__ ("lcall #0x3800");  //Jump to bootloader code

  while (1);
}

void loop() {


}



maybe its now neccesarry to activate the actual boot pin too in V2.5 before executing the lcall 0x3800 to stay in the loader


您好,CH552中直接调用LCALL 3800可能意外,是因为好多寄存器没有初始化,例如某个中断开着,只关EA全局是不行的,因为BOOT中会再开EA而不知道其他中断开着。

方便的话,请把你的测试代码发一下wsh@wch.cn。我们测试分析下。


@TECH10


I believe EA=0; is sufficient for calling the bootloader. The bootloader can not use any irqs and therefore there is no reason to activate EA. If I remember correctly none of the loaders executes EA=1; 

At least this was how all loaders from 1.1 to 2.4 were working. So if LCALL 0x3800 is not working anymore as before it might be because of IAP vector is set to 0 for unknown reason or more likely because of a different bootpin evaluation,


@usbman


No, pulling P3_6 up does not help.


Screen Shot 2022-04-05 at 8.43.20 AM.png


@TECH10 

感谢回复和提供信息。

我测试了一下代码,以https://github.com/Blinkinlabs/ch554_sdcc 编译 :

#include 

SBIT(P1_4, 0x90, 4);

void delayMicroseconds(unsigned short us) {
    us;
    __asm__ (".even                                    \n"
             "    mov  r6, dpl                         \n" //low 8-bit
             "    mov  r7, dph                         \n" //high 8-bit
             "    clr  c                               \n"
             "    mov  a,#0x01                         \n"
             "    subb a, r6                           \n"
             "    clr  a                               \n"
             "    subb a, r7                           \n"
             "    jc skip_0us$                         \n"
             "    ret                                  \n" //return if 0 1 us  about 1.2us total
             "    nop                                  \n"
             "skip_0us$:                               \n"
             "    clr  c                               \n" //do some loop init, not useful for 2us but better here
             "    mov  a, #0x02                        \n"
             "    subb a, r6                           \n"
             "    mov  r6, a                           \n"
             "    mov  a, #0x00                        \n"
             "    subb a, r7                           \n"
             "    mov  r7, a                           \n"
             
             "    nop                                  \n" //keep even
             "    cjne r6,#0x00,loop24m_us$            \n"
             "    cjne r7,#0x00,loop24m_us$            \n"
             "    nop                                  \n"
             "    ret                                  \n" //return if 2us  about 2 us total
             
             "loop24m_us$:                             \n" //about nus
             
             "    nop \n nop \n nop \n nop \n nop \n    " // 17 cycle
             "    nop \n "
             "loop24m_us_2$:                           \n"  //need more test
             
             "nop \n nop \n nop \n nop \n    "
             "    nop \n nop \n nop \n nop \n nop \n    "
             "    nop \n nop \n                         "
             
             "    inc  r6                              \n" // 1 cycle
             "    cjne r6, #0,loop24m_us$              \n" // 6 cycle
             "    inc  r7                              \n" // there will be extra 7 cycles for every 256us, ignore for now
             "    cjne r7, #0,loop24m_us_2$            \n"
             "    nop                                  \n"
             );
}

void main() {
    
    SAFE_MOD = 0x55;
    SAFE_MOD = 0xAA;
    CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x06;  // 24MHz
    SAFE_MOD = 0x00;
    
    P1_4=1;
    
    P1_MOD_OC = P1_MOD_OC & ~(1<<4);
    P1_DIR_PU = P1_DIR_PU | (1<<4);
    
    //test interrupt
    //init T0 for millis
    /*TMOD = (TMOD & ~0x0F)|(bT0_M1);//mode 2 for autoreload
    T2MOD = T2MOD & ~bT0_CLK;    //bT0_CLK=0;clk Div by 12
    TH0 = 255-250+1;
    TF0 = 0;
    ET0 = 1;
    TR0 = 1;
    EA = 1; //millis and delay needs interrupt*/
    
    P1_4=0;
    
    USB_CTRL = 0;
    EA = 0;                     //Disabling all interrupts is required.
    delayMicroseconds(50000);
    delayMicroseconds(50000);
    
    P1_4=1;
    
    __asm__ ("lcall #0x3800");  //Jump to bootloader code
    
    while (1);
}

代码没有任何外部依赖。

编译后确实可以跳转bootloader

without t0 interrupt.png

但是如果把注释的代码取消注释,即让T0产生中断,就不能跳转bootloader

with t0 interrupt.png


看起来问题是,新的bootloader从查询式通信换成了中断式通信,因此所有的中断使能位都应该关闭。


建议官方也把ch554_evt里的例程也更新一下。





@TECH10 


进一步测试,主代码有这句就不能进bootloader

TMOD = (TMOD & ~0x0F)|(bT0_M1);

既然bootloader不开源,还希望官方给出详细的bootloader寄存器使用信息,以免踩坑,毕竟作为用户遍历所有可能的寄存器配置并不现实。

我这边猜测是新版本bootloader对于使用的寄存器并没有完全重置初值,导致主程序的寄存器设定影响了bootloader的执行。


另附上可用的代码。

        USB_CTRL = 0;
        EA = 0;                     //Disabling all interrupts is required.
        TMOD = 0;
        delayMicroseconds(50000);
        delayMicroseconds(50000);
        
        __asm__ ("lcall #0x3800");  //Jump to bootloader code
        
        while(1);



2.5版本boot增加了超时(10s)退出机制,超时是基于定时器0定时处理,TMOD寄存器没有完全重置初值;在跳转boot之前需写TMOD  = 0,除此之外无其他条件。


只有登录才能回复,可以选择微信账号登录