GCC编译环境下的串口重定向

在不同编译环境下进行串口重定向,需要重写的函数不同。

serial.h

为方便移植,新建一个 User 文件夹,在文件夹中新建 serial.h 文件。

包含必要的头文件并声明要重定义的函数。

#ifndef __SERIAL_H
#define __SERIAL_H

#include "usart.h"
#include "stdio.h"

#pragma import(__use_no_semihosting)
int _write(int fd, char *ptr, int len);
void _sys_exit(int x);

#endif

serial.c

在 User 文件夹中新建 serial.c 文件。

重定义函数。

#include "serial.h"

int _write(int fd, char *ptr, int len)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)ptr, len, 0xFFFF);
    return len;
}

/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{
    x = x;
}

c_cpp_properties.json

在 .vscode 文件夹中找到 c_cpp_properties.json 文件。

在 “includePath” 中添加 “${workspaceFolder}/User”。

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**",
                "${workspaceFolder}/Core/Inc",
                "${workspaceFolder}/Drivers/STM32G4xx_HAL_Driver/Inc",
                "${workspaceFolder}/Drivers/STM32G4xx_HAL_Driver/Inc/Legacy",
                "${workspaceFolder}/Drivers/CMSIS/Device/ST/STM32G4xx/Include",
                "${workspaceFolder}/Drivers/CMSIS/Include",
                "${workspaceFolder}/Middlewares/Third_Party/FreeRTOS/Source/include",
                "${workspaceFolder}/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F",
                "${workspaceFolder}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2",
                "${workspaceFolder}/User"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE",
                "USE_HAL_DRIVER",
                "STM32G431xx"
            ],
            "compilerPath": "D:/app/gcc-arm-none-eabi/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc.exe",
            "cStandard": "c23",
            "intelliSenseMode": "gcc-arm",
            "cppStandard": "c++23"
        }
    ],
    "version": 4
}

Makefile

新建 .c 文件和 .h 文件后需要在 Makefile 文件中修改 C_SOURCEC_INCLUDES

若想打印浮点数,需要修改 LDFLAGS

  • C_SOURCE

    添加 “User/serial.c”。

    ######################################
    # source
    ######################################
    # C sources
    C_SOURCES =  \
    Core/Src/main.c \
    Core/Src/gpio.c \
    Core/Src/adc.c \
    Core/Src/dma.c \
    Core/Src/fdcan.c \
    Core/Src/stm32g4xx_it.c \
    Core/Src/stm32g4xx_hal_msp.c \
    Core/Src/stm32g4xx_hal_timebase_tim.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_adc.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_adc_ex.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_ll_adc.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc_ex.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ex.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ramfunc.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_gpio.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_exti.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma_ex.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr_ex.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_cortex.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_fdcan.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_tim.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_tim_ex.c \
    Core/Src/system_stm32g4xx.c \
    Core/Src/app_freertos.c \
    Middlewares/Third_Party/FreeRTOS/Source/croutine.c \
    Middlewares/Third_Party/FreeRTOS/Source/event_groups.c \
    Middlewares/Third_Party/FreeRTOS/Source/list.c \
    Middlewares/Third_Party/FreeRTOS/Source/queue.c \
    Middlewares/Third_Party/FreeRTOS/Source/stream_buffer.c \
    Middlewares/Third_Party/FreeRTOS/Source/tasks.c \
    Middlewares/Third_Party/FreeRTOS/Source/timers.c \
    Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c \
    Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c \
    Core/Src/usart.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_uart.c \
    Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_uart_ex.c \
    Core/Src/tim.c \
    Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c \
    User/serial.c
    
  • C_INCLUDES

    添加 “-IUser”。

    # C includes
    C_INCLUDES =  \
    -ICore/Inc \
    -IDrivers/STM32G4xx_HAL_Driver/Inc \
    -IDrivers/STM32G4xx_HAL_Driver/Inc/Legacy \
    -IDrivers/CMSIS/Device/ST/STM32G4xx/Include \
    -IDrivers/CMSIS/Include \
    -IMiddlewares/Third_Party/FreeRTOS/Source/include \
    -IMiddlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F \
    -IMiddlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 \
    -IUser 
    
  • LDFLAGS

    添加 “LDFLAGS += -lc -lrdimon -u _printf_float”。

    #######################################
    # LDFLAGS
    #######################################
    # link script
    LDSCRIPT = STM32G431KBUx_FLASH.ld
    
    # libraries
    LIBS = -lc -lm -lnosys 
    LIBDIR = 
    LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
    
    # printf float
    LDFLAGS += -lc -lrdimon -u _printf_float
    

printf

完成以上配置后就可以通过 printf 函数将数据打印到串口上了。

这里放一个我用于打印任务堆栈最小剩余空间的测试程序。

  • led.h

    使用 printf 函数需包含 “stdio.h” 头文件,这里我 “main.h” 中已经包含了。

    #ifndef __LED_H
    #define __LED_H
    
    #include "FreeRTOS.h"
    #include "task.h"
    #include "main.h"
    #include "cmsis_os.h"
    
    
    #endif
    
  • led.c

    #include "led.h"
    
    extern osThreadId_t LedHandle;
    
    void LedTask(void *argument)
    {
        while (pdTRUE)
        {
            // HAL_GPIO_TogglePin(GPIOA, LED_GREEN_Pin);
            HAL_GPIO_TogglePin(GPIOA, LED_RED_Pin);
            printf(" the min free stack size of LedTask is %ld \r\n", (uint32_t)uxTaskGetStackHighWaterMark(LedHandle));
            vTaskDelay(pdMS_TO_TICKS(250));
        }
    }
    
  • serial monitor

    ---- 已打开串行端口 COM4 ----
    the min free stack size of LedTask is 26
    the min free stack size of LedTask is 26
    the min free stack size of LedTask is 26
    the min free stack size of LedTask is 26
    the min free stack size of LedTask is 26
    the min free stack size of LedTask is 26
    the min free stack size of LedTask is 26
    the min free stack size of LedTask is 26
    the min free stack size of LedTask is 26
    the min free stack size of LedTask is 26
    ---- 关闭串行端口 COM4 ----

    printf 函数占用堆栈较大,若给任务分配的堆栈不足,运行时会进硬件错误中断。

    /**
      * @brief This function handles Hard fault interrupt.
      */
    void HardFault_Handler(void)
    {
      /* USER CODE BEGIN HardFault_IRQn 0 */
    
      /* USER CODE END HardFault_IRQn 0 */
      while (1)
      {
        /* USER CODE BEGIN W1_HardFault_IRQn 0 */
        /* USER CODE END W1_HardFault_IRQn 0 */
      }
    }
    
  • 38
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值