Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 01:41 14 Apr 2021 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : CMM2: V5.05.04b3a: CSUBs - not for the faint hearted!!!!

     Page 5 of 5    
Author Message
epsilon

Senior Member

Joined: 30/07/2020
Location: Belgium
Posts: 170
Posted: 10:25am 11 Mar 2021
Copy link to clipboard 
Print this post

  thwill said  
Good idea ... however it appears the problem isn't calling the function pointer, it's assigning it to fptr - WTF!


#include "ARMCFunctions.h"

void p_int(int a,int base){
 char b[64];
 IntToStr(b,a,base);
 MMPrintString(b);
}

void foo(void) {
putConsole('*'); putConsole('\r'); putConsole('\n');  
}

void main(long long int *c, MMFLOAT *b){
putConsole('a'); putConsole('\r'); putConsole('\n');
foo();
putConsole('b'); putConsole('\r'); putConsole('\n');
void (*fptr)(void);
putConsole('c'); putConsole('\r'); putConsole('\n');
fptr = &foo; // <--- hangs here, how is that even possible?
fptr(); //<-- EDIT: Added this to shut up the compiler
putConsole('d'); putConsole('\r'); putConsole('\n');
}




I tried this example and it worked just fine for me. The program produces:

*tomsTest.bas
a
*
b
c
*
d

I added a statement to actually call the fptr because the compiler gave me a warning that fptr was set but not used.

This is the build script I'm using:

@ECHO OFF

arm-none-eabi-gcc -c -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -Wall -Wno-main -ffunction-sections -O2 -fPIC -I. %1.c -o %1.o
IF ERRORLEVEL 1 Goto Done

arm-none-eabi-ld -nostartfiles -T arm-gcc-link.ld -o %1.elf %1.o
IF ERRORLEVEL 1 Goto Done

C:\cmm2\DOS_MMBasic\MMBasic ArmCfGenV143.bas %1.elf %2
Notepad %1.bas

:Done
Epsilon CMM2 projects
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 1312
Posted: 10:45am 11 Mar 2021
Copy link to clipboard 
Print this post

  matherp said  
  Quote  I'm no C programmer


Given your contribution above many of us might disagree  

Many thanks for finding and posting this mechanism


I agree, but I'm holding off having a proper look until I get to the bottom of why my original example worked for @epsilon, but not for me.

Tom
CMM2 Welcome Tape, Z-MIM: Zork on the CMM2
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 1312
Posted: 10:56am 11 Mar 2021
Copy link to clipboard 
Print this post

  epsilon said  I tried this example and it worked just fine for me ...


Thanks @epsilon,

That is peculiar as I believe I am using the same settings. I'll have to take another look tomorrow - it would certainly pour cold-water on my GOT theory.

I assume you used "merge" strategy to create the CSB and there was no funny-business in how you are calling the CSUB ... perhaps you could attach your calling code too so that I can repeat what you did exactly.

Best wishes,

Tom
CMM2 Welcome Tape, Z-MIM: Zork on the CMM2
 
epsilon

Senior Member

Joined: 30/07/2020
Location: Belgium
Posts: 170
Posted: 10:58am 11 Mar 2021
Copy link to clipboard 
Print this post

  thwill said   I agree, but I'm holding off having a proper look until I get to the bottom of why my original example worked for @epsilon, but not for me.


It's because in my case the compiler optimized away the fptr assignment and replaced it with a direct call to foo.
If I push it a little harder by making fptr volatile, I see the same problem. The program hangs after printing 'c':
a
*
b
c
<--- hangs here.


void main(long long int *c, MMFLOAT *b){
putConsole('a'); putConsole('\r'); putConsole('\n');
foo();
putConsole('b'); putConsole('\r'); putConsole('\n');
void (* volatile fptr)(void);
putConsole('c'); putConsole('\r'); putConsole('\n');
fptr = (void (* volatile)(void)) &foo; // <--- hangs here, how is that even possible?
fptr();
putConsole('d'); putConsole('\r'); putConsole('\n');
}

Epsilon CMM2 projects
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 1312
Posted: 11:06am 11 Mar 2021
Copy link to clipboard 
Print this post

  epsilon said  It's because in my case the compiler optimized away the fptr assignment and replaced it with a direct call to foo.


Ha, yes, because you put the actual call through the pointer into the code so as to suppress the compiler warning - glad I didn't do that or it would have frustrated the hell out of me when it worked for a small example but didn't work for the larger (Forth) example.

Back to my theory regarding the GOT then, which I still think holds water. @GerryL's "trick" works by bypassing the GOT, basically you would have to call every function in advance to get the function address and use those to build your own "GOT".

Best wishes,

Tom
Edited 2021-03-11 21:07 by thwill
CMM2 Welcome Tape, Z-MIM: Zork on the CMM2
 
