[单片机芯片] CH32L103免表中断和SysTick应用

[复制链接]
4348|9
 楼主| L-MCU 发表于 2024-6-28 17:21 | 显示全部楼层 |阅读模式
本帖最后由 L-MCU 于 2024-6-28 17:21 编辑

1、VTF与SysTick介绍
CH32L103内置可编程快速中断控制器(PFIC–Programmable Fast Interrupt Controller),特有免表VTF(Vector Table Free)中断响应机制,4路可编程直达中断向量地址。关于免表中断,可不经过中断向量表的查表过程,直达中断函数入口。关于免表中断的具体介绍,可看QingKeV4微处理器手册。
CH32L103内核自带了一个64位加减计数器(SysTick),支持HCLK或者HCLK/8作为时基,具有较高优先级,校准后可用于时间基准。

2、VTF与SysTick应用
开启免表中断(VTF)后,可以缩短中断延迟时间。关于中断延迟(响应)时间,即从中断触发条件产生到中断函数执行的时间。通过SysTick中断可以验证开启VTF后会缩短中断延迟时间。
CH32L103的SysTick进入中断的条件为:当计数寄存器的值与比较寄存器的值相同时,触发中断。测试程序配置SysTick计数模式为向上计数,选择HCLK作为时基,当计数器值与比较寄存器值相同时,会触发中断,此时SysTick计数器会重新从0开始计数,在中断第一时间读取计数器的值。通过对开启VTF和不开启VTF计数器值的比较,当开启VTF后计数器值变小,说明中断延迟时间被缩短。
具体测试程序如下:
  1. /********************************** (C) COPYRIGHT *******************************
  2. * File Name          : main.c
  3. * Author             : WCH
  4. * Version            : V1.0.0
  5. * Date               : 2023/07/08
  6. * Description        : Main program body.
  7. *********************************************************************************
  8. * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
  9. * Attention: This software (modified or not) and binary are used for
  10. * microcontroller manufactured by Nanjing Qinheng Microelectronics.
  11. *******************************************************************************/

  12. /*
  13. *@Note
  14. *VTF IRQ interrupt routine:
  15. *This example is used to demonstrate VTF IRQ
  16. */
  17. #include "debug.h"

  18. /* Global define */


  19. /* Global Variable */
  20. uint32_t time=0;

  21. void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

  22. /*********************************************************************
  23. * @fn      Systick_Init
  24. *
  25. * [url=home.php?mod=space&uid=247401]@brief[/url]   Initializes Systick.
  26. *
  27. * [url=home.php?mod=space&uid=266161]@return[/url]  none
  28. */
  29. void SYSTICK_Init_Config(u64 ticks)
  30. {
  31.     SysTick->SR = 0;
  32.     SysTick->CNT = 0;
  33.     SysTick->CMP = ticks;
  34.     SysTick->CTLR =0x0F;

  35.     NVIC_SetPriority(SysTicK_IRQn, 0);
  36.     NVIC_EnableIRQ(SysTicK_IRQn);
  37.     SetVTFIRQ((u32)SysTick_Handler,SysTicK_IRQn,0,ENABLE);
  38. }

  39. /*********************************************************************
  40. * @fn      main
  41. *
  42. * [url=home.php?mod=space&uid=247401]@brief[/url]   Main program.
  43. *
  44. * [url=home.php?mod=space&uid=266161]@return[/url]  none
  45. */
  46. int main(void)
  47. {
  48.     SystemCoreClockUpdate();
  49.     USART_Printf_Init(115200);
  50.     printf("SystemClk:%d\r\n",SystemCoreClock);
  51.     printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
  52.     printf("Interrupt VTF Test\r\n");

  53.     SYSTICK_Init_Config(SystemCoreClock-1);

  54.     while(1)
  55.     {
  56.     }
  57. }

  58. /*********************************************************************
  59. * @fn      SysTick_Handler
  60. *
  61. * @brief   This function handles SysTick exception.
  62. *
  63. * @return  none
  64. */
  65. void SysTick_Handler(void)
  66. {
  67.     printf("CNT:%d\r\n",(u32)SysTick->CNT);
  68.     SysTick->CTLR=0;
  69.     SysTick->SR=0;
  70. }
