RISC-V技术论坛
直播中

jf_1137202360

8年用户 1371经验值
擅长:嵌入式技术
私信 关注

【兆易创新GD32VF103R-START开发板试用体验】挑战极限之中断响应时间测量

本帖最后由 jf_1137202360 于 2022-5-13 11:14 编辑

前言


作为单片机,很多时候需要应用在实时性要求很高的场景,中断响应时间也是单片机的一项重要性能参数。
很多时候也是选型决定性关键参数,所以本文就实际测一测GD32VF103单片机的中断响应时间到底能到多少。

测试方案
使用PA0作为外部中断输入,上升沿触发中断。对应的是EXti线0

图片1.png 图片2.png


PA1作为输出,默认输出低,进入中断回调函数时拉高。测量PA0的上升沿和PA1上升沿就可以间接测得中断的响应时间。由于拉高PA1的代码本来需要时间,所以还需要想办法测试拉高PA1代码的执行时间并减去。

图片3.png

为了尽可能精确,所有代码都使用汇编代码编写,主频配置为108MHz。
如下图:
T3示波器可以直接测出,
T2也可以重复执行PA1拉高代码(重复拉高拉低)来模拟测量。
T1=T3-T2
file:///C:UsersqinyuAppDataLocalTempksohtml15540wps4.png 图片4.png

中断初始化

所有的端口都有外部中断能力,为了使用外部中断线,端口必须配置为输入模式
放在init.c
  1. void _init()
  2. {
  3.         SystemInit();
  4.         //ECLIC init
  5.         eclic_init(ECLIC_NUM_INTERRUPTS);
  6.         eclic_mode_enable();
  7.         //printf("After ECLIC mode enabled, the mtvec value is %x


  8. ", read_csr(mtvec));
  9.         // // It must be NOTED:
  10.         //  //    * In the RISC-V arch, if user mode and PMP supported, then by default if PMP is not configured
  11.         //  //      with valid entries, then user mode cannot access any memory, and cannot execute any instructions.
  12.         //  //    * So if switch to user-mode and still want to continue, then you must configure PMP first
  13.         //pmp_open_all_space();
  14.         //switch_m2u_mode();
  15.       
  16.     /* Before enter into main, add the cycle/instret disable by default to save power,
  17.     only use them when needed to measure the cycle/instret */
  18.         disable_mcycle_minstret();
  19.         /* enable the  clock */
  20.         rcu_periph_clock_enable(RCU_GPIOA);
  21.         /* PA0下降沿输入中断 */
  22.         gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_50MHZ,GPIO_PIN_0);
  23.         GPIO_BC(GPIOA) = GPIO_PIN_1;
  24.         /* PA1推挽高速输出  */
  25.         gpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_1);
  26.     /* enable the global interrupt */
  27.     eclic_global_interrupt_enable();
  28.     eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL3_PRIO1);
  29.     /* enable and set key EXTI interrupt to the lowest priority */
  30.     eclic_irq_enable(EXTI0_IRQn, 1, 1);
  31.     /* connect key EXTI line to key GPIO pin */
  32.     gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_0);
  33.     /* configure key EXTI line */
  34.     exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_RISING);
  35.     exti_interrupt_flag_clear(EXTI_0);
  36. }


T3:中断延迟时间+PA1拉高代码执行时间测量

中断回调函数编写如下,放在start.s
  1. EXTI0_IRQHandler:
  2.         lui     a4,0x40011  # C
  3.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  4.         li      a5,2
  5.         sw      a5,0(a3)    # 0x40010810 - 0
  6.         sw      a5,-2028(a4)# 0x40010814 =  0x40011000 -2028
  7.         lui     a4,0x40010  # C
  8.         li      a5,1
  9.         sw      a5,1044(a4)# 0x40010414 =  0x40010000 +0x414
  10.         ret


按键PA0产生上升沿,进入中断服务函数拉高PA1,测量PA0和PA1两个上升沿之间的时间为T3.
实际测得为406nS。

图片5.png

T2:PA1拉高代码执行时间测量

