OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5503|回复: 8

stm32mp157裸机启动过程探寻

[复制链接]

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
发表于 2020-11-23 14:05:45 | 显示全部楼层 |阅读模式
本帖最后由 sppz 于 2020-11-26 14:28 编辑

第一时间入手的原子mp157,但说实话教程等于0,所以自己来探索了.本文是裸机启动mp157的教程,也可以是其重要资料的汇集,更是本人自己摸索的汇总.

--------分割线,以下为资料地址--------
代码[裸机启动mp157,时钟mpu600Mhz,axi264Mhz,mcu200Mhz,led,uart4可能更改]
启动流程综述
romcode概览[重要]
stm32header说明[重要]
stm32mp157数据手册及参考手册[重要]
原子mp157硬件参考手册


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2020-11-23 14:06:08 | 显示全部楼层
本帖最后由 sppz 于 2020-11-23 18:38 编辑

本层分析stm32mp157的启动流程
根据启动概览所说
stm32mp157把启动分成了romcode(bootrom),fsbl,ssbl,其中romcode是固化在芯片内部的启动程序,它根据不同的启动设置加载fsbl到内存,之后再由fsbl加载跳转ssbl等.所以,我们这里只关心romcode和fsbl.而我们的程序实际上就是fsbl.
据romcode概览所述,根据不同的启动配置进行初始化并加载fsbl到0x2ffc2400,0x2ffc0000是一段256kb的ram,前0x2400被romcode所用.



回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2020-11-23 14:06:38 | 显示全部楼层
本帖最后由 sppz 于 2020-12-19 22:40 编辑

被romcode所加载的image必须有一个header

我们可以直接用链接脚本生成这个头,但需要改动验证相关的字节,这里我们需要改checksum
链接脚本如下
  1. MEMORY
  2. {
  3.     _ram(rwx) : ORIGIN = 0x2ffc2400, LENGTH = 252928
  4. }

  5. ENTRY(px_entry)
  6. SECTIONS
  7. {
  8.     . = ALIGN(4);
  9.     /* stm32 header */
  10.     .stm32 :
  11.     {
  12.         LONG(0x324D5453); /* magic number "STM"32 */
  13.         QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); /* image signature */
  14.         LONG(0); /* image checksum */
  15.         LONG(0x00010000); /* header version */
  16.         LONG(SIZEOF(.ARM.exidx) + SIZEOF(.ARM.extab) + SIZEOF(.init_array) + SIZEOF(.rodata) + SIZEOF(.bss) + SIZEOF(.data) + SIZEOF(.text)); /* image length */
  17.         LONG(px_entry); /* image entry */
  18.         LONG(0); /* reserved */
  19.         LONG(0x2ffc2500); /* load address of image */
  20.         LONG(0); /* reserved */
  21.         LONG(0); /* image version */
  22.         LONG(0x00000001); /* option flags */
  23.         LONG(0x00000001); /* ECDSA algorithm */
  24.         QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); /* ECDSA public key */
  25.         QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); QUAD(0); SHORT(0); BYTE(0); /* padding */
  26.         BYTE(0x0); /* binary type */
  27.     }
  28.     > _ram
  29.     /* exception sections */
  30.     .ARM.exidx : { *(.ARM.exidx); } > _ram
  31.     .ARM.extab : { *(.ARM.extab); } > _ram
  32.     /* .init_array */
  33.     .init_array : { *.(init_array); } > _ram
  34.     /* rodata */
  35.     .rodata : { *(.rodata); . = . + (. % 4 == 0 ? 0 : 4 - . % 4); } > _ram
  36.     /* bss */
  37.     .bss : { *(.bss); . = . + (. % 4 == 0 ? 0 : 4 - . % 4); } > _ram
  38.     /* data */
  39.     .data : { *(.data); . = . + (. % 4 == 0 ? 0 : 4 - . % 4); } > _ram
  40.     /* text */
  41.     .text : { *(.text); . = . + (. % 4 == 0 ? 0 : 4 - . % 4); } > _ram
  42. }
复制代码


用此链接脚本生成程序后,再用objdump就可抽出带header的二进制内容
之后我们需要改动checksum
此处写一个最简单的小工具来计算和改写checksum,如下
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <cstdint>

  5. int main(int argc, char** argv) {
  6.     if (argc < 2) {
  7.         std::cout << "usage:" << argv[0] << "file" << std::endl;
  8.         return 1;
  9.     }
  10.     std::fstream file(argv[1], std::ios::in | std::ios::out | std::ios::binary);
  11.     if (!file.is_open()) {
  12.         std::cout << "open " << argv[1] << " filed" << std::endl;
  13.         return 1;
  14.     }
  15.     file.seekg(256);
  16.     std::uint32_t sum;
  17.     std::uint8_t v;
  18.     do {
  19.         v = (std::uint8_t)file.get();
  20.         if (file.eof()) {
  21.             break;
  22.         }
  23.         sum += v;
  24.     } while (true);
  25.     file.clear();
  26.     file.seekp(68);
  27.     file.write((char*)&sum, 4);
  28.     file.close();
复制代码

具体流程请参看程序相关makefile
回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2020-11-23 14:07:01 | 显示全部楼层
本帖最后由 sppz 于 2020-11-23 15:15 编辑

romcode fsbl加载方式这里说两个
usb应该会直接加载0x1对应的文件内容,具体请参看程序中的px.tsv(应该也是lba34)
sdcard则是依次尝试GPT名为fsbl1,fsbl2,失败后尝试lba34,lba546,具体可参看sdcard启动
回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2020-11-23 14:07:26 | 显示全部楼层
本帖最后由 sppz 于 2020-11-26 14:29 编辑

程序说明
1.将所有时钟切换到HSI
2.关闭所有PLL
3.打开HSE并设置PLL
4.设置PLL使得,MPU时钟=600Mhz,AXI时钟=264Mhz,MCU时钟=200Mhz(参考手册10.6.3的实现)
5.设置GPIO
6.重置并设置UART4使得UART4时钟为100Mhz,波特率为115200,使能接受和发送
7.发送字符串"boot."
8.循环延迟计算约一秒并切换led,发送字符串"switch.",重新进行8.

板子裸机启动代码[可能被更改]

回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2020-11-23 14:07:47 | 显示全部楼层
本帖最后由 sppz 于 2020-11-23 17:44 编辑

便民措施
usb启动即可
px.zip (1.54 KB, 下载次数: 147)
回复 支持 反对

使用道具 举报

1

主题

91

帖子

0

精华

高级会员

Rank: 4

积分
790
金钱
790
注册时间
2020-7-30
在线时间
117 小时
发表于 2020-11-23 17:34:44 | 显示全部楼层
可以啊,可以直接用官方的头部信息工具,在加汇编代码。这样比较方便,
神一样的少年
回复 支持 反对

使用道具 举报

14

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2018-9-14
在线时间
157 小时
 楼主| 发表于 2020-11-23 17:39:23 | 显示全部楼层
lclinux 发表于 2020-11-23 17:34
可以啊,可以直接用官方的头部信息工具,在加汇编代码。这样比较方便,

没研究官方的工具,反正简单,自己来
回复 支持 反对

使用道具 举报

3

主题

187

帖子

0

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
558
金钱
558
注册时间
2019-5-22
在线时间
267 小时
发表于 2020-11-23 19:55:06 | 显示全部楼层
帮顶
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-1-31 19:47

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表