W801|XT804|启动|main函数|初始化|学习(5-3):W801-SDK启动分析之main()

目录

参考

正常的启动流程见图示。

startup.S文件的分析可参考

调试分析

进入调试模式:

​Main()函数的主要内容

选择PMU时钟频率

设置主频及uart端口

OS INIT function 操作系统初始化函数

初始化的工作内容:

Tick 实现方式

外设中断唤醒设置

任务分配及释放

示例代码


参考:

  1. 官方WM_W800_SDK用户手册(V1.1版);

  2. W800 SDK APIs说明文档

正常的启动流程见图示。

startup.S文件的分析可参考:

W801|XT804|启动|startup.S|内部中断|初始化|伪指令|学习(5-2):W801-SDK启动分析之startup.S_打酱油的工程师的博客-CSDN博客

W800 模块启动后通过 ROM 和 SECBOOT 程序运行后,最终会运行到 startup.S 开始执行,然后,跳转到 wm_main.c 文件进行一些初始化功能,最后,进入 main.c 打印 user task。

调试分析

本次采用CKLINK进入调试模式,进行启动程序的相关分析。

CKLINK调试概述可参考:W806|CKLINK LITE|ICE调试|HardPoint|elf模板|CSDK|Debug|学习(4):CKLINK调试W806_打酱油的工程师的博客-CSDN博客

进入调试模式:

先进行编译:

编译完成后界面,预置了debug所需要的工具菜单和窗口:

从debug结果看,SDK启动时,会先运行sys目录下的系统主程序文件(wm_main.c):G:\bsp\W800_aos\W80X_SDK_v1.00.10\platform\sys\wm_main.c

​Main()函数的主要内容为:

int main(void)
{
    u32 value = 0;

	/*standby reason setting in here,because pmu irq will clear it.*/
	if ((tls_reg_read32(HR_PMU_INTERRUPT_SRC)>>7)&0x1)
	{
		tls_sys_set_reboot_reason(REBOOT_REASON_STANDBY);
	}
	
    /*32K switch to use RC circuit & calibration*/
    tls_pmu_clk_select(0);
#if (TLS_CONFIG_HOSTIF&&TLS_CONFIG_UART)
	/*Configure uart port for user's AT Command*/
	tls_uart_set_at_cmd_port(TLS_UART_1);
#endif
    /*Switch to DBG*/
    value = tls_reg_read32(HR_PMU_BK_REG);
    value &= ~(BIT(19));
    tls_reg_write32(HR_PMU_BK_REG, value);
    value = tls_reg_read32(HR_PMU_PS_CR);
    value &= ~(BIT(5));
    tls_reg_write32(HR_PMU_PS_CR, value);
	
    /*Close those not initialized clk except touchsensor/trng, uart0,sdadc,gpio,rfcfg*/
    value = tls_reg_read32(HR_CLK_BASE_ADDR);
    value &= ~0x3fffff;
    value |= 0x201a02;
    tls_reg_write32(HR_CLK_BASE_ADDR, value);


    tls_sys_clk_set(CPU_CLK_80M);
    tls_os_init(NULL);

    /* before use malloc() function, must create mutex used by c_lib */
    tls_os_sem_create(&libc_sem, 1);

    /*configure wake up source begin*/
	csi_vic_set_wakeup_irq(SDIO_IRQn);
    csi_vic_set_wakeup_irq(MAC_IRQn);
    csi_vic_set_wakeup_irq(SEC_IRQn);
    csi_vic_set_wakeup_irq(DMA_Channel0_IRQn);
    csi_vic_set_wakeup_irq(DMA_Channel1_IRQn);
    csi_vic_set_wakeup_irq(DMA_Channel2_IRQn);
    csi_vic_set_wakeup_irq(DMA_Channel3_IRQn);
    csi_vic_set_wakeup_irq(DMA_Channel4_7_IRQn);
    csi_vic_set_wakeup_irq(DMA_BRUST_IRQn);
    csi_vic_set_wakeup_irq(I2C_IRQn);
    csi_vic_set_wakeup_irq(ADC_IRQn);
    csi_vic_set_wakeup_irq(SPI_LS_IRQn);
	csi_vic_set_wakeup_irq(SPI_HS_IRQn);
    csi_vic_set_wakeup_irq(GPIOA_IRQn);
    csi_vic_set_wakeup_irq(GPIOB_IRQn);
    csi_vic_set_wakeup_irq(UART0_IRQn);
    csi_vic_set_wakeup_irq(UART1_IRQn);
    csi_vic_set_wakeup_irq(UART24_IRQn);
    csi_vic_set_wakeup_irq(BLE_IRQn);
    csi_vic_set_wakeup_irq(BT_IRQn);
    csi_vic_set_wakeup_irq(PWM_IRQn);
    csi_vic_set_wakeup_irq(I2S_IRQn);
	csi_vic_set_wakeup_irq(SIDO_HOST_IRQn);
    csi_vic_set_wakeup_irq(SYS_TICK_IRQn);
    csi_vic_set_wakeup_irq(RSA_IRQn);
    csi_vic_set_wakeup_irq(CRYPTION_IRQn);
    csi_vic_set_wakeup_irq(PMU_IRQn);
    csi_vic_set_wakeup_irq(TIMER_IRQn);
    csi_vic_set_wakeup_irq(WDG_IRQn);
	/*should be here because main stack will be allocated and deallocated after task delete*/
	tls_mem_get_init_available_size();
	
    /*configure wake up source end*/
	TaskStartStk = tls_mem_alloc(sizeof(u32)*TASK_START_STK_SIZE);
	if (TaskStartStk)
    {
        tls_os_task_create(&tststarthdl, NULL,
                           task_start,
                           (void *)0,
                           (void *)TaskStartStk,          /* 任务栈的起始地址 */
                           TASK_START_STK_SIZE * sizeof(u32), /* 任务栈的大小     */
                           1,
                           0);
	   tls_os_start_scheduler();
    }
	else
	{
		while(1);
	}	

    return 0;
}

