mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-22 03:09:16 +08:00
sync branch rt-smart. (#6641)
* Synchronize the code of the rt mart branch to the master branch.
* TTY device
* Add lwP code from rt-smart
* Add vnode in DFS, but DFS will be re-write for rt-smart
* There are three libcpu for rt-smart:
* arm/cortex-a, arm/aarch64
* riscv64
Co-authored-by: Rbb666 <zhangbingru@rt-thread.com>
Co-authored-by: zhkag <zhkag@foxmail.com>
This commit is contained in:
+22
@@ -17,6 +17,13 @@ config RT_USING_ARCH_DATA_TYPE
|
||||
|
||||
Please re-define these data types in rtconfig_project.h file.
|
||||
|
||||
config RT_USING_SMART
|
||||
bool "Enable RT-Thread Smart (microkernel on kernel/userland)"
|
||||
default n
|
||||
select RT_USING_LWP
|
||||
help
|
||||
RT-Thread Smart is a microkernel based operating system on RT-Thread.
|
||||
|
||||
config RT_USING_SMP
|
||||
bool "Enable SMP(Symmetric multiprocessing)"
|
||||
default n
|
||||
@@ -407,6 +414,21 @@ menu "Kernel Device Object"
|
||||
bool "Using ops for each device object"
|
||||
default n
|
||||
|
||||
config RT_USING_DM
|
||||
bool "Enable device driver model with device tree"
|
||||
default n
|
||||
help
|
||||
Enable device driver model with device tree (FDT). It will use more memory
|
||||
to parse and support device tree feature.
|
||||
|
||||
config RT_USING_DM_FDT
|
||||
bool "Enablie builtin libfdt"
|
||||
depends on RT_USING_DM
|
||||
default y
|
||||
help
|
||||
libfdt - Flat Device Tree manipulation. If your code already contains the
|
||||
libfdt, you can cancel this built-in libfdt to avoid link issue.
|
||||
|
||||
config RT_USING_INTERRUPT_INFO
|
||||
bool "Enable additional interrupt trace information"
|
||||
default n
|
||||
|
||||
@@ -27,6 +27,9 @@ if GetDepend('RT_USING_DEVICE') == False:
|
||||
if GetDepend('RT_USING_SMP') == False:
|
||||
SrcRemove(src, ['cpu.c'])
|
||||
|
||||
if GetDepend('RT_USING_DM') == False:
|
||||
SrcRemove(src, ['driver.c'])
|
||||
|
||||
group = DefineGroup('Kernel', src, depend = [''], CPPPATH = inc, CPPDEFINES = ['__RTTHREAD__'])
|
||||
|
||||
Return('group')
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifdef RT_USING_USERSPACE
|
||||
#include <lwp.h>
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
static struct rt_cpu _cpus[RT_CPUS_NR];
|
||||
rt_hw_spinlock_t _cpus_lock;
|
||||
@@ -64,6 +68,7 @@ static void _cpu_preempt_enable(void)
|
||||
/* enable interrupt */
|
||||
rt_hw_local_irq_enable(level);
|
||||
}
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
/**
|
||||
* @brief Initialize a static spinlock object.
|
||||
@@ -72,7 +77,9 @@ static void _cpu_preempt_enable(void)
|
||||
*/
|
||||
void rt_spin_lock_init(struct rt_spinlock *lock)
|
||||
{
|
||||
#ifdef RT_USING_SMP
|
||||
rt_hw_spin_lock_init(&lock->lock);
|
||||
#endif
|
||||
}
|
||||
RTM_EXPORT(rt_spin_lock_init)
|
||||
|
||||
@@ -86,8 +93,12 @@ RTM_EXPORT(rt_spin_lock_init)
|
||||
*/
|
||||
void rt_spin_lock(struct rt_spinlock *lock)
|
||||
{
|
||||
#ifdef RT_USING_SMP
|
||||
_cpu_preempt_disable();
|
||||
rt_hw_spin_lock(&lock->lock);
|
||||
#else
|
||||
rt_enter_critical();
|
||||
#endif
|
||||
}
|
||||
RTM_EXPORT(rt_spin_lock)
|
||||
|
||||
@@ -98,8 +109,12 @@ RTM_EXPORT(rt_spin_lock)
|
||||
*/
|
||||
void rt_spin_unlock(struct rt_spinlock *lock)
|
||||
{
|
||||
#ifdef RT_USING_SMP
|
||||
rt_hw_spin_unlock(&lock->lock);
|
||||
_cpu_preempt_enable();
|
||||
#else
|
||||
rt_exit_critical();
|
||||
#endif
|
||||
}
|
||||
RTM_EXPORT(rt_spin_unlock)
|
||||
|
||||
@@ -115,6 +130,7 @@ RTM_EXPORT(rt_spin_unlock)
|
||||
*/
|
||||
rt_base_t rt_spin_lock_irqsave(struct rt_spinlock *lock)
|
||||
{
|
||||
#ifdef RT_USING_SMP
|
||||
unsigned long level;
|
||||
|
||||
_cpu_preempt_disable();
|
||||
@@ -123,6 +139,9 @@ rt_base_t rt_spin_lock_irqsave(struct rt_spinlock *lock)
|
||||
rt_hw_spin_lock(&lock->lock);
|
||||
|
||||
return level;
|
||||
#else
|
||||
return rt_hw_interrupt_disable();
|
||||
#endif
|
||||
}
|
||||
RTM_EXPORT(rt_spin_lock_irqsave)
|
||||
|
||||
@@ -135,10 +154,14 @@ RTM_EXPORT(rt_spin_lock_irqsave)
|
||||
*/
|
||||
void rt_spin_unlock_irqrestore(struct rt_spinlock *lock, rt_base_t level)
|
||||
{
|
||||
#ifdef RT_USING_SMP
|
||||
rt_hw_spin_unlock(&lock->lock);
|
||||
rt_hw_local_irq_enable(level);
|
||||
|
||||
_cpu_preempt_enable();
|
||||
#else
|
||||
rt_hw_interrupt_enable(level);
|
||||
#endif
|
||||
}
|
||||
RTM_EXPORT(rt_spin_unlock_irqrestore)
|
||||
|
||||
@@ -223,6 +246,9 @@ void rt_cpus_lock_status_restore(struct rt_thread *thread)
|
||||
{
|
||||
struct rt_cpu* pcpu = rt_cpu_self();
|
||||
|
||||
#ifdef RT_USING_USERSPACE
|
||||
lwp_mmu_switch(thread);
|
||||
#endif
|
||||
pcpu->current_thread = thread;
|
||||
if (!thread->cpus_lock_nest)
|
||||
{
|
||||
@@ -230,5 +256,3 @@ void rt_cpus_lock_status_restore(struct rt_thread *thread)
|
||||
}
|
||||
}
|
||||
RTM_EXPORT(rt_cpus_lock_status_restore);
|
||||
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
@@ -457,4 +457,87 @@ rt_err_t rt_device_set_tx_complete(rt_device_t dev,
|
||||
}
|
||||
RTM_EXPORT(rt_device_set_tx_complete);
|
||||
|
||||
#ifdef RT_USING_DM
|
||||
/**
|
||||
* This function bind drvier and device
|
||||
*
|
||||
* @param driver the pointer of driver structure
|
||||
* @param device the pointer of device structure
|
||||
* @param node the pointer of fdt node structure
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
rt_err_t rt_device_bind_driver(rt_device_t device, rt_driver_t driver, void *node)
|
||||
{
|
||||
if((!driver) || (!device))
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
device->drv = driver;
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
device->ops = driver->dev_ops;
|
||||
#endif
|
||||
device->dtb_node = node;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
RTM_EXPORT(rt_device_bind_driver);
|
||||
|
||||
/**
|
||||
* This function create rt_device according to driver infomation
|
||||
*
|
||||
* @param drv the pointer of driver structure
|
||||
* @param device_id specify the ID of the rt_device
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
rt_device_t rt_device_create_since_driver(rt_driver_t drv,int device_id)
|
||||
{
|
||||
rt_device_t device;
|
||||
if (!drv)
|
||||
{
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
device = (rt_device_t)rt_calloc(1,drv->device_size);
|
||||
if(device == RT_NULL)
|
||||
{
|
||||
return RT_NULL;
|
||||
}
|
||||
device->device_id = device_id;
|
||||
rt_snprintf(device->parent.name, sizeof(device->parent.name), "%s%d", drv->name, device_id);
|
||||
return device;
|
||||
}
|
||||
RTM_EXPORT(rt_device_create_since_driver);
|
||||
|
||||
/**
|
||||
* This function rt_device probe and init
|
||||
*
|
||||
* @param device the pointer of rt_device structure
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
rt_err_t rt_device_probe_and_init(rt_device_t device)
|
||||
{
|
||||
int ret = -RT_ERROR;
|
||||
if (!device)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
if(!device->drv)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
if(device->drv->probe)
|
||||
{
|
||||
ret = device->drv->probe((rt_device_t)device);
|
||||
}
|
||||
if(device->drv->probe_init)
|
||||
{
|
||||
ret = device->drv->probe_init((rt_device_t)device);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
RTM_EXPORT(rt_device_probe_and_init);
|
||||
#endif /* RT_USING_DM */
|
||||
#endif /* RT_USING_DEVICE */
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#ifdef RT_USING_FDT
|
||||
#include <dtb_node.h>
|
||||
#endif
|
||||
#if defined(RT_USING_POSIX_DEVIO)
|
||||
#include <rtdevice.h> /* for wqueue_init */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function driver device match with id
|
||||
*
|
||||
* @param drv the pointer of driver structure
|
||||
* @param device_id the id of the device
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
rt_err_t rt_driver_match_with_id(const rt_driver_t drv,int device_id)
|
||||
{
|
||||
rt_device_t device;
|
||||
int ret;
|
||||
if (!drv)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
device = rt_device_create_since_driver(drv,device_id);
|
||||
if(!device)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
ret = rt_device_bind_driver(device,drv,RT_NULL);
|
||||
if(ret != 0)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
ret = rt_device_probe_and_init(device);
|
||||
if(ret != 0)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RTM_EXPORT(rt_driver_match_with_id);
|
||||
|
||||
#ifdef RT_USING_FDT
|
||||
/**
|
||||
* This function driver device match with dtb_node
|
||||
*
|
||||
* @param drv the pointer of driver structure
|
||||
* @param from_node dtb node entry
|
||||
* @param max_dev_num the max device support
|
||||
*
|
||||
* @return the error code, RT_EOK on successfully.
|
||||
*/
|
||||
rt_err_t rt_driver_match_with_dtb(const rt_driver_t drv,void *from_node,int max_dev_num)
|
||||
{
|
||||
struct dtb_node** node_list;
|
||||
rt_device_t device;
|
||||
int ret,i;
|
||||
int total_dev_num = 0;
|
||||
if ((!drv)||(!drv->dev_match)||(!drv->dev_match->compatible)||(!from_node)||(!drv->device_size))
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
node_list = rt_calloc(max_dev_num,sizeof(void *));
|
||||
if(!node_list)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
ret = dtb_node_find_all_compatible_node(from_node,drv->dev_match->compatible,node_list,max_dev_num,&total_dev_num);
|
||||
if((ret != 0) || (!total_dev_num))
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
for(i = 0; i < total_dev_num; i ++)
|
||||
{
|
||||
if (!dtb_node_device_is_available(node_list[i]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
device = rt_device_create_since_driver(drv,i);
|
||||
if(!device)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = rt_device_bind_driver(device,drv,node_list[i]);
|
||||
if(ret != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ret = rt_device_probe_and_init(device);
|
||||
if(ret != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
rt_free(node_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
RTM_EXPORT(rt_driver_match_with_dtb);
|
||||
#endif
|
||||
|
||||
+68
-19
@@ -32,6 +32,12 @@
|
||||
#include <dlmodule.h>
|
||||
#endif /* RT_USING_MODULE */
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
#include <lwp.h>
|
||||
#include <lwp_user_mm.h>
|
||||
#include <console.h>
|
||||
#endif
|
||||
|
||||
/* use precision */
|
||||
#define RT_PRINTF_PRECISION
|
||||
|
||||
@@ -96,7 +102,7 @@ RTM_EXPORT(rt_strerror);
|
||||
*/
|
||||
rt_err_t rt_get_errno(void)
|
||||
{
|
||||
rt_thread_t tid;
|
||||
rt_thread_t tid = RT_NULL;
|
||||
|
||||
if (rt_interrupt_get_nest() != 0)
|
||||
{
|
||||
@@ -106,7 +112,9 @@ rt_err_t rt_get_errno(void)
|
||||
|
||||
tid = rt_thread_self();
|
||||
if (tid == RT_NULL)
|
||||
{
|
||||
return __rt_errno;
|
||||
}
|
||||
|
||||
return tid->error;
|
||||
}
|
||||
@@ -119,7 +127,7 @@ RTM_EXPORT(rt_get_errno);
|
||||
*/
|
||||
void rt_set_errno(rt_err_t error)
|
||||
{
|
||||
rt_thread_t tid;
|
||||
rt_thread_t tid = RT_NULL;
|
||||
|
||||
if (rt_interrupt_get_nest() != 0)
|
||||
{
|
||||
@@ -148,14 +156,18 @@ RTM_EXPORT(rt_set_errno);
|
||||
*/
|
||||
int *_rt_errno(void)
|
||||
{
|
||||
rt_thread_t tid;
|
||||
rt_thread_t tid = RT_NULL;
|
||||
|
||||
if (rt_interrupt_get_nest() != 0)
|
||||
{
|
||||
return (int *)&__rt_errno;
|
||||
}
|
||||
|
||||
tid = rt_thread_self();
|
||||
if (tid != RT_NULL)
|
||||
{
|
||||
return (int *) & (tid->error);
|
||||
}
|
||||
|
||||
return (int *)&__rt_errno;
|
||||
}
|
||||
@@ -188,10 +200,10 @@ RT_WEAK void *rt_memset(void *s, int c, rt_ubase_t count)
|
||||
#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
|
||||
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
|
||||
|
||||
unsigned int i;
|
||||
unsigned int i = 0;
|
||||
char *m = (char *)s;
|
||||
unsigned long buffer;
|
||||
unsigned long *aligned_addr;
|
||||
unsigned long buffer = 0;
|
||||
unsigned long *aligned_addr = RT_NULL;
|
||||
unsigned char d = (unsigned int)c & (unsigned char)(-1); /* To avoid sign extension, copy C to an
|
||||
unsigned variable. (unsigned)((char)(-1))=0xFF for 8bit and =0xFFFF for 16bit: word independent */
|
||||
|
||||
@@ -258,7 +270,7 @@ RT_WEAK void *rt_memcpy(void *dst, const void *src, rt_ubase_t count)
|
||||
{
|
||||
#ifdef RT_KSERVICE_USING_TINY_SIZE
|
||||
char *tmp = (char *)dst, *s = (char *)src;
|
||||
rt_ubase_t len;
|
||||
rt_ubase_t len = 0;
|
||||
|
||||
if (tmp <= s || tmp > (s + count))
|
||||
{
|
||||
@@ -282,8 +294,8 @@ RT_WEAK void *rt_memcpy(void *dst, const void *src, rt_ubase_t count)
|
||||
|
||||
char *dst_ptr = (char *)dst;
|
||||
char *src_ptr = (char *)src;
|
||||
long *aligned_dst;
|
||||
long *aligned_src;
|
||||
long *aligned_dst = RT_NULL;
|
||||
long *aligned_src = RT_NULL;
|
||||
rt_ubase_t len = count;
|
||||
|
||||
/* If the size is small, or either SRC or DST is unaligned,
|
||||
@@ -378,7 +390,7 @@ RTM_EXPORT(rt_memmove);
|
||||
*/
|
||||
rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_size_t count)
|
||||
{
|
||||
const unsigned char *su1, *su2;
|
||||
const unsigned char *su1 = RT_NULL, *su2 = RT_NULL;
|
||||
int res = 0;
|
||||
|
||||
for (su1 = (const unsigned char *)cs, su2 = (const unsigned char *)ct; 0 < count; ++su1, ++su2, count--)
|
||||
@@ -403,17 +415,23 @@ RTM_EXPORT(rt_memcmp);
|
||||
*/
|
||||
char *rt_strstr(const char *s1, const char *s2)
|
||||
{
|
||||
int l1, l2;
|
||||
int l1 = 0, l2 = 0;
|
||||
|
||||
l2 = rt_strlen(s2);
|
||||
if (!l2)
|
||||
return (char *)s1;
|
||||
{
|
||||
return (char *)s1;
|
||||
}
|
||||
|
||||
l1 = rt_strlen(s1);
|
||||
while (l1 >= l2)
|
||||
{
|
||||
l1 --;
|
||||
if (!rt_memcmp(s1, s2, l2))
|
||||
return (char *)s1;
|
||||
{
|
||||
return (char *)s1;
|
||||
}
|
||||
|
||||
s1 ++;
|
||||
}
|
||||
|
||||
@@ -435,7 +453,7 @@ RTM_EXPORT(rt_strstr);
|
||||
*/
|
||||
rt_int32_t rt_strcasecmp(const char *a, const char *b)
|
||||
{
|
||||
int ca, cb;
|
||||
int ca = 0, cb = 0;
|
||||
|
||||
do
|
||||
{
|
||||
@@ -476,7 +494,10 @@ char *rt_strncpy(char *dst, const char *src, rt_size_t n)
|
||||
{
|
||||
/* NUL pad the remaining n-1 bytes */
|
||||
while (--n != 0)
|
||||
*d++ = 0;
|
||||
{
|
||||
*d++ = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
} while (--n != 0);
|
||||
@@ -532,7 +553,10 @@ rt_int32_t rt_strncmp(const char *cs, const char *ct, rt_size_t count)
|
||||
while (count)
|
||||
{
|
||||
if ((__res = *cs - *ct++) != 0 || !*cs++)
|
||||
break;
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
count --;
|
||||
}
|
||||
|
||||
@@ -574,7 +598,7 @@ RTM_EXPORT(rt_strcmp);
|
||||
*/
|
||||
rt_size_t rt_strlen(const char *s)
|
||||
{
|
||||
const char *sc;
|
||||
const char *sc = RT_NULL;
|
||||
|
||||
for (sc = s; *sc != '\0'; ++sc) /* nothing */
|
||||
;
|
||||
@@ -623,7 +647,9 @@ char *rt_strdup(const char *s)
|
||||
char *tmp = (char *)rt_malloc(len);
|
||||
|
||||
if (!tmp)
|
||||
return RT_NULL;
|
||||
{
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
rt_memcpy(tmp, s, len);
|
||||
|
||||
@@ -1230,6 +1256,28 @@ RTM_EXPORT(rt_console_get_device);
|
||||
*/
|
||||
rt_device_t rt_console_set_device(const char *name)
|
||||
{
|
||||
#ifdef RT_USING_LWP
|
||||
rt_device_t new_iodev = RT_NULL, old_iodev = RT_NULL;
|
||||
extern void console_init();
|
||||
console_init(); /*add line discipline*/
|
||||
/* find new console device */
|
||||
new_iodev = rt_device_find(name);
|
||||
if (new_iodev != RT_NULL)
|
||||
{
|
||||
if (_console_device != RT_NULL)
|
||||
{
|
||||
old_iodev = console_set_iodev(new_iodev);
|
||||
}
|
||||
else
|
||||
{
|
||||
console_register("console", new_iodev);
|
||||
_console_device = rt_device_find("console");
|
||||
rt_device_open(_console_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
|
||||
}
|
||||
}
|
||||
|
||||
return old_iodev;
|
||||
#else
|
||||
rt_device_t new_device, old_device;
|
||||
|
||||
/* save old device */
|
||||
@@ -1255,6 +1303,7 @@ rt_device_t rt_console_set_device(const char *name)
|
||||
}
|
||||
|
||||
return old_device;
|
||||
#endif
|
||||
}
|
||||
RTM_EXPORT(rt_console_set_device);
|
||||
#endif /* RT_USING_DEVICE */
|
||||
@@ -1702,7 +1751,7 @@ RTM_EXPORT(rt_malloc_align);
|
||||
*/
|
||||
RT_WEAK void rt_free_align(void *ptr)
|
||||
{
|
||||
void *real_ptr;
|
||||
void *real_ptr = RT_NULL;
|
||||
|
||||
/* NULL check */
|
||||
if (ptr == RT_NULL) return;
|
||||
|
||||
@@ -23,6 +23,17 @@
|
||||
#include <dlmodule.h>
|
||||
#endif /* RT_USING_MODULE */
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
#include <lwp.h>
|
||||
#endif
|
||||
|
||||
struct rt_custom_object
|
||||
{
|
||||
struct rt_object parent;
|
||||
rt_err_t (*destroy)(void *);
|
||||
void *data;
|
||||
};
|
||||
|
||||
/*
|
||||
* define object_info for the number of _object_container items.
|
||||
*/
|
||||
@@ -59,6 +70,12 @@ enum rt_object_info_type
|
||||
#endif
|
||||
#ifdef RT_USING_HEAP
|
||||
RT_Object_Info_Memory, /**< The object is a memory. */
|
||||
#endif
|
||||
#ifdef RT_USING_LWP
|
||||
RT_Object_Info_Channel, /**< The object is a IPC channel */
|
||||
#endif
|
||||
#ifdef RT_USING_HEAP
|
||||
RT_Object_Info_Custom, /**< The object is a custom object */
|
||||
#endif
|
||||
RT_Object_Info_Unknown, /**< The object is unknown. */
|
||||
};
|
||||
@@ -112,6 +129,11 @@ static struct rt_object_information _object_container[RT_Object_Info_Unknown] =
|
||||
/* initialize object container - small memory */
|
||||
{RT_Object_Class_Memory, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Memory), sizeof(struct rt_memory)},
|
||||
#endif
|
||||
#ifdef RT_USING_LWP
|
||||
/* initialize object container - module */
|
||||
{RT_Object_Class_Channel, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Channel), sizeof(struct rt_channel)},
|
||||
{RT_Object_Class_Custom, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Custom), sizeof(struct rt_custom_object)},
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef __on_rt_object_attach_hook
|
||||
@@ -607,4 +629,60 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type)
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
/**
|
||||
* This function will create a custom object
|
||||
* container.
|
||||
*
|
||||
* @param name the specified name of object.
|
||||
* @param type the type of object
|
||||
* @param data the custom data
|
||||
* @param data_destroy the custom object destroy callback
|
||||
*
|
||||
* @return the found object or RT_NULL if there is no this object
|
||||
* in object container.
|
||||
*
|
||||
* @note this function shall not be invoked in interrupt status.
|
||||
*/
|
||||
|
||||
rt_object_t rt_custom_object_create(const char *name, void *data, rt_err_t (*data_destroy)(void *))
|
||||
{
|
||||
struct rt_custom_object *cobj = RT_NULL;
|
||||
|
||||
cobj = (struct rt_custom_object *)rt_object_allocate(RT_Object_Class_Custom, name);
|
||||
if (!cobj)
|
||||
{
|
||||
return RT_NULL;
|
||||
}
|
||||
cobj->destroy = data_destroy;
|
||||
cobj->data = data;
|
||||
return (struct rt_object *)cobj;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will destroy a custom object
|
||||
* container.
|
||||
*
|
||||
* @param obj the specified name of object.
|
||||
*
|
||||
* @note this function shall not be invoked in interrupt status.
|
||||
*/
|
||||
rt_err_t rt_custom_object_destroy(rt_object_t obj)
|
||||
{
|
||||
rt_err_t ret = -1;
|
||||
|
||||
struct rt_custom_object *cobj = (struct rt_custom_object *)obj;
|
||||
|
||||
if (obj && obj->type == RT_Object_Class_Custom)
|
||||
{
|
||||
if (cobj->destroy)
|
||||
{
|
||||
ret = cobj->destroy(cobj->data);
|
||||
}
|
||||
rt_object_delete(obj);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
||||
|
||||
+54
-15
@@ -33,6 +33,10 @@
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
#include <lwp.h>
|
||||
#endif /* RT_USING_LWP */
|
||||
|
||||
rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
|
||||
rt_uint32_t rt_thread_ready_priority_group;
|
||||
#if RT_THREAD_PRIORITY_MAX > 32
|
||||
@@ -94,6 +98,19 @@ static void _scheduler_stack_check(struct rt_thread *thread)
|
||||
{
|
||||
RT_ASSERT(thread != RT_NULL);
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
#ifndef ARCH_MM_MMU
|
||||
struct rt_lwp *lwp = thread ? (struct rt_lwp *)thread->lwp : 0;
|
||||
|
||||
/* if stack pointer locate in user data section skip stack check. */
|
||||
if (lwp && ((rt_uint32_t)thread->sp > (rt_uint32_t)lwp->data_entry &&
|
||||
(rt_uint32_t)thread->sp <= (rt_uint32_t)lwp->data_entry + (rt_uint32_t)lwp->data_size))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif /* not defined ARCH_MM_MMU */
|
||||
#endif /* RT_USING_LWP */
|
||||
|
||||
#ifdef ARCH_CPU_STACK_GROWS_UPWARD
|
||||
if (*((rt_uint8_t *)((rt_ubase_t)thread->stack_addr + thread->stack_size - 1)) != '#' ||
|
||||
#else
|
||||
@@ -322,13 +339,17 @@ void rt_schedule(void)
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SIGNALS
|
||||
if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
|
||||
if ((current_thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
|
||||
{
|
||||
/* if current_thread signal is in pending */
|
||||
|
||||
if ((current_thread->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL_PENDING)
|
||||
{
|
||||
#ifdef RT_USING_LWP
|
||||
rt_thread_wakeup(current_thread);
|
||||
#else
|
||||
rt_thread_resume(current_thread);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* RT_USING_SIGNALS */
|
||||
@@ -343,13 +364,20 @@ void rt_schedule(void)
|
||||
current_thread->oncpu = RT_CPU_DETACHED;
|
||||
if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
|
||||
{
|
||||
if (current_thread->current_priority < highest_ready_priority)
|
||||
if (current_thread->bind_cpu == RT_CPUS_NR || current_thread->bind_cpu == cpu_id)
|
||||
{
|
||||
to_thread = current_thread;
|
||||
}
|
||||
else if (current_thread->current_priority == highest_ready_priority && (current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
|
||||
{
|
||||
to_thread = current_thread;
|
||||
if (current_thread->current_priority < highest_ready_priority)
|
||||
{
|
||||
to_thread = current_thread;
|
||||
}
|
||||
else if (current_thread->current_priority == highest_ready_priority && (current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
|
||||
{
|
||||
to_thread = current_thread;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_schedule_insert_thread(current_thread);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -526,7 +554,7 @@ void rt_schedule(void)
|
||||
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interrupt\n"));
|
||||
|
||||
rt_hw_context_switch_interrupt((rt_ubase_t)&from_thread->sp,
|
||||
(rt_ubase_t)&to_thread->sp);
|
||||
(rt_ubase_t)&to_thread->sp, from_thread, to_thread);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -566,13 +594,17 @@ void rt_scheduler_do_irq_switch(void *context)
|
||||
current_thread = pcpu->current_thread;
|
||||
|
||||
#ifdef RT_USING_SIGNALS
|
||||
if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
|
||||
if ((current_thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
|
||||
{
|
||||
/* if current_thread signal is in pending */
|
||||
|
||||
if ((current_thread->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL_PENDING)
|
||||
{
|
||||
#ifdef RT_USING_LWP
|
||||
rt_thread_wakeup(current_thread);
|
||||
#else
|
||||
rt_thread_resume(current_thread);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* RT_USING_SIGNALS */
|
||||
@@ -596,13 +628,20 @@ void rt_scheduler_do_irq_switch(void *context)
|
||||
current_thread->oncpu = RT_CPU_DETACHED;
|
||||
if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
|
||||
{
|
||||
if (current_thread->current_priority < highest_ready_priority)
|
||||
if (current_thread->bind_cpu == RT_CPUS_NR || current_thread->bind_cpu == cpu_id)
|
||||
{
|
||||
to_thread = current_thread;
|
||||
}
|
||||
else if (current_thread->current_priority == highest_ready_priority && (current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
|
||||
{
|
||||
to_thread = current_thread;
|
||||
if (current_thread->current_priority < highest_ready_priority)
|
||||
{
|
||||
to_thread = current_thread;
|
||||
}
|
||||
else if (current_thread->current_priority == highest_ready_priority && (current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
|
||||
{
|
||||
to_thread = current_thread;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_schedule_insert_thread(current_thread);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+7
-3
@@ -102,10 +102,14 @@ static void _signal_deliver(rt_thread_t tid)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
|
||||
if ((tid->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
|
||||
{
|
||||
/* resume thread to handle signal */
|
||||
#ifdef RT_USING_LWP
|
||||
rt_thread_wakeup(tid);
|
||||
#else
|
||||
rt_thread_resume(tid);
|
||||
#endif
|
||||
/* add signal state */
|
||||
tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
|
||||
|
||||
@@ -197,7 +201,7 @@ void *rt_signal_check(void* context)
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
sig_context = rt_hw_stack_init((void *)_signal_entry, context,
|
||||
(void *)(context - 32), RT_NULL);
|
||||
(void*)((char*)context - 32), RT_NULL);
|
||||
return sig_context;
|
||||
}
|
||||
}
|
||||
@@ -350,7 +354,7 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
|
||||
}
|
||||
|
||||
/* suspend self thread */
|
||||
rt_thread_suspend(tid);
|
||||
rt_thread_suspend_with_flag(tid, RT_UNINTERRUPTIBLE);
|
||||
/* set thread stat as waiting for signal */
|
||||
tid->stat |= RT_THREAD_STAT_SIGNAL_WAIT;
|
||||
|
||||
|
||||
+202
-32
@@ -133,7 +133,7 @@ static void _thread_timeout(void *parameter)
|
||||
|
||||
/* parameter check */
|
||||
RT_ASSERT(thread != RT_NULL);
|
||||
RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND);
|
||||
RT_ASSERT((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK);
|
||||
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
|
||||
|
||||
/* disable interrupt */
|
||||
@@ -167,6 +167,10 @@ static rt_err_t _thread_init(struct rt_thread *thread,
|
||||
/* init thread list */
|
||||
rt_list_init(&(thread->tlist));
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
thread->wakeup.func = RT_NULL;
|
||||
#endif
|
||||
|
||||
thread->entry = (void *)entry;
|
||||
thread->parameter = parameter;
|
||||
|
||||
@@ -253,7 +257,13 @@ static rt_err_t _thread_init(struct rt_thread *thread,
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
thread->lwp = RT_NULL;
|
||||
#endif /* RT_USING_LWP */
|
||||
rt_list_init(&(thread->sibling));
|
||||
rt_memset(&thread->signal, 0, sizeof(lwp_sigset_t));
|
||||
rt_memset(&thread->signal_mask, 0, sizeof(lwp_sigset_t));
|
||||
thread->signal_mask_bak = 0;
|
||||
thread->signal_in_process = 0;
|
||||
rt_memset(&thread->user_ctx, 0, sizeof thread->user_ctx);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_CPU_USAGE
|
||||
thread->duration_tick = 0;
|
||||
@@ -598,6 +608,7 @@ rt_err_t rt_thread_sleep(rt_tick_t tick)
|
||||
{
|
||||
rt_base_t level;
|
||||
struct rt_thread *thread;
|
||||
int err;
|
||||
|
||||
if (tick == 0)
|
||||
{
|
||||
@@ -619,22 +630,31 @@ rt_err_t rt_thread_sleep(rt_tick_t tick)
|
||||
thread->error = RT_EOK;
|
||||
|
||||
/* suspend thread */
|
||||
rt_thread_suspend(thread);
|
||||
err = rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE);
|
||||
|
||||
/* reset the timeout of thread timer and start it */
|
||||
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);
|
||||
rt_timer_start(&(thread->thread_timer));
|
||||
if (err == RT_EOK)
|
||||
{
|
||||
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);
|
||||
rt_timer_start(&(thread->thread_timer));
|
||||
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
rt_schedule();
|
||||
thread->error = -RT_EINTR;
|
||||
|
||||
rt_schedule();
|
||||
|
||||
/* clear error number of this thread to RT_EOK */
|
||||
if (thread->error == -RT_ETIMEOUT)
|
||||
thread->error = RT_EOK;
|
||||
/* clear error number of this thread to RT_EOK */
|
||||
if (thread->error == -RT_ETIMEOUT)
|
||||
thread->error = RT_EOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
|
||||
return thread->error;
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -689,7 +709,7 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick)
|
||||
left_tick = *tick - cur_tick;
|
||||
|
||||
/* suspend thread */
|
||||
rt_thread_suspend(thread);
|
||||
rt_thread_suspend_with_flag(thread, RT_UNINTERRUPTIBLE);
|
||||
|
||||
/* reset the timeout of thread timer and start it */
|
||||
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &left_tick);
|
||||
@@ -734,6 +754,66 @@ rt_err_t rt_thread_mdelay(rt_int32_t ms)
|
||||
}
|
||||
RTM_EXPORT(rt_thread_mdelay);
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
static void rt_thread_cpu_bind(rt_thread_t thread, int cpu)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
if (cpu >= RT_CPUS_NR)
|
||||
{
|
||||
cpu = RT_CPUS_NR;
|
||||
}
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
|
||||
{
|
||||
/* unbind */
|
||||
/* remove from old ready queue */
|
||||
rt_schedule_remove_thread(thread);
|
||||
/* change thread bind cpu */
|
||||
thread->bind_cpu = cpu;
|
||||
/* add to new ready queue */
|
||||
rt_schedule_insert_thread(thread);
|
||||
if (rt_thread_self() != RT_NULL)
|
||||
{
|
||||
rt_schedule();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
thread->bind_cpu = cpu;
|
||||
if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
|
||||
{
|
||||
/* thread is running on a cpu */
|
||||
int current_cpu = rt_hw_cpu_id();
|
||||
|
||||
if (cpu != RT_CPUS_NR)
|
||||
{
|
||||
if (thread->oncpu == current_cpu)
|
||||
{
|
||||
/* current thread on current cpu */
|
||||
if (cpu != current_cpu)
|
||||
{
|
||||
/* bind to other cpu */
|
||||
rt_hw_ipi_send(RT_SCHEDULE_IPI, 1U << cpu);
|
||||
/* self cpu need reschedule */
|
||||
rt_schedule();
|
||||
}
|
||||
/* else do nothing */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no running on self cpu, but dest cpu can be itself */
|
||||
rt_hw_ipi_send(RT_SCHEDULE_IPI, 1U << thread->oncpu);
|
||||
}
|
||||
}
|
||||
/* else do nothing */
|
||||
}
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief This function will control thread behaviors according to control command.
|
||||
*
|
||||
@@ -837,26 +917,46 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
|
||||
{
|
||||
rt_uint8_t cpu;
|
||||
|
||||
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
|
||||
{
|
||||
/* we only support bind cpu before started phase. */
|
||||
return RT_ERROR;
|
||||
}
|
||||
|
||||
cpu = (rt_uint8_t)(rt_size_t)arg;
|
||||
thread->bind_cpu = cpu > RT_CPUS_NR? RT_CPUS_NR : cpu;
|
||||
break;
|
||||
}
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
default:
|
||||
break;
|
||||
cpu = (rt_uint8_t)(size_t)arg;
|
||||
rt_thread_cpu_bind(thread, cpu);
|
||||
break;
|
||||
}
|
||||
#endif /*RT_USING_SMP*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
RTM_EXPORT(rt_thread_control);
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
int lwp_suspend_sigcheck(rt_thread_t thread, int suspend_flag);
|
||||
#endif
|
||||
|
||||
static void rt_thread_set_suspend_state(struct rt_thread *thread, int suspend_flag)
|
||||
{
|
||||
rt_uint8_t stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
|
||||
|
||||
RT_ASSERT(thread != RT_NULL);
|
||||
switch (suspend_flag)
|
||||
{
|
||||
case RT_INTERRUPTIBLE:
|
||||
stat = RT_THREAD_SUSPEND_INTERRUPTIBLE;
|
||||
break;
|
||||
case RT_KILLABLE:
|
||||
stat = RT_THREAD_SUSPEND_KILLABLE;
|
||||
break;
|
||||
case RT_UNINTERRUPTIBLE:
|
||||
stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
|
||||
break;
|
||||
default:
|
||||
RT_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
thread->stat = stat | (thread->stat & ~RT_THREAD_STAT_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function will suspend the specified thread and change it to suspend state.
|
||||
*
|
||||
@@ -872,7 +972,7 @@ RTM_EXPORT(rt_thread_control);
|
||||
* @return Return the operation status. If the return value is RT_EOK, the function is successfully executed.
|
||||
* If the return value is any other values, it means this operation failed.
|
||||
*/
|
||||
rt_err_t rt_thread_suspend(rt_thread_t thread)
|
||||
rt_err_t rt_thread_suspend_with_flag(rt_thread_t thread, int suspend_flag)
|
||||
{
|
||||
rt_base_t stat;
|
||||
rt_base_t level;
|
||||
@@ -893,10 +993,24 @@ rt_err_t rt_thread_suspend(rt_thread_t thread)
|
||||
|
||||
/* disable interrupt */
|
||||
level = rt_hw_interrupt_disable();
|
||||
if (stat == RT_THREAD_RUNNING)
|
||||
{
|
||||
/* not suspend running status thread on other core */
|
||||
RT_ASSERT(thread == rt_thread_self());
|
||||
}
|
||||
#ifdef RT_USING_LWP
|
||||
if (lwp_suspend_sigcheck(thread, suspend_flag) == 0)
|
||||
{
|
||||
/* not to suspend */
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_kprintf("-RT_EINTR\r\n");
|
||||
return -RT_EINTR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* change thread stat */
|
||||
rt_schedule_remove_thread(thread);
|
||||
thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK);
|
||||
rt_thread_set_suspend_state(thread, suspend_flag);
|
||||
|
||||
/* stop thread timer anyway */
|
||||
rt_timer_stop(&(thread->thread_timer));
|
||||
@@ -907,6 +1021,12 @@ rt_err_t rt_thread_suspend(rt_thread_t thread)
|
||||
RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread));
|
||||
return RT_EOK;
|
||||
}
|
||||
RTM_EXPORT(rt_thread_suspend_with_flag);
|
||||
|
||||
rt_err_t rt_thread_suspend(rt_thread_t thread)
|
||||
{
|
||||
return rt_thread_suspend_with_flag(thread, RT_UNINTERRUPTIBLE);
|
||||
}
|
||||
RTM_EXPORT(rt_thread_suspend);
|
||||
|
||||
/**
|
||||
@@ -927,7 +1047,7 @@ rt_err_t rt_thread_resume(rt_thread_t thread)
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: %s\n", thread->name));
|
||||
|
||||
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND)
|
||||
if ((thread->stat & RT_THREAD_SUSPEND_MASK) != RT_THREAD_SUSPEND_MASK)
|
||||
{
|
||||
RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n",
|
||||
thread->stat));
|
||||
@@ -943,17 +1063,67 @@ rt_err_t rt_thread_resume(rt_thread_t thread)
|
||||
|
||||
rt_timer_stop(&thread->thread_timer);
|
||||
|
||||
/* insert to schedule ready list */
|
||||
rt_schedule_insert_thread(thread);
|
||||
#ifdef RT_USING_LWP
|
||||
thread->wakeup.func = RT_NULL;
|
||||
#endif
|
||||
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
/* insert to schedule ready list */
|
||||
rt_schedule_insert_thread(thread);
|
||||
|
||||
RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread));
|
||||
return RT_EOK;
|
||||
}
|
||||
RTM_EXPORT(rt_thread_resume);
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
/**
|
||||
* This function will wakeup a thread with customized operation.
|
||||
*
|
||||
* @param thread the thread to be resumed
|
||||
*
|
||||
* @return the operation status, RT_EOK on OK, -RT_ERROR on error
|
||||
*/
|
||||
rt_err_t rt_thread_wakeup(rt_thread_t thread)
|
||||
{
|
||||
register rt_base_t temp;
|
||||
rt_err_t ret;
|
||||
|
||||
RT_ASSERT(thread != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
|
||||
/* disable interrupt */
|
||||
temp = rt_hw_interrupt_disable();
|
||||
if (thread->wakeup.func)
|
||||
{
|
||||
ret = thread->wakeup.func(thread->wakeup.user_data, thread);
|
||||
thread->wakeup.func = RT_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = rt_thread_resume(thread);
|
||||
}
|
||||
|
||||
rt_hw_interrupt_enable(temp);
|
||||
return ret;
|
||||
}
|
||||
RTM_EXPORT(rt_thread_wakeup);
|
||||
|
||||
void rt_thread_wakeup_set(struct rt_thread *thread, rt_wakeup_func_t func, void* user_data)
|
||||
{
|
||||
register rt_base_t temp;
|
||||
|
||||
RT_ASSERT(thread != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
|
||||
|
||||
temp = rt_hw_interrupt_disable();
|
||||
thread->wakeup.func = func;
|
||||
thread->wakeup.user_data = user_data;
|
||||
rt_hw_interrupt_enable(temp);
|
||||
}
|
||||
RTM_EXPORT(rt_thread_wakeup_set);
|
||||
#endif
|
||||
/**
|
||||
* @brief This function will find the specified thread.
|
||||
*
|
||||
|
||||
+24
-6
@@ -502,7 +502,7 @@ rt_err_t rt_timer_start(rt_timer_t timer)
|
||||
{
|
||||
/* check whether timer thread is ready */
|
||||
if ((_soft_timer_status == RT_SOFT_TIMER_IDLE) &&
|
||||
((_timer_thread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
|
||||
((_timer_thread.stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK))
|
||||
{
|
||||
/* resume timer thread to check soft timer */
|
||||
rt_thread_resume(&_timer_thread);
|
||||
@@ -534,18 +534,21 @@ rt_err_t rt_timer_stop(rt_timer_t timer)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
/* parameter check */
|
||||
/* disable interrupt */
|
||||
level = rt_hw_interrupt_disable();
|
||||
|
||||
/* timer check */
|
||||
RT_ASSERT(timer != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
|
||||
|
||||
if (!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(timer->parent)));
|
||||
|
||||
/* disable interrupt */
|
||||
level = rt_hw_interrupt_disable();
|
||||
|
||||
_timer_remove(timer);
|
||||
/* change status */
|
||||
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
@@ -610,6 +613,21 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
|
||||
case RT_TIMER_CTRL_GET_REMAIN_TIME:
|
||||
*(rt_tick_t *)arg = timer->timeout_tick;
|
||||
break;
|
||||
case RT_TIMER_CTRL_GET_FUNC:
|
||||
*(void **)arg = timer->timeout_func;
|
||||
break;
|
||||
|
||||
case RT_TIMER_CTRL_SET_FUNC:
|
||||
timer->timeout_func = (void (*)(void*))arg;
|
||||
break;
|
||||
|
||||
case RT_TIMER_CTRL_GET_PARM:
|
||||
*(void **)arg = timer->parameter;
|
||||
break;
|
||||
|
||||
case RT_TIMER_CTRL_SET_PARM:
|
||||
timer->parameter = arg;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -801,7 +819,7 @@ static void _timer_thread_entry(void *parameter)
|
||||
if (_timer_list_next_timeout(_soft_timer_list, &next_timeout) != RT_EOK)
|
||||
{
|
||||
/* no software timer exist, suspend self. */
|
||||
rt_thread_suspend(rt_thread_self());
|
||||
rt_thread_suspend_with_flag(rt_thread_self(), RT_UNINTERRUPTIBLE);
|
||||
rt_schedule();
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user