Adding assembler function to C

Hi I am trying to add an assembler function to my C project. The assembler function is in a separate file asm.S. Compiling works fine and the asm.S.o file is generated but linking does not work and I get the warning “undefined reference to `ASM_TST(unsigned int, unsigned int, unsigned int, unsigned int)” and of course it does not work.
My assembler file asm.S:

.section    .text

.equ TEST_ABC, 0x40000000
.equ HUGO_ABC, 0x08

.global     ASM_TST
ASM_TST:
  mov   r0, #4
  mov   r1, #HUGO_ABC
  add   r0, r1

  bx    LR

.end

I have a prototype declaration for the function asm.h:

typedef unsigned int UINT32_t;

/* Prototype declarations */
UINT32_t          ASM_TST(UINT32_t, UINT32_t, UINT32_t, UINT32_t);

My C program is the standard blink:

#include <Arduino.h>

#include "asm.h"

//#define PIN_LED_RED PB14
//#define PIN_LED_RED PB12
#define PIN_LED_RED PC13

void setup()
{
  // initialize LED digital pin as an output.
  pinMode(PIN_LED_RED, OUTPUT);

  Serial.begin(115200);
}

void loop()
{
  // turn the LED on (HIGH is the voltage level)
  digitalWrite(PIN_LED_RED, HIGH);
  Serial.println("HIGH");

  // wait for a second
  delay(1000);
  // turn the LED off by making the voltage LOW
  digitalWrite(PIN_LED_RED, LOW);
  Serial.println("LOW");

   // wait for a second
  delay(1000);

  /* Call ASM routine */
  ASM_TST(1, 2, 3, 4);
}

My platform.ini file:

[env:genericSTM32F103CB]
platform = ststm32
board = genericSTM32F103CB
framework = arduino
upload_protocol = dfu
monitor_speed = 115200
board_build.core = maple
build_flags =
  -D SERIAL_USB
  -D GENERIC_BOOTLOADER
debug_tool = stlink
debug_init_break = tbreak setup
lib_extra_dirs = C:\Users\xxx\Documents\PlatformIO\Projects\lib_shared

What have I missed?

No it’s not, it’s a C++ program. Due to name mangling, when declaring a function as

UINT32_t          ASM_TST(UINT32_t, UINT32_t, UINT32_t, UINT32_t);

in a .cpp file and outside of an extern "C" block, it will look for a function called _Z7ASM_TSTjjjj.

Consequently, add extern "C" to disable name mangling, and the produced code will look for

More correctly, the asm.h should have the common pattern

#ifndef _ASM_H_
#define _ASM_H_

#ifdef __cplusplus
extern "C" {
#endif

typedef unsigned int UINT32_t;

/* Prototype declarations */
UINT32_t          ASM_TST(UINT32_t, UINT32_t, UINT32_t, UINT32_t);

#ifdef __cplusplus
}
#endif

#endif /* _ASM_H_ */

to be correct no matter whether C or C++ code is including that header.

1 Like

FYI

Amazing,
I was not aware of this. Now I can go on with my actual idea. I have put a lot of effort to solve this myself. I suspected that it was something with the name. As you can see capitol letters was one of my tests. I have also tried adding 1 and 2 underscores leading the name.
Regarding
#ifndef ASM_H
#define ASM_H
I of course have that, just thought it was irrelevant.

By the way is it possible to generate a .map file so that i can see detail information, I think I will need it when I start working with the assembler code?

Thank you very much for solving this issue.

Yes, see

Thanks, that works fine