通过上篇文章对STM32MP1双核机制的分析。我们知道M4内核的程序,不能够下载到FLASH当中。那怎么调试M4的程序呢。下面我们就开始讲一讲。
STM32MP1跟普通M4核MCU开发没有太大的区别,一样调用HAL库,一样可以通过CUBEMX工具生成
初始化代码。当然在能控制的外设方面比真正的M4单片机要少一些,上文已描述过。我们在这里就不多说了。
我们打开CUBEMX工具,选择对应型号,配置工程:
我们想控制板上一颗LED,并且串口能够收发数据。
LED引脚电路位置:
与STLINK相连的调试串口UART4电路位置:
CUBEMX配置:
配置时钟:
工程配置时,选择让每一个外设生成独立文件:
然后生成代码,我们这里没有官方的STM32CUBEIDE开发,用MDK。
生成的代码,我们不直接用,仅作为参考。
修改自己的led程序:
C:
- void led_init(void)
- {
- GPIO_InitTypeDef gpio_init_struct;
- LED0_GPIO_CLK_ENABLE(); /* LED0时钟使能 */
- gpio_init_struct.Pin = LED0_GPIO_PIN; /* LED0引脚 */
- gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
- gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; /* 高速 */
- HAL_GPIO_Init(LED0_GPIO_PORT, &gpio_init_struct); /* 初始化LED0引脚 */
- LED0(0); /* 关闭 LED0 */
- }
复制代码 H:
- #define LED0_GPIO_PORT GPIOE
- #define LED0_GPIO_PIN GPIO_PIN_12
- #define LED0_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0) /* PE口时钟使能 */
- /******************************************************************************************/
- /* LED端口定义 */
- #define LED0(x) do{ x ? \
- HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_SET) : \
- HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_RESET); \
- }while(0) /* LED0 = RED */
- /* LED取反定义 */
- #define LED0_TOGGLE() do{ HAL_GPIO_TogglePin(LED0_GPIO_PORT, LED0_GPIO_PIN); }while(0) /* LED0 = !LED0 */
- #define LED0_STATION HAL_GPIO_ReadPin(LED0_GPIO_PORT, LED0_GPIO_PIN)
- void led_init(void); /* 初始化 */
复制代码 UART4.C
主要处理都在接收回传函数里面,此接收函数一直参考正点原子。
- * 接收缓冲, 最大USART_REC_LEN个字节. */
- uint8_t g_usart_rx_buf[USART_REC_LEN];
- /* 接收状态
- * bit15, 接收完成标志
- * bit14, 接收到0x0d
- * bit13~0, 接收到的有效字节数目
- */
- uint16_t g_usart_rx_sta = 0;
- uint8_t g_rx_buffer[RXBUFFERSIZE]; /* HAL库使用的串口接收缓冲 */
- UART_HandleTypeDef g_uart4_handle; /* UART句柄 */
- /**
- * @brief 串口X初始化函数
- * @param baudrate: 波特率, 根据自己需要设置波特率值
- * @note 注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常.
- * 这里的USART的时钟源在sys_stm32_clock_init()函数中已经设置过了.
- * @retval 无
- */
- void usart_init(uint32_t baudrate)
- {
- g_uart4_handle.Instance = USART_UX; /* USART4 */
- g_uart4_handle.Init.BaudRate = baudrate; /* 波特率 */
- g_uart4_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
- g_uart4_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
- g_uart4_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
- g_uart4_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
- g_uart4_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
- HAL_UART_Init(&g_uart4_handle); /* HAL_UART_Init()会使能UART4 */
-
- /* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
- HAL_UART_Receive_IT(&g_uart4_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
- }
- /**
- * @brief UART底层初始化函数
- * @param huart: UART句柄类型指针
- * @note 此函数会被HAL_UART_Init()调用
- * 完成时钟使能,引脚配置,中断配置
- * @retval 无
- */
- void HAL_UART_MspInit(UART_HandleTypeDef *huart)
- {
- GPIO_InitTypeDef gpio_init_struct;
- RCC_PeriphCLKInitTypeDef rcc_periphclk_init_struct;
-
- if(huart->Instance == UART4) /* 如果是串口4,进行串口4 MSP初始化 */
- {
- USART_UX_CLK_ENABLE(); /* USART4时钟使能 */
- USART_TX_GPIO_CLK_ENABLE(); /* 发送引脚时钟使能 */
- USART_RX_GPIO_CLK_ENABLE(); /* 接收引脚时钟使能 */
- gpio_init_struct.Pin = USART_TX_GPIO_PIN; /* 指定TX引脚 */
- gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
- gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
- gpio_init_struct.Alternate = USART_TX_GPIO_AF; /* 复用为UART4 */
- HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init_struct); /* 初始化发送引脚 */
- gpio_init_struct.Pin = USART_RX_GPIO_PIN; /* 指定RX引脚 */
- gpio_init_struct.Alternate = USART_RX_GPIO_AF; /* 复用为UART4 */
- HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init_struct); /* 初始化接收引脚 */
-
- /* 设置UART4时钟源=PLL4Q=74.25MHz */
- rcc_periphclk_init_struct.Uart24ClockSelection = RCC_UART24CLKSOURCE_PLL4;
- HAL_RCCEx_PeriphCLKConfig(&rcc_periphclk_init_struct);
- #if USART_EN_RX
- HAL_NVIC_EnableIRQ(USART_UX_IRQn); /* 使能USART4中断通道 */
- HAL_NVIC_SetPriority(USART_UX_IRQn, 3, 3); /* 抢占优先级3,子优先级3 */
- #endif
- }
- }
- /**
- * @brief Rx传输回调函数
- * @param huart: UART4句柄类型指针
- * @retval 无
- */
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- if(huart->Instance == UART4) /* 如果是串口4 */
- {
- if((g_usart_rx_sta & 0x8000) == 0) /* 接收未完成 */
- {
- if(g_usart_rx_sta & 0x4000) /* 接收到了0x0d */
- {
- if(g_rx_buffer[0] != 0x0a)
- {
- g_usart_rx_sta = 0; /* 接收错误,重新开始 */
- }
- else
- {
- g_usart_rx_sta |= 0x8000; /* 接收完成了 */
- }
- }
- else /* 还没收到0X0D */
- {
- if(g_rx_buffer[0] == 0x0d)
- {
- g_usart_rx_sta |= 0x4000;
- }
- else
- {
- g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = g_rx_buffer[0] ;
- g_usart_rx_sta++;
- if(g_usart_rx_sta > (USART_REC_LEN - 1))
- {
- g_usart_rx_sta = 0; /* 接收数据错误,重新开始接收 */
- }
- }
- }
- }
- }
- }
- /**
- * @brief 串口4中断服务函数
- * @param 无
- * @retval 无
- */
- void USART_UX_IRQHandler(void)
- {
- uint32_t timeout = 0;
- uint32_t maxDelay = 0x1FFFF;
- HAL_UART_IRQHandler(&g_uart4_handle); /* 调用HAL库中断处理公用函数 */
- timeout = 0;
- while (HAL_UART_GetState(&g_uart4_handle) != HAL_UART_STATE_READY) /* 等待就绪 */
- {
- timeout++; /* 超时处理 */
- if(timeout > maxDelay)
- {
- break;
- }
- }
-
- timeout=0;
-
- /* 一次处理完成之后,重新开启中断并设置RxXferCount为1 */
- while (HAL_UART_Receive_IT(&g_uart4_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE) != HAL_OK)
- {
- timeout++; /* 超时处理 */
- if (timeout > maxDelay)
- {
- break;
- }
- }
- }
复制代码 main函数调用:
- if (g_usart_rx_sta & 0x8000) /* 接收到了数据 */
- {
- len = g_usart_rx_sta & 0x3fff; /* 得到此次接收到的数据长度 */
- printf("\r\nYou send message is: \r\n");
- for (t = 0; t < len; t++)
- {
- USART_UX->TDR = g_usart_rx_buf[t];
- while ((USART_UX->ISR & 0X40) == 0); /* 等待发送结束 */
- }
- printf("\r\n\r\n"); /* 插入换行 */
- g_usart_rx_sta = 0;
- }
- else
- {
- times++;
- if (times % 5000 == 0)
- {
- printf("\r\nSTM32MP1_DK1 UART4 TEST!\r\n");
- printf("JasonQiu@ST community \r\n\r\n\r\n");
- }
- if (times % 200 == 0) printf("Please putchar!\r\n");
- if (times % 30 == 0)
- {
- LED0_TOGGLE();
- printf("The led station is %d \r\n\r\n\r\n",LED0_STATION);
- }
- delay(10);
- }
复制代码 编译无误后,此时我们需要修改MCU的BOOT MODE :
我们选择从内部RAM启动的模式:
MDK中,有几次配置要注意:
下载后直接运行,看下输出的状态:
板子LED状态:
好了,M4核的裸机开发就到这了。
|