How to enable timer Interrupt in iMX8MQ EVK

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

How to enable timer Interrupt in iMX8MQ EVK

3,912 Views
yali_zhang
Contributor II

Hi,

I am trying to writing a bare metal OS in iMX8MQ EVK.

The OS is loaded by uboot to DDR @address: 0x60900000. The OS is running in EL2 of AArch64.

  • The GIC is working if i enabled interrupt of UART or watch dog.
  • And I can get the system counter work according the example of Linux kernel  in file drivers/clocksource/timer-imx-sysctr.c.

The is the system counter return value when boot my OS.

     System counter return 6b497049
     CNTID: 0 , CNTSR: 256 , CNTCV 1799998267 

But i can't get any interrupt from GIC.

System Counter Address:

static void *sys_ctr_rd_base = 0x306a0000;
static void *sys_ctr_cmp_base = 0x306b0000;

This is my code

int enable_timer(void)
{
uint64_t current_time;
uint32_t rd;
uint32_t i = 0;

//
// Configure the interrupt controller
//
rd = initGIC();

//
// Configure and enable the System Counter
//
printf("configure and enable the sytem couner \n");
setSystemCounterBaseAddr(0x306c0000); // Address of the System Counter
initSystemCounter(SYSTEM_COUNTER_CNTCR_nHDBG,
SYSTEM_COUNTER_CNTCR_FREQ0,
SYSTEM_COUNTER_CNTCR_nSCALE);
for (i = 10; i<50; i++) {
setIntPriority(i, rd, 0);
 setIntGroup(i, rd, 2);
 SetSPIRoute(i, 0, gicdirouter_ModeAny); // Route INTID to (this core)
 ConfigureSPI(i, gicdicfgr_Level); // Set INTID  as level-sensitive
 enableInt(i, rd);
 }

printf("Configure non-secure physical timer\n");
// Configure the Non-secure Physical Timer
// This uses the TVAL/timer to fire the timer in X ticks
~ current_time = getPhysicalCount();
~ setNSEL2PhysicalCompValue(current_time + 100000);
+ //setNSEL2PhysicalTimerValue(2000);
+ setNSEL2PhysicalTimerCtrl(CNTP_CTL_ENABLE);

}

uint32_t initGIC(void)
{
uint32_t rd;

printf("setGIC addr\n");
// Set location of GIC
setGICAddr((void*)0x38800000, (void*)0x38880000);


printf("Enable GIC\n");
// Set location of GIC
// Enable GIC
enableGIC();

printf("Get the ID of the Redistributor connected to this PE\n");
// Get the ID of the Redistributor connected to this PE
rd = getRedistID(getAffinity());

printf("Mark this core as beign active\n");
// Mark this core as beign active
wakeUpRedist(rd);

// Configure the CPU interface
// This assumes that the SRE bits are already set
setPriorityMask(0xFF);
printf("enableGroup0Ints skipped\n");
//enableGroup0Ints();
printf("enableGroup1Ints\n");
enableGroup1Ints();

return rd;
}

+ void sysctr_timer_enable(int enable)
+ {
+ unsigned int val;
+
+ val = mymmio_read_32(sys_ctr_cmp_base + CMPCR);
+ val &= ~SYS_CTR_EN;
+ if (enable)
+ val |= SYS_CTR_EN;
+
+ mymmio_write_32(sys_ctr_cmp_base + CMPCR, val);
+ }
+
+ unsigned long sysctr_read_counter(void)
+ {
+ unsigned int cnt_hi, tmp_hi, cnt_lo;
+
+ cnt_hi = mymmio_read_32(sys_ctr_rd_base + CNTCV_HI);
+ cnt_lo = mymmio_read_32(sys_ctr_rd_base + CNTCV_LO);
+ tmp_hi = mymmio_read_32(sys_ctr_rd_base + CNTCV_HI);
+
+ return ((unsigned long) cnt_hi << 32) | cnt_lo;
+ }

