EDA365电子论坛网

标题: ARM学习笔记 [打印本页]

作者: uperrua    时间: 2020-5-20 09:07
标题: ARM学习笔记
在ARM程序的开发中,需要大量读写硬件寄存器,尽量缩短程序的执行时间,因此部分初始化代码一般使用汇编语言来编写,比如ARM的启动代码,ARM的操作系统的移植代码等,除此之外,绝大多数代码可以使用C语言来完成。
: K/ ]# }6 s! B
- m! j7 O1 L) j/ _C语言使用的是标准的C语言,ARM的开发环境实际上就是嵌入了一个C语言的集成开发环境,只不过这个开发环境和ARM的硬件紧密相关。: v( t% r& V3 C' G
. ~# n5 [' B9 d# \5 g# ^
ARM使用C语言编程基本规则
5 a% Q$ \" N7 F4 q1 k  c7 U1 n! Q% w+ A/ @" x) |5 L& ?7 K
在应用系统的程序设计中,若所有的编程任务均由汇编语言来完成,其工作量巨大,并且不易移植。由于ARM的程序执行速度较高,存储器的存储速度和存储量也很高,因此,C语言的特点充分发挥,使得应用程序的开发时间大为缩短,代码的移植十分方便,程序的重复使用率提高,程序架构清晰易懂,管理较为容易等等。因此,C语言的在ARM编程中具有重要地位。0 s8 z4 P1 P8 I' K! ^' a9 C6 E

) r* r- Z' g8 c2 A0 j1 Y在ARM程序的开发中,需要大量读写硬件寄存器,尽量缩短程序的执行时间,因此部分初始化代码一般使用汇编语言来编写,比如ARM的启动代码,ARM的操作系统的移植代码等,除此之外,绝大多数代码可以使用C语言来完成。4 _" E- Z- {& ^  i  h% T4 _
; @- f' S" `% [+ Q& G
C语言使用的是标准的C语言,ARM的开发环境实际上就是嵌入了一个C语言的集成开发环境,只不过这个开发环境和ARM的硬件紧密相关。! E7 R* i1 p7 H& F) c

2 U" w( [8 r9 P' Q3 {在使用C语言时,有时要用到和汇编语言的混合编程。当汇编代码较为简洁,则可使用直接内嵌汇编的方法,否则,将汇编程序以文件的形式加入项目当中,通过ATPCS(ARM/Thumb Procedure Call Standard)的规定与C程序相互调用与访问。: ~$ _' g! }# _7 Z1 ~6 ?* _

