linux时钟中断周期,关于读取寄存器时间过长导致硬实时Linux中断响应时间极差的问题...

关于读取寄存器时间过长导致硬实时Linux中断响应时间极差的问题

问题描述

在调试硬实时Linux系统时发现,小概率情况下读取寄存器GPMC_IRQSTATUS所花时间非常长,需要180us左右才能读取完毕,导致硬实时Linux的中断响应时间变为极差(系统要求小于5us,其它情况下都满足)。而正常时间是纳秒级的。下面有评估板配置说明,正常与不正常时的示波器波形,以及对应的代码。

评估板配置说明

CPU :AM3358BZCZA100

NAND FLASH: MT29F4G08ABADA

DDR:镁光D9PSH

操作系统:linux-3.2.0

文件系统:UBIFS

出问题的代码

在arch\arm\mach-omap2\gpmc.c文件中。蓝色代码为怀疑出问题的代码。

int gpmc_read_status(int cmd)

{

int    status = -EINVAL;

u32  regval = 0;

extern void my_gpio1_low(void);

extern void my_gpio1_high(void);

extern void my_gpio2_low(void);

extern void my_gpio2_high(void);

extern unsigned long ustimer_get_origin(void);

extern int ustimer_init(void);

extern int omap_get_INTC_THRESHOLD(void);

extern int get_pidx(void);

unsigned long us0,us1;

unsigned long flags;

static int initflag=0;

int  pidx;

#if 0

asm volatile(

"       mrs %0, cpsr    @ arch_local_irq_save\n"

"       cpsid         i"

: "=r" (flags) : : "memory", "cc");

#else

if(!initflag)

{

ustimer_init();

initflag =1;

}

//关中断

asm volatile(

"       cpsid i              @ arch_local_irq_disable"

:

:

: "memory", "cc");

#endif

//my_gpio1_low();

switch (cmd) {

case GPMC_GET_IRQ_STATUS:

us0=ustimer_get_origin();

my_gpio2_high();//置管脚高电平

status = gpmc_read_reg(GPMC_IRQSTATUS);

my_gpio2_low();//置管脚低电平

us1=ustimer_get_origin();

if((us1-us0)*4/3 > 100)

{

asm volatile(

"       mrs  %0, cpsr   @ local_save_flags"

: "=r" (flags) : : "memory", "cc");

pidx=get_pidx();

dump_stack();

printk("[cmd=%x, %d, %d]=%x   %d\r\n", cmd, (us1-us0)*4/3 , omap_get_INTC_THRESHOLD(), flags, pidx);

}

break;

case GPMC_PREFETCH_FIFO_CNT:

regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);

status = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);

break;

case GPMC_PREFETCH_COUNT:

regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);

status = GPMC_PREFETCH_STATUS_COUNT(regval);

break;

case GPMC_STATUS_BUFFER:

regval = gpmc_read_reg(GPMC_STATUS);

/* 1 : buffer is available to write */

status = regval & GPMC_STATUS_BUFF_EMPTY;

break;

default:

printk(KERN_ERR "gpmc_read_status: Not supported\n");

}

{

//my_gpio1_high();

#if 0

asm volatile(

"       msr cpsr_c, %0         @ local_irq_restore"

:

: "r" (flags)

: "memory", "cc");

#else

//开中断

asm volatile(

"       cpsie i                         @ arch_local_irq_enable"

:

:

: "memory", "cc");

#endif

}

return status;

}

正常时的波形

在上面的代码

my_gpio2_high();//置管脚高电平

status = gpmc_read_reg(GPMC_IRQSTATUS);

my_gpio2_low();//置管脚低电平

中, 执行此代码之前已经关闭ARM中断。它们的波形如下(所花时间大概240ns):

b513442cd795ae6b36ad1a0aac6ba9b2.png

异常时的波形

在上面的代码

my_gpio2_high();//置管脚高电平

status = gpmc_read_reg(GPMC_IRQSTATUS);

my_gpio2_low();//置管脚低电平

中, 执行此代码之前已经关闭ARM中断。它们的波形如下(所花时间大概180us):

d977eb206929efa0ab6e21a80ae84d93.png

6.如何重现此问题

当在命令行中不断输入cat /proc/interrupts(或其它命令)并按回车,当重复到一定次数时,会出现读取寄存器GPMC_IRQSTATUS所花时间过长的现象(大概180us)。出问题时的堆栈信息如下:

[ 2721.118652] Backtrace:

[ 2721.121246] [] (dump_backtrace+0x0/0x10c) from [] (dump_stack+0x18/0x1c)

[ 2721.130096]  r6:0000038b r5:00000220 r4:00000000 r3:df3f1d00

[ 2721.136047] [] (dump_stack+0x0/0x1c) from [] (gpmc_read_status+0xe4/0x144)

[ 2721.145080] [] (gpmc_read_status+0x0/0x144) from [] (omap_dev_ready+0x18/0x7c)

[ 2721.154449]  r8:c09711c8 r7:0003b1c1 r6:c06bcd88 r5:df259810 r4:df259810

[ 2721.161499] [] (omap_dev_ready+0x0/0x7c) from [] (nand_wait+0xc0/0x150)

[ 2721.170227]  r4:df259a28 r3:c02a86ec

[ 2721.173980] [] (nand_wait+0x0/0x150) from [] (nand_write_page+0x78/0xc0)

[ 2721.182800]  r8:00006c46 r7:df437000 r6:00000000 r5:df259810 r4:df259a28

[ 2721.189666] r3:c02a2a18

[ 2721.192413] [] (nand_write_page+0x0/0xc0) from [] (nand_do_write_ops+0x1e4/0x3a8)

[ 2721.202056]  r8:00006c46 r7:df259810 r6:df259a28 r5:00000800 r4:00000800

[ 2721.209106] [] (nand_do_write_ops+0x0/0x3a8) from [] (nand_write+0x7c/0xa8)

[ 2721.218200] [] (nand_write+0x0/0xa8) from [] (part_write+0x68/0x90)

[ 2721.226593] [] (part_write+0x0/0x90) from [] (ubi_io_write+0x64/0xc0)

[ 2721.235137]  r7:00003000 r6:00000800 r5:00000000 r4:00000175

[ 2721.241088] [] (ubi_io_write+0x0/0xc0) from [] (ubi_eba_write_leb+0x74/0x68c)

[ 2721.250366]  r8:df2e1000 r7:00000000 r6:df259000 r5:000001a2 r4:00000175

[ 2721.257415] [] (ubi_eba_write_leb+0x0/0x68c) from [] (ubi_leb_write+0xe8/0x104)

[ 2721.266876] [] (ubi_leb_write+0x0/0x104) from [] (ubifs_leb_write+0x40/0xa4)

[ 2721.276092]  r7:000001a2 r6:00002000 r5:df3f6000 r4:df3f6000

[ 2721.282012] [] (ubifs_leb_write+0x0/0xa4) from [] (ubifs_wbuf_sync_nolock+0x74/0x130)

[ 2721.292022]  r7:000006f8 r6:00000800 r5:df3f6000 r4:df3f7d30

[ 2721.297973] [] (ubifs_wbuf_sync_nolock+0x0/0x130) from [] (ubifs_bg_wbufs_sync+0x104/0x154)

[ 2721.308532]  r7:df3f7d30 r6:00000002 r5:00000130 r4:df3f6000

[ 2721.314483] [] (ubifs_bg_wbufs_sync+0x0/0x154) from [] (ubifs_bg_thread+0x9c/0x118)

[ 2721.324310] [] (ubifs_bg_thread+0x0/0x118) from [] (kthread+0x8c/0x94)

[ 2721.332977] [] (kthread+0x0/0x94) from [] (do_exit+0x0/0x65c)

[ 2721.340789]  r6:c004087c r5:c0055f88 r4:df02dd84

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值