Zynq7000系列FreeRTOS源码分析

一、ARM架构分析
在这里插入图片描述
在ARM有以上寄存器组,此处不再多余分析,介绍的文章比较多,USR和SYS模式公用一组寄存器组,故没有列出,SP位堆栈寄存器,通过这个寄存器我们可以实现不同任务间以及任务与操作系统间的隔离。任务用SYS寄存器组(USR组),操作系统用SVC组,中断用IRQ组,FreeRtos共用了三组以上的。
RTOS跑的任务都属于内核级线程,在SYS下,我们可以看到,RTOS保存数据以及回复数据都是在SYS模式下进行的,操作系统的模式咋SVC下进行,这与M3内核的相似,比如说M3内核的是PSP线程堆栈,而A9则是利用不同模式下堆栈指针不同进行的。看下面代码:

/* Switch to system mode. */
.type vPortRestoreTaskContext, %function
vPortRestoreTaskContext:
	CPS		#SYS_MODE@作用是将模式切换到SYS模式
	portRESTORE_CONTEXT@将堆栈内容恢复此处便用的是堆栈指针

当进入中断后硬件会自动将CPSR模式转换为IRQ模式,而此时我们如果要保存线程数据,必须要进行切换到SYS下相应的堆栈指针。
下面分析IRQ中断,主要完成任务切换等

FreeRTOS_IRQ_Handler:
	/* Return to the interrupted instruction. */
	SUB		lr, lr, #4 //流水线有关 PC_cur = PC_now + 8中断此时命令还没执行故-4

	/* Push the return address and SPSR. */
	PUSH	{lr}
	MRS		lr, SPSR
	PUSH	{lr}

	/* Change to supervisor mode to allow reentry. */
	CPS		#SVC_MODE//因为要进入任务相关的切换,操作系通内核,所以侵入SVC模式,再后面要切换到IRQ模式,因为要根据SPSR恢复CPSR

	/* Push used registers. */
	PUSH	{r0-r4, r12}

	/* Increment nesting count.  r3 holds the address of ulPortInterruptNesting
	for future use.  r1 holds the original ulPortInterruptNesting value for
	future use. */
	LDR		r3, ulPortInterruptNestingConst
	LDR		r1, [r3]
	ADD		r4, r1, #1
	STR		r4, [r3]

	/* Read value from the interrupt acknowledge register, which is stored in r0
	for future parameter and interrupt clearing use. */
	LDR 	r2, ulICCIARConst
	LDR		r2, [r2]
	LDR		r0, [r2]

	/* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for
	future use.  _RB_ Does this ever actually need to be done provided the start
	of the stack is 8-byte aligned? */
	MOV		r2, sp
	AND		r2, r2, #4
	SUB		sp, sp, r2

	/* Call the interrupt handler.  r4 pushed to maintain alignment. */
	PUSH	{r0-r4, lr}
	LDR		r1, vApplicationIRQHandlerConst
	BLX		r1
	POP		{r0-r4, lr}
	ADD		sp, sp, r2

	CPSID	i
	DSB
	ISB

	/* Write the value read from ICCIAR to ICCEOIR. */
	LDR 	r4, ulICCEOIRConst
	LDR		r4, [r4]
	STR		r0, [r4]

	/* Restore the old nesting count. */
	STR		r1, [r3]

	/* A context switch is never performed if the nesting count is not 0. */
	CMP		r1, #0
	BNE		exit_without_switch

	/* Did the interrupt request a context switch?  r1 holds the address of
	ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
	use. */
	LDR		r1, =ulPortYieldRequired
	LDR		r0, [r1]
	CMP		r0, #0
	BNE		switch_before_exit

exit_without_switch:
	/* No context switch.  Restore used registers, LR_irq and SPSR before
	returning. */
	POP		{r0-r4, r12}
	CPS		#IRQ_MODE
	POP		{LR}
	MSR		SPSR_cxsf, LR
	POP		{LR}
	MOVS	PC, LR

switch_before_exit:
	/* A context swtich is to be performed.  Clear the context switch pending
	flag. */
	MOV		r0, #0
	STR		r0, [r1]

	/* Restore used registers, LR-irq and SPSR before saving the context
	to the task stack. */
	POP		{r0-r4, r12}
	CPS		#IRQ_MODE
	POP		{LR}
	MSR		SPSR_cxsf, LR
	POP		{LR}
	portSAVE_CONTEXT

	/* Call the function that selects the new task to execute.
	vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
	instructions, or 8 byte aligned stack allocated data.  LR does not need
	saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
	LDR		R0, vTaskSwitchContextConst
	BLX		R0

	/* Restore the context of, and branch to, the task selected to execute
	next. */
	portRESTORE_CONTEXT

上述代码再最后调用了IRQ代码的vApplicationIRQHandler,执行终端的程序,每次中断都会判段是否需要切换任务,这与M3实现大相径庭,M3的实现是在PENDSv内判断是否需要,这与硬件架构也有关系。如果需要那么变进行切换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值