feat(kos): Added the os adaptation layer feature.
This commit is contained in:
@@ -14,4 +14,10 @@ menu "Kernel"
|
||||
help
|
||||
This option controls the size of the inline name of the kobject.
|
||||
|
||||
# KTHREAD
|
||||
config MR_CFG_KTHREAD_IRES_SIZE
|
||||
int "Kthread inline resource size"
|
||||
default 256
|
||||
help
|
||||
This option controls the size of the inline resource of the kthread.
|
||||
endmenu
|
||||
|
||||
89
include/kernel/kos/mr_kos.h
Normal file
89
include/kernel/kos/mr_kos.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_KOS_H__
|
||||
#define __MR_KOS_H__
|
||||
|
||||
#include <kernel/mr_kclock.h>
|
||||
#include <kernel/mr_kobject.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Kos
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Kthread operations type */
|
||||
typedef struct mr_kthread_ops {
|
||||
mr_err_t (*init)(void *, const char *, void *, void *, mr_size_t,
|
||||
mr_uint32_t, mr_tick_t);
|
||||
mr_err_t (*del)(void *);
|
||||
mr_err_t (*startup)(void *);
|
||||
mr_err_t (*resume)(void *);
|
||||
mr_err_t (*yield)(void);
|
||||
mr_err_t (*suspend)(void *);
|
||||
mr_err_t (*sleep)(mr_tick_t tick);
|
||||
mr_err_t (*exit)(void *);
|
||||
void *(*self)(void);
|
||||
} mr_kthread_ops_t;
|
||||
|
||||
/* Kthread-type type */
|
||||
typedef struct mr_kthread_type {
|
||||
mr_uint32_t priority_max;
|
||||
mr_kthread_ops_t *ops;
|
||||
mr_size_t size;
|
||||
} mr_kthread_type_t;
|
||||
|
||||
/* Kos-type type */
|
||||
typedef struct mr_kos_type {
|
||||
mr_kthread_type_t *kth_type;
|
||||
} mr_kos_type_t;
|
||||
|
||||
/* Kos type */
|
||||
typedef struct mr_kos {
|
||||
mr_kset_t parent;
|
||||
mr_kos_type_t *type;
|
||||
} mr_kos_t;
|
||||
|
||||
/**
|
||||
* @brief This function registers kernel os.
|
||||
*
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kos_register(mr_kos_type_t *type);
|
||||
|
||||
/**
|
||||
* @brief This function gets kernel os.
|
||||
*
|
||||
* @return The kernel os.
|
||||
*/
|
||||
mr_kos_t *mr_kos_get(void);
|
||||
|
||||
/**
|
||||
* @brief This function puts kernel os.
|
||||
*/
|
||||
void mr_kos_put(void);
|
||||
|
||||
/**
|
||||
* @brief This macro function gets the kthread operations of a kernel os.
|
||||
*
|
||||
* @param _kos The kernel os.
|
||||
* @return The kthread operations of the kernel os.
|
||||
*/
|
||||
#define MR_KOS_KTH_OPS(_kos) ((_kos)->type->kth_type->ops)
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_KOS_H__ */
|
||||
177
include/kernel/kos/mr_kthread.h
Normal file
177
include/kernel/kos/mr_kthread.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_KTHREAD_H__
|
||||
#define __MR_KTHREAD_H__
|
||||
|
||||
#include <kernel/kos/mr_kos.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Kthread
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Kthread type */
|
||||
typedef struct mr_kthread {
|
||||
mr_kobject_t parent;
|
||||
const void *res;
|
||||
#if !defined(MR_CFG_KTHREAD_IRES_SIZE)
|
||||
#define MR_CFG_KTHREAD_IRES_SIZE (256)
|
||||
#endif /* !defined(MR_CFG_KTHREAD_IRES_SIZE) */
|
||||
mr_uint8_t ires[MR_CFG_KTHREAD_IRES_SIZE];
|
||||
mr_uint32_t priority;
|
||||
mr_tick_t tick;
|
||||
mr_ptr_t entry;
|
||||
mr_ptr_t args;
|
||||
mr_kos_t *os;
|
||||
} mr_kthread_t;
|
||||
|
||||
/**
|
||||
* @brief This function initialize a kthread.
|
||||
*
|
||||
* @param kth The kthread.
|
||||
* @param name The kthread name.
|
||||
* @param entry The kthread entry.
|
||||
* @param args The kthread arguments.
|
||||
* @param stack The kthread stack.
|
||||
* @param stack_size The kthread stack size.
|
||||
* @param priority The kthread priority.
|
||||
* @param tick The kthread time slice.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kthread_init(mr_kthread_t *kth, const char *name,
|
||||
void (*entry)(mr_kthread_t *, void *), void *args,
|
||||
void *stack, mr_size_t stack_size,
|
||||
mr_uint32_t priority, mr_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief This function create a kthread.
|
||||
*
|
||||
* @param name The kthread name.
|
||||
* @param entry The kthread entry.
|
||||
* @param args The kthread arguments.
|
||||
* @param stack_size The kthread stack size.
|
||||
* @param priority The kthread priority.
|
||||
* @param tick The kthread time slice.
|
||||
* @return The kthread on success, or NULL on failure.
|
||||
*/
|
||||
mr_kthread_t *mr_kthread_create(const char *name,
|
||||
void (*entry)(mr_kthread_t *, void *),
|
||||
void *args, mr_size_t stack_size,
|
||||
mr_uint32_t priority, mr_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief This function takeover a kthread.
|
||||
*
|
||||
* @param kth The kthread.
|
||||
* @param name The kthread name.
|
||||
* @param priority The kthread priority.
|
||||
* @param tick The kthread time slice.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kthread_takeover(mr_kthread_t *kth, const char *name,
|
||||
const void *res, mr_uint32_t priority,
|
||||
mr_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief This function delete a kthread.
|
||||
*
|
||||
* @param kth The kthread.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kthread_del(mr_kthread_t *kth);
|
||||
|
||||
/**
|
||||
* @brief This function startup a kthread.
|
||||
*
|
||||
* @param kth The kthread.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kthread_startup(mr_kthread_t *kth);
|
||||
|
||||
/**
|
||||
* @brief This function resume a kthread.
|
||||
*
|
||||
* @param kth The kthread.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kthread_resume(mr_kthread_t *kth);
|
||||
|
||||
/**
|
||||
* @brief This function yield the current kthread.
|
||||
*
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kthread_yield(void);
|
||||
|
||||
/**
|
||||
* @brief This function suspend a kthread.
|
||||
*
|
||||
* @param kth The kthread.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kthread_suspend(mr_kthread_t *kth);
|
||||
|
||||
/**
|
||||
* @brief This function sleep a kthread.
|
||||
*
|
||||
* @param tick The sleep time slice.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kthread_sleep(mr_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief This function exit a kthread.
|
||||
*
|
||||
* @param kth The kthread.
|
||||
* @return 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
mr_err_t mr_kthread_exit(mr_kthread_t *kth);
|
||||
|
||||
/**
|
||||
* @brief This function get the current kthread.
|
||||
*
|
||||
* @return The current kthread.
|
||||
*/
|
||||
mr_kthread_t *mr_kthread_self(void);
|
||||
|
||||
/**
|
||||
* @brief This function find a kthread.
|
||||
*
|
||||
* @param name The kthread name.
|
||||
* @return The kthread on success, or MR_NULL on failure.
|
||||
*/
|
||||
mr_kthread_t *mr_kthread_find(const char *name);
|
||||
|
||||
/**
|
||||
* @brief This function cleanup a kthread.
|
||||
*
|
||||
* @param kth The kthread.
|
||||
*/
|
||||
void mr_kthread_cleanup(mr_kthread_t *kth);
|
||||
|
||||
/**
|
||||
* @brief This function is the kthread entry.
|
||||
*
|
||||
* @param kth The kthread.
|
||||
*
|
||||
* @note User does not need to call this function.
|
||||
*/
|
||||
void mr_kthread_entry(mr_kthread_t *kth);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_KTHREAD_H__ */
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef __MR_KHOOK_H__
|
||||
#define __MR_KHOOK_H__
|
||||
|
||||
#include "mr_spinlock.h"
|
||||
#include <kernel/mr_spinlock.h>
|
||||
#include <libc/mr_errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -36,16 +36,16 @@ typedef struct mr_kname {
|
||||
|
||||
/* Ktype type */
|
||||
typedef struct mr_ktype {
|
||||
void (*release)(struct mr_kobject *kobj);
|
||||
void (*release)(struct mr_kobject *);
|
||||
} mr_ktype_t;
|
||||
|
||||
/* Kobject type */
|
||||
typedef struct mr_kobject {
|
||||
mr_uint32_t magic;
|
||||
mr_kname_t name;
|
||||
#ifndef MR_CFG_KOBJECT_INAME_SIZE
|
||||
#if !defined(MR_CFG_KOBJECT_INAME_SIZE)
|
||||
#define MR_CFG_KOBJECT_INAME_SIZE (16)
|
||||
#endif /* !MR_CFG_KOBJECT_INAME_SIZE */
|
||||
#endif /* !defined(MR_CFG_KOBJECT_INAME_SIZE) */
|
||||
char iname[MR_CFG_KOBJECT_INAME_SIZE];
|
||||
struct mr_kobject *parent;
|
||||
mr_ktype_t *type;
|
||||
@@ -65,7 +65,7 @@ typedef struct mr_kset {
|
||||
* @param _release The release function.
|
||||
*/
|
||||
#define MR_KTYPE_INIT(_release) \
|
||||
{ .release = _release }
|
||||
{ .release = (_release) }
|
||||
|
||||
/**
|
||||
* @brief This function initializes a ktype.
|
||||
@@ -160,6 +160,16 @@ void mr_kobject_put(mr_kobject_t *kobj);
|
||||
*/
|
||||
#define MR_KOBJECT_NAME(_kobj) (((mr_kobject_t *)(_kobj))->name.str)
|
||||
|
||||
/**
|
||||
* @brief This macro function gets the length of a kobject name.
|
||||
*
|
||||
* @param _kobj The kobject.
|
||||
* @return The length of the kobject name.
|
||||
*
|
||||
* @note The name length includes the null terminator('\0').
|
||||
*/
|
||||
#define MR_KOBJECT_NAME_LEN(_kobj) (((mr_kobject_t *)(_kobj))->name.len)
|
||||
|
||||
/**
|
||||
* @brief This macro function gets the parent of a kobject.
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef __MR_KPRINTF_H__
|
||||
#define __MR_KPRINTF_H__
|
||||
|
||||
#include <libc/mr_stdio.h>
|
||||
#include <libc/mr_printf.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -20,8 +20,8 @@ extern "C" {
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Lockref type */
|
||||
typedef mr_atomic_t mr_kref_t;
|
||||
/* Kref type */
|
||||
typedef mr_atomic_t mr_kref_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function initializes a kref.
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_SERVICE_H__
|
||||
#define __MR_SERVICE_H__
|
||||
#ifndef __MR_KSERVICE_H__
|
||||
#define __MR_KSERVICE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -35,7 +35,7 @@ extern "C" {
|
||||
* @param _array The array.
|
||||
* @return The size of the array.
|
||||
*/
|
||||
#define MR_ARRAY_SIZE(_array) (sizeof(_array) / sizeof(_array[0]))
|
||||
#define MR_ARRAY_SIZE(_array) (sizeof(_array) / sizeof((_array)[0]))
|
||||
|
||||
/**
|
||||
* @brief This macro function aligns a value upward.
|
||||
@@ -112,4 +112,4 @@ extern "C" {
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_SERVICE_H__ */
|
||||
#endif /* __MR_KSERVICE_H__ */
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_SLIST_H__
|
||||
#define __MR_SLIST_H__
|
||||
#ifndef __MR_KSLIST_H__
|
||||
#define __MR_KSLIST_H__
|
||||
|
||||
#include <kernel/mr_kservice.h>
|
||||
#include <libc/mr_compiler.h>
|
||||
@@ -18,21 +18,21 @@ extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Slist
|
||||
* @addtogroup Kslist
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Single list type */
|
||||
typedef struct mr_slist {
|
||||
struct mr_slist *next;
|
||||
} mr_slist_t;
|
||||
typedef struct mr_kslist {
|
||||
struct mr_kslist *next;
|
||||
} mr_kslist_t;
|
||||
|
||||
/**
|
||||
* @brief This macro function initializes a single list.
|
||||
*
|
||||
* @param _slist The list to initialize.
|
||||
* @param _kslist The list to initialize.
|
||||
*/
|
||||
#define MR_SLIST_INIT(_slist) \
|
||||
#define MR_KSLIST_INIT(_kslist) \
|
||||
{ .next = MR_NULL }
|
||||
|
||||
/**
|
||||
@@ -40,7 +40,7 @@ typedef struct mr_slist {
|
||||
*
|
||||
* @param entry The element to initialize.
|
||||
*/
|
||||
MR_INLINE void mr_slist_init(mr_slist_t *entry) {
|
||||
MR_INLINE void mr_kslist_init(mr_kslist_t *entry) {
|
||||
entry->next = MR_NULL;
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ MR_INLINE void mr_slist_init(mr_slist_t *entry) {
|
||||
*
|
||||
* @note Adds to the end of the list.
|
||||
*/
|
||||
MR_INLINE void mr_slist_add(mr_slist_t *head, mr_slist_t *entry) {
|
||||
mr_slist_t *p;
|
||||
MR_INLINE void mr_kslist_add(mr_kslist_t *head, mr_kslist_t *entry) {
|
||||
mr_kslist_t *p;
|
||||
|
||||
p = head;
|
||||
while (!p->next) {
|
||||
@@ -70,7 +70,7 @@ MR_INLINE void mr_slist_add(mr_slist_t *head, mr_slist_t *entry) {
|
||||
*
|
||||
* @note Inserts to the beginning of the list.
|
||||
*/
|
||||
MR_INLINE void mr_slist_insert(mr_slist_t *head, mr_slist_t *entry) {
|
||||
MR_INLINE void mr_kslist_insert(mr_kslist_t *head, mr_kslist_t *entry) {
|
||||
entry->next = head->next;
|
||||
head->next = entry;
|
||||
}
|
||||
@@ -81,8 +81,8 @@ MR_INLINE void mr_slist_insert(mr_slist_t *head, mr_slist_t *entry) {
|
||||
* @param head The list head.
|
||||
* @param entry The element to remove.
|
||||
*/
|
||||
MR_INLINE void mr_slist_del(mr_slist_t *head, mr_slist_t *entry) {
|
||||
mr_slist_t *p;
|
||||
MR_INLINE void mr_kslist_del(mr_kslist_t *head, mr_kslist_t *entry) {
|
||||
mr_kslist_t *p;
|
||||
|
||||
p = head;
|
||||
while (!p->next) {
|
||||
@@ -102,7 +102,7 @@ MR_INLINE void mr_slist_del(mr_slist_t *head, mr_slist_t *entry) {
|
||||
* @param head The list head.
|
||||
* @return MR_TRUE on empty, MR_FALSE otherwise.
|
||||
*/
|
||||
MR_INLINE mr_bool_t mr_slist_is_empty(mr_slist_t *head) {
|
||||
MR_INLINE mr_bool_t mr_kslist_is_empty(mr_kslist_t *head) {
|
||||
return (!head->next) ? MR_TRUE : MR_FALSE;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ MR_INLINE mr_bool_t mr_slist_is_empty(mr_slist_t *head) {
|
||||
* @param _pos The pointer to the element.
|
||||
* @param _head The list head.
|
||||
*/
|
||||
#define MR_SLIST_FOR_EACH(_pos, _head) \
|
||||
#define MR_KSLIST_FOR_EACH(_pos, _head) \
|
||||
for ((_pos) = (_head)->next; (_pos) != MR_NULL; (_pos) = (_pos)->next)
|
||||
|
||||
/**
|
||||
@@ -122,7 +122,7 @@ MR_INLINE mr_bool_t mr_slist_is_empty(mr_slist_t *head) {
|
||||
* @param _n The pointer to the next element.
|
||||
* @param _head The list head.
|
||||
*/
|
||||
#define MR_SLIST_FOR_EACH_SAFE(_pos, _n, _head) \
|
||||
#define MR_KSLIST_FOR_EACH_SAFE(_pos, _n, _head) \
|
||||
for ((_pos) = (_head)->next, (_n) = (_pos) ? (_pos)->next : MR_NULL; \
|
||||
(_pos) != MR_NULL; \
|
||||
(_pos) = (_n), (_n) = (_pos) ? (_pos)->next : MR_NULL)
|
||||
@@ -133,4 +133,4 @@ MR_INLINE mr_bool_t mr_slist_is_empty(mr_slist_t *head) {
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_SLIST_H__ */
|
||||
#endif /* __MR_KSLIST_H__ */
|
||||
@@ -74,7 +74,7 @@ menu "Libc"
|
||||
prompt "Stdio"
|
||||
default MR_USE_PRINTFK
|
||||
|
||||
config MR_USE_LIBC_STDIO
|
||||
config MR_USE_LIBC_PRINTF
|
||||
bool "Standard libc stdio"
|
||||
help
|
||||
Use the standard libc stdio for I/O operations.
|
||||
|
||||
@@ -38,6 +38,7 @@ typedef int mr_err_t;
|
||||
#define MR_EBUSY EBUSY
|
||||
#define MR_EEXIST EEXIST
|
||||
#define MR_EINVAL EINVAL
|
||||
#define MR_ENOSYS ENOSYS
|
||||
#define MR_ETIMEDOUT ETIMEDOUT
|
||||
#elif defined(MR_USE_3PARTY_ERRNO)
|
||||
/* In '3party/libc/mr_errno.h' */
|
||||
@@ -50,6 +51,7 @@ typedef int mr_err_t;
|
||||
#define MR_EBUSY 16
|
||||
#define MR_EEXIST 17
|
||||
#define MR_EINVAL 22
|
||||
#define MR_ENOSYS 40
|
||||
#define MR_ETIMEDOUT 116
|
||||
#endif /* defined(MR_USE_LIBC_ERRNO) */
|
||||
|
||||
|
||||
42
include/libc/mr_printf.h
Normal file
42
include/libc/mr_printf.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#ifndef __MR_PRINTF_H__
|
||||
#define __MR_PRINTF_H__
|
||||
|
||||
#include <mr_config.h>
|
||||
#if defined(MR_USE_LIBC_PRINTF)
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#include <libc/mr_types.h>
|
||||
#endif /* defined(MR_USE_LIBC_PRINTF) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* @addtogroup Stdio
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Stdio definition */
|
||||
#if defined(MR_USE_LIBC_PRINTF)
|
||||
#define mr_vprintf(_f, _a) vprintf(_f, _a)
|
||||
#define mr_vsnprintf(_b, _s, _f, _a) vsnprintf(_b, _s, _f, _a)
|
||||
#else
|
||||
|
||||
#endif /* defined(MR_USE_LIBC_PRINTF) */
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MR_PRINTF_H__ */
|
||||
@@ -5,11 +5,6 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
//#define MR_USE_THREAD
|
||||
#define MR_USE_LIBC_MALLOC
|
||||
#define MR_USE_ASSERT
|
||||
#define MR_USE_LIBC_ASSERT
|
||||
#define MR_USE_LIBC_STDIO
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -7,50 +7,15 @@
|
||||
*/
|
||||
|
||||
#include <kernel/mr_initcall.h>
|
||||
#ifdef MR_USE_THREAD
|
||||
#include <kernel/thread/mr_thread.h>
|
||||
|
||||
MR_INLINE void thread_main_entry(void *args) {
|
||||
extern int main(void);
|
||||
MR_UNUSED(args);
|
||||
/* Run main */
|
||||
main();
|
||||
}
|
||||
|
||||
MR_INLINE void thread_main(void) {
|
||||
#if !defined(MR_CFG_MAIN_THREAD_STACK_SIZE)
|
||||
#define MR_CFG_MAIN_THREAD_STACK_SIZE (1024)
|
||||
#endif /* !defined(MR_CFG_MAIN_THREAD_STACK_SIZE) */
|
||||
static mr_uint8_t main_stack[MR_CFG_MAIN_THREAD_STACK_SIZE];
|
||||
static mr_thread_t main_thread;
|
||||
|
||||
/* Init main thread */
|
||||
#if !defined(MR_CFG_MAIN_THREAD_PRIORITY)
|
||||
#define MR_CFG_MAIN_THREAD_PRIORITY (MR_CFG_THREAD_PRIORITY_MAX / 2)
|
||||
#endif /* !defined(MR_CFG_MAIN_THREAD_PRIORITY) */
|
||||
#if MR_CFG_MAIN_THREAD_PRIORITY >= MR_CFG_THREAD_PRIORITY_MAX
|
||||
#error "Main thread priority must be less than thread priority max."
|
||||
#endif /* MR_CFG_MAIN_THREAD_PRIORITY >= MR_CFG_THREAD_PRIORITY_MAX */
|
||||
mr_thread_init(&main_thread, "main", thread_main_entry, MR_NULL, main_stack,
|
||||
MR_CFG_MAIN_THREAD_STACK_SIZE, MR_CFG_MAIN_THREAD_PRIORITY,
|
||||
10);
|
||||
|
||||
/* Startup main thread */
|
||||
mr_thread_startup(&main_thread);
|
||||
}
|
||||
#endif /* MR_USE_THREAD */
|
||||
|
||||
MR_INLINE void entry(void) {
|
||||
extern int main(void);
|
||||
|
||||
/* Run autoinit(kernel) */
|
||||
mr_autoinit_kernel();
|
||||
|
||||
/* Run main */
|
||||
#ifdef MR_USE_THREAD
|
||||
thread_main();
|
||||
#else
|
||||
extern int main(void);
|
||||
main();
|
||||
#endif /* MR_USE_THREAD */
|
||||
}
|
||||
|
||||
/* MR-X entry point */
|
||||
|
||||
@@ -44,7 +44,7 @@ mr_uint32_t mr_kfifo_in(mr_kfifo_t *kfifo, const void *buf, mr_uint32_t size) {
|
||||
mr_memcpy(kfifo->buf + (kfifo->in & (kfifo->size - 1)), buf, s);
|
||||
|
||||
/* In start of kfifo */
|
||||
mr_memcpy(kfifo->buf, buf + s, size - s);
|
||||
mr_memcpy(kfifo->buf, (mr_uint8_t *)buf + s, size - s);
|
||||
|
||||
/* Update in index */
|
||||
kfifo->in += size;
|
||||
@@ -95,6 +95,6 @@ mr_uint32_t mr_kfifo_peek(mr_kfifo_t *kfifo, void *buf, mr_uint32_t size) {
|
||||
mr_memcpy(buf, kfifo->buf + (kfifo->out & (kfifo->size - 1)), s);
|
||||
|
||||
/* Out start of kfifo */
|
||||
mr_memcpy(buf + s, kfifo->buf, size - s);
|
||||
mr_memcpy((mr_uint8_t *)buf + s, kfifo->buf, size - s);
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ void mr_khook_init(mr_khook_t *khook, mr_ptr_t *entry, mr_size_t size) {
|
||||
|
||||
mr_err_t mr_khook_add(mr_khook_t *khook, mr_ptr_t entry) {
|
||||
mr_err_t ret;
|
||||
mr_size_t i;
|
||||
int mask;
|
||||
|
||||
/* Check arguments */
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <kernel/mr_kobject.h>
|
||||
#include <kernel/mr_spinlock.h>
|
||||
#include <libc/mr_malloc.h>
|
||||
#include <libc/mr_stdio.h>
|
||||
#include <libc/mr_printf.h>
|
||||
#include <libc/mr_string.h>
|
||||
|
||||
/* Last-word definition */
|
||||
@@ -188,9 +188,9 @@ MR_INLINE mr_err_t kobject_name_alloc(mr_kobject_t *kobj, const char *name) {
|
||||
s = kobj->iname;
|
||||
} else {
|
||||
s = mr_malloc(size + 1);
|
||||
}
|
||||
if (!s) {
|
||||
return -MR_ENOMEM;
|
||||
if (!s) {
|
||||
return -MR_ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy name */
|
||||
|
||||
48
kernel/kos/kos.c
Normal file
48
kernel/kos/kos.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/kos/mr_kos.h>
|
||||
|
||||
static mr_kos_t kos;
|
||||
|
||||
MR_INLINE void kos_init(mr_kos_t *os, mr_kos_type_t *type) {
|
||||
/* Init kos */
|
||||
os->type = type;
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kos_init_register(mr_kos_t *os, const char *name,
|
||||
mr_kos_type_t *type) {
|
||||
/* Init kos */
|
||||
kos_init(os, type);
|
||||
|
||||
/* Init kset */
|
||||
mr_kset_init((mr_kset_t *)os, MR_NULL);
|
||||
|
||||
/* Register kset */
|
||||
return mr_kset_register((mr_kset_t *)os, name);
|
||||
}
|
||||
|
||||
mr_err_t mr_kos_register(mr_kos_type_t *type) {
|
||||
/* Check arguments */
|
||||
if (MR_KOBJECT_IS_INITED(&kos) || (!type)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Init and register kos */
|
||||
return kos_init_register(&kos, "os", type);
|
||||
}
|
||||
|
||||
mr_kos_t *mr_kos_get(void) {
|
||||
/* Get kos */
|
||||
return (mr_kos_t *)mr_kobject_get((mr_kobject_t *)&kos);
|
||||
}
|
||||
|
||||
void mr_kos_put(void) {
|
||||
/* Put kos */
|
||||
mr_kobject_put((mr_kobject_t *)&kos);
|
||||
}
|
||||
400
kernel/kos/kthread.c
Normal file
400
kernel/kos/kthread.c
Normal file
@@ -0,0 +1,400 @@
|
||||
/**
|
||||
* @copyright (c) 2024, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <kernel/kos/mr_kthread.h>
|
||||
#include <kernel/mr_initcall.h>
|
||||
#include <libc/mr_malloc.h>
|
||||
#include <libc/mr_string.h>
|
||||
|
||||
static mr_ktype_t ktype1, ktype2;
|
||||
static mr_kset_t kroot = MR_KSET_INIT(&kroot, MR_NULL);
|
||||
|
||||
MR_INLINE mr_err_t kthread_res_alloc(mr_kthread_t *kth, mr_size_t size) {
|
||||
void *res;
|
||||
|
||||
/* Alloc resource */
|
||||
if (size <= sizeof(kth->ires)) {
|
||||
/* Use inline resource if possible */
|
||||
res = kth->ires;
|
||||
} else {
|
||||
res = mr_malloc(size);
|
||||
if (!res) {
|
||||
return -MR_ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init resource */
|
||||
mr_memset(res, 0, size);
|
||||
kth->res = res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kthread_init(mr_kthread_t *kth, const char *name,
|
||||
mr_ptr_t entry, mr_ptr_t args, void *stack,
|
||||
mr_size_t stack_size, mr_uint32_t priority,
|
||||
mr_tick_t tick, mr_kos_t *kos) {
|
||||
mr_kthread_type_t *type;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Get kthread kth_type and check priority */
|
||||
type = kos->type->kth_type;
|
||||
if ((!type) || (priority >= type->priority_max)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Init kthread */
|
||||
kth->priority = priority;
|
||||
kth->tick = tick;
|
||||
kth->entry = entry;
|
||||
kth->args = args;
|
||||
kth->os = kos;
|
||||
|
||||
/* Takeover kthread resources not need init. */
|
||||
if (!kth->entry) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Alloc resource */
|
||||
ret = kthread_res_alloc(kth, type->size);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Init kthread resource */
|
||||
return MR_KOS_KTH_OPS(kth->os)->init((void *)kth->res, name, kth, stack,
|
||||
stack_size, priority, tick);
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kthread_del(mr_kthread_t *kth) {
|
||||
/* Delete kthread resource */
|
||||
return MR_KOS_KTH_OPS(kth->os)->del((void *)kth->res);
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kthread_init_add(mr_kthread_t *kth, mr_ktype_t *ktype,
|
||||
const char *name, mr_ptr_t entry,
|
||||
mr_ptr_t args, void *stack,
|
||||
mr_size_t stack_size, mr_uint32_t priority,
|
||||
mr_tick_t tick) {
|
||||
mr_kos_t *kos;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Get kos */
|
||||
kos = mr_kos_get();
|
||||
if (!kos) {
|
||||
return -MR_ENOSYS;
|
||||
}
|
||||
|
||||
/* Init kthread */
|
||||
ret = kthread_init(kth, name, entry, args, stack, stack_size, priority,
|
||||
tick, kos);
|
||||
if (ret != 0) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Init kobject */
|
||||
mr_kobject_init((mr_kobject_t *)kth, ktype);
|
||||
|
||||
/* Add kobject to kroot */
|
||||
ret = mr_kobject_add((mr_kobject_t *)kth, (mr_kobject_t *)&kroot, name);
|
||||
if (ret != 0) {
|
||||
kthread_del(kth);
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
_exit:
|
||||
/* Put kos */
|
||||
mr_kos_put();
|
||||
return ret;
|
||||
}
|
||||
|
||||
mr_err_t mr_kthread_init(mr_kthread_t *kth, const char *name,
|
||||
void (*entry)(mr_kthread_t *, void *), void *args,
|
||||
void *stack, mr_size_t stack_size,
|
||||
mr_uint32_t priority, mr_tick_t tick) {
|
||||
/* Check arguments */
|
||||
if ((!kth) || (MR_KOBJECT_IS_INITED(kth)) || (!name) || (!entry) || (!stack)
|
||||
|| (!tick)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Init and add kthread */
|
||||
return kthread_init_add(kth, &ktype1, name, (mr_ptr_t)entry, args, stack,
|
||||
stack_size, priority, tick);
|
||||
}
|
||||
|
||||
mr_kthread_t *mr_kthread_create(const char *name,
|
||||
void (*entry)(mr_kthread_t *, void *),
|
||||
void *args, mr_size_t stack_size,
|
||||
mr_uint32_t priority, mr_tick_t tick) {
|
||||
mr_kthread_t *kth;
|
||||
mr_uint8_t *stack;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Check arguments */
|
||||
if ((!name) || (!entry) || (!tick)) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Create kthread */
|
||||
kth = mr_malloc(sizeof(mr_kthread_t) + stack_size);
|
||||
if (!kth) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Init and add kthread */
|
||||
stack = (mr_uint8_t *)kth + sizeof(mr_kthread_t);
|
||||
ret = kthread_init_add(kth, &ktype2, name, (mr_ptr_t)entry, args, stack,
|
||||
stack_size, priority, tick);
|
||||
if (ret != 0) {
|
||||
mr_free(kth);
|
||||
return MR_NULL;
|
||||
}
|
||||
return kth;
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kthread_takeover(mr_kthread_t *kth, const char *name,
|
||||
const void *res, mr_uint32_t priority,
|
||||
mr_tick_t tick) {
|
||||
/* Takeover kthread resource */
|
||||
kth->res = res;
|
||||
|
||||
/* Init and add kthread */
|
||||
return kthread_init_add(kth, &ktype1, name, MR_NULL, MR_NULL, MR_NULL, 0,
|
||||
priority, tick);
|
||||
}
|
||||
|
||||
mr_err_t mr_kthread_takeover(mr_kthread_t *kth, const char *name,
|
||||
const void *res, mr_uint32_t priority,
|
||||
mr_tick_t tick) {
|
||||
/* Check arguments */
|
||||
if ((!kth) || (MR_KOBJECT_IS_INITED(kth)) || (!name) || (!res)) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Takeover kthread */
|
||||
return kthread_takeover(kth, name, res, priority, tick);
|
||||
}
|
||||
|
||||
mr_err_t mr_kthread_del(mr_kthread_t *kth) {
|
||||
mr_err_t ret;
|
||||
|
||||
/* Check arguments */
|
||||
if ((!kth) || (!MR_KOBJECT_IS_INITED(kth))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Delete kthread */
|
||||
ret = kthread_del(kth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Delete kobject */
|
||||
mr_kobject_del((mr_kobject_t *)kth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kthread_startup(mr_kthread_t *kth) {
|
||||
/* Get kobject */
|
||||
mr_kobject_get((mr_kobject_t *)kth);
|
||||
|
||||
/* Startup kthread resource */
|
||||
return MR_KOS_KTH_OPS(kth->os)->startup((void *)kth->res);
|
||||
}
|
||||
|
||||
mr_err_t mr_kthread_startup(mr_kthread_t *kth) {
|
||||
/* Check arguments */
|
||||
if ((!kth) || (!MR_KOBJECT_IS_INITED(kth))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Start kthread */
|
||||
return kthread_startup(kth);
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kthread_resume(mr_kthread_t *kth) {
|
||||
/* Resume kthread resource */
|
||||
return MR_KOS_KTH_OPS(kth->os)->resume((void *)kth->res);
|
||||
}
|
||||
|
||||
mr_err_t mr_kthread_resume(mr_kthread_t *kth) {
|
||||
/* Check arguments */
|
||||
if ((!kth) || (!MR_KOBJECT_IS_INITED(kth))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Resume kthread */
|
||||
return kthread_resume(kth);
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kthread_yield(void) {
|
||||
mr_kos_t *kos;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Get kos */
|
||||
kos = mr_kos_get();
|
||||
if (!kos) {
|
||||
return -MR_ENOSYS;
|
||||
}
|
||||
|
||||
/* Yield kthread resource */
|
||||
ret = MR_KOS_KTH_OPS(kos)->yield();
|
||||
|
||||
/* Put kos */
|
||||
mr_kos_put();
|
||||
return ret;
|
||||
}
|
||||
|
||||
mr_err_t mr_kthread_yield(void) {
|
||||
/* Yield kthread */
|
||||
return kthread_yield();
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kthread_suspend(mr_kthread_t *kth) {
|
||||
/* Suspend kthread resource */
|
||||
return MR_KOS_KTH_OPS(kth->os)->suspend((void *)kth->res);
|
||||
}
|
||||
|
||||
mr_err_t mr_kthread_suspend(mr_kthread_t *kth) {
|
||||
/* Check arguments */
|
||||
if ((!kth) || (!MR_KOBJECT_IS_INITED(kth))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Suspend kthread */
|
||||
return kthread_suspend(kth);
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kthread_sleep(mr_tick_t tick) {
|
||||
mr_kos_t *kos;
|
||||
mr_err_t ret;
|
||||
|
||||
/* Get kos */
|
||||
kos = mr_kos_get();
|
||||
if (!kos) {
|
||||
return -MR_ENOSYS;
|
||||
}
|
||||
|
||||
/* Sleep kthread resource */
|
||||
ret = MR_KOS_KTH_OPS(kos)->sleep(tick);
|
||||
|
||||
/* Put kos */
|
||||
mr_kos_put();
|
||||
return ret;
|
||||
}
|
||||
|
||||
mr_err_t mr_kthread_sleep(mr_tick_t tick) {
|
||||
/* Sleep kthread */
|
||||
return kthread_sleep(tick);
|
||||
}
|
||||
|
||||
MR_INLINE mr_err_t kthread_exit(mr_kthread_t *kth) {
|
||||
/* Exit kthread resource */
|
||||
return MR_KOS_KTH_OPS(kth->os)->exit((void *)kth->res);
|
||||
}
|
||||
|
||||
mr_err_t mr_kthread_exit(mr_kthread_t *kth) {
|
||||
/* Check arguments */
|
||||
if ((!kth) || (!MR_KOBJECT_IS_INITED(kth))) {
|
||||
return -MR_EINVAL;
|
||||
}
|
||||
|
||||
/* Exit kthread */
|
||||
return kthread_exit(kth);
|
||||
}
|
||||
|
||||
MR_INLINE mr_kthread_t *kthread_self(void) {
|
||||
mr_kthread_t *ret;
|
||||
mr_kos_t *kos;
|
||||
|
||||
/* Get kos */
|
||||
kos = mr_kos_get();
|
||||
if (!kos) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Get kthread self */
|
||||
ret = MR_KOS_KTH_OPS(mr_kos_get())->self();
|
||||
|
||||
/* Put kos */
|
||||
mr_kos_put();
|
||||
return ret;
|
||||
}
|
||||
|
||||
mr_kthread_t *mr_kthread_self(void) {
|
||||
/* Get kthread self */
|
||||
return kthread_self();
|
||||
}
|
||||
|
||||
mr_kthread_t *mr_kthread_find(const char *name) {
|
||||
/* Lookup kthread in kroot */
|
||||
return (mr_kthread_t *)mr_kobject_lookup((mr_kobject_t *)&kroot, name);
|
||||
}
|
||||
|
||||
void mr_kthread_cleanup(mr_kthread_t *kth) {
|
||||
/* Check arguments */
|
||||
if ((!kth) || (!MR_KOBJECT_IS_INITED(kth))) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cleanup kthread */
|
||||
mr_kobject_put((mr_kobject_t *)kth);
|
||||
}
|
||||
|
||||
void mr_kthread_entry(mr_kthread_t *kth) {
|
||||
/* Check entry */
|
||||
if (!kth->entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call kthread entry */
|
||||
((void (*)(mr_kthread_t *, void *))kth->entry)(kth, kth->args);
|
||||
}
|
||||
|
||||
MR_INLINE mr_kthread_t *kthread_release_kobj(mr_kobject_t *kobj) {
|
||||
mr_kthread_t *kth;
|
||||
const void *res;
|
||||
|
||||
/* Get kthread */
|
||||
kth = MR_CONTAINER_OF(kobj, mr_kthread_t, parent);
|
||||
|
||||
/* If resource is inline or takeover, not need to free */
|
||||
res = ((kth->res != kth->ires) && (kth->entry)) ? kth->res : MR_NULL;
|
||||
if (res) {
|
||||
mr_free((void *)res);
|
||||
}
|
||||
|
||||
/* Put kos */
|
||||
mr_kos_put();
|
||||
return kth;
|
||||
}
|
||||
|
||||
MR_INLINE void kthread_release1_kobj(mr_kobject_t *kobj) {
|
||||
/* Release kthread */
|
||||
kthread_release_kobj(kobj);
|
||||
}
|
||||
|
||||
MR_INLINE void kthread_release2_kobj(mr_kobject_t *kobj) {
|
||||
mr_kthread_t *kth;
|
||||
|
||||
/* Release kobject */
|
||||
kth = kthread_release_kobj(kobj);
|
||||
|
||||
/* Free kthread */
|
||||
mr_free(kth);
|
||||
}
|
||||
|
||||
MR_INLINE void mr_kthread_kset_init(void) {
|
||||
/* Register kset */
|
||||
mr_kset_register(&kroot, "thread");
|
||||
|
||||
/* Init ktype */
|
||||
mr_ktype_init(&ktype1, kthread_release1_kobj);
|
||||
mr_ktype_init(&ktype2, kthread_release2_kobj);
|
||||
}
|
||||
MR_INIT_EXPORT(mr_kthread_kset_init, MR_INIT_LEVEL_KERNEL);
|
||||
@@ -72,7 +72,6 @@ mr_ktimer_t *mr_ktimer_create(const char *name,
|
||||
/* Init and add ktimer */
|
||||
ret = ktimer_init_add(ktimer, &ktype2, name, (mr_ptr_t)entry, args, tick);
|
||||
if (ret != 0) {
|
||||
/* Free ktimer */
|
||||
mr_free(ktimer);
|
||||
return MR_NULL;
|
||||
}
|
||||
@@ -246,13 +245,13 @@ MR_INLINE void ktimer_timeout_check(void) {
|
||||
mr_klist_move(&ktimer->list, &list);
|
||||
|
||||
/* Unlock */
|
||||
mr_spinlock_unlock(&klock);
|
||||
mr_spinlock_unlock_irqrestore(&klock, mask);
|
||||
|
||||
/* Call ktimer entry */
|
||||
((void (*)(mr_ktimer_t *, void *))ktimer->entry)(ktimer, ktimer->args);
|
||||
|
||||
/* Lock */
|
||||
mr_spinlock_lock(&klock);
|
||||
mask = mr_spinlock_lock_irqsave(&klock);
|
||||
|
||||
/* Check that the ktimer has not been moved */
|
||||
if (mr_klist_is_empty(&list)) {
|
||||
|
||||
1
tools/builder/__init__.py
Normal file
1
tools/builder/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .builder import Builder
|
||||
41
tools/builder/builder.py
Normal file
41
tools/builder/builder.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@copyright (c) 2024, MacRsh
|
||||
|
||||
@license SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
@date 2024-09-06 MacRsh First version
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from .parsers import BaseParser
|
||||
|
||||
|
||||
class Builder:
|
||||
def __init__(self, projdir: Path):
|
||||
# Choose suitable parser
|
||||
self.__parser = self._get_parser(projdir)
|
||||
if self.__parser is None:
|
||||
raise ValueError("Suitable parser not found.")
|
||||
self.projdir = projdir
|
||||
self.incdirs = []
|
||||
self.srcfiles = []
|
||||
|
||||
@staticmethod
|
||||
def _get_parser(projdir: Path) -> BaseParser | None:
|
||||
for parser_cls in BaseParser.__subclasses__():
|
||||
parser = parser_cls(projdir)
|
||||
if parser.can_handle(projdir):
|
||||
return parser
|
||||
return None
|
||||
|
||||
def add_include_dir(self, incdir: Path):
|
||||
self.incdirs.append(incdir)
|
||||
|
||||
def add_source_file(self, srcfile: Path):
|
||||
self.srcfiles.append(srcfile)
|
||||
|
||||
def build(self):
|
||||
self.__parser.build(self.incdirs, self.srcfiles)
|
||||
2
tools/builder/parsers/__init__.py
Normal file
2
tools/builder/parsers/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .base import BaseParser
|
||||
from .mdk import MdkParser
|
||||
39
tools/builder/parsers/base.py
Normal file
39
tools/builder/parsers/base.py
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@copyright (c) 2024, MacRsh
|
||||
|
||||
@license SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
@date 2024-09-06 MacRsh First version
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class BaseParser:
|
||||
def __init__(self, projdir: Path):
|
||||
self.projdir = projdir
|
||||
|
||||
def can_handle(self, projdir: Path) -> bool:
|
||||
"""
|
||||
Determines whether the parser can handle the given project directory.
|
||||
|
||||
Args:
|
||||
projdir (Path): The project directory to be checked.
|
||||
|
||||
Returns:
|
||||
bool: True if the parser can handle the project directory, False otherwise.
|
||||
"""
|
||||
pass
|
||||
|
||||
def build(self, incdirs: list[Path], srcfiles: list[Path]):
|
||||
"""
|
||||
Builds the project using the given include directories and source files.
|
||||
|
||||
Args:
|
||||
incdirs (list[Path]): The list of include directories.
|
||||
srcfiles (list[Path]): The list of source files.
|
||||
"""
|
||||
pass
|
||||
85
tools/builder/parsers/mdk.py
Normal file
85
tools/builder/parsers/mdk.py
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@copyright (c) 2024, MacRsh
|
||||
|
||||
@license SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
@date 2024-09-06 MacRsh First version
|
||||
"""
|
||||
|
||||
import os
|
||||
from lxml import etree
|
||||
from pathlib import Path
|
||||
from .base import BaseParser
|
||||
|
||||
|
||||
class MdkParser(BaseParser):
|
||||
def __init__(self, projdir: Path):
|
||||
super().__init__(projdir)
|
||||
self.projfile: Path | None = None
|
||||
self.tree: etree.ElementTree = None
|
||||
|
||||
def can_handle(self, projdir: Path) -> bool:
|
||||
# Look for ".uvprojx" files that can be parsed properly
|
||||
for file in projdir.rglob('*.uvprojx'):
|
||||
try:
|
||||
self.projfile = file
|
||||
self.tree = etree.parse(file)
|
||||
return True
|
||||
except:
|
||||
continue
|
||||
return False
|
||||
|
||||
def build(self, incdirs: list[Path], srcfiles: list[Path]):
|
||||
self._add_incdirs(incdirs)
|
||||
self._add_srcfiles(srcfiles)
|
||||
self._save()
|
||||
|
||||
def _add_incdirs(self, incdirs: list[Path]):
|
||||
projdir = self.projfile.parent
|
||||
mdk_incdirs = self.tree.xpath("//Cads/VariousControls/IncludePath")
|
||||
for incdir in incdirs:
|
||||
incdir = Path(os.path.relpath(incdir, projdir)).as_posix()
|
||||
if incdir not in mdk_incdirs[0].text.split(';'):
|
||||
mdk_incdirs[0].text += f";{incdir}"
|
||||
|
||||
def _add_srcfiles(self, srcfiles: list[Path]):
|
||||
projdir = self.projfile.parent
|
||||
for srcfile in srcfiles:
|
||||
gid = Path(
|
||||
os.path.relpath(Path(srcfile).parent, projdir)).relative_to(
|
||||
"..").as_posix()
|
||||
file = Path(os.path.relpath(srcfile, projdir))
|
||||
|
||||
# Add gid if it doesn't exist
|
||||
groups_node = self.tree.find('.//Groups')
|
||||
group_node = groups_node.find(f"./Group[GroupName='{gid}']")
|
||||
if group_node is None:
|
||||
group_node = etree.SubElement(groups_node, "Group")
|
||||
group_name_node = etree.SubElement(group_node, "GroupName")
|
||||
group_name_node.text = gid
|
||||
etree.SubElement(group_node, "Files")
|
||||
|
||||
# Add file if it doesn't exist
|
||||
files_node = group_node.find("Files")
|
||||
file_node = files_node.find(f"./File[FilePath='{file.as_posix()}']")
|
||||
if file_node is None:
|
||||
file_node = etree.SubElement(files_node, "File")
|
||||
file_path_node = file_node.find("FilePath")
|
||||
if file_path_node is None:
|
||||
file_path_node = etree.SubElement(file_node, "FilePath")
|
||||
file_name_node = file_node.find("FileName")
|
||||
if file_name_node is None:
|
||||
file_name_node = etree.SubElement(file_node, "FileName")
|
||||
file_type_node = file_node.find("FileType")
|
||||
if file_type_node is None:
|
||||
file_type_node = etree.SubElement(file_node, "FileType")
|
||||
file_path_node.text = file.as_posix()
|
||||
file_name_node.text = file.name
|
||||
file_type_node.text = '1'
|
||||
|
||||
def _save(self):
|
||||
self.tree.write(self.projfile, pretty_print=True, encoding="utf-8",
|
||||
xml_declaration=True)
|
||||
0
tools/config/__init__.py
Normal file
0
tools/config/__init__.py
Normal file
51
tools/config/kconfig.py
Normal file
51
tools/config/kconfig.py
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@copyright (c) 2023-2024, MR Development Team
|
||||
|
||||
@license SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
@date 2023-12-17 MacRsh First version
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from kconfiglib import Kconfig
|
||||
|
||||
|
||||
def generate_config(configfile: Path):
|
||||
kconf = Kconfig("Kconfig", warn=False, warn_to_stderr=False)
|
||||
|
||||
# Load config file
|
||||
kconf.load_config(".config")
|
||||
kconf.write_config(".config")
|
||||
kconf.write_autoconf(configfile)
|
||||
|
||||
with open(configfile, 'r+') as file:
|
||||
content = file.read()
|
||||
file.truncate(0)
|
||||
file.seek(0)
|
||||
|
||||
# Writes file header
|
||||
file.write("#ifndef __MR_CONFIG_H__\n")
|
||||
file.write("#define __MR_CONFIG_H__\n\n")
|
||||
|
||||
# Writes cplusplus header
|
||||
file.write("#ifdef __cplusplus\n")
|
||||
file.write("extern \"C\" {\n")
|
||||
file.write("#endif /* __cplusplus */\n\n")
|
||||
|
||||
# Writes the formatted context
|
||||
content = content.replace("#define CONFIG_", "#define ")
|
||||
content = re.sub(r'#define MR_USE_(\w+) (\d+)', r'#define MR_USE_\1',
|
||||
content)
|
||||
file.write(content)
|
||||
|
||||
# Writes cplusplus footer
|
||||
file.write("\n#ifdef __cplusplus\n")
|
||||
file.write("}\n")
|
||||
file.write("#endif /* __cplusplus */\n\n")
|
||||
|
||||
# Writes file footer
|
||||
file.write("#endif /* __MR_CONFIG_H__ */\n")
|
||||
3
tools/requirements.txt
Normal file
3
tools/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
kconfiglib==14.1.0
|
||||
lxml==5.2.2
|
||||
windows-curses==2.3.3
|
||||
90
tools/tool.py
Normal file
90
tools/tool.py
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@copyright (c) 2023-2024, MR Development Team
|
||||
|
||||
@license SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
@date 2024-07-26 MacRsh First version
|
||||
"""
|
||||
|
||||
import sys
|
||||
import logging
|
||||
import argparse
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from builder import Builder
|
||||
from config import kconfig
|
||||
|
||||
logging.basicConfig(level=logging.INFO,
|
||||
format='%(asctime)s [%(levelname)s] %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S')
|
||||
|
||||
|
||||
def _check_python_version():
|
||||
if sys.version_info < (3, 10):
|
||||
logging.error(f'Python version must be >= 3.10(current: {sys.version})')
|
||||
exit(1)
|
||||
|
||||
|
||||
def _find_mrlib() -> Path | None:
|
||||
for dir in Path(__file__).parents:
|
||||
if dir.name == 'mr-library':
|
||||
return dir
|
||||
return None
|
||||
|
||||
|
||||
def _build(projdir: Path, incdirs: list[Path], srcfiles: list[Path]):
|
||||
try:
|
||||
builder = Builder(projdir)
|
||||
for incdir in incdirs:
|
||||
builder.add_include_dir(incdir)
|
||||
for srcfile in srcfiles:
|
||||
builder.add_source_file(srcfile)
|
||||
builder.build()
|
||||
logging.info("Build succeeded")
|
||||
except Exception as e:
|
||||
logging.error(f"Error during build: {e}")
|
||||
exit(1)
|
||||
|
||||
|
||||
def _run_menuconfig(configfile: Path):
|
||||
try:
|
||||
subprocess.run(['menuconfig'], stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
kconfig.generate_config(configfile)
|
||||
logging.info("Menuconfig succeeded")
|
||||
except Exception as e:
|
||||
logging.error(f"Error during menuconfig: {e}")
|
||||
|
||||
|
||||
def main():
|
||||
# Check Python version
|
||||
_check_python_version()
|
||||
|
||||
# Find "mr-library"
|
||||
mrlib = _find_mrlib()
|
||||
if mrlib is None:
|
||||
logging.error('mr-library not found')
|
||||
return
|
||||
|
||||
# Parse arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-b', '--build', action='store_true',
|
||||
help='Build the project')
|
||||
parser.add_argument('-m', '--menuconfig', action='store_true',
|
||||
help='Run menuconfig')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Build the project
|
||||
if args.build:
|
||||
_build(mrlib.parent, [mrlib], list(mrlib.rglob('*.c')))
|
||||
|
||||
# Run menuconfig
|
||||
if args.menuconfig:
|
||||
_run_menuconfig(mrlib / 'include' / 'mr_config.h')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user