Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
Debug
中断
Rt-thread一种记录中断的思路
发布于 2021-10-26 11:41:38 浏览:1598
订阅该版
[tocm] # Rt-thread一种记录中断的思路 ## 前言 之前在使用Linux做开发时,无论在做验证还是后续debug的过程中,经常需要查看系统中断响应的记录,用以辅助验证、开发或者debug的过程。最近由于业务的需求,需要使用RTT作为开发的对象,在移植了标准版后,系统启动到MSH控制台,发现并没有查看中断相关的命令。于是自行做了list_interrupt命令,用来查询系统中断,可以查询当前系统已经响应过的中断以及中断所响应的次数。具体的过程如下,为大家做相关开发提供参考。以开源工程中thead-smart单板配置为例。 ## 中断响应的过程 要想记录中断,首先需要搞清楚CPU中断响应的过程。无论是ARM系列还是本文为例子的平头哥Risc-V系列CPU,中断响应的过程其实大同小异。首先会定义中断向量表,一般在start.S文件中定义,中断向量表正和他的名字一样,其本质就是一张表格,从代码的角度来看,是一个数组。数组的偏移量为中断号,比如数组的第16个成员,代表是硬件中断号为16的中断,第16个成员的内容,存放的是16号中断对应的Handler函数。也就是说当CPU进入到16号中断时,就会跳入中断向量表对应的16号中断的Handler函数中。thread-smart的中断向量表如下 ```c __Vectors: .long Default_Handler .long Default_Handler .long Default_Handler .long PendSV_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long SysTick_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler /* External interrupts */ .long USART_IRQHandler .long Default_Handler .long TIM0_IRQHandler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .long Default_Handler .size __Vectors,.-__Vectors ``` 可以看到,thead-master的异常向量表中,除了个别异常向量以外,其余异常向量都指向了Default_Handler。这里时开发者针对中断做了处理,无论时什么异常中断进来,都先进入Default_Handler中,在Default_Handler中会对中断再做分类处理,看是正常的中断还是cpu异常或者是高等级的中断,然后再做分派。整个Default_Handler的处理流程比较长,以下截取关键点进行流程分析。 ```c Default_Handler: /* Check for nmi */ addi sp, sp, -8 sw t0, 0x0(sp) sw t1, 0x4(sp) csrr t0, mcause //mcause中记录了本次异常是否为中断,如果是中断,会包含中断号。非中断会记录异常原因 andi t0, t0, 0x3FF //获取中断号记录在t0中 li t1, 24 //thead中将24号中断规定为nmi中断,为高等级中断。 beq t0, t1, .NMI_Handler //如果是nmi中断,跳入nmi中断处理流程。 lw t0, 0x0(sp) lw t1, 0x4(sp) addi sp, sp, 8 j trap //跳入trap流程 ``` ```c trap: /* Check for interrupt */ j . addi sp, sp, -4 sw t0, 0x0(sp) csrr t0, mcause //判断本次异常原因标志,若为中断,则该值是中断号 blt t0, x0, .Lirq //判断异常为中断,则跳入Lirq,否则跳入trap_c,标志cpu异常 addi sp, sp, 4 la t0, g_trap_sp addi t0, t0, -132 .... .... .... .... .... ..... csrr a0, mepc sw a0, 124(t0) csrr a0, mstatus sw a0, 128(t0) mv a0, t0 lw t0, -4(sp) mv sp, a0 sw t0, 16(sp) jal trap_c ``` ```c .Lirq: lw t0, 0x0(sp) addi sp, sp, 4 j Default_IRQHandler //跳入Default_IRQHandler处理流程 ``` ```c Default_IRQHandler: ipush #ifdef __riscv_flen csrr t1, mstatus srli t1, t1, 13 andi t1, t1, 0x3 la t3, irq_mstatus_fs_flag sw t1, (t3) li t0, 0x3 bne t1, t0, .F_RegNotSave1 .... .... ..... ..... csrr t1, mcause //再次获取中断号 andi t1, t1, 0x3FF slli t1, t1, 2 la t0, g_irqvector //g_irqvector指向中断向量表。将其地址存放于t0中 add t0, t0, t1 //t1为当前中断相对于中断向量表的偏移,即第几个成员。t0最终为该中断对应的Handler lw t2, (t0) //将中断对应的Handler地址放于t2中 jalr t2 //跳至Handler中 li t0, MSTATUS_PRV1 csrs mstatus, t0 ``` ## 记录中断 由以上对thead-master中断响应的分析,决定在cpu跳入到对应中断前将其记录,这样做流程上面清晰且能确保响应过的中断全部都会被记录。跳入中断Handler的流程在Default_IRQHandler中,具体的代码细节如下: ``` csrr t1, mcause andi t1, t1, 0x3FF slli t1, t1, 2 la t0, g_irqvector add t0, t0, t1 lw t2, (t0) jalr t2 ``` 其中,g_irqvector为指向中断向量表的一个数组。记录中断可借鉴原生代码处理中断向量表的这个方法。定义名为g_vector_list的一个数组,数组的成员偏移即为中断号,比如g_vector_list[16]数组成员代表第16号中断,对应成员的值为中断响应的次数。记录的基本原理为每当一个中断执行完毕对应的Handler返回时,将g_vector_list数组对应的数组成员量加1即可。g_vector_list的定义如下: ```c int (*g_vector_list[255])(void); ``` 记录流程如下: ```c csrr t1, mcause andi t1, t1, 0x3FF slli t1, t1, 2 mv t5, t1 //中断号存在t5中 la t0, g_irqvector add t0, t0, t1 lw t2, (t0) jalr t2 //跳入Handler中 li t0, MSTATUS_PRV1 //Handler执行完毕返回 csrs mstatus, t0 /** 记录中断 **/ la t4, g_vector_list //将g_vector_list的地址存放到t4 lrw t4,t4,t5,0 //获取该中断对应在g_vector_list中成员的值,存放于t4 addi t6,t4,1 //对应的成员内容加1,代表记录本次中断,记录于t6 la t4, g_vector_list srw t6,t4,t5,0 //更新到g_vector_list中,完成记录 ``` 由以上流程,g_vector_list中就能存储各个中断在系统的的响应次数。 ## 添加MSH指令 完成中断的记录流程后,剩下的就是添加MSH指令。选择将MSH指令加入到cmd.c中,与其他的指令放于同一文件中。代码如下: ```c long list_interrupt(void) { int maxlen; int i = 0; const char *item_title = "irq num"; maxlen = RT_NAME_MAX; rt_kprintf("%-*.s active-times name\n", maxlen, item_title);//打印title的格式 中断号/中断对应响应次数/中断名称(未实现) object_split(maxlen); rt_kprintf(" ---------- --------------\n"); for(i=0; i<=255;i++) { //依次打印出系统已响应过的中断 if(g_vector_list[i]) { rt_kprintf("%d %d name\n", i, g_vector_list[i]); rt_kprintf("\n"); } } return 0; } MSH_CMD_EXPORT(list_interrupt, list INTERRUPT in system);//声明为MSH指令 ``` ## 执行结果 本文的执行结果如下图: 图1:MSH指令样式 ![image.png](https://oss-club.rt-thread.org/uploads/20211026/feeef9e11245d49f791a76031f339dae.png) 图2:执行结果样式 ![image.png](https://oss-club.rt-thread.org/uploads/20211026/cc8caadba6b893db33223e024f154c60.png) ## 总结 目前该方法只是一个简单的demo,很多细节还没有实现,包括记录中断的name,响应中断的cpu编号等等。以此抛砖引玉。当前Rt-thread系统已经相对比较完善,但是在debug方面还有很多可以发展的空间,希望各位大神一起努力,完善社区,方便每一个人。
4
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
小鱼儿
小鱼儿
文章
1
回答
0
被采纳
0
关注TA
发私信
相关文章
1
RTTStudio调试时出现Debugger connection lost错误
2
RTT Studio ST-Link 每次Debug调试前都出错,但下载程序正常
3
使用RTT-Thread studio出现无法调试,且程序下载进去毫无反应?
4
rtt-studio debug模式优化
5
stlink下载程序不成功
6
studio中不能进入debug
7
studio Stlink 调试问题
8
同时接多个JLink,下载程序时需选择2次
9
studio的debug,有现场表达式吗?
10
大神们,rtthread-studio怎么自动刷新DEBUG的变量区的值?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
xiaorui
1
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部