C: Testing Serial Protocol And Simulating Inter-Propeller Communication
idbruce
Posts: 6,197
I am currently in a position, where I want to move forward with my programming, which involves inter-Propeller communication, but at the moment, I am just not too enthusiatic, about doing the necessary board modifications.
As I was pondering the simplest solution, I came up with an idea. I don't know if anyone has done this before, but I have never seen anything posted on the subject.
Anyhow, instead of doing the necessary board modifications for inter-Propeller communication, I simply want to simulate it, and I was thinking about using the Propeller Board of Education for this simulation.
The main idea is to pass a C struct from one prop to another
Here are my thoughts....
With this type of setup, I think I can simulate inter-Propeller communication. Will this work for a proper simulation?
As I was pondering the simplest solution, I came up with an idea. I don't know if anyone has done this before, but I have never seen anything posted on the subject.
Anyhow, instead of doing the necessary board modifications for inter-Propeller communication, I simply want to simulate it, and I was thinking about using the Propeller Board of Education for this simulation.
The main idea is to pass a C struct from one prop to another
Here are my thoughts....
-
2 pairs of IO pins inter-connected with a 2.2K resistor, with each pair having an RX and a TX end.
-
Have two seperate instances of full duplex serial running in two seperate cogs, with each having RX and TX pins, and with each having a header include for the C struct
With this type of setup, I think I can simulate inter-Propeller communication. Will this work for a proper simulation?
Comments
It should give a good starting point, but the signal phases on a single prop tester will be less variable than on two props, unless you have a common oscillator ?
If I am understanding you correctly, it will work, but I will have better results with the test setup, as compared to the actual inter-prop communications, unless I have a common oscillator. Is this correct?
No, I will not have a common oscillator.
Single board cog1 rx pin same as cog 2 tx pin & vice-versa - No errors up to 230K
Single board, 4 separate pins, 12" wire from rx to tx. No errors up to 230K.
Single board, 4 separate pins, RS485 drivers, 1000 feet cat6 pairs from rx to tx. No errors up to 230K.
Two boards, 4 separate pins, RS485 drivers, 1000 feet cat6 pairs from rx to tx. No errors up to 115K, 13 single character errors at 230K
Thank you for that very helpful information. It is always nice to have test case scenarios
* SysCLK phase can be anything, so jitter/uncertainty is worse by + ~1 sysclk
* if using Aync, & long unbroken duplex packets can need extra stop bits to avoid data squeeze errors.
With same-batch crystals, you should be ok to > 1000 bytes. With resonators, that can be 100 bytes.
Thank you for the clarification and extra information.
Had to get some rest. Now it is time to start setting it up and do some testing
I rarely use the Prop BOE, but in sitiuations like this, it is an indispenable tool.
There are two main sections of code, which I will discuss, and I have also atttached the simulation project as it stands.
If I comment the following section of code, the program works as directed, and if I uncomment it (attempting to serially send the struct) the code fails. The following code is in the main function:
In the next bit of code, located in processor.c, this runs in a seperate cog and attempts to read the struct being sent, and further copy it into a global GCODE_STRUCT, identified as sent_gcode, for serial terminal display purposes. In normal use case, GCODE_STRUCT received_gcode, would simply be added to an array of GCODE_STRUCT(s)
So the problem lies in the receiving cog.
I have it narrowed down to:
Bytes are being sent, but fdserial_rxReady is never returning > 0.
If you're only testing software, you can make your hardware really simple. For demonstrating a duplex UART in PropWare, I just connected two random pins together - 12 and 13 to be exact - with no resistors or anything. One cog outputs on pin 12 and the other cog reads pin 13. It's the only time I ever use the 0.1" breadboard wires! :P
I've suspected for a while (but haven't tried yet) that you could even use the same pin. The you don't have any hardware at all
Here's the code for the example I'm referring to:
http://david.zemon.name/PropWare/DuplexUART__Demo_8cpp_source.html
Looks like a fairly nice site that you have going there.
As for the hardware.....
#define PROCESSOR_TX 0
#define PROCESSOR_RX 2
#define PARSER_RX 1
#define PARSER_TX 3
A resistor between pins 0 and 1, and a resistor between pins 2 and 3. Nothing too complex
But more specifcally the following two lines:
According to documentation, these two print commands, should output equal results, yet the top print command always outputs -1, while the lower one varies, but never outputs -1.
EDIT: So I am now assuming that fdserial_txChar is never succeeding.
What documentation said this?
SimpleIDE help for the fdserial library says:
If the byte was sent, that should be the return, therefore they should be equal shouldn't they?
You have found a bug. The function always returns -1 unless the mode bit 3 was set.
Funny thing about documentation. Sometimes it states an ideal situation. The real documentation is the code in this case.
BTW, a cleaner way to do this is by using "writeChar(parser, ch);"
That way if you change the device you won't have to change hundreds of lines of code.
1) Is there anything visibly wrong with with adding characters to an array like this?
2) This loop is attempting to process 324 bytes, so what is the maximum size of a character array for Propeller GCC?
The size of an array is only limited by how much memory you have available. 324 bytes should not be a problem.
The only thing I see that might be an issue is the lack of a null-terminator.
To be really nitpicky...
I prefer using size_t for instances like this. It should compile into identical code, but since you're comparing `i` against a size_t value, might as well let `i` be an instance of size_t.
I suppose I should have mentioned, that it is never exiting the loop. By commenting out the loop, I have verified, that characters are indeed getting to the function, so the fdserial object is definitely valid, and the function permits further processing in the parent cog. I just can't understand why it isn't exiting a loop of 324 iterations.
The maximum size for an array is equal to the maximum available continuous memory.
BTW, you don't really need to declare received_struct_array as an array. It could just be a pointer that contains the address of the struct as in "char *received_struct_array = &received_gcode;". That way you don't need to allocate a 324-byte array, and you don't need to do the memcpy after you receive the data.
Okay, I got some good information out of that.... However, several things have changed since the original post, one of which is the stack size, it is now at 1400.
I took my troubleshooting one step further and just commented out this line, at which point it exits the loop.
One thing of interest, which was hard to find.... the two fdserial_open functions did not recognize the constants in my config file. That one had me going until I hard coded the pins, mode and baud rate.
If you really want to make it bullet-proof you could add a timeout on the receive side, and exit the receive loop if you haven't received a character for a while. I have some YMODEM code written in Spin that you could adapt to your needs if you're interested.
Sure let me see it.
Several years ago, kuroneko and I put together some code for inter-prop comms, which included a begin trans, data, checksum, and end trans. Although not perfect, I am sure it could be altered to suit this purpose.... but to be perfectly honest, I am really not up to the port, because it looks a bit complicated
/**
* @brief Get a byte from the receive buffer, or if it's emtpy, wait until
* a byte is received.
*
* @param *term Device ID returned by fdserial_open.
*
*/
int fdserial_rxChar(fdserial *term);
Which means if you're not receiving enough data the loop will hang.
More importantly though, I suggest you consider testing your ideas with smaller pieces and build on pieces that you know work for you. Changing from one method to another every few days won't solve your problem.
I agree. I am close and I know where the problem is, I just need to work it out.
I should have paid better attention..... I missed the point about waiting and that would surely cause it to hang.
Thanks Steve
I have wittled it down to a much smaller application, and I have had a little success. The program no longer hangs and the first three members of the struct are filled correctly, but the remaining members are all zeroed out.
I have attached the entire project below, but here is a snippet from the receiving cog: