10 years, 8 months ago.

Serial interrupt stdio

Hi,

I am having some trouble with using the serial interrupts.

I am trying to run this code. I have p9 connected to p10.

#include "mbed.h"
#include "rtos.h"

DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4);

Serial pc(USBTX, USBRX);
Serial out(p9, NC);
Serial in(NC, p10);

char latest = '0';

void serialInterrupt()
{
    led2 = 1;
    latest = in.getc();
    led3 = 1;
}

int main() {
    led1 = 1;

    in.attach(&serialInterrupt);
    out.putc('1');
    Thread::wait(1000);
    pc.printf("latest = %c\n",latest);

    led4 = 1;
}

With this code as it is, only LED1 and LED2 come on.

If I comment out line 15: "latest = in.getc();", LED3 now comes on, but LED4 still doesn't. I assume this is because on the Serial Handbook page it says: Note: you need to actually read from the serial to clear the RX interrupt, but I still don't understand why it stops at line 15.

The RTOS Handbook page says that you cannot use stdio during ISR, but then you can't clear the interrupt...

I am quite confused, any help would be much appreciated.

1 Answer

10 years, 8 months ago.

First question, does what you do at line 7 and 8, making seperate objects for the TX and RX pin, while they are connected to the same peripheral, actually work without RTOS? Might just work, but it is a bit different.

Regarding your question, that is correct, you cannot clear the ISR that way, which is a slight issue. You can directly write the relevant registers, that isn't blocked.

Option B, see this topic: http://mbed.org/forum/mbed/topic/4456/?page=1#comment-22274. It is a bit of a hack I made in a hurry for someone else, and making a proper RTOS version of modserial is something I'd like to do one day in the far future, but it should work.

Accepted Answer

What do you mean without RTOS? Try a single object for both directions, or try it without RTOS? It works fine if I don't attach a function for the interrupt, I have successfully communicated using serial and two declarations, one for in and one for out.

posted by Adam Osborn 21 Aug 2013

I meant without RTOS, so just to see if it works without the getc blocking due to rtos mutex.

But if it is just the getc blocking due to rtos you have the two options I mentioned.

posted by Erik - 21 Aug 2013

No I removed all the RTOS and it still hangs. How do I directly write the relevant registers? Is that what you meant by _getc? I tried in._getc() and it didn't compile.

posted by Adam Osborn 22 Aug 2013

That was only together with modserial, but the modserial + rtos library should allow for usage of getc/putc in RTOS ISRs.

I just tried it myself without RTOS, and that worked fine. Next with RTOS, and indeed didn't work. With some searching I got to https://mbed.org/users/sam_grove/code/BufferedSerial/, which seemed useful, but didn't work in this fashion at least. So back to plan B, I imported MODSERIAL-RTOS, and that worked fine for me, with the following code:

#include "mbed.h"
#include "rtos.h"
#include "MODSERIAL.h"
 
DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4);
 
Serial pc(USBTX, USBRX);
MODSERIAL out(p9, NC);
MODSERIAL in(NC, p10);
 
char latest = '0';
 
void serialInterrupt(MODSERIAL_IRQ_INFO *q)
{
    led2 = 1;
    latest = in.getc();
    led3 = 1;
}
 
int main() {
    led1 = 1;
 
    in.attach(&serialInterrupt);
    out.putc('1');
    Thread::wait(1000);
    //wait(1);
    led4 = 1;
    pc.printf("latest = %c\n",latest);
 
    while(1);
}

And just with standard mbed-rtos and MODSERIAL-RTOS libraries added, p9 and p10 shorted to each other.

posted by Erik - 22 Aug 2013

Thanks a lot for you help, will try this asap. Edit: Yep that works, thanks again.

posted by Adam Osborn 22 Aug 2013