How to see a function in a .S file

Go To Last Post
39 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi guys, I need to call a function from within a .S file.  How then do I see the function in the S file to call it?  Is there a way to declare the function within the file?

Last Edited: Thu. Aug 30, 2018 - 05:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

Look at the assembler the compiler generates for your code. Pick up on the tips and tricks it uses and apply it to your asm code.
There’s also a lot of examples on the interwebs. I also expect you are using gcc - it helps if you specify this.

I just did a quick google - Google gcc arm asm
Got this -
https://www.cse.unsw.edu.au/~cs3221/labs/assembler-intro.pdf

The moral of the story - Google first then ask question on a forum.

Last Edited: Tue. Aug 28, 2018 - 09:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

.global in the .S file, extern in the .C file

 

http://ww1.microchip.com/downloa...

Last Edited: Tue. Aug 28, 2018 - 09:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are also going to need to know the compiler' s ABI unless it's void/void

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys, just got around to testing this.  I've tried numerous things but I get the error, "undefined reference to `xapi_system_gateway'".

 

I've added the following to the code in the .S file:

 

.extern xapi_system_gateway

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:
.global in the .S file, extern in the .C file

Fianawarrior wrote:
I've added the following to the code in the .S file: .extern xapi_system_gateway

 

Shouldn't that be .global instead of .extern....????

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Still getting the error when I tried .gloabl

 

Do I need to do anything in the .h file it is in?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Fianawarrior wrote:
How then do I see the function in the S file to call it?

Fianawarrior wrote:
Still getting the error when I tried .gloabl
Calling from where? C++ perhaps?

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"calling from a .h file, using a gcc c compiler"

 

sorry, let make this clearer.  the function is in a .h file and I'm trying to call it from a .s file....

 

EDITED:

 

Tried the following with no joy

	.extern xapi_system_gateway;
	.type xapi_system_gateway, "function";

Just to add in case it throws any light on the matter, the ereror occurs after LINKING or during LINK

 

LINK build/sama5d4-xplained/ddram/target/bootstrap.elf
./build/sama5d4-xplained/ddram/target/sama5d4/toolchain/gnu/cstartup.o: In function `fiqHandler':
F:\atmel-software-package-master\examples\getting_started/../../target/sama5d4/toolchain/gnu/cstartup.S:125: undefined reference to `xapi_system_gateway'
./build/sama5d4-xplained/ddram/target/sama5d4/toolchain/gnu/cstartup.o: In function `irqHandler':
F:\atmel-software-package-master\examples\getting_started/../../target/sama5d4/toolchain/gnu/cstartup.S:177: undefined reference to `xapi_system_gateway'
collect2.exe: error: ld returned 1 exit status
make: *** [../../scripts/Makefile.rules:73: build/sama5d4-xplained/ddram/target/bootstrap.elf] Error 1

 

Last Edited: Wed. Aug 29, 2018 - 06:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Show a minimal compilable example. So far what you are describing (function in .h) makes absolutely no sense.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

the .s file is thus:

 


	.extern xapi_system_gateway;
	.type xapi_system_gateway, "function";

	.section    .text
//------------------------------------------------------------------------------
/// Handles a fast interrupt request by branching to the address defined in the
/// AIC.
//------------------------------------------------------------------------------

