|
From: | Dave Hansen |
Subject: | Re: [avr-gcc-list] Serial Communication |
Date: | Thu, 29 Jan 2004 09:10:59 -0500 |
From: Neil Johnson <address@hidden> [...]
> > #define USART_TX_BUFFER_MASK ( USART_TX_BUFFER_SIZE - 1 ) > The mask is used to maintain a ring buffer. **CAUTION** The masking trick works if the size of the buffer is a power of 2, e.g. 2, 4, 8, 16, 32, 64, 128, 256, 512, etc That way you can use bitwise AND to do the wraparound, e.g. index = (index + 1) & USART_TX_BUFFER_MASK; For any other buffer size you need to use the more expensive modulo operator "%": index = (index + 1) % USART_TX_BUFFER_MASK;
A couple nits to pick... The second case should actually be index = (index + 1) % (USART_TX_BUFFER_MASK+1); or index = (index + 1) % USART_TX_BUFFER_SIZE; There is another option as well, that some might find clearer: if (++index >= USART_TX_BUFFER_SIZE) index = 0;which should be more efficient than "%" if USART_TX_BUFFER_SIZE isn't a power of 2.
[...]
Discussion: one *could* stick with the BUFFER_SIZE value and hope thecompiler optimizes unsigned-modulo-with-(2^n) into bitwise AND-with-(2^n - 1).
Yes, it would be interesting to compare the code generated in each case when "USART_TX_BUFFER_SIZE" is a power of 2. A good compiler should be able to recognize the optimization and use the AND operation in both cases. I assume gcc is a good compiler, but I haven't examined this case yet...
Regards, -=Dave _________________________________________________________________High-speed usersbe more efficient online with the new MSN Premium Internet Software. http://join.msn.com/?pgmarket=en-us&page=byoa/prem&ST=1
[Prev in Thread] | Current Thread | [Next in Thread] |