First commit XiUOS

This commit is contained in:
xuetest
2021-04-28 17:49:18 +08:00
commit 6001051eb7
1331 changed files with 433955 additions and 0 deletions

317
kernel/Kconfig Normal file
View File

@@ -0,0 +1,317 @@
menu "Kernel feature"
menu "separate compile(choose none for compile once)"
config SEPARATE_COMPILE
bool
default n
config COMPILER_APP
bool "only compile application"
default n
select USER_APPLICATION
select SEPARATE_COMPILE
choice
prompt "select the startup site of APP "
default APP_STARTUP_FROM_FLASH
config APP_STARTUP_FROM_SDCARD
bool "app start from sd card"
config APP_STARTUP_FROM_FLASH
bool "app start from flash"
endchoice
config COMPILER_KERNEL
bool "only compile kernel"
default n
select SEPARATE_COMPILE
endmenu
menu "Memory Management"
config KERNEL_MEMBLOCK
bool "Using gather block"
default n
config MEM_ALIGN_SIZE
int "Alignment size for CPU architecture data access"
default 8
help
Alignment size for CPU architecture data access
config MM_PAGE_SIZE
int "Config memory page size"
default 4096
help
config memory page size
menu "Using small memory allocator"
config KERNEL_SMALL_MEM_ALLOC
bool "Using small memory allocator"
default y
if KERNEL_SMALL_MEM_ALLOC
config SMALL_NUMBER_32B
int "Config 32B small memory number"
range 1 256
default 64
config SMALL_NUMBER_64B
int "Config 64B small memory number"
range 1 128
default 32
endif
endmenu
endmenu
menu "Task feature"
config USER_APPLICATION
bool "start system application"
default y
config TASK_ISOLATION
bool "Enable task isolation"
default n
select SEPARATE_COMPILE
select COMPILER_APP
select COMPILER_KERNEL
help
Enable task isolation
menu "Inter-Task communication"
config KERNEL_SEMAPHORE
bool "Enable semaphore"
default y
config KERNEL_MUTEX
bool "Enable mutex"
default y
config KERNEL_EVENT
bool "Enable event"
default y
config KERNEL_MESSAGEQUEUE
bool "Enable message queue"
default y
config KERNEL_SOFTTIMER
bool "Enable softtimer "
select KERNEL_WORKQUEUE
default y
endmenu
choice
prompt "Scheduler Policy Set"
default SCHED_POLICY_RR_REMAINSLICE
config SCHED_POLICY_RR_REMAINSLICE
bool "config scheduler policy as RR REMAINSLICE"
config SCHED_POLICY_RR
bool "config scheduler policy as RR "
config SCHED_POLICY_FIFO
bool "config scheduler policy as FIFO"
endchoice
choice
prompt "The maximal level value of priority of task"
default KTASK_PRIORITY_32
config KTASK_PRIORITY_8
bool "8"
config KTASK_PRIORITY_32
bool "32"
config KTASK_PRIORITY_256
bool "256"
endchoice
config KTASK_PRIORITY_MAX
int
default 8 if KTASK_PRIORITY_8
default 32 if KTASK_PRIORITY_32
default 256 if KTASK_PRIORITY_256
config TICK_PER_SECOND
int "Tick frequency, Hz"
range 10 1000
default 100
help
System's tick frequency, Hz.
config KERNEL_STACK_OVERFLOW_CHECK
bool "Using stack overflow checking"
default y
help
Enable task stack overflow checking. The stack overflow is checking when
each task switch.
config IDLE_KTASK_STACKSIZE
int "The stack size of idle task"
default 1024
config ZOMBIE_KTASK_STACKSIZE
int "The stack size of zombie_recycle task"
default 2048
endmenu
menu "Kernel Console"
config KERNEL_CONSOLE
bool "config enable console"
default y
if KERNEL_CONSOLE
config KERNEL_BANNER
bool "config system banner print"
default y
config KERNEL_CONSOLEBUF_SIZE
int "default buffer size for console log printf"
default 128
endif
endmenu
menu "Kernel Hook"
menuconfig KERNEL_HOOK
bool "Enable system hook"
default n
help
Enable the hook function when system running, such as idle task hook,
task context switch etc.
if KERNEL_HOOK
menuconfig KERNEL_IDLE_HOOK
bool "Enable IDLE Task hook"
default y
if KERNEL_IDLE_HOOK
config IDEL_HOOK_LIST_SIZE
int "The max size of idle hook list"
default 4
range 1 16
help
The system has a hook list. This is the hook list size.
endif
endif
endmenu
source "$KERNEL_DIR/tool/shell/Kconfig"
menu "Kernel data structure Manage"
menuconfig KERNEL_QUEUEMANAGE
bool "Config Kernel Queue Manage"
default y
if KERNEL_QUEUEMANAGE
config KERNEL_WORKQUEUE
bool "Config kernel work queue"
default y
if KERNEL_WORKQUEUE
config WORKQUEUE_KTASK_STACKSIZE
int "The stack size for workqueue task"
default 2048
config WORKQUEUE_KTASK_PRIORITY
int
default 6 if KTASK_PRIORITY_8
default 23 if KTASK_PRIORITY_32
default 128 if KTASK_PRIORITY_256
config QUEUE_MAX
int "Config the max queue length"
default 16
endif
config KERNEL_WAITQUEUE
bool "Config kernel wait queue"
default y
config KERNEL_DATAQUEUE
bool "Config kernel data queue"
default y
endif
config KERNEL_CIRCULAR_AREA
bool "Config Kernel Circular Area"
default n
config KERNEL_AVL_TREE
bool "Config Kernel AVL Tree"
default n
endmenu
menu "Kernel components init"
menuconfig KERNEL_COMPONENTS_INIT
bool "Use components automatically initialization"
default y
if KERNEL_COMPONENTS_INIT
config ENV_INIT_KTASK_STACK_SIZE
int "Set env init task stack size"
default 8192
menuconfig KERNEL_USER_MAIN
bool "The main() function as user entry function"
default y
endif
endmenu
config NAME_NUM_MAX
int "The maximal size of kernel object name"
range 2 32
default 32
help
Each kernel object, such as task has a name,
the NAME_NUM_MAX is the maximal size of this name.
menuconfig KERNEL_DEBUG
bool "Enable debugging features"
default n
if KERNEL_DEBUG
config DEBUG_INIT_CONFIG
bool "Enable debugging of components initialization"
default y
config KDYN_LOG_DBG
bool "Enable DYNAMIC [DBG] LOG"
default y
config DBG_INIT
int
default 1 if DEBUG_INIT_CONFIG
endif
menuconfig ARCH_SMP
bool "Enable SMP(Symmetric multiprocessing)"
default n
help
This option should be selected by machines which have an SMP-
capable CPU.
The only effect of this option is to make the SMP-related
options available to the user for configuration.
config CPU_NUMBERS
int "Number of CPUs"
default 2
depends on ARCH_SMP
help
Number of CPUs in the system
menu "hash table config"
menuconfig ID_HTABLE_SIZE
int "ID hash table size"
range 1 256
default 16
help
Size of the hash table that ID manager uses internally
menuconfig ID_NUM_MAX
int "ID num max"
range 16 256
default 128
help
max num of the ID manager
endmenu
source "$KERNEL_DIR/kernel/kernel_test/Kconfig"
endmenu

9
kernel/Makefile Normal file
View File

@@ -0,0 +1,9 @@
SRC_DIR := thread memory
ifeq ($(CONFIG_KERNEL_TEST), y)
SRC_DIR += kernel_test
endif
SRC_DIR +=kernel_service
include $(KERNEL_ROOT)/compiler.mk

247
kernel/include/user_api.h Normal file
View File

@@ -0,0 +1,247 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: user_api.h
* @brief: the priviate user api for application
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef XS_USER_API_H
#define XS_USER_API_H
// #include <xiuos.h>
#include <xsconfig.h>
#include "../../../kernel/include/xs_service.h"
#include "../../../kernel/include/xs_base.h"
#include <stddef.h>
#include <stdint.h>
#include "../../../arch/kswitch.h"
#include <libc.h>
#ifdef SEPARATE_COMPILE
#define TASK_INFO 1
#define MEM_INFO 2
#define SEM_INFO 3
#define EVENT_INFO 4
#define MUTEX_INFO 5
#define MEMPOOL_INFO 6
#define MSGQUEUE_INFO 7
#define DEVICE_INFO 8
#define TIMER_INFO 9
int UserPrintInfo(unsigned long i);
struct utask
{
char name[NAME_NUM_MAX];
void *func_entry;
void *func_param;
int32_t stack_size;
uint8_t prio;
};
typedef struct utask utask_x;
typedef void DIR;
int32_t UserTaskCreate(utask_x utask);
x_err_t UserTaskStartup(int32_t id);
x_err_t UserTaskDelete(int32_t id);
void UserTaskQuit(void);
x_err_t UserTaskDelay(int32_t ms);
x_err_t UserGetTaskName(int32_t id ,char *name);
int32_t UserGetTaskID(void);
uint8_t UserGetTaskStat(int32_t id);
#ifdef ARCH_SMP
x_err_t UserTaskCoreCombine(int32_t id,uint8_t core_id);
x_err_t UserTaskCoreUnCombine(int32_t id);
uint8_t UserGetTaskCombinedCore(int32_t id);
uint8_t UserGetTaskRunningCore(int32_t id);
#endif
x_err_t UserGetTaskErrorstatus(int32_t id);
uint8_t UserGetTaskPriority(int32_t id);
void *UserMalloc(size_t size);
void *UserRealloc(void *pointer, size_t size);
void *UserCalloc(size_t count, size_t size);
void UserFree(void *pointer);
#ifdef KERNEL_MUTEX
int32_t UserMutexCreate();
void UserMutexDelete(int32_t mutex);
int32_t UserMutexObtain(int32_t mutex, int32_t wait_time);
int32_t UserMutexAbandon(int32_t mutex);
#endif
#ifdef KERNEL_SEMAPHORE
typedef int32 sem_t;
sem_t UserSemaphoreCreate(uint16_t val);
x_err_t UserSemaphoreDelete(sem_t sem);
x_err_t UserSemaphoreObtain(sem_t sem, int32_t wait_time);
x_err_t UserSemaphoreAbandon(sem_t sem);
x_err_t UserSemaphoreSetValue(sem_t sem, uint16_t val);
#endif
#ifdef KERNEL_EVENT
typedef int32 EventIdType;
EventIdType UserEventCreate(uint8_t flag);
void UserEventDelete(EventIdType event);
x_err_t UserEventTrigger(EventIdType event, uint32_t set);
x_err_t UserEventProcess(EventIdType event, uint32_t set, uint8_t option,
int32_t wait_time, uint32_t *Recved);
x_err_t UserEventReinit(EventIdType event);
#endif
#ifdef KERNEL_MESSAGEQUEUE
int32_t UserMsgQueueCreate(size_t msg_size, size_t max_msgs);
x_err_t UserMsgQueueDelete(int32_t mq );
x_err_t UserMsgQueueSendwait(int32_t mq, const void *buffer,
size_t size, int32_t wait_time);
x_err_t UserMsgQueueSend(int32_t mq, const void *buffer, size_t size);
x_err_t UserMsgQueueUrgentSend(int32_t mq, const void *buffer, size_t size);
x_err_t UserMsgQueueRecv(int32_t mq, void *buffer, size_t size,int32_t wait_time);
x_err_t UserMsgQueueReinit(int32_t mq);
#endif
int open(const char *path, int flags, ...);
int read(int fd, void *buf, size_t len);
int write(int fd, const void *buf, size_t len);
int close(int fd);
int ioctl(int fd, int cmd, void *args);
off_t lseek(int fd, off_t offset, int whence);
int rename(const char *from, const char *to);
int unlink(const char *path);
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int fsync(int fd);
int ftruncate(int fd, off_t length);
int mkdir(const char *path, mode_t mode);
DIR *opendir(const char *path);
int closedir(DIR *dirp);
struct dirent *readdir(DIR *dirp);
int rmdir(const char *path);
int chdir(const char *path);
char *getcwd(char *buf, size_t size);
long telldir(DIR *dirp);
void seekdir(DIR *dirp, off_t offset);
void rewinddir(DIR *dirp);
#ifdef FS_VFS
struct statfs {
size_t f_bsize;
size_t f_blocks;
size_t f_bfree;
};
int statfs(const char *path, struct statfs *buf);
#endif
void Userprintf(const char *fmt, ...);
#define printf Userprintf
#else
#ifdef FS_VFS
#include <iot-vfs_posix.h>
#endif
struct utask
{
char name[NAME_NUM_MAX];
void *func_entry;
void *func_param;
int32_t stack_size;
uint8_t prio;
};
typedef struct utask utask_x;
int32_t UserTaskCreate(utask_x utask);
#define UserTaskStartup StartupKTask
#define UserTaskDelete KTaskDelete
#define UserTaskQuit KTaskQuit
#define UserTaskDelay MdelayKTask
x_err_t UserGetTaskName(int32_t id ,char *name);
int32_t UserGetTaskID(void);
uint8_t UserGetTaskStat(int32_t id);
#ifdef ARCH_SMP
#define UserTaskCoreCombine KTaskCoreCombine
#define UserTaskCoreUnCombine KTaskCoreUnCombine
uint8_t UserGetTaskCombinedCore(int32_t id);
uint8_t UserGetTaskRunningCore(int32_t id);
#endif
x_err_t UserGetTaskErrorstatus(int32_t id);
uint8_t UserGetTaskPriority(int32_t id);
#define UserMalloc x_malloc
#define UserRealloc x_realloc
#define UserCalloc x_calloc
#define UserFree x_free
#ifdef KERNEL_MUTEX
#define UserMutexCreate KMutexCreate
#define UserMutexDelete KMutexDelete
#define UserMutexObtain KMutexObtain
#define UserMutexAbandon KMutexAbandon
#endif
#ifdef KERNEL_SEMAPHORE
#define UserSemaphoreCreate KSemaphoreCreate
#define UserSemaphoreDelete KSemaphoreDelete
#define UserSemaphoreObtain KSemaphoreObtain
#define UserSemaphoreAbandon KSemaphoreAbandon
#define UserSemaphoreSetValue KSemaphoreSetValue
#endif
#ifdef KERNEL_EVENT
#define UserEventCreate KEventCreate
#define UserEventDelete KEventDelete
#define UserEventTrigger KEventTrigger
#define UserEventProcess KEventProcess
#endif
#ifdef KERNEL_MESSAGEQUEUE
#define UserMsgQueueCreate KCreateMsgQueue
#define UserMsgQueueDelete KDeleteMsgQueue
#define UserMsgQueueSendwait KMsgQueueSendwait
#define UserMsgQueueSend KMsgQueueSend
#define UserMsgQueueUrgentSend KMsgQueueUrgentSend
#define UserMsgQueueRecv KMsgQueueRecv
#define UserMsgQueueReinit KMsgQueueReinit
#endif
#define UserPrintf KPrintf
#define printf KPrintf
#endif
#endif

50
kernel/include/xiuos.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xiuos.h
* @brief: all header files of kernel
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XIUOS_H
#define XIUOS_H
#include <xsconfig.h>
#include <xs_kdbg.h>
#include <xs_base.h>
#include <xs_mutex.h>
#include <xs_sem.h>
#include <xs_event.h>
#include <xs_msg.h>
#include <xs_ktask.h>
#include <xs_timer.h>
#include <xs_klist.h>
#include <xs_isr.h>
#include <string.h>
#include <stdio.h>
#include <xs_memory.h>
#include <xs_id.h>
#include <xs_ktick.h>
#include <xs_kdevice.h>
#include <xs_init.h>
#include <xs_assign.h>
#include <xs_banner.h>
#include <xs_poll.h>
#include <xs_workqueue.h>
#include <xs_circular_area.h>
#include <xs_dataqueue.h>
#endif

138
kernel/include/xs_assign.h Normal file
View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_assign.h
* @brief: function declaration and structure defintion of system assign
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XS_ASSIGN_H
#define XS_ASSIGN_H
#include <xs_base.h>
#include <xs_ktask.h>
#include <xs_klist.h>
#include <xs_spinlock.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MERGE_FLAG(src, flag) *(src) |= flag
#define CLEAR_FLAG(src, flag) *(src) &= ~flag
extern struct Assign Assign;
struct PriorityReadyVectorDone
{
void (*init)(struct OsAssignReadyVector *ready_vector);
void (*insert)(struct TaskDescriptor *task);
void (*remove)(struct TaskDescriptor *task);
};
#ifdef ARCH_SMP
struct smp_assign_done
{
x_ubase (*GetHighest)(void);
struct TaskDescriptor* (*select)(void);
void (*SwitchToNew)(struct TaskDescriptor* old_task, struct TaskDescriptor* new_task);
void (*SwitchToFirst)(struct TaskDescriptor* task);
void (*SetSystemTask)(struct TaskDescriptor* task);
void (*SmpInit)(void);
};
struct Assign
{
struct OsAssignReadyVector os_assign_read_vector;
struct OsAssignReadyVector smp_os_assign_ready_rector[CPU_NUMBERS];
struct TaskDescriptor *smp_os_running_task[CPU_NUMBERS];
struct PriorityReadyVectorDone *ready_vector_done;
struct smp_assign_done *smp_assign_done;
uint8 current_priority[CPU_NUMBERS];
uint16 assign_lock[CPU_NUMBERS];
};
void SwitchKtaskContext(x_ubase from, x_ubase to, struct TaskDescriptor *to_task);
void SwitchKtaskContextTo(x_ubase to, struct TaskDescriptor *to_task);
void HwInterruptcontextSwitch( x_ubase from, x_ubase to,struct TaskDescriptor *to_task , void *context);
#else
struct Assign
{
struct OsAssignReadyVector os_assign_read_vector;
struct TaskDescriptor *os_running_task;
struct PriorityReadyVectorDone *ready_vector_done;
uint8 current_priority;
};
void SwitchKtaskContext(x_ubase from, x_ubase to , struct TaskDescriptor *to_task);
void SwitchKtaskContextTo(x_ubase to, struct TaskDescriptor *to_task);
void HwInterruptcontextSwitch( x_ubase from, x_ubase to, struct TaskDescriptor *to_task ,void *context);
#endif
void KTaskInsertToReadyVector(struct TaskDescriptor *task);
int PrioCaculate(uint32 bitmap);
void SysInitOsAssign(void);
void ResetCriticalAreaLock(void );
void StartupOsAssign(void);
x_base CriticalAreaLock(void);
void CriticalAreaUnLock(x_base lock);
uint16 GetOsAssignLockLevel(void);
int32 JudgeAssignReadyBitmapIsEmpty(struct OsAssignReadyVector *ready_vector);
void OsAssignReadyVectorInit(struct OsAssignReadyVector *ready_vector);
void AssignPolicyInsert(struct TaskDescriptor *task, struct OsAssignReadyVector* ready_table);
struct TaskDescriptor * ChooseTaskWithHighestPrio(struct OsAssignReadyVector *ready_vector);
#ifdef KERNEL_STACK_OVERFLOW_CHECK
void _KTaskOsAssignStackCheck(struct TaskDescriptor *task);
#endif
#ifdef ARCH_SMP
extern HwSpinlock AssignSpinLock;
#define DO_KTASK_ASSIGN \
do \
{ \
NOT_IN_CRITICAL_AREA; \
x_base lock; \
lock = DISABLE_INTERRUPT(); \
HwLockSpinlock(&AssignSpinLock); \
KTaskOsAssign(); \
HwUnlockSpinlock(&AssignSpinLock); \
ENABLE_INTERRUPT(lock); \
} while (0);
#else
#define DO_KTASK_ASSIGN \
do \
{ \
NOT_IN_CRITICAL_AREA; \
x_base lock; \
lock = DISABLE_INTERRUPT(); \
KTaskOsAssign(); \
ENABLE_INTERRUPT(lock); \
} while (0);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_avltree.h
* @brief: function declaration and structure defintion of avl tree
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef AVL_TREE_H
#define AVL_TREE_H
#include <xs_base.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef KERNEL_AVL_TREE
struct AvlNode
{
int32 data;
uint32 height;
struct AvlNode *left;
struct AvlNode *right;
};
typedef struct AvlNode *AvlNodeType;
#ifndef AVL_MAX
#define AVL_MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef AVL_ABS
#define AVL_ABS(a) ((a > 0) ? (a) : (-a))
#endif
/*This function will insert data to the avl tree*/
AvlNodeType AvlTreeInsertNode(AvlNodeType avl_node, int32 data);
/*This function will delete data from the avl tree*/
AvlNodeType AvlTreeDeleteNode(AvlNodeType avl_node, int32 data);
/*This function will modify certain data of the avl tree*/
AvlNodeType AvlNodeModifyNode(AvlNodeType avl_node, int32 src_data, int32 dst_data);
/*This function will return the avl node which has the data*/
AvlNodeType AvlNodeSearchNode(AvlNodeType avl_node, int32 data);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_banner.h
* @brief: function declaration of system banner
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef XS_BANNER_H
#define XS_BANNER_H
#include <xs_base.h>
void ShowBanner(void);
#endif

133
kernel/include/xs_base.h Normal file
View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_base.h
* @brief: basic data type defintions
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XS_BASE_H
#define XS_BASE_H
/* import board special configuration */
#include <xsconfig.h>
#ifdef __cplusplus
extern "C" {
#endif
#if 0
/* the basic types of date*/
#ifdef ARCH_CPU_64BIT
typedef unsigned long int size_t;
typedef signed long int ssize_t;
#else
typedef unsigned int size_t;
typedef signed int ssize_t;
#endif
#endif
#ifndef CONFIG_ARCH_DATA_TYPE
typedef signed char int8;
typedef signed short int16;
typedef signed int int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
#ifdef ARCH_CPU_64BIT
typedef signed long int64;
typedef unsigned long uint64;
#else
typedef signed long long int64;
typedef unsigned long long uint64;
#endif
#endif
typedef int x_bool;
typedef long x_base;
typedef unsigned long x_ubase;
typedef x_base x_err_t;
typedef uint32 x_time_t;
typedef uint32 x_ticks_t;
typedef x_base x_flag_t;
typedef x_ubase x_size_t;
typedef x_ubase x_dev_t;
typedef x_base x_OffPos;
#define RET_TRUE 1
#define RET_FALSE 0
#define UINT8_SIZE_MAX 0xff
#define UINT16_SIZE_MAX 0xffff
#define UINT32_SIZE_MAX 0xffffffff
#define TICK_SIZE_MAX UINT32_SIZE_MAX
/* the type of components*/
#define Cmpt_KindN_Null 0
#define Cmpt_KindN_Task 1
#define Cmpt_KindN_Semaphore 2
#define Cmpt_KindN_Mutex 3
#define Cmpt_KindN_Event 4
#define Cmpt_KindN_MessageQueue 5
#define Cmpt_KindN_MemPool 6
#define Cmpt_KindN_Timer 7
#define Cmpt_KindN_Bus 8
#define Cmpt_KindN_Static 0x80
/* the type of error */
#define EOK 0
#define ERROR 1
#define ETIMEOUT 2
#define EFULL 3
#define EEMPTY 4
#define ENOMEMORY 5
#define ENONESYS 6
#define EDEV_BUSY 7
#define EPIO 8
#define EINTER 9
#define EINVALED 10
#define INVALID_TASK_ERROR 11
#define ALIGN_MEN_UP(size, align) ((((size) + (align) - 1) /(align))*(align))
#define ALIGN_MEN_DOWN(size, align) ((size)/(align)*(align))
#define NONE (0)
#ifndef SECTION
#if defined(__GNUC__)
#define SECTION(x) __attribute__((section(x)))
#else
#define SECTION(x)
#endif
#endif
#define WAITING_FOREVER -1
void KPrintf(const char *fmt, ...);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_circular_area.h
* @brief: function declaration and structure defintion of circular area
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef CIRCULAR_AREA_H
#define CIRCULAR_AREA_H
#include <xs_base.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef KERNEL_CIRCULAR_AREA
typedef struct CircularArea *CircularAreaType;
struct CircularAreaOps
{
uint32 (*read) (CircularAreaType circular_area, uint8 *output_buffer, uint32 data_length);
uint32 (*write) (CircularAreaType circular_area, uint8 *input_buffer, uint32 data_length, x_bool b_force);
void (*release) (CircularAreaType circular_area);
void (*reset) (CircularAreaType circular_area);
};
struct CircularArea
{
uint8 *data_buffer;
uint8 readidx;
uint8 writeidx;
uint8 *p_head;
uint8 *p_tail;
uint32 area_length;
x_bool b_status;
struct CircularAreaOps *CircularAreaOperations;
};
/*This function will return whether the circular_area is full or not*/
x_bool CircularAreaIsFull(CircularAreaType circular_area);
/*This function will return whether the circular_area is empty or not*/
x_bool CircularAreaIsEmpty(CircularAreaType circular_area);
/*This function will reset the circular_area and set the descriptor to default*/
void CircularAreaReset(CircularAreaType circular_area);
/*This function will release the circular_area descriptor and free the memory*/
void CircularAreaRelease(CircularAreaType circular_area);
/*This function will read data from the circular_area*/
uint32 CircularAreaRead(CircularAreaType circular_area, uint8 *output_buffer, uint32 data_length);
/*This function will write data to the circular_area*/
uint32 CircularAreaWrite(CircularAreaType circular_area, uint8 *input_buffer, uint32 data_length, x_bool b_force);
/*This function will get the circual_area max length*/
uint32 CircularAreaGetMaxLength(CircularAreaType circular_area);
/*This function will get the data length of the circular_area*/
uint32 CircularAreaGetDataLength(CircularAreaType circular_area);
/*This function will initialize the circular_area*/
CircularAreaType CircularAreaInit(uint32 circular_area_length);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_dataqueue.h
* @brief: function declaration and structure defintion of circular area
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef DATAQUEUE_H
#define DATAQUEUE_H
#include <xs_ktask.h>
#include <xs_timer.h>
#include <xs_sem.h>
#include <xs_queue_manager.h>
typedef struct
{
const void *data; ///< data pointer
x_size_t length; ///< data length
}DataElemType;
typedef struct
{
uint16 front;
uint16 rear;
uint16 max_len;
DataElemType *base;
int sem_blank;
int sem_data;
}DataQueueType;
x_err_t InitDataqueue(DataQueueType *p_queue, uint16 NodeNumber);
x_err_t PushDataqueue(DataQueueType *queue,const void *StartAddr, x_size_t DataSize, int32 timeout);
x_err_t PopDataqueue(DataQueueType *queue, const void **StartAddr, x_size_t *size, int32 timeout);
x_err_t DataqueuePeak(DataQueueType *queue, const void **StartAddr, x_size_t *size);
void DeInitDataqueue(DataQueueType *p_queue);
typedef struct
{
x_err_t (*InitDataqueue)(DataQueueType *p_queue, uint16 NodeNumber);
x_err_t (*PushDataqueue)(DataQueueType *queue,
const void *StartAddr,
x_size_t DataSize,
int32 timeout);
x_err_t (*PopDataqueue)(DataQueueType *queue,
const void **StartAddr,
x_size_t *size,
int32 timeout);
x_err_t (*DataqueuePeak)(DataQueueType *queue,
const void **StartAddr,
x_size_t *size);
void (*DeInitDataqueue)(DataQueueType *p_queue);
} DataQueueDoneType;
#endif

45
kernel/include/xs_delay.h Normal file
View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_delay.h
* @brief: function declaration and structure defintion of delay
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/11
*
*/
#ifndef XS_DELAY_H
#define XS_DELAY_H
#include <xsconfig.h>
#include <xs_kdbg.h>
#include <xs_base.h>
#include <xs_klist.h>
#define TASK_DELAY_INACTIVE 0
#define TASK_DELAY_ACTIVE 1
struct Delay {
struct TaskDescriptor *task;
x_ticks_t ticks;
uint8 status;
DoubleLinklistType link;
};
typedef struct Delay *delay_t;
x_err_t KTaskSetDelay(struct TaskDescriptor *task, x_ticks_t ticks);
x_err_t KTaskUnSetDelay(struct TaskDescriptor *task);
void CheckTaskDelay(void);
#endif

66
kernel/include/xs_event.h Normal file
View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_event.h
* @brief: function declaration and structure defintion of event
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XS_EVENT_H
#define XS_EVENT_H
#include <xsconfig.h>
#include <xs_kdbg.h>
#include <xs_base.h>
#include <xs_klist.h>
#include <xs_id.h>
#ifdef KERNEL_EVENT
#define EVENT_EVENTS_MASK 0x1FFFFFFF
#define EVENT_OPTIONS_MASK 0x7
#define EVENT_AND (1 << 0)
#define EVENT_OR (1 << 1)
#define EVENT_AUTOCLEAN (1 << 2)
typedef int32 EventIdType;
struct Event
{
struct IdNode id;
uint32 options : 3;
uint32 events : 29;
DoubleLinklistType pend_list;
DoubleLinklistType link;
};
typedef struct
{
int32 (*EventCreate)(uint32 options);
void (*EventDelete)(struct Event *event);
int32 (*EventTrigger)(struct Event *event, uint32 events);
int32 (*EventProcess)(struct Event *event, uint32 events, uint32 options, int32 msec, uint32 *processed);
} EventDoneType;
int32 KEventCreate(uint32 options);
void KEventDelete(int32 id);
int32 KEventTrigger(int32 id, uint32 events);
int32 KEventProcess(int32 id, uint32 events, uint32 options, int32 msec, uint32 *processed);
#endif
#endif

103
kernel/include/xs_hook.h Normal file
View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_hook.h
* @brief: function declaration and structure defintion of hook
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef XS_HOOK_H
#define XS_HOOK_H
#include <xs_base.h>
#include <xs_ktask.h>
#include <xs_kdbg.h>
#include <xs_memory.h>
#ifdef KERNEL_HOOK
#define HOOK(function, argv) \
do { if ((function) != NONE) function argv; } while (0)
#else
#define HOOK(function, argv)
#endif
#define REGISTER_HOOK(hook, function) \
{ if ((function) != NONE) hook = function ; }
#define UNREGISTER_HOOK(hook) \
{ hook = NONE ; }
struct AssignHook
{
void (*hook_Assign)(KTaskDescriptorType from, KTaskDescriptorType to);
};
struct TaskHook
{
void (*hook_TaskCreate) (KTaskDescriptorType task);
void (*hook_TaskSuspend)(KTaskDescriptorType task);
void (*hook_TaskResume) (KTaskDescriptorType task);
};
struct MemHook
{
void (*hook_Malloc)(void *ptr, x_size_t size);
void (*hook_Free)(void *ptr);
#ifdef KERNEL_MEMBLOCK
void (*hook_GmAlloc)(struct MemGather *gm, void *date_ptr);
void (*hook_GmFree)(struct MemGather *gm, void *date_ptr);
#endif
};
struct TimerHook
{
void (*hook_TimerEnter)(struct Timer *timer);
void (*hook_TimerExit)(struct Timer *timer);
};
struct IsrHook
{
void (*hook_IsrEnter)(void);
void (*hook_IsrLeave)(void);
};
struct IdleHook
{
void (*hook_Idle)(void);
};
struct TestHook
{
void (*hook_test)(const char *buf);
};
struct KernelHook
{
struct AssignHook assign;
struct TaskHook task;
struct MemHook mem;
struct TimerHook timer;
struct IsrHook isr;
struct IdleHook idle;
struct TestHook test;
};
extern struct KernelHook hook;
int hook_init(void);
#endif

66
kernel/include/xs_id.h Normal file
View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_id.h
* @brief: function declaration and structure defintion of id manager
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef XS_ID_H
#define XS_ID_H
#include <xs_klist.h>
#ifdef __cplusplus
extern "C" {
#endif
struct IdNode
{
uint16 id;
DoubleLinklistType link;
};
struct IdManager
{
uint16 id_max;
uint16 hoffset;
uint8 *id_map;
DoubleLinklistType *htable;
};
#define DECLARE_ID_MANAGER(_name, _id_max) \
uint8 __id_map_##_name[((_id_max) + 7) / 8]; \
DoubleLinklistType __htable_##_name[(_id_max) < ID_HTABLE_SIZE ? (_id_max) : ID_HTABLE_SIZE]; \
struct IdManager _name = { \
.id_max = _id_max, \
.hoffset = (_id_max) < ID_HTABLE_SIZE ? (_id_max) : ID_HTABLE_SIZE, \
.id_map = __id_map_##_name, \
.htable = __htable_##_name \
};
int IdInsertObj(struct IdManager *manager, struct IdNode *idnode);
struct IdNode *IdGetObj(struct IdManager *manager, uint16 id);
void IdRemoveObj(struct IdManager *manager, uint16 id);
#ifdef __cplusplus
}
#endif
#endif

53
kernel/include/xs_init.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_init.h
* @brief: init function declaration of components
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XS_INIT_H
#define XS_INIT_H
typedef int (*InitFnType)(void);
struct InitSequenceDesc
{
const char* fn_name;
const InitFnType fn;
};
#ifdef KERNEL_COMPONENTS_INIT
void InitCmpts(void);
#endif
extern int VfsInit(void);
extern int WorkSysWorkQueueInit(void);
extern int FlashW25qxxSpiDeviceInit(void);
extern int sal_mbedtls_proto_init(void);
extern int FatfsInit(void);
extern int Ch376fsInit(void);
extern int LibcSystemInit(void);
extern int sal_init(void);
extern int RtcNtpSyncInit(void);
extern int MountSDCard(void);
extern int dfs_mount_table(void);
extern int userShellInit(void);
extern int stm32_sdcard_mount(void);
extern int STM32USBHostRegister(void);
extern int WorkSysWorkQueueInit(void);
#endif

View File

@@ -0,0 +1,63 @@
/**
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_isolation.h
* @brief: The macro and callback functions definitions for memory protect
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/14
*
*/
#ifndef MEMORY_PROTECT_H
#define MEMORY_PROTECT_H
#include <xsconfig.h>
#ifdef TASK_ISOLATION
#include <xiuos.h>
#include <board.h>
#if defined(ARCH_ARM) && defined(SURPORT_MPU)
#include <mpu.h>
extern struct Mpu *isolation ;
#define MOMERY_PROTECT_ENABLE
#endif
#if defined(ARCH_RISCV) && defined(SURPORT_PMP)
#include <pmp.h>
extern struct Pmp *isolation ;
#define MOMERY_PROTECT_ENABLE
#endif
#define REGION_TYPE_CODE (1)
#define REGION_TYPE_DATA (2)
#define REGION_TYPE_BSS (3)
#define REGION_TYPE_HEAP (4)
struct MemoryAccessLimit {
void (* Enable)( uint32_t option);
void (* Disable)(void);
x_err_t (* Init)(void **mem_access);
x_err_t (* InitIsolation)(void **mem_access, x_ubase stack_start , size_t stack_size);
x_err_t (* AddRegion)(void *mem_access, x_ubase start , size_t size , uint8_t region_type );
x_err_t (* ClearRegion)(void *mem_access, x_ubase addr);
void (* Load)(void *mem_access);
void (* Free)(void *mem_access);
x_bool (* FaultHandle)(void *mem_access, x_ubase addr);
};
extern struct MemoryAccessLimit mem_access ;
#endif
#endif

98
kernel/include/xs_isr.h Normal file
View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_isr.h
* @brief: function declaration and structure defintion of isr
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XS_ISR_H
#define XS_ISR_H
#include <xs_base.h>
#include <arch_interrupt.h>
#ifdef __cplusplus
extern "C" {
#endif
#define DECLARE_HW_IRQ(_irq_num, _handler, _arg) \
const uint32 __irq_desc_idx_##_handler SECTION(".isrtbl.idx") = _irq_num + ARCH_IRQ_NUM_OFFSET ; \
const struct IrqDesc __irq_desc_##_handler SECTION(".isrtbl") = { \
.handler = _handler, \
.param = _arg, \
}
typedef void (*IsrHandlerType)(int vector, void *param);
struct IrqDesc
{
IsrHandlerType handler;
void *param;
#ifdef CONFIG_INTERRUPT_INFO
char name[NAME_NUM_MAX];
uint32 counter;
#endif
};
struct IsrDone
{
x_bool (*isInIsr)();
int32 (*registerIrq)(uint32 irq_num, IsrHandlerType handler, void *arg);
int32 (*freeIrq)(uint32 irq_num);
int32 (*enableIrq)(uint32 irq_num);
int32 (*disableIrq)(uint32 irq_num);
void (*handleIrq)(uint32 irq_num);
uint16 (*getCounter)() ;
void (*incCounter)();
void (*decCounter)();
uint8 (*getSwitchTrigerFlag)();
void (*setSwitchTrigerFlag)();
void (*clearSwitchTrigerFlag)();
};
struct InterruptServiceRoutines {
#ifdef ARCH_SMP
volatile uint16 isr_count[CPU_NUMBERS];
volatile uint8 isr_switch_trigger_flag[CPU_NUMBERS];
#else
volatile uint16 isr_count ;
volatile uint8 isr_switch_trigger_flag;
#endif
struct IrqDesc irq_table[ARCH_MAX_IRQ_NUM];
struct IsrDone *done;
};
extern struct InterruptServiceRoutines isrManager ;
x_base DisableLocalInterrupt();
void EnableLocalInterrupt(x_base level);
#define DISABLE_INTERRUPT DisableLocalInterrupt
#define ENABLE_INTERRUPT EnableLocalInterrupt
void SysInitIsrManager();
void InitHwinterrupt(void);
#ifdef __cplusplus
}
#endif
#endif

162
kernel/include/xs_kdbg.h Normal file
View File

@@ -0,0 +1,162 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_kdbg.h
* @brief: function declaration and structure defintion of kernel debug
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef XS_KDBG_H
#define XS_KDBG_H
#include <xsconfig.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef KERNEL_DEBUG
/*Kernel Section Debug Define*/
#define KDBG_MEM 0
#define KDBG_MEMHEAP 0
#define KDBG_SCHED 0
#define KDBG_KTASK 0
#define KDBG_SOFTTIMER 0
#define KDBG_IRQ 0
#define KDBG_IPC 0
#define KDBG_HOOK 0
#define SYS_KDEBUG_LOG(section, information) \
do \
{ \
if(section) { \
KPrintf information; \
} \
}while (0)
#define KDYN_NONE 0
#define KDYN_DBG 1
#define KDYN_ERROR 2
#define KDYN_WARNING 3
#ifdef KDYN_LOG_DBG
#define DBG(args, ...) KDYNAMIC_LOG(KDYN_DBG, args, ##__VA_ARGS__)
#define SYS_ERR(args, ...) KDYNAMIC_LOG(KDYN_ERROR, args, ##__VA_ARGS__)
#define SYS_WARN(args, ...) KDYNAMIC_LOG(KDYN_WARNING, args, ##__VA_ARGS__)
#else
#define DBG(args, ...) KDYNAMIC_LOG(KDYN_NONE, args, ##__VA_ARGS__)
#define SYS_ERR(args, ...) KDYNAMIC_LOG(KDYN_ERROR, args, ##__VA_ARGS__)
#define SYS_WARN(args, ...) KDYNAMIC_LOG(KDYN_WARNING, args, ##__VA_ARGS__)
#endif
#define KDYNAMIC_LOG(level, args, ...) \
do \
{ \
switch(level) \
{ \
case KDYN_NONE: \
break; \
case KDYN_DBG: \
KPrintf("[DBG]"); \
KPrintf(args, ##__VA_ARGS__); \
break; \
case KDYN_ERROR: \
KPrintf("[ERR]"); \
KPrintf(args, ##__VA_ARGS__); \
break; \
case KDYN_WARNING: \
KPrintf("[WARN]"); \
KPrintf(args, ##__VA_ARGS__); \
break; \
default: \
break; \
} \
}while (0)
#define NULL_PARAM_CHECK(param) \
do \
{ \
if(param == NONE) { \
KPrintf("PARAM CHECK FAILED ...%s %d %s is NULL.\n",__FUNCTION__,__LINE__,#param); \
while(RET_TRUE); \
} \
}while (0)
#define CHECK(TRUE_CONDITION) \
do \
{ \
if(!(TRUE_CONDITION)) { \
KPrintf("%s CHECK condition is false at line[%d] of [%s] func.\n",#TRUE_CONDITION,__LINE__,__FUNCTION__);\
while(RET_TRUE); \
} \
} while(0)
#define KDEBUG_NOT_IN_INTERRUPT \
do \
{ \
x_base level; \
level = DISABLE_INTERRUPT(); \
if (isrManager.done->getCounter() != 0) \
{ \
KPrintf("Function[%s] is not supported in ISR\n", __FUNCTION__); \
CHECK(0); \
} \
ENABLE_INTERRUPT(level); \
} while (0)
#define KDEBUG_IN_KTASK_CONTEXT \
do \
{ \
x_base level; \
level = DISABLE_INTERRUPT(); \
if (GetKTaskDescriptor() == NONE) \
{ \
KPrintf("Function[%s] is not supported before task assign\n", __FUNCTION__); \
CHECK(0); \
} \
KDEBUG_NOT_IN_INTERRUPT; \
ENABLE_INTERRUPT(level); \
} while (0)
#define NOT_IN_CRITICAL_AREA \
do { \
if(GetOsAssignLockLevel() != 0){ \
KPrintf("Function[%s] is not supported switch in critical area.\n", __FUNCTION__); \
CHECK(0); \
} \
} while (0)
#else
#define SYS_KDEBUG_LOG(section, information)
#define DBG(args, ...)
#define SYS_ERR(args, ...)
#define SYS_WARN(args, ...)
#define NULL_PARAM_CHECK(param)
#define CHECK(TRUE_CONDITION)
#define KDEBUG_NOT_IN_INTERRUPT
#define KDEBUG_IN_KTASK_CONTEXT
#define NOT_IN_CRITICAL_AREA
#endif
#ifdef __cplusplus
}
#endif
#endif

119
kernel/include/xs_kdevice.h Normal file
View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_kdevice.h
* @brief: macor and structure defintion of kdevice
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef XS_KDEVICE_H
#define XS_KDEVICE_H
/* import board special configuration */
#include <xsconfig.h>
#include <xs_klist.h>
#ifdef TOOL_SHELL
#include "shell.h"
#else
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc)
#endif
#ifdef __cplusplus
extern "C" {
#endif
enum dev
{
Dev_TYPE_Block,
Dev_TYPE_Char ,
Dev_TYPE_CAN ,
Dev_TYPE_Graphic,
Dev_TYPE_I2CBUS,
Dev_TYPE_Miscellaneous,
Dev_TYPE_NetIf ,
Dev_TYPE_RTC ,
Dev_TYPE_SPIBUS,
Dev_TYPE_SPIDevice,
Dev_TYPE_Timer,
Dev_TYPE_Touch,
Dev_TYPE_USBDevice,
Dev_TYPE_USBHost,
Dev_TYPE_Unknown
};
#define OSIGN_OPER_CLOSE (0U << 0)
#define OSIGN_OPER_RDONLY (1U << 0)
#define OSIGN_OPER_WRONLY (1U << 1)
#define OSIGN_OPER_RDWR (OSIGN_OPER_WRONLY| OSIGN_OPER_RDONLY )
#define OSIGN_OPER_OPEN (1U << 3)
#define OSIGN_OPER_MASK 0xf0f
#define SIGN_OPER_DEACTIVATE (0U << 0)
#define SIGN_OPER_RDONLY (1U << 0)
#define SIGN_OPER_WRONLY (1U << 1)
#define SIGN_OPER_RDWR (SIGN_OPER_RDONLY|SIGN_OPER_WRONLY)
#define SIGN_OPER_REMOVABLE (1U << 2)
#define SIGN_OPER_STANDALONE (1U << 3)
#define SIGN_OPER_ACTIVATED (1U << 4)
#define SIGN_OPER_SUSPENDED (1U << 5)
#define SIGN_OPER_STREAM (1U << 6)
#define SIGN_OPER_INT_RX (1U << 8)
#define SIGN_OPER_DMA_RX (1U << 9)
#define SIGN_OPER_INT_TX (1U << 10)
#define SIGN_OPER_DMA_TX (1U << 11)
enum SIGN_OPER
{
OPER_RESUME = 0x01,
OPER_SUSPEND = 0x02,
OPER_CONFIG = 0x03,
OPER_SET_INT = 0x10,
OPER_CLR_INT = 0x11,
OPER_GET_INT = 0x12,
OPER_CHAR_STREAM = 0x10,
OPER_BLK_GETGEOME = 0x10,
OPER_BLK_SYNC = 0x11,
OPER_BLK_ERASE = 0x12,
OPER_BLK_AUTOREFRESH = 0x13,
OPER_NETIF_GETMAC = 0x10,
OPER_MTD_FORMAT = 0x10,
OPER_RTC_GET_TIME = 0x10,
OPER_RTC_SET_TIME = 0x11,
OPER_RTC_GET_ALARM = 0x12,
OPER_RTC_SET_ALARM = 0x13,
};
struct DeviceBlockArrange
{
uint32 bank_num;
uint32 size_perbank;
uint32 block_size;
uint16 bank_start;
uint16 bank_end;
};
struct DeviceBlockAddr
{
uint32_t start;
uint32_t end;
};
#ifdef __cplusplus
}
#endif
#endif

129
kernel/include/xs_klist.h Normal file
View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_klist.h
* @brief: function declaration and structure defintion of linklist
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/2
*
*/
#ifndef XS_KLIST_H
#define XS_KLIST_H
#include <xs_base.h>
#include "libc.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LINKLIST_FLAG_FIFO 0x00
#define LINKLIST_FLAG_PRIO 0x01
typedef struct SysDoubleLinklistNode
{
struct SysDoubleLinklistNode *node_next;
struct SysDoubleLinklistNode *node_prev;
} DoubleLinklistType;
// Single List
typedef struct SingleLinklistNode
{
struct SingleLinklistNode *node_next;
} SysSingleLinklistType;
struct CommonMember
{
char name[NAME_NUM_MAX];
uint8 type;
uint8 flag;
DoubleLinklistType list;
};
#define CONTAINER_OF(item, type, member) \
((type *)((char *)(item) - (unsigned long)(&((type *)0)->member)))
#define DOUBLE_LINKLIST_OBJ_INIT(obj) { &(obj), &(obj) }
void InitDoubleLinkList(DoubleLinklistType *linklist_head);
void DoubleLinkListInsertNodeAfter(DoubleLinklistType *linklist, DoubleLinklistType *linklist_node);
void DoubleLinkListInsertNodeBefore(DoubleLinklistType *linklist, DoubleLinklistType *linklist_node);
void DoubleLinkListRmNode(DoubleLinklistType *linklist_node);
int IsDoubleLinkListEmpty(const DoubleLinklistType *linklist);
struct SysDoubleLinklistNode *DoubleLinkListGetHead(const DoubleLinklistType *linklist);
struct SysDoubleLinklistNode *DoubleLinkListGetNext(const DoubleLinklistType *linklist,
const struct SysDoubleLinklistNode *linklist_node);
unsigned int DoubleLinkListLenGet(const DoubleLinklistType *linklist);
#define SYS_DOUBLE_LINKLIST_ENTRY(item, type, member) \
CONTAINER_OF(item, type, member)
#define DOUBLE_LINKLIST_FOR_EACH(item, head) \
for (item = (head)->node_next; item != (head); item = item->node_next)
#define DOUBLE_LINKLIST_FOR_EACH_SAFE(item, node_next, head) \
for (item = (head)->node_next, node_next = item->node_next; item != (head); \
item = node_next, node_next = item->node_next)
#define DOUBLE_LINKLIST_FOR_EACH_ENTRY(item, head, member) \
for (item = SYS_DOUBLE_LINKLIST_ENTRY((head)->node_next, typeof(*item), member); \
&item->member != (head); \
item = SYS_DOUBLE_LINKLIST_ENTRY(item->member.node_next, typeof(*item), member))
#define DOUBLE_LINKLIST_FOR_EACH_ENTRY_SAFE(item, node_next, head, member) \
for (item = SYS_DOUBLE_LINKLIST_ENTRY((head)->node_next, typeof(*item), member), \
node_next = SYS_DOUBLE_LINKLIST_ENTRY(item->member.node_next, typeof(*item), member); \
&item->member != (head); \
item = node_next, node_next = SYS_DOUBLE_LINKLIST_ENTRY(node_next->member.node_next, typeof(*node_next), member))
#define DOUBLE_LINKLIST_FIRST_ENTRY(ptr, type, member) \
SYS_DOUBLE_LINKLIST_ENTRY((ptr)->node_next, type, member)
#define SYS_SINGLE_LINKLIST_OBJ_INIT(obj) { NONE }
void InitSingleLinkList(SysSingleLinklistType *linklist);
void AppendSingleLinkList(SysSingleLinklistType *linklist, SysSingleLinklistType *linklist_node);
void SingleLinkListNodeInsert(SysSingleLinklistType *linklist, SysSingleLinklistType *linklist_node);
unsigned int SingleLinkListGetLen(const SysSingleLinklistType *linklist);
SysSingleLinklistType *SingleLinkListRmNode(SysSingleLinklistType *linklist, SysSingleLinklistType *linklist_node);
SysSingleLinklistType *SingleLinkListGetFirstNode(SysSingleLinklistType *linklist);
SysSingleLinklistType *SingleLinkListGetTailNode(SysSingleLinklistType *linklist);
SysSingleLinklistType *SingleLinkListGetNextNode(SysSingleLinklistType *linklist_node);
int IsSingleLinkListEmpty(SysSingleLinklistType *linklist);
#define SYS_SINGLE_LINKLIST_ENTRY(node, type, member) \
CONTAINER_OF(node, type, member)
#define SINGLE_LINKLIST_FOR_EACH(item, head) \
for (item = (head)->node_next; item != NONE; item = item->node_next)
#define SINGLE_LINKLIST_FOR_EACH_ENTRY(item, head, member) \
for (item = SYS_SINGLE_LINKLIST_ENTRY((head)->node_next, typeof(*item), member); \
&item->member != (NONE); \
item = SYS_SINGLE_LINKLIST_ENTRY(item->member.node_next, typeof(*item), member))
#define SINGLE_LINKLIST_FIRST_ENTRY(ptr, type, member) \
SYS_SINGLE_LINKLIST_ENTRY((ptr)->node_next, type, member)
#define SINGLE_LINKLIST_TAIL_ENTRY(ptr, type, member) \
SYS_SINGLE_LINKLIST_ENTRY(SingleLinkListGetTailNode(ptr), type, member)
#ifdef __cplusplus
}
#endif
#endif

222
kernel/include/xs_ktask.h Normal file
View File

@@ -0,0 +1,222 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_ktask.h
* @brief: function declaration and structure defintion of kernel task
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XS_KTASK_H
#define XS_KTASK_H
#include <xsconfig.h>
#include <xs_kdbg.h>
#include <xs_base.h>
#include <xs_klist.h>
#include <xs_timer.h>
#include <xs_delay.h>
#ifdef __cplusplus
extern "C" {
#endif
#define KTASK_LOWEST_PRIORITY 0
#define KTASK_INIT 0x00
#define KTASK_READY 0x01
#define KTASK_SUSPEND 0x02
#define KTASK_RUNNING 0x03
#define KTASK_CLOSE 0x04
#define KTASK_STAT_MASK 0x07
#define KTASK_MAX_ADVANCE_PROCESS_TIME 0x1 ///< task max advance process times
#define UNCOMBINE_CPU_CORE CPU_NUMBERS
#ifdef ARCH_SMP
#define CPU_MASK ((1 << CPU_NUMBERS) - 1) /**< All CPUs mask bit. */
#ifndef ASSIGN_IPI
#define ASSIGN_IPI 0
#endif
#endif
struct TaskBaseInfo {
char name[NAME_NUM_MAX]; ///< task name
void *func_entry; ///< task function entry
void *func_param; ///< task parameter
uint8 origin_prio; ///< task init priority
uint32 stack_depth; ///< task stack size
void *stack_start; ///< task stack start address
};
typedef struct TaskBaseInfo TaskBaseInfoType;
struct TaskDyncSchedMember {
uint8 stat; ///< task stat
uint8 advance_cnt; ///< total time slice advance process count
uint8 cur_prio; ///< task current priority
x_ubase origin_timeslice; ///< task init timeslice
x_ubase rest_timeslice; ///< task remaining timeslice
#ifdef SEPARATE_COMPILE
uint8 isolation_flag; ///< task isolation flag
void *isolation; ///< task isolation pointer
uint8 isolation_status;
#if defined(ARCH_ARM)
uint32_t svc_return;
uint32_t exc_return;
#endif
#endif
DoubleLinklistType sched_link; ///< task sched list
#if KTASK_PRIORITY_MAX > 32
uint8 bitmap_offset;
uint8 bitmap_row;
#endif
uint32 bitmap_column;
delay_t delay;
};
typedef struct TaskDyncSchedMember TaskDyncSchedMembeType;
#ifdef ARCH_SMP
struct TaskSmpInfo {
uint8 combined_coreid; ///< task bind core id
uint8 runing_coreid; ///< task running core id
uint16 critical_lock_cnt; ///< critical lock count
};
typedef struct TaskSmpInfo TaskSmpInfoType;
#endif
struct TaskDescriptor
{
void *stack_point; ///< stack point
TaskDyncSchedMembeType task_dync_sched_member; ///< task dynamic sched member
TaskBaseInfoType task_base_info; ///< task base information
#ifdef ARCH_SMP
TaskSmpInfoType task_smp_info; ///< dual core information
#endif
#if defined(KERNEL_EVENT)
uint32 event_id_trigger : 29 ; ///< event ops (event trigger )
uint32 event_mode : 3; ///< event mode (AND/OR/AUTOCLEAN)
#endif
x_err_t exstatus; ///< exception status
DoubleLinklistType link; ///< manage list
struct IdNode id; ///< task id
struct KTaskDone *Done;
};
typedef struct TaskDescriptor *KTaskDescriptorType;
struct OsAssignReadyVector {
DoubleLinklistType priority_ready_vector[KTASK_PRIORITY_MAX];
uint32 priority_ready_group;
#if KTASK_PRIORITY_MAX > 32
/* Maximum priority level, 256 */
uint8 ready_vector[32];
#endif
x_ubase highest_prio;
};
struct KTaskDone
{
int32 (*init)(KTaskDescriptorType task,
const char *name,
void (*entry)(void *parameter),
void *parameter,
uint32 stack_size,
uint8 priority);
x_err_t (*start)(KTaskDescriptorType task);
x_err_t (*Delete)(KTaskDescriptorType task);
x_err_t (*delay)(KTaskDescriptorType task, x_ticks_t ticks);
x_err_t (*mdelay)(KTaskDescriptorType task,uint32 ms);
x_err_t (*prioset)(KTaskDescriptorType task, uint8 prio);
#ifdef ARCH_SMP
x_err_t (*combine)(KTaskDescriptorType task, uint8 coreid);
x_err_t (*uncombine)(KTaskDescriptorType task);
#endif
x_err_t (*suspend)(KTaskDescriptorType task);
x_err_t (*wake)(KTaskDescriptorType task);
};
int32 KTaskCreate(const char *name,
void (*entry)(void *parameter),
void *parameter,
uint32 stack_size,
uint8 priority);
void KTaskQuit(void);
#ifdef SEPARATE_COMPILE
int32 UTaskCreate(const char *name,
void (*entry)(void *parameter),
void *parameter,
uint32 stack_size,
uint8 priority);
#endif
void KUpdateExstatus(x_err_t no);
int *KObtainExstatus(void);
#if !defined(LIB_NEWLIB) && !defined(_WIN32)
#ifndef errno
#define errno *KObtainExstatus()
#endif
#endif
KTaskDescriptorType GetKTaskDescriptor(void);
KTaskDescriptorType KTaskSearch(char *name);
x_err_t StartupKTask(int32 id);
x_err_t KTaskDelete(int32 id);
x_err_t YieldOsAssign(void);
x_err_t DelayKTask(x_ticks_t tick);
x_err_t MdelayKTask(uint32 ms);
x_err_t KTaskPrioSet(int32 id, uint8 prio);
x_err_t KTaskCoreCombine(int32 id, uint8 coreid);
x_err_t KTaskCoreUnCombine(int32 id);
x_err_t SuspendKTask(int32 id);
x_err_t KTaskWakeup(int32 id);
void KTaskTimeout(void *parameter);
void InitIdleKTask(void);
void IdleKTaskExec(void);
KTaskDescriptorType GetIdleKTaskDescripter(void);
void KTaskOsAssign(void);
void KTaskOsAssignRemoveKTask(struct TaskDescriptor *task);
#if defined (SCHED_POLICY_FIFO)
void FifoTaskTimesliceInit(struct TaskDescriptor *task);
void FifoReadyVectorInsert(struct TaskDescriptor *task, struct OsAssignReadyVector* ready_table);
void FifoTaskTimesliceUpdate();
#elif defined (SCHED_POLICY_RR)
void RoundRobinTaskTimesliceInit(struct TaskDescriptor *task);
void RoundRobinReadyVectorInsert(struct TaskDescriptor *task, struct OsAssignReadyVector* ready_table);
void RoundRobinTaskTimesliceUpdate(struct TaskDescriptor *task);
#elif defined (SCHED_POLICY_RR_REMAINSLICE)
void RoundRobinRemainTaskTimesliceInit(struct TaskDescriptor *task);
void RoundRobinRemainReadyVectorInsert(struct TaskDescriptor *task, struct OsAssignReadyVector* ready_table);
void RoundRobinRemainTaskTimesliceUpdate(struct TaskDescriptor *task);
#endif
x_err_t LinklistSuspend(DoubleLinklistType *list,struct TaskDescriptor *task,uint8 flag);
x_err_t LinklistResume(DoubleLinklistType *list);
x_err_t LinklistResumeAll(DoubleLinklistType *list);
void HwSendIpi(int ipi_vector, unsigned int cpu_mask);
void KTaskIdDelete(int32 id);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_ktask_stat.h
* @brief: function declaration of task stat
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XS_KTASK_STAT_H
#define XS_KTASK_STAT_H
#include <xs_base.h>
#include<xs_ktask.h>
#include <stdbool.h>
void KTaskStateSet(KTaskDescriptorType task, uint8 stat);
void KTaskStatSetAsInit(KTaskDescriptorType task);
void KTaskStatSetAsReady(KTaskDescriptorType task);
void KTaskStatSetAsSuspend(KTaskDescriptorType task);
void KTaskStatSetAsRunning(KTaskDescriptorType task);
void KTaskStatSetAsClose(KTaskDescriptorType task);
uint8 KTaskStatGet(KTaskDescriptorType task);
bool JudgeKTaskStatIsInit(KTaskDescriptorType task);
bool JudgeKTaskStatIsReady(KTaskDescriptorType task);
bool JudgeKTaskStatIsSuspend(KTaskDescriptorType task);
bool JudgeKTaskStatIsRunning(KTaskDescriptorType task);
bool JudgeKTaskStatIsClose(KTaskDescriptorType task);
#endif

32
kernel/include/xs_ktick.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_ktick.h
* @brief: function declaration of kernel tick
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/2
*
*/
#ifndef XS_KTICK_H
#define XS_KTICK_H
#include <xs_base.h>
x_ticks_t CurrentTicksGain(void);
void TickAndTaskTimesliceUpdate(void);
x_ticks_t CalculteTickFromTimeMs(uint32 ms);
uint32 CalculteTimeMsFromTick(x_ticks_t ticks);
#endif

107
kernel/include/xs_memory.h Normal file
View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_memory.h
* @brief: function declaration and structure defintion of memory
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/2
*
*/
#ifndef XS_MEMORY_H
#define XS_MEMORY_H
#include <xsconfig.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MM_PAGE_SIZE
#define MM_PAGE_SIZE 4096
#endif
#define MM_PAGE_MASK (MM_PAGE_SIZE - 1)
#define MM_PAGE_BITS 12
/* Set static memory block */
#ifndef SMALL_NUMBER_32B
#define SMALL_NUMBER_32B (0) /* Calculate the numbers of SIZEOF_32B blocks*/
#endif
#ifndef SMALL_NUMBER_64B
#define SMALL_NUMBER_64B (0) /* Calculate the numbers of SIZEOF_64B blocks*/
#endif
#ifndef KERNEL_MALLOC
#define KERNEL_MALLOC(sz) x_malloc(sz)
#endif
#ifndef KERNEL_FREE
#define KERNEL_FREE(ptr) x_free(ptr)
#endif
#ifndef KERNEL_REALLOC
#define KERNEL_REALLOC(ptr, size) x_realloc(ptr, size)
#endif
#ifdef KERNEL_MEMBLOCK
struct MemGather
{
char m_name[NAME_NUM_MAX];
uint8 m_kind;
uint8 m_sign;
DoubleLinklistType m_link;
void *m_start_address;
x_size_t m_size;
x_size_t one_block_size;
uint8 *m_block_link;
x_size_t block_total_number;
x_size_t block_free_number;
DoubleLinklistType wait_task;
};
typedef struct MemGather *GatherMemType;
x_err_t InitMemGather(struct MemGather *gm_handler, const char *gm_name, void *begin_address, x_size_t gm_size, x_size_t one_block_size);
x_err_t RemoveMemGather(struct MemGather *gm_handler);
GatherMemType CreateMemGather(const char *gm_name, x_size_t block_number, x_size_t one_block_size);
x_err_t DeleteMemGather(GatherMemType gm_handler);
void *AllocBlockMemGather(GatherMemType gm_handler, int32 wait_time);
void FreeBlockMemGather(void *data_block);
#endif
void InitBoardMemory(void *begin_addr, void *end_addr);
void *x_malloc(x_size_t nbytes);
void x_free(void *ptr);
void *x_realloc(void *ptr, x_size_t nbytes);
void *x_calloc(x_size_t count, x_size_t size);
#ifdef USER_APPLICATION
void UserInitBoardMemory(void *begin_addr, void *end_addr);
void *x_umalloc(x_size_t nbytes);
void x_ufree(void *ptr);
void *x_urealloc(void *ptr, x_size_t nbytes);
void *x_ucalloc(x_size_t count, x_size_t size);
#endif
void MemoryInfo(uint32 *total, uint32 *used, uint32 *max_used);
#ifdef __cplusplus
}
#endif
#endif

67
kernel/include/xs_msg.h Normal file
View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_msg.h
* @brief: function declaration and structure defintion of message queue
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/2
*
*/
#ifndef XS_MSG_H
#define XS_MSG_H
#include <xsconfig.h>
#include <xs_kdbg.h>
#include <xs_base.h>
#include <xs_klist.h>
#ifdef KERNEL_MESSAGEQUEUE
struct MsgQueue
{
struct IdNode id;
void *msg_buf;
uint16 index;
uint16 num_msgs;
uint16 each_len;
uint16 max_msgs;
DoubleLinklistType send_pend_list;
DoubleLinklistType recv_pend_list;
DoubleLinklistType link;
struct MsgQueueDone *Done;
};
typedef struct MsgQueue *MsgQueueType;
struct MsgQueueDone
{
x_err_t (*init)(struct MsgQueue *mq, x_size_t msg_size, x_size_t max_msgs );
x_err_t (*urgensend)(struct MsgQueue *mq, const void *buffer, x_size_t size);
x_err_t (*send)(struct MsgQueue *mq, const void *buffer, x_size_t size,int32 timeout);
x_err_t (*recv)(struct MsgQueue *mq, void *buffer, x_size_t size, int32 timeout);
x_err_t (*reinit)(struct MsgQueue *mq);
x_err_t (*Delete)(struct MsgQueue *mq);
};
int32 KCreateMsgQueue( x_size_t msg_size, x_size_t max_msgs );
x_err_t KMsgQueueSendwait(int32 id, const void *buffer, x_size_t size, int32 timeout);
x_err_t KMsgQueueUrgentSend(int32 id, const void *buffer, x_size_t size);
x_err_t KMsgQueueSend(int32 id, const void *buffer, x_size_t size);
x_err_t KMsgQueueRecv(int32 id, void *buffer, x_size_t size, int32 timeout);
x_err_t KMsgQueueReinit(int32 id);
x_err_t KDeleteMsgQueue(int32 id);
#endif
#endif

56
kernel/include/xs_mutex.h Normal file
View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_mutex.h
* @brief: function declaration and structure defintion of mutex
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XS_MUTEX_H
#define XS_MUTEX_H
#include <xsconfig.h>
#include <xs_kdbg.h>
#include <xs_base.h>
#include <xs_klist.h>
#include <xs_id.h>
#ifdef KERNEL_MUTEX
struct Mutex {
struct IdNode id;
uint16 val;
uint8 recursive_cnt;
uint8 origin_prio;
struct TaskDescriptor *holder;
DoubleLinklistType pend_list;
DoubleLinklistType link;
};
typedef struct {
int32 (*MutexCreate)();
void (*MutexDelete)(struct Mutex *mutex);
int32 (*MutexObtain)(struct Mutex *mutex, int32 wait_time);
int32 (*MutexAbandon)(struct Mutex *mutex);
} MutexDoneType;
int32 KMutexCreate();
void KMutexDelete(int32 id);
int32 KMutexObtain(int32 id, int32 wait_time);
int32 KMutexAbandon(int32 id);
#endif
#endif

59
kernel/include/xs_poll.h Normal file
View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_pool.h
* @brief: function declaration and structure defintion of poll
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef XS_POLL_H
#define XS_POLL_H
#include <xs_base.h>
#include <xs_waitqueue.h>
#include <sys/time.h>
#if !defined(POLLIN) && !defined(POLLOUT)
#define POLLIN 0x001
#define POLLOUT 0x002
#define POLLERR 0x004
#define POLLHUP 0x008
#define POLLNVAL 0x010
#define POLLMASK_DEFAULT (POLLIN | POLLOUT )
typedef unsigned long NfdsType;
struct pollfd
{
int fd;
short events;
short revents;
};
#endif
struct Pollreq;
typedef void (*poll_queue_proc)(WaitQueueType *, struct Pollreq *);
typedef struct Pollreq
{
poll_queue_proc _proc;
short _key;
} pollreqType;
void PollAdd(WaitQueueType *wq, pollreqType *req);
int poll(struct pollfd *fds, NfdsType nfds, int timeout);
#endif

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_queue_manager.h
* @brief: function declaration and structure defintion of queue manager
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef XS_QUEUE_MANAGER_H
#define XS_QUEUE_MANAGER_H
#include <xsconfig.h>
#ifndef QUEUE_MAX
#define QUEUE_MAX 16
#endif
typedef struct
{
void *property;
void *done;
} queue;
enum QUEUE_TYPE
{
DATA_QUEUE = 1,
WORK_QUEUE,
WAIT_QUEUE,
};
extern void *g_queue_done[];
extern void queuemanager_done_register();
#endif

57
kernel/include/xs_sem.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_sem.h
* @brief: function declaration and structure defintion of sem
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/12
*
*/
#ifndef XS_SEM_H
#define XS_SEM_H
#include <xsconfig.h>
#include <xs_kdbg.h>
#include <xs_base.h>
#include <xs_klist.h>
#include <xs_id.h>
#ifdef KERNEL_SEMAPHORE
struct Semaphore
{
struct IdNode id;
uint16 value;
DoubleLinklistType pend_list;
DoubleLinklistType link;
};
typedef struct {
int32 (*SemaphoreCreate)(uint16 val);
void (*SemaphoreDelete)(struct Semaphore *sem);
int32 (*SemaphoreObtain)(struct Semaphore *sem, int32 wait_time);
int32 (*SemaphoreAbandon)(struct Semaphore *sem);
int32 (*SemaphoreSetValue)(struct Semaphore *sem, uint16 val);
} SemaphoreDoneType;
int32 KSemaphoreCreate(uint16 val);
void KSemaphoreDelete(int32 id);
int32 KSemaphoreObtain(int32 id, int32 wait_time);
int32 KSemaphoreAbandon(int32 id);
int32 KSemaphoreSetValue(int32 id, uint16 val);
#endif
#endif

115
kernel/include/xs_service.h Normal file
View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_service.h
* @brief: maroc and switch table definition of kernel switch
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XS_SERVICE_H
#define XS_SERVICE_H
#include <stdint.h>
#include "xs_base.h"
#ifdef SEPARATE_COMPILE
// #include <board.h>
enum KernelService
{
KS_USER_PRINT_INFO = 0,
KS_USER_TASK_CREATE ,
KS_USER_TASK_STARTUP ,
KS_USER_TASK_DELETE,
KS_USER_TASK_EXECEXIT,
KS_USER_TASK_CORE_COMBINE,
KS_USER_TASK_CORE_UNCOMBINE,
KS_USER_TASK_DELAY,
KS_USER_GET_TASK_NAME,
KS_USER_GET_TASK_ID,
KS_USER_GET_TASK_STAT,
KS_USER_GET_TASK_COMBINEED_CORE,
KS_USER_GET_TASK_RUNNING_CORE,
KS_USER_GET_TASK_ERROR_STATUS,
KS_USER_GET_TASK_PRIORITY,
KS_USER_MALLOC,
KS_USER_FREE,
KS_USER_MUTEX_CREATE,
KS_USER_MUTEX_DELETE,
KS_USER_MUTEX_OBTAIN,
KS_USER_MUTEX_ABANDON,
KS_USER_SEMAPHORE_CREATE,
KS_USER_SEMAPHORE_DELETE,
KS_USER_SEMAPHORE_OBTAIN,
KS_USER_SEMAPHORE_ABANDON,
KS_USER_SEMAPHORE_SETVALUE,
KS_USER_EVENT_CREATE,
KS_USER_EVENT_DELETE,
KS_USER_EVENT_TRIGGER,
KS_USER_EVENT_PROCESS,
KS_USER_MSGQUEUE_CREATE,
KS_USER_MSGQUEUE_DELETE,
KS_USER_MSGQUEUE_SENDWAIT,
KS_USER_MSGQUEUE_SEND,
KS_USER_MSGQUEUE_URGENTSEND,
KS_USER_MSGQUEUE_RECV,
KS_USER_MSGQUEUE_REINIT,
KS_USER_OPEN,
KS_USER_READ,
KS_USER_WRITE,
KS_USER_CLOSE,
KS_USER_IOCTL,
KS_USER_LSEEK,
KS_USER_RENAME,
KS_USER_UNLINK,
KS_USER_STAT,
KS_USER_FS_STAT,
KS_USER_FS_SYNC,
KS_USER_FTRUNCATE,
KS_USER_MKDIR,
KS_USER_OPENDIR,
KS_USER_CLOSEDIR,
KS_USER_READDIR,
KS_USER_RMDIR,
KS_USER_CHDIR,
KS_USER_GETCWD,
KS_USER_TELLDIR,
KS_USER_SEEKDIR,
KS_USER_REWIND_DIR,
KS_USER_STAT_FS,
KS_USER_END
};
#define SERVICETABLE ((struct Kernel_Service*)SERVICE_TABLE_ADDRESS)
#endif
typedef uintptr_t (*kservice)(uint32_t knum,uintptr_t *param,uint8_t param_num);
struct Kernel_Service
{
const kservice fun;
const uint8_t param_num;
};
extern struct Kernel_Service g_service_table[] ;
#endif

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_service.h
* @brief: maroc and switch table definition of kernel switch
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/2
*
*/
#ifndef XS_SPINLOCK_H
#define XS_SPINLOCK_H
#include <xs_isr.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef ARCH_SMP
typedef union
{
unsigned long slock;
struct __arch_tickets
{
unsigned short owner;
unsigned short next;
} tickets;
} HwSpinlock;
struct SpinLock
{
HwSpinlock lock;
};
struct Spin_Lockfileops
{ //定义自旋锁
struct SpinLock node_lock; //原有的自旋锁结构体
void (*SPinLock)(struct Spin_Lockfileops *spinlock);
void (*UnlockSpinLock)(struct Spin_Lockfileops *spinlock);
void (*UnlockSpinLockIrqRestore)(struct Spin_Lockfileops *spinlock, x_base level);
x_base (*SpinLockIrqSave)(struct Spin_Lockfileops *spinlock);
};
extern struct Spin_Lockfileops spinlock;
extern HwSpinlock _CriticalLock;
void InitHwSpinlock(HwSpinlock *lock);
void HwLockSpinlock(HwSpinlock *lock);
void HwUnlockSpinlock(HwSpinlock *lock);
int GetCpuId(void);
#define HW_SPIN_LOCK_INITIALIZER(lockname) {0}
#define HW_SPIN_LOCK_UNLOCKED(lockname) (HwSpinlock) HW_SPIN_LOCK_INITIALIZER(lockname)
#define DEFINE_SPINLOCK(x) HwSpinlock x = HW_SPIN_LOCK_UNLOCKED(x)
#define DECLARE_SPINLOCK(x)
void StartupSecondaryCpu(void);
void ExecSecondaryCpuIdleKtask(void);
#else
#define HwLockSpinlock(lock) *(lock) = DISABLE_INTERRUPT()
#define HwUnlockSpinlock(lock) ENABLE_INTERRUPT(*(lock))
#endif
#ifdef ARCH_SMP
struct SpinLock;
void InitSpinLock(struct Spin_Lockfileops * spinlock);
void _SpinLock(struct Spin_Lockfileops * spinlock);
void _UnlockSpinLock(struct Spin_Lockfileops * spinlock);
x_base _SpinLockIrqSave(struct Spin_Lockfileops * spinlock);
void _UnlockSpinLockIrqRestore(struct Spin_Lockfileops * spinlock, x_base level);
#else
#define InitSpinLock(lock) /* nothing */
#define SpinLock(lock) CriticalAreaLock()
#define UnlockSpinLock(lock) CriticalAreaUnLock()
#define SpinLockIrqSave(lock) DISABLE_INTERRUPT()
#define UnlockSpinLockIrqRestore(lock, level) ENABLE_INTERRUPT(level)
#endif
#ifdef __cplusplus
}
#endif
#endif

87
kernel/include/xs_timer.h Normal file
View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_timer.h
* @brief: function declaration and structure defintion of timer
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef XS_TIMER_H
#define XS_TIMER_H
#include <xsconfig.h>
#include <xs_kdbg.h>
#include <xs_base.h>
#include <xs_klist.h>
#include <xs_id.h>
#define TIMER_TRIGGER_ONCE (1 << 0)
#define TIMER_TRIGGER_PERIODIC (1 << 1)
#define TIMER_ACTIVE_FALSE (1 << 0)
#define TIMER_ACTIVE_TRUE (1 << 1)
struct Timer
{
struct IdNode id_node;
char name[NAME_NUM_MAX];
uint8 active_status;
uint8 trigger_mode;
void (*func_callback)(void *param);
void *param;
x_ticks_t origin_timeslice;
x_ticks_t deadline_timeslice;
DoubleLinklistType link;
DoubleLinklistType sortlist;
uint8 prio;
struct Work * t_work;
struct TimerDone* done;
};
typedef struct Timer *TimerType;
struct TimerDone
{
void (*Init)(struct Timer *timer,
const char *name,
void (*timeout)(void *parameter),
void *parameter,
x_ticks_t time,
uint8 trigger_mode);
x_err_t (*Delete)(TimerType timer);
x_err_t (*StartRun)(TimerType timer);
x_err_t (*QuitRun)(TimerType timer);
x_err_t (*Modify)(TimerType timer, x_ticks_t ticks);
};
int32 KCreateTimer(const char *name,
void (*timeout)(void *parameter),
void *parameter,
x_ticks_t time,
uint8 trigger_mode);
x_err_t KDeleteTimer(int32 timer_id);
x_err_t KTimerStartRun(int32 timer_id);
x_err_t KTimerQuitRun(int32 timer_id);
x_err_t KTimerModify(int32 timer_id, x_ticks_t ticks);
x_err_t KTimerAssignMemberRun(int32 timer_id, x_ticks_t ticks);
TimerType KGetTimer(int32 id);
int32 KGetTimerID(TimerType timer);
x_ticks_t TimerNextTimeoutTick(void);
void CheckTimerList(void);
#endif

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_waitqueue.h
* @brief: function declaration and structure defintion of waitqueue
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef XS_WAITQUEUE_H
#define XS_WAITQUEUE_H
#include <xs_ktask.h>
#include <xs_timer.h>
#include <xs_queue_manager.h>
#define WQ_FLAG_CLEAN 0x00
#define WQ_FLAG_WAKEUP 0x01
struct WaitQueue
{
DoubleLinklistType block_threads_list;
};
typedef struct WaitQueue WaitQueueType;
struct WaitqueueNode;
typedef int (*wqueue_func_t)(struct WaitqueueNode *wait, void *key);
struct WaitqueueNode
{
KTaskDescriptorType polling_task;
DoubleLinklistType list;
wqueue_func_t cb;
x_ticks_t deadline_tick;
uint32 key;
};
typedef struct WaitqueueNode WaitqueueNodeType;
int __WqueueDefaultWake(struct WaitqueueNode *wait, void *key);
void InitWqueue(WaitQueueType *queue);
void WqueueAdd(WaitQueueType *queue, struct WaitqueueNode *node);
void WqueueRemove(struct WaitqueueNode *node);
int WqueueWait(WaitQueueType *queue, x_ticks_t tick);
void WakeupWqueue(WaitQueueType *queue, void *key);
#define DEFINE_WAIT_FUNC(name, function) \
struct WaitqueueNode name = { \
os_running_task, \
DOUBLE_LINKLIST_OBJ_INIT(((name).list)), \
\
function, \
0 \
}
#define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, __WqueueDefaultWake)
typedef struct
{
void (*InitWqueue)(WaitQueueType *queue);
void (*WqueueAdd)(WaitQueueType *queue, WaitqueueNodeType *node);
void (*WqueueRemove)(WaitqueueNodeType *node);
int (*WqueueWait)(WaitQueueType *queue, x_ticks_t tick);
void (*WakeupWqueue)(WaitQueueType *queue, void *key);
} WaitQueueDoneType;
#endif

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_workqueue.h
* @brief: function declaration and structure defintion of workqueue
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/20
*
*/
#ifndef XS_WORKQUEUE_H
#define XS_WORKQUEUE_H
#include <xs_ktask.h>
#include <xs_timer.h>
#include <xs_queue_manager.h>
#define MAX_WORK_QUEUE 32
struct Work
{
void (*cb_func)(struct Work *work, void *work_data);
void *cb_param;
};
typedef struct
{
int front;
int rear;
struct Work* base;
int32 task;
}WorkqueueType;
typedef struct
{
WorkqueueType* p_queue;
struct Work* p_work;
int32 p_timer;
}WorkTimerParamType;
WorkqueueType *CreateWorkQueue(const char *name, uint16 stack_size, uint8 priority);
void WorkInit(struct Work *work, void (*work_func)(struct Work *work,void *work_data), void *work_data);
x_err_t WorkSubmit(WorkqueueType* sys_workq, struct Work *work, x_ticks_t time);
x_err_t WorkSubmit_immediate(WorkqueueType* sys_workq, struct Work *work);
int WorkSysWorkQueueInit(void);
typedef struct
{
WorkqueueType *(*CreateWorkQueue)(const char *name, uint16 stack_size, uint8 priority);
void (*WorkInit)(struct Work *work, void (*work_func)(struct Work *work, void *work_data), void *work_data);
x_err_t (*WorkSubmit)(WorkqueueType *sys_workq, struct Work *work, x_ticks_t time);
x_err_t (*WorkSubmit_immediate)(WorkqueueType *sys_workq, struct Work *work);
} WorkQueueDoneType;
#endif

View File

@@ -0,0 +1,4 @@
SRC_FILES := xs_service.c
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,710 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_service.c
* @brief: this file is provided for kernel switch of userapi
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/8
*
*/
#include <xs_service.h>
#ifdef FS_VFS
#include <iot-vfs_posix.h>
#endif
#ifdef TASK_ISOLATION
#include <xs_isolation.h>
#endif
extern inline struct TaskDescriptor *GetTaskWithIdnodeInfo(int32 id);
#ifdef SEPARATE_COMPILE
extern long ShowTask(void);
extern void ShowMemory(void);
extern long ShowSem(void);
extern long ShowEvent(void);
extern long ShowMutex(void);
//extern long ShowMemPool(void);
extern long ShowMsgQueue(void);
//extern long showdevice(void);
extern long ShowTimer(void);
uintptr_t KsPrintInfo(uint32_t knum,uintptr_t *param, uint8_t num )
{
uintptr_t arg = param[0];
uintptr_t ret = arg;
struct TaskDescriptor *tid = NONE;
KPrintf("ecall from user mode : arg: %d\n", arg );
switch (arg)
{
case 1:
#ifdef TOOL_SHELL
ShowTask();
#endif
break;
case 2:
ShowMemory();
break;
case 3:
#ifdef KERNEL_SEMAPHORE
//ShowSem();
#endif
break;
case 4:
#ifdef KERNEL_EVENT
ShowEvent();
#endif
break;
case 5:
#ifdef KERNEL_MUTEX
ShowMutex();
#endif
break;
case 6:
//ShowMemPool();
break;
case 7:
#ifdef KERNEL_MESSAGEQUEUE
ShowMsgQueue();
#endif
break;
case 8:
//showdevice();
break;
case 9:
#ifdef KERNEL_SOFTTIMER
ShowTimer();
#endif
break;
default:
KPrintf("unsurport \n");
break;
}
return ret;
}
uintptr_t KsTaskCreate(uint32_t knum,uintptr_t *param, uint8_t num)
{
return (uintptr_t) UTaskCreate((char *)(param[0]), (void *)(param[1]),(void *)(param[2]),(uint32)(param[3]),(uint8)(param[4]));
}
uintptr_t KsStartupTask(uint32_t knum,uintptr_t *param, uint8_t num)
{
x_err_t ret ;
int32 id = (int32)(param[0]);
ret = StartupKTask(id);
return (uintptr_t)ret;
}
uintptr_t KsTaskDelete(uint32_t knum,uintptr_t *param, uint8_t num)
{
x_err_t ret ;
ret = KTaskDelete((int32) (param[0]));
return (uintptr_t)ret;
}
extern void KTaskQuit(void);
uintptr_t KsTaskQuit(uint32_t knum,uintptr_t *param, uint8_t num )
{
KTaskQuit();
return 0;
}
uintptr_t KsTaskCoreCombine(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret = EOK ;
int32 id;
#ifdef ARCH_SMP
if( param[0] == NONE){
id = GetKTaskDescriptor()->id.id;
}else{
id = (int32 )(param[0]);
}
ret = KTaskCoreCombine(id, (uint8)(param[1]));
#endif
return (uintptr_t)ret;
}
uintptr_t KsTaskCoreUnCombine(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret = EOK;
int32 id;
#ifdef ARCH_SMP
KTaskDescriptorType tid;
if( param[0] == NONE){
id = GetKTaskDescriptor()->id.id;
}else{
id = (int32 )(param[0]);
}
ret = KTaskCoreUnCombine(id);
#endif
return (uintptr_t)ret;
}
uintptr_t KsMdelayTask(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret ;
ret = MdelayKTask((int32)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsGetTaskID(uint32_t knum,uintptr_t *param, uint8_t num )
{
return (uintptr_t)GetKTaskDescriptor()->id.id;
}
uintptr_t KsGetTaskName(uint32_t knum,uintptr_t *param, uint8_t num )
{
KTaskDescriptorType task ;
uint8_t *buf = (uint8_t *)(param[1]);
task = GetTaskWithIdnodeInfo( (int32)(param[0]));
if ( task == NONE )
return -ERROR;
strncpy(buf, task->task_base_info.name, NAME_NUM_MAX);
return EOK;
}
uintptr_t KsGetTaskStat(uint32_t knum,uintptr_t *param, uint8_t num )
{
KTaskDescriptorType task ;
task = GetTaskWithIdnodeInfo( (int32)(param[0]));
return (uintptr_t)task->task_dync_sched_member.stat;
}
uintptr_t KsGetTaskCombinedCore(uint32_t knum,uintptr_t *param, uint8_t num )
{
#ifdef ARCH_SMP
KTaskDescriptorType task ;
task = GetTaskWithIdnodeInfo( (int32)(param[0]));
return (uintptr_t)task->task_smp_info.combined_coreid;
#else
return (uintptr_t)0;
#endif
}
uintptr_t KsGetTaskRunningCore(uint32_t knum,uintptr_t *param, uint8_t num )
{
#ifdef ARCH_SMP
KTaskDescriptorType task ;
task = GetTaskWithIdnodeInfo( (int32)(param[0]));
return (uintptr_t)task->task_smp_info.runing_coreid;
#else
return (uintptr_t)0;
#endif
}
uintptr_t KsGetTaskErrorstatus(uint32_t knum,uintptr_t *param, uint8_t num )
{
KTaskDescriptorType task ;
task = GetTaskWithIdnodeInfo( (int32)(param[0]));
return (uintptr_t)task->exstatus;
}
uintptr_t KsGetTaskPriority (uint32_t knum,uintptr_t *param, uint8_t num )
{
KTaskDescriptorType task ;
task = GetTaskWithIdnodeInfo( (int32)(param[0]));
return (uintptr_t)task->task_dync_sched_member.cur_prio;
}
uintptr_t KsMalloc(uint32_t knum,uintptr_t *param, uint8_t num )
{
uintptr_t *ret = (uintptr_t *)x_umalloc( (x_size_t)param[0]);
#ifdef MOMERY_PROTECT_ENABLE
if( mem_access.AddRegion && ret != NONE){
struct TaskDescriptor *task;
task = GetKTaskDescriptor();
mem_access.AddRegion(task->task_dync_sched_member.isolation, (x_ubase)ret , (x_size_t)param[0] , REGION_TYPE_HEAP );
}
#endif
return (uintptr_t)ret;
}
uintptr_t KsFree(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_ufree((void *)(param[0]));
#ifdef MOMERY_PROTECT_ENABLE
if(mem_access.ClearRegion){
struct TaskDescriptor *task;
task = GetKTaskDescriptor();
mem_access.ClearRegion(task->task_dync_sched_member.isolation, (x_ubase)param[0]);
}
#endif
return 0;
}
#ifdef KERNEL_MUTEX
uintptr_t KsCreateMutex(uint32_t knum,uintptr_t *param, uint8_t num )
{
int32 ret;
ret = KMutexCreate();
return (uintptr_t)ret;
}
uintptr_t KsDeleteMutex(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret = EOK;
KMutexDelete((int32)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsMutexObtain(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret ;
ret = KMutexObtain((int32)(param[0]),(int32)(param[1]));
return (uintptr_t)ret;
}
uintptr_t KsMutexAbandon(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret ;
ret = KMutexAbandon((int32)(param[0]));
return (uintptr_t)ret;
}
#endif
#ifdef KERNEL_SEMAPHORE
uintptr_t KsCreateSemaphore(uint32_t knum,uintptr_t *param, uint8_t num)
{
int32 ret;
ret = KSemaphoreCreate((uint16)param[0]);
return (uintptr_t)ret ;
}
uintptr_t KsDeleteSemaphore(uint32_t knum,uintptr_t *param, uint8_t num )
{
KSemaphoreDelete((int32)(param[0]));
return 0;
}
uintptr_t KsSemaphoreObtain(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret ;
ret = KSemaphoreObtain((int32)(param[0]),(int32)(param[1]));
return (uintptr_t)ret;
}
uintptr_t KsSemaphoreAbandon(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret ;
ret = KSemaphoreAbandon((int32)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsSemaphoreSetValue(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret ;
ret = KSemaphoreSetValue((int32)(param[0]),(uint16)(param[1]));
return (uintptr_t)ret;
}
#endif
#ifdef KERNEL_EVENT
uintptr_t KsCreateEvent(uint32_t knum,uintptr_t *param, uint8_t num )
{
EventIdType ret;
ret = KEventCreate((uint8)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsDeleteEvent(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret = 0;
KEventDelete((EventIdType)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsEventTrigger(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret;
ret = KEventTrigger((EventIdType)(param[0]), (uint32)(param[1]));
return (uintptr_t)ret;
}
uintptr_t KsEventProcess(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret;
ret = KEventProcess((EventIdType)(param[0]), (uint32)(param[1]), (uint8)(param[2]), (int32)(param[3]), (uint32 *)(param[4]) );
return (uintptr_t)ret;
}
#endif
#ifdef KERNEL_MESSAGEQUEUE
uintptr_t KsCreateMsgQueue(uint32_t knum,uintptr_t *param, uint8_t num )
{
int32 ret;
ret = KCreateMsgQueue((int32)(param[0]), (x_size_t)(param[1]) );
return (uintptr_t)ret;
}
uintptr_t KsDeleteMsgQueue(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret;
ret = KDeleteMsgQueue((int32)(param[0]) );
return (uintptr_t)ret;
}
uintptr_t KsMsgQueueSendwait(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret;
ret = KMsgQueueSendwait((int32)(param[0]), (const void *)(param[1]), (x_size_t)(param[2]), (int32)(param[3]) );
return (uintptr_t)ret;
}
uintptr_t KsMsgQueueSend(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret;
ret = KMsgQueueSend((int32)(param[0]), (const void *)(param[1]), (x_size_t)(param[2]) );
return (uintptr_t)ret;
}
uintptr_t KsMsgQueueUrgentSend(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret;
ret = KMsgQueueUrgentSend((int32)(param[0]), (const void *)(param[1]), (x_size_t)(param[2]) );
return (uintptr_t)ret;
}
uintptr_t KsMsgQueueRecv(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret;
ret = KMsgQueueRecv((int32)(param[0]), (void *)(param[1]), (x_size_t)(param[2]), (int32)(param[3]) );
return (uintptr_t)ret;
}
uintptr_t KsMsgQueueReinit(uint32_t knum,uintptr_t *param, uint8_t num )
{
x_err_t ret;
ret = KMsgQueueReinit((int32)(param[0]) );
return (uintptr_t)ret;
}
#endif
/* fs posix*/
#ifdef FS_VFS
uintptr_t KsOpen(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = open((const char *)(param[0]), (int)(param[1]), (mode_t)(param[2]));
return (uintptr_t)ret;
}
uintptr_t KsRead(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = read((int)(param[0]), (void *)(param[1]), (size_t)(param[2]) );
return (uintptr_t)ret;
}
uintptr_t KsWrite(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = write((int)(param[0]), (const void *)(param[1]), (size_t)(param[2]));
return (uintptr_t)ret;
}
uintptr_t KsClose(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = close((int)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsIoctl(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = ioctl((int)(param[0]), (int)(param[1]), (void *)(param[2]));
return (uintptr_t)ret;
}
uintptr_t KsLseek(uint32_t knum,uintptr_t *param, uint8_t num )
{
off_t ret;
ret = lseek((int)(param[0]), (off_t)(param[1]), (int)(param[2]) );
return (uintptr_t)ret;
}
uintptr_t KsRename(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = rename((const char *)(param[0]), (const char *)(param[1]) );
return (uintptr_t)ret;
}
uintptr_t KsUnlink(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = unlink((const char *)(param[0]) );
return (uintptr_t)ret;
}
uintptr_t KsStat(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = stat((const char *)(param[0]), (struct stat *)(param[1]));
return (uintptr_t)ret;
}
uintptr_t KsFstat(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = fstat((int)(param[0]), (struct stat *)(param[1]));
return (uintptr_t)ret;
}
uintptr_t KsFsync(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = fsync((int)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsFtruncate(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = ftruncate((int)(param[0]), (off_t)(param[1]));
return (uintptr_t)ret;
}
uintptr_t KsMkdir(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = mkdir((const char *)(param[0]), (mode_t)(param[1]));
return (uintptr_t)ret;
}
uintptr_t KsOpendir(uint32_t knum,uintptr_t *param, uint8_t num )
{
DIR *ret;
ret = opendir((const char *)(param[0]) );
return (uintptr_t)ret;
}
uintptr_t KsClosedir(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = closedir((DIR *)(param[0]) );
return (uintptr_t)ret;
}
uintptr_t KsReaddir(uint32_t knum,uintptr_t *param, uint8_t num )
{
struct dirent *ret;
ret = readdir((DIR *)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsRmdir(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = rmdir((const char *)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsChdir(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = chdir((const char *)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsGetcwd(uint32_t knum,uintptr_t *param, uint8_t num )
{
char *ret;
ret = getcwd((char *)(param[0]), (size_t)(param[1]));
return (uintptr_t)ret;
}
uintptr_t KsTelldir(uint32_t knum,uintptr_t *param, uint8_t num )
{
long ret = 0;
//ret = telldir((DIR *)(param[0]));
return (uintptr_t)ret;
}
uintptr_t KsSeekdir(uint32_t knum,uintptr_t *param, uint8_t num )
{
seekdir((DIR *)(param[0]), (off_t)(param[1]));
return 0;
}
uintptr_t KsRewinddir(uint32_t knum,uintptr_t *param, uint8_t num )
{
rewinddir((DIR *)(param[0]));
return 0;
}
uintptr_t KsStatfs(uint32_t knum,uintptr_t *param, uint8_t num )
{
int ret;
ret = statfs((const char *)(param[0]), (struct statfs *)(param[1]));
return (uintptr_t)ret;
}
#endif
struct Kernel_Service g_service_table[256] __attribute__ ((section (".g_service_table"))) =
{
[KS_USER_PRINT_INFO] = { KsPrintInfo, 1 },
/*************** Task ************/
[KS_USER_TASK_CREATE] = { KsTaskCreate, 5 },
[KS_USER_TASK_STARTUP] = { KsStartupTask, 1 },
[KS_USER_TASK_DELETE] = { KsTaskDelete, 1 },
[KS_USER_TASK_EXECEXIT] = { KsTaskQuit, 0 },
[KS_USER_TASK_CORE_COMBINE] = { KsTaskCoreCombine, 2 },
[KS_USER_TASK_CORE_UNCOMBINE] = { KsTaskCoreUnCombine, 1 },
[KS_USER_TASK_DELAY] = { KsMdelayTask, 1 },
[KS_USER_GET_TASK_NAME] = { KsGetTaskName, 2 },
[KS_USER_GET_TASK_ID] = { KsGetTaskID, 0 },
[KS_USER_GET_TASK_STAT] = { KsGetTaskStat, 1 },
[KS_USER_GET_TASK_COMBINEED_CORE] = { KsGetTaskCombinedCore, 1 },
[KS_USER_GET_TASK_RUNNING_CORE] = { KsGetTaskRunningCore, 1 },
[KS_USER_GET_TASK_ERROR_STATUS] = { KsGetTaskErrorstatus, 1 },
[KS_USER_GET_TASK_PRIORITY] = { KsGetTaskPriority, 1 },
/*************** Memory ************/
[KS_USER_MALLOC] = { KsMalloc, 1 },
[KS_USER_FREE] = { KsFree, 1 },
#ifdef KERNEL_MUTEX
/*************** Mutex ************/
[KS_USER_MUTEX_CREATE] = { KsCreateMutex, 0 },
[KS_USER_MUTEX_DELETE] = { KsDeleteMutex, 1 },
[KS_USER_MUTEX_OBTAIN] = { KsMutexObtain, 2 },
[KS_USER_MUTEX_ABANDON] = { KsMutexAbandon, 1 },
#endif
#ifdef KERNEL_SEMAPHORE
/*************** Semaphore ************/
[KS_USER_SEMAPHORE_CREATE] = { KsCreateSemaphore, 1 },
[KS_USER_SEMAPHORE_DELETE] = { KsDeleteSemaphore, 1 },
[KS_USER_SEMAPHORE_OBTAIN] = { KsSemaphoreObtain, 2 },
[KS_USER_SEMAPHORE_ABANDON] = { KsSemaphoreAbandon, 1 },
[KS_USER_SEMAPHORE_SETVALUE] = { KsSemaphoreSetValue, 2 },
#endif
/*************** Event ************/
#ifdef KERNEL_EVENT
[KS_USER_EVENT_CREATE] = { KsCreateEvent, 1 },
[KS_USER_EVENT_DELETE] = { KsDeleteEvent, 1 },
[KS_USER_EVENT_TRIGGER] = { KsEventTrigger, 2 },
[KS_USER_EVENT_PROCESS] = { KsEventProcess, 5 },
#endif
#ifdef KERNEL_MESSAGEQUEUE
/*************** Msg queue ************/
[KS_USER_MSGQUEUE_CREATE] = { KsCreateMsgQueue, 2 },
[KS_USER_MSGQUEUE_DELETE] = { KsDeleteMsgQueue, 1 },
[KS_USER_MSGQUEUE_SENDWAIT] = { KsMsgQueueSendwait, 4 },
[KS_USER_MSGQUEUE_SEND] = { KsMsgQueueSend, 3 },
[KS_USER_MSGQUEUE_URGENTSEND] = { KsMsgQueueUrgentSend, 3 },
[KS_USER_MSGQUEUE_RECV] = { KsMsgQueueRecv, 4 },
[KS_USER_MSGQUEUE_REINIT] = { KsMsgQueueReinit, 1 },
#endif
#ifdef FS_VFS
/*************** fs poxix ************/
[KS_USER_OPEN] = { KsOpen , 3 },
[KS_USER_READ] = { KsRead , 3 },
[KS_USER_WRITE] = { KsWrite , 3 },
[KS_USER_CLOSE] = { KsClose , 1 },
[KS_USER_IOCTL] = { KsIoctl , 3 },
[KS_USER_LSEEK] = { KsLseek , 3 },
[KS_USER_RENAME] = { KsRename , 2 },
[KS_USER_UNLINK] = { KsUnlink , 1 },
[KS_USER_STAT] = { KsStat , 2 },
[KS_USER_FS_STAT] = { KsFstat , 2 },
[KS_USER_FS_SYNC] = { KsFsync , 1 },
[KS_USER_FTRUNCATE] = { KsFtruncate , 2 },
[KS_USER_MKDIR] = { KsMkdir , 2 },
[KS_USER_OPENDIR] = { KsOpendir , 1 },
[KS_USER_CLOSEDIR] = { KsClosedir , 1 },
[KS_USER_READDIR] = { KsReaddir , 1 },
[KS_USER_RMDIR] = { KsRmdir , 1 },
[KS_USER_CHDIR] = { KsChdir , 1 },
[KS_USER_GETCWD] = { KsGetcwd, 2 },
[KS_USER_TELLDIR] = { KsTelldir, 1 },
[KS_USER_SEEKDIR] = { KsSeekdir, 2 },
[KS_USER_REWIND_DIR] = { KsRewinddir, 1 },
[KS_USER_STAT_FS] = { KsStatfs, 2 },
#endif
[KS_USER_END ... 255] = {NONE, 0}
};
#else
struct utask
{
char name[NAME_NUM_MAX];
void *func_entry;
void *func_param;
int32_t stack_size;
uint8_t prio;
};
typedef struct utask utask_x;
int32_t UserTaskCreate(utask_x utask)
{
return KTaskCreate(utask.name, utask.func_entry, utask.func_param,utask.stack_size,utask.prio);
}
x_err_t UserGetTaskName(int32_t id ,char *name)
{
KTaskDescriptorType task ;
uint8_t *buf = (uint8_t *)(name);
task = GetTaskWithIdnodeInfo(id);
if ( task == NONE )
return -ERROR;
strncpy(buf, task->task_base_info.name, NAME_NUM_MAX);
return EOK;
}
int32_t UserGetTaskID(void)
{
return (uintptr_t)GetKTaskDescriptor()->id.id;
}
uint8_t UserGetTaskStat(int32_t id)
{
KTaskDescriptorType task ;
task = GetTaskWithIdnodeInfo(id);
return (uintptr_t)task->task_dync_sched_member.stat;
}
#ifdef ARCH_SMP
uint8_t UserGetTaskCombinedCore(int32_t id)
{
KTaskDescriptorType task ;
task = GetTaskWithIdnodeInfo(id);
return (uintptr_t)task->task_smp_info.combined_coreid;
}
uint8_t UserGetTaskRunningCore(int32_t id)
{
KTaskDescriptorType task ;
task = GetTaskWithIdnodeInfo(id);
return (uintptr_t)task->task_smp_info.runing_coreid;
}
#endif
x_err_t UserGetTaskErrorstatus(int32_t id)
{
KTaskDescriptorType task ;
task = GetTaskWithIdnodeInfo(id);
return (uintptr_t)task->exstatus;
}
uint8_t UserGetTaskPriority(int32_t id)
{
KTaskDescriptorType task ;
task = GetTaskWithIdnodeInfo(id);
return (uintptr_t)task->task_dync_sched_member.cur_prio;
}
long occupy_g_service_table __attribute__ ((section (".g_service_table"))) = 0;
#endif

View File

@@ -0,0 +1,62 @@
menuconfig KERNEL_TEST
bool "Enable kernel test function "
default n
if KERNEL_TEST
config KERNEL_TEST_AVLTREE
bool "Config test avl tree"
default n
select KERNEL_AVL_TREE
config KERNEL_TEST_CRICULAR_AREA
bool "Config test Circular area"
default n
select KERNEL_CIRCULAR_AREA
config KERNEL_TEST_MEM
bool "Config test mem"
default n
select KERNEL_MEMBLOCK
config KERNEL_TEST_TIMER
bool "Config test timer"
default n
config KERNEL_TEST_IWG
bool "Config test iwg"
default n
select BSP_USING_WDT
config KERNEL_TEST_REALTIME
bool "Config test realtime"
default n
config KERNEL_TEST_DBG
bool "Config test dbg"
default n
select KERNEL_DEBUG
config KERNEL_TEST_SCHED
bool "Config test sched"
default n
config KERNEL_TEST_RTC
bool "Config test rtc"
default n
config KERNEL_TEST_SERIAL
bool "Config test serial"
default n
config KERNEL_TEST_HWTIMER
bool "Config test hwtimer"
default n
config KERNEL_TEST_CAN
bool "Config test can"
default n
config KERNEL_TEST_TOUCH
bool "Config test touch"
default n
config KERNEL_TEST_LCD
bool "Config test lcd"
default n
config KERNEL_TEST_CH438
bool "Config test ch438"
default n
config KERNEL_TEST_I2C
bool "Config test i2c"
default n
config KERNEL_TEST_RISC_CAN
bool "Config test riscv can "
default n
endif

View File

@@ -0,0 +1,88 @@
SRC_FILES := test_main.c
ifeq ($(CONFIG_KERNEL_TEST_SEM),y)
SRC_FILES += test_sem.c
endif
ifeq ($(CONFIG_KERNEL_TEST_MUTEX),y)
SRC_FILES += test_mutex.c
endif
ifeq ($(CONFIG_KERNEL_TEST_EVENT),y)
SRC_FILES += test_event.c
endif
ifeq ($(CONFIG_KERNEL_TEST_MSG),y)
SRC_FILES += test_mq.c
endif
ifeq ($(CONFIG_KERNEL_TEST_AVLTREE),y)
SRC_FILES += test_avltree.c
endif
ifeq ($(CONFIG_KERNEL_TEST_CRICULAR_AREA),y)
SRC_FILES += test_circulararea.c
endif
ifeq ($(CONFIG_KERNEL_TEST_TOUCH),y)
SRC_FILES += test_touch.c
endif
ifeq ($(CONFIG_KERNEL_TEST_MEM),y)
SRC_FILES += test_mem.c
SRC_FILES += test_gatherblock.c
endif
ifeq ($(CONFIG_KERNEL_TEST_TIMER),y)
SRC_FILES += test_timer.c
endif
ifeq ($(CONFIG_KERNEL_TEST_IWG),y)
SRC_FILES += test_iwg.c
endif
ifeq ($(CONFIG_KERNEL_TEST_CAN),y)
SRC_FILES += test_can.c
endif
ifeq ($(CONFIG_KERNEL_TEST_REALTIME),y)
SRC_FILES += test_realtime.c
endif
ifeq ($(CONFIG_KERNEL_TEST_DBG),y)
SRC_FILES += test_dbg.c
endif
ifeq ($(CONFIG_KERNEL_TEST_SCHED),y)
SRC_FILES += test_threadsched.c
endif
ifeq ($(CONFIG_KERNEL_TEST_RTC),y)
SRC_FILES += test_rtc.c
endif
ifeq ($(CONFIG_KERNEL_TEST_SERIAL),y)
SRC_FILES += test_serial.c
endif
ifeq ($(CONFIG_KERNEL_TEST_HWTIMER),y)
SRC_FILES += test_hwtimer.c
endif
ifeq ($(CONFIG_KERNEL_TEST_LCD),y)
SRC_FILES += test_lcd.c
endif
ifeq ($(CONFIG_KERNEL_TEST_CH438),y)
SRC_FILES += test_ch438.c
endif
ifeq ($(CONFIG_KERNEL_TEST_I2C),y)
SRC_FILES += test_i2c.c
endif
ifeq ($(CONFIG_KERNEL_TEST_RISC_CAN),y)
SRC_FILES += riscv_test_can.c
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file riscv_test_can.c
* @brief support to test can function on aiit-riscv64-board
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#ifdef BOARD_AIIT_RISCV_EVB
#include <device.h>
#include <gpiohs.h>
#include "board.h"
#include "connect_ch438.h"
static struct Bus *bus;
static struct HardwareDev *dev;
static struct Driver *drv;
static int32 Timer = NONE;
static uint8 idx = 0;
static void Ch438Read(void *parameter)
{
uint8 rev_len;
uint8 ext_uart_no = 3;
static uint8 dat,i,count;
struct BusBlockReadParam read_param;
static uint8 Ch438Buff[8][BUFFSIZE];
while (1)
{
read_param.buffer = Ch438Buff[3];
rev_len = BusDevReadData(dev, &read_param);
for(count = 0 ;count < rev_len ;count++)
{
KPrintf("%#2x ",Ch438Buff[3][count]);
KPrintf("\n");
}
for(i=0;i<BUFFSIZE;i++)
{
Ch438Buff[3][i] = 0;
}
}
}
static void TestCh438Init(void)
{
x_err_t flag;
struct BusConfigureInfo configure_info;
int32 task_CH438 = KTaskCreate("task_CH438", Ch438Read, NONE, 2048, 10);
flag = StartupKTask(task_CH438);
if (flag != EOK) {
KPrintf("StartupKTask failed .\n");
return ;
}
bus = BusFind(CH438_BUS_NAME);
drv = BusFindDriver(bus, CH438_DRIVER_NAME);
dev = BusFindDevice(bus, CH438_DEVICE_NAME_3);
struct SerialCfgParam serial_cfg;
memset(&serial_cfg, 0, sizeof(struct SerialCfgParam));
configure_info.configure_cmd = OPE_INT;
configure_info.private_data = (void *)&serial_cfg;
serial_cfg.data_cfg.port_configure = PORT_CFG_INIT;
serial_cfg.data_cfg.ext_uart_no = 3;
serial_cfg.data_cfg.serial_baud_rate = 115200;
BusDrvConfigure(drv, &configure_info);
}
void CanTestSend(void)
{
uint8 MeterInstruction[8]={0x01, 0x04, 0x77, 0x66, 0x20, 0x03, 0xB0, 0x0B};
struct BusBlockWriteParam write_param;
write_param.buffer = MeterInstruction;
write_param.size = 8;
TestCh438Init();
MdelayKTask(500);
while(1)
{
BusDevWriteData(dev, &write_param);
KPrintf("test_can_send!\n");
MdelayKTask(500);
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
CanTestSend, CanTestSend, CanTestSend );
void CanTestRecv(void)
{
TestCh438Init();
MdelayKTask(500);
while(1)
{
;
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
CanTestRecv, CanTestRecv, CanTestRecv );
#endif

View File

@@ -0,0 +1,200 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file TestAvltree.c
* @brief support to test avltree function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <device.h>
#include <string.h>
#include <stdlib.h>
#include <xs_avltree.h>
static char string[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
static AvlNodeType g_avlnode;
static AvlNodeType create_tree(AvlNodeType avl_node)
{
uint32 i = 0;
uint32 string_len = strlen(string);
for(i = 0; i < string_len; i ++)
{
KPrintf("avl_node %8p data %d\n", avl_node, string[i]);
avl_node = AvlTreeInsertNode(avl_node, string[i]);
}
return avl_node;
}
static AvlNodeType DeleteNode(AvlNodeType avl_node, int32 data)
{
avl_node = AvlTreeDeleteNode(avl_node, data);
return avl_node;
}
static AvlNodeType DeleteTree(AvlNodeType avl_node)
{
uint32 i = 0;
uint32 string_len = strlen(string);
for(i = 0; i < string_len; i ++)
{
avl_node = AvlTreeDeleteNode(avl_node, string[i]);
}
return avl_node;
}
static AvlNodeType InsertNode(AvlNodeType avl_node, int32 data)
{
avl_node = AvlTreeInsertNode(avl_node, data);
return avl_node;
}
static AvlNodeType SearchNode(AvlNodeType avl_node, int32 data)
{
AvlNodeType dst_node;
dst_node = AvlNodeSearchNode(avl_node, data);
return dst_node;
}
static AvlNodeType ModyfiNode(AvlNodeType avl_node, int32 src_data, int32 dst_data)
{
AvlNodeType dst_node;
dst_node = AvlNodeModifyNode(avl_node, src_data, dst_data);
return dst_node;
}
static void PrintfRootnode(void)
{
KPrintf("g_avlnode %8p data %d left %8p data %d right %8p data %d\n",
g_avlnode, g_avlnode->data, g_avlnode->left, g_avlnode->left->data, g_avlnode->right, g_avlnode->right->data);
KPrintf("g_avlnode left %8p data %d left %8p data %d right %8p data %d\n",
g_avlnode->left, g_avlnode->left->data, g_avlnode->left->left, g_avlnode->left->left->data, g_avlnode->left->right, g_avlnode->left->right->data);
KPrintf("g_avlnode right %8p data %d left %8p data %d right %8p data %d\n",
g_avlnode->right, g_avlnode->right->data, g_avlnode->right->left, g_avlnode->right->left->data, g_avlnode->right->right, g_avlnode->right->right->data);
}
static void InorderPrintftree(AvlNodeType avl_node)
{
if(avl_node)
{
if(avl_node->left)
{
InorderPrintftree(avl_node->left);
}
KPrintf("%d ", avl_node->data);
if(avl_node->right)
{
InorderPrintftree(avl_node->right);
}
}
else
{
KPrintf("nil \n");
}
}
static uint32 TestAvltree(int argc, char *argv[])
{
if(0 == argc)
{
KPrintf("TestAvltree needs parameters. Just return\n");
return EOK;
}
if(0 == strcmp("-c", argv[1]))
{
g_avlnode = create_tree(g_avlnode);
if(NONE == g_avlnode)
{
KPrintf("TestAvltree g_avlnode create failed!\n");
return ERROR;
}
PrintfRootnode();
InorderPrintftree(g_avlnode);
}
else if(0 == strcmp("-d", argv[1]))
{
if(3 == argc)
{
int32 data = atoi(argv[2]);
g_avlnode = DeleteNode(g_avlnode, data);
PrintfRootnode();
InorderPrintftree(g_avlnode);
}
else if(2 == argc)
{
g_avlnode = DeleteTree(g_avlnode);
PrintfRootnode();
InorderPrintftree(g_avlnode);
}
}
else if(0 == strcmp("-i", argv[1]))
{
if(3 == argc)
{
int32 data = atoi(argv[2]);
g_avlnode = InsertNode(g_avlnode, data);
PrintfRootnode();
InorderPrintftree(g_avlnode);
}
}
else if(0 == strcmp("-s", argv[1]))
{
if(3 == argc)
{
int32 data = atoi(argv[2]);
AvlNodeType dst_node = SearchNode(g_avlnode, data);
KPrintf("find data %dx%d node %8p\n", dst_node->data, data, dst_node);
PrintfRootnode();
}
}
else if(0 == strcmp("-m", argv[1]))
{
if(4 == argc)
{
int32 src_data = atoi(argv[2]);
int32 dst_data = atoi(argv[3]);
g_avlnode = ModyfiNode(g_avlnode, src_data, dst_data);
PrintfRootnode();
InorderPrintftree(g_avlnode);
}
}
return EOK;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_PARAM_NUM(4),
TestAvltree, TestAvltree, Test the AVL tree Function);

View File

@@ -0,0 +1,169 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file test_can.c
* @brief support to test can function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include "bus_can.h"
#include "dev_can.h"
uint8 buf[8] = {0x33,0x55,0x77,0x99,0x66,0x44,0x88,0x11};
uint8 rx_buf[8];
struct BusBlockWriteParam cfx = {
.pos = 0,
.buffer = buf,
.size = 8
};
uint8 rx_buf[8] = {0};
struct BusBlockReadParam read_param = {
.pos = 0,
.buffer =rx_buf ,
.read_length =0
};
static struct CanDriverConfigure can_defconfig = {
.tsjw = 0,
.tbs2 = 5 ,
.tbs1 = 6,
.brp = 6,
.mode = 0
};
struct BusConfigureInfo configure_info ={
.configure_cmd = 0,
.private_data = &can_defconfig
};
static int _CanTestSend(const char *bus_name, const char *driver_name, const char *device_name0)
{
int i;
struct Bus *bus;
struct Driver *driver, *bus_driver;
struct HardwareDev *device0, *device1;
struct HardwareDev *bus_device0;
if(bus_name)
{
bus = BusFind(bus_name);
KPrintf("##test bus %p##\n", bus);
}
if(driver_name)
{
driver = CanDriverFind(driver_name, TYPE_CAN_DRV);
bus_driver = BusFindDriver(bus, driver_name);
KPrintf("##test driver %p bus_driver %p##\n", driver, bus_driver);
}
if(device_name0)
{
device0 = CanDeviceFind(device_name0, TYPE_CAN_DEV);
bus_device0 = BusFindDevice(bus, device_name0);
KPrintf("####test device0 %p bus_device0 %p####\n", device0, bus_device0);
KPrintf("####test device0 private %p\n", device0->private_data);
}
BusDrvConfigure(bus_driver, &configure_info);
while(1)
{
BusDevWriteData(device0, &cfx);
uint8 * buf =(uint8 *) cfx.buffer;
KPrintf("send:");
for(i = 0;i<cfx.size;i++)
KPrintf("0x%2x ", buf[i]);
KPrintf("\n");
MdelayKTask(2000);
}
}
void CanTestSend(void)
{
_CanTestSend(CAN_BUS_NAME_1,CAN_DRIVER_NAME,CAN_1_DEVICE_NAME_1);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),CanTestSend, CanTestSend, Close AC task );
static int _CanTestRecv(const char *bus_name, const char *driver_name, const char *device_name0)
{
int len ,i;
struct Bus *bus;
struct Driver *driver, *bus_driver;
struct HardwareDev *device0, *device1;
struct HardwareDev *bus_device0;
if(bus_name)
{
KPrintf("####test find bus %s\n", bus_name);
bus = BusFind(bus_name);
KPrintf("####test bus %p####\n", bus);
}
if(driver_name)
{
KPrintf("####test find driver %s\n", driver_name);
driver = CanDriverFind(driver_name, TYPE_CAN_DRV);
bus_driver = BusFindDriver(bus, driver_name);
KPrintf("####test driver %p bus_driver %p####\n", driver, bus_driver);
}
if(device_name0)
{
KPrintf("####test find device0 %s\n", device_name0);
device0 = CanDeviceFind(device_name0, TYPE_CAN_DEV);
bus_device0 = BusFindDevice(bus, device_name0);
KPrintf("####test device0 %p bus_device0 %p####\n", device0, bus_device0);
KPrintf("####test device0 private %p\n", device0->private_data);
}
BusDrvConfigure(bus_driver, &configure_info);
while(1)
{
len = BusDevReadData(bus_device0,&read_param);
if(0 != len)
{
for(i = 0; i<len;i++)
KPrintf("0x%02x ", rx_buf[i]);
KPrintf("\n");
}
else
{
MdelayKTask(100);
}
}
}
void CanTestRecv(void)
{
_CanTestRecv(CAN_BUS_NAME_1,CAN_DRIVER_NAME,CAN_1_DEVICE_NAME_1);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),CanTestRecv, CanTestRecv, Close AC task );

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file TestCh438.c
* @brief support to test ch438 function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <device.h>
#include "board.h"
#include "connect_ch438.h"
#if defined BOARD_AIIT_RISCV_EVB
#define EXT_UART_NO 2
#elif defined BOARD_STM32F407_EVB
#define EXT_UART_NO 4
#endif
#define DATA_BUFF_SIZE 255
static struct Bus *bus;
static struct HardwareDev *dev;
static struct Driver *drv;
static void Ch438Read(void *parameter)
{
uint8 RevLen;
uint8 ext_uart_no = EXT_UART_NO;
uint8 i;
uint16 vol, cur, pwr;
struct BusBlockReadParam read_param;
static uint8 Ch438Buff[8][DATA_BUFF_SIZE];
while (1)
{
MdelayKTask(100);
read_param.buffer = Ch438Buff[ext_uart_no];
RevLen = BusDevReadData(dev, &read_param);
vol = ((uint16)Ch438Buff[ext_uart_no][3] << 8) | Ch438Buff[ext_uart_no][4];
cur = ((uint16)Ch438Buff[ext_uart_no][5] << 8) | Ch438Buff[ext_uart_no][6];
pwr = ((uint16)Ch438Buff[ext_uart_no][7] << 8) | Ch438Buff[ext_uart_no][8];
KPrintf("Board voltage : %d.%d V current : %d mA power : %d.%03d W\n", vol/10, vol%10, cur, pwr/1000, pwr%1000);
for(i = 0 ; i < DATA_BUFF_SIZE; i ++) {
Ch438Buff[ext_uart_no][i] = 0;
}
}
}
static void Ch438Write(void *parameter)
{
x_err_t result;
uint8 MeterInstruction[8] = {0x01, 0x04, 0x00, 0x00, 0x00, 0x03, 0xB0, 0x0B};
struct BusBlockWriteParam write_param;
write_param.buffer = MeterInstruction;
write_param.size = 8;
while (1)
{
MdelayKTask(1000);
KPrintf("\n");
BusDevWriteData(dev, &write_param);
}
}
static void TestCh438Init(void)
{
x_err_t flag;
struct BusConfigureInfo configure_info;
bus = BusFind(CH438_BUS_NAME);
drv = BusFindDriver(bus, CH438_DRIVER_NAME);
#if defined BOARD_AIIT_RISCV_EVB
dev = BusFindDevice(bus, CH438_DEVICE_NAME_2);
#elif defined BOARD_STM32F407_EVB
dev = BusFindDevice(bus, CH438_DEVICE_NAME_4);
#endif
struct SerialCfgParam serial_cfg;
memset(&serial_cfg, 0, sizeof(struct SerialCfgParam));
configure_info.configure_cmd = OPE_INT;
configure_info.private_data = (void *)&serial_cfg;
serial_cfg.data_cfg.port_configure = PORT_CFG_INIT;
serial_cfg.data_cfg.ext_uart_no = EXT_UART_NO;
serial_cfg.data_cfg.serial_baud_rate = 9600;
BusDrvConfigure(drv, &configure_info);
int32 task_CH438_read = KTaskCreate("task_CH438_read", Ch438Read, NONE, 2048, 10);
flag = StartupKTask(task_CH438_read);
if (flag != EOK) {
KPrintf("StartupKTask task_CH438_read failed .\n");
return ;
}
int32 task_CH438_write = KTaskCreate("task_CH438_write", Ch438Write, NONE, 2048, 10);
flag = StartupKTask(task_CH438_write);
if (flag != EOK) {
KPrintf("StartupKTask task_CH438_write failed .\n");
return ;
}
}
void TestCh438(void)
{
TestCh438Init();
MdelayKTask(500);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
TestCh438, TestCh438, TestCh438 );

View File

@@ -0,0 +1,160 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file TestCirculararea.c
* @brief support to test circular area function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <device.h>
#include <string.h>
#ifdef KERNEL_CIRCULAR_AREA
#define READ_LENGTH 2
#define Write_LENGTH 3
#define CIRCULARAREA_LENGTH 8
static struct CircularArea *g_circular_area;
static int8 test_string[] = "Aiit-XiuOs";
static int32 task_caread;
static int32 task_cawrite;
int data_lock = -1;
static void CircularArea_ReadTsk_Entry(void *parameter)
{
uint8 i;
uint8 read_string[8] = {0};
uint8 read_cnt = 0;
while(read_cnt < 30)
{
KMutexObtain(data_lock, WAITING_FOREVER);
if(EOK == g_circular_area->CircularAreaOperations->read(g_circular_area, read_string, READ_LENGTH)){
for(i = 0; i < READ_LENGTH; i ++){
KPrintf("Read data i %u ch %c rdidx %u wridx %u\n", i, read_string[i], g_circular_area->readidx, g_circular_area->writeidx);
}
#ifdef Test_Dbg
KPrintf("Read TSK writeidx %u readidx %u status %u len %u\n",
g_circular_area->writeidx,
g_circular_area->readidx,
g_circular_area->b_status,
CircularAreaGetDataLength(g_circular_area));
#endif
}
read_cnt++;
MdelayKTask(500);
KMutexAbandon(data_lock);
}
KMutexDelete(data_lock);
KTaskDelete(task_caread);
g_circular_area->CircularAreaOperations->release(g_circular_area);
}
static void CircularAreaWriteTskEntry(void *parameter)
{
uint8 i;
uint8 write_cnt = 0;
uint8 string_length = strlen(test_string);
static uint32 single_write_length = 0;
while(write_cnt < 30)
{
KMutexObtain(data_lock, WAITING_FOREVER);
uint8 write_string[CIRCULARAREA_LENGTH] = {0};
if((write_cnt % string_length + Write_LENGTH) > string_length){
memcpy(write_string, &test_string[write_cnt % string_length], string_length - write_cnt % string_length);
memcpy(&write_string[string_length - write_cnt % string_length], test_string, Write_LENGTH - string_length + write_cnt % string_length);
}
else{
memcpy(write_string, &test_string[write_cnt % string_length], Write_LENGTH);
}
if(EOK == g_circular_area->CircularAreaOperations->write(g_circular_area, write_string, Write_LENGTH, 0))
{
for(i = 0; i < Write_LENGTH; i ++) {
KPrintf("Write data i %d ch %c rdidx %u wridx %u\n", i, write_string[i], g_circular_area->readidx, g_circular_area->writeidx);
}
write_cnt += (g_circular_area->writeidx - single_write_length + CIRCULARAREA_LENGTH) % CIRCULARAREA_LENGTH;
single_write_length = g_circular_area->writeidx;
}
#ifdef Test_Dbg
KPrintf("Write TSK writeidx %u readidx %u status %u len %u\n",
g_circular_area->writeidx,
g_circular_area->readidx,
g_circular_area->b_status,
CircularAreaGetDataLength(g_circular_area));
#endif
MdelayKTask(500);
KMutexAbandon(data_lock);
}
KTaskDelete(task_cawrite);
}
static uint32 TestCirculararea(void)
{
x_err_t flag;
g_circular_area = CircularAreaInit(CIRCULARAREA_LENGTH);
if(g_circular_area){
KPrintf("CircularAreaInit done buffer 0x%8p length %u phead 0x%8p ptail 0x%8p wridx %u rdidx %u\n",
g_circular_area->data_buffer, g_circular_area->area_length,
g_circular_area->p_head, g_circular_area->p_tail,
g_circular_area->writeidx, g_circular_area->readidx);
}
else{
KPrintf("CircularAreaInit failed!Just return\n");
CircularAreaRelease(g_circular_area);
return ERROR;
}
data_lock = KMutexCreate();
if (data_lock < 0){
KPrintf("data_lock creat failed.\n");
g_circular_area->CircularAreaOperations->release(g_circular_area);
return ERROR;
}
task_caread = KTaskCreate("task_caread", CircularArea_ReadTsk_Entry, NONE, 2048, 10);
flag = StartupKTask(task_caread);
if (EOK != flag){
KPrintf("CircularArea_Test StartupKTask task_caread failed!\n");
g_circular_area->CircularAreaOperations->release(g_circular_area);
return ERROR;
}
task_cawrite = KTaskCreate("task_cawrite", CircularAreaWriteTskEntry, NONE, 2048, 10);
flag = StartupKTask(task_cawrite);
if (EOK != flag){
KPrintf("CircularArea_Test StartupKTask task_cawrite failed!\n");
g_circular_area->CircularAreaOperations->release(g_circular_area);
return ERROR;
}
return EOK;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),
TestCirculararea, TestCirculararea, Test the Circular Area Function);
#endif

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file TestDbg.c
* @brief support to test dbg function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#define KDBG_TEST1 1
#define KDBG_TEST2 0
static uint32 TestDbg(void)
{
x_err_t flag;
SYS_WARN("TestDbg function 1!\n");
SYS_ERR("TestDbg function 2!\n");
DBG("TestDbg function 3!\n");
SYS_KDEBUG_LOG(KDBG_TEST1, ("TestDbg kernel function 1!\n"));
SYS_KDEBUG_LOG(KDBG_TEST2, ("TestDbg kernel function 2!\n"));
return EOK;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),
TestDbg, TestDbg, Test the log debug Function);

View File

@@ -0,0 +1,570 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file test_gatherblock.c
* @brief support to test gather block function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <string.h>
extern long ShowMemPool(void);
extern void ShowMemory(void);
extern void ListBuddy(void);
/**************************single gatherblock test sample***********************************/
static uint8 *ptr[30];
static uint8 mempool[2048];
static struct MemGather gm;
static GatherMemType gm_d;
#define TASK_PRIORITY 25
#define TASK_STACK_SIZE 2048
#define TASK_TIMESLICE 5
/* thread control pointer */
static int32 tid1;
static int32 tid2;
/* task1 entry */
static void Task1GmAlloc(void *parameter)
{
int i;
for (i = 0 ; i < 30 ; i++){
if (ptr[i] == NONE){
/* alloc memory blocks for 50 times, if failed, suspend task1 and start task2 */
if (0 == strncmp("static", parameter, strlen("static"))){
ptr[i] = AllocBlockMemGather(&gm, WAITING_FOREVER);
if (ptr[i] != NONE)
KPrintf("task1: allocate No.%d from static gatherblock\n", i);
}
else{
ptr[i] = AllocBlockMemGather(gm_d, WAITING_FOREVER);
if (ptr[i] != NONE)
KPrintf("task1: allocate No.%d from dynamic gatherblock\n", i);
}
}
}
}
/* task2 entry, its priority is lower than task1 */
static void Task2GmRelease(void *parameter)
{
int i;
KPrintf("task2 try to release block\n");
for (i = 0; i < 30 ; i++){
DelayKTask(10);
/* release all memory blocks */
if (ptr[i] != NONE){
KPrintf("release block %d\n", i);
FreeBlockMemGather(ptr[i]);
ptr[i] = NONE;
}
}
if (0 == strncmp("static", parameter, strlen("static"))) {
KPrintf("**************** detach gatherblock test *****************\n");
RemoveMemGather(&gm);
} else {
KPrintf("**************** delete gatherblock test *****************\n");
DeleteMemGather(gm_d);
}
}
int SingleGatherblockTest(char * parameter)
{
int i;
for (i = 0; i < 30; i ++) ptr[i] = NONE;
/* init memory blocks object */
if(0 == strncmp("static", parameter, strlen("static"))){
KPrintf("test static create gatherblock.\n");
InitMemGather(&gm, "mp_s", &mempool[0], sizeof(mempool), 80);
ShowMemPool();
}
if(0 == strncmp("dynamic", parameter, strlen("dynamic"))){
KPrintf("test dynamic create gatherblock.\n");
//FreeBlockMemGather(&mp, "mp1", &mempool[0], sizeof(mempool), 80);
gm_d = CreateMemGather("mp_d",20,80);
if(gm_d == NONE){
KPrintf("%s: allocate failure.\n",__func__);
return -1;
}
ShowMemPool();
}
/* create task1, alloc memory blocks */
tid1 = KTaskCreate("task1", Task1GmAlloc, parameter,
TASK_STACK_SIZE,
TASK_PRIORITY);
if (tid1 >= 0){
KPrintf("single test: task1 startup.\n");
StartupKTask(tid1);
}
/* create task2, release memory blocks */
tid2 = KTaskCreate("task2", Task2GmRelease, parameter,
TASK_STACK_SIZE,
TASK_PRIORITY + 1);
if (tid2 >= 0){
StartupKTask(tid2);
}
else{
KPrintf("create task2 for release failure.\n");
}
return 0;
}
/**************************************************************************************/
/**********************mutiple gatherblock test sample**************************************/
struct MemGather s_gm1;
struct MemGather *d_gm1 = NONE;
static uint8 mempool_gm1[1024];
#define MAX_SIZE 11
#define TASK_PRIORITY 25
#define TASK_STACK_SIZE 2048
#define TASK_TIMESLICE 5
/* thread control pointer */
static int32 m_tid1 = NONE;
static int32 m_tid2 = NONE;
static uint8 *multiple_s_ptr[20];
static uint8 *multiple_d_ptr[20];
void Task1AllocEntry(void *parameter){
int index = 0;
for(int i=0;i<20;i++){
multiple_s_ptr[i] = AllocBlockMemGather(&s_gm1, WAITING_FOREVER);
if(multiple_s_ptr[i] != NONE){
KPrintf("task1: allocate No.%d from static\n", i);
}
multiple_d_ptr[i] = AllocBlockMemGather(d_gm1, WAITING_FOREVER);
if (ptr[i] != NONE)
KPrintf("task1: allocate No.%d from dynamic\n", i);
}
}
void Task2FreeEntry(void *parameter){
DelayKTask(100);
for(int i=0;i<20;i++){
DelayKTask(10);
if(multiple_s_ptr[i]){
FreeBlockMemGather(multiple_s_ptr[i]);
KPrintf("task2: free No.%d of static\n", i);
}
DelayKTask(10);
if(multiple_d_ptr[i]){
FreeBlockMemGather(multiple_d_ptr[i]);
KPrintf("task2: free No.%d of dynamic\n", i);
}
}
KPrintf("**************** detach gatherblock test *****************\n");
RemoveMemGather(&s_gm1);
KPrintf("**************** delete gatherblock test *****************\n");
DeleteMemGather(d_gm1);
}
int MultipleGatherblockTest(void)
{
KPrintf("****************mutiple gatherblock test start*****************\n");
for(int i=0;i<20;i++){
multiple_s_ptr[i] = NONE;
multiple_d_ptr[i] = NONE;
}
InitMemGather(&s_gm1, "m_gm_s1", &mempool_gm1[0], sizeof(mempool_gm1), 80);
d_gm1 = CreateMemGather("m_gm_d1", MAX_SIZE, 80);
if (mempool_gm1 == NONE){
KPrintf("create m_gm_d2 failed.");
CHECK(0);
}
ShowMemPool();
/* create task1, alloc memory blocks */
m_tid1 = KTaskCreate("task1_m", Task1AllocEntry, NONE,
TASK_STACK_SIZE,
TASK_PRIORITY);
if (m_tid1 >= 0){
StartupKTask(m_tid1);
}
/* create task2, release memory blocks */
m_tid2 = KTaskCreate("task2_m", Task2FreeEntry, NONE,
TASK_STACK_SIZE,
TASK_PRIORITY + 1);
if (m_tid2 >= 0){
StartupKTask(m_tid2);
}
else{
KPrintf("create task2 for release failure.\n");
}
return 0;
}
/**************************************************************************************/
/* thread control pointer */
static int32 l_tid1 = NONE;
static int32 l_tid2 = NONE;
struct MemGather *gm_l = NONE;
void *l_ptr[50];
void LTask1AllocEntry(void *parameter){
int index = 0;
for(int i=0;i<50;i++){
l_ptr[i] = AllocBlockMemGather(gm_l, WAITING_FOREVER);
if(l_ptr[i] != NONE){
KPrintf("l_task1: allocate No.%d\n", i);
}
}
}
void LTask2FreeEntry(void *parameter){
DelayKTask(100);
for(int i=0;i<50;i++){
DelayKTask(10);
if(l_ptr[i]){
FreeBlockMemGather(l_ptr[i]);
KPrintf("l_task2: free No.%d\n", i);
}
}
KPrintf("**************** delete gatherblock test *****************\n");
DeleteMemGather(gm_l);
}
void GatherblockLimitTest(char *name, int count, int blocksize){
gm_l = CreateMemGather(name, count, blocksize);
if(gm_l == NONE){
KPrintf("no memory.\n");
return;
}
ListBuddy();
/* create task1, alloc memory blocks */
l_tid1 = KTaskCreate("task1_l", LTask1AllocEntry, NONE,
TASK_STACK_SIZE,
TASK_PRIORITY);
if (l_tid1 >= 0){
StartupKTask(l_tid1);
}
/* create task2, release memory blocks */
l_tid2 = KTaskCreate("task2_l", LTask2FreeEntry, NONE,
TASK_STACK_SIZE,
TASK_PRIORITY + 1);
if (l_tid2 >= 0){
StartupKTask(l_tid2);
}
}
#ifdef ARCH_ARM
#define CACHE_COUNT 1024
#else
#define CACHE_COUNT 8000
#endif
struct MemGather *pools[CACHE_COUNT];
void GatherblockLimitcountTest(char *name, int count, int blocksize, int poolcount){
if(poolcount>CACHE_COUNT || poolcount<=0){
KPrintf("type the poolcount between 0-%d\n",CACHE_COUNT);
return;
}
int index;
for(index=0;index < poolcount;index++){
pools[index] = CreateMemGather(name, count, blocksize);
if(pools[index] == NONE){
KPrintf("gatherblock allocation failure,count[%d],size[%d]\n", count, blocksize);
break;
}
KPrintf("gatherblock allocation,count[%d],size[%d]\n", count, blocksize);
}
ListBuddy();
index--;
for(;index>=0;index--){
DeleteMemGather(pools[index]);
}
}
/*****************************************************************/
static int32 traverse_tid = NONE;
static struct MemGather *traverse_gm = NONE;
void TraverseGmEntry(void *parameter){
int count,size;
int limit_count, limit_size;
for(count =1; count <= 30; count++){
for(size = 1; ;size++){
traverse_gm = CreateMemGather("hello",count,size);
if( traverse_gm == NONE ){
KPrintf("gatherblock allocation failure,count[%d],size[%d]\n", count, size);
if(count == 1)
limit_size = size;
break;
}else{
DeleteMemGather(traverse_gm);
}
}
if(size ==1){
limit_count = count;
break;
}
}
KPrintf("\n\n--------------------------- bound -----------------------------\n\n");
KPrintf("\n\n--------------------------- over end -----------------------------\n\n");
}
#define TRAVERSE_TASK_PRIORITY 5
void TraverseGmTest(){
traverse_tid = KTaskCreate("traverse_task", TraverseGmEntry, NONE,
TASK_STACK_SIZE ,
TRAVERSE_TASK_PRIORITY);
if(traverse_tid >= 0){
StartupKTask(traverse_tid);
}else{
KPrintf("Fail.\n");
}
}
/********************************************************************/
/***************************test random read and write **************/
static uint8 *random_ptr[50];
static struct MemGather random_static_gm;
static GatherMemType random_dynamic_gm;
static uint8 dynamic_mempool[2048];
/* thread control pointer */
static int32 random_tid1 = NONE;
static int32 random_tid2 = NONE;
/* task1 entry */
int time_seed = 1;
char temp_parameter[40];
static void RandomTask1GmAlloc(void *parameter)
{
int i;
int total=0;
time_seed++;
srand(time_seed);
char string[10];
while(total<40){
i = rand()%40;
if (random_ptr[i] == NONE){
/* alloc memory blocks for 50 times, if failed, suspend task1 and start task2 */
if (0 == strncmp("static", temp_parameter, strlen("static"))){
random_ptr[i] = AllocBlockMemGather(&random_static_gm, WAITING_FOREVER);
if (random_ptr[i] != NONE){
itoa(i,string,10);
memcpy(random_ptr[i],string,sizeof(string));
KPrintf("%s No.%d: %s\n",temp_parameter, i, random_ptr[i]);
}
}else{
random_ptr[i] = AllocBlockMemGather(random_dynamic_gm, WAITING_FOREVER);
if (random_ptr[i] != NONE){
itoa(i,string,10);
memcpy(random_ptr[i],string,sizeof(string));
KPrintf("%s No.%d: %s\n", temp_parameter, i, random_ptr[i]);
}
}
total++;
}
}
}
/* task2 entry, its priority is lower than task1 */
static void RandomTask2GmRelease(void *parameter)
{
int i;
time_seed++;
srand(time_seed);
int total = 0;
while(total<40){
i = rand()%40;
/* release all memory blocks */
if (random_ptr[i] != NONE){
DelayKTask(10);
KPrintf("release block %d: %s\n",i, random_ptr[i]);
FreeBlockMemGather(random_ptr[i]);
random_ptr[i] = NONE;
total++;
}
}
if (0 == strncmp("static", temp_parameter, strlen("static"))) {
KPrintf("**************** detach gatherblock test *****************\n");
RemoveMemGather(&random_static_gm);
} else {
KPrintf("**************** delete gatherblock test *****************\n");
DeleteMemGather(random_dynamic_gm);
}
}
int RandomAllocFreeTest(void *parameter)
{
int i;
for (i = 0; i < 40; i ++) random_ptr[i] = NONE;
memcpy(temp_parameter,parameter, 10);
/* init memory block object */
if(0 == strncmp("static", parameter, strlen("static"))){
KPrintf("test static create gatherblock-%s.\n",parameter);
InitMemGather(&random_static_gm, "ran_mp_s", &dynamic_mempool[0], sizeof(dynamic_mempool), 80);
ShowMemPool();
}else{
KPrintf("test dynamic create gatherblock.\n");
random_dynamic_gm = CreateMemGather("ran_mp_d",40,80);
if(random_dynamic_gm == NONE){
KPrintf("%s: allocate failure.\n",__func__);
return -1;
}
ShowMemPool();
}
/* create task1, alloc memory blocks */
random_tid1 = KTaskCreate("r_task1", RandomTask1GmAlloc, parameter,
TASK_STACK_SIZE,
TASK_PRIORITY);
if (random_tid1 >= 0){
StartupKTask(random_tid1);
}
/* create task2, release memory blocks */
random_tid2 = KTaskCreate("r_task2", RandomTask2GmRelease, parameter,
TASK_STACK_SIZE,
TASK_PRIORITY + 1);
if (random_tid2 >= 0){
StartupKTask(random_tid2);
}
else{
KPrintf("create task2 for release failure.\n");
}
return 0;
}
/********************************************************************/
void TestGatherblockUsage(void)
{
KPrintf("TestGatherblockUsage.\n");
KPrintf("test_main gm -a --static, dynamic and multiple test.\n");
KPrintf("test_main gm -s static/dynamic --test static create gatherblock to allocate and free.\n");
KPrintf("test_main gm -m --test multiple gatherblock to allocate and free.\n");
KPrintf("test_main gm count_size [count] [size] --create a gatherblock with typed count and size "
"to allocate and free.\n");
KPrintf("test_main gm multiple_gms [count] [size] [gm_ns] --create multiple gatherblocks with typed count and \n");
KPrintf(" size to allocate and free.\n");
KPrintf("test_main gm traverse --traverse.\n");
KPrintf("test_main gm -r static/dynamic --random allocate and free.\n");
}
int TestGatherblock(char *argv[])
{
int ret = 0;
if (NONE == argv || 0 == strncmp("-h", argv[0], strlen("-h")) || 0 == strncmp("usage", argv[0], strlen("usage"))) {
TestGatherblockUsage();
return -EINVALED;
}
/**************** gatherblock auto test ******************/
if (0 == strncmp("-a", argv[0], strlen("-a"))) {
ret = SingleGatherblockTest("static"); ///< static creat single gatherblock test
MdelayKTask(7000);
ret |= SingleGatherblockTest("dynamic"); ///< dynamic creat single gatherblock test
MdelayKTask(7000);
ret |= MultipleGatherblockTest();
MdelayKTask(7000);
ret |= RandomAllocFreeTest("static");
MdelayKTask(7000);
ret |= RandomAllocFreeTest("dynamic");
goto out;
}
/**************** single gatherblock test ****************/
if (0 == strncmp("-s",argv[0],strlen("-s")) ) {
if (0 == strncmp("static",argv[1],strlen("static"))) {
ret = SingleGatherblockTest("static"); ///< static creat single gatherblock test
} else {
ret = SingleGatherblockTest("dynamic"); ///< dynamic creat single gatherblock test
}
goto out;
}
/**************** mutiple gatherblock test ****************/
if (0 == strncmp("-m",argv[0],strlen("-m")) ) {
ret = MultipleGatherblockTest();
goto out;
}
/******************** limitation test **********************/
if (0 == strncmp("count_size",argv[0],strlen("count_size")) ) {
int size = atoi(argv[2]);
int count = atoi(argv[1]);
GatherblockLimitTest("xsos",count,size);
ret = 1;
goto out;
}
/******************** limitation test **********************/
if (0 == strncmp("multiple_gms",argv[0],strlen("multiple_gms")) ) {
int size = atoi(argv[2]);
int count = atoi(argv[1]);
int poolnumber = atoi(argv[3]);
GatherblockLimitcountTest("xsos",count,size,poolnumber);
ret = 1;
goto out;
}
/********************** traverse test **********************/
if (0 == strncmp("traverse",argv[0],strlen("traverse")) ) {
TraverseGmTest();
goto out;
}
/**************** random alloc and free test ****************/
if (0 == strncmp("-r",argv[0],strlen("-r")) ) {
ret = RandomAllocFreeTest(argv[1]);
goto out;
}
out:
if (ret < 0) {
KPrintf("test gatherblock failed ret = %d.\n",ret);
return -ERROR;
}
return 0;
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file test_hwtimer.c
* @brief support to test hwtimer function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <bus.h>
#include <xsconfig.h>
#include <dev_hwtimer.h>
#if defined (ARCH_ARM)
#define HWTIMER_BUS_NAME HWTIMER_BUS_NAME_2
#define HWTIMER_DEVICE_NAME HWTIMER_2_DEVICE_NAME_2
#elif defined (ARCH_RISCV)
#define HWTIMER_BUS_NAME HWTIMER_BUS_NAME_1
#define HWTIMER_DEVICE_NAME HWTIMER_1_DEVICE_NAME_1
#elif
#define HWTIMER_BUS_NAME
#define HWTIMER_DEVICE_NAME
#endif
void TimeoutCb(void* param){
KPrintf("resource_sample callback come ... \n");
}
void HwtimerSample(void)//int argc, char *argv[]
{
struct Bus * hwtimer_bus = BusFind(HWTIMER_BUS_NAME);
if (NULL == hwtimer_bus){
KPrintf("hwtimer bus find failed !\n");
return ;
}
struct HardwareDev* dev = BusFindDevice(hwtimer_bus, HWTIMER_DEVICE_NAME);
struct HwtimerHardwareDevice* hwtimer_dev = (struct HwtimerHardwareDevice*)dev;
if (NULL == hwtimer_dev){
KPrintf("hwtimer hwtimer_dev find failed !\n");
return ;
}
hwtimer_dev->hwtimer_param.repeat = 1;
hwtimer_dev->hwtimer_param.period_millisecond = 3000;
hwtimer_dev->hwtimer_param.cb_info.param = NULL;
hwtimer_dev->hwtimer_param.cb_info.TimeoutCb = TimeoutCb;
BusDevOpen(dev);
MdelayKTask(20000);
KPrintf("close hwtimer...\n");
BusDevClose(dev);
}
/* export to shell cmd */
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_DISABLE_RETURN|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
HwtimerSample, HwtimerSample, HwtimerSample );

View File

@@ -0,0 +1,178 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file test_i2c.c
* @brief support to test i2c function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <device.h>
#include <bus.h>
/*********************************************************************************************************************************************************/
/*
* functionI2C device sample support reading temperature and humidity sensor data and printfing on the terminal
* shell cmdi2c_HS3000_sample i2c1
* shell cmd parami2c device name,if null means default i2c device name
*/
#define HS_I2C_BUS_NAME I2C_BUS_NAME_1 /* I2C bus name */
#define HS_I2C_DEV_NAME I2C_1_DEVICE_NAME_0/* I2C device name */
#define HS_I2C_DRV_NAME I2C_DRV_NAME_1 /* I2C driver name */
#define ADDR 0x44 /* slave address */
static struct Bus *i2c_bus = NONE; /* I2C bus handle */
typedef struct Hs300xData
{
int humi_high;
int humi_low;
int temp_high;
int temp_low;
}Hs300xDataType;
Hs300xDataType g_hs300x_data;
static x_err_t WriteReg(struct HardwareDev *dev)
{
struct BusBlockWriteParam write_param;
/* use I2C device API transfer data */
if(1 == BusDevWriteData(dev, &write_param)) {
return EOK;
}
else{
return -ERROR;
}
}
/* read sensor register data */
static x_err_t ReadRegs(struct HardwareDev *dev, uint8 len, uint8 *buf)
{
struct BusBlockReadParam read_param;
read_param.buffer = (void *)buf;
read_param.size = len;
/* use I2C device API transfer data */
if(1 == BusDevReadData(dev, &read_param)){
return EOK;
}
else{
return -ERROR;
}
}
static void read_temp_humi(float *cur_temp, float *cur_humi)
{
uint8 temp[4],ret=0;
MdelayKTask(15);
ret = WriteReg(i2c_bus->owner_haldev); //reset
if(EOK != ret){
KPrintf("read_temp_humi WriteReg failed!\n");
}
MdelayKTask(50);
ret = ReadRegs(i2c_bus->owner_haldev, 4, temp); /* get sensor data */
if(EOK != ret){
KPrintf("read_temp_humi ReadRegs failed\n");
}
*cur_humi = ((temp[0] <<8 | temp[1] )& 0x3fff ) * 100.0 / ( (1 << 14) - 1); /* humidity data */
*cur_temp = ((temp[2] << 8 | temp[3]) >> 2) * 165.0 /( (1 << 14) - 1) - 40.0; /* temperature data */
}
static void _HS3000Init(const char *bus_name, const char *dev_name, const char *drv_name)
{
/* find I2C device and get I2C handle */
i2c_bus = BusFind(bus_name);
if (NONE == i2c_bus){
KPrintf("_HS3000Init can't find %s bus!\n", bus_name);
}
else{
KPrintf("_HS3000Init find %s bus!\n", bus_name);
}
i2c_bus->owner_haldev = BusFindDevice(i2c_bus, dev_name);
i2c_bus->owner_driver = BusFindDriver(i2c_bus, drv_name);
if(i2c_bus->match(i2c_bus->owner_driver, i2c_bus->owner_haldev)){
KPrintf("i2c match drv %s %p dev %s %p error\n", drv_name, i2c_bus->owner_driver, dev_name, i2c_bus->owner_haldev);
}
else{
KPrintf("_HS3000Init successfully!write %p read %p\n",
i2c_bus->owner_haldev->dev_done->write,
i2c_bus->owner_haldev->dev_done->read);
}
}
void Hs300xInit(void)
{
_HS3000Init(HS_I2C_BUS_NAME, HS_I2C_DEV_NAME, HS_I2C_DRV_NAME); /* init sensor */
}
void Hs300xRead(Hs300xDataType *Hs300xDataType)
{
float humidity = 0.0, temperature = 0.0;
read_temp_humi(&temperature, &humidity); /* read temperature and humidity sensor data */
Hs300xDataType->humi_high = (int)humidity;
Hs300xDataType->humi_low = (int)(humidity*10)%10;
if( temperature >= 0 ) {
Hs300xDataType->temp_high = (int)temperature;
Hs300xDataType->temp_low = (int)(temperature*10)%10;
}
else{
Hs300xDataType->temp_high = (int)temperature;
Hs300xDataType->temp_low = (int)(-temperature*10)%10;
}
}
void Tsk_hs300x_test()
{
memset(&g_hs300x_data, 0, sizeof(Hs300xDataType));
KPrintf("Tsk create successfully!\n");
while(1)
{
Hs300xRead(&g_hs300x_data);
KPrintf("HS300X:I2C humidity:%d.%d temperature:%d.%d\n",
g_hs300x_data.humi_high,
g_hs300x_data.humi_low,
g_hs300x_data.temp_high,
g_hs300x_data.temp_low);
MdelayKTask(1000);
}
return;
}
void Hs300xI2cTest(void)
{
Hs300xInit();
MdelayKTask(1000);
x_err_t flag;
int32 Tsk_hs300x = KTaskCreate("Tsk_hs300x", Tsk_hs300x_test, NONE, 2048, 10);
flag = StartupKTask(Tsk_hs300x);
if (EOK != flag){
KPrintf("Hs300xI2cTest StartupKTask failed!\n");
return;
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),
Hs300xI2cTest, Hs300xI2cTest, Test the HS300X using I2C);

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file TestIwg.c
* @brief support to test watchdog function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <device.h>
static BusType wdt;
/**
* @description: Feed watchdog task function
*/
static void FeedWatchdog(void)
{
while (1)
{
/* keep watchdog alive in idle task */
struct BusConfigureInfo cfg;
cfg.configure_cmd = OPER_WDT_KEEPALIVE;
cfg.private_data = NONE;
BusDrvConfigure(wdt->owner_driver, &cfg);
KPrintf("feed the dog!\n ");
}
}
/**
* @description: Watchdog test function
* @return success: EOK, failure: other
*/
int TestIwg(void)
{
x_err_t res = EOK;
uint32 timeout = 1000; /* timeout time */
wdt = BusFind(WDT_BUS_NAME_0);
wdt->owner_driver = BusFindDriver(wdt, WDT_DRIVER_NAME_0);
wdt->owner_haldev = BusFindDevice(wdt, WDT_0_DEVICE_NAME_0);
/* set watchdog timeout time */
struct BusConfigureInfo cfg;
cfg.configure_cmd = OPER_WDT_SET_TIMEOUT;
cfg.private_data = &timeout;
res = BusDrvConfigure(wdt->owner_driver, &cfg);
KPrintf("feed the dog!\n");
int32 WdtTask = KTaskCreate("WdtTask", (void *)FeedWatchdog, NONE, 2048, 20);
res = StartupKTask(WdtTask);
return res;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),TestIwg, TestIwg, TestIwg );

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file EnableLcd.c
* @brief support to test lcd function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include "bus_lcd.h"
#include "dev_lcd.h"
uint16 color = RED;
char *addr ="LCD Testing ";
/**
* @description: Enable LCD function
* @param bus_name - LCD bus name
* @param driver_name - LCD driver name
* @param device_name - LCD device name
*/
int EnableLcd(const char *bus_name, const char *driver_name, const char *device_name)
{
struct Bus *bus;
struct Driver *driver, *bus_driver;
struct HardwareDev *device;
struct HardwareDev *bus_device;
if (bus_name) {
KPrintf("##test find bus %s\n", bus_name);
bus = BusFind(bus_name);
KPrintf("##test bus %p##\n", bus);
}
if (driver_name) {
KPrintf("##test find driver %s\n", driver_name);
driver = LcdDriverFind(driver_name, TYPE_LCD_DRV);
bus_driver = BusFindDriver(bus, driver_name);
KPrintf("##test driver %p bus_driver %p####\n", driver, bus_driver);
}
if (device_name) {
KPrintf("##test find device %s\n", device_name);
device = LcdDeviceFind(device_name, TYPE_LCD_DEV);
bus_device = BusFindDevice(bus, device_name);
KPrintf("##test device %p bus_device %p##\n", device, bus_device);
}
LcdStringParam str;
str.x_pos = 60 ;
str.y_pos = 40;
str.width = 250;
str.height = 24;
str.font_size = 24;
str.addr = addr;
str.font_color = WHITE;
str.back_color = RED;
struct BusBlockWriteParam write_param;
memset(&write_param,0,sizeof(struct BusBlockWriteParam ));
struct BusConfigureInfo pdata = {RED,NONE};
write_param.pos = 0;
write_param.buffer = &str ;
while (1) {
BusDrvConfigure(bus_driver, &pdata );
MdelayKTask(1000);
BusDevWriteData(device,&write_param);
MdelayKTask(1000);
}
}
/**
* @description: LCD test function
*/
void TestLcd(void)
{
EnableLcd(LCD_BUS_NAME_1,LCD_DRV_NAME_1,LCD_1_DEVICE_NAME_0);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),TestLcd, TestLcd, Test LCD );

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file TestMain.c
* @brief support to test function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <stdio.h>
#define MAX_ITEM_NAME_LENGTH 16
extern int TestIwg(void);
int TestTmrD(void);
int TestTmrM(void);
extern int TestTmr(int argc, char *argv[]);
extern int TestMem(int argc, char *argv[]);
extern int TestGatherblock(char *argv[]);
extern int TestTaskReadyAndSched(int argc, char *argv[]);
extern int TestRealtime(int argc, char * argv[]);
void KernelTestusage(void)
{
KPrintf("test usage.\n");
KPrintf("e.g., TestMain -mem\n");
}
struct TestSubitem
{
char name[MAX_ITEM_NAME_LENGTH];
int item;
};
enum TestItem
{
USAGE = 0, /* usage idex */
MEM, /* mem test item index */
TIMER, /* timer test item index */
GATHERBLOCK,
SCHED, /* task sched test */
IWG, /* iwg test item index */
REALTIME,
INVALID_ITEM, /* invalid index */
};
static struct TestSubitem kernel_subitem[INVALID_ITEM] =
{
{ "-h", USAGE },
{ "-mem", MEM },
{ "-timer", TIMER},
{ "-gm", GATHERBLOCK},
{ "-sched", SCHED},
{ "-iwg", IWG},
{ "-realtime", REALTIME},
};
int TestMain(int argc, char*argv[])
{
char name[MAX_ITEM_NAME_LENGTH] = {0};
int i = 0;
int item = -1;
strncpy(name, argv[1], MAX_ITEM_NAME_LENGTH); ///< getting input name of test item
for(i = 0; i < INVALID_ITEM; i++) {
if(0 == strncmp(kernel_subitem[i].name, name, MAX_ITEM_NAME_LENGTH) ){
item = kernel_subitem[i].item;
break;
}
}
switch(item)
{
case USAGE:
KernelTestusage();
break;
case MEM:
#ifdef KERNEL_TEST_MEM
TestMem(argc-2,&argv[2]);
#endif
break;
case TIMER:
#ifdef KERNEL_TEST_TIMER
TestTmr(argc-2,&argv[2]);
#endif
break;
case GATHERBLOCK:
#ifdef KERNEL_TEST_MEM
TestGatherblock(&argv[2]);
#endif
break;
case SCHED:
#ifdef KERNEL_TEST_SCHED
TestTaskReadyAndSched(argc-2, &argv[2]);
#endif
break;
case IWG:
#ifdef KERNEL_TEST_IWG
TestIwg();
#endif
case REALTIME:
#ifdef KERNEL_TEST_REALTIME
TestRealtime(argc-2, &argv[2]);
#endif
default:
break;
}
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_DISABLE_RETURN|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
TestMain, TestMain, test main sample );

View File

@@ -0,0 +1,451 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file TestMem.c
* @brief support to test mem function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <string.h>
extern void ShowMemory(void);
extern void ListBuddy(void);
/**************************test memory usage***********************************/
#include<time.h>
#include<stdlib.h>
#define TASK_PRIORITY 5
#define TASK_STACK_SIZE 4096
#define TASK_TIMESLICE 5
#define MEM_TEST_NUMBER 23
int number_imm=0;
static int arr[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22};
void Fimm(void *parameter)
{
KPrintf("%s: task starts.\n",__func__);
int i=0;
unsigned long size;
char *ptr = NONE;
srand(number_imm);
while (i<50) {
size = 1 << arr[rand() % MEM_TEST_NUMBER];
ptr = x_malloc(size);
if (ptr != NULL) {
KPrintf("alloc-memory: %d btye\n",size);
x_free(ptr);
KPrintf("free--memory: %d byte\n",size);
ptr=NONE;
} else {
KPrintf("try to get %d byte memory failed!\n",size);
return;
}
i++;
}
number_imm++;
}
int FreeImmediatelly(void){
KPrintf("\033[32;1m***********test limitations*************\033[0m\n");
KPrintf("allocation and free pointer immdiatetely. \n");
int32 tid;
tid = KTaskCreate("Fimm",Fimm,NONE,TASK_STACK_SIZE,TASK_PRIORITY);
if (tid >= 0)
StartupKTask(tid);
return 0;
}
static int num_FTillEnd=1;
void FTillEnd(void *parameter)
{
int i=0;
unsigned long size;
char *ptr[55];
unsigned long arrsize[55];
// srand((unsigned)time(NULL)*10);
srand(num_FTillEnd);
num_FTillEnd++;
while (i<50) {
size = 1 << arr[rand() % MEM_TEST_NUMBER];
ptr[i] = x_malloc(size);
arrsize[i]=size;
if (ptr[i] != NULL) {
KPrintf("get memory: %d btye\n",size);
} else {
KPrintf("try to get %d byte memory failed!\n",size);
break;
}
i++;
}
i -= 1;
for( ; i>=0 ; i-- ) {
x_free(ptr[i]);
KPrintf("free memory: %d byte\n",arrsize[i]);
}
return;
}
int FreeEnd(void)
{
KPrintf("\033[32;1m***********test limitations*************\033[0m\n");
KPrintf("-------allocation until no memory-------\n");
int32 tid;
tid = KTaskCreate("fend",FTillEnd,NONE,TASK_STACK_SIZE,TASK_PRIORITY);
if (tid >= 0)
StartupKTask(tid);
return 0;
}
#ifdef ARCH_ARM
#define MEM_GRIN_COUNT 1024
#else
#define MEM_GRIN_COUNT 8000
#endif
char *ptr[MEM_GRIN_COUNT];
unsigned int arr_grin[MEM_GRIN_COUNT];
extern void ListBuddy();
int FendGrin()
{
KPrintf("\033[32;1m***********test limitations*************\033[0m\n");
KPrintf("-------allocation for 1 byte with step 1-------\n");
int i=0;
int tempvalue = 1;
while( i< MEM_GRIN_COUNT) {
KPrintf("\033[32;1malloc memory [%d]\033[0m\n",tempvalue);
ptr[i] = x_malloc(tempvalue);
if (ptr[i]) {
arr_grin[i] = tempvalue;
i++;
tempvalue++;
} else {
if (tempvalue == 60)
break;
tempvalue=60;
}
}
KPrintf("------------- limitation until [%d] -----------\n",i);
ListBuddy();
DelayKTask(2000);
i -= 1;
for ( ; i>=0 ; i-- ) {
x_free(ptr[i]);
KPrintf("free memory: %d byte\n",arr_grin[i]);
}
return 0;
}
#ifdef ARCH_ARM
#define MEM_CACHE_COUNT 1024
#else
#define MEM_CACHE_COUNT 8000
#endif
char *cache_ptr[MEM_CACHE_COUNT];
void TestCacheLimitation(int timers,int init)
{
KPrintf("\033[32;1m******test small memory limit****\033[0m\n");
int temp = init;
int index;
void *temp_ptr;
timers = timers > MEM_CACHE_COUNT? MEM_CACHE_COUNT: timers;
for (index = 1; index <= timers;index++) {
if (index&1) {
KPrintf("%d: x_malloc size [%d]. \n", index, temp);
cache_ptr[index] = x_malloc(temp);
} else {
KPrintf("%d: x_calloc size [%d]. \n", index, temp);
cache_ptr[index] = x_calloc(1,temp);
}
if (cache_ptr[index] == NONE) {
KPrintf("%d: malloc or calloc failure. \n", index);
break;
}
if ((index % 4) == 0) {
KPrintf("%d: x_realloc size [%d]. \n", index, temp+index);
temp_ptr = cache_ptr[index];
cache_ptr[index] = x_realloc(cache_ptr[index], temp+index);
if (cache_ptr[index] == NONE) {
KPrintf("%d: x_realloc failure, roll back old pointer. \n", index);
cache_ptr[index] = temp_ptr;
}
}
temp++;
temp %= 64;
temp = ((temp==0) ? (temp + 1) : temp);
}
ListBuddy();
DelayKTask(1000);
index--;
for(; index > 0; index--){
//KPrintf("free %d\n",index);
x_free(cache_ptr[index]);
}
}
void UsageMem()
{
KPrintf("%s: invalidate parameter\n",__func__);
KPrintf("%s: usage for memory \n",__func__);
KPrintf("%s: -s, test malloc allocation, e.g., test_main mem -s 64 \n",__func__);
KPrintf("%s: -c, test calloc allocation, e.g., test_main mem -c 64 \n",__func__);
KPrintf("%s: -r, test realloc allocation, e.g., test_main mem -r 64 80 \n",__func__);
KPrintf("%s: -Fimm, test limit allocation, e.g., test_main mem -Fimm \n",__func__);
KPrintf("%s: -fend, test limit allocation, e.g., test_main mem -fend \n",__func__);
KPrintf("%s: -grin, test limit allocation, e.g., test_main mem -grin \n",__func__);
KPrintf("%s: rw, test read and write opts, e.g., test_main mem rw 100 \"oldcontent\" \"newcontent\"\n",__func__);
KPrintf("%s: cache, test limit allocation, e.g., test_main mem cache 100 1,\n",__func__);
KPrintf("%s: allocate small mem for 100 timers started from 1. \n",__func__);
KPrintf("%s: exception, make exception, e.g., test_main mem exception 100\n",__func__);
}
void TestMalloc(x_size_t size)
{
KPrintf("\033[32;1m**********x_malloc & x_free***********\033[0m\n");
KPrintf("the memory size is [%u] for allocation. \n", size);
KPrintf("-------------before x_malloc-----------\n");
ShowMemory();
void *ptr = x_malloc(size);
if (ptr) {
KPrintf("----------x_malloc successfully--------\n");
ShowMemory();
x_free(ptr);
KPrintf("-----------x_free successfully---------\n");
ShowMemory();
} else {
KPrintf("------------x_malloc failure-----------\n");
}
KPrintf("****************** end *****************\n");
}
void TestReAlloc(x_size_t size_prev, x_size_t size_next)
{
KPrintf("\033[32;1m**********x_realloc & x_free**********\033[0m\n");
KPrintf("the memory size is [%u] for x_malloc. \n", size_prev);
KPrintf("-------------before x_malloc-----------\n");
ShowMemory();
void *ptr = x_malloc(size_prev);
void *ptr2;
if (ptr) {
KPrintf("---------x_malloc successfully--------\n");
ShowMemory();
KPrintf("-----------before x_realloc-----------\n");
KPrintf("the memory size is [%u] for x_malloc. \n", size_next);
ptr2 = x_realloc(ptr, size_next);
if (ptr2) {
KPrintf("-----------realloc successfully---------\n");
ShowMemory();
x_free(ptr2);
KPrintf("-----------x_free successfully---------\n");
ShowMemory();
} else {
KPrintf("-----------x_realloc failure-----------\n");
if(size_next !=0)
x_free(ptr);
KPrintf("-----------x_free successfully---------\n");
ShowMemory();
}
} else {
KPrintf("-----------x_malloc failure------------\n");
}
KPrintf("****************** end *****************\n");
}
void TestCalloc(x_size_t size)
{
KPrintf("\033[32;1m**********x_calloc & x_free***********\033[0m\n");
KPrintf("the memory size is [%u] for x_malloc. \n", size);
KPrintf("------------before x_calloc------------\n");
ShowMemory();
void*ptr = x_calloc(1, size);
if (ptr) {
KPrintf("---------x_calloc successfully---------\n");
ShowMemory();
x_free(ptr);
KPrintf("----------x_free successfully----------\n");
ShowMemory();
} else {
KPrintf("------------x_calloc failure-----------\n");
}
KPrintf("****************** end *****************\n");
}
void TestReadWrite(x_size_t size, char *raw_content, char *new_content)
{
KPrintf("\033[32;1m**********read and write opts***********\033[0m\n");
KPrintf("the memory size is [%u] for allocation. \n", size);
KPrintf("-------------before x_malloc-----------\n");
int endposition;
void *ptr = x_malloc(size);
if (ptr) {
KPrintf("----------x_malloc successfully--------\n");
KPrintf("---------- show raw content --------\n");
memcpy(ptr,raw_content, size > strlen(raw_content) ? strlen(raw_content): size);
endposition = size > strlen(raw_content) ? strlen(raw_content): size;
*((char*)ptr + endposition) = 0;
KPrintf("raw content is [\033[41;1m%s\033[0m]\n",ptr);
KPrintf("----- write and show new content -----\n");
memcpy(ptr,new_content, size > strlen(new_content)? strlen(new_content): size);
endposition = size>strlen(new_content)? strlen(new_content): size;
*((char*)ptr + endposition) = 0;
DelayKTask(100);
KPrintf("new content is [\033[41;1m%s\033[0m]\n",ptr);
x_free(ptr);
KPrintf("-----------x_free successfully---------\n");
} else {
KPrintf("------------x_malloc failure-----------\n");
}
KPrintf("\n------------------ end -----------------\n\n");
ptr = x_calloc(1,size);
if (ptr) {
KPrintf("----------x_calloc successfully--------\n");
KPrintf("---------- show raw content --------\n");
memcpy(ptr,raw_content,size > strlen(raw_content) ? strlen(raw_content): size);
endposition = size > strlen(raw_content) ? strlen(raw_content): size;
*((char*)ptr + endposition) = 0;
KPrintf("raw content is [\033[41;1m%s\033[0m]\n",ptr);
KPrintf("----- write and show new content -----\n");
memcpy(ptr,new_content,size > strlen(new_content) ? strlen(new_content): size);
endposition = size > strlen(new_content) ? strlen(new_content): size;
*((char*)ptr + endposition)=0;
DelayKTask(100);
KPrintf("new content is [\033[41;1m%s\033[0m]\n",ptr);
x_free(ptr);
KPrintf("-----------x_free successfully---------\n");
} else {
KPrintf("------------x_calloc failure-----------\n");
}
KPrintf("****************** end *****************\n");
}
void TestException(x_size_t size)
{
KPrintf("\033[32;1m**********test make exception***********\033[0m\n");
KPrintf("the memory size is [%u] for allocation. \n", size);
void*ptr = x_malloc(size);
if (ptr == NONE) {
KPrintf("------------x_malloc failure-----------\n");
} else {
memset(ptr-8, 5, size+8);
x_free(ptr);
}
KPrintf("****************** end *****************\n");
}
int TestMem(int argc,char*argv[])
{
x_size_t size;
x_size_t newsize;
if (0 == strncmp("-h", argv[0], strlen("-h"))) {
UsageMem();
}
if (0 == strncmp("cache", argv[0], strlen("cache"))) {
if (argc == 2) {
size = atoi(argv[1]);
newsize =1;
}
if(argc == 3) {
size = atoi(argv[1]);
newsize = atoi(argv[2]);
newsize = newsize==0 ? 1: newsize;
}
TestCacheLimitation(size, newsize);
}
if (0 == strncmp("-s", argv[0], strlen("-s"))) {
size = atoi(argv[1]);
TestMalloc(size);
}
if (0 == strncmp("-r", argv[0], strlen("-r"))) {
size = atoi(argv[1]);
newsize = atoi(argv[2]);
TestReAlloc(size,newsize);
}
if (0 == strncmp("-c", argv[0], strlen("-c"))) {
size = atoi(argv[1]);
TestCalloc(size);
}
if (0 == strncmp("-Fimm", argv[0], strlen("-Fimm"))) {
FreeImmediatelly();
}
if (0 == strncmp("-fend", argv[0], strlen("-fend"))) {
FreeEnd();
}
if (0 == strncmp("-grin", argv[0], strlen("-grin"))) {
FendGrin();
}
if (0 == strncmp("rw", argv[0], strlen("rw"))) {
size = atoi(argv[1]);
TestReadWrite(size, argv[2], argv[3]);
}
if (0 == strncmp("exception",argv[0],strlen("exception"))) {
size = atoi(argv[1]);
TestException(size);
}
return 0;
}
/************************** end ***********************************/

View File

@@ -0,0 +1,351 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file TestRealtime.c
* @brief support to test realtime function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <string.h>
#include <dev_pin.h>
extern unsigned int usleep(unsigned int seconds);
static BusType pin;
#ifdef ARCH_ARM
#include <hardware_gpio.h>
#define GPIO_C13 7
#define GPIO_C2 17
void PinIrqIsr(void *args)
{
*(volatile unsigned int *)0x40020818 = 0x2000;
*(volatile unsigned int *)0x4002081a = 0x2000;
}
int RealtimeIrqTest()
{
struct PinParam testpin_1;
struct PinStat testpin_1_stat;
struct PinParam testpin_2;
int ret = 0;
struct BusConfigureInfo configure_info_1;
struct BusConfigureInfo configure_info_2;
struct BusBlockWriteParam write_param_1;
configure_info_1.configure_cmd = OPE_CFG;
configure_info_1.private_data = (void *)&testpin_1;
write_param_1.buffer = (void *)&testpin_1_stat;
configure_info_2.configure_cmd = OPE_CFG;
configure_info_2.private_data = (void *)&testpin_2;
KPrintf("%s irq test\n",__func__);
/* config test pin 1 as output*/
testpin_1.cmd = GPIO_CONFIG_MODE;
testpin_1.pin = GPIO_C13;
testpin_1.mode = GPIO_CFG_OUTPUT;
ret = BusDrvConfigure(pin->owner_driver, &configure_info_1);
if (ret != EOK) {
KPrintf("config testpin_1 %d failed!\n", GPIO_C13);
return -ERROR;
}
/* set test pin 1 as high*/
testpin_1_stat.pin = GPIO_C13;
testpin_1_stat.val = GPIO_LOW;
BusDevWriteData(pin->owner_haldev, &write_param_1);
/* config test pin 2 as input*/
testpin_2.cmd = GPIO_CONFIG_MODE;
testpin_2.pin = GPIO_C2;
testpin_2.mode = GPIO_CFG_INPUT;
ret = BusDrvConfigure(pin->owner_driver, &configure_info_2);
if (ret != EOK) {
KPrintf("config testpin_2 %d input failed!\n", testpin_2.pin);
return -ERROR;
}
testpin_2.cmd = GPIO_IRQ_REGISTER;
testpin_2.pin = GPIO_C2;
testpin_2.irq_set.irq_mode = GPIO_IRQ_EDGE_BOTH;
testpin_2.irq_set.hdr = PinIrqIsr;
testpin_2.irq_set.args = NONE;
ret = BusDrvConfigure(pin->owner_driver, &configure_info_2);
if (ret != EOK) {
KPrintf("register testpin_2 %d irq failed!\n", testpin_2.pin);
return -ERROR;
}
testpin_2.cmd = GPIO_IRQ_ENABLE;
testpin_2.pin = GPIO_C2;
ret = BusDrvConfigure(pin->owner_driver, &configure_info_2);
if (ret != EOK) {
KPrintf("enable testpin_2 %d irq failed!\n", testpin_2.pin);
return -ERROR;
}
KPrintf("%s irq test\n",__func__);
return 0;
}
void RealtimeTaskSwitchTest()
{
struct PinParam testpin_1;
struct PinStat testpin_1_stat;
int ret = 0;
struct BusConfigureInfo configure_info_1;
struct BusBlockWriteParam write_param_1;
configure_info_1.configure_cmd = OPE_CFG;
configure_info_1.private_data = (void *)&testpin_1;
write_param_1.buffer = (void *)&testpin_1_stat;
/* config test pin 1 as output*/
testpin_1.cmd = GPIO_CONFIG_MODE;
testpin_1.pin = GPIO_C13;
testpin_1.mode = GPIO_CFG_OUTPUT;
ret = BusDrvConfigure(pin->owner_driver, &configure_info_1);
if (ret != EOK) {
KPrintf("config testpin_1 %d failed!\n", GPIO_C13);
return ;
}
/* set test pin 1 as low*/
testpin_1_stat.pin = GPIO_C13;
testpin_1_stat.val = GPIO_LOW;
BusDevWriteData(pin->owner_haldev, &write_param_1);
while (RET_TRUE) {
DelayKTask(1);
}
}
void GpioSpeedTest()
{
struct PinParam testpin_1;
struct PinStat testpin_1_stat;
struct PinParam testpin_2;
int ret = 0;
struct BusConfigureInfo configure_info_1;
struct BusConfigureInfo configure_info_2;
struct BusBlockWriteParam write_param_1;
configure_info_1.configure_cmd = OPE_CFG;
configure_info_1.private_data = (void *)&testpin_1;
write_param_1.buffer = (void *)&testpin_1_stat;
configure_info_2.configure_cmd = OPE_CFG;
configure_info_2.private_data = (void *)&testpin_2;
/* config test pin 1 as output*/
testpin_1.cmd = GPIO_CONFIG_MODE;
testpin_1.pin = GPIO_C13;
testpin_1.mode = GPIO_CFG_OUTPUT;
ret = BusDrvConfigure(pin->owner_driver, &configure_info_1);
if (ret != EOK) {
KPrintf("config testpin_1 %d failed!\n", GPIO_C13);
return ;
}
testpin_2.cmd = GPIO_CONFIG_MODE;
testpin_2.pin = GPIO_C2;
testpin_2.mode = GPIO_CFG_INPUT;
ret = BusDrvConfigure(pin->owner_driver, &configure_info_2);
/* set test pin 1 as low*/
testpin_1_stat.pin = GPIO_C13;
testpin_1_stat.val = GPIO_LOW;
BusDevWriteData(pin->owner_haldev, &write_param_1);
while (RET_TRUE) {
*(volatile unsigned int *)0x40020818 = 0x2000;
*(volatile unsigned int*)0x4002081a = 0x2000;
}
}
#else
#define GPIO_18 18
#define GPIO_19 19
void PinIrqIsr(void *args)
{
*(volatile unsigned int *)0x3800100c |= 0x5;
*(volatile unsigned int *)0x3800100c &= ~0x5;
}
int RealtimeIrqTest()
{
struct PinParam testpin_1;
struct PinStat testpin_1_stat;
struct PinParam testpin_2;
struct BusConfigureInfo configure_info_1;
struct BusConfigureInfo configure_info_2;
struct BusBlockWriteParam write_param_1;
configure_info_1.configure_cmd = OPE_CFG;
configure_info_1.private_data = (void *)&testpin_1;
write_param_1.buffer = (void *)&testpin_1_stat;
configure_info_2.configure_cmd = OPE_CFG;
configure_info_2.private_data = (void *)&testpin_2;
KPrintf("%s irq test\n",__func__);
/* config GPIO18 as output and set as low */
testpin_1.cmd = GPIO_CONFIG_MODE;
testpin_1.pin = GPIO_18;
testpin_1.mode = GPIO_CFG_OUTPUT;
BusDrvConfigure(pin->owner_driver, &configure_info_1);
testpin_1_stat.pin = GPIO_18;
testpin_1_stat.val = GPIO_LOW;
BusDevWriteData(pin->owner_haldev, &write_param_1);
/* config GPIO18 as input */
testpin_2.cmd = GPIO_CONFIG_MODE;
testpin_2.pin = GPIO_19;
testpin_2.mode = GPIO_CFG_INPUT;
BusDrvConfigure(pin->owner_driver, &configure_info_2);
testpin_2.cmd = GPIO_IRQ_REGISTER;
testpin_2.pin = GPIO_19;
testpin_2.irq_set.irq_mode = GPIO_IRQ_EDGE_RISING;
testpin_2.irq_set.hdr = PinIrqIsr;
testpin_2.irq_set.args = NONE;
BusDrvConfigure(pin->owner_driver, &configure_info_2);
testpin_2.cmd = GPIO_IRQ_ENABLE;
testpin_2.pin = GPIO_19;
BusDrvConfigure(pin->owner_driver, &configure_info_2);
return 0;
}
void RealtimeTaskSwitchTest()
{
struct PinParam testpin_1;
struct PinStat testpin_1_stat;
struct BusConfigureInfo configure_info_1;
struct BusBlockWriteParam write_param_1;
configure_info_1.configure_cmd = OPE_CFG;
configure_info_1.private_data = (void *)&testpin_1;
write_param_1.buffer = (void *)&testpin_1_stat;
testpin_1.cmd = GPIO_CONFIG_MODE;
testpin_1.pin = GPIO_18;
testpin_1.mode = GPIO_CFG_OUTPUT;
BusDrvConfigure(pin->owner_driver, &configure_info_1);
testpin_1_stat.pin = GPIO_18;
testpin_1_stat.val = GPIO_LOW;
BusDevWriteData(pin->owner_haldev, &write_param_1);
while (RET_TRUE) {
DelayKTask(10);
}
}
void GpioSpeedTest()
{
struct PinParam testpin_1;
struct PinStat testpin_1_stat;
struct BusConfigureInfo configure_info_1;
struct BusBlockWriteParam write_param_1;
configure_info_1.configure_cmd = OPE_CFG;
configure_info_1.private_data = (void *)&testpin_1;
write_param_1.buffer = (void *)&testpin_1_stat;
testpin_1.cmd = GPIO_CONFIG_MODE;
testpin_1.pin = GPIO_18;
testpin_1.mode = GPIO_CFG_OUTPUT;
BusDrvConfigure(pin->owner_driver, &configure_info_1);
testpin_1_stat.pin = GPIO_18;
testpin_1_stat.val = GPIO_LOW;
BusDevWriteData(pin->owner_haldev, &write_param_1);
while (RET_TRUE) {
*(volatile unsigned int *)0x3800100c |= 0x5;
*(volatile unsigned int *)0x3800100c &= ~0x5;
}
}
#endif
/********************************************************************/
static void UsageHelp(void)
{
KPrintf("TestRealtime.\n");
}
int TestRealtime(int argc, char * argv[])
{
int ret = 0;
struct BusConfigureInfo configure_info;
if (NONE == argv || 0 == strncmp("-h", argv[0], strlen("-h")) || 0 == strncmp("usage", argv[0], strlen("usage"))) {
UsageHelp();
return -EINVALED;
}
pin = BusFind(PIN_BUS_NAME);
if (!pin) {
KPrintf("find %s failed!\n", PIN_BUS_NAME);
return -ERROR;
}
pin->owner_driver = BusFindDriver(pin, PIN_DRIVER_NAME);
pin->owner_haldev = BusFindDevice(pin, PIN_DEVICE_NAME);
configure_info.configure_cmd = OPE_INT;
ret = BusDrvConfigure(pin->owner_driver, &configure_info);
if (ret != EOK) {
KPrintf("initialize %s failed!\n", PIN_BUS_NAME);
return -ERROR;
}
if (0 == strncmp("-irq",argv[0],strlen("-irq")) ) {
RealtimeIrqTest(); ///< static creat single sem test
}
if (0 == strncmp("-task",argv[0],strlen("-task")) ) {
RealtimeTaskSwitchTest();
}
if (0 == strncmp("-gpio",argv[0],strlen("-gpio")) ) {
GpioSpeedTest();
}
return 0;
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file TestRtc.c
* @brief support to test rtc function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <device.h>
#ifdef RESOURCES_RTC
static int TestRtc(int argc, char *argv[])
{
time_t now;
struct RtcSetParam rtc_set_param;
KPrintf("TestRtc cmd %s\n", argv[1]);
if (0 == strcmp("-s", argv[1])) {
rtc_set_param.rtc_set_cmd = OPER_RTC_SET_TIME;
rtc_set_param.date_param.year = 2021;
rtc_set_param.date_param.month = 4;
rtc_set_param.date_param.day = 6;
rtc_set_param.time_param.hour = 16;
rtc_set_param.time_param.minute = 0;
rtc_set_param.time_param.second = 0;
RtcDrvSetFunction(RTC_DRV_NAME, &rtc_set_param);
rtc_set_param.rtc_set_cmd = OPER_RTC_GET_TIME;
rtc_set_param.time = &now;
RtcDrvSetFunction(RTC_DRV_NAME, &rtc_set_param);
KPrintf("%s\n", ctime(&now));
} else if (0 == strcmp("-g", argv[1])) {
rtc_set_param.rtc_set_cmd = OPER_RTC_GET_TIME;
rtc_set_param.time = &now;
RtcDrvSetFunction(RTC_DRV_NAME, &rtc_set_param);
KPrintf("%s\n", ctime(&now));
}
return EOK;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_PARAM_NUM(4),
TestRtc, TestRtc, Test the RTC Function);
#endif

View File

@@ -0,0 +1,199 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file test_serial.c
* @brief support to test serial function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <device.h>
#if defined (ARCH_RISCV)
#include <connect_uart.h>
#elif defined(ARCH_ARM)
#include <connect_usart.h>
#endif
//#define TEST_POSIX
#ifdef TEST_POSIX
#include "user_api.h"
#endif
#ifdef RESOURCES_SERIAL
static char test_str[] = "Hello AIIT!\r\n";
struct Bus *bus = NONE;
struct Driver *bus_driver = NONE;
struct HardwareDev *bus_device = NONE;
#ifdef TEST_POSIX
static int uart3_fd = 0;
#endif
static int32 test_serial_task = 0;
static void TestSerialRecvTask(void *parameter)
{
int16 i = 0;
char recv_data = 0;
#ifdef TEST_POSIX
char data_buffer[128] = {0};
char data_size = 0;
#endif
struct BusBlockReadParam read_param;
struct BusBlockWriteParam write_param;
memset(&read_param, 0, sizeof(struct BusBlockReadParam));
memset(&write_param, 0, sizeof(struct BusBlockWriteParam));
while(RET_TRUE) {
#ifndef TEST_POSIX
read_param.size = 1;
read_param.buffer = &recv_data;
read_param.read_length = 0;
BusDevReadData(bus_device, &read_param);
for (i = 0; i < read_param.read_length; i ++) {
KPrintf("TestSerialRecvTask i %d char 0x%x\n", i, recv_data);
}
write_param.buffer = &recv_data;
write_param.size = 1;
BusDevWriteData(bus_device, &write_param);
#else
memset(data_buffer, 0, 128);
data_size = read(uart3_fd, data_buffer, 128);
KPrintf("uart 3 data size %d data %s\n", data_size, data_buffer);
#endif
}
}
static int SerialBusCheck(const char *bus_name, const char *driver_name, const char *device_name)
{
int ret = EOK;
#ifndef TEST_POSIX
struct SerialBus *serial_bus = NONE;
struct SerialDriver *serial_driver = NONE;
struct SerialHardwareDevice *serial_device = NONE;
struct SerialCfgParam *serial_cfg_default = NONE;
struct SerialDevParam *serial_dev_param = NONE;
struct BusConfigureInfo configure_info;
if(bus_name)
{
KPrintf("####test find bus %s\n", bus_name);
bus = BusFind(bus_name);
serial_bus = (struct SerialBus *)bus;
KPrintf("####test find bus %8p serial_bus %8p\n", bus, serial_bus);
}
if(driver_name)
{
KPrintf("####test find driver %s\n", driver_name);
bus_driver = BusFindDriver(bus, driver_name);
serial_driver = (struct SerialDriver *)bus_driver;
serial_cfg_default = (struct SerialCfgParam *)serial_driver->private_data;
KPrintf("####test bus_driver %8p serial_driver %8p done %8p serial_cfg_default %8p####\n",
bus_driver, serial_driver, serial_driver->drv_done, serial_cfg_default);
KPrintf("####hw cfg base 0x%x irq %d####\n", serial_cfg_default->hw_cfg.serial_register_base, serial_cfg_default->hw_cfg.serial_irq_interrupt);
KPrintf("####data cfg rate %u order %u size %u bits %u invert %u parity %u stop %u####\n", serial_cfg_default->data_cfg.serial_baud_rate, serial_cfg_default->data_cfg.serial_bit_order, serial_cfg_default->data_cfg.serial_buffer_size,
serial_cfg_default->data_cfg.serial_data_bits, serial_cfg_default->data_cfg.serial_invert_mode, serial_cfg_default->data_cfg.serial_parity_mode, serial_cfg_default->data_cfg.serial_stop_bits);
}
if(device_name)
{
KPrintf("####test find device0 %s\n", device_name);
bus_device = BusFindDevice(bus, device_name);
serial_device = (struct SerialHardwareDevice *)bus_device;
serial_dev_param = (struct SerialDevParam *)bus_device->private_data;
KPrintf("####test bus_device %8p serial_dev %8p hwdone %8p devdone %8p####\n",
bus_device, serial_device, serial_device->hwdev_done, serial_device->haldev.dev_done);
KPrintf("####dev_param %8p work mode 0x%x set mode 0x%x stream mode 0x%x\n",
serial_dev_param, serial_dev_param->serial_work_mode, serial_dev_param->serial_set_mode, serial_dev_param->serial_stream_mode);
}
//BusDevRecvCallback(bus_device, test_serial_callback);
/*step 1: init bus_driver, change struct SerialCfgParam if necessary*/
struct SerialCfgParam serial_cfg;
memset(&serial_cfg, 0, sizeof(struct SerialCfgParam));
configure_info.configure_cmd = OPE_INT;
configure_info.private_data = &serial_cfg;
BusDrvConfigure(bus_driver, &configure_info);
KPrintf("BusDrvConfigure OPE_INT done\n");
/*step 2: match bus_driver with bus_device*/
bus->match(bus_driver, bus_device);
/*step 3: open bus_device, configure struct SerialDevParam if necessary*/
serial_dev_param->serial_set_mode = SIGN_OPER_INT_RX;
serial_dev_param->serial_stream_mode = SIGN_OPER_STREAM;
BusDevOpen(bus_device);
KPrintf("BusDevOpen done\n");
/*step 4: write serial data, configure struct BusBlockWriteParam*/
struct BusBlockWriteParam write_param;
write_param.pos = 0;
write_param.buffer = (void *)test_str;
write_param.size = sizeof(test_str) - 1;
BusDevWriteData(bus_device, &write_param);
//BusDevClose(bus_device);
//KPrintf("BusDevClose done\n");
#else
uart3_fd = open("/dev/uart3_dev3", O_RDWR);
if (uart3_fd < 0) {
KPrintf("open fd error %d\n", uart3_fd);
}
KPrintf("open fd %d\n", uart3_fd);
struct SerialDataCfg cfg;
cfg.serial_baud_rate = BAUD_RATE_115200;
cfg.serial_data_bits = DATA_BITS_8;
cfg.serial_stop_bits = STOP_BITS_1;
cfg.serial_buffer_size = 128;
cfg.serial_parity_mode = PARITY_NONE;
cfg.serial_bit_order = 0;
cfg.serial_invert_mode = 0;
cfg.ext_uart_no = 0;
cfg.port_configure = 0;
if (ret != ioctl(uart3_fd, OPE_INT, &cfg)) {
KPrintf("ioctl fd error %d\n", ret);
}
#endif
}
int TestSerial(void)
{
/*use serial device 3 to test serial function*/
SerialBusCheck(SERIAL_BUS_NAME_3, SERIAL_DRV_NAME_3, SERIAL_3_DEVICE_NAME_0);
test_serial_task = KTaskCreate("TestSerialRecvTask",
TestSerialRecvTask,
NONE,
2048,
18);
StartupKTask(test_serial_task);
return EOK;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
TestSerial, TestSerial, TestSerial );
#endif

View File

@@ -0,0 +1,199 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file test_threadsched.c
* @brief support to test thread sched function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
#include <string.h>
#include <xs_assign.h>
extern long ShowTask(void);
extern unsigned int msleep(uint64_t msec);
static int32 tid1 = NONE;
static int32 tid2 = NONE;
static int32 tid3 = NONE;
static int32 tid4 = NONE;
static int32 tid5 = NONE;
#define DYNAMIC_TASK_STACK_SIZE 3072
#define PRIORITY 15
static void Task1Entry(void *parameter)
{
int cnt = 10;
DoubleLinklistType* node = NONE;
DoubleLinklistType* head = NONE;
struct TaskDescriptor *obj = NONE;
TaskDyncSchedMembeType *tmp = NONE;
register x_base level;
#ifdef ARCH_SMP
if (0 == strncmp(parameter,"-b",strlen("-b"))) { ///< if tasks bind to cpu 0
head = &(Assign.smp_os_assign_ready_rector[0].priority_ready_vector[PRIORITY]);
} else {
head = &(Assign.os_assign_read_vector.priority_ready_vector[PRIORITY]);
}
#else
head = &(Assign.os_assign_read_vector.priority_ready_vector[PRIORITY]);
#endif
while(cnt--) {
#ifdef TOOL_SHELL
ShowTask();
#endif
KPrintf("\n");
DOUBLE_LINKLIST_FOR_EACH(node, head) {
tmp = SYS_DOUBLE_LINKLIST_ENTRY(node, struct TaskDyncSchedMember, sched_link);
obj =CONTAINER_OF(tmp,struct TaskDescriptor, task_dync_sched_member);
KPrintf("task ready table node name = %s node remaining_tick= %d node advance_cnt =%d\n",obj->task_base_info.name,
obj->task_dync_sched_member.rest_timeslice, obj->task_dync_sched_member.advance_cnt);
}
#ifdef ARCH_SMP
#ifdef SCHED_POLICY_FIFO
MdelayKTask(30);
#else
msleep(30);
#endif
#else
#ifdef ARCH_ARM
MdelayKTask(3);
#else
MdelayKTask(80);
#endif
#endif
}
KTaskDelete(tid2);
KTaskDelete(tid3);
KTaskDelete(tid4);
KTaskDelete(tid5);
}
static void Task2Entry(void *parameter)
{
int i = 0;
while(RET_TRUE) {
i++;
}
}
static void Task3Entry(void *parameter)
{
int i = 0;
while(RET_TRUE) {
i++;
}
}
static void Task4Entry(void *parameter)
{
int i = 0;
while(RET_TRUE) {
i++;
}
}
static void Task5Entry(void *parameter)
{
int i = 0;
while(RET_TRUE) {
i++;
}
}
void DynamicTaskSchedTest(char* parm)
{
char t_parm[4];
#ifdef ARCH_SMP
if (0 == strncmp("-b", parm, strlen("-b")) || 0 == strncmp("-bind", parm, strlen("-bind"))){
strncpy(t_parm,"-b", 4);
}
#endif
tid1 = KTaskCreate("d_tid1",
Task1Entry,
t_parm,
DYNAMIC_TASK_STACK_SIZE,
16);
if (tid1 >= 0)
StartupKTask(tid1);
tid2 = KTaskCreate("d_tid2",
Task2Entry,
"d_tid2",
1024,
15);
#ifdef ARCH_SMP
if (0 == strncmp("-b", parm, strlen("-b")) || 0 == strncmp("-bind", parm, strlen("-bind"))){
KTaskCoreCombine(tid2, 0);
}
#endif
if (tid2 >= 0)
StartupKTask(tid2);
tid3 = KTaskCreate("d_tid3",
Task3Entry,
"d_tid3",
1024,
15);
#ifdef ARCH_SMP
if (0 == strncmp("-b", parm, strlen("-b")) || 0 == strncmp("-bind", parm, strlen("-bind"))){
KTaskCoreCombine(tid3, 0);
}
#endif
if (tid3 >= 0)
StartupKTask(tid3);
tid4 = KTaskCreate("d_tid4",
Task4Entry,
"d_tid4",
1024,
15);
#ifdef ARCH_SMP
if (0 == strncmp("-b", parm, strlen("-b")) || 0 == strncmp("-bind", parm, strlen("-bind"))){
KTaskCoreCombine(tid4, 0);
}
#endif
if (tid4 >= 0)
StartupKTask(tid4);
tid5 = KTaskCreate("d_tid5",
Task5Entry,
"d_tid5",
1024,
15);
#ifdef ARCH_SMP
if (0 == strncmp("-b", parm, strlen("-b")) || 0 == strncmp("-bind", parm, strlen("-bind"))){
KTaskCoreCombine(tid5, 0);
}
#endif
if (tid5 >= 0)
StartupKTask(tid5);
}
/********************************************************************/
static void UsageHelp(void)
{
KPrintf("test_task_ready_usage.\n");
}
int TestTaskReadyAndSched(int argc, char * argv[])
{
DynamicTaskSchedTest(argv[0]);
return 0;
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file test_timer.c
* @brief support to test timer function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <xiuos.h>
extern long ShowTimer(void);
/*****************************************************************************************************************/
/***********************************test create timer with dynamic style *****************************************/
static int32 dynamic_timer1;
static int32 dynamic_timer2;
static int dynamic_cnt = 0;
static void DynamicTimeout1Entry(void *parameter)
{
KPrintf("periodic timer is timeout %d\n", dynamic_cnt);
if (dynamic_cnt++>= 9){
KTimerQuitRun(dynamic_timer1);
KPrintf("periodic timer was stopped! \n");
}
}
static void DynamicTimeout2Entry(void *parameter)
{
KPrintf("one shot timer is timeout\n");
}
int TestDynamicTimer(void)
{
dynamic_timer1 = KCreateTimer("d_tmr1", DynamicTimeout1Entry,
NONE, 10,
TIMER_TRIGGER_PERIODIC);
if (dynamic_timer1 != NONE) KTimerStartRun(dynamic_timer1);
dynamic_timer2 = KCreateTimer("d_tmr2", DynamicTimeout2Entry,
NONE, 30,
TIMER_TRIGGER_ONCE);
if (dynamic_timer2 != NONE) KTimerStartRun(dynamic_timer2);
ShowTimer();
return 0;
}
int TestTmrD(void)
{
KPrintf("test dynamic timer\n");
TestDynamicTimer();
return 0;
}
/*******************************test mixed timers with dynamic and static style **********************************/
static int32 mixed_timer_d;
static int32 test_delete_timer;
static int num = 0;
static void MexedTimeout2Entry(void *parameter)
{
KPrintf("mixed\n");
KTimerQuitRun(mixed_timer_d);
}
int TimerMix(void)
{
mixed_timer_d = KCreateTimer("mix_t2", MexedTimeout2Entry, NONE, 30, TIMER_TRIGGER_ONCE);
if (mixed_timer_d != NONE) KTimerStartRun(mixed_timer_d);
test_delete_timer = KCreateTimer("del_t3", MexedTimeout2Entry, NONE, 30, TIMER_TRIGGER_ONCE);
ShowTimer();
if(test_delete_timer != NONE)
KDeleteTimer(test_delete_timer);
return 0;
}
int TestTmrM(void)
{
KPrintf("test mixed timer\n");
TimerMix();
return 0;
}
int TestTmr(int argc, char*argv[]) {
KPrintf("/******************************************** START **************************************************/\n");
TestTmrD();
MdelayKTask(4000);
KPrintf("/******************************************* boundary ************************************************/\n");
TestTmrM();
MdelayKTask(4000);
KPrintf("/********************************************* END **************************************************/\n");
return 0;
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file test_touch.c
* @brief support to test touch function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include "bus_touch.h"
#include "dev_touch.h"
int TestTouch(const char *bus_name, const char *driver_name, const char *device_name0)
{
struct Bus *bus;
struct Driver *driver, *bus_driver;
struct HardwareDev *device0;
struct HardwareDev *bus_device0;
struct TouchDataStandard datacfg;
struct TouchDataStandard data ={0,0};
struct BusConfigureInfo configure_info = {0,&data};
struct BusBlockReadParam read_param;
memset(&read_param,0,sizeof(struct BusBlockReadParam ));
read_param.buffer = &data;
if(bus_name)
{
KPrintf("##test find bus %s\n", bus_name);
bus = BusFind(bus_name);
KPrintf("##test bus %p####\n", bus);
}
if(driver_name)
{
KPrintf("##test find driver %s\n", driver_name);
driver = TouchDriverFind(driver_name, TYPE_TOUCH_DRV);
bus_driver = BusFindDriver(bus, driver_name);
KPrintf("##test driver %p bus_driver %p##\n", driver, bus_driver);
}
if(device_name0)
{
KPrintf("##test find device0 %s\n", device_name0);
device0 = TouchDeviceFind(device_name0, TYPE_TOUCH_DEV);
KPrintf("device0 :%p\n", device0);
bus_device0 = BusFindDevice(bus, device_name0);
KPrintf("bus_device0 :%p\n", bus_device0);
}
KPrintf("ttt\n");
BusDrvConfigure(bus_driver, &configure_info);
KPrintf("yyy\n");
while(1)
{
BusDevReadData(bus_device0,&read_param);
KPrintf("dev.x= %8d *** dev.y= %8d \r\n",data.x,data.y);
MdelayKTask(100);
}
}
void TouchTest(void)
{
TestTouch(TOUCH_BUS_NAME_1,TOUCH_DRV_NAME_1, TOUCH_1_DEVICE_NAME_0);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),TouchTest, TouchTest, Close AC task );

View File

@@ -0,0 +1,237 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file user_api.h
* @brief define user api function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#ifndef __XS_USER_API_H__
#define __XS_USER_API_H__
#include <xiuos.h>
#include <iot-vfs_posix.h>
#ifdef SEPARATE_COMPILE
#include <stddef.h>
#include <stdint.h>
#include <kswitch.h>
#if defined(FS_VFS)
#include <iot-vfs.h>
#ifndef TASK_ISOLATION
#include <iot-vfs_posix.h>
#endif
#endif
#include <xs_service.h>
#define TASK_INFO 1
#define MEM_INFO 2
#define SEM_INFO 3
#define EVENT_INFO 4
#define MUTEX_INFO 5
#define MEMPOOL_INFO 6
#define MSGQUEUE_INFO 7
#define DEVICE_INFO 8
#define TIMER_INFO 9
int UserPrintInfo(unsigned long i);
struct utask
{
char name[NAME_NUM_MAX];
void *func_entry;
void *func_param;
uint32 stack_size;
uint8 prio;
};
typedef struct utask utask_x;
typedef void DIR;
int32 UserTaskCreate(utask_x utask);
x_err_t UserTaskStartup(int32 id);
x_err_t UserTaskDelete(int32 id);
void UserTaskQuit(void);
x_err_t UserTaskDelay(int32 ms);
x_err_t UserGetTaskName(int32 id ,char *name);
int32 UserGetTaskID(void);
uint8 UserGetTaskStat(int32 id);
#ifdef ARCH_SMP
x_err_t UserTaskCoreCombine(int32 id,uint8 core_id);
x_err_t UserTaskCoreUnCombine(int32 id);
uint8 UserGetTaskCombinedCore(int32 id);
uint8 UserGetTaskRunningCore(int32 id);
#endif
x_err_t UserGetTaskErrorstatus(int32 id);
uint8 UserGetTaskPriority(int32 id);
void *UserMalloc(x_size_t size);
void *UserRealloc(void *pointer, x_size_t size);
void *UserCalloc(x_size_t count, x_size_t size);
void UserFree(void *pointer);
#ifdef KERNEL_MUTEX
int32 UserMutexCreate();
void UserMutexDelete(int32 mutex);
int32 UserMutexObtain(int32 mutex, int32 wait_time);
int32 UserMutexAbandon(int32 mutex);
#endif
#ifdef KERNEL_SEMAPHORE
typedef int32 sem_t;
sem_t UserSemaphoreCreate(uint16 val);
x_err_t UserSemaphoreDelete(sem_t sem);
x_err_t UserSemaphoreObtain(sem_t sem, int32 wait_time);
x_err_t UserSemaphoreAbandon(sem_t sem);
x_err_t UserSemaphoreSetValue(sem_t sem, uint16 val);
#endif
#ifdef KERNEL_EVENT
EventIdType UserEventCreate(uint8 flag);
void UserEventDelete(EventIdType event);
x_err_t UserEventTrigger(EventIdType event, uint32 set);
x_err_t UserEventProcess(EventIdType event, uint32 set, uint8 option,
int32 wait_time, uint32 *Recved);
x_err_t UserEventReinit(EventIdType event);
#endif
#ifdef KERNEL_MESSAGEQUEUE
int32 UserMsgQueueCreate(x_size_t msg_size, x_size_t max_msgs);
x_err_t UserMsgQueueDelete(int32 mq );
x_err_t UserMsgQueueSendwait(int32 mq, const void *buffer,
x_size_t size, int32 wait_time);
x_err_t UserMsgQueueSend(int32 mq, const void *buffer, x_size_t size);
x_err_t UserMsgQueueUrgentSend(int32 mq, const void *buffer, x_size_t size);
x_err_t UserMsgQueueRecv(int32 mq, void *buffer, x_size_t size,int32 wait_time);
x_err_t UserMsgQueueReinit(int32 mq);
#endif
int open(const char *path, int flags, ...);
int read(int fd, void *buf, size_t len);
int write(int fd, const void *buf, size_t len);
int close(int fd);
off_t lseek(int fd, off_t offset, int whence);
int rename(const char *from, const char *to);
int unlink(const char *path);
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int fsync(int fd);
int ftruncate(int fd, off_t length);
int mkdir(const char *path, mode_t mode);
DIR *opendir(const char *path);
int closedir(DIR *dirp);
struct dirent *readdir(DIR *dirp);
int rmdir(const char *path);
int chdir(const char *path);
char *getcwd(char *buf, size_t size);
long telldir(DIR *dirp);
void seekdir(DIR *dirp, off_t offset);
void rewinddir(DIR *dirp);
#ifdef FS_VFS
struct statfs {
size_t f_bsize;
size_t f_blocks;
size_t f_bfree;
};
int statfs(const char *path, struct statfs *buf);
#endif
void UserPrintf(const char *fmt, ...);
#else
struct utask
{
char name[NAME_NUM_MAX];
void *func_entry;
void *func_param;
int32_t stack_size;
uint8_t prio;
};
typedef struct utask utask_x;
int32_t UserTaskCreate(utask_x utask);
#define UserTaskStartup StartupKTask
#define UserTaskDelete KTaskDelete
#define UserTaskQuit KTaskQuit
#define UserTaskDelay MdelayKTask
x_err_t UserGetTaskName(int32_t id ,char *name);
int32_t UserGetTaskID(void);
uint8_t UserGetTaskStat(int32_t id);
#ifdef ARCH_SMP
#define UserTaskCoreCombine KTaskCoreCombine
#define UserTaskCoreUnCombine KTaskCoreUnCombine
uint8_t UserGetTaskCombinedCore(int32_t id);
uint8_t UserGetTaskRunningCore(int32_t id);
#endif
x_err_t UserGetTaskErrorstatus(int32_t id);
uint8_t UserGetTaskPriority(int32_t id);
#define UserMalloc x_malloc
#define UserRealloc x_realloc
#define UserCalloc x_calloc
#define UserFree x_free
#ifdef KERNEL_MUTEX
#define UserMutexCreate KMutexCreate
#define UserMutexDelete KMutexDelete
#define UserMutexObtain KMutexObtain
#define UserMutexAbandon KMutexAbandon
#endif
#ifdef KERNEL_SEMAPHORE
#define UserSemaphoreCreate KSemaphoreCreate
#define UserSemaphoreDelete KSemaphoreDelete
#define UserSemaphoreObtain KSemaphoreObtain
#define UserSemaphoreAbandon KSemaphoreAbandon
#define UserSemaphoreSetValue KSemaphoreSetValue
#endif
#ifdef KERNEL_EVENT
#define UserEventCreate KEventCreate
#define UserEventDelete KEventDelete
#define UserEventTrigger KEventTrigger
#define UserEventProcess KEventProcess
#endif
#ifdef KERNEL_MESSAGEQUEUE
#define UserMsgQueueCreate KCreateMsgQueue
#define UserMsgQueueDelete KDeleteMsgQueue
#define UserMsgQueueSendwait KMsgQueueSendwait
#define UserMsgQueueSend KMsgQueueSend
#define UserMsgQueueUrgentSend KMsgQueueUrgentSend
#define UserMsgQueueRecv KMsgQueueRecv
#define UserMsgQueueReinit KMsgQueueReinit
#endif
#define UserPrintf KPrintf
#endif
#endif

11
kernel/memory/Makefile Normal file
View File

@@ -0,0 +1,11 @@
SRC_FILES := byte_manage.c
ifeq ($(CONFIG_KERNEL_MEMBLOCK),y)
SRC_FILES += gatherblock.c
endif
ifeq ($(CONFIG_TASK_ISOLATION),y)
SRC_FILES += isolation.c
endif
include $(KERNEL_ROOT)/compiler.mk

1037
kernel/memory/byte_manage.c Normal file

File diff suppressed because it is too large Load Diff

414
kernel/memory/gatherblock.c Normal file
View File

@@ -0,0 +1,414 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: gatherblock.c
* @brief: block memory management file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/8
*
*/
#include <xiuos.h>
#include <xs_hook.h>
#ifdef KERNEL_MEMBLOCK
/* a global list, which record all the gatherblocks*/
DoubleLinklistType xiaoshan_memgather_head = {&xiaoshan_memgather_head, &xiaoshan_memgather_head};
/**
* This function initializes a gather block memory structure.
*
* @param gm_handler the gatherblock structure
* @param gm_name the name of gatherblock
* @param begin_address the start address of gatherblock
* @param gm_size the total size of gatherblock
* @param one_block_size one block size in gatherblock
*
* @return EOK
*/
x_err_t InitMemGather(struct MemGather *gm_handler, const char *gm_name, void *begin_address, x_size_t gm_size, x_size_t one_block_size)
{
x_base lock = 0;
register x_size_t off_block = 0;
register x_base critical_value = 0;
uint8 *block_ptr = NONE;
struct SysDoubleLinklistNode *list_entry = NONE;
/* parameter detection */
NULL_PARAM_CHECK(gm_handler);
NULL_PARAM_CHECK(gm_name);
NULL_PARAM_CHECK(begin_address);
CHECK(gm_size >= 1 && one_block_size >= 1);
lock = CriticalAreaLock();
/* try to find gatherblock object */
for (list_entry = xiaoshan_memgather_head.node_next;
list_entry != &(xiaoshan_memgather_head);
list_entry = list_entry->node_next) {
GatherMemType gm;
gm = SYS_DOUBLE_LINKLIST_ENTRY(list_entry, struct MemGather, m_link);
if (gm) {
CHECK(gm != gm_handler);
}
}
CriticalAreaUnLock(lock);
/* set the type attribute of gatherblock object */
gm_handler->m_kind = Cmpt_KindN_Static;
/* set the name of gatherblock object */
strncpy(gm_handler->m_name, gm_name, NAME_NUM_MAX);
critical_value = CriticalAreaLock();
/* insert gatherblock object into the global list */
DoubleLinkListInsertNodeAfter(&xiaoshan_memgather_head, &(gm_handler->m_link));
CriticalAreaUnLock(critical_value);
/* initialize the other attributes of gatherblock object */
gm_handler->m_start_address = begin_address;
gm_handler->m_size = ALIGN_MEN_DOWN(gm_size, MEM_ALIGN_SIZE);
one_block_size = ALIGN_MEN_UP(one_block_size, MEM_ALIGN_SIZE);
gm_handler->one_block_size = one_block_size;
gm_handler->block_total_number = gm_handler->m_size / (gm_handler->one_block_size + sizeof(uint8 *));
gm_handler->block_free_number = gm_handler->block_total_number;
InitDoubleLinkList(&(gm_handler->wait_task));
/* links all the blocks in gatherblock object */
block_ptr = (uint8 *)gm_handler->m_start_address;
for (off_block = 0; off_block < gm_handler->block_total_number; off_block ++) {
*(uint8 **)(block_ptr + off_block * (one_block_size + sizeof(uint8 *))) =
(uint8 *)(block_ptr + (off_block + 1) * (one_block_size + sizeof(uint8 *)));
}
*(uint8 **)(block_ptr + (off_block - 1) * (one_block_size + sizeof(uint8 *))) =
NONE;
gm_handler->m_block_link = block_ptr;
return EOK;
}
/**
* This function will remove the gatherblock from the global list, which is created by MemGatherInit function
*
* @param gm_handler the gatherblock to be removed
*
* @return EOK
*/
x_err_t RemoveMemGather(struct MemGather *gm_handler)
{
register x_ubase critical_value = 0;
struct TaskDescriptor *task = NONE;
/* parameter detection */
NULL_PARAM_CHECK(gm_handler);
CHECK((gm_handler->m_kind & Cmpt_KindN_Static)!=0);
/* resume all the suspend tasks on gatherblock object */
while (!IsDoubleLinkListEmpty(&(gm_handler->wait_task))) {
critical_value = CriticalAreaLock();
task = SYS_DOUBLE_LINKLIST_ENTRY(gm_handler->wait_task.node_next, struct TaskDescriptor, task_dync_sched_member.sched_link);
task->exstatus = -ERROR;
KTaskWakeup(task->id.id);
CriticalAreaUnLock(critical_value);
}
/* set the type attribute */
gm_handler->m_kind = 0;
critical_value = CriticalAreaLock();
/* remove the gatherblock object from the global links */
DoubleLinkListRmNode(&(gm_handler->m_link));
CriticalAreaUnLock(critical_value);
return EOK;
}
/**
* This function will create a gatherblock object.
*
* @param gm_name the name of gatherblock
* @param block_number the number of blocks in gatherblock
* @param one_block_size one block size
*
* @return EOK on success; NONE on failure
*/
GatherMemType CreateMemGather(const char *gm_name, x_size_t block_number, x_size_t one_block_size)
{
register x_size_t off_block = 0;
register x_base critical_value = 0;
uint8 *block_ptr = NONE;
struct MemGather *gm_handler = NONE;
KDEBUG_NOT_IN_INTERRUPT;
/* parameter detection */
NULL_PARAM_CHECK(gm_name);
CHECK(block_number >= 1 && one_block_size >= 1);
KDEBUG_NOT_IN_INTERRUPT;
/* allocate memory for gatherblock object */
gm_handler = (struct MemGather *)KERNEL_MALLOC(sizeof(struct MemGather));
if (NONE == gm_handler)
return NONE;
/* clear the gatherblock object */
memset(gm_handler, 0x0, sizeof(struct MemGather));
/* set the name attribute */
strncpy(gm_handler->m_name, gm_name, NAME_NUM_MAX);
/* set the flag attribute */
gm_handler->m_sign = 0;
critical_value = CriticalAreaLock();
/* insert gatherblock object into the global list */
DoubleLinkListInsertNodeAfter(&xiaoshan_memgather_head, &(gm_handler->m_link));
CriticalAreaUnLock(critical_value);
/* set the other attributes of gatherblock object */
one_block_size = ALIGN_MEN_UP(one_block_size, MEM_ALIGN_SIZE);
gm_handler->one_block_size = one_block_size;
gm_handler->m_size = (one_block_size + sizeof(uint8 *)) * block_number;
/* allocate memory for gather blocks */
gm_handler->m_start_address = x_malloc((one_block_size + sizeof(uint8 *)) * block_number);
if (NONE == gm_handler->m_start_address) {
gm_handler->m_kind = 0;
critical_value = CriticalAreaLock();
/* remove the gatherblock object from the global links */
DoubleLinkListRmNode(&(gm_handler->m_link));
CriticalAreaUnLock(critical_value);
/* release the memory for gather block structure */
KERNEL_FREE(gm_handler);
return NONE;
}
gm_handler->block_total_number = block_number;
gm_handler->block_free_number = gm_handler->block_total_number;
InitDoubleLinkList(&(gm_handler->wait_task));
/* links all the gather blocks */
block_ptr = (uint8 *)gm_handler->m_start_address;
for (off_block = 0; off_block < gm_handler->block_total_number; off_block ++) {
*(uint8 **)(block_ptr + off_block * (one_block_size + sizeof(uint8 *)))
= block_ptr + (off_block + 1) * (one_block_size + sizeof(uint8 *));
}
*(uint8 **)(block_ptr + (off_block - 1) * (one_block_size + sizeof(uint8 *)))
= NONE;
gm_handler->m_block_link = block_ptr;
return gm_handler;
}
/**
* This function will delete a gatherblock object, which is created by MemGatherCreate function.
*
* @param gm_handler the gatherblock object to be deleted
*
* @return EOK
*/
x_err_t DeleteMemGather(GatherMemType gm_handler)
{
register x_ubase critical_value = 0;
struct TaskDescriptor *task = NONE;
KDEBUG_NOT_IN_INTERRUPT;
/* parameter detection */
NULL_PARAM_CHECK(gm_handler);
CHECK(((gm_handler->m_kind & Cmpt_KindN_Static)==0));
/* resume all the suspend tasks on gatherblock object */
while (!IsDoubleLinkListEmpty(&(gm_handler->wait_task))) {
critical_value = CriticalAreaLock();
task = SYS_DOUBLE_LINKLIST_ENTRY(gm_handler->wait_task.node_next, struct TaskDescriptor, task_dync_sched_member.sched_link);
task->exstatus = -ERROR;
KTaskWakeup(task->id.id);
CriticalAreaUnLock(critical_value);
}
/* release the memory for gather blocks */
x_free(gm_handler->m_start_address);
gm_handler->m_kind = 0;
critical_value = CriticalAreaLock();
/* remove the gatherblock object from the global links */
DoubleLinkListRmNode(&(gm_handler->m_link));
CriticalAreaUnLock(critical_value);
/* release the memory for gather block structure */
KERNEL_FREE(gm_handler);
return EOK;
}
/**
* This function will allocate a data block from gatherblock object
*
* @param gm_handler the gatherblock object to get data block
* @param msec waiting time ,millisecond
*
* @return block pointer on success; NONE on failure
*/
void *AllocBlockMemGather(GatherMemType gm_handler, int32 msec)
{
int32 wait_time = 0;
uint32 before_sleep = 0;
register x_base critical_value = 0;
uint8 *block_ptr = NONE;
struct TaskDescriptor *task = NONE;
/* parameter detection */
NULL_PARAM_CHECK(gm_handler);
/* get descriptor of task */
task = GetKTaskDescriptor();
wait_time = CalculteTickFromTimeMs(msec);
critical_value = CriticalAreaLock();
/* no free gatherblock*/
while (0 == gm_handler->block_free_number) {
if (wait_time == 0) {
CriticalAreaUnLock(critical_value);
KUpdateExstatus(ETIMEOUT);
return NONE;
}
KDEBUG_NOT_IN_INTERRUPT;
task->exstatus = EOK;
/* suspend current task */
SuspendKTask(task->id.id);
DoubleLinkListInsertNodeAfter(&(gm_handler->wait_task), &(task->task_dync_sched_member.sched_link));
if (wait_time > 0) {
before_sleep = CurrentTicksGain();
/* start the timer */
KTaskSetDelay(task,wait_time);
}
CriticalAreaUnLock(critical_value);
/* schedule */
DO_KTASK_ASSIGN;
if (EOK != task->exstatus)
return NONE;
if (wait_time > 0) {
wait_time -= CurrentTicksGain() - before_sleep;
if (wait_time < 0)
wait_time = 0;
}
critical_value = CriticalAreaLock();
}
/* decrease the number of free gatherblocks */
gm_handler->block_free_number--;
block_ptr = gm_handler->m_block_link;
NULL_PARAM_CHECK(block_ptr);
/* set the block_list attribute of gather_block structure */
gm_handler->m_block_link = *(uint8 **)block_ptr;
*(uint8 **)block_ptr = (uint8 *)gm_handler;
CriticalAreaUnLock(critical_value);
HOOK(hook.mem.hook_GmAlloc, (gm_handler, (uint8 *)(block_ptr + sizeof(uint8 *))));
return (uint8 *)(block_ptr + sizeof(uint8 *));
}
/**
* This function will release a data block to gatherblock object
*
* @param data_block the data block to be released
*/
void FreeBlockMemGather(void *data_block)
{
uint8 **block_ptr;
register x_base critical_value = 0;
struct MemGather *gm_handler = NONE;
struct TaskDescriptor *task = NONE;
/* parameter detection */
NULL_PARAM_CHECK(data_block);
/* get gatherblock structure */
block_ptr = (uint8 **)((uint8 *)data_block - sizeof(uint8 *));
gm_handler = (struct MemGather *)*block_ptr;
HOOK(hook.mem.hook_GmFree, (gm_handler, data_block));
critical_value = CriticalAreaLock();
/* increase the number of gatherblocks */
gm_handler->block_free_number ++;
*block_ptr = gm_handler->m_block_link;
/* set the block_list attribute of gather_block object */
gm_handler->m_block_link = (uint8 *)block_ptr;
if (!IsDoubleLinkListEmpty(&(gm_handler->wait_task))) {
task = SYS_DOUBLE_LINKLIST_ENTRY(gm_handler->wait_task.node_next, struct TaskDescriptor, task_dync_sched_member.sched_link);
task->exstatus = EOK;
/* resume a suspend task */
KTaskWakeup(task->id.id);
CriticalAreaUnLock(critical_value);
DO_KTASK_ASSIGN;
return;
}
CriticalAreaUnLock(critical_value);
}
#endif

59
kernel/memory/isolation.c Normal file
View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: isolation.c
* @brief: memory access structure definitions of ARM/RISCV
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xs_isolation.h>
#ifdef TASK_ISOLATION
#if defined(ARCH_ARM) && defined(SURPORT_MPU)
struct Mpu *isolation = NONE;
struct MemoryAccessLimit mem_access = {
.Enable = MpuEnable ,
.Disable = MpuDisable ,
.Init = MpuInit ,
.InitIsolation = NONE,
.AddRegion = NONE,
.ClearRegion = NONE ,
.Free = NONE,
.Load = MpuLoad,
.FaultHandle = NONE,
};
#endif
#if defined(ARCH_RISCV) && defined(SURPORT_PMP)
struct Pmp *isolation = NONE;
struct MemoryAccessLimit mem_access = {
.Enable = NONE ,
.Disable = NONE ,
.Init = NONE ,
.InitIsolation = PmpInitIsolation,
.AddRegion = PmpAddTorRegion,
.ClearRegion = PmpClearRegion ,
.Free = PmpFree,
.Load = PmpLoad,
.FaultHandle = PmpAccessFaultHandle,
};
#endif
#endif

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: critical area.c
* @brief: the critical area lock functions definitions
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#ifndef __CRITICAL__AREA__
#define __CRITICAL__AREA__
#include <xs_isr.h>
#include <xs_ktask_stat.h>
#include <xs_assign.h>
#include <xs_spinlock.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef ARCH_SMP
HwSpinlock _CriticalLock;
/**
* This function will do OsAssign lock.
*
* @return lock
*/
x_base CriticalAreaLock(void)
{
x_base lock = 0;
lock = DisableLocalInterrupt();
if (Assign.smp_os_running_task[GetCpuId()]) {
if (Assign.smp_os_running_task[GetCpuId()]->task_smp_info.critical_lock_cnt == 0) {
Assign.assign_lock[GetCpuId()] ++;
HwLockSpinlock(&_CriticalLock);
}
Assign.smp_os_running_task[GetCpuId()]->task_smp_info.critical_lock_cnt ++;
}
return lock;
}
/**
* This function will do OsAssign unlock.
*
* @return lock
*/
void CriticalAreaUnLock(x_base lock)
{
if (Assign.smp_os_running_task[GetCpuId()]) {
if (Assign.smp_os_running_task[GetCpuId()]->task_smp_info.critical_lock_cnt > 0) {
Assign.smp_os_running_task[GetCpuId()]->task_smp_info.critical_lock_cnt --;
}
if (Assign.smp_os_running_task[GetCpuId()]->task_smp_info.critical_lock_cnt == 0) {
if(Assign.assign_lock[GetCpuId()] > 0)
Assign.assign_lock[GetCpuId()]--;
HwUnlockSpinlock(&_CriticalLock);
}
}
EnableLocalInterrupt(lock);
}
/**
* This function will get critical lock level.
*
* @return critical lock level
*/
uint16 GetOsAssignLockLevel(void)
{
return Assign.smp_os_running_task[GetCpuId()]->task_smp_info.critical_lock_cnt;
}
#else
#include <xs_hook.h>
static int16 KTaskOsAssignLockNest;
/**
* This function will get critical lock level.
*
* @return critical lock level
*/
uint16 GetOsAssignLockLevel(void) {
return KTaskOsAssignLockNest;
}
inline void ResetCriticalAreaLock(void ) {
KTaskOsAssignLockNest = 0;
}
/**
* This function will do OsAssign lock.
*
* @return lock
*/
x_base CriticalAreaLock(void) {
x_base lock;
lock = DISABLE_INTERRUPT();
KTaskOsAssignLockNest ++;
return lock;
}
/**
* This function will do OsAssign unlock.
*
* @return lock
*/
void CriticalAreaUnLock(x_base lock) {
if (KTaskOsAssignLockNest >= 1) {
KTaskOsAssignLockNest --;
}
ENABLE_INTERRUPT(lock);
}
#endif
#ifdef __cplusplus
}
#endif
#endif

78
kernel/thread/Makefile Normal file
View File

@@ -0,0 +1,78 @@
SRC_FILES := tick.c kservicetask.c zombierecycle.c init.c lock.c idle.c linklist.c isr.c console.c ktask.c id.c CriticalArea.c bitmap.c delay.c double_link.c single_link.c assignstat.c ktask_stat.c
ifeq ($(CONFIG_KERNEL_SEMAPHORE),y)
SRC_FILES += semaphore.c
endif
ifeq ($(CONFIG_KERNEL_MUTEX),y)
SRC_FILES += mutex.c
endif
ifeq ($(CONFIG_KERNEL_EVENT),y)
SRC_FILES += event.c
endif
ifeq ($(CONFIG_KERNEL_MESSAGEQUEUE),y)
SRC_FILES += msgqueue.c
endif
ifeq ($(CONFIG_KERNEL_SOFTTIMER),y)
SRC_FILES += softtimer.c
endif
ifeq ($(CONFIG_KERNEL_BANNER),y)
SRC_FILES += banner.c
endif
ifeq ($(CONFIG_KERNEL_HOOK),y)
SRC_FILES += hook.c
endif
ifeq ($(CONFIG_KERNEL_QUEUEMANAGE),y)
SRC_FILES += queue_manager.c
ifeq ($(CONFIG_KERNEL_WORKQUEUE),y)
SRC_FILES += workqueue.c
endif
ifeq ($(CONFIG_KERNEL_WAITQUEUE),y)
SRC_FILES += waitqueue.c
endif
ifeq ($(CONFIG_KERNEL_DATAQUEUE),y)
SRC_FILES += data_queue.c
endif
endif
ifeq ($(CONFIG_KERNEL_CIRCULAR_AREA),y)
SRC_FILES += circular_area.c
endif
ifeq ($(CONFIG_KERNEL_AVL_TREE),y)
SRC_FILES += avl_tree.c
endif
ifeq ($(CONFIG_ARCH_SMP),y)
SRC_FILES += smp_assign.c
else
SRC_FILES += assign.c
endif
ifeq ($(CONFIG_SCHED_POLICY_RR),y)
SRC_FILES += assign_roundrobin.c
endif
ifeq ($(CONFIG_SCHED_POLICY_FIFO),y)
SRC_FILES += assign_fifo.c
endif
ifeq ($(CONFIG_SCHED_POLICY_RR_REMAINSLICE),y)
SRC_FILES += assign_roundrobinremain.c
endif
ifeq ($(CONFIG_USER_APPLICATION),y)
SRC_FILES += appstartup.c
endif
include $(KERNEL_ROOT)/compiler.mk

177
kernel/thread/appstartup.c Normal file
View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: appstartup.c
* @brief: init application userspace and create main task
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#include <board.h>
#ifdef TASK_ISOLATION
#include <xs_isolation.h>
#endif
#ifdef APP_STARTUP_FROM_SDCARD
#include <iot-vfs_posix.h>
#endif
extern int main(void);
#ifdef USER_APPLICATION
#ifndef SEPARATE_COMPILE
void MainKTaskFunction(void *parameter)
{
#if defined(__ICCARM__) || defined(__GNUC__)
main();
#endif
}
#endif
/**
* This function will create main application
*
*
*/
void CreateMainTask(void)
{
int32 main = 0;
#ifdef SEPARATE_COMPILE
KPrintf("Tip!!! Kernel is separated with application. main entry : 0x%08x \n",USERSPACE->us_entrypoint);
main = UTaskCreate("main", (void*)USERSPACE->us_entrypoint, NONE,
MAIN_KTASK_STACK_SIZE, MAIN_KTASK_PRIORITY);
#else
main = KTaskCreate("main", MainKTaskFunction, NONE,
MAIN_KTASK_STACK_SIZE, MAIN_KTASK_PRIORITY);
#endif
if(main < 0) {
KPrintf("main create failed ...%s %d.\n",__FUNCTION__,__LINE__);
return;
}
StartupKTask(main);
}
#ifdef SEPARATE_COMPILE
int InitUserspace(void)
{
#ifdef APP_STARTUP_FROM_FLASH
uint8_t *src = NONE;
uint8_t *dest = NONE;
uint8_t *end = NONE;
dest = (uint8_t *)USERSPACE->us_bssstart;
end = (uint8_t *)USERSPACE->us_bssend;
while (dest != end) {
*dest++ = 0;
}
/* Initialize all of user-space .data */
src = (uint8_t *)USERSPACE->us_datasource;
dest = (uint8_t *)USERSPACE->us_datastart;
end = (uint8_t *)USERSPACE->us_dataend;
while (dest != end) {
*dest++ = *src++;
}
#ifndef TASK_ISOLATION
src = (uint8_t *)&g_service_table_start;
dest = (uint8_t *)SERVICE_TABLE_ADDRESS;
end = (uint8_t *)&g_service_table_end;
while (src != end) {
*dest++ = *src++;
}
#endif
UserInitBoardMemory((void*)USER_MEMORY_START_ADDRESS, (void*)USER_MEMORY_END_ADDRESS);
#ifdef MOMERY_PROTECT_ENABLE
if ( mem_access.Init != NONE){
if(mem_access.Init( (void **)(&isolation)) == EOK)
mem_access.Load(isolation);
}
#endif
return EOK;
#endif
#ifdef APP_STARTUP_FROM_SDCARD
int fd = 0;
char buf[1024] = {0};
int len = 0;
int len_check = 0;
uint8_t *src = NONE;
uint8_t *dest = NONE;
uint8_t *end = NONE;
#ifndef FS_VFS
KPrintf("fs not enable!%s %d\n",__func__,__LINE__);
CHECK(0);
#endif
fd = open(BOARD_APP_NAME,O_RDONLY );
if(fd > 0) {
KPrintf("open app bin %s success.\n",BOARD_APP_NAME);
dest = (uint8_t *)USERSPACE;
/* copy app to USERSPACE */
while(RET_TRUE) {
memset(buf, 0 , 1024);
len = read(fd, buf, 1024);
KPrintf("read app bin len %d\n",len);
if(len > 0) {
memcpy(dest, buf, len);
dest = dest + len;
len_check = len_check + len;
} else {
break;
}
}
if(len_check <= 0){
return -ERROR;
}
dest = (uint8_t *)USERSPACE->us_bssstart;
end = (uint8_t *)USERSPACE->us_bssend;
while (dest != end) {
*dest++ = 0;
}
src = (uint8_t *)&g_service_table_start;
dest = (uint8_t *)SERVICE_TABLE_ADDRESS;
end = (uint8_t *)&g_service_table_end;
while (src != end) {
*dest++ = *src++;
}
close(fd);
UserInitBoardMemory((void*)USER_MEMORY_START_ADDRESS, (void*)USER_MEMORY_END_ADDRESS);
return EOK;
} else {
KPrintf("open app bin %s failed.\n",BOARD_APP_NAME);
return -EEMPTY;
}
#endif
}
#endif
#endif

389
kernel/thread/assign.c Normal file
View File

@@ -0,0 +1,389 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: assign.c
* @brief: system scheduler of single cpu
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#include <xs_assign.h>
#include <xs_ktask_stat.h>
#include <xs_assign.h>
#include <xs_hook.h>
struct Assign Assign;
static struct PriorityReadyVectorDone SingleReadyVectorDone =
{
OsAssignReadyVectorInit,
KTaskInsertToReadyVector,
KTaskOsAssignRemoveKTask,
};
/**
* task schedule function.getting the highest priority task then switching to it
*/
void KTaskOsAssign(void)
{
x_ubase highest_prio = 0;
int need_insert_from_task = 0;
struct TaskDescriptor *new_task = NONE;
struct TaskDescriptor *from_task = NONE;
if(GetOsAssignLockLevel() >= 1) {
return;
}
if( isrManager.done->isInIsr() ){
isrManager.done->setSwitchTrigerFlag();
return;
}
/* if the bitmap is empty then do not switch */
if(RET_TRUE == JudgeAssignReadyBitmapIsEmpty(&Assign.os_assign_read_vector)) {
return;
}
highest_prio = Assign.os_assign_read_vector.highest_prio;
new_task = ChooseTaskWithHighestPrio(&Assign.os_assign_read_vector);
if(RET_TRUE != JudgeKTaskStatIsRunning(Assign.os_running_task)) {
CHECK(NONE != new_task);
goto SWITCH;
}
/* if the running task priority is the highest and this task is not be yield then do not switch */
if(highest_prio < Assign.os_running_task->task_dync_sched_member.cur_prio) {
return;
} else {
need_insert_from_task = 1;
}
SWITCH:
if (new_task != Assign.os_running_task) {
Assign.current_priority = (uint8)highest_prio;
from_task = Assign.os_running_task;
HOOK(hook.assign.hook_Assign, (from_task, new_task));
if (need_insert_from_task) {
Assign.ready_vector_done->insert(from_task);
}
Assign.ready_vector_done->remove(new_task);
KTaskStatSetAsRunning(new_task);
SYS_KDEBUG_LOG(KDBG_SCHED,
("[%d]switch to priority#%d "
"task:%.*s(sp:0x%08x), "
"from task:%.*s(sp: 0x%08x)\n",
isrManager.done->getCounter(), highest_prio,
NAME_NUM_MAX, new_task->task_base_info.name, new_task->stack_point,
NAME_NUM_MAX, from_task->task_base_info.name, from_task->stack_point));
#ifdef KERNEL_STACK_OVERFLOW_CHECK
_KTaskOsAssignStackCheck(new_task);
#endif
SwitchKtaskContext((x_ubase)&from_task->stack_point,
(x_ubase)&new_task->stack_point, new_task);
} else {
Assign.ready_vector_done->remove(Assign.os_running_task);
KTaskStatSetAsRunning(Assign.os_running_task);
}
return;
}
void KTaskOsAssignDoIrqSwitch(void *context)
{
x_ubase highest_prio = 0;
int need_insert_from_task = 0;
struct TaskDescriptor *new_task = NONE;
struct TaskDescriptor *from_task = NONE;
if(GetOsAssignLockLevel() >= 1) {
return;
}
if( isrManager.done->getSwitchTrigerFlag() == 0 ) {
return;
}
isrManager.done->clearSwitchTrigerFlag();
/* if the bitmap is empty then do not switch */
if(RET_TRUE == JudgeAssignReadyBitmapIsEmpty(&Assign.os_assign_read_vector)) {
return;
}
highest_prio = Assign.os_assign_read_vector.highest_prio;
new_task = ChooseTaskWithHighestPrio(&Assign.os_assign_read_vector);
if(RET_TRUE != JudgeKTaskStatIsRunning(Assign.os_running_task)) {
CHECK(NONE != new_task);
goto SWITCH;
}
/* if the running task priority is the highest and this task is not be yield then do not switch */
if(highest_prio < Assign.os_running_task->task_dync_sched_member.cur_prio) {
return;
} else {
need_insert_from_task = 1;
}
SWITCH:
if (new_task != Assign.os_running_task) {
Assign.current_priority = (uint8)highest_prio;
from_task = Assign.os_running_task;
HOOK(hook.assign.hook_Assign, (from_task, new_task));
if (need_insert_from_task) {
Assign.ready_vector_done->insert(from_task);
}
Assign.ready_vector_done->remove(new_task);
KTaskStatSetAsRunning(new_task);
SYS_KDEBUG_LOG(KDBG_SCHED,
("[%d]switch to priority#%d "
"task:%.*s(sp:0x%08x), "
"from task:%.*s(sp: 0x%08x)\n",
isrManager.done->getCounter(), highest_prio,
NAME_NUM_MAX, new_task->task_base_info.name, new_task->stack_point,
NAME_NUM_MAX, from_task->task_base_info.name, from_task->stack_point));
#ifdef KERNEL_STACK_OVERFLOW_CHECK
_KTaskOsAssignStackCheck(new_task);
#endif
SYS_KDEBUG_LOG(KDBG_SCHED, ("switch in interrupt\n"));
HwInterruptcontextSwitch((x_ubase)&from_task->stack_point,
(x_ubase)&new_task->stack_point, new_task, context);
} else {
Assign.ready_vector_done->remove(Assign.os_running_task);
KTaskStatSetAsRunning(Assign.os_running_task);
}
}
void KTaskOsAssignAfterIrq(void *context)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
KTaskOsAssignDoIrqSwitch(context);
ENABLE_INTERRUPT(lock);
}
/*
* insert a ready task to system ready table with READY state and remove it from suspend list
*
* @param task the task descriptor
*
*/
void KTaskInsertToReadyVector(struct TaskDescriptor *task)
{
x_base lock = 0;
NULL_PARAM_CHECK(task);
lock = DISABLE_INTERRUPT();
KTaskStatSetAsReady(task);
AssignPolicyInsert(task, &Assign.os_assign_read_vector);
SYS_KDEBUG_LOG(KDBG_SCHED, ("insert task[%.*s], the priority: %d\n",
NAME_NUM_MAX, task->task_base_info.name, task->task_dync_sched_member.cur_prio));
#if KTASK_PRIORITY_MAX > 32
MERGE_FLAG(&Assign.os_assign_read_vector.ready_vector[task->task_dync_sched_member.bitmap_offset], task->task_dync_sched_member.bitmap_row);
#endif
MERGE_FLAG(&Assign.os_assign_read_vector.priority_ready_group, task->task_dync_sched_member.bitmap_column);
ENABLE_INTERRUPT(lock);
}
/*
* a task will be removed from ready table.
*
* @param task task descriptor
*
*/
void KTaskOsAssignRemoveKTask(struct TaskDescriptor *task)
{
x_base lock = 0;
x_ubase number = 0;
x_ubase highest_priority = 0;
NULL_PARAM_CHECK(task);
lock = DISABLE_INTERRUPT();
SYS_KDEBUG_LOG(KDBG_SCHED, ("remove task[%.*s], the priority: %d\n",
NAME_NUM_MAX, task->task_base_info.name,
task->task_dync_sched_member.cur_prio));
DoubleLinkListRmNode(&(task->task_dync_sched_member.sched_link));
if (IsDoubleLinkListEmpty(&(Assign.os_assign_read_vector.priority_ready_vector[task->task_dync_sched_member.cur_prio]))) {
#if KTASK_PRIORITY_MAX > 32
CLEAR_FLAG(&Assign.os_assign_read_vector.ready_vector[task->task_dync_sched_member.bitmap_offset], task->task_dync_sched_member.bitmap_row);
if (Assign.os_assign_read_vector.ready_vector[task->task_dync_sched_member.bitmap_offset] == 0) {
CLEAR_FLAG(&Assign.os_assign_read_vector.priority_ready_group, task->task_dync_sched_member.bitmap_column);
}
number = PrioCaculate(Assign.os_assign_read_vector.priority_ready_group);
highest_priority = (number * 8) + PrioCaculate(Assign.os_assign_read_vector.ready_vector[number]);
#else
CLEAR_FLAG(&Assign.os_assign_read_vector.priority_ready_group, task->task_dync_sched_member.bitmap_column);
highest_priority = PrioCaculate(Assign.os_assign_read_vector.priority_ready_group);
#endif
Assign.os_assign_read_vector.highest_prio = highest_priority;
}
ENABLE_INTERRUPT(lock);
}
static inline void SwitchToFirstRunningTask(struct TaskDescriptor* task)
{
NULL_PARAM_CHECK(task);
Assign.ready_vector_done->remove(task);
KTaskStatSetAsRunning(task);
SwitchKtaskContextTo((x_ubase)&task->stack_point, task);
}
static inline void SetSystemRunningTask(struct TaskDescriptor* task)
{
NULL_PARAM_CHECK(task);
Assign.os_running_task = task;
}
/**
* This function will yield current task.
*
* @return EOK
*/
x_err_t YieldOsAssign(void)
{
x_base lock = 0;
x_ubase highest_prio = 0;
struct TaskDescriptor *new_task = NONE;
struct TaskDescriptor *from_task = NONE;
lock = DISABLE_INTERRUPT();
if(GetOsAssignLockLevel() >= 1) {
ENABLE_INTERRUPT(lock);
goto __exit;
}
if (isrManager.done->isInIsr()) {
ENABLE_INTERRUPT(lock);
goto __exit;
}
/* if the bitmap is empty then do not switch */
if(RET_TRUE == JudgeAssignReadyBitmapIsEmpty(&Assign.os_assign_read_vector)) {
ENABLE_INTERRUPT(lock);
return -ERROR;
}
highest_prio = Assign.os_assign_read_vector.highest_prio;
new_task = ChooseTaskWithHighestPrio(&Assign.os_assign_read_vector);
from_task = Assign.os_running_task;
if(RET_TRUE != JudgeKTaskStatIsRunning(from_task)) {
CHECK(NONE != new_task);
} else {
Assign.ready_vector_done->insert(from_task);
}
if (new_task != from_task) {
Assign.current_priority = (uint8)highest_prio;
HOOK(hook.assign.hook_Assign, (from_task, new_task));
Assign.ready_vector_done->remove(new_task);
KTaskStatSetAsRunning(new_task);
SYS_KDEBUG_LOG(KDBG_SCHED,
("[%d]switch to priority#%d "
"task:%.*s(sp:0x%08x), "
"from task:%.*s(sp: 0x%08x)\n",
isrManager.done->getCounter(), highest_prio,
NAME_NUM_MAX, new_task->task_base_info.name, new_task->stack_point,
NAME_NUM_MAX, from_task->task_base_info.name, from_task->stack_point));
#ifdef KERNEL_STACK_OVERFLOW_CHECK
_KTaskOsAssignStackCheck(new_task);
#endif
SwitchKtaskContext((x_ubase)&from_task->stack_point,
(x_ubase)&new_task->stack_point, new_task);
ENABLE_INTERRUPT(lock);
goto __exit;
} else {
Assign.ready_vector_done->remove(Assign.os_running_task);
KTaskStatSetAsRunning(Assign.os_running_task);
}
ENABLE_INTERRUPT(lock);
__exit:
return EOK;
}
/**
*
* OsAssign startup function
* .
*/
void StartupOsAssign(void)
{
struct TaskDescriptor *FirstRunningTask = NONE;
FirstRunningTask = ChooseTaskWithHighestPrio(&Assign.os_assign_read_vector);
SetSystemRunningTask(FirstRunningTask);
SwitchToFirstRunningTask(FirstRunningTask);
}
/**
*
* system OsAssign init function
*/
void SysInitOsAssign(void)
{
SYS_KDEBUG_LOG(KDBG_SCHED, ("start Os Assign: max priority 0x%02x\n",
KTASK_PRIORITY_MAX));
Assign.ready_vector_done = &SingleReadyVectorDone;
Assign.ready_vector_done->init(&Assign.os_assign_read_vector);
ResetCriticalAreaLock();
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: assign_roundrobin.c
* @brief: ready table and timeslice functions definitions of fifo scheduler algorithm
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#define NO_TIMESLICE (0)
void FifoTaskTimesliceInit(struct TaskDescriptor *task)
{
NULL_PARAM_CHECK(task);
task->task_dync_sched_member.origin_timeslice = NO_TIMESLICE;
task->task_dync_sched_member.rest_timeslice = NO_TIMESLICE;
}
void FifoReadyVectorInsert(struct TaskDescriptor *task, struct OsAssignReadyVector* ready_table)
{
DoubleLinklistType* tail = NONE;
NULL_PARAM_CHECK(task);
NULL_PARAM_CHECK(ready_table);
tail = ready_table->priority_ready_vector[task->task_dync_sched_member.cur_prio].node_prev;
DoubleLinkListInsertNodeAfter(tail, &(task->task_dync_sched_member.sched_link));
}
void FifoTaskTimesliceUpdate()
{
return;
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: assign_roundrobin.c
* @brief: ready table and timeslice functions definitions of roundrobin scheduler algorithm
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
void RoundRobinTaskTimesliceInit(struct TaskDescriptor *task)
{
NULL_PARAM_CHECK(task);
task->task_dync_sched_member.origin_timeslice = 10;
task->task_dync_sched_member.rest_timeslice = 10;
}
void RoundRobinReadyVectorInsert(struct TaskDescriptor *task, struct OsAssignReadyVector* ready_table)
{
DoubleLinklistType* tail = NONE;
NULL_PARAM_CHECK(task);
NULL_PARAM_CHECK(ready_table);
tail = ready_table->priority_ready_vector[task->task_dync_sched_member.cur_prio].node_prev;
DoubleLinkListInsertNodeAfter(tail, &(task->task_dync_sched_member.sched_link));
}
void RoundRobinTaskTimesliceUpdate(struct TaskDescriptor *task)
{
NULL_PARAM_CHECK(task);
-- task->task_dync_sched_member.rest_timeslice;
if (task->task_dync_sched_member.rest_timeslice == 0)
{
task->task_dync_sched_member.rest_timeslice = task->task_dync_sched_member.origin_timeslice;
DO_KTASK_ASSIGN;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: assign_roundrobin.c
* @brief: ready table and timeslice functions definitions of remain ticks first scheduler algorithm
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
void RoundRobinRemainTaskTimesliceInit(struct TaskDescriptor *task)
{
NULL_PARAM_CHECK(task);
task->task_dync_sched_member.origin_timeslice = 10;
task->task_dync_sched_member.rest_timeslice = 10;
}
void RoundRobinRemainReadyVectorInsert(struct TaskDescriptor *task, struct OsAssignReadyVector* ready_table)
{
DoubleLinklistType* node = NONE;
DoubleLinklistType* tail = NONE;
struct TaskDescriptor *tmp = NONE;
NULL_PARAM_CHECK(task);
NULL_PARAM_CHECK(ready_table);
if ( task->task_dync_sched_member.advance_cnt < KTASK_MAX_ADVANCE_PROCESS_TIME ) {
DOUBLE_LINKLIST_FOR_EACH(node, &ready_table->priority_ready_vector[task->task_dync_sched_member.cur_prio]) {
tmp = SYS_DOUBLE_LINKLIST_ENTRY(node, struct TaskDescriptor, task_dync_sched_member.sched_link);
if (task->task_dync_sched_member.rest_timeslice < tmp->task_dync_sched_member.rest_timeslice) {
break;
}
}
if ( node != &ready_table->priority_ready_vector[task->task_dync_sched_member.cur_prio]) {
DoubleLinkListInsertNodeBefore(node, &(task->task_dync_sched_member.sched_link));
} else {
tail = ready_table->priority_ready_vector[task->task_dync_sched_member.cur_prio].node_prev;
DoubleLinkListInsertNodeAfter(tail, &(task->task_dync_sched_member.sched_link));
}
} else {
tail = ready_table->priority_ready_vector[task->task_dync_sched_member.cur_prio].node_prev;
DoubleLinkListInsertNodeAfter(tail, &(task->task_dync_sched_member.sched_link));
}
}
void RoundRobinRemainTaskTimesliceUpdate(struct TaskDescriptor *task)
{
NULL_PARAM_CHECK(task);
-- task->task_dync_sched_member.rest_timeslice;
if (task->task_dync_sched_member.rest_timeslice == 0)
{
if ( task->task_dync_sched_member.advance_cnt < KTASK_MAX_ADVANCE_PROCESS_TIME ) {
task->task_dync_sched_member.advance_cnt++;
}
task->task_dync_sched_member.rest_timeslice = task->task_dync_sched_member.origin_timeslice;
DO_KTASK_ASSIGN;
}
}

112
kernel/thread/assignstat.c Normal file
View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: assignstat.c
* @brief: check system read ready and task stack
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xs_assign.h>
#ifdef KERNEL_STACK_OVERFLOW_CHECK
/**
* a task stack check function
*
* @param task task descriptor
*/
void _KTaskOsAssignStackCheck(struct TaskDescriptor *task)
{
NULL_PARAM_CHECK(task);
if ((x_ubase)task->stack_point<= (x_ubase)task->task_base_info.stack_start ||
(x_ubase)task->stack_point >
(x_ubase)task->task_base_info.stack_start + (x_ubase)task->task_base_info.stack_depth) {
KPrintf("task name:%s id:%d stack overflow,sp %p stacktop %p stack depth 0x%x\n", task->task_base_info.name,task->id.id,task->stack_point,(uint32*)task->task_base_info.stack_start + task->task_base_info.stack_depth,task->task_base_info.stack_depth);
while (1);
}
}
#endif
int32 JudgeAssignReadyBitmapIsEmpty(struct OsAssignReadyVector *ready_vector)
{
NULL_PARAM_CHECK(ready_vector);
return ((ready_vector->priority_ready_group == 0) ? RET_TRUE: 0);
}
struct TaskDescriptor * ChooseTaskWithHighestPrio(struct OsAssignReadyVector *ready_vector)
{
struct TaskDescriptor *TargetTask = NONE;
NULL_PARAM_CHECK(ready_vector);
TargetTask = SYS_DOUBLE_LINKLIST_ENTRY(ready_vector->priority_ready_vector[ready_vector->highest_prio].node_next,
struct TaskDescriptor,
task_dync_sched_member.sched_link);
return TargetTask;
}
void OsAssignReadyVectorInit(struct OsAssignReadyVector *ready_vector)
{
register x_base prio = 0;
NULL_PARAM_CHECK(ready_vector);
while(prio < KTASK_PRIORITY_MAX)
{
InitDoubleLinkList(&ready_vector->priority_ready_vector[prio]);
prio++;
}
ready_vector->highest_prio = 0;
ready_vector->priority_ready_group = 0;
#if KTASK_PRIORITY_MAX > 32
memset(ready_vector->ready_vector, 0, sizeof(ready_vector->ready_vector));
#endif
}
/*
* This function will insert a task to system ready table according to sched policy(FIFO/RR/RR+remain timeslice)
*
* @param task task descriptor
* @param ready_table task ready_table
*/
void AssignPolicyInsert(struct TaskDescriptor *task, struct OsAssignReadyVector* ready_table)
{
DoubleLinklistType* node = NONE;
DoubleLinklistType* tail = NONE;
struct TaskDescriptor *tmp = NONE;
NULL_PARAM_CHECK(task);
NULL_PARAM_CHECK(ready_table);
#if defined (SCHED_POLICY_FIFO)
FifoReadyVectorInsert(task, ready_table);
#elif defined (SCHED_POLICY_RR)
RoundRobinReadyVectorInsert(task, ready_table);
#elif defined (SCHED_POLICY_RR_REMAINSLICE)
RoundRobinRemainReadyVectorInsert(task, ready_table);
#endif
if(NONE == task || NONE == ready_table) {
KPrintf("PARAM CHECK FAILED ...%s %d param is NULL.\n",__FUNCTION__,__LINE__);
return;
}
if(task->task_dync_sched_member.cur_prio > ready_table->highest_prio) {
ready_table->highest_prio = task->task_dync_sched_member.cur_prio;
}
}

369
kernel/thread/avl_tree.c Normal file
View File

@@ -0,0 +1,369 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: avl_tree.c
* @brief: avl_tree file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include "xs_avltree.h"
#include <string.h>
#include <xs_kdbg.h>
#include <xs_klist.h>
#include <xs_memory.h>
/**
* This function will return the node height of the avl tree
*
* @param avl_node avl tree node descriptor
* @return 0
*/
static uint32 AvlTreeGetNodeHeight(AvlNodeType avl_node)
{
if(avl_node) {
return AVL_MAX(AvlTreeGetNodeHeight(avl_node->left), AvlTreeGetNodeHeight(avl_node->right)) + 1;
} else {
return 0;
}
}
/**
* This function will return the node balance factor of the avl tree
*
* @param avl_node avl tree node descriptor
*/
static int32 AvlTreeGetNodeBalanceFactor(AvlNodeType avl_node)
{
if(avl_node) {
return AvlTreeGetNodeHeight(avl_node->left) - AvlTreeGetNodeHeight(avl_node->right);
} else {
return 0;
}
}
/**
* This function will support right rotate to balance the avl tree(eg. LL case)
*
* @param avl_node avl tree node descriptor
* @return avl tree node
*/
static AvlNodeType AvlTreeSetRightRotate(AvlNodeType avl_node)
{
NULL_PARAM_CHECK(avl_node);
AvlNodeType new_node = avl_node->left;
avl_node->left = new_node->right;
new_node->right = avl_node;
new_node->height = AVL_MAX(AvlTreeGetNodeHeight(new_node->left), AvlTreeGetNodeHeight(new_node->right)) + 1;
avl_node->height = AVL_MAX(AvlTreeGetNodeHeight(avl_node->left), AvlTreeGetNodeHeight(avl_node->right)) + 1;
return new_node;
}
/**
* This function will support left rotate to balance the avl tree(eg. RR case)
*
* @param avl_node avl tree node descriptor
* @return avl tree node
*/
static AvlNodeType AvlTreeSetLeftRotate(AvlNodeType avl_node)
{
NULL_PARAM_CHECK(avl_node);
AvlNodeType new_node = avl_node->right;
avl_node->right = new_node->left;
new_node->left = avl_node;
new_node->height = AVL_MAX(AvlTreeGetNodeHeight(new_node->left), AvlTreeGetNodeHeight(new_node->right)) + 1;
avl_node->height = AVL_MAX(AvlTreeGetNodeHeight(avl_node->left), AvlTreeGetNodeHeight(avl_node->right)) + 1;
return new_node;
}
/**
* This function will support left and right rotate to balance the avl tree(eg. LR case)
*
* @param avl_node avl tree node descriptor
* @return avl tree node
*/
static AvlNodeType AvlTreeSetLRRotate(AvlNodeType avl_node)
{
NULL_PARAM_CHECK(avl_node);
AvlNodeType new_node = NONE;
AvlNodeType left_node = avl_node->left;
/*step1 : Left rotate*/
avl_node->left = AvlTreeSetLeftRotate(left_node);
/*step2 : Right rotate*/
new_node = AvlTreeSetRightRotate(avl_node);
return new_node;
}
/**
* This function will support right and left rotate to balance the avl tree(eg. RL case)
*
* @param avl_node avl tree node descriptor
* @return avl tree node
*/
static AvlNodeType AvlTreeSetRLRotate(AvlNodeType avl_node)
{
NULL_PARAM_CHECK(avl_node);
AvlNodeType new_node = NONE;
AvlNodeType right_node = avl_node->right;
/*step1 : Right rotate*/
avl_node->right = AvlTreeSetRightRotate(right_node);
/*step2 : Left rotate*/
new_node = AvlTreeSetLeftRotate(avl_node);
return new_node;
}
/**
* This function will balance the avl tree when inserting or deleting node
*
* @param avl_node avl tree node descriptor
* @return avl tree node
*/
static AvlNodeType AvlTreeBalance(AvlNodeType avl_node)
{
if(avl_node)
{
AvlNodeType new_node = NONE;
uint32 avlnode_BF = AVL_ABS(AvlTreeGetNodeBalanceFactor(avl_node));
if(avlnode_BF > 1) {
if(AvlTreeGetNodeBalanceFactor(avl_node->left) > 0) {
/*LL case*/
new_node = AvlTreeSetRightRotate(avl_node);
} else if(AvlTreeGetNodeBalanceFactor(avl_node->left) < 0) {
/*LR case*/
new_node = AvlTreeSetLRRotate(avl_node);
} else if(AvlTreeGetNodeBalanceFactor(avl_node->right) < 0) {
/*RR case*/
new_node = AvlTreeSetLeftRotate(avl_node);
} else if(AvlTreeGetNodeBalanceFactor(avl_node->right) > 0) {
/*RL case*/
new_node = AvlTreeSetRLRotate(avl_node);
}
} else {
/*the avl tree is balanced, no need to rebalance*/
new_node = avl_node;
}
return new_node;
} else {
return NONE;
}
}
/**
* This function will insert data to the avl tree
*
* @param avl_node avl tree node descriptor
* @param data input data
*/
AvlNodeType AvlTreeInsertNode(AvlNodeType avl_node, int32 data)
{
AvlNodeType new_node = NONE;
if(NONE == avl_node) {
new_node = x_malloc(sizeof(struct AvlNode));
if(NONE == new_node) {
KPrintf("AvlTreeInsertNode malloc AvlNode failed\n");
x_free(new_node);
return NONE;
}
new_node->data = data;
new_node->left = NONE;
new_node->right = NONE;
new_node->height = 1;
avl_node = new_node;
} else if(data == avl_node->data) {
/*input data is already existed*/
KPrintf("the input data is already existed. just return\n");
return avl_node;
} else {
if(avl_node->data < data) {
avl_node->right = AvlTreeInsertNode(avl_node->right, data);
if(NONE == avl_node->right) {
KPrintf("AvlTreeInsertNode find right avl_node data failed\n");
return NONE;
}
} else {
avl_node->left = AvlTreeInsertNode(avl_node->left, data);
if(NONE == avl_node->left) {
KPrintf("AvlTreeInsertNode find left avl_node data failed\n");
return NONE;
}
}
}
return AvlTreeBalance(avl_node);
}
/**
* This function will find the pre node of the avl_node
*
* @param avl_node avl tree node descriptor
* @return avl tree node
*/
static AvlNodeType AvlTreeFindPreNode(AvlNodeType avl_node)
{
NULL_PARAM_CHECK(avl_node);
AvlNodeType pre_node = NONE;
if(avl_node->left) {
if(avl_node->left->right) {
pre_node = avl_node->left->right;
while(pre_node->right) {
pre_node = pre_node->right;
}
} else {
pre_node = avl_node->left;
}
} else {
pre_node = avl_node;
}
return pre_node;
}
/**
* This function will delete a certain node, ultimate target is to find the leaf node
*
* @param avl_node avl tree node descriptor
* @param data delete data
* @return avl tree node
*/
static AvlNodeType AvlTreeDeleteLeafNode(AvlNodeType avl_node)
{
AvlNodeType pre_node = NONE;
if((NONE == avl_node->left) && (NONE == avl_node->right)) {
/*Leaf Node*/
avl_node = NONE;
x_free(avl_node);
} else if(NONE == avl_node->left) {
/*Right child is Leaf Node*/
avl_node->data = avl_node->right->data;
avl_node->right = NONE;
x_free(avl_node->right);
} else if(NONE == avl_node->right) {
/*Left child is Leaf Node*/
avl_node->data = avl_node->left->data;
avl_node->left = NONE;
x_free(avl_node->left);
} else {
/*Find the pre node to replace the avl node, then delete the pre node*/
pre_node = AvlTreeFindPreNode(avl_node);
if(pre_node) {
avl_node->data = pre_node->data;
avl_node->left = AvlTreeDeleteNode(avl_node->left, pre_node->data);
}
}
return avl_node;
}
/**
* This function will delete data from the avl tree
*
* @param avl_node avl tree node descriptor
* @param data delete data
*/
AvlNodeType AvlTreeDeleteNode(AvlNodeType avl_node, int32 data)
{
if(avl_node) {
if(data == avl_node->data) {
avl_node = AvlTreeDeleteLeafNode(avl_node);
} else {
if(avl_node->data < data) {
avl_node->right = AvlTreeDeleteNode(avl_node->right, data);
} else {
avl_node->left = AvlTreeDeleteNode(avl_node->left, data);
}
}
return AvlTreeBalance(avl_node);
} else {
KPrintf("AvlTreeDeleteNode cannot find the delete data\n");
return NONE;
}
}
/**
* This function will modify certain data of the avl tree
*
* @param avl_node avl tree node descriptor
* @param src_data src data
* @param dst_data dst data
*/
AvlNodeType AvlNodeModifyNode(AvlNodeType avl_node, int32 src_data, int32 dst_data)
{
AvlNodeType dst_node = NONE;
if(avl_node) {
/*Step1 : delete the src data node*/
avl_node = AvlTreeDeleteNode(avl_node, src_data);
/*Step2 : insert the dst data node*/
dst_node = AvlTreeInsertNode(avl_node, dst_data);
} else {
KPrintf("AvlNodeModifyNode cannot find the src data node\n");
return NONE;
}
return dst_node;
}
/**
* This function will return the avl node which has the data
*
* @param avl_node avl tree node descriptor
* @param data data
*/
AvlNodeType AvlNodeSearchNode(AvlNodeType avl_node, int32 data)
{
AvlNodeType dst_node = NONE;
if(avl_node) {
if(data == avl_node->data) {
dst_node = avl_node;
KPrintf("AvlNodeSearchNode %d is existed return the node\n", avl_node->data);
} else if(avl_node->data < data) {
dst_node = AvlNodeSearchNode(avl_node->right, data);
} else {
dst_node = AvlNodeSearchNode(avl_node->left, data);
}
} else {
KPrintf("AvlNodeSearchNode avl_node is NONE.\n");
return NONE;
}
return dst_node;
}

50
kernel/thread/banner.c Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: banner.c
* @brief: system banner
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/15
*
*/
#include <xs_banner.h>
/**
* This function will show the version of XiUOS
*/
void ShowBanner(void)
{
KPrintf("*********************************************************************************************\n");
KPrintf("AAAAAAA AAAAAAA IIIIIIII IIIIIIII IIIIIIIII TTTTTTTTTTTTTTT \n");
KPrintf("A:::::A A:::::A I::::::I I::::::I II:::::::::II TT:::::::::::::::T \n");
KPrintf("A:::::A A:::::A iiii I::::::I I::::::I II:::::::::::::II T:::::TTTTTT::::::T \n");
KPrintf("A::::::A A::::::A i::::i II:::::I I:::::III:::::::III:::::::IT:::::T TTTTTTT\n");
KPrintf("AAA:::::A A:::::AAA iiii I:::::I I:::::I I::::::I I::::::IT:::::T \n");
KPrintf(" A:::::A A:::::A I:::::I I:::::I I:::::I I:::::IT:::::T \n");
KPrintf(" A:::::A:::::A iiiiiii I:::::I I:::::I I:::::I I:::::I T::::TTTT \n");
KPrintf(" A:::::::::A i:::::i I:::::I I:::::I I:::::I I:::::I TT::::::TTTTT \n");
KPrintf(" A:::::::::A i::::i I:::::I I:::::I I:::::I I:::::I TTT::::::::TT \n");
KPrintf(" A:::::A:::::A i::::i I:::::I I:::::I I:::::I I:::::I TTTTTT::::T \n");
KPrintf(" A:::::A A:::::A i::::i I:::::I I:::::I I:::::I I:::::I T:::::T\n");
KPrintf("AAA:::::A A:::::AAA i::::i I::::::I I::::::I I::::::I I::::::I T:::::T\n");
KPrintf("A::::::A A::::::A i::::i I:::::::III:::::::I I:::::::III:::::::ITTTTTTT T:::::T\n");
KPrintf("A:::::A A:::::A i::::i II:::::::::::::II II:::::::::::::II T::::::TTTTTT:::::T \n");
KPrintf("A:::::A A:::::A i::::::i II:::::::::II II:::::::::II T:::::::::::::::TT \n");
KPrintf("AAAAAAA AAAAAAA iiiiiiii IIIIIIIII IIIIIIIII TTTTTTTTTTTTTTT \n");
KPrintf("*********************************************************************************************\n");
KPrintf("*********************-----X Industrial Ubiquitous Operating System-----**********************\n");
KPrintf("***************************2021 Copyright AIIT Ubiquitous-OS Team****************************\n");
KPrintf("*********************************************************************************************\n");
}

66
kernel/thread/bitmap.c Normal file
View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: bitmap.c
* @brief: calculate the highest priority
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xs_assign.h>
const uint8 LeaderZeroCount[] =
{
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int PrioCaculate(uint32 bitmap)
{
if (bitmap & 0xff000000)
{
return 31 - LeaderZeroCount[(bitmap & 0xff000000) >> 24];
}
else if (bitmap & 0xff0000)
{
return 23 - LeaderZeroCount[(bitmap & 0xff0000) >> 16];
}
else if (bitmap & 0xff00)
{
return 15 - LeaderZeroCount[(bitmap & 0xff00) >> 8];
}
else if (bitmap & 0xff)
{
return 7 - LeaderZeroCount[bitmap & 0xff];
}
else
{
return 0;
}
}

View File

@@ -0,0 +1,279 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: circular_area.c
* @brief: circular area file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include "xs_circular_area.h"
#include <string.h>
#include <xs_kdbg.h>
#include <xs_klist.h>
#include <xs_memory.h>
/**
* This function will return whether the circular_area is full or not
*
* @param circular_area CircularArea descriptor
*/
x_bool CircularAreaIsFull(CircularAreaType circular_area)
{
NULL_PARAM_CHECK(circular_area);
if((circular_area->readidx == circular_area->writeidx) && (circular_area->b_status)) {
KPrintf("the circular area is full\n");
return RET_TRUE;
} else {
return RET_FALSE;
}
}
/**
* This function will return whether the circular_area is empty or not
*
* @param circular_area CircularArea descriptor
*/
x_bool CircularAreaIsEmpty(CircularAreaType circular_area)
{
NULL_PARAM_CHECK(circular_area);
if((circular_area->readidx == circular_area->writeidx) && (!circular_area->b_status)) {
KPrintf("the circular area is empty\n");
return RET_TRUE;
} else {
return RET_FALSE;
}
}
/**
* This function will reset the circular_area and set the descriptor to default
*
* @param circular_area CircularArea descriptor
*/
void CircularAreaReset(CircularAreaType circular_area)
{
circular_area->writeidx = 0;
circular_area->readidx = 0;
circular_area->b_status = RET_FALSE;
}
/**
* This function will release the circular_area descriptor and free the memory
*
* @param circular_area CircularArea descriptor
*/
void CircularAreaRelease(CircularAreaType circular_area)
{
circular_area->readidx = 0;
circular_area->writeidx = 0;
circular_area->p_head = NONE;
circular_area->p_tail = NONE;
circular_area->b_status = RET_FALSE;
circular_area->area_length = 0;
x_free(circular_area->data_buffer);
x_free(circular_area);
}
/**
* This function will get the circual_area max length
*
* @param circular_area CircularArea descriptor
*/
uint32 CircularAreaGetMaxLength(CircularAreaType circular_area)
{
NULL_PARAM_CHECK(circular_area);
return circular_area->area_length;
}
/**
* This function will get the data length of the circular_area
*
* @param circular_area CircularArea descriptor
*/
uint32 CircularAreaGetDataLength(CircularAreaType circular_area)
{
NULL_PARAM_CHECK(circular_area);
if(CircularAreaIsFull(circular_area)) {
return circular_area->area_length;
} else {
return (circular_area->writeidx - circular_area->readidx + circular_area->area_length) % circular_area->area_length;
}
}
/**
* This function will return whether it is need to divide the read data into two parts or not
*
* @param circular_area CircularArea descriptor
* @param data_length output data length
*/
static uint32 CircularAreaDivideRdData(CircularAreaType circular_area, uint32 data_length)
{
NULL_PARAM_CHECK(circular_area);
if(circular_area->readidx + data_length <= circular_area->area_length) {
return RET_FALSE;
} else {
return RET_TRUE;
}
}
/**
* This function will return whether it is need to divide the write data into two parts or not
*
* @param circular_area CircularArea descriptor
* @param data_length input data length
*/
static uint32 CircularAreaDivideWrData(CircularAreaType circular_area, uint32 data_length)
{
NULL_PARAM_CHECK(circular_area);
if(circular_area->writeidx + data_length <= circular_area->area_length) {
return RET_FALSE;
} else {
return RET_TRUE;
}
}
/**
* This function will read data from the circular_area
*
* @param circular_area CircularArea descriptor
* @param output_buffer output data buffer poniter
* @param data_length output data length
*/
uint32 CircularAreaRead(CircularAreaType circular_area, uint8 *output_buffer, uint32 data_length)
{
NULL_PARAM_CHECK(circular_area);
NULL_PARAM_CHECK(output_buffer);
CHECK(data_length > 0);
if(CircularAreaIsEmpty(circular_area)) {
return ERROR;
}
data_length = (data_length > CircularAreaGetDataLength(circular_area)) ? CircularAreaGetDataLength(circular_area) : data_length;
if(CircularAreaDivideRdData(circular_area, data_length)) {
uint32 read_len_up = circular_area->area_length - circular_area->readidx;
uint32 read_len_down = data_length - read_len_up;
memcpy(output_buffer, &circular_area->data_buffer[circular_area->readidx], read_len_up);
memcpy(output_buffer + read_len_up, circular_area->p_head, read_len_down);
circular_area->readidx = read_len_down;
} else {
memcpy(output_buffer, &circular_area->data_buffer[circular_area->readidx], data_length);
circular_area->readidx = (circular_area->readidx + data_length) % circular_area->area_length;
}
circular_area->b_status = RET_FALSE;
return EOK;
}
/**
* This function will write data to the circular_area
*
* @param circular_area CircularArea descriptor
* @param input_buffer input data buffer poniter
* @param data_length input data length
* @param b_force whether to force to write data disregard the length limit
*/
uint32 CircularAreaWrite(CircularAreaType circular_area, uint8 *input_buffer, uint32 data_length, x_bool b_force)
{
NULL_PARAM_CHECK(circular_area);
NULL_PARAM_CHECK(input_buffer);
CHECK(data_length > 0);
if(CircularAreaIsFull(circular_area) && (!b_force)) {
return ERROR;
}
uint32 write_data_length = circular_area->area_length - CircularAreaGetDataLength(circular_area);
data_length = (data_length > write_data_length) ? write_data_length : data_length;
if(CircularAreaDivideWrData(circular_area, data_length)) {
uint32 write_len_up = circular_area->area_length - circular_area->writeidx;
uint32 write_len_down = data_length - write_len_up;
memcpy(&circular_area->data_buffer[circular_area->writeidx], input_buffer, write_len_up);
memcpy(circular_area->p_head, input_buffer + write_len_up, write_len_down);
circular_area->writeidx = write_len_down;
} else {
memcpy(&circular_area->data_buffer[circular_area->writeidx], input_buffer, data_length);
circular_area->writeidx = (circular_area->writeidx + data_length) % circular_area->area_length;
}
circular_area->b_status = RET_TRUE;
if(b_force) {
circular_area->readidx = circular_area->writeidx;
}
return EOK;
}
static struct CircularAreaOps CircularAreaOperations =
{
CircularAreaRead,
CircularAreaWrite,
CircularAreaRelease,
CircularAreaReset,
};
/**
* This function will initialize the circular_area
*
* @param circular_area_length circular_area length
*/
CircularAreaType CircularAreaInit(uint32 circular_area_length)
{
CHECK(circular_area_length > 0);
circular_area_length = ALIGN_MEN_DOWN(circular_area_length, MEM_ALIGN_SIZE);
CircularAreaType circular_area = x_malloc(sizeof(struct CircularArea));
if(NONE == circular_area) {
KPrintf("CircularAreaInit malloc struct circular_area failed\n");
x_free(circular_area);
return NONE;
}
CircularAreaReset(circular_area);
circular_area->data_buffer = x_malloc(circular_area_length);
if(NONE == circular_area->data_buffer) {
KPrintf("CircularAreaInit malloc circular_area data_buffer failed\n");
x_free(circular_area->data_buffer);
return NONE;
}
circular_area->p_head = circular_area->data_buffer;
circular_area->p_tail = circular_area->data_buffer + circular_area_length;
circular_area->area_length = circular_area_length;
KPrintf("CircularAreaInit done p_head %8p p_tail %8p length %u\n",
circular_area->p_head, circular_area->p_tail, circular_area->area_length);
circular_area->CircularAreaOperations = &CircularAreaOperations;
return circular_area;
}

685
kernel/thread/console.c Normal file
View File

@@ -0,0 +1,685 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: console.c
* @brief: console file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#include <device.h>
#if defined(KERNEL_CONSOLE)
static HardwareDevType _console = NONE;
#endif
/**
* Obtain the console
*
*/
HardwareDevType ObtainConsole(void)
{
#if defined(KERNEL_CONSOLE)
return _console;
#endif
}
/**
* Setup a console
*
*
* @param name console device name
*
*/
HardwareDevType InstallConsole(const char *bus_name, const char *drv_name, const char *dev_name)
{
#if defined(KERNEL_CONSOLE)
BusType console_bus;
DriverType console_drv = NONE;
HardwareDevType console = NONE;
struct SerialDevParam *serial_dev_param = NONE;
struct SerialCfgParam serial_cfg;
struct BusConfigureInfo configure_info;
NULL_PARAM_CHECK(bus_name);
NULL_PARAM_CHECK(drv_name);
NULL_PARAM_CHECK(dev_name);
console_bus = BusFind(bus_name);
console_drv = BusFindDriver(console_bus, drv_name);
console = BusFindDevice(console_bus, dev_name);
if (console != NONE) {
if (_console != NONE) {
BusDevClose(_console);
}
configure_info.configure_cmd = OPE_INT;
memset(&serial_cfg, 0, sizeof(struct SerialCfgParam));
configure_info.private_data = &serial_cfg;
BusDrvConfigure(console_drv, &configure_info);
console_bus->match(console_drv, console);
serial_dev_param = (struct SerialDevParam *)console->private_data;
serial_dev_param->serial_set_mode = 0;
serial_dev_param->serial_stream_mode = SIGN_OPER_STREAM;
BusDevOpen(console);
_console = console;
} else {
console = _console;
}
return console;
#endif
}
#if defined(KERNEL_CONSOLE)
static __inline x_bool IsDigit(char c)
{
return ((unsigned)((c) - '0') < 10);
}
static __inline unsigned int CharToNum(const char **s)
{
unsigned int i = 0;
while (IsDigit(**s)) {
i = i * 10 + **s - '0';
++ *s;
}
return i;
}
#define ZEROPAD (1 << 0)
#define LEFT (1 << 1)
#define SIGN (1 << 2)
#define SPACE (1 << 3)
#define HASH (1 << 4)
#define PRINTLONG (1 << 5)
#define PRINTLONGLONG (1 << 6)
#define PRINTSHORT (1 << 7)
#define PRINTCHAR (1 << 8)
#define CAPITAL (1 << 9)
static size_t LongToChar(char* str, unsigned long value, uint32 flags, int32 precision, uint8 base, int32 width, x_bool minus, int32 pointer, int32 size)
{
char buff[KERNEL_CONSOLEBUF_SIZE/4] = {0};
int32 length = 0;
if(!value)
flags &= ~HASH;
if(!(precision > 0) || value) {
do {
const char number = (char)(value % base);
if(number < 10) {
buff[length] = number + '0';
} else {
if(flags & CAPITAL)
buff[length] = 'A' + number - 10;
else
buff[length] = 'a' + number - 10;
}
++ length;
value /= base;
} while (value && (length < KERNEL_CONSOLEBUF_SIZE/4));
}
if(!(flags & LEFT)) {
if(width && (minus || (flags & (SIGN | SPACE | ZEROPAD))))
-- width;
while((length < precision) && (length < KERNEL_CONSOLEBUF_SIZE/4))
buff[length++] = '0';
while((length < width) && (flags & ZEROPAD) && (length < KERNEL_CONSOLEBUF_SIZE/4))
buff[length++] = '0';
}
if((flags & HASH) && ((base == 8) || (base == 16))) {
if(!(precision > 0) && length && ((length == precision) || (length == width))) {
-- length;
if(length && (base == 16))
-- length;
}
switch (base) {
case 8:
buff[length++] = '0';
break;
case 16:
if(flags & CAPITAL)
{
buff[length++] = 'X';
buff[length++] = '0';
}
else
{
buff[length++] = 'x';
buff[length++] = '0';
}
break;
default:
break;
}
}
if(length < KERNEL_CONSOLEBUF_SIZE/4) {
if(minus)
buff[length++] = '-';
else if(flags & SIGN)
buff[length++] = '+';
else if(flags & SPACE)
buff[length++] = ' ';
}
const int32 index = pointer;
if(!(flags & LEFT) && !(flags & ZEROPAD) && (length < width)) {
for(int32 i = length; i < width; i++) {
str[pointer++] = ' ';
if(pointer >= size) {
str[size - 1] = '\0';
return size;
}
}
}
while (length) {
str[pointer++] = buff[--length];
if(pointer >= size) {
str[size - 1] = '\0';
return size;
}
}
if(flags & LEFT) {
while (pointer - index < width) {
str[pointer++] = ' ';
if(pointer >= size) {
str[size - 1] = '\0';
return size;
}
}
}
return pointer;
}
static size_t LonglongToChar(char* str, unsigned long long value, uint32 flags, int32 precision, uint8 base, int32 width, x_bool minus, int32 pointer, int32 size)
{
char buff[KERNEL_CONSOLEBUF_SIZE/4] = {0};
int32 length = 0;
if(!value)
flags &= ~HASH;
if(!(precision > 0) || value){
do {
const char number = (char)(value % base);
if(number < 10) {
buff[length] = number + '0';
} else {
if(flags & CAPITAL)
buff[length] = 'A' + number - 10;
else
buff[length] = 'a' + number - 10;
}
++ length;
value /= base;
} while (value && (length < KERNEL_CONSOLEBUF_SIZE/4));
}
if(!(flags & LEFT)) {
if(width && (minus || (flags & (SIGN | SPACE | ZEROPAD))))
-- width;
while((length < precision) && (length < KERNEL_CONSOLEBUF_SIZE/4))
buff[length++] = '0';
while((length < width) && (flags & ZEROPAD) && (length < KERNEL_CONSOLEBUF_SIZE/4))
buff[length++] = '0';
}
if((flags & HASH) && ((base == 8) || (base == 16))) {
if(!(precision > 0) && length && ((length == precision) || (length == width))) {
-- length;
if(length && (base == 16))
-- length;
}
switch (base) {
case 8:
buff[length++] = '0';
break;
case 16:
if(flags & CAPITAL) {
buff[length++] = 'X';
buff[length++] = '0';
} else {
buff[length++] = 'x';
buff[length++] = '0';
}
break;
default:
break;
}
}
if(length < KERNEL_CONSOLEBUF_SIZE/4) {
if(minus)
buff[length++] = '-';
else if(flags & SIGN)
buff[length++] = '+';
else if(flags & SPACE)
buff[length++] = ' ';
}
const int32 index = pointer;
if(!(flags & LEFT) && !(flags & ZEROPAD) && (length < width)) {
for(int32 i = length; i < width; i++) {
str[pointer++] = ' ';
if(pointer >= size) {
str[size - 1] = '\0';
return size;
}
}
}
while (length) {
str[pointer++] = buff[--length];
if(pointer >= size) {
str[size - 1] = '\0';
return size;
}
}
if(flags & LEFT) {
while (pointer - index < width) {
str[pointer++] = ' ';
if(pointer >= size) {
str[size - 1] = '\0';
return size;
}
}
}
return pointer;
}
int VsnPrintf(char *buf, int32 size, const char *fmt, va_list args)
{
NULL_PARAM_CHECK(buf);
int32 pointer = 0;
int32 len = 0;
int32 i = 0;
int32 width = 0;
int32 precision = 0;
uint32 flags = 0;
uint8 base = 0;
char c = 0;
char *str = NONE;
char *s = NONE;
pointer = 0;
str = buf;
while(*fmt) {
if (*fmt != '%') {
buf[pointer++] = *fmt;
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
++ fmt;
continue;
}
flags = 0;
uint8 CheckFlags = 1;
while (CheckFlags) {
++ fmt;
switch (*fmt) {
case '0':
flags |= ZEROPAD;
break;
case '-':
flags |= LEFT;
break;
case '+':
flags |= SIGN;
break;
case ' ':
flags |= SPACE;
break;
case '#':
flags |= HASH;
break;
default:
CheckFlags = 0;
break;
}
}
width = -1;
if (IsDigit(*fmt))
width = CharToNum(&fmt);
else if (*fmt == '*') {
width = va_arg(args, int);
if (width < 0) {
width = -width;
flags |= LEFT;
}
++ fmt;
}
precision = -1;
if (*fmt == '.') {
++ fmt;
if (IsDigit(*fmt))
precision = CharToNum(&fmt);
else if (*fmt == '*') {
precision = va_arg(args, int);
++ fmt;
}
if (precision < 0)
precision = 0;
}
if (*fmt == 'l') {
++ fmt;
if (*fmt == 'l') {
flags |= PRINTLONGLONG;
++ fmt;
}
else
flags |= PRINTLONG;
}
else if(*fmt == 'h') {
++ fmt;
if (*fmt == 'h') {
flags |= PRINTCHAR;
++ fmt;
}
else
flags |= PRINTSHORT;
}
base = 10;
switch (*fmt) {
case 'c':
if (!(flags & LEFT)) {
while (--width > 0) {
buf[pointer++] = ' ';
if(pointer >= size)
{
buf[size - 1] = '\0';
return size - 1;
}
}
}
c = (char)va_arg(args, int);
buf[pointer++] = c;
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
while (--width > 0) {
buf[pointer++] = ' ';
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
}
break;
case 's':
s = va_arg(args, char *);
if (!s)
s = "(NULL)";
len = strlen(s);
if (precision > 0 && len > precision)
len = precision;
if (!(flags & LEFT)) {
while (len < width--) {
buf[pointer++] = ' ';
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
}
}
for (i = 0; i < len; ++ i) {
buf[pointer++] = *s;
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
++ s;
}
while (len < width--) {
buf[pointer++] = ' ';
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
}
break;
case 'p':
width = sizeof(void *) * 2;
flags |= ZEROPAD | CAPITAL;
/* Determine the machine word length */
if(sizeof(long) == sizeof(long long))
pointer = LonglongToChar(buf, (unsigned long long)va_arg(args, void*), flags, precision, 16, width, 0, pointer, size);
else
pointer = LongToChar(buf, (unsigned long)va_arg(args, void*), flags, precision, 16, width, 0, pointer, size);
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
break;
case '%':
buf[pointer] = '%';
++ pointer;
break;
case 'o':
flags &= ~SIGN;
base = 8;
if(flags & PRINTLONGLONG)
pointer = LonglongToChar(buf, va_arg(args, unsigned long long), flags, precision, base, width, 0, pointer, size);
else if(flags & PRINTLONG)
pointer = LongToChar(buf, va_arg(args, unsigned long), flags, precision, base, width, 0, pointer, size);
else {
if(flags & PRINTSHORT) {
const unsigned int value = (unsigned short int)va_arg(args, unsigned int);
pointer = LongToChar(buf, value, flags, precision, base, width, 0, pointer, size);
} else if(flags & PRINTCHAR) {
const unsigned int value = (unsigned char)va_arg(args, unsigned int);
pointer = LongToChar(buf, value, flags, precision, base, width, 0, pointer, size);
} else {
const unsigned int value = va_arg(args, unsigned int);
pointer = LongToChar(buf, value, flags, precision, base, width, 0, pointer, size);
}
}
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
break;
case 'X':
flags |= CAPITAL;
case 'x':
flags &= ~SIGN;
base = 16;
if(flags & PRINTLONGLONG)
pointer = LonglongToChar(buf, va_arg(args, unsigned long long), flags, precision, base, width, 0, pointer, size);
else if(flags & PRINTLONG)
pointer = LongToChar(buf, va_arg(args, unsigned long), flags, precision, base, width, 0, pointer, size);
else {
if(flags & PRINTSHORT) {
const unsigned int value = (unsigned short int)va_arg(args, unsigned int);
pointer = LongToChar(buf, value, flags, precision, base, width, 0, pointer, size);
} else if(flags & PRINTCHAR) {
const unsigned int value = (unsigned char)va_arg(args, unsigned int);
pointer = LongToChar(buf, value, flags, precision, base, width, 0, pointer, size);
} else {
const unsigned int value = va_arg(args, unsigned int);
pointer = LongToChar(buf, value, flags, precision, base, width, 0, pointer, size);
}
}
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
break;
case 'u':
flags &= ~SIGN;
base = 10;
flags &= ~HASH;
if(flags & PRINTLONGLONG)
pointer = LonglongToChar(buf, va_arg(args, unsigned long long), flags, precision, base, width, 0, pointer, size);
else if(flags & PRINTLONG)
pointer = LongToChar(buf, va_arg(args, unsigned long), flags, precision, base, width, 0, pointer, size);
else {
if(flags & PRINTSHORT) {
const unsigned int value = (unsigned short int)va_arg(args, unsigned int);
pointer = LongToChar(buf, value, flags, precision, base, width, 0, pointer, size);
} else if(flags & PRINTCHAR) {
const unsigned int value = (unsigned char)va_arg(args, unsigned int);
pointer = LongToChar(buf, value, flags, precision, base, width, 0, pointer, size);
} else {
const unsigned int value = va_arg(args, unsigned int);
pointer = LongToChar(buf, value, flags, precision, base, width, 0, pointer, size);
}
}
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
break;
case 'd':
case 'i':
base = 10;
flags &= ~HASH;
if(flags & PRINTLONGLONG) {
const long long value = va_arg(args, long long);
pointer = LonglongToChar(buf, (unsigned long long)(value > 0 ? value : 0 - value), flags, precision, base, width, (value < 0 ? 1 : 0), pointer, size);
} else if(flags & PRINTLONG) {
const long value = va_arg(args, long);
pointer = LongToChar(buf, (unsigned long)(value > 0 ? value : 0 - value), flags, precision, base, width, (value < 0 ? 1 : 0), pointer, size);
} else {
if(flags & PRINTSHORT) {
const int value = (short int)va_arg(args, int);
pointer = LongToChar(buf, (unsigned int)(value > 0 ? value : 0 - value), flags, precision, base, width, (value < 0 ? 1 : 0), pointer, size);
} else if(flags & PRINTCHAR) {
const int value = (char)va_arg(args, int);
pointer = LongToChar(buf, (unsigned int)(value > 0 ? value : 0 - value), flags, precision, base, width, (value < 0 ? 1 : 0), pointer, size);
} else {
const int value = va_arg(args, int);
pointer = LongToChar(buf, (unsigned int)(value > 0 ? value : 0 - value), flags, precision, base, width, (value < 0 ? 1 : 0), pointer, size);
}
}
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
break;
default:
buf[pointer++] = '%';
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
if (*fmt) {
buf[pointer++] = *fmt;
if(pointer >= size) {
buf[size - 1] = '\0';
return size - 1;
}
} else {
-- fmt;
}
break;
}
++ fmt;
}
if(pointer > size)
pointer = size - 1;
buf[pointer] = '\0';
return pointer;
}
#endif
void KPrintf(const char *fmt, ...)
{
#ifdef KERNEL_CONSOLE
if(_console != NONE) {
va_list args;
x_size_t length = 0;
static char logbuf[KERNEL_CONSOLEBUF_SIZE] = {0};
va_start(args, fmt);
length = VsnPrintf(logbuf, sizeof(logbuf) - 1, fmt, args);
if (length > KERNEL_CONSOLEBUF_SIZE - 1)
length = KERNEL_CONSOLEBUF_SIZE - 1;
struct BusBlockWriteParam write_param;
write_param.pos = 0;
write_param.buffer = (void *)logbuf;
write_param.size = length;
BusDevWriteData(_console, (void *)&write_param);
va_end(args);
}
#endif
}

233
kernel/thread/data_queue.c Normal file
View File

@@ -0,0 +1,233 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: data_queue.c
* @brief: data queue file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#include <device.h>
/**
* This function allocates dynamic memory from dynamic buddy memory.
*
* @param p_queue dataqueue structure
* @param NodeNumber the number of dataqueue
*
* @return EOK on success; ERROR on failure
*/
x_err_t InitDataqueue(DataQueueType *p_queue, uint16 NodeNumber)
{
x_base lock = 0;
NULL_PARAM_CHECK(p_queue);
KPrintf("InitDataqueue\n");
lock = CriticalAreaLock();
do {
memset(p_queue, 0, sizeof(DataQueueType));
p_queue->front = p_queue->rear = 0;
p_queue->max_len = NodeNumber;
p_queue->base = (DataElemType *)x_malloc(p_queue->max_len * sizeof(DataElemType));
if (!p_queue->base) {
break;
}
// The semaphore is initialized to len-1, because the full condition of the loop queue is real + 1 = = front,
// a vacancy is always wasted
p_queue->sem_blank = KSemaphoreCreate( p_queue->max_len - 1);
if (!p_queue->sem_blank) {
break;
}
p_queue->sem_data = KSemaphoreCreate( 0);
if (!p_queue->sem_data) {
break;
}
CriticalAreaUnLock(lock);
return EOK;
} while (0);
CriticalAreaUnLock(lock);
DeInitDataqueue(p_queue);
return -ERROR;
}
/**
* This function realses all dataqueue resource.
*
* @param p_queue dataqueue structure
*
*/
void DeInitDataqueue(DataQueueType *p_queue)
{
x_base lock = 0;
NULL_PARAM_CHECK(p_queue);
KPrintf("DeInitDataqueue\n");
lock = DISABLE_INTERRUPT();
if (p_queue->base) {
x_free(p_queue->base);
p_queue->base = NONE;
}
if (p_queue->sem_blank) {
KSemaphoreDelete(p_queue->sem_blank);
p_queue->sem_blank = NONE;
}
if (p_queue->sem_data) {
KSemaphoreDelete(p_queue->sem_data);
p_queue->sem_data = NONE;
}
ENABLE_INTERRUPT(lock);
}
/**
* This function will push a data into dataqueue .
*
* @param p_queue dataqueue structure
* @param StartAddr the data needed to be pushed
* @param DataSize data size
* @param timeout timeout
*
* @return EOK on success; ERROR on failure
*/
x_err_t PushDataqueue(DataQueueType *p_queue, const void *StartAddr, x_size_t DataSize, int32 timeout)
{
x_base lock = 0;
NULL_PARAM_CHECK(p_queue);
NULL_PARAM_CHECK(StartAddr);
KPrintf("PushDataqueue\n");
do {
if (WAITING_FOREVER == timeout) {
// block
KSemaphoreObtain(p_queue->sem_blank, WAITING_FOREVER);
break;
} else if (0 == timeout) {
// Nonblocking
if (EOK == KSemaphoreObtain(p_queue->sem_blank, 0)) {
break;
} else {
return -ERROR;
}
}
} while (0);
lock = CriticalAreaLock();
if ((p_queue->rear + 1) % p_queue->max_len != p_queue->front) {
DataElemType *pElem = &(p_queue->base[p_queue->rear]);
pElem->data = StartAddr;
pElem->length = DataSize;
p_queue->rear = (p_queue->rear + 1) % p_queue->max_len;
}
CriticalAreaUnLock(lock);
KSemaphoreAbandon(p_queue->sem_data);
return EOK;
}
/**
* This function will pop a data from dataqueue .
*
* @param p_queue dataqueue structure
* @param StartAddr the data needed to be popped
* @param DataSize data size
* @param timeout timeout
*
* @return EOK on success; ERROR on failure
*/
x_err_t PopDataqueue(DataQueueType *p_queue, const void **StartAddr, x_size_t *size, int32 timeout)
{
x_base lock = 0;
NULL_PARAM_CHECK(p_queue);
KPrintf("PopDataqueue\n");
do {
if (WAITING_FOREVER == timeout) {
// block
KSemaphoreObtain(p_queue->sem_data, WAITING_FOREVER);
break;
} else if (0 == timeout) {
// Nonblocking
if (EOK == KSemaphoreObtain(p_queue->sem_data, 0)) {
// Get success
break;
} else {
// Get failed, exit directly
return -ERROR;
}
}
} while (0);
lock = CriticalAreaLock();
// Semaphore surplus, read data directly
if (p_queue->front != p_queue->rear) {
DataElemType *pElem = &(p_queue->base[p_queue->front]);
*StartAddr = pElem->data;
*size = pElem->length;
p_queue->front = (p_queue->front + 1) % p_queue->max_len;
}
CriticalAreaUnLock(lock);
// Release data semaphore
KSemaphoreAbandon(p_queue->sem_blank);
return EOK;
}
/**
* This function will get the first data of dataqueue .
*
* @param p_queue dataqueue structure
* @param StartAddr the data needed to be popped
* @param size data size
*
* @return EOK on success; ERROR on failure
*/
x_err_t DataqueuePeak(DataQueueType *p_queue, const void **StartAddr, x_size_t *size)
{
x_base lock = 0;
NULL_PARAM_CHECK(p_queue);
KPrintf("DataqueuePeak\n");
if (p_queue->front != p_queue->rear) {
lock = CriticalAreaLock();
DataElemType *pElem = &(p_queue->base[p_queue->front]);
*StartAddr = pElem->data;
*size = pElem->length;
CriticalAreaUnLock(lock);
return EOK;
} else {
return -ERROR;
}
}

150
kernel/thread/delay.c Normal file
View File

@@ -0,0 +1,150 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: delay.c
* @brief: set task delay and check the timeout
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xs_klist.h>
#include<string.h>
#include<xs_isr.h>
#include <xs_ktask.h>
#include <xs_memory.h>
#include<xs_ktick.h>
#include<xiuos.h>
DoubleLinklistType xiaoshan_delay_head = {&xiaoshan_delay_head, &xiaoshan_delay_head};
/**
* This function will delay a task with sone ticks.
*
* @param task the task needed to be delayed
* @param ticks delay timeout
*
* @return EOK on success; ENOMEMORY on failure
*/
x_err_t KTaskSetDelay(KTaskDescriptorType task, x_ticks_t ticks)
{
x_base lock = 0;
struct Delay *delay = NONE;
struct Delay *dnode = NONE;
DoubleLinklistType *nodelink = NONE;
NULL_PARAM_CHECK(task);
if (task->task_dync_sched_member.delay == NONE) {
delay = (struct Delay *)x_malloc(sizeof(struct Delay));
if (delay == NONE)
{
return -ENOMEMORY;
}
memset(delay, 0x0, sizeof(struct Delay));
task->task_dync_sched_member.delay = delay;
} else {
delay = task->task_dync_sched_member.delay;
lock = CriticalAreaLock();
if(delay->status == TASK_DELAY_ACTIVE){
delay->status = TASK_DELAY_INACTIVE;
DoubleLinkListRmNode(&(delay->link));
}
CriticalAreaUnLock(lock);
}
delay->ticks = CurrentTicksGain() + ticks;
delay->task = task;
delay->status = TASK_DELAY_ACTIVE;
lock = CriticalAreaLock();
DOUBLE_LINKLIST_FOR_EACH(nodelink, &xiaoshan_delay_head) {
dnode =CONTAINER_OF(nodelink, struct Delay, link);
if (delay->ticks < dnode->ticks) {
DoubleLinkListInsertNodeBefore(nodelink, &delay->link);
break;
}
}
if (nodelink == &xiaoshan_delay_head) {
DoubleLinkListInsertNodeBefore(&xiaoshan_delay_head, &(delay->link));
}
CriticalAreaUnLock(lock);
return EOK;
}
/**
* This function will wakeup a task from delay list.
*
* @param task the task needed to be wakeup
*
* @return EOK
*/
x_err_t KTaskUnSetDelay(KTaskDescriptorType task)
{
x_base lock = 0;
struct Delay *delay = NONE;
NULL_PARAM_CHECK(task);
delay = task->task_dync_sched_member.delay;
if( delay != NONE && delay->status == TASK_DELAY_ACTIVE) {
lock = CriticalAreaLock();
delay->status = TASK_DELAY_INACTIVE;
DoubleLinkListRmNode(&(delay->link));
CriticalAreaUnLock(lock);
}
return EOK;
}
void CheckTaskDelay(void)
{
x_base level = 0;
x_ticks_t current_tick = 0;
struct Delay *node = NONE;
SYS_KDEBUG_LOG(0, ("delay check enter\n"));
current_tick = CurrentTicksGain();
level = CriticalAreaLock();
while (!IsDoubleLinkListEmpty(&xiaoshan_delay_head))
{
node = SYS_DOUBLE_LINKLIST_ENTRY(xiaoshan_delay_head.node_next,
struct Delay, link);
if ((current_tick - node->ticks) < TICK_SIZE_MAX / 2)
{
current_tick = CurrentTicksGain();
SYS_KDEBUG_LOG(KDBG_SOFTTIMER, ("current tick: %d\n", current_tick));
KTaskUnSetDelay(node->task);
CriticalAreaUnLock(level);
KTaskTimeout(node->task);
level = CriticalAreaLock();
}
else
break;
}
CriticalAreaUnLock(level);
SYS_KDEBUG_LOG(0, ("delay check leave\n"));
}

132
kernel/thread/double_link.c Normal file
View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: double_link.c
* @brief: functions definition of double linklist
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xs_klist.h>
/**
* This function will init a linklist.
*
* @param linklist_head linklist node
*/
void InitDoubleLinkList(DoubleLinklistType *linklist_head)
{
linklist_head->node_next = linklist_head;
linklist_head->node_prev = linklist_head;
}
/**
* This function will insert a node into list after the node.
*
* @param linklist linklist node
* @param linklist_node the node needed to inserted
*/
void DoubleLinkListInsertNodeAfter(DoubleLinklistType *linklist, DoubleLinklistType *linklist_node)
{
linklist->node_next->node_prev = linklist_node;
linklist_node->node_next = linklist->node_next;
linklist->node_next = linklist_node;
linklist_node->node_prev = linklist;
}
/**
* This function will insert a node into list after the node.
*
* @param linklist linklist node
* @param linklist_node the node needed to inserted
*/
void DoubleLinkListInsertNodeBefore(DoubleLinklistType *linklist, DoubleLinklistType *linklist_node)
{
linklist->node_prev->node_next = linklist_node;
linklist_node->node_prev = linklist->node_prev;
linklist->node_prev = linklist_node;
linklist_node->node_next = linklist;
}
/**
* This function will remove a node from the list.
*
* @param linklist_node the node needed to removed
*/
void DoubleLinkListRmNode(DoubleLinklistType *linklist_node)
{
linklist_node->node_next->node_prev = linklist_node->node_prev;
linklist_node->node_prev->node_next = linklist_node->node_next;
linklist_node->node_next = linklist_node;
linklist_node->node_prev = linklist_node;
}
/**
* This function will judge the list is empty.
*
* @param linklist the list head
* @return true
*/
int IsDoubleLinkListEmpty(const DoubleLinklistType *linklist)
{
return linklist->node_next == linklist;
}
/**
* This function will get the head of the list.
*
* @param linklist list head
* @return list head
*/
struct SysDoubleLinklistNode *DoubleLinkListGetHead(const DoubleLinklistType *linklist)
{
return IsDoubleLinkListEmpty(linklist) ? NONE : linklist->node_next;
}
/**
* This function will get the next node of the list head.
*
* @param linklist list head
* @param linklist_node list head
* @return next node of the list head
*/
struct SysDoubleLinklistNode *DoubleLinkListGetNext(const DoubleLinklistType *linklist,
const struct SysDoubleLinklistNode *linklist_node)
{
return linklist_node->node_next == linklist ? NONE : linklist_node->node_next;
}
/**
* This function will get length of the list.
*
* @param linklist list head
* @return length
*/
unsigned int DoubleLinkListLenGet(const DoubleLinklistType *linklist)
{
unsigned int linklist_length = 0;
const DoubleLinklistType *tmp_node = linklist;
while (tmp_node->node_next != linklist)
{
tmp_node = tmp_node->node_next;
linklist_length ++;
}
return linklist_length;
}

302
kernel/thread/event.c Normal file
View File

@@ -0,0 +1,302 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: event.c
* @brief: event file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
DECLARE_ID_MANAGER(k_event_id_manager, ID_NUM_MAX);
DoubleLinklistType k_event_list ={&k_event_list, &k_event_list};
static int32 _EventCreate(uint32 options)
{
int32 id = 0;
x_base lock = 0;
struct Event *event = NONE;
event = (struct Event *)x_malloc(sizeof(struct Event));
if (event == NONE)
return -ENOMEMORY;
memset(event, 0, sizeof(struct Event));
lock = CriticalAreaLock();
id = IdInsertObj(&k_event_id_manager, &event->id);
if (id < 0) {
CriticalAreaUnLock(lock);
x_free(event);
return -ENOMEMORY;
}
event->options = options;
InitDoubleLinkList(&event->pend_list);
DoubleLinkListInsertNodeAfter(&k_event_list, &event->link);
CriticalAreaUnLock(lock);
return id;
}
static void _EventDelete(struct Event *event)
{
int resched = 0;
x_base lock = 0;
NULL_PARAM_CHECK(event);
if (!IsDoubleLinkListEmpty(&event->pend_list)) {
resched = 1;
LinklistResumeAll(&event->pend_list);
}
lock = CriticalAreaLock();
IdRemoveObj(&k_event_id_manager, event->id.id);
DoubleLinkListRmNode(&event->link);
CriticalAreaUnLock(lock);
x_free(event);
if (resched)
DO_KTASK_ASSIGN;
}
static int32 _EventTrigger(struct Event *event, uint32 events)
{
x_bool resched;
x_ubase lock = 0;
x_base status = 0;
struct TaskDescriptor *task = NONE;
struct SysDoubleLinklistNode *n = NONE;
NULL_PARAM_CHECK(event);
if (events == 0)
return -ERROR;
resched = RET_FALSE;
lock = CriticalAreaLock();
event->events |= events;
if (IsDoubleLinkListEmpty(&event->pend_list)) {
CriticalAreaUnLock(lock);
return EOK;
}
n = event->pend_list.node_next;
while (n != &(event->pend_list)) {
task = SYS_DOUBLE_LINKLIST_ENTRY(n, struct TaskDescriptor, task_dync_sched_member.sched_link);
status = -ERROR;
if (task->event_mode & EVENT_AND) {
if ((task->event_id_trigger & (event->events & EVENT_EVENTS_MASK)) == task->event_id_trigger)
status = EOK;
} else if (task->event_mode & EVENT_OR) {
if (task->event_id_trigger & (event->events & EVENT_EVENTS_MASK)) {
task->event_id_trigger = task->event_id_trigger & (event->events & EVENT_EVENTS_MASK);
status = EOK;
}
}
n = n->node_next;
if (status == EOK) {
if (task->event_mode & EVENT_AUTOCLEAN)
event->events &= ~task->event_id_trigger;
KTaskWakeup(task->id.id);
resched = RET_TRUE;
}
}
CriticalAreaUnLock(lock);
if (resched == RET_TRUE)
DO_KTASK_ASSIGN;
return EOK;
}
static int32 _EventProcess(struct Event *event, uint32 events, uint32 options, int32 msec, uint32 *processed)
{
x_ubase lock = 0;
x_base status = 0;
int32 timeout = 0;
struct TaskDescriptor *task = NONE;
KDEBUG_IN_KTASK_CONTEXT;
NULL_PARAM_CHECK(event);
if (events == 0)
return -ERROR;
status = -ERROR;
task = GetKTaskDescriptor();
task->exstatus = EOK;
timeout = CalculteTickFromTimeMs(msec);
lock = CriticalAreaLock();
if (options & EVENT_AND) {
if ((event->events & events) == events)
status = EOK;
} else if (options & EVENT_OR) {
if (event->events & events)
status = EOK;
} else {
CHECK(0);
}
if (status == EOK) {
if (processed)
*processed = (event->events & events);
if (options & EVENT_AUTOCLEAN)
event->events &= ~events;
} else if (timeout == 0) {
task->exstatus = -ETIMEOUT;
} else {
task->event_id_trigger = (events & EVENT_EVENTS_MASK);
task->event_mode = (options & EVENT_OPTIONS_MASK);
LinklistSuspend(&(event->pend_list), task, event->options);
if (timeout > 0)
KTaskSetDelay(task,timeout);
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
if (task->exstatus != EOK)
return task->exstatus;
lock = CriticalAreaLock();
if (processed)
*processed = task->event_id_trigger;
}
CriticalAreaUnLock(lock);
return task->exstatus;
}
static EventDoneType done = {
.EventCreate = _EventCreate,
.EventDelete = _EventDelete,
.EventTrigger = _EventTrigger,
.EventProcess = _EventProcess,
};
static struct Event *FindEventById(int32 id)
{
x_base lock = 0;
struct IdNode *idnode = NONE;
struct Event *event = NONE;
if (id < 0)
return NONE;
lock = CriticalAreaLock();
idnode = IdGetObj(&k_event_id_manager, id);
if (idnode == NONE) {
CriticalAreaUnLock(lock);
return NONE;
}
event = CONTAINER_OF(idnode, struct Event, id);
CriticalAreaUnLock(lock);
return event;
}
/**
* This function will create a event.
*
* @param options the trigger way of event.
*
* @return id
*/
int32 KEventCreate(uint32 options)
{
KDEBUG_NOT_IN_INTERRUPT;
return done.EventCreate(options);
}
/**
* This function will delete a event.
*
* @param id the id number of event.
*
* @return
*/
void KEventDelete(int32 id)
{
KDEBUG_NOT_IN_INTERRUPT;
struct Event *event = FindEventById(id);
if (event == NONE)
return;
done.EventDelete(event);
}
/**
* This function will trigger the event
*
* @param id the id number of event
* @param events trigger way & events flag
*
* @return EOK on success.
*/
int32 KEventTrigger(int32 id, uint32 events)
{
KDEBUG_NOT_IN_INTERRUPT;
struct Event *event = FindEventById(id);
if (event == NONE)
return -ERROR;
return done.EventTrigger(event, events);
}
/**
* This function will get the event and process this event
*
* @param id the id number of event
* @param events events flag
* @param options trigger way
* @param msec timeout
* @processed event processed flag
*
* @return EOK on success.
*/
int32 KEventProcess(int32 id, uint32 events, uint32 options, int32 msec, uint32 *processed)
{
KDEBUG_NOT_IN_INTERRUPT;
struct Event *event = FindEventById(id);
return done.EventProcess(event, events, options, msec, processed);
}

216
kernel/thread/hook.c Normal file
View File

@@ -0,0 +1,216 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: hook.c
* @brief: the general interface functions of hook
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/20
*
*/
#include <xs_kdbg.h>
#include <xs_hook.h>
struct KernelHook hook;
/**
* a hook function, it will run when switch task
*
* @param from task descriptor
* @param to task descriptor
*/
void AssignHook(KTaskDescriptorType from, KTaskDescriptorType to)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], from task: %s, to task:%s\n",__func__,from->task_base_info.name,to->task_base_info.name));
/* add your code */
}
/**
*
* This hook function will be run after task inited .
*
* @param task task descripter
*
* @note no blocked or suspend function.
*/
void TaskCreatehook(KTaskDescriptorType task)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], Create task: %s\n",__func__,task->task_base_info.name));
/* add your code */
}
/**
*
* This hook function will be run after task suspended .
*
* @param task descripter
*
* @note no blocked or suspend function.
*/
void TaskSuspendhook(KTaskDescriptorType task)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], Suspend task: %s\n",__func__,task->task_base_info.name));
/* add your code */
}
/**
*
* This hook function will be run after task resumed .
*
* @param task descripter
*
* @note no blocked or suspend function.
*/
void TaskResumehook(KTaskDescriptorType task)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], Resume task: %s\n",__func__,task->task_base_info.name));
/* add your code */
}
/**
* a MallocHook function. The MallocHook function will be run before a memory block is allocated from buddy-memory.
*
* @param ptr alloc mem point
* @param size alloc mem size
*/
void MemMallochook(void *ptr, x_size_t size)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], Malloc memory: ptr:%p, size: %d\n",__func__,ptr,size));
/* add your code */
}
/**
* a FreeHook function. The FreeHook function will be run after a memory block is freed to buddy-memory.
*
* @param ptr free mem point
*/
void MemFreehook(void *ptr)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], Free memory: ptr:%p\n",__func__,ptr));
/* add your code */
}
#ifdef KERNEL_MEMBLOCK
/**
* a allocation hook function before a gatherblock allocation.
*
* @param gm the alloc hook function
* @param date_ptr mem point
*/
void GmAllocHook(struct MemGather *gm, void *date_ptr)
{
/* add your code */
return;
}
/**
* a free hook function after a gatherblock release.
*
* @param gm the free hook function
* @param date_ptr mem point
*/
void GmFreeHook(struct MemGather *gm, void *date_ptr)
{
/* add your code */
return;
}
#endif
/**
* this hook function will run when the system interrupt
*
* @note no blocked or suspend.
*/
void IsrEnterHook(void)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], Enter Isr\n",__func__));
/* add your code */
}
/**
* this hook function will run when the system leave interrupt
*
* @note no blocked or suspend.
*/
void IsrLeaveHook(void)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], Leave Isr\n",__func__));
/* add your code */
}
void TimerEnterHook(struct Timer *timer)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], Timer Enter\n",__func__));
/* add your code */
}
void TimerExitHook(struct Timer *timer)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], Timer Exit\n",__func__));
/* add your code */
}
void IdleTaskHook(void)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s], Idle0 \n",__func__));
/* add your code */
}
void testhook(const char *str)
{
SYS_KDEBUG_LOG(KDBG_HOOK,
("HOOK: Function[%s],Test: %s\n",__func__,str));
/* add your code */
return;
}
int hook_init(void)
{
REGISTER_HOOK(hook.assign.hook_Assign,AssignHook);
REGISTER_HOOK(hook.task.hook_TaskCreate,TaskCreatehook);
REGISTER_HOOK(hook.task.hook_TaskSuspend,TaskSuspendhook);
REGISTER_HOOK(hook.task.hook_TaskResume,TaskResumehook);
REGISTER_HOOK(hook.mem.hook_Malloc,MemMallochook);
REGISTER_HOOK(hook.mem.hook_Free,MemFreehook);
#ifdef KERNEL_MEMBLOCK
REGISTER_HOOK(hook.mem.hook_GmAlloc,GmAllocHook);
REGISTER_HOOK(hook.mem.hook_GmFree,GmFreeHook);
#endif
REGISTER_HOOK(hook.timer.hook_TimerEnter,TimerEnterHook);
REGISTER_HOOK(hook.timer.hook_TimerExit,TimerExitHook);
REGISTER_HOOK(hook.idle.hook_Idle,IdleTaskHook);
//REGISTER_HOOK(hook.idle[1].hook_Idle,IdleTask1Hook);
REGISTER_HOOK(hook.isr.hook_IsrEnter,IsrEnterHook);
REGISTER_HOOK(hook.isr.hook_IsrLeave,IsrLeaveHook);
REGISTER_HOOK(hook.test.hook_test,testhook);
return EOK;
}

142
kernel/thread/id.c Normal file
View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: id.c
* @brief: the management with id for all kernel object
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/4/15
*
*/
#include <xiuos.h>
static int AllocId(struct IdManager *manager)
{
int index = 0;
int end = 0;
int id = 0;
uint8 entry = 0;
NULL_PARAM_CHECK(manager);
end = (manager->id_max + 7) / 8;
for (index = 0; index < end; index++)
if (manager->id_map[index] != 0xff)
break;
if (index == end)
return -1;
id = index * 8;
entry = manager->id_map[index];
while (entry & 0x1) {
id++;
entry >>= 1;
}
if (id >= manager->id_max)
return -1;
manager->id_map[index] |= (0x1 << (id % 8));
return id;
}
static void FreeId(struct IdManager *manager, uint16 id)
{
NULL_PARAM_CHECK(manager);
manager->id_map[id / 8] &= ~(0x1 << (id % 8));
}
static void InsertObj(struct IdManager *manager, struct IdNode *idnode)
{
NULL_PARAM_CHECK(manager);
NULL_PARAM_CHECK(idnode);
DoubleLinklistType *head = &manager->htable[idnode->id % manager->hoffset];
if (head->node_prev == NONE)
InitDoubleLinkList(head);
DoubleLinkListInsertNodeAfter(head, &idnode->link);
}
static struct IdNode *GetObj(struct IdManager *manager, uint16 id)
{
NULL_PARAM_CHECK(manager);
DoubleLinklistType *head = &manager->htable[id % manager->hoffset];
DoubleLinklistType *node = NONE;
struct IdNode *idnode = NONE;
if (head->node_prev == NONE) {
InitDoubleLinkList(head);
return NONE;
}
DOUBLE_LINKLIST_FOR_EACH(node, head) {
idnode =CONTAINER_OF(node, struct IdNode, link);
if (idnode->id == id)
break;
idnode = NONE;
}
return idnode;
}
static struct IdNode *RemoveObj(struct IdManager *manager, struct IdNode *idnode)
{
NULL_PARAM_CHECK(manager);
NULL_PARAM_CHECK(idnode);
DoubleLinkListRmNode(&idnode->link);
}
int IdInsertObj(struct IdManager *manager, struct IdNode *idnode)
{
int id = 0;
NULL_PARAM_CHECK(manager);
NULL_PARAM_CHECK(idnode);
if ((id = AllocId(manager)) < 0)
return -1;
idnode->id = id;
InsertObj(manager, idnode);
return id;
}
struct IdNode *IdGetObj(struct IdManager *manager, uint16 id)
{
if (manager == NONE || id >= manager->id_max)
return NONE;
return GetObj(manager, id);
}
void IdRemoveObj(struct IdManager *manager, uint16 id)
{
NULL_PARAM_CHECK(manager);
struct IdNode *idnode = IdGetObj(manager, id);
if (idnode == NONE)
return;
FreeId(manager, idnode->id);
RemoveObj(manager, idnode);
idnode->id = -1;
}

105
kernel/thread/idle.c Normal file
View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: idle.c
* @brief: idle file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#include <xs_hook.h>
#include <xs_spinlock.h>
#if defined (KERNEL_HOOK)
#ifndef KERNEL_IDLE_HOOK
#define KERNEL_IDLE_HOOK
#endif
#endif
#ifndef IDLE_KTASK_STACKSIZE
#define IDLE_KTASK_STACKSIZE 256
#endif
#ifdef ARCH_SMP
#define CORE_NUM CPU_NUMBERS
#else
#define CORE_NUM 1
#endif
static int32 idle[CORE_NUM];
__attribute__((aligned(MEM_ALIGN_SIZE)))
void RunningIntoLowPowerMode()
{
#ifdef ARCH_ARM
__asm volatile("WFI");
#endif
#ifdef ARCH_RISCV
asm volatile ("wfi");
#endif
}
static void IdleKTaskEntry(void *arg)
{
while (1) {
#ifdef KERNEL_IDLE_HOOK
HOOK(hook.idle.hook_Idle,());
#endif
RunningIntoLowPowerMode();
}
}
/**
*
* init system idle task,then startup the idle task
*
*/
void InitIdleKTask(void)
{
uint8 coreid = 0;
char ktaskidle[NAME_NUM_MAX] = {0};
for (coreid = 0; coreid < CORE_NUM; coreid++) {
sprintf(ktaskidle, "ktaskidle%d", coreid);
idle[coreid] = KTaskCreate(ktaskidle,IdleKTaskEntry,NONE,IDLE_KTASK_STACKSIZE,KTASK_LOWEST_PRIORITY);
#ifdef ARCH_SMP
KTaskCoreCombine(idle[coreid], coreid);
#endif
StartupKTask(idle[coreid]);
}
}
/**
*
* This function will return the idle task descriptor
*
*/
KTaskDescriptorType GetIdleKTaskDescripter(void)
{
KTaskDescriptorType idle_p = NONE;
#ifdef ARCH_SMP
register int id = GetCpuId();
#else
register int id = 0;
#endif
idle_p = CONTAINER_OF(&idle[id], struct TaskDescriptor, id);
return idle_p;
}

260
kernel/thread/init.c Normal file
View File

@@ -0,0 +1,260 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: init.c
* @brief: init file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#include <xs_assign.h>
#include <xs_init.h>
#include <xs_spinlock.h>
#include <xs_workqueue.h>
#include <stdlib.h>
#include <board.h>
#ifdef BSP_USING_USBH
#include "connect_usb.h"
#endif
#ifdef KERNEL_USER_MAIN
#ifndef MAIN_KTASK_STACK_SIZE
#define MAIN_KTASK_STACK_SIZE 2048
#endif
#ifndef MAIN_KTASK_PRIORITY
#define MAIN_KTASK_PRIORITY (KTASK_PRIORITY_MAX / 3)
#endif
#endif
extern void CreateKServiceKTask(void);
extern int main(void);
void InitBoardHardware(void);
extern int hook_init(void);
int cplusplus_system_init(void);
#ifdef KERNEL_COMPONENTS_INIT
#ifdef USER_APPLICATION
extern void CreateMainTask(void);
#ifdef SEPARATE_COMPILE
int InitUserspace(void);
#endif
#endif
#ifndef ENV_INIT_KTASK_STACK_SIZE
#define ENV_INIT_KTASK_STACK_SIZE 8192
#endif
struct InitSequenceDesc prev_cmpts_init[] =
{
#ifdef FS_VFS
{ "vfs", VfsInit },
#endif
#ifdef LIB_CPLUSPLUS
{ "cplusplus_system", cplusplus_system_init },
#endif
#ifdef KERNEL_HOOK
{ "hook", hook_init },
#endif
{ " NONE ", NONE },
};
struct InitSequenceDesc device_init[] =
{
#ifdef KERNEL_WORKQUEUE
{ "work sys workqueue", WorkSysWorkQueueInit },
#endif
#ifdef ARCH_ARM
#ifdef RESOURCES_SPI_SFUD
{ "W25Qxx_spi", FlashW25qxxSpiDeviceInit},
#endif
#endif
{ " NONE ", NONE },
};
struct InitSequenceDesc components_init[] =
{
#ifdef CONNECTION_AT_SAL_USING_TLS
{"sal_mbedtls_proto", sal_mbedtls_proto_init},
#endif
#ifdef FS_VFS_FATFS
{ "fatfs", FatfsInit },
#endif
#ifdef FS_CH376
{ "ch376", Ch376fsInit },
#endif
{ "libc_system", LibcSystemInit },
#ifdef CONNECTION_AT_OS_USING_SAL
// { "sal_init", sal_init },
#endif
#ifdef RTC_SYNC_USING_NTP
{ "rtc_ntp_sync",RtcNtpSyncInit},
#endif
{ " NONE ", NONE },
};
struct InitSequenceDesc env_init[] =
{
#ifdef ARCH_RISCV
#if defined (RESOURCES_SPI_SD)|| defined(RESOURCES_SDIO )
{ "MountSDCard", MountSDCard },
#endif
#endif
#ifdef FS_VFS_MNTTABLE
{ "dfs_mount_table", dfs_mount_table },
#endif
#ifdef TOOL_SHELL
{ "letter-shell system", userShellInit },
#endif
{ " NONE ", NONE },
};
struct InitSequenceDesc communication_init[] =
{
// #ifdef BSP_USING_SDIO
// { "stm32_sdcard_mount",stm32_sdcard_mount },
// #endif
#ifdef BSP_USING_USBH
{ "STM32USBHostRegister", STM32USBHostRegister },
{ "hw usb", Stm32HwUsbInit },
#endif
{ " NONE ", NONE },
};
/**
* This function will init sub components
* @parm sub_components components type
*
*/
void _InitSubCmpts(struct InitSequenceDesc sub_cmpts[])
{
int i = 0;
int ret = 0;
for( i = 0; sub_cmpts[i].fn != NONE; i++ ) {
ret = sub_cmpts[i].fn();
KPrintf("initialize %s %s\n",sub_cmpts[i].fn_name, ret == 0 ? "success" : "failed");
}
}
#ifdef KERNEL_COMPONENTS_INIT
void EnvInitKTask(void *parameter)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
_InitSubCmpts(prev_cmpts_init);
_InitSubCmpts(device_init);
_InitSubCmpts(components_init);
_InitSubCmpts(env_init);
ENABLE_INTERRUPT(lock);
_InitSubCmpts(communication_init);
#ifdef ARCH_SMP
StartupSecondaryCpu();
#endif
#ifdef USER_APPLICATION
#ifdef SEPARATE_COMPILE
if(InitUserspace() == EOK) {
CreateMainTask();
}
#else
CreateMainTask();
#endif
#endif
}
#endif
void CreateEnvInitTask(void)
{
int32 env_init = 0;
env_init = KTaskCreate("env_init", EnvInitKTask, NONE,
ENV_INIT_KTASK_STACK_SIZE, KTASK_PRIORITY_MAX - 1);
if(env_init < 0) {
KPrintf("env_init create failed ...%s %d.\n",__FUNCTION__,__LINE__);
return;
}
StartupKTask(env_init);
}
#endif /* KERNEL_COMPONENTS_INIT */
/**
* kernel startup function
*
*
*/
int XiUOSStartup(void)
{
DISABLE_INTERRUPT();
#ifdef KERNEL_QUEUEMANAGE
queuemanager_done_register();
#endif
#ifdef KERNEL_BANNER
ShowBanner();
#endif
SysInitOsAssign();
CreateKServiceKTask();
#ifdef KERNEL_COMPONENTS_INIT
CreateEnvInitTask();
#else
#ifdef TOOL_SHELL
extern int userShellInit(void);
userShellInit();
#endif
#ifdef USER_APPLICATION
extern void CreateMainTask(void);
#ifdef SEPARATE_COMPILE
extern int InitUserspace(void);
if(InitUserspace() == EOK) {
CreateMainTask();
}
#else
CreateMainTask();
#endif
#endif
#endif
#ifdef ARCH_SMP
HwLockSpinlock(&AssignSpinLock);
#endif
StartupOsAssign();
return 0;
}
/* system entry */
int entry(void)
{
DISABLE_INTERRUPT();
/* system irq table must be inited before initialization of Hardware irq */
SysInitIsrManager();
InitBoardHardware();
XiUOSStartup();
return 0;
}

218
kernel/thread/isr.c Normal file
View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: isr.c
* @brief: the general management of system isr
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#include <xs_hook.h>
struct InterruptServiceRoutines isrManager = { 0} ;
#ifdef ARCH_SMP
extern int GetCpuId(void);
#endif
/**
* This functionwill get the isr nest level.
*
* @return isr nest level
*/
uint16 GetIsrCounter()
{
uint16 ret = 0;
#ifdef ARCH_SMP
ret = isrManager.isr_count[GetCpuId()];
#else
ret = isrManager.isr_count;
#endif
return ret;
}
void incIsrCounter()
{
#ifdef ARCH_SMP
isrManager.isr_count[GetCpuId()] ++ ;
#else
isrManager.isr_count ++;
#endif
return ;
}
void decIsrCounter()
{
#ifdef ARCH_SMP
isrManager.isr_count[GetCpuId()] -- ;
#else
isrManager.isr_count --;
#endif
return ;
}
x_bool Is_InIsr()
{
#ifdef ARCH_SMP
return ( isrManager.isr_count[GetCpuId()] != 0 ? RET_TRUE : RET_FALSE ) ;
#else
return ( isrManager.isr_count != 0 ? RET_TRUE : RET_FALSE ) ;
#endif
}
/**
* This function will register a new irq.
*
* @param irq_num the number of the irq
* @param handler the callback of the interrupt
* @param arg param of thge callback
*
* @return EOK on success; ERROR on failure
*/
int32 RegisterHwIrq(uint32 irq_num, IsrHandlerType handler, void *arg)
{
if (irq_num >= ARCH_MAX_IRQ_NUM )
return -ERROR;
struct IrqDesc *desc = &isrManager.irq_table[irq_num];
desc->handler = handler;
desc->param = arg;
return EOK;
}
/**
* This function will free a irq.
*
* @param irq_num the number of the irq
*
* @return EOK on success; ERROR on failure
*/
int32 FreeHwIrq(uint32 irq_num)
{
if (irq_num >= ARCH_MAX_IRQ_NUM )
return -ERROR;
memset(&isrManager.irq_table[irq_num], 0, sizeof(struct IrqDesc));
return EOK;
}
/**
* This function will enable a irq.
*
* @param irq_num the number of the irq
*
* @return EOK on success; ERROR on failure
*/
int32 EnableHwIrq(uint32 irq_num)
{
if (irq_num >= ARCH_MAX_IRQ_NUM )
return -ERROR;
return ArchEnableHwIrq(irq_num);
}
/**
* This function will disable a irq.
*
* @param irq_num the number of the irq
*
* @return EOK on success; ERROR on failure
*/
int32 DisableHwIrq(uint32 irq_num)
{
if (irq_num >= ARCH_MAX_IRQ_NUM )
return -ERROR;
return ArchDisableHwIrq(irq_num);
}
/* called from arch-specific ISR wrapper */
void IsrCommon(uint32 irq_num)
{
struct IrqDesc *desc = &isrManager.irq_table[irq_num];
if (desc->handler == NONE) {
SYS_KDEBUG_LOG(KDBG_IRQ, ("Spurious interrupt: IRQ No. %d\n", irq_num));
while (1) {}
}
desc->handler(irq_num, desc->param);
}
void setIsrSwitchTrigerFlag()
{
#ifdef ARCH_SMP
isrManager.isr_switch_trigger_flag[GetCpuId()] = 1;
#else
isrManager.isr_switch_trigger_flag = 1;
#endif
}
void clearIsrSwitchTrigerFlag()
{
#ifdef ARCH_SMP
isrManager.isr_switch_trigger_flag[GetCpuId()] = 0;
#else
isrManager.isr_switch_trigger_flag = 0;
#endif
}
uint8 getIsrSwitchTrigerFlag()
{
#ifdef ARCH_SMP
return isrManager.isr_switch_trigger_flag[GetCpuId()];
#else
return isrManager.isr_switch_trigger_flag ;
#endif
}
struct IsrDone isrDone = {
Is_InIsr,
RegisterHwIrq ,
FreeHwIrq,
EnableHwIrq,
DisableHwIrq,
IsrCommon,
GetIsrCounter,
incIsrCounter,
decIsrCounter,
getIsrSwitchTrigerFlag,
setIsrSwitchTrigerFlag,
clearIsrSwitchTrigerFlag
} ;
void SysInitIsrManager()
{
extern int __isrtbl_idx_start;
extern int __isrtbl_start;
extern int __isrtbl_end;
memset(&isrManager,0,sizeof(struct InterruptServiceRoutines));
isrManager.done = &isrDone;
uint32 *index = (uint32 *)&__isrtbl_idx_start;
struct IrqDesc *desc = (struct IrqDesc *)&__isrtbl_start;
while (desc != (struct IrqDesc *)&__isrtbl_end)
isrManager.irq_table[*index++] = *desc++;
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: kservicetask.c
* @brief: create service task for system
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
extern void ZombieTaskRecycleInit(void);
extern void InitIdleKTask(void);
void KSerciveKTaskIdle(void)
{
InitIdleKTask();
}
void xz_KServiceKTaskRecycle()
{
ZombieTaskRecycleInit();
}
void CreateKServiceKTask(void)
{
/* create zombie recycle task */
xz_KServiceKTaskRecycle();
/* create idle task */
KSerciveKTaskIdle();
}

1125
kernel/thread/ktask.c Normal file

File diff suppressed because it is too large Load Diff

105
kernel/thread/ktask_stat.c Normal file
View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: ktask_stat.c
* @brief: the stat function definition of task
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#ifndef XS_KTASK_STAT_H
#define XS_KTASK_STAT_H
#include <xs_kdbg.h>
#include <xs_base.h>
#include <xs_ktask.h>
#include <stdbool.h>
#include <xs_ktask_stat.h>
void KTaskStateSet(KTaskDescriptorType task, uint8 stat)
{
NULL_PARAM_CHECK(task);
task->task_dync_sched_member.stat = stat | (task->task_dync_sched_member.stat & ~KTASK_STAT_MASK);
}
void KTaskStatSetAsInit(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
KTaskStateSet(task, KTASK_INIT);
}
void KTaskStatSetAsReady(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
KTaskStateSet(task, KTASK_READY);
}
void KTaskStatSetAsSuspend(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
KTaskStateSet(task, KTASK_SUSPEND);
}
void KTaskStatSetAsRunning(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
KTaskStateSet(task, KTASK_RUNNING);
}
void KTaskStatSetAsClose(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
KTaskStateSet(task, KTASK_CLOSE);
}
uint8 KTaskStatGet(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
return task->task_dync_sched_member.stat & KTASK_STAT_MASK;
}
bool JudgeKTaskStatIsInit(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
return ((task->task_dync_sched_member.stat & KTASK_STAT_MASK) == KTASK_INIT);
}
bool JudgeKTaskStatIsReady(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
return ((task->task_dync_sched_member.stat & KTASK_STAT_MASK) == KTASK_READY);
}
bool JudgeKTaskStatIsSuspend(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
return ((task->task_dync_sched_member.stat & KTASK_STAT_MASK) == KTASK_SUSPEND);
}
bool JudgeKTaskStatIsRunning(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
return ((task->task_dync_sched_member.stat & KTASK_STAT_MASK) == KTASK_RUNNING);
}
bool JudgeKTaskStatIsClose(KTaskDescriptorType task)
{
NULL_PARAM_CHECK(task);
return ((task->task_dync_sched_member.stat & KTASK_STAT_MASK) == KTASK_CLOSE);
}
#endif

132
kernel/thread/linklist.c Normal file
View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: linklist.c
* @brief: suspend and wakeup function of task
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
/**
* a task will be suspended to a pend list
*
* @param list suspend task list
* @param task the task descriptor need to be suspended
* @param flag suspend flag
*
*/
x_err_t LinklistSuspend(DoubleLinklistType *list,
struct TaskDescriptor *task,
uint8 flag)
{
int32 ret = EOK;
x_ubase lock = 0;
DoubleLinklistType *node = NONE;
DoubleLinklistType *tail = NONE;
struct TaskDescriptor *tmp_task = NONE;
NULL_PARAM_CHECK(list);
NULL_PARAM_CHECK(task);
lock = CriticalAreaLock();
SuspendKTask(task->id.id);
switch (flag)
{
case LINKLIST_FLAG_FIFO:
DoubleLinkListInsertNodeBefore(list, &(task->task_dync_sched_member.sched_link));
break;
case LINKLIST_FLAG_PRIO:
DOUBLE_LINKLIST_FOR_EACH(node,list)
{
tmp_task = SYS_DOUBLE_LINKLIST_ENTRY(node, struct TaskDescriptor, task_dync_sched_member.sched_link);
if (task->task_dync_sched_member.cur_prio < tmp_task->task_dync_sched_member.cur_prio)
{
break;
}
}
if(node != list) {
DoubleLinkListInsertNodeBefore(&(tmp_task->task_dync_sched_member.sched_link), &(task->task_dync_sched_member.sched_link));
} else {
tail = list->node_prev;
DoubleLinkListInsertNodeAfter(tail,&(task->task_dync_sched_member.sched_link));
}
break;
default:
ret = -EINVALED;
break;
}
CriticalAreaUnLock(lock);
return ret;
}
/**
* resume the first task in the suspend list
*
* @param list task list
*
*/
x_err_t LinklistResume(DoubleLinklistType *list)
{
x_ubase lock = 0;
struct TaskDescriptor *task = NONE;
NULL_PARAM_CHECK(list);
lock = CriticalAreaLock();
task = SYS_DOUBLE_LINKLIST_ENTRY(list->node_next, struct TaskDescriptor, task_dync_sched_member.sched_link);
SYS_KDEBUG_LOG(KDBG_IPC, ("resume task:%s\n", task->task_base_info.name));
KTaskWakeup(task->id.id);
CriticalAreaUnLock(lock);
return EOK;
}
/**
* wakeup all the task in the suspend list
*
* @param list task list
*
*/
x_err_t LinklistResumeAll(DoubleLinklistType *list)
{
x_ubase lock = 0;
struct TaskDescriptor *task = NONE;
DoubleLinklistType *node = NONE;
NULL_PARAM_CHECK(list);
lock = CriticalAreaLock();
for(;;) {
node = list->node_next;
if(node != list) {
task = SYS_DOUBLE_LINKLIST_ENTRY(node, struct TaskDescriptor, task_dync_sched_member.sched_link);
task->exstatus = -ERROR;
KTaskWakeup(task->id.id);
} else {
break;
}
}
CriticalAreaUnLock(lock);
return EOK;
}

110
kernel/thread/lock.c Normal file
View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: lock.c
* @brief: system spinlock file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xs_spinlock.h>
#include <xiuos.h>
#include <xs_assign.h>
#ifdef ARCH_SMP
struct Spin_Lockfileops spinlock;
/*
* lock scheduler
*/
static void DisablePreempt(void)
{
x_base lock = 0;
lock = DisableLocalInterrupt();
Assign.assign_lock[GetCpuId()] ++;
EnableLocalInterrupt(lock);
}
/*
* enable scheduler
*/
static void EnablePreempt(void)
{
x_base lock = 0;
lock = DisableLocalInterrupt();
Assign.assign_lock[GetCpuId()] --;
DO_KTASK_ASSIGN;
EnableLocalInterrupt(lock);
}
void InitSpinLock( struct Spin_Lockfileops * spinlock)
{
InitHwSpinlock(&spinlock->node_lock.lock);
spinlock->SPinLock = _SpinLock;
spinlock->UnlockSpinLock =_UnlockSpinLock;
spinlock->UnlockSpinLockIrqRestore = _UnlockSpinLockIrqRestore;
spinlock->SpinLockIrqSave = _SpinLockIrqSave;
}
void _SpinLock(struct Spin_Lockfileops * spinlock)
{
DisablePreempt();
HwLockSpinlock(&spinlock->node_lock.lock);
}
void _UnlockSpinLock(struct Spin_Lockfileops * spinlock)
{
HwUnlockSpinlock(&spinlock->node_lock.lock);
EnablePreempt();
}
x_base _SpinLockIrqSave(struct Spin_Lockfileops * spinlock)
{
x_base lock = 0;
DisablePreempt();
lock = DisableLocalInterrupt();
HwLockSpinlock(&spinlock->node_lock.lock);
return lock;
}
void _UnlockSpinLockIrqRestore(struct Spin_Lockfileops * spinlock, x_base lock)
{
HwUnlockSpinlock(&spinlock->node_lock.lock);
EnableLocalInterrupt(lock);
EnablePreempt();
}
#endif
/**
* This function will restore the scheduler lock status
*
*/
void RestoreCpusLockStatus(struct TaskDescriptor *task)
{
#ifdef ARCH_SMP
Assign.smp_os_running_task[GetCpuId()] = task;
HwUnlockSpinlock(&AssignSpinLock);
#else
Assign.os_running_task = task;
#endif
}

496
kernel/thread/msgqueue.c Normal file
View File

@@ -0,0 +1,496 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: msgqueue.c
* @brief: msgqueue file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#include <xs_delay.h>
DECLARE_ID_MANAGER(k_mq_id_manager, ID_NUM_MAX);
DoubleLinklistType k_mq_list = {&k_mq_list, &k_mq_list};
struct mq_message
{
struct mq_message *next;
};
static struct MsgQueue *GetMsgQueueById(int32 id)
{
x_base lock = 0;
struct MsgQueue *mq = NONE;
struct IdNode *idnode = NONE;
if (id < 0 )
return NONE;
lock = CriticalAreaLock();
idnode = IdGetObj(&k_mq_id_manager, id);
if (idnode == NONE){
CriticalAreaUnLock(lock);
return NONE;
}
mq = CONTAINER_OF(idnode, struct MsgQueue, id);
CriticalAreaUnLock(lock);
return mq;
}
static x_err_t _InitMsgQueue( struct MsgQueue *mq ,x_size_t msg_size,
x_size_t max_msgs )
{
x_base lock = 0;
NULL_PARAM_CHECK(mq);
mq->max_msgs = max_msgs;
mq->num_msgs = 0;
mq->each_len = ALIGN_MEN_UP(msg_size, MEM_ALIGN_SIZE);
mq->index = 0;
InitDoubleLinkList(&mq->send_pend_list);
InitDoubleLinkList(&(mq->recv_pend_list));
mq->msg_buf = x_malloc( mq->each_len * mq->max_msgs);
if (mq->msg_buf == NONE) {
lock = CriticalAreaLock();
DoubleLinkListRmNode(&(mq->link));
CriticalAreaUnLock(lock);
KERNEL_FREE(mq);
return -ENOMEMORY;
}
return EOK;
}
static x_err_t _MsgQueueSend(struct MsgQueue *mq,
const void *buffer,
x_size_t size,
int32 msec)
{
x_ubase lock = 0;
uint32 tick_delta = 0;
int32 timeout = 0;
uint8 *msg = NONE;
struct TaskDescriptor *task = NONE;
NULL_PARAM_CHECK(mq);
NULL_PARAM_CHECK(buffer);
if (size > mq->each_len)
return -ERROR;
tick_delta = 0;
task = GetKTaskDescriptor();
timeout = CalculteTickFromTimeMs(msec);
lock = CriticalAreaLock();
if (mq->num_msgs >= mq->max_msgs && timeout == 0) {
CriticalAreaUnLock(lock);
return -EFULL;
}
while(mq->num_msgs >= mq->max_msgs ) {
task->exstatus = EOK;
if (timeout == 0) {
CriticalAreaUnLock(lock);
return -EFULL;
}
KDEBUG_IN_KTASK_CONTEXT;
LinklistSuspend(&(mq->send_pend_list), task, LINKLIST_FLAG_FIFO);
if (timeout > 0) {
tick_delta = CurrentTicksGain();
SYS_KDEBUG_LOG(KDBG_IPC, ("mq_send_wait: start timer of task:%s\n",
task->task_base_info.name));
KTaskSetDelay(task,timeout);
}
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
if (task->exstatus != EOK) {
return task->exstatus;
}
lock = CriticalAreaLock();
if (timeout > 0) {
tick_delta = CurrentTicksGain() - tick_delta;
timeout -= tick_delta;
if (timeout < 0)
timeout = 0;
}
}
msg = mq->msg_buf + ( ( mq->index + mq->num_msgs ) % mq->max_msgs ) * mq->each_len ;
memcpy(msg, buffer, size);
mq->num_msgs ++;
if (!IsDoubleLinkListEmpty(&mq->recv_pend_list)) {
LinklistResume(&(mq->recv_pend_list));
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
return EOK;
}
CriticalAreaUnLock(lock);
return EOK;
}
static x_err_t _MsgQueueUrgentSend(struct MsgQueue *mq, const void *buffer, x_size_t size)
{
x_ubase lock = 0;
uint8 *msg = NONE;
NULL_PARAM_CHECK(mq);
NULL_PARAM_CHECK(buffer);
if (size > mq->each_len)
return -ERROR;
lock = CriticalAreaLock();
if (mq->num_msgs >= mq->max_msgs) {
CriticalAreaUnLock(lock);
return -EFULL;
}
mq->index --;
if (mq->index < 0)
mq->index += mq->max_msgs;
msg = mq->msg_buf + ( ( mq->index + mq->num_msgs ) % mq->max_msgs ) * mq->each_len ;
memcpy(msg , buffer, size);
mq->num_msgs ++;
if (!IsDoubleLinkListEmpty(&mq->send_pend_list)) {
LinklistResume(&(mq->send_pend_list));
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
return EOK;
}
CriticalAreaUnLock(lock);
return EOK;
}
static x_err_t _MsgQueueRecv(struct MsgQueue *mq,
void *buffer,
x_size_t size,
int32 msec)
{
x_ubase lock = 0;
uint32 tick_delta = 0;
int32 timeout = 0;
struct mq_message *msg = NONE;
struct TaskDescriptor *task = NONE;
NULL_PARAM_CHECK(mq);
NULL_PARAM_CHECK(buffer);
tick_delta = 0;
task = GetKTaskDescriptor();
timeout = CalculteTickFromTimeMs(msec);
lock = CriticalAreaLock();
if (mq->index == 0 && timeout == 0) {
CriticalAreaUnLock(lock);
return -ETIMEOUT;
}
for( ; mq->num_msgs <= 0 ; ) {
KDEBUG_IN_KTASK_CONTEXT;
task->exstatus = EOK;
if (timeout == 0) {
CriticalAreaUnLock(lock);
task->exstatus = -ETIMEOUT;
return -ETIMEOUT;
}
LinklistSuspend(&(mq->recv_pend_list),
task,
LINKLIST_FLAG_FIFO);
if (timeout > 0) {
tick_delta = CurrentTicksGain();
SYS_KDEBUG_LOG(KDBG_IPC, ("set task:%s to timer list\n",
task->task_base_info.name));
KTaskSetDelay(task,timeout);
}
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
if (task->exstatus != EOK) {
return task->exstatus;
}
lock = CriticalAreaLock();
if (timeout > 0) {
tick_delta = CurrentTicksGain() - tick_delta;
timeout -= tick_delta;
if (timeout < 0)
timeout = 0;
}
}
msg = mq->msg_buf + mq->index * mq->each_len;
mq->index = (mq->index + 1) % mq->max_msgs;
memcpy(buffer, msg , size > mq->each_len ? mq->each_len : size);
mq->num_msgs --;
if (!IsDoubleLinkListEmpty(&(mq->send_pend_list))) {
LinklistResume(&(mq->send_pend_list));
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
return EOK;
}
CriticalAreaUnLock(lock);
return EOK;
}
static x_err_t _MsgQueueReinit(struct MsgQueue *mq)
{
x_ubase lock = 0;
NULL_PARAM_CHECK(mq);
lock = CriticalAreaLock();
LinklistResumeAll(&mq->send_pend_list);
LinklistResumeAll(&(mq->recv_pend_list));
mq->index = 0;
mq->num_msgs = 0;
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
return EOK;
}
static x_err_t _DeleteMsgQueue(struct MsgQueue *mq)
{
x_base lock = 0;
NULL_PARAM_CHECK(mq);
LinklistResumeAll(&(mq->send_pend_list));
LinklistResumeAll(&(mq->recv_pend_list));
KERNEL_FREE(mq->msg_buf);
lock = CriticalAreaLock();
DoubleLinkListRmNode(&(mq->link));
CriticalAreaUnLock(lock);
KERNEL_FREE(mq);
return EOK;
}
static struct MsgQueueDone Done = {
.init = _InitMsgQueue ,
.urgensend = _MsgQueueUrgentSend,
.send = _MsgQueueSend,
.recv = _MsgQueueRecv,
.reinit = _MsgQueueReinit,
.Delete = _DeleteMsgQueue
};
/**
* This function will create a msg queue.
*
* @param msg_size the length of the msg queue.
* @param max_msgs the max length of the msg queue.
*
* @return id on success;ENOMEMORY/ERROR on failure
*/
int32 KCreateMsgQueue(x_size_t msg_size,
x_size_t max_msgs)
{
int32 id = 0;
x_base temp = 0;
x_base lock = 0;
struct MsgQueue *mq = NONE;
mq = (struct MsgQueue *)x_malloc(sizeof(struct MsgQueue));
if (mq == NONE)
return -ENOMEMORY;
memset(mq,0x0,sizeof(struct MsgQueue));
lock = CriticalAreaLock();
id = IdInsertObj(&k_mq_id_manager, &mq->id);
CriticalAreaUnLock(lock);
if (id < 0) {
x_free(mq);
return -ENOMEMORY;
}
lock = CriticalAreaLock();
DoubleLinkListInsertNodeAfter(&k_mq_list, &mq->link);
CriticalAreaUnLock(lock);
mq->Done = &Done;
if( mq->Done->init(mq, msg_size,max_msgs) == EOK )
return mq->id.id;
else
return -ERROR;
}
/**
* This function will reset a event.
*
* @param id the id number of event.
*
* @return EOK on success;EINVALED on failure
*/
x_err_t KMsgQueueReinit(int32 id)
{
struct MsgQueue *mq = NONE;
if (id < 0)
return -EINVALED;
mq = GetMsgQueueById(id);
if (mq != NONE)
return mq->Done->reinit(mq);
else
return -EINVALED;
}
/**
* receive message with some waiting time
*
* @param id the message id
* @param buffer message info
* @param size the size of buffer
* @param timeout time needed waiting
*
* @return EOK on success;EINVALED on failure
*
*/
x_err_t KMsgQueueRecv(int32 id,
void *buffer,
x_size_t size,
int32 timeout)
{
struct MsgQueue *mq = NONE;
if (id < 0)
return -EINVALED;
mq = GetMsgQueueById(id);
if (mq != NONE)
return mq->Done->recv(mq,buffer,size,timeout);
else
return -EINVALED;
}
/**
* a dynamic messagequeue will be deleted from the manage list
*
* @param id the message id
*
* @return EOK on success;EINVALED on failure
*
*/
x_err_t KDeleteMsgQueue(int32 id)
{
struct MsgQueue *mq = NONE;
if (id < 0)
return -EINVALED;
mq = GetMsgQueueById(id);
if (mq != NONE)
return mq->Done->Delete(mq);
else
return -EINVALED;
}
/**
* send urgent message without waiting time, this message will be inserted to the head of the queue
*
* @param id the message id
* @param buffer message info
* @param size the size of buffer
*
* @return EOK on success;EINVALED on failure
*
*/
x_err_t KMsgQueueUrgentSend(int32 id, const void *buffer, x_size_t size)
{
struct MsgQueue *mq = NONE;
if (id < 0)
return -EINVALED;
mq = GetMsgQueueById(id);
if (mq != NONE)
return mq->Done->urgensend(mq,buffer,size);
else
return -EINVALED;
}
/**
* send message without waiting time,current suspend task will be resumed
*
* @param id the message id
* @param buffer message info
* @param size the size of buffer
*
* @return EOK on success;EINVALED on failure
*
*/
x_err_t KMsgQueueSend(int32 id, const void *buffer, x_size_t size)
{
struct MsgQueue *mq = NONE;
if (id < 0)
return -EINVALED;
mq = GetMsgQueueById(id);
if (mq != NONE)
return mq->Done->send(mq,buffer,size,0);
else
return -EINVALED;
}
/**
* send message with waiting time,current suspend task will be resumed
*
* @param id the message id
* @param buffer message info
* @param size the size of buffer
* @param timeout waiting time
*
* @return EOK on success;EINVALED on failure
*
*/
x_err_t KMsgQueueSendwait(int32 id, const void *buffer, x_size_t size,int32 timeout)
{
struct MsgQueue *mq = NONE;
if (id < 0)
return -EINVALED;
mq = GetMsgQueueById(id);
if (mq != NONE)
return mq->Done->send(mq,buffer,size,timeout);
else
return -EINVALED;
}

315
kernel/thread/mutex.c Normal file
View File

@@ -0,0 +1,315 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: mutex.c
* @brief: mutex file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
DECLARE_ID_MANAGER(k_mutex_id_manager, ID_NUM_MAX);
DoubleLinklistType k_mutex_list ={&k_mutex_list, &k_mutex_list}; ///< global mutex manage list
static int32 _MutexCreate()
{
int32 id = 0;
x_base lock = 0;
struct Mutex *mutex = NONE;
mutex = x_malloc(sizeof(struct Mutex));
if (mutex == NONE) {
return -ENOMEMORY;
}
memset(mutex, 0x0, sizeof(struct Mutex));
lock = CriticalAreaLock();
id = IdInsertObj(&k_mutex_id_manager, &mutex->id);
if (id < 0) {
CriticalAreaUnLock(lock);
x_free(mutex);
return -ENOMEMORY;
}
InitDoubleLinkList(&mutex->pend_list);
mutex->val = 1;
mutex->holder = NONE;
mutex->origin_prio = 0xFF;
mutex->recursive_cnt = 0;
DoubleLinkListInsertNodeAfter(&k_mutex_list, &mutex->link);
CriticalAreaUnLock(lock);
return id;
}
static void _MutexDelete(struct Mutex *mutex)
{
x_base lock = 0;
NULL_PARAM_CHECK(mutex);
LinklistResumeAll(&mutex->pend_list);
lock = CriticalAreaLock();
IdRemoveObj(&k_mutex_id_manager, mutex->id.id);
DoubleLinkListRmNode(&(mutex->link));
CriticalAreaUnLock(lock);
x_free(mutex);
}
static int32 _MutexObtain(struct Mutex *mutex, int32 msec)
{
x_base lock = 0;
int32 wait_time = 0;
struct TaskDescriptor *task = NONE;
NULL_PARAM_CHECK(mutex);
task = GetKTaskDescriptor();
wait_time = CalculteTickFromTimeMs(msec);
lock = CriticalAreaLock();
SYS_KDEBUG_LOG(KDBG_IPC,
("mutex_take: current task %s, mutex value: %d, hold: %d\n",
task->task_base_info.name, mutex->val, mutex->recursive_cnt));
task->exstatus = EOK;
if (mutex->holder == task) {
mutex->recursive_cnt++;
} else {
if (mutex->val > 0) {
mutex->val--;
mutex->holder = task;
mutex->origin_prio = task->task_dync_sched_member.cur_prio;
mutex->recursive_cnt++;
} else {
if (wait_time == 0) {
task->exstatus = -ETIMEOUT;
CriticalAreaUnLock(lock);
return -ETIMEOUT;
} else {
SYS_KDEBUG_LOG(KDBG_IPC, ("mutex_take: suspend task: %s\n",
task->task_base_info.name));
if (task->task_dync_sched_member.cur_prio > mutex->holder->task_dync_sched_member.cur_prio)
{
KTaskPrioSet(mutex->holder->id.id, task->task_dync_sched_member.cur_prio);
}
LinklistSuspend(&(mutex->pend_list), task, LINKLIST_FLAG_PRIO);
if (wait_time > 0) {
SYS_KDEBUG_LOG(KDBG_IPC,
("mutex_take: start the timer of task:%s\n",
task->task_base_info.name));
KTaskSetDelay(task,wait_time);
}
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
if (task->exstatus != EOK) {
return task->exstatus;
} else {
lock = CriticalAreaLock();
}
}
}
}
CriticalAreaUnLock(lock);
return EOK;
}
static int32 _MutexAbandon(struct Mutex *mutex)
{
int resched = 0;
x_base lock = 0;
struct TaskDescriptor *task = NONE;
NULL_PARAM_CHECK(mutex);
task = GetKTaskDescriptor();
lock = CriticalAreaLock();
SYS_KDEBUG_LOG(KDBG_IPC,
("mutex_release:current task %s, mutex value: %d, hold: %d\n",
task->task_base_info.name, mutex->val, mutex->recursive_cnt));
if (task != mutex->holder) {
task->exstatus = -ERROR;
CriticalAreaUnLock(lock);
return -ERROR;
}
mutex->recursive_cnt --;
if (mutex->recursive_cnt == 0) {
if (mutex->origin_prio != mutex->holder->task_dync_sched_member.cur_prio)
{
KTaskPrioSet(mutex->holder->id.id, mutex->origin_prio);
}
if (!IsDoubleLinkListEmpty(&mutex->pend_list)) {
task = SYS_DOUBLE_LINKLIST_ENTRY(mutex->pend_list.node_next, struct TaskDescriptor, task_dync_sched_member.sched_link);
SYS_KDEBUG_LOG(KDBG_IPC, ("mutex_release: resume task: %s\n",
task->task_base_info.name));
mutex->holder = task;
mutex->origin_prio = task->task_dync_sched_member.cur_prio;
mutex->recursive_cnt++;
LinklistResume(&(mutex->pend_list));
resched = RET_TRUE;
} else {
mutex->val++;
mutex->holder = NONE;
mutex->origin_prio = 0xff;
}
}
CriticalAreaUnLock(lock);
if (resched == RET_TRUE)
DO_KTASK_ASSIGN;
return EOK;
}
static MutexDoneType done = {
.MutexCreate = _MutexCreate,
.MutexDelete = _MutexDelete,
.MutexObtain = _MutexObtain,
.MutexAbandon = _MutexAbandon,
};
/**
* a mutex will be inited in static way,then this mutex will be inserted to the manage list
*
* @param mutex the mutex descriptor
* @param name mutex name
* @param flag mutex flag
*
* @return EOK on success
*
*/
int32 KMutexCreate()
{
KDEBUG_NOT_IN_INTERRUPT;
return done.MutexCreate();
}
/**
* a dynamic mutex will be deleted from the manage list
*
* @param mutex mutex descriptor
*
*/
void KMutexDelete(int32 id)
{
KDEBUG_NOT_IN_INTERRUPT;
x_base lock = 0;
struct Mutex *mutex = NONE;
struct IdNode *idnode = NONE;
if (id < 0)
return;
lock = CriticalAreaLock();
idnode = IdGetObj(&k_mutex_id_manager, id);
if (idnode == NONE) {
CriticalAreaUnLock(lock);
return;
}
mutex =CONTAINER_OF(idnode, struct Mutex, id);
CriticalAreaUnLock(lock);
done.MutexDelete(mutex);
}
/**
* a mutex will be taken when mutex is available
*
* @param mutex mutex descriptor
* @param msec the time needed waiting
*
* @return EOK on success;ERROR on failure
*
*/
int32 KMutexObtain(int32 id, int32 msec)
{
KDEBUG_IN_KTASK_CONTEXT;
x_base lock = 0;
struct Mutex *mutex = NONE;
struct IdNode *idnode = NONE;
if (id < 0)
return -ERROR;
lock = CriticalAreaLock();
idnode = IdGetObj(&k_mutex_id_manager, id);
if (idnode == NONE){
CriticalAreaUnLock(lock);
return -ERROR;
}
mutex =CONTAINER_OF(idnode, struct Mutex, id);
CriticalAreaUnLock(lock);
return done.MutexObtain(mutex, msec);
}
/**
* release the mutex and resume corresponding suspended task
*
* @param mutex mutex descriptor
*
* @return EOK on success;ERROR on failure
*/
int32 KMutexAbandon(int32 id)
{
KDEBUG_IN_KTASK_CONTEXT;
x_base lock = 0;
struct Mutex *mutex = NONE;
struct IdNode *idnode = NONE;
if (id < 0)
return -ERROR;
lock = CriticalAreaLock();
idnode = IdGetObj(&k_mutex_id_manager, id);
if (idnode == NONE) {
CriticalAreaUnLock(lock);
return -ERROR;
}
mutex = CONTAINER_OF(idnode, struct Mutex, id);
CriticalAreaUnLock(lock);
return done.MutexAbandon(mutex);
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: queue_manager.c
* @brief: Unified management of queue
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xs_queue_manager.h>
#include <xs_dataqueue.h>
#include <xs_workqueue.h>
#include <xs_waitqueue.h>
#include <xs_memory.h>
void* g_queue_done[QUEUE_MAX];
void queuemanager_done_register()
{
DataQueueDoneType* pdata_queue_done = (DataQueueDoneType*)x_malloc(sizeof(DataQueueDoneType));
pdata_queue_done->InitDataqueue = InitDataqueue;
pdata_queue_done->PushDataqueue = PushDataqueue;
pdata_queue_done->PopDataqueue = PopDataqueue;
pdata_queue_done->DataqueuePeak = DataqueuePeak;
pdata_queue_done->DeInitDataqueue = DeInitDataqueue;
WorkQueueDoneType* pwork_queue_done = (WorkQueueDoneType*)x_malloc(sizeof(WorkQueueDoneType));
pwork_queue_done->CreateWorkQueue = CreateWorkQueue;
pwork_queue_done->WorkInit = WorkInit;
pwork_queue_done->WorkSubmit = WorkSubmit;
pwork_queue_done->WorkSubmit_immediate = WorkSubmit_immediate;
WaitQueueDoneType* pwait_queue_done = (WaitQueueDoneType*)x_malloc(sizeof(WaitQueueDoneType));
pwait_queue_done->InitWqueue = InitWqueue;
pwait_queue_done->WqueueAdd = WqueueAdd;
pwait_queue_done->WqueueRemove = WqueueRemove;
pwait_queue_done->WqueueWait = WqueueWait;
pwait_queue_done->WakeupWqueue = WakeupWqueue;
g_queue_done[DATA_QUEUE] = pdata_queue_done;
g_queue_done[WORK_QUEUE] = pwork_queue_done;
g_queue_done[WAIT_QUEUE] = pwait_queue_done;
}

327
kernel/thread/semaphore.c Normal file
View File

@@ -0,0 +1,327 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: semaphore.c
* @brief: semaphore file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#ifdef KDEBUG_NOT_IN_INTERRUPT
#undef KDEBUG_NOT_IN_INTERRUPT
#endif
#define KDEBUG_NOT_IN_INTERRUPT
DECLARE_ID_MANAGER(k_sem_id_manager, ID_NUM_MAX);
DoubleLinklistType k_sem_list = {&k_sem_list, &k_sem_list};
static int32 _SemaphoreCreate(uint16 val)
{
int32 id = 0;
x_base lock = 0;
struct Semaphore *sem = NONE;
sem = (struct Semaphore *)x_malloc(sizeof(struct Semaphore));
if (sem == NONE)
return -ENOMEMORY;
memset(sem, 0, sizeof(struct Semaphore));
lock = CriticalAreaLock();
id = IdInsertObj(&k_sem_id_manager, &sem->id);
if (id < 0) {
x_free(sem);
CriticalAreaUnLock(lock);
return -ENOMEMORY;
}
sem->value = val;
InitDoubleLinkList(&sem->pend_list);
DoubleLinkListInsertNodeAfter(&k_sem_list, &sem->link);
CriticalAreaUnLock(lock);
SYS_KDEBUG_LOG(KDBG_IPC, ("created semaphore: id %d, value %d\n", id, (int)val));
return id;
}
static void _SemaphoreDelete(struct Semaphore *sem)
{
int resched = 0;
x_base lock = 0;
NULL_PARAM_CHECK(sem);
SYS_KDEBUG_LOG(KDBG_IPC, ("deleted semaphore: id %d\n", (int)sem->id.id));
lock = CriticalAreaLock();
if (!IsDoubleLinkListEmpty(&sem->pend_list)) {
resched = 1;
LinklistResumeAll(&sem->pend_list);
}
IdRemoveObj(&k_sem_id_manager, sem->id.id);
DoubleLinkListRmNode(&sem->link);
CriticalAreaUnLock(lock);
x_free(sem);
if (resched){
DO_KTASK_ASSIGN;
}
}
static int32 _SemaphoreObtain(struct Semaphore *sem, int32 msec)
{
int lock = 0;
int32 wait_time = 0;
struct TaskDescriptor *task = NONE;
NULL_PARAM_CHECK(sem);
wait_time = CalculteTickFromTimeMs(msec);
lock = CriticalAreaLock();
SYS_KDEBUG_LOG(KDBG_IPC, ("obtain semaphore: id %d, value %d, by task %s\n",
(int)sem->id.id, (int)sem->value, GetKTaskDescriptor()->task_base_info.name));
if (sem->value > 0) {
sem->value--;
CriticalAreaUnLock(lock);
return EOK;
}
if (wait_time == 0) {
CriticalAreaUnLock(lock);
return -ETIMEOUT;
}
task = GetKTaskDescriptor();
task->exstatus = EOK;
SYS_KDEBUG_LOG(KDBG_IPC, ("obtain semaphore: suspending task %s\n",
GetKTaskDescriptor()->task_base_info.name));
LinklistSuspend(&sem->pend_list, task, LINKLIST_FLAG_PRIO);
if (wait_time > 0) {
KTaskSetDelay(task, wait_time);
}
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
return task->exstatus;
}
static int32 _SemaphoreAbandon(struct Semaphore *sem)
{
int lock = 0;
int resched = 0;
NULL_PARAM_CHECK(sem);
lock = CriticalAreaLock();
SYS_KDEBUG_LOG(KDBG_IPC, ("abandon semaphore: id %d, value %d, by task %s\n",
(int)sem->id.id, (int)sem->value, GetKTaskDescriptor()->task_base_info.name));
if (!IsDoubleLinkListEmpty(&sem->pend_list)) {
resched = 1;
LinklistResume(&sem->pend_list);
} else {
sem->value++;
}
CriticalAreaUnLock(lock);
if (resched){
DO_KTASK_ASSIGN;
}
return EOK;
}
static int32 _SemaphoreSetValue(struct Semaphore *sem, uint16 val)
{
int lock = 0;
int resched = 0;
NULL_PARAM_CHECK(sem);
lock = CriticalAreaLock();
SYS_KDEBUG_LOG(KDBG_IPC, ("set semaphore value: id %d, old value %d, new value %d, by task %s\n",
(int)sem->id.id, (int)sem->value, (int)val, GetKTaskDescriptor()->task_base_info.name));
if (sem->value == val) {
CriticalAreaUnLock(lock);
return EOK;
}
if (!IsDoubleLinkListEmpty(&sem->pend_list)) {
resched = 1;
LinklistResumeAll(&sem->pend_list);
}
sem->value = val;
CriticalAreaUnLock(lock);
if (resched)
DO_KTASK_ASSIGN;
return EOK;
}
static SemaphoreDoneType done = {
.SemaphoreCreate = _SemaphoreCreate,
.SemaphoreDelete = _SemaphoreDelete,
.SemaphoreObtain = _SemaphoreObtain,
.SemaphoreAbandon = _SemaphoreAbandon,
.SemaphoreSetValue = _SemaphoreSetValue,
};
/**
* Create a new semaphore with specified initial value.
*
* @param val initial value
* @return id of the semaphore
*/
int32 KSemaphoreCreate(uint16 val)
{
KDEBUG_NOT_IN_INTERRUPT;
return done.SemaphoreCreate(val);
}
/**
* Delete a semaphore and wakeup all pending tasks on it.
*
* @param id id of the semaphore to be deleted
*/
void KSemaphoreDelete(int32 id)
{
x_base lock = 0;
struct Semaphore *sem = NONE;
struct IdNode *idnode = NONE;
KDEBUG_NOT_IN_INTERRUPT;
if (id < 0)
return;
lock = CriticalAreaLock();
idnode = IdGetObj(&k_sem_id_manager, id);
if (idnode == NONE){
CriticalAreaUnLock(lock);
return;
}
CriticalAreaUnLock(lock);
sem = CONTAINER_OF(idnode, struct Semaphore, id);
done.SemaphoreDelete(sem);
}
/**
* Obtain a semaphore when its value is greater than 0; pend on it otherwise.
*
* @param id id of the semaphore to be obtained
* @param msec wait time in millisecond
* @return EOK on success, error code on failure
*/
int32 KSemaphoreObtain(int32 id, int32 msec)
{
KDEBUG_NOT_IN_INTERRUPT;
x_base lock = 0;
struct Semaphore *sem = NONE;
struct IdNode *idnode = NONE;
if (id < 0)
return -ERROR;
lock = CriticalAreaLock();
idnode = IdGetObj(&k_sem_id_manager, id);
if (idnode == NONE){
CriticalAreaUnLock(lock);
return -ERROR;
}
sem =CONTAINER_OF(idnode, struct Semaphore, id);
CriticalAreaUnLock(lock);
return done.SemaphoreObtain(sem, msec);
}
/**
* Abandon a semaphore and wakeup a pending task if any.
*
* @param id id of the semaphore to be abandoned
* @return EOK on success, error code on failure
*/
int32 KSemaphoreAbandon(int32 id)
{
KDEBUG_NOT_IN_INTERRUPT;
x_base lock = 0;
struct Semaphore *sem = NONE;
struct IdNode *idnode = NONE;
if (id < 0)
return -ERROR;
lock = CriticalAreaLock();
idnode = IdGetObj(&k_sem_id_manager, id);
if (idnode == NONE) {
CriticalAreaUnLock(lock);
return -ERROR;
}
sem =CONTAINER_OF(idnode, struct Semaphore, id);
CriticalAreaUnLock(lock);
return done.SemaphoreAbandon(sem);
}
/**
* Set the value of a semaphore, wakeup all pending tasks if new value is positive.
*
* @param id id of the semaphore for which to set value
* @param val new value
* @return EOK on success, error code on failure
*/
int32 KSemaphoreSetValue(int32 id, uint16 val)
{
KDEBUG_NOT_IN_INTERRUPT;
x_base lock = 0;
struct Semaphore *sem = NONE;
struct IdNode *idnode = NONE;
if (id < 0)
return -ERROR;
lock = CriticalAreaLock();
idnode = IdGetObj(&k_sem_id_manager, id);
if (idnode == NONE) {
CriticalAreaUnLock(lock);
return -ERROR;
}
sem = CONTAINER_OF(idnode, struct Semaphore, id);
CriticalAreaUnLock(lock);
return done.SemaphoreSetValue(sem, val);
}

142
kernel/thread/single_link.c Normal file
View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: single_link.c
* @brief: functions definition of single linklist
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xs_klist.h>
/**
* This function will init a linklist.
*
* @param linklist_head linklist node
*/
void InitSingleLinkList(SysSingleLinklistType *linklist)
{
linklist->node_next = NONE;
}
void AppendSingleLinkList(SysSingleLinklistType *linklist, SysSingleLinklistType *linklist_node)
{
struct SingleLinklistNode *node;
node = linklist;
while (node->node_next) node = node->node_next;
node->node_next = linklist_node;
linklist_node->node_next = NONE;
}
/**
* This function will insert a node into list after the node.
*
* @param linklist linklist node
* @param linklist_node the node needed to inserted
*/
void SingleLinkListNodeInsert(SysSingleLinklistType *linklist, SysSingleLinklistType *linklist_node)
{
linklist_node->node_next = linklist->node_next;
linklist->node_next = linklist_node;
}
/**
* This function will get length of the list.
*
* @param linklist list head
* @return length
*/
unsigned int SingleLinkListGetLen(const SysSingleLinklistType *linklist)
{
unsigned int length = 0;
const SysSingleLinklistType *tmp_list = linklist->node_next;
while (tmp_list != NONE)
{
tmp_list = tmp_list->node_next;
length ++;
}
return length;
}
/**
* This function will remove a node from the list.
*
* @param linklist_node the node needed to removed
*/
SysSingleLinklistType *SingleLinkListRmNode(SysSingleLinklistType *linklist, SysSingleLinklistType *linklist_node)
{
struct SingleLinklistNode *node = linklist;
while (node->node_next && node->node_next != linklist_node) node = node->node_next;
if (node->node_next != (SysSingleLinklistType *)0){
node->node_next = node->node_next->node_next;
}
return linklist;
}
/**
* This function will get the head of the list.
*
* @param linklist list head
* @return list head
*/
SysSingleLinklistType *SingleLinkListGetFirstNode(SysSingleLinklistType *linklist)
{
return linklist->node_next;
}
/**
* This function will get the tail node of the list.
*
* @param linklist list head
* @return list taile node
*/
SysSingleLinklistType *SingleLinkListGetTailNode(SysSingleLinklistType *linklist)
{
while (linklist->node_next) linklist = linklist->node_next;
return linklist;
}
/**
* This function will get the next node of the list head.
*
* @param linklist list head
* @param linklist_node list head
* @return next node of the list head
*/
SysSingleLinklistType *SingleLinkListGetNextNode(SysSingleLinklistType *linklist_node)
{
return linklist_node->node_next;
}
/**
* This function will judge the list is empty.
*
* @param linklist the list head
* @return true
*/
int IsSingleLinkListEmpty(SysSingleLinklistType *linklist)
{
return linklist->node_next == NONE;
}

487
kernel/thread/smp_assign.c Normal file
View File

@@ -0,0 +1,487 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: smp_assign.c
* @brief: system scheduler of multiple cpu
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xs_isr.h>
#include <xs_spinlock.h>
#include <xs_ktask_stat.h>
#include <xs_assign.h>
#include <xs_hook.h>
#include <stdio.h>
struct Assign Assign;
HwSpinlock AssignSpinLock;
static struct PriorityReadyVectorDone ready_vector_done =
{
OsAssignReadyVectorInit,
KTaskInsertToReadyVector,
KTaskOsAssignRemoveKTask,
};
static inline x_ubase SmpGetReadyVectorHighestPrio(void)
{
uint8 coreid = GetCpuId();
return ((Assign.os_assign_read_vector.highest_prio > Assign.smp_os_assign_ready_rector[coreid].highest_prio) ? Assign.os_assign_read_vector.highest_prio : Assign.smp_os_assign_ready_rector[coreid].highest_prio);
}
/*
* get target highest priority task in ready queue
*/
static inline struct TaskDescriptor* SmpAssignTargetTaskSelect(void)
{
uint8 coreid = GetCpuId();
if (Assign.os_assign_read_vector.highest_prio > Assign.smp_os_assign_ready_rector[coreid].highest_prio)
{
return ChooseTaskWithHighestPrio(&Assign.os_assign_read_vector);
}
else
{
return ChooseTaskWithHighestPrio(&Assign.smp_os_assign_ready_rector[coreid]);
}
}
static inline void SmpOsAssignSwtichToNewTask(struct TaskDescriptor* old_task, struct TaskDescriptor* new_task)
{
NULL_PARAM_CHECK(old_task);
NULL_PARAM_CHECK(new_task);
Assign.ready_vector_done->remove(new_task);
KTaskStatSetAsRunning(new_task);
#ifdef USING_OVERFLOW_CHECK
_KTaskOsAssignStackCheck(new_task);
#endif
SwitchKtaskContext((x_ubase)&old_task->stack_point, (x_ubase)&new_task->stack_point, new_task);
}
static inline void SmpSwitchToFirstRunningTask(struct TaskDescriptor* task)
{
NULL_PARAM_CHECK(task);
Assign.ready_vector_done->remove(task);
KTaskStatSetAsRunning(task);
SwitchKtaskContextTo((x_ubase)&task->stack_point, task);
}
static inline void SetSystemRunningTask(struct TaskDescriptor* task)
{
NULL_PARAM_CHECK(task);
task->task_smp_info.runing_coreid = GetCpuId();
}
static void SmpOsAssignInit(void)
{
int coreid = 0;
while(coreid < CPU_NUMBERS) {
Assign.ready_vector_done->init(&Assign.smp_os_assign_ready_rector[coreid]);
Assign.smp_os_running_task[coreid] = NONE;
#ifdef ARCH_SMP
isrManager.isr_switch_trigger_flag[coreid] = 0;
#else
isrManager.isr_switch_trigger_flag = 0;
#endif
Assign.current_priority[coreid] = KTASK_PRIORITY_MAX - 1;
Assign.assign_lock[coreid] = 0;
coreid++;
}
}
struct smp_assign_done smp_assign_done =
{
SmpGetReadyVectorHighestPrio,
SmpAssignTargetTaskSelect,
SmpOsAssignSwtichToNewTask,
SmpSwitchToFirstRunningTask,
SetSystemRunningTask,
SmpOsAssignInit,
};
/**
* task schedule function.getting the highest priority task then switching to it
*/
void KTaskOsAssign(void)
{
x_base lock = 0;
int coreid = 0;
x_ubase highest_prio = 0;
struct TaskDescriptor *new_task = NONE;
struct TaskDescriptor *runningtask = NONE;
coreid = GetCpuId();
if (isrManager.done->isInIsr()) {
isrManager.done->setSwitchTrigerFlag();
return;
}
if(Assign.assign_lock[coreid] >= 1) {
return;
}
runningtask = Assign.smp_os_running_task[coreid];
/* if the bitmap is empty then do not switch */
if((RET_TRUE == JudgeAssignReadyBitmapIsEmpty(&Assign.os_assign_read_vector)) &&
(RET_TRUE == JudgeAssignReadyBitmapIsEmpty(&Assign.smp_os_assign_ready_rector[coreid]))) {
return;
}
highest_prio = Assign.smp_assign_done->GetHighest();
new_task = Assign.smp_assign_done->select();
if(RET_TRUE != JudgeKTaskStatIsRunning(runningtask)) {
CHECK(NONE != new_task);
goto SWITCH;
}
/* if the running task priority is the highest and this task is not be yield then do not switch */
if(highest_prio < runningtask->task_dync_sched_member.cur_prio) {
return;
} else {
Assign.ready_vector_done->insert(runningtask);
}
SWITCH:
new_task->task_smp_info.runing_coreid = coreid;
Assign.current_priority[coreid] = (uint8)highest_prio;
HOOK(hook.assign.hook_Assign,(runningtask, new_task));
SYS_KDEBUG_LOG(KDBG_SCHED,
("[%d]switch to priority#%d "
"task:%.*s(sp:0x%08x), "
"from task:%.*s(sp: 0x%08x)\n",
isrManager.done->getCounter(), highest_prio,
NAME_NUM_MAX, new_task->task_base_info.name, new_task->stack_point,
NAME_NUM_MAX, runningtask->task_base_info.name, runningtask->stack_point));
Assign.smp_assign_done->SwitchToNew(runningtask,new_task);
}
/**
* task switch in IRQ context.
*/
void KTaskOsAssignDoIrqSwitch(void *context)
{
int coreid = 0;
x_base lock = 0;
x_ubase highest_priority = 0;
struct TaskDescriptor *new_task = NONE;
struct TaskDescriptor *runningtask = NONE;
coreid = GetCpuId();
if ( isrManager.done->getSwitchTrigerFlag() == 0) {
return;
}
if (Assign.assign_lock[coreid] >= 1 || isrManager.done->getCounter() != 0) {
return;
}
isrManager.done->clearSwitchTrigerFlag();
runningtask = Assign.smp_os_running_task[coreid];
if((RET_TRUE == JudgeAssignReadyBitmapIsEmpty(&Assign.os_assign_read_vector)) &&
(RET_TRUE == JudgeAssignReadyBitmapIsEmpty(&Assign.smp_os_assign_ready_rector[coreid]))) {
return;
}
highest_priority = Assign.smp_assign_done->GetHighest();
new_task = Assign.smp_assign_done->select();
if (RET_TRUE == JudgeKTaskStatIsRunning(runningtask)) {
if (runningtask->task_dync_sched_member.cur_prio > highest_priority) {
new_task = runningtask;
} else {
Assign.ready_vector_done->insert(runningtask);
}
}
new_task->task_smp_info.runing_coreid = coreid;
if (new_task != runningtask) {
Assign.current_priority[coreid] = (uint8)highest_priority;
HOOK(hook.assign.hook_Assign, (runningtask, new_task));
Assign.ready_vector_done->remove(new_task);
KTaskStatSetAsRunning(new_task);
#ifdef KERNEL_STACK_OVERFLOW_CHECK
_KTaskOsAssignStackCheck(new_task);
#endif
SYS_KDEBUG_LOG(KDBG_SCHED, ("switch in interrupt\n"));
HwInterruptcontextSwitch( (x_ubase)&runningtask->stack_point,
(x_ubase)&new_task->stack_point, new_task, context);
}
}
void KTaskOsAssignAfterIrq(void *context)
{
x_base lock = 0;
lock = DISABLE_INTERRUPT();
HwLockSpinlock(&AssignSpinLock);
KTaskOsAssignDoIrqSwitch(context);
HwUnlockSpinlock(&AssignSpinLock);
ENABLE_INTERRUPT(lock);
}
static void UncombineInsert(struct TaskDescriptor *task)
{
uint32 cpu_mask = 0;
NULL_PARAM_CHECK(task);
#if KTASK_PRIORITY_MAX > 32
MERGE_FLAG(&Assign.os_assign_read_vector.ready_vector[task->task_dync_sched_member.bitmap_offset], task->task_dync_sched_member.bitmap_row);
#endif
MERGE_FLAG(&Assign.os_assign_read_vector.priority_ready_group, task->task_dync_sched_member.bitmap_column);
AssignPolicyInsert(task, &Assign.os_assign_read_vector);
cpu_mask = CPU_MASK ^ (1 << GetCpuId());
HwSendIpi(ASSIGN_IPI, cpu_mask);
}
static void ComnbineInsert(struct TaskDescriptor *task, int coreid)
{
NULL_PARAM_CHECK(task);
#if KTASK_PRIORITY_MAX > 32
MERGE_FLAG(&Assign.smp_os_assign_ready_rector[coreid].ready_vector[task->task_dync_sched_member.bitmap_offset], task->task_dync_sched_member.bitmap_row);
#endif
MERGE_FLAG(&Assign.smp_os_assign_ready_rector[coreid].priority_ready_group, task->task_dync_sched_member.bitmap_column);
AssignPolicyInsert(task, &Assign.smp_os_assign_ready_rector[coreid]);
if (coreid != task->task_smp_info.combined_coreid)
{
uint32 cpu_mask;
cpu_mask = 1 << task->task_smp_info.combined_coreid;
HwSendIpi(ASSIGN_IPI, cpu_mask);
}
}
/*
* insert a ready task to system ready table with READY state and remove it from suspend list
*
* @param task the task descriptor
*
*/
void KTaskInsertToReadyVector(struct TaskDescriptor *task)
{
int coreid = 0;
NULL_PARAM_CHECK(task);
KTaskStatSetAsReady(task);
coreid = task->task_smp_info.combined_coreid;
switch (coreid)
{
case UNCOMBINE_CPU_CORE:
UncombineInsert(task);
break;
default:
ComnbineInsert(task, coreid);
break;
}
SYS_KDEBUG_LOG(KDBG_SCHED, ("insert task[%.*s], the priority: %d\n",
NAME_NUM_MAX, task->task_base_info.name, task->task_dync_sched_member.cur_prio));
}
static void UncombineRemove(struct TaskDescriptor *task)
{
register x_ubase number = 0;
register x_ubase highest_priority = 0;
NULL_PARAM_CHECK(task);
if (IsDoubleLinkListEmpty(&(Assign.os_assign_read_vector.priority_ready_vector[task->task_dync_sched_member.cur_prio]))) {
#if KTASK_PRIORITY_MAX > 32
CLEAR_FLAG(&Assign.os_assign_read_vector.ready_vector[task->task_dync_sched_member.bitmap_offset], task->task_dync_sched_member.bitmap_row);
if (Assign.os_assign_read_vector.ready_vector[task->task_dync_sched_member.bitmap_offset] == 0) {
CLEAR_FLAG(&Assign.os_assign_read_vector.priority_ready_group, task->task_dync_sched_member.bitmap_column);
}
number = PrioCaculate(Assign.os_assign_read_vector.priority_ready_group);
highest_priority = (number * 8) + PrioCaculate(Assign.os_assign_read_vector.ready_vector[number]);
#else
CLEAR_FLAG(&Assign.os_assign_read_vector.priority_ready_group, task->task_dync_sched_member.bitmap_column);
highest_priority = PrioCaculate(Assign.os_assign_read_vector.priority_ready_group);
#endif
Assign.os_assign_read_vector.highest_prio = highest_priority;
}
}
static void CombineRemove(struct TaskDescriptor *task)
{
register x_ubase number = 0;
register x_ubase highest_prio_on_core = 0;
uint8 combined_coreid = task->task_smp_info.combined_coreid;
NULL_PARAM_CHECK(task);
if (IsDoubleLinkListEmpty(&(Assign.smp_os_assign_ready_rector[combined_coreid].priority_ready_vector[task->task_dync_sched_member.cur_prio]))) {
#if KTASK_PRIORITY_MAX > 32
CLEAR_FLAG(&Assign.smp_os_assign_ready_rector[combined_coreid].ready_vector[task->task_dync_sched_member.bitmap_offset], task->task_dync_sched_member.bitmap_row);
if (Assign.os_assign_read_vector.ready_vector[task->task_dync_sched_member.bitmap_offset] == 0) {
CLEAR_FLAG(&Assign.smp_os_assign_ready_rector[combined_coreid].priority_ready_group, task->task_dync_sched_member.bitmap_column);
}
number = PrioCaculate(Assign.smp_os_assign_ready_rector[combined_coreid].priority_ready_group);
highest_prio_on_core = (number * 8) + PrioCaculate(Assign.smp_os_assign_ready_rector[combined_coreid].ready_vector[number]);
#else
CLEAR_FLAG(&Assign.smp_os_assign_ready_rector[combined_coreid].priority_ready_group, task->task_dync_sched_member.bitmap_column);
highest_prio_on_core = PrioCaculate(Assign.smp_os_assign_ready_rector[combined_coreid].priority_ready_group);
#endif
Assign.smp_os_assign_ready_rector[combined_coreid].highest_prio = highest_prio_on_core;
}
}
/*
* a task will be removed from ready table.
*
* @param task task descriptor
*
*/
void KTaskOsAssignRemoveKTask(struct TaskDescriptor *task)
{
NULL_PARAM_CHECK(task);
SYS_KDEBUG_LOG(KDBG_SCHED, ("remove task[%.*s], the priority: %d\n",
NAME_NUM_MAX, task->task_base_info.name,
task->task_dync_sched_member.cur_prio));
DoubleLinkListRmNode(&(task->task_dync_sched_member.sched_link));
switch (task->task_smp_info.combined_coreid)
{
case UNCOMBINE_CPU_CORE:
UncombineRemove(task);
break;
default:
CombineRemove(task);
break;
}
}
x_err_t YieldOsAssign(void)
{
x_base lock = 0;
int coreid = 0;
x_ubase highest_prio = 0;
struct TaskDescriptor *new_task = NONE;
struct TaskDescriptor *runningtask = NONE;
lock = DISABLE_INTERRUPT();
HwLockSpinlock(&AssignSpinLock);
coreid = GetCpuId();
runningtask = Assign.smp_os_running_task[coreid];
if (isrManager.done->getCounter()) {
HwUnlockSpinlock(&AssignSpinLock);
ENABLE_INTERRUPT(lock);
return -ERROR;
}
if(Assign.assign_lock[coreid] >= 1) {
HwUnlockSpinlock(&AssignSpinLock);
ENABLE_INTERRUPT(lock);
return -ERROR;
}
/* if the bitmap is empty then do not switch */
if((RET_TRUE == JudgeAssignReadyBitmapIsEmpty(&Assign.os_assign_read_vector)) &&
(RET_TRUE == JudgeAssignReadyBitmapIsEmpty(&Assign.smp_os_assign_ready_rector[coreid]))) {
HwUnlockSpinlock(&AssignSpinLock);
ENABLE_INTERRUPT(lock);
return -ERROR;
}
highest_prio = Assign.smp_assign_done->GetHighest();
new_task = Assign.smp_assign_done->select();
if(RET_TRUE != JudgeKTaskStatIsRunning(runningtask)) {
CHECK(NONE != new_task);
} else {
Assign.ready_vector_done->insert(runningtask);
}
new_task->task_smp_info.runing_coreid = coreid;
Assign.current_priority[coreid] = (uint8)highest_prio;
HOOK(hook.assign.hook_Assign,(runningtask, new_task));
SYS_KDEBUG_LOG(KDBG_SCHED,
("[%d]switch to priority#%d "
"task:%.*s(sp:0x%08x), "
"from task:%.*s(sp: 0x%08x)\n",
isrManager.done->getCounter(), highest_prio,
NAME_NUM_MAX, new_task->task_base_info.name, new_task->stack_point,
NAME_NUM_MAX, runningtask->task_base_info.name, runningtask->stack_point));
Assign.smp_assign_done->SwitchToNew(runningtask,new_task);
ENABLE_INTERRUPT(lock);
return EOK;
}
/**
*
* OsAssign startup function
* .
*/
void StartupOsAssign(void)
{
struct TaskDescriptor *FirstRunningTask = NONE;
FirstRunningTask = Assign.smp_assign_done->select();
Assign.smp_assign_done->SetSystemTask(FirstRunningTask);
Assign.smp_assign_done->SwitchToFirst(FirstRunningTask);
}
/**
*
* system OsAssign init function
*/
void SysInitOsAssign(void)
{
SYS_KDEBUG_LOG(KDBG_SCHED, ("start Os Assign: max priority 0x%02x\n",
KTASK_PRIORITY_MAX));
Assign.ready_vector_done = &ready_vector_done;
Assign.smp_assign_done = &smp_assign_done;
Assign.ready_vector_done->init(&Assign.os_assign_read_vector);
Assign.smp_assign_done->SmpInit();
}

357
kernel/thread/softtimer.c Normal file
View File

@@ -0,0 +1,357 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: softtimer.c
* @brief: softtimer file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
DoubleLinklistType xiaoshan_timer_sort_head = {&xiaoshan_timer_sort_head, &xiaoshan_timer_sort_head};
DoubleLinklistType k_timer_list = {&k_timer_list, &k_timer_list};
DECLARE_ID_MANAGER(k_softtimer_id_manager, ID_NUM_MAX);
extern queue *sys_workq;
void _Init(struct Timer *timer,
const char *name,
void (*timeout)(void *parameter),
void *parameter,
x_ticks_t time,
uint8 trigger_mode)
{
x_base lock = 0;
NULL_PARAM_CHECK(timer);
strncpy(timer->name, name, NAME_NUM_MAX);
// insert to link
lock = CriticalAreaLock();
DoubleLinkListInsertNodeAfter(&(k_timer_list), &(timer->link));
CriticalAreaUnLock(lock);
timer->trigger_mode = trigger_mode;
timer->active_status = TIMER_ACTIVE_FALSE;
timer->func_callback = timeout;
timer->param = parameter;
timer->deadline_timeslice = 0;
timer->origin_timeslice = time;
timer->prio = GetKTaskDescriptor()->task_base_info.origin_prio;
}
x_err_t _Delete(TimerType timer)
{
x_base lock = 0;
NULL_PARAM_CHECK(timer);
lock = CriticalAreaLock();
DoubleLinkListRmNode(&(timer->sortlist));
DoubleLinkListRmNode(&(timer->link));
CriticalAreaUnLock(lock);
KERNEL_FREE(timer);
timer = NONE;
return EOK;
}
x_err_t _StartRun(TimerType timer)
{
NULL_PARAM_CHECK(timer);
x_base lock = CriticalAreaLock();
timer->active_status = TIMER_ACTIVE_FALSE;
CHECK(timer->origin_timeslice < TICK_SIZE_MAX / 2);
timer->deadline_timeslice = CurrentTicksGain() + timer->origin_timeslice;
timer->active_status = TIMER_ACTIVE_TRUE;
DoubleLinklistType *pLink = NONE;
TimerType pNode = NONE;
DOUBLE_LINKLIST_FOR_EACH(pLink, &xiaoshan_timer_sort_head) {
pNode = CONTAINER_OF(pLink, struct Timer, sortlist);
if (timer->deadline_timeslice < pNode->deadline_timeslice) {
DoubleLinkListInsertNodeBefore(pLink, &timer->sortlist);
break;
}
}
if (pLink == &xiaoshan_timer_sort_head) {
DoubleLinkListInsertNodeBefore(&xiaoshan_timer_sort_head, &timer->sortlist);
}
CriticalAreaUnLock(lock);
return EOK;
}
// Just stop working, don't free memory
x_err_t _QuitRun(TimerType timer)
{
x_base lock = 0;
NULL_PARAM_CHECK(timer);
if (!(timer->active_status == TIMER_ACTIVE_TRUE))
return -ERROR;
lock = CriticalAreaLock();
timer->active_status = TIMER_ACTIVE_FALSE;
timer->deadline_timeslice = 0;
DoubleLinkListRmNode(&(timer->sortlist));
CriticalAreaUnLock(lock);
return EOK;
}
x_err_t _Modify(TimerType timer, x_ticks_t ticks)
{
NULL_PARAM_CHECK(timer);
if (0 == ticks) {
KPrintf("timeout ticks must be setted more then 0.\n");
return -EINVALED;
}
timer->origin_timeslice = ticks;
return EOK;
}
static struct TimerDone Done =
{
.Init = _Init,
.Delete = _Delete,
.StartRun = _StartRun,
.QuitRun = _QuitRun,
.Modify = _Modify,
};
/**
* This function will create a softtimer.
*
* @param name the length of the msg queue.
* @param timeout the callback of the timer.
* @param parameter the parameter of the callback function
* @param time the timeout time
* @param trigger_mode the trigger way of the timer
*
* @return id on success
*/
int32 KCreateTimer(const char *name,
void (*timeout)(void *parameter),
void *parameter,
x_ticks_t time,
uint8 trigger_mode)
{
struct Timer *timer = NONE;
timer = (struct Timer *)x_malloc(sizeof(struct Timer));
if (timer == NONE) {
return NONE;
}
memset(timer, 0x0, sizeof(struct Timer));
// Generate ID
int32 id = IdInsertObj(&k_softtimer_id_manager, &timer->id_node);
if (id < 0) {
x_free(timer);
return NONE;
}
timer->done = &Done;
timer->done->Init(timer, name, timeout, parameter, time, trigger_mode);
return id;
}
/**
* This function will delete a timer.
*
* @param timer_id the id number of timer.
*
* @return
*/
x_err_t KDeleteTimer(int32 timer_id)
{
TimerType timer = KGetTimer(timer_id);
timer->done->Delete(timer);
}
/**
* This function will startup a timer.
*
* @param timer_id the id number of timer.
*
* @return
*/
x_err_t KTimerStartRun(int32 timer_id)
{
TimerType timer = KGetTimer(timer_id);
return timer->done->StartRun(timer);
}
/**
* This function will stop a timer.
*
* @param timer_id the id number of timer.
*
* @return
*/
x_err_t KTimerQuitRun(int32 timer_id)
{
TimerType timer = KGetTimer(timer_id);
timer->done->QuitRun(timer);
}
/**
* This function will modify the timeout of a timer.
*
* @param timer_id the id number of timer.
* @param ticks timeout ticks
*
* @return
*/
x_err_t KTimerModify(int32 timer_id, x_ticks_t ticks)
{
TimerType timer = KGetTimer(timer_id);
timer->done->Modify(timer, ticks);
}
static void TimerCBEnter(void *param)
{
struct Timer *t = (struct Timer *)param;
t->func_callback(t->param);
free(t->t_work);
}
void timer_work_func(struct Work *work, void *work_data)
{
x_err_t flag;
struct Timer *t = work_data;
int32 timer_work = KTaskCreate("timer_work_thr", TimerCBEnter, t, 2048, t->prio);
flag = StartupKTask(timer_work);
if (flag != EOK) {
KPrintf("timer create callback thread failed .\n");
}
return;
}
void CheckTimerList(void)
{
x_base lock = 0;
struct Timer *t = NONE;
x_ticks_t current_tick = 0;
SYS_KDEBUG_LOG(KDBG_SOFTTIMER, ("timer check enter\n"));
current_tick = CurrentTicksGain();
lock = CriticalAreaLock();
while (!IsDoubleLinkListEmpty(&xiaoshan_timer_sort_head)) {
t = SYS_DOUBLE_LINKLIST_ENTRY(xiaoshan_timer_sort_head.node_next,
struct Timer, sortlist);
if ((current_tick - t->deadline_timeslice) < TICK_SIZE_MAX / 2) {
if (t->active_status == TIMER_ACTIVE_TRUE) {
DoubleLinkListRmNode(&t->sortlist); // Take it off the list first
current_tick = CurrentTicksGain();
SYS_KDEBUG_LOG(KDBG_SOFTTIMER, ("current tick: %d\n", current_tick));
if (t->trigger_mode == TIMER_TRIGGER_PERIODIC) {
t->done->StartRun(t); // Periodic timer, re insert the appropriate position of the list
} else {
t->done->QuitRun(t);
}
// Throw it to the task queue and start a new thread
t->t_work = x_malloc(sizeof(struct Work));
((WorkQueueDoneType *)sys_workq->done)->WorkInit(t->t_work, timer_work_func, t);
CriticalAreaUnLock(lock);
((WorkQueueDoneType *)sys_workq->done)->WorkSubmit((WorkqueueType *)sys_workq->property, t->t_work, 0);
lock = CriticalAreaLock();
} else {
KPrintf("sortlist run unactive timer(%s), quit this timer\n", t->name);
}
}
else
break;
}
CriticalAreaUnLock(lock);
SYS_KDEBUG_LOG(KDBG_SOFTTIMER, ("timer check leave\n"));
}
x_err_t KTimerAssignMemberRun(int32 timer_id, x_ticks_t ticks)
{
TimerType timer = KGetTimer(timer_id);
NULL_PARAM_CHECK(timer);
if (ticks == 0) {
KPrintf("Timeout ticks must be setted more than 0.\n");
return -EINVALED;
}
timer->origin_timeslice = ticks;
return timer->done->StartRun(timer);
}
/**
* This function will get the timer with id.
*
* @param id the id number of timer.
*
* @return timer structrue
*/
TimerType KGetTimer(int32 id)
{
x_base lock = 0;
TimerType timer = NONE;
lock = CriticalAreaLock();
struct IdNode *idnode = IdGetObj(&k_softtimer_id_manager, id);
if (idnode == NONE){
CriticalAreaUnLock(lock);
return NONE;
}
timer = CONTAINER_OF(idnode, struct Timer, id_node);
CriticalAreaUnLock(lock);
return timer;
}
int32 KGetTimerID(TimerType timer)
{
return timer->id_node.id;
}

123
kernel/thread/tick.c Normal file
View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: tick.c
* @brief: system heartbeat_ticks update
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#include <xs_spinlock.h>
#include <xs_delay.h>
#ifdef ARCH_SMP
static x_ticks_t heartbeat_ticks[CPU_NUMBERS] = {0};
#else
static x_ticks_t heartbeat_ticks = 0;
#endif
#ifdef ARCH_SMP
#define UPDATE_GLOBAL_HEARTBEAT() \
do { \
heartbeat_ticks[GetCpuId()]++; \
} while(0);
#else
#define UPDATE_GLOBAL_HEARTBEAT() \
do { \
heartbeat_ticks ++; \
} while(0);
#endif
/**
* get haertbeat count
*
* @return CurrentTicks
*/
x_ticks_t CurrentTicksGain(void)
{
#ifdef ARCH_SMP
return heartbeat_ticks[GetCpuId()];
#else
return heartbeat_ticks;
#endif
}
/**
* this function increases global systick in tick interrupt,and process task time slice
*
*/
void TickAndTaskTimesliceUpdate(void)
{
struct TaskDescriptor *task = NONE;
UPDATE_GLOBAL_HEARTBEAT();
#if defined(SCHED_POLICY_FIFO)
FifoTaskTimesliceUpdate();
#elif defined (SCHED_POLICY_RR)
task = GetKTaskDescriptor();
RoundRobinTaskTimesliceUpdate(task);
#elif defined (SCHED_POLICY_RR_REMAINSLICE)
task = GetKTaskDescriptor();
RoundRobinRemainTaskTimesliceUpdate(task);
#endif
CheckTaskDelay();
#ifdef KERNEL_SOFTTIMER
CheckTimerList();
#endif
}
/**
* This function will convert ms to ticks.
*
* @param ms time need to be converted
* @return ticks
*/
#define MIN_TICKS 1
x_ticks_t CalculteTickFromTimeMs(uint32 ms)
{
uint32 tmp = 0;
x_ticks_t ticks = 0;
ticks = (uint32)(((uint64)(ms * TICK_PER_SECOND)) / 1000) ;
if (0 == ticks) {
ticks = MIN_TICKS;
} else {
tmp = (uint32)(((uint64)(ms * TICK_PER_SECOND)) % 1000);
if(tmp >= 5 && tmp <= 9) {
ticks = ticks + MIN_TICKS;
}
}
return ticks;
}
/**
* This function will convert ticks to ms.
*
* @param ticks ticks need to be converted
* @return ms
*/
uint32 CalculteTimeMsFromTick(x_ticks_t ticks)
{
uint32 ms = 0;
ms = (uint32)(((uint64)(ticks * 1000)) / TICK_PER_SECOND);
return ms;
}

148
kernel/thread/waitqueue.c Normal file
View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: waitqueue.c
* @brief: waitqueue file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <stdint.h>
#include <xs_isr.h>
#include <device.h>
#include <xs_klist.h>
#include <xs_memory.h>
/**
* This function will add a waitqueue node to the wait queue list
*@parm queue waitqueue descriptor
*@parm work the node need to be added
*
*/
void WqueueAdd(WaitQueueType *queue, struct WaitqueueNode *node)
{
x_base lock = 0;
NULL_PARAM_CHECK(queue);
NULL_PARAM_CHECK(node);
lock = CriticalAreaLock();
DoubleLinkListInsertNodeBefore(&(queue->block_threads_list), &(node->list));
CriticalAreaUnLock(lock);
}
/**
* This function will remove a waitqueue node from the wait queue list
*@parm work the node need to be removed
*
*/
void WqueueRemove(struct WaitqueueNode *node)
{
x_base lock = 0;
NULL_PARAM_CHECK(node);
lock = CriticalAreaLock();
DoubleLinkListRmNode(&(node->list));
CriticalAreaUnLock(lock);
}
/**
* This function restarts the suspended task of the queue
* @parm waitqueue pointer
* @parm the awake key
*/
void WakeupWqueue(WaitQueueType *queue, void *key)
{
x_base lock = 0;
NULL_PARAM_CHECK(queue);
NULL_PARAM_CHECK(key);
lock = CriticalAreaLock();
struct SysDoubleLinklistNode *node = NONE;
DOUBLE_LINKLIST_FOR_EACH(node, &(queue->block_threads_list)) {
struct WaitqueueNode *pEnter;
pEnter = SYS_DOUBLE_LINKLIST_ENTRY(node, struct WaitqueueNode, list);
if (pEnter->cb != NONE && pEnter->cb(pEnter, key) != 0) {
continue;
} else {
KTaskWakeup(pEnter->polling_task->id.id);
}
}
CriticalAreaUnLock(lock);
if (node == &(queue->block_threads_list)) {
return;
}
DO_KTASK_ASSIGN;
}
/**
* This function will suspend current task and start up a timer
* @parm queue waitqueue descriptor
* @parm msec waiting time
*
*/
int WqueueWait(WaitQueueType *queue, x_ticks_t tick)
{
NULL_PARAM_CHECK(queue);
if (tick == 0)
return 0;
struct WaitqueueNode* pin_node = x_malloc(sizeof(struct WaitqueueNode));
// set timeout awake
if (tick != WAITING_FOREVER) {
pin_node->deadline_tick = CurrentTicksGain() + tick;
KTaskSetDelay(GetKTaskDescriptor(), tick);
} else {
pin_node->deadline_tick = 0;
}
// init block node
pin_node->polling_task = GetKTaskDescriptor();
pin_node->key = 0;
pin_node->cb = NONE;
pin_node->list.node_next = &pin_node->list;
pin_node->list.node_prev = &pin_node->list;
// start block
x_base lock;
lock = CriticalAreaLock();
WqueueAdd(queue, pin_node);
SuspendKTask(GetKTaskDescriptor()->id.id);
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
// end block, delete node
WqueueRemove(pin_node);
x_free(pin_node);
return 0;
}
/**
* This function will create a wait queue.
*
* @param queue queue waitqueue descriptor
*
*/
void InitWqueue(WaitQueueType *queue)
{
NULL_PARAM_CHECK(queue);
InitDoubleLinkList(&(queue->block_threads_list));
}

183
kernel/thread/workqueue.c Normal file
View File

@@ -0,0 +1,183 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: workqueue.c
* @brief: workqueue file
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#include <device.h>
queue *sys_workq = NONE;
static void _WorkQueueKTaskEntry(void *parameter)
{
x_base lock = 0;
WorkqueueType *p_queue = (WorkqueueType *)parameter;
while (1)
{
lock = CriticalAreaLock();
if (p_queue->front != p_queue->rear) { // The team is not empty
struct Work *work = &(p_queue->base[p_queue->front]);
p_queue->front = (p_queue->front + 1) % MAX_WORK_QUEUE;
CriticalAreaUnLock(lock);
if (work->cb_func) {
work->cb_func(work, work->cb_param);
}
} else {
CriticalAreaUnLock(lock);
SuspendKTask(p_queue->task);
DO_KTASK_ASSIGN;
}
}
}
void DeInitWorkQueue(WorkqueueType *p_queue)
{
if (NONE != p_queue->task) {
KTaskDelete(p_queue->task);
}
if (NONE != p_queue) {
if (NONE != p_queue->base) {
x_free(p_queue->base);
}
x_free(p_queue);
}
}
WorkqueueType *CreateWorkQueue(const char *name, uint16 stack_size, uint8 priority)
{
WorkqueueType *p_queue = NONE;
do {
p_queue = x_malloc(sizeof(WorkqueueType));
if (NONE == p_queue) {
KPrintf("CreateWorkQueue x_malloc(sizeof(WorkqueueType) failed\n");
break;
}
memset(p_queue, 0, sizeof(WorkqueueType));
p_queue->base = x_malloc(MAX_WORK_QUEUE * sizeof(struct Work));
if (NONE == p_queue->base) {
KPrintf("CreateWorkQueue x_malloc(MAX_WORK_QUEUE * sizeof(struct Work) failed\n");
break;
}
memset(p_queue->base, 0, MAX_WORK_QUEUE * sizeof(struct Work));
p_queue->front = p_queue->rear = 0;
// start work thread
p_queue->task = KTaskCreate(name, _WorkQueueKTaskEntry, p_queue, 2048, priority);
if (NONE == p_queue->task) {
KPrintf("CreateWorkQueue KTaskCreate failed\n");
break;
}
StartupKTask(p_queue->task);
return p_queue;
} while (0);
DeInitWorkQueue(p_queue);
return NONE;
}
void WorkInit(struct Work *work, void (*work_func)(struct Work *work, void *work_data), void *work_data)
{
work->cb_func = work_func;
work->cb_param = work_data;
}
void work_elem_timeout(void *in_param)
{
WorkTimerParamType *param = (WorkTimerParamType *)in_param;
WorkSubmit_immediate(param->p_queue, param->p_work);
}
x_err_t WorkSubmit_immediate(WorkqueueType *sys_workq, struct Work *work)
{
x_base lock = CriticalAreaLock();
NULL_PARAM_CHECK(sys_workq);
NULL_PARAM_CHECK(work);
// check queue is full
if ((sys_workq->rear + 1 + MAX_WORK_QUEUE) % MAX_WORK_QUEUE == sys_workq->front) {
CriticalAreaUnLock(lock);
return -ERROR;
}
// add to queue
sys_workq->base[sys_workq->rear].cb_func = work->cb_func;
sys_workq->base[sys_workq->rear].cb_param = work->cb_param;
sys_workq->rear = (sys_workq->rear + 1) % MAX_WORK_QUEUE;
// awake work thread
KTaskWakeup(sys_workq->task);
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
}
x_err_t WorkSubmit(WorkqueueType *sys_workq, struct Work *work, x_ticks_t time)
{
NULL_PARAM_CHECK(sys_workq);
NULL_PARAM_CHECK(work);
if (0 == time) {
WorkSubmit_immediate(sys_workq, work);
} else {
// init a timer, add to queue later
WorkTimerParamType *param = x_malloc(sizeof(WorkTimerParamType));
param->p_queue = sys_workq;
param->p_work = work;
param->p_timer = KCreateTimer("wk_timer", work_elem_timeout, param, time, TIMER_TRIGGER_ONCE);
if (NONE == param->p_timer) {
KPrintf("WorkSubmit KCreateTimer failed \n");
x_free(param);
return -ERROR;
}
KTimerStartRun(param->p_timer);
}
return EOK;
}
/**
* This function will create a workqueue.
*
* @return EOK on success;ERROR on failure
*/
int WorkSysWorkQueueInit(void)
{
if (sys_workq != NONE)
return 0;
sys_workq = x_malloc(sizeof(queue));
sys_workq->done = g_queue_done[WORK_QUEUE];
sys_workq->property = ((WorkQueueDoneType*)sys_workq->done)->CreateWorkQueue("sys_work", WORKQUEUE_KTASK_STACKSIZE,
WORKQUEUE_KTASK_PRIORITY);
if (sys_workq->property == NONE) {
KPrintf("log sys_workq create failed\n");
} else {
KPrintf("log sys_workq create success\n");
}
return sys_workq->property == NONE ? ERROR : EOK;
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: zombierecycle.c
* @brief: a recycle task of system
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <xiuos.h>
#ifdef TASK_ISOLATION
#include <xs_isolation.h>
#endif
DoubleLinklistType KTaskZombie;
#ifndef ZOMBIE_KTASK_STACKSIZE
#define ZOMBIE_KTASK_STACKSIZE 2048
#endif
int32 zombie_recycle;
int JudgeZombieKTaskIsNotEmpty(void)
{
return (IsDoubleLinkListEmpty(&KTaskZombie) ? 0 : RET_TRUE);
}
static void ZombieKTaskEntry(void *parameter)
{
x_base lock = 0;
KTaskDescriptorType task = NONE;
while(RET_TRUE)
{
KDEBUG_NOT_IN_INTERRUPT;
lock = CriticalAreaLock();
if (JudgeZombieKTaskIsNotEmpty()) {
task = SYS_DOUBLE_LINKLIST_ENTRY(KTaskZombie.node_next, struct TaskDescriptor, task_dync_sched_member.sched_link);
DoubleLinkListRmNode(&(task->task_dync_sched_member.sched_link));
CriticalAreaUnLock(lock);
#ifdef SEPARATE_COMPILE
if(1 == task->task_dync_sched_member.isolation_flag ){
#ifdef MOMERY_PROTECT_ENABLE
if(mem_access.Free)
mem_access.Free(task->task_dync_sched_member.isolation);
#endif
x_ufree(task->task_base_info.stack_start);
} else
#endif
{
KERNEL_FREE(task->task_base_info.stack_start);
}
DoubleLinkListRmNode(&(task->link));
KTaskIdDelete(task->id.id);
if(task->task_dync_sched_member.delay != NONE){
}
KERNEL_FREE(task->task_dync_sched_member.delay);
KERNEL_FREE(task);
} else {
SuspendKTask(zombie_recycle);
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
}
}
}
void ZombieTaskRecycleInit(void)
{
InitDoubleLinkList(&KTaskZombie);
zombie_recycle = KTaskCreate("ZombieRecycleKTask",
ZombieKTaskEntry,
NONE,
ZOMBIE_KTASK_STACKSIZE,
KTASK_LOWEST_PRIORITY + 1);
StartupKTask(zombie_recycle);
}