fiqHandler:

	sub     lr, lr, #4
	stmfd   sp!, {lr}
	//mrs     lr, SPSR
	stmfd   sp!, {r0}

	/* Write in the IVR to support Protect Mode */

	ldr     lr, =SAIC
	ldr     r0, [r14, #AIC_IVR]
	str     lr, [r14, #AIC_IVR]
	/* Dummy read to force AIC_IVR write completion */
	ldr     lr, [r14, #AIC_SMR]

	/* Branch to interrupt handler in Supervisor mode */

	msr     CPSR_c, #ARM_MODE_SVC
	stmfd   sp!, {r1-r3, r4, r12, lr}

	blx      r0

	ldmia   sp!, {r1-r3, r4, r12, lr}
	msr     CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT

	/* Acknowledge interrupt */

	ldr     lr, =SAIC
	str     lr, [r14, #AIC_EOICR]

	//bl 		xapi_system_gateway

	/* Restore interrupt context and branch back to calling code */


	ldmia   sp!, {r0}
	//msr     SPSR_cxsf, lr
	ldmia   sp!, {pc}^

and the called function is thus:

// Enter Application api_program Interface Mode
void xapi_system_gateway(void){


	if((deferral_service__controller.nr_active != 0) || (kernel_core.round_robin_trigger)){

		if((core_executing_task->application_mode == false) &&
		    (core_executing_task->interrupt_mode   == 0)){

			core_executing_task->application_mode = true;
			cleanup_interrupts(0);
		}
	}
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The error is coming from the linker, not the compiler or the assembler.

 

.extern is unnecessary, but harmless.

.type should be in the .s file emitted by the C compiler.

If you are using C++, you probably have a name-mangling issue.

My guess is that you are not linking the object file with xapi_system_gateway.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your makefile probably only compiles .c files, so your function in the .h doesn’t get compiled and therefore the linker barfs.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi steeve, I'm using gcc C compiler

I think that you bhoys are right.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's why I said:

clawson wrote:
what you are describing (function in .h) makes absolutely no sense

and in what you posted in #11 does not help much. You show the xapi_system_gateway() function but do not show enough context to show how it is instantiated. If you get link errors then it is NOT being instantiated. Here is a very simple example (AVR8 because that's what I have) that shows calling both ways between C and Asm in .S:

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>type avr.c
#include <avr/io.h>

void foo(uint8_t n);

uint8_t bar(uint8_t n) {
    return n + 1;
}

int main(void) {
    while(1) {
        foo(0xAA);
    }
}
D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>type asm.S
#define __SFR_OFFSET 0
#include <avr/io.h>

    .global foo
    .extern bar

    ; void foo(uint8_t n)
foo:
    rcall bar
    out PORTB, r24
    ret
D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>avr-gcc -mmcu=atmega16 avr.c asm.S -Os -g -o avr.elf

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>avr-objdump.exe -S avr.elf

avr.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
   0:   0c 94 2a 00     jmp     0x54    ; 0x54 <__ctors_end>
   4:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
   8:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
   c:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  10:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  14:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  18:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  1c:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  20:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  24:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  28:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  2c:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  30:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  34:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  38:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  3c:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  40:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  44:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  48:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  4c:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>
  50:   0c 94 34 00     jmp     0x68    ; 0x68 <__bad_interrupt>

00000054 <__ctors_end>:
  54:   11 24           eor     r1, r1
  56:   1f be           out     0x3f, r1        ; 63
  58:   cf e5           ldi     r28, 0x5F       ; 95
  5a:   d4 e0           ldi     r29, 0x04       ; 4
  5c:   de bf           out     0x3e, r29       ; 62
  5e:   cd bf           out     0x3d, r28       ; 61
  60:   0e 94 3b 00     call    0x76    ; 0x76 <main>
  64:   0c 94 3f 00     jmp     0x7e    ; 0x7e <_exit>

00000068 <__bad_interrupt>:
  68:   0c 94 00 00     jmp     0       ; 0x0 <__vectors>

0000006c <bar>:

void foo(uint8_t n);

uint8_t bar(uint8_t n) {
    return n + 1;
}
  6c:   8f 5f           subi    r24, 0xFF       ; 255
  6e:   08 95           ret

00000070 <foo>:
    .global foo
    .extern bar

    ; void foo(uint8_t n)
foo:
    rcall bar
  70:   fd df           rcall   .-6             ; 0x6c <bar>
    out PORTB, r24
  72:   88 bb           out     0x18, r24       ; 24
  74:   08 95           ret

00000076 <main>:

int main(void) {
    while(1) {
        foo(0xAA);
  76:   8a ea           ldi     r24, 0xAA       ; 170
  78:   0e 94 38 00     call    0x70    ; 0x70 <foo>
  7c:   fc cf           rjmp    .-8             ; 0x76 <main>

0000007e <_exit>:
  7e:   f8 94           cli

00000080 <__stop_program>:
  80:   ff cf           rjmp    .-2             ; 0x80 <__stop_program>

D:\atmel_avr\avr8-gnu-toolchain-win32_x86\bin>

foo() is an asm function called from the C in avr.c, bar() is a C function called from the asm in asm.S

 

The code is written safe in the knowledge (for the 8bit avr-gcc) that the ABI states that (8 bit) input parameters to functions will be passed in R24.

 

As Skeeve says the .extern in the Asm is not entirely necessary. The assembler assumes anything unresolved is extern anyway. But it's usefully documentary to the reader to say "that function is not located here, so look elsewhere". The .global is necessary - it says "this function, foo, should be visible to those from outside that come looking".

 

Just follow this template for your own code.

 

(and don't plan to ever instantiate anything from a .h file!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have you looked at the other current thread on calling assembler from 'C' ?

 

https://www.avrfreaks.net/forum/assmber-code-c-project

 

In particular, there's an App Note: https://www.avrfreaks.net/commen...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi freaks,

 

The error is being generated during linking of the project, "LINK build/sama5d4-xplained/ddram/getting-started.elf"

 

Still no closer to solving this, the bare metal examples don't have a linker script just a load of makefiles.

 

Last Edited: Thu. Aug 30, 2018 - 04:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Fianawarrior wrote:
Still no closer to solving this

So why have you marked #3 as The Solution?!

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Aug 30, 2018 - 05:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well we've told you why and how to avoid it. Which bit of that are you not understanding?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kk6gm wrote:

.global in the .S file, extern in the .C file

 

http://ww1.microchip.com/downloa...

.C , unlike .c , might be taken as C++ .

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson, I've split the function that is called into it's .c and .h format.  I have followed the use of .extern and .global and yet it still does not link the file.

 

Everything is perfect, I just need a solution because which like a lot of programming throws these spin balls, i.e errors.  Oh, and I unmark the solution.  The solution given is correct but the bare metal frame work is I quess where the problem lies.  And the frame work was provided by Microchip.  So the ball is in there court.  This ain't rocket science.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Fianawarrior wrote:
Everything is perfect

Clearly not!

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

lol, awneil.

Anyways, I've found something to do with the LINKER in a makefile.RULES

 

include $(TOP)/samba_applets/common/Makefile.inc
include $(TOP)/flash_loaders/applets/common/Makefile.inc
include $(TOP)/scripts/Makefile.config
include $(TOP)/arch/Makefile.inc
include $(TOP)/utils/Makefile.inc
include $(TOP)/target/Makefile.inc
include $(TOP)/drivers/Makefile.inc
include $(TOP)/lib/Makefile.inc

vpath %.c $(TOP)
vpath %.S $(TOP)

OBJS := $(addprefix $(BUILDDIR)/,$(gnu-cstartup-y) $(obj-y))
LIBS := $(addprefix $(BUILDDIR)/,$(lib-y))

-include $(OBJS:.o=.d)

.PHONY: all build clean size debug

all:: build

build: $(BUILDDIR)/$(BINNAME).elf \
	$(BUILDDIR)/$(BINNAME).symbols \
	$(BUILDDIR)/$(BINNAME).bin

ifeq ($(VARIANT),ddram)
CONFIG_BOOTSTRAP ?= y
ifeq ($(CONFIG_BOOTSTRAP),y)
$(BUILDDIR)/$(BINNAME).elf: $(BUILDDIR)/target/bootstrap.elf

$(BUILDDIR)/target/bootstrap.elf: $(BOOTSTRAP_OBJS) $(LIBS)
	@mkdir -p $(dir $@)
	$(ECHO) LINK $@
	$(Q)$(CC) $(LDFLAGS) $(CFLAGS_CPU) $(CFLAGS_DEFS) -T$(bootstrap-linker-script-y) -Wl,-Map,$(BUILDDIR)/bootstrap.map -o $@ $(BOOTSTRAP_OBJS) -Wl,--start-group $(LIBS) -Wl,--end-group
endif
endif

$(BUILDDIR):
	@mkdir -p $(BUILDDIR)

$(BUILDDIR)/%.d: %.c
	@mkdir -p $(dir $@)
	$(ECHO) DEP $<
	$(Q)$(CC) $(CFLAGS) $(CFLAGS_CPU) $(CFLAGS_INC) $(CFLAGS_DEFS) -MM $< -MT $(basename $@).o -o $(basename $@).d

$(BUILDDIR)/%.o: %.c
	@mkdir -p $(dir $@)
	$(ECHO) CC $<
	$(Q)$(CC) $(CFLAGS) $(CFLAGS_CPU) $(CFLAGS_INC) $(CFLAGS_DEFS) -c $< -o $@

$(BUILDDIR)/%.d: %.S
	@mkdir -p $(dir $@)
	$(ECHO) DEP $<
	$(Q)$(CC) $(CFLAGS_ASM) $(CFLAGS_CPU) $(CFLAGS_INC) $(CFLAGS_DEFS) -MM $< -MT $(basename $@).o -o $(basename $@).d

$(BUILDDIR)/%.o: %.S
	@mkdir -p $(dir $@)
	$(ECHO) CC $<
	$(Q)$(CC) $(CFLAGS_ASM) $(CFLAGS_CPU) $(CFLAGS_INC) $(CFLAGS_DEFS) -c $< -o $@

$(BUILDDIR)/$(BINNAME).elf: $(OBJS) $(LIBS) $(gnu-debug-lib-y) $(gnu-linker-script-y)
	@cp $(gnu-debug-lib-y) $(BUILDDIR)/target/
	$(ECHO) LINK $@
	$(Q)$(CC) $(LDFLAGS) $(CFLAGS_CPU) $(CFLAGS_DEFS) -T$(gnu-linker-script-y) -Wl,-Map,$(BUILDDIR)/$(BINNAME).map -o $@ $(OBJS) -Wl,--start-group $(LIBS) -Wl,--end-group -Wl,--no-undefined

$(BUILDDIR)/$(BINNAME).symbols: $(BUILDDIR)/$(BINNAME).elf
	$(Q)$(NM) $< >$@

$(BUILDDIR)/$(BINNAME).bin: $(BUILDDIR)/$(BINNAME).elf
	$(ECHO) OBJCOPY $@
	$(Q)$(OBJCOPY) -O binary $< $@

clean:
	@rm -rf $(BUILDDIR) settings
	@rm -f $(BINNAME)_$(TARGET).eww $(BINNAME)_$(TARGET).ewp $(BINNAME)_$(TARGET).ewd $(BINNAME)_$(TARGET).ewt $(BINNAME)_$(TARGET).dep

size: $(BUILDDIR)/$(BINNAME).elf
	@$(SIZE) $(OBJECTS) $(BUILDDIR)/$(BINNAME).elf

debug: $(BUILDDIR)/$(BINNAME).elf
	$(Q)$(GDB) -cd $(BUILDDIR) -x "$(realpath $(gnu-debug-script-y))" -ex "reset" -readnow -se $(realpath $(BUILDDIR)/$(BINNAME).elf)

include $(TOP)/scripts/Makefile.iar

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I haven't the foggiest idea how make files and linkers work in make files but would the problem reside here:

$(BUILDDIR)/$(BINNAME).elf: $(OBJS) $(LIBS) $(gnu-debug-lib-y) $(gnu-linker-script-y)
	@cp $(gnu-debug-lib-y) $(BUILDDIR)/target/
	$(ECHO) LINK $@
	$(Q)$(CC) $(LDFLAGS) $(CFLAGS_CPU) $(CFLAGS_DEFS) -T$(gnu-linker-script-y) -Wl,-Map,$(BUILDDIR)/$(BINNAME).map -o $@ $(OBJS) -Wl,--start-group $(LIBS) -Wl,--end-group -Wl,--no-undefined

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Copy and paste the name of your .c file.

Can you find the .o file corresponding to the .c file?

Does the link command get printed?

If so, does it contain the above .o file?

 

If you can, paste the result of avr-nm *.o | uniq > nm-out.txt

from a directory where there are .o files.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If not already being done: -Wl, -Map, prog.map

 

Then study it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

no main.o, I'll try again the morrow Clawson

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
If not already being done: -Wl, -Map, prog.map
I think OP also needs -Wl,--no-inhibit-exec to get an executable despite the unresolved reference.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think OP also needs -Wl,--no-inhibit-exec to get an executable despite the unresolved reference.

Here is the full makefile.RULES skeeve:

I tried as you suggested and still no give.  Thanks for the suggestion though.  


# default target
all::

include $(TOP)/scripts/Makefile.vars

BUILDDIR ?= ./build/$(TARGET)/$(VARIANT)

#-------------------------------------------------------------------------------
#		Rules
#-------------------------------------------------------------------------------

include $(TOP)/samba_applets/common/Makefile.inc
include $(TOP)/flash_loaders/applets/common/Makefile.inc
include $(TOP)/scripts/Makefile.config
include $(TOP)/arch/Makefile.inc
include $(TOP)/utils/Makefile.inc
include $(TOP)/target/Makefile.inc
include $(TOP)/drivers/Makefile.inc
include $(TOP)/lib/Makefile.inc

vpath %.c $(TOP)
vpath %.S $(TOP)

OBJS := $(addprefix $(BUILDDIR)/,$(gnu-cstartup-y) $(obj-y))
LIBS := $(addprefix $(BUILDDIR)/,$(lib-y))

-include $(OBJS:.o=.d)

.PHONY: all build clean size debug

all:: build

build: $(BUILDDIR)/$(BINNAME).elf \
	$(BUILDDIR)/$(BINNAME).symbols \
	$(BUILDDIR)/$(BINNAME).bin

ifeq ($(VARIANT),ddram)
CONFIG_BOOTSTRAP ?= y
ifeq ($(CONFIG_BOOTSTRAP),y)
$(BUILDDIR)/$(BINNAME).elf: $(BUILDDIR)/target/bootstrap.elf

$(BUILDDIR)/target/bootstrap.elf: $(BOOTSTRAP_OBJS) $(LIBS)
	@mkdir -p $(dir $@)
	$(ECHO) LINK $@
	$(Q)$(CC) $(LDFLAGS) $(CFLAGS_CPU) $(CFLAGS_DEFS) -T$(bootstrap-linker-script-y) -Wl,-Map,$(BUILDDIR)/bootstrap.map -o $@ $(BOOTSTRAP_OBJS) -Wl,--start-group $(LIBS) -Wl,--end-group
endif
endif

$(BUILDDIR):
	@mkdir -p $(BUILDDIR)

$(BUILDDIR)/%.d: %.c
	@mkdir -p $(dir $@)
	$(ECHO) DEP $<
	$(Q)$(CC) $(CFLAGS) $(CFLAGS_CPU) $(CFLAGS_INC) $(CFLAGS_DEFS) -MM $< -MT $(basename $@).o -o $(basename $@).d

$(BUILDDIR)/%.o: %.c
	@mkdir -p $(dir $@)
	$(ECHO) CC $<
	$(Q)$(CC) $(CFLAGS) $(CFLAGS_CPU) $(CFLAGS_INC) $(CFLAGS_DEFS) -c $< -o $@

$(BUILDDIR)/%.d: %.S
	@mkdir -p $(dir $@)
	$(ECHO) DEP $<
	$(Q)$(CC) $(CFLAGS_ASM) $(CFLAGS_CPU) $(CFLAGS_INC) $(CFLAGS_DEFS) -MM $< -MT $(basename $@).o -o $(basename $@).d

$(BUILDDIR)/%.o: %.S
	@mkdir -p $(dir $@)
	$(ECHO) CC $<
	$(Q)$(CC) $(CFLAGS_ASM) $(CFLAGS_CPU) $(CFLAGS_INC) $(CFLAGS_DEFS) -c $< -o $@

$(BUILDDIR)/$(BINNAME).elf: $(OBJS) $(LIBS) $(gnu-debug-lib-y) $(gnu-linker-script-y)
	@cp $(gnu-debug-lib-y) $(BUILDDIR)/target/
	$(ECHO) LINK $@
	$(Q)$(CC) $(LDFLAGS) $(CFLAGS_CPU) $(CFLAGS_DEFS) -T$(gnu-linker-script-y) -Wl,-Map,$(BUILDDIR)/$(BINNAME).map -o $@ $(OBJS) -Wl,--start-group $(LIBS) -Wl,--end-group -Wl,--no-undefined

$(BUILDDIR)/$(BINNAME).symbols: $(BUILDDIR)/$(BINNAME).elf
	$(Q)$(NM) $< >$@

$(BUILDDIR)/$(BINNAME).bin: $(BUILDDIR)/$(BINNAME).elf
	$(ECHO) OBJCOPY $@
	$(Q)$(OBJCOPY) -O binary $< $@

clean:
	@rm -rf $(BUILDDIR) settings
	@rm -f $(BINNAME)_$(TARGET).eww $(BINNAME)_$(TARGET).ewp $(BINNAME)_$(TARGET).ewd $(BINNAME)_$(TARGET).ewt $(BINNAME)_$(TARGET).dep

size: $(BUILDDIR)/$(BINNAME).elf
	@$(SIZE) $(OBJECTS) $(BUILDDIR)/$(BINNAME).elf

debug: $(BUILDDIR)/$(BINNAME).elf
	$(Q)$(GDB) -cd $(BUILDDIR) -x "$(realpath $(gnu-debug-script-y))" -ex "reset" -readnow -se $(realpath $(BUILDDIR)/$(BINNAME).elf)

include $(TOP)/scripts/Makefile.iar

 

Last Edited: Fri. Aug 31, 2018 - 12:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The question is whether your C function is actually getting built. Your map file should tell you this. You can also verify this by calling the C function in your main(). If it's not working there, it aint gonna work anywhere else.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Kartman, it compiles and works from within my project folder.

Can I ask a question?

 

The following functions are called from within cstartup.s file that I'm trying to call my function from.  

/* Initialize the C library */

	bl      __libc_init_array

/* Perform board initialization */

	bl      board_init

/* Branch to main() */

	bl      main

where are they defined and linked???

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What about this file lads!!!!

VERSION = 2.12
DEFAULT_AVAILABLE_TARGETS = sama5d4-generic sama5d4-xplained sama5d4-ek \
		   sama5d2-generic sama5d2-xplained \
		   sama5d2-vb-bga196 sama5d2-vb-bga289 \
		   sama5d27-som1-ek sama5d2-ptc-ek \
		   sama5d3-generic sama5d3-xplained sama5d3-ek \
		   sam9g15-generic sam9g25-generic sam9g35-generic \
		   sam9x25-generic sam9x35-generic \
		   sam9g15-ek sam9g25-ek sam9g35-ek \
		   sam9x25-ek sam9x35-ek \
		   samv71-generic same70-xplained samv71-xplained
AVAILABLE_TARGETS ?= $(DEFAULT_AVAILABLE_TARGETS)
AVAILABLE_VARIANTS ?= sram ddram qspi0 qspi1 flash
VARIANT ?= ddram

eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))

ifndef TARGET
$(error "No TARGET specified.")
endif

ifndef $(or RELEASE,DEBUG)
DEBUG = 5
endif


### Expand '*' available targets from example makefiles
TARGETS := $(subst *,%,$(filter %*,$(AVAILABLE_TARGETS)))
AVAILABLE_TARGETS := $(filter-out %*,$(AVAILABLE_TARGETS))
TARGETS := $(foreach target,$(TARGETS),$(filter $(TARGETS),$(DEFAULT_AVAILABLE_TARGETS)))
AVAILABLE_TARGETS += $(TARGETS)
AVAILABLE_TARGETS := $(sort $(AVAILABLE_TARGETS))
SELECTED_TARGET = $(strip $(foreach target,$(AVAILABLE_TARGETS),$(if $(call eq,$(TARGET),$(target)),$(target))))
###

ifeq ($(SELECTED_TARGET),)
$(info The selected target "$(TARGET)" is not supported or not available)
$(error Please set TARGET to one value from the list above: $(AVAILABLE_TARGETS))
endif

ifeq ($(V),1)
Q :=
ECHO := @true
else
Q := @
ECHO := @echo
endif

#-------------------------------------------------------------------------------
#		Create version string using git if possible
#-------------------------------------------------------------------------------
GIT_VERSION = $(shell if git rev-parse --show-toplevel >/dev/null 2>&1 ; \
	then git describe --tags --dirty; fi)
ifneq ($(GIT_VERSION),)
SOFTPACK_VERSION := $(VERSION) ($(GIT_VERSION))
else
SOFTPACK_VERSION := $(VERSION)
endif

#-------------------------------------------------------------------------------
#		Setup cross-compilation tools
#-------------------------------------------------------------------------------
# Tool suffix when cross-compiling
CROSS_COMPILE ?= arm-none-eabi-

# Compilation tools
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
SIZE = $(CROSS_COMPILE)size
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
GDB = $(CROSS_COMPILE)gdb
NM = $(CROSS_COMPILE)nm
AR = $(CROSS_COMPILE)ar

#-------------------------------------------------------------------------------
#		Setup compilation params
#-------------------------------------------------------------------------------

CFLAGS_OPT ?= -Os

# compiler flags
CFLAGS = -Wall -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int
CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses
CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs
CFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef
CFLAGS += -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings
CFLAGS += -Waggregate-return -Wstrict-prototypes
CFLAGS += -Wmissing-prototypes -Wmissing-declarations
CFLAGS += -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations
CFLAGS += -Wredundant-decls -Wnested-externs -Winline
CFLAGS += -Wunreachable-code -Wno-aggregate-return -Wall -Dprintf=iprintf
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += -std=gnu99
CFLAGS += $(CFLAGS_OPT)

CFLAGS_ASM = -Wall -D__ASSEMBLY__

CFLAGS_DEFS += -DSOFTPACK_VERSION="\"$(SOFTPACK_VERSION)\""

# Trace level used for compilation
# (can be overriden by adding TRACE_LEVEL=#number to the command-line)
# TRACE_LEVEL_DEBUG      5
# TRACE_LEVEL_INFO       4
# TRACE_LEVEL_WARNING    3
# TRACE_LEVEL_ERROR      2
# TRACE_LEVEL_FATAL      1
# TRACE_LEVEL_NO_TRACE   0
ifdef DEBUG
TRACE_LEVEL ?= 5
CFLAGS_DEFS += -DTRACE_LEVEL=$(TRACE_LEVEL)
CFLAGS += -g3
CFLAGS_ASM += -g3
else
TRACE_LEVEL ?= 4
CFLAGS_DEFS += -DNDEBUG -DTRACE_LEVEL=$(TRACE_LEVEL)
endif

# append variant define
CFLAGS_DEFS += -DVARIANT_$(shell echo $(VARIANT) | tr '[:lower:]' '[:upper:]')

# linker flags
LDFLAGS = --specs=nano.specs -Wl,--cref -Wl,--check-sections -Wl,--gc-sections
LDFLAGS += -Wl,--unresolved-symbols=report-all -Wl,--warn-common
LDFLAGS += -Wl,--sort-section=alignment -lgcc -lc

# include target-specific config
include $(TOP)/scripts/Makefile.vars.sam9xx5
include $(TOP)/scripts/Makefile.vars.sama5d2
include $(TOP)/scripts/Makefile.vars.sama5d3
include $(TOP)/scripts/Makefile.vars.sama5d4
include $(TOP)/scripts/Makefile.vars.samv71

# check if variant is compatible with example (AVAILABLE_VARIANTS) and SoC (COMPATIBLE_VARIANTS)
ALL_VARIANTS := $(filter $(AVAILABLE_VARIANTS), $(COMPATIBLE_VARIANTS))
SELECTED_VARIANT := $(strip $(foreach variant,$(ALL_VARIANTS),$(if $(call eq,$(VARIANT),$(variant)),$(variant))))
ifeq ($(SELECTED_VARIANT),)
$(info The selected variant "$(VARIANT)" is not supported or not available)
$(error Please set VARIANT to one value from the list above: $(ALL_VARIANTS))
endif

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys, guess what I've learned today? FECKALL!

 

cheeky

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
.extern hard_fault_handler_c

HardFault_Handler:
  TST LR, #4
  ITE EQ
  MRSEQ R0, MSP
  MRSNE R0, PSP
  B hard_fault_handler_c

The above is in my startup.s file

/**
* @brief This function handles Hard fault interrupt.
*/
void hard_fault_handler_c (unsigned int * hardfault_args)
{
	  /* USER CODE BEGIN HardFault_IRQn 0 */
  unsigned int stacked_r0;
  unsigned int stacked_r1;
  unsigned int stacked_r2;
  unsigned int stacked_r3;
  unsigned int stacked_r12;
  unsigned int stacked_lr;
  unsigned int stacked_pc;
  unsigned int stacked_psr;

  stacked_r0 = ((unsigned long) hardfault_args[0]);
  stacked_r1 = ((unsigned long) hardfault_args[1]);
  stacked_r2 = ((unsigned long) hardfault_args[2]);
  stacked_r3 = ((unsigned long) hardfault_args[3]);

  stacked_r12 = ((unsigned long) hardfault_args[4]);
  stacked_lr = ((unsigned long) hardfault_args[5]);
  stacked_pc = ((unsigned long) hardfault_args[6]);
  stacked_psr = ((unsigned long) hardfault_args[7]);

  printf ("\n\n[Hard fault handler - all numbers in hex]\n");
  printf ("R0 = %x\n", stacked_r0);
  printf ("R1 = %x\n", stacked_r1);
  printf ("R2 = %x\n", stacked_r2);
  printf ("R3 = %x\n", stacked_r3);
  printf ("R12 = %x\n", stacked_r12);
  printf ("LR [R14] = %x  subroutine call return address\n", stacked_lr);
  printf ("PC [R15] = %x  program counter\n", stacked_pc);
  printf ("PSR = %x\n", stacked_psr);
  printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));
  printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));
  printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));
  printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));
  printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));
  printf ("SCB_SHCSR = %x\n", SCB->SHCSR);

	flash_logger_add_string("\r\n<Hardfault>\r\n");
	flash_logger_commit();

  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
  }
  /* USER CODE BEGIN HardFault_IRQn 1 */

  /* USER CODE END HardFault_IRQn 1 */
}

