你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32调试过程中常见的问题及解决方法【转自秋水leochin】

[复制链接]
xingye-2040894 发布时间:2015-1-6 11:34
一、 在“Debug选项卡”下设置好仿真器的类型后,下载程序时却提示“No ULINK Device found.”
' \& p) X3 ^# A- W& {' \9 j  w- N6 F( y4 \9 U' }
   解决办法: Keil MDK默认使用ULINK仿真器下载程序,在“Utilities选项卡”下把编程所使用的仿真器改为相应的类型即可。# [* E8 G  I9 t- l" h$ ?' {
4 m' G  G/ u0 Y# L% |1 _
二、 编译工程时提示如下信息:9 S8 D( z5 O2 y$ }6 X0 ]! b2 z
7 a2 S, ~; [+ N! C8 ]
main.axf: Error: L6218E: Undefined symbol __BASEPRICONFIG (referred from stm32f10x_nvic.o).
) f8 X- ?+ @3 d( d# S# {$ r  Z3 B8 e
* x, {2 o) m; P/ w5 E9 p0 ymain.axf: Error: L6218E: Undefined symbol __GetBASEPRI (referred from stm32f10x_nvic.o).2 v/ {: P$ a8 h, H- g

" h5 `  R! b# @main.axf: Error: L6218E: Undefined symbol __RESETFAULTMASK (referred from stm32f10x_nvic.o).3 A5 r* ~' f5 E' @: ^
$ O' N. n* B- R9 F/ z) L& e: D6 o
main.axf: Error: L6218E: Undefined symbol __RESETPRIMASK (referred from stm32f10x_nvic.o).( I9 y3 B' s+ z! Z

- ^" P6 q4 B& a/ J! Dmain.axf: Error: L6218E: Undefined symbol __SETFAULTMASK (referred from stm32f10x_nvic.o).
. \/ b4 y# m& ]7 r0 V
% b) M4 X: b+ Vmain.axf: Error: L6218E: Undefined symbol __SETPRIMASK (referred from stm32f10x_nvic.o).  t) b9 Q3 m. @" d# [$ u

- N& _! d) b2 @, m$ g, e    解决办法:工程缺少“cortexm3_macro.s”文件,把cortexm3_macro.s和STM3210x.s全部添加到工程即可。
" L% V2 R+ Y  L) ?' u
/ S0 N* x/ c/ O3 W9 A$ t. N; q三、调试器不能连接到STM32的问题与解决办法
( ?3 f; X0 X. i, o, A5 w5 O2 ~$ b9 e1 {
    很多人都碰到过调试器不能连接到STM32的问题,不管是IAR的J-Link还是Keil的ULink,或者是ST的ST-Link。出现这个问题时,调试软件会提示不能建立与Cortex-M3的连接,或提示不能下载程序,或提示找不到要调试的设备等。( p% _* A" P2 w% |2 k6 U6 r

! C. `5 y- F6 |/ v    这样的问题都是发生在调试那些可以在CPU不干预的时候自动运行的模块、或在调试低功耗模式的程序的时候。所谓“可以在CPU不干预的时候自动运行的模块”包括:DMA、定时器、连续转换模式下的ADC、看门狗等模块。; D  k8 L2 F0 B# y% u$ x

- ]3 u' p5 m7 E6 {/ C1 Y--------------------------------------------------------------------------------7 b- E4 v$ C2 z
, ^; {* j  W. T0 a
这个问题的根源是:7 s7 p2 t. u: C& ~9 \. t

( B! G: w7 P6 H8 L+ V; k    1. 调试器需要在RAM内执行一段程序,对Flash进行擦写操作,如果不停止这些自动运行的模块,它们会干扰程序在RAM中的执行,致使下载失败。比如DMA模块被配置为不停地拷贝一段数据区,而调试器刚好需要使用DMA数据传输的目标区域,这时DMA的操作将会与调试器的操作发生冲突。再比如,如果启动了看门狗而没有执行硬件复位,则在下次调试器需要下载程序时,看门狗超时将触发芯片复位,导致下载操作失败。$ l$ [) X- l8 ~4 K
, R( L+ t, s- g( X. Y& s8 E
    2. 低功耗是通过停止CPU的时钟而实现,JTAG调试是通过与CPU的通信实现,停止了CPU的时钟致使调试器会失去与CPU的通信。
% J: y7 t- E2 z8 t1 z) {' t& c: B9 q: v" T4 k* n$ b! C$ V" X" ]
--------------------------------------------------------------------------------- ~4 O7 @- o/ W) }0 A

" O* f! f- @$ `0 E5 S3 d# C( f    有人说“我停止调试的时候,这些模块已经停止了运行,应该不会干扰到后续的调试”,这个问题要从几方面看:
& o, K' h4 N; U% Y6 A" U, X7 Y0 w+ m1 }' m' j3 _2 p/ E
    1. 调试器是通过停止CPU核心的时钟来停止被调试程序的运行,实际上被调试芯片的硬件模块并没有被复位,它们还处于使能状态,那些能够自动运行的模块只是处于暂停状态,一旦恢复了时钟之后,它们仍会继续运行。1 a5 ]4 f  o$ i4 m& n

5 Y+ T( T( Z- @. s1 A    2. 目前常用的调试软件,不管是IAR EWARM还是Keil MDK,调试软件界面上的"复位"按钮都不能对芯片执行硬件的复位,这个"复位"按钮只能对芯片内的程序执行软件复位,即把运行指针重新指向复位地址。' a0 E6 _5 E, E+ w

, B$ {) d. [9 D. N  a7 N. S& L    3. 使用板上的复位按钮可以手动地进行硬件复位,使所有模块(包括那些能够自动运行的模块)停止工作并恢复到复位状态。但是当调试器需要控制CPU之前,它需要先为CPU核心提供时钟,然后需要较长的一段时间做一些初始化的动作,然后才能接管CPU核心的控制权。在调试器为CPU核心提供时钟之后,用户程序就已经开始运行起来,如果用户程序在调试器接管CPU核心的控制权之前,就初始化好硬件模块并启动运行,则仍然会产生与调试器的冲突。
& Y- }  `* w/ b7 {6 v& e1 l- D) L% x! U* `% O/ Y; m( S
--------------------------------------------------------------------------------5 |7 [/ i5 V; C3 \- r% [

3 l) V6 I% k' r4 H  w( p    根据以上的分析,解决这个问题的关键是,在调试器接管CPU核心的控制权之前,必须停止所有能够自动运行模块的操作,使它们处于关闭状态,要做到这一点,可以有以下几种方案:
+ s% L' l6 D+ n9 J9 a& c. j: L, m* a! \
    1. 每次退出调试状态时,先停止所有模块的运行,比如执行该模块的DeInit()操作。
% _. w: Q/ K7 d5 M& P7 Q7 B& b
, }, i& y; S' r    2. 在main()函数开始时,不管各模块处于什么状态,先执行该模块的DeInit()操作,然后在程序中较晚的时间或真正需要时再开启相应的模块。这样保证在刚进入调试状态时,调试器能够有充足的时间完成初始化和下载程序的操作。先执行该模块的DeInit()操作的目的是为了关闭哪些上一次操作开启的模块。* {9 b. ]7 ]# `5 J) P( F

" m6 H" l( `# }; \2 h    3. 调整BOOT0/BOOT1的设置,把启动模式改变为从内部SRAM启动,再结合手工硬件复位。由于BOOT0/BOOT1的状态只在硬件复位时是有意义的,而调试器不做硬件复位,所以这样的设置不会影响调试器下载程序到Flash中,也不会影响在Flash中调试程序。
, h  e1 @% Y4 p+ f. w9 F/ U% a6 H1 ]$ A% A1 T* Y
四、调试STM32程序时,某些标志位被调试软件意外清除的问题
& g, N' n  P! i/ O# h3 A- _
% |4 Q8 w) r0 L$ E6 {1 l6 b; t    在调试的过程中,使用调试软件的寄存器或存储器显示窗口,可以很方便地查看外设寄存器的状态。
+ w3 x5 q/ @% g
( u8 ^4 s2 F( S0 B# K! a    很多朋友都碰到过这样的问题:在单步调试时始终不能在显示窗口看到某些标志位的变化,应该设置这些标志位的时候,窗口中却显示为0,不少人都错误地认为这是芯片的问题。5 ]1 T2 o* W' q! p2 K; ]4 D
2 @# u+ \3 j. J# m9 ^( j5 r( S) a
    我们知道,不少STM32外设的状态寄存器位,可以通过对某些寄存器的读操作而清除(例如I2C的I2C_SR1中的很多标志位),在调试过程中,每当程序停止在设置的断点或单步停止时,调试软件都会自动地读出所有指定的寄存器和存储器中的内容,并刷新窗口的显示,调试软件的这个读操作恰好清除了那些标志位,造成了上面描述的现象。4 Y: Y1 `: [$ ]5 M; G

- J0 p% u9 m0 ?+ Q    有几个简单的办法解决这个问题:
  {% U: _5 B5 Y3 b
- p" s1 y5 i/ o$ ^3 Y9 m  1. 关闭寄存器或存储器显示窗口。
8 ^: |& g: K/ f, W  2. 在寄存器或存储器显示窗口中不显示这些敏感的寄存器。 . R5 L. U7 x* Q1 L% ~0 w4 o
  3. 不要把断点放在对这些敏感的寄存器位操作的前面,以保证这些寄存器位不被调试软件意外地操作。
& ]/ R; @! {; j' n* t" F  4. 看官自己添加~~~~~: l4 \- v2 [8 K- o% v% K4 r$ U. F# z

$ }2 C" G3 D6 P$ P; _五、在使用STM32的外设时,由于IO口被用作复用功能,但是外设的初始化正确,GPIO口初始化正确,外设的时钟也已开启,但是外设无法正常运行
; a0 S8 C: S) f/ O! D) k2 d# X( _3 }3 `9 [6 s' J
    其中最关键的一项,大多数使用者多没有设置,就是某个IO口被用作外设的接口时,需要开启IO口的复用功能的时钟,即进行外设、IO的时钟使能时,需要如下代码:
( v9 _6 w# h' H) P9 ~, e( s, N2 f2 d7 r& F& P
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx | RCC_APB2Periph_AFIO, ENABLE);    /* GPIOx and AFIO clock enable */$ l9 v. J8 g8 |( l" n
: _5 s9 M$ c  _% ]  N
x --- 为对应的GPIO口,如:A、B、C、D、E。( r. U) c1 n6 J  _/ E2 ~5 [9 a
2 t) ~6 {# f' r! v: M" l5 Y* _$ C8 Z6 E
    在使用时,一定要注意该要点!
赞 收藏 评论3 发布时间:2015-1-6 11:34

举报

3个回答
feel-376797 回答时间:2015-1-25 07:34:50
谢谢楼主分享
博根 回答时间:2015-1-25 11:56:31
6 Z: @9 ?3 B& t4 _9 I* O
好帖子呢 谢谢楼主分享
Jimmy1987 回答时间:2015-2-6 10:36:40
从头开始,一步一步来
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版