2013-10-26

CooCox CoIDE 1.7.4 Beginners guide to printf

Beginers guide to CooCox CoIDE printf() - jfragos 2012

http://www.coocox.org/forum/topic.php?id=1821

CoIDE1.5.0 - STM32F4: Beginers guide & solutions to printf() and floating points

Coocox v1.5.0 preparations to have all systems GO with STM32F4 (includes the printf() and floating point issues)

Follows a step by step tutorial to using CoIDE including the solution to printf() and floating point variables problems

CoIDE states clearly in the help, first of all to go and download and install the recommended GNU Arm toolchain GCC ARM Embedded 2011-q4-major from here https://launchpad.net/gcc-arm-embedded/4.6/2011-q4-major

Well, the basics are checked with this release, but lately I found out there is a newer release. So go here  https://launchpad.net/gcc-arm-embedded/+milestone/4.6-2012-q2-update and get the latest (if so far this is still the latest). If you upgrade, and install to a new directory, check the paths of your system, not to refer to the new and to the old one. All the rest of this document will refer to this toolchain and to CoIDE 1.5.0

Get used with the CoIDE (play around) having as guide the super nice tutorial you will find at the beginnings of the help. Notice that the examples are the same of the ST’s Standard Peripherals Library, mainly divided into two files, a minimum “main.c” and an “example_name.c”. This Repository system of the CoIDE is awesome for beginning to play with e.g. the STM32F4 discovery board. Play with the LEDs for example, but don’t play around too much and mess with printf() or floating numbers until you read the following:

HOW TO MAKE printf() working:

For reasons regarding your phycology and how much money to give to your Shrink:

a) This issue is not easy with any new MCU and having achieved it you have a great milestone done.

b) printf() of the GNU toolchain is the most advanced in capabilities with the penalty of HUGE flash memory footprint. Do not worry, STM32F4s have a lot of Flash and GCC is of the most efficient in size and speed compilers (see http://www.raisonance.com/arm_benchmark.html). But if you write your first small 20 lines program and see 59KBs size, relax, it will not become 60K bigger every 20 lines.

Preparing the toolchain:

In project -> configuration click on the “Add” of the “linked libraries” box and put there a single m (Yes, a f&@^# single letter, an “m” without quotes)

Do not use “FPU Hard” in the commands of the compiler (to be resolved in a next post)

At the command of the linker use the “Base C library”, do not use the “Redirect”

In startup code (startup/startup_stm32f4xx.c) change:

(void *)&pulStack[STACK_SIZE-1],

to

(void (*)(void))((unsigned long)pulStack + sizeof(pulStack)),

In main.c, before using printf( ) function, add

 /* Set unbuffered mode for stdout (newlib) */
setvbuf( stdout, 0, _IONBF, 0 );   

Don't forget to include stdio.h 

Increase the stack size. Full formatting may need up to 4K itself (yeaaaaa  ST32F4 has it for breakfast). To do that find the

#define STACK_SIZE       0x00000100      /*!< Stack size (in Words)           */

in the beginning of startup/startup_stm32f4xx.c and change this number to something like   0x00002000 (8KBs!)

Remember… the only monster in your code (in size) will most probably be the printf() and the rest of the similar to it IO functions (sprintf(), scanf() etc)

Now the coding work:

printf() streams what it prints, character by character to a function that is unimplemented cause the hardware is considered unimplemented also for the general purposes of Coocox. To customize to your hardware, say to use a USART you can take an idea from my example code where I used USART2. The great goal is to write such code in this that follows, where you choose on run-time where (hardware peripheral, even screen) to print.

The unimplemented function that takes every character of the printf function is in the syscalls/syscalls.c file and is the

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

Fill it with code similar (or the same) as follows:

In text:

int _write(int file, char *ptr, int len)
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART */
        int counter;

        counter = len;
        for (; counter > 0; counter--)
        {
                        if (*ptr == 0) break;
                        USART_SendData(USART2, (uint16_t) (*ptr));
                        /* Loop until the end of transmission */
                        while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
                        ptr++;
        }
        return len;
}

Other implementations may use Semihosting or really whatever (preferably switchable)

Same philosophy applies to have input to, say scanf(), by implementing the
int _read(int file, char *ptr, int len){}

In the same file, but you may never need such thing.


SO FAR printf() MUST BE FULLY AT YOUR WILL (I hope)

Having done the above, FLOATS AND DOUBLES MUST BE WORKING VERY WELL TOO. A big solution to the floats has been this m letter at the linked libraries list. Without these workarounds, printf() had a big problem in floats and doubles handling.

Thanks to all the people contributing to the Coocox forum, especially two girls :)

Be careful. The precision of the floats in some configurations of the compiler is not very good. Check how they are truncated, use doubles whenever such problem exists and speed is no care.

To be continued with HOW TO USE THE ULTIMATE FPU of this magnificent MCU and unleash 15x speed in human understandable numbers….

I’ll be back

Asta la Vista

I am going studying more on GCC

/ More ... http://www.coocox.org/forum/topic.php?id=1821

.END



The above is NOT working for ARM NXT LPC1114. 

A get ground is to use milliVolt instead of Volt to get rid of the decimals.[tlfong01 2013oct26]


http://www.coocox.org/forum/topic.php?id=1821

...

HOW TO MAKE printf() working:

Preparing the toolchain:

1. View > configuration (a) click on the “Add” of the “linked libraries” box and (b) put there a single m [an “m” without quotes]

2. Compile FPU option = No use FPU [No other choice actually]

3. Link Library option = Semihosting

4. In startup code system_LPC11xx.c change: [no such change possible!]

    (void *)&pulStack[STACK_SIZE-1],

    to

    (void (*)(void))((unsigned long)pulStack + sizeof(pulStack)),

5. In main.c, before using printf( ) function, add

    /* Set unbuffered mode for stdout (newlib) */
    setvbuf( stdout, 0, _IONBF, 0 );  

6. Don't forget to include stdio.h

7. Increase the stack size. Full formatting may need up to 4K itself ... . To do that find the
 
   #define STACK_SIZE       0x00000100      /*!< Stack size (in Words)           */

   in the beginning of [startup/startup_stm32f4xx.c] and change this number to something like   0x00002000 (8KBs!)

.END




1 comment: