在研究stm32f407的I2S时发现有几个函数是官方写的,但是在手册和官方文档中没有找到出处,请官方能否忙里偷闲加入这部分内容,我将此部分源码贴出来请官方获知:
/**
* Audio Memory Node Manage
*/
struct rt_data_node
{
char *data_ptr;
rt_uint32_t data_size;
};
struct rt_data_node_list
{
struct rt_data_node *node;
rt_uint32_t size;
rt_uint32_t read_index, write_index;
rt_uint32_t data_offset;
void (*read_complete)(struct rt_data_node *node, void *user_data);
void *user_data;
};
int rt_data_node_init(struct rt_data_node_list **node_list, rt_uint32_t size)
{
int result = RT_EOK;
struct rt_data_node_list *list = RT_NULL;
struct rt_data_node *node = RT_NULL;
list = rt_malloc(sizeof(struct rt_data_node_list));
if (list == RT_NULL)
{
result = -RT_ENOMEM;
goto __exit;
}
memset(list, 0, sizeof(struct rt_data_node_list));
node = rt_malloc(sizeof(struct rt_data_node) * size);
if (size == RT_NULL)
{
result = -RT_ENOMEM;
goto __exit;
}
memset(node, 0, sizeof(struct rt_data_node));
list->node = node;
list->size = size;
list->read_index = 0;
list->write_index = 0;
list->data_offset = 0;
list->read_complete = RT_NULL;
list->user_data = 0;
*node_list = list;
return result;
__exit:
if (list)
rt_free(list);
if (node)
rt_free(node);
return result;
}
int rt_data_node_is_empty(struct rt_data_node_list *node_list)
{
rt_uint32_t read_index, write_index;
rt_base_t level;
level = rt_hw_interrupt_disable();
read_index = node_list->read_index;
write_index = node_list->write_index;
rt_hw_interrupt_enable(level);
if (read_index == write_index)
{
return RT_TRUE;
}
else
{
return RT_FALSE;
}
}
void wait_node_free(struct rt_data_node_list *node_list)
{
while (node_list->read_index != node_list->write_index)
rt_thread_mdelay(5);
}
int rt_data_node_write(struct rt_data_node_list *node_list, void *buffer, rt_uint32_t size)
{
struct rt_data_node *node = RT_NULL;
rt_uint32_t read_index, write_index, next_index;
rt_base_t level;
level = rt_hw_interrupt_disable();
read_index = node_list->read_index;
write_index = node_list->write_index;
rt_hw_interrupt_enable(level);
next_index = write_index + 1;
if (next_index >= node_list->size)
next_index = 0;
if (next_index == read_index)
{
rt_kprintf("[node]:node list full, write index = %d, read index = %d <br>", write_index, read_index);
return -RT_ERROR;
}
level = rt_hw_interrupt_disable();
/* set node attribute */
node = &node_list->node[write_index];
node->data_ptr = (char *) buffer;
node->data_size = size;
node_list->write_index = next_index;
rt_hw_interrupt_enable(level);
return size;
}
int rt_data_node_read(struct rt_data_node_list *node_list, void *buffer, rt_uint32_t size)
{
struct rt_data_node *node = RT_NULL;
rt_uint32_t read_index, write_index, next_index;
rt_int32_t remain_len, copy_size;
rt_uint32_t read_offset, data_offset;
rt_base_t level;
rt_uint32_t result = size;
level = rt_hw_interrupt_disable();
read_index = node_list->read_index;
write_index = node_list->write_index;
rt_hw_interrupt_enable(level);
read_offset = 0;
if (read_index == write_index)
{
result = 0;
}
else
{
do
{
node = &node_list->node[node_list->read_index];
data_offset = node_list->data_offset;
remain_len = node->data_size - data_offset;
if (size - read_offset > remain_len)
{
/* Full*/
copy_size = remain_len;
}
else
{
/* reamain buffer */
copy_size = size - read_offset;
}
memcpy((char *)buffer + read_offset, node->data_ptr + data_offset, copy_size);
read_offset += copy_size;
data_offset += copy_size;
node_list->data_offset = data_offset;
if (data_offset >= node->data_size)
{
/* notify transmitted complete. */
if (node_list->read_complete != RT_NULL)
{
node_list->read_complete(node, node_list->user_data);
}
level = rt_hw_interrupt_disable();
read_index = node_list->read_index;
write_index = node_list->write_index;
rt_hw_interrupt_enable(level);
next_index = read_index + 1;
if (next_index >= node_list->size)
next_index = 0;
level = rt_hw_interrupt_disable();
node_list->read_index = next_index;
node_list->data_offset = 0;
rt_hw_interrupt_enable(level);
if (next_index == write_index)
{
result = read_offset;
break;
}
}
}
while (read_offset < size);
}
return result;
}
static void data_node_read_complete(struct rt_data_node *node, void *user_data)
{
struct rt_device *dev = RT_NULL;
dev = (struct rt_device *)user_data;
if (dev->tx_complete != RT_NULL)
{
dev->tx_complete(dev, node->data_ptr);
}
}