Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[Cortex-M3] [GCC CodeSourcery 2009q3-68] Float w printf

michalko12 27 Nov 2009 11:16 3943 20
  • #1
    michalko12
    MCUs specialist
    Witam

    Mam problem z konwersją flota w printf/sprintf. W miejscu gdzie powinien być wynik konwersji, printf wstawia "ERROR". Biblioteka libm jest niby dołączona (-lm), ale to nic nie daje. Co powinno być jeszcze wstawione w opcjach żeby zaczęło to działać, a może to z innego powodu nie działa? Może malloc nie che przydzielić pamięci dla printfa? Tu jeszcze mam prośbę o kod sprawdzonej funkcji _sbrk_r, może w tej co ja mam jest coś nie tak, ale z drugiej strony nic w niej takiego nie ma.

    Code:
    /* "malloc clue function" */
    



       /**** Locally used variables. ****/
    extern char _ebss[];              /*  end is set in the linker command    */
                /* file and is the end of statically    */
                /* allocated data (thus start of heap).   */

    static char *heap_ptr;      /* Points to current end of the heap.   */

    /************************** _sbrk_r *************************************/
    /*  Support function.  Adjusts end of heap to provide more memory to   */
    /* memory allocator. Simple and dumb with no sanity checks.      */
    /*  struct _reent *r   -- re-entrancy structure, used by newlib to    */
    /*         support multiple threads of operation.      */
    /*  ptrdiff_t nbytes   -- number of bytes to add.         */
    /*  Returns pointer to start of new heap area.            */
    /*  Note:  This implementation is not thread safe (despite taking a   */
    /* _reent structure as a parameter).                 */
    /*  Since _s_r is not used in the current implementation, the following   */
    /* messages must be suppressed.                  */

    void * _sbrk_r(
        struct _reent *_s_r,
        ptrdiff_t nbytes)
    {
       char  *base;      /*  errno should be set to  ENOMEM on error   */

       if (!heap_ptr) {   /*  Initialize if first time through.      */
          heap_ptr = _ebss;
       }
       base = heap_ptr;   /*  Point to end of heap.         */
       heap_ptr += nbytes;   /*  Increase heap.            */
       
       return base;      /*  Return pointer to start of new heap area.   */
    }
  • Helpful post
    #2
    Freddie Chopin
    MCUs specialist
    Tu masz coś o sbrk(), ale dla innego skryptu linkera, więc nieszczególnie Ci pomoże. Twój jednak wygląda mi na dobry (pozatym, że heap_ptr można zainicjalizować normalnie, bez tego if() ). Jak chcesz uciszyć warningi o nieużywanej zmiennej, to wystarczy na początku funkcji zrobić - _s_r = _s_r i po problemie.

    https://www.elektroda.pl/rtvforum/topic1443142.html

    Co do printf() i tym podobnych, to u mnie działały jak należy bez dodatkowych zabiegów (oczywiście musi być trochę tej pamięci na heap, dużo pamięci na stos i jeszcze więcej na program [; )

    https://www.elektroda.pl/rtvforum/viewtopic.php?p=7086385#7086385

    4/3!!
  • #3
    michalko12
    MCUs specialist
    Freddie Chopin wrote:

    Co do printf() i tym podobnych, to u mnie działały jak należy bez dodatkowych zabiegów (oczywiście musi być trochę tej pamięci na heap, dużo pamięci na stos i jeszcze więcej na program [; )

    https://www.elektroda.pl/rtvforum/viewtopic.php?p=7086385#7086385

    4\/3!!


    Zmiana kompilatora to nie jest rozwiazanie :(

    Malloc i sbrk działają. Problem jest chyba w samej bibliotece, albo jest to wersja bez obsługi float'ów, albo potrzebny jest jakiś przełącznik do uruchomienia tej opcji. Printf tak samo odpowiada na %f jak i na %z czyli raczej nie obsługuje float'ów. Nigdzie nie mogę znaleźć informacji w dokumentacji Cs na ten temat.
  • #5
    michalko12
    MCUs specialist
    Freddie Chopin wrote:

    Jeśli u ciebie nie działa, to podeślij przykład z sprintf który Ci nie chodzi i sprawdzę u siebie.

    4\/3!!


    Dzięki za podpowiedzi, dopiero w poniedziałek będę mógł to sprawdzić. Zastanawia mnie tylko te "ERROR" zamiast wyniku lub chociaż "0.0000", dodam jeszcze że to samo miałem na ostatniej wersji kompilatora z 2008 roku. Na przedostatniej nie sprawdzałem.

    >>>Tutaj<<<ktoś miał już taki problem z obsługą float'ów i teoretycznie znalazł jakieś rozwiązanie, ale u niego tak samo jak u Ciebie wyświetlało się 0.000000. U mnie sprintf zachowuje się jak siprintf.
  • #7
    michalko12
    MCUs specialist
    Freddie Chopin wrote:
    Tymi zerami zbytnio się nie sugeruj, bo czasami zamiast zer była jakaś okrutnie wielka liczba bez przecinka, a do tego często masakrowało całą pamięć.

    4\/3!!


    O lol, znalazłem przyczynę "ERRORA". Tyle razy patrzyłem w tego makefile, ale za każdym razem tylko na opcje linkera, a tu inny zonk. :oops:

    Code:
          -D sprintf=usprintf \
    
          -D snprintf=usnprintf \
          -D printf=uipprintf \
  • #9
    User removed account
    User removed account  
  • #10
    Freddie Chopin
    MCUs specialist
    Przeczytałem taką samą podpowiedź (zakładając, że ty też mówisz o wyrównaniu stosu) na liście dyskusyjnej codesourcery, ale nie miałem jeszcze czasu na zagłębienie sprawy.

    ARMy liczą floaty (i double zresztą też, ale +/- 2-3x wolniej) całkiem szybko, więc czemuż by nie używać ... ? <:

    EDIT:
    Dobra - cofam wszystko co napisałem o -nostartfiles i --gc-sections - wyrównanie stosów do 8 faktycznie załatwiło sprawę!

    4\/3!!
  • #11
    aszewczyk
    Level 11  
    Wyjasnijcie to wyrownanie do 8(robie to na str912 ale to chyba zadna roznica jesli chodiz o ten blad to dotyczy on codesourcery a nie konkretnego proca)
    Moj skrypt linkera:
    Quote:
    /**
    * File: STR91x-ROM.ld
    *
    * Project: STR91x Eclipse demo
    *
    * Description: Linker script to load the application in flash.
    *
    * Created: 27/08/2008
    *
    * <dl>
    * <dt>Author:</dt>
    * <dd>Stefano Oliveri</dd>
    * <dt>E-mail:</dt>
    * <dd>software@stf12.net</dd>
    * </dl>
    */

    /* _HEAPSIZE = 8; */


    MEMORY
    {
    flash (rx) : ORIGIN = 0x00000000, LENGTH = 512K
    ram (rw) : ORIGIN = 0x04000000, LENGTH = 96K
    }


    SECTIONS
    {
    /* first section is .text which is used for code */

    .text :
    {
    KEEP(*(.vectors))
    KEEP(*(.init))
    *(.text .text.*)
    *(.gnu.linkonce.t.*)
    *(.glue_7t .glue_7)
    KEEP(*(.fini))
    *(.gcc_except_table)
    } >flash =0
    . = ALIGN(4);


    /* .rodata section which is used for read-only data (constants) */

    .rodata :
    {
    *(.rodata .rodata.*)
    *(.gnu.linkonce.r.*)
    } >flash
    . = ALIGN(4);

    _etext = .;
    PROVIDE (etext = .);

    /* .data section which is used for initialized data */

    .data : AT (_etext)
    {
    __data_start = .;
    *(.data .data.*)
    *(.gnu.linkonce.d.*)
    . = ALIGN(4);
    *(.fastrun .fastrun.*)
    } >ram
    . = ALIGN(4);

    _edata = .;
    PROVIDE (edata = .);

    /* .bss section which is used for uninitialized data */

    .bss :
    {
    __bss_start = .;
    __bss_start__ = .;
    *(.bss .bss.*)
    *(.gnu.linkonce.b.*)
    *(COMMON)
    . = ALIGN(4);
    __bss_end__ = .;
    } >ram
    . = ALIGN(4);
    /* __bss_end__ = .; */

    _end = .;
    PROVIDE(end = .);

    /*
    .heap (NOLOAD) :
    {
    __heap_start__ = .;
    _heap_start = .;
    *(.heap)
    . = MAX(__heap_start__ + _HEAPSIZE , .);
    } >ram
    __heap_end__ = __heap_start__ + SIZEOF(.heap);
    _heap_end = __heap_start__ + SIZEOF(.heap);

    */

    }
    . = ALIGN(32 / 8);
    _end = .;
    _bss_end__ = . ; /* __bss_end__ = . ; */ __end__ = . ;
    PROVIDE (end = .);




    Po zmianie flag linkera tak jak pisal freddie floaty dzialaja, ale chcialbym wiedziec co i dla czego robie.

    Edited:
    Ok. Czyli wywalenie pierwszej z flag powoduje dolaczenie standardowych plikow naglowkowych itp. A dodanie drugiej wywala to z czego nie korzystamy. To ma sens. Ale dalej prosze o info co i jak z tym wyrownaniem do 8.
  • #13
    gaskoin
    Level 38  
    aszewczyk wrote:
    Wyjasnijcie to wyrownanie do 8


    Chodzi o to, żeby rozmiar stosu był podzielny przez 8
  • #14
    michalko12
    MCUs specialist
    gaskoin wrote:
    aszewczyk wrote:
    Wyjasnijcie to wyrownanie do 8


    Chodzi o to, żeby rozmiar stosu był podzielny przez 8


    Nie rozmiar stosu tylko adres początku stosu.
  • #15
    aszewczyk
    Level 11  
    Hmmm. To ma byc adres ktorego ze stosow? I jezeli ten adres byl by zly to jak do tego ma sie kwestia flagi -nostartfiles?
    Quote:
    /**
    * File: startup.s
    *
    * Project: STR91x Eclipse demo
    *
    * Description: This module performs:
    * - Flash remapping.
    * - Stack pointer intialization for each mode.
    * - .bss section initialization.
    * - Branches to main.
    *
    *
    * Created: 27/08/2008
    *
    * <dl>
    * <dt>Author:</dt>
    * <dd>Stefano Oliveri</dd>
    * <dt>E-mail:</dt>
    * <dd>software@stf12.net</dd>
    * </dl>
    */

    .global _start

    /* set these dependent on memory sizes */

    .equ SRAM_96K, 1 /* 0 = 64k, 1 = 96k ram */
    .equ FLASH_512K, 1 /* 0 = 256k, 1 = 512k flash */
    .equ BUFFERED_MODE, 0 /* 0 = non-buffered, 1 = buffered */


    /* Stack Sizes */
    .set UND_STACK_SIZE, 0x00000020
    .set ABT_STACK_SIZE, 0x00000020
    .set FIQ_STACK_SIZE, 0x00000020
    .set IRQ_STACK_SIZE, 0X00001000
    .set SVC_STACK_SIZE, 0x00002000


    /* some definitions */

    .equ MODE_USR, 0x10
    .equ MODE_FIQ, 0x11
    .equ MODE_IRQ, 0x12
    .equ MODE_SVC, 0x13
    .equ MODE_ABT, 0x17
    .equ MODE_UND, 0x1B
    .equ MODE_SYS, 0x1F /* available on ARM Arch 4 and later */

    .equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */
    .equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */

    /* System configuration register 0 unbuffered */
    .equ SCU_SCRO, 0x5C002034

    /* FMI registers unbuffered */
    .equ FMI_BASE, 0x54000000
    .equ FMI_BBSR, 0x00
    .equ FMI_NBBSR, 0x04
    .equ FMI_BBADR, 0x0C
    .equ FMI_NBBADR, 0x10
    .equ FMI_CR, 0x18


    .equ SRAM_START, 0x4000000


    .if SRAM_96K
    .equ SRAM_SIZE, 0x10 /* 96k sram */
    .equ SRAM_END, 0x04018000 /* at the top of 96 KB SRAM */
    .else
    .equ SRAM_SIZE, 0x08 /* 64k sram */
    .equ SRAM_END, 0x04010000 /* at the top of 64 KB SRAM */
    .endif

    .if FLASH_512K
    .equ FLASH_SIZE, 0x04 /* 512k flash */
    .else
    .equ FLASH_SIZE, 0x03 /* 256k flash */
    .endif


    .text
    .arm
    .section .init, "ax"


    _start:
    ldr pc, =NextInst
    NextInst:

    nop /* Wait for OSC stabilization */
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop



    .if BUFFERED_MODE
    mrc p15, 0, r0, c1, c0, 0 /* Read CP15 register 1 into r0 */
    orr r0, r0, #0x8 /* Enable Write Buffer on AHB */
    mcr p15, 0, r0, c1, c0, 0 /* Write CP15 register 1 */
    .endif



    /* Remap Flash Bank 0 at address 0x0 and Bank 1 at address 0x80000, */
    /* when the bank 0 is the boot bank, then enable the Bank 1. */

    ldr r6, = FMI_BASE
    ldr r7, = FLASH_SIZE /* configure 256k/512k Boot bank 0 */
    str r7, [r6, #FMI_BBSR]

    ldr r7, = 0x2 /* configure 32KB Non Boot bank 1 */
    str r7, [r6, #FMI_NBBSR]

    ldr r7, = 0x0 /* Boot Bank Base Address */
    str r7, [r6, #FMI_BBADR]

    ldr r7, = 0x20000 /* Non Boot Bank Base Address */
    str r7, [r6, #FMI_NBBADR] /* Need to put 0x20000 because
    FMI bus on A[25:2] CPU bus*/

    ldr r7, = 0x18 /* Flash Banks 0 1 enabled */
    str r7, [r6, #FMI_CR]


    /* Enable RAM */

    ldr r0, = SCU_SCRO
    ldr r1, = 0x0187 | SRAM_SIZE
    str r1, [r0]


    /* Set bits 17-18 (Instruction/Data TCM order) of the */
    /* Core Configuration Control Register */

    mov r0, #0x60000
    mcr p15, 0x1, r0, c15, c1, 0


    /* setup stacks */

    ldr r0, = SRAM_END
    msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */
    mov sp, r0
    sub r0, r0, #UND_STACK_SIZE
    msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */
    mov sp, r0
    sub r0, r0, #ABT_STACK_SIZE
    msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */
    mov sp, r0
    sub r0, r0, #FIQ_STACK_SIZE
    msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */
    mov sp, r0
    sub r0, r0, #IRQ_STACK_SIZE
    msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */
    mov sp, r0
    sub r0, r0, #SVC_STACK_SIZE
    msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* System Mode */
    mov sp, r0


    /* switch to supervisor mode*/
    msr CPSR_c, #MODE_SVC|I_BIT|F_BIT


    /* Clear uninitialized data section (bss) */
    ldr r4, =__bss_start__ /* First address*/
    ldr r5, =__bss_end__ /* Last address*/
    mov r6, #0x0

    loop_zero:
    str r6, [r4]
    add r4, r4, #0x4
    cmp r4, r5
    blt loop_zero

    /* copy initialised data */
    ldr r4, = _etext /* First address from*/
    ldr r5, = __data_start /* First address to*/
    ldr r7, = _edata /* end of copy */

    cmp r5, r7
    beq skip_initialise

    loop_initialise:
    ldr r6, [r4]
    str r6, [r5]
    add r4, r4, #0x4
    add r5, r5, #0x4
    cmp r5, r7
    blt loop_initialise

    skip_initialise:



    /* --- Now enter the C code */
    B main /* Note : use B not BL, because an application will */
    /* never return this way */



    .end
  • #16
    Freddie Chopin
    MCUs specialist
    aszewczyk wrote:
    To ma byc adres ktorego ze stosow?

    Każdego.

    Quote:
    I jezeli ten adres byl by zly to jak do tego ma sie kwestia flagi -nostartfiles?

    Przecież napisałem, że wycofuję się z tych flag, bo ich użycie PRZYPADKOWO i CZASEM "rozwiązuje" ten problem, ale to po prostu przypadek...

    Na początku upewnij się, że początkowy adres od którego zaczynasz odejmowanie jest podzielny przez 8 (3 ostatnie bity równe 0), potem każdą wartość którą odejmujesz musisz również mieć podzielną przez 8. Wydaje mi się, że to masz spełnione.

    Wczoraj jednak usłyszałem od pewnej doświadczonej osoby, że bardziej zabugowanych ARMów od STR7xx i STR9xx nie ma, więc może tutaj jest Twój problem?

    4\/3!!
  • #17
    aszewczyk
    Level 11  
    No niestety. Str912 jest straszny to mu trzeba przyznac(choc to nie oznacza ze nie dziala z jakis magicznych powodow, poprostu miewam z nim wszystkie ,mozliwe problemy, ale jak na razie dalo sie dojsc co jest ich przycyzna. Najsmieszniejsyz byl timer ktorego wlasciwie nie da sie uzyc poza paroma konkretnymi przypadkami:P). Faktycznie wszystkie rozmiary stosow sa podzielne przez 8 a adres bazowy konczy sie trzem zerami czyli tez. Zatem zaufam magicznemu rozwiazaniu z flagami i wracam do pisania kodu.
  • #19
    aszewczyk
    Level 11  
    Znowu nie dziala:P Widzialem myk ze ktos wszystkie sekcje alignowal do 8 ale to chyba tez nie zalatwia sprawy na zawsze a tylko jesli zastosuje sie tego floata jako zmienna globalna.
  • #20
    aszewczyk
    Level 11  
    W rtosie(ponoc dla cortexow cos tam zmienili powyzej 6.0 , ale nie moge sie doczytac co piwinienem zmienic zeby moj port pod str912 to obslogiwal) trzeba jeszcze cos zmieniac w inicjalizacji stosow dla taskow zeby floaty dzialaly?