在线时间49 小时
UID3126933
注册时间2015-10-21
NXP金币0
TA的每日心情 | 开心 2017-7-10 09:04 |
---|
签到天数: 3 天 连续签到: 1 天 [LV.2]偶尔看看I
中级会员
 
- 积分
- 342
- 最后登录
- 2020-7-29
|
本帖最后由 baicaiaichibaicai 于 2017-6-23 18:13 编辑
板子还没到,但是离本周交卷的时间不多了,那就趁板子还没来,先来熟悉一下双核的启动,参考的是SDK_2.2.1_LPC54114J256\boards\lpcxpresso54114\multicore_examples\hello_world例程。
系统复位后,执行的时片内ROM的代码,片内ROM功能有两个,一个是ISP,另外一个就是启动应用程序。
ROM根据管脚判断是否进入ISP模式,如果不是进入ISP模式就根据镜像的头部信息来启动旧镜像/单镜像/双镜像,详见《UM10914.pdf》的Chapter 6: LPC5411x Boot process,我就挑最简单的流程,复位后没有进入ISP,直接进入旧镜像的启动。
ROM执行完后,应该是M0+内核和M4内核同时运行(此处为猜测,未找到官方描述,有知道的同学还望指教一下)。
看一下两者的入口代码Reset_Handler,两者的入口代码一样,见startup_LPC54114_cm4.s或者startup_LPC54114_cm0plus.s
- AREA |.text|, CODE, READONLY
- cpu_id EQU 0xE000ED00
- cpu_ctrl EQU 0x40000800
- coproc_boot EQU 0x40000804
- coproc_stack EQU 0x40000808
- rel_vals
- DCD cpu_id, cpu_ctrl, coproc_boot, coproc_stack
- DCW 0xFFF, 0xC24
- ; Reset Handler - shared for both cores
- Reset_Handler PROC
- EXPORT Reset_Handler [WEAK]
- IMPORT SystemInit
- IMPORT __main
- IF :LNOT::DEF:SLAVEBOOT
- ; Both the M0+ and M4 core come via this shared startup code,
- ; but the M0+ and M4 core have different vector tables.
- ; Determine if the core executing this code is the master or
- ; the slave and handle each core state individually.
- shared_boot_entry
- LDR r6, =rel_vals
- MOVS r4, #0 ; Flag for slave core (0)
- MOVS r5, #1
- ; Determine which core (M0+ or M4) this code is running on
- ; r2 = (((*cpu_id) >> 4) & 0xFFF); (M4 core == 0xC24)
- get_current_core_id
- LDR r0, [r6, #0]
- LDR r1, [r0] ; r1 = CPU ID status
- LSRS r1, r1, #4 ; Right justify 12 CPU ID bits
- LDRH r2, [r6, #16] ; Mask for CPU ID bits
- ANDS r2, r1, r2 ; r2 = ARM COrtex CPU ID
- LDRH r3, [r6, #18] ; Mask for CPU ID bits
- CMP r3, r2 ; Core ID matches M4 identifier
- BNE get_master_status
- MOV r4, r5 ; Set flag for master core (1)
- ; Determine if M4 core is the master or slave
- ; r3 = ((*cpu_ctrl) & 1); (0 == m0+, 1 == M4)
- get_master_status
- LDR r0, [r6, #4]
- LDR r3, [r0] ; r3 = SYSCON co-processor CPU control status
- ANDS r3, r3, r5 ; r3 = (Bit 0: 1 = M4 is master, 0 = M4 is slave)
- ; Select boot based on selected master core and core ID
- select_boot
- EORS r3, r3, r4 ; r4 = (Bit 0: 0 = master, 1 = slave)
- BNE slave_boot
- B normal_boot
- ; Slave boot
- slave_boot
- LDR r0, [r6, #8]
- LDR r2, [r0] ; r1 = SYSCON co-processor boot address
- CMP r2, #0 ; Slave boot address = 0 (not set up)?
- BEQ cpu_sleep
- LDR r0, [r6, #12]
- LDR r1, [r0] ; r5 = SYSCON co-processor stack address
- MOV sp, r1 ; Update slave CPU stack pointer
- ; Be sure to update VTOR for the slave MCU to point to the
- ; slave vector table in boot memory
- BX r2 ; Jump to slave boot address
- ; Slave isn't yet setup for system boot from the master
- ; so sleep until the master sets it up and then reboots it
- cpu_sleep
- MOV sp, r5 ; Will force exception if something happens
- cpu_sleep_wfi
- WFI ; Sleep forever until master reboots
- B cpu_sleep_wfi
- ENDIF
- ; Normal boot for master/slave
- normal_boot
- LDR r0, =SystemInit
- BLX r0
- LDR r0, =__main
- BX r0
- ENDP
复制代码 注释都比较清楚,大致的流程是:
1. 先从寄存器地址0xE000ED00获取到CPU的ID,(本寄存器我在数据手册上面也没找到,有知道的同学还望再指教一下)。
2. 在get_master_status中判断出执行这段代码是M0+核还是M4核。
3. 在select_boot中判断,如果是M0+的核则跳转到slave_boot,如果是M4核则跳转到normal_boot
4. 在normal_boot中调用SystemInit函数,接着调用MDK的内部函数__main最终在该函数中进入main函数
5. 在slave_boot中判断SYSCON->BPBOOT是否为0,如果为0则跳转到cpu_sleep函数,否则跳转到以SYSCON->BPBOOT位地址的入口中执行。此时SYSCON->BPBOOT值应为0
也就是说,M4内核程序正常执行,M0+内核进入休眠。
M0+内核的启动是由M4内核触发的,编译M4内核的镜像时,要把M0+内核的镜像文件当作一个数据数组编译进来,在M4启动之后,通过设置SYSCON->BPBOOT和SYSCON->CPSTACK寄存器,最后在操作SYSCON->CPCTRL中的M0RST和M0EN位来启动M0+内核。
大致的流程就是如此,欢迎同学指教。
啥,你问我两个内核的中断向量表怎么处理。
哦哦,在startup_LPC54114_cm4.c或者startup_LPC54114_cm0plus.c文件中的SystemInit函数有对中断向量表进行重定向
SCB->VTOR = (uint32_t)&__Vectors;
这样子即可保证两个内核触发中断时响应的地址无误。
|
|