This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Hardware Implementation

hi i created a hardware that calculates the square root of (a^2+b^2 )

i sent the inputs (a and b) with assembly and that was fine however when i tried to send them using c code the hardware take them as inputs calculates a^2 + b^2 but never do the square root

i am really clueless here i couldn't locate the problem

heeeeeeeeeeeeeeelp

  • Could you provide the assembly listing that works, the C code that doesn't and a disassembly (objdump -d executable on Unix/Linux systems) of the non-working C code for analysis ?

  • my assembly code 

    PRESERVE8
                   THUMB
           AREA RESET, DATA, READONLY   ; First 32 WORDS is VECTOR TABLE
           EXPORT __Vectors
    __Vectors     DCD 0x000003FC
           DCD Reset_Handler
           DCD
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
          
           ; External Interrupts
           
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0
           DCD 0

                 

                    AREA |.text|, CODE, READONLY

    ;Reset Handler

    Reset_Handler   PROC

                    GLOBAL Reset_Handler

        

    ENTRY
    AGAIN   LDR R1, =0x59000000
    LDR R0, =0x00000022
    STR R0, [R1]
    LDR R1, =0x59000000
    LDR R0, =0x00002200
    STR R0, [R1]
    B AGAIN
    ENDP

                  

    ALIGN 4 ;; Align to a word boundary
    END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

      

    my c code

     unsigned int xd[10];
    
     unsigned int yd[10];
    
     volatile unsigned int regdistance __attribute__((at(0x59000000)));
    
    int main() {
    
    int i;
    
    for( i=0;i<10;i++){
    
     xd[0]=0;
    
     yd[0]=0;
    
    xd[i+1]= xd[i]+1;
    
    yd[i+1]= yd[i]+1;
    
    regdistance = xd[i];
    
    regdistance = yd[i];
    
    while(1);
    
    }

    code.hex

    0000FFFC
    
    00000169
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    00000000
    
    F802F000
    
    F832F000
    
    C830A00C
    
    18243808
    
    46A2182D
    
    46AB1E67
    
    465D4654
    
    D10142AC
    
    F824F000
    
    3E0F467E
    
    46B6CC0F
    
    42332601
    
    1AFBD000
    
    46AB46A2
    
    47184333
    
    00000138
    
    00000148
    
    24002300
    
    26002500
    
    D3013A10
    
    D8FBC178
    
    D3000752
    
    D500C130
    
    4770600B
    
    46C0B51F
    
    BD1F46C0
    
    BD10B510
    
    F851F000
    
    F7FF4611
    
    F000FFF5
    
    F000F809
    
    B403F869
    
    FFF2F7FF
    
    F000BC03
    
    0000F86D
    
    E0202100
    
    4A122000
    
    4A126010
    
    00886010
    
    58104A0F
    
    1C4A1C40
    
    4B0D0092
    
    00885098
    
    58104A0C
    
    1C4A1C40
    
    4B0A0092
    
    00885098
    
    58104A07
    
    60104A08
    
    461A0088
    
    4A065810
    
    BF006010
    
    290AE7FE
    
    2000DBDC
    
    00004770
    
    00000204
    
    0000022C
    
    59000000
    
    47004803
    
    49044803
    
    4B054A04
    
    00004770
    
    00000081
    
    000002C0
    
    00000AC0
    
    000006C0
    
    000006C0
    
    47704770
    
    46754770
    
    F822F000
    
    000546AE
    
    46534669
    
    00C008C0
    
    B0184685
    
    F7FFB520
    
    BC60FFDF
    
    08492700
    
    260046B6
    
    C5C0C5C0
    
    C5C0C5C0
    
    C5C0C5C0
    
    C5C0C5C0
    
    00493D40
    
    4770468D
    
    46C04604
    
    462046C0
    
    FF91F7FF
    
    47704800
    
    00000254
    
    20184901
    
    E7FEBEAB
    
    00020026
    
    00004770
    
    00000204
    
    00000204
    
    000008BC
    
    000000C4

  • Assuming regdistance is an address of your hardware peripheral, then it needs to be a pointer, not an integer, and you need to write to the value pointed at by the pointer, rather than just setting the address locally. Eg. something like:

    volatile unsigned int * regdistance __attribute__((at(0x59000000)));
    int main() { 
        int i;
        for( i=0;i<10;i++) {
            xd[0]=0;
            yd[0]=0;
            xd[i+1]= xd[i]+1;
            yd[i+1]= yd[i]+1;
    
            *regdistance = xd[i];
            *regdistance = yd[i];
        }
        while(1);
    }
    

    P.S. It looks like you will overflow your loop (I had to guess a bit what the expected indentation for the for loop was). E.g. your access xd[i+1] will access xd[10]which is element 11 in the array, but they are only allocated as 10 elements long.

    HTH,
    Pete

  • >

    http://www.keil.com/support/docs/2829.htm

    With the Keil CARM C Compiler, you may use either pointer definitions (as

    shown above) or at keyword to define a variable at a fixed memory

    address. As with the RealView C Compiler, the following definition also

    makes a correct memory reservation, so that the area cannot be used twice.

    i tried to send these inputs with a pointer but in vain however when i used

    this form at least the hardware took them as inputs however now even

    a2+b2 don't calculate it !!!

    2016-06-02 11:07 GMT+01:00 peterharris <community@arm.com>:

    Hardware Implementation

    reply from Peter Harris

    <https://community.arm.com/people/peterharris?et=watches.email.thread> in

  • So, if I understand correctly :

    AGAIN  
           LDR R1, =0x59000000
           LDR R0, =0x00000022
           STR R0, [R1]
           LDR R1, =0x59000000
           LDR R0, =0x00002200
           STR R0, [R1]
           B AGAIN
    ENDP
    

    0x59000000 is the address where the input should be sent. I'll call it input_address here.

    Then the first input value (a in your algebraic formulae) is retrieved from address 0x22 and stored at input_address.

    Same thing for second input value (b), which address seems to be 0x2200.

    Then, I guess, once two values provided the hardware do the whole calculation automatically ?

    In that case, do this code work in your case :

    test.c

    int calculate(int a, int b) {
    volatile int *input_address = (int*)0x59000000;
      while(1) {
        *input_address = a;
        *input_address = b;
      }
    }
    

    Compiling it with gcc like this :

    armv7a-hardfloat-linux-gnueabi-gcc -O3 -nostdlib -shared -o test.o test.c

    Generates this machine code :

    armv7a-hardfloat-linux-gnueabi-objdump -d test.o

    00000218 <calculate>:
     218:   e3a03459        mov     r3, #1493172224 ; 0x59000000
     21c:   e5830000        str     r0, [r3]
     220:   e5831000        str     r1, [r3]
     224:   eafffffc        b       21c <calculate+0x4>
    

    Which is roughly the same.

    In any case, in your provided code, did you try this instead :

    int main() {
    the_old_days:
      
      xd[0]=0;
      yd[0]=0;
      int i;
      for(i=0;i<9;i++){ /* with i < 10, when i = 9, xd[i+1] will be equal to xd[10] which is out of bounds */
        xd[i+1]= xd[i]+1;
        yd[i+1]= yd[i]+1;
        regdistance = xd[i];  
        regdistance = yd[i];  
      }
    
      goto the_old_days;
    }
    
  • as i told M

    Peter Harris

    I don't why my keil can't allocate a memory address with a pointer however i think that the problem is within the def of the "attribute" which allocate a fixed address that can't be reused by another

    i tried to differentiate the output of yd and xd and  when i compiled my code i observed that regdistance take only the value of xd so i defined another address memory to put the yd and when i simulate my hardware behavior i found that now it calculates the a^2+b^2   but not the square root

    if anyone has a suggestion or any idea how can i resolve this prob please help

  • Well, can you use objdump -d on the bugged binary file and paste the output here.

    I do not think that the variable definition is the problem here. However, one way to be sure is to try defining regdistance within main like this :

    volatile int *regdistance = (int*)0x59000000;

    And see if it works.

    Note that you might want to replace

    for (i = 0; i < 10; i++)
    

    by

    for (i = 0; i < 9; i++)
    

    else you will write into places you did not define (xd[9+1] is not defined).

    However, the "at" behaviour can also be emulated doing something like :

    test.c

    volatile int input_address __attribute__ ((section ("regdistance")));
    
    int calculate(int a, int b) {
      while(1) {
        input_address = a;
        input_address = b;
      }
    }
    

    Using a linker script like this :

    test.ld

    ENTRY(calculate)

    SECTIONS

    {

      . = 0x10000;

      .text : { *(.text*) }

      . = 0x59000000;

      .regdistance : { *(regdistance*) }

    }

    And then compile like this :

    armv7a-hardfloat-linux-gnueabi-gcc -O3 -nostdlib -mthumb -T test.ld -o test test.c

    Code produced :

    LANG=C armv7a-hardfloat-linux-gnueabi-objdump -d test

    test:    file format elf32-littlearm

    Disassembly of section .text:

    00010000 <calculate>:
      10000:      f240 0300      movw    r3, #0
      10004:      f6c5 1300      movt    r3, #22784      ; 0x5900
      10008:      6018            str    r0, [r3, #0]
      1000a:      6019            str    r1, [r3, #0]
      1000c:      e7fc            b.n    10008 <calculate+0x8>
      1000e:      bf00            nop