MPLAB XC16: Mixing C and Assembly

2.2k views Asked by At

I am attempting to mix some C and assembly language and I am having a bear of a time. I am experienced with C, somewhat with assembly, but I haven't used them on the same project before.

At the moment, I am attempting to compile the simplest possible project, which is a Q1.15 fixed-point multiplication. I don't actually care about the code output, I just needed something to compile so that I could build off of it.

myq15.h:

#ifndef _Q15_MATH
#define _Q15_MATH

#include <stdint.h>

typedef int16_t q15_t;

extern q15_t q15_mul(q15_t multiplicand, q15_t multiplier);
q15_t q15_add(q15_t addend, q15_t adder);

#endif

myq15.c

#include "myq15.h"

q15_t q15_add(q15_t addend, q15_t adder){
    int32_t result = (uint32_t)addend + (uint32_t)adder;

    if(result > 32767)          result = 32767;
    else if(result < -32768)    result = -32768;

    return (q15_t)result;
}

myq15.s:

    .include "xc.inc"

    .text
    .global _q15_mul

_q15_mul:
    ; w3:w2 = w1 * w0
    mul.ss  w0, w1, w2

    ; w0 = (w3:w2) >> 15
    rlc     w2, w2
    rlc     w3, w3

    ; w0 = w3
    mov     w3, w0

    return

    .end

My 'main' file simply calls a q15_add() and q15_mul() instance.

On compile, The linker states:

build/default/production/_ext/608098890/myq15.o(.text+0x0): In function `_q15_mul':
: multiple definition of `_q15_mul'

Again, I am trying to figure out how to mix the assembly and C file for other purposes, but if I can't get this simple program to work, I'm hopeless!

Thanks,

2

There are 2 answers

1
Jester On BEST ANSWER

It's a bad idea to name your files the same, the toolchain might confuse them, given that both myq15.c and myq15.s compile to myq15.o by default.

0
Ryan B On

You can use inline assembly in a c file. If you don't have a lot of assembly, this is probably the easiest way.

It's recommended to encapsulate any assembly into its own function call (which can be inlined) to prevent any side effects with optimization.

inline void SomeAssembly(void) {
  asm volatile(“pwrsav #”);
  asm volatile(“reset”);
} 

int main (void) {
  SomeAssembly();
  while(1);
  return -1;
}