放在start.s

  1. call _init
  2.         lui     a4,0x40011  # C
  3.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  4.         li      a5,2
  5.         sw      a5,0(a3)    # 0x40010810 - 0
  6.         lui     a4,0x40011  # C
  7.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  8.         li      a5,2
  9.         sw      a5,-2028(a4)# 0x40010814 =  0x40011000 -2028
  10.         lui     a4,0x40011  # C
  11.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  12.         li      a5,2
  13.         sw      a5,0(a3)    # 0x40010810 - 0
  14.         lui     a4,0x40011  # C
  15.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  16.         li      a5,2
  17.         sw      a5,-2028(a4)# 0x40010814 =  0x40011000 -2028
  18.         lui     a4,0x40011  # C
  19.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  20.         li      a5,2
  21.         sw      a5,0(a3)    # 0x40010810 - 0
  22.         lui     a4,0x40011  # C
  23.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  24.         li      a5,2
  25.         sw      a5,-2028(a4)# 0x40010814 =  0x40011000 -2028
  26.         lui     a4,0x40011  # C
  27.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  28.         li      a5,2
  29.         sw      a5,0(a3)    # 0x40010810 - 0
  30.         lui     a4,0x40011  # C
  31.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  32.         li      a5,2
  33.         sw      a5,-2028(a4)# 0x40010814 =  0x40011000 -2028
  34.         /* argc = argv = 0 */
  35.         li a0, 0
  36.         li a1, 0
  37.         call main
  38.         tail exit


由于中断回调函数中拉高PA1的代码如下
  1.         lui     a4,0x40011  # C
  2.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  3.         li      a5,2
  4.         sw      a5,0(a3)    # 0x40010810 - 0


执行也需要时间所以需要测量这部分代码的执行时间。
重复执行以下拉高拉低代码使用示波器测量即可得到执行时间。
  1. lui     a4,0x40011  # C
  2.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  3.         li      a5,2
  4.         sw      a5,0(a3)    # 0x40010810 - 0
  5.         lui     a4,0x40011  # C
  6.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  7.         li      a5,2
  8.         sw      a5,-2028(a4)# 0x40010814 =  0x40011000 -2028


图片6.png

时间测得时间为T2=74/2=37nS。

T1:中断响应时间计算
T1=T3-T1=406-37=369nS

直接使用指令最快IO翻转速率测量

放在start.s
  1.         call _init
  2.         lui     a4,0x40011  # C
  3.         addi    a3,a4,-2032 # 0x40010810 =  0x40011000-2032
  4.         li      a5,2
  5.         sw      a5,0(a3)    # 0x40010810 - 0
  6.         sw      a5,-2028(a4)# 0x40010814 =  0x40010810 -2028
  7.         sw      a5,0(a3)    # 0x40010810 - 0
  8.         sw      a5,-2028(a4)# 0x40010814 =  0x40010810 -2028
  9.         sw      a5,0(a3)    # 0x40010810 - 0
  10.         sw      a5,-2028(a4)# 0x40010814 =  0x40010810 -2028
  11.         sw      a5,0(a3)    # 0x40010810 - 0
  12.         sw      a5,-2028(a4)# 0x40010814 =  0x40010810 -2028
  13.         sw      a5,0(a3)    # 0x40010810 - 0
  14.         sw      a5,-2028(a4)# 0x40010814 =  0x40010810 -2028
  15.         sw      a5,0(a3)    # 0x40010810 - 0
  16.         sw      a5,-2028(a4)# 0x40010814 =  0x40010810 -2028
  17.         /* argc = argv = 0 */
  18.         li a0, 0
  19.         li a1, 0
  20.         call main
  21.         tail exit


图片7.png

直接使用指令最快IO翻转速率是26.74MHZ

总结

中断延迟在369nS左右,属于nS级别,108MHz,1个CLK也就是9ns左右,大概40个CLK。
响应时间还是比较短的,在大部分实时性要求情况下应该都是满足需求的。

回帖(2)

dianzi

2022-5-13 11:06:54
感谢分享
举报

北山独狼

2022-5-14 12:54:36
谢谢分享,学习学习
举报

更多回帖

发帖
×
20
完善资料,
赚取积分