0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

浅析Zephyr在ESP32上的启动流程

ZephyrProject 来源:开源中国 作者:HalfCoder 2021-06-07 17:04 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

理解Zephyr在一款soc上的启动流程,有利于分析和调试开机过程卡死,驱动异常等的问题。因此在上手一款新的soc时掌握Zephyr在其上面的启动流程非常必要。本文对Zephyr在ESP32上的启动流程进行分析,说明ESP32从上电开始如何执行到Zephyr应用的main函数。

Zephyr支持两种ESP32引导方式:

配置CONFIG_BOOTLOADER_ESP_IDF=n:ROM Boot -》 Zephyr

配置CONFIG_BOOTLOADER_ESP_IDF=y. ROM Boot -》 ESP32 Bootloader -》 Zephyr

本文只分析CONFIG_BOOTLOADER_ESP_IDF=y的流程,在该流程理解另一种也类似,在CONFIG_BOOTLOADER_ESP_IDF=n的情况下相当于是在ESP32的bootloader处放了一个zephyr应用。

ESP32下Zephyr是被当作ESP32的APP被引导,因此有必要简单了解ESP32的启动流程

ESP32启动阶段

ESP32是双核CPU,其中cpu0叫做PRO CPU, cpu1叫做APP CPU,启动流程如下:

SOC上电, PRO CPU开始运行,跳到ROM 0x40000400 处复位向量代码处执行

在PRO CPU上运行ROM上一级引导代码从Flash的0x1000读出二级引导程序加载到内部IRAM

跳转到内部IRAM上二级引导程序执行

二级引导程序从 Flash 的 0x8000 偏移地址处读取分区表, 从分区表中读到APP的信息

二级引导程序将Zephyr数据和代码段复制到DRAM和IRAM。对于Zephyr内一些加载地址位于DROM和IROM区域的段,通过配置 Flash MMU 为其提供正确的映射。

二级引导程序会从Zephyr二进制镜像文件的头部寻找的入口地址,然后跳转到该地址处运行。

以上流程中1~3是已经被固化到ESP32的ROM中无法修改,4~6是由modules/hal/espressif/components/bootloader完成,可以做定制修改,但一般不修改。以上1~6都是在PRO CPU中执行。

Zephyr的入口地址就是函数__start,第六步后就会跳转到__start中执行

Zephyr阶段

Zephyr阶段运行到main主要步骤:__start-》z_cstart-》bg_thread_main-》main

__start

文件位置zephyr/soc/xtensa/esp32/soc.c, 主要完成下面内容:

搬移中断向量表

初始化bss段

关闭中断

确保APP CPU没有运行(将在后面SMP初始化阶段打开)

代码摘要如下

void __attribute__((section(“.iram1”))) \_\_start(void)

{

//搬移中断向量表

__asm__ __volatile__ (

“wsr %0, vecbase”

: “r”(&_init_start));

//BSS段初始化

(void)memset(&_bss_start, 0,

(&_bss_end - &_bss_start) * sizeof(_bss_start));

__asm__ __volatile__ (

“”

: “g”(&_bss_start)

: “memory”);

//关闭中断

__asm__ __volatile__ (

“wsr %0, PS”

: “r”(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE));

//关闭APP CPU

*app_cpu_config_reg &= ~DPORT_APPCPU_CLKGATE_EN;

//初始化cpu指针

__asm__ volatile(“wsr.MISC0 %0; rsync” : : “r”(&_kernel.cpus[0]));

//开始zephyr初始化

z_cstart();

CODE_UNREACHABLE;

}

是否发现跳到zephyr的__start是一个C函数,但之前Zephyr并没有做C堆栈(SP指针)初始化?这是因为在ESP32的bootloader阶段已经做了,Zephyr无需再做。

z_cstart

主要完成kernel初始化,PRE_KERNEL_1和PRE_KERNEL_2级别的驱动初始化,然后启动main thread:bg_thread_main,剩下的其它初始化和应用程序的main都在bg_thread_main中。

代码摘要如下

__boot_func

FUNC_NORETURN void z_cstart(void)

{

//架构相关的内核初始化

arch_kernel_init();

// static devices初始化

z_device_state_init();

//初始化PRE_KERNEL_1和PRE_KERNEL_2驱动,大多都是硬件相关

z_sys_init_run_level(_SYS_INIT_LEVEL_PRE_KERNEL_1);

z_sys_init_run_level(_SYS_INIT_LEVEL_PRE_KERNEL_2);

//创建并切换到main thread运行

switch_to_main_thread(prepare_multithreading());

CODE_UNREACHABLE; /* LCOV_EXCL_LINE */

}

__boot_func

static char *prepare_multithreading(void)

