• AVR Freaks

Hot!UART Ring Buffer in MPlab Harmony

Author
m_snaeem@hotmail.com
Starting Member
  • Total Posts : 76
  • Reward points : 0
  • Joined: 2020/07/10 10:54:03
  • Location: 0
  • Status: offline
2020/10/17 08:17:54 (permalink)
0

UART Ring Buffer in MPlab Harmony

Hello,
I am currently working on input message protocol. currently i am using Uart ring buffer with fix amount of ring buffer size say 34. Whenever i got 34bytes interrupt occurs and this is working fine.
But now my requirement is changed and i have to read  2 bytes at the start and the second bytes have the length of further bytes. So i have set read threshold to 2 so i can get length of further bytes which i got. but ring buffer only have these two bytes. As i have set ring buffer length to 10 so i need maximum 9 bytes.
can anybody suggest how can i read further bytes so i can read full message??
#1

16 Replies Related Threads

    vexorg
    Senior Member
    • Total Posts : 139
    • Reward points : 0
    • Joined: 2019/09/27 10:59:40
    • Location: 0
    • Status: online
    Re: UART Ring Buffer in MPlab Harmony 2020/10/18 11:12:32 (permalink)
    0
    Write your own and have full control over it.
     
    Use 2^n buffer size, and a head and tail pointer. That way a simple masking of head and tail deals with the wrapover.
     
    The idea of a ring buffer is to give you some headroom in processing, if the buffer is just the size of the packet you want then it's a bit pointless.
    #2
    Paul PortSol
    Super Member
    • Total Posts : 635
    • Reward points : 0
    • Joined: 2015/07/03 11:52:03
    • Location: Newfoundland, Canada
    • Status: offline
    Re: UART Ring Buffer in MPlab Harmony 2020/10/19 09:09:18 (permalink)
    0
    ((done editting..., this time had to swap angle brackets for curved in my text))
     
    Is this a standard protocol or your own custom protocol?
     
    If custom may I suggest a "stuffed" protocol. Select characters <start, stop, stuff>. Upon receiving "stop" set flag to process the receive buffer. Characters traditionally like ASCII <STX, ETX, DLE>, but I like readable chars <[,],x>. If any of the characters occur in the packet data you replace them with pair (stuff+modified start, stuff+modified stop, stuff+modified stuff), i.e. <^{, ^}, ^~>. Upon receive easy to detect <start, stop, stuff> and appropriately handle packet. If a "stuff received" set a flag to "unmodify following byte. Typically a CRC/Checksum just before <stop>, if it is a cyclic checksum <crc> just check that your result is zero. Checksum should be on "all unstuffed data" between <start,stop> for consistency. Bonus: If receiver out of sync any "start" byte immediately establishes packet sync.
      
    If a "fixed length" protocol create a state variable (enum), and increment the state according to what you are expecting:
    - Initially enum = Wait Start
    - Then maybe enum = wait type (type defines how to process packet, like "has length field" or "fixed length"
    - Then enum = WaitLenInfo or enum = WaitFixedLen
    - Then when got length bytes enum=WaitLenBytes
    - Then enum=WaitCRC
    = Then Process packet. 
    * adjust to match the protocol.
     
    I've found the "stuffed" protocol style results in easier shorter code, and supports variable length packets. The CRC catches any errors, just ensure start with non-zero CRC in calculations. 
     
    Paul
    post edited by Paul PortSol - 2020/10/19 09:21:32
    #3
    NorthGuy
    Super Member
    • Total Posts : 6347
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: UART Ring Buffer in MPlab Harmony 2020/10/19 10:36:41 (permalink)
    0
    For your usage, ring buffer is not the best choice.
     
    It's better to use a ping-pong buffer - two linear buffers (each can fit one command). While one gets filled (presumably by the interrupt), the other gets analized. When you receive a character, the receiver inserts it in the currently active buffer. As soon as the whole command has been read, the receiver signals that the buffer is ready and switches to the other buffer.
     
    #4
    NKurzman
    A Guy on the Net
    • Total Posts : 18967
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: online
    Re: UART Ring Buffer in MPlab Harmony 2020/10/19 11:55:34 (permalink)
    0
    There is not one best way to do this.
    I would make sure the ring buffer is Big enough to receive two or three packets , Depending on the timing and the design. For example if you have to reply to one transmission before receiving the next then a ring buffer only needs to be big enough to hold one full packet.
    At which point I would pull out one byte at a time to put into a buffer, until I am satisfied that I have a good packet. Then I would process it.

    If you have the room then that’s probably good enough. Some people will have a peek function where they can look into the Ring buffer and see what’s there, when they’re happy with what’s there, then they pull the entire Packet it out.

    I personally am not a fan of ping-pong buffers, since they require extra code to deal with the problem of extra or missing bytes in a transmission. But that’s just me.
    #5
    Murton Pike Systems
    Senior Member
    • Total Posts : 48
    • Reward points : 0
    • Joined: 2020/09/10 02:13:01
    • Location: 0
    • Status: offline
    Re: UART Ring Buffer in MPlab Harmony 2020/10/19 14:36:45 (permalink)
    0
    I tend to not use ring buffers and use a linear buffer which is packet based.
    It has length, data and CRC.
     
    #6
    ric
    Super Member
    • Total Posts : 28645
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: UART Ring Buffer in MPlab Harmony 2020/10/19 14:42:45 (permalink)
    0
    Paul PortSol
    ((done editting..., this time had to swap angle brackets for curved in my text))
     

    The web firewall tends to choke if it sees "char" followed by "(" with less than two spaces between them.




    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #7
    NKurzman
    A Guy on the Net
    • Total Posts : 18967
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: online
    Re: UART Ring Buffer in MPlab Harmony 2020/10/19 14:48:00 (permalink)
    0
    It depends on the application.
    For modbus I used a linear Buffer.
    Since Each packet must be responded too.
    And the host will not send a new command until the response is received, or timed out.
    it is up to the consuming code to determine when the packet is complete, or if it’s invalid it needs to be thrown away.
    There was no one solution that will work for every problem.
    #8
    m_snaeem@hotmail.com
    Starting Member
    • Total Posts : 76
    • Reward points : 0
    • Joined: 2020/07/10 10:54:03
    • Location: 0
    • Status: offline
    Re: UART Ring Buffer in MPlab Harmony 2020/10/20 11:36:21 (permalink)
    0
    Earlier I was trying to set the read threshold at 2 so the second byte further set the read threshold at to its value. But for that purpose, there was the solution to send 1 message in two packets which was not a good thing so  I have accomplished the task using interrupt on each byte instead of Ring Buffer which works successfully.
    Thanks for your suggestion as I am not an experienced programmer so this method seems easy to me.
    #9
    NKurzman
    A Guy on the Net
    • Total Posts : 18967
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: online
    Re: UART Ring Buffer in MPlab Harmony 2020/10/20 13:57:10 (permalink)
    0
    The advantage of the ring buffer would be the bytes would go into the Buffer in the interrupt.
    You could remove them from the ring buffer one byte at a time in your main loop. This would mean you would not have to process your packet in the interrupt.

    However depending on your Application doing the work in the interrupted may not be an issue. But remember doing too much in an interrupt will pause everything else.
    #10
    m_snaeem@hotmail.com
    Starting Member
    • Total Posts : 76
    • Reward points : 0
    • Joined: 2020/07/10 10:54:03
    • Location: 0
    • Status: offline
    Re: UART Ring Buffer in MPlab Harmony 2020/10/20 14:05:49 (permalink)
    0
    I have nothing in main while loop
    and until now it is functioning with no delay or pause but i will try you implement your suggestion also.
    i also like to do it with ring buffer but unfortunately i dont have much time to spend on ring buffer to implement other methods.
    #11
    vexorg
    Senior Member
    • Total Posts : 139
    • Reward points : 0
    • Joined: 2019/09/27 10:59:40
    • Location: 0
    • Status: online
    Re: UART Ring Buffer in MPlab Harmony 2020/10/21 01:44:29 (permalink)
    0
    In it's simplest form a ring buffer is just an array:
     
    char ring_buffer[256];
    unsigned char head=0;
    unsigned char tail=0;
     
    Have a head and tail variable as unsigned char.
     
    In the interrupt have: ring_buffer[head++] = uart receive char;
     
    In the main loop check if head = tail, if not equal then you have data.
    To read a char out then use: val=ring_buffer[tail++];
     
    The bytes in the buffer are head-tail.
     
    You can get fancier as you go, for example, in the interrupt check head!=(tail+1) for the ring buffer overrun and set a flag.
     
    You can have flags in the interrupt to check for certain chars, like packet start or end so that you know when to grab the data. Depends on your send packet structure.
    #12
    rpg7
    Super Member
    • Total Posts : 1416
    • Reward points : 0
    • Joined: 2003/11/07 12:47:35
    • Status: offline
    Re: UART Ring Buffer in MPlab Harmony 2020/10/21 02:58:40 (permalink)
    0
    I always use a ring buffer that is fille in the interrupt. In main I transfer the char from the ring buffer to a linear buffer. All messages in ascii , terminated by CR. (0x0D)
    #13
    Chris A
    Super Member
    • Total Posts : 860
    • Reward points : 0
    • Joined: 2010/07/20 04:37:07
    • Location: 0
    • Status: offline
    Re: UART Ring Buffer in MPlab Harmony 2020/10/21 05:49:20 (permalink)
    0
    I've built ring FIFOs functions that allow the data to be accessed "in FIFO" that give the advantage of both worlds and avoids moving data over and over. It allows a protocol to be decoded and start message syncronisation to be be restarted earlier on the data stream that is still in the buffer.
    int FiFoGet(struct UFIFO *pF);
    uint8_t FiFoPeek(struct UFIFO *pF, uint8_t n);
    uint8_t FiFoGetPtr(struct UFIFO *pF, uint8_t **ppData, uint8_t s, uint8_t maxlen);
    uint8_t FiFoGetN(struct UFIFO *pF, uint8_t *pOut, uint8_t Len);

    I use this on a typical protocol that goes <Start flag><Length><Data   .....><crc>
     
    post edited by Chris A - 2020/10/21 05:50:52
    #14
    NorthGuy
    Super Member
    • Total Posts : 6347
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: UART Ring Buffer in MPlab Harmony 2020/10/21 08:52:41 (permalink)
    0
    NKurzman
    The advantage of the ring buffer would be the bytes would go into the Buffer in the interrupt.
    You could remove them from the ring buffer one byte at a time in your main loop. This would mean you would not have to process your packet in the interrupt.



    The amount of processing you need to for put a byte into the ping-pong buffer is not that much different as for putting a byte into the ring buffer.
     
    For example, ping-pong:
     
    if (ByteNo == 1) {
      // OP has the command length in the second byte
      if (ByteIn > MAX_COMMAND_SIZE) {
        // disaster. wrong command size. Do something and return
      }
      ByteCount = ByteIn;
    }
    buffer[ByteNo++] = ByteIn;
    if (ByteNo > ByteCount) {
      CommandToProcess = buffer;
      buffer += Delta;
      Delta = -Delta;
      ByteNo = 0;
    }

     
    compare to the ring buffer:
     
    if (BytesUsed > RING_BUFFER_SIZE) {  
      // disaster. bufer is full. Do something and return
    }
    if ++Head >= RING_BUFFER_SIZE {
      Head = 0;
    }
    buffer[Head] = ByteIn;
    BytesUsed++;

     
    But in case of ping-pong, you already receive the command which can be processed. In case of ring buffer, the main will need to read the buffer byte-by-byte to get a command.
     
    #15
    NKurzman
    A Guy on the Net
    • Total Posts : 18967
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: online
    Re: UART Ring Buffer in MPlab Harmony 2020/10/21 09:38:28 (permalink)
    0
    My problem with a ping pong preferences you need to expect a specific number of bytes. Which doesn’t always happen. Bytes occasionally get lost, and noise can make extra ones.
    Unless you’re talking about using ping pong buffers to catch chunks of the message between checks in the main loop.
    That I had not considered.
    Reading the message byte by Byte can Determine if the packet is corrupt and you need to look for the start of a new packet.
    I’m a big fan of a unique byte for start of packet.

    Complicating this would be what is the Harmony support for both?
    #16
    vexorg
    Senior Member
    • Total Posts : 139
    • Reward points : 0
    • Joined: 2019/09/27 10:59:40
    • Location: 0
    • Status: online
    Re: UART Ring Buffer in MPlab Harmony 2020/10/21 12:29:30 (permalink)
    0
    NKurzman
    I’m a big fan of a unique byte for start of packet.



    You often dont get that choice if you are reading from another product.
    There's no issue as long as the start / end chars cannot be in the main packet.
    #17
    Jump to:
    © 2020 APG vNext Commercial Version 4.5