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

发现CubeMX一个bug。DMA和ADC初始化顺序反了,导致DMA设置错误

[复制链接]
zxk126 发布时间:2020-1-7 15:21
: h! A- v; y) n3 _* e* g
问题描述:7 [4 H. d. U: g9 @, o/ y' x

) L5 ~7 H; H! M7 \* t- s! {4 p7 C  @    利用CubeMX初始化ADC和DMA,发现DMA设置CCR寄存器不能设置成功,导致DMA不能按照预定工作模式工作,后经调试发现,Cube生成的初始化代码先进行ADC设置代码中也对DMA一部分寄存器进行了设置,但这部分设置由于DMA未启动,导致设置不成功。具体描述如下:
* R: }; b) p" ]2 @% j& m: l9 c- K7 ^

' H. k$ A  j2 I5 P5 c# T; z( L9 a% s( o
软件版本:CubeMXV5.4.0* f8 H/ c6 U3 r+ D" Z" v+ q

0 |- y/ U6 B, A: w* H: N3 L' BADC设置:6 E' N0 a/ Z1 }- e. ~
1.png 2 ?! U. |% Q" j) e# I
! f! E1 m/ B5 I* }. m& |

: b3 l  i6 S- R( Y ; E3 ]* r: _& n! B. m, ^
7 S1 t4 n% c6 |
DMA设置:7 O/ {7 M6 w* M& N1 W: P

% D) m6 B8 K. q+ s
2.png

  Z! h- a* N. A , b/ W3 t7 o/ A8 x4 b) G4 G

* i) P4 J1 F* f生产初始化代码为:% Z8 x$ t# Q6 F) S! B5 }

' V! ~* A/ s  G" ]5 n9 B' B, t7 f! u
  /* Initialize all configured peripherals */
( r$ j3 n7 r- j" K( R
  MX_GPIO_Init();
7 [3 A& Q7 w/ q
  MX_ADC1_Init();
, y' H. U# T3 s- I* }
  MX_DAC1_Init();

% N  O( X3 P% T$ Z: w) C& u
  MX_RTC_Init();
4 O8 S8 \" G; _) w& ^% ]) a
  MX_TIM6_Init();

) F& m" i' [3 W* T( I
  MX_DMA_Init();
- u. {1 E, l8 O* j  L0 z3 }
: q! m. \) A' s  v+ L7 u& M
MX_ADC1_Init->HAL_ADC_Init->HAL_ADC_MspInit:

; ?* x  ]: i9 t: i" G8 O
. W6 C8 y4 k3 b8 G; `
voidHAL_ADC_MspInit(ADC_HandleTypeDef* hadc):

- l; }' d7 `% E, U5 v# W* L) H0 m
    /* ADC1 DMA Init */

+ E3 m3 r: B4 V
    /* ADC1 Init */

8 F8 o# q0 k; I$ |5 t8 g1 N, F+ q( q
    hdma_adc1.Instance = DMA1_Channel1;
6 f) A- A0 Z7 r5 Y, S# N% j# g) f, C
    hdma_adc1.Init.Request = DMA_REQUEST_0;
' _. D  z: o0 G" k  P
    hdma_adc1.Init.Direction =DMA_PERIPH_TO_MEMORY;

* d( ], P3 E0 O" P
    hdma_adc1.Init.PeriphInc =DMA_PINC_DISABLE;
* W- Q3 k- r) ^) s! ?- {1 _0 K
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
/ ]* A% |; l4 z: n
    hdma_adc1.Init.PeriphDataAlignment =DMA_PDATAALIGN_HALFWORD;
1 t& P& k" \  Q( u; B2 `
    hdma_adc1.Init.MemDataAlignment =DMA_MDATAALIGN_HALFWORD;
! z0 z, O' J1 p6 x7 x8 i" L- c$ r
    hdma_adc1.Init.Mode = DMA_CIRCULAR;

1 o& x$ J6 R, Z" x3 ^. U' V. j8 V
    hdma_adc1.Init.Priority =DMA_PRIORITY_HIGH;
& M2 h7 }6 R+ I
    if (HAL_DMA_Init(&hdma_adc1)!= HAL_OK)

' E6 K$ N* F; Z
    {
/ {9 {- a) T0 i1 \; E
      Error_Handler();

2 O- w3 o1 \# P: Y- ?8 D1 _
    }

9 H9 R3 l+ E. T( i* k

$ w6 h% Z. d+ j! B5 t
    __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
( m% n  h; A9 P8 V
: w0 ]1 T: O$ I; J7 O! U
    /* ADC1 interrupt Init */
# @- |; h& h7 T1 _
    HAL_NVIC_SetPriority(ADC1_IRQn, 5, 0);
& h9 _2 ?/ \4 T3 \4 }; C
    HAL_NVIC_EnableIRQ(ADC1_IRQn);
, x' w! Q5 U6 @5 t* R: L8 ?
  /* USER CODE BEGIN ADC1_MspInit 1 */

9 }7 S$ Z/ X1 U1 }

