[RISCV]为RISC-V移植FreeRTOS系列之四 -- 中断与trap handler

前言

上回说到了我们已经把系统的心跳动起来了,但是这里面还有一个问题,我们都知道timer中断,中断的trap怎么来的呢。
这回就来解决这个事情。


作者:wangyijieonline
链接:https://blog.csdn.net/wangyijieonline/article/details/109726839
来源:CSDN
著作权归作者所有。商业转载请联系作者获得授权,非商业转载必须注明出处。


回顾一下官方Guide:Using FreeRTOS on RISC-V Microcontrollers

要为 RISC-V 内核构建 FreeRTOS,您需要:
1、在项目中包括核心 FreeRTOS 源文件和 FreeRTOS RISC-V 端口层源文件。
2、确保汇编器的包含路径包括描述任何芯片特定实现详细信息的标头文件的路径。
3、定义 FreeRTOSConfig.h 中的常量或链接器变量以指定要用作中断堆栈的内存。
4、在 freeRTOScong.h configMTIME_BASE_ADDRESS定义configMTIMECMP_BASE_ADDRESS和定义。
5、对于汇编#define portasmHANDLE_INTERRUPT,请使用芯片或工具供应商为处理外部中断而提供的功能的名称。
6、安装 FreeRTOS 陷阱处理程序。

再来看一下,FreeRTOS/Source/portable/GCC/RISC-V目录,这里面有几个需要我们定义的portasmHAS_MTIMEportasmHANDLE_INTERRUPT
在这里插入图片描述
在上一篇博文中我们其实已经定义好了portasmHAS_MTIME,表明我们的立场是用mtime作为整个系统的时基,现在只需要定义一个trap,能正常的让我们的中断函数掉进实现注册好的中断里,要注意,这个地方很重要,因为mtime也需要这个中断来服务。

细心的小伙伴应该恍然大悟了,这个我们也已经实现了,就是之前我们裸机的时候用的中断注册和处理函数,具体实现还真的是没办法细说,SOC这玩意就是这样,每个厂家都有自己的想法,都想做自己特有的东西,但是好在我们已经准备好了裸机再来做操作系统,什么?你告诉我你并没有准备好裸机的中断注册和处理函数,那我真的无话可说了。

这里给出一种实现作为参考:

#include <stdio.h>
#include "platform.h"

typedef void (*isr_func)(void);

void default_irq_handler(void)
{
	printf("Default interrupt handler\n");
}


void wdt_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void rtc_period_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void rtc_alarm_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void pit_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void spi1_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void spi2_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void i2c_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void gpio_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void uart1_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void uart2_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void dma_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void bmc_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void swint_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void sdc_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void mac_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void standby_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));
void wakeup_irq_handler(void) __attribute__((weak, alias("default_irq_handler")));

const isr_func irq_handler[] = {
	wdt_irq_handler,
	rtc_period_irq_handler,
	rtc_alarm_irq_handler,
	pit_irq_handler,
	spi1_irq_handler,
	spi2_irq_handler,
	i2c_irq_handler,
	gpio_irq_handler,
	uart1_irq_handler,
	uart2_irq_handler,
	dma_irq_handler,
	bmc_irq_handler,
	swint_irq_handler,
	default_irq_handler,
	default_irq_handler,
	default_irq_handler,
	default_irq_handler,
	default_irq_handler,
	sdc_irq_handler,
	mac_irq_handler,
	default_irq_handler,
	default_irq_handler,
	default_irq_handler,
	default_irq_handler,
	default_irq_handler,
	default_irq_handler,
	standby_irq_handler,
	wakeup_irq_handler,
	default_irq_handler,
	default_irq_handler,
	default_irq_handler,
	default_irq_handler
};

