Serial Interrupt Library with mbed RTOS for multi-threading

Dependencies:   buffered-serial1 mbed-rtos mbed

Fork of Serial_interrupts by jim hamblen

Files at this revision

API Documentation at this revision

Comitter:
tylerjw
Date:
Mon Dec 10 00:32:22 2012 +0000
Parent:
0:023c5cda6102
Child:
2:3d959c9fc9d7
Commit message:
library based buffered serial

Changed in this revision

buffered_serial.cpp Show annotated file Show diff for this revision Revisions of this file
buffered_serial.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/buffered_serial.cpp	Mon Dec 10 00:32:22 2012 +0000
@@ -0,0 +1,123 @@
+#include "buffered_serial.h"
+
+BufferedSerial::BufferedSerial(PinName tx, PinName rx) : Serial(tx,rx)
+{
+    tx_in=0;
+    tx_out=0;
+    rx_in=0;
+    rx_out=0;
+    
+    switch( _serial.index ) {
+        case 0:
+            device_irqn = UART0_IRQn;
+            break;
+        case 1:
+            device_irqn = UART1_IRQn;
+            break;
+        case 2:
+            device_irqn = UART2_IRQn;
+            break;
+        case 3:
+            device_irqn = UART3_IRQn;
+            break;
+    }
+    //device_irqn = UART1_IRQn;
+    // attach the interrupts
+    Serial::attach(this, &BufferedSerial::Rx_interrupt, Serial::RxIrq);
+    Serial::attach(this, &BufferedSerial::Tx_interrupt, Serial::TxIrq);
+}
+
+// Copy tx line buffer to large tx buffer for tx interrupt routine
+void BufferedSerial::send_line(char *c)
+{
+    int i;
+    char temp_char;
+    bool empty;
+    i = 0;
+    strncpy(tx_line,c,LINE_SIZE);
+// Start Critical Section - don't interrupt while changing global buffer variables
+    NVIC_DisableIRQ(device_irqn);
+    empty = (tx_in == tx_out);
+    while ((i==0) || (tx_line[i-1] != '\n')) {
+// Wait if buffer full
+        if (((tx_in + 1) & BUFFER_SIZE) == tx_out) {
+// End Critical Section - need to let interrupt routine empty buffer by sending
+            NVIC_EnableIRQ(device_irqn);
+            while (((tx_in + 1) & BUFFER_SIZE) == tx_out) {
+            }
+// Start Critical Section - don't interrupt while changing global buffer variables
+            NVIC_DisableIRQ(device_irqn);
+        }
+        tx_buffer[tx_in] = tx_line[i];
+        i++;
+        tx_in = (tx_in + 1) & BUFFER_SIZE;
+    }
+    if (Serial::writeable() && (empty)) {
+        temp_char = tx_buffer[tx_out];
+        tx_out = (tx_out + 1) & BUFFER_SIZE;
+// Send first character to start tx interrupts, if stopped
+        Serial::putc(temp_char);
+    }
+// End Critical Section
+    NVIC_EnableIRQ(device_irqn);
+    return;
+}
+
+// Read a line from the large rx buffer from rx interrupt routine
+void BufferedSerial::read_line(char *c)
+{
+    int i;
+    i = 0;
+// Start Critical Section - don't interrupt while changing global buffer variables
+    NVIC_DisableIRQ(device_irqn);
+// Loop reading rx buffer characters until end of line character
+    while ((i==0) || (rx_line[i-1] != '\r')) {
+// Wait if buffer empty
+        if (rx_in == rx_out) {
+// End Critical Section - need to allow rx interrupt to get new characters for buffer
+            NVIC_EnableIRQ(device_irqn);
+            while (rx_in == rx_out) {
+            }
+// Start Critical Section - don't interrupt while changing global buffer variables
+            NVIC_DisableIRQ(device_irqn);
+        }
+        rx_line[i] = rx_buffer[rx_out];
+        i++;
+        rx_out = (rx_out + 1) & BUFFER_SIZE;
+    }
+    rx_line[i-1] = 0;
+// End Critical Section
+    NVIC_EnableIRQ(device_irqn);
+    strncpy(c,rx_line,LINE_SIZE);
+    return;
+}
+
+// Interupt Routine to read in data from serial port
+void BufferedSerial::Rx_interrupt()
+{
+    //led1=1;
+// Loop just in case more than one character is in UART's receive FIFO buffer
+// Stop if buffer full
+    while ((Serial::readable()) || (((rx_in + 1) & BUFFER_SIZE) == rx_out)) {
+        rx_buffer[rx_in] = Serial::getc();
+// Uncomment to Echo to USB serial to watch data flow
+//        monitor_Serial::putc(rx_buffer[rx_in]);
+        rx_in = (rx_in + 1) & BUFFER_SIZE;
+    }
+    //led1=0;
+    return;
+}
+
+// Interupt Routine to write out data to serial port
+void BufferedSerial::Tx_interrupt()
+{
+    //led2=1;
+// Loop to fill more than one character in UART's transmit FIFO buffer
+// Stop if buffer empty
+    while ((Serial::writeable()) && (tx_in != tx_out)) {
+        Serial::putc(tx_buffer[tx_out]);
+        tx_out = (tx_out + 1) & BUFFER_SIZE;
+    }
+    //led2=0;
+    return;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/buffered_serial.h	Mon Dec 10 00:32:22 2012 +0000
@@ -0,0 +1,39 @@
+#ifndef BUFFERED_SERIAL_H
+#define BUFFERED_SERIAL_H
+
+#define BUFFER_SIZE     255
+#define LINE_SIZE       80
+
+#include "mbed.h"
+
+class BufferedSerial : public Serial
+{
+public:
+    BufferedSerial::BufferedSerial(PinName tx, PinName rx);
+
+    void send_line(char*);
+    void read_line(char*);
+
+
+private:
+    void Tx_interrupt();
+    void Rx_interrupt();
+
+// for disabling the irq
+    IRQn device_irqn;
+// Circular buffers for serial TX and RX data - used by interrupt routines
+// might need to increase buffer size for high baud rates
+    char tx_buffer[BUFFER_SIZE];
+    char rx_buffer[BUFFER_SIZE];
+// Circular buffer pointers
+// volatile makes read-modify-write atomic
+    volatile int tx_in;
+    volatile int tx_out;
+    volatile int rx_in;
+    volatile int rx_out;
+// Line buffers for sprintf and sscanf
+    char tx_line[LINE_SIZE];
+    char rx_line[LINE_SIZE];
+};
+
+#endif
\ No newline at end of file
--- a/main.cpp	Tue Nov 16 15:00:30 2010 +0000
+++ b/main.cpp	Mon Dec 10 00:32:22 2012 +0000
@@ -1,5 +1,5 @@
-
 #include "mbed.h"
+#include "buffered_serial.h"
 // Serial TX & RX interrupt loopback test using formatted IO - sprintf and sscanf
 // Connect TX to RX (p9 to p10)
 // or can also use USB and type back in the number printed out in a terminal window
@@ -9,7 +9,8 @@
 // LED3 changing indicate main loop running
 
 
-Serial device(p9, p10);  // tx, rx
+BufferedSerial device(p13,p14);  // tx, rx
+//IRQn device_irqn = UART1_IRQn;
 // Can also use USB and type back in the number printed out in a terminal window
 // Serial monitor_device(USBTX, USBRX);
 DigitalOut led1(LED1);
@@ -17,7 +18,7 @@
 DigitalOut led3(LED3);
 DigitalOut led4(LED4);
 
-
+/*
 void Tx_interrupt();
 void Rx_interrupt();
 void send_line();
@@ -35,21 +36,23 @@
 volatile int tx_out=0;
 volatile int rx_in=0;
 volatile int rx_out=0;
+*/
 // Line buffers for sprintf and sscanf
 char tx_line[80];
 char rx_line[80];
 
 // main test program
-int main() {
+int main()
+{
     int i=0;
     int rx_i=0;
     device.baud(9600);
-
+/*
 // Setup a serial interrupt function to receive data
     device.attach(&Rx_interrupt, Serial::RxIrq);
 // Setup a serial interrupt function to transmit data
     device.attach(&Tx_interrupt, Serial::TxIrq);
-
+*/
 // Formatted IO test using send and receive serial interrupts
 // with sprintf and sscanf
     while (1) {
@@ -59,30 +62,30 @@
 // Print ASCII number to tx line buffer in hex
             sprintf(tx_line,"%x\r\n",i);
 // Copy tx line buffer to large tx buffer for tx interrupt routine
-            send_line();
+            device.send_line(tx_line);
 // Print ASCII number to tx line buffer in decimal
             sprintf(tx_line,"%d\r\n",i);
 // Copy tx line buffer to large tx buffer for tx interrupt routine
-            send_line();
+            device.send_line(tx_line);
 // Print ASCII number to tx line buffer in octal
             sprintf(tx_line,"%o\r\n",i);
 // Copy tx line buffer to large tx buffer for tx interrupt routine
-            send_line();
+            device.send_line(tx_line);
             led3=0;
 // Read a line from the large rx buffer from rx interrupt routine
-            read_line();
+            device.read_line(rx_line);
 // Read ASCII number from rx line buffer
             sscanf(rx_line,"%x",&rx_i);
 // Check that numbers are the same
             if (i != rx_i) led4=1;
 // Read a line from the large rx buffer from rx interrupt routine
-            read_line();
+            device.read_line(rx_line);
 // Read ASCII number from rx line buffer
             sscanf(rx_line,"%d",&rx_i);
 // Check that numbers are the same
             if (i != rx_i) led4=1;
 // Read a line from the large rx buffer from rx interrupt routine
-            read_line();
+            device.read_line(rx_line);
 // Read ASCII number from rx line buffer
             sscanf(rx_line,"%o",&rx_i);
 // Check that numbers are the same
@@ -91,91 +94,3 @@
     }
 }
 
-// Copy tx line buffer to large tx buffer for tx interrupt routine
-void send_line() {
-    int i;
-    char temp_char;
-    bool empty;
-    i = 0;
-// Start Critical Section - don't interrupt while changing global buffer variables
-    NVIC_DisableIRQ(UART1_IRQn);
-    empty = (tx_in == tx_out);
-    while ((i==0) || (tx_line[i-1] != '\n')) {
-// Wait if buffer full
-        if (((tx_in + 1) % buffer_size) == tx_out) {
-// End Critical Section - need to let interrupt routine empty buffer by sending
-            NVIC_EnableIRQ(UART1_IRQn);
-            while (((tx_in + 1) % buffer_size) == tx_out) {
-            }
-// Start Critical Section - don't interrupt while changing global buffer variables
-            NVIC_DisableIRQ(UART1_IRQn);
-        }
-        tx_buffer[tx_in] = tx_line[i];
-        i++;
-        tx_in = (tx_in + 1) % buffer_size;
-    }
-    if (device.writeable() && (empty)) {
-        temp_char = tx_buffer[tx_out];
-        tx_out = (tx_out + 1) % buffer_size;
-// Send first character to start tx interrupts, if stopped
-        device.putc(temp_char);
-    }
-// End Critical Section
-    NVIC_EnableIRQ(UART1_IRQn);
-    return;
-}
-
-// Read a line from the large rx buffer from rx interrupt routine
-void read_line() {
-    int i;
-    i = 0;
-// Start Critical Section - don't interrupt while changing global buffer variables
-    NVIC_DisableIRQ(UART1_IRQn);
-// Loop reading rx buffer characters until end of line character
-    while ((i==0) || (rx_line[i-1] != '\r')) {
-// Wait if buffer empty
-        if (rx_in == rx_out) {
-// End Critical Section - need to allow rx interrupt to get new characters for buffer
-            NVIC_EnableIRQ(UART1_IRQn);
-            while (rx_in == rx_out) {
-            }
-// Start Critical Section - don't interrupt while changing global buffer variables
-            NVIC_DisableIRQ(UART1_IRQn);
-        }
-        rx_line[i] = rx_buffer[rx_out];
-        i++;
-        rx_out = (rx_out + 1) % buffer_size;
-    }
-    rx_line[i-1] = 0;
-// End Critical Section
-    NVIC_EnableIRQ(UART1_IRQn);
-    return;
-}
-
-// Interupt Routine to read in data from serial port
-void Rx_interrupt() {
-    led1=1;
-// Loop just in case more than one character is in UART's receive FIFO buffer
-// Stop if buffer full
-    while ((device.readable()) || (((rx_in + 1) % buffer_size) == rx_out)) {
-        rx_buffer[rx_in] = device.getc();
-// Uncomment to Echo to USB serial to watch data flow
-//        monitor_device.putc(rx_buffer[rx_in]);
-        rx_in = (rx_in + 1) % buffer_size;
-    }
-    led1=0;
-    return;
-}
-
-// Interupt Routine to write out data to serial port
-void Tx_interrupt() {
-    led2=1;
-// Loop to fill more than one character in UART's transmit FIFO buffer
-// Stop if buffer empty
-    while ((device.writeable()) && (tx_in != tx_out)) {
-        device.putc(tx_buffer[tx_out]);
-        tx_out = (tx_out + 1) % buffer_size;
-    }
-    led2=0;
-    return;
-}
\ No newline at end of file
--- a/mbed.bld	Tue Nov 16 15:00:30 2010 +0000
+++ b/mbed.bld	Mon Dec 10 00:32:22 2012 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
+http://mbed.org/users/mbed_official/code/mbed/builds/63cdd78b2dc1
\ No newline at end of file