关于SysTick的配置,程序中:
(1)首先对系统计数状态寄存器(STK_SR)以及系统计数寄存器(STK_CNT)置0,清除对应标志位,以及将计数器值置0,从0开始向上计数。
(2)其次对系统计数比较寄存器寄存器(STK_CMP)进行赋值,此处赋值为SystemCoreClock-1,SystemCoreClock的大小为96M,则需要计数96M次,即96000000次。
(3)最后对系统计数控制寄存器(STK_CTLR)进行配置并进行中断使能以及开启免表中断。系统计数控制寄存器(STK_CTLR)赋值为0x0F,即配置启动系统计数器STK,使能计数器中断,选择HCLK做时基,向上计数到比较值后重新从0开始计数。
关于SysTick时基,可选择HCLK或HCLK/8作为时基。以测试例程为例,选择HCLK作为时基,HCLK大小一般为系统主频大小,具体看配置,此处为系统主频大小96MHz,则SysTick计数一次的时间为1/96MHz。比较寄存器值设置为96M-1,从0开始计数,则计数96M次。因此进一次SysTick中断的时间为1s进一次中断。
关于系统计数控制寄存器(STK_CTLR),具体如下:
7862667e5d3b78fb6.png
根据例程:
当不开启免表中断时,进入中断后,打印计数器的值为22,如下图
93193667e5d508f184.png
当开启免表中断时,进入中断后,打印计数器的值为20,如下图  
40959667e5d60170c6.png
由结果可知,开启免表中断后,中断延迟时间还是缩短一些的。

3、软件中断
通过配置系统计数控制寄存器(STK_CTLR)的位31置1,可以配置触发软件中断,如下图
83457667e5d8ed01c7.png
关于软件中断的触发以及对应标志位的清除函数如下:
  1. /*********************************************************************
  2. * @fn      main
  3. *
  4. * @brief   Main program.
  5. *
  6. * @return  none
  7. */
  8. int main(void)
  9. {
  10.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  11.     SystemCoreClockUpdate();
  12.     Delay_Init();
  13.     USART_Printf_Init(115200);
  14.     printf("SystemClk:%d\r\n", SystemCoreClock);
  15.     printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
  16.     printf("This is printf example\r\n");

  17.     NVIC_EnableIRQ(Software_IRQn);

  18.     while(1)
  19.     {
  20.         SysTick->CTLR |= (1<<31);
  21.         Delay_Ms(1000);
  22.     }
  23. }

  24. void SW_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  25. void SW_Handler(void)
  26. {
  27.     SysTick->CTLR &= ~(1<<31);
  28.     printf("Enter INT\r\n");

  29. }
程序中,首先使能开启软件中断,然后在while循环中每隔1s将位31置1进入软件中断,软件中断中将该位清0。

附件为测试所用例程,有需要可以下载看一下。


CH32L103 SysTick和软件中断.zip

1.32 MB, 下载次数: 2

tpgf 发表于 2024-7-1 12:13 | 显示全部楼层
在什么情况下需要开启免表中断呢
heimaojingzhang 发表于 2024-7-1 12:51 | 显示全部楼层
请问楼主能不能详细的解释一下什么叫做免表中断呢
keaibukelian 发表于 2024-7-1 13:32 | 显示全部楼层
为什么要关闭软件的中断使能呢
wakayi 发表于 2024-7-1 14:12 | 显示全部楼层
免表中断响应机制是无需查看中断表吗

评论

是的,不经过查表过程,直达中断函数入口  发表于 2024-7-1 16:23
 楼主| L-MCU 发表于 2024-7-1 16:22 | 显示全部楼层
tpgf 发表于 2024-7-1 12:13
在什么情况下需要开启免表中断呢

免表中断可以直达中断函数入口,当你对中断延迟响应时间有要求可以开启
 楼主| L-MCU 发表于 2024-7-1 16:23 | 显示全部楼层
heimaojingzhang 发表于 2024-7-1 12:51
请问楼主能不能详细的解释一下什么叫做免表中断呢

可以看青稞手册的介绍
renzheshengui 发表于 2024-7-1 21:50 | 显示全部楼层
中断延迟时间的时长 可以配置吗
paotangsan 发表于 2024-7-1 22:21 | 显示全部楼层
系统时钟最长可以多长时间进入一次中断啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

39

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部