8338|9

7452

帖子

18

TA的资源

五彩晶圆(高级)

楼主
 

【LPC54100】双核的引导 [复制链接]

 
本帖最后由 freebsder 于 2015-3-8 02:32 编辑

freebsder发于www.eeworld.com.cn,如需转载或转发请保留此行声明。

板子还没有拿到,以下文字是基于人肉计算机虚拟跑出来的,所以很可能会在板子拿到之后进行修正。

本来只想看看lpc54xxx的低功耗相关特性,不过既然有两个核也顺便瞄了一下这个功能,没想到的是居然nxp这次还搞了保留。。。有朋友也在询问这部分东西,所以一边墙裂鄙视这种流行于山寨国的行为,一边花了接近两个小时来寻找答案,先整理出来供大家参考。

新建基于lpcxpresso的S/M(艹,好工程,Slave/Master)的工程过程就不详表了,新建一个合一的image。

一、代码

里面有几个宏__MULTICORE_MASTER,__MULTICORE_MASTER_SLAVE_M4SLAVE, __MULTICORE_MASTER_SLAVE_M0SLAVE开关,需要注意的是虽然有定义__MULTICORE_MASTER_SLAVE_M4SLAVE这样的开关,但是不意味着M4核在启动时可以作为S,这里的定义只为了保持索引的完整性和对未来的扩展(假设下一款lpc65xxx就可以呢)。

M中的cr_startup_lpc5410x.c在ResetISR中的一段汇编,后面有调用ResetISR2。ResetISR2才是一般意义上cortex的ResetISR,前面的汇编是一段stub来辅助引导。在M的boot_multicore_slave.c中的boot_multicore_slave调用Chip_CPU_CM0Boot启动S。结果nxp以power库的形式给出来的,墙裂鄙视之,后面第三步在看回头说。S的ResetISR就比较简单了,基本就是cp data和bss清0,然后调用它自己的main,中间systeminit都被宏关掉了,想来所有资源(除了几个IRQ之外)都是可共享的,S也不需要来抢M的活。

二、工程

lpcxpresso是基于makefile的过程管理和gcc/ld的编译链接,这里也只涉及和双核有关的叙述,如果不熟悉的话,我也没法了。

S的ldscript是一个常规链接脚本,技巧性的东西在M的ldscript,S/M的Makefile中。

M的ldscript中.data_RAM2段完全包含S的所有代码,看见里面其实填充的是*(.core_m0slave)。另外__start_data_RAM2,__core_m0slave_END__等符号,在M的引导中需要为S设置,这是下面“引导”的前奏。

M的ld过程中,可以看到会把S.axf.o(S是Slave的工程名称)作为链接对象之一,添加到M.axf(M是Master的工程名称)。

倒回来看S的makefile,看到nxp又把关键部分写在很长的一行,不拉滚动还看不到的一句 arm-none-eabi-objcopy  。。。

里面关键的是 --redefine-sym __vectors_start__=__vectors_start___core_m0slave --keep-symbol __vectors_start___core_m0slave --rename-section .text=".core_m0slave" --rename-section .data=".core_m0slave.data"。

好吧,到这里也应该能知道M的ldscript中填充的东西,也应该能知道M的ld过程就是把S.axf.o的.data和.text两个段端到M的.data_RAM2中去。

三、引导

再一次鄙视nxp的这种行为,弄个库来糊弄人。

上电或复位的时候,两个核同时运行,但是S马上进入sleep状态,只有M继续按照正常流程运行。两者只有在引导过程中分S和M,一旦两者都引导起来之后,从执行上看他们地位平等,就没有S和M之分了。

M中的那一段汇编stub,它确实是汇编。这段汇编默认作为S/M复位时都要执行的一小段代码。S的复位,也是按照cortex手册规定的地址,当然这时候就和M的复位异常是一个地方。所以这段确实是汇编的代码只能用汇编来做是为了确保编出来的东西M0+核与M4核都可以运行。需要注意的是这段代码也和上面说的一些宏一样,为了完整性和扩展性,也把M做了S化处理。

那么里面有三个寄存器0x40000300,0x40000304,0x40000308手册里没有涉及。0x40000304 存放boot执行地址,0x40000308存放堆栈栈顶。这里相当于M作为S的固件,为M0+核填充了interrupt vector[0]和[1]。0x40000300 是控制寄存器,复位初始4D。[31:7]是保留位;[6:6]用于设置SM哪一个可以作为控制CPU来使得系统进入Sleep,Deep Sleep,Power-down和Deep Power-down模式,0=M0+,1=M4;[5:5]复位M0+核,0=disable,1=enable复位; [4:4]复位M4核, 0=disable,1=enable复位; [3:3] M0+时钟使能,0=disable,1=enable; [2:2] M4时钟使能,0=disable,1=enable; [1:1]保留位; [0:0]设置哪一个核作为M处理器,0=M0+核,1=M4核。这里实在没看出来不开放这部分内容的意义啊,好吧,把fsl都合并了,太有钱了,任性点也能理解。

