win32 timeSetEvent usage record (win32 porting ucos ii)

When using the ucos porting code provided on the Internet on win32, it often appears that it either cannot be started or will fake death within 0-5 hours (the threads of ucos ii are waiting and the task scheduling stops), and there will be no error in the middle. Let's take a look at the principle of Porting ucos on win32 first;

Porting ucos ii to win32 depends on a timeSetEvent multimedia timer (which seems to have the highest accuracy) and a task scheduling thread. First, initialize a timeSetEvent timer, an OSTickEventHandle event and an OSTickW32 win32 thread. These three groups form the timer interrupt in the MCU (tick clock), that is, task scheduling. The accuracy of the multimedia timer is 1ms (the actual task scheduling is scheduled once in 2ms, and windows scheduling once in 1ms is a little difficult. After all, it is not a real-time operating system). The multimedia timer 2ms sets the OSTickEventHandle event to be valid, and then OSTickW32 waits for the event to be valid. Skip the wait and start executing OSTickISR(), That is, task scheduling;

DWORD WINAPI OSTickW32( LPVOID lpParameter )
{
    OS_INIT_CRITICAL();

    while(!OSTerminateTickW32)
    {
        OSTickISR();
        
#ifdef WIN_MM_TICK
        
        if( WaitForSingleObject(OSTickEventHandle, 5000) == WAIT_TIMEOUT)
        {
            #ifdef OS_CPU_TRACE
                OS_Printf("Error: MM OSTick Timeout!\n");
            #endif
        }

        ResetEvent(OSTickEventHandle);
#else
        Sleep(1000/OS_TICKS_PER_SEC);
#endif
    }

    return 0;
}

During the simulation, when ucos stopped, I found that the OSTickEventHandle thread would never be valid again. At this time, I suspected that it was a timer problem and began to check the timer initialization code, as follows:

OSTickTimer       = timeSetEvent((1000/OS_TICKS_PER_SEC),OSTimeCap.wPeriodMin,(LPTIMECALLBACK)OSTickEventHandle, dwID,TIME_PERIODIC/|TIME_CALLBACK_EVENT_SET);

Top OS_TICKS_PER_SEC defines 500, that is, the timing period is 2ms, and then the timer cycle executes to set the event OSTickEventHandle to valid;

Since the timer directly sets the event as valid, I can't know whether it is executing periodically. Therefore, I specially wrote a callback function and modified the initialization code, as follows:

void OSTickTimerHandle_Callback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
    if (OSIntNesting == 0)  //
    {
        SetEvent(OSTickEventHandle);

    }
}

OSTickTimer       = timeSetEvent((1000/OS_TICKS_PER_SEC),OSTimeCap.wPeriodMin,/*(LPTIMECALLBACK)OSTickEventHandle*/(LPTIMECALLBACK)OSTickTimerHandle_Callback, dwID,TIME_PERIODIC/*|TIME_CALLBACK_EVENT_SET*/);

The test shows that the callback function can be executed normally and periodically. If OSIntNesting is not 0, it means that the interrupt has been closed. At this time, it can no longer be scheduled. During the test, the program will no longer be scheduled for a few minutes to hours, and at this time vs will directly report an error, but the program can continue. The error position is in the callback function, At first, it was thought that something was wrong with the event. Later, when the callback function was cleared, it still reported an error: there was an unhandled exception at 0x00000000: 0xC0000005: Access violation

Finally, I began to suspect that it was the problem of timeSetEvent. Since I hadn't used it before, I began to search for timeSetEvent on the Internet for learning, and finally found it on the Internet. The CALLBACK function of timeSetEvent must be decorated with {CALLBACK}, otherwise an error will occur. If the error is 100% immediate, the problem can be found on the spot, The trouble is that it will run for a few minutes to a few hours and then make mistakes, which is a bit of a pit father. The modified code is as follows. You only need to modify the CALLBACK function and add the {CALLBACK modifier;

//Note that the CALLBACK part must not be lost in the function, otherwise the program will crash. There is an unhandled exception at 0x00000000: 0xC0000005: Access violation
void CALLBACK OSTickTimerHandle_Callback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
    if (OSIntNesting == 0)  //
    {
        SetEvent(OSTickEventHandle);

    }
}

So now I suspect that the previous event is the same reason, but I didn't test it again. It takes too much time. I can control whether to start the interrupt and debug if there is a problem. After several days of continuous testing, there is no non scheduling again.

Keywords: WIN32

Added by mikegzarejoyce on Fri, 31 Dec 2021 04:54:12 +0200