上电时间计算

 前言:

CH573/582上电到运行第一个初始化的时间最快约53ms左右;592最快约22ms左右。

注意将串口免按键功能关闭。

思路:

上电之后从启动文件启动,直接跳转到60M主频进行运行,然后在main函数中翻转io进行判断时间。

测试工具,使用功耗计测试(可以看到上电的波形和运行到翻转io的波形)。

代码(CH582):

启动文件:

startup.s
.section	.init,"ax",@progbits
	.global	_start
	.align	1
_start:
	j	handle_reset

    .section    .vector,"ax",@progbits
    .align  1
_vector_base:
    .option norvc;

    .word   0
    .word   0
    .word   NMI_Handler                 /* NMI Handler */
    .word   HardFault_Handler           /* Hard Fault Handler */
    .word   0xF5F9BDA9
    .word   Ecall_M_Mode_Handler        /* 5 */
    .word   0
    .word   0
    .word   Ecall_U_Mode_Handler		/* 8 */
    .word   Break_Point_Handler			/* 9 */
    .word   0
    .word   0
    .word   SysTick_Handler            /* SysTick Handler */
    .word   0
    .word   SW_Handler                 /* SW Handler */
    .word   0
    /* External Interrupts */
    .word   TMR0_IRQHandler            /* 0:  TMR0 */
    .word   GPIOA_IRQHandler           /* GPIOA */
    .word   GPIOB_IRQHandler           /* GPIOB */
    .word   SPI0_IRQHandler            /* SPI0 */
    .word   BB_IRQHandler              /* BLEB */
    .word   LLE_IRQHandler             /* BLEL */
    .word   USB_IRQHandler             /* USB */
    .word   USB2_IRQHandler			   /* USB2 */
    .word   TMR1_IRQHandler            /* TMR1 */
    .word   TMR2_IRQHandler            /* TMR2 */
    .word   UART0_IRQHandler           /* UART0 */
    .word   UART1_IRQHandler           /* UART1 */
    .word   RTC_IRQHandler             /* RTC */
    .word   ADC_IRQHandler             /* ADC */
    .word   I2C_IRQHandler 			   /* I2C */
    .word   PWMX_IRQHandler            /* PWMX */
    .word   TMR3_IRQHandler            /* TMR3 */
    .word   UART2_IRQHandler           /* UART2 */
    .word   UART3_IRQHandler           /* UART3 */
    .word   WDOG_BAT_IRQHandler        /* WDOG_BAT */

    .option rvc;

    .section    .vector_handler, "ax", @progbits
    .weak   NMI_Handler
    .weak   HardFault_Handler
    .weak   Ecall_M_Mode_Handler
    .weak   Ecall_U_Mode_Handler
    .weak   Break_Point_Handler
    .weak   SysTick_Handler
    .weak   SW_Handler
    .weak   TMR0_IRQHandler
    .weak   GPIOA_IRQHandler
    .weak   GPIOB_IRQHandler
    .weak   SPI0_IRQHandler
    .weak   BB_IRQHandler
    .weak   LLE_IRQHandler
    .weak   USB_IRQHandler
    .weak   USB2_IRQHandler
    .weak   TMR1_IRQHandler
    .weak   TMR2_IRQHandler
    .weak   UART0_IRQHandler
    .weak   UART1_IRQHandler
    .weak   RTC_IRQHandler
    .weak   ADC_IRQHandler
    .weak   I2C_IRQHandler
    .weak   PWMX_IRQHandler
    .weak   TMR3_IRQHandler
    .weak   UART2_IRQHandler
    .weak   UART3_IRQHandler
    .weak   WDOG_BAT_IRQHandler

NMI_Handler:
HardFault_Handler:
Ecall_M_Mode_Handler:
Ecall_U_Mode_Handler:
Break_Point_Handler:
SysTick_Handler:
SW_Handler:
TMR0_IRQHandler:
GPIOA_IRQHandler:
GPIOB_IRQHandler:
SPI0_IRQHandler:
BB_IRQHandler:
LLE_IRQHandler:
USB_IRQHandler:
USB2_IRQHandler:
TMR1_IRQHandler:
TMR2_IRQHandler:
UART0_IRQHandler:
UART1_IRQHandler:
RTC_IRQHandler:
ADC_IRQHandler:
I2C_IRQHandler:
PWMX_IRQHandler:
TMR3_IRQHandler:
UART2_IRQHandler:
UART3_IRQHandler:
WDOG_BAT_IRQHandler: 
1:  
	j 1b

	.section	.handle_reset,"ax",@progbits
	.weak	handle_reset
	.align	1
handle_reset:
.option push 
.option	norelax 
	la gp, __global_pointer$
.option	pop 
1:
	la sp, _eusrstack 


