GPS receiver uart buffer line break - gps

I am trying to read the whole stream of messsages from my gps receiver, i need some sort of recognition for end of stream, between one block of messages and the next.
I've tried to read into a buffer with various dimensions (100, 200, 500, 1000) and obviously if is too short I break messages, if is too long i find same block of messages repeated, example:
GNGGA,XXXXXXXXXX*CC
GNGNS,XXXXXXXX*CC
GNRMC,XXXXXXXXXXX*CC
GNGSV,XXXXXXXXXX*CC
That is what i'd like to receive for every interrupt on receive (with HAL_UART_ReveiveIT() for example, but also in other platforms the concept is the same).
Instead, regarding the size of the buffer that i give, i have data like:
GNGGA,XXXXXXXXXX*CC
GNGNS,XXXXXXXX*CC
GNRMC,XXXX
or
GNGGA,XXXXXXXXXX*CC
GNGNS,XXXXXXXX*CC
GNRMC,XXXXXXXXXXX*CC
GNGSV,XXXXXXXXXX*CC
GNGGA,XXXXXXXXXX*CC
GNGNS,XXXXXXXX*CC
GNRMC,XXXXXXXXX
or
GNGGA,XXXXXXXXXX*CC
GNGNS,XXXXXXXX*CC
GNRMC,XXXXXXXXXXX*CC
GNGSV,XXXXXXXXXX*CC
GNGGA,XXXXXXXXXX*CC
GNGNS,XXXXXXXX*CC
GNRMC,XXXXXXXXXXX*CC
GNGSV,XXXXXXXXXX*CC
GNGGA,XXXXXXXXXX*CC
GNGNS,XXXXXXXX*CC
GNRMC,XXXXXXXXXXX*CC
GNGSV,XXXX
I am not able to detect the end of a block of message, that will repeat again, like:
GNGGA,XXXXXXXXXX*CC
GNGNS,XXXXXXXX*CC
GNRMC,XXXXXXXXXXX*CC
GNGSV,XXXXXXXXXX*CC
GNGGA,XXXXXXXXXX*CC
GNGNS,XXXXXXXX*CC
GNRMC,XXXXXXXXXXX*CC
GNGSV,XXXXXXXXXX*CC
GNGGA,XXXXXXXXXX*CC
GNGNS,XXXXXXXX*CC
GNRMC,XXXXXXXXXXX*CC
GNGSV,XXXXXXXXXX*CC
I've tried to detect interrupt on received char, so checking if current char is '\r' or '\n', but this works for every line, it detects only the end of a line, not the end of a block.
I would like to read from the uart, with interrupt on complete receive or interrupt on DMA, only the complete block of messages, and read again the next block, but I can't find any flag or termination character that can help me to distiguish between blocks.
Also, the block can have different size depending on the data of every message, so I can't give a fixed length array.
I was thinking about hw flow control or to use the fix LED signal from gps to send an external interrupt that can trigger the end of the block...
Do you have any idea?
It's all a matter of post processing with a parser?
Maybe discarding or overwriting fields found in multiple sentences of the same kind?
Thanks for your help

Since what you posted as the Output from your GPS receiver seems to have always the same structure and most importent same lenght I would suggest yout to count the UART messegas that you received.
If that is not the case and the lenght of your lines vary due to the suppression of leading zeros you could as well count the lines witch you told you can allready identify.
If even the length of the block varys since your blocks seem to start witch GNGGA you could trigger on the line ends to minimise the interrupt load (even better if you configer your UART interface with caracter match) and onve you find a line starting witch GNGGA you know every line before that one in your buffer is one block.
When you know exactly how long a block is you can let DMA do the work of counting for you and generate an interrupt of set a fleg once the configred number of bytes is in your buffer. This would give you a selfmade "EndOfBlock" flag/interrupt.

I would not care so much about detecting end of block directly in the UART receiver code.
I would rather let the UART receiver use a circular buffer.
Have a simple parser trying to find each line in the circular buffer as it fills up, and forward one and one line the (NMEA) parser.
And let the NMEA parser store up data as it receives data, until a complete message has been received, and then forward this to your main program flow.
(so basically, make some simple layers, and each layer should be easy to debug, as it is only responsible for one task)

Related

STM32F4-Discovery UART receive by DMA with included start-marker as well as an end-marker