{

char *stack_ptr;

//初始化OS调度器

z_sched_init();

//创建main thread

stack_ptr = z_setup_new_thread(&z_main_thread, z_main_stack,

CONFIG_MAIN_STACK_SIZE, bg_thread_main,

NULL, NULL, NULL,

CONFIG_MAIN_THREAD_PRIORITY,

K_ESSENTIAL, “main”);

//将main thread加入到就绪态

z_mark_thread_as_started(&z_main_thread);

z_ready_thread(&z_main_thread);

//为每颗CPU 创建idle thread

for (int i = 0; i 《 CONFIG_MP_NUM_CPUS; i++) {

init_idle_thread(i);

_kernel.cpus[i].idle_thread = &z_idle_threads[i];

_kernel.cpus[i].id = i;

_kernel.cpus[i].irq_stack =

(Z_KERNEL_STACK_BUFFER(z_interrupt_stacks[i]) +

K_KERNEL_STACK_SIZEOF(z_interrupt_stacks[i]));

}

initialize_timeouts();

return stack_ptr;

}

main thread被加入到就绪态,因此下一次调度时bg_thread_main就会被执行

bg_thread_main

在bg_thread_main中完成剩余的驱动初始化,并且启动esp32的第二颗CPU: APP CPU, 然后运行到应用的main函数。

代码摘要如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

__boot_func

static void bg_thread_main(void *unused1, void *unused2, void *unused3)

{

z_sys_post_kernel = true;

//初始化POST_KERNEL级别驱动

z_sys_init_run_level(_SYS_INIT_LEVEL_POST_KERNEL);

boot_banner();

//初始化APPLICATION级别驱动

z_sys_init_run_level(_SYS_INIT_LEVEL_APPLICATION);

//初始化静态声明的thread

z_init_static_threads();

#ifdef CONFIG_SMP

//初始化SMP, 到这里才会启动ESP32的另一颗CPU

z_smp_init();

//初始SMP级别的驱动,例如跨CPU通信的mailbox, ipm驱动

z_sys_init_run_level(_SYS_INIT_LEVEL_SMP);

#endif

extern void main(void);

//执行应用程序的main

main();

/* Mark nonessenrial since main() has no more work to do */

z_main_thread.base.user_options &= ~K_ESSENTIAL;

}

关于main

这里调用的main函数,是在Zephyr应用程序中实现,最后通过链接器链接在一起。Zephyr应用程序的main是在main thread中执行,由于main thread的默认优先级比较高0, 因此要注意不要在main中去做while(1),避免导致其它抢占式线程拿不到CPU。

关于SMP

从前面的分析可以看到z_smp_init前,Zephyr上包括main thread的所有代码都是在PRO CPU上执行,在z_smp_init后Zephyr的代码才有机会运行到APP CPU上, SMP是一个很大的议题,不是在本文分析范围内。这里简单列出esp32 SMP初始化的主要流程供参考:

z_smp_init(smp.c)-》arch_start_cpu(esp32-mp.c)-》appcpu_start-》esp32_rom_ets_set_appcpu_boot_addr-》appcpu_entry1-》z_appcpu_stack_switch-》appcpu_entry2-》smp_init_top(smp.c)

参考

https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-guides/startup.html

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    11370

    浏览量

    226394
  • soc
    soc
    +关注

    关注

    40

    文章

    4658

    浏览量

    230573
  • SMP
    SMP
    +关注

    关注

    0

    文章

    82

    浏览量

    20990
  • ESP32
    +关注

    关注

    27

    文章

    1234

    浏览量

    22686

原文标题:Zephyr ESP32启动流程

