This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

BiDirectional USB <-> UART bridge

Other Parts Discussed in Thread: MSP430F5528

Briefly, I am attempting to create a bi-directional USB to UART bridge using the USB Developer Pack (v4.1) code on a MSP430F5528. However I'm having problems with the UART to USB direction.

The setup for this project involves three pieces of hardware. There is the data acquisition platform, an F5528 which does all the heavy lifting including various computations, forming the communication packet etc. This communicates via UART (19200 8N1 at about 100 packets/sec) to the interface platform. The interface platform is a separate MSP430F5528 which, at this moment, sole purpose is to take this data from the data acquisition platform and relay it over USB to the third piece of hardware, a PC. The PC identifies the interface platform as a CDC device and interprets the data for display to the user.

[Data Acquisition Platform] <-UART-> [Interface Platform] <-USB-> [PC]

The data acquisition platform works well and I don't believe to be the source of our problems. Nor do I believe that the PC is causing the issue.

What is happening is if I connect the interface platform to the PC while the pc application is running ready to accept data, no problem. However if the pc application is not running, and I attempt to connect to the interface platform 5 or so seconds after connecting the usb to the computer, it will be unable to connect. This happens regardless of the pc application I use (virtual terminal, custom app, etc.).

The code on the interface platform is very simple. It uses the empty USB project from the developer pack, with descriptor files created using the descriptor tool. There is nothing happening in the main loop. The data handling happens in the ISRs as seen below:

*** This receives the data on the usb and writes it to our custom queue, this works fine.

uint8_t USBCDC_handleDataReceived (uint8_t intfNum)
{
	bytesReceived = cdcReceiveDataInBuffer((uint8_t*)dataBuffer, BUFFER_SIZE, CDC0_INTFNUM);

	writesilo(UCA1_OUTSILO, dataBuffer, bytesReceived);
	PrimeUCA1();

        return (FALSE);
}

*** This receives the data on the UART port and writes it to the USB, maybe something is up here?

#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
{
	_disable_interrupt();

	switch (UCA1IV)
	{
	  case USCI_UCTXIFG:
		  // 04h = Interrupt Source: Transmit buffer empty; Interrupt Flag: UCTXIFG;
		  // Interrupt Priority: Lowest
		  // Transmit interrupt flag. UCTXIFG is set when UCAxTXBUF empty.
			UCA1_Silo_serial_tx_interrupt();
		  break;

	  case USCI_NONE:
		  // 00h = No interrupt pending
		  break;

	  case USCI_UCRXIFG:
	  {
		  // 02h = Interrupt Source: Data received; Interrupt Flag: UCRXIFG;
		  // Interrupt Priority: Highest
		  // Receive interrupt flag. UCRXIFG is set when UCAxRXBUF has received a complete character.
		  if(cdcSendDataInBackground(&UCA1RXBUF, 1, CDC0_INTFNUM, 1))
		  {
		  	USBCDC_abortSend(1,CDC0_INTFNUM);
		  }
	    break;
	  }

	  default:
	    break;
	 }

	_enable_interrupt();

}

Of course there are other routines to handle the initialization of the ports and other aspects of the device as needed.

I'll be happy to provide any additional information as needed and I appreciate anyone's help solving this.

Thanks,

  • I think your code has a conceptual problem.

    But first: don’t disable or enable interrupts inside an ISR. ISRs are disabled automatically and are enabled again on exit. If you enable interrupts inside an ISR, this may lead to all kinds of trouble, up to interrupting itself again and again until the stack overflows.

    That being said, you cannot do an USB transfer inside an ISR. Because the USB transfer likely uses interrupts itself. Or does busy-waiting and expects interrupts to work, which they don’t when called form inside an ISR.

    If you receive something, put it into a buffer (e.g. a ring buffer) and tell main that data has arrived. Data may then assemble the USB packet and send it, while reception and transmission in the interrupt can continue. This way, you also can collect some bytes before you send an USB packet. Sending a whole USB packet for a single data byte is highly inefficient – up to the point where your throughput is slower than that of the serial connection despite of the high USB baudrate.

**Attention** This is a public forum