[PropGCC] Symbols clashing when compiled into COG module and CMM/LMM module in the same binary?
DavidZemon
Posts: 2,973
I can share more specific code, but here's the gist of it:
Main.cpp - This is compiled as CMM or LMM
driver.cogcpp - This is a COG module, compiled with the "-mcog -xc++ -r" flags
This code works. I see "Hello, world!" printed at the console.
But if I uncomment the constructor in my cog module...
driver.cogcpp - This is a COG module, compiled with the "-mcog -xc++ -r" flags
The console no longer shows anything.
If I take the contents of uart.h, which looks something like this:
uart.h
and copy them directly into driver.cogcpp, I get exactly the same results (no real surprises here... I just wanted to be sure.
So now driver.cogcpp looks like this:
But I can get it working again by changing the symbols. The easiest way to do this was remove the PropWare namespace around the UART definition in driver.cogcpp:
Now, I don't think this should be necessary. I think GCC should be smart enough to recognize that, though these are named the same in source code, the symbols should be different because they are compiled with different memory models. But my tests show that isn't the case. Is this a bug in PropGCC? Maybe better described as a feature request? Or is there something else I'm misunderstanding?
Main.cpp - This is compiled as CMM or LMM
#include <uart.h> using namespace PropWare; int main () { UART tx; tx.send_array("Hello, world!\n"); return 0; }
driver.cogcpp - This is a COG module, compiled with the "-mcog -xc++ -r" flags
#include <uart.h> using namespace PropWare; _NATIVE int main () { // const UART tx; }
This code works. I see "Hello, world!" printed at the console.
But if I uncomment the constructor in my cog module...
driver.cogcpp - This is a COG module, compiled with the "-mcog -xc++ -r" flags
#include <uart.h> using namespace PropWare; _NATIVE int main () { const UART tx; }
The console no longer shows anything.
If I take the contents of uart.h, which looks something like this:
uart.h
namespace PropWare { class UART { ... }; }
and copy them directly into driver.cogcpp, I get exactly the same results (no real surprises here... I just wanted to be sure.
So now driver.cogcpp looks like this:
namespace PropWare { class UART { ... }; } using namespace PropWare; _NATIVE int main () { const UART tx; }
But I can get it working again by changing the symbols. The easiest way to do this was remove the PropWare namespace around the UART definition in driver.cogcpp:
using namespace PropWare; class UART { ... }; _NATIVE int main () { const UART tx; }
Now, I don't think this should be necessary. I think GCC should be smart enough to recognize that, though these are named the same in source code, the symbols should be different because they are compiled with different memory models. But my tests show that isn't the case. Is this a bug in PropGCC? Maybe better described as a feature request? Or is there something else I'm misunderstanding?
Comments
This only work for code within the PropWare namespace though... not good.
If your UART class has static data members though, then there can still be conflicts, and I'm afraid that there's not much we can do there. COG and "regular" code can share data and that's as designed, but if the COG version and non-COG version handle the static data differently then they will conflict.
Regards,
Eric
PropellerCogLocalizeSymbols.txt contains:
There are static variables on the UART class, but they are all declared const.
(1) The UART class in PropWare looks to be abstractl. I presume you're sub-classing it in your application. Are you doing that the same way in the COG and non-COG code?
(2) The send_array function is marked as HUBTEXT. Why is that? I'm wondering if that might somehow be confusing things.
(3) Does the same class work if you include it twice in non-COG code?
The odd thing is that if a definition in the COG and non-COG code were conflicting, I would expect a linker error instead of the code failing to work.
I'm working in the PropWare_BufferedUART example:
https://github.com/parallaxinc/PropWare/tree/develop/Examples/PropWare_BufferedUART
As I mentioned though, I was able to get it working by providing the macro "#define PropWare PropWare_cog", so the real code is not as simple as my original snippets at the top anymore.
Now that you can see the exact code I'm working with, I'll answer your questions:
1) Yes - both are in fact using the UARTTX and UARTRX classes. The only difference is that I have the following macros at the top of uart.h for better size optimizations:
2) No idea why I had send_array declared as HUBTEXT in the old 2.x release. It's gone in the develop branch.
3) I know I can have two UART instances, one UARTTX and one UARTRX. I don't know that I've ever tried to have two UARTTX instances.
To reproduce on a Linux box: This assumes:
git, cmake 3.3+ and GNU Make are available on PATH
PropGCC is extracted to /opt/parallax.
A Propeller is plugged into your computer and can be found by propeller-load.
If PropGCC is installed somewhere else, use "cmake -DPROPGCC_PREFIX=<whatever> .." instead of "cmake .."
The above should program the prop's RAM and begin a simple interactive program. You'll then need to remove my fix by finding the four files where it was applied and removing it:
Then running the "make clean debug-BufferedUARTRX_Demo" command again (be sure to run the clean target... I just found a bug with the cog drivers not rebuilding when headers change).
--Edit--
feature/14 branch has been merged into develop and deleted. Post edited to reflect this change.
I'm not sure if this is a bug, exactly, but it's certainly awkward. For now your work-around is probably the best solution.
Regards,
Eric