1. 阅读公司代码的时候,发现公司代码向串口打印,先把数据加载到数组中,进入临界区,然后通过串口输出,退出临界区。
2. 当然还有向flash写数据,直接一次性原文写入,也没进入临界区,挂起任务调度,
3. 网络数据发送的时候,也是直接发送,而发送的数据量过大,已经出现好多关于网络发送时,芯片往接口丢数据过大,过快导致发送失败。
似乎所有的这种输入大于输出的问题,都会存在,如果强制关中断,或挂起任务调度,确实可以解决,但是我认为这样速度就下降了。
我想到的方法是,通过增加缓存,往缓存写入数据,但是我们必须清楚,大数据时缓存必定会满,这个时候肯定需要涉及动态内存申请(内存池,内存堆,可能内存池会对内存使用会造成一定的浪费,但是速度会很快)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>/*
1.定一个小*/
typedef struct cache_simple {struct cache_simple* cache_next;unsigned int buf_len;unsigned char buf[0];
}cache_simple_t;typedef struct cache{unsigned char* data_head;unsigned char* data_tail;unsigned int block_size;cache_simple_t* cache_next;
}cache_t;void init_my_cache(cache_t* cache_head, unsigned int block_size)
{cache_simple_t* my_cache = (cache_t*)malloc(sizeof(cache_simple_t) + block_size);if (!my_cache) {return;}my_cache->buf_len = block_size;my_cache->cache_next = NULL;cache_head->cache_next = my_cache;cache_head->data_head = my_cache->buf;cache_head->data_tail = my_cache->buf;cache_head->block_size = block_size;
}static void insert_cache(cache_t* cache_head, unsigned int size)//尾插
{cache_simple_t* p = cache_head->cache_next;cache_simple_t* new_cache = (cache_simple_t*)malloc(sizeof(cache_simple_t) + size);if (new_cache == NULL) {return;}while (p->cache_next) {p = p->cache_next;}p->cache_next = new_cache;new_cache->buf_len = size;new_cache->cache_next = NULL;
}//static void delet_cache(cache_t* cache_head)//头删
//{
// cache_simple_t* p = cache_head->cache_next;
//
// if (p) {
// cache_head->cache_next = p->cache_next;
// free(p);
// }
//}void insert_data(cache_t* cache_head, unsigned char* buf, unsigned int len)
{cache_simple_t* p = cache_head->cache_next;cache_t* p_head = cache_head;unsigned int malloc_size;unsigned int block_num, i;while (p->cache_next){p = p->cache_next;}/* 数据尾指针总是指向最后, 如果要插入数据, 要计算申请多少块block_size的内存来存储 */if (p_head->data_tail + len > p->buf + p->buf_len) {malloc_size = len - (unsigned int)(p->buf + p->buf_len - p_head->data_tail);block_num = malloc_size / p_head->block_size + ((malloc_size % p_head->block_size) ? 1 : 0);for (i = 0; i < block_num; i++) {insert_cache(p_head, p_head->block_size);}}/* 将数据存入申请的内存中 */for (i = 0; i < len; i++) {*p_head->data_tail = buf[i];if (p_head->data_tail == p->buf + p_head->block_size -1) {p_head->data_tail = p->cache_next->buf;p = p->cache_next;} else {p_head->data_tail++;}}}void display_list(cache_t* cache)
{cache_simple_t* p = cache->cache_next;unsigned int i;while (p) {for (i = 0; i < cache->block_size; i++) {printf("%c ", p->buf[i]);}p = p->cache_next;}
}unsigned int read_data(cache_t* cache, unsigned char* data)
{cache_simple_t* p = cache->cache_next;/* 如果数据头尾指针相等, 则此时链表中数据为空 */if (cache->data_head == cache->data_tail) {cache->data_head = cache->data_tail = cache->cache_next->buf;return 0;}/* 数据头指针指向的就是数据 */*data = *cache->data_head;/* 数据头指针必定在cache_head指向的第一结点 */if (cache->data_head == p->buf + cache->block_size - 1) {if (p->cache_next) {/* 只有当前结点的下一个结点不为空,才能将数据指针指向下一位置, 并删除当前这个结点 */cache->data_head = p->cache_next->buf;cache->cache_next = p->cache_next;free(p);}}else {cache->data_head++;}if (cache->data_head == cache->data_tail) {cache->data_head = cache->data_tail = cache->cache_next->buf;}return 1;
}
unsigned int read_ndata(cache_t* cache, unsigned char* data, unsigned int len)
{unsigned int i, read_len = 0;for (i = 0; i < len; i++){if (read_data(cache, data + i)) {read_len++;}}return read_len;
}
char * str = "123456789qwertyuiopasdfghjkl";
char * str1 = "mnbvcxzlk";
void main()
{int i, len;unsigned char data[100];cache_t cache;init_my_cache(&cache, 10);insert_data(&cache, str, strlen(str));len = read_ndata(&cache, data, 28);for (i = 0; i < len; i++){printf("%c ", data[i]);}printf("\n");insert_data(&cache, str1, strlen(str1));display_list(&cache);while (1);
}
如果我们是单纯的写入数据, 串口打印,lwip发送这样没问题, 但是考虑到这个要用到对flash的操作, 意味着内部写入的数据, 要附带地址起始位置, 写入的数据, 数据长度,通通写道这个buf中, 然后底层接口读取的时候, 就需要获取这些信息, 并且读取数据
代码没在实际项目跑过, 并且这里面的内存分配malloc是有问题的, 如果是跑的裸机, 请使用我的另一篇内存池设计实现, 当然也可以把内存池跑到RTOS中, 或者直接使用RTOS的内存管理算法, 如果可以希望朋友们帮忙一起验证一下这篇和内存池.实际上内存池就是我打算设计给到这里来使用的.
这里实际就是一个队列的实现, 当数据一个一个入队, 当入队的数据满了一个预先申请的块, 则会重新申请相同大小的一块, 继续存储数据. 出队的时候, 一个数据一个数据的出, 当出完一个存储块, 则释放这段内存, 如果出到最后一块, 是不会把这块删除的, 同时如果队列为空了, 则链表指针会恢复到当前内存块的起始位置.