Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of UtilityLib by
Revision 9:f71dc1b426da, committed 2014-03-18
- Comitter:
- mgottscho
- Date:
- Tue Mar 18 23:56:23 2014 +0000
- Parent:
- 8:e79637fbb035
- Commit message:
- Made the Utility class just a SerialManager, and factored out useful functionality not relevant to serial operation into global C functions.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialManager.cpp Tue Mar 18 23:56:23 2014 +0000 @@ -0,0 +1,201 @@ +/* SerialManager.cpp + * Tested with mbed board: FRDM-KL46Z + * Author: Mark Gottscho + * mgottscho@ucla.edu + */ + +#include "mbed.h" +#include "SerialManager.h" + +using namespace std; + +SerialManager::SerialManager(PinName serial_tx_pin, PinName serial_rx_pin, int baudrate, bool enableSerialInterrupts) : + serial(serial_tx_pin, serial_rx_pin), + __interrupts_en(enableSerialInterrupts), + __user_fptr(NULL), + __rx_head(0), + __rx_tail(0), + __tx_head(0), + __tx_tail(0), + __have_rx_serial(false) + { + + serial.baud(baudrate); + + //Set up serial interrupt handlers + if (__interrupts_en) { + serial.attach(this, &SerialManager::__serial_rx_ISR, Serial::RxIrq); + //serial.attach(this, &SerialManager::__serial_tx_ISR, Serial::TxIrq); + } +} + +SerialManager::~SerialManager() { + detach_rx(); +} + +void SerialManager::attach_rx(void (*fptr)(void)) { + //set user function pointer + detach_rx(); + if (fptr != NULL) + __user_fptr = new FunctionPointer(fptr); +} + +template<typename T> void SerialManager::attach_rx(T *tptr, void (T::*mptr)(void)) { + //set user function pointer + detach(); + if (tptr != NULL && mptr != NULL) + __user_fptr = new FunctionPointer(tptr, mptr); +} + +void SerialManager::detach_rx() { + if (__user_fptr != NULL) + delete __user_fptr; + __user_fptr = NULL; +} + +//THIS DOES NOT WORK YET +/*uint32_t SerialManager::sendLine(const char *line, const uint32_t len) { + int i = 0; + char temp_byte; + bool buf_empty; + + if (line == NULL) //check input + return 0; + + G_red_led = 0; + + // Start critical section - don't interrupt while changing global buffer variables + __disable_irq(); + buf_empty = (G_tx_head == G_tx_tail); + + while (i < len && line[i] != '\r') { //Loop until we have sent the maximum number of characters or we hit a carriage return + // Wait if tx buffer full + if ((G_tx_head + 1) % BUFFER_SIZE == G_tx_tail) { //If TX buffer is full, wait. + // End critical section - need to let interrupt routine empty buffer by sending + __enable_irq(); + while ((G_tx_head + 1) % BUFFER_SIZE == G_tx_tail) { } //Spinloop until TX buffer is not full + // Start critical section - don't interrupt while changing global buffer variables + __disable_irq(); + } + G_tx_head = (G_tx_head + 1) % BUFFER_SIZE; + G_tx_buf[G_tx_head] = line[i++]; + } + + //Now we have buffered all characters in the line. Trigger the TX serial interrupt + if (G_console.writeable() && buf_empty) { + //Write the first byte to get it started + temp_byte = G_tx_buf[G_tx_tail]; + G_tx_tail = (G_tx_tail + 1) % BUFFER_SIZE; + + // Send first character to start tx interrupts, if stopped + G_console.putc(temp_byte); + } + + // End critical section + __enable_irq(); + + G_red_led = 1; + + return i; +}*/ + + +uint32_t SerialManager::receiveLine(char *line, const uint32_t len) { + int i = 0; + char lastChar = '\0'; + + if (line == NULL) //check input + return 0; + + // Start critical section - don't interrupt while changing global buffer variables + __disable_uart_irq(); + + while (i < len && lastChar != '\r') { //Loop until maximum number of characters or a newline symbol + //Wait for more characters if the rx buffer is empty + if (__rx_tail == __rx_head) { + // End critical section - need to allow rx interrupt to get new characters for buffer + __enable_uart_irq(); + while (__rx_tail == __rx_head) { } //Spinloop until there are some characters + // Start critical section - don't interrupt while changing global buffer variables + __disable_uart_irq(); + } + + lastChar = __rx_buf[__rx_tail]; + if (lastChar == '\r') //newline symbol + line[i] = '\0'; + else + line[i] = lastChar; + i++; + __rx_tail = (__rx_tail + 1) % BUFFER_SIZE; + } + + //Clear flag + __have_rx_serial = false; + + // End critical section + __enable_uart_irq(); + + return i; +} + +bool SerialManager::haveRxSerialData() { + return __have_rx_serial; +} + +void SerialManager::flush() { + while (serial.readable()) { + serial.getc(); + } +} + +void SerialManager::print_line(const char *line, int len) { + if (line == NULL || len < 1) + return; + + const char *curr = line; + while (curr < line+len && *curr != '\0') { + serial.putc(*curr); + curr++; + } +} + +void SerialManager::__serial_rx_ISR() { + char tmp; + + if (__user_fptr != NULL) //user callback + __user_fptr->call(); + + //Loop while the UART inbound FIFO is not empty and the receiving buffer is not full + while (serial.readable() && (__rx_head != (__rx_tail - 1) % BUFFER_SIZE)) { + tmp = serial.getc(); //read a byte into the buffer from the serial port + __rx_buf[__rx_head] = tmp; + __rx_head = (__rx_head + 1) % BUFFER_SIZE; + if (tmp == '\r') + __have_rx_serial = true; + } +} + +//THIS DOES NOT WORK YET +/*void SerialManager::__serial_tx_ISR() { + //Loop while the UART outbound FIFO is not full and the transmitting buffer is not empty + while (G_console.writeable() && (G_tx_tail != G_tx_head)) { + G_console.putc(G_tx_buf[G_tx_tail]); //write a byte to the serial port from the buffer + G_tx_tail = (G_tx_tail + 1) % BUFFER_SIZE; + } +}*/ + +inline void SerialManager::__disable_uart_irq() { + // Start critical section - don't interrupt with serial I/O + // Since user specifies UART TX/RX pins, we don't know which we are using, so disable all 3 + NVIC_DisableIRQ(UART0_IRQn); + NVIC_DisableIRQ(UART1_IRQn); + NVIC_DisableIRQ(UART2_IRQn); +} + +inline void SerialManager::__enable_uart_irq() { + // End critical section - can now interrupt with serial I/O + // Since user specifies UART TX/RX pins, we don't know which we are using, so enable all 3 + NVIC_EnableIRQ(UART0_IRQn); + NVIC_EnableIRQ(UART1_IRQn); + NVIC_EnableIRQ(UART2_IRQn); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialManager.h Tue Mar 18 23:56:23 2014 +0000 @@ -0,0 +1,111 @@ +/* SerialManager.h + * Tested with mbed board: FRDM-KL46Z + * Author: Mark Gottscho + * mgottscho@ucla.edu + */ + +#ifndef SERIALMANAGER_H +#define SERIALMANAGER_H + +#include "mbed.h" + +class SerialManager { + public: + /** + * Constructs a SerialManager object, which manages serial communication and interrupts for a specific port. + * @param serial_tx_pin pin for the UART TX + * @param serial_rx_pin pin for the UART RX + * @param enableSerialInterrupts if true, allows interrupt handlers on the serial port + */ + SerialManager(PinName serial_tx_pin, PinName serial_rx_pin, int baudrate, bool enableSerialInterrupts); + + /** + * Destructor. + */ + ~SerialManager(); + + /** + * Attaches a user-specified callback function that is called each time serial data is received. + * @param fptr the user callback function + */ + void attach_rx(void (*fptr)(void)); + + /** + * Attaches a user-specified callback member function that is called each time serial data is received. + * @param tptr the object + * @param mptr method to call on the object + */ + template<typename T> void attach_rx(T *tptr, void (T::*mptr)(void)); + + /** + * Detaches the user-specified RX callback function, if any. + */ + void detach_rx(); + + /** + * Receives a line of data from the serial console, terminated by a carriage return character. + * @param line a pointer to the buffer in which to store the incoming data + * @param len the maximum number of bytes to receive + * @returns number of bytes received + */ + uint32_t receiveLine(char *line, const uint32_t len); + + /** + * Sends a line of data to the serial port. + * @param line a pointer to the beginning of the data to send + * @param len the number of bytes to send + * @returns number of bytes sent + */ + //uint32_t sendLine(const char *line, const uint32_t len); + + /** + * @returns true if there is data received from serial port ready to use. + */ + bool haveRxSerialData(); + + /** + * Flushes the serial RX buffer. + */ + void flush(); + + /** + * Prints a string to the serial device, terminated by CRLF. Interrupt-safe. + * @param line the C string to print + * @param len the maximum length of the line + */ + void print_line(const char *line, int len); + + /** + * In case the user needs direct Serial access. + */ + Serial serial; + + private: + /** + * Interrupt service routine for serial RX + */ + void __serial_rx_ISR(); + + /** + * Interrupt service routine for serial TX + */ + //void __serial_tx_ISR(); + + inline void __disable_uart_irq(); + inline void __enable_uart_irq(); + + bool __interrupts_en; + FunctionPointer *__user_fptr; //User callback function that is invoked in __serial_rx_ISR() + + //Buffers for working with the serial interface + const static uint32_t BUFFER_SIZE = 512; //For serial buffer + volatile uint8_t __rx_buf[BUFFER_SIZE]; + volatile uint8_t __tx_buf[BUFFER_SIZE]; + volatile uint32_t __rx_head; //Head always points to the first item to read (oldest) + volatile uint32_t __rx_tail; //Tail always points to the last item written (newest) + volatile uint32_t __tx_head; + volatile uint32_t __tx_tail; + volatile bool __have_rx_serial; //Flag for the RX data +}; + +#endif \ No newline at end of file
--- a/Utility.cpp Wed Mar 12 19:47:18 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,283 +0,0 @@ -/* Utility.cpp - * Tested with mbed board: FRDM-KL46Z - * Author: Mark Gottscho - * mgottscho@ucla.edu - */ - -#include "mbed.h" -#include <string> -#include "Utility.h" - -using namespace std; - -Utility::Utility(DigitalOut *green_led, DigitalOut *red_led, PinName serial_tx_pin, PinName serial_rx_pin, int baudrate, bool enableSerialInterrupts) : - console(serial_tx_pin, serial_rx_pin), - __green_led(green_led), - __red_led(red_led), - __valid_green(false), - __valid_red(false), - __interrupts_en(enableSerialInterrupts), - __user_fptr(NULL), - __green_led_interrupt(), - __red_led_interrupt(), - __rx_head(0), - __rx_tail(0), - __tx_head(0), - __tx_tail(0), - __have_rx_serial(false) - { - - if (__green_led != NULL) { - __valid_green = true; - *__green_led = 1; - } - if (__red_led != NULL) { - __valid_red = true; - *__red_led = 1; - } - - console.baud(baudrate); //115200, 230400 confirmed to work, above this seems to fail - - //Set up serial interrupt handlers - if (__interrupts_en) { - console.attach(this, &Utility::__console_rx_ISR, Serial::RxIrq); - //console.attach(this, &Utility::__console_tx_ISR, Serial::TxIrq); - } -} - -Utility::~Utility() { - detach(); -} - -void Utility::attach(void (*fptr)(void)) { - //set user function pointer - detach(); - if (fptr != NULL) - __user_fptr = new FunctionPointer(fptr); -} - -template<typename T> void Utility::attach(T *tptr, void (T::*mptr)(void)) { - //set user function pointer - detach(); - if (tptr != NULL && mptr != NULL) - __user_fptr = new FunctionPointer(tptr, mptr); -} - -void Utility::detach() { - if (__user_fptr != NULL) - delete __user_fptr; - __user_fptr = NULL; -} - -void Utility::panic(string errorMessage, int errorCode) { - //We're dead. This is the point of no return! Permanently ignore interrupts. - __disable_irq(); - - console.printf(">>> PANIC, CODE # %d: %s <<<\r\n", errorCode, errorMessage.c_str()); - - if (__valid_green) - *__green_led = 1; - if (__valid_red) - *__red_led = 0; - - while(1); //Spinloop for eternity -} - -void Utility::warn(string errorMessage, int errorCode) { - console.printf(">>> WARN, CODE # %d: %s <<<\r\n", errorCode, errorMessage.c_str()); -} - -#ifdef NDEBUG -void Utility::myAssert(bool condition, const char *file, const unsigned long line) { } -#else -void Utility::myAssert(bool condition, const char *file, const unsigned long line) { - if (!condition) - { - char msg[256]; - sprintf(msg, "Assertion failed at file %s, line %d", file, line); - panic(msg, -1); \ - } -} -#endif - -void Utility::blinkGreen(bool enable, float half_period) { - if (__valid_green) { - if (enable) { - if (half_period <= 0.01) { - __green_led_interrupt.detach(); - *__green_led = 0; - } else if (half_period <= 1800) - __green_led_interrupt.attach(this, &Utility::__greenLED_ISR, half_period); - } - else { - __green_led_interrupt.detach(); - *__green_led = 1; - } - } -} - -void Utility::blinkRed(bool enable, float half_period) { - if (__valid_red) { - if (enable) { - if (half_period <= 0.01) { - __red_led_interrupt.detach(); - *__red_led = 0; - } else if (half_period <= 1800) - __red_led_interrupt.attach(this, &Utility::__redLED_ISR, half_period); - } - else { - __red_led_interrupt.detach(); - *__red_led = 1; - } - } -} - -//THIS DOES NOT WORK YET -/*uint32_t Utility::sendLine(const char *line, const uint32_t len) { - int i = 0; - char temp_byte; - bool buf_empty; - - if (line == NULL) //check input - return 0; - - G_red_led = 0; - - // Start critical section - don't interrupt while changing global buffer variables - __disable_irq(); - buf_empty = (G_tx_head == G_tx_tail); - - while (i < len && line[i] != '\r') { //Loop until we have sent the maximum number of characters or we hit a carriage return - // Wait if tx buffer full - if ((G_tx_head + 1) % BUFFER_SIZE == G_tx_tail) { //If TX buffer is full, wait. - // End critical section - need to let interrupt routine empty buffer by sending - __enable_irq(); - while ((G_tx_head + 1) % BUFFER_SIZE == G_tx_tail) { } //Spinloop until TX buffer is not full - // Start critical section - don't interrupt while changing global buffer variables - __disable_irq(); - } - G_tx_head = (G_tx_head + 1) % BUFFER_SIZE; - G_tx_buf[G_tx_head] = line[i++]; - } - - //Now we have buffered all characters in the line. Trigger the TX serial interrupt - if (G_console.writeable() && buf_empty) { - //Write the first byte to get it started - temp_byte = G_tx_buf[G_tx_tail]; - G_tx_tail = (G_tx_tail + 1) % BUFFER_SIZE; - - // Send first character to start tx interrupts, if stopped - G_console.putc(temp_byte); - } - - // End critical section - __enable_irq(); - - G_red_led = 1; - - return i; -}*/ - - -uint32_t Utility::receiveLine(char *line, const uint32_t len) { - int i = 0; - char lastChar = '\0'; - - if (line == NULL) //check input - return 0; - - // Start critical section - don't interrupt while changing global buffer variables - __disable_uart_irq(); - - while (i < len && lastChar != '\r') { //Loop until maximum number of characters or a newline symbol - //Wait for more characters if the rx buffer is empty - if (__rx_tail == __rx_head) { - // End critical section - need to allow rx interrupt to get new characters for buffer - __enable_uart_irq(); - while (__rx_tail == __rx_head) { } //Spinloop until there are some characters - // Start critical section - don't interrupt while changing global buffer variables - __disable_uart_irq(); - } - - lastChar = __rx_buf[__rx_tail]; - if (lastChar == '\r') //newline symbol - line[i] = '\0'; - else - line[i] = lastChar; - i++; - __rx_tail = (__rx_tail + 1) % BUFFER_SIZE; - } - - //Clear flag - __have_rx_serial = false; - - // End critical section - __enable_uart_irq(); - - return i; -} - -bool Utility::haveRxSerialData() { - return __have_rx_serial; -} - -void Utility::flushConsole() { - while (console.readable()) { - console.getc(); - } -} - -void Utility::__greenLED_ISR() { - if (*__green_led == 0) //Just flip the LED status every time we are called - *__green_led = 1; - else - *__green_led = 0; -} - -void Utility::__redLED_ISR() { - if (*__red_led == 0) //Just flip the LED status every time we are called - *__red_led = 1; - else - *__red_led = 0; -} - -void Utility::__console_rx_ISR() { - char tmp; - - if (__user_fptr != NULL) //user callback - __user_fptr->call(); - - //Loop while the UART inbound FIFO is not empty and the receiving buffer is not full - while (console.readable() && (__rx_head != (__rx_tail - 1) % BUFFER_SIZE)) { - tmp = console.getc(); //read a byte into the buffer from the serial port - __rx_buf[__rx_head] = tmp; - __rx_head = (__rx_head + 1) % BUFFER_SIZE; - if (tmp == '\r') - __have_rx_serial = true; - } -} - -//THIS DOES NOT WORK YET -/*void Utility::__console_tx_ISR() { - //Loop while the UART outbound FIFO is not full and the transmitting buffer is not empty - while (G_console.writeable() && (G_tx_tail != G_tx_head)) { - G_console.putc(G_tx_buf[G_tx_tail]); //write a byte to the serial port from the buffer - G_tx_tail = (G_tx_tail + 1) % BUFFER_SIZE; - } -}*/ - -inline void Utility::__disable_uart_irq() { - // Start critical section - don't interrupt with serial I/O - // Since user specifies UART TX/RX pins, we don't know which we are using, so disable all 3 - NVIC_DisableIRQ(UART0_IRQn); - NVIC_DisableIRQ(UART1_IRQn); - NVIC_DisableIRQ(UART2_IRQn); -} - -inline void Utility::__enable_uart_irq() { - // End critical section - can now interrupt with serial I/O - // Since user specifies UART TX/RX pins, we don't know which we are using, so enable all 3 - NVIC_EnableIRQ(UART0_IRQn); - NVIC_EnableIRQ(UART1_IRQn); - NVIC_EnableIRQ(UART2_IRQn); -} \ No newline at end of file
--- a/Utility.h Wed Mar 12 19:47:18 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -/* Utility.h - * Tested with mbed board: FRDM-KL46Z - * Author: Mark Gottscho - * mgottscho@ucla.edu - */ - -#ifndef UTILITY_H -#define UTILITY_H - -#include "mbed.h" -#include <string> - -class Utility { - public: - /** - * Constructs a Utility object, which manages LEDs, serial communication, and other helper methods. - * @param green_led pointer to a DigitalOut for green LED blinking - * @param red_led pointer to a DigitalOut for green LED blinking - * @param serial_tx_pin pin for the UART TX - * @param serial_rx_pin pin for the UART RX - * @param enableSerialInterrupts if true, allows interrupt handlers on the serial port - */ - Utility(DigitalOut *green_led, DigitalOut *red_led, PinName serial_tx_pin, PinName serial_rx_pin, int baudrate, bool enableSerialInterrupts); - - /** - * Utility destructor. - */ - ~Utility(); - - /** - * Attaches a user-specified callback function that is called each time serial data is received. - * @param fptr the user callback function - */ - void attach(void (*fptr)(void)); - - /** - * Attaches a user-specified callback member function that is called each time serial data is received. - * @param tptr the object - * @param mptr method to call on the object - */ - template<typename T> void attach(T *tptr, void (T::*mptr)(void)); - - /** - * Detaches the user-specified callback function, if any. - */ - void detach(); - - /** - * Infinitely loop in a panic condition, disabling the green user LED, enabling the red user LED and printing an error message to the serial console. - * This method never returns. - * @param errorMessage the string to print - * @param errorCode the accompanying error code to print - */ - void panic(string errorMessage, int errorCode); - - /** - * Print a warning message to the serial console. - * @param errorMessage the string to print - * @param errorCode the accompanying error code to print - */ - void warn(string errorMessage, int errorCode); - - /** - * Object-oriented assert statement. - * @param condition if false, calls panic() with results of the assertion, and never returns. - * @param file string representing the source file where the assertion is called - * @param line line number of the source file where the assertion is called - */ - void myAssert(bool condition, const char *file, const unsigned long line); - - /** - * Blink the green user LED. This is a non-blocking call. The LED will blink until it is disabled. - * @param enable if true, enables the blinking LED - * @param half_period half of the blink period. This is the "on-time" and "off-time" of LED (50% duty cycle). - * If non-positive, the LED will stay on. - * half_period must be no more than 1800 seconds (30 minutes), or this method will have no effect. - */ - void blinkGreen(bool enable, float half_period); - - /** - * Blink the red user LED. This is a non-blocking call. The LED will blink until it is disabled. - * @param enable if true, enables the blinking LED - * @param half_period half of the blink period. This is the "on-time" and "off-time" of LED (50% duty cycle). - * If non-positive, the LED will stay on. - * half_period must be no more than 1800 seconds (30 minutes), or this method will have no effect. - */ - void blinkRed(bool enable, float half_period); - - /** - * Receives a line of data from the serial console, terminated by a carriage return character. - * @param line a pointer to the buffer in which to store the incoming data - * @param len the maximum number of bytes to receive - * @returns number of bytes received - */ - uint32_t receiveLine(char *line, const uint32_t len); - - /** - * Sends a line of data to the serial port. - * @param line a pointer to the beginning of the data to send - * @param len the number of bytes to send - * @returns number of bytes sent - */ - //uint32_t sendLine(const char *line, const uint32_t len); - - /** - * @returns true if there is data received from serial port ready to use. - */ - bool haveRxSerialData(); - - /** - * Flushes the console serial RX buffer. - */ - void flushConsole(); - - Serial console; - - private: - /** - * Interrupt service routine for blinking the green user LED. - */ - void __greenLED_ISR(); - - /** - * Interrupt service routine for blinking the red user LED. - */ - void __redLED_ISR(); - - /** - * Interrupt service routine for serial RX - */ - void __console_rx_ISR(); - - - /** - * Interrupt service routine for serial TX - */ - //void __console_tx_ISR(); - - inline void __disable_uart_irq(); - inline void __enable_uart_irq(); - - DigitalOut *__green_led; - DigitalOut *__red_led; - - bool __valid_green; - bool __valid_red; - - bool __interrupts_en; - FunctionPointer *__user_fptr; //User callback function that is invoked in __console_rx_ISR() - - Ticker __green_led_interrupt; - Ticker __red_led_interrupt; - - //Buffers for working with the serial console - const static uint32_t BUFFER_SIZE = 512; //For serial buffer - volatile uint8_t __rx_buf[BUFFER_SIZE]; - volatile uint8_t __tx_buf[BUFFER_SIZE]; - volatile uint32_t __rx_head; //Head always points to the first item to read (oldest) - volatile uint32_t __rx_tail; //Tail always points to the last item written (newest) - volatile uint32_t __tx_head; - volatile uint32_t __tx_tail; - volatile bool __have_rx_serial; //Flag for the RX data -}; - -#endif \ No newline at end of file
--- a/util.cpp Wed Mar 12 19:47:18 2014 +0000 +++ b/util.cpp Tue Mar 18 23:56:23 2014 +0000 @@ -23,4 +23,58 @@ b2 = (var >> 16) & 0xFF; b1 = (var >> 8) & 0xFF; b0 = (var) & 0xFF; +} + +void panic(Serial *serial, const char *errorMessage, int errorCode, DigitalOut *green_led, DigitalOut *red_led) { + //We're dead. This is the point of no return! Permanently ignore interrupts. + __disable_irq(); + + if (green_led != NULL) + *green_led = 1; //Turn off green LED + if (red_led != NULL) + *red_led = 0; //Turn on red LED + + if (serial != NULL) { + if (errorMessage != NULL) + serial->printf(">>> PANIC, CODE # %d: %s <<<\r\n", errorCode, errorMessage); + else + serial->printf(">>> PANIC <<<\r\n"); + } + + while(1); //Spinloop for eternity +} + +void warn(Serial *serial, const char *errorMessage, int errorCode) { + if (serial != NULL) { + if (errorMessage != NULL) + serial->printf(">>> WARN, CODE # %d: %s <<<\r\n", errorCode, errorMessage); + else + serial->printf(">>> WARN <<<\r\n"); + } +} + + +#ifdef NDEBUG +void myAssert(Serial *serial, bool condition, const char *file, unsigned long line, DigitalOut *green_led, DigitalOut *red_led) { } +#else +void myAssert(Serial *serial, bool condition, const char *file, unsigned long line, DigitalOut *green_led, DigitalOut *red_led) { + if (!condition) + { + char msg[256]; + if (file != NULL) + sprintf(msg, "Assertion failed at file %s, line %d", file, line); + else + sprintf(msg, "Assertion failed at file UNKNOWN, line %d", line); + panic(serial, msg, -1, green_led, red_led); + } +} +#endif + +void toggleLED(DigitalOut *led) { + if (led != NULL) { + if (*led == 1) + *led = 0; + else + *led = 1; + } } \ No newline at end of file
--- a/util.h Wed Mar 12 19:47:18 2014 +0000 +++ b/util.h Tue Mar 18 23:56:23 2014 +0000 @@ -6,5 +6,48 @@ #include "mbed.h" +/** + * Convert four bytes to an unsigned 32-bit int, MSB first. + */ uint32_t bytes_to_unsigned(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0); -void unsigned_to_bytes(const uint32_t var, uint8_t &b3, uint8_t &b2, uint8_t &b1, uint8_t &b0); \ No newline at end of file + +/** + * Convert an unsigned 32-bit int to 4 bytes, MSB first. + */ +void unsigned_to_bytes(const uint32_t var, uint8_t &b3, uint8_t &b2, uint8_t &b1, uint8_t &b0); + +/** + * Infinitely loop in a panic condition, disabling the green user LED, enabling the red user LED and printing an error message. + * This method never returns! + * @param serial the serial interface to use if any + * @param errorMessage the C string to print + * @param errorCode the accompanying error code to print + * @param green_led the green LED if any + * @param red_led the red LED if any + */ +void panic(Serial *serial, const char *errorMessage, int errorCode, DigitalOut *green_led, DigitalOut *red_led); + +/** + * Print a warning message to a serial console. + * @param serial the serial interface to use if any + * @param errorMessage the C string to print + * @param errorCode the accompanying error code to print + */ +void warn(Serial *serial, const char *errorMessage, int errorCode); + +/** + * Assert statement. + * @param serial the serial interface to use if any + * @param condition if false, calls panic() with results of the assertion, and never returns. + * @param file string representing the source file where the assertion is called + * @param line line number of the source file where the assertion is called + * @param green_led the green LED, if any + * @param red_led the red LED, if any + */ +void myAssert(Serial *serial, bool condition, const char *file, unsigned long line, DigitalOut *green_led, DigitalOut *red_led); + +/** + * Toggles an LED, if any. + * @param led the LED. + */ +void toggleLED(DigitalOut *led); \ No newline at end of file