ModSERIAL help please

22 May 2012

Hello

I am trying to convert some custom written buffer code over to the MODSERIAL library and am having some difficulty getting it to work. I have looked through the example programs and pieced together what I think should work but it doesnt seem to work. Below is a snippet of my code showing what I am trying to do. Basically I send serial strings terminated with '\n' to the mbed and the mbed fills a buffer until it sees the '\n' character and then flags to parse the data.

It never prints the "got char" or "Parsed" or anything for that matter.

#include "mbed.h"
#include "MODSERIAL.h"

MODSERIAL pc(USBTX,USBRX);
char buf[100];

void parse();
void rxCallback(MODSERIAL_IRQ_INFO *info);

int main() {
    pc.baud(115200);
//    pc.attach(&Serialint,Serial::RxIrq);
    pc.attach(&rxCallback, MODSERIAL::RxIrq);



    while (1) {
        wait(0.3);

        if (sFlag==1) {
            NVIC_DisableIRQ(UART0_IRQn);    //added to fix lockup 9-27-11
            pc.printf("got char");
            parse();
            pc.printf("parsed");
            NVIC_EnableIRQ(UART0_IRQn);     //added to fix lockup 9-27-11
        }
    }
}

void rxCallback(MODSERIAL_IRQ_INFO *q) {
    MODSERIAL *pc = q->serial;
 //   char c = pc->rxGetLastChar();
    if ( pc->rxGetLastChar() == '\n') {
        sFlag=1;
    }
}

void parse() {
   char *cp;
    cp = buf;
    while (pc.readable() ) {
        *cp++ = pc.getc();
    }
    --cp;           //move back to CR or LF
    *cp = '\0';     //terminate buffer
    //print buffer contents 
    pc.printf("buf = <%s>\n", buf);
}
22 May 2012

Okay so I found the MODSERIAL move command and that along with setting the check bit to ==13 instead of ==\n allowed it to sorta start working. The output is still getting jumbled a little.

#include "mbed.h"
#include "MODSERIAL.h"

MODSERIAL pc(USBTX,USBRX);
char buf[100];

void parse();
void rxCallback(MODSERIAL_IRQ_INFO *info);

int main() {
    pc.baud(115200);
//    pc.attach(&Serialint,Serial::RxIrq);
    pc.attach(&rxCallback, MODSERIAL::RxIrq);



    while (1) {
        wait(0.3);

        if (sFlag==1) {
            NVIC_DisableIRQ(UART0_IRQn);    //added to fix lockup 9-27-11
            pc.printf("got char\r\n");
            parse();
            pc.printf("parsed\r\n");
            NVIC_EnableIRQ(UART0_IRQn);     //added to fix lockup 9-27-11
        }
    }
}

void rxCallback(MODSERIAL_IRQ_INFO *q) {
    MODSERIAL *pc = q->serial;

    if ( pc->rxGetLastChar() == 13) {
        serial->move(buf, 100,13);
        serial->rxBufferFlush();
        sFlag=1;
    }
}

void parse() {
    pc.printf("buf = <%s>\n", buf);
}

Once I parse the input buf for commands I report status with pc.prinf("blahblah"); commands. Are these safe to use or should I be using sprintf(outbuf,"Blahblah"); and then using a pc.puts(outbuf); or some other mechanism to make use of the tx buffering?

22 May 2012

Okay so now I'm getting closer but still having a weird behavior. Its like the buffer never gets flushed or cleared and keeps a copy of the last stuff that was in it. Below is a hyperterminal output with what I typed commented inline.

     Terminal Output
     **I typed "Matt" + return
buf = <>
parsed
     **I typed "ma" + return
got char
buf = <ma>
parsed
     **I typed "l" + return
got char
buf = <la>
parsed
     **I typed "listmatt" + return
got char
buf = <listmatt>
parsed
    **I typed "T" + return
got char
buf = <Tistmatt>
parsed

How do I clear the buffer so that after I move a copy its empty?

23 May 2012

I cannot see where yo declared sFlag in your code. However, remember when setting a var in an ISR and also in main loop code, declare it as volatile:-

volatile bool sFlag;

Also, you do not need to look for \n directly. Have MODSERIAL's autoDetectChar() do it for you.

