Main Site Documentation

Receiving data from a serial port


#1

I’m trying to set up a bluetooth connection in native code, and I can’t seem to get the reading to work properly. Writing to bluetooth from native code is working, and both reading and writing are working from c# so the connections on the board are correct. I’m setting up the bluetooth connection in c#, then using the RLP method EnableInterruptInputMode to set up an interrupt, which is being called but I can’t figure out where to read the value of the received byte. I’m creating the connection over COM1 by creating the interrupt on pin 20 (as per page 13 of http://www.ghielectronics.com/downloads/USBizi/USBizi_User_Manual.pdf), and trying to read from U1RBR to get the data (as well as U0RBR since page 28 of that same document shows that COM1 uses UART0, but I always get zeros from each register.

Here’s the useful segments of the code I’m using:
In C# code:


bluetooth = new SerialPort("COM1", BAUD_RATE, Parity.None, 8, StopBits.One);
            //bluetooth.DataReceived += new SerialDataReceivedEventHandler(bluetooth_DataReceived);
            
            bluetooth.Open();
            int result = rlp_StartBluetooth.Invoke();
            Debug.Print("StartBluetooth() returned " + result.ToString());

            Thread.Sleep(Timeout.Infinite);

Setting up bluetooth connection in c:



		RLP_InterruptInputPinArgs pinArgs = {0, 0, 0};
		pinArgs.GlitchFilterEnable = RLP_FALSE;
		pinArgs.IntEdge = RLP_GPIO_INT_EDGE_HIGH;
		pinArgs.ResistorState = RLP_GPIO_RESISTOR_DISABLED;
		
		if(RLPext->GPIO.EnableInterruptInputMode(RX_INTERRUPT_PIN, &pinArgs, bluetoothReceiveISR, 0))
		{
			Debug("RLPext->GPIO.EnableInterruptInputMode() returned 1");
		}
		else
		{
			Debug("RLPext->GPIO.EnableInterruptInputMode() returned 0");
		}
		
		Debug("finished setupBluetoothReceiving()");


And finally the interrupt function:



Debug("Start of bluetoothReceiveISR");
	
	volatile char c;
	c = U1RBR;
	Debug("U1RBR:");
	Debug_int(c);
	
	c = U0RBR;
	Debug("U0RBR: " );
	Debug_int(c);
	
	VICVectAddr = 0; // Acknowledge Interrupt 


Any ideas why U0RBR and U1RBR are both always 0? Do I need to set anything else to have them filled with data, or am I reading from the wrong place? Thanks!


#2

nick, welcome to the forum.

I have no direct input, but a question. Why are you going to this level when you can deal with serial IO wholly within C# managed code? RLP is good for some things, but I am not sure you need it in this scenario.


#3

My plan is to use a Fez Domino to get analog input, do some data analysis and then send it over bluetooth to a computer where an application will run and be controlled by the the updates coming from bluetooth. I ran some quick tests using c# and was able to get these updates at an alright, but not great speed. There will also be some reasonably heavy data processing that I’ll definitely want to do in native code, and I figured I’d try to pretty much write everything in native


#4

When you open a serial port in C# then C# sets the interrupts to receive the data and so any data coming will be captured by the COPM drivers in C#.

If you want to use serial in RLP then you have to initialize it in RLP and never use int on managed side


#5

That makes sense, thanks!


#6

I’m now opening the connection entirely in C code, but I’m still unable to actually read the data that is being received. I have tried registering an interrupt function one of two ways:

Registering the function using RLPext->GPIO.EnableInterruptInputMode(). Here I get into the interrupt function, but every time U0IIR is 193 (1100 0001), which seems to mean that I have FIFO Enabled, but no interrupt.

Declaring an interrupt function as “attribute ((interrupt (“IRQ”)))” and setting it in the VICVectAddr6 register. When I do this I don’t actually see the output from the interrupt function being called, but Visual Studio hangs everytime I stop my application after sending the microcontroller a bluetooth message, so it seems like something is happening here but I don’t know what.

I’m able to send successfully over bluetooth, and in the first setup I see the debug output coming when (and only when) I send the device a message. Any ideas why I’m still not able to see whats being received? Here’s all the code that I’m currently using:



 #define RX_INTERRUPT_PIN 	20

 #define VIC_CHAN_NUM_UART0    6
 #define VIC_CHAN_TO_MASK(vctm_chan_num__) (1UL<<vctm_chan_num__)

// FIFO Control Register bit definitions
 #define UFCR_FIFO_ENABLE    (1 << 0)    // FIFO Enable
 #define UFCR_RX_FIFO_RESET  (1 << 1)    // Reset Receive FIFO
 #define UFCR_TX_FIFO_RESET  (1 << 2)    // Reset Transmit FIFO
 #define UFCR_FIFO_TRIG1     (0 << 6)    // Trigger @ 1 character in FIFO
 #define UFCR_FIFO_TRIG4     (1 << 6)    // Trigger @ 4 characters in FIFO
 #define UFCR_FIFO_TRIG8     (2 << 6)    // Trigger @ 8 characters in FIFO
 #define UFCR_FIFO_TRIG14    (3 << 6)    // Trigger @ 14 characters in FIFO

