OpenEdv-开源电子网

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

脱离IDE,使用汇编在战舰上点个灯

[复制链接]

15

主题

786

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3223
金钱
3223
注册时间
2015-7-26
在线时间
811 小时
发表于 2018-11-28 21:29:13 | 显示全部楼层 |阅读模式
本帖最后由 it_do_just 于 2019-11-7 07:49 编辑

很久没回来发贴了,最近抽空写了个简单的汇编程序,由于我后面开发大多在linux平台下进行,所以这次写这个程序的时候也考虑了下使用gcc来完成整个编译链接的过程,当然实际开发不会这么做,毕竟代码一大了,写起Makefile来还是比较麻烦的,而且也没有IDE这个强大的调试追踪功能,所以使用gcc和汇编来完成点灯纯粹仅供学习,这个程序没有使用官方提供的启动文件,也没有那些官方的配置文件,做到了一个文件就能点灯,下面是点灯的汇编代码,可以直接使用原子提供的FlyMcu这个isp下载工具把这段代码进行编译链接后下载到战舰上测试。
首先使用 EQU 指示字来定义常数, 主要是定义寄存器地址和一些操作数
  1. ;RCC 寄存器地址定义
  2. .equ        RCC_BASE,                 0x40021000
  3. .equ        RCC_CR,                         (RCC_BASE + 0x00)
  4. .equ        RCC_CFGR,        (RCC_BASE + 0x04)
  5. .equ        RCC_APB2ENR,     (RCC_BASE + 0x18)

  6. ;GPIOB 寄存器地址定义
  7. .equ        GPIOB_BASE,      0x40010C00
  8. .equ        GPIOB_CRL,       (GPIOB_BASE + 0x00)
  9. .equ        GPIOB_ODR,       (GPIOB_BASE + 0x0C)

  10. ;FLASH缓冲区及访问速度配置
  11. .equ        FLASH_ACR,             0x40022000

  12. ;用于操作寄存器的一些常数
  13. .equ        Bit0,            0x00000001
  14. .equ        Bit1,            0x00000002
  15. .equ        Bit2,            0x00000004
  16. .equ        Bit3,            0x00000008
  17. .equ        Bit4,            0x00000010
  18. .equ        Bit5,            0x00000020
  19. .equ        Bit6,            0x00000040
  20. .equ        Bit7,            0x00000080
  21. .equ        Bit8,            0x00000100
  22. .equ        Bit9,            0x00000200
  23. .equ        Bit10,           0x00000400
  24. .equ        Bit11,           0x00000800
  25. .equ        Bit12,           0x00001000
  26. .equ        Bit13,           0x00002000
  27. .equ        Bit14,           0x00004000
  28. .equ        Bit15,           0x00008000
  29. .equ        Bit16,           0x00010000
  30. .equ        Bit17,           0x00020000
  31. .equ        Bit18,           0x00040000
  32. .equ        Bit19,           0x00080000
  33. .equ        Bit20,           0x00100000
  34. .equ        Bit21,           0x00200000
  35. .equ        Bit22,           0x00400000
  36. .equ        Bit23,           0x00800000
  37. .equ        Bit24,           0x01000000
  38. .equ        Bit25,           0x02000000
  39. .equ        Bit26,           0x04000000
  40. .equ        Bit27,           0x08000000
  41. .equ        Bit28,           0x10000000
  42. .equ        Bit29,           0x20000000
  43. .equ        Bit30,           0x40000000
  44. .equ        Bit31,           0x80000000

  45.         .equ        STACK_TOP,        0x20000800
  46.         .text
  47.         .global _start
  48.         .code 16
  49.         .syntax unified

  50. _start:
  51.         .word STACK_TOP, start
  52.         .type start, function
  53.         
  54.         
  55. start:
  56.         ;外部高速时钟时能 RCC->CR |= Bit16
  57.         LDR                R0, =RCC_CR
  58.         LDR                R1, [R0]
  59.         ORR                R1, #Bit16
  60.         STR                R1, [R0]
  61.         
  62.         ;检验外部时钟是否就绪
  63. RCC_CLK_NOTOK:
  64.         LDR                R1, [R0]
  65.         ANDS        R1, #Bit17
  66.         BEQ                RCC_CLK_NOTOK
  67.         LDR                R1, [R0]
  68.         ORR                R1, #Bit17
  69.         STR                R1, [R0]
  70.         
  71.         ;FLASH缓冲区及访问速度配置
  72.         LDR                R0, =FLASH_ACR
  73.         MOV                R1, #0X00000032
  74.         STR                R1, [R0]
  75.         
  76.         ;设置系统时钟倍频
  77.         LDR                R0, =RCC_CFGR
  78.         LDR                R1, [R0]
  79.         
  80.         ;HCLK 2分频
  81.         ORR                R1, #Bit10
  82.         
  83.         ;9倍频[21:18]-->0111
  84.         ORR                R1, #Bit18
  85.         ORR                R1, #Bit19
  86.         ORR                R1, #Bit20

  87.         ;设置HSE为PLL输入时钟源
  88.         ORR                R1, #Bit16
  89.         STR                R1, [R0]
  90.         
  91.         ;开启倍频
  92.         LDR                R0, =RCC_CR
  93.         LDR                R1, [R0]
  94.         ORR                R1, #Bit24
  95.         STR                R1, [R0]
  96.         
  97.         ;等待倍频生效
  98. RCC_PLL_NOTOK:        
  99.         LDR                R1, [R0]
  100.         ANDS        R1, #Bit25
  101.         BEQ                RCC_PLL_NOTOK
  102.         
  103.         ;设置PLL为当前系统时钟
  104.         LDR                R0, =RCC_CFGR
  105.         LDR                R1, [R0]
  106.         ORR                R1, #Bit1
  107.         STR                R1, [R0]

  108.         ;验证系统时钟状态是否切换为PLL
  109.         MOV                R2, #0X02
  110. RCC_PLL_NOTRDY:        
  111.         LDR                R1, [R0]
  112.         LSR                R1, R1, #2
  113.         AND                R1, #0X03
  114.         CMP                R1, R2
  115.         BNE                RCC_PLL_NOTRDY
  116.         

  117.         ;开启APB2口时钟
  118.         LDR                R0, =RCC_APB2ENR
  119.         LDR                R1, [R0]
  120.         ORR                R1, #Bit3
  121.         STR                R1, [R0]
  122.         
  123.         ;配置PB口功能,PB5设置为通用推挽输出
  124.         LDR                R0, =GPIOB_CRL
  125.         LDR                R1, [R0]
  126.         LDR                R2, =0XFF0FFFFF
  127.         AND                R1, R2
  128.         MOV                R2, #0X03
  129.         ORR                R1, R1, R2, LSL #20
  130.         STR                R1, [R0]
  131.         
  132.         ;初始化led灯的状态,默认打开        
  133.         LDR                R0, =GPIOB_ODR
  134.         LDR                R1, [R0]
  135.         ORR                R1, #0
  136.         STR                R1, [R0]

  137.         ;死循环
  138. deadloop:
  139.         b deadloop        
  140.         .end
