通过上篇文章对STM32MP1双核机制的分析。我们知道M4内核的程序,不能够下载到FLASH当中。那怎么调试M4的程序呢。下面我们就开始讲一讲。
3 F, k6 J; V/ q( `STM32MP1跟普通M4核MCU开发没有太大的区别,一样调用HAL库,一样可以通过CUBEMX工具生成# w' ]7 J0 Y! W5 b) s. h
初始化代码。当然在能控制的外设方面比真正的M4单片机要少一些,上文已描述过。我们在这里就不多说了。
7 [' q* S) t# x1 f我们打开CUBEMX工具,选择对应型号,配置工程:
" m' L i2 S7 G; B. j" `我们想控制板上一颗LED,并且串口能够收发数据。, ^" k! K c' F0 W2 U
LED引脚电路位置:
' Q. b1 W) V! w
$ a# u6 S# S% V, {: w
与STLINK相连的调试串口UART4电路位置:3 Z5 B; u I6 R0 R
" E" ^. c! `5 d" L
" f* z' s6 ~; U0 o9 O
2 u' R" s. k; X A: w: Z: `
! H5 h% Q8 X( p6 a$ [6 G6 W6 _6 [# ~+ xCUBEMX配置:. r, i, X+ b7 E; @7 G! o! r
/ g6 W3 X. _- r ]
! F. d; l! ?! B' K( m" N* L
7 S. Z+ [* {/ F; o* U( `配置时钟:
4 r' U5 V* e4 D3 m% V. i
7 u5 c* i( b1 X6 |7 o6 ~- @
% A) k& ?4 o6 d# M( b( @1 E
k! m8 z. h: S; c7 Q" J3 ]工程配置时,选择让每一个外设生成独立文件:4 _4 w# J- B7 H$ M+ d' N
6 V( x. e s: E# E# D! I然后生成代码,我们这里没有官方的STM32CUBEIDE开发,用MDK。4 p3 I, T1 W0 y: x% M6 z% h2 H2 d
生成的代码,我们不直接用,仅作为参考。
; ]' ~. g$ m$ B" Q. B修改自己的led程序:
, R- e! l) c5 Z6 N; CC:1 V* o0 W$ B4 k' L8 {
- void led_init(void)
% ]0 E9 m; |, t: f* S- N- i - {3 |8 l9 w. D, ^$ Z! d" r
- GPIO_InitTypeDef gpio_init_struct;" I, ]6 x& O. E) [" ~1 W/ H6 V
- LED0_GPIO_CLK_ENABLE(); /* LED0时钟使能 */6 ]3 W# l7 Q+ V- z
- + q0 ]% w0 k% [7 t5 J$ O0 l+ G
- - {- {+ H, B0 }/ A
- gpio_init_struct.Pin = LED0_GPIO_PIN; /* LED0引脚 */- {% b) |/ P3 O/ [, ~% P" z1 I
- gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
# D# ?. R8 U- @4 a! S3 i+ t4 v8 U* b - gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
0 K0 |3 B0 y1 k) m8 @ - gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; /* 高速 */0 @5 v: D" ]: U. [4 r
- HAL_GPIO_Init(LED0_GPIO_PORT, &gpio_init_struct); /* 初始化LED0引脚 */
' k- r) P5 |; e: E* X6 u- l- w
( U. Q: Q7 G0 I6 V: S
" \% ^, L9 p+ b/ V2 i" V' R- LED0(0); /* 关闭 LED0 */( ^) c6 P; x6 z+ T, x
( U& Y2 p0 B$ Q. P* `- }
复制代码 H:& m! V, v! G# o+ `) x
- #define LED0_GPIO_PORT GPIOE' S" Y# k+ D A5 h1 c- U
- #define LED0_GPIO_PIN GPIO_PIN_12
8 ~- A" u1 l; D: J7 E; u' f4 y - #define LED0_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口时钟使能 */1 \$ b+ B$ U" r0 _) L
: [. Z" b9 z* R) z6 b; A- /******************************************************************************************/
4 X& @7 r! W9 o. q! n! M' N - , U. O! Y0 T2 G9 [) h7 A
% X% a5 g5 O: k' g0 L- /* LED端口定义 */& U* t4 z1 V" Y2 ~
- #define LED0(x) do{ x ? \6 u5 B; U3 ~% q9 t! b& k
- HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_SET) : \
1 \" q G5 j H4 h8 W - HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_RESET); \
/ v8 B1 S/ m2 @& I, B - }while(0) /* LED0 = RED */
0 Z2 `: i! a- J; H J$ F( u4 r* s - # {9 @1 X' _7 R4 g$ E8 c7 C* F
- /* LED取反定义 */
7 K. `2 C" w9 H/ \3 L! g* ` - #define LED0_TOGGLE() do{ HAL_GPIO_TogglePin(LED0_GPIO_PORT, LED0_GPIO_PIN); }while(0) /* LED0 = !LED0 */
% }1 k6 l4 _" E" ^
3 W4 F9 ~9 S- H, r- - D$ m2 B% M. `) M h) p
- #define LED0_STATION HAL_GPIO_ReadPin(LED0_GPIO_PORT, LED0_GPIO_PIN)
/ D8 R4 G: G8 r7 J+ ]& F
2 ?# H7 _! V* G) k- void led_init(void); /* 初始化 */
复制代码 UART4.C" X% w8 A+ F. S% l/ ^+ t3 _5 D2 V
主要处理都在接收回传函数里面,此接收函数一直参考正点原子。
# \5 D5 x0 y2 `- ^/ E n6 q- * 接收缓冲, 最大USART_REC_LEN个字节. */% ~. e4 X J7 D1 o3 U. q
- uint8_t g_usart_rx_buf[USART_REC_LEN];
4 I9 [, {& U7 X& G - $ r+ `* H* v6 N3 K/ j5 }) o8 d; {, Z& p
- /* 接收状态2 n1 s. f( }) y& d& Q
- * bit15, 接收完成标志
D' T4 K( H3 |+ @% [# { - * bit14, 接收到0x0d
& m3 E1 P/ k0 S/ X - * bit13~0, 接收到的有效字节数目, ?0 A- x, j& c# L8 d
- */: N) z9 I$ |# `9 u/ N
- uint16_t g_usart_rx_sta = 0;" i7 [4 J* M8 C2 L& P* a
$ O( z3 y" ^6 z- uint8_t g_rx_buffer[RXBUFFERSIZE]; /* HAL库使用的串口接收缓冲 */: {" x" d7 g7 @0 z3 Y- `- @9 y) M
2 [2 k2 {9 R9 i# H- j# H- UART_HandleTypeDef g_uart4_handle; /* UART句柄 */
3 H8 c/ i& c# e1 C) W) p
3 e8 y$ r, r- P- 0 P' z0 s/ \2 F7 V& M: \
- /**& R/ n; v8 A+ ` b6 W
- * @brief 串口X初始化函数
( q; z% L7 ~% Z: d3 o - * @param baudrate: 波特率, 根据自己需要设置波特率值+ M+ G& y' `8 \0 {; J) z! O0 `
- * @note 注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常. a' f% p; d. P. R/ I
- * 这里的USART的时钟源在sys_stm32_clock_init()函数中已经设置过了.$ P* U' B( j; ^- ]7 |7 n% J
- * @retval 无
8 c. |4 Z% k' y, Y; s' n1 F& _ - */
6 _0 {$ [/ [/ A6 r, F - void usart_init(uint32_t baudrate): Z4 y# |* l5 u0 w
- {; [. P2 f x9 O
- g_uart4_handle.Instance = USART_UX; /* USART4 */
" T# U$ ?4 [" H - g_uart4_handle.Init.BaudRate = baudrate; /* 波特率 */& x/ x. C! K7 U8 s7 ]2 B
- g_uart4_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
% ~: {0 J( t& e2 i6 Z9 ` - g_uart4_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
& `! \9 m* @9 ]! `. V! v - g_uart4_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */7 j J3 q( V0 g+ B" m# F% ?$ o
- g_uart4_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
7 j+ |" |% O4 T; K( s0 A - g_uart4_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
; e: ?2 L3 j& s) I2 [7 E& K - HAL_UART_Init(&g_uart4_handle); /* HAL_UART_Init()会使能UART4 */* g' v7 ?- h# r# \! s# Z% Y
-
/ R: d- }9 N& }9 M% c: \ - /* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
) F l* h; R6 x - HAL_UART_Receive_IT(&g_uart4_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
3 n2 Q6 T0 f& w/ t - }
- S: _. Z% c' f! K+ C, E; }% w, f# H - ; d. v- d: i& B( [5 a0 V" N
- /**
% E8 D7 W' G8 p/ O, Q - * @brief UART底层初始化函数
1 l# I' n& N' o$ k( A - * @param huart: UART句柄类型指针
( g! \# L9 }( E+ [$ \: _4 `7 p7 R3 h - * @note 此函数会被HAL_UART_Init()调用% a8 j2 O% e' t
- * 完成时钟使能,引脚配置,中断配置- C1 }% G6 l0 Q% f* A, N
- * @retval 无8 ~, M) S- V, H& S0 r3 n6 l
- */8 ?1 n) f H0 M# H$ @% q$ s
- void HAL_UART_MspInit(UART_HandleTypeDef *huart)$ p# q R" V% f* _5 z
- {' H4 v: K# x# y9 G: N# r
- GPIO_InitTypeDef gpio_init_struct;
) v* Q% d% e( D! B k - RCC_PeriphCLKInitTypeDef rcc_periphclk_init_struct;
+ a9 \% F, c, |) L% V2 Q -
! H, t2 o! |8 Q. {0 z( c# ~2 a - if(huart->Instance == UART4) /* 如果是串口4,进行串口4 MSP初始化 */1 _5 N# P: z- s( |9 u5 f
- {6 V4 Z5 g) a# y% I) E
- USART_UX_CLK_ENABLE(); /* USART4时钟使能 */
* g0 V: Z! Z! H: Q - USART_TX_GPIO_CLK_ENABLE(); /* 发送引脚时钟使能 */4 k( o. ~) \2 d I6 L
- USART_RX_GPIO_CLK_ENABLE(); /* 接收引脚时钟使能 */8 v5 |: |7 z# U$ g; e+ T! A+ U( V5 O
7 r# L* ^* y- W4 {2 f2 j- L- gpio_init_struct.Pin = USART_TX_GPIO_PIN; /* 指定TX引脚 */. s' C4 ^' d& j2 G, y
- gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
( R9 `& u: X7 ]0 W3 F0 b - gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
; v" c- S8 P, {' }" e - gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */: [ v' X8 p4 ]* G! k" A: Z
- gpio_init_struct.Alternate = USART_TX_GPIO_AF; /* 复用为UART4 */8 q( \+ D- C$ S. p0 N) D* e
- HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init_struct); /* 初始化发送引脚 */ F& l3 l2 C: d$ v
, `4 u e. ^( g5 j1 m" c2 R/ n- gpio_init_struct.Pin = USART_RX_GPIO_PIN; /* 指定RX引脚 */5 z6 w' i# c% t; h: O j4 ?
- gpio_init_struct.Alternate = USART_RX_GPIO_AF; /* 复用为UART4 */' E, H) U3 a. w/ L
- HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init_struct); /* 初始化接收引脚 */5 e+ V( b1 i0 H# w* K7 D
- # k" P" p: s- y6 p; D1 r2 {
- /* 设置UART4时钟源=PLL4Q=74.25MHz */
, P" a1 V! E+ o% `( e& ?/ A - rcc_periphclk_init_struct.Uart24ClockSelection = RCC_UART24CLKSOURCE_PLL4;* K' ], P ?! i* C
- HAL_RCCEx_PeriphCLKConfig(&rcc_periphclk_init_struct);
! e+ _! f H- S b0 i) W+ y
1 y$ W" H' ~+ @- c: n# b% h- #if USART_EN_RX
# D6 Q- j( I/ q% J/ ^ - HAL_NVIC_EnableIRQ(USART_UX_IRQn); /* 使能USART4中断通道 */1 ?# d% Q1 e+ k/ Y8 r1 z
- HAL_NVIC_SetPriority(USART_UX_IRQn, 3, 3); /* 抢占优先级3,子优先级3 */+ r$ B* X' h6 a1 Z' ?; o
- #endif
& O2 G4 f# u4 w# h/ O: f - }
`: E. x) s5 V7 k8 E9 ?0 H# q - }8 _# u' N* E2 U( e
' ~( ~# V5 Y+ B4 b& m- /**
$ b# W# }' t/ u0 r, Y; {! j - * @brief Rx传输回调函数2 C" }5 V& } \6 ^/ D* H
- * @param huart: UART4句柄类型指针
7 V2 l5 X/ i8 g - * @retval 无9 B# M5 u" S. D: M
- */+ l% x0 \3 e$ d n) B u* }
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)1 w; d6 Z' Y% e6 V0 `" C
- {8 H+ j' `: G9 [" f i6 S4 z; n
- if(huart->Instance == UART4) /* 如果是串口4 */# M( ~, o7 ~4 U$ d; M5 C
- {
0 a: v, M) ?( N5 |0 P, D0 r4 g, l - if((g_usart_rx_sta & 0x8000) == 0) /* 接收未完成 */) q# ?, B& X' |3 c9 v8 A
- {0 Q( n8 a+ \, F+ g+ }
- if(g_usart_rx_sta & 0x4000) /* 接收到了0x0d */
; R2 y: t/ r3 U3 S0 ` - {6 b9 h& p" L! ~
- if(g_rx_buffer[0] != 0x0a) 7 s V+ y/ T, K. L0 |, k
- {
! q* z, E8 m, r L - g_usart_rx_sta = 0; /* 接收错误,重新开始 */
+ x- x* M8 D( u6 r - }* O4 r, e }9 u2 A
- else 1 f) Y7 Y4 m% c. b" ^4 S
- {
9 d6 M0 h2 e) }" C5 c2 v* d - g_usart_rx_sta |= 0x8000; /* 接收完成了 */
4 n, a+ @9 S$ c. B; R - }4 x3 q- F/ k+ ~, |/ L: Y
- } D$ |3 b5 j4 J4 @" l/ i0 ~) O
- else /* 还没收到0X0D */
( G/ Y+ g/ q- q) _) T - {5 Y& h; j# I3 y0 e( u
- if(g_rx_buffer[0] == 0x0d)( g- [# q0 S1 Z3 Z
- {4 t @* O% q' [* ]1 C( ~
- g_usart_rx_sta |= 0x4000;
1 I: I4 i7 q2 F$ q# d! h5 v - }
2 k- A* l* _$ V - else
- {6 i) Q8 P+ n7 Q0 G6 e - {5 \$ V g5 r5 _/ q
- g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = g_rx_buffer[0] ;
5 y4 k. n, a+ A8 X: I# Z - g_usart_rx_sta++;
! R& E3 v/ w) [. V, P$ X - if(g_usart_rx_sta > (USART_REC_LEN - 1))4 D6 _! S" T0 F1 J7 _" {2 z5 L& m8 m
- {. `* B P" a# }$ A
- g_usart_rx_sta = 0; /* 接收数据错误,重新开始接收 */$ i1 V2 N5 c; H$ _6 P2 g; L
- }' k" |0 {9 P; U7 }% s
- }
2 a7 v% p8 _! W8 L - }
9 c/ i! C; A: ~3 v' S4 R - }
: B0 i, S4 X. O5 C - }/ ~! o4 D! j3 p( G/ y2 V& Z
- }* b) D1 [1 J0 B7 ^, w0 S
- L3 j* a; {: `$ O& l. I1 D- /**- h3 Z0 b- U" ^7 q/ J
- * @brief 串口4中断服务函数6 P- i( f0 @) @0 F
- * @param 无
; M+ R* ^0 u- L( g1 a - * @retval 无4 ^' I- S. w. Z5 j3 {
- */
9 D( C6 j% i Z - void USART_UX_IRQHandler(void)
& h/ \4 P, M1 }* p& l - {
7 t8 v) t/ N- O; D0 R - uint32_t timeout = 0;
/ h# G1 Z- ]; |+ ~8 q+ Y0 m6 c - uint32_t maxDelay = 0x1FFFF;0 x- }* O7 D' m) m( \9 a7 ~' X
- . C( ^& v- A( f2 Q3 q& v) D2 w
- HAL_UART_IRQHandler(&g_uart4_handle); /* 调用HAL库中断处理公用函数 */. j! E/ P* l" s6 X/ J2 y) n
3 h6 J. E) ]3 O) W- timeout = 0;
! K0 R7 j% k, f Z - while (HAL_UART_GetState(&g_uart4_handle) != HAL_UART_STATE_READY) /* 等待就绪 */; c3 Q0 K/ A$ N0 ?4 _! q1 r
- {
2 z8 {& R: m9 n! J+ v2 Z - timeout++; /* 超时处理 */% m8 s) J5 e2 g4 b
- if(timeout > maxDelay)
0 ]2 O% v- W3 |+ M# h3 l4 [& U# h - {" r$ ]% t7 w1 a
- break;
% g: {. V/ h9 X5 E p - }
8 `; D- d# `8 ?; n- H8 |- D" u - } y2 W/ R- z7 m; [
- " s$ k0 O6 I9 w" y* i
- timeout=0;5 _% P$ D& ^& p+ \1 M6 n
- 4 `* ]* g% z3 E
- /* 一次处理完成之后,重新开启中断并设置RxXferCount为1 */+ Z! S; T9 J2 D8 ^
- while (HAL_UART_Receive_IT(&g_uart4_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE) != HAL_OK)
- y6 o$ ^$ b/ s, d- y. y) l- h - {
0 k, ]$ {8 \2 O% _, U% F; O - timeout++; /* 超时处理 */
5 ? y% B! n( y9 N6 ?7 \ - if (timeout > maxDelay), f b% } {1 Q/ d8 ^% H
- {+ X9 }3 g; d$ ~/ S5 ~" a( N+ N) Y
- break;6 \- Y- w. ^4 D: X
- }
( x4 |. V7 n: m( V1 } - }
) X/ n5 I; w4 w+ l1 E+ C3 N - 9 L8 a8 J& Z8 r, T5 Z0 g
- }
复制代码 main函数调用:
" v1 \, {% ?8 M2 @6 A6 `- if (g_usart_rx_sta & 0x8000) /* 接收到了数据 */
. p$ {; N3 D" q7 @ - {& I. Z5 Y; V9 L/ |1 D$ n( e
- len = g_usart_rx_sta & 0x3fff; /* 得到此次接收到的数据长度 */% d! k5 E+ o7 T; l, x G
- printf("\r\nYou send message is: \r\n");
4 R! m) f; _! K* s. v2 s - for (t = 0; t < len; t++)& A0 c7 M9 S+ u' l
- {) t* V. ~) ? f- Q! i8 i
- USART_UX->TDR = g_usart_rx_buf[t];
4 O0 F' k" N& j' R% a - while ((USART_UX->ISR & 0X40) == 0); /* 等待发送结束 */
7 C. ?; f( k' {5 p - }* Y3 R. T% o- ^0 e2 g: h
- printf("\r\n\r\n"); /* 插入换行 */
* i, j/ L# c! A$ z' n1 y - g_usart_rx_sta = 0;; Z4 Q5 ^0 [) z% {1 ^0 ^$ F: a
- }' z: X: {( D2 t' a
- else9 J+ a* C% N* X, ^
- {
, w. @4 n* u9 h - times++;
L% b! h1 {* Z0 S - if (times % 5000 == 0)
9 Q/ s' b+ |( C+ a7 S - {* i+ C6 G ? a6 M; U. [: e
- printf("\r\nSTM32MP1_DK1 UART4 TEST!\r\n");& t+ @! h. I4 o
- printf("JasonQiu@ST community \r\n\r\n\r\n");4 C0 Q3 M& s1 a- R
- }, U( U- s; X" Q7 |# N* p+ Z
- if (times % 200 == 0) printf("Please putchar!\r\n");
1 [/ P8 j! X. Z; S - if (times % 30 == 0) ( F! g# ?& |; a( s! P7 y
- {
$ n6 Z1 Z6 v4 b: G5 Q+ N0 J5 { - LED0_TOGGLE(); 9 Y: B( h5 g% ]9 r1 m: K3 i; b
- printf("The led station is %d \r\n\r\n\r\n",LED0_STATION);; ~; r$ ]! |9 L# |2 o! {! B
- }# w ^' l/ K: y8 G
- delay(10);2 W9 H- B; N( L( R
- }
复制代码 编译无误后,此时我们需要修改MCU的BOOT MODE :: U y: g, D% X+ z
我们选择从内部RAM启动的模式:
3 q/ [/ t; d+ o& K+ w
( |# l J J* r/ P
1 P r) J) Z' y7 A$ B& `- D
9 s. u) i; `( a* P% `" wMDK中,有几次配置要注意:
8 G, ^( v; B5 _6 ^0 T3 S
8 Z, R( U& d6 g) U6 P _$ h6 S
! `% t9 a) J; O8 H D* o. Z
1 N' B" g Y9 c( h1 N
9 [( p. _2 H z- x, D' C) I" y" ?+ G
% r/ |6 C+ S7 ^) Q Z
% N* E4 R. M& w _下载后直接运行,看下输出的状态:
1 V# ~) J; x- M3 m, O
- p% Y9 m; o+ ~- f0 ~
板子LED状态:
( W( L; L! V6 k+ ?8 a
4 Z9 m3 I6 @7 q5 k0 e
好了,M4核的裸机开发就到这了。
9 @8 \/ C& m/ M# M" ]" e |