UART2 doesn't seem to work

02 Aug 2012

I'm using the MBED as part of the m3pi setup. It communicates with the 3pi robot base, a WiFly wireless UART bridge, and an Arduino acting as a sensor coprocessor. Since the USB UART isn't broken out, that means I need to use all three of the other available UARTS. UART3 is hardwired into the 3pi.

My communications implementation is based on a state machine that operates asynchronously inside uart Rx interrupts. This works perfectly fine on UART1. However, on UART2, the RxIRQ is never fired. Code excerpts:

//UART device to communicate on (m3pi uses 9 and 10 aka UART3)
MODSERIAL _wifly(p28, p27); //UART2

void wifly_input_handler(MODSERIAL_IRQ_INFO *q) {
    char c;
    led2=~led2;
    //While we can get a character and we're still getting a command...
    while (!cur_command.complete) {
        while(!_wifly.readable()){}
        c=_wifly.getc();
        switch (cur_command.type) { //Command recognizer state machine
            case command_t::COM_CLEAR: //Only case where state may be switched in this function
                switch (c) { //Command state transition block
                    case 'M':
                        cur_command.type=command_t::COM_MOTOR_LR;
                        cur_command.counter=0;
                        break;
                    case 'm':
                        cur_command.type=command_t::COM_MOTOR_VW;
                        cur_command.counter=0;
                        break;
                    case 'V':
                        cur_command.type=command_t::COM_VERSION;
                        cur_command.counter=0;
                        cur_command.complete=1; //Only need 1 char to recognize
                        break;
                    case 'K':
                        cur_command.type=command_t::COM_ECHO_SEN;
                        cur_command.counter=0;
                        cur_command.complete=1;
                        break;
                    case 'Q':
                        cur_command.type=command_t::COM_CONN_OPEN;
                        cur_command.counter=0;
                        cur_command.complete=1; //Only need 1 char to recognize
                        break;
                    case 'R':
                        cur_command.type=command_t::COM_CONN_CLOSE;
                        cur_command.counter=0;
                        cur_command.complete=1; //Only need 1 char to recognize
                        break;
                    default: //Character is not in protocol
                        cur_command.type=command_t::COM_CLEAR; //Reset state
                        cur_command.complete=0;
                        break;
                }
                break; //End of CLEAR case
            case command_t::COM_MOTOR_LR: //Recieving motor command specifiers
                cur_command.content.lrd[cur_command.counter]=(signed char)c;
                cur_command.counter++;
                if (cur_command.counter==3) { //If we've recieved all 3 chars...
                    cur_command.complete=1; //We're done
                }
                break;
            case command_t::COM_MOTOR_VW:
                cur_command.content.vwd[cur_command.counter]=(signed char)c;
                cur_command.counter++;
                if (cur_command.counter==3) { //If we've recieved all 3 chars...
                    cur_command.complete=1; //We're done
                }
                break;
            default: //Something has gone wrong
                cur_command.complete=0; //Reset recognizer state
                cur_command.type=command_t::COM_CLEAR;
                cur_command.counter=0;
                break;
        }
    }
}

void wifly_output_handler( MODSERIAL_IRQ_INFO *q) {
    __disable_irq();
    static int _sbuff_out=0;
    if (connection_ok) { //Only if there is an open connection
        //_sbuff_out = cinc(_sbuff_out, BUFFER_SIZE-1);
        int sbuff_in_local_copy = _sbuff_in;
        static char c[3];
        m3pi.locate(0, 1);
        c[1] = sbuff_in_local_copy % 10 + '0';
        c[0] = (sbuff_in_local_copy / 10 ) % 10 + '0';
        m3pi.print(c, 2);
        
        
        m3pi.locate(3, 1);
        c[1] = _sbuff_out % 10 + '0';
        c[0] = (_sbuff_out / 10 ) % 10 + '0';
        m3pi.print(c, 2);
       
        if(_sbuff_out != sbuff_in_local_copy){
        while (_sbuff_out != sbuff_in_local_copy) {
            _wifly.putc(g_output_buff[_sbuff_out]);
            g_output_buff[_sbuff_out] = 0;
            _sbuff_out=cinc(_sbuff_out, BUFFER_SIZE-1);
        }
        } else {
            _wifly.putc(0); //Well don't know how else to do it
        }
    }
    __enable_irq();
}

//Utility to set motor speeds to 0. Ends current command after its duration expires.
void m3pi_nullmotors(void) {
    m3pi.stop();
}

void main(void){
_wifly.attach(&wifly_input_handler, MODSERIAL::RxIrq);
    _wifly.attach(&wifly_output_handler, MODSERIAL::TxIrq);
 while(1){
    led1=connection_ok;
  }
}

I'm using MODSERIAL here because the standard serial class wasn't working; MODSERIAL also doesn't work and shows the same results.

Is there anything that's particularly different about UART2 that makes its ISRs not work?

Thanks!

03 Aug 2012

In fact, the problem goes beyond interrupts. The following code, which should echo incoming characters as well as send a heartbeat character, does not do anything.

#include "mbed.h"
#include "m3pi.h"
 void main(void)
{
    Serial wifly(p28, p27);
    DigitalOut led1(LED1);
    DigitalOut led2(LED2);
    while(1){
        led1=~led1;
        while(!wifly.readable()){}
        wifly.putc(wifly.getc());
        led2=~led2;
        wifly.putc('h');
    }
}