简介:
我们在前一篇已经了解了STM32H7S78-DK XIP 工程的运行方式,我们基于此基础上添加串口打印功能,从原理图可以看到,STM32H7S78-DK 的PD0/PD1 UART4引脚连接到STLINK 上并虚拟出一个虚拟串口用于串口打印。


UART 配置
我们使用Cubemux 工具配置uart4 ,在application mode 下配置PTD0/PTD1为串口功能

Cubemux 使能uart 中断,然后生成初始化代码。

在cubemux 上配置好串口会自动初始化好,在此基础上添加如下代码重定向printf函数至uart4,实现底层IO __write 函数通过uart4打印,本地使用的IAR 9.50.2 环境。
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#if defined(__ICCARM__)
#include <LowLevelIOInterface.h>
#endif /* __ICCARM__ */
/* USER CODE END Includes */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
#if defined(__ICCARM__)
/* New definition from EWARM V9, compatible with EWARM8 */
int iar_fputc(int ch);
#define PUTCHAR_PROTOTYPE int iar_fputc(int ch)
#elif defined ( __CC_ARM ) || defined(__ARMCC_VERSION)
/* ARM Compiler 5/6*/
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#elif defined(__GNUC__)
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#endif /* __ICCARM__ */
/* USER CODE END PM */
#if defined(__ICCARM__)
size_t __write(int file, unsigned char const *ptr, size_t len)
{
size_t idx;
unsigned char const *pdata = ptr;
for (idx = 0; idx < len; idx++)
{
iar_fputc((int)*pdata);
pdata++;
}
return len;
}
#endif /* __ICCARM__ */
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART2 and Loop until the end of transmission */
HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END 4 */以上修改后在main函数内添加printf 周期打印 hello world,下载运行后连接STLINK的虚拟串口已经按照预取的能够打印输出。

上述我们已经适配好了串口输出功能,我们在此基础上继续适配串口接收功能,串口我们使用中断接收的方式处理数据,接收到的数据通过ringbuff 来缓存避免应用程序未及时读取数据造成的数据丢失,添加如下代码对接收的数据进行回显。
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void pUART_RxdataCallback(UART_HandleTypeDef *huart)
{
(void)huart;
RingBuffer_Write(&uart_rx,&uartrx,1);
HAL_UART_Receive_IT(&huart4, &uartrx, 1);
}
uint8_t uartgetchar(uint8_t * pdata)
{
return RingBuffer_Read(&uart_rx,pdata,1);
}
void ThreadOne_Entry(void)
{
/* Enable uart2 rx interrupt */
static uint8_t uart_rx_buff[128] = {0};
RingBuffer_Init(&uart_rx,uart_rx_buff,128);
HAL_UART_RegisterCallback(&huart4,HAL_UART_RX_COMPLETE_CB_ID,pUART_RxdataCallback);
HAL_UART_Receive_IT(&huart4, &uartrx, 1);
//littleshell_main_entry(NULL);
}
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
MPU_Config();
/* USER CODE END 1 */
/* Enable the CPU Cache */
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
/* MCU Configuration--------------------------------------------------------*/
/* Update SystemCoreClock variable according to RCC registers values. */
SystemCoreClockUpdate();
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_UART4_Init();
ThreadOne_Entry();
/* USER CODE BEGIN 2 */
/* Initialize LD1 */
BSP_LED_Init(LD1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* Toggle LD1 every 250ms */
BSP_LED_Toggle(LD1);
HAL_Delay(250);
uint8_t ch;
if(uartgetchar(&ch))
{
printf("%c\r\n",ch);
}
//printf("hello world.\r\n");
}
/* USER CODE END 3 */
}下载到板卡里验证已经按照预期的将接收到的数据进行回显,说明串口的收发功能都已经是ok的了,串口的收发都是适配完毕了,我们可以在此基础上添加shell 功能和板子交互。
我要赚赏金
