Redesigning dma::CircBuffer
DrTobe opened this issue · comments
The CircBuffer
seems to be designed for a continuous reception of incoming data, using CircBuffer::partial_peek()
to give access to the data in the half which is currently being written. Like this, the user/reader does not have to wait for the "HalfComplete" and "Complete" flags/interrupts. In my opinion, this is a valuable feature because this allows for handling data which is not a multiple of the buffer size.
Unfortunately, the current approach can be affected by a race condition. For example, if the last byte of half "A" and the first byte of half "B" is received between the user's call of readable_half()
and partial_peek()
, the implementation of partial_peek()
will still assume half "A" as being written and read one byte there although this byte was already read before. The first byte of half "B" will be skipped ultimately. I guess with interrupts firing between the two function calls and with a relatively fast serial connection, this can definitely happen.
If I am not wrong, this can be resolved and the CircBuffer
as a whole could be simplified by only using a read_ptr
which roughly corresponds to the current consumed_offset
and a write_ptr = full_capacity - (self.channel.get_cndtr() as usize)
. Then, the whole CircBuffer
could be implemented like a regular single-writer-single-reader queue: The read_ptr
should never pass the write_ptr
. If the write_ptr
passes the read_ptr
, this is an overrun. Checking for the overrun condition could be complemented by using the flags/interrupts for "HalfComplete" and "Complete".
Is there something I am missing here or are there any objections to redesigning the CircBuffer
like that? Otherwise I would give it a try and redesign it like that.
Hi, this sounds like a good idea!
If you want to give it a try it would be great.