summaryrefslogtreecommitdiff
path: root/components/drivers/src
diff options
context:
space:
mode:
authorguo <[email protected]>2021-09-28 10:36:54 +0800
committerGitHub <[email protected]>2021-09-28 10:36:54 +0800
commit55a302cd092758a44b589d65470a69d9e8ae4ced (patch)
treee60fc53994c426007e9eb4877e5bd123f124ef39 /components/drivers/src
parent00727d6b6db92dc1cf98f028f26fd6168594b905 (diff)
parent00d42ef73cff61ecda7ff006b077a73e1a4ff669 (diff)
Merge branch 'master' into usbh_construct
Diffstat (limited to 'components/drivers/src')
-rw-r--r--components/drivers/src/completion.c29
-rw-r--r--components/drivers/src/dataqueue.c28
-rw-r--r--components/drivers/src/pipe.c36
-rw-r--r--components/drivers/src/ringblk_buf.c48
-rw-r--r--components/drivers/src/ringbuffer.c113
-rw-r--r--components/drivers/src/waitqueue.c6
-rw-r--r--components/drivers/src/workqueue.c393
7 files changed, 391 insertions, 262 deletions
diff --git a/components/drivers/src/completion.c b/components/drivers/src/completion.c
index 9e461e49ce..f13718f9b3 100644
--- a/components/drivers/src/completion.c
+++ b/components/drivers/src/completion.c
@@ -1,11 +1,12 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2012-09-30 Bernard first version.
+ * 2021-08-18 chenyingchun add comments
*/
#include <rthw.h>
@@ -15,6 +16,11 @@
#define RT_COMPLETED 1
#define RT_UNCOMPLETED 0
+/**
+ * @brief This function will initialize a completion object.
+ *
+ * @param completion is a pointer to a completion object.
+ */
void rt_completion_init(struct rt_completion *completion)
{
rt_base_t level;
@@ -27,6 +33,22 @@ void rt_completion_init(struct rt_completion *completion)
}
RTM_EXPORT(rt_completion_init);
+/**
+ * @brief This function will wait for a completion, if the completion is unavailable, the thread shall wait for
+ * the completion up to a specified time.
+ *
+ * @param completion is a pointer to a completion object.
+ *
+ * @param timeout is a timeout period (unit: OS ticks). If the completion is unavailable, the thread will wait for
+ * the completion done up to the amount of time specified by the argument.
+ * NOTE: Generally, we use the macro RT_WAITING_FOREVER to set this parameter, which means that when the
+ * completion is unavailable, the thread will be waitting forever.
+ *
+ * @return Return the operation status. ONLY when the return value is RT_EOK, the operation is successful.
+ * If the return value is any other values, it means that the completion wait failed.
+ *
+ * @warning This function can ONLY be called in the thread context. It MUST NOT be called in interrupt context.
+ */
rt_err_t rt_completion_wait(struct rt_completion *completion,
rt_int32_t timeout)
{
@@ -94,6 +116,11 @@ __exit:
}
RTM_EXPORT(rt_completion_wait);
+/**
+ * @brief This function indicates a completion has done.
+ *
+ * @param completion is a pointer to a completion object.
+ */
void rt_completion_done(struct rt_completion *completion)
{
rt_base_t level;
diff --git a/components/drivers/src/dataqueue.c b/components/drivers/src/dataqueue.c
index 1651417bb9..f32efa1849 100644
--- a/components/drivers/src/dataqueue.c
+++ b/components/drivers/src/dataqueue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -62,7 +62,7 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
rt_ubase_t level;
rt_thread_t thread;
rt_err_t result;
-
+
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
@@ -85,7 +85,7 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
/* reset thread error number */
thread->error = RT_EOK;
-
+
/* suspend thread on the push list */
rt_thread_suspend(thread);
rt_list_insert_before(&(queue->suspended_push_list), &(thread->tlist));
@@ -155,13 +155,13 @@ RTM_EXPORT(rt_data_queue_push);
rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
const void** data_ptr,
- rt_size_t *size,
+ rt_size_t *size,
rt_int32_t timeout)
{
rt_ubase_t level;
rt_thread_t thread;
rt_err_t result;
-
+
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
RT_ASSERT(data_ptr != RT_NULL);
@@ -185,7 +185,7 @@ rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
/* reset thread error number */
thread->error = RT_EOK;
-
+
/* suspend thread on the pop list */
rt_thread_suspend(thread);
rt_list_insert_before(&(queue->suspended_pop_list), &(thread->tlist));
@@ -269,11 +269,11 @@ rt_err_t rt_data_queue_peek(struct rt_data_queue *queue,
rt_size_t *size)
{
rt_ubase_t level;
-
+
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
- if (queue->is_empty)
+ if (queue->is_empty)
{
return -RT_EEMPTY;
}
@@ -293,7 +293,7 @@ void rt_data_queue_reset(struct rt_data_queue *queue)
{
rt_ubase_t level;
struct rt_thread *thread;
-
+
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
@@ -303,9 +303,9 @@ void rt_data_queue_reset(struct rt_data_queue *queue)
queue->put_index = 0;
queue->is_empty = 1;
queue->is_full = 0;
-
+
rt_hw_interrupt_enable(level);
-
+
rt_enter_critical();
/* wakeup all suspend threads */
@@ -375,7 +375,7 @@ rt_err_t rt_data_queue_deinit(struct rt_data_queue *queue)
level = rt_hw_interrupt_disable();
queue->magic = 0;
rt_hw_interrupt_enable(level);
-
+
rt_free(queue->queue);
return RT_EOK;
@@ -386,7 +386,7 @@ rt_uint16_t rt_data_queue_len(struct rt_data_queue *queue)
{
rt_ubase_t level;
rt_int16_t len;
-
+
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
@@ -405,7 +405,7 @@ rt_uint16_t rt_data_queue_len(struct rt_data_queue *queue)
{
len = queue->size + queue->put_index - queue->get_index;
}
-
+
rt_hw_interrupt_enable(level);
return len;
diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c
index bd392cba2b..af90f13c6f 100644
--- a/components/drivers/src/pipe.c
+++ b/components/drivers/src/pipe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -11,11 +11,13 @@
#include <rthw.h>
#include <rtdevice.h>
#include <stdint.h>
+#include <sys/errno.h>
-#if defined(RT_USING_POSIX)
+#ifdef RT_USING_POSIX
#include <dfs_file.h>
#include <dfs_posix.h>
-#include <dfs_poll.h>
+#include <poll.h>
+#include <sys/ioctl.h>
static int pipe_fops_open(struct dfs_fd *fd)
{
@@ -320,7 +322,7 @@ static const struct dfs_file_ops pipe_fops =
};
#endif /* end of RT_USING_POSIX */
-rt_err_t rt_pipe_open (rt_device_t device, rt_uint16_t oflag)
+rt_err_t rt_pipe_open(rt_device_t device, rt_uint16_t oflag)
{
rt_pipe_t *pipe = (rt_pipe_t *)device;
rt_err_t ret = RT_EOK;
@@ -330,7 +332,7 @@ rt_err_t rt_pipe_open (rt_device_t device, rt_uint16_t oflag)
ret = -RT_EINVAL;
goto __exit;
}
-
+
rt_mutex_take(&(pipe->lock), RT_WAITING_FOREVER);
if (pipe->fifo == RT_NULL)
@@ -348,7 +350,7 @@ __exit:
return ret;
}
-rt_err_t rt_pipe_close (rt_device_t device)
+rt_err_t rt_pipe_close(rt_device_t device)
{
rt_pipe_t *pipe = (rt_pipe_t *)device;
@@ -366,7 +368,7 @@ rt_err_t rt_pipe_close (rt_device_t device)
return RT_EOK;
}
-rt_size_t rt_pipe_read (rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count)
+rt_size_t rt_pipe_read(rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count)
{
uint8_t *pbuf;
rt_size_t read_bytes = 0;
@@ -374,7 +376,7 @@ rt_size_t rt_pipe_read (rt_device_t device, rt_off_t pos, void *buffer, rt_siz
if (device == RT_NULL)
{
- rt_set_errno(-EINVAL);
+ rt_set_errno(EINVAL);
return 0;
}
if (count == 0) return 0;
@@ -394,7 +396,7 @@ rt_size_t rt_pipe_read (rt_device_t device, rt_off_t pos, void *buffer, rt_siz
return read_bytes;
}
-rt_size_t rt_pipe_write (rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count)
+rt_size_t rt_pipe_write(rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count)
{
uint8_t *pbuf;
rt_size_t write_bytes = 0;
@@ -402,7 +404,7 @@ rt_size_t rt_pipe_write (rt_device_t device, rt_off_t pos, const void *buffer,
if (device == RT_NULL)
{
- rt_set_errno(-EINVAL);
+ rt_set_errno(EINVAL);
return 0;
}
if (count == 0) return 0;
@@ -428,7 +430,7 @@ rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args)
}
#ifdef RT_USING_DEVICE_OPS
-const static struct rt_device_ops pipe_ops =
+const static struct rt_device_ops pipe_ops =
{
RT_NULL,
rt_pipe_open,
@@ -507,7 +509,7 @@ int rt_pipe_delete(const char *name)
rt_device_unregister(device);
/* close fifo ringbuffer */
- if (pipe->fifo)
+ if (pipe->fifo)
{
rt_ringbuffer_destroy(pipe->fifo);
pipe->fifo = RT_NULL;
@@ -516,12 +518,12 @@ int rt_pipe_delete(const char *name)
}
else
{
- result = -ENODEV;
+ result = -RT_EINVAL;
}
}
else
{
- result = -ENODEV;
+ result = -RT_EINVAL;
}
return result;
@@ -531,8 +533,8 @@ int rt_pipe_delete(const char *name)
int pipe(int fildes[2])
{
rt_pipe_t *pipe;
- char dname[8];
- char dev_name[32];
+ char dname[RT_NAME_MAX];
+ char dev_name[RT_NAME_MAX * 4];
static int pipeno = 0;
rt_snprintf(dname, sizeof(dname), "pipe%d", pipeno++);
@@ -564,7 +566,7 @@ int pipe(int fildes[2])
int mkfifo(const char *path, mode_t mode)
{
rt_pipe_t *pipe;
-
+
pipe = rt_pipe_create(path, PIPE_BUFSZ);
if (pipe == RT_NULL)
{
diff --git a/components/drivers/src/ringblk_buf.c b/components/drivers/src/ringblk_buf.c
index 7d83149c5e..b966da3d36 100644
--- a/components/drivers/src/ringblk_buf.c
+++ b/components/drivers/src/ringblk_buf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -44,32 +44,34 @@ void rt_rbb_init(rt_rbb_t rbb, rt_uint8_t *buf, rt_size_t buf_size, rt_rbb_blk_t
}
RTM_EXPORT(rt_rbb_init);
+#ifdef RT_USING_HEAP
+
/**
* ring block buffer object create
*
* @param buf_size buffer size
* @param blk_max_num max block number
*
- * @return != NULL: ring block buffer object
- * NULL: create failed
+ * @return != RT_NULL: ring block buffer object
+ * RT_NULL: create failed
*/
rt_rbb_t rt_rbb_create(rt_size_t buf_size, rt_size_t blk_max_num)
{
- rt_rbb_t rbb = NULL;
+ rt_rbb_t rbb = RT_NULL;
rt_uint8_t *buf;
rt_rbb_blk_t blk_set;
rbb = (rt_rbb_t)rt_malloc(sizeof(struct rt_rbb));
if (!rbb)
{
- return NULL;
+ return RT_NULL;
}
buf = (rt_uint8_t *)rt_malloc(buf_size);
if (!buf)
{
rt_free(rbb);
- return NULL;
+ return RT_NULL;
}
blk_set = (rt_rbb_blk_t)rt_malloc(sizeof(struct rt_rbb_blk) * blk_max_num);
@@ -77,7 +79,7 @@ rt_rbb_t rt_rbb_create(rt_size_t buf_size, rt_size_t blk_max_num)
{
rt_free(buf);
rt_free(rbb);
- return NULL;
+ return RT_NULL;
}
rt_rbb_init(rbb, buf, buf_size, blk_set, blk_max_num);
@@ -102,6 +104,8 @@ void rt_rbb_destroy(rt_rbb_t rbb)
}
RTM_EXPORT(rt_rbb_destroy);
+#endif
+
static rt_rbb_blk_t find_empty_blk_in_set(rt_rbb_t rbb)
{
rt_size_t i;
@@ -116,7 +120,7 @@ static rt_rbb_blk_t find_empty_blk_in_set(rt_rbb_t rbb)
}
}
- return NULL;
+ return RT_NULL;
}
/**
@@ -127,14 +131,14 @@ static rt_rbb_blk_t find_empty_blk_in_set(rt_rbb_t rbb)
*
* @note When your application need align access, please make the blk_szie is aligned.
*
- * @return != NULL: allocated block
- * NULL: allocate failed
+ * @return != RT_NULL: allocated block
+ * RT_NULL: allocate failed
*/
rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size)
{
rt_base_t level;
rt_size_t empty1 = 0, empty2 = 0;
- rt_rbb_blk_t head, tail, new_rbb = NULL;
+ rt_rbb_blk_t head, tail, new_rbb = RT_NULL;
RT_ASSERT(rbb);
RT_ASSERT(blk_size < (1L << 24));
@@ -178,7 +182,7 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size)
else
{
/* no space */
- new_rbb = NULL;
+ new_rbb = RT_NULL;
}
}
else
@@ -202,7 +206,7 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size)
else
{
/* no space */
- new_rbb = NULL;
+ new_rbb = RT_NULL;
}
}
}
@@ -217,7 +221,7 @@ rt_rbb_blk_t rt_rbb_blk_alloc(rt_rbb_t rbb, rt_size_t blk_size)
}
else
{
- new_rbb = NULL;
+ new_rbb = RT_NULL;
}
rt_hw_interrupt_enable(level);
@@ -245,13 +249,13 @@ RTM_EXPORT(rt_rbb_blk_put);
*
* @param rbb ring block buffer object
*
- * @return != NULL: block
- * NULL: get failed
+ * @return != RT_NULL: block
+ * RT_NULL: get failed
*/
rt_rbb_blk_t rt_rbb_blk_get(rt_rbb_t rbb)
{
rt_base_t level;
- rt_rbb_blk_t block = NULL;
+ rt_rbb_blk_t block = RT_NULL;
rt_slist_t *node;
RT_ASSERT(rbb);
@@ -271,7 +275,7 @@ rt_rbb_blk_t rt_rbb_blk_get(rt_rbb_t rbb)
}
}
/* not found */
- block = NULL;
+ block = RT_NULL;
__exit:
@@ -364,7 +368,7 @@ rt_size_t rt_rbb_blk_queue_get(rt_rbb_t rbb, rt_size_t queue_data_len, rt_rbb_bl
rt_base_t level;
rt_size_t data_total_size = 0;
rt_slist_t *node;
- rt_rbb_blk_t last_block = NULL, block;
+ rt_rbb_blk_t last_block = RT_NULL, block;
RT_ASSERT(rbb);
RT_ASSERT(blk_queue);
@@ -388,7 +392,7 @@ rt_size_t rt_rbb_blk_queue_get(rt_rbb_t rbb, rt_size_t queue_data_len, rt_rbb_bl
else
{
/* the first block must be put status */
- last_block = NULL;
+ last_block = RT_NULL;
continue;
}
}
@@ -493,7 +497,7 @@ rt_size_t rt_rbb_next_blk_queue_len(rt_rbb_t rbb)
rt_base_t level;
rt_size_t data_len = 0;
rt_slist_t *node;
- rt_rbb_blk_t last_block = NULL, block;
+ rt_rbb_blk_t last_block = RT_NULL, block;
RT_ASSERT(rbb);
@@ -510,7 +514,7 @@ rt_size_t rt_rbb_next_blk_queue_len(rt_rbb_t rbb)
if (last_block->status != RT_RBB_BLK_PUT)
{
/* the first block must be put status */
- last_block = NULL;
+ last_block = RT_NULL;
continue;
}
}
diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c
index 88afd19506..3e76b1774a 100644
--- a/components/drivers/src/ringbuffer.c
+++ b/components/drivers/src/ringbuffer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -8,6 +8,8 @@
* 2012-09-30 Bernard first version.
* 2013-05-08 Grissiom reimplement
* 2016-08-18 heyuanjie add interface
+ * 2021-07-20 arminker fix write_index bug in function rt_ringbuffer_put_force
+ * 2021-08-14 Jackistang add comments for function interface.
*/
#include <rtthread.h>
@@ -26,6 +28,13 @@ rt_inline enum rt_ringbuffer_state rt_ringbuffer_status(struct rt_ringbuffer *rb
return RT_RINGBUFFER_HALFFULL;
}
+/**
+ * @brief Initialize the ring buffer object.
+ *
+ * @param rb A pointer to the ring buffer object.
+ * @param pool A pointer to the buffer.
+ * @param size The size of the buffer in bytes.
+ */
void rt_ringbuffer_init(struct rt_ringbuffer *rb,
rt_uint8_t *pool,
rt_int16_t size)
@@ -44,7 +53,13 @@ void rt_ringbuffer_init(struct rt_ringbuffer *rb,
RTM_EXPORT(rt_ringbuffer_init);
/**
- * put a block of data into ring buffer
+ * @brief Put a block of data into the ring buffer. If the capacity of ring buffer is insufficient, it will discard out-of-range data.
+ *
+ * @param rb A pointer to the ring buffer object.
+ * @param ptr A pointer to the data buffer.
+ * @param length The size of data in bytes.
+ *
+ * @return Return the data size we put into the ring buffer.
*/
rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
const rt_uint8_t *ptr,
@@ -91,9 +106,13 @@ rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
RTM_EXPORT(rt_ringbuffer_put);
/**
- * put a block of data into ring buffer
+ * @brief Put a block of data into the ring buffer. If the capacity of ring buffer is insufficient, it will overwrite the existing data in the ring buffer.
*
- * When the buffer is full, it will discard the old data.
+ * @param rb A pointer to the ring buffer object.
+ * @param ptr A pointer to the data buffer.
+ * @param length The size of data in bytes.
+ *
+ * @return Return the data size we put into the ring buffer.
*/
rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,
const rt_uint8_t *ptr,
@@ -138,7 +157,8 @@ rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,
if (length > space_length)
{
- rb->read_mirror = ~rb->read_mirror;
+ if (rb->write_index <= rb->read_index)
+ rb->read_mirror = ~rb->read_mirror;
rb->read_index = rb->write_index;
}
@@ -147,7 +167,13 @@ rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,
RTM_EXPORT(rt_ringbuffer_put_force);
/**
- * get data from ring buffer
+ * @brief Get data from the ring buffer.
+ *
+ * @param rb A pointer to the ring buffer.
+ * @param ptr A pointer to the data buffer.
+ * @param length The size of the data we want to read from the ring buffer.
+ *
+ * @return Return the data size we read from the ring buffer.
*/
rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
rt_uint8_t *ptr,
@@ -194,7 +220,14 @@ rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
RTM_EXPORT(rt_ringbuffer_get);
/**
- * peak data from ring buffer
+ * @brief Get the first readable byte of the ring buffer.
+ *
+ * @param rb A pointer to the ringbuffer.
+ * @param ptr When this function return, *ptr is a pointer to the first readable byte of the ring buffer.
+ *
+ * @note It is recommended to read only one byte, otherwise it may cause buffer overflow.
+ *
+ * @return Return the size of the ring buffer.
*/
rt_size_t rt_ringbuffer_peak(struct rt_ringbuffer *rb, rt_uint8_t **ptr)
{
@@ -228,7 +261,12 @@ rt_size_t rt_ringbuffer_peak(struct rt_ringbuffer *rb, rt_uint8_t **ptr)
RTM_EXPORT(rt_ringbuffer_peak);
/**
- * put a character into ring buffer
+ * @brief Put a byte into the ring buffer. If ring buffer is full, this operation will fail.
+ *
+ * @param rb A pointer to the ring buffer object.
+ * @param ch A byte put into the ring buffer.
+ *
+ * @return Return the data size we put into the ring buffer. The ring buffer is full if returns 0. Otherwise, it will return 1.
*/
rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
{
@@ -256,9 +294,12 @@ rt_size_t rt_ringbuffer_putchar(struct rt_ringbuffer *rb, const rt_uint8_t ch)
RTM_EXPORT(rt_ringbuffer_putchar);
/**
- * put a character into ring buffer
+ * @brief Put a byte into the ring buffer. If ring buffer is full, it will discard an old data and put into a new data.
+ *
+ * @param rb A pointer to the ring buffer object.
+ * @param ch A byte put into the ring buffer.
*
- * When the buffer is full, it will discard one old data.
+ * @return Return the data size we put into the ring buffer. Always return 1.
*/
rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb, const rt_uint8_t ch)
{
@@ -293,7 +334,13 @@ rt_size_t rt_ringbuffer_putchar_force(struct rt_ringbuffer *rb, const rt_uint8_t
RTM_EXPORT(rt_ringbuffer_putchar_force);
/**
- * get a character from a ringbuffer
+ * @brief Get a byte from the ring buffer.
+ *
+ * @param rb The pointer to the ring buffer object.
+ * @param ch A pointer to the buffer, used to store one byte.
+ *
+ * @return 0 The ring buffer is empty.
+ * @return 1 Success
*/
rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
{
@@ -303,7 +350,7 @@ rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
if (!rt_ringbuffer_data_len(rb))
return 0;
- /* put character */
+ /* put byte */
*ch = rb->buffer_ptr[rb->read_index];
if (rb->read_index == rb->buffer_size-1)
@@ -320,8 +367,12 @@ rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
}
RTM_EXPORT(rt_ringbuffer_getchar);
-/**
- * get the size of data in rb
+/**
+ * @brief Get the size of data in the ring buffer in bytes.
+ *
+ * @param rb The pointer to the ring buffer object.
+ *
+ * @return Return the size of data in the ring buffer in bytes.
*/
rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
{
@@ -333,16 +384,22 @@ rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
return rb->buffer_size;
case RT_RINGBUFFER_HALFFULL:
default:
- if (rb->write_index > rb->read_index)
- return rb->write_index - rb->read_index;
+ {
+ rt_size_t wi = rb->write_index, ri = rb->read_index;
+
+ if (wi > ri)
+ return wi - ri;
else
- return rb->buffer_size - (rb->read_index - rb->write_index);
- };
+ return rb->buffer_size - (ri - wi);
+ }
+ }
}
RTM_EXPORT(rt_ringbuffer_data_len);
-/**
- * empty the rb
+/**
+ * @brief Reset the ring buffer object, and clear all contents in the buffer.
+ *
+ * @param rb A pointer to the ring buffer object.
*/
void rt_ringbuffer_reset(struct rt_ringbuffer *rb)
{
@@ -357,12 +414,19 @@ RTM_EXPORT(rt_ringbuffer_reset);
#ifdef RT_USING_HEAP
-struct rt_ringbuffer* rt_ringbuffer_create(rt_uint16_t size)
+/**
+ * @brief Create a ring buffer object with a given size.
+ *
+ * @param size The size of the buffer in bytes.
+ *
+ * @return Return a pointer to ring buffer object. When the return value is RT_NULL, it means this creation failed.
+ */
+struct rt_ringbuffer *rt_ringbuffer_create(rt_uint16_t size)
{
struct rt_ringbuffer *rb;
rt_uint8_t *pool;
- RT_ASSERT(size > 0);
+ RT_ASSERT(size > 0);
size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
@@ -384,6 +448,11 @@ exit:
}
RTM_EXPORT(rt_ringbuffer_create);
+/**
+ * @brief Destroy the ring buffer object, which is created by rt_ringbuffer_create() .
+ *
+ * @param rb A pointer to the ring buffer object.
+ */
void rt_ringbuffer_destroy(struct rt_ringbuffer *rb)
{
RT_ASSERT(rb != RT_NULL);
diff --git a/components/drivers/src/waitqueue.c b/components/drivers/src/waitqueue.c
index 02240edbdf..7fe75a51ba 100644
--- a/components/drivers/src/waitqueue.c
+++ b/components/drivers/src/waitqueue.c
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
- * 2018/06/26 Bernard Fix the wait queue issue when wakeup a soon
+ * 2018/06/26 Bernard Fix the wait queue issue when wakeup a soon
* to blocked thread.
*/
@@ -121,7 +121,7 @@ int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec)
level = rt_hw_interrupt_disable();
__exit_wakeup:
- queue->flag = 0;
+ queue->flag = RT_WQ_FLAG_CLEAN;
rt_hw_interrupt_enable(level);
rt_wqueue_remove(&__wait);
diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c
index 2b5630d8d0..b5d803472b 100644
--- a/components/drivers/src/workqueue.c
+++ b/components/drivers/src/workqueue.c
@@ -1,11 +1,13 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
- * 2017-02-27 bernard fix the re-work issue.
+ * 2017-02-27 Bernard fix the re-work issue.
+ * 2021-08-01 Meco Man remove rt_delayed_work_init()
+ * 2021-08-14 Jackistang add comments for function interface.
*/
#include <rthw.h>
@@ -58,15 +60,17 @@ static void _workqueue_thread_entry(void *parameter)
while (1)
{
+ level = rt_hw_interrupt_disable();
if (rt_list_isempty(&(queue->work_list)))
{
/* no software timer exist, suspend self. */
rt_thread_suspend(rt_thread_self());
+ rt_hw_interrupt_enable(level);
rt_schedule();
+ continue;
}
/* we have work to do with. */
- level = rt_hw_interrupt_disable();
work = rt_list_entry(queue->work_list.next, struct rt_work, list);
rt_list_remove(&(work->list));
queue->work_current = work;
@@ -76,177 +80,145 @@ static void _workqueue_thread_entry(void *parameter)
/* do work */
work->work_func(work, work->work_data);
- level = rt_hw_interrupt_disable();
/* clean current work */
queue->work_current = RT_NULL;
- rt_hw_interrupt_enable(level);
/* ack work completion */
_workqueue_work_completion(queue);
}
}
-static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work)
+static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue,
+ struct rt_work *work, rt_tick_t ticks)
{
rt_base_t level;
+ rt_err_t err;
level = rt_hw_interrupt_disable();
- if (work->flags & RT_WORK_STATE_PENDING)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EBUSY;
- }
-
- if (queue->work_current == work)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EBUSY;
- }
-
- /* NOTE: the work MUST be initialized firstly */
+ /* remove list */
rt_list_remove(&(work->list));
-
- rt_list_insert_after(queue->work_list.prev, &(work->list));
- work->flags |= RT_WORK_STATE_PENDING;
-
- /* whether the workqueue is doing work */
- if (queue->work_current == RT_NULL)
+ work->flags &= ~RT_WORK_STATE_PENDING;
+ /* */
+ if (ticks == 0)
{
- rt_hw_interrupt_enable(level);
- /* resume work thread */
- rt_thread_resume(queue->work_thread);
- rt_schedule();
+ if (queue->work_current != work)
+ {
+ rt_list_insert_after(queue->work_list.prev, &(work->list));
+ work->flags |= RT_WORK_STATE_PENDING;
+ work->workqueue = queue;
+ err = RT_EOK;
+ }
+ else
+ {
+ err = -RT_EBUSY;
+ }
+
+ /* whether the workqueue is doing work */
+ if (queue->work_current == RT_NULL &&
+ ((queue->work_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
+ {
+ /* resume work thread */
+ rt_thread_resume(queue->work_thread);
+ rt_hw_interrupt_enable(level);
+ rt_schedule();
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
+ return err;
}
- else
+ else if (ticks < RT_TICK_MAX / 2)
{
+ /* Timer started */
+ if (work->flags & RT_WORK_STATE_SUBMITTING)
+ {
+ rt_timer_stop(&work->timer);
+ rt_timer_control(&work->timer, RT_TIMER_CTRL_SET_TIME, &ticks);
+ }
+ else
+ {
+ rt_timer_init(&(work->timer), "work", _delayed_work_timeout_handler,
+ work, ticks, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
+ work->flags |= RT_WORK_STATE_SUBMITTING;
+ }
+ work->workqueue = queue;
+ /* insert delay work list */
+ rt_list_insert_after(queue->delayed_list.prev, &(work->list));
rt_hw_interrupt_enable(level);
+ rt_timer_start(&(work->timer));
+ return RT_EOK;
}
-
- return RT_EOK;
+ rt_hw_interrupt_enable(level);
+ return -RT_ERROR;
}
static rt_err_t _workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work)
{
rt_base_t level;
+ rt_err_t err;
level = rt_hw_interrupt_disable();
- if (queue->work_current == work)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EBUSY;
- }
rt_list_remove(&(work->list));
work->flags &= ~RT_WORK_STATE_PENDING;
- rt_hw_interrupt_enable(level);
-
- return RT_EOK;
-}
-
-static rt_err_t _workqueue_cancel_delayed_work(struct rt_work *work)
-{
- rt_base_t level;
- int ret = RT_EOK;
-
- if (!work->workqueue)
- {
- ret = -EINVAL;
- goto __exit;
- }
-
- if (work->flags & RT_WORK_STATE_PENDING)
- {
- /* Remove from the queue if already submitted */
- ret = _workqueue_cancel_work(work->workqueue, work);
- if (ret)
- {
- goto __exit;
- }
- }
- else
+ /* Timer started */
+ if (work->flags & RT_WORK_STATE_SUBMITTING)
{
- if (work->flags & RT_WORK_STATE_SUBMITTING)
- {
- level = rt_hw_interrupt_disable();
- rt_timer_stop(&(work->timer));
- rt_timer_detach(&(work->timer));
- work->flags &= ~RT_WORK_STATE_SUBMITTING;
- rt_hw_interrupt_enable(level);
- }
+ rt_timer_stop(&(work->timer));
+ rt_timer_detach(&(work->timer));
+ work->flags &= ~RT_WORK_STATE_SUBMITTING;
}
-
- level = rt_hw_interrupt_disable();
- /* Detach from workqueue */
+ err = queue->work_current != work ? RT_EOK : -RT_EBUSY;
work->workqueue = RT_NULL;
- work->flags &= ~(RT_WORK_STATE_PENDING);
rt_hw_interrupt_enable(level);
-
-__exit:
- return ret;
+ return err;
}
-static rt_err_t _workqueue_submit_delayed_work(struct rt_workqueue *queue,
- struct rt_work *work, rt_tick_t ticks)
+static void _delayed_work_timeout_handler(void *parameter)
{
+ struct rt_work *work;
+ struct rt_workqueue *queue;
rt_base_t level;
- rt_err_t ret = RT_EOK;
- /* Work cannot be active in multiple queues */
- if (work->workqueue && work->workqueue != queue)
- {
- ret = -RT_EINVAL;
- goto __exit;
- }
+ work = (struct rt_work *)parameter;
+ queue = work->workqueue;
+ RT_ASSERT(queue != RT_NULL);
- /* Cancel if work has been submitted */
- if (work->workqueue == queue)
+ level = rt_hw_interrupt_disable();
+ rt_timer_detach(&(work->timer));
+ work->flags &= ~RT_WORK_STATE_SUBMITTING;
+ /* remove delay list */
+ rt_list_remove(&(work->list));
+ /* insert work queue */
+ if (queue->work_current != work)
{
- ret = _workqueue_cancel_delayed_work(work);
- if (ret < 0)
- {
- goto __exit;
- }
+ rt_list_insert_after(queue->work_list.prev, &(work->list));
+ work->flags |= RT_WORK_STATE_PENDING;
}
-
- level = rt_hw_interrupt_disable();
- /* Attach workqueue so the timeout callback can submit it */
- work->workqueue = queue;
- rt_hw_interrupt_enable(level);
-
- if (!ticks)
+ /* whether the workqueue is doing work */
+ if (queue->work_current == RT_NULL &&
+ ((queue->work_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
{
- /* Submit work if no ticks is 0 */
- ret = _workqueue_submit_work(work->workqueue, work);
+ /* resume work thread */
+ rt_thread_resume(queue->work_thread);
+ rt_hw_interrupt_enable(level);
+ rt_schedule();
}
else
{
- level = rt_hw_interrupt_disable();
- /* Add timeout */
- work->flags |= RT_WORK_STATE_SUBMITTING;
- rt_timer_init(&(work->timer), "work", _delayed_work_timeout_handler, work, ticks,
- RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
rt_hw_interrupt_enable(level);
- rt_timer_start(&(work->timer));
}
-
-__exit:
- return ret;
-}
-
-static void _delayed_work_timeout_handler(void *parameter)
-{
- struct rt_work *delayed_work;
- rt_base_t level;
-
- delayed_work = (struct rt_work *)parameter;
- level = rt_hw_interrupt_disable();
- rt_timer_stop(&(delayed_work->timer));
- rt_timer_detach(&(delayed_work->timer));
- delayed_work->flags &= ~RT_WORK_STATE_SUBMITTING;
- delayed_work->type &= ~RT_WORK_TYPE_DELAYED;
- rt_hw_interrupt_enable(level);
- _workqueue_submit_work(delayed_work->workqueue, delayed_work);
}
+/**
+ * @brief Create a work queue with a thread inside.
+ *
+ * @param name The name of the work queue thread.
+ * @param stack_size The stack size of the work queue thread.
+ * @param priority The priority of the work queue thread.
+ *
+ * @return Return A pointer to the workqueue object. It will return RT_NULL if failed.
+ */
struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_size, rt_uint8_t priority)
{
struct rt_workqueue *queue = RT_NULL;
@@ -256,6 +228,7 @@ struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_siz
{
/* initialize work list */
rt_list_init(&(queue->work_list));
+ rt_list_init(&(queue->delayed_list));
queue->work_current = RT_NULL;
rt_sem_init(&(queue->sem), "wqueue", 0, RT_IPC_FLAG_FIFO);
@@ -273,44 +246,69 @@ struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_siz
return queue;
}
+/**
+ * @brief Destroy a work queue.
+ *
+ * @param queue A pointer to the workqueue object.
+ *
+ * @return RT_EOK Success.
+ */
rt_err_t rt_workqueue_destroy(struct rt_workqueue *queue)
{
RT_ASSERT(queue != RT_NULL);
+ rt_workqueue_cancel_all_work(queue);
rt_thread_delete(queue->work_thread);
+ rt_sem_detach(&(queue->sem));
RT_KERNEL_FREE(queue);
return RT_EOK;
}
+/**
+ * @brief Submit a work item to the work queue without delay.
+ *
+ * @param queue A pointer to the workqueue object.
+ * @param work A pointer to the work item object.
+ *
+ * @return RT_EOK Success.
+ * @return -RT_EBUSY This work item is executing.
+ */
rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work)
{
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(work != RT_NULL);
- return _workqueue_submit_work(queue, work);
+ return _workqueue_submit_work(queue, work, 0);
}
+/**
+ * @brief Submit a work item to the work queue with a delay.
+ *
+ * @param queue A pointer to the workqueue object.
+ * @param work A pointer to the work item object.
+ * @param time The delay time (unit: OS ticks) for the work item to be submitted to the work queue.
+ *
+ * @return RT_EOK Success.
+ * @return -RT_EBUSY This work item is executing.
+ * @return -RT_ERROR The time parameter is invalid.
+ */
rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t time)
{
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(work != RT_NULL);
- if (time > 0)
- {
- work->type |= RT_WORK_TYPE_DELAYED;
- }
-
- if (work->type & RT_WORK_TYPE_DELAYED)
- {
- return _workqueue_submit_delayed_work(queue, work, time);
- }
- else
- {
- return _workqueue_submit_work(queue, work);
- }
+ return _workqueue_submit_work(queue, work, time);
}
+/**
+ * @brief Submit a work item to the work queue without delay. This work item will be executed after the current work item.
+ *
+ * @param queue A pointer to the workqueue object.
+ * @param work A pointer to the work item object.
+ *
+ * @return RT_EOK Success.
+ */
rt_err_t rt_workqueue_critical_work(struct rt_workqueue *queue, struct rt_work *work)
{
rt_base_t level;
@@ -318,51 +316,55 @@ rt_err_t rt_workqueue_critical_work(struct rt_workqueue *queue, struct rt_work *
RT_ASSERT(work != RT_NULL);
level = rt_hw_interrupt_disable();
- if (queue->work_current == work)
- {
- rt_hw_interrupt_enable(level);
- return -RT_EBUSY;
- }
-
/* NOTE: the work MUST be initialized firstly */
rt_list_remove(&(work->list));
-
- rt_list_insert_after(queue->work_list.prev, &(work->list));
- if (queue->work_current == RT_NULL)
+ rt_list_insert_after(&queue->work_list, &(work->list));
+ /* whether the workqueue is doing work */
+ if (queue->work_current == RT_NULL &&
+ ((queue->work_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
{
- rt_hw_interrupt_enable(level);
/* resume work thread */
rt_thread_resume(queue->work_thread);
+ rt_hw_interrupt_enable(level);
rt_schedule();
}
- else rt_hw_interrupt_enable(level);
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
return RT_EOK;
}
+/**
+ * @brief Cancel a work item in the work queue.
+ *
+ * @param queue A pointer to the workqueue object.
+ * @param work A pointer to the work item object.
+ *
+ * @return RT_EOK Success.
+ * @return -RT_EBUSY This work item is executing.
+ */
rt_err_t rt_workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work)
{
- RT_ASSERT(queue != RT_NULL);
RT_ASSERT(work != RT_NULL);
-
- if (work->type & RT_WORK_TYPE_DELAYED)
- {
- return _workqueue_cancel_delayed_work(work);
- }
- else
- {
- return _workqueue_cancel_work(queue, work);
- }
+ RT_ASSERT(queue != RT_NULL);
+ return _workqueue_cancel_work(queue, work);
}
+/**
+ * @brief Cancel a work item in the work queue. If the work item is executing, this function will block until it is done.
+ *
+ * @param queue A pointer to the workqueue object.
+ * @param work A pointer to the work item object.
+ *
+ * @return RT_EOK Success.
+ */
rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_work *work)
{
- rt_base_t level;
-
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(work != RT_NULL);
- level = rt_hw_interrupt_disable();
if (queue->work_current == work) /* it's current work in the queue */
{
/* wait for work completion */
@@ -370,60 +372,85 @@ rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_wor
}
else
{
- rt_list_remove(&(work->list));
+ _workqueue_cancel_work(queue, work);
}
- work->flags &= ~RT_WORK_STATE_PENDING;
- rt_hw_interrupt_enable(level);
return RT_EOK;
}
+/**
+ * @brief This function will cancel all work items in work queue.
+ *
+ * @param queue A pointer to the workqueue object.
+ *
+ * @return RT_EOK Success.
+ */
rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue *queue)
{
- struct rt_list_node *node, *next;
+ struct rt_work *work;
+
RT_ASSERT(queue != RT_NULL);
+ /* cancel work */
rt_enter_critical();
- for (node = queue->work_list.next; node != &(queue->work_list); node = next)
+ while (rt_list_isempty(&queue->work_list) == RT_FALSE)
+ {
+ work = rt_list_first_entry(&queue->work_list, struct rt_work, list);
+ _workqueue_cancel_work(queue, work);
+ }
+ /* cancel delay work */
+ while (rt_list_isempty(&queue->delayed_list) == RT_FALSE)
{
- next = node->next;
- rt_list_remove(node);
+ work = rt_list_first_entry(&queue->delayed_list, struct rt_work, list);
+ _workqueue_cancel_work(queue, work);
}
rt_exit_critical();
return RT_EOK;
}
-void rt_delayed_work_init(struct rt_delayed_work *work, void (*work_func)(struct rt_work *work,
- void *work_data), void *work_data)
-{
- rt_work_init(&work->work, work_func, work_data);
-}
-
#ifdef RT_USING_SYSTEM_WORKQUEUE
static struct rt_workqueue *sys_workq;
+/**
+ * @brief Submit a work item to the system work queue with a delay.
+ *
+ * @param work A pointer to the work item object.
+ * @param time The delay time (unit: OS ticks) for the work item to be submitted to the work queue.
+ *
+ * @return RT_EOK Success.
+ * @return -RT_EBUSY This work item is executing.
+ * @return -RT_ERROR The time parameter is invalid.
+ */
rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t time)
{
return rt_workqueue_submit_work(sys_workq, work, time);
}
+/**
+ * @brief Cancel a work item in the system work queue.
+ *
+ * @param work A pointer to the work item object.
+ *
+ * @return RT_EOK Success.
+ * @return -RT_EBUSY This work item is executing.
+ */
rt_err_t rt_work_cancel(struct rt_work *work)
{
return rt_workqueue_cancel_work(sys_workq, work);
}
-int rt_work_sys_workqueue_init(void)
+static int rt_work_sys_workqueue_init(void)
{
if (sys_workq != RT_NULL)
- return 0;
+ return RT_EOK;
sys_workq = rt_workqueue_create("sys_work", RT_SYSTEM_WORKQUEUE_STACKSIZE,
RT_SYSTEM_WORKQUEUE_PRIORITY);
+ RT_ASSERT(sys_workq != RT_NULL);
return RT_EOK;
}
-
INIT_PREV_EXPORT(rt_work_sys_workqueue_init);
-#endif
-#endif
+#endif /* RT_USING_SYSTEM_WORKQUEUE */
+#endif /* RT_USING_HEAP */