I have a piece of code here that was generated by Atmel START Wizard. It setups a UART and it also creates a ring buffer for reading data.
This is the code that reads data from the buffer:
uint8_t USART_2_read(void)
{
uint8_t tmptail;
/* Wait for incoming data */
while (USART_2_rx_elements == 0)
;
/* Calculate buffer index */
tmptail = (USART_2_rx_tail + 1) & USART_2_RX_BUFFER_MASK;
/* Store new index */
USART_2_rx_tail = tmptail;
ENTER_CRITICAL(R);
USART_2_rx_elements--;
EXIT_CRITICAL(R);
/* Return data */
return USART_2_rxbuf[tmptail];
}
When the main program access the buffer it calls an ENTER_CRITICAL(R) macro before decreases the elements counter by one.
Here is the ENTER_CRITICAL macro:
#define ENTER_CRITICAL(UNUSED) __asm__ __volatile__ ( \
"in __tmp_reg__, __SREG__" "\n\t" \
"cli" "\n\t" \
"push __tmp_reg__" "\n\t" \
::: "memory" \
)
and the EXIT_CRITICAL macro:
#define EXIT_CRITICAL(UNUSED) __asm__ __volatile__ ( \
"pop __tmp_reg__" "\n\t" \
"out __SREG__, __tmp_reg__" "\n\t" \
::: "memory" \
)
I noticed that it disables the global interrupt, not only the Receive Complete Interrupt of the UART. Usually what I'd do is to disable only the "Receive Complete Interrupt" letting any other interrupt enabled. This all make me wonder if there's any particular reason that Atmel or Microchip developers make it that way.
Does Global Interrupt need to be disabled? Would the other interrupt affect this operation if they were enabled? Is there any difference by disabling only peripheral's respective interrupt?
This code is running on an AVR8
buffer[pos++]=...
butbuffer[pos]=...; pos++;
) and calculate the number of elements in the buffer from both pointers... \$\endgroup\$