Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2301_76519099
rt-thread
提交
dff8a2c5
R
rt-thread
项目概览
2301_76519099
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
3
Star
1
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
dff8a2c5
编写于
9月 11, 2018
作者:
armink_ztl
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[DeviceDriver] Add rbb (ring block buffer) data structure.
上级
7d3f38e4
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
991 addition
and
0 deletion
+991
-0
components/drivers/include/ipc/ringblk_buf.h
components/drivers/include/ipc/ringblk_buf.h
+115
-0
components/drivers/include/rtdevice.h
components/drivers/include/rtdevice.h
+1
-0
components/drivers/src/ringblk_buf.c
components/drivers/src/ringblk_buf.c
+534
-0
examples/test/rbb_test.c
examples/test/rbb_test.c
+341
-0
未找到文件。
components/drivers/include/ipc/ringblk_buf.h
0 → 100644
浏览文件 @
dff8a2c5
/*
* File : ringblk_buf.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2018-08-25 armink the first version
*/
#ifndef _RINGBLK_BUF_H_
#define _RINGBLK_BUF_H_
/*
* Introduction:
* The rbb is the ring buffer which is composed with many blocks. It is different from the ring buffer.
* The ring buffer is only composed with chars. The rbb put and get supported zero copies. So the rbb
* is very suitable for put block and get block by a certain order. Such as DMA block transmit,
* communicate frame send/recv, and so on.
*/
#ifdef __cplusplus
extern
"C"
{
#endif
enum
rt_rbb_status
{
/* unused status when first initialize or after blk_free() */
RT_RBB_BLK_UNUSED
,
/* initialized status after blk_alloc() */
RT_RBB_BLK_INITED
,
/* put status after blk_put() */
RT_RBB_BLK_PUT
,
/* get status after blk_get() */
RT_RBB_BLK_GET
,
};
typedef
enum
rt_rbb_status
rt_rbb_status_t
;
/**
* the block of rbb
*/
struct
rt_rbb_blk
{
rt_rbb_status_t
status
:
8
;
/* less then 2^24 */
rt_size_t
size
:
24
;
rt_uint8_t
*
buf
;
rt_slist_t
list
;
};
typedef
struct
rt_rbb_blk
*
rt_rbb_blk_t
;
/**
* Rbb block queue: the blocks (from block1->buf to blockn->buf) memory which on this queue is continuous.
*/
struct
rt_rbb_blk_queue
{
rt_rbb_blk_t
blocks
;
rt_size_t
blk_num
;
};
typedef
struct
rt_rbb_blk_queue
*
rt_rbb_blk_queue_t
;
/**
* ring block buffer
*/
struct
rt_rbb
{
rt_uint8_t
*
buf
;
rt_size_t
buf_size
;
/* all of blocks */
rt_rbb_blk_t
blk_set
;
rt_size_t
blk_max_num
;
/* saved the initialized and put status blocks */
rt_slist_t
blk_list
;
};
typedef
struct
rt_rbb
*
rt_rbb_t
;
/* rbb (ring block buffer) API */
void
rt_rbb_init
(
rt_rbb_t
rbb
,
rt_uint8_t
*
buf
,
rt_size_t
buf_size
,
rt_rbb_blk_t
block_set
,
rt_size_t
blk_max_num
);
rt_rbb_t
rt_rbb_create
(
rt_size_t
buf_size
,
rt_size_t
blk_max_num
);
void
rt_rbb_destroy
(
rt_rbb_t
rbb
);
rt_size_t
rt_rbb_get_buf_size
(
rt_rbb_t
rbb
);
/* rbb block API */
rt_rbb_blk_t
rt_rbb_blk_alloc
(
rt_rbb_t
rbb
,
rt_size_t
blk_size
);
void
rt_rbb_blk_put
(
rt_rbb_blk_t
block
);
rt_rbb_blk_t
rt_rbb_blk_get
(
rt_rbb_t
rbb
);
void
rt_rbb_blk_free
(
rt_rbb_t
rbb
,
rt_rbb_blk_t
block
);
/* rbb block queue API */
rt_size_t
rt_rbb_blk_queue_get
(
rt_rbb_t
rbb
,
rt_size_t
queue_data_len
,
rt_rbb_blk_queue_t
blk_queue
);
rt_size_t
rt_rbb_blk_queue_len
(
rt_rbb_blk_queue_t
blk_queue
);
rt_uint8_t
*
rt_rbb_blk_queue_buf
(
rt_rbb_blk_queue_t
blk_queue
);
void
rt_rbb_blk_queue_free
(
rt_rbb_t
rbb
,
rt_rbb_blk_queue_t
blk_queue
);
rt_size_t
rt_rbb_next_blk_queue_len
(
rt_rbb_t
rbb
);
#ifdef __cplusplus
}
#endif
#endif
/* _RINGBLK_BUF_H_ */
components/drivers/include/rtdevice.h
浏览文件 @
dff8a2c5
...
...
@@ -35,6 +35,7 @@
#include "ipc/waitqueue.h"
#include "ipc/pipe.h"
#include "ipc/poll.h"
#include "ipc/ringblk_buf.h"
#ifdef __cplusplus
extern
"C"
{
...
...
components/drivers/src/ringblk_buf.c
0 → 100644
浏览文件 @
dff8a2c5
/*
* File : ringblk_buf.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2018-08-25 armink the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
/**
* ring block buffer object initialization
*
* @param rbb ring block buffer object
* @param buf buffer
* @param buf_size buffer size
* @param block_set
* @param blk_max_num
*/
void
rt_rbb_init
(
rt_rbb_t
rbb
,
rt_uint8_t
*
buf
,
rt_size_t
buf_size
,
rt_rbb_blk_t
block_set
,
rt_size_t
blk_max_num
)
{
rt_size_t
i
;
RT_ASSERT
(
rbb
);
RT_ASSERT
(
buf
);
RT_ASSERT
(
block_set
);
rbb
->
buf
=
buf
;
rbb
->
buf_size
=
buf_size
;
rbb
->
blk_set
=
block_set
;
rbb
->
blk_max_num
=
blk_max_num
;
rt_slist_init
(
&
rbb
->
blk_list
);
/* initialize block status */
for
(
i
=
0
;
i
<
blk_max_num
;
i
++
)
{
block_set
[
i
].
status
=
RT_RBB_BLK_UNUSED
;
}
}
RTM_EXPORT
(
rt_rbb_init
);
/**
* 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
*/
rt_rbb_t
rt_rbb_create
(
rt_size_t
buf_size
,
rt_size_t
blk_max_num
)
{
rt_rbb_t
rbb
=
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
;
}
buf
=
(
rt_uint8_t
*
)
rt_malloc
(
buf_size
);
if
(
!
buf
)
{
rt_free
(
rbb
);
return
NULL
;
}
blk_set
=
(
rt_rbb_blk_t
)
rt_malloc
(
sizeof
(
struct
rt_rbb_blk
)
*
blk_max_num
);
if
(
!
blk_set
)
{
rt_free
(
buf
);
rt_free
(
rbb
);
return
NULL
;
}
rt_rbb_init
(
rbb
,
buf
,
buf_size
,
blk_set
,
blk_max_num
);
return
rbb
;
}
RTM_EXPORT
(
rt_rbb_create
);
/**
* ring block buffer object destroy
*
* @param rbb ring block buffer object
*/
void
rt_rbb_destroy
(
rt_rbb_t
rbb
)
{
RT_ASSERT
(
rbb
);
rt_free
(
rbb
);
rt_free
(
rbb
->
buf
);
rt_free
(
rbb
->
blk_set
);
}
RTM_EXPORT
(
rt_rbb_destroy
);
static
rt_rbb_blk_t
find_empty_blk_in_set
(
rt_rbb_t
rbb
)
{
rt_size_t
i
;
RT_ASSERT
(
rbb
);
for
(
i
=
0
;
i
<
rbb
->
blk_max_num
;
i
++
)
{
if
(
rbb
->
blk_set
[
i
].
status
==
RT_RBB_BLK_UNUSED
)
{
return
&
rbb
->
blk_set
[
i
];
}
}
return
NULL
;
}
/**
* Allocate a block by given size. The block will add to blk_list when allocate success.
*
* @param rbb ring block buffer object
* @param blk_size block size
*
* @return != NULL: allocated block
* 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
=
NULL
;
RT_ASSERT
(
rbb
);
RT_ASSERT
(
blk_size
<
1L
<<
24
);
level
=
rt_hw_interrupt_disable
();
new
=
find_empty_blk_in_set
(
rbb
);
if
(
rt_slist_len
(
&
rbb
->
blk_list
)
<
rbb
->
blk_max_num
&&
new
)
{
if
(
rt_slist_len
(
&
rbb
->
blk_list
)
>
0
)
{
head
=
rt_slist_first_entry
(
&
rbb
->
blk_list
,
struct
rt_rbb_blk
,
list
);
tail
=
rt_slist_tail_entry
(
&
rbb
->
blk_list
,
struct
rt_rbb_blk
,
list
);
if
(
head
->
buf
<=
tail
->
buf
)
{
/**
* head tail
* +--------------------------------------+-----------------+------------------+
* | empty2 | block1 | block2 | block3 | empty1 |
* +--------------------------------------+-----------------+------------------+
* rbb->buf
*/
empty1
=
(
rbb
->
buf
+
rbb
->
buf_size
)
-
(
tail
->
buf
+
tail
->
size
);
empty2
=
head
->
buf
-
rbb
->
buf
;
if
(
empty1
>=
blk_size
)
{
rt_slist_append
(
&
rbb
->
blk_list
,
&
new
->
list
);
new
->
status
=
RT_RBB_BLK_INITED
;
new
->
buf
=
tail
->
buf
+
tail
->
size
;
new
->
size
=
blk_size
;
}
else
if
(
empty2
>=
blk_size
)
{
rt_slist_append
(
&
rbb
->
blk_list
,
&
new
->
list
);
new
->
status
=
RT_RBB_BLK_INITED
;
new
->
buf
=
rbb
->
buf
;
new
->
size
=
blk_size
;
}
else
{
/* no space */
new
=
NULL
;
}
}
else
{
/**
* tail head
* +----------------+-------------------------------------+--------+-----------+
* | block3 | empty1 | block1 | block2 |
* +----------------+-------------------------------------+--------+-----------+
* rbb->buf
*/
empty1
=
head
->
buf
-
(
tail
->
buf
+
tail
->
size
);
if
(
empty1
>=
blk_size
)
{
rt_slist_append
(
&
rbb
->
blk_list
,
&
new
->
list
);
new
->
status
=
RT_RBB_BLK_INITED
;
new
->
buf
=
tail
->
buf
+
tail
->
size
;
new
->
size
=
blk_size
;
}
else
{
/* no space */
new
=
NULL
;
}
}
}
else
{
/* the list is empty */
rt_slist_append
(
&
rbb
->
blk_list
,
&
new
->
list
);
new
->
status
=
RT_RBB_BLK_INITED
;
new
->
buf
=
rbb
->
buf
;
new
->
size
=
blk_size
;
}
}
else
{
new
=
NULL
;
}
rt_hw_interrupt_enable
(
level
);
return
new
;
}
RTM_EXPORT
(
rt_rbb_blk_alloc
);
/**
* put a block to ring block buffer object
*
* @param block the block
*/
void
rt_rbb_blk_put
(
rt_rbb_blk_t
block
)
{
RT_ASSERT
(
block
);
RT_ASSERT
(
block
->
status
==
RT_RBB_BLK_INITED
);
block
->
status
=
RT_RBB_BLK_PUT
;
}
RTM_EXPORT
(
rt_rbb_blk_put
);
/**
* get a block from the ring block buffer object
*
* @param rbb ring block buffer object
*
* @return != NULL: block
* 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_slist_t
*
node
;
RT_ASSERT
(
rbb
);
if
(
rt_slist_isempty
(
&
rbb
->
blk_list
))
return
0
;
level
=
rt_hw_interrupt_disable
();
for
(
node
=
rt_slist_first
(
&
rbb
->
blk_list
);
node
;
node
=
rt_slist_next
(
node
))
{
block
=
rt_slist_entry
(
node
,
struct
rt_rbb_blk
,
list
);
if
(
block
->
status
==
RT_RBB_BLK_PUT
)
{
block
->
status
=
RT_RBB_BLK_GET
;
goto
__exit
;
}
}
/* not found */
block
=
NULL
;
__exit:
rt_hw_interrupt_enable
(
level
);
return
block
;
}
RTM_EXPORT
(
rt_rbb_blk_get
);
/**
* free the block
*
* @param rbb ring block buffer object
* @param block the block
*/
void
rt_rbb_blk_free
(
rt_rbb_t
rbb
,
rt_rbb_blk_t
block
)
{
rt_base_t
level
;
RT_ASSERT
(
rbb
);
RT_ASSERT
(
block
);
RT_ASSERT
(
block
->
status
!=
RT_RBB_BLK_UNUSED
);
level
=
rt_hw_interrupt_disable
();
/* remove it on rbb block list */
rt_slist_remove
(
&
rbb
->
blk_list
,
&
block
->
list
);
block
->
status
=
RT_RBB_BLK_UNUSED
;
rt_hw_interrupt_enable
(
level
);
}
RTM_EXPORT
(
rt_rbb_blk_free
);
/**
* get a continuous block to queue by given size
*
* tail head
* +------------------+---------------+--------+----------+--------+
* | block3 | empty1 | block1 | block2 |fragment|
* +------------------+------------------------+----------+--------+
* |<-- return_size -->| |
* |<--- queue_data_len --->|
*
* tail head
* +------------------+---------------+--------+----------+--------+
* | block3 | empty1 | block1 | block2 |fragment|
* +------------------+------------------------+----------+--------+
* |<-- return_size -->| out of len(b1+b2+b3) |
* |<-------------------- queue_data_len -------------------->|
*
* @param rbb ring block buffer object
* @param queue_data_len The max queue data size, and the return size must less then it.
* @param queue continuous block queue
*
* @return the block queue data total size
*/
rt_size_t
rt_rbb_blk_queue_get
(
rt_rbb_t
rbb
,
rt_size_t
queue_data_len
,
rt_rbb_blk_queue_t
blk_queue
)
{
rt_base_t
level
;
rt_size_t
data_total_size
=
0
;
rt_slist_t
*
node
;
rt_rbb_blk_t
last_block
=
NULL
,
block
;
RT_ASSERT
(
rbb
);
RT_ASSERT
(
blk_queue
);
if
(
rt_slist_isempty
(
&
rbb
->
blk_list
))
return
0
;
level
=
rt_hw_interrupt_disable
();
for
(
node
=
rt_slist_first
(
&
rbb
->
blk_list
);
node
;
node
=
rt_slist_next
(
node
))
{
if
(
!
last_block
)
{
last_block
=
rt_slist_entry
(
node
,
struct
rt_rbb_blk
,
list
);
if
(
last_block
->
status
==
RT_RBB_BLK_PUT
)
{
/* save the first put status block to queue */
blk_queue
->
blocks
=
last_block
;
blk_queue
->
blk_num
=
0
;
}
else
{
/* the first block must be put status */
last_block
=
NULL
;
continue
;
}
}
else
{
block
=
rt_slist_entry
(
node
,
struct
rt_rbb_blk
,
list
);
/*
* these following conditions will break the loop:
* 1. the current block is not put status
* 2. the last block and current block is not continuous
* 3. the data_total_size will out of range
*/
if
(
block
->
status
!=
RT_RBB_BLK_PUT
||
last_block
->
buf
>
block
->
buf
||
data_total_size
+
block
->
size
>
queue_data_len
)
{
break
;
}
/* backup last block */
last_block
=
block
;
}
/* remove current block */
rt_slist_remove
(
&
rbb
->
blk_list
,
&
last_block
->
list
);
data_total_size
+=
last_block
->
size
;
last_block
->
status
=
RT_RBB_BLK_GET
;
blk_queue
->
blk_num
++
;
}
rt_hw_interrupt_enable
(
level
);
return
data_total_size
;
}
RTM_EXPORT
(
rt_rbb_blk_queue_get
);
/**
* get all block length on block queue
*
* @param blk_queue the block queue
*
* @return total length
*/
rt_size_t
rt_rbb_blk_queue_len
(
rt_rbb_blk_queue_t
blk_queue
)
{
rt_size_t
i
,
data_total_size
=
0
;
RT_ASSERT
(
blk_queue
);
for
(
i
=
0
;
i
<
blk_queue
->
blk_num
;
i
++
)
{
data_total_size
+=
blk_queue
->
blocks
[
i
].
size
;
}
return
data_total_size
;
}
RTM_EXPORT
(
rt_rbb_blk_queue_len
);
/**
* return the block queue buffer
*
* @param blk_queue the block queue
*
* @return block queue buffer
*/
rt_uint8_t
*
rt_rbb_blk_queue_buf
(
rt_rbb_blk_queue_t
blk_queue
)
{
RT_ASSERT
(
blk_queue
);
return
blk_queue
->
blocks
[
0
].
buf
;
}
RTM_EXPORT
(
rt_rbb_blk_queue_buf
);
/**
* free the block queue
*
* @param rbb ring block buffer object
* @param blk_queue the block queue
*/
void
rt_rbb_blk_queue_free
(
rt_rbb_t
rbb
,
rt_rbb_blk_queue_t
blk_queue
)
{
rt_size_t
i
;
RT_ASSERT
(
rbb
);
RT_ASSERT
(
blk_queue
);
for
(
i
=
0
;
i
<
blk_queue
->
blk_num
;
i
++
)
{
rt_rbb_blk_free
(
rbb
,
&
blk_queue
->
blocks
[
i
]);
}
}
RTM_EXPORT
(
rt_rbb_blk_queue_free
);
/**
* The put status and buffer continuous blocks can be make a block queue.
* This function will return the length which from next can be make block queue.
*
* @param rbb ring block buffer object
*
* @return the next can be make block queue's length
*/
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_ASSERT
(
rbb
);
if
(
rt_slist_isempty
(
&
rbb
->
blk_list
))
return
0
;
level
=
rt_hw_interrupt_disable
();
for
(
node
=
rt_slist_first
(
&
rbb
->
blk_list
);
node
;
node
=
rt_slist_next
(
node
))
{
if
(
!
last_block
)
{
last_block
=
rt_slist_entry
(
node
,
struct
rt_rbb_blk
,
list
);
if
(
last_block
->
status
!=
RT_RBB_BLK_PUT
)
{
/* the first block must be put status */
last_block
=
NULL
;
continue
;
}
}
else
{
block
=
rt_slist_entry
(
node
,
struct
rt_rbb_blk
,
list
);
/*
* these following conditions will break the loop:
* 1. the current block is not put status
* 2. the last block and current block is not continuous
*/
if
(
block
->
status
!=
RT_RBB_BLK_PUT
||
last_block
->
buf
>
block
->
buf
)
{
break
;
}
/* backup last block */
last_block
=
block
;
}
data_len
+=
last_block
->
size
;
}
rt_hw_interrupt_enable
(
level
);
return
data_len
;
}
RTM_EXPORT
(
rt_rbb_next_blk_queue_len
);
/**
* get the ring block buffer object buffer size
*
* @param rbb ring block buffer object
*
* @return buffer size
*/
rt_size_t
rt_rbb_get_buf_size
(
rt_rbb_t
rbb
)
{
RT_ASSERT
(
rbb
);
return
rbb
->
buf_size
;
}
RTM_EXPORT
(
rt_rbb_get_buf_size
);
examples/test/rbb_test.c
0 → 100644
浏览文件 @
dff8a2c5
/*
* File : rbb_test.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2018-08-31 armink the first version
*/
#include <string.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <stdlib.h>
static
rt_bool_t
put_finish
=
RT_FALSE
;
static
void
put_thread
(
void
*
param
)
{
rt_rbb_t
rbb
=
(
rt_rbb_t
)
param
;
rt_rbb_blk_t
block
;
rt_uint8_t
put_count
=
0
;
put_finish
=
RT_FALSE
;
while
(
put_count
<
255
)
{
if
(
put_count
==
10
)
{
put_count
=
10
;
}
block
=
rt_rbb_blk_alloc
(
rbb
,
rand
()
%
10
+
1
);
if
(
block
)
{
block
->
buf
[
0
]
=
put_count
++
;
rt_rbb_blk_put
(
block
);
}
rt_thread_mdelay
(
rand
()
%
10
);
}
rt_kprintf
(
"Put block data finish.
\n
"
);
put_finish
=
RT_TRUE
;
}
static
void
get_thread
(
void
*
param
)
{
rt_rbb_t
rbb
=
(
rt_rbb_t
)
param
;
rt_rbb_blk_t
block
;
rt_uint8_t
get_count
=
0
;
while
(
get_count
<
255
)
{
if
(
get_count
==
10
)
{
get_count
=
10
;
}
block
=
rt_rbb_blk_get
(
rbb
);
if
(
block
)
{
if
(
block
->
buf
[
0
]
!=
get_count
++
)
{
rt_kprintf
(
"Error: get data (times %d) has an error!
\n
"
,
get_count
);
}
rt_rbb_blk_free
(
rbb
,
block
);
}
else
if
(
put_finish
)
{
break
;
}
rt_thread_mdelay
(
rand
()
%
10
);
}
rt_kprintf
(
"Get block data finish.
\n
"
);
rt_kprintf
(
"
\n
====================== rbb dynamic test finish =====================
\n
"
);
}
void
rbb_test
(
void
)
{
rt_rbb_t
rbb
;
rt_rbb_blk_t
blk1
,
blk2
,
blk3
,
blk4
,
blk5
,
blk6
,
_blk1
,
_blk2
;
rt_size_t
i
,
j
,
k
,
req_size
,
size
;
struct
rt_rbb_blk_queue
blk_queue1
;
rt_thread_t
thread
;
/* create ring block buffer */
rt_kprintf
(
"
\n
====================== rbb create test =====================
\n
"
);
rbb
=
rt_rbb_create
(
52
,
6
);
if
(
rbb
)
{
rt_kprintf
(
"6 blocks in 52 bytes ring block buffer object create success.
\n
"
);
}
else
{
rt_kprintf
(
"Test error: 6 blocks in 52 bytes ring block buffer object create failed.
\n
"
);
}
/* allocate block */
rt_kprintf
(
"
\n
====================== rbb alloc test =====================
\n
"
);
blk1
=
rt_rbb_blk_alloc
(
rbb
,
2
);
if
(
blk1
&&
blk1
->
size
==
2
)
{
memset
(
blk1
->
buf
,
1
,
blk1
->
size
);
rt_kprintf
(
"Block1 (2 bytes) allocate success.
\n
"
);
}
else
{
rt_kprintf
(
"Test error: block1 (2 bytes) allocate failed.
\n
"
);
goto
__exit
;
}
blk2
=
rt_rbb_blk_alloc
(
rbb
,
4
);
if
(
blk2
&&
blk2
->
size
==
4
)
{
memset
(
blk2
->
buf
,
2
,
blk2
->
size
);
rt_kprintf
(
"Block2 (4 bytes) allocate success.
\n
"
);
}
else
{
rt_kprintf
(
"Test error: block2 (4 bytes) allocate failed.
\n
"
);
goto
__exit
;
}
blk3
=
rt_rbb_blk_alloc
(
rbb
,
8
);
if
(
blk3
&&
blk3
->
size
==
8
)
{
memset
(
blk3
->
buf
,
3
,
blk3
->
size
);
rt_kprintf
(
"Block3 (8 bytes) allocate success.
\n
"
);
}
else
{
rt_kprintf
(
"Test error: block3 (8 bytes) allocate failed.
\n
"
);
goto
__exit
;
}
blk4
=
rt_rbb_blk_alloc
(
rbb
,
16
);
if
(
blk4
&&
blk4
->
size
==
16
)
{
memset
(
blk4
->
buf
,
4
,
blk4
->
size
);
rt_kprintf
(
"Block4 (16 bytes) allocate success.
\n
"
);
}
else
{
rt_kprintf
(
"Test error: block4 (16 bytes) allocate failed.
\n
"
);
goto
__exit
;
}
blk5
=
rt_rbb_blk_alloc
(
rbb
,
32
);
if
(
blk5
&&
blk5
->
size
==
32
)
{
memset
(
blk5
->
buf
,
5
,
blk5
->
size
);
rt_kprintf
(
"Block5 (32 bytes) allocate success.
\n
"
);
}
else
{
rt_kprintf
(
"Block5 (32 bytes) allocate failed.
\n
"
);
}
blk5
=
rt_rbb_blk_alloc
(
rbb
,
18
);
if
(
blk5
&&
blk5
->
size
==
18
)
{
memset
(
blk5
->
buf
,
5
,
blk5
->
size
);
rt_kprintf
(
"Block5 (18 bytes) allocate success.
\n
"
);
}
else
{
rt_kprintf
(
"Test error: block5 (18 bytes) allocate failed.
\n
"
);
goto
__exit
;
}
rt_kprintf
(
"Ring block buffer current status:
\n
"
);
rt_kprintf
(
"next block queue length: %d
\n
"
,
rt_rbb_next_blk_queue_len
(
rbb
));
rt_kprintf
(
"block list length: %d
\n
"
,
rt_slist_len
(
&
rbb
->
blk_list
));
rt_kprintf
(
"|<- 2 -->|<-- 4 -->|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|
\n
"
);
rt_kprintf
(
"+--------+---------+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| blcok1 | block2 | block3 | block4 | block5 | empty |
\n
"
);
rt_kprintf
(
"+--------+---------+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| inited | inited | inited | inited | inited | |
\n
"
);
/* put block */
rt_kprintf
(
"
\n
====================== rbb put test =====================
\n
"
);
rt_rbb_blk_put
(
blk1
);
rt_rbb_blk_put
(
blk2
);
rt_rbb_blk_put
(
blk3
);
rt_rbb_blk_put
(
blk4
);
rt_rbb_blk_put
(
blk5
);
rt_kprintf
(
"Block1 to block5 put success.
\n
"
);
rt_kprintf
(
"Ring block buffer current status:
\n
"
);
rt_kprintf
(
"next block queue length: %d
\n
"
,
rt_rbb_next_blk_queue_len
(
rbb
));
rt_kprintf
(
"block list length: %d
\n
"
,
rt_slist_len
(
&
rbb
->
blk_list
));
rt_kprintf
(
"|<- 2 -->|<-- 4 -->|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|
\n
"
);
rt_kprintf
(
"+--------+---------+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| blcok1 | block2 | block3 | block4 | block5 | empty |
\n
"
);
rt_kprintf
(
"+--------+---------+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| put | put | put | put | put | |
\n
"
);
/* get block */
rt_kprintf
(
"
\n
====================== rbb get test =====================
\n
"
);
_blk1
=
rt_rbb_blk_get
(
rbb
);
_blk2
=
rt_rbb_blk_get
(
rbb
);
for
(
i
=
0
;
i
<
_blk1
->
size
;
i
++
)
{
if
(
_blk1
->
buf
[
i
]
!=
1
)
break
;
}
for
(
j
=
0
;
j
<
_blk2
->
size
;
j
++
)
{
if
(
_blk2
->
buf
[
j
]
!=
2
)
break
;
}
if
(
blk1
==
_blk1
&&
blk2
==
_blk2
&&
i
==
_blk1
->
size
&&
j
==
_blk2
->
size
)
{
rt_kprintf
(
"Block1 and block2 get success.
\n
"
);
}
else
{
rt_kprintf
(
"Test error: block1 and block2 get failed.
\n
"
);
goto
__exit
;
}
rt_kprintf
(
"Ring block buffer current status:
\n
"
);
rt_kprintf
(
"next block queue length: %d
\n
"
,
rt_rbb_next_blk_queue_len
(
rbb
));
rt_kprintf
(
"block list length: %d
\n
"
,
rt_slist_len
(
&
rbb
->
blk_list
));
rt_kprintf
(
"|<- 2 -->|<-- 4 -->|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|
\n
"
);
rt_kprintf
(
"+--------+---------+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| blcok1 | block2 | block3 | block4 | block5 | empty |
\n
"
);
rt_kprintf
(
"+--------+---------+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| get | get | put | put | put | |
\n
"
);
/* free block */
rt_kprintf
(
"
\n
====================== rbb free test =====================
\n
"
);
rt_rbb_blk_free
(
rbb
,
blk2
);
rt_kprintf
(
"Block2 free success.
\n
"
);
rt_rbb_blk_free
(
rbb
,
blk1
);
rt_kprintf
(
"Block1 free success.
\n
"
);
rt_kprintf
(
"Ring block buffer current status:
\n
"
);
rt_kprintf
(
"next block queue length: %d
\n
"
,
rt_rbb_next_blk_queue_len
(
rbb
));
rt_kprintf
(
"block list length: %d
\n
"
,
rt_slist_len
(
&
rbb
->
blk_list
));
rt_kprintf
(
"|<------- 6 ------>|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|
\n
"
);
rt_kprintf
(
"+------------------+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| empty2 | block3 | block4 | block5 | empty1 |
\n
"
);
rt_kprintf
(
"+------------------+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| | put | put | put | |
\n
"
);
blk6
=
rt_rbb_blk_alloc
(
rbb
,
5
);
if
(
blk6
)
{
rt_kprintf
(
"Block6 (5 bytes) allocate success.
\n
"
);
}
else
{
rt_kprintf
(
"Test error: block6 (5 bytes) allocate failed.
\n
"
);
goto
__exit
;
}
rt_rbb_blk_put
(
blk6
);
rt_kprintf
(
"Block6 put success.
\n
"
);
rt_kprintf
(
"Ring block buffer current status:
\n
"
);
rt_kprintf
(
"next block queue length: %d
\n
"
,
rt_rbb_next_blk_queue_len
(
rbb
));
rt_kprintf
(
"block list length: %d
\n
"
,
rt_slist_len
(
&
rbb
->
blk_list
));
rt_kprintf
(
"|<--- 5 ---->|< 1 >|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|
\n
"
);
rt_kprintf
(
"+------------+-----+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| block6 |empty| block3 | block4 | block5 | fragment |
\n
"
);
rt_kprintf
(
"+------------+-----+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| put | | put | put | put | |
\n
"
);
/* get block queue */
rt_kprintf
(
"
\n
====================== rbb block queue get test =====================
\n
"
);
req_size
=
rt_rbb_next_blk_queue_len
(
rbb
)
+
5
;
size
=
rt_rbb_blk_queue_get
(
rbb
,
req_size
,
&
blk_queue1
);
i
=
j
=
k
=
0
;
for
(;
i
<
blk3
->
size
;
i
++
)
{
if
(
rt_rbb_blk_queue_buf
(
&
blk_queue1
)[
i
]
!=
3
)
break
;
}
for
(;
j
<
blk4
->
size
;
j
++
)
{
if
(
rt_rbb_blk_queue_buf
(
&
blk_queue1
)[
i
+
j
]
!=
4
)
break
;
}
for
(;
k
<
blk5
->
size
;
k
++
)
{
if
(
rt_rbb_blk_queue_buf
(
&
blk_queue1
)[
i
+
j
+
k
]
!=
5
)
break
;
}
if
(
size
&&
size
==
42
&&
rt_rbb_blk_queue_len
(
&
blk_queue1
)
==
42
&&
k
==
blk5
->
size
)
{
rt_kprintf
(
"Block queue (request %d bytes, actual %d) get success.
\n
"
,
req_size
,
size
);
}
else
{
rt_kprintf
(
"Test error: Block queue (request %d bytes, actual %d) get failed.
\n
"
,
req_size
,
size
);
goto
__exit
;
}
rt_kprintf
(
"Ring block buffer current status:
\n
"
);
rt_kprintf
(
"next block queue length: %d
\n
"
,
rt_rbb_next_blk_queue_len
(
rbb
));
rt_kprintf
(
"block list length: %d
\n
"
,
rt_slist_len
(
&
rbb
->
blk_list
));
rt_kprintf
(
"| | |<----- block queue1 (42 bytes continuous buffer) ----->| |
\n
"
);
rt_kprintf
(
"|<--- 5 ---->|< 1 >|<---- 8 ----->|<------- 16 -------->|<------ 18 ------>|<---- 4 ---->|
\n
"
);
rt_kprintf
(
"+------------+-----+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| block6 |empty| block3 | block4 | block5 | fragment |
\n
"
);
rt_kprintf
(
"+------------+-----+--------------+---------------------+------------------+-------------+
\n
"
);
rt_kprintf
(
"| put | | get | get | get | |
\n
"
);
/* free block queue */
rt_kprintf
(
"
\n
====================== rbb block queue free test =====================
\n
"
);
rt_rbb_blk_queue_free
(
rbb
,
&
blk_queue1
);
rt_kprintf
(
"Block queue1 free success.
\n
"
);
rt_kprintf
(
"Ring block buffer current status:
\n
"
);
rt_kprintf
(
"next block queue length: %d
\n
"
,
rt_rbb_next_blk_queue_len
(
rbb
));
rt_kprintf
(
"block list length: %d
\n
"
,
rt_slist_len
(
&
rbb
->
blk_list
));
rt_kprintf
(
"|<--- 5 ---->|<--------------------------------- 47 ------------------------------------>|
\n
"
);
rt_kprintf
(
"+------------+---------------------------------------------------------------------------+
\n
"
);
rt_kprintf
(
"| block6 | empty |
\n
"
);
rt_kprintf
(
"+------------+---------------------------------------------------------------------------+
\n
"
);
rt_kprintf
(
"| put | |
\n
"
);
rt_rbb_blk_free
(
rbb
,
blk6
);
rt_kprintf
(
"
\n
====================== rbb static test SUCCESS =====================
\n
"
);
rt_kprintf
(
"
\n
====================== rbb dynamic test =====================
\n
"
);
thread
=
rt_thread_create
(
"rbb_put"
,
put_thread
,
rbb
,
1024
,
10
,
25
);
if
(
thread
)
{
rt_thread_startup
(
thread
);
}
thread
=
rt_thread_create
(
"rbb_get"
,
get_thread
,
rbb
,
1024
,
10
,
25
);
if
(
thread
)
{
rt_thread_startup
(
thread
);
}
__exit
:
rt_rbb_destroy
(
rbb
);
}
MSH_CMD_EXPORT
(
rbb_test
,
run
ring
block
buffer
testcase
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录