Author Topic: Inserting some Assembly inside C code for PIC24FJ series.  (Read 4053 times)

0 Members and 1 Guest are viewing this topic.

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7733
  • Country: ca
Inserting some Assembly inside C code for PIC24FJ series.
« on: February 19, 2018, 10:13:37 am »
Hi,  I'm using MPLABX built in C compiler.  A variation of this code worked for PIC16/PIC18 variants, but, once switching over to PIC24F, 16bit cpu, MPLABX wont compile this code.  I've counted the braces, but, it doesn't like it.

Code:
Code: [Select]
void Drive_Meter(){
    int temp = 0;
    int temp2 = meter_position * 3;
    int temp3 = 0;
for (temp=0 ; temp<24 ; temp++) {
temp3 = leds[temp2];

asm {
        bset     WriteLed
        nop
        btss   temp3,7
        bclr     WriteLed
        nop
        nop
        bclr     WriteLed
        nop
        nop
        nop
        nop
        nop
        nop     

        bset     WriteLed
        nop
        btss   temp3,6
        bclr     WriteLed
        nop
        nop
        bclr     WriteLed
        nop
        nop
        nop
        nop
        nop
        nop     

        bset     WriteLed
        nop
        btss   temp3,5
        bclr     WriteLed
        nop
        nop
        bclr     WriteLed
        nop
        nop
        nop
        nop
        nop
        nop     

        bset     WriteLed
        nop
        btss   temp3,4
        bclr     WriteLed
        nop
        nop
        bclr     WriteLed
        nop
        nop
        nop
        nop
        nop
        nop     

        bset     WriteLed
        nop
        btss   temp3,3
        bclr     WriteLed
        nop
        nop
        bclr     WriteLed
        nop
        nop
        nop
        nop
        nop
        nop     

        bset     WriteLed
        nop
        btss   temp3,2
        bclr     WriteLed
        nop
        nop
        bclr     WriteLed
        nop
        nop
        nop
        nop
        nop
        nop     

        bset     WriteLed
        nop
        btss   temp3,1
        bclr     WriteLed
        nop
        nop
        bclr     WriteLed
        nop
        nop
        nop
        nop
        nop
        nop     

        bset     WriteLed
        nop
        btss   temp3,0
        bclr     WriteLed
        nop
        nop
        bclr     WriteLed

        //nop
        //nop
        //nop
        //nop
        //nop
        //nop     
        } //endasm
        temp2++;
    }
 

}

Error:
Code: [Select]
CLEAN SUCCESSFUL (total time: 18ms)
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory 'C:/Users/Admin/MPLABXProjects/LED_Strip_Count_PIC24FJ.X'
make  -f nbproject/Makefile-default.mk dist/default/production/LED_Strip_Count_PIC24FJ.X.production.hex
make[2]: Entering directory 'C:/Users/Admin/MPLABXProjects/LED_Strip_Count_PIC24FJ.X'
"C:\Program Files (x86)\Microchip\xc16\v1.33\bin\xc16-gcc.exe"   mcc_generated_files/pin_manager.c  -o build/default/production/mcc_generated_files/pin_manager.o  -c -mcpu=24FJ128GA606  -MMD -MF "build/default/production/mcc_generated_files/pin_manager.o.d"      -mno-eds-warn  -g -omf=elf -DXPRJ_default=default  -legacy-libc    -O0 -msmart-io=1 -Wall -msfr-warn=off 
"C:\Program Files (x86)\Microchip\xc16\v1.33\bin\xc16-gcc.exe"   mcc_generated_files/mcc.c  -o build/default/production/mcc_generated_files/mcc.o  -c -mcpu=24FJ128GA606  -MMD -MF "build/default/production/mcc_generated_files/mcc.o.d"      -mno-eds-warn  -g -omf=elf -DXPRJ_default=default  -legacy-libc    -O0 -msmart-io=1 -Wall -msfr-warn=off 
"C:\Program Files (x86)\Microchip\xc16\v1.33\bin\xc16-gcc.exe"   mcc_generated_files/interrupt_manager.c  -o build/default/production/mcc_generated_files/interrupt_manager.o  -c -mcpu=24FJ128GA606  -MMD -MF "build/default/production/mcc_generated_files/interrupt_manager.o.d"      -mno-eds-warn  -g -omf=elf -DXPRJ_default=default  -legacy-libc    -O0 -msmart-io=1 -Wall -msfr-warn=off 
"C:\Program Files (x86)\Microchip\xc16\v1.33\bin\xc16-gcc.exe"   main.c  -o build/default/production/main.o  -c -mcpu=24FJ128GA606  -MMD -MF "build/default/production/main.o.d"      -mno-eds-warn  -g -omf=elf -DXPRJ_default=default  -legacy-libc    -O0 -msmart-io=1 -Wall -msfr-warn=off 
main.c: In function 'Drive_Meter':
main.c:69:5: error: expected '(' before '{' token   *********************************************HERE********************
main.c:70:9: error: 'bset' undeclared (first use in this function)  ***************************HERE**********************
main.c:70:9: note: each undeclared identifier is reported only once for each function it appears in
main.c:70:18: error: expected ';' before 'PORTF'
nbproject/Makefile-default.mk:148: recipe for target 'build/default/production/main.o' failed
make[2]: *** [build/default/production/main.o] Error 255
make[2]: *** Waiting for unfinished jobs....
make[2]: Leaving directory 'C:/Users/Admin/MPLABXProjects/LED_Strip_Count_PIC24FJ.X'
nbproject/Makefile-default.mk:90: recipe for target '.build-conf' failed
make[1]: Leaving directory 'C:/Users/Admin/MPLABXProjects/LED_Strip_Count_PIC24FJ.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