首先使用tls_reg_read32()函数从寄存器地址处读取值,

DEVICE_地址计算示例:

DEVICE_BASE_ADDR 0x40000000

HR_PMU_BASE_ADDR (DEVICE_BASE_ADDR + 0xD00)

HR_PMU_INTERRUPT_SRC (HR_PMU_BASE_ADDR + 0x14)

40000D14>>7=0X0080001A(8388634)

故:((tls_reg_read32(HR_PMU_INTERRUPT_SRC)>>7)&0x1)的值为0

选择PMU时钟频率

This function is used to select pmu clk.

Parameters

[in] bypass pmu clk whether or not use bypass mode 1 pmu clk use 32K by 40MHZ other pmu clk 32K by calibration circuit

/*Configure uart port for user's AT Command*/

tls_uart_set_at_cmd_port(TLS_UART_1);

value = tls_reg_read32(HR_PMU_BK_REG);

define

HR_PMU_BK_REG (HR_PMU_BASE_ADDR + 0x20)

/*Close those not initialized clk except touchsensor/trng, uart0,sdadc,gpio,rfcfg*/

除了touchsensor/trng, uart0,sdadc,gpio,rfcfg*/ 关闭那些没有初始化的clk

#define

HR_CLK_BASE_ADDR (DEVICE_BASE_ADDR + 0xE00)

设置主频及uart端口:

1)、tls_sys_clk_set(CPU_CLK_240M);

tls_os_init(NULL);

2)、为用户的AT命令配置uart端口

3)、切换到DBG

OS INIT function 操作系统初始化函数

初始化的工作内容:

1)、OS scheduler start function

2)、get OS type(OS_FREERTOS = 1)

3)、OS tick handler

操作系统节拍处理程序,时间管理模块中执行最频繁的函数,每当 Tick 中断发生时就会调用该函数

Tick 实现方式

void tls_os_time_tick(void *p){

}

static uint32_t CK_IN_INTRP(void)
{
    uint32_t vec = 0;
    asm volatile(
        "mfcr    %0, psr \n"
        "lsri    %0, 16\n"
        "sextb   %0\n"
        :"=r"(vec):);

    if (vec >= 32 || (vec == 10)) {
        return 1;
    } else {
        return 0;
    }
}

/**
 * @brief          	get isr count
 *
 * @param[in]      	None
 *
 * @retval         	count
 *
 * @note           	None
 */

//extern int portGET_IPSR(void);
u8 tls_get_isr_count(void)
{	 
//    return intr_counter;
	//return (portGET_IPSR() > 13);
	return (u8)CK_IN_INTRP();
}

int csi_kernel_intrpt_enter(void)
{
    return 0;
}

int csi_kernel_intrpt_exit(void)
{
    portYIELD_FROM_ISR(pdTRUE);
    return 0;
}

#endif

外设中断唤醒设置

任务分配及释放

任务删除后将分配和释放主堆栈。

示例代码:

   /*configure wake up source end*/
	TaskStartStk = tls_mem_alloc(sizeof(u32)*TASK_START_STK_SIZE);
	if (TaskStartStk)
    {
        tls_os_task_create(&tststarthdl, NULL,
                           task_start,
                           (void *)0,
                           (void *)TaskStartStk,          /* 任务栈的起始地址 */
                           TASK_START_STK_SIZE * sizeof(u32), /* 任务栈的大小     */
                           1,
                           0);
	   tls_os_start_scheduler();
    }
	else
	{
		while(1);
	}	

该步骤完成后进入用户main()函数自定义部分的流程。WM_SDK 的用户程序入口为: UserMain(void) ,用户可在此文件,基于 CreateDemoTask 函数中创建自己的 Task, 完成用户定制化功能。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

打酱油的工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值