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

【经验分享】关于 AN4065 中 STM32F0 IAP 升级后的外部中断不响应问题

[复制链接]
STMCU小助手 发布时间:2022-2-27 16:46
前言. ^) j/ `9 X- }  E
客户在使用 STM32F051C8T6 的 IAP 功能时,发现有些端口(比如 PB 端口)的外部中断端口没有反应,但是有些还是可以的(比如 PA 端口),不知是何原因,客户也验证过应用代码在没有使用 IAP 功能时是没有问题的。客户是参考了我们的应用笔记 AN4065 来编写这部分代码.
+ L& \) G$ G- Y% N; n
5 q1 j/ t6 }* h问题分析
; O/ z3 ?' G/ g, d8 ~4 \应用代码
% R1 o/ q0 Q/ M$ V' i通过查找客户的应用代码,发现如下 API 函数的调用:
" r3 |2 Y" x; o9 V$ s0 J
  1. /* Enable the SYSCFG peripheral clock*/
    ) V% A! q/ z' g/ |: \3 Z3 D( m' o2 \, o
  2. RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    - {8 ?" B( Q7 z* G& w$ k
  3. /* Remap SRAM at 0x00000000 */4 @! u0 i( r  U8 P; f) B$ D1 L
  4. SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
复制代码
& _. G  ]  `" z$ u
红色标记的 API 函数此处是有问题的,在此处应该将 RCC_APB2PeriphResetCmd 函数替换为RCC_APB2PeriphClockCmd 函数。这个在 AN4065 的附件工程中也是这么写的,所以应该是代码的问题。修改后的代码如下,修改之后,程序正常运行了.
+ s  F  I0 B; q* X2 z/ a
  1. /* Enable the SYSCFG peripheral clock*/
    ! Z3 _+ b  m3 L  c2 m
  2. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);  J; w7 C: \/ ]! ?: X# p
  3. /* Remap SRAM at 0x00000000 */% _  s" _7 D9 T9 P% C- @
  4. SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
复制代码
9 U" ?0 |/ z8 T3 J
深入研究
+ f: U, f# K2 L, }& Q0 D/ u这个问题其实是这样的:因为 SYSCFG 寄存器的时钟被关闭了,所以才造成一些外部中断没有响应。
- F. ?2 _: ?! U首先:我们看看 RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);这个函数做了哪些操作,它是应该是如何工作的?; x4 x+ g; x0 f; U1 G
在 APB2PeriphResetCmd()函数中得知这个函数是设置 RCC->APB2RSTR 的对应位,如果设置了这个寄存器的对应位,那么对应的外设(或者是寄存器)的时钟就被关闭了,那么这个函数本来应该如何工作的呢?通过查看我们的库文件,这个函数只有在 PPPP_DeInit()中才会使用,而且是一对儿一对儿的出现:
4 o: V( W. C! y4 s
  1. /* Enable SPI1 reset state */
    ) f' }; x- w, p# |, u, L
  2. RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);  S/ y: E$ ?) E( i
  3. /* Release SPI1 from reset state */
    1 t& b8 X# Y% H4 d+ J/ {* u
  4. RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);
复制代码
  1. RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, ENABLE);% R( S6 u% b4 \* ^  }, O
  2. RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, DISABLE);6 R1 y/ P6 W+ {# K5 _, E/ H0 m9 c$ `
  3. if (USARTx == USART1)
    ! I" T& S! T3 C8 n# o2 j
  4. {* s. M) k# }2 [1 R+ x+ e* F$ r' F
  5. RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE);: K9 `1 F" p9 k  D
  6. RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE);
    & Z+ m2 i; k/ q: q4 V5 F' D
  7. }
复制代码
2 H" s  i2 V8 O- E9 j3 @0 {& Z$ A
还有很多的例子,就不一一列出了。总之是为了简单的把一个外设或者是寄存器的值恢复到出厂设置,就可以通过调用两次这个函数来做到(比一个一个位清除要来的快),但是如果单独的只是调用了一次,比如客户代码中的情况,那么就是时钟被关闭了(这个可以简单的通过一个 GPIO 来测试,我已经测试过了,只要单独的设置上这个位,那么这个外设就肯定不工作了,无论你是不是开启这个外设的时钟在 RCC_ AHBENR 中),所以这个寄存器该起到的效果都没有了。关于RCC_APB2PeriphClockCmd()这个函数就很简单了,只是打开对应外设的时钟而已,就不说了.
5 Y# d! S" m# `/ H$ |6 A" L9 Y% A& T
其次,我们再来看看这个 SYSCFG 寄存器,为啥没有时钟了,它看起来好像也在工作呢?6 n  j; {! [& E* E; c- }! m, P
8 K! K" l  H5 J( \" `) F) H
_7BO{AZ}SRB4LA9}]W_M0JO.png # U8 t  G8 {% c
; o5 ?! z6 g2 F7 Q: Z$ b. y" G* v
看看画红线的地方就行了,他是用来重映射内存地址和管理外部中断连接到 GPIO 的。在默认的时候,这个寄存器的时钟是关闭的,所以默认都是从 Flash 的起始地址开始运行,外部中断也都连接到 GPIOA 上,只有需要修改的时候我们才会去开启这个寄存器的时钟,并做对应的修改。 这也就是解释了,为什么客户有的 GPIO 是好使的(GPIOA 是 OK 的),有些 GPIO是不好使的(GPIOB 上的就不好使).
% m# z4 f" `0 t3 E0 Y
) u4 g( G+ v! \# |* o0 A' s$ X8 A2 P" c$ \4 h
总结:
9 g' g3 R5 H9 C; x; h根本原因是应用代码中 API 调用错误,一般客户在自己建立工程的时候,又不是很了解如何在开始的时候去设置这个地方造成的。需要以后的工程师在参考 AN4065 中注意一下这个地方.
7 q& X5 s' i. a, ^8 l
" L3 a9 e' g5 A- Y  T; }! g) q$ ^0 N! z* i$ I# P! g& E6 Q
赞 收藏 评论0 发布时间:2022-2-27 16:46

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版