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.
Tool/software:
I have a small application based on the rfUARTbridge example. I have been struggling with errors that occur when a larger block of data needs
to be received and forwarded in multiple i/o s.
I am basicly trying to transmit SLIP packets, and since SLIP encodes certain data by 'escaping' them the size of the resulting frame is varying
depending on the data before encoding.
I have been running SLIP with small framesizes for DAYS without errors. When increasing size above the internal uart buffer uart2 will not receive all
characters. This is dependent on other program activties.
I learnt that the UART2 driver does not always return data received after "timeout", i.e. partial receive.
I thought I had some obscure bug in my program, but trying to track that down changed behaviour in different ways.
Initially I could ping at up to slightly above uart buffer size. By rearranging code I am now at about 2.5 buffers worth of data.
My observations are that it "seems" like the problem is provoked by activity on the OTHER uart. The common denominator
is a higher amount of BLOCKING io, the SLIP code runs with "callback" just as TI's original example.
Questions:
Q1 How is the "partial receive" timeout computed? Can I set it? It is a good idea, but its value must be adapted to the typical use.
Q2 If as I suspect there is data in the "circular driver buffer" why does not the next receive pick it up?
Q3 How is the size of the circular buffer calculated?
Q4 Any other suggestions, I need to receive "every byte" and need to packetize the frames, and as long as I do NOT miss
incoming data, the packet is reassembled without elaborate programming.
Gullik
Hi Gullik,
you can find a doxygen documentation of our driver Api's shipped with the SDK and online on dev.ti.com where you can read through all the different operation modes: https://dev.ti.com/tirex/explore/content/simplelink_cc13xx_cc26xx_sdk_7_41_00_17/docs/drivers/doxygen/html/_u_a_r_t2_8h.html
When configuring the UART2 in .syscfg you can also adjust the ring buffer size.
Regarding your issue it is hard to debug without seeing all the code changes as their is no error with the example. But in callback mode the uart is nonblocking and so the callback might be triggered before the transmission finished. A finished transmission is signaled by the UART2_EVENT_TX_FINISHED event.
Please check your code against the driver documentation.
Kind regards,
Theo
I have been studying the driver doc. However, it is not clear to me what the "timeout" parameter
that is used for partial input is, how it is calculated, if it changes with baud rate etc.
I do not think I have a problem with transmission, I think that sometimes my code strictly based
on the rfUARTbridge example somehow does not get woken up frequently enough.
I have a short queue with 4 fullsize buffers (253 bytes). This is filled when a uart receive
is called back, but outside of the callback function, exactly as the example code.
I never get overrun in this queue (as of now)
When nothing happens in the main loop (rf received or uart received) the dequeue function is called
and data is transmitted to the uart. This is a poor mans trick to separate the different functions
timing-wise. This enabled packet sizes of up to 538 bytes, 2 and a half buffer to get through.
With larger packets in on UART an entire packet is dropped. This is usually a 253 byte packet
and is manifested in the SLIP dump as "missing bytes".
But I still do not understand what is happening ( or NOT happening).
Gullik
Hi Gullik,
the default example does not use a timeout it uses the UART read and write functions without timeout. If the timeout function is used the user can specify it. As stated in the driver definition:
* timeout The number of system clock ticks to wait until
* all data is received. If not all requested data
* was received within the timeout period, an error of
* UART2_STATUS_ETIMEOUT will be returned. This
* parameter is only applicable to #UART2_Mode_BLOCKING.
It is very hard to follow your description. Please answer the following questions:
1. Which modifications have you made to the rfUARTBridge example?
2. Please provide a structured explanation on what you want to achieve. I understood that you want to receive a large data packet and send it over UART. Is my understanding correct? Can you add on it?
3. At which part is the code failing when you run it in debug? You are saying that some part of the UART message is ignored. Did you read that the UART in callback mode as it is used in the example is non blocking so it does not guarantee that the whole message was sent. If you want to ensure it you need to either give it some time, use blocking mode or wait for the event that I mentioned before.
Please let us get some structure in that so that I can help you to get the functionality that you need.
Thank you,
Theo
Hello Theo,
Maybe I am describing the problem bad.
I have added code to the rfUARTBridge example. The use of the UART2 driver as I understand it is that a callback is set, and the partial_read like this, cut from the unmodified example.
/* Initialize UART with callback read mode */
UART2_Params_init(&uartParams);
uartParams.baudRate = 115200;
uartParams.readMode = UART2_Mode_CALLBACK;
uartParams.readCallback = ReceiveonUARTcallback;
uartParams.readReturnMode = UART2_ReadReturnMode_PARTIAL;
Reading the documentation, I get the impression that the read terminates either by
Reading the number of bytes specified in the call
A timeout, that returns what is in the buffer after a short "idle" period where no characters come in.
Thus, you can type single characters and forward them even if the read size is longer.
I have modified the code adding ethernet, which works nicely, a command interpreter on a second uart and many other things. However, the original forwarding code is as in the example.
I try to use the uart-bridge for SLIP IP forwarding. I have two linux machines with a slip link set up
between them. I can ping across the slip link for 24 hours without packet loss, if the packet size is belo 538 bytes (as produced by ping and slip converiosn in Linux).
When I receive a maximum of 253 bytes from the uart this is not sent to the radio directly as in the original example, but put in a 4 item long queue, with a read pointer and a write pointer.
This can store maximum of 1012 characters before it overflows.
If I increase the Linux ping size so that the resulting SLIP packet is longer than 538 bytes, I do not receive all bytes any more. It is the uart reception that has a problem, because I log all the segment sizes I receive and get 253, 253, 66 or so, unfortunately this does not always add up EXACTLY, because SLIP does character stuffing, so depending on the data sent into the SLIP driver a number of characters can be added. However, this does NOT overrun my queue, and worst case, a SLIP packet can be at most (original size *2) + 2, 2 flags and ALL data duplicated. I need to reach 576 bytes of IP, since that is the minimum packet size and IP node should accept to be compliant with IP segmentation and reassembly.
When I try with larger sizes I typically drop an entire 253 bytes buffer, so the SLIP packet does not reassemble correctly.
I guess I must actually be missing an entire read, since the Callback is asynchronous and tied to an interrupt, and IF i issue the read WITHIN the callback I should be sure to catch ALL characters.
Right now both my code and the example have the read in the main() program, and we do not know what the program is doing when the callback occurs.
Thank you Theo, I guess I will have to move that UART2_Read.
It is indeed useful to discuss problems, it forces you to rethink the whole thing..
Best Regards
Gullik
Thanks again Theo,
Everything now works as expected, and even though this is an extremely rudimentary program,
I can now ping with 600 byte packets. Only modifications left are to increase the UART buffer que
to take 2 worst case SLIP packets, and bump the Verison number.
So moral of the story: IF you use callbacks AND have blocking IO elsewhere in your program
set up the receive Inside the callback or you will eventually risk loosing data.
Gullik
Hi Gullik,
great that our discussion helped to find a working solution for your program.
Kind regards,
Theo