epsilon

Senior Member

Joined: 30/07/2020
Location: Belgium
Posts: 170
Posted: 11:22am 11 Mar 2021
Copy link to clipboard 
Print this post

Interestingly, just declaring foo() static also seems to work:


static void foo(void) {
putConsole('*'); putConsole('\r'); putConsole('\n');  
}


For a static call, the compiler generates position independent code rather than going through a GOT:


80000ba:       4b0b            ldr     r3, [pc, #44]   ; (80000e8 <main+0x84>)
80000bc:       447b            add     r3, pc       <-- foo converted here from relative to absolute
80000be:       60fb            str     r3, [r7, #12]
80000c0:       68fb            ldr     r3, [r7, #12]
80000c2:       4798            blx     r3
80000c4:       4b07            ldr     r3, [pc, #28]   ; (80000e4 <main+0x80>)
80000c6:       681b            ldr     r3, [r3, #0]
80000c8:       2064            movs    r0, #100        ; 0x64
80000ca:       4798            blx     r3
80000cc:       4b05            ldr     r3, [pc, #20]   ; (80000e4 <main+0x80>)
80000ce:       681b            ldr     r3, [r3, #0]
80000d0:       200d            movs    r0, #13
80000d2:       4798            blx     r3
80000d4:       4b03            ldr     r3, [pc, #12]   ; (80000e4 <main+0x80>)
80000d6:       681b            ldr     r3, [r3, #0]
80000d8:       200a            movs    r0, #10
80000da:       4798            blx     r3
80000dc:       bf00            nop
80000de:       3710            adds    r7, #16
80000e0:       46bd            mov     sp, r7
80000e2:       bd80            pop     {r7, pc}
80000e4:       080002a4        .word   0x080002a4
80000e8:       ffffff81        .word   0xffffff81  <-- offset to 'foo'

Epsilon CMM2 projects
 
GerryL
Newbie

Joined: 24/01/2019
Location: Australia
Posts: 16
Posted: 01:13am 22 Mar 2021
Copy link to clipboard 
Print this post

Just a FYI in case you also see this when building CMM2 CSUBS,

Whilst writing a large CSUB for the CMM2 I noticed a minor issue with armcfgenV143.bas, which I assume is due to the fact that 16 bit and 32 bit instructions can be generated by the compiler. As armcfgenV143 reads the '.text' section of the ELF file in 32 bit chunks its possible, in the case where a function does not finish on a 32 bit boundary due to an uneven number of 16 bit instructions, that the start of the next function is missed in armcfgenV143.  In the case of a MERGE all the code is there so it runs OK but you wont see in the generated CSUB text the commented name of the function directly after this missed 32 bit boundary function  and the missing function code gets appended to this previous function that didn't finish on the 32 bit boundary. All not an issue as its all relative branches.  In the case of a JOIN where you have multiple functions in the source a missing function could  be a problem, but a quick fix would be to go to the function directly before the missing function (i.e. the one with the uneven 16 bit instructions) and add asm("nop"); to even up the 16 bit instructions or you could just ensure your source only has a single function. In my experience its not often you end up with an uneven number of 16 bit instructions and if using MERGE of no consequence to it running.

Gerry
 
epsilon

Senior Member

Joined: 30/07/2020
Location: Belgium
Posts: 170
Posted: 08:15am 22 Mar 2021
Copy link to clipboard 
Print this post

  GerryL said   In the case of a JOIN where you have multiple functions in the source a missing function could  be a problem


Isn't JOIN the option you're supposed to use when you have just one function? What exactly happens if you run armcfgen with join on a file with multiple functions? Which function gets called when you invoked the CSUB?
Epsilon CMM2 projects
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 1312
Posted: 10:51am 22 Mar 2021
Copy link to clipboard 
Print this post

  epsilon said  
  GerryL said   In the case of a JOIN where you have multiple functions in the source a missing function could  be a problem


Isn't JOIN the option you're supposed to use when you have just one function? What exactly happens if you run armcfgen with join on a file with multiple functions? Which function gets called when you invoked the CSUB?


Unless my short-term memory is malfunctioning:

MERGE combines everything into a single CSUB with main() as its entry point.

JOIN keeps the functions separate ... and is strangely named.

Best wishes,

Tom
CMM2 Welcome Tape, Z-MIM: Zork on the CMM2
 
epsilon

Senior Member

Joined: 30/07/2020
Location: Belgium
Posts: 170
Posted: 01:12pm 22 Mar 2021
Copy link to clipboard 
Print this post

OK. Got it. If a C file has multiple functions, join will generate multiple CSUBs, one for each function, and in that case you might get bitten by the bug that Gerry found.

Good find, Gerry! I'm glad I didn't have to debug my way through that one.
Epsilon CMM2 projects
 
     Page 5 of 5    
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2021