rel_1.6.0 init

This commit is contained in:
guocheng.kgc 2020-06-18 20:06:52 +08:00 committed by shengdong.dsd
commit 27b3e2883d
19359 changed files with 8093121 additions and 0 deletions

View file

@ -0,0 +1,20 @@
## Contents
## Introduction
**armv5** arch files of armv5
### Features
- armv5 system api
### Directories
```sh
armv5
├─ gcc # System adapter file of armv5 architecture for gcc
├─ armcc # System adapter file of armv5 architecture for armcc
├─ panic # panic adapter file of armv5 architecture
```
### Dependencies
## Reference

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static __inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,165 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#pragma arm
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(base + size);
/*stack need 8 bytes align*/
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
*(--stk) = (uint32_t)entry; /* Entry Point */
*(--stk) = (uint32_t)krhino_task_deathbed; /* LR */
*(--stk) = (uint32_t)0; /* R12 */
*(--stk) = (uint32_t)0; /* R11 */
*(--stk) = (uint32_t)0; /* R10 */
*(--stk) = (uint32_t)0; /* R9 */
*(--stk) = (uint32_t)0; /* R8 */
*(--stk) = (uint32_t)0; /* R7 : */
*(--stk) = (uint32_t)0; /* R6 */
*(--stk) = (uint32_t)0; /* R5 */
*(--stk) = (uint32_t)0; /* R4 */
*(--stk) = (uint32_t)0; /* R3 */
*(--stk) = (uint32_t)0; /* R2 */
*(--stk) = (uint32_t)0; /* R1 */
*(--stk) = (uint32_t)arg; /* R0 argument */
*(--stk) = (uint32_t)0x13; /* CPSR SVC mode */
return stk;
}
void fiq_pre_proc(void)
{
g_intrpt_nested_level[cpu_cur_get()]++;
}
void fiq_end_proc(void)
{
g_intrpt_nested_level[cpu_cur_get()]--;
}
/*-----------------------------------------------------------*/
uint32_t platform_is_in_irq_enable( void )
{
#define ARM968_IF_MASK 0xC0
#define ARM968_IRQ_ENABLE 0x80
uint32_t interrupt;
__asm volatile(
"MRS interrupt,CPSR\n"
"AND interrupt,interrupt,#0xC0\n"
);
return (!(interrupt & ARM968_IRQ_ENABLE));
}
/*-----------------------------------------------------------*/
uint32_t platform_is_in_fiq_enable( void )
{
#define ARM968_IF_MASK 0xC0
#define ARM968_FIQ_ENABLE 0x40
uint32_t interrupt;
__asm volatile(
"MRS interrupt,CPSR\n"
"AND interrupt,interrupt,#0xC0\n"
);
return (!(interrupt & ARM968_FIQ_ENABLE));
}
/*-----------------------------------------------------------*/
uint32_t platform_is_in_irq_context( void )
{
#define ARM968_IRQ_MODE 0x12
uint32_t mode;
__asm volatile(
"MRS mode,CPSR\n"
"AND mode,mode,#0x1f\n"
);
return (ARM968_IRQ_MODE == mode);
}
/*-----------------------------------------------------------*/
uint32_t platform_is_in_fiq_context( void )
{
#define ARM968_FIQ_MODE 0x11
uint32_t mode;
__asm volatile(
"MRS mode,CPSR\n"
"AND mode,mode,#0x1f\n"
);
return (ARM968_FIQ_MODE == mode);
}
uint32_t platform_is_in_interrupt_context( void )
{
return ((platform_is_in_fiq_context())
|| (platform_is_in_irq_context()));
}
/*-----------------------------------------------------------*/
int portDISABLE_FIQ(void)
{
unsigned long temp;
unsigned long mask;
__asm volatile(
"mrs mask, cpsr \n"
"orr temp, mask, #0x40\n"
"msr cpsr_c, temp"
);
return (!!(mask & 0x40));
}
int portDISABLE_IRQ(void)
{
unsigned long temp;
unsigned long mask;
__asm volatile(
"mrs mask, cpsr \n"
"orr temp, mask, #0x80\n"
"msr cpsr_c, temp"
);
return (!!(mask & 0x80));
}
void portENABLE_IRQ(void)
{
unsigned long temp;
__asm volatile(
"mrs temp, cpsr \n"
"bic temp, temp, #0x80\n"
"msr cpsr_c, temp"
);
}
void portENABLE_FIQ(void)
{
unsigned long temp;
__asm volatile(
"mrs temp, cpsr \n"
"bic temp, temp, #0x40\n"
"msr cpsr_c, temp"
);
}

View file