+ int sysctr_set_next_event(unsigned long delta)
+ {
+ unsigned int cmp_hi, cmp_lo;
+ unsigned long next;
+
+ sysctr_timer_enable(false);
+
+ next = sysctr_read_counter();
+
+ next += delta;
+
+ cmp_hi = (next >> 32) & 0x00fffff;
+ cmp_lo = next & 0xffffffff;
+
+ mymmio_write_32(sys_ctr_cmp_base + CMPCV_HI, cmp_hi);
+ mymmio_write_32(sys_ctr_cmp_base + CMPCV_LO, cmp_lo);
+
+ sysctr_timer_enable(true);
+
+ return 0;
+ }

Labels (1)
Tags (1)
0 Kudos
6 Replies

3,588 Views
yali_zhang
Contributor II

For system counter, we found that the interrupt ID should be 79 instead of 47. There are 32 bits shift. The driver code is similar with the Linux kernel driver in drivers/clocksource/timer-imx-sysctr.c

3,588 Views
igorpadykov
NXP Employee
NXP Employee

Hi zhang

one can refer to linux gpt interrupt example, described in sect.2.1.3.3 Timer
Source Code Structure, sect.2.1.2.4 Interrupt Source Code Structure
attached Linux Manual.

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

3,588 Views
yali_zhang
Contributor II

Hi, Ignorpadykov

Thanks. I will try to review the code of GPT in the Linux kernel.

BTW, according to the i.MX_Referenc_Manul, The i.MX 8M used the 
System Counter instead of GP. And I tried to programming the GPT by myself, it doesn't work. 

The following tables describes the different timers used.

Timer Description
General Purpose Timer (GPT) GPT is configured to generate a periodic interrupt at a certain
interval (every 10 ms). Used by i.MX 6 to go into WFI mode.
Used by i.MX 6 and i.MX 7.
Enhanced Periodic Interrupt Timer (EPIT) Available on i.MX 6 and i.MX 7.
Arm Arch Timer i.MX 8 usage instead of GPT
System Counter Timer i.MX 8M and i.MX 8X usage instead of GP

This is the code from the Linux kernel. There is no iMX8MQ support.

572 TIMER_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt);
573 TIMER_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt);
574 TIMER_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt);
575 TIMER_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt);
576 TIMER_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt);
577 TIMER_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt);
578 TIMER_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt);
579 TIMER_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt);
580 TIMER_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt);
581 TIMER_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt);
582 TIMER_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt);
583 TIMER_OF_DECLARE(imx6sll_timer, "fsl,imx6sll-gpt", imx6dl_timer_init_dt);
584 TIMER_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt);
585 TIMER_OF_DECLARE(imx6ul_timer, "fsl,imx6ul-gpt", imx6dl_timer_init_dt);
586 TIMER_OF_DECLARE(mx7d_timer, "fsl,imx7d-gpt", imx6dl_timer_init_dt);
587 #ifdef CONFIG_ARM64
588 subsys_initcall(imx8qxp_timer_init);
589 #endif

0 Kudos

3,588 Views
igorpadykov
NXP Employee
NXP Employee

from source.codeaurora.org/external/imx/linux-imx/tree/arch/arm64/boot/dts/freescale/fsl-imx8mq.dtsi

it is compatible with "mx7d_timer, "fsl,imx7d-gpt"

    gpt1: gpt@302d0000 {
        compatible = "fsl,imx8mq-gpt", "fsl,imx7d-gpt";

fsl-imx8mq.dtsi\freescale\dts\boot\arm64\arch - linux-imx - i.MX Linux kernel 

Best regards
igor

0 Kudos

3,587 Views
yali_zhang
Contributor II

The GPT driver doesn't work in my side. I could read the timer count, but there is no interrupt from GIC.

I don't know what is missing.

0 Kudos

3,588 Views
igorpadykov
NXP Employee
NXP Employee

nxp has special service for helping with porting custom software

Commercial Support and Engineering Services | NXP 

Best regards
igor

0 Kudos