Questions about this serial communication code? [Cortex-M4]










0














I'm looking at the following code from STMicroelectronics on implementing USART communication with interrupts



#include <stm32f10x_lib.h> // STM32F10x Library Definitions
#include <stdio.h>
#include "STM32_Init.h" // STM32 Initialization


/*----------------------------------------------------------------------------
Notes:
The length of the receive and transmit buffers must be a power of 2.
Each buffer has a next_in and a next_out index.
If next_in = next_out, the buffer is empty.
(next_in - next_out) % buffer_size = the number of characters in the buffer.
*----------------------------------------------------------------------------*/
#define TBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
#define RBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/

/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#if TBUF_SIZE < 2
#error TBUF_SIZE is too small. It must be larger than 1.
#elif ((TBUF_SIZE & (TBUF_SIZE-1)) != 0)
#error TBUF_SIZE must be a power of 2.
#endif

#if RBUF_SIZE < 2
#error RBUF_SIZE is too small. It must be larger than 1.
#elif ((RBUF_SIZE & (RBUF_SIZE-1)) != 0)
#error RBUF_SIZE must be a power of 2.
#endif

/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
struct buf_st
unsigned int in; // Next In Index
unsigned int out; // Next Out Index
char buf [RBUF_SIZE]; // Buffer
;

static struct buf_st rbuf = 0, 0, ;
#define SIO_RBUFLEN ((unsigned short)(rbuf.in - rbuf.out))

static struct buf_st tbuf = 0, 0, ;
#define SIO_TBUFLEN ((unsigned short)(tbuf.in - tbuf.out))

static unsigned int tx_restart = 1; // NZ if TX restart is required

/*----------------------------------------------------------------------------
USART1_IRQHandler
Handles USART1 global interrupt request.
*----------------------------------------------------------------------------*/
void USART1_IRQHandler (void)
volatile unsigned int IIR;
struct buf_st *p;

IIR = USART1->SR;
if (IIR & USART_FLAG_RXNE) // read interrupt
USART1->SR &= ~USART_FLAG_RXNE; // clear interrupt

p = &rbuf;

if (((p->in - p->out) & ~(RBUF_SIZE-1)) == 0)
p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
p->in++;



if (IIR & USART_FLAG_TXE)
USART1->SR &= ~USART_FLAG_TXE; // clear interrupt

p = &tbuf;

if (p->in != p->out)
USART1->DR = (p->buf [p->out & (TBUF_SIZE-1)] & 0x1FF);
p->out++;
tx_restart = 0;

else
tx_restart = 1;
USART1->CR1 &= ~USART_FLAG_TXE; // disable TX interrupt if nothing to send





/*------------------------------------------------------------------------------
buffer_Init
initialize the buffers
*------------------------------------------------------------------------------*/
void buffer_Init (void)

tbuf.in = 0; // Clear com buffer indexes
tbuf.out = 0;
tx_restart = 1;

rbuf.in = 0;
rbuf.out = 0;


/*------------------------------------------------------------------------------
SenChar
transmit a character
*------------------------------------------------------------------------------*/
int SendChar (int c)
struct buf_st *p = &tbuf;

// If the buffer is full, return an error value
if (SIO_TBUFLEN >= TBUF_SIZE)
return (-1);

p->buf [p->in & (TBUF_SIZE - 1)] = c; // Add data to the transmit buffer.
p->in++;

if (tx_restart) = USART_FLAG_TXE; // enable TX interrupt


return (0);


/*------------------------------------------------------------------------------
GetKey
receive a character
*------------------------------------------------------------------------------*/
int GetKey (void)
struct buf_st *p = &rbuf;

if (SIO_RBUFLEN == 0)
return (-1);

return (p->buf [(p->out++) & (RBUF_SIZE - 1)]);



/*----------------------------------------------------------------------------
MAIN function
*----------------------------------------------------------------------------*/
int main (void)

buffer_Init(); // init RX / TX buffers
stm32_Init (); // STM32 setup

printf ("Interrupt driven Serial I/O Examplernrn");

while (1) // Loop forever
unsigned char c;

printf ("Press a key. ");
c = getchar ();
printf ("rn");
printf ("You pressed '%c'.rnrn", c);
// end while
// end main