@ -0,0 +1,94 @@
#include <k_config.h>
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
EXTERN g_active_task
EXTERN g_preferred_ready_task
EXTERN krhino_stack_ovf_check
EXTERN krhino_task_sched_stats_get
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
EXPORT cpu_intrpt_save
EXPORT cpu_intrpt_restore
EXPORT cpu_task_switch
EXPORT cpu_intrpt_switch
EXPORT cpu_first_task_start
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
PRESERVE8
CODE32
AREA |.text|, CODE, READONLY
GLOBAL cpu_intrpt_save
cpu_intrpt_save
MRS R0, CPSR ; Set IRQ and FIQ bits in CPSR to disable all interrupts
ORR R1, R0, #0xC0
MSR CPSR_c, R1
MRS R1, CPSR ; Confirm that CPSR contains the proper interrupt disable flags
AND R1, R1, #0xC0
CMP R1, #0xC0
BNE cpu_intrpt_save ; Not properly disabled (try again)
BX LR ; Disabled, return the original CPSR contents in R0
GLOBAL cpu_intrpt_restore
cpu_intrpt_restore
MSR CPSR_c, R0
BX LR
cpu_first_task_start
LDR R0, =g_active_task
LDR R0, [R0]
LDR SP, [R0]
LDMFD SP!, {R0}
LDR R1, [SP, #56]
TST R1, #1
ORRNE R0, #32 ; if PC is thumb mode, set SPSR to thumb
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^
GLOBAL cpu_task_switch
cpu_task_switch
STMFD SP!, {LR}
STMFD SP!, {R0-R12,LR}
MRS R0, CPSR
STMFD SP!, {R0} ; push current cpsr
; g_active_task->task_stack = SP
LDR R0, =g_active_task
LDR R0, [R0]
STR SP, [R0]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
GLOBAL cpu_intrpt_switch
cpu_intrpt_switch
LDR R0, =g_preferred_ready_task
LDR R1, =g_active_task
LDR R0, [R0]
STR R0, [R1]
LDR R0, =g_active_task
LDR R0, [R0]
LDR SP, [R0]
; Restore New Task context
LDMFD SP!, {R0}
LDR R1, [SP, #56]
TST R1, #1
ORRNE R0, #32 ; if PC is thumb mode, set SPSR to thumb
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^
END

View file

@ -0,0 +1,15 @@
NAME := arch_armv5
$(NAME)_MBINS_TYPE := kernel
$(NAME)_VERSION := 1.0.0
$(NAME)_SUMMARY := arch for armv5
GLOBAL_INCLUDES += common
$(NAME)_CFLAGS := -marm -mthumb-interwork
$(NAME)_SOURCES += gcc/port_c.c \
gcc/port_s.S \
common/panic_c.c \
common/panic_gcc.S

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_COMPILER_H
#define K_COMPILER_H
#if defined(__CC_ARM)
#define RHINO_INLINE static __inline
/* get the return address of the current function
unsigned int __return_address(void) */
#define RHINO_GET_RA() (void *)__return_address()
/* get the the value of the stack pointer
unsigned int __current_sp(void) */
#define RHINO_GET_SP() (void *)__current_sp()
#ifndef __WEAK
#define __WEAK __weak
#endif
#elif defined(__ICCARM__)
#define RHINO_INLINE static inline
/* get the return address of the current function
unsigned int __get_LR(void) */
#define RHINO_GET_RA() (void *)__get_LR()
/* get the the value of the stack pointer
unsigned int __get_SP(void) */
#define RHINO_GET_SP() (void *)__get_SP()
#ifndef __WEAK
#define __WEAK __weak
#endif
#elif defined(__GNUC__)
#define RHINO_INLINE static inline
/* get the return address of the current function
void * __builtin_return_address (unsigned int level) */
#define RHINO_GET_RA() __builtin_return_address(0)
/* get the return address of the current function */
__attribute__((always_inline)) RHINO_INLINE void *RHINO_GET_SP(void)
{
void *sp;
asm volatile("mov %0, SP\n" : "=r" (sp));
return sp;
}
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#else
#error "Unsupported compiler"
#endif
#endif /* K_COMPILER_H */

View file

@ -0,0 +1,21 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TYPES_H
#define K_TYPES_H
#include "k_compiler.h"
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t cpu_cpsr_t;
#endif /* K_TYPES_H */

View file

@ -0,0 +1,94 @@
#include "k_config.h"
#include "k_dftdbg_config.h"
;******************************************************************************
; EQUATES
;******************************************************************************
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
AREA |.text|, CODE, READONLY, ALIGN=2
REQUIRE8
PRESERVE8
#if (RHINO_CONFIG_PANIC > 0)
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
EXTERN panicHandler
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
EXPORT _exc_udf_handler
EXPORT _exc_pabt_handler
EXPORT _exc_dabt_handler
;******************************************************************************
; FAULT FUNCTIONS
;******************************************************************************
_exc_udf_handler
PUSH {R0-R3}
MOV R2, #1 ; Exception type
MRS R1, SPSR ; CPSR before exception
SUB R0, LR, #2
TST R1, #0x20 ; CPSR[5], 1 Thumb, 0 ARM
SUBEQ R0, R0, #2 ; PC before exception
PUSH {R4}
MOV R3, SP ; SP_udf
ADD SP, SP, #20
B _exc_handler
_exc_pabt_handler
PUSH {R0-R3}
MOV R2, #2 ; Exception type
MRS R1, SPSR ; CPSR before exception
SUB R0, LR, #4 ; PC before exception
PUSH {R4}
MOV R3, SP ; SP_abt
ADD SP, SP, #20
B _exc_handler
_exc_dabt_handler
PUSH {R0-R3}
MOV R2, #3 ; Exception type
MRS R1, SPSR ; CPSR before exception
SUB R0, LR, #8 ; PC before exception
PUSH {R4}
MOV R3, SP ; SP_abt
ADD SP, SP, #20
B _exc_handler
;input R0 PC; R1 CPSR; R2, exctype; R3 where saved context R0~R3; R4 temp
_exc_handler
AND R4, R1, #0x1F
ORR R4, R4, #0xC0
MSR CPSR_c, R4
LDMFD R3!, {R4}
STMFD R3!, {R0-R2} ; save "PANIC_CONTEXT" on exception stack
MOV R0, SP
STMFD R3!, {R0, LR}
STMFD R3!, {R4-R12}
ADD R0, R3, #56
LDMFD R0, {R5-R8}
STMFD R3!, {R5-R8}
LDR R0, =g_crash_steps
LDR R1, [R0]
ADD R1, #1
STR R1, [R0]
MOV R4, SP
MOV SP, R3
MOV R0, R3
CMP R1, #1
MOVNE R0, #0
BL panicHandler
ALIGN
#endif
END

View file

@ -0,0 +1,542 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "k_dbg_api.h"
#if (RHINO_CONFIG_BACKTRACE > 0)
#if defined(__CC_ARM)
#ifdef __BIG_ENDIAN
#error "Not support big-endian!"
#endif
#elif defined(__ICCARM__)
#if (__LITTLE_ENDIAN__ == 0)
#error "Not support big-endian!"
#endif
#elif defined(__GNUC__)
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#error "Not support big-endian!"
#endif
#endif
#define FUNC_SIZE_LIMIT 0x2000
#define BACK_TRACE_LIMIT 64
#define LR_2_ADDR(lr) ((char *)(((int)(lr)) & 0xfffffffe))
#if defined(__ICCARM__)
static unsigned int __builtin_popcount(unsigned int u)
{
unsigned int ret = 0;
while (u) {
u = (u & (u - 1));
ret++;
}
return ret;
}
#endif
void getPLSfromCtx(void *context, char **PC, char **LR, int **SP)
{
int *ptr = context;
/* reference to cpu_task_stack_init */
*PC = LR_2_ADDR((char *)ptr[15]);
*LR = LR_2_ADDR((char *)ptr[14]);
*SP = ptr + 16;
}
/* get "blx" or "bl" before LR, return offset */
static int backtraceFindLROffset(char *LR,
int (*print_func)(const char *fmt, ...))
{
char *PC;
unsigned short ins16;
char s_panic_call[] = "backtrace : 0x \r\n";
/* compiler specific */
#if defined(__CC_ARM)
PC = (char *)__current_pc();
#elif defined(__ICCARM__)
asm volatile("mov %0, pc\n" : "=r"(PC));
#elif defined(__GNUC__)
__asm__ volatile("mov %0, pc\n" : "=r"(PC));
#endif
/* backtrace bottom check for interrupt */
if (LR != NULL && ((int)LR & 1) == 0 &&
((int)LR & 0x400000) == ((int)PC & 0x400000)) {
if (print_func != NULL) {
print_func("backtrace : ^interrupt^\r\n");
}
return 0;
}
LR = LR_2_ADDR(LR);
if (LR == LR_2_ADDR(&krhino_task_deathbed)) {
/* task delete, so here is callstack bottom of task */
if (print_func != NULL) {
print_func("backtrace : ^task entry^\r\n");
}
return 0;
}
ins16 = *(unsigned short *)(LR - 4);
if ((ins16 & 0xf000) == 0xf000) {
if (print_func != NULL) {
k_int2str((int)LR - 4, &s_panic_call[14]);
print_func(s_panic_call);
}
return 5;
} else {
if (print_func != NULL) {
k_int2str((int)LR - 2, &s_panic_call[14]);
print_func(s_panic_call);
}
return 3;
}
}
/* find current function caller, update PC and SP
returns: 0 success
1 success and find buttom
-1 fail */
int backtraceFromStack(int **pSP, char **pPC,
int (*print_func)(const char *fmt, ...))
{
char *CodeAddr = NULL;
int *SP = *pSP;
char *PC = *pPC;
char *LR;
int i;
unsigned short ins16;
unsigned int ins32;
unsigned int framesize = 0;
unsigned int shift = 0;
unsigned int sub = 0;
unsigned int offset = 1;
if (SP == krhino_task_stack_bottom(NULL)) {
if (print_func != NULL) {
print_func("backtrace : ^task entry^\r\n");
}
return 1;
}
/* func call ways:
1. "stmdb sp!, ..." or "push ..." to open stack frame and save LR
2. "sub sp, ..." or "sub.w sp, ..." to open stack more
3. call
*/
/* 1. scan code, find frame size from "push" or "stmdb sp!" */
for (i = 2; i < FUNC_SIZE_LIMIT; i += 2) {
/* find nearest "push {..., lr}" */
ins16 = *(unsigned short *)(PC - i);
if ((ins16 & 0xff00) == 0xb500) {
framesize = __builtin_popcount((unsigned char)ins16);
framesize++;
/* find double push */
ins16 = *(unsigned short *)(PC - i - 2);
if ((ins16 & 0xff00) == 0xb400) {
offset += __builtin_popcount((unsigned char)ins16);
framesize += __builtin_popcount((unsigned char)ins16);
}
CodeAddr = PC - i;
break;
}
/* find "stmdb sp!, ..." */
/* The Thumb instruction stream is a sequence of halfword-aligned
* halfwords */
ins32 = *(unsigned short *)(PC - i);
ins32 <<= 16;
ins32 |= *(unsigned short *)(PC - i + 2);
if ((ins32 & 0xFFFFF000) == 0xe92d4000) {
framesize = __builtin_popcount(ins32 & 0xfff);
framesize++;
CodeAddr = PC - i;
break;
}
}
if (CodeAddr == NULL) {
/* error branch */
if (print_func != NULL) {
print_func("Backtrace fail!\r\n");
}
return -1;
}
/* 2. scan code, find frame size from "sub" or "sub.w" */
for (i = 0; i < FUNC_SIZE_LIMIT;) {
if (CodeAddr + i > PC) {
break;
}
/* find "sub sp, ..." */
ins16 = *(unsigned short *)(CodeAddr + i);
if ((ins16 & 0xff80) == 0xb080) {
framesize += (ins16 & 0x7f);
break;
}
/* find "sub.w sp, sp, ..." */
ins32 = *(unsigned short *)(CodeAddr + i);
ins32 <<= 16;
ins32 |= *(unsigned short *)(CodeAddr + i + 2);
if ((ins32 & 0xFBFF8F00) == 0xF1AD0D00) {
sub = 128 + (ins32 & 0x7f);
shift = (ins32 >> 7) & 0x1;
shift += ((ins32 >> 12) & 0x7) << 1;
shift += ((ins32 >> 26) & 0x1) << 4;
framesize += sub<<(30 - shift);
break;
}
if ((ins16 & 0xf800) >= 0xe800) {
i += 4;
} else {
i += 2;
}
}
/* 3. output */
*pSP = SP + framesize;
LR = (char *)*(SP + framesize - offset);
offset = backtraceFindLROffset(LR, print_func);
*pPC = LR - offset;
return offset == 0 ? 1 : 0;
}
/* find current function caller, update PC and SP
returns: 0 success
1 success and find buttom
-1 fail */
int backtraceFromLR(int **pSP, char **pPC, char *LR,
int (*print_func)(const char *fmt, ...))
{
int *SP = *pSP;
char *PC = *pPC;
char *CodeAddr = NULL;
int i;
unsigned short ins16;
unsigned int framesize = 0;
unsigned int offset;
if (PC == NULL) {
offset = backtraceFindLROffset(LR, print_func);
PC = LR - offset;
*pPC = PC;
return offset == 0 ? 1 : 0;
}
/*find stack framesize:
1. "push ..." to open stack
2. "sub sp, ..." to open stack
3. 1 + 2
4. do not open stack
*/
/* 1. scan code, find frame size from "push" or "sub" */
for (i = 2; i < FUNC_SIZE_LIMIT; i += 2) {
ins16 = *(unsigned short *)(PC - i);
/* find "push {..., lr}" */
if ((ins16 & 0xff00) == 0xb500) {
/* another function */
break;
}
/* find "push {...}" */
if ((ins16 & 0xff00) == 0xb400) {
framesize = __builtin_popcount((unsigned char)ins16);
CodeAddr = PC - i;
break;
}
/* find "sub sp, ..." */
if ((ins16 & 0xff80) == 0xb080) {
framesize = (ins16 & 0x7f);
CodeAddr = PC - i;
/* find push before sub */
ins16 = *(unsigned short *)(PC - i - 2);
if ((ins16 & 0xff00) == 0xb400) {
framesize += __builtin_popcount((unsigned char)ins16);
CodeAddr = PC - i - 2;
}
break;
}
}
/* 2. check the "push" or "sub sp" belongs to another function */
if (CodeAddr != NULL) {
for (i = 2; i < PC - CodeAddr; i += 2) {
ins16 = *(unsigned short *)(PC - i);
/* find "pop {..., pc}" or "bx lr" */
if ((ins16 & 0xff00) == 0xbd00 || ins16 == 0x4770) {
/* SP no changed */
framesize = 0;
}
}
} /* else: SP no changed */
/* 3. output */
*pSP = SP + framesize;
offset = backtraceFindLROffset(LR, print_func);
*pPC = LR - offset;
return offset == 0 ? 1 : 0;
}
/* printf call stack */
int backtrace_now(int (*print_func)(const char *fmt, ...))
{
char *PC;
int *SP;
int lvl;
int ret;
if (print_func == NULL) {
print_func = printf;
}
/* compiler specific */
#if defined(__CC_ARM)
SP = (int *)__current_sp();
PC = (char *)__current_pc();
#elif defined(__ICCARM__)
asm volatile("mov %0, sp\n" : "=r"(SP));
asm volatile("mov %0, pc\n" : "=r"(PC));
#elif defined(__GNUC__)
__asm__ volatile("mov %0, sp\n" : "=r"(SP));
__asm__ volatile("mov %0, pc\n" : "=r"(PC));
#endif
print_func("========== Call stack ==========\r\n");
for (lvl = 0; lvl < BACK_TRACE_LIMIT; lvl++) {
ret = backtraceFromStack(&SP, &PC, print_func);
if (ret != 0) {
break;
}
}
print_func("========== End ==========\r\n");
return lvl;
}
int backtrace_task(char *taskname, int (*print_func)(const char *fmt, ...))
{
char *PC;
char *LR;
int *SP;
int lvl;
int ret;
ktask_t *task;
if (print_func == NULL) {
print_func = printf;
}
task = krhino_task_find(taskname);
if (task == NULL) {
print_func("Task not found : %s\n", taskname);
return 0;
}
if (krhino_task_is_running(task)) {
print_func("Status of task \"%s\" is 'Running', Can not backtrace!\n",
taskname);
return 0;
}
getPLSfromCtx(task->task_stack, &PC, &LR, &SP);
print_func("TaskName : %s\n", taskname);
print_func("========== Call stack ==========\r\n");
for (lvl = 0; lvl < BACK_TRACE_LIMIT; lvl++) {
ret = backtraceFromStack(&SP, &PC, print_func);
if (ret != 0) {
break;
}
}
print_func("========== End ==========\r\n");
return lvl;
}
#endif
#if (RHINO_CONFIG_PANIC > 0)
#define REG_NAME_WIDTH 7
typedef struct
{
/* saved in assembler */
int R0;
int R1;
int R2;
int R3;
int R4;
int R5;
int R6;
int R7;
int R8;
int R9;
int R10;
int R11;
int R12;
int SP; // Stack Pointer
int LR; // Link Register
int PC; // Program Counter
int CPSR; // Current Program Status Registers
int EXCTYPE; // 1-undefined; 2-prefetch; 3-data
} PANIC_CONTEXT;
void panicGetCtx(void *context, char **pPC, char **pLR, int **pSP)
{
PANIC_CONTEXT *arm_context = (PANIC_CONTEXT *)context;
*pSP = (int *)arm_context->SP;
*pPC = (char *)arm_context->PC;
*pLR = (char *)arm_context->LR;
}
void panicShowRegs(void *context, int (*print_func)(const char *fmt, ...))
{
int x;
int *regs = (int *)context;
char s_panic_regs[REG_NAME_WIDTH + 14];
/* PANIC_CONTEXT */
char s_panic_ctx[] = "R0 "
"R1 "
"R2 "
"R3 "
"R4 "
"R5 "
"R6 "
"R7 "
"R8 "
"R9 "
"R10 "
"R11 "
"R12 "
"SP "
"LR "
"PC "
"CPSR "
"EXCTYPE";
if (regs == NULL) {
return;
}
print_func("========== Regs info ==========\r\n");
/* show PANIC_CONTEXT */
for (x = 0; x < sizeof(s_panic_ctx) / REG_NAME_WIDTH - 1; x++) {
memcpy(&s_panic_regs[0], &s_panic_ctx[x * REG_NAME_WIDTH],
REG_NAME_WIDTH);
memcpy(&s_panic_regs[REG_NAME_WIDTH], " 0x", 3);
k_int2str(regs[x], &s_panic_regs[REG_NAME_WIDTH + 3]);
s_panic_regs[REG_NAME_WIDTH + 11] = '\r';
s_panic_regs[REG_NAME_WIDTH + 12] = '\n';
s_panic_regs[REG_NAME_WIDTH + 13] = 0;
print_func(s_panic_regs);
}
switch (regs[x]) {
case 1:
print_func("ExcCasue: Undefined instruction\r\n");
break;
case 2:
print_func("ExcCasue: Prefetch Abort\r\n");
break;
case 3:
print_func("ExcCasue: Data Abort\r\n");
break;
default:
print_func("ExcCasue: Unknown\r\n");
break;
}
}
#if (RHINO_CONFIG_BACKTRACE > 0)
/* backtrace start with PC and SP, find LR from stack memory
return levels os callstack */
int panicBacktraceCaller(char *PC, int *SP,
int (*print_func)(const char *fmt, ...))
{
int *bt_sp;
char *bt_pc;
int lvl, ret;
char s_panic_call[] = "backtrace : 0x \r\n";
/* caller must save LR in stack, so find LR from stack */
if (SP == NULL) {
return 0;
}
bt_sp = SP;
bt_pc = LR_2_ADDR(PC);
ret = -1;
for (lvl = 0; lvl < BACK_TRACE_LIMIT; lvl++) {
ret = backtraceFromStack(&bt_sp, &bt_pc, NULL);
if (ret != 0) {
break;
}
}
if (ret == 1) {
/* assume right! print */
k_int2str((int)PC, &s_panic_call[14]);
if (print_func != NULL) {
print_func(s_panic_call);
}
bt_sp = SP;
bt_pc = PC;
ret = -1;
for (lvl = 1; lvl < BACK_TRACE_LIMIT; lvl++) {
ret = backtraceFromStack(&bt_sp, &bt_pc, print_func);
if (ret != 0) {
break;
}
}
return lvl;
}
return 0;
}
/* backtrace start with PC SP and LR */
int panicBacktraceCallee(char *PC, int *SP, char *LR,
int (*print_func)(const char *fmt, ...))
{
int *bt_sp;
char *bt_pc;
char *bt_lr;
int lvl, ret;
char s_panic_call[] = "backtrace : 0x \r\n";
if (SP == NULL) {
return 0;
}
/* Backtrace: assume ReturnAddr is saved in LR when exception */
k_int2str((int)PC, &s_panic_call[14]);
if (print_func != NULL) {
print_func(s_panic_call);
}
lvl = 1;
bt_sp = SP;
bt_pc = PC;
bt_lr = LR;
ret = backtraceFromLR(&bt_sp, &bt_pc, bt_lr, print_func);
if (ret == 0) {
for (; lvl < BACK_TRACE_LIMIT; lvl++) {
ret = backtraceFromStack(&bt_sp, &bt_pc, print_func);
if (ret != 0) {
break;
}
}
}
return lvl;
}
#endif
#endif

View file

@ -0,0 +1,99 @@
#include "k_config.h"
#include "k_dftdbg_config.h"
@******************************************************************************
@ EQUATES
@******************************************************************************
@******************************************************************************
@ CODE GENERATION DIRECTIVES
@******************************************************************************
.text
.align 2
.syntax unified
#if (RHINO_CONFIG_PANIC > 0)
@******************************************************************************
@ EXTERN PARAMETERS
@******************************************************************************
.extern panicHandler
@******************************************************************************
@ EXPORT FUNCTIONS
@******************************************************************************
.global __wrap_boot_undefined
.global __wrap_boot_pabort
.global __wrap_boot_dabort
@******************************************************************************
@ FAULT FUNCTIONS
@******************************************************************************
__wrap_boot_undefined:
PUSH {R0-R3}
MOV R2, #1 @ Exception type
MRS R1, SPSR @ CPSR before exception
SUB R0, LR, #2
TST R1, #0x20 @ CPSR[5], 1 Thumb, 0 ARM
SUBEQ R0, R0, #2 @ PC before exception
PUSH {R4}
MOV R3, SP @ SP_udf
ADD SP, SP, #20
B _exc_handler
__wrap_boot_pabort:
PUSH {R0-R3}
MOV R2, #2 @ Exception type
MRS R1, SPSR @ CPSR before exception
SUB R0, LR, #4 @ PC before exception
PUSH {R4}
MOV R3, SP @ SP_abt
ADD SP, SP, #20
B _exc_handler
__wrap_boot_dabort:
PUSH {R0-R3}
MOV R2, #3 @ Exception type
MRS R1, SPSR @ CPSR before exception
SUB R0, LR, #8 @ PC before exception
PUSH {R4}
MOV R3, SP @ SP_abt
ADD SP, SP, #20
B _exc_handler
@input: R0 PC; R1 CPSR; R2, exctype; R3 where saved context R0~R3; R4 temp
_exc_handler:
AND R4, R1, #0x1F
ORR R4, R4, #0xC0
MSR CPSR_c, R4
LDMFD R3!, {R4}
STMFD R3!, {R0-R2} @ save "PANIC_CONTEXT" on exception stack
MOV R0, SP
STMFD R3!, {R0, LR}
STMFD R3!, {R4-R12}
ADD R0, R3, #56
LDMFD R0, {R5-R8}
STMFD R3!, {R5-R8}
LDR R0, =g_crash_steps
LDR R1, [R0]
ADD R1, #1
STR R1, [R0]
MOV R4, SP
MOV SP, R3
MOV R0, R3
CMP R1, #1
MOVNE R0, #0
#if (RHINO_CONFIG_PANIC_PRT_INT > 0)
@printf use interrupt, so here enable it
MRS R1, CPSR @ Set IRQ and FIQ bits in CPSR to disable all interrupts
ORR R1, R1, #0xC0
MSR CPSR_c, R1
#endif
BL panicHandler
#endif
.end

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
cpu_cpsr_t cpu_intrpt_save(void);
void cpu_intrpt_restore(cpu_cpsr_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() cpu_cpsr_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() do{cpsr = cpu_intrpt_save();}while(0)
#define RHINO_CPU_INTRPT_ENABLE() do{cpu_intrpt_restore(cpsr);}while(0)
#endif /* PORT_H */

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,185 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(base + size);
/*stack need 8 bytes align*/
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
*(--stk) = (uint32_t)entry; /* Entry Point */
*(--stk) = (uint32_t)krhino_task_deathbed; /* LR */
*(--stk) = (uint32_t)0; /* R12 */
*(--stk) = (uint32_t)0; /* R11 */
*(--stk) = (uint32_t)0; /* R10 */
*(--stk) = (uint32_t)0; /* R9 */
*(--stk) = (uint32_t)0; /* R8 */
*(--stk) = (uint32_t)0; /* R7 : */
*(--stk) = (uint32_t)0; /* R6 */
*(--stk) = (uint32_t)0; /* R5 */
*(--stk) = (uint32_t)0; /* R4 */
*(--stk) = (uint32_t)0; /* R3 */
*(--stk) = (uint32_t)0; /* R2 */
*(--stk) = (uint32_t)0; /* R1 */
*(--stk) = (uint32_t)arg; /* R0 argument */
*(--stk) = (uint32_t)0x13; /* CPSR SVC mode */
return stk;
}
void fiq_pre_proc(void)
{
g_intrpt_nested_level[cpu_cur_get()]++;
}
void fiq_end_proc(void)
{
g_intrpt_nested_level[cpu_cur_get()]--;
}
/*-----------------------------------------------------------*/
uint32_t platform_is_in_irq_enable( void )
{
#define ARM968_IF_MASK 0xC0
#define ARM968_IRQ_ENABLE 0x80
uint32_t interrupt;
__asm volatile(
"MRS %0,CPSR\n"
"AND %0,%0,#0xC0\n"
: "=r" (interrupt)
:
: "memory"
);
return (!(interrupt & ARM968_IRQ_ENABLE));
}
/*-----------------------------------------------------------*/
uint32_t platform_is_in_fiq_enable( void )
{
#define ARM968_IF_MASK 0xC0
#define ARM968_FIQ_ENABLE 0x40
uint32_t interrupt;
__asm volatile(
"MRS %0,CPSR\n"
"AND %0,%0,#0xC0\n"
: "=r" (interrupt)
:
: "memory"
);
return (!(interrupt & ARM968_FIQ_ENABLE));
}
/*-----------------------------------------------------------*/
uint32_t platform_is_in_irq_context( void )
{
#define ARM968_IRQ_MODE 0x12
uint32_t mode;
__asm volatile(
"MRS %0,CPSR\n"
"AND %0,%0,#0x1f\n"
: "=r" (mode)
:
: "memory"
);
return (ARM968_IRQ_MODE == mode);
}
/*-----------------------------------------------------------*/
uint32_t platform_is_in_fiq_context( void )
{
#define ARM968_FIQ_MODE 0x11
uint32_t mode;
__asm volatile(
"MRS %0,CPSR\n"
"AND %0,%0,#0x1f\n"
: "=r" (mode)
:
: "memory"
);
return (ARM968_FIQ_MODE == mode);
}
uint32_t platform_is_in_interrupt_context( void )
{
return ((platform_is_in_fiq_context())
|| (platform_is_in_irq_context()));
}
/*-----------------------------------------------------------*/
int portDISABLE_FIQ(void)
{
unsigned long temp;
unsigned long mask;
__asm volatile(
"mrs %1, cpsr @ local_irq_disable\n"
"orr %0, %1, #0x40\n"
"msr cpsr_c, %0"
: "=r" (temp), "=r" (mask)
:
: "memory");
return (!!(mask & 0x40));
}
int portDISABLE_IRQ(void)
{
unsigned long temp;
unsigned long mask;
__asm volatile(
"mrs %1, cpsr @ local_irq_disable\n"
"orr %0, %1, #0x80\n"
"msr cpsr_c, %0"
: "=r" (temp), "=r" (mask)
:
: "memory");
return (!!(mask & 0x80));
}
void portENABLE_IRQ(void)
{
unsigned long temp;
__asm volatile(
"mrs %0, cpsr @ local_irq_enable\n"
"bic %0, %0, #0x80\n"
"msr cpsr_c, %0"
: "=r" (temp)
:
: "memory");
}
void portENABLE_FIQ(void)
{
unsigned long temp;
__asm volatile(
"mrs %0, cpsr @ local_irq_enable\n"
"bic %0, %0, #0x40\n"
"msr cpsr_c, %0"
: "=r" (temp)
:
: "memory");
}

View file

@ -0,0 +1,94 @@
#include <k_config.h>
@******************************************************************************
@ EXTERN PARAMETERS
@******************************************************************************
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_stack_ovf_check
.extern krhino_task_sched_stats_get
@******************************************************************************
@ EXPORT FUNCTIONS
@******************************************************************************
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
@******************************************************************************
@ CODE GENERATION DIRECTIVES
@******************************************************************************
.text
.align 2
.type cpu_intrpt_save, %function
cpu_intrpt_save:
MRS R0, CPSR @ Set IRQ and FIQ bits in CPSR to disable all interrupts
ORR R1, R0, #0xC0
MSR CPSR_c, R1
MRS R1, CPSR @ Confirm that CPSR contains the proper interrupt disable flags
AND R1, R1, #0xC0
CMP R1, #0xC0
BNE cpu_intrpt_save @ Not properly disabled (try again)
BX LR @ Disabled, return the original CPSR contents in R0
.type cpu_intrpt_restore, %function
cpu_intrpt_restore:
MSR CPSR_c, R0
BX LR
.type cpu_first_task_start, %function
cpu_first_task_start:
LDR R0, =g_active_task
LDR R0, [R0]
LDR SP, [R0]
LDMFD SP!, {R0}
LDR R1, [SP, #56]
TST R1, #1
ORRNE R0, #32 @ if PC is thumb mode, set SPSR to thumb
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^
.type cpu_task_switch, %function
cpu_task_switch:
STMFD SP!, {LR}
STMFD SP!, {R0-R12,LR}
MRS R0, CPSR
STMFD SP!, {R0} @ push current cpsr
@ g_active_task->task_stack = SP
LDR R0, =g_active_task
LDR R0, [R0]
STR SP, [R0]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
.type cpu_intrpt_switch, %function
cpu_intrpt_switch:
LDR R0, =g_preferred_ready_task
LDR R1, =g_active_task
LDR R0, [R0]
STR R0, [R1]
LDR R0, =g_active_task
LDR R0, [R0]
LDR SP, [R0]
@ Restore New Task context
LDMFD SP!, {R0}
LDR R1, [SP, #56]
TST R1, #1
ORRNE R0, #32 @ if PC is thumb mode, set SPSR to thumb
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^
.end

View file

@ -0,0 +1,16 @@
src = Split('''
gcc/port_c.c
gcc/port_s.S
common/panic_c.c
common/panic_gcc.S
''')
component = aos_component('armv5', src)
component.add_global_includes('common')
local_cflags = Split('''
-marm
-mthumb-interwork
''')
for cflags in local_cflags:
component.add_cflags(cflags)

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static __inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* task context saved & restore by hardware: */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* task context saved & restore by software: */
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,165 @@
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
IMPORT g_active_task
IMPORT g_preferred_ready_task
IMPORT krhino_stack_ovf_check
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
EXPORT cpu_intrpt_save
EXPORT cpu_intrpt_restore
EXPORT cpu_task_switch
EXPORT cpu_intrpt_switch
EXPORT cpu_first_task_start
EXPORT PendSV_Handler
;******************************************************************************
; EQUATES
;******************************************************************************
SCB_ICSR EQU 0xE000ED04 ; Interrupt Control and State Register.
ICSR_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
SHPR3_PRI_14_15 EQU 0xE000ED20 ; System Handler Priority Register 3 (PendSV + SysTick).
SHPR3_PRI_LVL EQU 0xC0C00000 ; PendSV + SysTick priority level (lowest).
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
;******************************************************************************
; Functions:
; size_t cpu_intrpt_save(void);
; void cpu_intrpt_restore(size_t cpsr);
;******************************************************************************
cpu_intrpt_save
MRS R0, PRIMASK
CPSID I
BX LR
cpu_intrpt_restore
MSR PRIMASK, R0
BX LR
;******************************************************************************
; Functions:
; void cpu_intrpt_switch(void);
; void cpu_task_switch(void);
;******************************************************************************
cpu_task_switch
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
cpu_intrpt_switch
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
;******************************************************************************
; Functions:
; void cpu_first_task_start(void);
;******************************************************************************
cpu_first_task_start
;set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14_15
LDR R2, [R0]
LDR R1, =SHPR3_PRI_LVL
ORRS R2, R1
STR R2, [R0]
;indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
;align MSP to 8 byte
MRS R0, MSP
LSRS R0, R0, #3
LSLS R0, R0, #3
MSR MSP, R0
;make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
;goto PendSV_Handler
CPSIE I
B .
;******************************************************************************
; Functions:
; void krhino_pendsv_handler(void);
;******************************************************************************
PendSV_Handler
CPSID I
MRS R0, PSP
CMP R0, #0
;branch if cpu_first_task_start
BEQ _pendsv_handler_nosave
;hardware saved R0~R3,R12,LR,PC,xPSR
;save context
SUBS R0, R0, #0x20
STMIA R0!, {R4 - R7}
MOV R4, R8
MOV R5, R9
MOV R6, R10
MOV R7, R11
STMIA R0!, {R4 - R7}
;g_active_task->task_stack = context region
SUBS R0, R0, #0x20
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
;save and restore LR
MOV R4, LR
bl krhino_stack_ovf_check
MOV LR, R4
_pendsv_handler_nosave
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
;R0 = g_active_task->task_stack = context region
LDR R0, [R2]
;restore context
LDMIA R0!, {R4 - R7}
LDMIA R0!, {R2 - R3}
MOV R8, R2
MOV R9, R3
LDMIA R0!, {R2 - R3}
MOV R10, R2
MOV R11, R3
;return stack = PSP
MSR PSP, R0
;after exception return: stack = PSP
MOV R0, LR
MOVS R1, #0x04
ORRS R0, R1
MOV LR, R0
CPSIE I
;hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
ALIGN
END

View file

@ -0,0 +1,15 @@
NAME := armv6m
ifeq ($(COMPILER),armcc)
$(NAME)_SOURCES := armcc/m0/port_c.c
$(NAME)_SOURCES += armcc/m0/port_s.S
GLOBAL_INCLUDES += armcc/m0/
else ifeq ($(COMPILER),iar)
$(NAME)_SOURCES := iccarm/m0/port_c.c
$(NAME)_SOURCES += iccarm/m0/port_s.S
GLOBAL_INCLUDES += iccarm/m0/
else
$(NAME)_SOURCES := gcc/m0/port_c.c
$(NAME)_SOURCES += gcc/m0/port_s.S
GLOBAL_INCLUDES += gcc/m0/
endif

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* task context saved & restore by hardware: */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* task context saved & restore by software: */
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,171 @@
@******************************************************************************
@ EXTERN PARAMETERS
@******************************************************************************
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_stack_ovf_check
@******************************************************************************
@ EXPORT FUNCTIONS
@******************************************************************************
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global PendSV_Handler
@******************************************************************************
@ EQUATES
@******************************************************************************
.equ SCB_ICSR, 0xE000ED04 @ Interrupt Control and State Register.
.equ ICSR_PENDSVSET, 0x10000000 @ Value to trigger PendSV exception.
.equ SHPR3_PRI_14_15, 0xE000ED20 @ System Handler Priority Register 3 (PendSV + SysTick).
.equ SHPR3_PRI_LVL, 0xC0C00000 @ PendSV + SysTick priority level (lowest).
@******************************************************************************
@ CODE GENERATION DIRECTIVES
@******************************************************************************
.text
.align 2
.thumb
.syntax unified
@******************************************************************************
@ Functions:
@ size_t cpu_intrpt_save(void);
@ void cpu_intrpt_restore(size_t cpsr);
@******************************************************************************
.thumb_func
cpu_intrpt_save:
MRS R0, PRIMASK
CPSID I
BX LR
.thumb_func
cpu_intrpt_restore:
MSR PRIMASK, R0
BX LR
@******************************************************************************
@ Functions:
@ void cpu_intrpt_switch(void);
@ void cpu_task_switch(void);
@******************************************************************************
.thumb_func
cpu_task_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
.thumb_func
cpu_intrpt_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
@******************************************************************************
@ Functions:
@ void cpu_first_task_start(void);
@******************************************************************************
.thumb_func
cpu_first_task_start:
@set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14_15
LDR R2, [R0]
LDR R1, =SHPR3_PRI_LVL
ORRS R2, R1
STR R2, [R0]
@indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
@align MSP to 8 byte
MRS R0, MSP
LSRS R0, R0, #3
LSLS R0, R0, #3
MSR MSP, R0
@make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
@goto PendSV_Handler
CPSIE I
B .
@******************************************************************************
@ Functions:
@ void krhino_pendsv_handler(void);
@******************************************************************************
.thumb_func
PendSV_Handler:
CPSID I
MRS R0, PSP
CMP R0, #0
@branch if cpu_first_task_start
BEQ _pendsv_handler_nosave
@hardware saved R0~R3,R12,LR,PC,xPSR
@save context
SUBS R0, R0, #0x20
STMIA R0!, {R4 - R7}
MOV R4, R8
MOV R5, R9
MOV R6, R10
MOV R7, R11
STMIA R0!, {R4 - R7}
@g_active_task->task_stack = context region
SUBS R0, R0, #0x20
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
@save and restore LR
MOV R4, LR
bl krhino_stack_ovf_check
MOV LR, R4
.thumb_func
_pendsv_handler_nosave:
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
@R0 = g_active_task->task_stack = context region
LDR R0, [R2]
@restore context
LDMIA R0!, {R4 - R7}
LDMIA R0!, {R2 - R3}
MOV R8, R2
MOV R9, R3
LDMIA R0!, {R2 - R3}
MOV R10, R2
MOV R11, R3
@return stack = PSP
MSR PSP, R0
@after exception return: stack = PSP
MOV R0, LR
MOVS R1, #0x04
ORRS R0, R1
MOV LR, R0
CPSIE I
@hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
.end

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* task context saved & restore by hardware: */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* task context saved & restore by software: */
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,165 @@
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
IMPORT g_active_task
IMPORT g_preferred_ready_task
IMPORT krhino_stack_ovf_check
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
PUBLIC cpu_intrpt_save
PUBLIC cpu_intrpt_restore
PUBLIC cpu_task_switch
PUBLIC cpu_intrpt_switch
PUBLIC cpu_first_task_start
PUBLIC PendSV_Handler
;******************************************************************************
; EQUATES
;******************************************************************************
SCB_ICSR EQU 0xE000ED04 ; Interrupt Control and State Register.
ICSR_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
SHPR3_PRI_14_15 EQU 0xE000ED20 ; System Handler Priority Register 3 (PendSV + SysTick).
SHPR3_PRI_LVL EQU 0xC0C00000 ; PendSV + SysTick priority level (lowest).
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
SECTION .text:CODE(2)
THUMB
REQUIRE8
PRESERVE8
;******************************************************************************
; Functions:
; size_t cpu_intrpt_save(void);
; void cpu_intrpt_restore(size_t cpsr);
;******************************************************************************
cpu_intrpt_save:
MRS R0, PRIMASK
CPSID I
BX LR
cpu_intrpt_restore:
MSR PRIMASK, R0
BX LR
;******************************************************************************
; Functions:
; void cpu_intrpt_switch(void);
; void cpu_task_switch(void);
;******************************************************************************
cpu_task_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
cpu_intrpt_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
;******************************************************************************
; Functions:
; void cpu_first_task_start(void);
;******************************************************************************
cpu_first_task_start:
;set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14_15
LDR R2, [R0]
LDR R1, =SHPR3_PRI_LVL
ORRS R2, R1
STR R2, [R0]
;indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
;align MSP to 8 byte
MRS R0, MSP
LSRS R0, R0, #3
LSLS R0, R0, #3
MSR MSP, R0
;make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
;goto PendSV_Handler
CPSIE I
B .
;******************************************************************************
; Functions:
; void krhino_pendsv_handler(void);
;******************************************************************************
PendSV_Handler:
CPSID I
MRS R0, PSP
CMP R0, #0
;branch if cpu_first_task_start
BEQ _pendsv_handler_nosave
;hardware saved R0~R3,R12,LR,PC,xPSR
;save context
SUBS R0, R0, #0x20
STMIA R0!, {R4 - R7}
MOV R4, R8
MOV R5, R9
MOV R6, R10
MOV R7, R11
STMIA R0!, {R4 - R7}
;g_active_task->task_stack = context region
SUBS R0, R0, #0x20
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
;save and restore LR
MOV R4, LR
bl krhino_stack_ovf_check
MOV LR, R4
_pendsv_handler_nosave:
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
;R0 = g_active_task->task_stack = context region
LDR R0, [R2]
;restore context
LDMIA R0!, {R4 - R7}
LDMIA R0!, {R2 - R3}
MOV R8, R2
MOV R9, R3
LDMIA R0!, {R2 - R3}
MOV R10, R2
MOV R11, R3
;return stack = PSP
MSR PSP, R0
;after exception return: stack = PSP
MOV R0, LR
MOVS R1, #0x04
ORRS R0, R1
MOV LR, R0
CPSIE I
;hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
END

View file

@ -0,0 +1,10 @@
NAME := armv7a
ifeq ($(COMPILER),armcc)
else ifeq ($(COMPILER),iar)
else
$(NAME)_SOURCES := gcc/a5/port_s.S
$(NAME)_SOURCES += gcc/a5/port_c.c
GLOBAL_INCLUDES += gcc/a5/
endif

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,74 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
extern int fpu_reg_count(void);
/* ARMCC || IAR || GNU */
#define FPU_AVL ((defined(__CC_ARM) && defined(__TARGET_FPU_VFP)) \
|| (defined(__ICCARM__) && defined(__ARMVFP__)) \
|| (defined(__GNUC__) && defined(__VFP_FP__) && !defined(__SOFTFP__)))
#define ARM_MODE_ARM 0x00000000u
#define ARM_MODE_THUMB 0x00000020u
#define ARM_SVC_MODE_THUMB (0x00000013u + ARM_MODE_THUMB)
#define ARM_SVC_MODE_ARM (0x00000013u + ARM_MODE_ARM)
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
cpu_stack_t task_addr;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
task_addr = (cpu_stack_t)entry & ~1u; /* Mask off lower bit in case task is thumb mode */
*(--stk) = (cpu_stack_t)task_addr; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* Reg R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212u; /* Reg R12 */
*(--stk) = (cpu_stack_t)0x11111111u; /* Reg R11 */
*(--stk) = (cpu_stack_t)0x10101010u; /* Reg R10 */
*(--stk) = (cpu_stack_t)0x09090909u; /* Reg R9 */
*(--stk) = (cpu_stack_t)0x08080808u; /* Reg R8 */
*(--stk) = (cpu_stack_t)0x07070707u; /* Reg R7 */
*(--stk) = (cpu_stack_t)0x06060606u; /* Reg R6 */
*(--stk) = (cpu_stack_t)0x05050505u; /* Reg R5 */
*(--stk) = (cpu_stack_t)0x04040404u; /* Reg R4 */
*(--stk) = (cpu_stack_t)0x03030303u; /* Reg R3 */
*(--stk) = (cpu_stack_t)0x02020202u; /* Reg R2 */
*(--stk) = (cpu_stack_t)0x01010101u; /* Reg R1 */
*(--stk) = (cpu_stack_t)arg; /* Reg R0 : argument */
if (((cpu_stack_t)entry & 0x01u) == 0x01u) { /* See if task runs in Thumb or ARM mode */
*(--stk) = (cpu_stack_t)ARM_SVC_MODE_THUMB; /* CPSR (Enable IRQ and FIQ interrupts, THUMB-mode) */
} else {
*(--stk) = (cpu_stack_t)ARM_SVC_MODE_ARM; /* CPSR (Enable IRQ and FIQ interrupts, ARM-mode) */
}
#if (FPU_AVL > 0)
uint32_t fpu_reg_cnt = fpu_reg_count();
uint32_t i;
if (fpu_reg_cnt != 0u) {
*(--stk) = (cpu_stack_t)0; /* Initialize Floating point status & control register */
/* Initialize general-purpose Floating point registers */
for (i = 0u; i < fpu_reg_cnt * 2u; i++) {
*(--stk) = (cpu_stack_t)0;
}
*(--stk) = (cpu_stack_t)(0x40000000); /* Initialize Floating-Point Exception Register (Enable)*/
}
#endif
return stk;
}

View file

@ -0,0 +1,387 @@
/*
*
* @file port_s.S
*
*/
@******************************************************************************
@ EXTERN PARAMETERS
@******************************************************************************
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_stack_ovf_check
@******************************************************************************
@ EXPORT FUNCTIONS
@******************************************************************************
.global fpu_reg_count
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global vector_undef
.global vector_swi
.global vector_pabt
.global vector_dabt
.global vector_resv
.global vector_irq
.global vector_fiq
@******************************************************************************
@ EQUATES
@******************************************************************************
.equ AMR_Mode_USR, 0x10
.equ AMR_Mode_FIQ, 0x11
.equ AMR_Mode_IRQ, 0x12
.equ AMR_Mode_SVC, 0x13
.equ AMR_Mode_ABT, 0x17
.equ AMR_Mode_UND, 0x1B
.equ AMR_Mode_SYS, 0x1F
.equ ARM_CONTROL_INT_DIS, 0xC0 @ Disable both FIQ and IRQ.
.equ ARM_CONTROL_FIQ_DIS, 0x40 @ Disable FIQ.
.equ ARM_CONTROL_IRQ_DIS, 0x80 @ Disable IRQ.
.equ ARM_CONTROL_THUMB, 0x20 @ Set THUMB mode.
.equ ARM_CONTROL_ARM, 0x00 @ Set ARM mode.
.equ ARM_EXCEPT_RESET, 0x00
.equ ARM_EXCEPT_UNDEF_INSTR, 0x01
.equ ARM_EXCEPT_SWI, 0x02
.equ ARM_EXCEPT_PREFETCH_ABORT, 0x03
.equ ARM_EXCEPT_DATA_ABORT, 0x04
.equ ARM_EXCEPT_ADDR_ABORT, 0x05
.equ ARM_EXCEPT_IRQ, 0x06
.equ ARM_EXCEPT_FIQ, 0x07
@******************************************************************************
@ CODE GENERATION DIRECTIVES
@******************************************************************************
.text
.align 2
@******************************************************************************
@ MACRO DEFINED
@******************************************************************************
.macro POP_FP_REG reg
POP {\reg}
VMSR FPEXC, \reg /* Pop FPEXC */
FLDMIAS SP!, {S0-S31} /* Pop floating point registers. */
POP {\reg}
VMSR FPSCR, \reg /* Pop FPSCR. */
.endm
.macro PUSH_FP_REG reg
VMRS \reg, FPSCR /* Save FPSCR */
PUSH {\reg} /* Save floating-point registers. */
FSTMDBS SP!, {S0-S31}
VMRS \reg, FPEXC /* Save FPEXC. */
PUSH {\reg}
.endm
@******************************************************************************
@ Functions:
@ size_t fpu_reg_count(void);
@******************************************************************************
fpu_reg_count:
MOV R0, #16
BX LR
@******************************************************************************
@ Functions:
@ size_t cpu_intrpt_save(void);
@ void cpu_intrpt_restore(size_t cpsr);
@******************************************************************************
cpu_intrpt_save:
mrs r0, cpsr
CPSID IF
dsb
bx lr
cpu_intrpt_restore:
dsb
msr cpsr, r0
bx lr
@******************************************************************************
@ Functions:
@ void cpu_first_task_start(void);
@******************************************************************************
cpu_first_task_start:
MSR CPSR_c, #(ARM_CONTROL_INT_DIS | AMR_Mode_SVC) @ change to SVC mode.
@ switch to highest priority task:
LDR R0, =g_active_task @ g_active_task = g_preferred_ready_task;
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0] @ R0 = g_active_task->task_stack = context region
LDR SP, [R2]
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
POP_FP_REG R0 @ Pop fpu register.
#endif
LDR R0, [SP], #4 @ R0 = SPSR; SP = SP + 4
MSR SPSR_cxsf, R0 @ restore new task CPSR
LDMFD SP!, {R0-R12, LR, PC}^ @ restore new task context.
@******************************************************************************
@ Functions:
@ void cpu_task_switch(void);
@******************************************************************************
cpu_task_switch:
@ save current task context:
STMFD SP!, {LR} @ Push return address.
STMFD SP!, {LR}
STMFD SP!, {R0-R12} @ Push R0-R12 registers
MRS R0, CPSR @ Push old task CPSR
TST LR, #1 @ test if called from Thumb mode,
ORRNE R0, R0, #ARM_CONTROL_THUMB @ if yes, set the T-bit.
STMFD SP!, {R0}
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
PUSH_FP_REG R0 @ Push fpu register.
#endif
@g_active_task->task_stack = context region
LDR R1, =g_active_task @ g_active_task->task_stack = SP;
LDR R1, [R1]
STR SP, [R1]
bl krhino_stack_ovf_check
LDR R0, =g_active_task @ g_active_task = g_preferred_ready_task;
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0] @ R0 = g_active_task->task_stack = context region
LDR SP, [R2]
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
POP_FP_REG R0 @ Pop fpu register.
#endif
LDMFD SP!, {R0} @ restore CPSR
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ @ restore new task context.
@******************************************************************************
@ Functions:
@ void cpu_intrpt_switch(void);
@******************************************************************************
cpu_intrpt_switch:
LDR R0, =g_active_task @ g_active_task = g_preferred_ready_task;
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0] @ R0 = g_active_task->task_stack = context region
LDR SP, [R2]
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
POP_FP_REG R0 @ Pop fpu register.
#endif
LDMFD SP!, {R0} @ Pop new task CPSR
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ @ restore new task context.
.section .text.isr, "ax"
/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */
.align 5
vector_undef:
STMFD SP!, {R0-R3} @ Push R0-R3 registers.
MOV R0, #ARM_EXCEPT_UNDEF_INSTR @ Set exception type to ARM_EXCEPT_UNDEF_INSTR.
MRS R1, SPSR @ Save CPSR
MOV R2, LR @ Save LR(PC) register.
MOV R3, SP @ Save SP register.
ADD SP, SP, #(4 * 4) @ set SP to undef stack top.
B common_except_handler @ bl to common_except_handler.
.align 5
vector_swi:
STMFD SP!, {R0-R3} @ Push R0-R3 registers.
MOV R0, #ARM_EXCEPT_SWI @ Set exception type to ARM_EXCEPT_SWI.
MRS R1, SPSR @ Save CPSR
MOV R2, LR @ Save LR(PC) register.
MOV R3, SP @ Save SP register.
ADD SP, SP, #(4 * 4) @ set SP to swi stack top.
B common_except_handler @ bl to common_except_handler.
.align 5
vector_pabt:
STMFD SP!, {R0-R3} @ Push R0-R3 registers.
MOV R0, #ARM_EXCEPT_PREFETCH_ABORT @ Set exception type to ARM_EXCEPT_PREFETCH_ABORT.
MRS R1, SPSR @ Save CPSR.
SUB R2, LR, #4 @ Save LR(PC) register: -4.
MOV R3, SP @ Save SP register.
ADD SP, SP, #(4 * 4) @ set SP to padt stack top.
B common_except_handler @ bl to common_except_handler.
.align 5
vector_dabt:
STMFD SP!, {R0-R3} @ Push R0-R3 registers.
MOV R0, #ARM_EXCEPT_DATA_ABORT @ Set exception type to ARM_EXCEPT_DATA_ABORT.
MRS R1, SPSR @ Save CPSR.
SUB R2, LR, #8 @ Save LR(PC) register: -8.
MOV R3, SP @ Save SP register.
ADD SP, SP, #(4 * 4) @ set SP to dabt stack top.
B common_except_handler @ bl to common_except_handler.
.align 5
vector_resv:
STMFD SP!, {R0-R3} @ Push R0-R3 registers.
MOV R0, #ARM_EXCEPT_ADDR_ABORT @ Set exception type to ARM_EXCEPT_ADDR_ABORT.
MRS R1, SPSR @ Save CPSR.
SUB R2, LR, #8 @ Save LR(PC) register: -8.
MOV R3, SP @ Save SP register.
ADD SP, SP, #(4 * 4) @ set SP to resv stack top.
B common_except_handler @ bl to common_except_handler.
.align 5
vector_irq:
STMFD SP!, {R0-R3} @ Push R0-R3 registers.
MOV R0, #ARM_EXCEPT_IRQ @ Set exception type to ARM_EXCEPT_IRQ.
MRS R1, SPSR @ Save CPSR.
SUB R2, LR, #4 @ Save LR(PC) register: -4.
MOV R3, SP @ Save SP register.
ADD SP, SP, #(4 * 4) @ set SP to irq stack top.
B common_except_handler @ bl to common_except_handler.
.align 5
vector_fiq:
STMFD SP!, {R0-R3} @ Push R0-R3 registers.
MOV R0, #ARM_EXCEPT_FIQ @ Set exception type to ARM_EXCEPT_FIQ.
MRS R1, SPSR @ Save CPSR.
SUB R2, LR, #4 @ Save LR(PC) register: -4.
MOV R3, SP @ Save SP register.
ADD SP, SP, #(4 * 4) @ set SP to fiq stack top.
B common_except_handler @ bl to common_except_handler.
common_except_handler:
@ change to SVC mode & disable interruptions.
MSR CPSR_c, #(ARM_CONTROL_INT_DIS | AMR_Mode_SVC)
STMFD SP!, {R2} @ Push old task PC,
STMFD SP!, {LR} @ Push old task LR,
STMFD SP!, {R4-R12} @ Push old task R12-R4,
LDMFD R3!, {R5-R8} @ Pop old task R3-R0 from irq stack.
STMFD SP!, {R5-R8} @ Push old task R3-R0,
STMFD SP!, {R1} @ Push task CPSR.
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
PUSH_FP_REG R1 @ Push task fpu register.
#endif
@ if (g_sys_stat == RHINO_RUNNING)
LDR R3, =g_sys_stat
LDR R4, [R3]
CMP R4, #3 @ RHINO_RUNNING = 3
BNE except_before_task_running
PUSH {R0}
BL krhino_intrpt_enter @ g_intrpt_nested_level++;
POP {R0}
LDR R3,=g_intrpt_nested_level
LDRB R4, [R3]
CMP R4, #1 @ if (g_intrpt_nested_level == 1)
BNE except_from_intrpt
except_from_task:
@ g_active_task->task_stack = context region
LDR R3, =g_active_task @ g_active_task->task_stack = SP;
LDR R4, [R3]
STR SP, [R4]
LDR R3, =except_stack_top @ Switch to except stack.
MOV SP, R3
BL aos_cpu_except_handler @ aos_cpu_except_handler(except_type = R0)
@ change to SVC mode & disable interruptions.
MSR CPSR_c, #(ARM_CONTROL_INT_DIS | AMR_Mode_SVC)
@ call krhino_intrpt_exit() to return if a ready task with higher priority.
BL krhino_intrpt_exit
LDR R3, =g_active_task @ SP = g_active_task->task_stack;
LDR R4, [R3]
LDR SP, [R4]
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
POP_FP_REG R0 @ Pop task fpu register.
#endif
LDMFD SP!, {R0} @ Pop new task CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ @ restore new task context.
except_from_intrpt:
@ align SP to 4 byte
MOV R1, SP
AND R1, R1, #4
SUB SP, SP, R1
STMFD SP!, {R1, LR}
BL aos_cpu_except_handler @ aos_cpu_except_handler(except_type = R0)
LDMIA SP!, {R1, LR}
ADD SP, SP, R1
@ change to SVC mode & disable interruptions.
MSR CPSR_c, #(ARM_CONTROL_INT_DIS | AMR_Mode_SVC)
LDR R3,=g_intrpt_nested_level @ g_intrpt_nested_level--;
LDRB R4, [R3]
SUB R4, R4, #1
STRB R4, [R3]
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
POP_FP_REG R0 @ Pop task fpu register.
#endif
LDMFD SP!, {R0} @ Pop old task CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ @ restore working registers and return from exception.
except_before_task_running:
@ align SP to 4 byte.
MOV R1, SP
AND R1, R1, #4
SUB SP, SP, R1
STMFD SP!, {R1, LR}
LDR R3,=aos_cpu_except_handler @ aos_cpu_except_handler(except_type = R0)
MOV LR, PC
BX R3
LDMIA SP!, {R1, LR}
ADD SP, SP, R1
@ change to SVC mode & disable interruptions.
MSR CPSR_c, #(ARM_CONTROL_INT_DIS | AMR_Mode_SVC)
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
POP_FP_REG R0 @ Pop task fpu register.
#endif
LDMFD SP!, {R0} @ Pop old CPSR,
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ @ restore working registers and return from exception.

