Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Mechanism Problem

Status
Not open for further replies.

electroRF

Member
Hi,

I'd love to share the problem I have with a Shared Circular Buffer between two uCs that is used for sending Messages between them.

Each uC holds Tail and Head Indexes for the Shared Circular Buffer, which are initialized to zero.

When one uC wants to send a message to another uC, it puts the Message in the Buffer and Interrupts the other uC.

Now, the other uC knows to look for the message in its Tail Index (it'd know the length of the Message since it's located at the beginning of the message as a rule between the two uCs).

I hope the Mechanism is clear.

I'm debugging a problem I got with the Mechanism and I think that this is what happened.

One of the uC sent Message to the other uC.

the other uC was still occupied with a high-priority task, and therefore did not read the Message yet until it finished handling that task.

In the meantime, the uC sent another 2 Messages to the other uC.

Only now, having 3 pending Messages waiting for it in the buffer, the other uC turned to read the Messages from the Buffer.

What happened was the the other uC read garbage.

I'm afraid the these 3 Messages exceeded the length of the Buffer (which is Circular), and therefore the 3rd Message ran over the 1st Message;

For that reason, the 1st Message looked like garbage to the other uC when it turned to read it.

How could I overcome such situation?

Increasing the Shared Circular Buffer is not an ideal solution since it could still happen.

Thank you.
 
Here's the thing about buffers: no matter how big they are, given enough time, enough speed on the sending end, and enough slowness on the receiving end, they can overflow. The only thing you can do is to detect the overflow.
 
Hi NorthGuy,
Im thankful for you taking part in the thread.

You are right.

How would you detect such case of overflow?
 
To keep track of overflow, you need to maintain some sort of information, e.g. serial numbers in messages or such.

Overall, I would maintain separate buffers on sending and receiving ends, which would reduce overhead and minimize errors.
 
When the head wraps around and crosses over the tail, then you know that you will overflow the buffer and ruin the first message if you attempt to write a new one. The solution would be to drop the new messages and wait for the receiving cpu to empty the buffer.
Also I wouldnt call the indexes head and tail, but rather something like lastWrittenAddress and lastReadAddress respectively. Receiver increments lastReadAddress, sender increments lastWrittenAddres, when lastWrittenAddress reaches lastReadAddress after it wraps around, then you know you filled the buffer completely and need to stop further writes.
 
If at any point after the first written byte the head index equals the tail then you have filled the buffer.

BTW, how do the two micros communicate the head and tail variables between each other? I don't see how this can be done.

Mike.
 
Each uC holds Tail and Head Indexes for the Shared Circular Buffer, which are initialized to zero.
How are they sharing the buffer? Is it an external memory that both access?
 
Hi dear folks, thank you very much! :)

To keep track of overflow, you need to maintain some sort of information, e.g. serial numbers in messages or such.

Overall, I would maintain separate buffers on sending and receiving ends, which would reduce overhead and minimize errors.

Yes, you're right. :)
By maintaining serial number of each message, I could check whether the serial number of the currently read message is bigger than the last serial number by 1.
If yes, no overflow.
If not, overflow occurred and the Message the uC reads is garbage.

I believe I could instead maintain a 16-bit (or 32-bit) SOP (Start Of Packet) for each Message, and if the Message turns garbage, I'd know it.

I do use 2 separate buffers as you said (but it of course doesn't protect against overflow).

When the head wraps around and crosses over the tail, then you know that you will overflow the buffer and ruin the first message if you attempt to write a new one. The solution would be to drop the new messages and wait for the receiving cpu to empty the buffer.
Also I wouldnt call the indexes head and tail, but rather something like lastWrittenAddress and lastReadAddress respectively. Receiver increments lastReadAddress, sender increments lastWrittenAddres, when lastWrittenAddress reaches lastReadAddress after it wraps around, then you know you filled the buffer completely and need to stop further writes.

That is also a good idea, thank you.

How would you easily tell that the head (lastWrittenAddress) wrapped around?

If at any point after the first written byte the head index equals the tail then you have filled the buffer.

BTW, how do the two micros communicate the head and tail variables between each other? I don't see how this can be done.

Mike.

yes, but you need to somehow know (as I told kubeek) that the head wrapped around.
How would you tell that?
The 2 uCs don't send to each other the head and tail, but they do write the length of each message inside the message.
That way, each uC maintains its own head and tail.

How are they sharing the buffer? Is it an external memory that both access?
Exactly :)
 
You need to keep the head and tail indexes in the shared memory.
 
You can tell it has wrapped around when head index becomes lower than tail index.
 
If you have two way communication in the same buffer then I can't see how it can work efficiently. Do you just check the first message in the buffer and if it's for you then you somehow invalidate it or do you check all messages in the buffer? Plus, if the other communicator invalidates then you move your tail pointer? It would be a lot simpler to have two separate buffers.

The only way (currently) to know if it's full is, on every write you test for the start of a valid message. However, this would be very inefficient.

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top