2:
    la a0, _highcode_copy_lma
    la a1, _highcode_copy_start
    la a2, _highcode_copy_end
    bgeu a1, a2, 2f
1:
    lw t0, (a0)
    sw t0, (a1)
    addi a0, a0, 4
    addi a1, a1, 4
    bltu a1, a2, 1b

	jal SystemInit


/* Load highcode code  section from flash to RAM */

/*
2:
    la a0, _highcode_lma
    la a1, _highcode_vma_start
    la a2, _highcode_vma_end
    bgeu a1, a2, 2f
1:
    lw t0, (a0)
    sw t0, (a1)
    addi a0, a0, 4
    addi a1, a1, 4
    bltu a1, a2, 1b

2:
	la a0, _data_lma
	la a1, _data_vma
	la a2, _edata
	bgeu a1, a2, 2f
1:
	lw t0, (a0)
	sw t0, (a1)
	addi a0, a0, 4
	addi a1, a1, 4
	bltu a1, a2, 1b
2:

	la a0, _sbss
	la a1, _ebss
	bgeu a0, a1, 2f
1:
	sw zero, (a0)
	addi a0, a0, 4
	bltu a0, a1, 1b
	*/

2:
	/* 流水线控制位 & 动态预测控制位 */
	li t0, 0x1f
	csrw 0xbc0, t0
	/* 打开嵌套中断、硬件压栈功能 */
	li t0, 0x3
	csrw 0x804, t0
	
    li t0, 0x88
    csrs mstatus, t0
	la t0, _vector_base

	/* 配置向量表模式为绝对地址模式 */
    ori t0, t0, 3
	csrw mtvec, t0

	la t0, main
	csrw mepc, t0
	
	
	mret

跳转并配置时钟c文件:

soctestct.c
/*
 * soctest.c
 *
 *  Created on: Jan 4, 2024
 *      Author: OWNER
 */

#include "soctestct.h"


typedef enum
{
  CLK_FLASH_4 = 0X01,
  CLK_FLASH_5 = 0X05,
  CLK_FLASH_6 = 0X02,
  CLK_FLASH_7 = 0X06,
  CLK_FLASH_8 = 0X03,
  CLK_FLASH_9 = 0X07,

  AHB_READY_SHORT = 0X00,
  AHB_READY_NORMAL = 0X40,
  AHB_READY_LONG = 0X80,
  AHB_READY_LONGER = 0XC0,

  AHB_SAMPLE_NORMAL = 0X00,
  AHB_SAMPLE_DELAY = 0X10,
  AHB_SAMPLE_BEFORE = 0X20,

  AHB_SCSWIDTH_3 = 0X00,
  AHB_SCSWIDTH_2 = 0X08,

}FLASH_CLKTypeDef;


extern uint32_t _highcode_lma;
extern uint32_t _highcode_vma_start;
extern uint32_t _highcode_vma_end;

extern uint32_t _data_lma;
extern uint32_t _data_vma;
extern uint32_t _edata;

extern uint32_t _sbss;
extern uint32_t _ebss;


__attribute__((section(".highcode_copy")))
static void __attribute__((noinline)) copy_section(uint32_t * p_load, uint32_t * p_vma, uint32_t * p_vma_end)
{
    while(p_vma <= p_vma_end)
    {
        *p_vma = *p_load;
        ++p_load;
        ++p_vma;
    }
}

__attribute__((section(".highcode_copy")))
static void __attribute__((noinline)) zero_section(uint32_t * start, uint32_t * end)
{
    uint32_t * p_zero = start;

    while(p_zero <= end)
    {
        *p_zero = 0;
        ++p_zero;
    }
}