View file

@ -0,0 +1,20 @@
## Contents
## Introduction
**armv7m** arch files of armv7m
### Features
- armv7m system api
### Directories
```sh
armv7m
├─ gcc # System adapter file of armv7m architecture for gcc
├─ armcc # System adapter file of armv7m architecture for armcc
├─ iccarm # System adapter file of armv7m architecture for iccarm
├─ panic # panic adapter file of armv7m architecture
```
### Dependencies
## Reference

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static __inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* task context saved & restore by hardware: */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,161 @@
#include <k_config.h>
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
EXTERN g_active_task
EXTERN g_preferred_ready_task
EXTERN krhino_stack_ovf_check
EXTERN krhino_task_sched_stats_get
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
EXPORT cpu_intrpt_save
EXPORT cpu_intrpt_restore
EXPORT cpu_task_switch
EXPORT cpu_intrpt_switch
EXPORT cpu_first_task_start
EXPORT PendSV_Handler
EXPORT _first_task_restore
;******************************************************************************
; EQUATES
;******************************************************************************
SCB_ICSR EQU 0xE000ED04 ; Interrupt Control and State Register.
SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register.
ICSR_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
SHPR3_PRI_14 EQU 0xE000ED22 ; System Handler Priority Register 3 (PendSV).
PRI_LVL_PENDSV EQU 0xFF ; PendSV priority level (lowest).
SHPR3_PRI_15 EQU 0xE000ED23 ; System Handler Priority Register 3 (SysTick).
PRI_LVL_SYSTICK EQU 0xFF ; SYstick priority level (lowest).
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
;******************************************************************************
; Functions:
; size_t cpu_intrpt_save(void);
; void cpu_intrpt_restore(size_t cpsr);
;******************************************************************************
cpu_intrpt_save
MRS R0, PRIMASK
CPSID I
BX LR
cpu_intrpt_restore
MSR PRIMASK, R0
BX LR
;******************************************************************************
; Functions:
; void cpu_intrpt_switch(void);
; void cpu_task_switch(void);
;******************************************************************************
cpu_task_switch
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
cpu_intrpt_switch
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
;******************************************************************************
; Functions:
; void cpu_first_task_start(void);
;******************************************************************************
cpu_first_task_start
;set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14
LDR R1, =PRI_LVL_PENDSV
STRB R1, [R0]
;set Systick prority to the lowest
LDR R0, =SHPR3_PRI_15
LDR R1, =PRI_LVL_SYSTICK
STRB R1, [R0]
;indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
;make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
;goto PendSV_Handler
CPSIE I
B .
;******************************************************************************
; Functions:
; void krhino_pendsv_handler(void);
;******************************************************************************
PendSV_Handler
CPSID I
MRS R0, PSP
;branch if cpu_first_task_start
CMP R0, #0
BEQ _first_task_restore
;hardware saved R0~R3,R12,LR,PC,xPSR
;save context
SUBS R0, R0, #0x24
STM R0, {R4-R11, LR}
;g_active_task->task_stack = context region
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
_pendsv_handler_nosave
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
;R0 = g_active_task->task_stack = context region
LDR R0, [R2]
;restore context
LDM R0, {R4-R11, LR}
ADDS R0, R0, #0x24
;return stack = PSP
MSR PSP, R0
CPSIE I
;hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
_first_task_restore
;set MSP to the base of system stack
LDR R0, =SCB_VTOR
LDR R0, [R0]
LDR R0, [R0]
MSR MSP, R0
B _pendsv_handler_nosave
ALIGN
END

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static __inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
/* ARMCC || IAR || GNU */
#define FPU_AVL ((defined(__CC_ARM) && defined(__TARGET_FPU_VFP)) \
|| (defined(__ICCARM__) && defined(__ARMVFP__)) \
|| (defined(__GNUC__) && defined(__VFP_FP__) && !defined(__SOFTFP__)))
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* Exception stack frame with non-floating-point state */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* in PendSV_Handler, D8~D15 is always saved & restroe */
#if (FPU_AVL > 0)
*(--stk) = (cpu_stack_t)0x31uL; /* S31 */
*(--stk) = (cpu_stack_t)0x30uL; /* S30 */
*(--stk) = (cpu_stack_t)0x29uL; /* S29 */
*(--stk) = (cpu_stack_t)0x28uL; /* S28 */
*(--stk) = (cpu_stack_t)0x27uL; /* S27 */
*(--stk) = (cpu_stack_t)0x26uL; /* S26 */
*(--stk) = (cpu_stack_t)0x25uL; /* S25 */
*(--stk) = (cpu_stack_t)0x24uL; /* S24 */
*(--stk) = (cpu_stack_t)0x23uL; /* S23 */
*(--stk) = (cpu_stack_t)0x22uL; /* S22 */
*(--stk) = (cpu_stack_t)0x21uL; /* S21 */
*(--stk) = (cpu_stack_t)0x20uL; /* S20 */
*(--stk) = (cpu_stack_t)0x19uL; /* S19 */
*(--stk) = (cpu_stack_t)0x18uL; /* S18 */
*(--stk) = (cpu_stack_t)0x17uL; /* S17 */
*(--stk) = (cpu_stack_t)0x16uL; /* S16 */
#endif
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + non-floating-point state + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,177 @@
#include <k_config.h>
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
EXTERN g_active_task
EXTERN g_preferred_ready_task
EXTERN krhino_stack_ovf_check
EXTERN krhino_task_sched_stats_get
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
EXPORT cpu_intrpt_save
EXPORT cpu_intrpt_restore
EXPORT cpu_task_switch
EXPORT cpu_intrpt_switch
EXPORT cpu_first_task_start
EXPORT PendSV_Handler
EXPORT _first_task_restore
;******************************************************************************
; EQUATES
;******************************************************************************
SCB_ICSR EQU 0xE000ED04 ; Interrupt Control and State Register.
SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register.
ICSR_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
SHPR3_PRI_14 EQU 0xE000ED22 ; System Handler Priority Register 3 (PendSV).
PRI_LVL_PENDSV EQU 0xFF ; PendSV priority level (lowest).
SHPR3_PRI_15 EQU 0xE000ED23 ; System Handler Priority Register 3 (SysTick).
PRI_LVL_SYSTICK EQU 0xFF ; SYstick priority level (lowest).
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
;******************************************************************************
; Functions:
; size_t cpu_intrpt_save(void);
; void cpu_intrpt_restore(size_t cpsr);
;******************************************************************************
cpu_intrpt_save
MRS R0, PRIMASK
CPSID I
BX LR
cpu_intrpt_restore
MSR PRIMASK, R0
BX LR
;******************************************************************************
; Functions:
; void cpu_intrpt_switch(void);
; void cpu_task_switch(void);
;******************************************************************************
cpu_task_switch
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
cpu_intrpt_switch
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
;******************************************************************************
; Functions:
; void cpu_first_task_start(void);
;******************************************************************************
cpu_first_task_start
;set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14
LDR R1, =PRI_LVL_PENDSV
STRB R1, [R0]
;set Systick prority to the lowest
LDR R0, =SHPR3_PRI_15
LDR R1, =PRI_LVL_SYSTICK
STRB R1, [R0]
;indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
;make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
;goto PendSV_Handler
CPSIE I
B .
;******************************************************************************
; Functions:
; void krhino_pendsv_handler(void);
;******************************************************************************
PendSV_Handler
CPSID I
MRS R0, PSP
;branch if cpu_first_task_start
CMP R0, #0
BEQ _first_task_restore
;hardware saved R0~R3,R12,LR,PC,xPSR
;save context
IF {FPU} != "SoftVFP"
;if the switchout task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VSTMFDEQ R0!, {D8 - D15}
;hardware saved D0~D7, FPSCR
ENDIF
SUBS R0, R0, #0x24
STM R0, {R4-R11, LR}
;g_active_task->task_stack = context region
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
_pendsv_handler_nosave
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
;R0 = g_active_task->task_stack = context region
LDR R0, [R2]
;restore context
LDM R0, {R4-R11, LR}
ADDS R0, R0, #0x24
IF {FPU} != "SoftVFP"
;if the switchin task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VLDMFDEQ R0!, {D8 - D15}
;hardware will restore D0~D7, FPSCR
ENDIF
;return stack = PSP
MSR PSP, R0
CPSIE I
;hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
_first_task_restore
;set MSP to the base of system stack
LDR R0, =SCB_VTOR
LDR R0, [R0]
LDR R0, [R0]
MSR MSP, R0
B _pendsv_handler_nosave
ALIGN
END

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static __inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
/* ARMCC || IAR || GNU */
#define FPU_AVL ((defined(__CC_ARM) && defined(__TARGET_FPU_VFP)) \
|| (defined(__ICCARM__) && defined(__ARMVFP__)) \
|| (defined(__GNUC__) && defined(__VFP_FP__) && !defined(__SOFTFP__)))
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* Exception stack frame with non-floating-point state */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* in PendSV_Handler, D8~D15 is always saved & restroe */
#if (FPU_AVL > 0)
*(--stk) = (cpu_stack_t)0x31uL; /* S31 */
*(--stk) = (cpu_stack_t)0x30uL; /* S30 */
*(--stk) = (cpu_stack_t)0x29uL; /* S29 */
*(--stk) = (cpu_stack_t)0x28uL; /* S28 */
*(--stk) = (cpu_stack_t)0x27uL; /* S27 */
*(--stk) = (cpu_stack_t)0x26uL; /* S26 */
*(--stk) = (cpu_stack_t)0x25uL; /* S25 */
*(--stk) = (cpu_stack_t)0x24uL; /* S24 */
*(--stk) = (cpu_stack_t)0x23uL; /* S23 */
*(--stk) = (cpu_stack_t)0x22uL; /* S22 */
*(--stk) = (cpu_stack_t)0x21uL; /* S21 */
*(--stk) = (cpu_stack_t)0x20uL; /* S20 */
*(--stk) = (cpu_stack_t)0x19uL; /* S19 */
*(--stk) = (cpu_stack_t)0x18uL; /* S18 */
*(--stk) = (cpu_stack_t)0x17uL; /* S17 */
*(--stk) = (cpu_stack_t)0x16uL; /* S16 */
#endif
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + non-floating-point state + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,177 @@
#include <k_config.h>
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
EXTERN g_active_task
EXTERN g_preferred_ready_task
EXTERN krhino_stack_ovf_check
EXTERN krhino_task_sched_stats_get
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
EXPORT cpu_intrpt_save
EXPORT cpu_intrpt_restore
EXPORT cpu_task_switch
EXPORT cpu_intrpt_switch
EXPORT cpu_first_task_start
EXPORT PendSV_Handler
EXPORT _first_task_restore
;******************************************************************************
; EQUATES
;******************************************************************************
SCB_ICSR EQU 0xE000ED04 ; Interrupt Control and State Register.
SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register.
ICSR_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
SHPR3_PRI_14 EQU 0xE000ED22 ; System Handler Priority Register 3 (PendSV).
PRI_LVL_PENDSV EQU 0xFF ; PendSV priority level (lowest).
SHPR3_PRI_15 EQU 0xE000ED23 ; System Handler Priority Register 3 (SysTick).
PRI_LVL_SYSTICK EQU 0xFF ; SYstick priority level (lowest).
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
;******************************************************************************
; Functions:
; size_t cpu_intrpt_save(void);
; void cpu_intrpt_restore(size_t cpsr);
;******************************************************************************
cpu_intrpt_save
MRS R0, PRIMASK
CPSID I
BX LR
cpu_intrpt_restore
MSR PRIMASK, R0
BX LR
;******************************************************************************
; Functions:
; void cpu_intrpt_switch(void);
; void cpu_task_switch(void);
;******************************************************************************
cpu_task_switch
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
cpu_intrpt_switch
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
;******************************************************************************
; Functions:
; void cpu_first_task_start(void);
;******************************************************************************
cpu_first_task_start
;set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14
LDR R1, =PRI_LVL_PENDSV
STRB R1, [R0]
;set Systick prority to the lowest
LDR R0, =SHPR3_PRI_15
LDR R1, =PRI_LVL_SYSTICK
STRB R1, [R0]
;indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
;make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
;goto PendSV_Handler
CPSIE I
B .
;******************************************************************************
; Functions:
; void krhino_pendsv_handler(void);
;******************************************************************************
PendSV_Handler
CPSID I
MRS R0, PSP
;branch if cpu_first_task_start
CMP R0, #0
BEQ _first_task_restore
;hardware saved R0~R3,R12,LR,PC,xPSR
;save context
IF {FPU} != "SoftVFP"
;if the switchout task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VSTMFDEQ R0!, {D8 - D15}
;hardware saved D0~D7, FPSCR
ENDIF
SUBS R0, R0, #0x24
STM R0, {R4-R11, LR}
;g_active_task->task_stack = context region
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
_pendsv_handler_nosave
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
;R0 = g_active_task->task_stack = context region
LDR R0, [R2]
;restore context
LDM R0, {R4-R11, LR}
ADDS R0, R0, #0x24
IF {FPU} != "SoftVFP"
;if the switchin task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VLDMFDEQ R0!, {D8 - D15}
;hardware will restore D0~D7, FPSCR
ENDIF
;return stack = PSP
MSR PSP, R0
CPSIE I
;hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
_first_task_restore
;set MSP to the base of system stack
LDR R0, =SCB_VTOR
LDR R0, [R0]
LDR R0, [R0]
MSR MSP, R0
B _pendsv_handler_nosave
ALIGN
END