复制代码

上面代码的寄存器的配置参考了原子哥代码和网友代码的配置,这部分配置跟原来没什么差别,如果嫌看手册麻烦,也可以反汇编原子哥提供的例程代码,可以很容易得出汇编配置的代码,copy过来用也行。这份汇编代码的反汇编文件我会作为附件上传上来,总的来说就是先配置时钟再配置GPIO,也没有把中断向量表加进来,纯粹的为了点个灯,具体汇编指令的含义如下:
1 . word :指示字定义 MSP 起始值为 0x2000_0800,并且把”start”作为复位向量。
2 . text :也是一个预定义的指示字,表示从这以后是一个代码区,需要予以汇编。
3 . global :使_start 标号可以由其它目标文件使用。
4 . code 16 :指示程序代码使用 thumb 写成。
5 . syntax unified :指示使用了统一汇编语言语法。
6 . _start :是一个标号,指示出程序区的入口点
7 . start :是另一个标号,它指示复位向量。
8 . type start, function :宣告了 start 是一个函数。对于所有处于向量表中的异常向量,这种
宣告都是必要的,否则汇编器会把向量的 LSB 清零——这在 thumb 中是不允许的。
9 . end :指示程序文件的结束

其它汇编指令含义如下:
EQU:指示字来定义常数
LDR : 从存储器中加载字到一个寄存器中
ORR : 按位或
STR : 把一个寄存器按字存储到存储器中
ANDS/AND : 按位与
BEQ : 数据跳转指令, 标志寄存器中Z标志位等于零时, 跳转到BEQ后标签处
BNE : 数据跳转指令,标志寄存器中Z标志位不等于零时, 跳转到BNE后标签处
MOV : 寄存器加载数据,既能用于寄存器间的传输,也能用于加载立即数
LSR : 逻辑右移
LSL:逻辑左移
b : 跳转

