Propeller assembly in a cog, interfaced to either Catalina or propeller-gcc.
Fastrobot
Posts: 51
Hi,
I've got a CNC stepper driver program written in assembly language, which is meant to run two stepper motor axii from each COG for up to 10 axii simultaneously on 5 Cogs. These cogs are meant to be slaves of a C program (a master spooler program) which feeds motion vectors to them.
Since I'm trying to port this from another muti-processor platform, I don't know SPIN and don't really want to learn and rewrite my program in Spin if I can avoid it -- especially since I already have the main program in C, and spin is very *slow* compared to assembly language for timing critical operations.
Catalina seems to allow me to load assembly programs into a cog using a _coginit( (int)data_structure>>2, (int)code>>2 ); call, but there is no documentation on how to generate a PASM binary from assembly code that originates correctly at address 0, and resolves relative symbols within the aseembly language module without confusing them with global C varaibles, etc. Rather Catalina's demos show an example where someone had the code already written to an array like: unsigned long code[] = { 0x68ffec01, 0x64ffe801, ... }; which means a miraculous step was omitted where an assembler someplace generated those numbers ... which means I need an assembler ... but I don't see any stand alone assembler anywhere in Catalina or propeller-gcc (EDIT: yes! propeller-elf-as exists--but no docs...), or documentation for one, and nothing obvious in prop-gcc learner modules, either.
So: How can I create a the binary pattern/array for a stand alone, independent assembly language program, which can be loaded into a cog by a C program but whose addresses and labels are NOT part of the C program, and does not run on the C core ?
if I were to try using *inline* assembly, say in a C function, or use the prop-gcc run_cog() command, then the assembly language, as far as I can tell, would be running on the C core -- and not independently. eg: The C compiler would want to link the local inline assembly variables to the main C program, and Jump addresses would likely be wrong as they would be in hub memory -- and it's not really a hand written and independent assembly lanugague program anymore, meant to run by iteself in a COG but something being run on the C interpreter/loader core.
The program I want to run has an extremely simple interface where the 'par' register points to a C structure (in hub ram) of three longs and that *alone* is the complete interface through which all information comes to the slave Cogs from the main program/spooler: eg:
typedef struct { long command; long data; long synchronizeStatus; } stepper_interface;
stepper_interface queue[5];
So, what I want is to be able to do something like: _coginit( (&queue[0]) >>2, (&my_program_is_here)>>2 ); and my program will automatically link itself to the main C prorgam through the data structure called queue.
But I don't know how to covert an assembly language program into a byte stream called 'my_program_is_here' that I can embed portably in a C program.
To be very clear, here is a skeleton outline of the assembly language slave program I need to load into cog ram and execute:
How can I turn a program like that one into an array of longs using either the tools in propeller-gcc, or in catalina ?
I've got a CNC stepper driver program written in assembly language, which is meant to run two stepper motor axii from each COG for up to 10 axii simultaneously on 5 Cogs. These cogs are meant to be slaves of a C program (a master spooler program) which feeds motion vectors to them.
Since I'm trying to port this from another muti-processor platform, I don't know SPIN and don't really want to learn and rewrite my program in Spin if I can avoid it -- especially since I already have the main program in C, and spin is very *slow* compared to assembly language for timing critical operations.
Catalina seems to allow me to load assembly programs into a cog using a _coginit( (int)data_structure>>2, (int)code>>2 ); call, but there is no documentation on how to generate a PASM binary from assembly code that originates correctly at address 0, and resolves relative symbols within the aseembly language module without confusing them with global C varaibles, etc. Rather Catalina's demos show an example where someone had the code already written to an array like: unsigned long code[] = { 0x68ffec01, 0x64ffe801, ... }; which means a miraculous step was omitted where an assembler someplace generated those numbers ... which means I need an assembler ... but I don't see any stand alone assembler anywhere in Catalina or propeller-gcc (EDIT: yes! propeller-elf-as exists--but no docs...), or documentation for one, and nothing obvious in prop-gcc learner modules, either.
So: How can I create a the binary pattern/array for a stand alone, independent assembly language program, which can be loaded into a cog by a C program but whose addresses and labels are NOT part of the C program, and does not run on the C core ?
if I were to try using *inline* assembly, say in a C function, or use the prop-gcc run_cog() command, then the assembly language, as far as I can tell, would be running on the C core -- and not independently. eg: The C compiler would want to link the local inline assembly variables to the main C program, and Jump addresses would likely be wrong as they would be in hub memory -- and it's not really a hand written and independent assembly lanugague program anymore, meant to run by iteself in a COG but something being run on the C interpreter/loader core.
The program I want to run has an extremely simple interface where the 'par' register points to a C structure (in hub ram) of three longs and that *alone* is the complete interface through which all information comes to the slave Cogs from the main program/spooler: eg:
typedef struct { long command; long data; long synchronizeStatus; } stepper_interface;
stepper_interface queue[5];
So, what I want is to be able to do something like: _coginit( (&queue[0]) >>2, (&my_program_is_here)>>2 ); and my program will automatically link itself to the main C prorgam through the data structure called queue.
But I don't know how to covert an assembly language program into a byte stream called 'my_program_is_here' that I can embed portably in a C program.
To be very clear, here is a skeleton outline of the assembly language slave program I need to load into cog ram and execute:
DAT org '' Assembly routine to output quadratures or step & direction pulses. begin rdlong temp,par '' Initialize prescalar offsets from 'Command' member. neg temp,temp '' add temp,#28 '' movs PS0,temp '' Hardcode prescalar offsets in self modifying code. add temp,#2 '' movs PS1,temp '' mov dataMem, par '' Precompute Data & Sync member pointers. add dataMem, #4 '' data=&par[1] mov syncMem, par '' add syncMem, #8 '' sync=&par[2] rdlong outputPin,dataMem '' setup outputs for step/direction/quadratures mov temp,#3 '' shl temp, outputPin '' mov dira, temp '' wrlong inSync, syncMem '' Write the zeroed sync in mem. neg outputPin,outputPin '' Compute backshift outputPin add outputPin,#28 '' waitpeq firstTrig, firstTrig '' Indicate cog awaits init. mov inSync, inSyncStart '' NotRunning + cleared Qs. jmp #Axis0 '' Begin operations. firstTrig long 2 '' ------ CONSTANTS ----- sgnExt long $FFFFFFFF axis0R long $01000000 '' Axis0 is Runable. axis1R long $02000000 '' Axis1 is Runable. axis0U long $00000007 '' Axis0 is Usable mask. axis1U long $00000700 '' Axis1 is Usable mask. inSyncStart long $FCFFFFFF '' not running, but now in use constant. combMask long $50000000 PSM0 long $30000000 PSM1 long $C0000000 {{ Lots of assembly language to do encoder/step direction counts goes here }} PS0 shl temp, #28 ''19 and temp, PSM0 ''20 {{ lots more code would go here... but omitted....}} '' --------------------------------------------------------- END OF TRAJECTORY LOOP '' Totaly zero data-block; these are state variables, local to the COG. axis0Tn long 0 ''Reg 0 Time of next motion axis0An long 0 ''Reg 1 Acceleration of next motion axis0Vn long 0 ''Reg 2 Velocity of next motion axis0PH long 0 ''Reg 3 Position of next motion axis0T long 0 ''Reg 4 Presently executing motion's Time. axis0A long 0 ''... Acceleration axis0VL long 0 ''... Velocity axis0PL long 0 ''... Position axis1Tn long 0 " Same as above, but for second axis.... axis1An long 0 axis1Vn long 0 axis1PH long 0 axis1T long 0 axis1A long 0 axis1VL long 0 axis1PL long 0 triggerX long 0 '' Reg16 Simultaneous trigger of all axii. unSync long 0 '' Reg17 Force the sync to use these. axisEN long 0 '' Reg18 Enable axii beyond 1 cycle. inSync long 0 '' Reg19 tracking data for what is queued. temp long 0 '' Reg20 outputPin long 0 '' Reg21 output pin offset. combine long 0 '' Reg22 Where to combine outputs for the axii. axis0VH long 0 '' Reg23 sign extension for velocity. axis1VH long 0 '' Reg24 register long 0 '' Reg25 dataMem long 0 '' Reg26 syncMem long 0 '' Reg27
How can I turn a program like that one into an array of longs using either the tools in propeller-gcc, or in catalina ?
Comments
With .S assembly files:
https://github.com/libpropeller/libpropeller/tree/master/libpropeller/pulsewidthreader
https://github.com/libpropeller/libpropeller/tree/master/libpropeller/pwm2
https://github.com/libpropeller/libpropeller/tree/master/libpropeller/quadrature_encoder
https://github.com/libpropeller/libpropeller/tree/master/libpropeller/serial
With binary blobs:
https://github.com/libpropeller/libpropeller/tree/master/libpropeller/pwm32
https://github.com/libpropeller/libpropeller/tree/master/libpropeller/sd
With inline assembly:
https://github.com/libpropeller/libpropeller/blob/master/libpropeller/i2c/i2c_base.h
The assembly is assembled during the makefile, and PropGCC automagically creates a global variable called `_load_start_XXXX_cog`, based on the following line at the beginning of your .S file:
In your C/C++ code, you can then do:
The `someVariable` is your shared memory (mailbox) for communication.
For assembling and compiling the whole business, I like to just throw all my .cpp, .h, and .S files at propeller-elf-g++ and let it sort it out (with the --Wl,--gc-sections flag to optimize) rather than dealing with a real Makefile. You can see that approach here.
Alternatively, you can pre-assembly the assembly and include that directly as a binary blob. I don't really like doing that, although I have on a couple of occasions (I think there was some issue with having the assembly out for those? I don't recall).
Inline assembly can also be a good choice if you don't really want to dedicate a whole cog to the task, and your "master" cog will be blocking on the slave cog anyways. In that case you might as well run the I/O in your master for which assembly is a good choice. I2C is an example. In the inline assembly code linked above, note that it runs in the cog natively, with no PropGCC stuff in the way (via forced FCACHE). That little piece of code is what I'm most proud of out of the entire libpropeller code base.
There are examples (look for plugins IRC) in the latest Catalina.
Does Catalina compile your C program? Are there interrupts in your C program (because the propeller doesn't have interrupts)?
Of course there is now also PropGCC but I haven't used it so cannot help you here.
By someone else's recommendation, I created a function at the bottom of my assembly file which does the cognew for me. I like this solution a little more than the alternative because the C file depends on an symbol whose name is explicitly defined rather than a file name. It also ensures the assembly file gets linked in and you don't find yourself fighting linker issues down the road.
https://github.com/DavidZemon/PropWare/blob/release-2.0/PropWare/spi_as.S#L526
I began looking at plugins, although that's a farily complicated system that requires the use of SPIN to register it, etc. I would rather not use something so proprietary if I can avoid it. Catalina is able to do inline assembly, so it *should* be able to create cog code in a manner similar to the inline example shown for PROP-gcc in SLRM's post. The problems are going to be associated with linker issues and compression (if any); eg: if there a possibility of multiple BSS sections, or of symbols from different inline assembly code being resolved to a single address when multiple separate addresses are intended (local vs. global variables.) then these collisions are what I am concerned about screwing things up.
Yes, Catalina compiles the C portion of it just fine. There are no interrupts, and never were. The code originally ran on microchip 8 bit processors without any interrupts, mulitplies, etc. It's just going to be far more efficient, faster, and cost effective to run on a single propeller chip rather than 12 microchip MCU's with all the wiring between them. I get 10 axii / propeller + a PLC to boot for less cost. I just have to re-write the assembly language code for the trajectory execution (basically cycle counting, and position delta's addition...) into propeller assembly, which isn't hard for such a simple program.
Both propeller gcc and Catalina have problems, although the PropGCC is showing promise at being a more robust solution at the moment, having less show stopper bugs; but mostly its' just documentation issues that are making it hard to figure out how to get this working on either system.
I like Catalina quite a bit; for Catalina can be run from any directory on my linux machine, so I can happily place it on a memory key and take it with me from place to place, esp; if I am talking to professors at universities and don't have superuser privileges to install it on their machines with. Catalina will run from a user directory just by setting an environment variable. But ... Unfortunately, Ross hasn't got the latest version debugged for 64 bit linux's (See my post here http://forums.parallax.com/showthread.php/153750-Catalina-3.13.2-smaller-and-faster-better-IDE?p=1324802&viewfull=1#post1324802 ) -- so Catalina as hosted on Sourceforge can't download to QUICKSTART boards from a 64 bit linux machine right now.
However, PropGCC is linux flavor dependent -- basically packaged for UBUNTU, and requiring to be installed in the /opt directory with root privileges. But I *REALLY* like to have my tools installed on a USB key in a generic way.... not on the system root. just FYI, and for others who may want to try PropGCC on many other flavors of Linux: I am able to install it on other versions of Linux -- just got a generic tar file for PropGCC from the Ubuntu .deb by manual extraction; eg: "ar -x simple-ide_1-0-1-rc1_amd64.deb ; tar -xf data.tar.gz"; and then I had to copy the system's libncurses.so.5 to the memory key where I untarred simple-ide, but with ncurses renamed as libtinfo.so.5, to be found with the environment variable LD_LIBRARY_PATH="/media/memory1/.local/opt/parallax/bin" all because PropGCC is linked against a nonstandard library name. But even with the LD_LIBRARY_PATH set, only the command line tools in opt/parallax/bin are usable. The graphical IDE is too dumb to figure out that it has been installed in a different directory than /opt, and will start up -- but not load a project, or compile anything; and nothing in the instructions shows how to set an environment variable to get it to work...
Nothing short of building a changeroot environment (basically a bad idea for portability reasons) will allow PropGCC to be installed on a memory key that I can take from computer to computer at a university and use and share with friends. That's it's primary downfall... not portable.
But, on the other hand -- the command line tools at least work, so I can take code compiled on Catalina and load it into a propeller using PropGCC's propeller-load program. Without that, I wouldn't be able to use Catalina or PropGCC -- so as I said, they both have problems.
Thanks David, that's a really good example of how to write a C function in assembly language to load the separate assembly language module but be inside the same .S file and be automatically linked together with no scripting glue or Makefile required....
Very helpful!
Your examples are excellent.
How did you make the binary blobs, though ?
I figured out, last night, that I can compile a prorgam using ./propeller-elf-gcc -mcog -nostartfiles ${f}.S # create an a.out file.
and then use readelf to get a hexdump of the .text section and turn it into a binary blob C file, using sed and grep to fix the byte order issues:
So, the script I wrote auto-generates a file changing the .S of the original assembly name to -S.c, so it can be used like: #include "myfile-S.c"
I compile using gcc so that the macro-preprocessing (cpp) is available in my source code, and I see you can do the same with g++ if so desired, not that c vs c++ matters for an assembly language file....
I think the .S file is probably the way to go, over using inline assembly, as Catalina and PropGcc use different ways of implementing the _asm_ directive ; but they both seem to accept propeller assembly in .S files OK.
Is there a simpler way to automatically generate the blobs using command line tools included in PropGcc?
I tried bin2c , but it converts the WHOLE file not just the .text section into a binary blob, and that's not a good idea....
You are into Linux and C way more than me. We use Catalina for a 3prop professional solution although I only interfaced the spin/pasm section to the c section.
Since you can compile both GCC and Catalina to do your job (but not Catalina on a 64bit linus machine), you might just be able to compile the C section as standalone.
Then start your objects with spin and then load the compiled c program. You can do this with Catalina, so presume you can also do this with GCC.
The binary blobs are from the original spin2cpp conversion of those objects. You could look there to see how it does the conversion. Like I said, I don't really like the binary blob solution but I haven't had a chance to update those objects and I included it for completeness. I much prefer to just toss the .S file to propeller-elf-g++ and let it deal with it.
mmm... I see. I agree -- the .S file is much nicer. It's easy to read, edit, and link by mere inclusion to GCC compile line, or Catalina's.
The binary blob is just one way that I know is compatible between PropGcc and Catalina, so I wanted to know how to do it. Both systems have the ability to do either _coginit() or cognew() to launch arbitrary binaries into a cog after #include <propeller.h>, although the calling conventions differ I can use a few #defines, to make one source code file work on Catalina and PropGCC just fine.
Catalina, now that I'm looking carefully -- has a program "spinc" -- which converts a spin objects to a "C' array binary blob, but when I check for a program called spin2c* or spin2cpp, in the PropGCC package, I don't find it; eg: I'm using simple-ide-1-0-1-rc1_amd64.deb -- so I guess making a binary blob via. spin2cpp is not going to be supported by default in the gcc tools.
So -- I'll just keep my own script, then.
On the other hand, The .S files, do have a few compatibility gotchas.... let's see if I can work through them:
Catalina does accept .S files, but as far as I can tell -- they must be in PASM format, GAS format is not an option, and PASM doesn't accept .section, .compress, or fcache directives, or 0x hex prefixing. Worst of all, Catalina refuses to do C pre-processing on .S files passed to the C compiler. darn.
So, to be more compatible -- I ought to write my assembly in pure PASM with no preprocessor macros.
That brings up a question, will GCC compile PASM files flawlessly? David's example (SwimDude0614) above included an assembly language directive to indicate PASM was being used; eg: .pasm , but when I try adding that directive -- both Catalina and propeller-elf-gcc reject it as invalid.
Is it no longer necessary ?
I seem to be able to compile this just fine on either Catalina, or propeller-elf-gcc ; am I reasonably safe, or are there known issues I should be aware of?
Secondly, you used a fcache directive in your assembly language examples.
I assume that is to force the entire image to be loaded into hub ram at once, or something, so as not to have a fragmented piece of code when loading from external eeprom/SD memory?
And, the compress directive is intended to prevent automatic optimizations that can be decompressed by the C-core, but are not runnable directly on a propeller COG?
Is there a way to compile a .S file into a .o file with command line switches to do the same things as those directives, or do I have to edit the file by hand each time I want to move it back and forth between Catalina and PropGcc?
With PASM, if it works at all it probably works just fine. You can always compare the binaries to be sure though. In regards to `.pasm`, there was some discussion about it's necessity and use. I forget what that resulted in, so I'll let someone else chime in on that.
The fcache is a PropGCC feature to load up a block of assembly code from the hub to a cog, and run it there. It allows you to get native speed for code that's part of a larger LMM or CMM* program. I use it in the I2C examples so that the clock can run at 400kHz and the timing is as exact as possible, while still being "just a function" to calling C programs.
* fcache is probably used in the XMM models, but I never use those so I'm not sure.
Native assembly code that you launch with `cognew()` won't use fcache: it's only relevant for CMM, LMM, etc.
The `.compress` directive is to make it the assembly work right when you're using CMM for the rest of your program.
Most of the directive issues that you can use with PropGCC assembly has to do with figuring out what address to use (cog, hub, or program) in which situation. It can get a bit tricky trying to figure out where everything refers to. I don't think you can get around the directives.
I'd also suggest getting a newer version of PropGCC than the one bundled with SimpleIDE. That one (the 1.0 release) is pretty ancient. The current default tree has a much better assembler that will accept PASM code (with either the .pasm directive or a -pasm command line option) instead of GAS syntax. The main difference is the handling of addresses: in GAS mode addresses are always byte addresses, even inside COG memory. This matters if you do arithmetic on labels: something like "foo+1" in PASM would have to be written as "foo+4" in GAS mode (but as I said the new gas does have a compatible PASM mode where "foo+1" works the same as in PASM). -pasm also tells the compiler to ignore Spin statements, so you can pretty much just feed it .spin files and get the assembled PASM code out.
Eric
(1) The .pasm directive is for PropGCC 1.9 and later. In PropGCC 1.0 (the one included with SimpleIDE) there was a .cog_ram directive that was kind of similar but much more limited. You had to be very careful about any arithmetic on labels in the PropGCC 1.0 assembler -- basically I would suggest avoiding that. The new assembler allows you to use a -pasm command line option instead of the .pasm directive.
(2) The .compress directive is for CMM mode. With .compress on the instructions are compressed, but have to be decompressed by the CMM kernel -- they cannot be directly executed by hardware. So in CMM mode you have to be careful to put ".compress off" in front of any code you plan to load in to a COG. If you're not using CMM you can omit the directives.
I'd love your help testing this new build of PropGCC. Go here (click "log in as guest") and then download the artifact for PropGCC gcc4-linux-x64 (assuming you're on a 64-bit machine... I don't have 32-bit linux builds yet). That page will always have the most up-to-date and stable version of PropGCC
Since you are using SimpleIDE, post 65 in the link below shows a way to include PASM code from a Spin object into a C program. So you could write a simple spin program that declares the variables in order that you want to transfer to the PASM and call the PASM cog, and have the PASM program in a dat block. Then call the PASM from the C program. The entire thread shows me being taught how to do this, along with my errors and successes.
http://forums.parallax.com/showthread.php/157441-Can-SPI-in-Simple-Libraries-be-speeded-up/page4
Post 22 in the link below is another example. Since only one array variable was transferred for each call to the PASM, it wasn't necessary to define a structure.
http://forums.parallax.com/showthread.php/134106-Updated-17seg-LED-driver-for-PPDB-now-available./page2
Hope this helps.
Tom
Unfortunately the IDE portion of SImpleIDE does not work. I need to take David up on testing the next version of it...
I looked at your examples, but I'm not sure how you made the binary blobs -- unless you mean, you made them with some button on the IDE, or it does it automatically.
I have a method that works and is compatible with PropGCC and Catalina both, and so it should also work in the IDE.
Perhaps you can tell me, if you have a working copy of the SIMPLE-IDE whether or not you can compile my example program.
The major problem I've been encountering is that the Catalina preprocessor is somewhat broken, and I can't make automatic linkage macros that I can just type a name into and have it produce a header file -- rather I have to hand edit it for Catalina. I would love to have just used the method in post #2 of this thread, but unfortunately PropGCC makes variable names in excess of 16 characters -- which also causes spinnaker in Catalina to bomb out with undefined variable name errors. So the best I can do is a hybrid method that uses post#2's majic, but automatically store the hub load address in a shorter global variable name which both Catalina and PropGCC are happy with.
I'm open to suggestions on how to make this cleaner... but at least it works.
There are three files, a compatibility header: "gcc2catalina.h", an assembly language driver to run on a cog, and a C program to load the driver.
File names are listed at the start of each code snippet.
From the command line, it compiles and runs by one of two ways:
. use_catalina
catalina test.S stest.c -lc
payload -z -t 1000 test
Or using PropGCC from the command line:
propeller-elf-gcc test.S stest.c
propeller-load -r a.out
I'm not sure how to do it in an IDE.
I am posting from an Android tablet, so I'm not able to test your code.
I apologize that the code shown in post 65 did not have everything needed to show how my code works.
The binary blob is made and loaded from a Spin file that is added to the SimpleIDE project. All my code showed was the PASM part of the spin file. A full copy of the modified spin object is in libspipasm v2.zip in post 70 of that thread. The file name is xSPIAsm.spin. That file should be added in "project" view to the project (left hand window).
The C program and SimpleIDE does not use the spin part of the program, but loads (assembles?) the PASM code into a cog using the lines:
The structure that is declared before main () contains the variables for the PASM in the order they are needed (which was originally established in the spin object). When I wrote the C code my intent was to just use a preexisting spin/PASM object as a black box. The original spin object comes from the library that is provided with the proptool. I did have to slightly modify the PASM because the initialization parameters (clockstate and clockdelay) were assigned in the spin portion of the object which couldn't be used in the C program.
Tom
Oh, I see ! So -- PropGCC is actually a separate project from SimpleIDE and you have builds for the GCC portion.... Up until now, I was thinking that as they were packaged together in the simple-ide release that it was all one code base... but I need to upgrade parts of the package separately. OK.
So, Basically, PropGCC command line tools can run from a USB key -- it's just the GUI/IDE which seems to be hardcoded to run properly only from root install.
I notice, in the package I have now -- simple-IDE-1.0.1's "propeller-load -r -g " GDB command doesn't work (doesn't recognize -g); so is the flag working in the package you list as gcc 4 -- ? or do I need to get the gcc 5 release ?
Also, one other question -- the linker auto-generates a variable _load_start_XXXX_cog , but of course, that symbol isn't available at the time the assembler is generating objects. So, I had to use a linker trick to shorten the linker name for compatibility with Catalina; but I'd like to add a line to the linker script so as to auto-generate a shorter name automagically... but when I did a search for linker scripts with find . -iname '*.ld" I came up blank. Where does PropGCC keep the default GNU linker scripts for the targets, and how are they named ?
and one other bit of feedback... as a linux user, I tend to type pr [tab] in order to get linux autocomplete to do the compiler type as quickly as possible, I expect it to produce propeller-elf- and then I finish by typing gcc or nm or whatever.... So: It's a bit of a pain to have an inconsistent name, eg: propeller-loader in the same directory, as that stops autocomplete early and requires extra typing for all tools which are used more often than the loader.... propeller-load is still an elf binary system, even if it loads other binary types as well. It would be more convenient to have it also named propeller-elf-load ; is there a particular reason it isn't named that way ?
Now you got it
As for gdb, that must be run separately. Here's what I use for running GDB (not that I do it very often, as it is only moderately helpful) Taken from here
You on the other hand, have a version which supports -g , but no gdb executable. It's like dutch doors, half way -- either way.
I'm trying out the gcc 4 version from your repository.
The tools you do have for x86_64 appear to be working fine, although I still can't find any gcc/ld default linker scripts.... weird.
Just as a note, though, I have multilib installed so I can do 32 and 64 bit binaries, so my test won't catch things that require a 64 bit clean environment.
I just installed BTRFS, though, so I can do a snapshot of my stystem and uninstall all 32 bit compatability stuff later this week on the backup snapshot -- eg: to make sure it fully works for 64 bit only systems. I'm absolutely loving linux kernel version 3.18.9 ! Lots of bug fixes, and a union file system built in without needing to patch the kernel. YAY!
I wonder if I can take the PROP_IDE1.0.1 executable for GDB and run it with your executable for propeller-load....
We'll know in a few minutes.....
David - the 32-bit Linux issue probably needs to be addressed in the propgcc thread some day. I'm not too worried at the moment though since all my stuff is 64-bit :P
I have a special install script program that takes the slackware 64 bit and 32 bit distributions, and runs a diff on each file in the packages. It then removes all duplicate files, and any files (eg: binaries) which are in the same directory but conflict in elf size, so the 32 bit version gets moved to a /32 subdirectory.
Pretty much, I install linux twice on the same hard drive but save space by deleting all duplicate files. Since linux installs 64 bit binaries in /usr/lib64 and 32 bit binaries in /lib -- there's no conflicts in libraries, and any programs which expect 32 or 64 bit libraries find them exactly where they ought to. So, I can run 64 bit or 32 bit binaries on the same system with little or no problem, but if I want to single out 32 bit executables for system tools -- I have to change the path that I search for executables in. Slackware comes with a multilib capable version of GCC, so If I Set a few enviornment variables, eg: a path script found in Slackware in /etc/profile.d/32dev.sh -- that tells gcc where to look for 32 bit files instead of 64, then wallah... everything compiles 32 bit instead of 64 bit. It's not too hard -- just confusing at first.
He's already testing it for you on a 64 bit clean machine, so I really don't need to.
As long as you don't hardcode the paths, I'm happy to test and work my system around to suit the binaries available.
About the program GDB, It does run -- but doesn't communicate with the propeller. I copied over both propeller-elf-gdb and gdbstubs.
After GDB starts, When I tell it to 'run' it doesn't know the target. No error messages appear.
So GDB needs some kind of initialization file somewhere that I don't see a copy of. The site you mentioned doesn't seem to show an init file anywhere obvious on that page...
Normally, a system being debugged by GDB over a serial line or a TCP/IP connection runs a monitor program on the embedded device, and then GCC talks to it by using the target command, eg: "target remote 127.0.0.1:3000" or perhaps "target /det/ttyUSB0". I tried the latter one, as that's where the propeller is located -- compiling the last example program from a few posts back as: propeller-elf-gcc test.S stest.c -g
When I loaded it, I was told it was "patching for debug at offset 0x774" so, it's primed for debugging -- but when I tried "target /dev/ttyUSB0" GDB complained that it received:
NOTE: Your tools happily produce -g and even -ggdb3 files, but the propeller loader only recognizes the -g file, otherwise it produces an "error: unable to debug this ELF file: __ccr__ symbol missing"
So, we're close -- but there seems to be a problem in the communications target of gdb and I don't know what target protocol to tell gdb to use.
Edit: AHA! Perhaps it's a pipe to a communications program?
target remote |gdbstub
It seems to work, but for some reason it 'starts' at the exit() function ?!
That's not good...! I can't debug anything beginning from exit() !!
nope... although I do understand about the hub ram vs. processor ram confusion. When I did object dumps to see how my code was linked... it would give kernel symbols for addresses below 496*4...
This is what continuing makes happen:
And I did it a second time, after freshly propeller-loading the file again, and without doing a break before setting the target.
Whatever is wrong, at least it is *very* repeatable.
I'm also not quite sure what is going on with the gdb disassembler. That code looks suspiciously like exit code to me... but when I do an propeller-elf-objdump -d a.out | less
I can't find that fragment of code anywhere in the program.
What is GDB actually dissasembling?, and what is the breakpoint address ? that of execution in hub ram or cog ram ?
Well, I don't think GDB is the problem here. By inspection, I can tell it's disassembling hub ram just fine, and able to find registers and change the PC, too.
There's a small blob of nonzero memory in the first 0x278 addresses, that's roughly 632 bytes. Then it's all zeroes until addres 0x8000 -- which is where the parallax propeller Character ROM, etc. area starts. That tells me right away, when my .nocompress program bytes can't be found anywhere in memory, but the character shapes CAN be found -- that the propeller-loader is malfunctioning, not GDB.
propeller-load says that it's downloaded 3260 bytes, and patched at 0x774 -- but that much information is not present in memory.
Hence, I'm pretty sure that the monitor program loaded -- and the rest did not, or else it was erased and replaced by the monitor program.
I am not sure how the monitor runs, but -- basically -- if the monitor program is running in a COG, by itself, I should be able to erase hub ram without crashing GDB. When I type, "load a.out" in GDB -- it says it downloaded the code into ram, and the monitor does not crash -- so far, so good... and when I do a dis-assembly, I now find the code matches what "propeller-elf-objdump -d a.out" says it should be. SO -- the problem isn't GDB. The problem was expecting propeller-load to load the program AND the debugger monitor together. It doesn't.
Now, the question is -- what was propeller loader trying to patch, and what can and can't be done with the monitor program as it is...
Oooohh.... that sounds like it might be a bit of large project at the moment, and maybe un-necessary work...
eg: GDB already understands all elf versions, and is capable of loading a program in to the propeller using the monitor program by itself.
So, if I want to use ggdb3 -- I should be able to load a dummy program with -g compiled on it, and then use gdb to re-load my actual program compiled with ggdb3. There's no reason to load ggdb files except when debuggging -- so it's not really a problem to do it through gdb anyhow. Almost everything can be done in an automated way with a gdb startup script...
What, exactly, is the the loader trying to "patch", anyway? If there is source code for it, then I think it might be something that we could more easily accomplish by simply calling the gnu tools linker, ld,during compile time, to add it to the program. eg: it's not uncommon to have debug libraries on modern computers, so -- it shouldn't be strange to be able to link in a debug "C" kernel if necessary.
Are there documents you might point me at, showing what exists of the gdb debugger monitor program ?
It might be something I could do in a matter of hours, if it can be done with the normal compiler and linker tools....