Hi I am really new at embedded programming. I am using stm32cube IDE. I am trying to read a string to the DMA buffer but I need to implement start-marker as well as an end-marker. For example I only need to read the serial data in between '<' and '>' to the DMA buffer and when soon as it gets to the end-marker I want to call following call back function and process the data.
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//Process Data
}
I want this to run in the background all the time. Is this possible?
No, the DMA controller cannot check the value of the data and stop or interrupt when a delimiter or marker byte is received. The DMA controller can only copy the received byte to memory. If you want to read variable length packets between delimiters then you need to use the CPU to check whether each byte is a delimiter. You can use the UART's RX interrupt to check for the delimiter as each byte is received.
DMA might be useful for receiving a continuous stream of bytes or a packet of known length.

How to read variable length data from an asynchronous tcp socket?

I'm using CocoaAsyncSocket for an iOS project. I'm trying to read VarInts through an asynchronous interface. The problem is unlike something else like a String, where I can prefix a length, I don't know the length of a varint beforehand. It needs to be processed one byte at a time, but since each read operation is asynchronous other read calls may have been queued in between.
I considered reading into a buffer then processing it, say reading 5 bytes (the max length for a varint-32), and pushing extra bytes back, but that may hang unnecessarily if the varint is only 4 bytes and I'm waiting for a 5th byte to be available.
How can I do this? Also, I cannot change the protocol on the other end, to use fixed size ints.
Here's a snippet of code as Josh requested
- (void)readByte:(void (^)(int8_t))onComplete {
NSUInteger size = 1;
int32_t tag = OSAtomicAdd32(1, &_nextTag);
dispatch_async(self.dispatchQueue, ^{
[self.onCompleteHandlers setObject:(^void (NSData* data) {
int8_t x = 0;
[data getBytes:&x length:size];
onComplete(x);
}) forKey:[NSNumber numberWithInteger:((NSInteger) tag)]];
[self.socket readDataToLength:size withTimeout:-1 tag:tag];
});
}
A callback is saved in a dictionary, which is used in the delegate method socket: didReadData: withTag.
Suppose I'm reading a VarInt byte by byte:
execute read first byte for varint
don't know if we need to read another byte for a varint or not; that depends on the result of the first read
(possible) read another byte for something else
read second byte for varint, but now it's actually the 3rd byte being read
I can imagine using a flag to indicate whether or not I'm in a multipart-read, and a queue to hold reads that should be executed after the multipart-read, and I've started writing it but it's quite messy. Just wondering if there is a standard/recommended/better way to approach this problem.
in short there are 4 ways to know how much to read from a socket...
read some format that you can infer the length from like the Content-Length header... only works if the whole request can be put together before the body is sent.
read until some pattern: like \r\n\r\n at the end of the headers
read until some timeout... after you get no bytes after n seconds you flush the buffers and close the connection.
read until the server closes the connection... actually used to be pretty common.
these each have problems and I would probably lean in your case from using some existing protocol.
of course there is overhead to doing it that way, and you may find that you don't want to use any of that application level stuff and your requests may be like:
client>"doMath(2+5)\0"
server>"(7)\0"
but it is hard to answer your general question specifically.
edit:
So I looked into the varint base-128 issue a little more and I think really only a timeout or the server closing the connection will work, if you are writing these right at the TCP level which is horrible...

lpc1788 ssp (SPI) - proc to proc communication

I would like to send string of chars from one proc (master) to another (slave) and then read string from a slave.
Currently im mixing up the arduino and LPC1788, using lpc as master and arduino as slave.
LPC sent's the string correctly which is received by the arduino in ISR. In loop function i check if all of the chars are received and then try to send string back. On LPC side ISR is not working for some reason. I have set SR as
SR = (1<<TNF) | (1<<RNE);
So i have put delay after sending the string from LPC and then initiate read from arduino.
What i see on LA for sending the string is:
but reading of string from Arduino looks odd (string should be "Pong\n", it is not always P that i received... it varies)
i guess majority of problem is within the sync of sending and reading of SPI buffer. How do i achieve that without functional ISR on LPC?
The SPI specification states that the CS (SSEL) line should be active during a frame and become inactive in between. NXP interpreted this as a word being one frame. This means that the CS as generated by the SSP block (the same goes for the legacy SPI) is only active during one transaction of up to 16 bits.
Note also that there is always a gap in between the words/frames being sent. So even when you fill the FIFO or use DMA you will see 16 clock pulses, a short delay and then 16 more pulses.
When using a GPIO pin as SSEL, please note you have to wait for SSEL assertion or de-assertion until the peripheral is idle.

how redis ensure all request data can be readed into buffer by only one 'read' function call?

