Interrupt for EPIT is not working in sleep mode.

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

Interrupt for EPIT is not working in sleep mode.

Jump to solution
5,416 Views
jamesban
Contributor I

I moved the question to this community.

---------------------------------------

Now I am trying to make a timer which is working at sleep mode of iMX6.

BSP version is Linux 3.0.35(imx_3.0.35_4.0.0).

Because already GPT has been used as general timer in the kernel, EPIT has been used for a special timer.

The use case is to wake up the system from sleep mode after several seconds.(for example 100 sec)

I confirmed that the interrupt has worked well at active mode and the timer counter has gone well at sleep mode.

But there has been always a crash in kernel side whenever the interrupt has happened at sleep mode.

The setting is below for the special timer.

val = __raw_readl(MXC_CCM_CCGR1);

val |= (MXC_CCM_CCGRx_CG_MASK << MXC_CCM_CCGRx_CG6_OFFSET);

  __raw_writel(val, MXC_CCM_CCGR1);

hwtimer_base = ioremap(EPIT1_BASE_ADDR, SZ_4K);

  __raw_writel(0x0, hwtimer_base + EPITCR);

  __raw_writel(0xffffffff, hwtimer_base + EPITLR);

  __raw_writel(EPITCR_EN | EPITCR_CLKSRC_REF_LOW | EPITCR_WAITEN | EPITCR_STOPEN ,  hwtimer_base + EPITCR);

  set_irq_flags(MXC_INT_EPIT1, IRQF_VALID);

  val = request_threaded_irq(MXC_INT_EPIT1, NULL, epit_timer_interrupt, IRQF_ONESHOT|IRQF_NO_SUSPEND ,  "EPIT1", (void *)0);

  enable_irq_wake(MXC_INT_EPIT1);

val = __raw_readl(hwtimer_base + EPITCR);

val |= EPITCR_OCIEN;

__raw_writel(val, hwtimer_base + EPITCR);

tcmp = __raw_readl(hwtimer_base + EPITCNR);

  __raw_writel(-3200000, hwtimer_base + EPITCMPR);

Is there anything for me to do more for this use case?

0 Kudos
Reply
1 Solution
3,751 Views
CommunityBot
Community Manager
This an automatic process.

We are marking this post as solved, due to the either low activity or any reply marked as correct.

If you have additional questions, please create a new post and reference to this closed post.

NXP Community!

View solution in original post

0 Kudos
Reply
12 Replies
3,752 Views
CommunityBot
Community Manager
This an automatic process.

We are marking this post as solved, due to the either low activity or any reply marked as correct.

If you have additional questions, please create a new post and reference to this closed post.

NXP Community!
0 Kudos
Reply
3,750 Views
JasonZhao
Contributor V

Hi James,

Can you give me the whole changes (called in which file, which function) or you can give me a patch, I want to test it on our board.

0 Kudos
Reply
3,750 Views
jamesban
Contributor I

Hi Shousheng,

I attached the modified file.

The location of this file is arch\arm\plat-mxc.

In the source, the timer is set as 100 sec because the system goes to sleep within 100 sec after boot.

You might need to control the system to go to sleep within 100 sec or extend the time.

Regards,

James

0 Kudos
Reply
3,750 Views
JasonZhao
Contributor V

Hi James,

I tried you code and it cannot boot,  it stopped after uncompressing kerenel.  I do the test on i.mx6qsabresd.

MMC read: dev # 2, block # 2048, count 16384 ... 16384 blocks read: OK

## Booting kernel from Legacy Image at 10800000 ...

  Image Name:  Linux-3.0.35-2666-gbdde708-g997a

  Image Type:  ARM Linux Kernel Image (uncompressed)

  Data Size:    3866712 Bytes =  3.7 MB

  Load Address: 10008000

  Entry Point:  10008000

  Verifying Checksum ... OK

  Loading Kernel Image ... OK

OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.

(...blocked here, no further log exported...)

For the EPIT clock source changing, you should strictly follow the below sequence.

1. Disable the EPIT - set EN=0 in EPIT_EPITCR.

2. Disable EPIT ouput - program OM=00 in the EPIT_EPITCR.

3. Disable EPIT interrupts.

4. Program CLKSRC to desired clock source in EPIT_EPITCR.

5. Clear the EPIT status register (EPIT_EPITSR), that is, write "1" to clear (w1c).

6. Set ENMOD= 1 in the EPIT_EPITCR, to bring the EPIT Counter to defined state (EPIT_EPITLR value or 0xFFFF_FFFF).

7. Enable EPIT - set (EN=1) in the EPIT_EPITCR

8. Enable the EPIT interrupts.

0 Kudos
Reply
3,750 Views
jamesban
Contributor I

Hi Shousheng,

I am sorry for your inconvenience.

I attached our implementation as a file.

You have to include this file in the Makefile of arch\arm\mach-mx6.

obj-$(CONFIG_MACH_MX6Q_SABRESD) += board-mx6q_sabresd.o mx6q_sabresd_pmic_pfuze100.o dlg.o

And you can call a function in mx6_sabresd_board_init.

void hwtimer_irq(void *data); //dlg add