/* At the time of writing, interrupt nesting is not supported, so do not use
the default mext_interrupt() implementation as that enables interrupts.  A
version that does not enable interrupts is provided below.  THIS INTERRUPT
HANDLER IS SPECIFIC TO FREERTOS WHICH USES PLIC! */
void mext_interrupt(void)
{
	unsigned int irq_source = __nds__plic_claim_interrupt();

	/* Do interrupt handler */
	irq_handler[irq_source]();

	__nds__plic_complete_interrupt(irq_source);
}
void trap_handler(unsigned long mcause, SAVED_CONTEXT *context)
{
#ifdef __riscv_32e
	/* Syscall num is passed in t0 (x5) for RV32E. */
	long which = context->x5;
#else
	long which = context->x17;
#endif

	/* Do your trap handling */
	if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) {
		/* Machine-level interrupt from PLIC */
		mext_interrupt();
	} else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)) {
		/* Machine timer interrupt */
		mtime_handler();
	} else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT)) {
		/* Machine SWI interrupt */
		mswi_handler();
   		/* Machine SWI is connected to PLIC_SW source 1 */
		__nds__plic_sw_complete_interrupt(1);
	} else if (!(mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == TRAP_M_ECALL)) {
		/* Machine Syscal call */
		syscall_handler(which, context->x10, context->x11, context->x12, context->x13);
		context->mepc += 4;
	}else {
		/* Unhandled Trap */
		context->mepc = except_handler(mcause, context->mepc, context->caller_regs);
	}
}

其中trap_handler的入口是在start.S里面。

总结

其实在写这一篇的时候我比较纠结,每个厂家的实现细节都不一样,很难来说中断注册或者中断处理函数怎么来描述,这个还是要靠广大读者来自己啃下这块硬骨头,我当时也是在这个地方卡了一两天,但是总的来说,只要这个搞通了,基本就没啥大问题了。

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
### 回答1: rt-thread是一个轻量级的实时操作系统,并且它可以被移植到不同的处理器架构上,包括RISC-V。移植rt-thread到RISC-V处理器需要进行一些步骤。 首先,需要根据RISC-V处理器的体系结构和指令集特性,进行rt-thread的适配和修改。这可能涉及到整理处理器的文件和寄存器初始化的代码,以匹配RISC-V的特性。 其次,需要编写RISC-V处理器对应的启动代码,这些代码的目的是初始化处理器并设置一些必需的环境变量,例如堆栈指针和中断向量表。 接下来,需要实现RISC-V处理器的硬件抽象层(HAL),包括时钟管理、中断管理、内存管理和设备驱动等。这些代码将负责处理处理器底层的硬件操作和通信。 然后,根据目标RISC-V处理器的内存映射和外设配置,进行rt-thread的内核配置和编译。这包括选择所需的组件、功能和驱动器,并进行相应的配置。 最后,在RISC-V处理器上运行rt-thread,并进行测试和调试。这可能包括验证系统的稳定性、性能和功能。如果有必要,还可以进行性能优化和问题修复。 通过以上步骤,就可以成功地将rt-thread移植RISC-V处理器上,并实现在该处理器上运行实时操作系统的功能。这样可以为RISC-V处理器提供更多的应用和开发选择。 ### 回答2: rt-thread是一个开源的实时操作系统,支持多种硬件平台。而RISC-V是一种基于开源指令集架构的处理器架构。要将rt-thread移植RISC-V平台,需要进行以下步骤: 1. 首先,需要了解RISC-V处理器的初步知识,包括其指令集、寄存器、内存架构等等。这样才能更好地理解RISC-V的工作方式和特性。 2. 接下来,需要根据RISC-V处理器的特点,对rt-thread进行修改和适配。这包括对内核的调度器、中断处理、任务管理等进行适配,以使其能够在RISC-V平台上正常工作。 3. 在适配过程中,需要根据RISC-V的指令集架构,对rt-thread的汇编代码进行修改。这涉及到对寄存器、堆栈、内存访问等方面的调整,以确保rt-thread能够在RISC-V上正确运行。 4. 还需要根据RISC-V平台的硬件特性,对rt-thread的设备驱动进行适配。这包括对串口、GPIO、定时器等外设的驱动程序进行修改,以使其能够与RISC-V平台上的硬件相匹配。 5. 最后,进行一系列的测试和验证,确保rt-thread在RISC-V平台上的正常运行。这包括对实时性、稳定性、性能等方面进行测试,以验证移植的正确性和可靠性。 综上所述,rt-thread移植RISC-V平台需要对rt-thread进行修改和适配,同时还需要对汇编代码和设备驱动程序进行调整。最终需要进行测试和验证,以确保rt-thread在RISC-V平台上的正常工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山猫Show

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值