上面有关于 FLASH_ACR 的配置寄存器信息如下:
1.png

上面的代码写完后就可以使用 gcc 来编译啦,当前提是你已经搭建好了linux的开发环境,我使用的ubuntu18,安装相应的编译器指令如下:
sudo apt-get install gcc-arm-none-eabi

下载好编译器后,使用下面的指令进行编译链接:
编译:arm-none-eabi-as -mcpu=cortex-m3 -mthumb led.s -o led.o
链接:arm-none-eabi-ld -Ttext 0x8000000 -o led.out led.o
生成反汇编:arm-none-eabi-objdump -S led.out > led.list  
生成hex文件:arm-none-eabi-objcopy -Oihex led.out led.hex

3.png

需要说明的是上面 -Ttext 0x8000000 用于指示代码段的存放地址,编译后就可以把 hex 文件通过串口下载到战舰开发板上啦,串口烧写过程原子哥的教程有说明,使用FlyMcu这个软件就可以了。
最后就是激动人心的点灯效果了:

2.jpg





led.zip

2.07 KB, 下载次数: 29

我的博客:http://blog.csdn.net/itdo_just
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13135
金钱
13135
注册时间
2012-11-26
在线时间
3814 小时
发表于 2018-11-28 22:16:28 | 显示全部楼层
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2018-11-29 10:19:25 | 显示全部楼层
cool
回复 支持 反对

使用道具 举报

2

主题

194

帖子

0

精华

高级会员

Rank: 4

积分
981
金钱
981
注册时间
2015-9-20
在线时间
148 小时
发表于 2018-11-29 10:51:14 | 显示全部楼层
厉害了。。
回复 支持 反对

使用道具 举报

15

主题

786

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3223
金钱
3223
注册时间
2015-7-26
在线时间
811 小时
 楼主| 发表于 2018-11-29 16:04:14 | 显示全部楼层
我的博客:http://blog.csdn.net/itdo_just
回复 支持 反对

使用道具 举报

33

主题

159

帖子

0

精华

高级会员

Rank: 4

积分
527
金钱
527
注册时间
2017-1-21
在线时间
192 小时
发表于 2018-11-29 16:54:48 | 显示全部楼层
膜拜大神,万分期待大神用汇编跑原子的综合试验。哈哈哈哈。
回复 支持 反对

使用道具 举报

15

主题

786

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3223
金钱
3223
注册时间
2015-7-26
在线时间
811 小时
 楼主| 发表于 2018-11-29 17:21:05 | 显示全部楼层
oyixi001 发表于 2018-11-29 16:54
膜拜大神,万分期待大神用汇编跑原子的综合试验。哈哈哈哈。

你这工作量就大了,聪明人不做那种事
我的博客:http://blog.csdn.net/itdo_just
回复 支持 反对

使用道具 举报

10

主题

71

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
478
金钱
478
注册时间
2018-10-7
在线时间
66 小时
发表于 2018-11-29 17:25:08 | 显示全部楼层
虽然很麻烦,但是不得不说大佬牛掰
回复 支持 反对

使用道具 举报

13

主题

633

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2018-11-30 17:37:28 | 显示全部楼层
已结这么厉害了牛逼
Loto虚拟示波器 官方qq群: 706769836 https://shop296209296.taobao.com/shop/view_shop.htm?tracelog=t
回复 支持 反对

使用道具 举报

13

主题

