Questions about this serial communication code? [Cortex-M4]
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:
- In the handler function, when does the statement
((p->in - p->out) & ~(RBUF_SIZE-1))
ever evaluate to a value other than zero? IfRBUF_SIZE
is a power of 2 as indicated, then~(RBUF_SIZE-1)
should always be zero. Is it checking ifp->in
>p->out
? Even if this isn't true, the conditional should evaluate to zero anyway, right? - In the line following, the statement
p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
is made. Why does the code ANDp->in
withRBUF_SIZE-1
? - What kind of buffer are we using in this code? FIFO?
interrupt interrupt-handling cortex-m usart
add a comment |
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:
- In the handler function, when does the statement
((p->in - p->out) & ~(RBUF_SIZE-1))
ever evaluate to a value other than zero? IfRBUF_SIZE
is a power of 2 as indicated, then~(RBUF_SIZE-1)
should always be zero. Is it checking ifp->in
>p->out
? Even if this isn't true, the conditional should evaluate to zero anyway, right? - In the line following, the statement
p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
is made. Why does the code ANDp->in
withRBUF_SIZE-1
? - What kind of buffer are we using in this code? FIFO?
interrupt interrupt-handling cortex-m usart
add a comment |
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:
- In the handler function, when does the statement
((p->in - p->out) & ~(RBUF_SIZE-1))
ever evaluate to a value other than zero? IfRBUF_SIZE
is a power of 2 as indicated, then~(RBUF_SIZE-1)
should always be zero. Is it checking ifp->in
>p->out
? Even if this isn't true, the conditional should evaluate to zero anyway, right? - In the line following, the statement
p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
is made. Why does the code ANDp->in
withRBUF_SIZE-1
? - What kind of buffer are we using in this code? FIFO?
interrupt interrupt-handling cortex-m usart
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:
- In the handler function, when does the statement
((p->in - p->out) & ~(RBUF_SIZE-1))
ever evaluate to a value other than zero? IfRBUF_SIZE
is a power of 2 as indicated, then~(RBUF_SIZE-1)
should always be zero. Is it checking ifp->in
>p->out
? Even if this isn't true, the conditional should evaluate to zero anyway, right? - In the line following, the statement
p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
is made. Why does the code ANDp->in
withRBUF_SIZE-1
? - What kind of buffer are we using in this code? FIFO?
interrupt interrupt-handling cortex-m usart
interrupt interrupt-handling cortex-m usart
asked Nov 12 at 8:49
user50420
245
245
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Not so. For example, assuming 32-bit arithmetic, if
RBUF_SIZE == 0x00000100
thenRBUF_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
).p->in & (RBUF_SIZE-1)
is the same asp->in % RBUF_SIZE
whenp->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 anAND
operation, but given thatRBUF_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).Looks like it. FIFO implemented as a circular buffer.
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
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Not so. For example, assuming 32-bit arithmetic, if
RBUF_SIZE == 0x00000100
thenRBUF_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
).p->in & (RBUF_SIZE-1)
is the same asp->in % RBUF_SIZE
whenp->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 anAND
operation, but given thatRBUF_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).Looks like it. FIFO implemented as a circular buffer.
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
add a comment |
Not so. For example, assuming 32-bit arithmetic, if
RBUF_SIZE == 0x00000100
thenRBUF_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
).p->in & (RBUF_SIZE-1)
is the same asp->in % RBUF_SIZE
whenp->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 anAND
operation, but given thatRBUF_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).Looks like it. FIFO implemented as a circular buffer.
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
add a comment |
Not so. For example, assuming 32-bit arithmetic, if
RBUF_SIZE == 0x00000100
thenRBUF_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
).p->in & (RBUF_SIZE-1)
is the same asp->in % RBUF_SIZE
whenp->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 anAND
operation, but given thatRBUF_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).Looks like it. FIFO implemented as a circular buffer.
Not so. For example, assuming 32-bit arithmetic, if
RBUF_SIZE == 0x00000100
thenRBUF_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
).p->in & (RBUF_SIZE-1)
is the same asp->in % RBUF_SIZE
whenp->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 anAND
operation, but given thatRBUF_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).Looks like it. FIFO implemented as a circular buffer.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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