目录
1.前言
2.SDK的启动流程
3.挖坑
W801的SDK需要配套的CDK集成开发环境进行开发,该SDK具有W801单片机所有硬件的驱动程序,FreeRTOS操作系统,基于蓝牙和WiFi功能的上层应用,以及各种功能的例程,可以通过例程测试硬件并模仿例程编写自己所需要的功能。
该篇文章主要以SDK启动的启动流程,例程的使用,以及SDK中部分文件在实际使用中的修改尝试。
W801在上电后先通过复位电路复位,并使用内部振荡器开始工作。此后单片机先进入启动扇区即地址为0X0000_0000,启动扇区检测BOOT0引脚,若需要更新固件则开始从串口接收数据开始更新固件;若无需更新固件,则引导单片机从FLASH启动地址为0X0800_0000。至此就进入了汇编编写的启动文件。Start.S,这个文件与STM32的startup_stm32.s类似,主要有这几个部分:
至于start.S文件的具体内容后期将会单独出一篇文章介绍。
现在主要理清晰W801的启动过程,故现在只看如下图部分:
W801多了一个板级初始化(board_init)功能的调用 内容如下:
是串口的初始化,该功能是配合W801的SDK的控制台使用的,而且W801的SDK已经将printf函数重新定向到串口,在自己的程序中直接调用printf即可在串口助手上看到内容。
接下来看main函数,main函数的具体位置在wm_main.c文件中,内容如下:
int main(void)
{
u32 value = 0;
/*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 uart0,sdadc,gpio,rfcfg*/
value = tls_reg_read32(HR_CLK_BASE_ADDR);
value &= ~0x3fffff;
value |= 0x1a02;
tls_reg_write32(HR_CLK_BASE_ADDR, value);
tls_sys_clk_set(CPU_CLK_240M);
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);
/*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;
}
这个文件无需全部看明白,只需要知道干了什么事情,和几句我们需要修改的着重了解一下即可。这个main函数干了如下事情:
上述代码中需要着重如下函数,其参数分别如下:
tls_sys_clk_set(CPU_CLK_240M);//设置处理器工作速度
//参数如下
enum CPU_CLK{
CPU_CLK_240M = 2,
CPU_CLK_160M = 3,
CPU_CLK_80M = 6,
CPU_CLK_40M = 12,
CPU_CLK_2M = 240,
};
这个函数将决定处理器的工作速度,此处在SDK中默认设置为80MHZ,故如果发现自己买的W801的CPU性能不佳不要怀疑国产芯片的实力,请来此处将其设置为240MHZ。
接下将会运行task_start进程,代码如下:
/*****************************************************************************
* Function Name // task_start
* Descriptor // before create multi_task, we create a task_start task
* // in this example, this task display the cpu usage
* Input
* Output
* Return
****************************************************************************/
void task_start (void *data)
{
u8 enable = 0;
u8 mac_addr[6] = {0x00, 0x25, 0x08, 0x09, 0x01, 0x0F};
#if TLS_CONFIG_CRYSTAL_24M
tls_wl_hw_using_24m_crystal();
#endif
tls_mem_get_init_available_size();
/* must call first to configure gpio Alternate functions according the hardware design */
wm_gpio_config();
tls_irq_init();
#if TLS_CONFIG_HARD_CRYPTO
tls_crypto_init();
#endif
#if (TLS_CONFIG_LS_SPI)
tls_spi_init();
tls_spifls_init();
#endif
tls_fls_init();
tls_fls_sys_param_postion_init();
/*PARAM GAIN,MAC default*/
tls_ft_param_init();
tls_param_load_factory_default();
tls_param_init(); /*add param to init sysparam_lock sem*/
tls_get_tx_gain(&tx_gain_group[0]);
TLS_DBGPRT_INFO("tx gain ");
TLS_DBGPRT_DUMP((char *)(&tx_gain_group[0]), 27);
if (tls_wifi_mem_cfg(WIFI_MEM_START_ADDR, 7, 7)) /*wifi tx&rx mem customized interface*/
{
TLS_DBGPRT_INFO("wl mem initial failured\n");
}
tls_get_mac_addr(&mac_addr[0]);
TLS_DBGPRT_INFO("mac addr ");
TLS_DBGPRT_DUMP((char *)(&mac_addr[0]), 6);
if(tls_wl_init(NULL, &mac_addr[0], NULL) == NULL)
{
TLS_DBGPRT_INFO("wl driver initial failured\n");
}
if (wpa_supplicant_init(mac_addr))
{
TLS_DBGPRT_INFO("supplicant initial failured\n");
}
/*wifi-temperature compensation,default:open*/
tls_wifi_set_tempcomp_flag(0);
tls_wifi_set_psm_chipsleep_flag(0);
tls_wifi_psm_chipsleep_cb_register(tls_pmu_chipsleep_callback, NULL, NULL);
tls_ethernet_init();
#if TLS_CONFIG_BT
tls_bt_entry();
#endif
tls_sys_init();
#if TLS_CONFIG_ONLY_FACTORY_ATCMD
factory_atcmd_init();
#else
/*HOSTIF&UART*/
#if TLS_CONFIG_HOSTIF
tls_hostif_init();
#if (TLS_CONFIG_HS_SPI)
tls_hspi_init();
#endif
#if TLS_CONFIG_UART
tls_uart_init();
#endif
#if TLS_CONFIG_HTTP_CLIENT_TASK
http_client_task_init();
#endif
#endif
tls_param_get(TLS_PARAM_ID_PSM, &enable, TRUE);
if (enable != TRUE)
{
enable = TRUE;
tls_param_set(TLS_PARAM_ID_PSM, &enable, TRUE);
}
UserMain();
tls_sys_auto_mode_run();
#endif
for (;;)
{
#if MAIN_TASK_DELETE_AFTER_START_FTR
if (tststarthdl)
{
tls_os_task_del_by_task_handle(tststarthdl,task_start_free);
}
tls_os_time_delay(0x10000000);
#else
#if 1
tls_os_time_delay(0x10000000);
#else
//printf("start up\n");
extern void tls_os_disp_task_stat_info(void);
tls_os_disp_task_stat_info();
tls_os_time_delay(1000);
#endif
#endif
}
}
这个进程主要有中断及各类外设的初始化,其中包括W801的特色——蓝牙和WiFi功能的初始化。其初始化流程与STM32略有不同,STM32在初始化需要连接GPIO口的外设时,GPIO的设置将会与外设在同一个函数中初始化。而W801现在这个进程里单独初始化外设而不对应GPIO,在其后真的需要使用的时候再指定引脚(蓝牙和WiFi功能除外)。
此进程中的UserMain();是下一步,即用户进程,该函数再main.c文件中。具体路径如下:
该文件SDK中默认有且只有一个函数,即 UserMain();内容如下:
void UserMain(void)
{
printf("\n user task \n");
#if DEMO_CONSOLE
CreateDemoTask();
#endif
//用户自己的task
}
可见此函数中,首先打印”user task“,然后创建例程进程,最后是用户自定义代码的编写处。至于例程进程,可参考文件链接如下:
链接:https://pan.baidu.com/s/173Ek7qeY0i3ibqt9vvfuUg
提取码:SYHT
W801单片机SDK例程使用手册-单片机文档类资源-CSDN下载
至此,W801的启动流程分析完毕。
下期分享W801的SDK中一些让人不爽的地方,并提出修改建议。