// Line Control Register bit definitions
 #define ULCR_CHAR_5         (0 << 0)    // 5-bit character length
 #define ULCR_CHAR_6         (1 << 0)    // 6-bit character length
 #define ULCR_CHAR_7         (2 << 0)    // 7-bit character length
 #define ULCR_CHAR_8         (3 << 0)    // 8-bit character length
 #define ULCR_STOP_1         (0 << 2)    // 1 stop bit
 #define ULCR_STOP_2         (1 << 2)    // 2 stop bits
 #define ULCR_PAR_NO         (0 << 3)    // No Parity
 #define ULCR_PAR_ODD        (1 << 3)    // Odd Parity
 #define ULCR_PAR_EVEN       (3 << 3)    // Even Parity
 #define ULCR_PAR_MARK       (5 << 3)    // MARK "1" Parity
 #define ULCR_PAR_SPACE      (7 << 3)    // SPACE "0" Paruty
 #define ULCR_BREAK_ENABLE   (1 << 6)    // Output BREAK line condition
 #define ULCR_DLAB_ENABLE    (1 << 7)    // Enable Divisor Latch Access

 #define UART_8N1      (uint8_t)(ULCR_CHAR_8 + ULCR_PAR_NO   + ULCR_STOP_1)
 #define UART_FIFO_1   (uint8_t)(UFCR_FIFO_ENABLE + UFCR_FIFO_TRIG1)

 #define UIER_RBR           (1UL << 0)    // (UIER_ERBFI) Enable Receive Data Available Interrupt

void interruptHandler()
{
	Debug("Start of bluetoothReceiveISR");

	volatile char dummy;
  volatile char IIR;
  IIR = U0IIR;
  Debug("U0IIR:");
  Debug_int(IIR);

	//while (((IIR = U0IIR) & 0x01) == 0) {
	
	 uart_interrupt_count++;
     switch (IIR & 0x0F) {
       case 0x06: /* Receive Line Status */
		Debug("receive line status");
         dummy = U0LSR;  /* Just clear the interrupt source */
         break;

       case 0x04: /* Receive Data Available */
		Debug("Receive dat available");
       case 0x0C: /* Character Time-Out */
		Debug("Character timeout");
		   dummy = U0RBR;
         break;

       case 0x02: /* THRE Interrupt */
	   Debug("THRE interrupt");
         break;

       case 0x00: /* Modem Interrupt */
	   Debug("Modem interrupt");
         dummy = U1MSR;  /* Just clear the interrupt source */
         break;

       default:
         break;
     }
  //}
	
	VICVectAddr = 0;
}

/*
function used to register an interrupt using RLPext->GPIO.EnableInterruptInputMode()
*/
void bluetoothReceiveISR( unsigned int Pin, unsigned int PinState, void* Param )
{  
	interruptHandler();
}	

/*
interrupt function to be registered in the Vectored Interrupt Controller
*/
__attribute__ ((interrupt ("IRQ")))
void uart0ISR (void)
{
	interruptHandler();
}


int USE_RLP_FOR_INTERRUPT = 0;
/*
This gets called by c# to open the connection
*/
void openBluetoothConnection()
{
	int mode = UART_8N1; 	//8bits/char, no parity, 1 stop bit
	int fmode = UART_FIFO_1;	//fifo enable, trigger interrupt every char
	
	PINSEL0 |= 0x50;	//Enabled TxD0 and RxD0
	PINMODE0 |= 0xA0;	//set proper pin mode for rx and tx registers(no resistor enabled)
	
	U0IER = 0;	//disable all interrupts
	U0IIR;                                // clear interrupt ID
	U0RBR;                                // clear receive register
	U0LSR;                                // clear line status register

	// set the baudrate
	U0LCR = ULCR_DLAB_ENABLE;             // select divisor latches 
	
	//these are copied from what happens when the connection is opened in C# code, for baud rate 9600
	U0DLL = 74;
	U0DLM = 0;
	U0FDR = 199;
	
	U0LCR = (mode & ~ULCR_DLAB_ENABLE);	//set mode(#bits, parity?, #stop bits), disable dlab
	U0FCR = fmode;	//set trigger level, enable fifo
	
	if(USE_RLP_FOR_INTERRUPT)
	{
		RLP_InterruptInputPinArgs pinArgs = {RLP_FALSE, RLP_GPIO_INT_EDGE_HIGH, RLP_GPIO_RESISTOR_DISABLED};
		int result = RLPext->GPIO.EnableInterruptInputMode(RX_INTERRUPT_PIN, &pinArgs, bluetoothReceiveISR, 0);
		Debug("Result of RLPext->GPIO.EnableInterruptInputMode:");
		Debug_int(result);
	}
	else 
	{
		//initialize the interrupt vector
		VICIntSelect    &= ~VIC_CHAN_TO_MASK(VIC_CHAN_NUM_UART0);	//set interrupt type irq
		VICIntEnClr      = VIC_CHAN_TO_MASK(VIC_CHAN_NUM_UART0); 	//clear bit from the interrupt enable register
		VICVectAddr6     = (uint32_t)uart0ISR;						//set the actual interrupt 
		VICVectCntl6 = 0xF;											//set priority to highest(15)
		VICIntEnable     = VIC_CHAN_TO_MASK(VIC_CHAN_NUM_UART0);	//enable the interrupt
	}
	
	
	U0IER = UIER_RBR;	//enable interrupts on rbr
}

Thanks


#7

I am not sure as I haven’t tried it. It may help to take a look at the LPC2468 UART drivers in the porting kit. I think GHI’s code is very similar.


#8

Is http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=5868 where I should be getting the porting kit from, or have I found the wrong thing? I took a quick look through that one but couldn’t find anything related to UARTs


#9

C:\MicroFrameworkPK_v4_2\DeviceCode\Targets\Native\LPC24XX\DeviceCode\USART