Skip to content

Commit

Permalink
introduce user interrupt feature
Browse files Browse the repository at this point in the history
Now we can use function user_interrupt_register() to
inject an user interrupt into a task. But it can only
be injected by other task.

Signed-off-by: lizhe <493321524@qq.com>
  • Loading branch information
kaka555 committed Oct 23, 2021
1 parent 85463c4 commit 906ce22
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 8 deletions.
9 changes: 6 additions & 3 deletions include/os_core/schedule/TCB.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
#include <os_error.h>
#include <os_cpu.h>

typedef unsigned int STACK_TYPE;
typedef unsigned int STACK_TYPE;

typedef unsigned int TASK_PRIO_TYPE;
typedef void (*functionptr)(void *para);
typedef void (*user_interrupt_fun)(void);

typedef unsigned int TASK_PRIO_TYPE;
typedef void (*functionptr)(void *para);

#define SYS_ENTER_INTERRUPT() do { CPU_IntDis();++g_interrupt_count;CPU_IntEn();} while (0)
#define SYS_EXIT_INTERRUPT() do { CPU_IntDis();--g_interrupt_count;CPU_IntEn();} while (0)
Expand Down Expand Up @@ -52,6 +54,7 @@ extern volatile int g_interrupt_count;
struct dynamic_module;
typedef struct task_struct {
STACK_TYPE *stack; /*the stack top of the task*/
user_interrupt_fun fun;
unsigned int stack_size; /*bytes*/
STACK_TYPE *stack_end; /*the stack tail of the task*/
TASK_PRIO_TYPE reserve_prio; /*used for Priority inversion problem*/
Expand Down
8 changes: 8 additions & 0 deletions include/os_core/schedule/user_interrupt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _USER_INTERRUPT_H
#define _USER_INTERRUPT_H

#include <TCB.h>

void user_interrupt_register(struct task_struct *task_ptr, user_interrupt_fun fun);

#endif
1 change: 1 addition & 0 deletions src/kernel/OS_CORE/schedule/TCB.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ int _must_check _task_init(
return ret;
}
TCB_ptr->ref = 1;
TCB_ptr->fun = NULL;
++g_task_num;
return 0;
}
Expand Down
40 changes: 40 additions & 0 deletions src/kernel/OS_CORE/schedule/user_interrupt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <user_interrupt.h>
#include <os_cpu_stm32.h>
#include <myassert.h>

extern volatile struct task_struct *OSTCBCurPtr;

#define current OSTCBCurPtr
#define SAVED_REGISTER_NUM 15

static void restore_frame(void)
{
/* we put some register in stack to build a stack frame for
user interrupt function, so now we have to restore it*/
current->stack += SAVED_REGISTER_NUM;
OSIntCtxSw();
}

static void default_user_interrupt_handler(void *para)
{
ASSERT(NULL == para, ASSERT_PARA_AFFIRM);
struct task_struct *task_ptr = (struct task_struct *)current;
user_interrupt_fun fun = task_ptr->fun;
fun();
restore_frame();
}

static inline void user_interrupt_set_task_frame(struct task_struct *task_ptr)
{
set_register((void **)&task_ptr->stack, default_user_interrupt_handler, NULL, NULL);
}

void user_interrupt_register(struct task_struct *task_ptr, user_interrupt_fun fun)
{
ASSERT(task_ptr != current, ASSERT_PARA_AFFIRM);
ASSERT(fun != NULL, ASSERT_PARA_AFFIRM);
task_ptr->fun = fun;
user_interrupt_set_task_frame(task_ptr);
return;
}

13 changes: 10 additions & 3 deletions src/kernel/OS_CPU/stm32f103/OS_CPU_A.s
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ OS_CPU_PendSVHandler:
LDR R1, =OSTCBCurPtr /* ; OSTCBCurPtr->OSTCBStkPtr = SP;*/
LDR R1, [R1]
CBZ R1, OS_CPU_PendSVHandler_nosave
LDR R2, [R1, #4] /* get user interrupt fun */
CBNZ R2, OS_CLEAR_USER_INTERRUPT_FUN

SUBS R0, R0, #0x20 /*; Save remaining regs r4-11 on process stack*/
STM R0, {R4-R11}
Expand All @@ -74,10 +76,15 @@ OS_CPU_PendSVHandler_nosave:
LDM R0, {R4-R11}
ADDS R0, R0, #0x20

MSR PSP, R0
ORR LR, LR, #0x04
MSR PSP, R0
ORR LR, LR, #0x04
CPSIE I

BX LR
BX LR

OS_CLEAR_USER_INTERRUPT_FUN:
MOV R2, #0
STR R2, [R1, #4]
B OS_CPU_PendSVHandler_nosave

/*END*/
3 changes: 2 additions & 1 deletion src/kernel/OS_LIB/myassert.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#include <myassert.h>
#include <myMicroLIB.h>
#include <dmesg.h>
#include <printf_debug.h>

void my_abort(void)
{
pr_emerg("os stop\n");
panic("os stop\n");
while (1);
}

Expand Down
2 changes: 1 addition & 1 deletion testcase/makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SRCS = testcase20.c
SRCS = testcase21.c

#ifeq ($(PROJECT),stm32f103)
#SRCS += bsp_led.c
Expand Down
42 changes: 42 additions & 0 deletions testcase/testcase21.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* test user interupt top */
#include <user_interrupt.h>
#include <user.h>
#include <osinit.h>
#include <os_delay.h>
#include <os_cpu.h>
#include <myassert.h>

extern volatile struct task_struct *OSTCBCurPtr;
extern volatile struct task_struct *OSTCBHighRdyPtr;

static struct task_struct *task_three = NULL;

#include <printf_debug.h>

void three(void *para)
{
pr_shell("this is three\n");
task_three = (struct task_struct *)OSTCBCurPtr;
while (1) {
sleep(2 * HZ);
ASSERT(OSTCBCurPtr->fun == para, ASSERT_PARA_AFFIRM);
pr_shell("this is three next\n");
}
}

void my_fun(void)
{
pr_shell("user interrupt from task four\n");
pr_shell("this is task %s\n", OSTCBCurPtr->name);
}

void four(void *para)
{
pr_shell("this is four\n");
if (task_three == NULL) {
pr_shell("user interupt test fail\n");
return;
}
user_interrupt_register(task_three, my_fun);
pr_shell("register_complete\n");
}

0 comments on commit 906ce22

Please sign in to comment.