Shop OBEX P1 Docs P2 Docs Learn Events
MCP3208 Build Failing (undefined reference to 'MCP3208_Entry' — Parallax Forums

MCP3208 Build Failing (undefined reference to 'MCP3208_Entry'

TrezitorulTrezitorul Posts: 68
edited 2015-02-07 20:26 in Propeller 1
Hi guys I figured I would start learning C and C++ and I am trying to interface to the MCP3208 but my build keeps failing with the following errors:

(.text+0x24): undefined reference to `MCP3208_Entry'
/tmp/cckxDf1w.o: In function `_main':
(.text+0x88): undefined reference to `__load_start_mcp3208_cog'

As far as I can tell its because of the mcp3208.s file is not being picked up properly by the simpleIde compiler...however, I am very new with C and C++ so it could also just be gross incompetence on my part.

I copied the mcp3208.h, mcp3208.test.h, and mcp3208.s file into the same folder as my project as suggested by the libpropeller readme. The code that I wrote to try to interface with the MCP is below:
#include "simpletools.h"                      // Include simple tools
#include "mcp3208.h"
//using namespace libpropeller;

int main()                                    // Main function
{ 
  libpropeller::MCP3208 mcp;
  print("Hello from the PropStick");
  mcp.Start(31,29,30,0xFF,-1,-1);
  int in=-1;
  while(1)
  {
    in=mcp.In(0);
    print("The ADC Value is: %d \n",in);
  }    
}
Thanks for the help!

-Trezitorul

Comments

  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-01-31 12:06
    First, kudos for trying libpropeller and C++. Great library.

    Second, it may help if you post a zip of your project. Under "Project" choose the "Zip" option and the post the resulting file.
  • TrezitorulTrezitorul Posts: 68
    edited 2015-01-31 20:42
    Alright, so I made the zip file of the project, however, I noticed that the .S file was not in the project so I tried adding it as a tab to the project but then SimpleIDE just says: "A file named MCP3208.S" already exists (clearly not from the zip file contents) and then it creates a new blank file called mcp3208 without a file extension.

    In the libpropeller instructions it states:

    "Some objects (that take a seperate cog, usually) have an associated .S file that you'll have to include in your make file or on the command line."

    They do not, however, elaborate on exactly how one would include them in your make file or on the command line. How would I go about doing that since just adding it to the SimpleIDE project does not seem to work successfully? I did notice that I can add command line arguments to both the compiler and the linker in the simpleIDE, is there a way I can add the .S file there?

    Thanks!

    -Trezitorul

    P.S. I have attached my projects zipfile before and after attempting to add mcp3208.S to the project.

    PullTester1.zip <- Without trying to add mcp3208.S to project
    PullTester1(Added.S).zip <- After trying to add mcp3208.S to the project
  • dgatelydgately Posts: 1,630
    edited 2015-01-31 21:29
    To include the .S file into the project zip, you can left-click (Control-click on Mac OS X) on any file in the Project Manager section of SimpleIDE to copy or link-in files to include in the project. Then, the Zip option should include your .S file...


    CopyFile.png


    dgately
    676 x 352 - 172K
  • TrezitorulTrezitorul Posts: 68
    edited 2015-02-02 18:32
    Wow thanks! The compiler is definitely seeing the .S file now but it is generating a whole new slew of errors, I am suspicious that the compiler is now trying to pull it in as
    C++ code not as the assembly file it is? Is that what is happening or is it something else and what might I do about it?

    Error output when I try to compile project.
    Project Directory: /home/trezitorul/ownCloud/Hephaestus/Hep Software/Pull Tester/
    
    SimpleIDE Version 1.0.1
    /home/trezitorul/Documents/SimpleIDE/Learn/Simple Libraries/
    /home/trezitorul/Documents/SimpleIDE/ Updated on: 2015-01-23
    
    propeller-elf-gcc -v GCC 4.6.1 (propellergcc_v1_0_0_2411)
    propeller-elf-as -o lmm/mcp3208.o mcp3208.S
    mcp3208.S: Assembler messages:
    mcp3208.S:0: Warning: end of file not at end of a line; newline inserted
    mcp3208.S:8: Error: bad expression
    mcp3208.S:8: Error: Too many operands
    mcp3208.S:10: Error: bad expression
    mcp3208.S:10: Error: bad expression
    mcp3208.S:10: Error: Improper call target
    mcp3208.S:13: Error: bad expression
    mcp3208.S:13: Error: bad expression
    mcp3208.S:13: Error: Improper call target
    mcp3208.S:16: Error: bad expression
    mcp3208.S:16: Error: bad expression
    mcp3208.S:16: Error: Improper call target
    mcp3208.S:19: Error: bad expression
    mcp3208.S:19: Error: bad expression
    mcp3208.S:19: Error: Improper call target
    mcp3208.S:22: Error: bad expression
    mcp3208.S:22: Error: bad expression
    mcp3208.S:22: Error: Improper call target
    mcp3208.S:38: Error: bad expression
    mcp3208.S:38: Error: Too many operands
    mcp3208.S:39: Error: bad expression
    mcp3208.S:39: Error: Too many operands
    mcp3208.S:42: Error: bad expression
    mcp3208.S:42: Warning: division by zero
    mcp3208.S:42: Error: Too many operands
    mcp3208.S:43: Error: bad expression
    mcp3208.S:43: Error: Too many operands
    mcp3208.S:44: Error: bad expression
    mcp3208.S:44: Error: Too many operands
    mcp3208.S:45: Error: bad expression
    mcp3208.S:45: Warning: division by zero
    mcp3208.S:45: Error: Too many operands
    mcp3208.S:48: Error: Too many operands
    mcp3208.S:51: Error: Too many operands
    mcp3208.S:55: Error: bad expression
    mcp3208.S:55: Error: Too many operands
    mcp3208.S:56: Error: bad expression
    mcp3208.S:56: Error: Too many operands
    mcp3208.S:57: Error: bad expression
    mcp3208.S:57: Warning: division by zero
    mcp3208.S:57: Error: Too many operands
    mcp3208.S:60: Error: Too many operands
    mcp3208.S:63: Error: Too many operands
    mcp3208.S:66: Error: bad expression
    mcp3208.S:66: Error: Too many operands
    mcp3208.S:67: Error: bad expression
    mcp3208.S:67: Error: Too many operands
    mcp3208.S:72: Error: bad expression
    mcp3208.S:72: Error: Too many operands
    mcp3208.S:74: Error: Too many operands
    mcp3208.S:77: Error: bad expression
    mcp3208.S:77: Error: Too many operands
    mcp3208.S:79: Error: bad expression
    mcp3208.S:79: Error: Too many operands
    mcp3208.S:82: Error: bad expression
    mcp3208.S:82: Error: Too many operands
    mcp3208.S:86: Error: bad expression
    mcp3208.S:86: Warning: division by zero
    mcp3208.S:86: Error: Too many operands
    mcp3208.S:87: Error: bad expression
    mcp3208.S:87: Warning: division by zero
    mcp3208.S:87: Error: Too many operands
    mcp3208.S:88: Error: bad expression
    mcp3208.S:88: Error: Too many operands
    mcp3208.S:90: Error: bad expression
    mcp3208.S:90: Error: Too many operands
    mcp3208.S:93: Error: bad expression
    mcp3208.S:93: Error: Too many operands
    mcp3208.S:101: Error: bad expression
    mcp3208.S:101: Error: Too many operands
    mcp3208.S:102: Error: bad expression
    mcp3208.S:102: Warning: division by zero
    mcp3208.S:102: Error: Too many operands
    mcp3208.S:105: Error: bad expression
    mcp3208.S:105: Warning: division by zero
    mcp3208.S:105: Error: Too many operands
    mcp3208.S:108: Error: Too many operands
    
    

    Current project included below:

    PullTester1(Added.S).zip

    Thanks for the help!

    -Trezitorul
  • dgatelydgately Posts: 1,630
    edited 2015-02-03 00:30
    The log shows that it is using propeller-elf-as (assembler) on the .S file...
    propeller-elf-as -o lmm/mcp3208.o mcp3208.S                   <== assembler!
    mcp3208.S: Assembler messages:
    mcp3208.S:0: Warning: end of file not at end of a line; newline inserted
    mcp3208.S:8: Error: bad expression
    mcp3208.S:8: Error: Too many operands
    

    Is your .S file a GAS-compatible source file?


    dgately
  • TrezitorulTrezitorul Posts: 68
    edited 2015-02-03 03:25
    My apologies for being slow, as far as I can tell the code in the .S file is GAS compatible (it is almost a verbatim copy of Chip Gracey's MCP3208 DAT section from the Spin + PASM driver). I have gone ahead and attached the code below, I played around with it for a while but I can't find any reason why mov T1, par would throw the error too many operands and bad expression as far as I can tell that is perfectly good assembly.
                    .section .mcp3208.cog, "ax"
                    .global MCP3208_Entry
                    .compress off
    
    MCP3208_Entry
    ..start
    		.org	0
    		mov	T1, PAR             // Read parameters
    
    		call	#Param              // Setup DIN/DOUT pin
    		mov	Dmask, T2
    
    		call	#Param              // Setup CLK pin
    		mov	Cmask, T2
    
    		call	#Param              // Setup CS Pin
    		mov	Smask, T2
    
    		call	#Param              // Set mode
    		mov	Enables, T3
    
    		call	#Param              // Setup DAC configuration
    	if_c 	or	DIRA, T2
    	if_c 	movs	CTRA, T3
    	if_c 	movi	CTRA, #0b00110000
    
    		shr	T3, #8
    		call	#Param2
    	if_c 	or	DIRA, T2
    	if_c 	movs	CTRB, T3
    	if_c 	movi	CTRB, #0b0011000
    
    
    //
    //
    // Perform Conversions Continuously
    //
    		or	DIRA, Cmask         // Output CLK
    		or	DIRA, Smask         // Output CS
    
    Main_loop
    		mov	Command, #$10       // Init command
    		mov	T1, PAR             // Reset sample pointer
    		mov	T2, Enables         // Get enables
    		mov	T3, #8              // Ready 8 channels
    
    Cloop
    		shr	T2, #1	wc          // If channel disabled, skip
    	if_nc 	jmp	#Skip
    
    		test	T2, #$80	wc  // Channel enabled, get single/diff mode
    		muxnc	Command, #8
    		mov	Stream, Command
    
    		or	OUTA, Smask         // CS high
    		or	DIRA, Dmask         // make DIN/DOUT output
    		mov	Bits, #20           // ready 20 bits (cs+1+diff+ch[3]+0+0+data[12])
    
    Bloop   
    		test	Stream, #$20	wc  // update DIN/DOUT
    		muxc	OUTA, Dmask
    
    		cmp	Bits, #$e	wz  // if command done, input DIN/DOUT
    	if_z 	andn	DIRA, Dmask
    
    		andn	OUTA, Cmask         // CLK low
    		mov	T4, PAR             // update DACs between clock transitions
    		add	T4, #$14
    		rdlong	FRQA, T4
    		add	T4, #4
    		rdlong	FRQB, T4
    		or	OUTA, Cmask         // CLK high
    
    		test	Dmask, INA	wc  // Sample DIN/DOUT
    		rcl	Stream, #1
    
    		andn	OUTA, Smask         // CS Low
    
    		djnz	Bits, #Bloop        // Next data bit
    
    
    		and	Stream, Mask12      // Trim and write sample
    		wrword	Stream, T1
    
    Skip
    		add	T1, #2              // Advance sample pointer
    		add	Command, #1         // Advance command
    		djnz	T3, #Cloop          // more channels?
    
    		wrlong	Counter, T1         // Channels done, update counter
    		add	Counter, #1
    
    		jmp	#Main_loop          // perform conversions again
    
    
    //
    //
    // Get parameter
    //
    Param
    		rdlong	T3, T1              // Get parameter into T3
    		add	T1, #4              // Point to next parameter
    
    Param2
    		mov	T2, #1              // Make pin mask in T2
    		shl	T2, T3
    
    		test	T3, #$80	wc  // Get DAC flag into c
    
    Param2_ret
    Param_ret
    		ret
    
    
    Dlsb        .long	(1 << 9)
    Mask12      .long	$fff
    T1          .res1
    T2          .res1
    T3          .res1
    T4          .res1
    Dmask       .res1
    Cmask       .res1
    Smask       .res1
    Enables     .res1
    Command     .res1
    Stream      .res1
    Bits        .res1
    Counter     .res1
    
                    .compress default
    

    the output it produces when run is in my previous post.

    Thanks for the help!

    -Trezitorul
  • dgatelydgately Posts: 1,630
    edited 2015-02-03 10:28
    Change all of your "//" C/C++-style comments to ' comments
    ..start
            .org    0
            mov T1, PAR             ' Read parameters
    
    

    dgately
  • TrezitorulTrezitorul Posts: 68
    edited 2015-02-03 14:45
    Alright, that fixed all the errors from the assembler. However, there were several more errors that I encountered and fixed. Either I am doing something totally wrong or the libpropeller C++ object has a lot of significant bugs that make it unusable out of box.

    As dgately pointed out that comments were the wrong type and fixing those almost let the object compile. However, there is another error at the bottom of the file. The .res1 should be .res 1 .

    e.g.
    T1          .res1
    T2          .res1
    T3          .res1
    T4          .res1
    Dmask       .res1
    Cmask       .res1
    Smask       .res1
    Enables     .res1
    Command     .res1
    Stream      .res1
    Bits        .res1
    Counter     .res1
    

    should be
    T1          .res 1
    T2          .res 1
    T3          .res 1
    T4          .res 1
    Dmask       .res 1
    Cmask       .res 1
    Smask       .res 1
    Enables     .res 1
    Command     .res 1
    Stream      .res 1
    Bits        .res 1
    Counter     .res 1
    

    Once that if corrected everything seems to be in order and the assembler produces mcp3208.o files as would be expected with a successful build of the .S file. However, the overall build fails with the following message:
    SimpleIDE Version 1.0.1
    /home/trezitorul/Documents/SimpleIDE/Learn/Simple Libraries/
    /home/trezitorul/Documents/SimpleIDE/ Updated on: 2015-01-23
    
    propeller-elf-gcc -v GCC 4.6.1 (propellergcc_v1_0_0_2411)
    propeller-elf-as -o lmm/mcp3208.o mcp3208.S
    mcp3208.S: Assembler messages:
    mcp3208.S:0: Warning: end of file not at end of a line; newline inserted
    propeller-elf-c++ -I . -L . -I /home/trezitorul/Documents/SimpleIDE/Learn/Simple Libraries/Utility/libsimpletools -L /home/trezitorul/Documents/SimpleIDE/Learn/Simple Libraries/Utility/libsimpletools/lmm/ -I /home/trezitorul/Documents/SimpleIDE/Learn/Simple Libraries/TextDevices/libsimpletext -L /home/trezitorul/Documents/SimpleIDE/Learn/Simple Libraries/TextDevices/libsimpletext/lmm/ -I /home/trezitorul/Documents/SimpleIDE/Learn/Simple Libraries/Protocol/libsimplei2c -L /home/trezitorul/Documents/SimpleIDE/Learn/Simple Libraries/Protocol/libsimplei2c/lmm/ -o lmm/PullTester1.elf -Os -mlmm -m32bit-doubles -fno-exceptions -fno-rtti lmm/mcp3208.S.o PullTester1.cpp -ltiny -lsimpletools -lsimpletext -lsimplei2c -ltiny -ltiny -lsimpletools -lsimpletext -lsimplei2c -ltiny -lsimpletools -lsimpletext -ltiny -lsimpletools -ltiny
    propeller-elf-c++: error: lmm/mcp3208.S.o: No such file or directory
    Done. Build Failed!
    

    Then I found a really sketchy work around by going to the lmm folder and taking the mcp3208.o file and renaming it mcp3208.S.o as is expected by the compiler for some reason. Is there a more elegant/proper solution to this that I don't know about? (Sorry the documentation for dealing with .S files with simpleIDE is nonexistant as far as I can tell).

    Once all of this is done all is well and my project builds...however, there is another error that pops up. For some reason the way the MCP driver is written right now it seems to overwrite the serial buffer. For example my code is suppose to say "The ADC Value is: %d \n" to the serial port. However, if I start up the MCP driver it outputs strange characters in the middle of the output such as:
    UieC Velue is:04095 
    e EDC Valuu0s 4095 
    The ADC Vqlu is: 4095 
    The QDSalue is: 4095 
    Txe DC Vanue is: 409= 
    he ADC Value is:(4095 
    Thg ADC Valum(is: 4095 
    The ADC(^ilue is: 4095!
    The(ALK Value is;!509 
    \he ADC value!is 40=5$
    


    This happens even if you output a message such as "Hello World" after starting up the MCP. Any ideas why such a thing would happen?

    I am just now learning how to use propgcc but I would be interested in working through the bugs together. Should I start a new thread for debugging the MCP driver in libpropeller?

    -Trezitorul
  • SRLMSRLM Posts: 5,045
    edited 2015-02-03 15:12
    Thanks for trying out libpropeller, and sorry for having so much trouble.

    The first place to look when you're having trouble is the repository. In particular, the Makefile and the unit tests (source). I just ran them for MCP3208.h and they run fine under propgcc version (propellergcc-alpha_v1_9_0_2408) 4.6.1. So we know that it works with one setup. I'm not sure where I can get a propgcc version history, so I can't tell if you have an earlier or later version of propgcc.

    First off, I'm not having any problem with double slash // comments versus apostrophe ' comments. The double slash is compiling just fine.

    Second, the "T1 .res1" that you mentioned at the end appears to be a copy error on your end. If you look at the source you can see that there is a tab in there.

    I think I read somewhere that SimpleIDE doesn't support .S files, although I could be wrong about that. My recommendation is to try compiling from the command line, getting that working, then trying to integrate with SimpleIDE.

    Can you post your current code?

    ps: if you (or any readers) are ever having trouble with libpropeller code please PM me or open an issue on Github so that I don't miss it.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-02-03 18:04
    Your best bet may be to grab a binary distribution of PropWare, find the library (bin/libpropeller/source/<model>/libLibpropeller_<model>.a) and drop it in your project. This library file would replace your .S file. You can then add a link option in SimpleIDE to link to the pre-compiled libpropeller library.

    PropWare binary: http://david.zemon.name/downloads/PropWare_Binaries/PropWare_current.zip
  • TrezitorulTrezitorul Posts: 68
    edited 2015-02-06 15:24
    Hi everyone sorry for the delay...I was learning how to compile using the command line. I think I made some progress.

    The first thing I did was use the assembler to generate the mcp3208.o file from the mcp3208.S and the commenting errors showed up again and were gone when I changed the "//" to " ' ". I am using propgcc version: "propeller-elf-gcc -v GCC 4.6.1 (propellergcc_v1_0_0_2411)". The problem does not occur if I run the makefile included with the mcp3208.h file...is there a flag of some kind in the make file telling it to read the assembly comments as "//" instead of " ' ".

    The other thing that SRLM mentioned was that there was a copy error, and with that I concur I did make copy error so ... disregard my previous comment about the RES 1 spacing error.

    Finally, I did manage to get SimpleIDE to compile and build the whole project. However, I believe there is a bug in simpleIDE in which instead of searching for mcp3208.o which it does assemble correctly it searches for mcp3208.S.o which is incorrect. I went to the lmm and cmm folders of the project and simply renamed my mcp3208.o files to mcp3208.S.o and the project builds and compiles now. I have other issues but that solved the build issues. Does anyone know where I should report the bug in simpleIDE? Or ...if it is a bug at all? Oh and just in case it helps my simpleIDE version is: 1.0.1 (RC1) the latest version as far as I can tell.

    I have gone ahead and just zipped up the whole project directory to show the renaming of the mcp files. I have another issue which I described in my previous post regarding the serial output getting trashed by the mcp3208 being started...I honestly have no idea what could be causing that since theoretically the mcp code and the serial output are running on entirely different cogs. Is it possible that the i2c driver which is being used to communicate with the MCP is interfering with the serial output?

    And thank you everyone for your help! The mud is beginning to clear!

    Pull Tester.zip
  • SRLMSRLM Posts: 5,045
    edited 2015-02-06 21:00
    The problem is line 15 of your PullTester1.cpp file:
    mcp.Start(31,29,30,0xFF,-1,-1);
    

    You're starting the MCP3208 on pins 29,30, and 31. That's not allowed. Those pins are reserved for I2C (28 and 29) and USB host serial (30 and 31). You'll need to put the MCP3208 on another set of 3 pins (any are fine).

    The MCP3208 is not I2C. It's an SPI device.

    For compiling I much prefer to use a makefile and Netbeans or (my new favorite) CLion. So, I can't provide much support for SimpleIDE usage except to say that since you got it working with the rename you might as well continue with that. The ASM file shouldn't ever change, so you don't really need to have it in your build system.

    Also keep in mind that libpropeller (and PropWare?) is designed for a single step compilation and linking (a single translation unit) to fully optimize the result binary. So you'll get slightly smaller binaries by using a makefile similar to what's in the libpropeller library.
  • TrezitorulTrezitorul Posts: 68
    edited 2015-02-07 13:27
    Wow thanks! From the deep recesses of my mind I was beginning to vaguely remember that those pins were dedicated to serial (I moved them and all is well now). I also discovered the magic of make files and its amazing what they can do!

    I am curious if you could elucidate a bit further what you mean by single step linking and compilation. Also how does one use the make files in the libpropeller library, do I just copy them and modify them to add my source files to them for a new project or is there a better way to do this?

    Thanks for all the help everyone!

    -Trezitorul
  • SRLMSRLM Posts: 5,045
    edited 2015-02-07 17:38
    For C++ programming on the Propeller I prefer to use single step compilation and linking. What this means is that, every time I make a change to my program, I compile it from scratch in a single `propeller-elf-g++` command.

    This is different from pretty much every other example has you do. Those other examples would prefer that you compile .cpp source files into a .o object file, then link those together to build the final program.

    My approach is to give the entire program (all *.cpp, *.h, and *.S files) to a single call of the GCC. This has two benefits:
    1. Saves a few hundred bytes or so, due to increased optimization opportunities
    2. Makes the most of inline headers, whose justification I set out here.

    C++ tutorials recommend against this approach with a passion bordering on vehemence. But there's pretty much one reason why they want to do that: because compiling a big program takes time. But large PropGCC programs are physically impossible, and hence compilation times are always short. So, it makes more sense to get the most out of every byte, and that's what libpropeller was designed for from the ground up.

    As a side benefit, makefiles get really simple. It's easy to just pass `*.cpp *.h *.S` to your compilation command and let GCC work out the details. No more dealing with writing all the rules for your makefile.

    The libpropeller makefile is a good place to start. Just strip out the unit testing relevant stuff (the UNIT_TEST and ruby stuff), and set it up to pull the sources of your project. It has all the compilation flags that I've found to work best with PropGCC for the smallest binary size.

    Anyway, other than the building and liking approach the same general structure of a makefile applies. Rules, variable replacements, and tabs for indentation, etc. Any makefile tutorial would be a good place to start to get up to speed on that aspect.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-02-07 20:26
    SRLM wrote: »
    Also keep in mind that libpropeller (and PropWare?) is designed for a single step compilation and linking

    I did not try to do that when PropWare moved to CMake.

    Glad to hear we have another CLion fan! :D
Sign In or Register to comment.