#include "mbed.h"
#include "MODSERIAL.h"

MODSERIAL pc( USBTX,USBRX );

char buf[100];

volatile bool sFlag;

void modserialCallback( MODSERIAL_IRQ_INFO *info )
{
    sFlag = true;
}

int main() 
{
    sFlag = false;
    pc.baud(115200);
    pc.autoDetectChar( '\n' );
    pc.attach( &modserialCallback, MODSERIAL::RxAutoDetect );

    while (1) 
    {
        wait(0.3);

        if ( sFlag ) 
        {
            sFlag = false;
            pc.move( buf, 100 );
            pc.printf("buf = <%s>\n", buf);           
        }
    }
}

I haven't tried that, it's "pseudo code" but should give you an idea.

Edit: Note I used MODSERIAL::move() to copy the contents of the RX buffer to buf and then clear the RX buffer. The ::move command comes in two flavours:

::move( char *dst, int max ) which moves until autodetect char is found or buffer empty

::move( char *dst, int max, char inCharStopAt ) which moves until inCharStopAt char is found or buffer empty

23 May 2012

Thanks for responding Andy

I'm sorry, I do have

Volatile int sFlag=0; 

in my main.cpp file. I just copied the relavant code out to paste here and missed that. I will try compiling this code and see if it makes any sense. I think, I am still not sure what you mean by the autodetect function.

I did try both move commands and tried to use with no apparent change to my output.

        serial->move(buf, 100,13); <-char=13 was the character for return on the keyboard I think?  
     OR
        serial->move(buf, 100);
23 May 2012

Andy, couple of follow up ?'s

1. Does the act of copying the RX buffer to buf also clear the RX Buffer or do I need to do a flush?

2. Does moving it from RX buffer to buf also add on a '\0' to make it a proper string so I can parse and use strcmp?

Quote:

I haven't tried that, it's "pseudo code" but should give you an idea.

Edit: Note I used MODSERIAL::move() to copy the contents of the RX buffer to buf and then clear the RX buffer. The ::move command comes in two flavours:

23 May 2012

1. Yes, in itself it just loops using getc() to fill your buffer which removes from the rx buffer.

2. No, it doesn't insert anything, it just moves them. It does return the number of bytes moved so you can null term the string yourself with some simple pointer arithmetic:

   int nNum = pc.move( but, 100 );
   buf[ nNum ] = '\0';

autodetect is a simple feature. You give MODSERIAL the character to "detect". It will make a callback when it detects it. Simple as that. It's designed to easily chop up a string stream based on a single byte character. And ::move( buf, 100 ) without the third parameter will use the character you set with autodetect as a default.

23 May 2012

Quote:

char=13 was the character for return on the keyboard I think?

That would depend on your OS I believe.

24 May 2012

Andy, Thanks for pointing me in the right direction.

I noticed you did the buf move in main rather than isr.....is that way safer?

If I'm sending larger than 16 byte printf's how do I use the buffer on TX?

I will post fixed code tomorrow morning for anyone else following the thread.

24 May 2012

I do still have one weird problem. The first time after a reboot of the board that I type anything, the board responds with an empty string like this. It only happens the first time on a reboot. I thought maybe it required 16 bytes to output but I can enter 20 characters on the first input and it still comes back empty. The next time I type even 1 character it works.

   **I rebooted board and typed "HelloThisIsATestofBoard" + return
got char
buf = <>
parsed
   **I then type "1" + return
got char
buf = <1>
parsed

Also.... I noticed you did the buf move in main rather than isr.....is that way safer?

If I'm sending larger than 16 byte printf's how do I use the buffer on TX?

WoRKING CODE Below!!!! THANKS ANDY.

#include "mbed.h"
#include "MODSERIAL.h"

MODSERIAL pc(USBTX,USBRX);
char buf[100];

void parse();
void rxCallback(MODSERIAL_IRQ_INFO *info);

int main() {
    pc.baud(115200);
    pc.autoDetectChar('\r');  //<--to catch the return button press on keyboard in hyperterminal
    pc.attach(&rxCallback, MODSERIAL::RxAutoDetect);

    while (1) {
        wait(0.3);
        if (sFlag==1) {
            NVIC_DisableIRQ(UART0_IRQn);    //added to fix lockup 9-27-11
            pc.printf("got char\r\n");
            int nNum = pc.move(buf, 100);  // <--can I use the api for how many chars are in RX buffer instead of all 100??
            buf[nNum] = '\0';
            parse();
            pc.printf("parsed\r\n");
            NVIC_EnableIRQ(UART0_IRQn);     //added to fix lockup 9-27-11
        }
    }
}

