通过上篇文章对STM32MP1双核机制的分析。我们知道M4内核的程序,不能够下载到FLASH当中。那怎么调试M4的程序呢。下面我们就开始讲一讲。: U, a ]1 T! I$ e5 V! N
STM32MP1跟普通M4核MCU开发没有太大的区别,一样调用HAL库,一样可以通过CUBEMX工具生成$ H- `/ @# T, k O# P3 G' p6 R
初始化代码。当然在能控制的外设方面比真正的M4单片机要少一些,上文已描述过。我们在这里就不多说了。- \& m) @9 g! {% S
我们打开CUBEMX工具,选择对应型号,配置工程:
$ |+ s* h0 U8 P Q3 r$ \ o我们想控制板上一颗LED,并且串口能够收发数据。
" }: n) h, C! i* | p8 @ s& SLED引脚电路位置:
9 C7 U" ] c( P3 F& k4 E: A0 X. q
5 j8 y- [ {- D3 @" v2 g1 |( D与STLINK相连的调试串口UART4电路位置:
- n% w, O+ S# M0 w3 H# c3 N
9 B( d& H% z% M3 u) Z# n' \* ~
6 o( S; c2 a6 y* c: t
; D6 c* ]' E& i. S- i0 B
6 p" u# s: Q) |8 a: ]! f" DCUBEMX配置:
6 M f0 P+ N9 L# [- W7 Y# O& q: I9 B, A3 O9 T
, g ^1 v: C3 W( M+ E# }9 q
3 m& O- ^: m2 E' G配置时钟:) U; p9 h) M. u% \. r8 p! q2 ^
" k2 v$ ~, {" o; A
* M; [; s1 U" e7 k r, u2 M
7 y) b( ]9 O# R/ @" Z% @! |+ \工程配置时,选择让每一个外设生成独立文件:
2 w+ J( J1 t4 _/ a6 t' A. d
4 `3 h' N/ w: l! w- e然后生成代码,我们这里没有官方的STM32CUBEIDE开发,用MDK。) _3 E. }4 x) a
生成的代码,我们不直接用,仅作为参考。+ V. \! B, Q% ~- Z6 Q) G ]
修改自己的led程序:
3 s7 T) N* O% k- ]$ ZC:
' e( n: c# }" X- void led_init(void)4 o- P" V/ o& Z2 g! ^4 i
- {! s: U' T& J9 K3 N% L: q
- GPIO_InitTypeDef gpio_init_struct;+ e. }+ l2 [: y. \
- LED0_GPIO_CLK_ENABLE(); /* LED0时钟使能 */
2 |7 O: C2 u5 i; u% w" k
0 d! h$ b* C: s _# w. d0 o, j4 [
$ E, U! g* C H& A2 R. j- gpio_init_struct.Pin = LED0_GPIO_PIN; /* LED0引脚 */
* t) X/ A- C* \& j5 x9 N - gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */+ s' a2 u# p% Y7 K( A2 h
- gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */ d0 U6 \ U6 A8 V- ~/ J( D
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; /* 高速 */
% u8 A2 f9 p- M5 U+ h L c - HAL_GPIO_Init(LED0_GPIO_PORT, &gpio_init_struct); /* 初始化LED0引脚 */0 B6 W5 V4 k. a" K# ?7 }
, b" Q2 M3 A& @5 F3 I
' |/ E. ~' h4 n% D% z* k* e- LED0(0); /* 关闭 LED0 */
) E: \/ b0 j* p+ J) X
3 g, S, U0 `3 f+ E6 e7 t' q- }
复制代码 H:9 N: J0 p+ U8 z+ S9 ^
- #define LED0_GPIO_PORT GPIOE+ K4 p) n* L& m" u
- #define LED0_GPIO_PIN GPIO_PIN_12
) P, [/ e( K. Z# u+ ` - #define LED0_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口时钟使能 */8 F( |' J+ |2 h: K& f
9 O3 A# j8 H. l2 k O- /******************************************************************************************// I9 [* D4 [3 V! `
* a! Y2 M+ l; u" r$ g; E, }2 B- + T- p5 ]+ [6 r. D$ j- M2 D4 g5 l
- /* LED端口定义 */
# d/ v& \$ z9 q7 p - #define LED0(x) do{ x ? \% x3 S5 q8 [, w. r+ e( D* T
- HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_SET) : \/ b/ w% x' _, p( a. U5 z
- HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_RESET); \ R9 j! d0 h) u) e; @# \" v6 d
- }while(0) /* LED0 = RED */
2 m4 c/ t: ?3 T, J3 X3 K - 1 q5 ~& l, u* b! Q( o
- /* LED取反定义 */$ P; E' @' i0 ` |7 ~! X0 a
- #define LED0_TOGGLE() do{ HAL_GPIO_TogglePin(LED0_GPIO_PORT, LED0_GPIO_PIN); }while(0) /* LED0 = !LED0 */
+ x# F* b# N& Y {$ x" O
1 T- u3 s6 c$ k; b" X$ j4 c9 L" b- 1 J# F" H5 u8 ?) F: \8 q* D, Q
- #define LED0_STATION HAL_GPIO_ReadPin(LED0_GPIO_PORT, LED0_GPIO_PIN)
( N- p R! J# w& H# `4 u) M3 e
. N" X4 H$ P4 a% [$ m7 w# b* r' t- void led_init(void); /* 初始化 */
复制代码 UART4.C5 W# A/ v2 j6 y: }" w$ ?% |3 o
主要处理都在接收回传函数里面,此接收函数一直参考正点原子。
1 B+ O$ s, n+ b' |& w$ Q& A/ z- * 接收缓冲, 最大USART_REC_LEN个字节. */
2 R3 R- _- t( r - uint8_t g_usart_rx_buf[USART_REC_LEN];
. ?; U& M. W/ ^: ^, Z9 f! g
. T2 S* q. W6 \5 \ D7 Q, G- /* 接收状态( j# H \$ e& l8 B( Y, o
- * bit15, 接收完成标志- z) H1 R: \1 \; M
- * bit14, 接收到0x0d
% D3 ^& ]* D: V; @: G6 f* H: {! h5 a - * bit13~0, 接收到的有效字节数目
- M" S) Q& C" |, W u - */) j% ]) T" X5 m2 i" ]2 b2 L
- uint16_t g_usart_rx_sta = 0;
" g5 b& ?. M3 x0 ?* ]& |; `
, R# X2 j7 {* n$ @) c. X0 `' l- uint8_t g_rx_buffer[RXBUFFERSIZE]; /* HAL库使用的串口接收缓冲 */
n) Y% Q' x) b7 @0 C+ `6 i7 s+ E, ~
1 j5 w- Y5 x* K/ \- UART_HandleTypeDef g_uart4_handle; /* UART句柄 */
% V! r# p1 U* F - 1 j1 T2 O1 F* Z
" G w/ W7 q5 L7 c- /**
: G. m& Z; {9 r9 w; l% p - * @brief 串口X初始化函数
. B3 S% E: {2 c - * @param baudrate: 波特率, 根据自己需要设置波特率值
0 l. @: j& o3 i8 o0 z) U2 z - * @note 注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常.
; Y% `% V$ x% c2 t! S5 H - * 这里的USART的时钟源在sys_stm32_clock_init()函数中已经设置过了.
9 H T! v3 A. N1 P& p0 ]" J - * @retval 无" ?/ E9 B& @! U4 C4 r3 ^$ I) X
- */2 k+ V w8 N* E- W
- void usart_init(uint32_t baudrate)
2 I# M* m; i7 m# w! ` - {
: J, {" E- W: U5 N: F x2 G: v- { - g_uart4_handle.Instance = USART_UX; /* USART4 */; z& w0 q9 S: V: r7 t# X* O7 D& `
- g_uart4_handle.Init.BaudRate = baudrate; /* 波特率 */4 `% q4 x' f7 N. c \) p& ]
- g_uart4_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
* @3 {9 l6 [: I' _/ x: n; E0 P - g_uart4_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
2 ?" M" ~0 b; @8 e5 _6 Z - g_uart4_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
, t: e% y$ }; E4 e6 }9 g$ N - g_uart4_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */1 r+ q& {3 Y4 G6 l- O, Q& n
- g_uart4_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
/ x- ~% k! ]4 O/ q7 Z$ r - HAL_UART_Init(&g_uart4_handle); /* HAL_UART_Init()会使能UART4 */
7 D1 j3 K8 G( y2 M5 [: N -
9 ]( I+ e5 L$ w+ C S9 G5 _" N/ e - /* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
) L& T3 W" W5 c) e) L6 z6 r - HAL_UART_Receive_IT(&g_uart4_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
# }( G" M1 `/ }% { - }2 k$ C" V! o- w8 R6 h
E, J* s' _/ j: {/ p- /**
7 I; |; y9 u/ L9 {2 _0 A3 |( R8 n - * @brief UART底层初始化函数" K9 J- \" j* v4 Y, v" O+ g3 d4 q
- * @param huart: UART句柄类型指针
* Y A3 x' P r% k5 t0 N2 S - * @note 此函数会被HAL_UART_Init()调用3 ?' B. N) o1 m& b2 a q* a4 e
- * 完成时钟使能,引脚配置,中断配置5 b W( J0 W, C( Y
- * @retval 无9 U/ `" }9 W5 e( O- o8 Y) [! V
- */
3 `8 c1 Q, `0 {* `% R! [' M* O* u - void HAL_UART_MspInit(UART_HandleTypeDef *huart)# h, R: {2 O G% `6 S
- {
& i) B! M. X3 \% ~: H, N - GPIO_InitTypeDef gpio_init_struct;
+ v8 ]5 k5 W( u7 c - RCC_PeriphCLKInitTypeDef rcc_periphclk_init_struct;' {" e3 @) s' i* V
- & L7 a/ W/ [: [
- if(huart->Instance == UART4) /* 如果是串口4,进行串口4 MSP初始化 */
9 s! `0 U2 |: R" ~9 Z - {) K. q( Z3 Q/ d( p( j: G" O K, n2 d
- USART_UX_CLK_ENABLE(); /* USART4时钟使能 */
( T3 C1 h7 h; r" J# c+ h) U - USART_TX_GPIO_CLK_ENABLE(); /* 发送引脚时钟使能 */; m u f" M. E( C
- USART_RX_GPIO_CLK_ENABLE(); /* 接收引脚时钟使能 */3 e: h' X- h! @1 q0 Y
) }3 ?3 x1 p7 I4 n- gpio_init_struct.Pin = USART_TX_GPIO_PIN; /* 指定TX引脚 */+ S/ f. f! m) Z4 ~1 U9 q7 J* F* h
- gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */' G- X+ y( l( k- @! \
- gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
( B) P& o3 s, [4 n - gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */# O/ S! {! |/ ?9 }: O
- gpio_init_struct.Alternate = USART_TX_GPIO_AF; /* 复用为UART4 */& i% t3 O* ^: D# O$ ]4 Q
- HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init_struct); /* 初始化发送引脚 */
+ m( B/ i/ F' C l/ \
3 K/ ~8 r; ? P# G- gpio_init_struct.Pin = USART_RX_GPIO_PIN; /* 指定RX引脚 */: H6 r( o- l3 W0 G$ w: {' T
- gpio_init_struct.Alternate = USART_RX_GPIO_AF; /* 复用为UART4 */" [5 Y4 w F# |
- HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init_struct); /* 初始化接收引脚 */ _& z, a+ T1 B4 y! R2 N7 f
- ; f9 s* y. F- u0 ^: t o
- /* 设置UART4时钟源=PLL4Q=74.25MHz */3 x, n ^- F8 `/ M# I7 M# ]4 S
- rcc_periphclk_init_struct.Uart24ClockSelection = RCC_UART24CLKSOURCE_PLL4;
/ I# X$ `% W- p7 [ - HAL_RCCEx_PeriphCLKConfig(&rcc_periphclk_init_struct);9 D5 }9 ^8 A3 }9 X" o% E
5 U5 V6 V" E7 s8 N- #if USART_EN_RX
6 x" e) }' |0 F - HAL_NVIC_EnableIRQ(USART_UX_IRQn); /* 使能USART4中断通道 */
X+ U1 }( U* w4 Y$ v& p; | - HAL_NVIC_SetPriority(USART_UX_IRQn, 3, 3); /* 抢占优先级3,子优先级3 */- C! p8 A8 Q5 G8 b$ V# l3 ]4 T4 b% v
- #endif
; D7 n6 |4 x/ |% C - }1 ?# f3 p* P- I! x0 W* q
- }
3 i, A) p- l5 p" T/ ]
$ R0 |% Y l, N% n9 D5 ?* p3 o9 ]! x- /**
4 b& k1 }! [' {1 S' i0 N( O - * @brief Rx传输回调函数7 T8 j( `# A* e. o1 ?* J8 w
- * @param huart: UART4句柄类型指针) t8 \& a+ v& L2 T6 Y5 K5 Y$ E8 I
- * @retval 无
( m6 Y; T& e+ y' G; R - */
3 F4 `+ Z* S0 L, S- r - void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)/ r. b6 J. k) e
- {# _0 k1 |5 Q/ {
- if(huart->Instance == UART4) /* 如果是串口4 */- S* F7 V* e0 w2 \3 Y* ^7 {/ f
- {
2 \! o, d7 l2 J6 ~5 X3 ~ - if((g_usart_rx_sta & 0x8000) == 0) /* 接收未完成 */8 ^( T r8 E- ^! S( a4 W& l7 J
- {
& \- U$ f7 w. @% p6 @4 Q) r( S - if(g_usart_rx_sta & 0x4000) /* 接收到了0x0d */
* {4 `9 C& j1 A, f - {
* H" D' R l! G7 r# o5 B - if(g_rx_buffer[0] != 0x0a)
+ W; s; e! f& x - {0 L ^. v! y6 h( O2 m
- g_usart_rx_sta = 0; /* 接收错误,重新开始 */
3 [$ D& l1 e- L - }
A8 G; d8 F5 }/ s: E& ~9 }3 r5 X - else $ j' o' Z# Y9 H) ^9 N
- {
M! _. B( Q1 d3 K6 o" R/ {1 b - g_usart_rx_sta |= 0x8000; /* 接收完成了 */
% C+ f/ w, J) k) s" U0 B# V( \5 R - }2 [9 i4 T Q: T* g4 U2 V( \
- }
$ P5 M4 S3 l- k8 m8 L - else /* 还没收到0X0D */. [7 M/ l& u- P1 ?
- {
! b; m, N, l% {" _; A5 ~ - if(g_rx_buffer[0] == 0x0d): D3 X8 b2 G( Q- ?" F7 j; N( A8 e' L
- {
, D( n: v% D; U6 b. @+ a - g_usart_rx_sta |= 0x4000;
; O% g' P3 k& b- Z$ U. I& v4 Z& W" C - }
8 I* N( c; d0 m; w) R - else
* u, _% L3 q" I" n - {
$ i( |8 c9 n2 a+ x - g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = g_rx_buffer[0] ;
5 n5 Q2 R2 y# O - g_usart_rx_sta++;7 e5 j3 G9 W8 M$ J3 U* |
- if(g_usart_rx_sta > (USART_REC_LEN - 1))) i( }& V) j( _* O+ ~7 }
- {8 {- i- k0 c7 a- z
- g_usart_rx_sta = 0; /* 接收数据错误,重新开始接收 */* b, x- @: U& t: k+ x7 \- Z- L+ U4 F
- }5 M" }1 B1 M7 w6 u& F# I" Y- Q* G
- }
8 H- A) U' ^; \2 J2 t; [" J - }) a# D+ D0 d6 ~; j+ f
- }
$ G8 g4 L3 C; u7 v4 H - }
8 R9 W! e! A9 f8 m: Y - }
. d# o( z4 k$ N) I. B6 f
! o3 Y! `9 S* y" P! Y1 x, r- /**- Q: r# ]6 ~. Z2 X
- * @brief 串口4中断服务函数
( L; s$ ]6 @% P# T5 ] - * @param 无
: \9 b8 _6 I1 j% E) r) J$ X - * @retval 无
! c i$ r( X3 E8 {) h3 n; T - */
5 r& t h$ c$ p J& y7 h - void USART_UX_IRQHandler(void); f1 R) h' D3 }9 J0 q3 i
- {
/ K- W' Q4 P1 T& V7 w c6 F. P - uint32_t timeout = 0;) h" T3 c) Q( F
- uint32_t maxDelay = 0x1FFFF;
1 u- g/ c5 O. [ - ) [* n" d9 g5 y" L& L5 z+ E5 l
- HAL_UART_IRQHandler(&g_uart4_handle); /* 调用HAL库中断处理公用函数 */ {5 S8 x1 L; ]$ z3 _/ Q! m+ {1 w; y
- 5 X: ]) C5 a" m" r6 p7 E; P7 [
- timeout = 0;
6 p* Y+ R/ @8 I2 X, O5 Z, @ - while (HAL_UART_GetState(&g_uart4_handle) != HAL_UART_STATE_READY) /* 等待就绪 */# o# m. m- B8 z& a4 U, V+ ^! z. N8 x+ j
- {
i; W% K; X& ~ ]: r9 g - timeout++; /* 超时处理 */
; M2 ^( C i3 X1 h0 t6 g0 U - if(timeout > maxDelay)- I" H# @# A( i$ [& x, p
- {
2 u$ m+ }" L$ P0 @( c$ K: x - break;
( M' Q3 U: }4 }3 P5 H" N. r$ m - }# {" x) P) c3 D# _3 L: T; c' t
- }* q0 @4 T% _: B n7 Y
-
9 P* M5 H; W; w! {: Q - timeout=0;# O' I' L2 E A0 v6 S7 {
- & E! ^' H+ ? l+ |3 ?" M( ]
- /* 一次处理完成之后,重新开启中断并设置RxXferCount为1 */, `5 E+ }* I( N+ Z
- while (HAL_UART_Receive_IT(&g_uart4_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE) != HAL_OK)
! `' x$ D$ I# N6 U" Y( V6 W - { e* b g% d' K
- timeout++; /* 超时处理 */
# x$ J& J( T. ^1 u - if (timeout > maxDelay). t. R1 M$ z9 A1 b
- {% o/ O3 {: [, J7 T) |3 C. H
- break;
$ g7 E2 V K4 T - }7 x+ x1 h7 j6 R5 L
- }
3 [* B( E1 Z; r2 V/ C" R - . Q' z& k l1 j5 V/ `
- }
复制代码 main函数调用:( f' l/ g, Y) |0 X
- if (g_usart_rx_sta & 0x8000) /* 接收到了数据 */5 N) p4 w+ Y F
- {
8 y; ?# N5 {0 K- u* p) Q/ l' E: T - len = g_usart_rx_sta & 0x3fff; /* 得到此次接收到的数据长度 */
3 Z4 e6 j9 Z# h* q$ n- t' r5 F- g - printf("\r\nYou send message is: \r\n");% n) T1 R, @% {# X' f" e
- for (t = 0; t < len; t++)
8 V( C& J. W3 b- U2 [2 C2 | q - {% h4 q: g, Z5 j5 Q1 D
- USART_UX->TDR = g_usart_rx_buf[t];1 Z. [, V+ ~# F3 |$ ^: K
- while ((USART_UX->ISR & 0X40) == 0); /* 等待发送结束 *// d3 O# u: X4 ~) ^- H! N0 d8 t
- }2 D+ g5 ?! ?7 Z5 l* f. O
- printf("\r\n\r\n"); /* 插入换行 */
# s9 t2 H! Q" N7 m. e4 O% h - g_usart_rx_sta = 0;
+ U! U8 Z" a4 d- h- I. ]. L) z - }4 Z! a- F q" W( I- `
- else Q+ G9 e6 B7 f
- {7 r1 f4 B+ R9 [( y* y5 j6 w
- times++;
w7 q* H7 A% [' Z3 a - if (times % 5000 == 0)
& ~" b4 N# f3 A- d( f" k7 e - {( {6 g/ E2 Q" I e
- printf("\r\nSTM32MP1_DK1 UART4 TEST!\r\n");
. J$ R2 j' g* R7 g: i7 i0 |6 H - printf("JasonQiu@ST community \r\n\r\n\r\n");
: a7 g. o$ l9 m! _ k - }
$ H1 e; ]" o) D8 y/ X" a4 I - if (times % 200 == 0) printf("Please putchar!\r\n");& E J% [9 @& o8 [1 _
- if (times % 30 == 0) 0 T5 f7 S" g( ]5 Z+ H$ I
- {
: N! p5 O# x# y" }- e7 _$ u7 k - LED0_TOGGLE(); 3 P: [% {- c, T2 ^
- printf("The led station is %d \r\n\r\n\r\n",LED0_STATION);
& }) o- ?& s# }: o: {# O( z; P - }1 k8 b0 S9 u) k5 L, [
- delay(10);
( h, i. o8 M. w0 s - }
复制代码 编译无误后,此时我们需要修改MCU的BOOT MODE :
& Q2 R1 r d* Z我们选择从内部RAM启动的模式:7 p7 l* T' x7 c* G3 \7 P% M8 p% v1 C
4 L& J, Z: r3 C7 X2 X5 t+ B% B+ ^& B
- P5 V7 d+ v5 }( U: V& z5 U& P
3 h5 ~& g2 a: J* O2 |* {/ pMDK中,有几次配置要注意:
3 Y/ g1 o$ | h- ^/ A) A2 H) @& C* R, M+ i8 t& ^5 z9 u
/ T7 c$ H$ M( R1 c4 a, I) Q6 h# R
7 c2 l+ z0 o9 W7 Q1 G/ ^
" u% q9 S5 |, n/ _3 W
! `& Q6 b, S: S8 \* D, K9 ?3 d
0 ]: p7 h. o& V6 l! k: B下载后直接运行,看下输出的状态:- M g( |' X) I+ z* a* D
/ g( D8 v7 L9 a; c$ `' Z
板子LED状态:
6 Y9 }4 t' |6 Q5 s9 i
6 P2 P1 l6 h- Q2 |+ \
好了,M4核的裸机开发就到这了。
# `" H& m* N, O% j/ K |