8 J: h" k0 [, R7 N. }
HAL_DMA_Init:

1 ^* x& a; s0 U1 D, q
1 N/ ?+ ^: B6 Z6 J  y; K& H
HAL_StatusTypeDefHAL_DMA_Init(DMA_HandleTypeDef *hdma)
" c1 x) @' T0 x- `& d
{
2 }* \( v, z3 R7 i
  uint32_t tmp;
' `) U! J% \9 V9 B
2 B+ y2 l6 ]. ?$ K
  /* Check the DMA handle allocation */
2 V% `1 G2 y$ |) u7 f7 {
  if(hdma == NULL)
* a+ T- `% [) \5 R" a/ s
  {

$ Z* o. g. c3 R% V% K$ r2 \
    return HAL_ERROR;
( F0 C! D" Q- g
  }

+ G# g" A7 n$ h1 ]% b3 e" X
3 {+ c1 v4 f. y- R
  /* Check the parameters */

$ a1 A! d# v3 n& S2 D# ]4 ]
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));

% |2 f, ^7 r) n
  assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
2 I/ \3 N# h4 Q2 ?
assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
1 Q! g4 d9 v$ V! ~0 s
assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
8 z. d3 U8 Y% p) L
assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
% i7 x8 R# d$ h
  assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
, ?7 n: K" }# ?. `, P2 Q
assert_param(IS_DMA_MODE(hdma->Init.Mode));
  [9 ]: i( }2 i/ P6 p
assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));

2 \3 f( ^' R/ @4 o& U& I
; f! U2 o4 [+ V/ N4 O
assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request));

: c7 y+ D/ g( P

  h7 R6 c* j# [
  /* Compute the channel index */

) {, W) c4 d4 l6 b- A
  if ((uint32_t)(hdma->Instance) <(uint32_t)(DMA2_Channel1))

# x6 `; c/ v  q2 o+ T, M, Q
  {

. v, D0 Q/ d! g  |7 E) B) m. b
    /* DMA1 */