This is the called C function in a .c file.

 

In terms of the makefile, this gets built automatically by the IDE. I didn't have to do anything specific to make it work. In my .map file, I get this:

 

.text.hard_fault_handler_c

                0x00000000080066c4       0xfc Application/User/stm32l4xx_it.o

                0x00000000080066c4                hard_fault_handler_c

 

How does the linker find these names? Symbols are embedded in the .o files. When you do a .global, you're telling the assembler to put the symbol in its symbol table. When you do a .extern you're telling the assembler that the symbol is external and the linker has to resolve it. You feed all the .o files to the linker and it attempts to resolve all of these symbols. If something is missing, it knows it and tells you. 

Where things can become 'fun' is when using C++. The compiler 'mangles' the symbols so that you don't get the same symbol from different classes/files etc. The upshot is everything looks 'ok' from the programmers perspective, but the symbol in question isn't quite what you expect - it's been 'mangled'. To get around this, you use extern 'C' to force the compiler to not mangle the symbol. Again, look in the .map file - if other code has called your C function, then it's in the map file. If the name has been mangled, then you'll see your function name with some extra shite appended/prepended.

I can't count the times I've been caught by this. I'm just more wise to the issue now.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It would be an interesting test to try calling xapi_system_gateway() from a c file.

 

If that builds OK you'll have a good set of LST and MAP files to work from.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Winterbottomo, I functions correctly being called from a c file...

I'm going to let this thread die for a few days until microchip support get back me...

 

Thanks Lads.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

If it's callable from .c to .c then do that and build with -save-temps then study the generated .s and di exactly the same in your own .S
.
BTW I wonder if this may be about -function-sections and - gc-sections?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
BTW I wonder if this may be about -function-sections and - gc-sections?
Why?

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You’ve got plenty of time then........
I dare say the answer is in front of your nose - you just have to look for it.