Serial crashes after function return?

11 Oct 2011

Hi!

I have a function called send_network_packet which takes a Serial object, a source address, a destination address, packet data and length, like so:

void send_network_packet(Serial s, char *src, char *dst, char *pkt, uint8_t len) {
	int i;

	while (!s.writeable()); s.putc(1);
	for (i = 0; i < 8; i++) { while (!s.writeable()); s.putc(src[i]); }
	for (i = 0; i < 8; i++) { while (!s.writeable()); s.putc(dst[i]); }
	while (!s.writeable()); s.putc(len);
	for (i = 0; i < len; i++) { while (!s.writeable()); s.putc(pkt[i]); }
}

Don't mind all the writeable() checks, they're there for making sure that nothing is wrong during debugging. Now, I call this function twice in a row:

send_network_packet(serial[i], ADDR_LOCAL, ADDR_BROADCAST, "OHAITHAR", 8);
send_network_packet(serial[i], ADDR_LOCAL, ADDR_BROADCAST, "OHAITHAR", 8);

I call it with the same data both times. Before I make these calls however I send a bunch of null-bytes. The problem is that the second message is never sent, and later on in the code I have while(serial[i].readable()) { ... }. When I receive a character from the PC, readable() will constantly return true, hanging in an infinite loop but it can't actually read or send anything. Any putc()-calls just fails.

Now, if I don't call send_network_packet at all, I can receive characters just fine.

I was also confused as to why the second send_network_packet call fails to send even a single character (but it runs through the code past all writeable() checks). So I changed the function to send everything twice:

void send_network_packet(Serial s, char *src, char *dst, char *pkt, uint8_t len) {
	int i;

	while (!s.writeable()); s.putc(1);
	for (i = 0; i < 8; i++) { while (!s.writeable()); s.putc(src[i]); }
	for (i = 0; i < 8; i++) { while (!s.writeable()); s.putc(dst[i]); }
	while (!s.writeable()); s.putc(len);
	for (i = 0; i < len; i++) { while (!s.writeable()); s.putc(pkt[i]); }

	while (!s.writeable()); s.putc(1);
	for (i = 0; i < 8; i++) { while (!s.writeable()); s.putc(src[i]); }
	for (i = 0; i < 8; i++) { while (!s.writeable()); s.putc(dst[i]); }
	while (!s.writeable()); s.putc(len);
	for (i = 0; i < len; i++) { while (!s.writeable()); s.putc(pkt[i]); }
}

And it sends it twice! The only difference is that this doesn't return from the function before getting called again. So, apparently, when this function returns, the UART dies in some funny way.

The serial-array is defined as follows:

Serial serial[4] = { Serial(USBTX, USBRX), Serial(p9, p10), Serial(p13, p14), Serial(p28, p27) };

Any ideas?

11 Oct 2011

Problem solved! I'm now passing the Serial object as a pointer instead, otherwise it seems like it got destroyed when the function returned or something.

16 Oct 2011

I have had similar problems with the Serial object. It crashed on USB and p9/p10 pins.

I noticed that on USB you dont see the blue LED flashing anymore when data is transmitted. The mbed program doesnt seem to crash however. Fix was made by using pointers.

#include "mbed.h"

// mbed Interface Hardware definitions
DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut heartbeatLED(LED4);


// Host PC Communication channels
Serial usb(USBTX, USBRX);
Serial com(p9, p10);

// Variables for Heartbeat and Status monitoring
Ticker heartbeat;

#if (0)
// This does not work
void test_string(Serial serial) {
    serial.printf("Test %d\r", 1234);
}
#else

// This works
void test_string(Serial &serial) {
    serial.printf("Test %d\r", 1234);
}
#endif
      
// Heartbeat monitor
void pulse() {
  heartbeatLED = !heartbeatLED;
}

void heartbeat_start() {
  heartbeat.attach(&pulse, 0.5);
}

void heartbeat_stop() {
  heartbeat.detach();
}

int main() {
    heartbeat_start();
    
    usb.printf("This message is showing!\n\r");          

    test_string(usb);

    usb.printf("This message is only showing when you use pointers!\n\r");
        
//mbed continues, but serial port may be dead

    while(1) {
        myled1 = 1;
        wait(0.2);
        myled1 = 0;
        test_string(usb);
        wait(2.0);        
    }
}
17 Oct 2011

Pontus Rodling wrote:

I'm now passing the Serial object as a pointer instead, otherwise it seems like it got destroyed when the function returned or something.

The problem is that if you don't pass the Serial object as pointer, the copy constructor will get called (the parameter is by value, then). And this means you have two of them afterwards. And yes, the second one will get destroyed when you leave the method.