再看那段小汇编,这里要注意的是S和M在复位时执行的是同一段代码,然后这段代码为了完整性写的比较绕。里面有注释,很好理解,大概意思是找CPUID寄存器先确定当前是哪个核,然后分开引导。如果M0+执行的时候发现0x40000304不为0(这是在M为S初始化环境时设置进去的),那么再把0x40000308拿出来,设置成SP,然后跳过去;如果M4执行的时候,基本可以忽略这段汇编而直接跳进ResetISR2。

从M的填充代码里可以看到相当于还是取出了S的int vector[0]和[1],标准的cortex中断向量,

    volatile unsigned int resetaddr;

    volatile  unsigned int spaddr;
    spaddr = *slavevectortable_ptr;
    resetaddr = *(slavevectortable_ptr+1);

    Chip_CPU_CM0Boot((uint32_t *)resetaddr, (uint32_t *)spaddr);

Chip_CPU_CM0Boot比较简单,可以找这段汇编

00000000 :
   0:        f04f 4380         mov.w        r3, #1073741824        ; 0x40000000
   4:        4a07              ldr        r2, [pc, #28]        ; (24 )
   6:        f8c3 1308         str.w        r1, [r3, #776]        ; 0x308
   a:        f8c3 0304         str.w        r0, [r3, #772]        ; 0x304
   e:        f8d3 0300         ldr.w        r0, [r3, #768]        ; 0x300
  12:        4905              ldr        r1, [pc, #20]        ; (28 )
  14:        4302              orrs        r2, r0
  16:        4301              orrs        r1, r0
  18:        f8c3 1300         str.w        r1, [r3, #768]        ; 0x300
  1c:        f8c3 2300         str.w        r2, [r3, #768]        ; 0x300
  20:        4770              bx        lr
  22:        bf00              nop
  24:        c0c40008         sbcgt        r0, r4, r8
  28:        c0c40028         sbcgt        r0, r4, r8, lsr #32

简单说,就是把引导地址和堆栈指针放到0x40000304和0x40000308里面去,然后把ctrl(0x40000300)的[5:5]复一次位(18:xxx),就可以正常启动了(1c:xxx)。

好了,引导完了。

此帖出自NXP MCU论坛

最新回复

牛人,感谢分享  详情 回复 发表于 2016-2-27 19:54

赞赏

1

查看全部赞赏

点赞 关注(3)
个人签名

默认摸鱼,再摸鱼。2022、9、28

 

回复
举报

1042

帖子

6

TA的资源

纯净的硅(中级)

沙发
 

强啊,都双核的MCU了;
此帖出自NXP MCU论坛
 
 
 

回复

527

帖子

1

TA的资源

一粒金砂(高级)

板凳
 
顶一个,看来想搞懂启动,汇编是必须得看的啊~
此帖出自NXP MCU论坛

点评

这次主要是nxp玩了手保留,不得已。平时基本还是不需要汇编什么的。  详情 回复 发表于 2015-3-9 10:33
 
 
 

回复

7452

帖子

18

TA的资源

五彩晶圆(高级)

4
 
这次主要是nxp玩了手保留,不得已。平时基本还是不需要汇编什么的。
此帖出自NXP MCU论坛

点评

看样子是啊,我还以为我添加的文件不够全,找不到这句话,以为会都开源,而且它提供的技术文章也支支吾吾,说的不全。  详情 回复 发表于 2015-3-9 13:29
 
 
 

回复

527

帖子

1

TA的资源

一粒金砂(高级)

5
 
freebsder 发表于 2015-3-9 10:33
这次主要是nxp玩了手保留,不得已。平时基本还是不需要汇编什么的。



看样子是啊,我还以为我添加的文件不够全,找不到这句话,以为会都开源,而且它提供的技术文章也支支吾吾,说的不全。
此帖出自NXP MCU论坛
 
 
 

回复

1295

帖子

0

TA的资源

纯净的硅(中级)

6
 
关注
此帖出自NXP MCU论坛
 
个人签名

 

 

 
 

回复

104

帖子

0

TA的资源

一粒金砂(中级)

7
 
赞。
此帖出自NXP MCU论坛
 
 
 

回复

116

帖子

2

TA的资源

一粒金砂(中级)

8
 
NXP总有些遮遮掩掩...
请教,这LPCOPEN库中的GPIO怎么有些只对port0可用呢?
在gpio_5410x.h

/**
* @brief        Set all GPIO raw pin states (regardless of masking)
* @param        pGPIO        : The base of GPIO peripheral on the chip
* @param        port        : port Number (supports port 0 only)  ????????????????????????????????/
* @param        value        : Value to set all GPIO pin states (0..n) to
* @return        Nothing
*/
__STATIC_INLINE void Chip_GPIO_SetPortValue(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t value)
{
        pGPIO->PIN[port] = value;
}
此帖出自NXP MCU论坛
 
个人签名熙熙攘攘的世界,我们不懈前行......
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

9
 
此帖出自NXP MCU论坛
 
个人签名光纤激光打标机 www.chinabote.net
 
 

回复

12

帖子

0

TA的资源

一粒金砂(初级)

10
 
牛人,感谢分享
此帖出自NXP MCU论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表