View file

@ -0,0 +1,47 @@
NAME := arch_armv7m
$(NAME)_MBINS_TYPE := kernel
$(NAME)_VERSION := 1.0.0
$(NAME)_SUMMARY := arch for armv7m
$(NAME)_SOURCES := common/panic_c.c
$(NAME)_SOURCES += common/port_c.c
$(NAME)_SOURCES += common/panic_mpu.c
GLOBAL_INCLUDES += common/
ifeq ($(COMPILER),armcc)
$(NAME)_SOURCES += common/panic_armcc.S
GLOBAL_ASMFLAGS += --cpreproc
ifeq ($(HOST_ARCH),Cortex-M3)
$(NAME)_SOURCES += armcc/m3/port_s.S
else ifeq ($(HOST_ARCH),Cortex-M4)
$(NAME)_SOURCES += armcc/m4/port_s.S
else ifeq ($(HOST_ARCH),Cortex-M7)
$(NAME)_SOURCES += armcc/m7/port_s.S
endif
else ifeq ($(COMPILER),iar)
$(NAME)_SOURCES += common/panic_iccarm.S
ifeq ($(HOST_ARCH),Cortex-M3)
$(NAME)_SOURCES += iccarm/m3/port_s.S
else ifeq ($(HOST_ARCH),Cortex-M4)
$(NAME)_SOURCES += iccarm/m4/port_s.S
else ifeq ($(HOST_ARCH),Cortex-M7)
$(NAME)_SOURCES += iccarm/m7/port_s.S
endif
else
$(NAME)_SOURCES += common/panic_gcc.S
ifeq ($(HOST_ARCH),Cortex-M3)
$(NAME)_SOURCES += gcc/m3/port_s.S
else ifeq ($(HOST_ARCH),Cortex-M4)
$(NAME)_SOURCES += gcc/m4/port_s.S
else ifeq ($(HOST_ARCH),Cortex-M7)
$(NAME)_SOURCES += gcc/m7/port_s.S
endif
endif

View file

@ -0,0 +1,101 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_COMPILER_H
#define K_COMPILER_H
#if defined(__CC_ARM)
#define RHINO_INLINE static __inline
/* get the return address of the current function
unsigned int __return_address(void) */
#define RHINO_GET_RA() (void *)__return_address()
/* get the the value of the stack pointer
unsigned int __current_sp(void) */
#define RHINO_GET_SP() (void *)__current_sp()
/* get the number of leading 0-bits in x
unsigned char __clz(unsigned int val) */
#define RHINO_BIT_CLZ(x) __clz(x)
#ifndef __WEAK
#define __WEAK __weak
#endif
/* Instruction Synchronization Barrier */
#define OS_ISB() __isb(15) /* Full system Any-Any */
/* Data Memory Barrier */
#define OS_DMB() __dmb(15) /* Full system Any-Any */
/* Data Synchronization Barrier */
#define OS_DSB() __dsb(15) /* Full system Any-Any */
#elif defined(__ICCARM__)
#define RHINO_INLINE static inline
/* get the return address of the current function
unsigned int __get_LR(void) */
#define RHINO_GET_RA() (void *)__get_LR()
/* get the the value of the stack pointer
unsigned int __get_SP(void) */
#define RHINO_GET_SP() (void *)__get_SP()
/* get the value of the stack pointer register
unsigned int __CLZ(unsigned int) */
//#define RHINO_BIT_CLZ(x) __CLZ(x)
#ifndef __WEAK
#define __WEAK __weak
#endif
/* Instruction Synchronization Barrier */
#define OS_ISB() __isb(15) /* Full system Any-Any */
/* Data Memory Barrier */
#define OS_DMB() __dmb(15) /* Full system Any-Any */
/* Data Synchronization Barrier */
#define OS_DSB() __dsb(15) /* Full system Any-Any */
#elif defined(__GNUC__)
#define RHINO_INLINE static inline
/* get the return address of the current function
void * __builtin_return_address (unsigned int level) */
#define RHINO_GET_RA() __builtin_return_address(0)
/* get the return address of the current function */
__attribute__((always_inline)) RHINO_INLINE void *RHINO_GET_SP(void)
{
void *sp;
asm volatile("mov %0, SP\n":"=r"(sp));
return sp;
}
__attribute__((always_inline)) RHINO_INLINE unsigned char RHINO_BIT_CLZ_(unsigned int bitmap)
{
unsigned char cnt;
asm volatile("clz %0, %1":"=r"(cnt):"r"(bitmap));
return cnt;
}
/* get the number of leading 0-bits in x
int __builtin_clz (unsigned int x) */
#define RHINO_BIT_CLZ(x) RHINO_BIT_CLZ_(x)
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
/* Instruction Synchronization Barrier */
#define OS_ISB() \
__asm volatile ("isb sy":::"memory")
/* Data Memory Barrier */
#define OS_DMB() \
__asm volatile ("dmb sy":::"memory")
/* Data Synchronization Barrier */
#define OS_DSB() \
__asm volatile ("dsb sy":::"memory")
#else
#error "Unsupported compiler"
#endif
#endif /* K_COMPILER_H */

View file

@ -0,0 +1,21 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TYPES_H
#define K_TYPES_H
#include "k_compiler.h"
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t cpu_cpsr_t;
#endif /* K_TYPES_H */

View file

