After ISSUE #9134 (BSP V1.3beta1) PIT interrupt stop working

Hello,

starting from the BSP V1.3beta1 release the following sample code (based on the Int_Demo library demo) stop working. The PIT timer run and the TIF flag is set but no Event is triggered. Using the BSP V1.2 the same code was running fine. What is wrong or missing?

With Kind Regards

G. Scotti

Sample code:

#include <windows.h>
#include "coproc.h"
#include "MapMem.h"
#include "int.h"
#include "int_vyb.h"

HANDLE hEvent;
HANDLE hIrqThread;
HANDLE hIntr = NULL;
BOOL threadStatus = 1;
DWORD * pPIT_MCR;
DWORD * pPIT_LDVALn;
DWORD * pPIT_CVALn;
DWORD * pPIT_TCTRLn;
DWORD * pPIT_FLAGn;

void PitIrqThread(DWORD *sysirq);

int WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdLine, int cmdShow)
{
	HANDLE hMapReg = NULL;
    DWORD sysIrq;
	int nPit = 7;

    // Initialize MapReg Library
    hMapReg = Map_Init();
    if (hMapReg == NULL)
		printf("ERROR:: MapReg init function");

	// Map PIT registers
	// MCR Address: 4003_7000h
	pPIT_MCR = (DWORD *)Map_OALPAtoVA(0x40037000, FALSE);
	// LOAD Address: 4003_7000h base + 100h offset + (16 × i)
	pPIT_LDVALn	= (DWORD *)Map_OALPAtoVA(0x40037000 + 0x00000100 + (16 * nPit), FALSE);
	// CVAL Address: 4003_7000h base + 104h offset + (16 × i)
	pPIT_CVALn = (DWORD *)Map_OALPAtoVA(0x40037000 + 0x00000104 + (16 * nPit), FALSE);
	// CTRL Address: 4003_7000h base + 108h offset + (16 × i)
	pPIT_TCTRLn = (DWORD *)Map_OALPAtoVA(0x40037000 + 0x00000108 + (16 * nPit), FALSE);
	// FLAG Address: 4003_7000h base + 10Ch offset + (16 × i)
	pPIT_FLAGn = (DWORD *)Map_OALPAtoVA(0x40037000 + 0x0000010C + (16 * nPit), FALSE);

    // Initialize interrupt Library
    hIntr = Int_Init();
    if (hIntr == NULL)
        printf("ERROR:: interrupt init function");

    // Create an Event
    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (hEvent == NULL)
    {
        printf("ERROR:: Create Event failed number %d\r\n", GetLastError());
        return -1;
    }
    // Get the system interrupt for the corresponding Irq number
    sysIrq = Int_RequestSysInterrupt(hIntr, TIMER_IRQ(nPit));
    // Initialize interrupt
    Int_InterruptInitialize(hIntr, sysIrq, hEvent, NULL, 0);

    // Create thread to handle Interrupt event
    hIrqThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PitIrqThread, &sysIrq, 0, NULL);

    // Initialize PIT timer
	// *pPIT_MCR = 0x00000006;
	*pPIT_TCTRLn = 0x00000000; // Disable timer
	*pPIT_LDVALn = 0x007FFFFF; // Load timer value
	*pPIT_FLAGn = 0x00000001; // Clear TIF flag
	*pPIT_TCTRLn = 0x00000002; // Set TIE
	*pPIT_TCTRLn |= 0x00000001; // Set TEN
	*pPIT_MCR = 0x00000000;

    printf("Enter key to Exit Irq test\r\n");
    getchar();

	*pPIT_TCTRLn = 0x00000000;	// Disable timer

    threadStatus = 0;
    SetEvent(hEvent);
    Sleep(1000);

    // It is very important to deinitalise the interrupt, otherwise it will not work the next time you start the program
    Int_InterruptDisable(hIntr, sysIrq);
    Int_ReleaseSysIntr(hIntr, sysIrq);
    Int_Deinit(hIntr);
    Int_Deinit(hMapReg);

    Sleep(1000);

    return TRUE;
}

void PitIrqThread(DWORD *sysirq)
{
    int count = 1;
    DWORD lpdwExitCode;
    while (threadStatus)
    {
        if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, INFINITE))
        {
            printf("IRQ Trigger number of %d \r\n", count++);
			*pPIT_FLAGn = 0x00000001; // Clear TIF flag
            Int_InterruptDone(hIntr, *sysirq);
        }
    }
    printf("Close Thread \r\n");
    if (hIrqThread != NULL)
    {
        GetExitCodeThread(hIrqThread, &lpdwExitCode);
        // Exit Thread
        ExitThread(lpdwExitCode);
        hIrqThread = NULL;
    }
}

In the latest releases of the BSP we are no longer using PIT for the system scheduler.
This means that it’s no longer enabled on system startup.
If you want to use it you’ve to enable the corresponding enable bits in the CCM registers (CCM_CCGR1[CG23]).

As I wrote, the PIT timer is running (PIT_CVALn is counting) and the TIF flag is set (PIT_TFLGn, bit 0 = 1 := Timeout has occurred) but no Event is generated, so I guess that the CCM Clock Gating Register (CCM_CCGRn) is already “well” configured.
Anyhow I will give a try to your suggestion.

With Kind Regards

G. Scotti

Hi,

I looked into this and I see you only enable interrupt retuned with IRQ_PIT. When PIT was used for system timer we enabled PIT interrupt in the kernel now you have to enable it in your application.

You can add this lines to your code and it will work.

hEvent1 = CreateEvent(NULL, FALSE, FALSE, NULL);
sysIrq1 = Int_RequestSysInterrupt(hIntr, 71);
Int_InterruptInitialize(hIntr, sysIrq1, hEvent1, NULL, 0);

I have checked the CCM_CCGR1 register. After the boot, its value is 0x0CC0C300 (CG23 = 3) so the PIT clock is already on, as I supposed. The PIT interrupt issue should be somewhere else. Any suggestion?

With Kind Regards

G. Scotti

Now it works!

Thanks

Sorry, I took the wrong assumption. Luka’s answer is correct. As you said PIT is enabled, but the main PIT interrupt wasn’t.