4297|1

1382

帖子

2

TA的资源

五彩晶圆(初级)

楼主
 

STM32MP157A-DK1测评 (7) M4核程序小试 [复制链接]

 
本帖最后由 cruelfox 于 2020-4-30 00:46 编辑

  前面玩的都是 STM32MP157A 的 Cortex-A7 核,因为这对我而言是新东西。除了两个A7核,此芯片还配备了一个 Cortex-m4 核。不过 M4 核的地位要“矮”一些,在对片上设备的访问权限上是 A7 核当领导的。STM32MP157A 内部没有 Flash, Boot ROM 仅是给 A7 核运行的,因此 M4 核运行的程序需要由 A7 核提供给它。这样也有更大的灵活性,可以在 Linux 运行时候动态地为 M4 核加载软件。

  STM32MP157 有一个 "Engineering Mode",留给调试使用。在 DK1 开发板上,可以将底下的BOOT开关设成 BOOT0=0, BOOT2=1状态,就进入"Engineering Mode" (wiki上介绍了,但数据表中没有说,只描述为 ”Reserved(Noboot)“)。在这个模式下,ROM Bootloader 会将 M4 核启动,可以用 OpenOCD 调试 M4 核程序。我以前调试时,OpenOCD列出来的 cpu2 (对应M4核)状态总是 "examine deferred" 所以无法访问它。
  但是我更改 BOOT 状态重开机后,发现 cpu2 仍然是 "examine deferred".  似乎是调试器本身的问题。后来从网络上找到答案——还需要在 OpenOCD 中使用 set ENG_MODE 1 命令。这样就能切换到调试 M4 核了。

  这样就有点像以前STM32那样调试的感觉了,除了没有Flash, 不能 reset init 停在第一条指令之外。两个A7核是保持运行状态的,切换后halt命令只对cpu2有效。(切换前是对cpu0, cpu1一起有效,还不能单独停止cpu0或cpu1, 这个问题我不明白)

 

  为了测试 M4 核,我拿个以前的程序改一下:

int main(void)
{
	gpio_config();
	xTaskCreate( blink1, "Blink One", STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );
	xTaskCreate( blink2, "Blink Two", STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );
	xTaskCreate( blink3, "Blink Three", STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );
	xTaskCreate( blink4, "Blink Four", STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );

	vTaskStartScheduler();
}

就是搭了个FreeRTOS的框架,用4个任务分别以不同的时间间隔操作GPIO翻转,使不同的LED亮灭变化。GPIO的寄存器操作和 STM32F4 一样,RCC中使能GPIO的操作与 STM32F4 有所不同,我在A7程序编写时已发现。因为现在不涉及和 A7 核争用资源,所以不考虑其它的。

  除了必须的寄存器定义头文件 stm32mp157axx_cm4.h , 从开发软件包中还可以找到 startup_stm32mp15xx.s 启动文件(包含中断向量表,ResetHandler代码),和 stm32mp15x_m4.ld 链接脚本。这样用 GCC 编译程序需要的文件就够了。注意提供的 LD 脚本中对内存分配的描述:

MEMORY
{
  m_interrupts (RX)  : ORIGIN = 0x00000000, LENGTH = 0x00000298
  m_text       (RX)  : ORIGIN = 0x10000000, LENGTH = 0x00020000
  m_data       (RW)  : ORIGIN = 0x10020000, LENGTH = 0x00020000
  m_ipc_shm    (RW)  : ORIGIN = 0x10040000, LENGTH = 0x00008000
}

  M4核执行的程序是放在几块 SRAM 中的,和 A7 核的 SYSRAM 彼此不干扰。编译得到 HEX 文件,可以用 OpenOCD 载入运行。操作命令如下:

> load_image f:/test.hex
664 bytes written at address 0x00000000
3076 bytes written at address 0x10000000
downloaded 3740 bytes in 0.031250s (116.875 KiB/s)
> mdw 0 2
0x00000000: 10040000 10000b71
> reg sp 0x10040000
sp (/32): 0x10040000
> reg pc 0x10000b71
pc (/32): 0x10000B71
> resume

  虽然中断向量表写在 0x0 处,但只有 reset 时才能加载,现在只能改 SP 和 PC 寄存器手动初始化。最后用 resume 命令让 M4 核跑起来。


  那么只有 Engineer mode 才能调试 M4 核?当然不是这样,只是这个模式下 ROM bootloader 让这个核启动了而已。默认,M4核是被停住的,需要软件让它起来:

  手册中说,BOOT_MCU 位(RCC的MP_GCR寄存器里面)写成1,当MCU复位时,才脱离Stop状态。那么我就来测试一下:将板子调到正常启动模式,通电,启动到 U-Boot 提示时在终端里按个键让 u-boot 等待。然后启动 OpenOCD,并使用 set ENG_MODE 1 连接板子。此时,查看 M4 核状态有所不同:

> targets
    TargetName         Type       Endian TapName            State
--  ------------------ ---------- ------ ------------------ ------------
 0* stm32mp15x.cpu0    cortex_a   little stm32mp15x.tap     running
 1  stm32mp15x.cpu1    cortex_a   little stm32mp15x.tap     running
 2  stm32mp15x.axi     mem_ap     little stm32mp15x.tap     running
 3  stm32mp15x.ap1     mem_ap     little stm32mp15x.tap     running
 4  stm32mp15x.cpu2    cortex_m   little stm32mp15x.tap     unknown
 5  stm32mp15x.ap2     mem_ap     little stm32mp15x.tap     unknown

因为它还处于 CStop 状态。我就将 BOOT_MCU 置1试试(寄存器地址 0x5000010C):

> mdw 0x5000010c
0x5000010c: 00000000
> mww 0x5000010c 1
> mdw 0x5000010c
0x5000010c: 00000001

再让 MCU 复位。按 reset 开关当然不行,不能复位其它部分。从手册中我找到这个寄存器:

其中 bit2 是 MCURST, 写1就可以复位 MCU 了。于是执行:

> mww 0x50000404 2
> targets
    TargetName         Type       Endian TapName            State
--  ------------------ ---------- ------ ------------------ ------------
 0* stm32mp15x.cpu0    cortex_a   little stm32mp15x.tap     halted
 1  stm32mp15x.cpu1    cortex_a   little stm32mp15x.tap     halted
 2  stm32mp15x.axi     mem_ap     little stm32mp15x.tap     running
 3  stm32mp15x.ap1     mem_ap     little stm32mp15x.tap     running
 4  stm32mp15x.cpu2    cortex_m   little stm32mp15x.tap     unknown
 5  stm32mp15x.ap2     mem_ap     little stm32mp15x.tap     unknown

但 OpenOCD 还没有识别这个核的状态?可能是 OpenOCD 的问题,于是我将 OpenOCD 退出,重新连接,查看状态——好了,cpu2 处于 halted.

 

  那么我就能将程序装到 SRAM 了,采用同样的 load_image 命令。然后,我将 MCU 复位让它从中断向量表获取入口地址。

> targets stm32mp15x.cpu2

> load_image f:/test.hex
664 bytes written at address 0x00000000
3076 bytes written at address 0x10000000
downloaded 3740 bytes in 0.031250s (116.875 KiB/s)

> targets stm32mp15x.cpu0

> mww 0x50000404 2

  复位MCU的操作必须由MCU来进行,所以在 OpenOCD 中需要切换 targets. 

  从 LED 闪烁状态我可以判定 M4 核程序已经正常运行了。

  这会 A7 核仍然在 halted 状态,那我就恢复它,然后让 U-Boot 接着完成后面的工作:启动 Linux. LED继续闪烁着,然后在 Linux 系统启动过程中,闪烁状态消失了——我想该是 Linux 接管了 GPIO,于是 M4 程序无法操作它们。在 OpenOCD 中却已无法调试 M4 核了,看来 Linux 对 M4 的运行已有干预了,这只有深入下去才知道……

  让 A7 核和 M4 核协同工作是更高级的话题。STM32MP157 硬件上有一些设计用来让MPU和MCU子系统之间通信,软件上也有相应支持的框架。若让 Linux 进入 Suspend to RAM 模式,保留 M4 核在低功耗运行处理简单任务,只在需要的时候才唤醒 A7 核恢复 Linux 执行,将比单纯的 Linux 系统更节省功耗。


此内容由EEWORLD论坛网友cruelfox原创,如需转载或用于商业用途需征得作者同意并注明出处

最新回复

谢谢楼主分享   详情 回复 发表于 2020-5-9 07:51

赞赏

1

查看全部赞赏

点赞(1) 关注
 
 

回复
举报

1万

帖子

2853

TA的资源

管理员

沙发
 

谢谢楼主分享

加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
个人签名玩板看这里:
https://bbs.eeworld.com.cn/elecplay.html
EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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

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

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

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