" J: W: T3 ^9 I( t
    hdma->ChannelIndex =(((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) /((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
& Z- p( g# C  @7 z: S# }0 ]
    hdma->DmaBaseAddress = DMA1;

, K8 G+ s0 O: S- Q/ x5 o
  }

' b# P2 M) ?' _$ w, ^' U4 x8 n8 l0 R
  else
  b3 q: a, D% |7 N3 I
  {
9 s6 A. H) y( e; K
    /* DMA2 */

% G- V+ z$ X2 e8 }. e! o2 [- t4 a
    hdma->ChannelIndex =(((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) /((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U;
% l0 A' K4 ~/ N$ Q% r. }
    hdma->DmaBaseAddress = DMA2;
# }9 j* Z2 D2 |  q1 c6 D8 i5 C: g2 |
  }

& n0 l# e0 a9 ^: g5 L1 j

% F& P6 C) @0 b* @* X+ C
  /* Change DMA peripheral state */
0 O. X) i2 u2 E+ n: o0 v$ [
  hdma->State = HAL_DMA_STATE_BUSY;

7 B' r' x+ Y1 ?; l& T( @3 u

# w$ P2 e: j  g5 ?9 q
  /* Get the CR register value */
/ Z  k6 p) @3 ^! k% X
  tmp = hdma->Instance->CCR;
/ H2 w% _) u+ U4 r9 W8 P7 \
2 }0 u$ ~, u, v$ @, B4 }
  /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC,DIR and MEM2MEM bits */
  O+ Z+ S2 n( O6 e: o
  tmp &= ((uint32_t)~(DMA_CCR_PL    | DMA_CCR_MSIZE  | DMA_CCR_PSIZE  |
4 p6 v2 O( r% r2 G6 ~
                      DMA_CCR_MINC  | DMA_CCR_PINC   | DMA_CCR_CIRC   |
$ x3 J% y: p# L" }0 a7 d; m" z
                      DMA_CCR_DIR   | DMA_CCR_MEM2MEM));

4 F7 q! j9 e5 W7 ^& o- n+ r& r. c( Y3 Q
, d7 Z& {* Y& L+ u1 s! }/ r
  /* Prepare the DMA Channel configuration */
( F5 W9 I/ ^. }. M! R
  tmp |= hdma->Init.Direction        |

# D5 {5 T4 m. e& _* U% P# j
          hdma->Init.PeriphInc           | hdma->Init.MemInc           |
. w3 E8 }& N4 e$ [7 F
          hdma->Init.PeriphDataAlignment |hdma->Init.MemDataAlignment |

' R, F0 |& t* K2 E- W* O% B
          hdma->Init.Mode                | hdma->Init.Priority;

# n4 t! p! U$ _& R$ a4 x
+ m6 P7 w3 ]; p4 V
  /* Write to DMA Channel CR register */
- e5 F9 v8 I! s0 ?1 S( ]3 i
  hdma->Instance->CCR = tmp;
$ f) Q/ _: I; g  d
) f; ~! E# b* [: h5 l
上述初始化代码为CubeMX根据配置生产,代码本身没有问题。在此时设置DMA时,需要设置CCR寄存器,但此时DMA的使能并没有打开,因此设置不成功。

* _" p9 i  s0 o% B" E
3.png

4 K: n# k+ j% U- i) }
. i$ I5 ]1 [* z) M" `
    如果调整一开始的初始化顺序,先进行DMA初始化,调整代码如下:

& Y, E5 o9 F. Y+ j$ N1 m+ f
  /* Initialize allconfigured peripherals */
" v0 R9 y! _" Y7 N  M$ x( L# D
  MX_GPIO_Init();

- s2 o* }7 q0 y2 C6 c* J7 R+ i7 u
  MX_DMA_Init();
2 F- j- f7 T" D, T. |1 J; g( |
  MX_ADC1_Init();

0 m/ K  a' F7 M1 ~5 a2 c" A, o
  MX_DAC1_Init();
3 W0 ?% n3 D. [: v3 l# ^+ U
  MX_RTC_Init();

) D: ^7 E" F1 Z9 M- o! B& \
  MX_TIM6_Init();

9 k# c5 @# Z7 I( Y: u$ h) c
/ f  m  g8 d$ j
4.png
  z" q" p9 X6 g0 c
此时DMA1EN为1,CCR1寄存器也设置成功。
$ e  j6 H2 @9 B! p4 y

, I/ h: O8 A! @5 S. Y' ]
    以前也是这么用的,也没这个问题,等到更新了CubeMX版本后,就出现了这个问题。总感觉CubeMX更新太快,而且每次更新变化太大,刚刚适应的一更新又变了,而且更新完了还有问题。虽然更新是好事情,但不能没测试好就更新吧,这么多人把代码用在产品中,出一点问题就增加多少人的工作量和隐患呢?希望以后更新能慎重。

$ ]; o' o, S+ j, ?

% N4 t* j, f! Y* c
$ \, k0 \3 T: z/ `1 `- p# D( @% N6 O, C* J, j
赞 收藏 评论3 发布时间:2020-1-7 15:21

举报

3个回答
pkoko 回答时间:2020-1-8 12:53:09
最近搞一个UART的串口DMA也碰到类似问题,CubeMX自动生成的代码如下,初始化DMA放到初始化串口后面了1 A2 A9 T- _* _
  1.   MX_USART2_UART_Init();
    # p' X. C* d0 t& t4 N% g2 G
  2.   MX_TIM2_Init();
    ( r0 d* r0 i, y7 f
  3.   MX_DMA_Init();
复制代码

9 G7 D3 E8 A% {3 C4 l1 q改为如下,才能正常工作:, k, J) c% b4 k+ u1 r6 R
  1.   MX_DMA_Init();8 i# {( D  o& `9 z5 ?. ?
  2.   MX_USART2_UART_Init();
    , `( H7 z: X8 k+ t
  3.   MX_TIM2_Init();
复制代码
zxk126 回答时间:2020-1-9 13:42:01
pkoko 发表于 2020-1-8 12:53
/ W6 f$ {/ f4 Y/ p最近搞一个UART的串口DMA也碰到类似问题,CubeMX自动生成的代码如下,初始化DMA放到初始化串口后面了
2 q5 B0 F' T! c- l8 p
# w4 B: {, T9 {0 Y+ b改为 ...
! k7 a+ m2 A) l  D# ^9 O* N
看了以前版本生成的代码,DMA初始化在前面,就没有问题,不知道为什么后来的版本调整为后面了。
zxk126 回答时间:2020-1-13 09:22:50
发现这个论坛里面好像没什么官方技术支持人员,这样的问题都不出来声明一声,是这个问题太小了,根本不值得说明呢,还是我的用法错误,水平太低了,不值得指出错误在什么地方?
+ F4 j$ r6 R1 h* E7 S
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版