serial interrupt driven transmit

19 Oct 2010

Hi Y'all,

New to mbed, tho not to embedded systems :)>

I'm attempting to use the interrupt driven features of the serial API as shown in the following code. The LED keeps blinking but I never see any activity on the serial port. I've previously had success using the polled interface so I'm pretty confident that I've got things hooked up properly. My theory is that the UART transmit buffer empty interrupt service routine is never being invoked. I have no idea why.

 

#include "pc-serial.h"

DigitalOut alive_led(LED1);

int main() {    
    PCSerial pc_serial;
    char c = '!';
    while (1) {
        alive_led = 1;
        wait(0.2);
        pc_serial.Putc(c);
        alive_led = 0;
        wait(0.2);
        c = (c + 1) & 0x7f;
        if (c<=0) c = '!';
    }
}
#include "mbed.h"
#include "LPC17xx.h"

class PCSerial {
private:
    static const int outbuf_size = 32;
    static const int pointer_mask = 0x1f;
    char outbuf[outbuf_size];
    volatile int wp, rp;
    bool overflow;
    void TxISR(void);
    void enableTxIrq(void);
    void disableTxIrq(void);
public:
    PCSerial(void);
    void Putc(char c);
    bool isOverflow() {return overflow;};   
};
#include "pc-serial.h"

Serial pc(USBTX, USBRX);

PCSerial::PCSerial(void) {

    // init the serial port
    pc.baud(115200);
    pc.format(8, Serial::None, 1);
    
    // init the output FIFO
    wp = 0; rp = 0;

    // Attach a member function to call whenever a transmit buffer empty 
    // interrupt is generated    
    pc.attach(this, &PCSerial::TxISR, Serial::TxIrq);
    disableTxIrq(); // initially disabled since the output FIFO is empty   
    
}

// Copy the input byte to the output buffer, enable the UART transmit 
// buffer empty interrupt
void PCSerial::Putc(char c) {
    outbuf[wp] = c;
    disableTxIrq(); // ---- critical
    wp = ++wp & pointer_mask;
    enableTxIrq();  // ---- \critical
    if (wp == rp) {
        overflow = true;
    } else {
        overflow = false;
    }
}

// This is the UART transmit buffer empty interrupt service routine 
void PCSerial::TxISR(void) {

    // If the output FIFO has data, copy the head to the UART
    if (rp != wp) {
        pc.putc(outbuf[rp]);
        rp = ++rp & pointer_mask;
    }
    
    // If the output FIFO is empty, disable the transmit buffer empty 
    // interrupt
    if (rp == wp) {
       disableTxIrq();
    }

}

void PCSerial::enableTxIrq(void) {
    LPC_UART0->IER |= 0x0002;
}

void PCSerial::disableTxIrq(void) {
    LPC_UART0->IER &= ~0x0002;
} 

 

In case you're curious, I'm using the mbed to acquire data from an ADIS16355 IMU over the SPI bus and send it to a host PC over the serial port.

yahugh!

19 Oct 2010

Hi Hugh, welcom to Mbed.

Not actually looked at your code. But if you are already experienced with uC then some working examples will probably be enough to set you off.

First is a simple library I put together to buffer tx and rx http://mbed.org/users/AjK/libraries/SerialBuffered/lfp8fd/docs/files.html

I also released my project (not complete but the serial functions are, all 4 UARTs under int control) so you could look at the various parts of my project to see wotking examples of UARTs under interrupt control:-

http://mbed.org/users/AjK/programs/SOWB/lg489e/docs/files.html

You'll be most interested in debuc.c, gps.c which both contain irq driven UARTs (amoung others).

Hope that helps.

regards,

--Andy

19 Oct 2010

So reading your code it appears that you've chosen not to use the mbed Serial protocol and its associated attach() method. Probably a good idea since it seems not to work. I did download and test your library and it behaves well. My test application follows:

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

int main() {    
    SerialBuffered pc_serial(USBTX, USBRX);
    pc_serial.baud(115200);
    DigitalOut alive_led(LED1);
    char c = '!';
    while (1) {
        alive_led = 1;
        wait(0.2);
        pc_serial.putc(c);
        alive_led = 0;
        wait(0.2);
        c = (c + 1) & 0x7f;
        if (c<=0) c = '!';
    }
}
If I make any useful changes to the library I'll send them along to you.

Thanks,

yahugh!

 

 

19 Oct 2010

Hugh,

The Mbed Serial objects do work, I have used them. But they are of a "generic" nature that fits most solutions well. However, times you need to breakout beyond what's on offer. You then have two choices. Use an derivative class (like the one you used) or "build your own". I just choose the later simply because I've written so many Uart drivers over the last 25yrs it's just second nature. But writing your own can come with it's own problems remember, less support being one of the biggest factors!

regards,

--Andy