diff --git a/arch/linux/common/include/tos_cpu.h b/arch/linux/common/include/tos_cpu.h new file mode 100644 index 00000000..736077a9 --- /dev/null +++ b/arch/linux/common/include/tos_cpu.h @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------------- + * Tencent is pleased to support the open source community by making TencentOS + * available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * If you have downloaded a copy of the TencentOS binary from Tencent, please + * note that the TencentOS binary is licensed under the BSD 3-Clause License. + * + * If you have downloaded a copy of the TencentOS source code from Tencent, + * please note that TencentOS source code is licensed under the BSD 3-Clause + * License, except for the third-party components listed below which are + * subject to different license terms. Your integration of TencentOS into your + * own projects may require compliance with the BSD 3-Clause License, as well + * as the other licenses applicable to the third-party components included + * within TencentOS. + *---------------------------------------------------------------------------*/ + +#ifndef _TOS_CPU_H_ +#define _TOS_CPU_H_ + +typedef void (*task_code)( void * ); + +typedef struct cpu_context_st { + pthread_t thread_id; + task_code entry; + task_code exit; + void *arg; +} cpu_context_t; + +__API__ uint32_t tos_cpu_clz(uint32_t val); + +__API__ void tos_cpu_int_disable(void); + +__API__ void tos_cpu_int_enable(void); + +__API__ cpu_cpsr_t tos_cpu_cpsr_save(void); + +__API__ void tos_cpu_cpsr_restore(cpu_cpsr_t cpsr); + +#if (TOS_CFG_CPU_HRTIMER_EN > 0u) + +__API__ void tos_cpu_hrtimer_init(void); + +__API__ cpu_hrtimer_t tos_cpu_hrtimer_read(void); + +#endif + +__KERNEL__ void cpu_init(void); + +__KERNEL__ void cpu_reset(void); + +__KERNEL__ void cpu_systick_init(k_cycle_t cycle_per_tick); + +__KERNEL__ void cpu_sched_start(void); + +__KERNEL__ void cpu_context_switch(void); + +__KERNEL__ void cpu_irq_context_switch(void); + +#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u + +__KERNEL__ k_err_t cpu_task_stack_draught_depth(k_stack_t *stk_base, size_t stk_size, int *depth); + +#endif + +__KERNEL__ k_stack_t *cpu_task_stk_init(void *entry, + void *arg, + void *exit, + k_stack_t *stk_base, + size_t stk_size); + +#if TOS_CFG_TICKLESS_EN > 0u + +__KERNEL__ void cpu_systick_resume(void); + +__KERNEL__ void cpu_systick_suspend(void); + +__KERNEL__ void cpu_systick_reload_reset(void); + +__KERNEL__ void cpu_systick_pending_reset(void); + +__KERNEL__ k_time_t cpu_systick_max_delay_millisecond(void); + +__KERNEL__ void cpu_systick_expires_set(k_time_t millisecond); + +__KERNEL__ void cpu_systick_reset(void); + +#endif + +#if TOS_CFG_PWR_MGR_EN > 0u + +__KERNEL__ void cpu_sleep_mode_enter(void); + +__KERNEL__ void cpu_stop_mode_enter(void); + +__KERNEL__ void cpu_standby_mode_enter(void); + +#endif + +#if TOS_CFG_FAULT_BACKTRACE_EN > 0u + +#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U) + +__KERNEL__ void cpu_flush_fpu(void); + +#endif /* TOS_CFG_CPU_ARM_FPU_EN */ + +__KERNEL__ void cpu_fault_diagnosis(void); + +#endif + +/* Allocates CPU status register word. */ +#define TOS_CPU_CPSR_ALLOC() cpu_cpsr_t cpu_cpsr = (cpu_cpsr_t)0u + +/* Save CPU status word & disable interrupts.*/ +#define TOS_CPU_INT_DISABLE() \ + do { \ + cpu_cpsr = tos_cpu_cpsr_save(); \ + } while (0) + +/* Restore CPU status word. */ +#define TOS_CPU_INT_ENABLE() \ + do { \ + tos_cpu_cpsr_restore(cpu_cpsr); \ + } while (0) + +#endif /* _TOS_CPU_H_ */ + diff --git a/arch/linux/common/include/tos_cpu_def.h b/arch/linux/common/include/tos_cpu_def.h new file mode 100644 index 00000000..f71d7c8e --- /dev/null +++ b/arch/linux/common/include/tos_cpu_def.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------- + * Tencent is pleased to support the open source community by making TencentOS + * available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * If you have downloaded a copy of the TencentOS binary from Tencent, please + * note that the TencentOS binary is licensed under the BSD 3-Clause License. + * + * If you have downloaded a copy of the TencentOS source code from Tencent, + * please note that TencentOS source code is licensed under the BSD 3-Clause + * License, except for the third-party components listed below which are + * subject to different license terms. Your integration of TencentOS into your + * own projects may require compliance with the BSD 3-Clause License, as well + * as the other licenses applicable to the third-party components included + * within TencentOS. + *---------------------------------------------------------------------------*/ + +#ifndef _TOS_CPU_DEF_H_ +#define _TOS_CPU_DEF_H_ + +enum CPU_WORD_SIZE { + CPU_WORD_SIZE_08, + CPU_WORD_SIZE_16, + CPU_WORD_SIZE_32, + CPU_WORD_SIZE_64, +}; + +enum CPU_STK_GROWTH { + CPU_STK_GROWTH_ASCENDING, + CPU_STK_GROWTH_DESCENDING, +}; + +#endif /* _TOS_CPU_DEF_H_ */ + diff --git a/arch/linux/common/include/tos_cpu_types.h b/arch/linux/common/include/tos_cpu_types.h new file mode 100644 index 00000000..acb5f8a9 --- /dev/null +++ b/arch/linux/common/include/tos_cpu_types.h @@ -0,0 +1,61 @@ +/*---------------------------------------------------------------------------- + * Tencent is pleased to support the open source community by making TencentOS + * available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * If you have downloaded a copy of the TencentOS binary from Tencent, please + * note that the TencentOS binary is licensed under the BSD 3-Clause License. + * + * If you have downloaded a copy of the TencentOS source code from Tencent, + * please note that TencentOS source code is licensed under the BSD 3-Clause + * License, except for the third-party components listed below which are + * subject to different license terms. Your integration of TencentOS into your + * own projects may require compliance with the BSD 3-Clause License, as well + * as the other licenses applicable to the third-party components included + * within TencentOS. + *---------------------------------------------------------------------------*/ + +#ifndef _TOS_CPU_TYPES_H_ +#define _TOS_CPU_TYPES_H_ + +/* CPU address type based on address bus size. */ +#if (TOS_CFG_CPU_ADDR_SIZE == CPU_WORD_SIZE_64) +typedef uint64_t cpu_addr_t; +#elif (TOS_CFG_CPU_ADDR_SIZE == CPU_WORD_SIZE_32) +typedef uint32_t cpu_addr_t; +#elif (TOS_CFG_CPU_ADDR_SIZE == CPU_WORD_SIZE_16) +typedef uint16_t cpu_addr_t; +#else +typedef uint8_t cpu_addr_t; +#endif + +/* CPU data type based on data bus size. */ +#if (TOS_CFG_CPU_DATA_SIZE == CPU_WORD_SIZE_64) +typedef uint64_t cpu_data_t; +#elif (TOS_CFG_CPU_DATA_SIZE == CPU_WORD_SIZE_32) +typedef uint32_t cpu_data_t; +#elif (TOS_CFG_CPU_DATA_SIZE == CPU_WORD_SIZE_16) +typedef uint16_t cpu_data_t; +#else +typedef uint8_t cpu_data_t; +#endif + +#if (TOS_CFG_CPU_HRTIMER_EN > 0) +#if (TOS_CFG_CPU_HRTIMER_SIZE == CPU_WORD_SIZE_08) +typedef uint8_t cpu_hrtimer_t; +#elif (TOS_CFG_CPU_HRTIMER_SIZE == CPU_WORD_SIZE_16) +typedef uint16_t cpu_hrtimer_t; +#elif (TOS_CFG_CPU_HRTIMER_SIZE == CPU_WORD_SIZE_64) +typedef uint64_t cpu_hrtimer_t; +#else +typedef uint32_t cpu_hrtimer_t; +#endif +#else +typedef uint32_t cpu_hrtimer_t; +#endif + +//typedef cpu_addr_t size_t; +typedef cpu_addr_t cpu_cpsr_t; + +#endif + diff --git a/arch/linux/common/include/tos_fault.h b/arch/linux/common/include/tos_fault.h new file mode 100644 index 00000000..784c5f9d --- /dev/null +++ b/arch/linux/common/include/tos_fault.h @@ -0,0 +1,236 @@ +/*---------------------------------------------------------------------------- + * Tencent is pleased to support the open source community by making TencentOS + * available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * If you have downloaded a copy of the TencentOS binary from Tencent, please + * note that the TencentOS binary is licensed under the BSD 3-Clause License. + * + * If you have downloaded a copy of the TencentOS source code from Tencent, + * please note that TencentOS source code is licensed under the BSD 3-Clause + * License, except for the third-party components listed below which are + * subject to different license terms. Your integration of TencentOS into your + * own projects may require compliance with the BSD 3-Clause License, as well + * as the other licenses applicable to the third-party components included + * within TencentOS. + *---------------------------------------------------------------------------*/ + +#ifndef _TOS_FAULT_H_ +#define _TOS_FAULT_H_ + +#if TOS_CFG_FAULT_BACKTRACE_EN > 0u + +typedef int (*k_fault_log_writer_t)(const char *format, ...); + +#define K_FAULT_STACK_DUMP_DEPTH 10u + +#define K_FAULT_CALL_STACK_BACKTRACE_DEPTH 5u + +#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U) +typedef struct fault_fpu_frame_st { + cpu_data_t s0; + cpu_data_t s1; + cpu_data_t s2; + cpu_data_t s3; + cpu_data_t s4; + cpu_data_t s5; + cpu_data_t s6; + cpu_data_t s7; + cpu_data_t s8; + cpu_data_t s9; + cpu_data_t s10; + cpu_data_t s11; + cpu_data_t s12; + cpu_data_t s13; + cpu_data_t s14; + cpu_data_t s15; + cpu_data_t fpscr; +} fault_fpu_frame_t; +#endif + +typedef struct fault_cpu_frame_st { + cpu_data_t r0; + cpu_data_t r1; + cpu_data_t r2; + cpu_data_t r3; + cpu_data_t r12; + cpu_data_t lr; + cpu_data_t pc; + cpu_data_t spsr; +} fault_cpu_frame_t; + +typedef struct fault_exc_frame_st { + fault_cpu_frame_t cpu_frame; + +#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U) + fault_fpu_frame_t fpu_frame; +#endif +} fault_exc_frame_t; + +/** + * information we need to do fault backtrace + */ +typedef struct fault_information_st { + int is_thumb : 1; /**< whether it is thumb we use when we fall into fault? */ + int is_on_task : 1; /**< whether we are on a task when fall into fault? */ + int is_stk_ovrf : 1; /**< whether we get a stack overflow */ + +#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U) + int is_ext_stk_frm : 1; /**< whether it is a extended stack frame?(whether the cpu has pushed fpu registers onto the stack) */ +#endif + + cpu_addr_t pc; /**< just where fault happens */ + + cpu_addr_t sp_before_fault; /**< original sp just before the cpu push the fault exception frame */ + + /** + * we need main_stack_start & main_stack_limit to do call stack backtrace + * when we fall into fault during a task, we should do the call stack backtrace on the task's stack + * but if not, which means we are in kernel, we should do the call stack backtrace on the main stack + * in arm v7-m, this should be the MSP's start and limit + * in arm v7-a, call stack backtrace is another story(much more elegant because we have FP). + */ + cpu_addr_t stack_start; /**< current sp start address we use. if on task, it'll be the task's stack, otherwise it'll be the msp */ + cpu_addr_t stack_limit; /**< current sp limit address */ + cpu_addr_t code_start; /**< current code start address */ + cpu_addr_t code_limit; /**< current code limit address */ +} fault_info_t; + +#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) + +#define DEFAULT_CODE_SECTION_NAME ER_IROM1 +#define DEFAULT_CSTACK_SECTION_NAME STACK + +#define SECTION_START(_name_) _name_##$$Base +#define SECTION_END(_name_) _name_##$$Limit +#define IMAGE_SECTION_START(_name_) Image$$##_name_##$$Base +#define IMAGE_SECTION_END(_name_) Image$$##_name_##$$Limit +#define CSTACK_BLOCK_START(_name_) SECTION_START(_name_) +#define CSTACK_BLOCK_END(_name_) SECTION_END(_name_) +#define CODE_SECTION_START(_name_) IMAGE_SECTION_START(_name_) +#define CODE_SECTION_END(_name_) IMAGE_SECTION_END(_name_) + +extern const int CSTACK_BLOCK_START(DEFAULT_CSTACK_SECTION_NAME); +extern const int CSTACK_BLOCK_END(DEFAULT_CSTACK_SECTION_NAME); +extern const int CODE_SECTION_START(DEFAULT_CODE_SECTION_NAME); +extern const int CODE_SECTION_END(DEFAULT_CODE_SECTION_NAME); + +__STATIC_INLINE__ cpu_addr_t fault_code_start(void) +{ + return (cpu_addr_t)&CODE_SECTION_START(DEFAULT_CODE_SECTION_NAME); +} + +__STATIC_INLINE__ cpu_addr_t fault_code_limit(void) +{ + return (cpu_addr_t)&CODE_SECTION_END(DEFAULT_CODE_SECTION_NAME); +} + +__STATIC_INLINE__ cpu_addr_t fault_msp_start(void) +{ + return (cpu_addr_t)&CSTACK_BLOCK_START(DEFAULT_CSTACK_SECTION_NAME); +} + +__STATIC_INLINE__ cpu_addr_t fault_msp_limit(void) +{ + return (cpu_addr_t)&CSTACK_BLOCK_END(DEFAULT_CSTACK_SECTION_NAME); +} + +#elif defined(__ICCARM__) + +#define DEFAULT_CODE_SECTION_NAME ".text" +#define DEFAULT_CSTACK_SECTION_NAME "CSTACK" + +#pragma section=DEFAULT_CSTACK_SECTION_NAME +#pragma section=DEFAULT_CODE_SECTION_NAME + +__STATIC_INLINE__ cpu_addr_t fault_code_start(void) +{ + return (cpu_addr_t)__section_begin(DEFAULT_CODE_SECTION_NAME); +} + +__STATIC_INLINE__ cpu_addr_t fault_code_limit(void) +{ + return (cpu_addr_t)__section_end(DEFAULT_CODE_SECTION_NAME); +} + +__STATIC_INLINE__ cpu_addr_t fault_msp_start(void) +{ + return (cpu_addr_t)__section_begin(DEFAULT_CSTACK_SECTION_NAME); +} + +__STATIC_INLINE__ cpu_addr_t fault_msp_limit(void) +{ + return (cpu_addr_t)__section_end(DEFAULT_CSTACK_SECTION_NAME); +} + +#elif defined(__GNUC__) + +/** + * if we are using keil(armcc) or mdk(iccarm), we probably use the defult link script supplied by the IDE. + * the way to locate the text/stack section start and limit is to find them in default link script. + * but if we build our project by makefile(or something like scons, cmake, etc), we probably need to write + * our own link scrpit, if so, we should do like this(just a demo): + * + _stext = .; + .text : { + *(.text.startup) + *(.text) + *(.text.*) + } + _etext = .; + + __bss_start = .; + .bss : { + *(.bss) + *(.bss.*) + *(COMMON) + _sstack = .; + *(.cstack) + _estack = .; + } + __bss_end = .; + * by this, we can locate text/stack section start and limit by _stext/_etext and _sstack/_estack + */ +#define DEFAULT_CODE_SECTION_START _stext +#define DEFAULT_CODE_SECTION_END _etext +#define DEFAULT_CSTACK_SECTION_START _sstack +#define DEFAULT_CSTACK_SECTION_END _estack + +extern const int DEFAULT_CODE_SECTION_START; +extern const int DEFAULT_CODE_SECTION_END; + +extern const int DEFAULT_CSTACK_SECTION_START; +extern const int DEFAULT_CSTACK_SECTION_END; + +__STATIC_INLINE__ cpu_addr_t fault_code_start(void) +{ + return (cpu_addr_t)(&(DEFAULT_CODE_SECTION_START)); +} + +__STATIC_INLINE__ cpu_addr_t fault_code_limit(void) +{ + return (cpu_addr_t)(&(DEFAULT_CODE_SECTION_END)); +} + +__STATIC_INLINE__ cpu_addr_t fault_msp_start(void) +{ + return (cpu_addr_t)(&(DEFAULT_CSTACK_SECTION_START)); +} + +__STATIC_INLINE__ cpu_addr_t fault_msp_limit(void) +{ + return (cpu_addr_t)(&(DEFAULT_CSTACK_SECTION_END)); +} + +#endif + +__API__ void tos_fault_log_writer_set(k_fault_log_writer_t log_writer); + +__KERNEL__ int fault_default_log_writer(const char *format, ...); + +__KERNEL__ void fault_backtrace(cpu_addr_t lr, fault_exc_frame_t *frame); + +#endif + +#endif /* _TOS_FAULT_H_ */ + diff --git a/arch/linux/common/tos_cpu.c b/arch/linux/common/tos_cpu.c new file mode 100644 index 00000000..d1b16e22 --- /dev/null +++ b/arch/linux/common/tos_cpu.c @@ -0,0 +1,264 @@ +/*---------------------------------------------------------------------------- + * Tencent is pleased to support the open source community by making TencentOS + * available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * If you have downloaded a copy of the TencentOS binary from Tencent, please + * note that the TencentOS binary is licensed under the BSD 3-Clause License. + * + * If you have downloaded a copy of the TencentOS source code from Tencent, + * please note that TencentOS source code is licensed under the BSD 3-Clause + * License, except for the third-party components listed below which are + * subject to different license terms. Your integration of TencentOS into your + * own projects may require compliance with the BSD 3-Clause License, as well + * as the other licenses applicable to the third-party components included + * within TencentOS. + *---------------------------------------------------------------------------*/ + +#include + +__API__ uint32_t tos_cpu_clz(uint32_t val) +{ +#if defined(TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT) && (TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT == 0u) + uint32_t nbr_lead_zeros = 0; + + if (!(val & 0XFFFF0000)) { + val <<= 16; + nbr_lead_zeros += 16; + } + + if (!(val & 0XFF000000)) { + val <<= 8; + nbr_lead_zeros += 8; + } + + if (!(val & 0XF0000000)) { + val <<= 4; + nbr_lead_zeros += 4; + } + + if (!(val & 0XC0000000)) { + val <<= 2; + nbr_lead_zeros += 2; + } + + if (!(val & 0X80000000)) { + nbr_lead_zeros += 1; + } + + if (!val) { + nbr_lead_zeros += 1; + } + + return (nbr_lead_zeros); +#else + return port_clz(val); +#endif +} + +__API__ void tos_cpu_int_disable(void) +{ + port_int_disable(); +} + +__API__ void tos_cpu_int_enable(void) +{ + port_int_enable(); +} + +__API__ cpu_cpsr_t tos_cpu_cpsr_save(void) +{ + return port_cpsr_save(); +} + +__API__ void tos_cpu_cpsr_restore(cpu_cpsr_t cpsr) +{ + port_cpsr_restore(cpsr); +} + +__KERNEL__ void cpu_init(void) +{ + k_cpu_cycle_per_tick = TOS_CFG_CPU_CLOCK / k_cpu_tick_per_second; + cpu_systick_init(k_cpu_cycle_per_tick); + +#if (TOS_CFG_CPU_HRTIMER_EN > 0) + tos_cpu_hrtimer_init(); +#endif +} + +__KERNEL__ void cpu_reset(void) +{ + port_cpu_reset(); +} + +__KERNEL__ void cpu_sched_start(void) +{ + port_sched_start(); +} + +__KERNEL__ void cpu_context_switch(void) +{ + port_context_switch(); +} + +__KERNEL__ void cpu_irq_context_switch(void) +{ + port_irq_context_switch(); +} + +__KERNEL__ void cpu_systick_init(k_cycle_t cycle_per_tick) +{ + port_systick_priority_set(TOS_CFG_CPU_SYSTICK_PRIO); + port_systick_config(cycle_per_tick); +} + +#if TOS_CFG_TICKLESS_EN > 0u + +/** + * @brief Set value to systick reload value register + * + * @param cycles The value set to register + * + * @return None + */ +__STATIC_INLINE__ void cpu_systick_reload(k_cycle_t cycle_per_tick) +{ + port_systick_reload(cycle_per_tick); +} + +/** + * @brief Enable systick interrupt + * + * @return None + */ +__KERNEL__ void cpu_systick_resume(void) +{ + port_systick_resume(); +} + +/** + * @brief Disable systick interrupt + * + * @return None + */ +__KERNEL__ void cpu_systick_suspend(void) +{ + port_systick_suspend(); +} + +__KERNEL__ k_time_t cpu_systick_max_delay_millisecond(void) +{ + return port_systick_max_delay_millisecond(); +} + +__KERNEL__ void cpu_systick_expires_set(k_time_t millisecond) +{ + k_cycle_t cycles; + + cycles = (k_cycle_t)((uint64_t)millisecond * TOS_CFG_CPU_CLOCK / K_TIME_MILLISEC_PER_SEC); /* CLOCK means cycle per second */ + + cpu_systick_reload(cycles - 12); /* interrupt delay */ +} + +__KERNEL__ void cpu_systick_pending_reset(void) +{ + port_systick_pending_reset(); +} + +__KERNEL__ void cpu_systick_reset(void) +{ + cpu_systick_reload(k_cpu_cycle_per_tick); +} + +#endif /* TOS_CFG_TICKLESS_EN */ + +#if TOS_CFG_PWR_MGR_EN > 0u + +__KERNEL__ void cpu_sleep_mode_enter(void) +{ + port_sleep_mode_enter(); +} + +__KERNEL__ void cpu_stop_mode_enter(void) +{ + port_stop_mode_enter(); +} + +__KERNEL__ void cpu_standby_mode_enter(void) +{ + port_standby_mode_enter(); +} + +#endif /* TOS_CFG_PWR_MGR_EN */ + +__KERNEL__ k_stack_t *cpu_task_stk_init(void *entry, + void *arg, + void *exit, + k_stack_t *stk_base, + size_t stk_size) +{ + cpu_context_t *sp; + + sp = (cpu_context_t *)&stk_base[stk_size]; + sp = (cpu_context_t *)(((cpu_addr_t)sp & 0xFFFFFFFFFFFFFFF8)-sizeof(cpu_context_t)); + +#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u + uint8_t *slot = (uint8_t *)&stk_base[0]; + for (; slot < (uint8_t *)sp; ++slot) { + *slot = 0xCC; + } +#endif + + sp->entry = entry; + sp->arg = arg; + sp->exit = exit; + sp->thread_id = port_create_thread(sp); + + return (k_stack_t *)sp; +} + +#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u + +__KERNEL__ k_err_t cpu_task_stack_draught_depth(k_stack_t *stk_base, size_t stk_size, int *depth) +{ + uint8_t *slot; + uint8_t *sp, *bp; + int the_depth = 0; + + bp = (uint8_t *)&stk_base[0]; + + sp = &stk_base[stk_size]; + sp = (uint8_t *)((cpu_addr_t)sp & 0xFFFFFFFFFFFFFFF8); + + for (slot = sp - 1; slot >= bp; --slot) { + if (*slot != 0xCC) { + the_depth = sp - slot; + } + } + + *depth = the_depth; + if (the_depth == stk_size) { + return K_ERR_TASK_STK_OVERFLOW; + } + + return K_ERR_NONE; +} + +#endif + +#if TOS_CFG_FAULT_BACKTRACE_EN > 0u + +#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U) +__KERNEL__ void cpu_flush_fpu(void) +{ + (void)__get_FPSCR(); +} +#endif + +__KERNEL__ void cpu_fault_diagnosis(void) +{ + port_fault_diagnosis(); +} + +#endif /* TOS_CFG_FAULT_BACKTRACE_EN */ + diff --git a/arch/linux/common/tos_fault.c b/arch/linux/common/tos_fault.c new file mode 100644 index 00000000..d2f2e951 --- /dev/null +++ b/arch/linux/common/tos_fault.c @@ -0,0 +1,268 @@ +/*---------------------------------------------------------------------------- + * Tencent is pleased to support the open source community by making TencentOS + * available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * If you have downloaded a copy of the TencentOS binary from Tencent, please + * note that the TencentOS binary is licensed under the BSD 3-Clause License. + * + * If you have downloaded a copy of the TencentOS source code from Tencent, + * please note that TencentOS source code is licensed under the BSD 3-Clause + * License, except for the third-party components listed below which are + * subject to different license terms. Your integration of TencentOS into your + * own projects may require compliance with the BSD 3-Clause License, as well + * as the other licenses applicable to the third-party components included + * within TencentOS. + *---------------------------------------------------------------------------*/ + +#include "tos.h" + +#if TOS_CFG_FAULT_BACKTRACE_EN > 0u + +__STATIC_INLINE__ void fault_spin(void) +{ + tos_knl_sched_lock(); + tos_cpu_int_disable(); + while (K_TRUE) { + ; + } +} + +/* EXC_RETURN: + 31 - 28 : EXC_RETURN flag + 27 - 5 : reserved + 4 : 1, basic stack frame; 0, extended stack frame + 3 : 1, return to Thread mode; 0, return to Handler mode + 2 : 1, return to PSP; 0, return to MSP + 1 : reserved, 0 + 0 : reserved, 1 + */ +__STATIC_INLINE__ int fault_is_on_task(cpu_data_t lr) +{ + return (lr & (1u << 2)) != 0; +} + +__STATIC_INLINE__ int fault_is_thumb(cpu_data_t psr) +{ + return (psr & (1u << 24)) != 0; +} + +__STATIC_INLINE__ int fault_is_code(fault_info_t *info, cpu_data_t value) +{ + return value >= info->code_start && value <= info->code_limit; +} + +#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U) +__STATIC_INLINE__ int fault_is_extended_stack_frame(cpu_data_t lr) +{ + return (lr & (1u << 4)) == 0; +} + +__STATIC__ void fault_dump_fpu_frame(fault_fpu_frame_t *fpu_frame) +{ + /* + * As known, v7-m has a feature named "LAZY PUSH", for the reason we do not do any float + * operation in fault_backtrace, cpu will not do the real fpu register push to the stack. + * that means the value we dump in fault_dump_fpu_frame will not be the correct value of + * each FPU register. + * We define a function here which access to FPSCR, if this function involved, cpu will do + * the real FPU register push so we will get the correct dump. + * I know it's ugly, but it works. If you know a better way, please tell me. + */ + cpu_flush_fpu(); + + k_fault_log_writer("\n\n====================== FPU Registers =======================\n"); + k_fault_log_writer(" %s: %08x\n", "FPSCR", fpu_frame->fpscr); + k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n", + "S0 ", fpu_frame->s0, + "S1 ", fpu_frame->s1, + "S2 ", fpu_frame->s2, + "S3 ", fpu_frame->s3); + k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n", + "S4 ", fpu_frame->s4, + "S5 ", fpu_frame->s5, + "S6 ", fpu_frame->s6, + "S7 ", fpu_frame->s7); + k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n", + "S8 ", fpu_frame->s8, + "S9 ", fpu_frame->s9, + "S10", fpu_frame->s10, + "S11", fpu_frame->s11); + k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n", + "S12", fpu_frame->s12, + "S13", fpu_frame->s13, + "S14", fpu_frame->s14, + "S15", fpu_frame->s15); +} + +#endif + +__STATIC__ void fault_dump_cpu_frame(fault_cpu_frame_t *cpu_frame) +{ + k_fault_log_writer("\n\n====================== CPU Registers =======================\n"); + k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n", + "R0 ", cpu_frame->r0, + "R1 ", cpu_frame->r1, + "R2 ", cpu_frame->r2, + "R3 ", cpu_frame->r3); + k_fault_log_writer(" %s: %08x %s: %08x %s: %08x %s: %08x\n", + "R12", cpu_frame->r12, + "LR ", cpu_frame->lr, + "PC ", cpu_frame->pc, + "PSR", cpu_frame->spsr); +} + +__STATIC__ void fault_dump_stack(fault_info_t *info, size_t depth) +{ + cpu_addr_t sp = info->sp_before_fault;; + + k_fault_log_writer("\nTASK STACK DUMP:\n"); + while (sp <= info->stack_limit && depth--) { + k_fault_log_writer(" addr: %08x data: %08x\n", sp, (cpu_data_t)*(cpu_data_t *)sp); + sp += sizeof(cpu_addr_t); + } +} + +__STATIC__ void fault_call_stack_backtrace(fault_info_t *info, size_t depth) +{ + cpu_data_t value; + cpu_addr_t sp = info->sp_before_fault; + + if (info->is_stk_ovrf) { + return; + } + + k_fault_log_writer("\n\n====================== Dump Call Stack =====================\n"); + + k_fault_log_writer(" %x\n", info->pc); + + /* walk through the stack, check every content on stack whether is a instruction(code) */ + for (; sp < info->stack_limit && depth; sp += sizeof(cpu_addr_t)) { + value = *((cpu_addr_t *)sp) - sizeof(cpu_addr_t); + + /* if thumb, a instruction's first bit must be 1 */ + if (info->is_thumb && !(value & 1)) { + continue; + } + + if (fault_is_code(info, value)) { + k_fault_log_writer(" %x\n", value); + --depth; + } + } +} + +__STATIC__ void fault_dump_task(fault_info_t *info) +{ + k_task_t *task; + + if (!info->is_on_task) { + return; + } + + task = k_curr_task; + k_fault_log_writer("\n\n====================== Fault on task =======================\n"); + k_fault_log_writer(" TASK NAME: %s\n", task->name); + k_fault_log_writer(" STK BASE: %x\n", info->stack_start); + k_fault_log_writer(" STK SIZE: %x\n", task->stk_size * sizeof(k_stack_t)); + k_fault_log_writer(" STK LIMIT: %x\n", info->stack_limit); + + if (!info->is_stk_ovrf) { + fault_dump_stack(info, K_FAULT_STACK_DUMP_DEPTH); + } +} + +__STATIC__ void fault_dump_information(fault_info_t *info) +{ + k_fault_log_writer("\n\n================== Dump Fault Information ==================\n"); + k_fault_log_writer(" THUMB: %s\n", info->is_thumb ? "TRUE" : "FALSE"); + k_fault_log_writer(" ON TASK: %s\n", info->is_on_task? "TRUE" : "FALSE"); + k_fault_log_writer(" STK OVRF: %s\n", info->is_stk_ovrf? "TRUE" : "FALSE"); + +#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U) + k_fault_log_writer(" EXT STK: %s\n", info->is_ext_stk_frm? "TRUE" : "FALSE"); +#endif + + k_fault_log_writer(" PC: %08x\n", info->pc); + k_fault_log_writer(" SP: %08x\n", info->sp_before_fault); + k_fault_log_writer(" STK START: %08x\n", info->stack_start); + k_fault_log_writer(" STK LIMIT: %08x\n", info->stack_limit); + k_fault_log_writer(" COD START: %08x\n", info->code_start); + k_fault_log_writer(" COD LIMIT: %08x\n", info->code_limit); +} + +__STATIC__ void fault_gather_information(cpu_data_t lr, fault_exc_frame_t *frame, fault_info_t *info) +{ + info->is_thumb = fault_is_thumb(frame->cpu_frame.spsr); + info->is_on_task = fault_is_on_task(lr); + + info->pc = frame->cpu_frame.pc; + + info->sp_before_fault = (cpu_addr_t)frame + sizeof(fault_cpu_frame_t); + +#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U) + info->is_ext_stk_frm = fault_is_extended_stack_frame(lr); + + if (info->is_ext_stk_frm) { + info->sp_before_fault += sizeof(fault_fpu_frame_t); + } +#endif + + info->code_start = fault_code_start(); + info->code_limit = fault_code_limit(); + + if (info->is_on_task) { + info->stack_start = (cpu_addr_t)k_curr_task->stk_base; + info->stack_limit = info->stack_start + k_curr_task->stk_size * sizeof(k_task_t); + } else { + info->stack_start = fault_msp_start(); + info->stack_limit = fault_msp_limit(); + } + + info->is_stk_ovrf = (info->sp_before_fault < info->stack_start || info->sp_before_fault > info->stack_limit); +} + +__KERNEL__ int fault_default_log_writer(const char *format, ...) +{ + int len; + va_list ap; + + va_start(ap, format); + len = vprintf(format, ap); + va_end(ap); + + return len; +} + +__API__ void tos_fault_log_writer_set(k_fault_log_writer_t log_writer) +{ + k_fault_log_writer = log_writer; +} + +__KERNEL__ void fault_backtrace(cpu_addr_t lr, fault_exc_frame_t *frame) +{ + fault_info_t info; + + fault_gather_information(lr, frame, &info); + + fault_dump_information(&info); + + fault_dump_task(&info); + + fault_dump_cpu_frame(&frame->cpu_frame); + +#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U) + if (info.is_ext_stk_frm) { + fault_dump_fpu_frame(&frame->fpu_frame); + } +#endif + + fault_call_stack_backtrace(&info, K_FAULT_CALL_STACK_BACKTRACE_DEPTH); + + cpu_fault_diagnosis(); + + fault_spin(); +} + +#endif + diff --git a/arch/linux/posix/gcc/port.c b/arch/linux/posix/gcc/port.c new file mode 100644 index 00000000..730c639a --- /dev/null +++ b/arch/linux/posix/gcc/port.c @@ -0,0 +1,359 @@ +/*---------------------------------------------------------------------------- + * Tencent is pleased to support the open source community by making TencentOS + * available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * If you have downloaded a copy of the TencentOS binary from Tencent, please + * note that the TencentOS binary is licensed under the BSD 3-Clause License. + * + * If you have downloaded a copy of the TencentOS source code from Tencent, + * please note that TencentOS source code is licensed under the BSD 3-Clause + * License, except for the third-party components listed below which are + * subject to different license terms. Your integration of TencentOS into your + * own projects may require compliance with the BSD 3-Clause License, as well + * as the other licenses applicable to the third-party components included + * within TencentOS. + *---------------------------------------------------------------------------*/ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2018 Armink (armink.ztl@gmail.com) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * 'Software'), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "tos.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern k_task_t *k_curr_task; +extern k_task_t *k_next_task; + +__PORT__ void _handle_tick_signal(); +__PORT__ void _handle_context_switch(); +__PORT__ void _delay_ms(uint32_t ms); +__PORT__ void _suspend_thread(pthread_t thread_id); +__PORT__ void _resume_thread(pthread_t thread_id); +__PORT__ void _wait_resume(); +__PORT__ void _handle_suspend_thread(); +__PORT__ void _handle_resume_thread(); +__PORT__ void *_thread_entry(void *arg); +__PORT__ void _suspend_task(k_task_t *task); +__PORT__ void _resume_task(k_task_t *task); +__PORT__ void _install_signal(int sig,void (*func)(int)); +__PORT__ void _filter_signal(sigset_t *sigset); + +typedef struct { + sigset_t signal_mask; + uint32_t count; +}interrupt_manager; + +interrupt_manager _int_manager={ + .count = 0 +}; + +__PORT__ void port_int_disable(void) +{ + sigset_t signal_mask,*manager_mask=NULL; + if(_int_manager.count == 0){ + manager_mask = &(_int_manager.signal_mask); + } + _int_manager.count ++; + sigfillset(&signal_mask); + _filter_signal(&signal_mask); + pthread_sigmask(SIG_BLOCK,&signal_mask,manager_mask); +} + +__PORT__ void port_int_enable(void) +{ + if(_int_manager.count == 0) return; + + _int_manager.count--; + if(_int_manager.count == 0){ + sigaddset(&(_int_manager.signal_mask),SIG_RESUME); //ensure SIG_RESUME is blocked + _filter_signal(&(_int_manager.signal_mask)); + pthread_sigmask(SIG_SETMASK,&(_int_manager.signal_mask),NULL); + } +} + +__PORT__ cpu_cpsr_t port_cpsr_save(void) +{ + port_int_disable(); + return (cpu_cpsr_t)_int_manager.count; +} + +__PORT__ void port_cpsr_restore(cpu_cpsr_t cpsr) +{ + port_int_enable(); +} + +__PORT__ pthread_t port_create_thread(void *arg) +{ + pthread_t thread_id; + pthread_create(&thread_id,NULL,_thread_entry,arg); + return thread_id; +} + +__PORT__ void port_sched_start(void) +{ + _install_signal(SIG_SUSPEND, _handle_suspend_thread); + _install_signal(SIG_RESUME, _handle_resume_thread); + _install_signal(SIG_CONTEXT_SWITCH, _handle_context_switch); + + k_curr_task = k_next_task; + _resume_task(k_curr_task); + + while(1){ + _delay_ms(1000); + } +} + +__PORT__ void port_context_switch(void) +{ + raise(SIG_CONTEXT_SWITCH); +} + +__PORT__ void port_irq_context_switch(void) +{ + raise(SIG_CONTEXT_SWITCH); +} + +__PORT__ void port_cpu_reset(void) +{ + printf("func %s\n",__FUNCTION__); + exit(0); +} + +__PORT__ void port_systick_config(uint32_t cycle_per_tick) +{ + struct itimerval itimer, oitimer; + uint32_t timeer_usec = cycle_per_tick/(TOS_CFG_CPU_CLOCK/1000000u); + + _install_signal(SIG_TICK,_handle_tick_signal); + + /* Initialise the structure with the current timer information. */ + if ( 0 == getitimer( TIMER_TYPE, &itimer ) ) + { + /* Set the interval between timer events. */ + itimer.it_interval.tv_sec = 0; + itimer.it_interval.tv_usec = timeer_usec; + + /* Set the current count-down. */ + itimer.it_value.tv_sec = 0; + itimer.it_value.tv_usec = timeer_usec; + + /* Set-up the timer interrupt. */ + if ( 0 != setitimer( TIMER_TYPE, &itimer, &oitimer ) ) + { + printf( "set timer problem.\n" ); + } + } + else + { + printf( "get timer problem.\n" ); + } +} + +__PORT__ void port_systick_priority_set(uint32_t prio) +{ +} + +__PORT__ void _filter_signal(sigset_t *sigset) +{ + sigdelset(sigset,SIGINT); + sigdelset(sigset,SIGKILL); //ensure program cloud be kill +} + + +__PORT__ uint64_t _get_time_ms(void) +{ + struct timeval timer; + gettimeofday( &timer, NULL ); + + return (1000 * timer.tv_sec + timer.tv_usec/1000); +} + +__PORT__ void _delay_ms(uint32_t ms) +{ + uint64_t start_time = _get_time_ms(); + do{ + usleep(100); + }while((_get_time_ms() - start_time) < ms); +} + +__PORT__ void _install_signal(int sig,void (*func)(int)) +{ + struct sigaction sig_install; + + sig_install.sa_flags = 0; + sig_install.sa_handler = func; + sigfillset( &sig_install.sa_mask ); + + if ( 0 != sigaction( sig, &sig_install, NULL ) ) + { + printf( "problem installing %d\n",sig ); + } +} + +__PORT__ void _handle_tick_signal() +{ + if(tos_knl_is_running()) { + tos_knl_irq_enter(); + tos_tick_handler(); + tos_knl_irq_leave(); + } +} + +__PORT__ void _suspend_thread(pthread_t thread_id) +{ + pthread_kill(thread_id,SIG_SUSPEND); +} + +__PORT__ void _resume_thread(pthread_t thread_id) +{ + pthread_kill(thread_id,SIG_RESUME); +} + +__PORT__ void _suspend_task(k_task_t *task) +{ + cpu_context_t *context = (cpu_context_t *)(task->sp); + pthread_t thread_id = context->thread_id; + _suspend_thread(thread_id); +} + +__PORT__ void _resume_task(k_task_t *task) +{ + cpu_context_t *context = (cpu_context_t *)(task->sp); + pthread_t thread_id = context->thread_id; + _resume_thread(thread_id); +} + +__PORT__ void _wait_resume() +{ + sigset_t signals; + int sig; + sigemptyset( &signals ); + sigaddset( &signals, SIG_RESUME); + pthread_sigmask(SIG_BLOCK, &signals,NULL); + sigwait(&signals,&sig); +} + +__PORT__ void _handle_suspend_thread() +{ + _wait_resume(); +} + +__PORT__ void _handle_resume_thread() +{ + printf("some thread not block SIG_RESUME\n"); +} + +__PORT__ void *_thread_entry(void *arg) +{ + cpu_context_t *params = (cpu_context_t *)arg; + _wait_resume(); + params->entry(params->arg); + params->exit(params->arg); +} + +__PORT__ void _handle_context_switch() +{ + _suspend_task(k_curr_task); + k_curr_task = k_next_task; + _resume_task(k_curr_task); +} + +#if TOS_CFG_TICKLESS_EN > 0u + +__PORT__ k_time_t port_systick_max_delay_millisecond(void) +{ + +} + +__PORT__ void port_systick_resume(void) +{ + +} + +__PORT__ void port_systick_suspend(void) +{ + +} + +__PORT__ void port_systick_reload(uint32_t cycle_per_tick) +{ + +} + +__PORT__ void port_systick_pending_reset(void) +{ + +} + +#endif + +#if TOS_CFG_PWR_MGR_EN > 0u + +__PORT__ void port_sleep_mode_enter(void) +{ + +} + +__PORT__ void port_stop_mode_enter(void) +{ + +} + +__PORT__ void port_standby_mode_enter(void) +{ + +} + +#endif + +#if TOS_CFG_FAULT_BACKTRACE_EN > 0u +__STATIC__ void port_fault_do_diagnosis(port_fault_regs_t *regs) +{ + k_fault_log_writer("\n\n====================== Fault Diagnosis =====================\n"); + +} + +__PORT__ void port_fault_diagnosis(void) +{ + port_fault_regs_t regs; + + port_fault_do_diagnosis(®s); +} + +// implementation jump to fault_backtrace + +#endif /* TOS_CFG_FAULT_BACKTRACE_EN */ + diff --git a/arch/linux/posix/gcc/port.h b/arch/linux/posix/gcc/port.h new file mode 100644 index 00000000..5c7498a8 --- /dev/null +++ b/arch/linux/posix/gcc/port.h @@ -0,0 +1,121 @@ +/*---------------------------------------------------------------------------- + * Tencent is pleased to support the open source community by making TencentOS + * available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * If you have downloaded a copy of the TencentOS binary from Tencent, please + * note that the TencentOS binary is licensed under the BSD 3-Clause License. + * + * If you have downloaded a copy of the TencentOS source code from Tencent, + * please note that TencentOS source code is licensed under the BSD 3-Clause + * License, except for the third-party components listed below which are + * subject to different license terms. Your integration of TencentOS into your + * own projects may require compliance with the BSD 3-Clause License, as well + * as the other licenses applicable to the third-party components included + * within TencentOS. + *---------------------------------------------------------------------------*/ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2018 Armink (armink.ztl@gmail.com) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * 'Software'), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _PORT_H_ +#define _PORT_H_ + +#include + +#define SIG_SUSPEND SIGUSR1 +#define SIG_RESUME SIGUSR2 +#define SIG_CONTEXT_SWITCH SIGRTMIN +#define SIG_TICK SIGALRM +#define TIMER_TYPE ITIMER_REAL + +#if TOS_CFG_FAULT_BACKTRACE_EN > 0u +typedef struct port_fault_regs { + uint32_t error_flags; +} port_fault_regs_t; + +enum fault_info { + //FAULT_INFO_XXX, +}; + +static const char *const fault_msg[] = { + //[FAULT_INFO_XXX] = "FAULT_INFO_XXX string msg", +}; + +__PORT__ void port_fault_diagnosis(void); +#endif + +#if defined(TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT) && (TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT == 1u) +__PORT__ uint32_t port_clz(uint32_t val); +#endif + +__PORT__ void port_int_disable(void); + +__PORT__ void port_int_enable(void); + +__PORT__ cpu_cpsr_t port_cpsr_save(void); + +__PORT__ void port_cpsr_restore(cpu_cpsr_t cpsr); + +__PORT__ void port_cpu_reset(void); //ok + +__PORT__ void port_sched_start(void) __NO_RETURN__; + +__PORT__ void port_context_switch(void); + +__PORT__ void port_irq_context_switch(void); + +__PORT__ void port_systick_config(uint32_t cycle_per_tick); + +__PORT__ void port_systick_priority_set(uint32_t prio); //ok + +__PORT__ pthread_t port_create_thread(void *arg); + +#if TOS_CFG_TICKLESS_EN > 0u + +__PORT__ void port_systick_resume(void); + +__PORT__ void port_systick_suspend(void); + +__PORT__ void port_systick_reload(uint32_t cycle_per_tick); + +__PORT__ void port_systick_pending_reset(void); + +__PORT__ k_time_t port_systick_max_delay_millisecond(void); + +#endif + +#if TOS_CFG_PWR_MGR_EN > 0u + +__PORT__ void port_sleep_mode_enter(void); + +__PORT__ void port_stop_mode_enter(void); + +__PORT__ void port_standby_mode_enter(void); + +#endif + +#endif /* _PORT_H_ */ + diff --git a/arch/linux/posix/gcc/port_config.h b/arch/linux/posix/gcc/port_config.h new file mode 100644 index 00000000..e87668e6 --- /dev/null +++ b/arch/linux/posix/gcc/port_config.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------- + * Tencent is pleased to support the open source community by making TencentOS + * available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * If you have downloaded a copy of the TencentOS binary from Tencent, please + * note that the TencentOS binary is licensed under the BSD 3-Clause License. + * + * If you have downloaded a copy of the TencentOS source code from Tencent, + * please note that TencentOS source code is licensed under the BSD 3-Clause + * License, except for the third-party components listed below which are + * subject to different license terms. Your integration of TencentOS into your + * own projects may require compliance with the BSD 3-Clause License, as well + * as the other licenses applicable to the third-party components included + * within TencentOS. + *---------------------------------------------------------------------------*/ + +#ifndef _PORT_CONFIG_H_ +#define _PORT_CONFIG_H_ + +#define TOS_CFG_CPU_ADDR_SIZE CPU_WORD_SIZE_64 +#define TOS_CFG_CPU_DATA_SIZE CPU_WORD_SIZE_64 +#define TOS_CFG_CPU_STK_GROWTH CPU_STK_GROWTH_DESCENDING +// #define TOS_CFG_CPU_HRTIMER_SIZE CPU_WORD_SIZE_32 +#define TOS_CFG_CPU_HRTIMER_EN 0u +#define TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT 0u + +#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) +#define TOS_CFG_CPU_ARM_FPU_EN 1u +#else +#define TOS_CFG_CPU_ARM_FPU_EN 0u +#endif + +#endif /* _PORT_CONFIG_H_ */ + diff --git a/board/Linux_Posix/hello_world/CMakeLists.txt b/board/Linux_Posix/hello_world/CMakeLists.txt new file mode 100644 index 00000000..4a7b5a4b --- /dev/null +++ b/board/Linux_Posix/hello_world/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.8) + +project(hello_world) + +set(CMAKE_BUILD_TYPE "Debug") +set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb") +set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") + +set(TINY_ROOT ../../../) + +include_directories(${TINY_ROOT}/osal/cmsis_os) +include_directories(${TINY_ROOT}/kernel/core/include) +include_directories(${TINY_ROOT}/kernel/evtdrv/include) +include_directories(${TINY_ROOT}/kernel/hal/include) +include_directories(${TINY_ROOT}/kernel/pm/include) + +aux_source_directory(${TINY_ROOT}/osal/cmsis_os CMSIS_SRCS) +aux_source_directory(${TINY_ROOT}/kernel/core CORE_SRCS) +aux_source_directory(${TINY_ROOT}/kernel/evtdrv EVTDRV_SRCS) +aux_source_directory(${TINY_ROOT}/kernel/pm PM_SRCS) + +set(ARCH_ROOT ${TINY_ROOT}/arch/linux) + +include_directories(${ARCH_ROOT}/common/include) +include_directories(${ARCH_ROOT}/posix/gcc) + +aux_source_directory(${ARCH_ROOT}/common ARCH_COMMON_SRCS) +aux_source_directory(${ARCH_ROOT}/posix/gcc ARCH_POSIX_SRCS) + +set(ARCH_SRCS ${ARCH_COMMON_SRCS} ${ARCH_POSIX_SRCS}) + +set(TINY_SRCS ${ARCH_SRCS} ${CMSIS_SRCS} ${EVTDRV_SRCS} ${PM_SRCS} ${CORE_SRCS} ) + +include_directories(./) +include_directories(./inc) + +set(APP_SRCS src/main.c) + +add_executable(hello_world ${APP_SRCS} ${TINY_SRCS}) + +target_link_libraries(hello_world pthread) \ No newline at end of file diff --git a/board/Linux_Posix/hello_world/inc/tos_config.h b/board/Linux_Posix/hello_world/inc/tos_config.h new file mode 100644 index 00000000..7cd5e2a9 --- /dev/null +++ b/board/Linux_Posix/hello_world/inc/tos_config.h @@ -0,0 +1,46 @@ +#ifndef _TOS_CONFIG_H_ +#define _TOS_CONFIG_H_ + +#include "stddef.h" + +#define TOS_CFG_TASK_PRIO_MAX 10u // 配置TencentOS tiny默认支持的最大优先级数量 + +#define TOS_CFG_ROUND_ROBIN_EN 1u // 配置TencentOS tiny的内核是否开启时间片轮转 + +#define TOS_CFG_OBJECT_VERIFY 0u // 配置TencentOS tiny是否校验指针合法 + +#define TOS_CFG_EVENT_EN 1u // TencentOS tiny 事件模块功能宏 + +#define TOS_CFG_MMHEAP_EN 1u // 配置TencentOS tiny是否开启动态内存模块 + +#define TOS_CFG_MMHEAP_POOL_SIZE 0x100 // 配置TencentOS tiny动态内存池大小 + +#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x100 // 配置TencentOS tiny动态内存池大小 + +#define TOS_CFG_MUTEX_EN 1u // 配置TencentOS tiny是否开启互斥锁模块 + +#define TOS_CFG_QUEUE_EN 1u // 配置TencentOS tiny是否开启队列模块 + +#define TOS_CFG_TIMER_EN 1u // 配置TencentOS tiny是否开启软件定时器模块 + +#define TOS_CFG_SEM_EN 1u // 配置TencentOS tiny是否开启信号量模块 + +#define TOS_CFG_MMBLK_EN 1u + +#if (TOS_CFG_QUEUE_EN > 0u) +#define TOS_CFG_MSG_EN 1u +#else +#define TOS_CFG_MSG_EN 0u +#endif + +#define TOS_CFG_MSG_POOL_SIZE 10u // 配置TencentOS tiny消息队列大小 + +#define TOS_CFG_IDLE_TASK_STK_SIZE 256u // 配置TencentOS tiny空闲任务栈大小 + +#define TOS_CFG_CPU_TICK_PER_SECOND 1000u // 配置TencentOS tiny的tick频率 + +#define TOS_CFG_CPU_CLOCK 1000000u // 配置TencentOS tiny CPU频率 + +#define TOS_CFG_TIMER_AS_PROC 1u // 配置是否将TIMER配置成函数模式 + +#endif \ No newline at end of file diff --git a/board/Linux_Posix/hello_world/readme.md b/board/Linux_Posix/hello_world/readme.md new file mode 100644 index 00000000..a35c15da --- /dev/null +++ b/board/Linux_Posix/hello_world/readme.md @@ -0,0 +1,36 @@ +# How to run the demo in linux + +## step1 +make sure your develop environment. ++ `cmake` and version greater than 3.8.2 ++ `gcc` `gdb` `make` is installed + +## step2 +make `build` directory and compile in `build` + +```bash +mkdir build && cd build +cmake .. +make +``` + +## step3 +run program !! + +```bash +# in build directory +./hello_world +``` + +## other +you can copy this demo to other path, but if you want do it, +you need modify `CMakeLists.txt`. find line + +```cmake +set(TINY_ROOT ../../../) +``` + +and modify `path-to-tinyos` +```cmake +set(TINY_ROOT path-to-tinyos) +``` diff --git a/board/Linux_Posix/hello_world/src/main.c b/board/Linux_Posix/hello_world/src/main.c new file mode 100644 index 00000000..ce858a11 --- /dev/null +++ b/board/Linux_Posix/hello_world/src/main.c @@ -0,0 +1,53 @@ +#include "cmsis_os.h" + +#define TASK1_STK_SIZE 512 +void task1(void *arg); +osThreadDef(task1, osPriorityNormal, 1, TASK1_STK_SIZE); + +#define TASK2_STK_SIZE 512 +void task2(void *arg); +osThreadDef(task2, osPriorityNormal, 1, TASK2_STK_SIZE); + +void task1(void *arg) +{ + int count = 1; + while (1) { + printf("###This is task1, %d\r\n", count++); + osDelay(2000); + } +} + +void task2(void *arg) +{ + int count = 1; + while (1) { +#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u + k_err_t rc; + int depth; + + rc = tos_task_stack_draught_depth(K_NULL, &depth); + printf("%d %d\n", rc, depth); +#endif + + printf("***This is task2, %d\r\n", count++); + osDelay(1000); + } +} + +void application_entry(void *arg) +{ + osThreadCreate(osThread(task1), NULL); // Create task1 + osThreadCreate(osThread(task2), NULL); // Create task2 +} + + +int main(void) +{ + osKernelInitialize(); //TOS Tiny kernel initialize + application_entry(NULL); + osKernelStart(); //Start TOS Tiny + + while (1) + { + } +}