Mixing languages C + Spin + pasm

Until now, I have written everything that has to run fast (hardware drivers) in pasm and evrything else (command interpreter, string processing) in Spin. The big performance gain of the P2 makes it possible to code more and more in highlevel language. Even control loops that have to run several 1000 times a second can be written in Spin (at least in fastspin), now.

Because C has better support for data types (struct and float) I'm currently experimenting with C. I saw that there are lots of include files in the FlexGui/include folder, some samples and documentastion in /sample and /doc. But unfortunatelly it doesn't answer all of my questions so I have to ask here.

How can I include C objects into Spin code? Declaring an OBJ doesn't work for a .c file. Do I have to use
PUB FILE "myfile.c" myfunction(arg)
for each function?

How can I declare a DAT section in a .c file to be used as assembler code to COGNEW()? I tried __pasm{} at the global scope but I fear it doesn't do exacly what I want. It doesn't allow ORG or RES.


  • I'd like to know too...

    Think I found how to do the other way and include spin in c:

    struct __using("PropSerial/SmartSerial.spin2") fds;
    fds.start(63, 62, 0, 23400);
  • Wow, putting
    struct __using("
    into the search box gives a funny result...
  • Obj should work for including .c and .bas files in Spin. See the file server samples for an example (it uses .cc instead of .c for a technical reason involving the scope of enums, but in most cases it wont matter)

    And org and res should work in c pasm sections, if for some reason they dont thats a new bug.
  • Ok, thanks. I found out that for including .c files as OBjs in Spin you have to specify the filename including extension. For .spin and -spin2 files the extension is optional.

    The following file compiles with errors. It says "unexpected constant" in the line of the "ORG 0". If I remove the "0" the ORG seems OK but it complains "res not valid after orgh".
  • documentation says to do it this way:
    ## Extensions to C
    ### Inline Assembly (C Style)
    The inline assembly syntax is similar to that of MSVC. Inline assembly blocks are marked with the keyword `__asm`. For example, a function to get the current cog id could be written as:
    int getcogid() {
       int x;
       __asm {
          cogid x
       return x;

    I think you have pasm instead of asm...
  • Inline assembly works perfecly. My problem is that I have a larger block of code which I want to start in an extra cog. Res is there to save memory so that the place holders for uninitilized longs at the end do not use hub ram and unnecesarily add to the program size. Not absolutely important theese days now we have 512kB. But it should work anyway I thought.
  • I found out that
    * I had to add a header file. Otherwise the including into the main (Spin) file doesn't work
    * I had to convert all function idetifiers to lowercase
    * I replaced RES by LONG

    But it still doesn't work. Somehow the assembler thinks that my assembler code is meant to go to hub ram, not cog ram.
    __pasm {
    		drvl    #pinEncTe
    		fltl	#pinEncTx		' reset smartpin
    		wrpin	mode_stx,#pinEncTx	' synchronous serial transmit
    		wxpin	baud_bits,#pinEncTx	' 2.5MBd 16N1
    		drvl	#pinEncTx		' enable TX smartpin
    is compiled to
    	byte	$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    '-' ORG
    '-' startEnc
    '-' 		drvl # 3
    	byte	$58, $06, $64, $fd
    '-' 		fltl # 2
    	byte	$50, $04, $64, $fd
    '-' 		wrpin mode_stx,# 2
    	long	((@@@_Sc3_SanyoEnc_dat_ + 240)>>9) | $fc05e002
    	long	(((@@@_Sc3_SanyoEnc_dat_ + 240)&$1ff)<<9) | $fc15f002
    	byte	$58
    	byte	$04
    	byte	$64
    	byte	$fd
    which is complete nonsense. The ORG is ignored. It seems that I'm doing something fundamentally wrong. __pasm{} is probably not meant for code running in a cog.
  • I saw that the led_server_asm example does the same thing. And it compiles without errors. The only difference I see is that it has the __pasm{} at the begining and my code has it at the end.
  • I think any inline assembly is going to be hubexec mode in HUB RAM with FastSpin, just like the rest of the code.
    Also, I think the documentation says that Spin can be mixed case, but you have to use the lowercase in C.

    If you really want the code to be in a cog, you need to do a coginit on it and start in another cog.
    At least, I think so.
  • I guess this is one big difference between Spin2 and Fastspin...
    I think Spin2 inline assembly is in the cog...
  • __pasm outside of functions is intended to work the same as dat in spin. The code does have to be placed in hub memory initially, this is true of all code (everything starts in hub and gets loaded into cog or lut by coginit). The listing file generated by -l is a much better guide to where things are intended to run than the .pasm file
  • Ah, thanks Eric. Can you take a look at my code and tell what's the difference? I.E. why it works in led_server_asm and doesn't in mine?

    ... WOW, wait! I just moved the __pasm{} section to the beginning of the file right after the #include and #defines. And now it suddenly works, at least the compiler no longer complains.

    There must be some unintended mode change when __pasm{} is placed after variable or function definitions. I'm not good at finding problems in hexdumps or .lst files. I'm not sure if it's a compiler bug or if I did something wrong.
  • I did notice one potential issue: you used "ORG" instead of "org", and C is case sensitive, so it didn't recognize the directive. I'll add some code to work around this in the next version of the compiler.
  • ersmith: Hope you're getting better!
Sign In or Register to comment.