Menu

find error Q_ERROR_CRIT_(110) in qf_actq.cpp file

June Zhou
2024-08-06
2024-08-12
  • June Zhou

    June Zhou - 2024-08-06

    Hello there,

    Our project use QM 5.1.1 (QP 6.9.0) to develop some applications. QM generates C++ file that will be merged in Keil uvsion5 development platform to run compiling and create firmware to download into our device.

    Last week, our device just changed touch screen and one chip, the software did not update. But when I run the long message receiving ( size larger than 90 bytes) , the device crashed. ( old device have no this problem)

    So, I debugged and found the program reached the line 119 "Q_ERROR_CRIT_(110) **" in function:
    bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin) noexcept
    in qf_actq.cpp file.

    I attached the qf_actq.cpp file. Here, looks our program arrived the margin. But do you know which margin I exceeded? I checked arrays and memory set, should more than 90 bytes.

    We are currently very anxious because hundreds of devices are waiting to be delivered to customers. We needs to find out the reason and solve the problem as soon as possible., so have to ask your help.

    Thank you so much in advance and looking forward to your reply.

     
  • Quantum Leaps

    Quantum Leaps - 2024-08-06

    Hi June,
    The error Q_ERROR_CRIT_(110) while posting an event fires when the event queue gets overflown and the QP framework cannot post an event.

    To troubleshoot this issue, you need to look how this failing QActive::post_() function was called. I'm not sure what you mean by "I run the long message receiving..."

    But I suspect that the change in hardware caused the system to get flooded with interrupts (e.g., you might have a "ringing" interrupt line that interrupts the CPU constantly). This might produce a lot of events that overflow one of your Active Object event queues. So, this might be a hardware issue that needs to be fixed. You might want to hook up an oscilloscope to the interrupt line coming out your new chip into the MCU and see if it is "noisy".

    Alternatively, your new touch screen and a new chip might be fine, but somehow cause production of more events. If these events are disposable (meaning that your system can function correctly even if you lose some of these events), you might want to post the events without asserting that the posting must succeed. You achieve this by specifying the "margin" parameter to QActive::post_(). Please refer to the QActive::post_() documentation.

    --MMS

     

    Last edit: Quantum Leaps 2024-08-06
  • June Zhou

    June Zhou - 2024-08-12

    Thank you so much for your quick and detailed reply. Really appreciate it. Very sorry for the late reply due to illness.

    At the first, I explanate for our long message receiving: Our device has an Iridium modem that can receive some messages from the platform. So far, when our device tries to receive long messages large than 102 bytes, it gives the error: Q_ERROR_CRIT_(110) in function: bool QActive::post(...) in qf_actq.cpp. Message less than 102 bytes, no problem. Message is received char by char.

    I did some tests and find: after our device sent AT+SBDRB to modem to try to read message char by char. Finally, the program enters the following for loop and run QP::QF::PUBLISH(pModem, this). After PUBLISH, program call "case ASP_MODEM_UARTRX_SIG" to run me->at_process_char(iChr) to process the char of the message.

    //Process RX chars
    for (iIndex = 0; iIndex < APP::m_oIridium.m_iRxBufferIndex; iIndex++)
    {
    UartRxEvt *pModem = Q_NEW(UartRxEvt, ASP_MODEM_UARTRX_SIG);
    pModem->m_iChr = APP::m_oIridium.m_iRxBuffer[iIndex];
    **QP::QF::PUBLISH(pModem, this); ** //QP::QF::publish(pModem);
    }

    case ASP_MODEM_UARTRX_SIG: {
    uint8_t iChr = ((UartRxEvt const )e)->m_iChr;
    me->at_process_char(iChr);*
    status_ = Q_RET_HANDLED;
    break;
    }

    If the message larger than 102, for example, APP::m_oIridium.m_iRxBufferIndex=139, the program will go to Q_ERROR_CRIT_(110); after run QP::QF::PUBLISH(pModem, this) at 102 times, at this 102 time, the program cannot enter case ASP_MODEM_UARTRX_SIG but getting Q_ERROR_CRIT_(110)

    So, do you know why the PUBLISH will report the error"Q_ERROR_CRIT_(110)" at 102 times?And the error occurs every time at 102 times. Could you give me some suggestion to fix the issue? Thanks a lot.

    June Zhou

     
  • Quantum Leaps

    Quantum Leaps - 2024-08-12

    Hi June,
    Your design to publish an event that carries only one character at a time is horribly inefficient.

    Imagine that you write a letter, but instead of sending one letter with the whole message, you send hundreds of letters, each containing one character packaged in its own envelope with a postage stamp and address. Sounds ridiculous, doesn't it? Yet, this is precisely what you're doing.

    Your system handled this somehow up to this point, but the design is so horribly expensive that at some point the system simply cannot take it anymore.

    Your situation is very common and, unfortuantaly, many people design their communication like that. So, here is how I recommend to handle such situation:

    1. Declare an event class big enough to hold the worst-case size of your message:
    class IridiumMsgEvt : public QEvt {
        std::uint8_t data[128]; // worst-case payload size
        std::uint8_t len;      // the actual length of the message
    };
    
    1. Assemble whole messages in your ISR:
    void UARTxx_Handler(void) {
        static IridiumMsgEvt *msg = nullptr; // note 'static'
        if (msg == nullptr) {
            msg = Q_NEW(IridiumMsgEvt, ASP_MODEM_UARTRX_SIG);
            msg->len = 0U;
        }
        std::uint8_t byte = UARTxx->DTR; // byte delivered by the UART
        if (byte != '\n') { // not the end of the message?
            if (msg->len < Q_DIM(msg->data)) {
                msg->data[msg->len] = byte; // store the byte
                ++msg->len; // increment the length of the message
            }
            else { // message bigger than worst-case
               // do something about it
            }
        }
        else { // end of the message -- publish it
            QP::QF::PUBLISH(msg, l_UARTxxx);
            msg = nullptr; // <== invalidate the msg!
        }
    }
    
    1. Allocate the big event pool for the IridiumMsgEvts. This pool might have only a few events, for example two (double-buffering):
    ...
    static QF_MPOOL_EL(IridiumMsgEvt) bigPoolSto[2];
    QP::QF::poolInit(bigPoolSto, sizeof(bigPoolSto), sizeof(bigPoolSto[0]));
    ...
    

    Please note that this saves you memory because the small event pool for the previous 1-character events can be much smaller. (You don't need hundreds of such events anymore).

    I hope that my comments make sense to you.

    --MMS

     

    Last edit: Quantum Leaps 2024-08-12

Log in to post a comment.