BUILD FAILED (exit value 2, total time: 9s)

The syntax and handling of assembly is different when dealing with 16 bit C compiler.  I cant find any good documentation on mixing both.  Only with 8 bit pics.  This is my first mixing of code in 16 bit pic, so please be patient.

 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #1 on: February 19, 2018, 10:22:13 am »
GCC has its own inline assembly syntax (see also this HOWTO).
 
The following users thanked this post: BrianHG

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7733
  • Country: ca
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #2 on: February 19, 2018, 10:41:03 am »
Ok, the brackets of:

asm (
         blahhhh
         blahhhh
         blahhhh
         blahhhh
);

Now recognizes the inside of the brackets as assembly.  Next, the first bitset.

I wish to set bit 4 of PORTF.  Now, I currently have:

        bset     PORTF,4

but, the compiler says 'main.c:70:9: error: expected string literal before 'bset'  '

Must I seriously place every assembly line in a set of ""Quotes""???
Talk about a mess.
 

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7733
  • Country: ca
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #3 on: February 19, 2018, 10:55:46 am »
I tried the " .... " (Quotes), now I get a bunch of errors to a file I cant even access, not even part of any of my source files.
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #4 on: February 19, 2018, 11:16:40 am »
Have you checked this document "XC16 C Compiler User’s Guide":

http://ww1.microchip.com/downloads/en/DeviceDoc/50002071F.pdf

See section 16.3. USING INLINE ASSEMBLY LANGUAGE, starting on page 230. Good luck! :)
 
The following users thanked this post: BrianHG

Online BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7733
  • Country: ca
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #5 on: February 19, 2018, 11:26:59 am »
Have you checked this document "XC16 C Compiler User’s Guide":

http://ww1.microchip.com/downloads/en/DeviceDoc/50002071F.pdf

See section 16.3. USING INLINE ASSEMBLY LANGUAGE, starting on page 230. Good luck! :)
Actually, it starts on page 227 if I want to be more neat about it...
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #6 on: February 19, 2018, 12:26:21 pm »
Actually, it starts on page 227 if I want to be more neat about it...
I wanted to give a direct pointer to the inline asm section. But yes, you are right that the section regarding mixing C and assembly code starts at page 227.
 
The following users thanked this post: BrianHG

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #7 on: February 19, 2018, 01:53:15 pm »
it was my understanding that a long time ago they removed the block assembly feature and now you can only add single-lines inline assembly.
You can of course get around that with newline characters "\n"
but if you tell me that hitting return works, good to know!
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #8 on: February 19, 2018, 02:27:49 pm »
it was my understanding that a long time ago they removed the block assembly feature and now you can only add single-lines inline assembly.

I'm not sure if it ever was in XC16 or C30 (ISTBC!), and these days I don't often use assembly language except at specific pinch points, but certainly looking at the last two projects I've used assembly language in I've used single liners, see an example below.