My questions are the following:



  1. In the handler function, when does the statement ((p->in - p->out) & ~(RBUF_SIZE-1)) ever evaluate to a value other than zero? If RBUF_SIZE is a power of 2 as indicated, then ~(RBUF_SIZE-1) should always be zero. Is it checking if p->in > p->out? Even if this isn't true, the conditional should evaluate to zero anyway, right?

  2. In the line following, the statement p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF); is made. Why does the code AND p->in with RBUF_SIZE-1?

  3. What kind of buffer are we using in this code? FIFO?









share|improve this question


























    0














    I'm looking at the following code from STMicroelectronics on implementing USART communication with interrupts



    #include <stm32f10x_lib.h> // STM32F10x Library Definitions
    #include <stdio.h>
    #include "STM32_Init.h" // STM32 Initialization


    /*----------------------------------------------------------------------------
    Notes:
    The length of the receive and transmit buffers must be a power of 2.
    Each buffer has a next_in and a next_out index.
    If next_in = next_out, the buffer is empty.
    (next_in - next_out) % buffer_size = the number of characters in the buffer.
    *----------------------------------------------------------------------------*/
    #define TBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
    #define RBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/

    /*----------------------------------------------------------------------------
    *----------------------------------------------------------------------------*/
    #if TBUF_SIZE < 2
    #error TBUF_SIZE is too small. It must be larger than 1.
    #elif ((TBUF_SIZE & (TBUF_SIZE-1)) != 0)
    #error TBUF_SIZE must be a power of 2.
    #endif

    #if RBUF_SIZE < 2
    #error RBUF_SIZE is too small. It must be larger than 1.
    #elif ((RBUF_SIZE & (RBUF_SIZE-1)) != 0)
    #error RBUF_SIZE must be a power of 2.
    #endif

    /*----------------------------------------------------------------------------
    *----------------------------------------------------------------------------*/
    struct buf_st
    unsigned int in; // Next In Index
    unsigned int out; // Next Out Index
    char buf [RBUF_SIZE]; // Buffer
    ;

    static struct buf_st rbuf = 0, 0, ;
    #define SIO_RBUFLEN ((unsigned short)(rbuf.in - rbuf.out))

    static struct buf_st tbuf = 0, 0, ;
    #define SIO_TBUFLEN ((unsigned short)(tbuf.in - tbuf.out))

    static unsigned int tx_restart = 1; // NZ if TX restart is required

    /*----------------------------------------------------------------------------
    USART1_IRQHandler
    Handles USART1 global interrupt request.
    *----------------------------------------------------------------------------*/
    void USART1_IRQHandler (void)
    volatile unsigned int IIR;
    struct buf_st *p;

    IIR = USART1->SR;
    if (IIR & USART_FLAG_RXNE) // read interrupt
    USART1->SR &= ~USART_FLAG_RXNE; // clear interrupt

    p = &rbuf;

    if (((p->in - p->out) & ~(RBUF_SIZE-1)) == 0)
    p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
    p->in++;



    if (IIR & USART_FLAG_TXE)
    USART1->SR &= ~USART_FLAG_TXE; // clear interrupt

    p = &tbuf;

    if (p->in != p->out)
    USART1->DR = (p->buf [p->out & (TBUF_SIZE-1)] & 0x1FF);
    p->out++;
    tx_restart = 0;

    else
    tx_restart = 1;
    USART1->CR1 &= ~USART_FLAG_TXE; // disable TX interrupt if nothing to send





    /*------------------------------------------------------------------------------
    buffer_Init
    initialize the buffers
    *------------------------------------------------------------------------------*/
    void buffer_Init (void)

    tbuf.in = 0; // Clear com buffer indexes
    tbuf.out = 0;
    tx_restart = 1;

    rbuf.in = 0;
    rbuf.out = 0;


    /*------------------------------------------------------------------------------
    SenChar
    transmit a character
    *------------------------------------------------------------------------------*/
    int SendChar (int c)
    struct buf_st *p = &tbuf;

    // If the buffer is full, return an error value
    if (SIO_TBUFLEN >= TBUF_SIZE)
    return (-1);

    p->buf [p->in & (TBUF_SIZE - 1)] = c; // Add data to the transmit buffer.
    p->in++;

    if (tx_restart) = USART_FLAG_TXE; // enable TX interrupt


    return (0);


    /*------------------------------------------------------------------------------
    GetKey
    receive a character
    *------------------------------------------------------------------------------*/
    int GetKey (void)
    struct buf_st *p = &rbuf;

    if (SIO_RBUFLEN == 0)
    return (-1);

    return (p->buf [(p->out++) & (RBUF_SIZE - 1)]);



    /*----------------------------------------------------------------------------
    MAIN function
    *----------------------------------------------------------------------------*/
    int main (void)

    buffer_Init(); // init RX / TX buffers
    stm32_Init (); // STM32 setup

    printf ("Interrupt driven Serial I/O Examplernrn");

    while (1) // Loop forever
    unsigned char c;

    printf ("Press a key. ");
    c = getchar ();
    printf ("rn");
    printf ("You pressed '%c'.rnrn", c);
    // end while
    // end main


    My questions are the following:



    1. In the handler function, when does the statement ((p->in - p->out) & ~(RBUF_SIZE-1)) ever evaluate to a value other than zero? If RBUF_SIZE is a power of 2 as indicated, then ~(RBUF_SIZE-1) should always be zero. Is it checking if p->in > p->out? Even if this isn't true, the conditional should evaluate to zero anyway, right?

    2. In the line following, the statement p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF); is made. Why does the code AND p->in with RBUF_SIZE-1?

    3. What kind of buffer are we using in this code? FIFO?









    share|improve this question
























      0












      0








      0







      I'm looking at the following code from STMicroelectronics on implementing USART communication with interrupts



      #include <stm32f10x_lib.h> // STM32F10x Library Definitions
      #include <stdio.h>
      #include "STM32_Init.h" // STM32 Initialization


      /*----------------------------------------------------------------------------
      Notes:
      The length of the receive and transmit buffers must be a power of 2.
      Each buffer has a next_in and a next_out index.
      If next_in = next_out, the buffer is empty.
      (next_in - next_out) % buffer_size = the number of characters in the buffer.
      *----------------------------------------------------------------------------*/
      #define TBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
      #define RBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/

      /*----------------------------------------------------------------------------
      *----------------------------------------------------------------------------*/
      #if TBUF_SIZE < 2
      #error TBUF_SIZE is too small. It must be larger than 1.
      #elif ((TBUF_SIZE & (TBUF_SIZE-1)) != 0)
      #error TBUF_SIZE must be a power of 2.
      #endif

      #if RBUF_SIZE < 2
      #error RBUF_SIZE is too small. It must be larger than 1.
      #elif ((RBUF_SIZE & (RBUF_SIZE-1)) != 0)
      #error RBUF_SIZE must be a power of 2.
      #endif

      /*----------------------------------------------------------------------------
      *----------------------------------------------------------------------------*/
      struct buf_st
      unsigned int in; // Next In Index
      unsigned int out; // Next Out Index
      char buf [RBUF_SIZE]; // Buffer
      ;

      static struct buf_st rbuf = 0, 0, ;
      #define SIO_RBUFLEN ((unsigned short)(rbuf.in - rbuf.out))

      static struct buf_st tbuf = 0, 0, ;
      #define SIO_TBUFLEN ((unsigned short)(tbuf.in - tbuf.out))

      static unsigned int tx_restart = 1; // NZ if TX restart is required

      /*----------------------------------------------------------------------------
      USART1_IRQHandler
      Handles USART1 global interrupt request.
      *----------------------------------------------------------------------------*/
      void USART1_IRQHandler (void)
      volatile unsigned int IIR;
      struct buf_st *p;

      IIR = USART1->SR;
      if (IIR & USART_FLAG_RXNE) // read interrupt
      USART1->SR &= ~USART_FLAG_RXNE; // clear interrupt

      p = &rbuf;

      if (((p->in - p->out) & ~(RBUF_SIZE-1)) == 0)
      p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
      p->in++;



      if (IIR & USART_FLAG_TXE)
      USART1->SR &= ~USART_FLAG_TXE; // clear interrupt

      p = &tbuf;

      if (p->in != p->out)
      USART1->DR = (p->buf [p->out & (TBUF_SIZE-1)] & 0x1FF);
      p->out++;
      tx_restart = 0;

      else
      tx_restart = 1;
      USART1->CR1 &= ~USART_FLAG_TXE; // disable TX interrupt if nothing to send





      /*------------------------------------------------------------------------------
      buffer_Init
      initialize the buffers
      *------------------------------------------------------------------------------*/
      void buffer_Init (void)

      tbuf.in = 0; // Clear com buffer indexes
      tbuf.out = 0;
      tx_restart = 1;

      rbuf.in = 0;
      rbuf.out = 0;


      /*------------------------------------------------------------------------------
      SenChar
      transmit a character
      *------------------------------------------------------------------------------*/
      int SendChar (int c)
      struct buf_st *p = &tbuf;

      // If the buffer is full, return an error value
      if (SIO_TBUFLEN >= TBUF_SIZE)
      return (-1);

      p->buf [p->in & (TBUF_SIZE - 1)] = c; // Add data to the transmit buffer.
      p->in++;

      if (tx_restart) = USART_FLAG_TXE; // enable TX interrupt


      return (0);


      /*------------------------------------------------------------------------------
      GetKey
      receive a character
      *------------------------------------------------------------------------------*/
      int GetKey (void)
      struct buf_st *p = &rbuf;

      if (SIO_RBUFLEN == 0)
      return (-1);

      return (p->buf [(p->out++) & (RBUF_SIZE - 1)]);



      /*----------------------------------------------------------------------------
      MAIN function
      *----------------------------------------------------------------------------*/
      int main (void)

      buffer_Init(); // init RX / TX buffers
      stm32_Init (); // STM32 setup

      printf ("Interrupt driven Serial I/O Examplernrn");

      while (1) // Loop forever
      unsigned char c;

      printf ("Press a key. ");
      c = getchar ();
      printf ("rn");
      printf ("You pressed '%c'.rnrn", c);
      // end while
      // end main


      My questions are the following:



      1. In the handler function, when does the statement ((p->in - p->out) & ~(RBUF_SIZE-1)) ever evaluate to a value other than zero? If RBUF_SIZE is a power of 2 as indicated, then ~(RBUF_SIZE-1) should always be zero. Is it checking if p->in > p->out? Even if this isn't true, the conditional should evaluate to zero anyway, right?

      2. In the line following, the statement p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF); is made. Why does the code AND p->in with RBUF_SIZE-1?

      3. What kind of buffer are we using in this code? FIFO?









      share|improve this question













      I'm looking at the following code from STMicroelectronics on implementing USART communication with interrupts



      #include <stm32f10x_lib.h> // STM32F10x Library Definitions
      #include <stdio.h>
      #include "STM32_Init.h" // STM32 Initialization


      /*----------------------------------------------------------------------------
      Notes:
      The length of the receive and transmit buffers must be a power of 2.
      Each buffer has a next_in and a next_out index.
      If next_in = next_out, the buffer is empty.
      (next_in - next_out) % buffer_size = the number of characters in the buffer.
      *----------------------------------------------------------------------------*/
      #define TBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
      #define RBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/

      /*----------------------------------------------------------------------------
      *----------------------------------------------------------------------------*/
      #if TBUF_SIZE < 2
      #error TBUF_SIZE is too small. It must be larger than 1.
      #elif ((TBUF_SIZE & (TBUF_SIZE-1)) != 0)
      #error TBUF_SIZE must be a power of 2.
      #endif

      #if RBUF_SIZE < 2
      #error RBUF_SIZE is too small. It must be larger than 1.
      #elif ((RBUF_SIZE & (RBUF_SIZE-1)) != 0)
      #error RBUF_SIZE must be a power of 2.
      #endif

      /*----------------------------------------------------------------------------
      *----------------------------------------------------------------------------*/
      struct buf_st
      unsigned int in; // Next In Index
      unsigned int out; // Next Out Index
      char buf [RBUF_SIZE]; // Buffer
      ;

      static struct buf_st rbuf = 0, 0, ;
      #define SIO_RBUFLEN ((unsigned short)(rbuf.in - rbuf.out))

      static struct buf_st tbuf = 0, 0, ;
      #define SIO_TBUFLEN ((unsigned short)(tbuf.in - tbuf.out))

      static unsigned int tx_restart = 1; // NZ if TX restart is required

      /*----------------------------------------------------------------------------
      USART1_IRQHandler
      Handles USART1 global interrupt request.
      *----------------------------------------------------------------------------*/
      void USART1_IRQHandler (void)
      volatile unsigned int IIR;
      struct buf_st *p;

      IIR = USART1->SR;
      if (IIR & USART_FLAG_RXNE) // read interrupt
      USART1->SR &= ~USART_FLAG_RXNE; // clear interrupt

      p = &rbuf;

      if (((p->in - p->out) & ~(RBUF_SIZE-1)) == 0)
      p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
      p->in++;



      if (IIR & USART_FLAG_TXE)
      USART1->SR &= ~USART_FLAG_TXE; // clear interrupt

      p = &tbuf;

      if (p->in != p->out)
      USART1->DR = (p->buf [p->out & (TBUF_SIZE-1)] & 0x1FF);
      p->out++;
      tx_restart = 0;

      else
      tx_restart = 1;
      USART1->CR1 &= ~USART_FLAG_TXE; // disable TX interrupt if nothing to send





      /*------------------------------------------------------------------------------
      buffer_Init
      initialize the buffers
      *------------------------------------------------------------------------------*/
      void buffer_Init (void)

      tbuf.in = 0; // Clear com buffer indexes
      tbuf.out = 0;
      tx_restart = 1;

      rbuf.in = 0;
      rbuf.out = 0;


      /*------------------------------------------------------------------------------
      SenChar
      transmit a character
      *------------------------------------------------------------------------------*/
      int SendChar (int c)
      struct buf_st *p = &tbuf;

      // If the buffer is full, return an error value
      if (SIO_TBUFLEN >= TBUF_SIZE)
      return (-1);

      p->buf [p->in & (TBUF_SIZE - 1)] = c; // Add data to the transmit buffer.
      p->in++;

      if (tx_restart) = USART_FLAG_TXE; // enable TX interrupt


      return (0);


      /*------------------------------------------------------------------------------
      GetKey
      receive a character
      *------------------------------------------------------------------------------*/
      int GetKey (void)
      struct buf_st *p = &rbuf;

      if (SIO_RBUFLEN == 0)
      return (-1);

      return (p->buf [(p->out++) & (RBUF_SIZE - 1)]);



      /*----------------------------------------------------------------------------
      MAIN function
      *----------------------------------------------------------------------------*/
      int main (void)

      buffer_Init(); // init RX / TX buffers
      stm32_Init (); // STM32 setup

      printf ("Interrupt driven Serial I/O Examplernrn");

      while (1) // Loop forever
      unsigned char c;

      printf ("Press a key. ");
      c = getchar ();
      printf ("rn");
      printf ("You pressed '%c'.rnrn", c);
      // end while
      // end main


      My questions are the following:



      1. In the handler function, when does the statement ((p->in - p->out) & ~(RBUF_SIZE-1)) ever evaluate to a value other than zero? If RBUF_SIZE is a power of 2 as indicated, then ~(RBUF_SIZE-1) should always be zero. Is it checking if p->in > p->out? Even if this isn't true, the conditional should evaluate to zero anyway, right?

      2. In the line following, the statement p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF); is made. Why does the code AND p->in with RBUF_SIZE-1?

      3. What kind of buffer are we using in this code? FIFO?






      interrupt interrupt-handling cortex-m usart






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 12 at 8:49









      user50420

      245




      245






















          1 Answer
          1






          active

          oldest

          votes


















          3














          1. Not so. For example, assuming 32-bit arithmetic, if RBUF_SIZE == 0x00000100 then RBUF_SIZE-1 == 0x000000FF and ~(RBUF_SIZE-1) == 0xFFFFFF00 (it's a bitwise NOT, not a logical NOT). The check you refer to is therefore effectively the same as (p->in - p->out) < RBUF_SIZE, and it's not clear why it is superior. ARM GCC 7.2.1 produces identical length code for the two (-O1).


          2. p->in & (RBUF_SIZE-1) is the same as p->in % RBUF_SIZE when p->in is unsigned. Again, not sure why the former would be used when the latter is clearer; sure, it effectively forces the compiler to compute the modulo using an AND operation, but given that RBUF_SIZE is known at compile time to be a power of two my guess is that most compilers could figure this out (again, ARM GCC 7.2.1 certainly can, I've just tried it - it produces the same instructions either way).


          3. Looks like it. FIFO implemented as a circular buffer.






          share|improve this answer






















          • thanks for your interpretation. I, too, am not sure why ST chose to write their code in this indirect way
            – user50420
            Nov 12 at 9:57










          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53258561%2fquestions-about-this-serial-communication-code-cortex-m4%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          3














          1. Not so. For example, assuming 32-bit arithmetic, if RBUF_SIZE == 0x00000100 then RBUF_SIZE-1 == 0x000000FF and ~(RBUF_SIZE-1) == 0xFFFFFF00 (it's a bitwise NOT, not a logical NOT). The check you refer to is therefore effectively the same as (p->in - p->out) < RBUF_SIZE, and it's not clear why it is superior. ARM GCC 7.2.1 produces identical length code for the two (-O1).


          2. p->in & (RBUF_SIZE-1) is the same as p->in % RBUF_SIZE when p->in is unsigned. Again, not sure why the former would be used when the latter is clearer; sure, it effectively forces the compiler to compute the modulo using an AND operation, but given that RBUF_SIZE is known at compile time to be a power of two my guess is that most compilers could figure this out (again, ARM GCC 7.2.1 certainly can, I've just tried it - it produces the same instructions either way).


          3. Looks like it. FIFO implemented as a circular buffer.






          share|improve this answer






















          • thanks for your interpretation. I, too, am not sure why ST chose to write their code in this indirect way
            – user50420
            Nov 12 at 9:57















          3














          1. Not so. For example, assuming 32-bit arithmetic, if RBUF_SIZE == 0x00000100 then RBUF_SIZE-1 == 0x000000FF and ~(RBUF_SIZE-1) == 0xFFFFFF00 (it's a bitwise NOT, not a logical NOT). The check you refer to is therefore effectively the same as (p->in - p->out) < RBUF_SIZE, and it's not clear why it is superior. ARM GCC 7.2.1 produces identical length code for the two (-O1).


          2. p->in & (RBUF_SIZE-1) is the same as p->in % RBUF_SIZE when p->in is unsigned. Again, not sure why the former would be used when the latter is clearer; sure, it effectively forces the compiler to compute the modulo using an AND operation, but given that RBUF_SIZE is known at compile time to be a power of two my guess is that most compilers could figure this out (again, ARM GCC 7.2.1 certainly can, I've just tried it - it produces the same instructions either way).


          3. Looks like it. FIFO implemented as a circular buffer.






          share|improve this answer






















          • thanks for your interpretation. I, too, am not sure why ST chose to write their code in this indirect way
            – user50420
            Nov 12 at 9:57













          3












          3








          3






          1. Not so. For example, assuming 32-bit arithmetic, if RBUF_SIZE == 0x00000100 then RBUF_SIZE-1 == 0x000000FF and ~(RBUF_SIZE-1) == 0xFFFFFF00 (it's a bitwise NOT, not a logical NOT). The check you refer to is therefore effectively the same as (p->in - p->out) < RBUF_SIZE, and it's not clear why it is superior. ARM GCC 7.2.1 produces identical length code for the two (-O1).


          2. p->in & (RBUF_SIZE-1) is the same as p->in % RBUF_SIZE when p->in is unsigned. Again, not sure why the former would be used when the latter is clearer; sure, it effectively forces the compiler to compute the modulo using an AND operation, but given that RBUF_SIZE is known at compile time to be a power of two my guess is that most compilers could figure this out (again, ARM GCC 7.2.1 certainly can, I've just tried it - it produces the same instructions either way).


          3. Looks like it. FIFO implemented as a circular buffer.






          share|improve this answer














          1. Not so. For example, assuming 32-bit arithmetic, if RBUF_SIZE == 0x00000100 then RBUF_SIZE-1 == 0x000000FF and ~(RBUF_SIZE-1) == 0xFFFFFF00 (it's a bitwise NOT, not a logical NOT). The check you refer to is therefore effectively the same as (p->in - p->out) < RBUF_SIZE, and it's not clear why it is superior. ARM GCC 7.2.1 produces identical length code for the two (-O1).


          2. p->in & (RBUF_SIZE-1) is the same as p->in % RBUF_SIZE when p->in is unsigned. Again, not sure why the former would be used when the latter is clearer; sure, it effectively forces the compiler to compute the modulo using an AND operation, but given that RBUF_SIZE is known at compile time to be a power of two my guess is that most compilers could figure this out (again, ARM GCC 7.2.1 certainly can, I've just tried it - it produces the same instructions either way).


          3. Looks like it. FIFO implemented as a circular buffer.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 12 at 10:06

























          answered Nov 12 at 9:44









          cooperised

          1,236812




          1,236812











          • thanks for your interpretation. I, too, am not sure why ST chose to write their code in this indirect way
            – user50420
            Nov 12 at 9:57
















          • thanks for your interpretation. I, too, am not sure why ST chose to write their code in this indirect way
            – user50420
            Nov 12 at 9:57















          thanks for your interpretation. I, too, am not sure why ST chose to write their code in this indirect way
          – user50420
          Nov 12 at 9:57




          thanks for your interpretation. I, too, am not sure why ST chose to write their code in this indirect way
          – user50420
          Nov 12 at 9:57

















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53258561%2fquestions-about-this-serial-communication-code-cortex-m4%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          How to read a connectionString WITH PROVIDER in .NET Core?

          Node.js Script on GitHub Pages or Amazon S3

          Museum of Modern and Contemporary Art of Trento and Rovereto