void rxCallback(MODSERIAL_IRQ_INFO *q) {
        sFlag=1;
    }
}

void parse() {
    pc.printf("buf = <%s>\r\n", buf);
}
31 May 2012

I do still have one weird problem. The first time after a reboot of the board that I type anything, the board responds with an empty string like this. It only happens the first time on a reboot. I thought maybe it required 16 bytes to output but I can enter 20 characters on the first input and it still comes back empty. The next time I type even 1 character it works.

What do I need to do to clear the buffers so that my first typed character is correctly fed into the system.

   **I rebooted board and typed "HelloThisIsATestofBoard" + return
got char
buf = <>
parsed
   **I then type "1" + return
got char
buf = <1>
parsed

Also.... I noticed you did the buf move in main rather than isr.....is that way safer?

If I'm sending larger than 16 byte printf's how do I use the buffer on TX?

14 Jun 2012

As a workaround can I use the library call to remove the last character? I have tried setting the first character in the string to '\0' thinking that would clear the string on powerup but that didnt help so I removed it.

???

09 Nov 2012

Still never found a good reason for this to be happening. Thoughts?

09 Nov 2012

It would be easier to test with working code. I added from your last code posted here the sFlag declaration (volatile int), removed an '}' too much (line 32), and added sFlag = 0 inside the if statement in the main loop.

After that the result: (Tera Term, 9600 baud, receive CR + LF, transmit CR)

got char

buf = <This is a test>

parsed

got char

buf = <And now it is weekend>

parsed
09 Nov 2012

ahhh now i'm getting somewhere. I also tried the sample i provided and with the noted changes it works fine as expected.

I then added some hardware changes that are in my mainline code that are not in this example. I have an FTDI chip used as the serial port here. I also have a digitalout pin wired to the reset line of the FTDI chip. I made the following changes and it no longer works as above and performs as I mentioned where it misses everything up to the first time return is pressed and then works fine after that.

DigitalOut rUSB(p14);
MODSERIAL pc(USBTX,USBRX);
char buf[100];
volatile int sFlag;

void parse();
void rxCallback(MODSERIAL_IRQ_INFO *info);

int main()
{
    rUSB=0;   //0 holds it in reset and 1 puts it into operation.
    wait(5);  
    rUSB=1;    

09 Nov 2012

This works. I needed to flush the buffer at the right time I guess.

#include "mbed.h"
#include "MODSERIAL.h"

DigitalOut rUSB(p14);
MODSERIAL pc(USBTX,USBRX);
char buf[100];
volatile int sFlag;

void parse();
void rxCallback(MODSERIAL_IRQ_INFO *info);
void flushSerialBuffer(void);


int main()
{
    pc.baud(115200);
    pc.autoDetectChar('\r');  //<--to catch the return button press on keyboard in hyperterminal
    pc.attach(&rxCallback, MODSERIAL::RxAutoDetect);

    rUSB=0;
    wait(5);   
    rUSB=1;     
    wait(2);
    flushSerialBuffer();
    

    while (1) {
        wait(0.3);
        if (sFlag==1) {
            NVIC_DisableIRQ(UART0_IRQn);    //added to fix lockup 9-27-11
            pc.printf("got char\r\n");
            int nNum = pc.move(buf, 100);  // <--can I use the api for how many chars are in RX buffer instead of all 100??
            buf[nNum] = '\0';
            parse();
            pc.printf("parsed\r\n");
            NVIC_EnableIRQ(UART0_IRQn);     //added to fix lockup 9-27-11
            sFlag=0;
        }
    }
}

void flushSerialBuffer(void)
{
    char char1;
    while (pc.readable()) {
        char1 = pc.getc();
    }
    return;
}

void rxCallback(MODSERIAL_IRQ_INFO *q)
{
    sFlag=1;
}


void parse()
{
    pc.printf("buf = <%s>\r\n", buf);
}

You need to log in to post a reply