I have tried other terminators besides '>', such as ';', and ':', but the results are the same. I believe one of the memcpy(s) is screwing up the data, but I could be wrong
I have tried other terminators besides '>', such as ';', and ':', but the results are the same. I believe one of the memcpy(s) is screwing up the data, but I could be wrong
Instead of using a terminating character, why not apply a header of a known size, that gives the transmission length???
You are also sure that none of your struct bytes contain a zero, right? That will cause your loop to terminate also.
There are plenty of zeros, but to my knowledge, the are no "null" characters, but I am not certain. I am a little out of my playground. How would that terminate my loop?
@David
Instead of using a terminating character, why not apply a header of a known size, that gives the transmission length???
At least for the moment, I do not believe the terminator is the problem. If it is determined that any terminator will be a problem, well then of course I would explore that option. Right now, I am proceeding the struct with a '<' for STX and following the struct with a '>' for ETX. I believe it should work, but I also believe the data is getting screwed up somewhere, perhaps with all this "volatile" mumbo jumbo.
Now do you see it? What you really need is a loop that terminates after reading all the bytes, such as.
for (index = 0; index < sizeof(GCODE_STRUCT); index++)
received_struct_array[index] = fdserial_rxChar(processor);
So what happens if you don't receive all of the bytes. Your code get's stuck. So you need a timeout to get out of that stupid loop. What you need is a rxChar that times out have a certain period of time, such as 100 msec. I don't want to do all of your homework, so I'll let you figure that out on your own.
What you really need is a loop that terminates after reading all the bytes, such as.
for (index = 0; index < sizeof(GCODE_STRUCT); index++)
received_struct_array[index] = fdserial_rxChar(processor);
So what happens if you don't receive all of the bytes. Your code get's stuck. So you need a timeout to get out of that stupid loop. What you need is a rxChar that times out have a certain period of time, such as 100 msec. I don't want to do all of your homework, so I'll let you figure that out on your own.
On a further note, while trying to resolve the problem of sending a structure serially with differing data types, I came across several references that indicated that the structure should be byte aligned with "#pragma pack(n)" and in some instance may need "push" or "pop".
Thank you Dave and Steve for pointing me in the right direction.
For all others, you now have a working example of passing a struct serially from one cog to another cog, thus simulating the passing of a struct serially from one Propeller to another Propeller
I hope it is of good use to you As for me, NOW I can move forward with my project
EDIT: I have updated the original upload to include a few extra additional comments.
For those of you who downloaded my previous upload, I forgot to add a few comments to StructTest.c and to processor.c. These comments are just friendly reminders that STX and ETX should be the same on both the transmitting and receiving end of the serial connections. So I have updated that upload, for those that like friendly reminders
After looking the project over just one more time, I decided to rearrange some things and remove some things. There was an extra GCODE_STRUCT that wasn't needed, which added an extra memcpy and an extra memset, etc... so on... so forth...
So the following attachment, is the final draft, at least for now
Try this generic packet code which does a loopback but could be used between boards. Byte receive timeout, packet length, and primitive checksum are included. Other packet items are left to the imagination.
This can be used for a ASCII byte oriented transport layer. Making marshalling layer code like XDR is left as an exercise.
Output:
Packet Test
Send packets
Dequeue received packets:
-> Hello
-> Packet
-> Tester
/**
* This is the main PacketTest program file.
* @file PacketTest.c
*
* Add wire between P0 and P1
*/
#include <string.h>
#include "simpletext.h"
#include "fdserial.h"
#include "packet.h"
fdserial *pktport;
packet_st g_packet;
char *msg[] = { "Hello", "Packet", "Tester", 0 };
int main(void)
{
int n = 0;
pktport = fdserial_open(PROD_RX, PROD_TX, PROD_MODE, PROD_BAUD);
printi("Packet Test\n");
packet_start(pktport);
printi("Send packets\n");
for (n = 0; msg[n]; n++) {
packet_make(&g_packet, msg[n], strlen(msg[n])+1);
packet_send(pktport, &g_packet);
}
printi("Dequeue received packets:\n");
for (;;) { // for (ever)
// if packet available
if (packet_ready()) {
packet_read(&g_packet);
// print packet contents
//packet_print(&mypacket);
printi("-> %s\n",g_packet.data);
}
}
return 0;
}
/**
* @file packet.c
* Packet utilities.
*/
#include <stdio.h>
#include "packet.h"
static volatile packet_st queue[PACKET_QLEN];
static volatile int qhead = 0;
static volatile int qtail = 0;
static volatile int qcount = 0;
static volatile fdserial *grec;
static char packet_stack[sizeof(_thread_state_t)+20*sizeof(int)];
static int gcog;
//#define LED1 (1 << 26)
//#define LED2 (1 << 27)
void packet_cog(void *parm);
void packet_start(fdserial *rec)
{
grec = rec;
gcog = cogstart(packet_cog, 0, packet_stack, sizeof(packet_stack));
//debug("packet_start %d cog %d\n", sizeof(packet_stack), gcog);
}
void packet_stop(void)
{
if (gcog > 0) {
//debug("packet_stop %d\n", gcog);
cogstop(gcog);
gcog = 0;
}
}
void packet_cog(void *parm)
{
int len = 0;
int byte = 0;
int n = 0;
int sum = 0;
volatile packet_st *pkt = 0;
//DIRA |= LED1 | LED2;
for (;;) { // for (ever)
//OUTA |= LED1;
// got a char?
if (fdserial_rxReady((fdserial*)grec)) {
// read length
len = fdserial_rxChar((fdserial*)grec);
if (len > -1) {
//OUTA |= LED2;
// read into packet packet
pkt = &queue[qhead];
pkt->length = len;
sum = 0;
// wait for packet
waitcnt(CNT+CNT/100);
// get bytes while valid
for (n = 0; n < len; n++) {
byte = fdserial_rxTime((fdserial*)grec,10);
//byte = fdserial_rxCheck((fdserial*)grec);
if (byte < 0) break;
if (n < len-1) sum += byte;
pkt->data[n] = byte; // last byte is sum
}
sum &= 0xff;
byte &= 0xff;
// if valid length and sum increment queue head
// otherwise recycle queue entry.
if (n > len-2) {
if (sum == byte)
{
//OUTA &= ~LED2;
qhead++;
qhead &= PACKET_QMASK;
qcount++;
}
}
}
}
}
// don't exit function
}
int packet_make(packet_st *pkt, char *s, int len)
{
int n = 0;
int sum = 0;
pkt->length = len+1;
for (n = 0; n < len && n < PACKET_DLEN; n++) {
pkt->data[n] = s[n];
if (n < len-1) sum += s[n];
}
sum &= 0xff;
pkt->data[n] = sum;
//packet_print(pkt);
return n;
}
int packet_send(fdserial *port, packet_st *pkt)
{
int n;
//packet_print(pkt);
writeChar(port, pkt->length);
for (n = 0; n < pkt->length; n++) {
writeChar(port, pkt->data[n]);
}
return 0;
}
int packet_ready(void)
{
int rc = 0;
if (qhead != qtail) rc = 1;
return rc;
}
int packet_read(packet_st *rxpkt)
{
packet_st *pkt = (packet_st*) &queue[qtail];
memcpy((void*)rxpkt, (void*)pkt, sizeof(packet_st));
qtail++;
qtail &= PACKET_QMASK;
return pkt->length;
}
int packet_print(packet_st *pkt)
{
int n;
int len = pkt->length;
printi("\npacket len %d : ", len);
for (n = 0; n < len; n++) {
printi(" %02x", pkt->data[n]);
}
printi("\n");
return 0;
}
/**
* @file packet.h
*/
#ifndef __PACKET_H__
#define __PACKET_H__
#define CONS_RX 0
#define CONS_TX 1
#define CONS_MODE 0
#define CONS_BAUD 115200
#define PROD_RX 1
#define PROD_TX 0
#define PROD_MODE 0
#define PROD_BAUD CONS_BAUD
#define PACKET_DLEN 30
#define PACKET_QLEN 16 // power of 2 for queue
#define PACKET_QMASK (PACKET_QLEN-1)
#include <stdint.h>
#include "simpletext.h"
#include "fdserial.h"
typedef struct packet_struct {
uint8_t length; // total packet length including length and checksum byte
uint8_t data[PACKET_DLEN+1]; // add 1 for checksum
} packet_st;
void packet_start(fdserial *rec);
void packet_stop(void);
int packet_make(packet_st *pkt, char *s, int len);
int packet_send(text_t *port, packet_st *pkt);
int packet_ready(void);
int packet_read(packet_st *pkt);
int packet_print(packet_st *pkt);
#endif
Try this generic packet code which does a loopback but could be used between boards. Byte receive timeout, packet length, and primitive checksum are included. Other packet items are left to the imagination.
This can be used for a ASCII byte oriented transport layer. Making marshalling layer code like XDR is left as an exercise.
Thanks, it looks very interesting and useful Of course I will have to study it for a while, just to be able to understand it, but I will study it. I am very curious about your use of:
static volatile packet_st queue[PACKET_QLEN];
static volatile int qhead = 0;
static volatile int qtail = 0;
static volatile int qcount = 0;
Like I said, it will be very interesting to see how it all works.
Using a Propeller BOE for the attached code of Post #46 and using 470 ohm resistors for the serial connections, the baud rate can be increased to 230400 from the current 115200 full duplex serial settings.
Comments
I have tried other terminators besides '>', such as ';', and ':', but the results are the same. I believe one of the memcpy(s) is screwing up the data, but I could be wrong
There are plenty of zeros, but to my knowledge, the are no "null" characters, but I am not certain. I am a little out of my playground. How would that terminate my loop?
@David
At least for the moment, I do not believe the terminator is the problem. If it is determined that any terminator will be a problem, well then of course I would explore that option. Right now, I am proceeding the struct with a '<' for STX and following the struct with a '>' for ETX. I believe it should work, but I also believe the data is getting screwed up somewhere, perhaps with all this "volatile" mumbo jumbo.
Yes, I get the point
Last night, after you asked the question:
I altered my test code within StructTest.c to include:
The output from this included many zeros. How do I combat the zeros or is there another way around it?
Okay, I will see what kind of concoction I can come up with
Thank you Dave and Steve for pointing me in the right direction.
For all others, you now have a working example of passing a struct serially from one cog to another cog, thus simulating the passing of a struct serially from one Propeller to another Propeller
I hope it is of good use to you As for me, NOW I can move forward with my project
EDIT: I have updated the original upload to include a few extra additional comments.
So the following attachment, is the final draft, at least for now
Try this generic packet code which does a loopback but could be used between boards. Byte receive timeout, packet length, and primitive checksum are included. Other packet items are left to the imagination.
This can be used for a ASCII byte oriented transport layer. Making marshalling layer code like XDR is left as an exercise.
Output:
Thanks, it looks very interesting and useful Of course I will have to study it for a while, just to be able to understand it, but I will study it. I am very curious about your use of:
Like I said, it will be very interesting to see how it all works.
Thank you very much!!!!
(void*) <- Key to removing all my warnings for volatile memcpy(s) and memset(s). Those warnings were annoying the bejeezers out of me.
Using a Propeller BOE for the attached code of Post #46 and using 470 ohm resistors for the serial connections, the baud rate can be increased to 230400 from the current 115200 full duplex serial settings.