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?
已解决! 转到解答。
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
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.
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.
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
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.
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.