【问题标题】:Not Equals Operator not working when interrupts are enabled on PIC32 [closed]在 PIC32 上启用中断时,不等于运算符不工作 [关闭]
【发布时间】:2018-04-04 05:16:50
【问题描述】:

我目前正在尝试通过 UART 接收中断协议解析从 PIC32MZ2048EFG100 微控制器上的 GPS 模块通过 UART 接收的字符串。我正在为我的 IDE 和编译器使用 MPLAB X IDE v4.10 和 XC32 v2.05。

当我启用 UART4 接收中断时,!= 运算符停止正常运行。我的 main 函数中有一段代码永远不应该被执行,但它确实是。

我已将其范围缩小到启用中断是问题所在。如果我在 ISR 中注释掉所有工作代码,我仍然会面临 myCounter 被递增的问题。

这是我的 main 函数中的代码。

int myCounter = 0;

void main ( void ){

    hal_sys_init();
    hal_uart4_init();
    gps_init();

    //Setup interrupt
    asm volatile("di"); //Disable all interrupts
    asm volatile("ehb"); //Disable all interrupts

    INTCON = 0; //Clear interrupt control register

    IEC0 = 0;
    IEC1 = 0;
    IEC2 = 0;
    IEC3 = 0;
    IEC4 = 0;
    IEC5 = 0;
    IEC6 = 0;

    INTCONbits.MVEC = 1; //Enable multi-vectored interrupts

    IFS5bits.U4RXIF = 0; //Clear interrupt flag
    IPC42bits.U4RXIP = 1; //Set priority level to 7
    IPC42bits.U4RXIS = 0; //Set sub-priority to 0
    IEC5bits.U4RXIE = 1; //Enable interrupt

    asm volatile("ei"); //Enable all interrupts

    while(1){
        int x = 0;
        if(x != 0){
            myCounter++;  //Should never be executed
        }
    }
}

在启用中断的情况下在我的 PIC 上运行此代码时,myCounter 会递增。

这是我的中断服务程序的代码。

void __ISR(_UART4_RX_VECTOR, ipl7SRS) UART4_Interrupt(void) {
    while (U4STAbits.URXDA) {
        char c = U4RXREG;
        if (c == '\n') {
            currentLine[--lineIndex] = 0; //Overwrite /r as null terminator for string
            parseStringFlag = 1;
            lineIndex = 0;

            if (currentLine == buff_1) {
                currentLine = buff_2;
                previousLine = buff_1;
            } else {
                currentLine = buff_1;
                previousLine = buff_2;
            }

        } else if (lineIndex < MAX_LINE_LENGTH) {
            currentLine[lineIndex++] = c;
        } else {
            currentLine[--lineIndex] = c;
        }
    }
    IFS5bits.U4RXIF = 0; //Clear interrupt flag
    return;
}

这是仍然使 myCounter 递增的基本 ISR 代码。

void __ISR(_UART4_RX_VECTOR, ipl7SRS) UART4_Interrupt(void) {
    while (U4STAbits.URXDA) {
        char c = U4RXREG;
    }
    IFS5bits.U4RXIF = 0; //Clear interrupt flag
    return;
}

什么可能导致不应该执行的代码执行?如果我在禁用中断的情况下在 main 中运行中断代码,则代码可以工作,并且永远不应该执行的代码不会被执行。

【问题讨论】:

  • main 中的代码看起来确实不应该增加 x。恐怕你正在看一些邪恶的东西,stackoverflow,野指针,UB,......祝你好运(无意讽刺)。
  • 您可能希望将您的代码报价升级为minimal reproducible example。我缺少lineIndexcurrentLine 的声明和定义;没有这个currentLine[--lineIndex] = 0; 看起来很可疑。
  • 请在您方便的时候拨打tour
  • 看起来很可疑,因为损坏的lineIndex 低于 0,这可能会向 x currentLine[--lineIndex] = c; 写入除 0 以外的其他内容。
  • @Yunnosch :不需要像这样“损坏” - 如果收到的第一个字符是 \n,它将从零开始递减。

标签: c embedded uart mplab pic32


【解决方案1】:

这里:

    if (c == '\n') {
        currentLine[--lineIndex] = 0; //Overwrite /r as null terminator for string

如果接收到的第一个字符是\n 并且lineIndex 初始化为零,则lineIndex 将从零开始递减。假设它是无符号的,那么lineIndex &lt; MAX_LINE_LENGTH 将是假的并且:

    } else {
        currentLine[--lineIndex] = c;
    }

将重复运行,直到 lineIndex 最终递减为 MAX_LINE_LENGTH - 1 - 踩到大量内存 - 这很可能是在这种情况下发生的情况。

建议:

    if( lineIndex != 0 && c == '\n' && ) 
    {
        currentLine[--lineIndex] = 0; //Overwrite /r as null terminator for 

或:

    if( c == '\n' ) 
    {
        if( lineIndex != 0 ) 
        {
            lineindex-- ;
        }
        currentLine[lineIndex] = 0; //Overwrite /r as null terminator for 

取决于您需要的语义。发送系统不使用 CR+LF 对作为线路末端,您不应该假设。在递减lineindex 之前,可能应该进一步修改代码以检查前面的字符是否确实是CR。供读者练习。

最后的 else 也是如此:

    } 
    else if( lineIndex != 0 )
    {
        currentLine[--lineIndex] = c;
    }

    } 
    else
    {
        if( lineIndex != 0 ) 
        {
            lineindex-- ;
        }
        currentLine[lineIndex] = c;
    }

后一种保护可能不是必需的,但保护可能有助于清晰和维护 - 它是防御性代码 - 你的电话。

让 ISR 简单地将任何接收到的字符放入环形缓冲区,然后在中断上下文之外处理行输入,这可能是一种更安全、更高效的设计。您可以在收到的每个 \n 上增加一个计数器,并在 \n 未缓冲时减少它,以便接收器知道当前缓冲了多少行以进行处理。

【讨论】:

  • 我更新并添加了一些信息到我的问题中。我当然需要解决您指出的问题,但不幸的是,这不是执行无法访问的代码块的根本原因,因为我可以运行问题中现在发布的更简化的 ISR 并获得相同的结果。跨度>
  • @K.Crow :如果您有必要的调试工具,请在变量 x 上设置数据访问断点以查看正在写入的内容。失败使它静止,将其移出堆栈,看看会发生什么。如果它不再损坏,则为堆栈错误。您还有其他活动中断吗?
  • 我刚才能够解决这个问题。似乎我没有将中断配置为使用影子寄存器集,因此将IPL7SRS 更改为IPL7SOFT 解决了这个问题。似乎是在没有正确配置的情况下尝试使用影子寄存器集导致了问题。
猜你喜欢
  • 1970-01-01
  • 2017-02-23
  • 2021-12-29
  • 1970-01-01
  • 1970-01-01
  • 2017-06-06
  • 2011-08-05
  • 1970-01-01
  • 2012-01-10
相关资源
最近更新 更多