__attribute__((section(".highcode_copy")))
void mySystemInit(void) {
    uint32_t i;
    uint8_t sc = 0x46;
    sys_safe_access_enable();
    R8_PLL_CONFIG &= ~(1 << 5); //
    sys_safe_access_disable();

    sys_safe_access_enable();
    R8_HFCK_PWR_CTRL |= RB_CLK_PLL_PON | RB_CLK_XT32M_PON;
    sys_safe_access_disable();

//    if(sc & 0x20)  // HSE div
//    {
//        if(!(R8_HFCK_PWR_CTRL & RB_CLK_XT32M_PON))
//        {
//            sys_safe_access_enable();
//            R8_HFCK_PWR_CTRL |= RB_CLK_XT32M_PON; // HSE power on
//            sys_safe_access_disable();
////            for(i = 0; i < 1200; i++)
////            {
//                __nop();
//                __nop();
////            }
//        }
//
//        sys_safe_access_enable();
//        R16_CLK_SYS_CFG = (0 << 6) | (sc & 0x1f);
//        __nop();
//        __nop();
//        __nop();
//        __nop();
//        sys_safe_access_disable();
//        sys_safe_access_enable();
//        SAFEOPERATE;
//        R8_FLASH_CFG = 0X51;
//        sys_safe_access_disable();
//    }

     if(sc & 0x40) // PLL div
    {
        if(!(R8_HFCK_PWR_CTRL & RB_CLK_PLL_PON))
        {
            sys_safe_access_enable();
            R8_HFCK_PWR_CTRL |= RB_CLK_PLL_PON; // PLL power on
            sys_safe_access_disable();
            for(i = 0; i < 2000; i++)
            {
                __nop();
                __nop();
            }
        }
        sys_safe_access_enable();
        R16_CLK_SYS_CFG = (1 << 6) | (sc & 0x1f);
        sys_safe_access_disable();
        __nop();
        __nop();
        __nop();
        __nop();

        if(sc == CLK_SOURCE_PLL_80MHz)
        {
            sys_safe_access_enable();
            R8_FLASH_CFG = 0X02;
            sys_safe_access_disable();
        }
        else
        {
            sys_safe_access_enable();
            R8_FLASH_CFG = 0X55;
            sys_safe_access_disable();
        }
    }
//    else
//    {
//        sys_safe_access_enable();
//        R16_CLK_SYS_CFG |= RB_CLK_SYS_MOD;
//        sys_safe_access_disable();
//    }
    //更改FLASH clk的驱动能力
    sys_safe_access_enable();
    R8_PLL_CONFIG |= 1 << 7;
    sys_safe_access_disable();



    copy_section(&_highcode_lma, &_highcode_vma_start, &_highcode_vma_end);
    copy_section(&_data_lma, &_data_vma, &_edata);
    zero_section(&_sbss, &_ebss);

//    R32_PB_OUT |= 1<<0;
//    R32_PB_PD_DRV &= ~(1<<0);
//    R32_PB_DIR |= 1<<0;
//    mDelaymS(1);
//    R32_PB_CLR |= 1<<0;
//    mDelaymS(1);
//    R32_PB_OUT |= 1<<0;
//    mDelaymS(1);
//    R32_PB_CLR |= 1<<0;
}

void SystemInit(void){
    mySystemInit();
}

跳转并配置时钟h文件:

socttestct.h
/*
 * soctest.h
 *
 *  Created on: Jan 4, 2024
 *      Author: OWNER
 */

#ifndef SRC_INCLUDE_SOCTEST_H_
#define SRC_INCLUDE_SOCTEST_H_

#include "CH58x_common.h"

#define DEFINE_FAST_IRQ_HANDLER(irq_handler) void irq_handler() __attribute__((interrupt("WCH-Interrupt-fast")))