Code: [Select]
void IQCorr(int nSamples)
{
/*

register int i=NO_OF_BYTES_TRANSFRED_IN_A_USB_FRAME/4;
signed short *ps16=_as16Buffer;

while (i-->0)
*/
{

    // Preload the I/Q correction factors here to save time in the loop
asm ("mov __s16PhaseCorr,W6": : : "w6");
asm ("mov __u16GainCorr,W4": : : "w4");
asm ("mov __s16DCICorr,W7": : : "w7");
asm ("mov __s16DCQCorr,W8": : : "w8");

// W1 points to the current sample starting at _asIQ[0]
asm ("mov #__as16IQ,W1": : : "w1");

// W5 is the loop counter, one iteration per sample
asm ("mov %0,W5": : "r"(nSamples) : "w5");

asm ("loop:");

// DCI correction
asm ("add W7,[W1],W0": : : "w0"); // W0 = I + DCICorr
asm ("mov W0,[W1++]": : : "w1"); // I = I + DCICorr

// DCQ correction
asm ("add W8,[W1],W9": : : "w9"); // W9 = Q + DCQCorr

// Phase & gain correction Qout = (Qdccorr + (Idccorr * PhaseCorr)) * GainCorr
asm ("mul.ss W6,W0,W2": : : "w2","w3"); // W3:W2 has I * PhaseCorr
asm ("add W3,W9,W0": : : "w0"); // W0 has Q + (I * PhaseCorr)
asm ("mul.su W0,W4,W2": : : "w2","w3"); // W3:W2 has (Q + (I * PhaseCorr)) * GainCorr
asm ("sl W2,W2": : : "w2");
asm ("rlc W3,W3": : : "w3"); // W3 now has corrected Q
asm ("mov W3,[W1++]": : : "w1");

asm ("dec W5,W5": : : "w5");
asm ("bra NZ,loop");

/*

register signed short s16=(signed short)(__builtin_mulss(*ps16++,_s16PhaseCorr)>>16);

*ps16++=(signed short)(__builtin_mulsu(*ps16+s16,_u16GainCorr)>>15);
*/
/*

signed short s16=(signed short)((((signed long)(*ps16++))*_s16PhaseCorr)>>16);

*ps16++=(signed short)((((signed long)(*ps16+s16))*_u16GainCorr)>>15);
*/
}
// Nop();
}
 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #9 on: February 19, 2018, 02:55:03 pm »
(ISTBC? Never encountered the acronym)

these days I don't often use assembly language except at specific pinch points

same.. for example a 16/32 point Antialiasing FIR.. the microchip dsp libary require 61 cycles just for setup.. or this is what the manual says.
I don't understand why,
-pushing and popping all the needed WREGs is like 12 instructions total.
-another dozen to set up the circular buffers
-one clear with prefetch + 16/32 MACs
-one to retreive the result from the accumulator
so i use my own function.

Code: [Select]
asm ("mov __s16DCQCorr,W8": : : "w8")could you explain how this gets translated? my knowledge of dspic assembler is just this much..
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5319
  • Country: gb
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #10 on: February 20, 2018, 09:57:54 am »
(ISTBC? Never encountered the acronym)


ISTBC = "I stand to be corrected", i.e., a caveat that my memory may be failing me!

Quote
these days I don't often use assembly language except at specific pinch points

same.. for example a 16/32 point Antialiasing FIR..cc the microchip dsp libary require 61 cycles just for setup.. or this is what the manual says.
I don't understand why,
-pushing and popping all the needed WREGs is like 12 instructions total.
-another dozen to set up the circular buffers
-one clear with prefetch + 16/32 MACs
-one to retreive the result from the accumulator
so i use my own function.


I haven't done much in recent years with dsPIC, but pretty much across the entire PIC range for exceptionally low latency interrupt handling I've found I sometimes have to hand craft ISR prolog and epilog code, even when the part has shadow registers.

Quote

Code: [Select]
asm ("mov __s16DCQCorr,W8": : : "w8")could you explain how this gets translated? my knowledge of dspic assembler is just this much..

This is GCC syntax and to be honest this syntax came to me relatively recently compared to my assembly language career, so I am certainly no expert in it, pretty much most of my knowledge of it comes from looking at others' examples, I should spend more time looking at the manual! The code example I gave I wrote over seven years ago!

There's a 16 bit global C RAM variable called __s16DCQCorr, the contents of which are moved in the W8 register.

Code: [Select]
int16_t __s16DCQCorr=0;
Specifying the "w8" at the end there tells the compiler that the W8 register is clobbered, i.e. overwritten, by my assembly language, so it takes that into account when compiling any C code around my ASM.

In retrospect, it would probably be better (more correct) to write it like this:

Code: [Select]
asm ("mov %0,W8": :"U" (__s16DCQCorr) : "w8")
This tells it explicitly that the variable is near.

If you overwrite several registers, then you can list them, comma separated, for example:

Code: [Select]
asm ("mul.ss W6,W0,W2": : : "w2","w3"); // W3:W2 has I * PhaseCorr

The MUL generates a 32 bit result, so clobbers two 16 bit registers, shown in the clobber list.

As stated, I am no expert in this GCC syntax, sometimes I find it easier to write the code directly into a .s.

 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: Inserting some Assembly inside C code for PIC24FJ series.
« Reply #11 on: February 20, 2018, 10:27:39 am »
Usually when i encounter a new acronym i give it to the urbandictionary search engine, but it failed me this time :)

Thank you for your explanation, i found it easier to understand that the relevant compiler manual chapter (16.3)

which basically says the same thing in the same way but.. whatever, sometimes when somebody repeats something it stucks with you better
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf