Receiving packet via UART interrupt

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
DaHu_285096
Level 5
Level 5
10 likes received 250 replies posted 100 replies posted

 I have been using state machines to date on the PIC processor to receive Asynchronous serial data. These relied on a timeout between bytes to know when packet has stopped transmission.

   

With the PSOC, I am having trouble with the timers to implement this strategy and also have been advised to do less within the interrupt.

   

What do you do for receiving Asynchronous data with interrupt? 

   

Would you for instance:

   

Change packet structure to have exclusive start and stop delimiters (adding overhead as data would need to be sent as ASCII hex).

   

Start with an emppty buffer and simply poke each incoming byte into the buffer abd increment buf ptr.

   

In main code, check the buffer and if first character is not start delimiter then reset start ptr to beginning.

   

If start delimiter IS found then check data for end delimiter.

   

If End delimiter found then found then parse data. (probably use circular buffer to kep incoming bytes happening while processing the received packet (as long as it is process before overwriting as buffer rolls over). I expect buffer shjould be greater than 2 packet lengths.

   

If this is a typical method for handling data, how do you cope with data overuns and new valid data coming in after the overrun. Do you simply leave the UART to pack bytes into the circular buffer and in main code parse from Buffer TAIL until Head - looking for start byte? 

   

Finally, Do you set a flag to indicate Start delimiter or do you just repeat search for start and then end every time round the main code?

   

An example would be much appreciated if anyone has one.

0 Likes
18 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

There are plenty of concepts for protocolls. Stricted is the OSI-model

   

Smaller implementations are not too difficult to implement, but there is rarely a "best" solution.

   

Basic concept usually is a "Circular Buffer" filled by the interrupt handler.

   

For completion you need a function that tells if the buffer is empty and a function that returns the actual char of the buffer and advances to the next char.

   

This ensures that you receive all characters (when the buffer is large enough)

   

 

   

Lead-in characters, timeouts, fixed length messages and decoding you may use at your need and are handled during the main-loop.

   

 

   

Bob

0 Likes
DaHu_285096
Level 5
Level 5
10 likes received 250 replies posted 100 replies posted

 Thanks Bob,

   

I will look at something like below 

   

isr()

   

If circ buffer NOT full (ie. Tail_Ptr != Head_Ptr-1)

   

    Add data to circular buffer

   

    INC head ptr

   

init()

   

    Head_Ptr = Tail_Ptr;  {circ buffer = empty)

   

    FRAMECOMPLETE = false

   

   State MAchine = IDLE

   

main()

   

Receive frame()  -> State machine that;

   

   Checks for data in circ buffer if circ buffer not empty (ie: Head Ptr != Tail_Ptr)

   

   Removes data to memory buffer

   

   INC Tail Ptr

   

   SET FRAMECOMPLETEt flag if whole packet received.

   

   Reset to IDLE state and set data ptr = 0 if main buffer = FULL or START delimiter found before frame complete

   

Process frame() -> If the packet received flag set then process the packet and clear the flag

0 Likes
DaHu_285096
Level 5
Level 5
10 likes received 250 replies posted 100 replies posted

 I still have a bit of uncertainty using the UART. (Intterupt on single RX bytes)

   

 

   

1. The examples show only UART_Getchar() used to read bytes in the interrupt with no handling for overruns or clearing the rx buffer etc.If the result of getchar is non-zero, doesd this mean data is valid and there are no errors and once read, you can continuiung gathering data? 

   

2. I have followed the advice of using a circular buffer to get incoing bytes. I then pop them into a working buffer in the main loop. This all works ok. However, to parse the data, I need to look for command strings within the packet (using strstr) but can strstr handle the buffer without null terminator? ie. Do I have to add a '\0' to the last byte of my working buffer (to make into a string) every time I pass the loop and check for packet arrived?

   

3. Some packet formats have the same delimiters throughout the string. Like SMS has \n\rOK\n\r or "CMT:....\n\r\n\r

   

My current application will send a command to SMS and then wait for a timeout period for a response. While waiting for response, the working buffer must be being built from the circular buffer and comparison on each time around the loop for the string "OK". This may work for the short simple response but I also get unsolicited messaged (text received) and need to process the string. Would I then look for the expected string start characters "CMT" and THEN scan for \n\r characters to know where packet ends?

   

Thanks

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Your question can be re-formed into "How to write a parser". This is programming technique which is far beyond what can be done in a developer forum, I think you will have to read a book about that.

   

 

   

Parsers principially divide the input stream into "symbols" which can be defined in BNF. Then you "only" need a program that parses your input by the rules given by BNF. Have a look into Unix's "yacc" and "lex" program which you can get in source freely.

   

 

   

Bob

0 Likes
DaHu_285096
Level 5
Level 5
10 likes received 250 replies posted 100 replies posted

 Bob,

   

That brings up an interesting point. Where can I find guidelines for the forums to better understand the intended scope of them? 

   

My initial assumption was the forums consisted of a bunch of users that worked on various projects (commercial and hobby) and were asking questions of the community in the hope someone else had encountered something similar to save each having to "reinvent the wheel".

   

Do you mean my question was utside the scope of ALL forums on this site or just THIS forum? In which case, my question would be "which is the most appropriate forum".

   

some of my questions come about because I had implemented things differently in the microcontroller environment and now I am faced with a range of components that I have not yet fully become accustomed to.

   

At first, I ask a question relating to some technical hitch I encounter while attempting to port code from my previous projects across to the PSOC environment. However, when I ask the question I often receive another question that raises further issues.

   

For instance. I was having trouble getting the timers working to signal end of UART packets. When asking how to use the timers as I wanted to use them, I was asked Why not use a circular buffer, you should do the processing out of the interrupt where possible (keep it small). So, I branched off in this direction and now having trouble understanding whether I need to add a NULL terminator on every pass of the parser in order to do a strstr search. 

   

The same occurred with the PWM drive of a full bridge 125 kHz modulated signal I was attempting to write in code to ensure there was no cross conduction. Then I was asked why I did not use a PWM. It seems reasonable if someone has experience doing it this way to listen to them. However, I could not see from the PWM waveforms how I could control the 4 driver signals of my bridge. Now I am left wondering how to work that one out or going back to the original methid and not knowing why I am having troubles with the timer.

   

These seem like recursive issues to me. A question leads to a question that leads to a new method that leads to more questions as I am unfamiliar with the new method.

   

As I have routines already running on the microcontrolle rprojects, the original methods worked ok. The issue is now trying to get them running on the PSOC environment. I find overall that the community is very helpful and willing to answer questions (for this I am appreciative). But when a question is answered by another question or a generic remark like "read the manual", "do a google search" I am left a bit frustrated as I would usually done those first and the reason I am now asking is because I either could not understand the material I found or it did not appear relevant to my situation.

0 Likes
lock attach
Attachments are accessible only for community members.
EvPa_264126
Level 7
Level 7
500 replies posted 250 replies posted 100 likes received

I tried to do something similar for protocol DCON
see the project  ICP_DAS.cywrk.Archive.zip
at  this page:    ICP-DAS  simulators.
Sometimes I additionally  use the  two functions (attached below).

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Orbit,

   

during my IT education I learnt a lot of math, statistics, compiler build, 5 different programming languages, 3 assemblers and how to handle a neutron generator (no joke). This was a 3 1/2 year education but it did not end with that. So, just to say it with other words: Give it some time!

   

You will never find a forum answering all your questions but you will always find one that answers some of them. As a matter of fact, you will have to go through them and decide what it may be good for. Google is a good step to get hands on the forums.

   

Another approach (which I do prefer) is: Getting hands on a book describing the matter I am interested in. This could be the base of a good library and the foundation of good knowledge.

   

This forum, the CDC, is mostly able to help you to circumvent the difficulties a complex chip (as a PSoC is) has got. Understanding and handling of more than 100 implementations of hardware and software components is a big job and all of the contributors here are together able to manage that.

   

Basic programming techniques which can be described in less than 10 lines of pseudo-code you can lookup everywhere. There are websites for C-libraries and code for many different purposes you will just have to search for. Of course someone in this community might know an example code, so do not hesitate to ask questions.

   

 

   

Bob

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Here is a more extensive ap note/project on motor driving and protection -

   

 

   

www.cypress.com/    AN75813

   

 

   

Regards, Dana.

0 Likes
DaHu_285096
Level 5
Level 5
10 likes received 250 replies posted 100 replies posted

 Bob,

   

Maybe you are correct. Given the complexity of this hardware, I may have selected the wrong platform for my projects.

   

Though I did have to contend with low level register setup for the PIC microcontroller solution, I had very little trouble getting UARTS and Bit-Bashed ports running.

   

Fortunately, I still have PCBs in stock and the development tools to work with the PIC. The real thing that interested me with the PSOC was the programmable architecture. However, I don't have anough time for a steep learning curve to figure out issues like not being able to debug with the timer interrupt running and having trouble getting timeouts running with UART reception.

   

Thanks for the "heads up". This saves me a lot more pain than I was prepared for.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Yes, you learnt to solve some of your issues the "hard way", but I can assure you that errors in the components are rare. I experienced that the Cypress datasheets are mandantory to read while programming one of the components.

   

And when you review the solution for your timeout of the UART receiver that couldn't have been too complicated, just a hardware timer that is stopped and re-started in the rx-interrupt.

   

Working with PSoCs is quite different from working with PICs, it will take some time until you are "thinking PSoC" and finding your personal project balance between hardware and software solution.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

For people that had been working with register based and port based microcomputer, PSoC needs some time to get used to, it takes a while to have our team to get around telling people port3.4 and port2.6 can be used together as a 2 bit port. As suggested by Bob, one needs to think differently, I think the closer way is considering you have a CPU with a CPLD in the same chip

   
    For your timer issue. I use timer for timeout between bytes and timeout between packets, Not so sure what your issue is.   
   
    We suggest circular buffer because it is easy to work with, however, it doesn’t mean you need to change it especially if you already have a working solution.   
   
    For the parser issue, If you only has a few keywords, a switch or some if statement can do the job. If you already have that workout with your PIC project, there is no reason you need to change it.   
   
    One big advantage with PSoC is you can change hardware internally without having to re-design the PCB, whether it is an error of the original design or some late requirement change.   
0 Likes
JiGi_284761
Level 4
Level 4
Welcome!

I also would like to see some better documentation on this.

   

The  Data Sheet for this component IS vague and difficult to understand. It gives you a single very simplistic example that would never be used in normal programming. There is also a sample project that is also too simplistic and dosent show real world usage.

   

Most other MCU manufactures provide you with a basic API to parse the data coming off their UARTS. It would be nice to see one here too.

   

I use the PSOC-4's and 5's for some products but a better understanding of the UART and parsing its data would open up many more doors.

   

Any info or book recommendations on this subject would be greatly appreciated by me and im sure by others too..

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

In the world of embedded processors the parsing of an input stream is rather unusual. Moreoften a communication link between two devices is opened and a protocol is used to communicate with each other. This can be done rather simple, because a "device" does not need to talk in many different "sentences" from which each one can be distinguished at a very early stage of transmission.

   

I did not find any ambiguities or unprecise terms in the UART documentation, if you can highlight any, I am quite sure that Cypress is thankfully willing to correct that.

   

 

   

Bob

0 Likes
DaHu_285096
Level 5
Level 5
10 likes received 250 replies posted 100 replies posted

 I even have trouble reading a simple Digital input pin array.

   

I dropped a Digital Input onto the workspace 

   

Set up Number of Pins = 6

   

Named component "DigIn"

   

Set Contigious OFF so I could 

   

Set to show as bus 

   

Compiled.

   

The datasheet states that you can read the current values for all pins in the component using PinName_Read();

   

portval = DigIn_Read();

   

But Digin_Read() is not recognised, I get "impicit declaration of function" error, Digin does not appear in the autocomplete list.

   

The auto complete shows DigIn_0 to DigIn_5 but these do not have read functions available either.

   

Have I missed something real obvious in the datasheet? 

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Note port level APIs only generated if "Contiguous" checked.

   

 

   

Regards, Dana.

   

 

   

0 Likes
JiGi_284761
Level 4
Level 4
Welcome!
    Hi Bob. First thing I think that you and Dana and others do a great service here. Lots of useful and accurate data.   
   
    I am mainly a hardware engineer. I design industrial control systems. Historically this meant turning things on and off, taking measurements and displaying these measurements for an operator or as a register value for a control.   
   
    Those days are quickly fading away.   
   
    Today, they want a  “intelligent”  sensor. Something that trends and collects data such as measurements, video so an and so forth.   
   
    However they want the sensor to hold on to that data and send only the data that is requested by the controller and to make it even more difficult this is all wireless and on batteries that they expect to last for 2 years. Then it all has to fit in an explosion proof box 4 inches in diameter.   
   
    Then the customer wants to be able to read this data in realtime on his I-phone while he is vacationing in Hawaii and if necessary turn the equipment on and off from there or adjust values.   
   
    My point is, embedded systems carry much more data today than they ever have. Parsing data IS necessary.   
   
    I usually build a product with basic drivers installed that I program myself. I send these to my customers who reply that they cannot understand the UART API nor get it to work in a manner that is acceptable to them.  I have to agree with them. So I am forced to install another processor that has a api that they can understand. This raises the cost, the size and worst of all the power consumption.   
   
    Im not the best programmer. I can do it and for somethings  im quite good. However in this case im not and I cant seem to explain it well to my customers either.   
   
    My customers demand API’s that are commented well and to the point that don’t require explanation or weeks of studying the code to determine what it does.   
   
    So any help or direction to good UART  books or sample projects would be greatly appreciated.   
0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

My UART times go back to late '70 , so I am afraid that there aren't any books that survived which I could recommend.

   

Looking at your problem(s) I would say that it would not make any difference when you use I2C, UART, SPI or USB for the communication, so within the OSI-modell your problem is related to the protocol level (or above).

   

So when you find yourself a general good-working protocol or even construct one yourself, you will be fine off.

   

Phantasy is reqiured.

   

One solution: Define Messages. First part of every message is a "Message Number" (telling the sense and meaning) a message length (number of bytes to follow). Message is followed by a lead-out (CRC and a "Terminator".

   

This format could be used to transfer *ANY* message over byte-oriented communication paths. Not absolutely efficient, but it would work. Expanding the original solution can easily be done by expanding the number of supported messages (good idea to already start with an uint16_t). The documentation narrows down to describing the message formats and the communication interface used. The APIs can be reduced to sending and receiving a message and the processing of the received informations.

   

A (not small) bit of work has to be put into the part to manage the direction of information flow: A master-slave connection is always easier to handle that a full-duplex, so it would be advisable to check the project if the easier (and cheaper) solution could be made.

   

 

   

Hoping to have saved you from reading some not very helpful books, read some about the OSI-model.

   

Bob

0 Likes
Anonymous
Not applicable

 How about this

   

1 message start byte 

   

2 total length of packet

   

3&4 transation ID

   

5 message type

   

6~n-2 pay load

   

Last 2 bytes CRC

   

 

   

You may add

   

1. source and destination address to the packet

   

2. ACK or NACK of message

   

3. X-ON X-OFF or some form of flow control

   

4. Define your own inter-byte and response time-out

   

5. Define re-transmision scheme and sync recovery scheme

0 Likes