; k& d/ u. u' Q; @ATPCS,就是ARM、Thumb的过程调用标准,它规定了一些子程序间调用的基本规则。如寄存器的使用规则,堆栈的使用规则,参数的传递规则等。
8 E/ F( S8 \' j0 q, f- X# h! b
) C4 \+ O! R, n; C9 k" v在C程序和ARM的汇编程序之间相互调用必须遵守ATPCS。而使用ADS的C语言编译器编译的C语言子程序满足用户指定的ATPCS的规则。但是,对于汇编语言来说,完全要依赖用户保证各个子程序遵循ATPCS的规则。具体来说,汇编语言的子程序应满足下面3个条件:
7 w( g% b8 w2 l4 A$ o- @- d+ H$ x/ r2 r9 V" N& @$ ]
.  在子程序编写时,必须遵守相应的ATPCS规则;
: j2 {8 Z& N$ A0 ]$ e: r
1 N# J0 P% p8 e.  堆栈的使用要遵守相应的ATPCS规则;! V9 v" J$ |4 y6 ~; z

! e8 Q; g5 {3 v.  在汇编编译器中使用-atpcs选项。
' ?9 I0 Z8 f, f6 i; J
1 ^: Z# \. ?( I. u; g9 U基本的ATPCS规定,详情请见相关PDF文档,简单说明就是:
3 K4 m+ s5 [( S5 |3 d; X: N3 w/ G2 i' K/ @
1. 汇编程序调用C程序# r% q: @) U) l. t3 ]
9 p3 F! V& o  q2 u" e4 m% C9 {5 Q
.  汇编程序的设置要遵循ATPCS规则,保证程序调用时参数正确传递。5 b0 Z& }# R: H, w- D) @

, G9 j& R! ]0 _5 u2 Q2 f! c.  在汇编程序中使用IMPORT伪指令声明将要调用的C程序函数。
) i- F) Z8 S  b; n0 Y6 d
5 K" S; n0 v9 K5 H6 `.  在调用C程序时,要正确设置入口参数,然后使用BL调用。
6 n# n" T9 X# t7 ]
2 `* p& U" b/ x2. C程序调用汇编程序/ }5 j$ ?8 s6 {0 O+ H+ h+ ]" W

# F) ^' s4 o$ @% v0 ]* _6 k4 i.  汇编程序的设置要遵循ATPCS规则,保证程序调用时参数正确传递。! @2 o2 P& h3 ?0 K. k
2 n* C. W6 a3 p3 F# r/ D' @  h' T4 R
.  在汇编程序中使用EXPORT伪指令声明本子程序,使其他程序可以调用此子程序。5 d3 }- H9 R3 V2 S" d+ ^0 D/ K. \6 y0 I
5 c! }, S$ _& N0 w
.  在C语言中使用extern关键字声明外部函数(声明要调用的汇编子程序)。
7 k  V0 X) [, r- f" G0 d$ A
5 W. [* S" d! Q" S5 H在C语言的环境内开发应用程序,一般需要一个汇编的启动程序,从汇编的启动程序,跳到C语言下的主程序,然后,执行C程序,在C环境下读写硬件的寄存器,一般是通过宏调用,在每个项目文件的Startup2410/INC目录下都有一个2410addr.h的头文件,那里面定义了所有关于2410的硬件寄存器的宏,对宏读写,就能操作2410的硬件,具体的编程规则同标准C语言。1 u9 l! B: h' Q. v- e5 J
  K, e. ^. [6 U3 ^1 C' l; W) W2 d

0 K1 Z! [! ]3 I
$ z" ]9 C7 C  c  L  b+ MARM Cortex™ 微控制器软件接口标准(CMSIS:CortexMicrocontroller Software Interface Standard) 是 Cortex-M 处理器系列的与供应商无关的硬件抽象层。
8 v% |$ t# H0 e$ y
8 a& x$ u4 }. I3 C+ c$ O& X9 \  p& d3 c9 A/ O# Z5 K
' W. \* W& a- E9 Z8 Y
+ G* H- _6 U3 ~+ U5 O
- K- }, \& Z  x) X
基于CMSIS标准的软件架构主要分为以下4层:用户应用层、操作系统及
7 q5 p0 U: r+ k5 @
* ~( N& h" {& ^% O$ G% e中间件接口层、CMSIS层、硬件寄存器层。其中CMSIS层起着承上启下的作用:一方面该层
/ c9 H. w8 l! Y* y' D% Y: ]$ N1 G) j9 R" |. l) P" U6 M. _8 G
对硬件寄存器层进行统一实现,屏蔽了不同厂商对Cortex‐M系列微处理器核内外设寄存器4 ]; b- b' P! N, k) D8 D) [8 M7 h7 {8 L
; V) A" S& X% S  K& G; a% l
的不同定义;另一方面又向上层的操作系统及中间件接口层和应用层提供接口,简化了应用! C4 {: ~. `( t0 q, g; P& f
- H- ~% u8 j2 G
程序开发难度,使开发人员能够在完全透明的情况下进行应用程序开发。也正是如此,CMSIS
; R6 W6 e6 B. e* t8 A1 ~* D0 {
7 h1 A3 z1 ?3 d: F# h; Q% g( N层的实现相对复杂。
. A2 O8 p5 {! {4 T# |; k, J, p9 P1 h2 o. Z

, T2 R" Y& a, k  B/ q% w
+ W+ b( E1 q. {# n# ostm32f10x.h:CMSIS 的! u* `' D0 Z; c/ z) U4 o+ x

. y: G1 d- S+ M4 u& `$ |# _$ gCortex‐M3 STM32f10xxx微
; a+ J4 o$ \" F5 ~" f* i7 I2 B+ t& {1 y+ j
控制器外设访问层头文件
% ^& U. j+ }8 h! x7 k- @- V' b( t; G' F+ p, t& f0 A% m' D) q
system_stm32f10x.h :
& g4 i' M$ m* u) {6 `: V- k6 f2 C8 Y2 ?3 ^. d
CMSIS 的 Cortex‐M34 n; e% e* l+ s# q

" `8 K4 D1 ]& W$ Q6 x# kSTM32f10xxx 微控制器外9 }* `, [1 n: i4 j
) h& i* s9 E7 `% N" f4 G3 [8 B
设访问层头文件2 j  W* y! A5 w, t, v
5 q0 z' q0 A. K0 k6 u2 J1 x; \( c
system_stm32f10x.c :5 M* ^. H! p: V; r

: z- V. {$ r4 |. Z0 }& VCMSIS 的 Cortex‐M3* P, r' H% e6 P  u

1 f6 d0 y3 ?4 q& kSTM32f10xxx 微控制器外" E5 s1 Z8 r, s" R! m/ u1 J3 N6 o
2 V) w8 I0 D  p1 c
设访问层源文件
3 _, B7 A; X& V8 @( z
& o! k9 {3 k( o0 ]* ^" @* }2 M0 b
3 M9 A, u, X. n$ h
# c! m7 `% f2 `( v* \9 ]7 E首先新建一个项目并设置工具链对应的启动文件,可以使用标准外设库中提供的模板,也可
4 n% A- [1 O- h" W2 V  ]: W9 W  k+ [% X" P5 {, p
以自己根据自己的需求新建。标准外设库中已经提供了不同工具链对应的文件,位于
" }) c5 N2 u3 U
- r/ ~9 v2 }( h8 J; USTM32F10x_StdPeriph_Lib_V3.4.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup5 O6 x1 i! n  I$ p
) {6 S: e( l9 F1 M8 P9 t

( i+ O9 Q9 I- D1 t7 o. |, I0 S8 g! c$ `- p
目录下。$ }' A% H8 Y7 p+ c
. z2 X* w, H  ^6 c
其次按照使用产品的具体型号选择具体的启动文件,加入工程。文件主要按照使用产品的容+ e' g. X- q0 J7 d1 _  Q
! W/ s  G: Z% H3 t( |
量进行区分,根据产品容量进行选择即可。& p& \  C/ W  E' _  ~1 {) P
5 T% i& O" N( U  V( d

" C; k+ x! ]: d& O, k' g* B! }9 `

6 `' t! s+ Z+ a
- f2 L9 a8 Q" b) A6 G. G7 X% mstm32f4xx_it.h外设中断函数文件 用户可以相应的加入自己的中断程序的代码,对于指向同一个中断向量的多个不同中断请求,用户可以通过判断外设的中断标志位来确定准确的中断源,执行相应的中断服务函数4 a7 W8 A. D! _% ^
│  system_stm32f4xx.c  文件  函数Sysem_ExtMemCtl,用来配置外部存储器控制器。它位于文件startup_stm32f10x_xx.s /.c,在跳转到main前调用 SystemFrequncy,该值代表系统时钟频率
: Z9 I. k  ]* g8 Y& O4 a0 y- j! {* _" h

# k. O) d1 N7 \' h( G9 a! |3 J0 ?) t* l& e, b4 U# {- ^+ g

) b/ F- ]* j0 n  H, m' V9 E
9 U8 x0 f. _7 I. S9 `2 BLibraries\STM32F10x_StdPeriph_Driver\下的内容很好理解就是stm32的各个
4 b, R, C* X9 A3 ]5 j( B. m- R" k& O& r/ h) r" N- g
外设模块驱动代码。
" H  ?. O1 _2 _! T' J! a& H, ?) h" V& z6 D% Z; k/ x
misc.h和misc.c是和CM3内核有关的NVIC和SysTick的驱动代码。
1 G) V* j! G2 n7 T) K- P
' F& Z0 O  P, U; E Libraries\CMSIS下是什么呢?cmsis英文全称:CortexMicrocontroller
$ f0 b9 y! n$ j- x
6 ~8 ^: J" E7 U+ P, ?Software Interface Standard,是Cortex系列处理器硬件抽象层,可以理解为cortex. k* r& |1 \5 c, ~5 Q7 Y
4 D4 o. e$ n, d
内核的软件接口。
( L8 ]6 I8 R/ p
' U1 \/ Q3 L6 P6 R1 V+ j& ^: c+ t core_cm3.c, core_cm3.h' O' u2 I: I/ f' o* A

# Z9 K% Q3 ]6 R& g* ^0 O它们的目录名为CoreSupport,说明这两个文件是CM3内核支撑文件,其他使
  n8 Z0 }4 o6 T7 k. H( f- N' N) W5 `' y/ Q
用CM3内核的芯片也可以用,不一定是stm32。这两个文件用来获取设置CM3内
  \+ j  z% R0 q. x7 o
; C' f, [; C  D核,配置一些内核寄存器。; @# a1 t/ U& A' u

& R/ }6 Y- r% M& l$ F9 zstm32f10x.h, system_stm32f10x.c,system_stm32f10x.h和
9 D( X7 R8 M* `! o9 p
; Y" ?) v: g: G' A4 n# tstartup_stm32f10x_hd.s在DeviceSupport目录下,说明这几个文件是和具体的芯8 z# s* p7 ~' s% e& w: Z0 k  L0 j
* x& i4 @0 k: d0 f% b
片有关的,也就是stm32芯片的支撑文件。其中stm32f10x.h是标准外设库的入口,
# {; ]6 ?& o, H( E4 P8 f9 _0 t2 p3 h$ ?
使用标准外设库的代码中必须包含该头文件。system_stm32f10x.c,
% }/ }  d$ G2 Q) c) u" m5 {* c& P& T8 ~8 B1 o
system_stm32f10x.h这两个文件提供函数用来初始化stm32芯片,配置PLL、系
, E5 T: h' e4 z; {( ]8 {$ U8 l  G& i  @
统时钟和内置flash接口。startup_stm32f10x_hd.s是大容量型stm32芯片的启动- _) U4 Z9 F. o% Q
- b# G, c' x0 ~; ~2 t3 Q0 b
文件; T7 a5 @; g+ [4 z
6 L  U+ ?. K* o; [

" ]* Z6 e3 ~8 i1 Q; H
7 @# `' a8 O# b& ?# ^! r: qstm32f10x_it.c,stm32f10x_it.h是中断服务程序文件。stm32f10x_conf.h是标5 k! \1 g. Y8 q. F" H

; h) p% ]) v) d' d' i- V3 d准外设库的配置文件,对于工程中不需要的外设,可以注释掉里面的包含的头文件。
. F. ]2 h2 }5 O) j$ P0 s4 F2 @2 P1 s- |1 U) n; O. U: H* @, u# i0 F- h
这里我建议先仅留下stm32f10x_gpio.h,stm32f10x_rcc.h,misc.h,用到什么再打4 T& T8 A8 [* M( d: y9 ~9 @" q

$ @& S( n  \, Q! R0 H, G开什么,这样编译起来快一点,当然也可都留着。
+ L0 B  N7 d5 h' V, ~# ~. h7 t6 j" W# r9 `
7 f! x7 k5 L. m# t, S% h

8 B3 `  w  @$ Z1 E4 |" I5 l
作者: embnn    时间: 2020-5-20 10:29
汇编程序调用C程




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2