8 years, 7 months ago.

RawSerial Rx interrupt only triggering once. LPC1768

I have setup RawSerial within an RTOS and attached an ISR to the Rx interrupt. The first character triggers the ISR but then it is never called again, my only thought is that the interrupt is not being cleared? RawSerial is working fine without using the RTOS.

main

void network(void const *args)
{
    NetworkInterface net(p13, p14, 9600);
    
    while(true)
    {        
    }
}

int main() 
{
    Thread networkThread(network);
    
    while(1){};
}

NetworkInterface.cpp

NetworkInterface::NetworkInterface(PinName tx, PinName rx, int baudRate)
: RawSerial(tx, rx)
, mIO(LED3)
{
    baud(baudRate);
    attach(this, &NetworkInterface::onNetworkData);
}

void NetworkInterface::onNetworkData()
{
    mIO = !mIO; //LED only changes on first character.
    char c = getc();
    
    mBuffer += c;
}

Any help would be greatly appreciated.

1 Answer

8 years, 7 months ago.

The receive interrupt is only cleared when the buffer is empty. Any interrupts that deal with data input should check for multiple bytes/packets. e.g.

void NetworkInterface::onNetworkData()
{
    mIO = !mIO; //LED only changes on interrupts not every byte. Move inside the while for every byte.

    while (readable())
      mBuffer += getc();

}

Thanks for the help. Unfortunately that didn't fix it. I also tried adding a check so the LED only flicks on a specific letter, in case there was always an even amount of data causing the LED to stay on.

What's weird is simply by adding the RTOS package is enough to stop it working even in a standard 'super-loop' configuration. Removing the RTOS I have to perform a 'Compile-All' for it to work correctly again. Any ideas?

Edit: Forwarding the output to PC serial also shows only the first character is sent/received.

posted by Thomas Kilsby 18 Aug 2015

how/where is mBuffer defined?

posted by Andy A 18 Aug 2015

mBuffer is defined in my NetworkInterface class. Here are all three files of the project:

main.cpp

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

#include "NetworkInterface.h"

void network(void const *args)
{
    NetworkInterface net(p13, p14, 9600);
    
    while(1){}
}


int main() 
{
    Thread networkThread(network);
    
    while(1){};
}

NetworkInterface.h

#include "mbed.h"
#include <string>

class NetworkInterface : public RawSerial
{    
    public:       
                    NetworkInterface(PinName, PinName, int);
    
    private:
    void            onNetworkData();
    
    DigitalOut      mIO;
    std::string     mBuffer;
};

NetworkInterface.cpp

#include "NetworkInterface.h"

NetworkInterface::NetworkInterface(PinName tx, PinName rx, int baudRate)
: RawSerial(tx, rx)
, mIO(LED3)
{
    baud(baudRate);
    attach(this, &NetworkInterface::onNetworkData);
}

void NetworkInterface::onNetworkData()
{    
    mIO = !mIO;
    
    while(readable())
    {
        char c = getc();
        mBuffer += c;
    }
}

Thanks again.

posted by Thomas Kilsby 18 Aug 2015

A quick google (google searches this site far better than the search box on the site) shows this is a fairly common problem.

Try:

void NetworkInterface::onNetworkData()
{    
    mIO = !mIO;
    
    while(readable())
    {
        int temp = (int)LPC_UART1->RBR; 
        char c = getc();
        mBuffer += c;
    }
}

Not very portable since it's dependent on the specific serial port being used but there is no point in creating a more generic implementation if it doesn't fix the issue.

posted by Andy A 18 Aug 2015

That seemed very promising but annoyingly didn't work. I tried performing it both inside and out the while loop and on UART0, UART1, UART2 to no avail. Perhaps I need to alter another element? Could you link the source? Thanks again.

posted by Thomas Kilsby 18 Aug 2015

One more thing to try:

uint32_t IRR1 = LPC_UART1->IIR;

Outside the loop and then the RBR line inside

Pins 13 and 14 should be UART1.

I'm basing this on https://developer.mbed.org/users/tylerjw/notebook/buffered-serial-with-rtos/ however https://www.google.co.uk/search?q=site%3Adeveloper.mbed.org%20RTOS%20serial%20interrupt&rct=j gives a lot of other posts about similar problems.

posted by Andy A 18 Aug 2015

Thanks for the links. Adding the IIR statement didn't work, damn. And the buffered serial code seems to suggest that's exactly what I need to do..

posted by Thomas Kilsby 18 Aug 2015

Well I'm out of ideas. This isn't really an area I know well. Sorry.

posted by Andy A 18 Aug 2015

No worries, I finally solved it. Using std::string as a buffer was the cause. I presume std::string += operator uses some STDIO functions hence the RTOS hanging.

posted by Thomas Kilsby 18 Aug 2015