STM32: gcc下printf重定向

发布者:幸福的家园最新更新时间:2025-02-07 来源: jianshu关键字:STM32  gcc  printf重定向 手机看文章 扫描二维码
随时随地手机看文章

1. 创建工程

用cubemx创建一个工程makefile工程。记得开串口


2. 重定向

在main.c对printf重定向,增加如下代码


#ifdef __GNUC__

/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf

   set to 'Yes') calls __io_putchar() */

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif /* __GNUC__ */


/**

 * @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 USART1 and Loop until the end of transmission */

    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);


    return ch;

}


3. syscalls.c

很多网上的资料只提到了上一步,忽视了需要加入syscalls.c文件。
在cubemx的仓库目录下找到文件'C:UsersxxxSTM32CubeRepositorySTM32Cube_FW_H7_V1.11.1ProjectsSTM32H743I-EVALExamplesUARTUART_PrintfSTM32CubeIDEExampleUsersyscalls.c'
复制syscalls.c到工程中,并在makefile中加入syscalls.c。


/* Support files for GNU libc.  Files in the system namespace go here.

   Files in the C namespace (ie those that do not start with an

   underscore) go in .c.  */


#include <_ansi.h>

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include


#define FreeRTOS

#define MAX_STACK_SIZE 0x200


extern int __io_putchar(int ch) __attribute__((weak));

extern int __io_getchar(void) __attribute__((weak));


#ifndef FreeRTOS

register char *stack_ptr asm('sp');

#endif


caddr_t _sbrk(int incr)

{

    extern char end asm('end');

    static char *heap_end;

    char *prev_heap_end, *min_stack_ptr;


    if (heap_end == 0)

        heap_end = &end;


    prev_heap_end = heap_end;


#ifdef FreeRTOS

    /* Use the NVIC offset register to locate the main stack pointer. */

    min_stack_ptr = (char *)(*(unsigned int *)*(unsigned int *)0xE000ED08);

    /* Locate the STACK bottom address */

    min_stack_ptr -= MAX_STACK_SIZE;


    if (heap_end + incr > min_stack_ptr)

#else

    if (heap_end + incr > stack_ptr)

#endif

    {

        //      write(1, 'Heap and stack collisionn', 25);

        //      abort();

        errno = ENOMEM;

        return (caddr_t)-1;

    }


    heap_end += incr;


    return (caddr_t)prev_heap_end;

}


/*

 * _gettimeofday primitive (Stub function)

 * */

int _gettimeofday(struct timeval *tp, struct timezone *tzp)

{

    /* Return fixed data for the timezone.  */

    if (tzp)

    {

        tzp->tz_minuteswest = 0;

        tzp->tz_dsttime = 0;

    }


    return 0;

}

void initialise_monitor_handles()

{

}


int _getpid(void)

{

    return 1;

}


int _kill(int pid, int sig)

{

    errno = EINVAL;

    return -1;

}


void _exit(int status)

{

    _kill(status, -1);

    while (1)

    {

    }

}


int _write(int file, char *ptr, int len)

{

    int DataIdx;


    for (DataIdx = 0; DataIdx < len; DataIdx++)

    {

        __io_putchar(*ptr++);

    }

    return len;

}


int _close(int file)

{

    return -1;

}


int _fstat(int file, struct stat *st)

{

    st->st_mode = S_IFCHR;

    return 0;

}


int _isatty(int file)

{

    return 1;

}


int _lseek(int file, int ptr, int dir)

{

    return 0;

}


int _read(int file, char *ptr, int len)

{

    int DataIdx;


    for (DataIdx = 0; DataIdx < len; DataIdx++)

    {

        *ptr++ = __io_getchar();

    }


    return len;

}


int _open(char *path, int flags, ...)

{

    /* Pretend like we always fail */

    return -1;

}


int _wait(int *status)

{

    errno = ECHILD;

    return -1;

}


int _unlink(char *name)

{

    errno = ENOENT;

    return -1;

}


int _times(struct tms *buf)

{

    return -1;

}


int _stat(char *file, struct stat *st)

{

    st->st_mode = S_IFCHR;

    return 0;

}


int _link(char *old, char *new)

{

    errno = EMLINK;

    return -1;

}


int _fork(void)

{

    errno = EAGAIN;

    return -1;

}


int _execve(char *name, char **argv, char **env)

{

    errno = ENOMEM;

    return -1;

}


我们需要syscalls.c,是因为syscalls.c中实现了int _write(int file, char *ptr, int len)。


4. 补充

如果需要打印浮点型数据,需要在makefile文件中加入-u_printf_float编译参数。

#######################################

# LDFLAGS

#######################################

# link script

LDSCRIPT = STM32H743IITx_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 -u_printf_float


# default action: build all

all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin


关键字:STM32  gcc  printf重定向 引用地址:STM32: gcc下printf重定向

上一篇:stm32设置读保护后不运行问题
下一篇:手把手教你玩转蓝牙模块(原理+驱动)

小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved