一个volatile的bug

2019-07-20 23:16发布

问题描述:
定义一个 queue struct,里面的成员是volatile的,因为这些成员可能在中断和主程序中都被访问.发现如果queue struct的变量定义在另一个文件里面,
访问的时候不论是通过指针还是直接用struct的名字去访问,都会导致eof,sof,length值出现异常.
但是如果queue struct的变量定义在和queue代码一个文件内,就不会有问题.

源代码如下
typedef struct byte_queue
{
        volatile uint16_t sof;
        volatile uint16_t eof;
        volatile uint16_t length;//当前长度
        volatile uint16_t size;//总大小
        int8u* buff;
}byte_queue_t;

文件a.c
//把byte_queue_test定义在另一个文件中,会导致问题出现
int8u queue_test_buff[512];
byte_queue_t byte_queue_test={0,0,0,256,queue_test_buff};

文件b.c
extern byte_queue_t byte_queue_test;
byte_queue_t *p_q=&test_queue;
int byte_queue_receive(byte_queue_t *queue, int8u* out)//主程序中调用
{
        int count=0;
        __disable_irq();
        if(p_q->length>0)
        {
                *out=p_q->buff[p_q->sof %p_q->size];
                if(p_q->eof!=(uint16_t)(p_q->length+p_q->sof))//检测eof,sof,length的值是否正常
                        __nop();
                p_q->length--;
                p_q->sof++;
                count= 1;
        }
        else
        {
                count= 0;
        }
        __enable_irq();
        return count;
       
}

int byte_queue_put(byte_queue_t *queue, int8u data)//中断内调用
{
        //struct byte_queue volatile *p_q=queue;
        int count=0;
        __disable_irq();
        if(p_q->length<p_q->size)
        {
                p_q->buff[p_q->eof % p_q->size]=data;
                p_q->eof++;
                p_q->length++;
                count= 1;
        }
        else
        {
                count= 0;
        }
        __enable_irq();
        return count;
}

起初以为是volatile的问题,这样看来好像不是,请大神帮忙看看,谢谢.
另外我在网上看到文章,struct内的volatile成员,如果访问的时候是以指针的方式访问struct的,这个指针必须也是volatile的,但是我看到STM32的库函数里面也没有这样做啊
比如
typedef struct
{
  __IO uint32_t MODER;    /*!< GPIO port mode register,               Address offset: 0x00      */
  __IO uint32_t OTYPER;   /*!< GPIO port output type register,        Address offset: 0x04      */
  __IO uint32_t OSPEEDR;  /*!< GPIO port output speed register,       Address offset: 0x08      */
  __IO uint32_t PUPDR;    /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */
  __IO uint32_t IDR;      /*!< GPIO port input data register,         Address offset: 0x10      */
  __IO uint32_t ODR;      /*!< GPIO port output data register,        Address offset: 0x14      */
  __IO uint16_t BSRRL;    /*!< GPIO port bit set/reset low register,  Address offset: 0x18      */
  __IO uint16_t BSRRH;    /*!< GPIO port bit set/reset high register, Address offset: 0x1A      */
  __IO uint32_t LCKR;     /*!< GPIO port configuration lock register, Address offset: 0x1C      */
  __IO uint32_t AFR[2];   /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */
} GPIO_TypeDef;
并不需要把 GPIO_TypeDef申明的变量申明成 __IO 的

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。