VF50 128IT 1.2B eboot 1.3 problem

Until yesterday we were using VF50 colibri modules 1.2A using our production image with eboot 1.3 and wince 6 without problems.
Now we have got some new VF50 colibri modules 1.2B and we are not able to use our production image because, after flashing, the module does not boot at all and the recovery mode must be used to restore the original bootloader (eboot 1.7).
We have also tried to flash just our wince image (nk.bin) using the eboot 1.7 but the result is the same: the module stuck and it must be recovered.
From the VF50 module revision history it seems that from release 1.2A to 1.2B there is a NAND flash change. Is there any issue concerning the VF50 1.2B NAND flash that can result into the problem we are facing?

According to Colibri VF50 128MB IT V1.2B PCN :

4.2. Software
− WinCE: The new NAND flash device reports a different product ID and device name. The Toradex
WinCE BSP checks the product ID and therefore requires a BSP update. The following BSP
version provides support for the new flash. Customers are required to update their BSPs
accordingly.
- WinCE: BSP V1.5

So you have to update eBoot and WinCE image at least to 1.5 version, though we highly recommend to use latest 1.7 release.

What a bad news! We have to build and validate a new production image :cry:

If your app doesn’t require a custom WinCE image you can

  • Flash Toradex WinCE image 1.7
  • install your app
  • Do all registry and filesystems mods
  • Backup everything using the UpdateTool included in 1.7 image.

Then you can use created backup for factorey programming. Please note that you must use the save version of UpdateTool you created backup image. Ie you can do direct update from 1.5 to 1.7 but don’t run an Update tool included in 1.5 image. Use an UpdateTool from 1.7 image instead.

After several hours testing and debugging, here is an issues brief list

Our application

  • Pit #7 interrupt stops working after a call to the system function ‘SetLocalTime’

Toradex WinCE image 1.5

  • Update Tool 7.3.0 (2.0) generates an empty registry backup file
  • RegEdit does not allow to delete registry keys: error “Can’t query key ‘…’”

Toradex WinCE image 1.7

  • Ethernet ports do not work
  • RegEdit does not allow to delete registry keys: error “Can’t query key ‘…’”

Could you please specify WInCE version you are using and exact repro steps?

We are using WinCE 6.0

PIT #7 interrupt stops working after a call to the system function SetLocalTime

On WinCE 6.0 with BSP 1.3beta4 the following sample code works fine, while with BSP 1.5 and newer does not.

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

HANDLE hEvent, hEventPIT;
HANDLE hIrqThread;
HANDLE hIntr = NULL;
BOOL threadStatus = 1;
DWORD * pCCM_CCGRn;
DWORD * pPIT_MCR;
DWORD * pPIT_LDVALn;
DWORD * pPIT_CVALn;
DWORD * pPIT_TCTRLn;
DWORD * pPIT_FLAGn;
int g_count = 0;

void PitIrqThread(DWORD *sysirq);

int WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdLine, int cmdShow)
{
    int result = 0;
    HANDLE hMapReg = NULL;
    DWORD sysIrq, sysIrqPIT;
    int nCG = 23;
    int nCCGR = nCG >> 4;
    int nPit = 7;
    SYSTEMTIME sysTime;
    BOOL bResult;

    // Initialize MapReg Library
    hMapReg = Map_Init();
    if (hMapReg == NULL)
    {
        printf("ERROR:: MapReg init function");
        result = -1;
        goto fail_01;
    }
    
    // Map CCM_CCGRn
    // CCM_CCGRn Address: 4006_B000h base + 40h offset + (4 × i)
    pCCM_CCGRn = (DWORD *)Map_OALPAtoVA(0x4006B000 + 0x00000040 + (4 * nCCGR), FALSE);

    // 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");
        result = -1;
        goto fail_02;
    }

    // Create an Event for PIT
    hEventPIT = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (hEventPIT == NULL)
    {
        printf("ERROR:: Create Event for PIT failed number %d\r\n", GetLastError());
        result = -1;
        goto fail_03;
    }
    // Get the system interrupt for the corresponding PIT Irq number
    sysIrqPIT = Int_RequestSysInterrupt(hIntr, IRQ_PIT);
    // Initialize PIT interrupt
    Int_InterruptInitialize(hIntr, sysIrqPIT, hEventPIT, NULL, 0);

    // Create an Event
    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (hEvent == NULL)
    {
        printf("ERROR:: Create Event failed number %d\r\n", GetLastError());
        result = -1;
        goto fail_04;
    }
    // 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 CCM_CCGRn
    printf("CCM_CCGR%d = 0x%08lX \r\n", nCCGR, *pCCM_CCGRn);
    //*pCCM_CCGRn &= ~((DWORD)0x03 << (2 * (nCG & 0x0F)));
    //printf("CCM_CCGR%d = 0x%08lX \r\n", nCCGR, *pCCM_CCGRn);
    //*pCCM_CCGRn |= ((DWORD)0x03 << (2 * (nCG & 0x0F)));
    //printf("CCM_CCGR%d = 0x%08lX \r\n", nCCGR, *pCCM_CCGRn);

    // 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;

    // Get current time
    GetLocalTime(&sysTime);

    printf("GetLocalTime(), Time: %02d:%02d%:%02d.%03d  Date: %02d/%02d/%04d\r\n",
        sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds,
        sysTime.wDay, sysTime.wMonth, sysTime.wYear);

    printf("Enter key to set time\r\n");
    getchar();

    // Change something
    sysTime.wMilliseconds = 0;
    sysTime.wSecond = 0;
    // Set current time
    bResult = SetLocalTime(&sysTime);

    printf("SetLocalTime() = %s, Time: %02d:%02d%:%02d.%03d  Date: %02d/%02d/%04d\r\n",
        bResult ? "OK" : "FAILED",
        sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds,
        sysTime.wDay, sysTime.wMonth, sysTime.wYear);

    // Get current time
    GetLocalTime(&sysTime);

    printf("GetLocalTime(), Time: %02d:%02d%:%02d.%03d  Date: %02d/%02d/%04d\r\n",
        sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds,
        sysTime.wDay, sysTime.wMonth, sysTime.wYear);

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

    *pPIT_TCTRLn = 0x00000000;  // Disable timer
    Sleep(1000);

    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);
    CloseHandle(hEvent);
fail_04:
    Int_InterruptDisable(hIntr, sysIrqPIT);
    Int_ReleaseSysIntr(hIntr, sysIrqPIT);
    CloseHandle(hEventPIT);
fail_03:
    Int_Deinit(hIntr);
fail_02:
    Int_Deinit(hMapReg);
fail_01:

    Sleep(1000);

    return 0;
}

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

Hi @gscotti,

Could you test to find out at what exact BSP verision the issue starts to happen.
Is it still working with 1.3 final or 1.4?

Dear Germano,

I’m sorry, I can’t do this test but I think you can do it by yourself using the sample source code with your Toradex WinCE images. Just in case, find attached the compiled sample code.

With Kind Regards
Int_Demo.exe (10.5 KB)