文章出处:【微信号:ZephyrProject,微信公众号:ZephyrProject】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    乐鑫科技新品ESP32-H4亮点速递!

    近期,乐鑫科技新品发布节奏持续加快。作为乐鑫科技一级代理商,启明云端为您带来最新芯片产品ESP32-H4的详细解读。ESP32-H4隶属于乐鑫科技ESP32-H系列,低功耗物联网应用
    的头像 发表于 04-16 18:05 651次阅读
    乐鑫科技新品<b class='flag-5'>ESP32</b>-H4亮点速递!

    ESP32/ESP8266开发板单向多对一ESP-NOW无线通信

    本实验通过ESP-NOW无线通信协议实现多个ESP32/ESP 8266开发板向ESP32开发板发送数据。例如可以应用于从多个远程传感器
    的头像 发表于 03-30 10:14 296次阅读
    <b class='flag-5'>ESP32</b>/<b class='flag-5'>ESP</b>8266开发板单向多对一<b class='flag-5'>ESP</b>-NOW无线通信

    ESP32开发板单向点对点ESP-NOW无线通信

    本例程通过两个ESP32开发板实现单向点对点ESP-NOW无线通信,一个ESP32开发板作为Sender发送方,另一个开发板作为Receiver接收方接收发送方的数据。
    的头像 发表于 03-19 09:21 394次阅读
    <b class='flag-5'>ESP32</b>开发板单向点对点<b class='flag-5'>ESP</b>-NOW无线通信

    ESP32/ESP8266开发板单向一对多ESP-NOW无线通信

    通过ESP-NOW无线通信协议实现ESP32开发板向多个ESP32/ESP 8266开发板发送数据。
    的头像 发表于 03-13 09:23 372次阅读
    <b class='flag-5'>ESP32</b>/<b class='flag-5'>ESP</b>8266开发板单向一对多<b class='flag-5'>ESP</b>-NOW无线通信

    Zephyr OS启用NPU的实用方案

    今天,我们将正式 Zephyr中加入NPU软件支持,让模型不仅能“跑起来”,还能“跑得飞快”。是的,本期开始就是实战环节!
    的头像 发表于 03-09 10:37 1233次阅读
    <b class='flag-5'>在</b><b class='flag-5'>Zephyr</b> OS<b class='flag-5'>上</b>启用NPU的实用方案

    VisionFive 2 尝试 Zephyr 时没有输出是怎么回事?

    我按照指示进行作官方文档 VisionFive 2 测试 Zephyr hello_world demo,虽然我成功编译了目标程序,但发送到 UART 后,我 tty
    发表于 02-05 06:49

    ESP32开发板创建同步WebServer网页服务器

    ESP32 内置了 Wi-Fi 功能,能够作为网页服务器(Web Server)向网络中的其他设备提供服务。通过 ESP32 运行网页服务器,可以创建基于浏览器的用户界面,用于监控
    的头像 发表于 01-30 11:36 496次阅读
    <b class='flag-5'>ESP32</b>开发板创建同步WebServer网页服务器

    无需安装!浏览器里就能玩转ESP32/ESP8266,这个神器绝了!

    无需安装!浏览器里就能玩转ESP32/ESP8266,这个神器绝了!【往期精选】十年嵌入式最深的痛,不是Bug,而是抓不到日志!vivo宣布原生支持HomeAssistant生态设备接入(含
    的头像 发表于 01-10 10:01 1762次阅读
    无需安装!<b class='flag-5'>在</b>浏览器里就能玩转<b class='flag-5'>ESP32</b>/<b class='flag-5'>ESP</b>8266,这个神器绝了!

    ESP32 Wi-Fi 控制 LED 灯的原理

    智能家居、物联网设备中,用手机通过Wi-Fi控制灯光、风扇或插座,已经非常普遍。而在嵌入式开发中,ESP32是最常用的Wi-Fi模块之一。本文将带你系统理解:ESP32是如何通过Wi-Fi实现远程
    的头像 发表于 01-09 19:04 704次阅读
    <b class='flag-5'>ESP32</b> Wi-Fi 控制 LED 灯的原理

    ESP32蓝牙驱动MAX98357对音频音乐播放

    本文介绍了MAX98357音频模块的基本特性,并利用ESP32的蓝牙功能程序驱动此模块,最后用手机蓝牙连接ESP32播放手机音乐
    的头像 发表于 12-19 19:55 3477次阅读
    <b class='flag-5'>ESP32</b>蓝牙驱动MAX98357对音频音乐播放

    ESP32­WROOM­32 技术规格书

    电子发烧友网站提供《ESP32­WROOM­32 技术规格书.pdf》资料免费下载
    发表于 11-11 17:27 0次下载

    乐鑫ESP32-C6和ESP32-C61究竟该如何选择?一文读懂本质区别

    乐鑫科技推出的ESP32-C6和ESP32-C61均支持Wi-Fi6,但定位不同。ESP32-C6是多协议枢纽,集成Wi-Fi6、蓝牙5、Zigbee和Thread,适合智能家居网关和Matter
    的头像 发表于 10-28 14:17 2976次阅读
    乐鑫<b class='flag-5'>ESP32</b>-C6和<b class='flag-5'>ESP32</b>-C61究竟该如何选择?一文读懂本质区别

    ESP32开发板元件资料

    ESP32开发板元件
    发表于 07-21 14:47 17次下载

    ESP32-P4 C5开发板烧录小智全流程!速看!

    没错,你没有看错!我们带着WT99P4C5-S1开发板烧录小智全流程走来了!开发板搭载乐鑫科技ESP32-P4和ESP32-C5芯片,代码完全开源,支持灵活二次开发。什么?文字教程不好理解?别怕
    的头像 发表于 07-04 18:03 3189次阅读
    <b class='flag-5'>ESP32</b>-P4 C5开发板烧录小智全<b class='flag-5'>流程</b>!速看!

    ESP32-S3开发板烧录小智AI系统全流程指南

    AI语音交互领域不断发展的今天,开发者们对于功能强大、开源灵活的开发板需求日益增长。今天,我们就来详细了解一下ESP32AgentDevKit烧录小智的全流程,这款搭载乐鑫科技ESP32
    的头像 发表于 06-16 18:01 9135次阅读
    <b class='flag-5'>ESP32</b>-S3开发板烧录小智AI系统全<b class='flag-5'>流程</b>指南