How to add and enable external watch crystal to a board to support RTC?

Hi,
I am testing drift RTC over time and get some really big numbers. On Arch_max board that doesn’t install external watch crystal, I get 300+ seconds/per hour drift.
The following is my code to measure the drift. It syncs time with a NTP server, and record time right before and after the sync, also the time taken by NTP request via timer.

    minuteTicker.attach(&mtCallback, 60);
    Timer t;
    t.start();
    NTPClient ntp(network);
    time_t tbSync, taSync;   

    while (1)
    {
        if(minutePassed>= 59)
        {
            tbSync = time(NULL);
            t.reset();
            ntp.setTime("pool.ntp.org");
            taSync = time(NULL);
            printf("%ld: NTP synced, a-b = %ld, NTP took %f seconds\r\n", (long)taSync, (long)taSync - (long)tbSync, t.read());
            minutePassed = 0;
        }
        ThisThread::sleep_for(5000);
    }

On a customized board based on arch_max but with added external watch crystal, I get smaller but still disturbingly large numbers:

1578903084: NTP synced, a-b = 20, NTP took 0.044439 seconds
1578906672: NTP synced, a-b = 47, NTP took 0.080382 seconds
1578910263: NTP synced, a-b = 46, NTP took 0.090190 seconds
1578913856: NTP synced, a-b = 42, NTP took 0.089087 seconds
1578917449: NTP synced, a-b = 50, NTP took 0.105676 seconds
1578921042: NTP synced, a-b = 48, NTP took 0.077139 seconds
1578924636: NTP synced, a-b = 48, NTP took 0.083152 seconds

Change LSE_AVAILABLE in mbed_app.json doesn’t seem to make a difference:

"ARCH_MAX": {
            "target.LSE_AVAILABLE": false,
            "target.stdio_uart_tx": "PC_6",
            "target.stdio_uart_rx": "PC_7"
        }

Meanwhile, on NUCLEO_F401RE board, I get much smaller therefore more acceptable numbers:

1578903771: NTP re-synced, a-b = 1, took 0.284276
1578907330: NTP re-synced, a-b = 1, took 0.144254
1578910890: NTP re-synced, a-b = 4, took 4.068612
1578914454: NTP re-synced, a-b = 0, took 0.183230
1578918015: NTP re-synced, a-b = 1, took 0.128623
1578921577: NTP re-synced, a-b = 0, took 0.093269
1578925138: NTP re-synced, a-b = 1, took 0.134251
1578928701: NTP re-synced, a-b = 0, took 0.112265

Can anyone point a direction to how to increase the RTC accuracy of arch_max based boards? Thanks,

Hello Zhiyong,
In the “mbed-os/targets/tartgets.json” file the “lse_available” is set to 1 (Yes) for the “FAMILY_STM32” targets :

"FAMILY_STM32": {
    "inherits": ["Target"],
    ...
    "config": {
        "lse_available": {
            "help": "Define if a Low Speed External xtal (LSE) is available on the board (0 = No, 1 = Yes). If Yes, the LSE will be used to clock the RTC, LPUART, ... otherwise the Low Speed Internal clock (LSI) will be used",
            "value": "1"
        },

But because the ARCH MAX target is not equipped with an external 32 768Hz crystal the “lse_available” is overridden with 0 (No):

"ARCH_MAX": {
    "inherits": ["FAMILY_STM32"],
    ...
    "overrides": {
        "lse_available": 0,
        "network-default-interface-type": "ETHERNET"
    }
}

When in a “custom_targets.json” file you define your own custom target based on the ARCH_MAX but equipped with an external 32 768 Hz crystal then in the “overrides” section omit “lse_available”: 0,

For example:

"ARCH_MAX_WITH_LSE": {
    "inherits": ["FAMILY_STM32"],
    "supported_form_factors": ["ARDUINO"],
    "core": "Cortex-M4F",
    "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"],
    "program_cycle_s": 2,
    "components_add": ["SD", "FLASHIAP"],
    "extra_labels_add": [
        "STM32F4",
        "STM32F407",
        "STM32F407xx",
        "STM32F407xE",
        "STM32F407VE"
    ],
    "device_has_add": ["ANALOGOUT", "TRNG", "FLASH", "EMAC", "MPU"],
    "device_has_remove": [
        "LPTICKER",
        "SERIAL_FC"
    ],
    "macros_add": ["USB_STM_HAL"],
    "config": {
        "clock_source": {
            "help": "Mask value : USE_PLL_HSE_EXTC | USE_PLL_HSE_XTAL | USE_PLL_HSI | USE_PLL_MSI",
            "value": "USE_PLL_HSE_XTAL",
            "macro_name": "CLOCK_SOURCE"
        }
    },
    "release_versions": ["2", "5"],
    "device_name": "STM32F407VETx",
    "bootloader_supported": true,
    "overrides": {
        "network-default-interface-type": "ETHERNET"
    }
}

Thanks for the explanation. Later on we figured out that we need to use lower case for lse_available in target override. Something like the following:

"ARCH_MAX": {
            "target.lse_available": true,
            "target.stdio_uart_tx": "PC_6",
            "target.stdio_uart_rx": "PC_7"
        }