How to make printf work on STM32F103?

前端 未结 4 884
醉话见心
醉话见心 2021-01-16 18:51

I am new to the world of STM32F103. I have a demo code for STM32F103 and I am using arm-none-eabi to compile it.

I tried what I could find on Google, but nothing wor

相关标签:
4条回答
  • 2021-01-16 19:26

    Link: How to retarget printf() on an STM32F10x?

    Try hijacking the _write function like so:

    #define STDOUT_FILENO   1
    #define STDERR_FILENO   2
    
    int _write(int file, char *ptr, int len)
    {
        switch (file)
        {
        case STDOUT_FILENO: /*stdout*/
            // Send the string somewhere
            break;
        case STDERR_FILENO: /* stderr */
            // Send the string somewhere
            break;
        default:
            return -1;
        }
        return len;
    }
    

    The original printf will go through this function (depending on what libs you use of course).

    0 讨论(0)
  • 2021-01-16 19:28

    By including the following linker flags:

    LDFLAGS   += --specs=rdimon.specs -lc -lrdimon
    

    it looks like you are trying to use what is called semihosting. You are telling the linker to include system call libraries.

    Semihosting is a mechanism that enables code running on an ARM target to communicate and use the Input/Output facilities on a host computer that is running a debugger.

    Examples of these facilities include keyboard input, screen output, and disk I/O. For example, you can use this mechanism to enable functions in the C library, such as printf() and scanf(), to use the screen and keyboard of the host instead of having a screen and keyboard on the target system.

    Since you are using openSource tools for your STM32 development (Makefile and arm-none-eabi), I am assuming you are also using openOCD to program your microcontroller. openOCD requires you to enable semihosting as well using the following command:

    arm semihosting enable
    

    You can at the command to your openOCD script making sure you terminate the configuration stage and enter the run stage with the 'init' command. Below is an example of an openOCD script (adapted for STM32F103):

     source [find target/stm32f1x.cfg]
     init
     arm semihosting enable
    

    Other solutions mentioned here where your retarget the fputc() function to a UART interface will also work and might. Semihosting will work on all recent ARM Cortex-M but will require some compiler & debugger configuration (see above). Retargeting the fputc() function to a UART interface will work with any compiler but you will have to check your pin configurations for every board.

    0 讨论(0)
  • 2021-01-16 19:32

    Writing an own printf implementation is an option, and probably the most recommended option according to me. Get some inspiration from the standard library implementation and write your own version, only to cater your requirements. In general, what you have to do is, first retarget a putc function to send char s through your serial interface. Then override the printf method by using the putc custom implementation. Perhaps, a very simple approach is sending the string character-wise by recursive calls for putc function.

    Last but not least, you can find some lightweight printf implementations. The code size and the set of features offered by these lightweight implementations lie in between the custom written printf function and the stock standard printf function (aka the beast). I have recently tried this Tiny Printf and very pleased with its performance on an ARM core in terms of memory footprint and the number of execution cycles required.

    -PS

    Copied from my own writings sometime back.

    0 讨论(0)
  • 2021-01-16 19:33

    Look there. This is printf from glib. But you have microcontroller. So you sould write own printf, where vfprintf will return result into buffer and next you will send data from buffer to UART. Kind of

    void printf( const char * format, ... )
    {
      char buffer[256];
      va_list args;
      va_start (args, format);
      vsprintf (buffer,format, args);
      send_via_USART1 (buffer);
      va_end (args);
    }
    

    Also you can write own vsprintf. Standart vsprintf is very heavy. Usually little part of vsprintf features is used.

    0 讨论(0)
提交回复
热议问题