W801|XT804|启动|startup.S|内部中断|初始化|伪指令|学习(5-2):W801-SDK启动分析之startup.S

文章目录

  • 芯片规格书及寄存器手册
  • 前言
  • startup.S文件分析
    • 中断定义
      • 引入相关头文件:
      • 内部中断定义
    • 3个初始化进程
      • 系统初始化
        • 定义:
        • irq堆栈定义:
        • 函数csi_coret_get_load
        • 函数csi_coret_get_value:
      • 板级初始化:
        • 初始化内容:
        • uart0Init()函数定义:
        • 函数set_printf_port()定义:
        • uart1Init()函数定义:
        • uart1_io_init函数定义
      • 主函数体
  • TIPS:伪汇编/操作指令
    • 常见的伪操作:

芯片规格书及寄存器手册

W801|芯片规格书|寄存器手册|总线|时钟|主频|学习(5-1):W801-SDK启动分析之芯片规格书及寄存器手册阅读笔记

前言

W801 默认程序是从内部FLASH 中开始运行的。
(具体执行流程及.ELF文件可参考:FLASH算法|.elf文件|基本类型- FLASH算法文件介绍)
SDK所采用的编译工具链为csky-elfabiv2。链接文件是:gcc_csky.ld。
W801|XT804|启动|startup.S|内部中断|初始化|伪指令|学习(5-2):W801-SDK启动分析之startup.S_第1张图片
关键字ENTRY所指向的入口是Reset_Handler,即启动时先进行复位操作,之后进入启动程序,执行startup.S。

startup.S文件分析

startup.S 是SDK的启动文件,位于:G:\bsp\W800_aos\W80X_SDK_v1.00.10\platform\arch\xt804\bsp\startup.S
smartl的启动文件应与GCC一起用于CSKY嵌入式处理器,SDK启动时,先运行sys目录下的startup.S。
W801|XT804|启动|startup.S|内部中断|初始化|伪指令|学习(5-2):W801-SDK启动分析之startup.S_第2张图片

中断定义

引入相关头文件:

#include 

.section .vectors

内部中断定义

/*内部中断 */
    .long   SDIO_IRQHandler            /*  0:  SDIO         */
    .long   MAC_IRQHandler             /*  1:  MAC          */
    .long   RF_Cfg_IRQHandler          /*  2:  RF Cfg       */
    .long   SEC_IRQHandler             /*  3:  SEC          */
    .long   DMA_Channel0_IRQHandler         /*  4:  DMA_Channel0       */
    .long   DMA_Channel1_IRQHandler         /*  5:  DMA_Channel1       */
    .long   DMA_Channel2_IRQHandler         /*  6:  DMA_Channel2       */
    .long   DMA_Channel3_IRQHandler         /*  7:  DMA_Channel3       */
    .long   DMA_Channel4_7_IRQHandler       /*  8:  DMA_Channel4_7     */
    .long   DMA_BRUST_IRQHandler            /*  9:  DMA_BRUST          */
    .long   I2C_IRQHandler            /*  10: IIC         */
    .long   ADC_IRQHandler            /*  11: SD ADC      */
    .long   SPI_LS_IRQHandler         /*  12: LS SPI      */
    .long   SPI_HS_IRQHandler         /*  13: HS SPI      */
    .long   GPIOA_IRQHandler          /*  14: GPIOA       */
    .long   GPIOB_IRQHandler          /*  15: GPIOB       */
    .long   USART_IRQHandler          /*  16: UART0       */
    .long   USART1_IRQHandler         /*  17: UART1       */
    .long   USART2_IRQHandler         /*  18: UART2&7816  */
    .long   USART3_5_IRQHandler       /*  19: USART3_5    */
    .long   BLE_IRQHandler            /*  20: BLE         */
    .long   BT_IRQHandler             /*  21: BT          */
    .long   PWM_IRQHandler            /*  22: PWM         */
    .long   I2S_IRQHandler            /*  23: I2S         */
    .long   SDIO_HOST_IRQHandler      /*  24: SDIO HOST   */
    .long   CORET_IRQHandler        /*  25:  CoreTIM      */
    .long   RSA_IRQHandler          /*  26:  RSA          */
    .long   GPSEC_IRQHandler        /*  27:  GPSEC        */
    .long   FLASH_IRQHandler        /*  28:  Flash        */
    .long   PMU_IRQHandler          /*  29:  PMU          */
    .long   TIM0_5_IRQHandler       /*  30:  Timer0_5     */
    .long   WDG_IRQHandler          /*  31:  Watch dog    */

接着运行系统初始化程序:

3个初始化进程

主要执行3个初始化进程:

系统初始化

#ifndef __NO_SYSTEM_INIT
    jbsr    SystemInit
#endif
SystemInit执行G:\bsp\W800_aos\W80X_SDK_v1.00.10\platform\arch\xt804\bsp\system.c
引入必要的头文件:
#include 
#include "csi_core.h"
#include "wm_regs.h"
#include "wm_cpu.h"

定义:

extern int32_t g_top_irqstack;

irq堆栈定义:

g_top_irqstack:

.section .vdata
	.align  10
    .globl  irq_vectors
    .type   irq_vectors, @object
irq_vectors:
	.space CONFIG_IRQ_VECTOR_SIZE
	.size   irq_vectors, . - irq_vectors

    .globl  irq_vectors_end
irq_vectors_end:

函数csi_coret_get_load

extern uint32_t csi_coret_get_load(void);
函数体
功能:获取核心计时器重新装载值
返回值:核心计时器值

__STATIC_INLINE uint32_t csi_coret_get_load(void)
{
return CORET->LOAD;
}

函数csi_coret_get_value:

extern uint32_t csi_coret_get_value(void);

函数体
功能:获取核心计时器计数器值
返回值: 核心计时器计数器值

__STATIC_INLINE uint32_t csi_coret_get_value(void)
{
return CORET->VAL;
}

板级初始化:

主要完成采用UART0或UART1串口波特率及端口设置。

#ifndef __NO_BOARD_INIT
    jbsr    board_init
#endif

初始化内容:

void board_init(void)
{

#if USE_UART0_PRINT
    /* use uart0 as log output io */
    uart0Init(115200);
	set_printf_port(0);
#else
    uart1_io_init();
    /* use uart1 as log output io */
	uart1Init(115200);
	set_printf_port(1);
#endif
}

uart0Init()函数定义:

static void uart0Init (int bandrate)
{
	unsigned int bd;

	NVIC_DisableIRQ(UART0_IRQn);
	NVIC_ClearPendingIRQ(UART0_IRQn);

	bd = (APB_CLK/(16*bandrate) - 1)|(((APB_CLK%(bandrate*16))*16/(bandrate*16))<<16);
	tls_reg_write32(HR_UART0_BAUD_RATE_CTRL, bd);

	tls_reg_write32(HR_UART0_LINE_CTRL, UART_BITSTOP_VAL | UART_TXEN_BIT | UART_RXEN_BIT);
	tls_reg_write32(HR_UART0_FLOW_CTRL, 0x00);   			/* Disable afc */
	tls_reg_write32(HR_UART0_DMA_CTRL, 0x00);             		/* Disable DMA */
	tls_reg_write32(HR_UART0_FIFO_CTRL, 0x00);             		/* one byte TX/RX */
//	tls_reg_write32(HR_UART0_INT_MASK, 0x00);             		/* Disable INT */

}

函数set_printf_port()定义:

位于G:\bsp\W800_aos\W80X_SDK_v1.00.10\platform\arch\xt804\libc\libc_port.c中。
函数定义

void set_printf_port(unsigned char port)
{
    if(port == 0)
    {
        printf_port = 0;
    }
    else if(port == 1)
    {
        printf_port = 1;
    }
    else
    {
        printf_port = 0xff;
    }
}

uart1Init()函数定义:

static void uart1Init (int bandrate)
{
	unsigned int bd;

	NVIC_DisableIRQ(UART1_IRQn);
	NVIC_ClearPendingIRQ(UART1_IRQn);

	bd = (APB_CLK/(16*bandrate) - 1)|(((APB_CLK%(bandrate*16))*16/(bandrate*16))<<16);
	tls_reg_write32(HR_UART1_BAUD_RATE_CTRL, bd);

	tls_reg_write32(HR_UART1_LINE_CTRL, UART_BITSTOP_VAL | UART_TXEN_BIT | UART_RXEN_BIT);
	tls_reg_write32(HR_UART1_FLOW_CTRL, 0x00);   			/* Disable afc */
	tls_reg_write32(HR_UART1_DMA_CTRL, 0x00);             		/* Disable DMA */
	tls_reg_write32(HR_UART1_FIFO_CTRL, 0x00);             		/* one byte TX/RX */
	tls_reg_write32(HR_UART1_INT_MASK, 0x00);             		/* Disable INT */

}

uart1_io_init函数定义

static void uart1_io_init(void)
{
    uint32_t temp;

    /* PB6.7 AF Close */
	temp = tls_reg_read32(HR_GPIOB_AFSEL);
	temp &= ~0xC0;
	tls_reg_write32(HR_GPIOB_AFSEL, temp);

    /* PB6.7 AF Open opt1 */
    temp = tls_reg_read32(HR_GPIOB_AFSEL);
    temp |= 0xC0;
    tls_reg_write32(HR_GPIOB_AFSEL, temp);

    temp = tls_reg_read32(HR_GPIOB_AFS0);
    temp &= ~0xC0;
    tls_reg_write32(HR_GPIOB_AFS0, temp);

    temp = tls_reg_read32(HR_GPIOB_AFS1);
    temp &= ~0xC0;
    tls_reg_write32(HR_GPIOB_AFS1, temp);

}

主函数体

    jbsr    main
.size   Reset_Handler, . - Reset_Handler

之后跳转至系统主程序文件(wm_main.c)进行主频、PMU等初始化过程:G:\bsp\W800_aos\W80X_SDK_v1.00.10\platform\sys\wm_main.c

TIPS:伪汇编/操作指令

引自:ARM汇编指令学习—基于启动文件startup.S分析
以 . 开头一般是伪汇编/操作指令,形如:
.section伪操作来定义一个段,形如:
.section .testsection //定义一个testsection段
汇编系统预定义了一些段名:
.text:代码段
.data:初始化数据段
.bss:未初始化的数据段
.rodata:只读数据段
.global:定义一个全局符号,通常是为ld使用。例子如下:
.global _start
_start: //_start符号,汇编器在翻译汇编程序时会计算每个数据对象和每条指令的地址,当看到这样一个符号定义时,就把它后面一条指令的地址作为这个符号所代表的地址
ldr r0, =0x12 @r0=0x12
//.global 是伪操作,表示_start 是一个全局标号且是一个符号(Symbol),符号在汇编程序中代表一个地址,可以用在指令中,汇编程序经过汇编器的处理之后,所有的符号都被替换成它所代表的地址值

注:" : "前的为标号

常见的伪操作:

.byte 定义单字节数据,比如.byte 0x12。
.short 定义双字节数据,比如.short 0x1234。
.long 定义一个 4 字节数据,比如.long 0x12345678。
.equ 赋值语句,格式为:.equ 变量名,表达式,比如.equ num, 0x12,表示 num=0x12。//相当于#define num 0x12
.align 数据字节对齐,比如:.align 4 表示 4 字节对齐。
.end 表示源文件结束。
.global 定义一个全局符号,格式为:.global symbol,比如:.global _start。
.if … .else … .endif 条件预编译
.abort 停止汇编
.include 指定的头文件, 可以把一个汇编常量定义放在头文件中,比如:.include “file”
注:伪汇编指令不是真正的指令,并没有与之对应的的机器码,不会被执行。伪指令所起的作用主要是对汇编过程进行控制,只用于汇编过程中为汇编程序提供汇编信息。

你可能感兴趣的:(W80X,xt804,W801,startup.S,启动分析,mcu)