DEFINE_FAST_IRQ_HANDLER(NMI_Handler);
DEFINE_FAST_IRQ_HANDLER(HardFault_Handler);
DEFINE_FAST_IRQ_HANDLER(Ecall_U_Mode_Handler);
DEFINE_FAST_IRQ_HANDLER(SysTick_Handler);
DEFINE_FAST_IRQ_HANDLER(SW_Handler);
DEFINE_FAST_IRQ_HANDLER(TMR0_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(GPIOA_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(GPIOB_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(SPI0_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(BB_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(LLE_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(USB_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(TMR1_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(TMR2_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(UART0_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(UART1_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(RTC_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(ADC_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(PWMX_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(TMR3_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(UART2_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(UART3_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(I2C_IRQHandler);
DEFINE_FAST_IRQ_HANDLER(WDOG_BAT_IRQHandler);


void SystemInit(void);

void mySystemInit(void);

#endif /* SRC_INCLUDE_SOCTEST_H_ */

LD文件

查看代码
ENTRY( _start )

__stack_size = 512;

PROVIDE( _stack_size = __stack_size );

MEMORY
{
	FLASH (rx) : ORIGIN = 0x0000C000, LENGTH = 16K
	RAM (xrw) : ORIGIN = 0x20002000, LENGTH = 24K
}

    PROVIDE( __global_pointer$ = 0x20002000 );

SECTIONS
{
	.init :
	{
		_sinit = .;
		. = ALIGN(4);
		KEEP(*(SORT_NONE(.init)))
		. = ALIGN(4);
		_einit = .;
	} >FLASH AT>FLASH
	
 /*   .vector :
    {
        *(.vector);
    } >FLASH AT>FLASH */
    
	.highcodecopylalign : 
    {       
        . = ALIGN(4);
        PROVIDE(_highcode_copy_lma = .); 
    } >FLASH AT>FLASH 
    
    .highcode_copy :
    {
        . = ALIGN(4);
        PROVIDE(_highcode_copy_start = .);
        *(.highcode_copy);
		*(.highcode_copy.*);
        PROVIDE(_highcode_copy_end = .);
        . = ALIGN(4);
    } >RAM AT>FLASH
	
    .highcodelalign : 
    {       
        . = ALIGN(4);
        PROVIDE(_highcode_lma = .); 
    } >FLASH AT>FLASH 
    
    .highcode : 
    {
        . = ALIGN(4);
        PROVIDE(_highcode_vma_start = .);
        *(.vector);
		KEEP(*(SORT_NONE(.vector_handler)))
        *(.highcode);
        *(.highcode.*);
		. = ALIGN(4); 
        PROVIDE(_highcode_vma_end = .);
    } >RAM AT>FLASH
     
	.text :
	{
		. = ALIGN(4);
		KEEP(*(SORT_NONE(.handle_reset)))
		*(.text)
		*(.text.*)
		*(.rodata)
		*(.rodata*)
  *(.sdata2.*)
		*(.glue_7)
		*(.glue_7t)
		*(.gnu.linkonce.t.*)
		. = ALIGN(4);
	} >FLASH AT>FLASH 

	.fini :
	{
		KEEP(*(SORT_NONE(.fini)))
		. = ALIGN(4);
	} >FLASH AT>FLASH

	PROVIDE( _etext = . );
	PROVIDE( _eitcm = . );	

	.preinit_array  :
	{
	  PROVIDE_HIDDEN (__preinit_array_start = .);
	  KEEP (*(.preinit_array))
	  PROVIDE_HIDDEN (__preinit_array_end = .);
	} >FLASH AT>FLASH 
	
	.init_array     :
	{
	  PROVIDE_HIDDEN (__init_array_start = .);
	  KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
	  KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
	  PROVIDE_HIDDEN (__init_array_end = .);
	} >FLASH AT>FLASH 
	
	.fini_array     :
	{
	  PROVIDE_HIDDEN (__fini_array_start = .);
	  KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
	  KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
	  PROVIDE_HIDDEN (__fini_array_end = .);
	} >FLASH AT>FLASH 
	
	.ctors          :
	{
	  /* gcc uses crtbegin.o to find the start of
	     the constructors, so we make sure it is
	     first.  Because this is a wildcard, it
	     doesn't matter if the user does not
	     actually link against crtbegin.o; the
	     linker won't look for a file to match a
	     wildcard.  The wildcard also means that it
	     doesn't matter which directory crtbegin.o
	     is in.  */
	  KEEP (*crtbegin.o(.ctors))
	  KEEP (*crtbegin?.o(.ctors))
	  /* We don't want to include the .ctor section from
	     the crtend.o file until after the sorted ctors.
	     The .ctor section from the crtend file contains the
	     end of ctors marker and it must be last */
	  KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
	  KEEP (*(SORT(.ctors.*)))
	  KEEP (*(.ctors))
	} >FLASH AT>FLASH 
	
	.dtors          :
	{
	  KEEP (*crtbegin.o(.dtors))
	  KEEP (*crtbegin?.o(.dtors))
	  KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
	  KEEP (*(SORT(.dtors.*)))
	  KEEP (*(.dtors))
	} >FLASH AT>FLASH 

	.dlalign :
	{
		. = ALIGN(4); 
		PROVIDE(_data_lma = .);
	} >FLASH AT>FLASH

	.data :
	{
		. = ALIGN(4); 
		PROVIDE(_data_vma = .);
    	*(.gnu.linkonce.r.*)
    	*(.data .data.*)
    	*(.gnu.linkonce.d.*)
		. = ALIGN(8);
    	*(.sdata .sdata.*)
    	*(.gnu.linkonce.s.*)
    	. = ALIGN(8);
    	*(.srodata.cst16)
    	*(.srodata.cst8)
    	*(.srodata.cst4)
    	*(.srodata.cst2)
    	*(.srodata .srodata.*)
    	. = ALIGN(4);
		PROVIDE( _edata = .);
	} >RAM AT>FLASH

	.bss :
	{
		. = ALIGN(4);
		PROVIDE( _sbss = .);
  	    *(.sbss*)
        *(.gnu.linkonce.sb.*)
		*(.bss*)
     	*(.gnu.linkonce.b.*)		
		*(COMMON*)
		. = ALIGN(4);
		PROVIDE( _ebss = .);
	} >RAM AT>FLASH

	PROVIDE( _end = _ebss);
	PROVIDE( end = . );
	
    .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
    {
        PROVIDE( _heap_end = . );   
        . = ALIGN(4);
        PROVIDE(_susrstack = . );
        . = . + __stack_size;
        PROVIDE( _eusrstack = .);
    } >RAM 
}

posted @ 2024-04-03 10:15  SweetTea_lllpc  阅读(331)  评论(0)    收藏  举报