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

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

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

2,272件の閲覧回数
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.

ラベル(3)
0 件の賞賛
返信
6 返答(返信)

1,620件の閲覧回数
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 件の賞賛
返信

2,095件の閲覧回数
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 件の賞賛
返信

2,095件の閲覧回数
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 件の賞賛
返信

2,095件の閲覧回数
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 件の賞賛
返信

1,568件の閲覧回数
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 件の賞賛
返信

667件の閲覧回数
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 件の賞賛
返信