static void __init mx6_sabresd_board_init(void)

{

....

   imx6_add_armpmu();

  imx6q_add_perfmon(0);

  imx6q_add_perfmon(1);

  imx6q_add_perfmon(2);

  hwtimer_irq(NULL); //dlg add

}

According to the log, we can see below interrupt every 10 sec at active mode.

[HWTIMER] Occurred Interrupt!!!!!!!!!!!!!!!!!

[HWTIMER][mxc_timer_interrupt] #### Restart hwtimer ####

[HWTIMER][hwtimer_start] Function Start

[HWTIMER]EPITCR value = 0x3280003

[HWTIMER]EPITCR value = 0x3280002

[HWTIMER]EPITCR value = 0x3280002

[HWTIMER]EPITCR value = 0x3280002

[HWTIMER][hwtimer_start] Function End

But we can not see any interrupt at sleep mode. It seems linux go to crash or some abnormal state.

We also applied your suggestion when timer  stop and restart. But the result was the same.

Please check it again.

0 Kudos
Reply
3,750 Views
JasonZhao
Contributor V

Hi James,

I tested  the program on L3.0.35 4.1.0, i.mx6qsabresd, and find that it works well. My test step is as following.

1) Run the image

2) Observe that in the active stage, the EPIT interrupt  occurred

3) Put  the system into low power mode by

echo mem > /sys/power/state

it indeed cannot output the info to console, but it can be wakeup by epit interrupt all the time.

4) I guess the interrupt actually occurred, so I add a delayed workqueue into the isr handler to verify it. It proves the interrupt actually occurs.

My code segments:

struct delayed_work zss_dwork;

static void do_zss_dwork(struct work_struct *work)

{

  printk("zss %s:%d called\n",__func__, __LINE__);

}

INIT_DELAYED_WORK(&zss_dwork, do_zss_dwork);                  <-----------hwtimer_irq

schedule_delayed_work(&zss_dwork,msecs_to_jiffies( 5 * 1000)); <---------hwtimer_start()

The printed log:

root@freescale ~$ echo mem > /sys/power/state

PM: Syncing filesystems ... done.

Freezing user space processes ... (elapsed 0.01 seconds) done.

Freezing remaining freezable tasks ... (elapsed 0.01 seconds) done.

Suspending console(s) (use no_console_suspend to debug)

add wake up source irq 101

add wake up source irq 99

add wake up source irq 103

add wake up source irq 51

PM: suspend of devices complete after 25.270 msecs

PM: late suspend of devices complete after 0.629 msecs

Restarting tasks ... done.

                                                                     <---system is waked up by epit interrupt after 5sec

zss do_zss_dwork:143 called                           <----delayed scheduled work print out the interrupt


[HWTIMER] Occurred Interrupt!!!!!!!!!!!!!!!!!             <--------The next interrupt in active mode

[HWTIMER][mxc_timer_interrupt:87] #### Restart hwtimer ####

[HWTIMER][hwtimer_start:152] Function Start

[HWTIMER]EPITCR value = 0x3280003

[HWTIMER]EPITCR value = 0x3280002

[HWTIMER]EPITCR value = 0x3280002

[HWTIMER]EPITCR value = 0x3280002

[HWTIMER][hwtimer_start:196] Function End

zss do_zss_dwork:143 called

0 Kudos
Reply
3,750 Views
jamesban
Contributor I

Hi Shousheng,


Thanks for your testing.

We have tested on L3.0.35 4.0.0 so far.

The difference between you and me is the version of kernel. Maybe some patch in L3.0.35 4.1.0 could impact on this issue.

We will try to port L3.0.35 4.1.0 to our system.

But if you give me some suggestion about which patch of L3.0.35 4.1.0 could impact on this, it would be very helpful to me.

Because the different between two version is quite much and it takes some time to change whole version.

0 Kudos
Reply
3,750 Views
JasonZhao
Contributor V

Hi, James,

BTW, For safety, I added local_irq_save(flags) and local_irq_restore(flags) pair to embrace epit_irq_disable() or epit_irq_enable() for the test.

0 Kudos
Reply
3,750 Views
williamseo
Contributor I

Hi Shousheng,

Where can I get the source with L3.0.35 4.1.0 version ?

and Could you please attach the source you tested ?

Regards,

William

0 Kudos
Reply
3,750 Views
JasonZhao
Contributor V

Hi William,

You can get the sourcecode from out official website. you can search "L3.0.35_4.1.0_ER_SOURCE_BSP" to get it.

0 Kudos
Reply
3,750 Views
igorpadykov
NXP Employee
NXP Employee

Hi James

I think it may be useful to look at RTC wake example

mxc_rtc/rtcwakeup.c in imx-test ltib package.

Best regards

igor

0 Kudos
Reply
3,750 Views
jamesban
Contributor I

Hi Igor,

Thanks for your fast response.

Your suggestion might be a solution.

But I have to implement it in kernel driver. And it could be conflict with RTC alarm application.

According to manual, EPIT have to generate an interrupt properly and system have to wake up properly.

Is not the interrupt of EPIT working originally?

EPIT is best way for me.

0 Kudos
Reply