i.MX 8M Mini - Are clocks synchronized across Cortex A and Cortex M?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.MX 8M Mini - Are clocks synchronized across Cortex A and Cortex M?

2,326 Views
stephen_eng
Contributor III

I have an i.MX 8M Mini EVK, and I'm running Linux on the Cortex A53 and was planning on running FreeRTOS on the Cortex M4. I was curious, if I'm doing stuff on the Cortex A53, like changing the wall-clock time via Linux (think synchronizing its wall clock to a master clock source), does that change propagate to the Cortex M4 running FreeRTOS? 

If not, how would you reliably synchronize the two clocks to run in step with each other?

Thanks.

0 Kudos
Reply
6 Replies

1,674 Views
RoccoBr
Contributor I

hello, I'm in the same situation and I have two questions:

1. the paragraph above mentions the HP_TS bit of the SNSVS_HP Control Register, but I can't find it in the register map. do you mean the RTC_EN bit of the of SNVS_HP Control Register (HPCR)? 

RoccoBr_0-1649249682752.png

2. how can I access the SNVS_HP submodule from Linux? in my device tree I can see the rct-lp as 30370000.snvs:svns-rct-lp, but I can't see the rct-hp module. I do have 30370000.snvs:svns-power-key in my device tree, is is the same as the HP submodule?

0 Kudos
Reply

2,149 Views
Bio_TICFSL
NXP TechSupport
NXP TechSupport

Hello Stephen,

If the clock parent is the same for A53 and M4, then by modifying the clock speed on Linux, will also modify at M4 side, for example, if both domains are fed by SYSTEM_PLL1, by changing the PLL1 speed, changes all the clock tree tied to this source.

 

There are 2 methods to change the clock speed of one domain without changing the other side:

 - Each domain uses a different clock source

 - Change the speed by selecting a different clock divider, instead of modifying the PLL parameters, for example.

 

If not, how would you reliably synchronize the two clocks to run in step with each other?

 

To syncronize the clocks, the application may select the same clock source for both cores, for example in the table below, the ARM_A53_CLK_ROOT may derive from SYSTEM_PLL1_CLK and ARM_M4_CLK_ROOT may derive from SYSTEM_PLL1_DIV3. In this situation, the speed for M4 is 1/3 of A53 and they will be in synchronization.

 

pastedImage_3.png

 

Just pay attention for the maximum frequency speed for each domains.

Regards

0 Kudos
Reply

2,149 Views
stephen_eng
Contributor III

Hi Bio_TICFSL,

Thanks for the pointers. I'll take a look at that a little more, but I either don't quite understand everything you mentioned, or I didn't word my question clearly enough.

If I were to display the date/time from the Cortex A processor (i.e. the 'date' command), I'll get something like April 8, 2020, 1:01:03 pm. If I were to do something similar on the Cortex M processor (which, I don't actually know how to do that... if you happen to know the API function call, I would be immensely appreciative), should I expect to see the same answer? If I change the date/time on the Cortex A processor to something ridiculous, would it automatically affect the Cortex M processor as well?

Configuring the two to use the same clock source would indeed keep them in lock step with one another, and I won't have to worry about drift over time. I just wasn't sure about how the real-time clock works with these two processors.

Kind regards.

0 Kudos
Reply

2,149 Views
Bio_TICFSL
NXP TechSupport
NXP TechSupport

The date and time is stored in SNVS (Secure Non-Volatile Storage) domain, which normally has an uninterrupted power supply, like a coin-cell battery, and its clock is derived from external 32kHz crystal.  So when you type a command 'date' in Linux, the driver reads the data from Secure RTC (Real Time Clock).

 

The date and time is stored at SNVS_LP SRTC register, this is a secure region, so not all peripherals have access to it, a simple method is to "mirror" this register synchronizing it with the HP (High Power) counter of the SNVS, thus, you can read it from M4, as explained below on Reference Manual.

 

pastedImage_1.png

As this is a register, any modification on A53 side, is immediately observed at M4 side. 

 

There is no specific API, you'll have to implement a register read on M4 code. Using the SDK makes this implementation much faster.

Regards

0 Kudos
Reply

1,622 Views
RoccoBr
Contributor I

Hi,

where is defined the HP_TS bit of the SVNS_HP control register? I can't find it in the register map of the reference manual.

thanks

0 Kudos
Reply

721 Views
StephanOostveen
Contributor II

The following worked on the I.MX 8M plus: Setting the 16th bit of the SVNS_HP Control Registers copies the RTC1 clock (SVNS LP), simultaneously setting the 0th bit will then also enable the clock. I use Torizon OS, which by default uses the external rtc as its main rtc. This means that RTC1 will not contain a valid value by default and will thus reset at each power on reset. Sharing the synchronized wall clock between the Cortex A and M cores is done as follows:

First ensure that the system clock is synchronized using ntp or by manually setting it. Then issue the following command to write the system clock to rtc1:

 

sudo hwclock -s -f /dev/rtc1

 

On the Cortex M7 you can use the following c++ code or equivalent c code to read the timestamp:

 

void enable_timer(){
    SNVS->HPCR = (1U << 16U) | (1U << 0U);
}

auto read_time() noexcept
{
    /* According to section 6.4.2.2.1.3 of the i.MX 8M Pluse Applications Processor Reference
       Manual the time resgisters must be read twice and compared. If the value are the same
       the retrieved time was correct, else retry for a maximum of three times after which the value
       should be correct
    */

    auto msb_first = SNVS->HPRTCMR;
    auto lsb_first = SNVS->HPRTCLR;

    auto msb_second = SNVS->HPRTCMR;
    auto lsb_second = SNVS->HPRTCLR;
    int i = 0;
    while (msb_first != msb_second || lsb_first != lsb_second)
    {
        msb_first = SNVS->HPRTCMR;
        lsb_first = SNVS->HPRTCLR;

        msb_second = SNVS->HPRTCMR;
        lsb_second = SNVS->HPRTCLR;
        ++i;
    }
    uint64_t ret = (msb_first << 32 )|(lsb_first);
    ret = ret / 32768; // the clock counts at 32 khz, divide by 32khz to get the "real" unix timestamp in seconds.
    return ret;
}

 

0 Kudos
Reply