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.

Passing Data between two internal UARTs



Hello,

I am trying to pass data internally between two UARTs- for example, Rx data from UART0 goes to Tx on UART1, and Rx data from UART1 goes to Tx on UART0.  I'm basically a passthrough for UART data between two peripherals.  I've been simply putting the incoming data into buffers and then transferring the data from those buffers periodically, but with heavy data flow I can't keep up.  Is there a way to directly pass this UART data through, or do I need to set up uDMA for this traffic?

Thanks!

Cindy

  • uDMA may be the solution, but can you sketch out what you are doing now? There may be process optimizations you can make.

    Are the two running at the same baud rate? Any need to buffer spikes in the traffic?

    Robert
  • Cynthia Crutchfield said:
    but with heavy data flow I can't keep up

    Nor can hapless helpers - for whom "heavy data flow" - has less than crystal clear meaning...

    Should your MCU do nothing more than, "Divert & rebroadcast" that UART data - why burden your MCU (i.e. your bottleneck) at all?  Cannot you simply - signal buffer and/or level shift that data - then "Passing it on" - w/out routing it through the MCU?  (i.e. the "role" of the MCU has escaped description...)

    Such "parallel transmission paths" of serial, UART data is not uncommon - especially when the data serves, "Command/Control" purposes - and simply MUST get through!

    Your statement, "trying to pass data (internally) between 2 UARTs" fails to fully/properly convey your (real) objective...

  • Hi Robert,

    I am not processing the data at all- simply passing UART1 RX to UART2 TX and UART2 RX to UART1 TX. This is a situation where we have one console and I'm passing data back and forth through it from another processor at times. I'm looking at the Tiva Library function uDMAChannelTransferSet() and wondering if I can set up the sources and destinations there to be my UARTS (requiring two calls- one for each path)... I'm looking at the TI example: udma_demo.c

    Thanks for your help,

    Cindy
  • Hi cb1-

    As I just stated to Robert, I am a go between for another processor and a terminal- I really am just passing the data back and forth. I'd like to handle the data as little as possible and as quickly as possible-

    Cindy
  • It remains unclear as to why the MCU must become involved.

    If your MCU "does nothing" w/that UART data - its insertion into the path seems w/out merit...

    Robert's requested, "System Diagram" may better convey your intent...

  • To quote the hardware engineer when I asked that question (months ago) the answer is, "because that's the design."
  • That hardware engineer will (surely) go far!

  • And yes- same baud rate. Not processing done with the data. Just a byte by byte pass through...

    Cindy
  • Hello Cindy

    Based on the post so far, uDMA may be the only option. But do enable the UART Interrupt bits for error as the uDMA does not check for any data error and this needs to be informed to the processor.

    Regards
    Amit
  • Hi Again Amit-
    Does the uDMA require a data buffer between the two UARTs, or can I use uDMAChannelTransferSet() where the source is one UART RX and the destination is the other UART's TX? I'm unclear if direct peripheral to peripheral transfers are possible.
    Thanks,
    Cindy
  • Hi Amit,

    May I respectfully disagree?   Are we not forcing Cindy upon a long, arduous course - from which there (appears) to be NO benefit - when a vastly, "Simpler & Faster" solution is at her doorstep?   (i.e. very few "master" µDMA w/out substantial struggle - isn't that true?)

    Instead - might a more proper (and vastly faster, simpler) solution see the MCU serve instead as a, "UART traffic cop (or flow director) which simply "steers" the incoming UART data out to "1 of N" remotes?   Such is achieved by limiting the MCU to simple channel selection - the MCU (again) may "broadcast" incoming UART data via "1 of N" or "M of N" (multiple channel) broadcast.   In such case the MCU simply "listens" and then employs select GPIO outputs to route the external UART data as desired via external data selector ICs.   From our well defined specification - absolutely no benefit accrues from involving the MCU in UART "pass thru."

    Such is a fairly standard UART protocol - sometimes employed when existing UART channels cannot be converted to "multi-drop RS485."   The MCU (usually) needs to know "where" to route the incoming UART data - and that task is degrees of magnitude faster & simpler than, "engaging µDMA & routing data (needlessly) thru the MCU!

    Staff @ cb1 tech firm ask - is that "spec disciplined, HW engineer" the son (or daughter) of the owner/president/director?   (note: cb1 is mere reporter...)

  • Hello Cynthia,

    No, it does not have a data buffer. And that is why it important to use the FIFO of the UART. The uDMA request must be on the RX side getting a data byte in its buffer causing the uDMA to send the byte to the TX of the other UART. The RX sides Overrun Error (amongst other errors) must be used the CPU to know that the bytes may have been corrupted and the switch implementation is performing Garbage IN-Garbage OUT.

    Regards
    Amit
  • Agreed DMA is seldom straight forward.

    Given the description so far I'd suggest the simplest solution is a pair of flywires. However, ruling that out I'm still left with unanswered questions.

    Cynthia,
    What is the current process you are using? Can you sketch it out?
    Are there traffic spikes in either direction?
    What is the baud rate?
    What else is being done in the micro?

    Depending on what your current structure is I could envision a significant speed increase by modifying the algorithm.

    It is hard to believe that anyone would route a serial signal through a micro unless there was some intent to modify it. The fact you are running into performance issues even before modification should raise a red flag.

    Robert
  • Might I take it that the characteristics of the serial interfaces were not known or the amount of processing on the data wasn't known or one or more of them was expected to be variable?

    Robert
  • Doubtful that anyone other than (owner's son/daughter) {whoops meant - detail obsessed/conveying, HW engineer} can answer... 

    Cyndi's "sucked you in" (I believe) w/"data spikes" but the total absence of any real MCU role condemns this to simple UART re-route.  (aka flyaway)

    Neither you, Amit nor I were "at the scene" (of her written specification's disappearance/murder) and Cyndi (now) iasks us to perform in-depth - after-the-fact - forensics.   Might such be tad "outside" our (usual) role?   (and have nothing - at all - to do w/TM4C!)  

  • Hi Robert,

    I am servicing 3 UARTS (might eventually be 4, but for now it's 3)- one for console input to my microcontroller,  and two to another processor on the board.  One of the UARTs to the other processor is pass-through console connection I'm having trouble with, and the other one is for data traffic between myself and the other processor.  All of the UARTs are 115200. 

    I currently do nothing in the UART ISRs except put the incoming data into buffers that are then serviced during normal system processing.  I process my own console data as well as the DATA coming from the other processor, but I just pass the other processor's console data back and forth.  When I say "normal system processing", I am also trying to gather system health data regularly, which involves a lot of I2C traffic.  However, even without health checking, I still will sometimes lose characters if the other processor's console traffic is heavy (the traffic spikes you were asking about- yes they exist and that's when I'm having trouble), especially if I'm printing to my console simultaneously.

    I've tried to streamline the UART ISRs by checking and servicing all the UARTs each time a UART interrupt occurs, rather than servicing them each individually. What I haven't tried yet, but I'm considering, is using the internal UART buffers and only interrupting when they're half full (at least for the other processor's console), in hopes of reducing the number of interrupts I'm servicing.  But then I'll have to check regularly for the less than half full buffer cases that aren't causing interrupts... No easy options!

    I agree that, "It is hard to believe that anyone would route a serial signal through a micro unless there was some intent to modify it," but believe it!

    I'm considering Amit's description of the straight uDMA between UARTs for the other processor's console traffic.  I've been considering it for a while, but have been dissuaded by complexity of the set up...

    Thanks for your help,

    Cindy

  • Thank you Amit. I'll give it a try... And thanks for the clarification on where the uDMA request comes from- I was confused on that point.

    Cindy
  • That clarifies things a bit. A few comments

    Given the speeds involved I would expect the processor to be able to keep up, but program structure could be an issue. So I would want to do the following

    Instrument the code. Set and clear output pins on interrupt entry/exit, as you receive bytes etc... This will let you not only measure execution time but more critically latency.

    Rationalize your priorities. Use rate monotonic analysis. The highest frequency sources should be highest priority.
    Turn on the FIFOs, that will help deal with latency
    Receive interrupts only I think, if possible. It doesn't appear you have the same latency issues on transmit
    Keep track of the peak and average buffer levels so you can size the buffers properly

    That should make a difference. I would expect the system health to be your lowest priority, but work out the requirements. Make sure your periods with interrupts disabled are short. I don't think DMA is necessary, it might even be harmful. Instrumentation is essential. The suggestions above are in the order I'd address them.

    Robert
  • Hello Robert,

    I kind of agree with you. Considering the UART function at mostly low baud rates, it is rather strange, that a switch cannot keep up.

    I also have a slight different thought. If the system load is high, can the code be checked to see if non-critical compute are being performed in Interrupt Handler.

    Regards
    Amit
  • Many here are too kind to note that key/critical facts are arriving @ 9600 millibaud! (if that...)

    It appears that the "HW engineer" is not alone in, "Withholding necessary information..."   Much time, effort has been wasted by such lack of care!

    No one is directed to "feel bad" - yet the (early & complete) presentation of "all the facts" saves hapless helpers from substantial, "guess-work, lost time and tail-chasing..."

  • Cynthia Crutchfield said:
    I currently do nothing in the UART ISRs except put the incoming data into buffers that are then serviced during normal system processing.  I process my own console data as well as the DATA coming from the other processor, but I just pass the other processor's console data back and forth.  When I say "normal system processing", I am also trying to gather system health data regularly, which involves a lot of I2C traffic.  However, even without health checking, I still will sometimes lose characters if the other processor's console traffic is heavy (the traffic spikes you were asking about- yes they exist and that's when I'm having trouble), especially if I'm printing to my console simultaneously.

    Is the problem that the printing to the local console at the same time as console data is being received from the other processor exceeds the bandwidth of the UARTs operating at 115200 baud?

    i.e. does the amount of buffering for console data received from the other processor need to increase in case printing to the local console is happening at the same time?

  • That certainly isn't contradicted by the description so far Chester. However, it suggests an issue with priorities rather than buffering to me.

    Robert
  • One thing occurs to me. We, I at least, have been assuming that this is comparable to console I/O. If it is instead something like Modbus none of the solutions bandied about so far are appropriate. DMA would not be a good choice at all in that situation. And there are even worse examples.

    Robert
  • Yes, just regular console traffic- from the micro UARTs out of the board through two serial lines to my computer running ssh through putty. Most of the time I can handle all of this traffic without issue. It's only at times when the other controller is printing at full rate that I can run into issues. If the question is whether or not the characters are being lost BEFORE they get to me, the answer is no. I set a flag when my buffers overrun, and they DO overrun when the characters are lost- not often, and not many, but it does happen.

    Thank you Robert for your thoughtful replies. I'll work on some analysis and fine-turing before I jump into the uDMA world. I'll keep you posted.

    Thanks again,

    Cindy :)
  • Hi Chester,
    Thanks for jumping in. The loss is definitely occurring in the buffers. I'm struggling to process the buffers before they overrun- if I had unlimited buffers, I'd be fine because the heavy UART traffic is only occasional. But the question is if it possible to process the data more efficiently so that I CAN keep up. I could also lower the baud rate on some or all of the UARTS- that is actually a possibility if I can't keep up and I've exhausted all my options.
    Thanks,
    Cindy
  • Measurement is critical Cindy.

    You can easily measure the maximum time from receiving a byte to when you start sending and also how long it takes on average to send, that will determine the size required for your buffer.

    It may be simpler for the console, you can simply wait until there is room to send.

    Robert
  • Hi,

    At least you can analyze the other option available for the two UARTs: do not use any FIFO or DMA or buffers - just configure the UARTs only for receive interrupts and inside interrupt clear the interrupt flag, get the character received and immediately drop it on the sending uart DR register. Use hwreg macro and make both receive interrupts the highest priority interrupts for your system - and take into account that enabling an UART silently enables the FIFO, so use UARTFIFODisable() function immediately after enabling an UART.

    For console operation, use buffering and a slower baudrate.

  • Truthfully, I'd avoid doing that as a first step Petrei. It might be the final solution but I think it is essential to measure first, then assign priorities here. Otherwise the temptation to declare problem solved if it happens to work may be too strong to resist.

    Robert
  • Should not, "CTS & RTS" have received (some) consideration?   (and even Xon & Xoff)

    Poster (and helpers) serve as a dumping ground for past, "Horrid specification & System Design" - do they not?

    Again - is this (really) a legitimate TM4C issue?   Does our solving not encourage (yet more), "Ready - Shoot - Aim" specification?

  • cb1- said:
    Should not, "CTS & RTS" have received (some) consideration?

    Only if the other end(s) supports it, and in a well define useful manner.

    cb1- said:
    (and even Xon & Xoff)

    Xon/Xoff is rife with problems. IMO better to avoid it.

    Robert

  • Robert, "Only if the other end(s) supports it..."

    Yet that's the point - is it not? Horrid spec leads to unnecessary/unwanted/inefficient EXTRA Work!

    Not all designs are destined for greatness - those with serious flaws/short-comings may do well to meet their (deserved) fate.
  • Hi Petrei,

    This was close to my original solution, except I was using UARTCharGet and UARTCharPut to move characters within the ISR.  I also didn't use UARTFIFODisable().  My process worked fine in all my normal situations- but when the other processor is printing constantly, I end up in the ISR for the majority of the time and the TM4C ends up unable to do anything.  I don't lose characters but I'm also not able to do any other processing.  I'll look at your solution once I do the interrupt timing measurements that Robert has suggested.

    THANKS,

    Cindy

  • Thank you Robert. I plan to do the measurements you suggest- I think it will be edifying for me and a good process for me to go through. I won't be able to do it until after Thanksgiving- this issue has sidelined me for a while and I have some urgent work I need to get to before the holiday. I'll let you know what I discover next week. I really appreciate your thoughtful insight into how to approach my problem.

    THANKS!

    Cindy
  • Hi Amit,
    Nothing happens in the ISR except moving the data from the UARTs to memory buffers. I do, however, check ALL the UARTs in one ISR (I mentioned this earlier), with the thought that this would save time in the long run by reducing the interrupt service time overall. So in the ISR, each UART is checked to see if a receive interrupt occurred there, and if so, data is moved to a buffer. I'm not sure if servicing all the UARTs together is helping me or hurting me, actually.
    Thanks again,
    Cindy
  • Note those serial calls are blocking. Not necessarily an issue but if they are it will be a big issue in an ISR. Your measurements may indicate if that's an issue (you'll see unexplained pauses).

    Robert
  • And when I said, "my original solution" I want to point out that I abandoned it a while ago in favor of buffering of the data, so that my TM4C would be able to function during heavy UART processing.
    Cindy
  • Got it. Yes, the measurements will be edifying for sure.
    Cindy
  • Keep in mind, you do probably want to remove the possibility of blocking at some point

    Robert
  • Hello Robert,

    Yes, that is true. I have noticed the same on the I2C with interrupt v/s I2C with DMA. The interrupt handler can be a substantial overhead.

    Regards
    Amit
  • Hi Cynthia,

    Some times less is more, while more is better than less. As U I 2 have opted for UART pass through order to redirected COM ports via existing virtual serial CDM low level device drivers into Windows. No need to reinvent the wheel when TI has done that part for us, was my first thought. The Launch pads ICDI do a few magic tricks that disappear when it (ICDI) is not integrated topology in that custom PCB. That point was made forum topic bulk device drivers morphed into high speed USBprintf being a better solution than UARTS.

    All the SW deployed is written assuming everyone group will have space on their custom PCB for the magic of the TMC123 ICID virtual serial CMD interface as TI dreamed of in the lab. Should we abandon the great empire or just push our way into hyper space and find another docking port, was my thought and WA. Behold there are issue in USB device transport as well so hold fast but prepare for the worst with a fire escape is my thought. More plugs means more escape routes from the fire behind us.

    Reading that U set baud rate 115200kb - have U tried to double the pass through speed to see what happens? Sometimes NVIC becomes bottle necked if he is not allowed to span the galactic empire in his own way and time. Robert may be on to something is my first intuition.
  • Ok I take back the USB transport issue comment - after all it was my bad uint32value declaration didn't belong in the uint8_t line.

    All better now:

    void
    USBvprintf(const uint8_t *pcString, va_list vaArgP)
    {       
        uint32_t ui32Idx,  ui32Pos, ui32Count, ui32Base, ui32Neg, ui32Value;
        uint8_t *pcStr, pcBuf[8], cFill;

  • Hi!

    Are you asking if I've tried making the input baud rate half of the output baud rate on the data line I'm struggling with?  I actually haven't tried adjusting the baud rates at all.  But it's on my list of eventual possibilities.  I'm going to follow Robert's suggestion and do some time measurements on my ISR, and associated processing code, to get a handle on where my processing time is going and then proceed from there.  Thanks so much for taking the time to try to help.  I'll keep you posted on what I discover and my ultimate solution...

    Cindy

  • Hi Cindy,
    Actually speeding up both in/out lines if possible to improve throughput, was my thought. I saw similar character drops into the windows virtual client when the baud rate was set to low for the actual variable update flow the application was pushing.
    Have a great Thanks Giving!
  • Cynthia Crutchfield said:
    with heavy data flow I can't keep up.

    BP's, "Speed the flow up" directly conflicts w/poster Cindy's opening post.    (which was a (long) time ago...)

    Speeding data input beyond an already identified, "Breaking Point" seems "not too good" a suggestion...

    Her processes & implementations must (surely) be improved (prior) to any increase in input data rate.  

  • >but with heavy data flow I can't keep up
    Does that infer the pass through focus in the middle and suggests a busy data pipe being choked?
    Seems with to slow a pass through rate the bottle neck (breaking point) can be created even with buffers on either end.
    My find has been Increasing BW is the only way to remove that pesky rat from the pipe!
  • BP101 said:
    Actually speeding up both in/out lines if possible to improve throughput, was my thought.

    That's your quote - and now you "roll that back" to (a far more reasonable) increase BW.   (bandwidth)

    Speeding up the data input is surely NOT the way to go!   And - what makes you believe - "speeding data input can (even) be done?  (such is NOT a "given")

    Might we extend your (logic) to Danica complaining of "bad brakes" and the bp "fix" is: "sever her brake lines!"   (I.e. make the problem worse!)

  • And what part of speeding up the rate is not improving throughput or dynamic BW. A faster rate get tasks done faster while log jams seldom do. The default data rate often chosen without any though as to way or how come is more often 115200k baud regardless of the source being adjustable or not.

    You make the assumption that which is left unsaid is a given where I choose to extrapolate the architecture in new direction.
  • Danica would surely (reject) the bp "fix."

    Does not the "Input Data Rate" - which you suggested be increased - result from increasing the output data rate - emanating (only) from the remote source?   Several here agree w/that as most obvious interpretation of your "fix."

    Your quote, "Speed up the input data rate" may not (properly) reflect your meaning.   That's your responsibility - our interpretation is judged reasonable.

    Your (latest) "raise the bandwidth" has been obvious from post #1 - the methods of achieving such remain elusive.   Any "restatement" of the obvious is not value laden...

  • It seems highly unlikely that a process that is failing at a high data rate will improve when you increase the data rate.

    Robert
  • Bonjour Robert,

    Thank you - once more Monsieur BP presents a procedure not (fully) in lock-step w/logic.   (i.e. Let's "cure" this (slightly) injured (deer, elk, moose) by "clubbing it over the head w/this stack of 2 by 4s!")  

    Hard to believe that BP (really) believes this - easier to suspect that his language did not (really) reflect his meaning.

    It is heartening to have you read BP's writing as my group did.  

    Now that our poster "C" has "added many necessary facts" your suggestion of performing key execution-time measurements is sure to prove of value - and the data harvested will then allow proper design choices.   Further "clubbing" of large "road-stunned beast" (the analog of increasing the data rate into an already failing system) is far more likely to "kill" rather than "re-animate" our victim!   (be it animal or silicon)   {did we just see (& hear) Danica whiz by - going way too fast for this sharp "S" curve - and w/out brakes?}  (a la, crew-chief bp's suggested, "make things worse!...")