@ -0,0 +1,152 @@
#include "k_config.h"
#include "k_dftdbg_config.h"
;******************************************************************************
; EQUATES
;******************************************************************************
CONTEXT_REGION EQU 88 ;bigger than sizeof(PANIC_CONTEXT)
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
#if (RHINO_CONFIG_PANIC > 0)
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
EXTERN panicHandler
EXTERN g_crash_steps
EXTERN _first_task_restore
EXTERN panicRestoreCheck
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
EXPORT HardFault_Handler
EXPORT MemManage_Handler
EXPORT BusFault_Handler
EXPORT UsageFault_Handler
;******************************************************************************
; FAULT FUNCTIONS
;******************************************************************************
HardFault_Handler
MemManage_Handler
BusFault_Handler
UsageFault_Handler
PUSH {R1, LR}
BL panicRestoreCheck
POP {R1, LR}
CBZ R0, unrecoverable_crash
BL _first_task_restore
unrecoverable_crash
;check double crash
LDR R1, =g_crash_steps
LDR R2, [R1]
ADD R3, R2, #1
STR R3, [R1]
CBZ R2, first_panic
;return from exc to handle panic
MRS R1, PSP
AND R2, LR, #4 ;EXC_RETURN:bit2, 0 MSP, 1 PSP
CBNZ R2, double_panic
MRS R1, MSP
double_panic
LDR R0, =double_panic_entry
STR R0, [R1, #24]
LDR R0, [R1, #28]
ORR R0, R0, #0x1000000
STR R0, [R1, #28] ;set thumb mode
BX LR
double_panic_entry
MOV R0, #0 ;double crash, do not save context
BL panicHandler
B .
first_panic
;R0 as PANIC_CONTEXT
SUB R0, SP, #CONTEXT_REGION
;R1 as CONTEXT saved by hardware
MRS R1, PSP
AND R2, LR, #4 ;EXC_RETURN:bit2, 0 MSP, 1 PSP
CBNZ R2, context_save
MRS R1, MSP
context_save
ADD R2, R0, #16
STM R2!,{R4-R11} ;ctx save, R4~R11
LDM R1, {R4-R11}
STM R0, {R4-R7} ;ctx save, R0~R3
STM R2!,{R8-R11} ;ctx save, R12 LR PC xPSR
;xPSR[9] and EXC_RETURN[4] to determine whether
;the previous top-of-stack was at offset 0x20, 0x24, 0x68, or0x6C
ADD R4, R1, #0x20
IF {FPU} != "SoftVFP"
AND R3, LR, #0x10 ;EXC_RETURN:bit4, 0 floating, 1 non-floating
CBNZ R3, check_aligner
ADD R4, R4, #0x48
check_aligner
ENDIF
LDR R3, [R1, #28]
AND R3, R3, #0x200 ;xPSR:bit9, 0 no-aligner, 1 aligner
CBZ R3, sp_save
ADD R4, R4, #0x4
sp_save
STM R2!,{R4} ;ctx save, SP
MOV R4, LR
STM R2!,{R4} ;ctx save, EXC_RETURN
MRS R4, IPSR
STM R2!,{R4} ;ctx save, EXC_NUMBER
MRS R4, PRIMASK
STM R2!,{R4} ;ctx save, PRIMASK
MRS R4, FAULTMASK
STM R2!,{R4} ;ctx save, FAULTMASK
MRS R4, BASEPRI
STM R2!,{R4} ;ctx save, BASEPRI
;return from exc to handle panic
STR R0, [R1, #0]
LDR R0, =panic_entry
STR R0, [R1, #24]
LDR R0, [R1, #28]
ORR R0, R0, #0x1000000
STR R0, [R1, #28] ;set thumb mode
CPSID I
BX LR
panic_entry
#if (RHINO_CONFIG_PANIC_PRT_INT > 0)
MRS R1, CONTROL
MOVS R2, #2
BICS R1, R2
MSR CONTROL, R1
ISB
;printf use interrupt, so here enable it
CPSIE I
#endif
MOV SP, R0
BL panicHandler
B .
ALIGN
#endif
END

View file

@ -0,0 +1,569 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "k_dbg_api.h"
#if (RHINO_CONFIG_BACKTRACE > 0)
#if defined(__CC_ARM)
#ifdef __BIG_ENDIAN
#error "Not support big-endian!"
#endif
#elif defined(__ICCARM__)
#if (__LITTLE_ENDIAN__ == 0)
#error "Not support big-endian!"
#endif
#elif defined(__GNUC__)
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#error "Not support big-endian!"
#endif
#endif
#define FUNC_SIZE_LIMIT 0x2000
#define BACK_TRACE_LIMIT 64
#define LR_2_ADDR(lr) ((char *)(((int)(lr)) & 0xfffffffe))
#if defined(__ICCARM__)
static unsigned int __builtin_popcount(unsigned int u)
{
unsigned int ret = 0;
while (u) {
u = (u & (u - 1));
ret++;
}
return ret;
}
#endif
void getPLSfromCtx(void *context, char **PC, char **LR, int **SP)
{
int *ptr = context;
int exc_return;
/* reference to cpu_task_stack_init */
exc_return = ptr[8];
if ((exc_return & 0x10) == 0x10) {
*PC = (char *)ptr[15];
*LR = (char *)ptr[14];
*SP = ptr + 17;
} else {
*PC = (char *)ptr[31];
*LR = (char *)ptr[30];
*SP = ptr + 51;
}
}
/* get "blx" or "bl" before LR, return offset */
static int backtraceFindLROffset(char *LR,
int (*print_func)(const char *fmt, ...))
{
unsigned short ins16;
char s_panic_call[] = "backtrace : 0x \r\n";
LR = LR_2_ADDR(LR);
/* callstack bottom */
if (((int)LR & 0xffffffe0) == 0xffffffe0) {
/* EXC_RETURN, so here is callstack bottom of interrupt handler */
if (print_func != NULL) {
print_func("backtrace : ^interrupt^\r\n");
}
return 0;
}
if (LR == LR_2_ADDR(&krhino_task_deathbed)) {
/* task delete, so here is callstack bottom of task */
if (print_func != NULL) {
print_func("backtrace : ^task entry^\r\n");
}
return 0;
}
ins16 = *(unsigned short *)(LR - 4);
if ((ins16 & 0xf000) == 0xf000) {
if (print_func != NULL) {
k_int2str((int)LR - 4, &s_panic_call[14]);
print_func(s_panic_call);
}
return 5;
} else {
if (print_func != NULL) {
k_int2str((int)LR - 2, &s_panic_call[14]);
print_func(s_panic_call);
}
return 3;
}
}
/* find current function caller, update PC and SP
returns: 0 success
1 success and find buttom
-1 fail */
int backtraceFromStack(int **pSP, char **pPC,
int (*print_func)(const char *fmt, ...))
{
char *CodeAddr = NULL;
int *SP = *pSP;
char *PC = *pPC;
char *LR;
int i;
unsigned short ins16;
unsigned int ins32;
unsigned int framesize = 0;
unsigned int shift = 0;
unsigned int sub = 0;
unsigned int offset = 1;
if (SP == krhino_task_stack_bottom(NULL)) {
if (print_func != NULL) {
print_func("backtrace : ^task entry^\r\n");
}
return 1;
}
/* func call ways:
1. "stmdb sp!, ..." or "push ..." to open stack frame and save LR
2. "sub sp, ..." or "sub.w sp, ..." to open stack more
3. call
*/
/* 1. scan code, find frame size from "push" or "stmdb sp!" */
for (i = 2; i < FUNC_SIZE_LIMIT; i += 2) {
/* find nearest "push {..., lr}" */
ins16 = *(unsigned short *)(PC - i);
if ((ins16 & 0xff00) == 0xb500) {
framesize = __builtin_popcount((unsigned char)ins16);
framesize++;
/* find double push */
ins16 = *(unsigned short *)(PC - i - 2);
if ((ins16 & 0xff00) == 0xb400) {
offset += __builtin_popcount((unsigned char)ins16);
framesize += __builtin_popcount((unsigned char)ins16);
}
CodeAddr = PC - i;
break;
}
/* find "stmdb sp!, ..." */
/* The Thumb instruction stream is a sequence of halfword-aligned
* halfwords */
ins32 = *(unsigned short *)(PC - i);
ins32 <<= 16;
ins32 |= *(unsigned short *)(PC - i + 2);
if ((ins32 & 0xFFFFF000) == 0xe92d4000) {
framesize = __builtin_popcount(ins32 & 0xfff);
framesize++;
CodeAddr = PC - i;
break;
}
}
if (CodeAddr == NULL) {
/* error branch */
if (print_func != NULL) {
print_func("Backtrace fail!\r\n");
}
return -1;
}
/* 2. scan code, find frame size from "sub" or "sub.w" */
for (i = 0; i < FUNC_SIZE_LIMIT;) {
if (CodeAddr + i > PC) {
break;
}
/* find "sub sp, ..." */
ins16 = *(unsigned short *)(CodeAddr + i);
if ((ins16 & 0xff80) == 0xb080) {
framesize += (ins16 & 0x7f);
break;
}
/* find "sub.w sp, sp, ..." */
ins32 = *(unsigned short *)(CodeAddr + i);
ins32 <<= 16;
ins32 |= *(unsigned short *)(CodeAddr + i + 2);
if ((ins32 & 0xFBFF8F00) == 0xF1AD0D00) {
sub = 128 + (ins32 & 0x7f);
shift = (ins32 >> 7) & 0x1;
shift += ((ins32 >> 12) & 0x7) << 1;
shift += ((ins32 >> 26) & 0x1) << 4;
framesize += sub<<(30 - shift);
break;
}
if ((ins16 & 0xf800) >= 0xe800) {
i += 4;
} else {
i += 2;
}
}
/* 3. output */
*pSP = SP + framesize;
LR = (char *)*(SP + framesize - offset);
offset = backtraceFindLROffset(LR, print_func);
*pPC = LR - offset;
return offset == 0 ? 1 : 0;
}
/* find current function caller, update PC and SP
returns: 0 success
1 success and find buttom
-1 fail */
int backtraceFromLR(int **pSP, char **pPC, char *LR,
int (*print_func)(const char *fmt, ...))
{
int *SP = *pSP;
char *PC = *pPC;
char *CodeAddr = NULL;
int i;
unsigned short ins16;
unsigned int framesize = 0;
unsigned int offset;
if (PC == NULL) {
offset = backtraceFindLROffset(LR, print_func);
PC = LR - offset;
*pPC = PC;
return offset == 0 ? 1 : 0;
}
/*find stack framesize:
1. "push ..." to open stack
2. "sub sp, ..." to open stack
3. 1 + 2
4. do not open stack
*/
/* 1. scan code, find frame size from "push" or "sub" */
for (i = 2; i < FUNC_SIZE_LIMIT; i += 2) {
ins16 = *(unsigned short *)(PC - i);
/* find "push {..., lr}" */
if ((ins16 & 0xff00) == 0xb500) {
/* another function */
break;
}
/* find "push {...}" */
if ((ins16 & 0xff00) == 0xb400) {
framesize = __builtin_popcount((unsigned char)ins16);
CodeAddr = PC - i;
break;
}
/* find "sub sp, ..." */
if ((ins16 & 0xff80) == 0xb080) {
framesize = (ins16 & 0x7f);
CodeAddr = PC - i;
/* find push before sub */
ins16 = *(unsigned short *)(PC - i - 2);
if ((ins16 & 0xff00) == 0xb400) {
framesize += __builtin_popcount((unsigned char)ins16);
CodeAddr = PC - i - 2;
}
break;
}
}
/* 2. check the "push" or "sub sp" belongs to another function */
if (CodeAddr != NULL) {
for (i = 2; i < PC - CodeAddr; i += 2) {
ins16 = *(unsigned short *)(PC - i);
/* find "pop {..., pc}" or "bx lr" */
if ((ins16 & 0xff00) == 0xbd00 || ins16 == 0x4770) {
/* SP no changed */
framesize = 0;
}
}
} /* else: SP no changed */
/* 3. output */
*pSP = SP + framesize;
offset = backtraceFindLROffset(LR, print_func);
*pPC = LR - offset;
return offset == 0 ? 1 : 0;
}
/* printf call stack */
int backtrace_now(int (*print_func)(const char *fmt, ...))
{
char *PC;
int *SP;
int lvl;
int ret;
if (print_func == NULL) {
print_func = printf;
}
/* compiler specific */
#if defined(__CC_ARM)
SP = (int *)__current_sp();
PC = (char *)__current_pc();
#elif defined(__ICCARM__)
asm volatile("mov %0, sp\n" : "=r"(SP));
asm volatile("mov %0, pc\n" : "=r"(PC));
#elif defined(__GNUC__)
__asm__ volatile("mov %0, sp\n" : "=r"(SP));
__asm__ volatile("mov %0, pc\n" : "=r"(PC));
#endif
print_func("========== Call stack ==========\r\n");
for (lvl = 0; lvl < BACK_TRACE_LIMIT; lvl++) {
ret = backtraceFromStack(&SP, &PC, print_func);
if (ret != 0) {
break;
}
}
print_func("========== End ==========\r\n");
return lvl;
}
int backtrace_task(char *taskname, int (*print_func)(const char *fmt, ...))
{
char *PC;
char *LR;
int *SP;
int lvl;
int ret;
ktask_t *task;
if (print_func == NULL) {
print_func = printf;
}
task = krhino_task_find(taskname);
if (task == NULL) {
print_func("Task not found : %s\n", taskname);
return 0;
}
if (krhino_task_is_running(task)) {
print_func("Status of task \"%s\" is 'Running', Can not backtrace!\n",
taskname);
return 0;
}
getPLSfromCtx(task->task_stack, &PC, &LR, &SP);
print_func("TaskName : %s\n", taskname);
print_func("========== Call stack ==========\r\n");
for (lvl = 0; lvl < BACK_TRACE_LIMIT; lvl++) {
ret = backtraceFromStack(&SP, &PC, print_func);
if (ret != 0) {
break;
}
}
print_func("========== End ==========\r\n");
return lvl;
}
#endif
#if (RHINO_CONFIG_PANIC > 0)
#define REG_NAME_WIDTH 7
typedef struct
{
/* saved in assembler */
int R0;
int R1;
int R2;
int R3;
int R4;
int R5;
int R6;
int R7;
int R8;
int R9;
int R10;
int R11;
int R12;
int LR; // Link Register (LR)
int PC; // Program Counter (PC)
int xPSR; // Program Status Registers
int SP; // Stack Pointer
int EXC_RETURN; // Exception Return
int EXC_NUMBER; // Exception Num
int PRIMASK; // Interrupt Mask
int FAULTMASK; // Interrupt Mask
int BASEPRI; // Interrupt Mask
} PANIC_CONTEXT;
typedef struct
{
int CFSR;
int HFSR;
int MMFAR;
int BFAR;
int AFSR;
} FAULT_REGS;
void panicGetCtx(void *context, char **pPC, char **pLR, int **pSP)
{
PANIC_CONTEXT *arm_context = (PANIC_CONTEXT *)context;
*pSP = (int *)arm_context->SP;
*pPC = (char *)arm_context->PC;
*pLR = (char *)arm_context->LR;
}
void panicShowRegs(void *context, int (*print_func)(const char *fmt, ...))
{
int x;
int *regs = (int *)context;
char s_panic_regs[REG_NAME_WIDTH + 14];
FAULT_REGS stFregs;
/* PANIC_CONTEXT */
char s_panic_ctx[] = "R0 "
"R1 "
"R2 "
"R3 "
"R4 "
"R5 "
"R6 "
"R7 "
"R8 "
"R9 "
"R10 "
"R11 "
"R12 "
"LR "
"PC "
"xPSR "
"SP "
"EXC_RET"
"EXC_NUM"
"PRIMASK"
"FLTMASK"
"BASEPRI";
/* FAULT_REGS */
char s_panic_reg[] = "CFSR "
"HFSR "
"MMFAR "
"BFAR "
"AFSR ";
if (regs == NULL) {
return;
}
print_func("========== Regs info ==========\r\n");
/* show PANIC_CONTEXT */
for (x = 0; x < sizeof(s_panic_ctx) / REG_NAME_WIDTH; x++) {
memcpy(&s_panic_regs[0], &s_panic_ctx[x * REG_NAME_WIDTH],
REG_NAME_WIDTH);
memcpy(&s_panic_regs[REG_NAME_WIDTH], " 0x", 3);
k_int2str(regs[x], &s_panic_regs[REG_NAME_WIDTH + 3]);
s_panic_regs[REG_NAME_WIDTH + 11] = '\r';
s_panic_regs[REG_NAME_WIDTH + 12] = '\n';
s_panic_regs[REG_NAME_WIDTH + 13] = 0;
print_func(s_panic_regs);
}
/* show FAULT_REGS */
stFregs.CFSR = (*((volatile int *)(0xE000ED28)));
stFregs.HFSR = (*((volatile int *)(0xE000ED2C)));
stFregs.MMFAR = (*((volatile int *)(0xE000ED34)));
stFregs.BFAR = (*((volatile int *)(0xE000ED38)));
stFregs.AFSR = (*((volatile int *)(0xE000ED3C)));
for (x = 0; x < sizeof(stFregs) / sizeof(int); x++) {
memcpy(&s_panic_regs[0], &s_panic_reg[x * REG_NAME_WIDTH],
REG_NAME_WIDTH);
memcpy(&s_panic_regs[REG_NAME_WIDTH], " 0x", 3);
k_int2str(((int *)(&stFregs))[x], &s_panic_regs[REG_NAME_WIDTH + 3]);
s_panic_regs[REG_NAME_WIDTH + 11] = '\r';
s_panic_regs[REG_NAME_WIDTH + 12] = '\n';
s_panic_regs[REG_NAME_WIDTH + 13] = 0;
print_func(s_panic_regs);
}
}
#if (RHINO_CONFIG_BACKTRACE > 0)
/* backtrace start with PC and SP, find LR from stack memory
return levels os callstack */
int panicBacktraceCaller(char *PC, int *SP,
int (*print_func)(const char *fmt, ...))
{
int *bt_sp;
char *bt_pc;
int lvl, ret;
char s_panic_call[] = "backtrace : 0x \r\n";
/* caller must save LR in stack, so find LR from stack */
if (SP == NULL) {
return 0;
}
bt_sp = SP;
bt_pc = LR_2_ADDR(PC);
ret = -1;
for (lvl = 0; lvl < BACK_TRACE_LIMIT; lvl++) {
ret = backtraceFromStack(&bt_sp, &bt_pc, NULL);
if (ret != 0) {
break;
}
}
if (ret == 1) {
/* assume right! print */
k_int2str((int)PC, &s_panic_call[14]);
if (print_func != NULL) {
print_func(s_panic_call);
}
bt_sp = SP;
bt_pc = PC;
ret = -1;
for (lvl = 1; lvl < BACK_TRACE_LIMIT; lvl++) {
ret = backtraceFromStack(&bt_sp, &bt_pc, print_func);
if (ret != 0) {
break;
}
}
return lvl;
}
return 0;
}
/* backtrace start with PC SP and LR */
int panicBacktraceCallee(char *PC, int *SP, char *LR,
int (*print_func)(const char *fmt, ...))
{
int *bt_sp;
char *bt_pc;
char *bt_lr;
int lvl, ret;
char s_panic_call[] = "backtrace : 0x \r\n";
if (SP == NULL) {
return 0;
}
/* Backtrace: assume ReturnAddr is saved in LR when exception */
k_int2str((int)PC, &s_panic_call[14]);
if (print_func != NULL) {
print_func(s_panic_call);
}
lvl = 1;
bt_sp = SP;
bt_pc = PC;
bt_lr = LR;
ret = backtraceFromLR(&bt_sp, &bt_pc, bt_lr, print_func);
if (ret == 0) {
for (; lvl < BACK_TRACE_LIMIT; lvl++) {
ret = backtraceFromStack(&bt_sp, &bt_pc, print_func);
if (ret != 0) {
break;
}
}
}
return lvl;
}
#endif
#endif

View file

@ -0,0 +1,154 @@
#include "k_config.h"
#include "k_dftdbg_config.h"
@******************************************************************************
@ EQUATES
@******************************************************************************
.equ CONTEXT_REGION, 88 @bigger than sizeof(PANIC_CONTEXT)
@******************************************************************************
@ CODE GENERATION DIRECTIVES
@******************************************************************************
.text
.align 2
.thumb
.syntax unified
#if (RHINO_CONFIG_PANIC > 0)
@******************************************************************************
@ EXTERN PARAMETERS
@******************************************************************************
.extern panicHandler
.extern g_crash_steps
.extern _first_task_restore
.extern panicRestoreCheck
@******************************************************************************
@ EXPORT FUNCTIONS
@******************************************************************************
.global HardFault_Handler
.global MemManage_Handler
.global BusFault_Handler
.global UsageFault_Handler
@******************************************************************************
@ FAULT FUNCTIONS
@******************************************************************************
.thumb_func
HardFault_Handler:
.thumb_func
MemManage_Handler:
.thumb_func
BusFault_Handler:
.thumb_func
UsageFault_Handler:
PUSH {R1, LR}
BL panicRestoreCheck
POP {R1, LR}
CBZ R0, unrecoverable_crash
BL _first_task_restore
unrecoverable_crash:
@check double crash
LDR R1, =g_crash_steps
LDR R2, [R1]
ADD R3, R2, #1
STR R3, [R1]
CBZ R2, first_panic
@return from exc to handle panic
MRS R1, PSP
AND R2, LR, #4 @EXC_RETURN:bit2, 0 MSP, 1 PSP
CBNZ R2, double_panic
MRS R1, MSP
double_panic:
LDR R0, =double_panic_entry
STR R0, [R1, #24]
LDR R0, [R1, #28]
ORR R0, R0, #0x1000000
STR R0, [R1, #28] @set thumb mode
BX LR
double_panic_entry:
MOV R0, #0 @double crash, do not save context
BL panicHandler
B .
first_panic:
@R0 as PANIC_CONTEXT
SUB R0, SP, #CONTEXT_REGION
@R1 as CONTEXT saved by hardware
MRS R1, PSP
AND R2, LR, #4 @EXC_RETURN:bit2, 0 MSP, 1 PSP
CBNZ R2, context_save
MRS R1, MSP
context_save:
ADD R2, R0, #16
STM R2!,{R4-R11} @ctx save, R4~R11
LDM R1, {R4-R11}
STM R0, {R4-R7} @ctx save, R0~R3
STM R2!,{R8-R11} @ctx save, R12 LR PC xPSR
@xPSR[9] and EXC_RETURN[4] to determine whether
@the previous top-of-stack was at offset 0x20, 0x24, 0x68, or0x6C
ADD R4, R1, #0x20
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
AND R3, LR, #0x10 @EXC_RETURN:bit4, 0 floating, 1 non-floating
CBNZ R3, check_aligner
ADD R4, R4, #0x48
check_aligner:
#endif
LDR R3, [R1, #28]
AND R3, R3, #0x200 @xPSR:bit9, 0 no-aligner, 1 aligner
CBZ R3, sp_save
ADD R4, R4, #0x4
sp_save:
STM R2!,{R4} @ctx save, SP
MOV R4, LR
STM R2!,{R4} @ctx save, EXC_RETURN
MRS R4, IPSR
STM R2!,{R4} @ctx save, EXC_NUMBER
MRS R4, PRIMASK
STM R2!,{R4} @ctx save, PRIMASK
MRS R4, FAULTMASK
STM R2!,{R4} @ctx save, FAULTMASK
MRS R4, BASEPRI
STM R2!,{R4} @ctx save, BASEPRI
@return from exc to handle panic
STR R0, [R1, #0]
LDR R0, =panic_entry
STR R0, [R1, #24]
LDR R0, [R1, #28]
ORR R0, R0, #0x1000000
STR R0, [R1, #28] @set thumb mode
CPSID I
BX LR
panic_entry:
#if (RHINO_CONFIG_PANIC_PRT_INT > 0)
MRS R1, CONTROL
MOVS R2, #2
BICS R1, R2
MSR CONTROL, R1
ISB
@printf use interrupt, so here enable it
CPSIE I
#endif
MOV SP, R0
BL panicHandler
B .
#endif
.end

View file

@ -0,0 +1,151 @@
#include "k_config.h"
#include "k_dftdbg_config.h"
;******************************************************************************
; EQUATES
;******************************************************************************
CONTEXT_REGION EQU 88 ;bigger than sizeof(PANIC_CONTEXT)
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
SECTION .text:CODE(2)
THUMB
REQUIRE8
PRESERVE8
#if (RHINO_CONFIG_PANIC > 0)
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
EXTERN panicHandler
EXTERN g_crash_steps
EXTERN _first_task_restore
EXTERN panicRestoreCheck
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
PUBLIC HardFault_Handler
PUBLIC MemManage_Handler
PUBLIC BusFault_Handler
PUBLIC UsageFault_Handler
;******************************************************************************
; FAULT FUNCTIONS
;******************************************************************************
HardFault_Handler:
MemManage_Handler:
BusFault_Handler:
UsageFault_Handler:
PUSH {R1, LR}
BL panicRestoreCheck
POP {R1, LR}
CBZ R0, unrecoverable_crash
BL _first_task_restore
unrecoverable_crash:
;check double crash
LDR R1, =g_crash_steps
LDR R2, [R1]
ADD R3, R2, #1
STR R3, [R1]
CBZ R2, first_panic
;return from exc to handle panic
MRS R1, PSP
AND R2, LR, #4 ;EXC_RETURN:bit2, 0 MSP, 1 PSP
CBNZ R2, double_panic
MRS R1, MSP
double_panic:
LDR R0, =double_panic_entry
STR R0, [R1, #24]
LDR R0, [R1, #28]
ORR R0, R0, #0x1000000
STR R0, [R1, #28] ;set thumb mode
BX LR
double_panic_entry:
MOV R0, #0 ;double crash, do not save context
BL panicHandler
B .
first_panic:
;R0 as PANIC_CONTEXT
SUB R0, SP, #CONTEXT_REGION
;R1 as CONTEXT saved by hardware
MRS R1, PSP
AND R2, LR, #4 ;EXC_RETURN:bit2, 0 MSP, 1 PSP
CBNZ R2, context_save
MRS R1, MSP
context_save:
ADD R2, R0, #16
STM R2!,{R4-R11} ;ctx save, R4~R11
LDM R1, {R4-R11}
STM R0, {R4-R7} ;ctx save, R0~R3
STM R2!,{R8-R11} ;ctx save, R12 LR PC xPSR
;xPSR[9] and EXC_RETURN[4] to determine whether
;the previous top-of-stack was at offset 0x20, 0x24, 0x68, or0x6C
ADD R4, R1, #0x20
#if defined(__ARMVFP__)
AND R3, LR, #0x10 ;EXC_RETURN:bit4, 0 floating, 1 non-floating
CBNZ R3, check_aligner
ADD R4, R4, #0x48
check_aligner:
#endif
LDR R3, [R1, #28]
AND R3, R3, #0x200 ;xPSR:bit9, 0 no-aligner, 1 aligner
CBZ R3, sp_save
ADD R4, R4, #0x4
sp_save:
STM R2!,{R4} ;ctx save, SP
MOV R4, LR
STM R2!,{R4} ;ctx save, EXC_RETURN
MRS R4, IPSR
STM R2!,{R4} ;ctx save, EXC_NUMBER
MRS R4, PRIMASK
STM R2!,{R4} ;ctx save, PRIMASK
MRS R4, FAULTMASK
STM R2!,{R4} ;ctx save, FAULTMASK
MRS R4, BASEPRI
STM R2!,{R4} ;ctx save, BASEPRI
;return from exc to handle panic
STR R0, [R1, #0]
LDR R0, =panic_entry
STR R0, [R1, #24]
LDR R0, [R1, #28]
ORR R0, R0, #0x1000000
STR R0, [R1, #28] ;set thumb mode
CPSID I
BX LR
panic_entry:
#if (RHINO_CONFIG_PANIC_PRT_INT > 0)
MRS R1, CONTROL
MOVS R2, #2
BICS R1, R2
MSR CONTROL, R1
ISB
;printf use interrupt, so here enable it
CPSIE I
#endif
MOV SP, R0
BL panicHandler
B .
#endif
END

View file

@ -0,0 +1,224 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include "panic_mpu.h"
#include "k_compiler.h"
#include "k_dbg_api.h"
typedef struct {
unsigned long start;
unsigned long size;
unsigned long mpusize;
} mem_region_t;
#if (RHINO_CONFIG_PANIC > 0)
static void mpu_enable(void);
static void mpu_disable(void);
static void mpu_config_region(MPU_Region_Init_t *init);
static unsigned int size_to_mpusize(unsigned int size);
/*
* Func: mpu is valid in mcu
* IN : none
* Out : 0 -- valid; 1 -- invalid
* */
static unsigned int mpu_is_valid(void)
{
return ((MPU->type) & MPU_TYPE_DREGION_MASK == 0) ? 1: 0;
}
static void mpu_enable(void)
{
MPU->ctrl = MPU_CTRL_ENABLE_MASK | MPU_CTRL_PRIVDEFENA_MASK;
/* Enable memory manage fault */
*(SHCSR_M) |= (1<<16);
OS_DSB();
OS_ISB();
OS_DMB();
}
static void mpu_disable(void)
{
MPU->ctrl = 0U;
OS_DSB();
OS_ISB();
OS_DMB();
}
static void enable_region(mem_region_t *region, int rng_no,
int subregion_disable, int ext_type,
int access_permission, int disable_exec,
int shareable, int cacheable, int bufferable)
{
MPU_Region_Init_t init;
init.range_no = rng_no;
init.base_addr = region->start;
init.size = region->mpusize;
init.subregion_disable = subregion_disable;
init.ext_type = ext_type;
init.access_permission = access_permission;
init.disable_exec = disable_exec;
init.shareable = shareable;
init.cacheable = cacheable;
init.bufferable = bufferable;
init.enable = 1;
mpu_config_region(&init);
}
static void mpu_config_region(MPU_Region_Init_t *init)
{
MPU->rnr = init->range_no;
if (init->enable) {
MPU->rbar = init->base_addr;
MPU->rasr = (init->disable_exec << MPU_RASR_XN_OFFSET
| init->access_permission << MPU_RASR_AP_OFFSET
| init->ext_type << MPU_RASR_TEX_OFFSET
| init->shareable << MPU_RASR_S_OFFSET
| init->cacheable << MPU_RASR_C_OFFSET
| init->bufferable << MPU_RASR_B_OFFSET
| init->subregion_disable << MPU_RASR_SRD_OFFSET
| init->size << MPU_RASR_SIZE_OFFSET
| init->enable << MPU_RASR_ENABLE_OFFSET);
} else {
MPU->rbar = 0;
MPU->rasr = 0;
}
OS_DSB();
OS_ISB();
OS_DMB();
}
static unsigned int size_to_mpusize(unsigned int size)
{
switch (size) {
case 0x20: return MPU_REGION_SIZE_32B;
case 0x40: return MPU_REGION_SIZE_64B;
case 0x80: return MPU_REGION_SIZE_128B;
case 0x100: return MPU_REGION_SIZE_256B;
case 0x200: return MPU_REGION_SIZE_512B;
case 0x400: return MPU_REGION_SIZE_1KB;
case 0x800: return MPU_REGION_SIZE_2KB;
case 0x1000: return MPU_REGION_SIZE_4KB;
case 0x2000: return MPU_REGION_SIZE_8KB;
case 0x4000: return MPU_REGION_SIZE_16KB;
case 0x8000: return MPU_REGION_SIZE_32KB;
case 0x10000: return MPU_REGION_SIZE_64KB;
case 0x20000: return MPU_REGION_SIZE_128KB;
case 0x40000: return MPU_REGION_SIZE_256KB;
case 0x80000: return MPU_REGION_SIZE_512KB;
case 0x100000: return MPU_REGION_SIZE_1MB;
case 0x200000: return MPU_REGION_SIZE_2MB;
case 0x400000: return MPU_REGION_SIZE_4MB;
case 0x800000: return MPU_REGION_SIZE_8MB;
case 0x1000000: return MPU_REGION_SIZE_16MB;
case 0x2000000: return MPU_REGION_SIZE_32MB;
case 0x4000000: return MPU_REGION_SIZE_64MB;
case 0x8000000: return MPU_REGION_SIZE_128MB;
case 0x10000000: return MPU_REGION_SIZE_256MB;
case 0x20000000: return MPU_REGION_SIZE_512MB;
case 0x40000000: return MPU_REGION_SIZE_1GB;
case 0x80000000: return MPU_REGION_SIZE_2GB;
default: return 0;
}
}
static void mpu_set(unsigned long addr, unsigned long size, unsigned int mode)
{
mem_region_t region;
region.start = addr;
region.size = size;
region.mpusize = size_to_mpusize(region.size);
mpu_disable();
enable_region(&region, 0, 0, 0, mode, 0, 0, 1, 1);
mpu_enable();
}
static unsigned int mpu_check(unsigned long addr, unsigned long size)
{
if ((size < 0x20) || (size > 0x80000000)) {
printf("mpu region size error\r\n");
return 1;
}
if (mpu_is_valid() != 0) {
printf("error:no mpu in mcu\r\n");
return 1;
}
return 0;
}
/**
* set mpu region for memory unauthorized access check
*
* @param[in] addr_start monitor start addr
* @param[in] addr_size monitor size
* @param[in] mode prohibit access (0) or read only(>0)
*/
void debug_memory_access_err_check(unsigned long addr_start, unsigned long addr_size, unsigned int mode)
{
unsigned int mpu_region_type;
if (mpu_check(addr_start, addr_size) != 0)
return;
if ((addr_start % addr_size) != 0)
addr_start = (addr_start + (addr_size - 1)) & ~(addr_size - 1);
if (mode > 0) {
mpu_region_type = MPU_AP_RO_NA;
} else
mpu_region_type = MPU_AP_NA_NA;
mpu_set(addr_start, addr_size, mpu_region_type);
printf("mpu addr: 0x%x\n", addr_start);
}
void debug_task_stack_ovf_check(char *task_name)
{
int ret;
ktask_t *task;
cpu_stack_t *task_stack_base;
if (task_name == NULL) {
printf("error: task name invalid\r\n");
return;
}
task = krhino_task_find(task_name);
if (task == NULL) {
printf("error: task do not exist\r\n");
return;
}
task_stack_base = task->task_stack_base;
if (task_stack_base == NULL) {
printf("error: task_stack_base err\r\n");
return;
}
debug_memory_access_err_check((unsigned long)task_stack_base, 0x20, 1);
}
void debug_check_mem_access_disable(void)
{
mpu_disable();
}
#endif

View file

@ -0,0 +1,187 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef MPU_H
#define MPU_H
typedef struct {
// MPU type register
unsigned int type;
// MPU control register
unsigned int ctrl;
// MPU range number register
unsigned int rnr;
// MPU region base address register
unsigned int rbar;
// MPU region attribute and size register
unsigned int rasr;
// MPU alias registers
unsigned int rbar_a1;
unsigned int rasr_a1;
unsigned int rbar_a2;
unsigned int rasr_a2;
unsigned int rbar_a3;
unsigned int rasr_a3;
} MPU_t;
/* System Handler Control and State register */
#define SHCSR_M ((unsigned int*)0xE000ED24UL)
/* MPU registers */
#define MPU_BASE (0xE000ED90UL)
#define MPU ((MPU_t*)(MPU_BASE))
#define MPU_TYPE_IREGION_OFFSET (16U)
#define MPU_TYPE_IREGION_MASK (0xFFUL << MPU_TYPE_IREGION_OFFSET)
#define MPU_TYPE_DREGION_OFFSET (8U)
#define MPU_TYPE_DREGION_MASK (0xFFUL << MPU_TYPE_DREGION_OFFSET)
#define MPU_TYPE_SEPARATE_OFFSET (0U)
#define MPU_TYPE_SEPARATE_MASK (1UL)
#define MPU_CTRL_PRIVDEFENA_OFFSET (2U)
#define MPU_CTRL_PRIVDEFENA_MASK (1UL << MPU_CTRL_PRIVDEFENA_OFFSET)
#define MPU_CTRL_HFNMIENA_OFFSET (1U)
#define MPU_CTRL_HFNMIENA_MASK (1UL << MPU_CTRL_HFNMIENA_OFFSET)
#define MPU_CTRL_ENABLE_OFFSET (0U)
#define MPU_CTRL_ENABLE_MASK (1UL)
#define MPU_RNR_REGION_OFFSET (0U)
#define MPU_RNR_REGION_MASK (0xFFUL)
#define MPU_RBAR_ADDR_OFFSET (5U)
#define MPU_RBAR_ADDR_MASK (0x7FFFFFFUL << MPU_RBAR_ADDR_OFFSET)
#define MPU_RBAR_VALID_OFFSET (4U)
#define MPU_RBAR_VALID_MASK (1UL << MPU_RBAR_VALID_OFFSET)
#define MPU_RBAR_REGION_OFFSET (0U)
#define MPU_RBAR_REGION_MASK (0xFUL)
#define MPU_RASR_ATTRS_OFFSET (16U)
#define MPU_RASR_ATTRS_MASK (0xFFFFUL << MPU_RASR_ATTRS_OFFSET)
#define MPU_RASR_XN_OFFSET (28U)
#define MPU_RASR_XN_MASK (1UL << MPU_RASR_XN_OFFSET)
#define MPU_RASR_AP_OFFSET (24U)
#define MPU_RASR_AP_MASK (0x7UL << MPU_RASR_AP_OFFSET)
#define MPU_RASR_TEX_OFFSET (19U)
#define MPU_RASR_TEX_MASK (0x7UL << MPU_RASR_TEX_OFFSET)
#define MPU_RASR_S_OFFSET (18U)
#define MPU_RASR_S_MASK (1UL << MPU_RASR_S_OFFSET)
#define MPU_RASR_C_OFFSET (17U)
#define MPU_RASR_C_MASK (1UL << MPU_RASR_C_OFFSET)
#define MPU_RASR_B_OFFSET (16U)
#define MPU_RASR_B_MASK (1UL << MPU_RASR_B_OFFSET)
#define MPU_RASR_SRD_OFFSET (8U)
#define MPU_RASR_SRD_MASK (0xFFUL << MPU_RASR_SRD_OFFSET)
#define MPU_RASR_SIZE_OFFSET (1U)
#define MPU_RASR_SIZE_MASK (0x1FUL << MPU_RASR_SIZE_OFFSET)
#define MPU_RASR_ENABLE_OFFSET (0U)
#define MPU_RASR_ENABLE_MASK (1UL)
/* MPU regions size */
#define MPU_REGION_SIZE_32B (0x04U)
#define MPU_REGION_SIZE_64B (0x05U)
#define MPU_REGION_SIZE_128B (0x06U)
#define MPU_REGION_SIZE_256B (0x07U)
#define MPU_REGION_SIZE_512B (0x08U)
#define MPU_REGION_SIZE_1KB (0x09U)
#define MPU_REGION_SIZE_2KB (0x0AU)
#define MPU_REGION_SIZE_4KB (0x0BU)
#define MPU_REGION_SIZE_8KB (0x0CU)
#define MPU_REGION_SIZE_16KB (0x0DU)
#define MPU_REGION_SIZE_32KB (0x0EU)
#define MPU_REGION_SIZE_64KB (0x0FU)
#define MPU_REGION_SIZE_128KB (0x10U)
#define MPU_REGION_SIZE_256KB (0x11U)
#define MPU_REGION_SIZE_512KB (0x12U)
#define MPU_REGION_SIZE_1MB (0x13U)
#define MPU_REGION_SIZE_2MB (0x14U)
#define MPU_REGION_SIZE_4MB (0x15U)
#define MPU_REGION_SIZE_8MB (0x16U)
#define MPU_REGION_SIZE_16MB (0x17U)
#define MPU_REGION_SIZE_32MB (0x18U)
#define MPU_REGION_SIZE_64MB (0x19U)
#define MPU_REGION_SIZE_128MB (0x1AU)
#define MPU_REGION_SIZE_256MB (0x1BU)
#define MPU_REGION_SIZE_512MB (0x1CU)
#define MPU_REGION_SIZE_1GB (0x1DU)
#define MPU_REGION_SIZE_2GB (0x1EU)
#define MPU_REGION_SIZE_4GB (0x1FU)
#define MPU_AP_NA_NA (0x00U)
#define MPU_AP_RW_NA (0x01U)
#define MPU_AP_RW_RO (0x02U)
#define MPU_AP_RW_RW (0x03U)
#define MPU_AP_RESV (0x04U)
#define MPU_AP_RO_NA (0x05U)
#define MPU_AP_RO_RO (0x06U)
typedef struct {
unsigned long base_addr;
unsigned char range_no;
unsigned char size;
unsigned char ext_type;
unsigned char access_permission;
unsigned char disable_exec;
unsigned char subregion_disable;
unsigned char shareable;
unsigned char cacheable;
unsigned char bufferable;
unsigned char enable;
} MPU_Region_Init_t;
#if (RHINO_CONFIG_PANIC > 0)
/**
* set mpu region for memory unauthorized access check
*
* @param[in] addr_start monitor start addr
* @param[in] addr_size monitor size
* @param[in] mode prohibit access(0) or read only(>0)
*/
void debug_memory_access_err_check(unsigned long addr_start, unsigned long addr_size, unsigned int mode);
void debug_task_stack_ovf_check(char *task_name);
void debug_check_mem_access_disable(void);
#endif
#endif // MPU_H

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
cpu_cpsr_t cpu_intrpt_save(void);
void cpu_intrpt_restore(cpu_cpsr_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() cpu_cpsr_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() do{cpsr = cpu_intrpt_save();}while(0)
#define RHINO_CPU_INTRPT_ENABLE() do{cpu_intrpt_restore(cpsr);}while(0)
#endif /* PORT_H */

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* task context saved & restore by hardware: */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* task context saved & restore by software: */
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + non-floating-point state + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* task context saved & restore by hardware: */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,168 @@
#include <k_config.h>
@******************************************************************************
@ EXTERN PARAMETERS
@******************************************************************************
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_stack_ovf_check
.extern krhino_task_sched_stats_get
@******************************************************************************
@ EXPORT FUNCTIONS
@******************************************************************************
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global PendSV_Handler
.global _first_task_restore
@******************************************************************************
@ EQUATES
@******************************************************************************
.equ SCB_ICSR, 0xE000ED04 @ Interrupt Control and State Register.
.equ SCB_VTOR, 0xE000ED08 @ Vector Table Offset Register.
.equ ICSR_PENDSVSET, 0x10000000 @ Value to trigger PendSV exception.
.equ SHPR3_PRI_14, 0xE000ED22 @ System Handler Priority Register 3 (PendSV).
.equ PRI_LVL_PENDSV, 0xFF @ PendSV priority level (lowest).
.equ SHPR3_PRI_15, 0xE000ED23 @ System Handler Priority Register 3 (Systick).
.equ PRI_LVL_SYSTICK, 0xFF @ SYstick priority level (lowest).
@******************************************************************************
@ CODE GENERATION DIRECTIVES
@******************************************************************************
.text
.align 2
.thumb
.syntax unified
@******************************************************************************
@ Functions:
@ size_t cpu_intrpt_save(void);
@ void cpu_intrpt_restore(size_t cpsr);
@******************************************************************************
.thumb_func
cpu_intrpt_save:
MRS R0, PRIMASK
CPSID I
BX LR
.thumb_func
cpu_intrpt_restore:
MSR PRIMASK, R0
BX LR
@******************************************************************************
@ Functions:
@ void cpu_intrpt_switch(void);
@ void cpu_task_switch(void);
@******************************************************************************
.thumb_func
cpu_task_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
.thumb_func
cpu_intrpt_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
@******************************************************************************
@ Functions:
@ void cpu_first_task_start(void);
@******************************************************************************
.thumb_func
cpu_first_task_start:
@set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14
LDR R1, =PRI_LVL_PENDSV
STRB R1, [R0]
@set Systick prority to the lowest
LDR R0, =SHPR3_PRI_15
LDR R1, =PRI_LVL_SYSTICK
STRB R1, [R0]
@indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
@make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
@goto PendSV_Handler
CPSIE I
B .
@******************************************************************************
@ Functions:
@ void krhino_pendsv_handler(void);
@******************************************************************************
.thumb_func
PendSV_Handler:
CPSID I
MRS R0, PSP
@branch if cpu_first_task_start
CMP R0, #0
BEQ _first_task_restore
@hardware saved R0~R3,R12,LR,PC,xPSR
@save context
SUBS R0, R0, #0x24
STM R0, {R4-R11, LR}
@g_active_task->task_stack = context region
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
.thumb_func
_pendsv_handler_nosave:
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
@R0 = g_active_task->task_stack = context region
LDR R0, [R2]
@restore context
LDM R0, {R4-R11, LR}
ADDS R0, R0, #0x24
@return stack = PSP
MSR PSP, R0
CPSIE I
@hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
.thumb_func
_first_task_restore:
@set MSP to the base of system stack
LDR R0, =SCB_VTOR
LDR R0, [R0]
LDR R0, [R0]
MSR MSP, R0
B _pendsv_handler_nosave
.end

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
/* ARMCC || IAR || GNU */
#define FPU_AVL ((defined(__CC_ARM) && defined(__TARGET_FPU_VFP)) \
|| (defined(__ICCARM__) && defined(__ARMVFP__)) \
|| (defined(__GNUC__) && defined(__VFP_FP__) && !defined(__SOFTFP__)))
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* Exception stack frame with non-floating-point state */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* in PendSV_Handler, D8~D15 is always saved & restroe */
#if (FPU_AVL > 0)
*(--stk) = (cpu_stack_t)0x31uL; /* S31 */
*(--stk) = (cpu_stack_t)0x30uL; /* S30 */
*(--stk) = (cpu_stack_t)0x29uL; /* S29 */
*(--stk) = (cpu_stack_t)0x28uL; /* S28 */
*(--stk) = (cpu_stack_t)0x27uL; /* S27 */
*(--stk) = (cpu_stack_t)0x26uL; /* S26 */
*(--stk) = (cpu_stack_t)0x25uL; /* S25 */
*(--stk) = (cpu_stack_t)0x24uL; /* S24 */
*(--stk) = (cpu_stack_t)0x23uL; /* S23 */
*(--stk) = (cpu_stack_t)0x22uL; /* S22 */
*(--stk) = (cpu_stack_t)0x21uL; /* S21 */
*(--stk) = (cpu_stack_t)0x20uL; /* S20 */
*(--stk) = (cpu_stack_t)0x19uL; /* S19 */
*(--stk) = (cpu_stack_t)0x18uL; /* S18 */
*(--stk) = (cpu_stack_t)0x17uL; /* S17 */
*(--stk) = (cpu_stack_t)0x16uL; /* S16 */
#endif
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + non-floating-point state + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,184 @@
#include <k_config.h>
@******************************************************************************
@ EXTERN PARAMETERS
@******************************************************************************
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_stack_ovf_check
.extern krhino_task_sched_stats_get
@******************************************************************************
@ EXPORT FUNCTIONS
@******************************************************************************
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global PendSV_Handler
.global _first_task_restore
@******************************************************************************
@ EQUATES
@******************************************************************************
.equ SCB_ICSR, 0xE000ED04 @ Interrupt Control and State Register.
.equ SCB_VTOR, 0xE000ED08 @ Vector Table Offset Register.
.equ ICSR_PENDSVSET, 0x10000000 @ Value to trigger PendSV exception.
.equ SHPR3_PRI_14, 0xE000ED22 @ System Handler Priority Register 3 (PendSV).
.equ PRI_LVL_PENDSV, 0xFF @ PendSV priority level (lowest).
.equ SHPR3_PRI_15, 0xE000ED23 @ System Handler Priority Register 3 (Systick).
.equ PRI_LVL_SYSTICK, 0xFF @ SYstick priority level (lowest).
@******************************************************************************
@ CODE GENERATION DIRECTIVES
@******************************************************************************
.text
.align 2
.thumb
.syntax unified
@******************************************************************************
@ Functions:
@ size_t cpu_intrpt_save(void);
@ void cpu_intrpt_restore(size_t cpsr);
@******************************************************************************
.thumb_func
cpu_intrpt_save:
MRS R0, PRIMASK
CPSID I
BX LR
.thumb_func
cpu_intrpt_restore:
MSR PRIMASK, R0
BX LR
@******************************************************************************
@ Functions:
@ void cpu_intrpt_switch(void);
@ void cpu_task_switch(void);
@******************************************************************************
.thumb_func
cpu_task_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
.thumb_func
cpu_intrpt_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
@******************************************************************************
@ Functions:
@ void cpu_first_task_start(void);
@******************************************************************************
.thumb_func
cpu_first_task_start:
@set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14
LDR R1, =PRI_LVL_PENDSV
STRB R1, [R0]
@set Systick prority to the lowest
LDR R0, =SHPR3_PRI_15
LDR R1, =PRI_LVL_SYSTICK
STRB R1, [R0]
@indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
@make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
@goto PendSV_Handler
CPSIE I
B .
@******************************************************************************
@ Functions:
@ void krhino_pendsv_handler(void);
@******************************************************************************
.thumb_func
PendSV_Handler:
CPSID I
MRS R0, PSP
@branch if cpu_first_task_start
CMP R0, #0
BEQ _first_task_restore
@hardware saved R0~R3,R12,LR,PC,xPSR
@save context
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
@if the switchout task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VSTMDBEQ R0!, {D8 - D15}
@hardware saved D0~D7, FPSCR
#endif
SUBS R0, R0, #0x24
STM R0, {R4-R11, LR}
@g_active_task->task_stack = context region
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
.thumb_func
_pendsv_handler_nosave:
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
@R0 = g_active_task->task_stack = context region
LDR R0, [R2]
@restore context
LDM R0, {R4-R11, LR}
ADDS R0, R0, #0x24
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
@if the switchin task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VLDMIAEQ R0!, {D8 - D15}
@hardware will restore D0~D7, FPSCR
#endif
@return stack = PSP
MSR PSP, R0
CPSIE I
@hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
.thumb_func
_first_task_restore:
@set MSP to the base of system stack
LDR R0, =SCB_VTOR
LDR R0, [R0]
LDR R0, [R0]
MSR MSP, R0
B _pendsv_handler_nosave
.end

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
/* ARMCC || IAR || GNU */
#define FPU_AVL ((defined(__CC_ARM) && defined(__TARGET_FPU_VFP)) \
|| (defined(__ICCARM__) && defined(__ARMVFP__)) \
|| (defined(__GNUC__) && defined(__VFP_FP__) && !defined(__SOFTFP__)))
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* Exception stack frame with non-floating-point state */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* in PendSV_Handler, D8~D15 is always saved & restroe */
#if (FPU_AVL > 0)
*(--stk) = (cpu_stack_t)0x31uL; /* S31 */
*(--stk) = (cpu_stack_t)0x30uL; /* S30 */
*(--stk) = (cpu_stack_t)0x29uL; /* S29 */
*(--stk) = (cpu_stack_t)0x28uL; /* S28 */
*(--stk) = (cpu_stack_t)0x27uL; /* S27 */
*(--stk) = (cpu_stack_t)0x26uL; /* S26 */
*(--stk) = (cpu_stack_t)0x25uL; /* S25 */
*(--stk) = (cpu_stack_t)0x24uL; /* S24 */
*(--stk) = (cpu_stack_t)0x23uL; /* S23 */
*(--stk) = (cpu_stack_t)0x22uL; /* S22 */
*(--stk) = (cpu_stack_t)0x21uL; /* S21 */
*(--stk) = (cpu_stack_t)0x20uL; /* S20 */
*(--stk) = (cpu_stack_t)0x19uL; /* S19 */
*(--stk) = (cpu_stack_t)0x18uL; /* S18 */
*(--stk) = (cpu_stack_t)0x17uL; /* S17 */
*(--stk) = (cpu_stack_t)0x16uL; /* S16 */
#endif
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + non-floating-point state + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,184 @@
#include <k_config.h>
@******************************************************************************
@ EXTERN PARAMETERS
@******************************************************************************
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_stack_ovf_check
.extern krhino_task_sched_stats_get
@******************************************************************************
@ EXPORT FUNCTIONS
@******************************************************************************
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global PendSV_Handler
.global _first_task_restore
@******************************************************************************
@ EQUATES
@******************************************************************************
.equ SCB_ICSR, 0xE000ED04 @ Interrupt Control and State Register.
.equ SCB_VTOR, 0xE000ED08 @ Vector Table Offset Register.
.equ ICSR_PENDSVSET, 0x10000000 @ Value to trigger PendSV exception.
.equ SHPR3_PRI_14, 0xE000ED22 @ System Handler Priority Register 3 (PendSV).
.equ PRI_LVL_PENDSV, 0xFF @ PendSV priority level (lowest).
.equ SHPR3_PRI_15, 0xE000ED23 @ System Handler Priority Register 3 (Systick).
.equ PRI_LVL_SYSTICK, 0xFF @ SYstick priority level (lowest).
@******************************************************************************
@ CODE GENERATION DIRECTIVES
@******************************************************************************
.text
.align 2
.thumb
.syntax unified
@******************************************************************************
@ Functions:
@ size_t cpu_intrpt_save(void);
@ void cpu_intrpt_restore(size_t cpsr);
@******************************************************************************
.thumb_func
cpu_intrpt_save:
MRS R0, PRIMASK
CPSID I
BX LR
.thumb_func
cpu_intrpt_restore:
MSR PRIMASK, R0
BX LR
@******************************************************************************
@ Functions:
@ void cpu_intrpt_switch(void);
@ void cpu_task_switch(void);
@******************************************************************************
.thumb_func
cpu_task_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
.thumb_func
cpu_intrpt_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
@******************************************************************************
@ Functions:
@ void cpu_first_task_start(void);
@******************************************************************************
.thumb_func
cpu_first_task_start:
@set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14
LDR R1, =PRI_LVL_PENDSV
STRB R1, [R0]
@set Systick prority to the lowest
LDR R0, =SHPR3_PRI_15
LDR R1, =PRI_LVL_SYSTICK
STRB R1, [R0]
@indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
@make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
@goto PendSV_Handler
CPSIE I
B .
@******************************************************************************
@ Functions:
@ void krhino_pendsv_handler(void);
@******************************************************************************
.thumb_func
PendSV_Handler:
CPSID I
MRS R0, PSP
@branch if cpu_first_task_start
CMP R0, #0
BEQ _first_task_restore
@hardware saved R0~R3,R12,LR,PC,xPSR
@save context
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
@if the switchout task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VSTMDBEQ R0!, {D8 - D15}
@hardware saved D0~D7, FPSCR
#endif
SUBS R0, R0, #0x24
STM R0, {R4-R11, LR}
@g_active_task->task_stack = context region
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
.thumb_func
_pendsv_handler_nosave:
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
@R0 = g_active_task->task_stack = context region
LDR R0, [R2]
@restore context
LDM R0, {R4-R11, LR}
ADDS R0, R0, #0x24
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
@if the switchin task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VLDMIAEQ R0!, {D8 - D15}
@hardware will restore D0~D7, FPSCR
#endif
@return stack = PSP
MSR PSP, R0
CPSIE I
@hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
.thumb_func
_first_task_restore:
@set MSP to the base of system stack
LDR R0, =SCB_VTOR
LDR R0, [R0]
LDR R0, [R0]
MSR MSP, R0
B _pendsv_handler_nosave
.end

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* task context saved & restore by hardware: */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,160 @@
#include <k_config.h>
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
EXTERN g_active_task
EXTERN g_preferred_ready_task
EXTERN krhino_stack_ovf_check
EXTERN krhino_task_sched_stats_get
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
PUBLIC cpu_intrpt_save
PUBLIC cpu_intrpt_restore
PUBLIC cpu_task_switch
PUBLIC cpu_intrpt_switch
PUBLIC cpu_first_task_start
PUBLIC _first_task_restore
PUBLIC PendSV_Handler
;******************************************************************************
; EQUATES
;******************************************************************************
SCB_ICSR EQU 0xE000ED04 ; Interrupt Control and State Register.
SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register.
ICSR_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
SHPR3_PRI_14 EQU 0xE000ED22 ; System Handler Priority Register 3 (PendSV).
PRI_LVL_PENDSV EQU 0xFF ; PendSV priority level (lowest).
SHPR3_PRI_15 EQU 0xE000ED23 ; System Handler Priority Register 3 (SysTick).
PRI_LVL_SYSTICK EQU 0xFF ; SYstick priority level (lowest).
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
SECTION .text:CODE(2)
THUMB
REQUIRE8
PRESERVE8
;******************************************************************************
; Functions:
; size_t cpu_intrpt_save(void);
; void cpu_intrpt_restore(size_t cpsr);
;******************************************************************************
cpu_intrpt_save:
MRS R0, PRIMASK
CPSID I
BX LR
cpu_intrpt_restore:
MSR PRIMASK, R0
BX LR
;******************************************************************************
; Functions:
; void cpu_intrpt_switch(void);
; void cpu_task_switch(void);
;******************************************************************************
cpu_task_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
cpu_intrpt_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
;******************************************************************************
; Functions:
; void cpu_first_task_start(void);
;******************************************************************************
cpu_first_task_start:
;set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14
LDR R1, =PRI_LVL_PENDSV
STRB R1, [R0]
;set Systick prority to the lowest
LDR R0, =SHPR3_PRI_15
LDR R1, =PRI_LVL_SYSTICK
STRB R1, [R0]
;indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
;make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
;goto PendSV_Handler
CPSIE I
B .
;******************************************************************************
; Functions:
; void krhino_pendsv_handler(void);
;******************************************************************************
PendSV_Handler:
CPSID I
MRS R0, PSP
;branch if cpu_first_task_start
CMP R0, #0
BEQ _first_task_restore
;hardware saved R0~R3,R12,LR,PC,xPSR
;save context
SUBS R0, R0, #0x24
STM R0, {R4-R11, LR}
;g_active_task->task_stack = context region
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
_pendsv_handler_nosave:
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
;R0 = g_active_task->task_stack = context region
LDR R0, [R2]
;restore context
LDM R0, {R4-R11, LR}
ADDS R0, R0, #0x24
;return stack = PSP
MSR PSP, R0
CPSIE I
;hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
_first_task_restore:
;set MSP to the base of system stack
LDR R0, =SCB_VTOR
LDR R0, [R0]
LDR R0, [R0]
MSR MSP, R0
B _pendsv_handler_nosave
END

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
/* ARMCC || IAR || GNU */
#define FPU_AVL ((defined(__CC_ARM) && defined(__TARGET_FPU_VFP)) \
|| (defined(__ICCARM__) && defined(__ARMVFP__)) \
|| (defined(__GNUC__) && defined(__VFP_FP__) && !defined(__SOFTFP__)))
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* Exception stack frame with non-floating-point state */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* in PendSV_Handler, D8~D15 is always saved & restroe */
#if (FPU_AVL > 0)
*(--stk) = (cpu_stack_t)0x31uL; /* S31 */
*(--stk) = (cpu_stack_t)0x30uL; /* S30 */
*(--stk) = (cpu_stack_t)0x29uL; /* S29 */
*(--stk) = (cpu_stack_t)0x28uL; /* S28 */
*(--stk) = (cpu_stack_t)0x27uL; /* S27 */
*(--stk) = (cpu_stack_t)0x26uL; /* S26 */
*(--stk) = (cpu_stack_t)0x25uL; /* S25 */
*(--stk) = (cpu_stack_t)0x24uL; /* S24 */
*(--stk) = (cpu_stack_t)0x23uL; /* S23 */
*(--stk) = (cpu_stack_t)0x22uL; /* S22 */
*(--stk) = (cpu_stack_t)0x21uL; /* S21 */
*(--stk) = (cpu_stack_t)0x20uL; /* S20 */
*(--stk) = (cpu_stack_t)0x19uL; /* S19 */
*(--stk) = (cpu_stack_t)0x18uL; /* S18 */
*(--stk) = (cpu_stack_t)0x17uL; /* S17 */
*(--stk) = (cpu_stack_t)0x16uL; /* S16 */
#endif
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + non-floating-point state + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,176 @@
#include <k_config.h>
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
EXTERN g_active_task
EXTERN g_preferred_ready_task
EXTERN krhino_stack_ovf_check
EXTERN krhino_task_sched_stats_get
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
PUBLIC cpu_intrpt_save
PUBLIC cpu_intrpt_restore
PUBLIC cpu_task_switch
PUBLIC cpu_intrpt_switch
PUBLIC cpu_first_task_start
PUBLIC _first_task_restore
PUBLIC PendSV_Handler
;******************************************************************************
; EQUATES
;******************************************************************************
SCB_ICSR EQU 0xE000ED04 ; Interrupt Control and State Register.
SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register.
ICSR_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
SHPR3_PRI_14 EQU 0xE000ED22 ; System Handler Priority Register 3 (PendSV).
PRI_LVL_PENDSV EQU 0xFF ; PendSV priority level (lowest).
SHPR3_PRI_15 EQU 0xE000ED23 ; System Handler Priority Register 3 (SysTick).
PRI_LVL_SYSTICK EQU 0xFF ; SYstick priority level (lowest).
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
SECTION .text:CODE(2)
THUMB
REQUIRE8
PRESERVE8
;******************************************************************************
; Functions:
; size_t cpu_intrpt_save(void);
; void cpu_intrpt_restore(size_t cpsr);
;******************************************************************************
cpu_intrpt_save:
MRS R0, PRIMASK
CPSID I
BX LR
cpu_intrpt_restore:
MSR PRIMASK, R0
BX LR
;******************************************************************************
; Functions:
; void cpu_intrpt_switch(void);
; void cpu_task_switch(void);
;******************************************************************************
cpu_task_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
cpu_intrpt_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
;******************************************************************************
; Functions:
; void cpu_first_task_start(void);
;******************************************************************************
cpu_first_task_start:
;set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14
LDR R1, =PRI_LVL_PENDSV
STRB R1, [R0]
;set Systick prority to the lowest
LDR R0, =SHPR3_PRI_15
LDR R1, =PRI_LVL_SYSTICK
STRB R1, [R0]
;indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
;make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
;goto PendSV_Handler
CPSIE I
B .
;******************************************************************************
; Functions:
; void krhino_pendsv_handler(void);
;******************************************************************************
PendSV_Handler:
CPSID I
MRS R0, PSP
;branch if cpu_first_task_start
CMP R0, #0
BEQ _first_task_restore
;hardware saved R0~R3,R12,LR,PC,xPSR
;save context
#if defined(__ARMVFP__)
;if the switchout task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VSTMDBEQ R0!, {D8 - D15}
;hardware saved D0~D7, FPSCR
#endif
SUBS R0, R0, #0x24
STM R0, {R4-R11, LR}
;g_active_task->task_stack = context region
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
_pendsv_handler_nosave:
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
;R0 = g_active_task->task_stack = context region
LDR R0, [R2]
;restore context
LDM R0, {R4-R11, LR}
ADDS R0, R0, #0x24
#if defined(__ARMVFP__)
;if the switchin task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VLDMIAEQ R0!, {D8 - D15}
;hardware will restore D0~D7, FPSCR
#endif
;return stack = PSP
MSR PSP, R0
CPSIE I
;hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
_first_task_restore:
;set MSP to the base of system stack
LDR R0, =SCB_VTOR
LDR R0, [R0]
LDR R0, [R0]
MSR MSP, R0
B _pendsv_handler_nosave
END

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
typedef uint32_t hr_timer_t;
typedef uint32_t lr_timer_t;
typedef uint32_t mutex_nested_t;
typedef uint8_t suspend_nested_t;
typedef uint64_t ctx_switch_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t cpsr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size, void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() { cpsr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(cpsr); }
#endif /* PORT_H */

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
/* ARMCC || IAR || GNU */
#define FPU_AVL ((defined(__CC_ARM) && defined(__TARGET_FPU_VFP)) \
|| (defined(__ICCARM__) && defined(__ARMVFP__)) \
|| (defined(__GNUC__) && defined(__VFP_FP__) && !defined(__SOFTFP__)))
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
/* stack aligned by 8 byte */
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;
/* Exception stack frame with non-floating-point state */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */
/* in PendSV_Handler, D8~D15 is always saved & restroe */
#if (FPU_AVL > 0)
*(--stk) = (cpu_stack_t)0x31uL; /* S31 */
*(--stk) = (cpu_stack_t)0x30uL; /* S30 */
*(--stk) = (cpu_stack_t)0x29uL; /* S29 */
*(--stk) = (cpu_stack_t)0x28uL; /* S28 */
*(--stk) = (cpu_stack_t)0x27uL; /* S27 */
*(--stk) = (cpu_stack_t)0x26uL; /* S26 */
*(--stk) = (cpu_stack_t)0x25uL; /* S25 */
*(--stk) = (cpu_stack_t)0x24uL; /* S24 */
*(--stk) = (cpu_stack_t)0x23uL; /* S23 */
*(--stk) = (cpu_stack_t)0x22uL; /* S22 */
*(--stk) = (cpu_stack_t)0x21uL; /* S21 */
*(--stk) = (cpu_stack_t)0x20uL; /* S20 */
*(--stk) = (cpu_stack_t)0x19uL; /* S19 */
*(--stk) = (cpu_stack_t)0x18uL; /* S18 */
*(--stk) = (cpu_stack_t)0x17uL; /* S17 */
*(--stk) = (cpu_stack_t)0x16uL; /* S16 */
#endif
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + non-floating-point state + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;
*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */
return stk;
}

View file

@ -0,0 +1,176 @@
#include <k_config.h>
;******************************************************************************
; EXTERN PARAMETERS
;******************************************************************************
EXTERN g_active_task
EXTERN g_preferred_ready_task
EXTERN krhino_stack_ovf_check
EXTERN krhino_task_sched_stats_get
;******************************************************************************
; EXPORT FUNCTIONS
;******************************************************************************
PUBLIC cpu_intrpt_save
PUBLIC cpu_intrpt_restore
PUBLIC cpu_task_switch
PUBLIC cpu_intrpt_switch
PUBLIC cpu_first_task_start
PUBLIC _first_task_restore
PUBLIC PendSV_Handler
;******************************************************************************
; EQUATES
;******************************************************************************
SCB_ICSR EQU 0xE000ED04 ; Interrupt Control and State Register.
SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register.
ICSR_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception.
SHPR3_PRI_14 EQU 0xE000ED22 ; System Handler Priority Register 3 (PendSV).
PRI_LVL_PENDSV EQU 0xFF ; PendSV priority level (lowest).
SHPR3_PRI_15 EQU 0xE000ED23 ; System Handler Priority Register 3 (SysTick).
PRI_LVL_SYSTICK EQU 0xFF ; SYstick priority level (lowest).
;******************************************************************************
; CODE GENERATION DIRECTIVES
;******************************************************************************
SECTION .text:CODE(2)
THUMB
REQUIRE8
PRESERVE8
;******************************************************************************
; Functions:
; size_t cpu_intrpt_save(void);
; void cpu_intrpt_restore(size_t cpsr);
;******************************************************************************
cpu_intrpt_save:
MRS R0, PRIMASK
CPSID I
BX LR
cpu_intrpt_restore:
MSR PRIMASK, R0
BX LR
;******************************************************************************
; Functions:
; void cpu_intrpt_switch(void);
; void cpu_task_switch(void);
;******************************************************************************
cpu_task_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
cpu_intrpt_switch:
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
BX LR
;******************************************************************************
; Functions:
; void cpu_first_task_start(void);
;******************************************************************************
cpu_first_task_start:
;set PendSV prority to the lowest
LDR R0, =SHPR3_PRI_14
LDR R1, =PRI_LVL_PENDSV
STRB R1, [R0]
;set Systick prority to the lowest
LDR R0, =SHPR3_PRI_15
LDR R1, =PRI_LVL_SYSTICK
STRB R1, [R0]
;indicate PendSV_Handler branch to _pendsv_handler_nosave
MOVS R0, #0
MSR PSP, R0
;make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]
;goto PendSV_Handler
CPSIE I
B .
;******************************************************************************
; Functions:
; void krhino_pendsv_handler(void);
;******************************************************************************
PendSV_Handler:
CPSID I
MRS R0, PSP
;branch if cpu_first_task_start
CMP R0, #0
BEQ _first_task_restore
;hardware saved R0~R3,R12,LR,PC,xPSR
;save context
#if defined(__ARMVFP__)
;if the switchout task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VSTMDBEQ R0!, {D8 - D15}
;hardware saved D0~D7, FPSCR
#endif
SUBS R0, R0, #0x24
STM R0, {R4-R11, LR}
;g_active_task->task_stack = context region
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif
_pendsv_handler_nosave:
LDR R0, =g_active_task
LDR R1, =g_preferred_ready_task
LDR R2, [R1]
STR R2, [R0]
;R0 = g_active_task->task_stack = context region
LDR R0, [R2]
;restore context
LDM R0, {R4-R11, LR}
ADDS R0, R0, #0x24
#if defined(__ARMVFP__)
;if the switchin task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VLDMIAEQ R0!, {D8 - D15}
;hardware will restore D0~D7, FPSCR
#endif
;return stack = PSP
MSR PSP, R0
CPSIE I
;hardware restore R0~R3,R12,LR,PC,xPSR
BX LR
_first_task_restore:
;set MSP to the base of system stack
LDR R0, =SCB_VTOR
LDR R0, [R0]
LDR R0, [R0]
MSR MSP, R0
B _pendsv_handler_nosave
END

View file

@ -0,0 +1,32 @@
src = []
component = aos_arch_component('armv7m', src)
component.add_sources('common/panic_c.c', 'common/port_c.c')
component.add_global_includes('common/')
if aos_global_config.compiler == 'armcc':
component.add_global_asflags('--cpreproc')
component.add_sources('common/panic_armcc.S')
if aos_global_config.arch == 'Cortex-M3':
component.add_sources('armcc/m3/port_s.S')
elif aos_global_config.arch == 'Cortex-M4':
component.add_sources('armcc/m4/port_s.S')
elif aos_global_config.arch == 'Cortex-M7':
component.add_sources('armcc/m7/port_s.S')
elif aos_global_config.compiler == 'iar':
component.add_sources('common/panic_iccarm.S')
if aos_global_config.arch == 'Cortex-M3':
component.add_sources('iccarm/m3/port_s.S')
elif aos_global_config.arch == 'Cortex-M4':
component.add_sources('iccarm/m4/port_s.S')
elif aos_global_config.arch == 'Cortex-M7':
component.add_sources('iccarm/m7/port_s.S')
else:
component.add_sources('common/panic_gcc.S')
if aos_global_config.arch == 'Cortex-M3':
component.add_sources('gcc/m3/port_s.S')
elif aos_global_config.arch == 'Cortex-M4':
component.add_sources('gcc/m4/port_s.S')
elif aos_global_config.arch == 'Cortex-M7':
component.add_sources('gcc/m7/port_s.S')

View file

@ -0,0 +1,103 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef CKCPU_H
#define CKCPU_H
.macro csky_cpu_initpsr
mfcr a3, psr
bseti a3, 8
bseti a3, 5
bseti a3, 31
bseti a3, 30
mtcr a3, psr
.endm
.macro csky_cpu_initnspsr
mfcr a3, cr<0,3>
bseti a3, 5
bseti a3, 6
bseti a3, 8
bseti a3, 31
mtcr a3, cr<0,3>
.endm
.macro csky_cpu_initvec vsrtable
lrw a2, \vsrtable
mtcr a2, vbr
.endm
.macro csky_cpu_initnsvec nsvsrtable
/* setup initial security vector base table for interrupts and exceptions */
lrw a2, \nsvsrtable
mtcr a2, cr<1,0>
.endm
.macro csky_cpu_initstack stack
/* initialize the normal stack pointer from the linker definition */
lrw a3, \stack
mov sp, a3
.endm
.macro csky_cpu_init_nor_stack _nor_stack
/* initialize the normal stack pointer from the linker definition */
lrw a3, \_nor_stack
mtcr a3, cr<14,3>
.endm
.macro csky_cpu_init_ns_stack ns_stack
/* initialize the normal stack pointer from the linker definition */
lrw a3, \ns_stack
mov sp, a3
.endm
.macro csky_cpu_init_nor_ns_stack _nor_ns_stack
/* initialize the normal stack pointer from the linker definition */
lrw a3, \_nor_ns_stack
mtcr a3, cr<14,1>
.endm
.macro csky_cpu_initfstack fstack
/* initialize the fast interrupt stack pointer */
psrset af
lrw a3, \fstack
mov sp, a3
psrclr af
.endm
.macro csky_bss_init sadr eadr
lrw r7, \sadr /* get start of bss from linking script file */
lrw r6, \eadr /* get end of bss from linking script file */
subu r6, r7 /* calculate size of bss */
lsri r6, r6, 2 /* size of whole words */
cmpnei r6, 0
bf .L_bss_init_end
movi r5, 0 /* set zero value to write */
.L_bss_init_loop:
stw r5, (r7) /* zero next word */
addi r7, 4 /* increase bss pointer */
subi r6, 1 /* decrease counter */
cmpnei r6, 0
bt .L_bss_init_loop /* repeat for all bss */
.L_bss_init_end:
.endm
.macro csky_load_data saddr eaddr eeaddr
lrw a3, \saddr /* get start of data from linking script file */
lrw a1, \eaddr /* get end of data from linking script file */
cmphs a3, a1 /* galculate size of data */
lrw a2, \eeaddr /* get end of rodata from linking script file */
.L_load_data:
ld.w a0, (a2, 0) /* load data from flash */
st.w a0, (a3, 0) /* store data to SSRAM */
addi a3, 4 /* increase data pointer of flash */
addi a2, 4 /* increase data pointer of SSRAM */
cmphs a3, a1
bf .L_load_data /* repeat for all data */
.endm
#endif

View file

@ -0,0 +1,93 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
#include <k_config.h>
#if (YUNOS_CONFIG_STACK_OVF_CHECK_HW != 0)
void cpu_intrpt_stack_protect(void)
{
}
void task_stack_crash_warning(void)
{
printf("****The task stack base has been broken !!!****\n");
}
void cpu_task_stack_protect(cpu_stack_t *base, size_t size)
{
uint32_t base_addr = (uint32_t)base;
int num_return = wp_register(base_addr, AWATCH, task_stack_crash_warning);
if (num_return == 1) {
wp_enable(1);
} else if (num_return == 2 || num_return == -1) {
wp_unregister(1);
int number_tmp = wp_register(base_addr, AWATCH, task_stack_crash_warning);
if (number_tmp == 1){
wp_enable(1);
}
}
}
#endif
#ifdef CONFIG_STACK_GUARD
void csky_set_stackbound(void)
{
uint32_t size;
cpu_stack_t *base;
ktask_t *get_task = (ktask_t *)g_active_task;
base = get_task->task_stack_base;
size = get_task->stack_size;
asm volatile(
"mfcr r9, cr<0, 4>\n\r"
"bclri r9, 0\n\r"
"mtcr r9, cr<0, 4>\n\r"
"mtcr %0, cr<2, 4>\n\r"
"lsli %1, %1, 2\n\r"
"add %0, %0, %1\n\r"
"mtcr %0, cr<1, 4>\n\r"
::"r"(base), "r"(size):"r9");
}
int stack_guard_save(void)
{
int value;
asm volatile(
"mfcr %0, cr<0, 4>\n\t"
"mov r0, %0\n\t"
"bclri r0, 0\n\t"
"mtcr r0, cr<0, 4>\n\t"
:"=r"(value)
::"r0");
return value;
}
void stack_guard_restore(int value)
{
asm volatile(
"mtcr %0, cr<0, 4>\n\t"
::"r"(value):
);
}
#endif

View file

@ -0,0 +1,92 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
#undef PSR_SP
#define PSR_SP (1UL << 29)
static ktask_t *tee_caller_task = NULL;
static inline uint32_t getcurrentpsr(void)
{
uint32_t flags;
__asm__ __volatile__(
"mfcr %0, psr \n"
:"=r"(flags)
:
:
);
return flags;
}
static inline void clear_psr_sp(void)
{
__asm__ __volatile__ (
"mfcr r0, psr \n"
"bclri r0, 29 \n"
"mtcr r0, psr \n"
:
:
:"r0"
);
}
static inline void set_psr_sp(void)
{
__asm__ __volatile__ (
"mfcr r0, psr \n"
"bseti r0, 29 \n"
"mtcr r0, psr \n"
:
:
:"r0"
);
}
void csky_get_tee_caller_task(void)
{
uint32_t temp_psr;
temp_psr = getcurrentpsr();
if (temp_psr & PSR_SP) {
tee_caller_task = (tee_caller_task == NULL) ? g_active_task[cpu_cur_get()] : tee_caller_task;
}
}
void csky_deal_tee_caller_task(void)
{
uint32_t temp_psr;
temp_psr = getcurrentpsr();
if (temp_psr & PSR_SP) {
if (tee_caller_task != NULL) {
if (tee_caller_task == g_active_task[cpu_cur_get()]) {
tee_caller_task = NULL;
} else {
clear_psr_sp();
}
}
} else {
if (tee_caller_task != NULL) {
if (tee_caller_task == g_active_task[cpu_cur_get()]) {
tee_caller_task = NULL;
set_psr_sp();
}
}
}
}

View file

@ -0,0 +1,2 @@
NAME := cskyv2-l

View file

@ -0,0 +1,111 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <csi_config.h>
#ifdef CONFIG_BACKTRACE
#include <stdio.h>
#include <stdlib.h>
#include <backtrace.h>
#define BT_SIZE 40
void *g_bt_buffer[BT_SIZE];
#define BT_STACK_SIZE 600
int g_bt_stack[BT_STACK_SIZE / 4];
char *g_dumpbuf = NULL;
int g_dump_len = 0;
int g_dump_max = 0;
void dump_backtrace(void)
{
int i;
int nptr;
g_dump_len = 0;
nptr = backtrace(g_bt_buffer, BT_SIZE);
if (nptr <= 0) {
printf("error: backtrace_symbols\n");
return;
}
for (i = 0; i < nptr; i++) {
if (g_dumpbuf == NULL) {
printf("[<%p>]\n", g_bt_buffer[i]);
} else {
g_dump_len += snprintf(&g_dumpbuf[g_dump_len], g_dump_max - g_dump_len, "[<%p>]\n", g_bt_buffer[i]);
if (g_dump_len >= g_dump_max) {
printf("error, user buffer no space \n");
return;
}
}
}
}
void __attribute__((naked))csky_show_backtrace(void *stack)
{
asm volatile(
"subi sp, 68\n\t"
"stm r0-r13, (sp)\n\t"
"mtcr sp, cr<14, 1>\n\t"
"stw r15, (sp, 56)\n\t"
"mov sp, %0\n\t"
"lrw r0, g_bt_stack\n\t"
"mov r1, sp\n\t"
"sub r1, %1\n\t"
"mov r2, %1\n\t"
"mov r4, %1\n\t"
"jbsr memcpy\n\t"
"ldw r8, (sp, 32)\n\t"
"ldw r15, (sp, 64)\n\t"
"subi sp, 16\n\t"
"stw r8, (sp, 0)\n\t"
"stw r15, (sp, 4)\n\t"
"mov r8, sp\n\t"
"jbsr dump_backtrace\n\t"
"addi sp, 16\n\t"
"lrw r1, g_bt_stack\n\t"
"mov r0, sp\n\t"
"sub r0, r4\n\t"
"mov r2, r4\n\t"
"jbsr memcpy\n\t"
"mfcr sp, cr<14, 1>\n\t"
"ldw r15, (sp, 56)\n\t"
"ldm r0-r13, (sp)\n\t"
"addi sp, 68\n\t"
"jmp r15\n\t"
::"r"(stack), "r"(BT_STACK_SIZE):);
}
int csky_task_backtrace(void *stack, void *buf, int len)
{
g_dumpbuf = buf;
g_dump_max = len;
csky_show_backtrace(stack);
return g_dump_len;
}
#endif

View file

@ -0,0 +1,162 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_config.h>
#include <csi_config.h>
.global watchpoint_handler
.import g_top_irqstack
.import csky_get_tee_caller_task
.import csky_deal_tee_caller_task
.import g_irqvector
/******************************************************************************
* Functions:
* void watchpoint_handler(void);
* watchpoint exception handler
******************************************************************************/
#if defined(CONFIG_WATCHPOINT)
.align 2
.globl watchpoint_handler
.type watchpoint_handler, %function
watchpoint_handler:
psrset ee
subi sp, 72
stm r0-r15, (sp)
addi r0, sp, 72
stw r0, (sp, 56)
mfcr r0, epsr
stw r0, (sp, 64)
mfcr r0, epc
stw r0, (sp, 68)
ldh r0, (r0)
cmpnei r0, 0
lrw r0, wp_get_callback
lrw r1, trap_c
movf r0, r1
jsr r0
mov r0, sp
ldw r0, (sp, 64)
mtcr r0, epsr
ldw r0, (sp, 68)
mtcr r0, epc
ldm r0-r13, (sp)
ldw r15, (sp, 60)
ldw sp, (sp, 56)
rte
.size watchpoint_handler, . - watchpoint_handler
#endif
/******************************************************************************
* Functions:
* void NOVIC_IRQ_Default_Handler(void);
* novic default irq entry
******************************************************************************/
.global NOVIC_IRQ_Default_Handler
.type NOVIC_IRQ_Default_Handler, %function
NOVIC_IRQ_Default_Handler:
psrset ee
#ifndef CONFIG_HAVE_VIC
subi sp, 68
stm r0-r13, (sp)
stw r15, (sp, 56)
mfcr r0, epsr
stw r0, (sp, 60)
mfcr r0, epc
stw r0, (sp, 64)
#ifdef CONFIG_STACK_GUARD
lrw r0, g_top_irqstack
mtcr r0, cr<1, 4>
subi r0, CONFIG_ARCH_INTERRUPTSTACK
mtcr r0, cr<2, 4>
mfcr r0, cr<0, 4>
bseti r0, 0
bseti r0, 1
mtcr r0, cr<0, 4>
#endif
lrw r0, g_active_task
ldw r0, (r0)
stw sp, (r0)
lrw sp, g_top_irqstack
#if (YUNOS_CONFIG_TASK_STACK_OVF_CHECK > 0)
jbsr krhino_stack_ovf_check
#endif
#ifdef CONFIG_SUPPORT_REE_SCHEDULE_IN_TEE
jbsr csky_get_tee_caller_task
#endif
lrw r1, g_irqvector
mfcr r0, psr
lsri r0, 16
sextb r0
subi r0, 32
lsli r0, 2
add r1, r0
ldw r5, (r1)
lsri r0, 2
mov r4, r0
jbsr krhino_intrpt_enter_hook
mov r0, r4
jsr r5
mov r0, r4
jbsr krhino_intrpt_exit_hook
#ifdef CONFIG_SUPPORT_REE_SCHEDULE_IN_TEE
jbsr csky_deal_tee_caller_task
#endif
#ifdef CONFIG_STACK_GUARD
jbsr csky_set_stackbound
#endif
lrw r0, g_active_task
ldw r0, (r0)
ldw sp, (r0)
#ifdef CONFIG_STACK_GUARD
mfcr r3, cr<0, 4>
bseti r3, 0
bseti r3, 1
mtcr r3, cr<0, 4>
#endif
ldw r0, (sp, 64)
mtcr r0, epc
ldw r0, (sp, 60)
mtcr r0, epsr
ldm r0-r13, (sp)
ldw r15, (sp, 56)
addi sp, 68
rte
#else /* CONFIG_HAVE_VIC */
bkpt
#endif /* CONFIG_HAVE_VIC */

View file

@ -0,0 +1,194 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef CONFIG_H
#define CONFIG_H
/* chip level conf */
#ifndef RHINO_CONFIG_LITTLE_ENDIAN
#define RHINO_CONFIG_LITTLE_ENDIAN 1
#endif
#ifndef RHINO_CONFIG_CPU_STACK_DOWN
#define RHINO_CONFIG_CPU_STACK_DOWN 1
#endif
/* kernel feature conf */
#ifndef RHINO_CONFIG_SEM
#define RHINO_CONFIG_SEM 1
#endif
#ifndef RHINO_CONFIG_QUEUE
#define RHINO_CONFIG_QUEUE 1
#endif
#ifndef RHINO_CONFIG_TASK_SEM
#define RHINO_CONFIG_TASK_SEM 1
#endif
#ifndef RHINO_CONFIG_EVENT_FLAG
#define RHINO_CONFIG_EVENT_FLAG 1
#endif
#ifndef RHINO_CONFIG_TIMER
#define RHINO_CONFIG_TIMER 1
#endif
#ifndef RHINO_CONFIG_BUF_QUEUE
#define RHINO_CONFIG_BUF_QUEUE 1
#endif
#ifndef RHINO_CONFIG_MM_BLK
#define RHINO_CONFIG_MM_BLK 1
#endif
#ifndef RHINO_CONFIG_KOBJ_SET
#define RHINO_CONFIG_KOBJ_SET 1
#endif
/*
#ifndef RHINO_CONFIG_TICKS_PER_SECOND
#define RHINO_CONFIG_TICKS_PER_SECOND 100
#endif
#ifndef RHINO_CONFIG_TICK_HEAD_ARRAY
#define RHINO_CONFIG_TICK_HEAD_ARRAY 1
#endif
#ifndef RHINO_CONFIG_SCHED_RR
#define RHINO_CONFIG_SCHED_RR 0
#endif
#ifndef RHINO_CONFIG_TIMER_RATE
#define RHINO_CONFIG_TIMER_RATE 1
#endif
#ifndef RHINO_CONFIG_TIMER
#define RHINO_CONFIG_TIMER 1
#endif
*/
#ifndef RHINO_CONFIG_TASK_STACK_CUR_CHECK
#define RHINO_CONFIG_TASK_STACK_CUR_CHECK 1
#endif
/* kernel task conf */
#ifndef RHINO_CONFIG_TASK_SUSPEND
#define RHINO_CONFIG_TASK_SUSPEND 1
#endif
#ifndef RHINO_CONFIG_TASK_INFO
#define RHINO_CONFIG_TASK_INFO 1
#endif
#ifndef RHINO_CONFIG_TASK_DEL
#define RHINO_CONFIG_TASK_DEL 1
#endif
#ifndef RHINO_CONFIG_TASK_WAIT_ABORT
#define RHINO_CONFIG_TASK_WAIT_ABORT 1
#endif
#ifndef RHINO_CONFIG_TASK_STACK_OVF_CHECK
#define RHINO_CONFIG_TASK_STACK_OVF_CHECK 1
#endif
#ifndef RHINO_CONFIG_SCHED_RR
#define RHINO_CONFIG_SCHED_RR 0
#endif
#ifndef RHINO_CONFIG_TIME_SLICE_DEFAULT
#define RHINO_CONFIG_TIME_SLICE_DEFAULT 50
#endif
#ifndef RHINO_CONFIG_PRI_MAX
#define RHINO_CONFIG_PRI_MAX 62
#endif
#ifndef RHINO_CONFIG_USER_PRI_MAX
#define RHINO_CONFIG_USER_PRI_MAX (RHINO_CONFIG_PRI_MAX - 2)
#endif
/* kernel workqueue conf */
#ifndef RHINO_CONFIG_WORKQUEUE
#define RHINO_CONFIG_WORKQUEUE 0
#endif
/* kernel timer&tick conf */
#ifndef RHINO_CONFIG_HW_COUNT
#define RHINO_CONFIG_HW_COUNT 1
#endif
#ifndef RHINO_CONFIG_TICK_TASK
#define RHINO_CONFIG_TICK_TASK 1
#endif
#if (RHINO_CONFIG_TICK_TASK > 0)
#ifndef RHINO_CONFIG_TICK_TASK_STACK_SIZE
#define RHINO_CONFIG_TICK_TASK_STACK_SIZE 256
#endif
#ifndef RHINO_CONFIG_TICK_TASK_PRI
#define RHINO_CONFIG_TICK_TASK_PRI 1
#endif
#endif
#ifndef RHINO_CONFIG_TICKS_PER_SECOND
#define RHINO_CONFIG_TICKS_PER_SECOND 100
#endif
#ifndef RHINO_CONFIG_TIMER_TASK_STACK_SIZE
#define RHINO_CONFIG_TIMER_TASK_STACK_SIZE 200
#endif
#ifndef RHINO_CONFIG_TIMER_RATE
#define RHINO_CONFIG_TIMER_RATE 1
#endif
#ifndef RHINO_CONFIG_TIMER_TASK_PRI
#define RHINO_CONFIG_TIMER_TASK_PRI 5
#endif
/* kernel intrpt conf */
#ifndef RHINO_CONFIG_INTRPT_STACK_REMAIN_GET
#define RHINO_CONFIG_INTRPT_STACK_REMAIN_GET 1
#endif
#ifndef RHINO_CONFIG_INTRPT_STACK_OVF_CHECK
#define RHINO_CONFIG_INTRPT_STACK_OVF_CHECK 0
#endif
#ifndef RHINO_CONFIG_INTRPT_MAX_NESTED_LEVEL
#define RHINO_CONFIG_INTRPT_MAX_NESTED_LEVEL 188u
#endif
#ifndef RHINO_CONFIG_INTRPT_GUARD
#define RHINO_CONFIG_INTRPT_GUARD 0
#endif
/* kernel dyn alloc conf */
#ifndef RHINO_CONFIG_KOBJ_DYN_ALLOC
#define RHINO_CONFIG_KOBJ_DYN_ALLOC 1
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
#ifndef RHINO_CONFIG_K_DYN_QUEUE_MSG
#define RHINO_CONFIG_K_DYN_QUEUE_MSG 30
#endif
#ifndef RHINO_CONFIG_K_DYN_TASK_STACK
#define RHINO_CONFIG_K_DYN_TASK_STACK 256
#endif
#ifndef RHINO_CONFIG_K_DYN_MEM_TASK_PRI
#define RHINO_CONFIG_K_DYN_MEM_TASK_PRI RHINO_CONFIG_USER_PRI_MAX
#endif
#endif
/* kernel idle conf */
#ifndef RHINO_CONFIG_IDLE_TASK_STACK_SIZE
#define RHINO_CONFIG_IDLE_TASK_STACK_SIZE 100
#endif
/* kernel hook conf */
#ifndef RHINO_CONFIG_USER_HOOK
#define RHINO_CONFIG_USER_HOOK 0
#endif
/* kernel stats conf */
#ifndef RHINO_CONFIG_SYSTEM_STATS
#define RHINO_CONFIG_SYSTEM_STATS 1
#endif
#ifndef RHINO_CONFIG_DISABLE_SCHED_STATS
#define RHINO_CONFIG_DISABLE_SCHED_STATS 0
#endif
#ifndef RHINO_CONFIG_DISABLE_INTRPT_STATS
#define RHINO_CONFIG_DISABLE_INTRPT_STATS 0
#endif
#ifndef RHINO_CONFIG_CPU_USAGE_STATS
#define RHINO_CONFIG_CPU_USAGE_STATS 1
#endif
#ifndef RHINO_CONFIG_CPU_USAGE_TASK_PRI
#define RHINO_CONFIG_CPU_USAGE_TASK_PRI (RHINO_CONFIG_PRI_MAX - 2)
#endif
#ifndef RHINO_CONFIG_TASK_SCHED_STATS
#define RHINO_CONFIG_TASK_SCHED_STATS 0
#endif
#ifndef RHINO_CONFIG_CPU_USAGE_TASK_STACK
#define RHINO_CONFIG_CPU_USAGE_TASK_STACK 256
#endif
#endif /* CONFIG_H */

View file

@ -0,0 +1,27 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef TYPES_H
#define TYPES_H
#define RHINO_TASK_STACK_OVF_MAGIC 0xdeadbeafu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_INTRPT_STACK_OVF_MAGIC 0xdeaddeadu /* 32 bit or 64 bit stack overflow magic value */
#define RHINO_MM_CORRUPT_DYE 0xFEFEFEFE
#define RHINO_MM_FREE_DYE 0xABABABAB
#define RHINO_INLINE static __inline /* inline keyword, it may change under different compilers */
typedef char name_t;
typedef uint32_t sem_count_t;
typedef uint32_t cpu_stack_t;
/* you may change here depend on your hardware timer */
typedef uint32_t hr_timer_t; /* 32 bit or 64 bit unsigned value */
typedef uint32_t lr_timer_t; /* 32 bit or 64 bit unsigned value */
typedef uint32_t mutex_nested_t; /* 8 bit or 16bit or 32bit unsigned value */
typedef uint8_t suspend_nested_t; /* 8 bit normally */
typedef uint64_t ctx_switch_t; /* 32 bit or 64 bit unsigned value */
typedef int32_t ssize_t;
typedef uint32_t cpu_cpsr_t;
#endif /* TYPES_H */

View file

@ -0,0 +1,29 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef PORT_H
#define PORT_H
#include <k_types.h>
#include <k_task.h>
size_t cpu_intrpt_save(void);
void cpu_intrpt_restore(size_t psr);
void cpu_intrpt_switch(void);
void cpu_task_switch(void);
void cpu_first_task_start(void);
void *cpu_task_stack_init(cpu_stack_t *base, size_t size,
void *arg, task_entry_t entry);
RHINO_INLINE uint8_t cpu_cur_get(void)
{
return 0;
}
#define CPSR_ALLOC() size_t psr
#define RHINO_CPU_INTRPT_DISABLE() { psr = cpu_intrpt_save(); }
#define RHINO_CPU_INTRPT_ENABLE() { cpu_intrpt_restore(psr); }
#endif /* PORT_H */

View file

@ -0,0 +1,53 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_api.h>
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);
temp &= 0xfffffffc;
stk = (cpu_stack_t *)temp;
*(--stk) = (uint32_t)entry; /* entry point */
#ifndef CONFIG_SYSTEM_SECURE
*(--stk) = (uint32_t)0x80000140L; /* PSR */
#else
*(--stk) = (uint32_t)0xe0000140L; /* PSR */
#endif
*(--stk) = (uint32_t)krhino_task_deathbed; /* R15 (LR) */
*(--stk) = (uint32_t)0x13131313L; /* R13 */
*(--stk) = (uint32_t)0x12121212L; /* R12 */
*(--stk) = (uint32_t)0x11111111L; /* R11 */
*(--stk) = (uint32_t)0x10101010L; /* R10 */
*(--stk) = (uint32_t)0x09090909L; /* R9 */
*(--stk) = (uint32_t)0x00000000L; /* R8 */
*(--stk) = (uint32_t)0x07070707L; /* R7 */
*(--stk) = (uint32_t)0x06060606L; /* R6 */
*(--stk) = (uint32_t)0x05050505L; /* R5 */
*(--stk) = (uint32_t)0x04040404L; /* R4 */
*(--stk) = (uint32_t)0x03030303L; /* R3 */
*(--stk) = (uint32_t)0x02020202L; /* R2 */
*(--stk) = (uint32_t)0x01010101L; /* R1 */
*(--stk) = (uint32_t)arg; /* R0 : argument */
return stk;
}

View file

@ -0,0 +1,148 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_config.h>
#define VIC_TSPDR 0XE000EC08
.extern g_active_task
.extern g_preferred_ready_task
.extern krhino_task_sched_stats_get
.extern krhino_stack_ovf_check
/******************************************************************************
* EXPORT FUNCTIONS
******************************************************************************/
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global tspend_handler
/******************************************************************************
* EQUATES
******************************************************************************/
/******************************************************************************
* CODE GENERATION DIRECTIVES
******************************************************************************/
.text
.align 2
/******************************************************************************
* Functions:
* size_t cpu_intrpt_save(void);
* void cpu_intrpt_restore(size_t psr);
******************************************************************************/
.type cpu_intrpt_save, %function
cpu_intrpt_save:
mfcr r0, psr
psrclr ie
rts
.type cpu_intrpt_restore, %function
cpu_intrpt_restore:
mtcr r0, psr
rts
/******************************************************************************
* Functions:
* void cpu_intrpt_switch(void);
* void cpu_task_switch(void);
******************************************************************************/
.type cpu_task_switch, %function
cpu_task_switch:
lrw r0, VIC_TSPDR
bgeni r1, 0
stw r1, (r0)
rts
.type cpu_intrpt_switch, %function
cpu_intrpt_switch:
lrw r0, VIC_TSPDR
bgeni r1, 0
stw r1, (r0)
rts
/******************************************************************************
* Functions:
* void cpu_first_task_start(void);
******************************************************************************/
.type cpu_first_task_start, %function
cpu_first_task_start:
psrclr ie
jbr __tspend_handler_nosave
/******************************************************************************
* Functions:
* void __task_switch(void);
******************************************************************************/
.type tspend_handler, %function
tspend_handler:
subi sp, 68
stm r0-r13, (sp)
stw r15, (sp, 56)
mfcr r0, epsr
stw r0, (sp, 60)
mfcr r0, epc
stw r0, (sp, 64)
lrw r1, g_active_task
ldw r1, (r1)
stw sp, (r1)
#if (YUNOS_CONFIG_TASK_STACK_OVF_CHECK > 0)
jbsr krhino_stack_ovf_check
#endif
#if (YUNOS_CONFIG_TASK_SCHED_STATS > 0)
jbsr krhino_task_sched_stats_get
#endif
__tspend_handler_nosave:
lrw r4, g_active_task
lrw r5, g_preferred_ready_task
ldw r6, (r5)
stw r6, (r4)
#ifdef CONFIG_STACK_GUARD
jbsr csky_set_stackbound
#endif
ldw sp, (r6)
#ifdef CONFIG_STACK_GUARD
mfcr r3, cr<0, 4>
bseti r3, 0
bseti r3, 1
mtcr r3, cr<0, 4>
#endif
ldw r0, (sp, 64)
mtcr r0, epc
ldw r0, (sp, 60)
mtcr r0, epsr
ldw r15, (sp, 56)
ldm r0-r13, (sp)
addi sp, 68
rte

View file

@ -0,0 +1,166 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <k_config.h>
#include <csi_config.h>
.extern g_active_task
.extern g_preferred_ready_task
.import csky_deal_tee_caller_task
.import csky_get_tee_caller_task
/******************************************************************************
* EXPORT FUNCTIONS
******************************************************************************/
.global cpu_intrpt_save
.global cpu_intrpt_restore
.global cpu_task_switch
.global cpu_intrpt_switch
.global cpu_first_task_start
.global tspend_handler
/******************************************************************************
* EQUATES
******************************************************************************/
/******************************************************************************
* CODE GENERATION DIRECTIVES
******************************************************************************/
.text
.align 2
/******************************************************************************
* Functions:
* size_t cpu_intrpt_save(void);
* void cpu_intrpt_restore(size_t psr);
******************************************************************************/
.type cpu_intrpt_save, %function
cpu_intrpt_save:
mfcr r0, psr
psrclr ie
rts
.type cpu_intrpt_restore, %function
cpu_intrpt_restore:
mtcr r0, psr
rts
/******************************************************************************
* Functions:
* void cpu_intrpt_switch(void);
* void cpu_task_switch(void);
******************************************************************************/
.type cpu_task_switch, %function
cpu_task_switch:
lrw r0, g_intrpt_nested_level
ldb r0, (r0)
cmpnei r0, 0
jbf __task_switch
lrw r0, g_active_task
lrw r1, g_preferred_ready_task
ldw r2, (r1)
stw r2, (r0)
rts
.type cpu_intrpt_switch, %function
cpu_intrpt_switch:
lrw r0, g_active_task
lrw r1, g_preferred_ready_task
ldw r2, (r1)
stw r2, (r0)
rts
/******************************************************************************
* Functions:
* void cpu_first_task_start(void);
******************************************************************************/
.type cpu_first_task_start, %function
cpu_first_task_start:
psrclr ie
jbr __task_switch_nosave
/******************************************************************************
* Functions:
* void __task_switch(void);
******************************************************************************/
.type __task_switch, %function
__task_switch:
subi sp, 68
stm r0-r13, (sp)
stw r15, (sp, 56)
mfcr r0, psr
stw r0, (sp, 60)
stw r15, (sp, 64)
lrw r1, g_active_task
ldw r1, (r1)
stw sp, (r1)
#if (YUNOS_CONFIG_TASK_STACK_OVF_CHECK > 0)
jbsr krhino_stack_ovf_check
#endif
__task_switch_nosave:
#ifdef CONFIG_SUPPORT_REE_SCHEDULE_IN_TEE
jbsr csky_get_tee_caller_task
#endif
lrw r4, g_preferred_ready_task
lrw r5, g_active_task
ldw r6, (r4)
stw r6, (r5)
#ifdef CONFIG_SUPPORT_REE_SCHEDULE_IN_TEE
jbsr csky_deal_tee_caller_task
#endif
#ifdef CONFIG_STACK_GUARD
jbsr csky_set_stackbound
#endif
ldw sp, (r6)
#ifdef CONFIG_STACK_GUARD
mfcr r3, cr<0, 4>
bseti r3, 0
bseti r3, 1
mtcr r3, cr<0, 4>
#endif
ldw r0, (sp, 64)
mtcr r0, epc
ldw r0, (sp, 60)
mtcr r0, epsr
ldw r15, (sp, 56)
ldm r0-r13, (sp)
addi sp, 68
rte
.global tspend_handler
.type tspend_handler, %function
tspend_handler:
bkpt

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2016 YunOS Project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#include <stdio.h>
#include <csi_kernel.h>
void trap_c(uint32_t *regs)
{
int i;
uint32_t vec = 0;
asm volatile(
"mfcr %0, psr \n"
"lsri %0, 16 \n"
"sextb %0 \n"
:"=r"(vec):);
printf("CPU Exception : %d", vec);
if (vec == 2) {
printf(",maybe Stack-Guard stopped the invalid behaviors!");
}
printf("\n");
for (i = 0; i < 16; i++) {
printf("r%d: %08x\t", i, regs[i]);
if ((i % 5) == 4) {
printf("\n");
}
}
printf("\n");
printf("epsr: %8x\n", regs[16]);
printf("epc : %8x\n", regs[17]);
// csi_kernel_task_list(NULL, 0);
while (1);
}

View file

@ -0,0 +1,4 @@
src = Split('''
''')
component = aos_component('cskyv2-l', src)

View file

@ -0,0 +1,10 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifdef __i386__
#include "cpu_longjmp_32.h"
#else
#include "cpu_longjmp_64.h"
#endif

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef CPU_EVENT_H
#define CPU_EVENT_H
typedef void (*cpu_event_handler)(const void *);
typedef struct {
cpu_event_handler handler;
const void *arg;
} cpu_event_t;
#ifdef VCALL_RHINO
int cpu_notify_event(cpu_event_t *event);
void *cpu_event_malloc(int size);
void cpu_event_free(void *p);
static inline int cpu_call_handler(cpu_event_handler handler, const void *arg)
{
cpu_event_t event = {
.handler = handler,
.arg = arg,
};
return cpu_notify_event(&event);
}
#else
#define cpu_event_malloc malloc
#define cpu_event_free free
static inline int cpu_call_handler(cpu_event_handler handler, const void *arg)
{
handler(arg);
return 0;
}
#endif
#endif /* CPU_EVENT_H */

Some files were not shown because too many files have changed in this diff Show more