ruinned 发表于 2006-12-29 10:22:37

请教大家一个关于IAR volatile的问题

我用IAR 4.2来编译ATMEL官方的串口中断通信程序(稍微改动,主要是波特率定义等,不影响这个问题),编译后提示Warning: undefined behavior: the order of volatile accesses is undefined in this statement 大体上看,这个警告是说volatile的访问顺序没定义,那应该如果解决呢?

ruinned 发表于 2006-12-29 10:23:12

附源代码:

// AVR306: Using the AVR USART in C

// Routines for interrupt controlled USART

// Last modified: 02-06-21

// Modified by: AR



/* Includes */

#include <iom16.h>

#include <intrinsics.h>



/* USART Buffer Defines */

#define USART_RX_BUFFER_SIZE 32   /* 2,4,8,16,32,64,128 or 256 bytes */

#define USART_TX_BUFFER_SIZE 32





#define USART_RX_BUFFER_MASK ( USART_RX_BUFFER_SIZE - 1 )

#if ( USART_RX_BUFFER_SIZE & USART_RX_BUFFER_MASK )

        #error RX buffer size is not a power of 2

#endif



#define USART_TX_BUFFER_MASK ( USART_TX_BUFFER_SIZE - 1 )

#if ( USART_TX_BUFFER_SIZE & USART_TX_BUFFER_MASK )

        #error TX buffer size is not a power of 2

#endif





/* Static Variables */

static unsigned char USART_RxBuf;

static volatile unsigned char USART_RxHead;

static volatile unsigned char USART_RxTail;

static unsigned char USART_TxBuf;

static volatile unsigned char USART_TxHead;

static volatile unsigned char USART_TxTail;



/* Prototypes */

void InitUSART( unsigned char baudrate );

unsigned char ReceiveByte( void );

void TransmitByte( unsigned char data );



/* Main - a simple test program*/

void main( void )

{

        InitUSART( 47 );   /* Set the baudrate to 19,200 bps using a 3.6864MHz crystal */



        __enable_interrupt();         /* Enable interrupts => enable USART interrupts */



        for( ; ; )      /* Forever */

        {

                TransmitByte( ReceiveByte() ); /* Echo the received character */

        }

}



/* Initialize USART */

void InitUSART( unsigned char baudrate )

{

        //unsigned char x;



        UBRRH = (unsigned char)(baudrate>>8);

        UBRRL = (unsigned char)baudrate;/* Set the baud rate */

        /* Enable USART receiver and transmitter, and receive interrupt */

        //UCR = ( (1<<RXCIE) | (1<<RXEN) | (1<<TXEN) );

        UCSRB = ( (1<<RXEN) | (1<<TXEN) | (1<<RXCIE) );/* Enable USART receiver and transmitter */

        UCSRC = ((1<<URSEL)|(3<<UCSZ0));



        //x = 0;                           /* Flush receive buffer */



        USART_RxTail = 0;

        USART_RxHead = 0;

        USART_TxTail = 0;

        USART_TxHead = 0;

}



/* Interrupt handlers */

#pragma vector=USART_RXC_vect

__interrupt void USART_RX_interrupt( void )

{

        unsigned char data;

        unsigned char tmphead;



        data = UDR;               /* Read the received data */

        /* Calculate buffer index */

        tmphead = ( USART_RxHead + 1 ) & USART_RX_BUFFER_MASK;

        USART_RxHead = tmphead;      /* Store new index */



        if ( tmphead == USART_RxTail )

        {

                /* ERROR! Receive buffer overflow */

        }

       

        USART_RxBuf = data; /* Store received data in buffer */

}



#pragma vector=USART_UDRE_vect

__interrupt void USART_TX_interrupt( void )

{

        unsigned char tmptail;



        /* Check if all data is transmitted */

        if ( USART_TxHead != USART_TxTail )

        {

                /* Calculate buffer index */

                tmptail = ( USART_TxTail + 1 ) & USART_TX_BUFFER_MASK;

                USART_TxTail = tmptail;      /* Store new index */

       

                UDR = USART_TxBuf;/* Start transmition */

        }

        else

        {

                UCSRB &= ~(1<<UDRIE);         /* Disable UDRE interrupt */

        }

}



/* Read and write functions */

unsigned char ReceiveByte( void )

{

        unsigned char tmptail;

       

        while ( USART_RxHead == USART_RxTail )/* Wait for incomming data */

                ;

        tmptail = ( USART_RxTail + 1 ) & USART_RX_BUFFER_MASK;/* Calculate buffer index */

       

        USART_RxTail = tmptail;                /* Store new index */

       

        return USART_RxBuf;         /* Return data */

}



void TransmitByte( unsigned char data )

{

        unsigned char tmphead;

        /* Calculate buffer index */

        tmphead = ( USART_TxHead + 1 ) & USART_TX_BUFFER_MASK; /* Wait for free space in buffer */

        while ( tmphead == USART_TxTail );



        USART_TxBuf = data;         /* Store data in buffer */

        USART_TxHead = tmphead;                /* Store new index */



        UCSRB |= (1<<UDRIE);                  /* Enable UDRE interrupt */

}



unsigned char DataInReceiveBuffer( void )

{

        return ( USART_RxHead != USART_RxTail ); /* Return 0 (FALSE) if the receive buffer is empty */

}

ruinned 发表于 2006-12-29 10:25:20

if ( USART_TxHead != USART_TxTail )



        while ( USART_RxHead == USART_RxTail )/* Wait for incomming data */



        return ( USART_RxHead != USART_RxTail ); /* Return 0 (FALSE) if the receive buffer is empty */





这三行提示警告信息

liuhongyu 发表于 2010-5-25 23:25:39

遇到同样的问题 ~~把volatile去掉就好了.....求解ing

xiezheming 发表于 2011-8-15 19:27:15

volatile类型的变量一般不直接参与运算,因为在运算的过程中该变量就已经改变

xuhaikun 发表于 2011-8-20 13:13:46

使用一个临时变量将volatile修饰的变量读出来参与运算。。。

wangzugong 发表于 2014-9-6 17:44:49

xuhaikun 发表于 2011-8-20 13:13
使用一个临时变量将volatile修饰的变量读出来参与运算。。。

好办法!

bli19 发表于 2014-9-7 01:05:39

本帖最后由 bli19 于 2014-9-7 01:20 编辑

UB,就是不符合编译器所遵循的C标准,可能会带来不可预知的结果。应该是C99吧。。
你可以忽略,前提是你知道你自己在做什么。
原作者既然说好用,那自然有他的道理。
----
建议看看此贴,很详细:
http://www.amobbs.com/thread-5497299-1-1.html
页: [1]
查看完整版本: 请教大家一个关于IAR volatile的问题