I read redis source code recently, and I'm now studying the networking codes.
Redis use nonblock mode and epoll(or something simliar) for networking data read/write. When read data event arrived,"readQueryFromClient" function will be called, and in this function request data will be readed into buffer.
In "readQueryFromClient" function, if there are really data arrived, data will be readed into buffer through one 'read' function, and then the request will be handled.
nread = read(fd, c->querybuf+qblen, readlen); // **one read function**
//... some other codes to check read function retuen value
processInputBuffer(c);// **request will be handled in this function**
My question is: how redis ensure all request data can be readed into buffer by only one 'read' function call, maybe all data will be gotten by more 'read' function call?
processInputBuffer(c);// request will be handled in this function
That part is not true. Redis protocol is designed to include length of every chunk of data passed around. So the server always knows how much data it has to read to make a complete request out of it. Inside processInputBuffer if neither processInlineBuffer nor processMultibulkBuffer returns REDIS_OK (i.e. request terminator was not found in the buffer/not enough arguments), control simply falls out of the function. All that processInputBuffer did in this case was filling up a chunk of the client buffer and updating the parsing state. Then, on the next iteration of event loop, in the call to aeProcessEvents, if there is unread data remaining in the socket buffer, readQueryFromClient callback will be triggered again to parse the remaining data.

Bits Are Scrambled

The Problem: I send one value into a UART and nulls emerge on the other UART.
--- Details ---
These are both PIC processors (PIC24 and PIC32)
They are both hard wired onto a printed circuit board.
They are communicating, each via one of the UART modules which reside within them.
They are (ostensibly; according to docs) both configured for 115200 bps, 8-N-1
No handshaking, no CTS enabled, no RTS enabled; I'm just putting bytes on the wire and out they go.
(These are short little 4-byte commands and responses which fits pretty neatly)
The PIC32 is going 80 MHz.
The PIC24 has F[cy] = 14745600
i.e., it is going 14.7456 MHz
The PIC24 sends four bytes (a specific command sequence)
When I set a breakpoint at the Interrupt Service Routine for the UART, The PIC32 shows nulls, then I am seeing repeated hits on the (PIC32 code) breakpoint after the first four, and I continue to see nulls (which makes sense since the PIC24 is not sending anything)
i.e., the UART appears to be repeatedly generating interrupts when there is no reason
I did not write the code on the PIC32 side, and I am learning daily how it works.
Then I let the code just run, and I inevitably wind up on a line that says
52570 1D01_335C 9D01_335C _general_execption_handler sdbbp 0x0
When I get there,
The cause register holds 0080181C
The EPC register holds 9D00F228
The SP register holds 9F8FFFA0
This happened like clockwork, so I got suspicious of the __ISR that would not stop. MpLab showed me this...
432:
433: //*********************************************************//
434: void __ISR(_UART1_VECTOR, ipl5) IntUart1Handler(void) //MCU communication port
435: {
9D00F204 415DE800 rdpgpr sp,sp
9D00F208 401A7000 mfc0 k0,EPC
9D00F20C 401B6000 mfc0 k1,Status
9D00F210 27BDFF88 addiu sp,sp,-120
9D00F214 AFBA0074 sw k0,116(sp)
9D00F218 AFBB0070 sw k1,112(sp)
9D00F21C 7C1B7844 ins k1,zero,1,15
9D00F220 377B1400 ori k1,k1,0x1400
9D00F224 409B6000 mtc0 k1,Status
9D00F228 AFBF0064 sw ra,100(sp) ;<<<-------EPC register always points here
9D00F22C AFBE0060 sw s8,96(sp)
9D00F230 AFB9005C sw t9,92(sp)
9D00F234 AFB80058 sw t8,88(sp)
9D00F238 AFAF0054 sw t7,84(sp)
9D00F23C AFAE0050 sw t6,80(sp)
9D00F240 AFAD004C sw t5,76(sp)
9D00F244 AFAC0048 sw t4,72(sp)
9D00F248 AFAB0044 sw t3,68(sp)
9D00F24C AFAA0040 sw t2,64(sp)
9D00F250 AFA9003C sw t1,60(sp)
9D00F254 AFA80038 sw t0,56(sp)
9D00F258 AFA70034 sw a3,52(sp)
9D00F25C AFA60030 sw a2,48(sp)
9D00F260 AFA5002C sw a1,44(sp)
9D00F264 AFA40028 sw a0,40(sp)
9D00F268 AFA30024 sw v1,36(sp)
9D00F26C AFA20020 sw v0,32(sp)
9D00F270 AFA1001C sw at,28(sp)
9D00F274 00001012 mflo v0
9D00F278 AFA2006C sw v0,108(sp)
9D00F27C 00001810 mfhi v1
9D00F280 AFA30068 sw v1,104(sp)
9D00F284 03A0F021 addu s8,sp,zero
I look a little more closely at the numbers, and I see that at that time, if we add 100 (0x64) to FFA0 (the bottom 16 bits of the SP) we get 0x10004, which I am guessing is 4 too much.
PIC Manual DS61143E-page 50 says that that nomenclature means, SW Store Word Mem[Rs+offset> = Rt and other experts have told me that the cause register is telling me that the EXCCODE bits are 7 which is the code for a bus exception on load or store.
Or, I'm totally guessing here (would love to get some experts' knowledge on this) something is not clearing something and I'm encountering infinite recursion on an int handler.
All of this is starting to make sense.
THE QUESTION
Could someone please suggest the most common reasons for an int like this to be repeatedly hitting me ?
Does anyone see any common relationship between the bogus nuls coming from the UART which could somehow be connected with this endlessly generated int ? Am I even on the right track ?
In your answer, please tell me how to acknowledge the Int from the UART. I know how I do that in the PIC24 (I wrote that code totally, in ASM) but I don't know how this is done in in C on the PIC32. Assembly will be fine. I'll inline it. I'm working with code I didn't write here, and I thank you for your answers
What is the most common reason that the UART (#1, in this case) would be repeatedly generating interrupts ?
The most common reason an interrupt subroutine is called over and over is that the interrupt request is never acknowledged in the routine.
Are you sure you clear the corresponding IRQ bit?
To ease UART debugging you should first connect the UART to a PC and make sure your target can communicate both ways with the PC. With two targets at the same time, you can't determine on which one the problem is apart from inspecting signals with a scope.
On many devices an interrupt must be explicitly cleared to prevent the ISR from simply re-entering when complete.
In most cases a UART will have status bits that indicate the source of the interrupt, knowing that might tell you something, but not telling us makes it difficult to help you. You can inspect the UART registers directly in the debugger, however in some devices the act of reading a bit may in fact clear a bit, and that is true in the debugger too, so be aware of that possibility (check the data sheet/user manual).
Some UARTS require their transmitter to be explicitly switched off to stop transmitting nulls, while others are triggered automatically when data is placed in the tx register and stop after the necessary number of bits are shifted out. Again check the data sheet/manual for the part. If the PIC32 code is known to be working, then since this possible error would be with the PIC24 code, it seems to fit. You can check this simply by using an oscilloscope on the Tx line from the PIC24, if it is transmitting, you will see at least start/stop bit transitions (framing). If there is nothing, then the problem is probably at the PIC32 end.
While you have the scope out, you can check that the bit timing is correct and that you are actually transmitting at 115200. It is easy to get the clocking wrong, and that should be your first check. If the baud rate is incorrect, the PIC32 will likely generate framing error interrupts, which if not handled may persist indefinitely.
Another possibility is that after transmission the PIC24 leaves the line in the "break" state, and that the PIC32 UART is generating "line-break" interrupts. That is why it is important to look at the UART status registers to determine the interrupt cause.
As you can see, there are many possibilities; I think I have covered the most likely ones, but more methodical debugging effort and information gathering on your part is required. I hope I have guided you in this too.
There were the three root causes which were in place...
The interrupt priority level was set at value 6 in the initialization code for UART1
The first line of the interrupt service routine was coded with an interrupt priority level of 5
The first three bytes of UART data were disappearing from the data stream (this is still unsolved)
Here's the not-so-obvious way they were causing the problem
First three bytes never appeared
Fourth byte did appear
Interrupt hit (as level 6) and invoked __ISR routine
__ISR was acting as ipl5 agent
First instruction executed (possibly more, I couldn't debug that accurately)
As soon as the first instruction finished, the "higher" priority 6 interrupt immediately kicked in
This resulted in the same interrupt again
The process repeated itself infinitely.
In short order, Stack Overflow resulted
The Fix
Make sure these two lines of code agree with each other...
The IPL line in the init code, wrong way then the right way
//IPC6bits.U1IP=6; //// Wrong !!! Uart 1 IPL should not be 6 !!!
IPC6bits.U1IP=5; //// Uart 1 IPL = 5 Correct way; matches __ISR
Interrupt Service Routine
void __ISR(_UART1_VECTOR, ipl5) IntUart1Handler(void) //// Operating as IPL 5
:
:
:
:
Poor design decision. If both are on same board SPI would have been more feasible and a lot faster.