633

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2018-11-30 17:37:49 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

13

主题

633

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2018-11-30 17:39:13 | 显示全部楼层
佩服您
回复 支持 反对

使用道具 举报

17

主题

466

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2164
金钱
2164
注册时间
2013-1-11
在线时间
510 小时
发表于 2018-11-30 18:18:56 | 显示全部楼层
佩服佩服
回复 支持 反对

使用道具 举报

头像被屏蔽

12

主题

167

帖子

0

精华

禁止访问

积分
517
金钱
517
注册时间
2017-5-30
在线时间
110 小时
发表于 2018-11-30 18:51:47 | 显示全部楼层
这样就是精华了?感觉没什么难度啊,代码也不算精简。
之前我用ASM实现了单双精度浮点四则运算,也没见有人捧场,更不要说版主推荐了。
可惜没时间,以后我还想自己实现一些常见的数学运算。
签名被屏蔽
回复 支持 反对

使用道具 举报

15

主题

786

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3223
金钱
3223
注册时间
2015-7-26
在线时间
811 小时
 楼主| 发表于 2018-12-2 17:06:52 | 显示全部楼层
NULLFF 发表于 2018-11-30 18:51
这样就是精华了?感觉没什么难度啊,代码也不算精简。
之前我用ASM实现了单双精度浮点四则运算,也没见有 ...

代码上确实是没什么难度的,可能只是因为比较少人用gcc自己编译链接吧,点个灯只是抛砖引玉罢了,呵呵
我的博客:http://blog.csdn.net/itdo_just
回复 支持 反对

使用道具 举报

头像被屏蔽

12

主题

167

帖子

0

精华

禁止访问

积分
517
金钱
517
注册时间
2017-5-30
在线时间
110 小时
发表于 2018-12-3 11:54:33 | 显示全部楼层
229382777@qq.co 发表于 2018-12-2 17:06
代码上确实是没什么难度的,可能只是因为比较少人用gcc自己编译链接吧,点个灯只是抛砖引玉罢了,呵呵

gcc好处是什么,在Windows下的集成开发环境己经做好了一切,很方便。gcc要写除了源码外的不少脚本呢。
签名被屏蔽
回复 支持 反对

使用道具 举报

0

主题

62

帖子

0

精华

初级会员

Rank: 2

积分
111
金钱
111
注册时间
2018-11-29
在线时间
9 小时
发表于 2018-12-3 12:51:00 | 显示全部楼层
炫酷666
回复 支持 反对

使用道具 举报

15

主题

786

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3223
金钱
3223
注册时间
2015-7-26
在线时间
811 小时
 楼主| 发表于 2018-12-3 14:03:18 | 显示全部楼层
NULLFF 发表于 2018-12-3 11:54
gcc好处是什么,在Windows下的集成开发环境己经做好了一切,很方便。gcc要写除了源码外的不少脚本呢。

MCU上gcc用在开发中没任何好处,只能说有利于学习吧,此贴主要让人了解最底层的操作形式,自己来实现编译链接和代码段的定位这些,如何不依赖ST提供的启动文件,如果真的要这么做写通用的Makefile也是挺麻烦的
我的博客:http://blog.csdn.net/itdo_just
回复 支持 反对

使用道具 举报

6

主题

36

帖子

1

精华

初级会员

Rank: 2

积分
169
金钱
169
注册时间
2018-12-5
在线时间
4 小时
发表于 2018-12-5 16:39:19 | 显示全部楼层
电灯是个大学问呢
回复 支持 反对

使用道具 举报

0

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2019-4-11
在线时间
4 小时
发表于 2019-4-12 17:22:27 | 显示全部楼层
太牛逼了
回复 支持 反对

使用道具 举报

18

主题

80

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
313
金钱
313
注册时间
2019-4-2
在线时间
31 小时
发表于 2019-4-13 12:04:16 | 显示全部楼层
大佬呀
回复 支持 反对

使用道具 举报

8

主题

56

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
224
金钱
224
注册时间
2019-4-17
在线时间
34 小时
发表于 2020-5-8 10:34:43 | 显示全部楼层
收下我的膝盖
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-28 03:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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