上电时间计算
前言:
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
}

浙公网安备 33010602011771号