查看: 3610|回复: 15

[求助] 关于共享变量的冲突问题

[复制链接]
  • TA的每日心情
    慵懒
    2016-11-24 10:19
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    50

    主题

    1028

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2870
    最后登录
    1970-1-1
    发表于 2015-4-14 18:55:08 | 显示全部楼层 |阅读模式
    我最近调试KL串口的时候遇到一个很为难的问题,就是共享变量的访问问题。
    共享变量:uint32_t datanum = 0;
    在中断中会修改该变量,该中断发送的很频繁,大概1ms一次,在中断处理函数中循环递减该变量,n ~ 0。
    而在应用程序中会一直查询该变量,判断该变量是否是0,如下:
    while(1)
    {
        while(datanum)
        {
            ......
        }
    }
    这样操作导致datanum的值出现紊乱,导致while(datanum)中的数据出现错误。有人遇到这样的问题吗
    我知道答案 目前已有15人回答
    回复

    使用道具 举报

    该用户从未签到

    124

    主题

    3600

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    5781
    最后登录
    1970-1-1
    发表于 2015-4-15 10:24:13 | 显示全部楼层
    本帖最后由 FSL_TICS_ZP 于 2015-4-15 10:25 编辑

    这更多的涉及到软件流程设计啊,你可以参考一下uc/OS中的互斥条件概念来避免共享数据可能造成的数据读取差错你可以通过百度了解一下
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2016-11-24 10:19
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    50

    主题

    1028

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2870
    最后登录
    1970-1-1
     楼主| 发表于 2015-4-15 11:02:13 | 显示全部楼层
    FSL_TICS_ZP 发表于 2015-4-15 10:24
    这更多的涉及到软件流程设计啊,你可以参考一下uc/OS中的互斥条件概念来避免共享数据可能造成的数据读取差 ...

    这个我了解过,在任何可能修改该共享变量的地方我都添加了开关中断进行保护。但是读取的地方没有加,KL都是32位的字长,按道理读取不应该出现字节截取一类的问题的啊
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2021-12-15 16:01
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    305

    主题

    4701

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    377
    最后登录
    2023-8-16
    发表于 2015-4-15 16:40:51 | 显示全部楼层
    楼主发一下中断中处理的代码,还有发生异常的时候,datanum的值是多少?
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2016-11-24 10:19
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    50

    主题

    1028

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2870
    最后登录
    1970-1-1
     楼主| 发表于 2015-4-15 17:17:01 | 显示全部楼层
    安 发表于 2015-4-15 16:40
    楼主发一下中断中处理的代码,还有发生异常的时候,datanum的值是多少?

    // ·¢ËÍ»º³åÇø¿ÕÖжÏ
            if(itflag & UART_FLAG_T)
            {
                    if(Uart0Info.TxInfo.DataNum)
                    {
                            LPUART0->DATA = Uart0Info.TxInfo.Buf[Uart0Info.TxInfo.rItem];
                            disable_interrupt(); // disable interrupt
                            Uart0Info.TxInfo.DataNum--;
                            Uart0Info.TxInfo.rItem++;
                            if(Uart0Info.TxInfo.rItem == Uart0Info.TxInfo.BufLen)
                                    Uart0Info.TxInfo.rItem = 0;
                            enable_interrupt(); // enable interrupt
                    }
                    else
                    {
                            LPUART0->CTRL &= ~UART_IT_T;
                            LPUART0->CTRL |= UART_IT_TC;
                            Uart0Info.BaseInfo.b.TxBusy = 0;
                    }
            }
            // ·¢ËÍÍê³ÉÖжÏ
            if(itflag & UART_FLAG_TC)
            {
                    if(Uart0Info.BaseInfo.b.TxBusy == 0)
                    {
                            Uart0Info.BaseInfo.b.TxActive = 0;
                            LPUART0->CTRL &= ~UART_IT_TC;
                            // callback or post event
                            if(Uart0Info.ParsInfo.txCallback)
                                    Uart0Info.ParsInfo.txCallback();
                    }
            }
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2016-11-24 10:19
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    50

    主题

    1028

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2870
    最后登录
    1970-1-1
     楼主| 发表于 2015-4-15 17:18:15 | 显示全部楼层
    安 发表于 2015-4-15 16:40
    楼主发一下中断中处理的代码,还有发生异常的时候,datanum的值是多少?

    123.png
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2016-11-24 10:19
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    50

    主题

    1028

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2870
    最后登录
    1970-1-1
     楼主| 发表于 2015-4-15 17:20:49 | 显示全部楼层
    本帖最后由 cxtarm 于 2015-4-15 18:00 编辑
    安 发表于 2015-4-15 16:40
    楼主发一下中断中处理的代码,还有发生异常的时候,datanum的值是多少?


    发送的时候
    while(len)
            {
                    if(Uart0Info.TxInfo.DataNum < Uart0Info.TxInfo.BufLen)
                    {
                            Uart0Info.TxInfo.Buf[Uart0Info.TxInfo.wItem] = *pdata++;
                            // notice 1: Ò»¶¨Òª×¢Òâ¹²Ïí±äÁ¿µÄ±£»¤£¬·ñÔòÈÝÒ×Ôì³É±äÁ¿±»Òì²½¸ü¸Ä£¬½ø¶øµ¼ÖÂ
                            //           ´®¿Ú·¢ËÍÊý¾Ý´íÂÒÉõÖÁÄÚ´æÒç³ö
                            disable_interrupt(); // disable interrupt
                            Uart0Info.TxInfo.DataNum++;
                            Uart0Info.TxInfo.wItem++;
                            if(Uart0Info.TxInfo.wItem == Uart0Info.TxInfo.BufLen)
                                    Uart0Info.TxInfo.wItem = 0;
                            enable_interrupt(); // enable interrupt
                            if(Uart0Info.BaseInfo.b.TxBusy == 0)// && (Uart0Info.BaseInfo.b.TxActive == 0))
                            {
                                    LPUART0->CTRL |= LPUART_CTRL_TIE_MASK;
                                    Uart0Info.BaseInfo.b.TxBusy = 1;
                                    Uart0Info.BaseInfo.b.TxActive = 1;
                            }
                            len--;
                    }
    }
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2021-12-15 16:01
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    305

    主题

    4701

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    377
    最后登录
    2023-8-16
    发表于 2015-4-15 17:40:31 | 显示全部楼层
    楼主是发送数据,先关闭中断,然后把数据一次性放入到缓冲区,再开中断。
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2016-11-24 10:19
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    50

    主题

    1028

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2870
    最后登录
    1970-1-1
     楼主| 发表于 2015-4-15 18:02:20 | 显示全部楼层
    安 发表于 2015-4-15 17:40
    楼主是发送数据,先关闭中断,然后把数据一次性放入到缓冲区,再开中断。 ...

    不是的,我是只要缓冲区中有数据就会打开中断(见红色部分),发送完成后再关中断,为避免重复打开中断,我用了一个busy标志
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    2021-12-15 16:01
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    305

    主题

    4701

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    377
    最后登录
    2023-8-16
    发表于 2015-4-16 09:00:14 | 显示全部楼层
    我们来分析一下,
    默认是关闭中断的,busy=0,当你需要发送数据的时候,写入一个字节到缓冲区中,busy=0,你去发送数据,这样可能在你下次写入缓冲区的时候,中断已经先发送了上次写入的一个字节。这个时候busy=1;但是Uart0Info.TxInfo.DataNum这个值可能已经减过1了。导致Uart0Info.TxInfo.DataNum=0。
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-9-15 15:54 , Processed in 0.107649 second(s), 30 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表