巧夺天工 的 KFIFO ,用STM32实现。

实现源文件如下:

/**********************************************************
*
*  文件名: kfifo.c
*
*  文件描述: 该文件包含的kfifo的处理函数
*
*  创建人: GXP
*
* 创建日期: 2016年8月9日16:13:06
*
*  版本号: 1.0
*
*  修改记录: 无
*
* 本文参考博客地址: http://blog.csdn.net/linyt/article/details/5764312
* http://blog.csdn.net/chen19870707/article/details/39899743
*
***********************************************************/ #include "kfifo.h" #include "FreeRTOS.h"
#include "task.h" #define min(a, b) (((a) < (b)) ? (a) : (b)) //找出最接近 最大2的指数次幂
unsigned int roundup_pow_of_two(unsigned int date_roundup_pow_of_two )
{
/* 这里采用 STM32 硬件提供的计算前导零指令 CLZ
* 举个例子,假如变量date_roundup_pow_of_two 0x09
*(二进制为:0000 0000 0000 0000 0000 0000 0000 1001), 即bit3和bit0为1
* 则__clz( (date_roundup_pow_of_two)的值为28,即最高位1 前面有28个0,32-28 =3 代表最高位1 的 位置
* 31UL 表示 无符号 int 数字 31,否则默认为 有符号 int 数字 31
* 这里参考 FreeRTOS 的 寻找高级优先级任务 的写法,详细解释到朱工博客
* 博客地址: http://blog.csdn.net/zhzht19861011/article/details/51418383
*/ return ( 1UL << ( 32UL - ( unsigned int ) __clz( (date_roundup_pow_of_two) ) ) ); } /*
* 每次调用这个函数都会产生 两个内存块,一个内存块指向struct KFIFO,一个指向 KFIFO.buff
* 因此 如果这两个内存块不在使用请释放掉!GXP,2016年8月17日12:55:54
*/ struct KFIFO *kfifo_alloc(unsigned int size)
{
unsigned char *buffer; struct KFIFO *ret; ret=(struct KFIFO *) pvPortMalloc(sizeof (struct KFIFO)); /*
* round up to the next power of 2, since our 'let the indices
* wrap' tachnique works only in this case.
* 如果size 是2的 次幂圆整,则 size & (size - 1) =0
*/ if (size & (size - ))
{
// BUG_ON(size > 0x80000000); //如果你要申请的buffer 不是 2的 次幂圆整,就要把 size 变成 2的次幂圆整 ,方便下面计算
size = roundup_pow_of_two(size);
} //这里使用 FreeRTOS的 分配内存的 API
buffer = (unsigned char*) pvPortMalloc(size); if (!buffer) //如果返回的值为NULL,这说明分配内存失败
return 0UL; // ret = kfifo_init(buffer, size, lock); ret->buffer=buffer;
ret->size =size;
ret->in = ;
ret->out = ; if (!ret) //如果ret的值为NULL,这说明分配内存失败
vPortFree(buffer); //释放之前分配的 内存空间 return ret; } unsigned int __kfifo_put(struct KFIFO *fifo, unsigned char *buffer, unsigned int len)
{
unsigned int L; //环形缓冲区的剩余容量为fifo->size - fifo->in + fifo->out,让写入的长度取len和剩余容量中较小的,避免写越界;
len = min( len , fifo->size - fifo->in + fifo->out ); /*
* Ensure that we sample the fifo->out index -before- we
* start putting bytes into the kfifo.
*/
//多处理器 处理内存 的 屏障,STM32不需要这个
// smp_mb(); /* first put the data starting from fifo->in to buffer end */
/* 首先将数据从fifo.in 所在的位置开始写,写之前,首先要看一下fifo->in到 buffer 末尾的大小 是不是 比 len 大*/ /*
* 前面讲到fifo->size已经2的次幂圆整,主要是方便这里计算,提升效率
* 在对10进行求余的时候,我们发现,余数总是整数中的个位上的数字,而不用管其他位是什么;
* 所以,kfifo->in % kfifo->size 可以转化为 kfifo->in & (kfifo->size – 1),效率会提升
* 所以fifo->size - (fifo->in & (fifo->size - L)) 即位 fifo->in 到 buffer末尾所剩余的长度,
* L取len和剩余长度的最小值,即为需要拷贝L 字节到fifo->buffer + fifo->in的位置上。
*/
L = min(len, fifo->size - (fifo->in & (fifo->size - ))); memcpy(fifo->buffer + (fifo->in & (fifo->size - )), buffer, L); /* then put the rest (if any) at the beginning of the buffer */ memcpy(fifo->buffer, buffer + L, len - L); /*
* Ensure that we add the bytes to the kfifo -before-
* we update the fifo->in index.
*/ // smp_wmb(); //多处理器 处理内存 的 屏障,STM32不需要这个 /*
* 注意这里 只是用了 fifo->in += len而未取模,
* 这就是kfifo的设计精妙之处,这里用到了unsigned int的溢出性质,
* 当in 持续增加到溢出时又会被置为0,这样就节省了每次in向前增加都要取模的性能,
* 锱铢必较,精益求精,让人不得不佩服。
*/ fifo->in += len; /*返回值 代表 写入数据的个数 ,这样 就可以根据返回值 判断缓冲区是否写满*/
return len;
} unsigned int __kfifo_get(struct KFIFO *fifo, unsigned char *buffer, unsigned int len)
{
unsigned int L; len = min(len, fifo->in - fifo->out); /*
* Ensure that we sample the fifo->in index -before- we
* start removing bytes from the kfifo.
*/ //smp_rmb(); //多处理器 处理内存 的 屏障,STM32不需要这个 /* first get the data from fifo->out until the end of the buffer */
L = min(len, fifo->size - (fifo->out & (fifo->size - )));
memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - )), L); /* then get the rest (if any) from the beginning of the buffer */
memcpy(buffer + L, fifo->buffer, len - L); /*
* Ensure that we remove the bytes from the kfifo -before-
* we update the fifo->out index.
*/ //smp_mb(); //多处理器 处理内存 的 屏障,STM32不需要这个 /*
* 注意这里 只是用了 fifo->out += len 也未取模运算,
* 同样unsigned int的溢出性质,当out 持续增加到溢出时又会被置为0,
* 如果in先溢出,出现 in < out 的情况,那么 in – out 为负数(又将溢出),
* in – out 的值还是为buffer中数据的长度。
*/ fifo->out += len; return len;
}

头文件如下:

#ifndef _KFIFO_H_
#define _KFIFO_H //声明 一个 结构体 kfifo struct KFIFO
{
unsigned char *buffer; /* the buffer holding the data */
unsigned int size; /* the size of the allocated buffer */
unsigned int in; /* data is added at offset (in % size) */
unsigned int out; /* data is extracted from off. (out % size) */
/*STM32 只有一个核心,同一时刻只能写或者读,因此不需要*/
// volatile unsigned int *lock; /* protects concurrent modifications */
}; unsigned int roundup_pow_of_two( unsigned int date_roundup_pow_of_two ); struct KFIFO *kfifo_alloc(unsigned int size); unsigned int __kfifo_put(struct KFIFO *fifo, unsigned char *buffer, unsigned int len); unsigned int __kfifo_get(struct KFIFO *fifo, unsigned char *buffer, unsigned int len); #endif

上面  实现 找出  最接近 最大2的指数次幂 的是通过 STM32 一个特殊的 寄存器实现的 ,可以百度 找 C 语言 实现的方式。

以及内存 的 分配 是由  FreeRTOS提供  的 内存分配和释放  实现的 。

使用 方式如下:

//创建一个 KFIFO 的结构体 指针

struct KFIFO *test_kifo_buffer=NULL;
        //kfifo 测试 第一步: 创建 一个 1024字节的 fifo buff

            //首先定义一个 在全局变量中定义一个 KFIFO 结构体 test_kifo_buffer

            //接着 给这个 KFIFO 结构体 test_kifo_buffer 申请 一个 1024字节的 内存空间

    //你如果分配468,会分配512字节的空间,你如果写 668,就会分配1024字节的 空间,1025就分配 2048
//因为这样 会方便计算 test_kifo_buffer=kfifo_alloc( );//这里写入668,也分配的是 1024 字节的 空间 if( !test_kifo_buffer )
printf("\r\n KFIFO 结构体 test_kifo_buffer 没有创建成功!\r\n");
    //kfifo 测试 第二步: 发送10个字节写入到 KFIFO 结构体 test_kifo_buffer 中
write_counter=__kfifo_put(test_kifo_buffer, test_fifo_write_buff, ); if(write_counter!=)
printf("\r\n发送10个字节写入到KFIFO结构体test_kifo_buffer失败,写入个数是:%d.\r\n",write_counter);
        read_counter=read_counter=__kfifo_get(test_kifo_buffer, test_fifo_read_buff,);

        printf("从test_kifo_buffer缓冲区读取的数据是%s,读出的个数是%d.\r\n",test_fifo_read_buff,read_counter);

        printf("test_kifo_buffer->size:%d,test_kifo_buffer->out:%d,test_kifo_buffer->in:%d.\r\n",test_kifo_buffer->size,test_kifo_buffer->out,test_kifo_buffer->in);

STM32 & FreeRTOS & KFIFO (巧夺天工)的更多相关文章

  1. 【MCU】移植AT32库&FreeRTOS教程

    目录 前言 1. 移植AT库 1.1 移植内核相关文件 1.2 移植芯片型号相关文件 1.3 移植芯片外设驱动库 1.4 移植配置文件及中断回调函数文件 2. 移植FreeRTOS源码 2.1 获取 ...

  2. 【FreeRTOS】cpu利用率统计

    目录 前言 概念 作用 必看点 实现 添加几个宏定义 源码 FreeRTOS STM32 定时器 简要说明 前言 本笔记基于 stm32+FreeRTOS. 主要参考野火.安富莱. 概念 简单概要: ...

  3. 【RTOS】堆栈与任务栈

    目录 前言 概念 双堆栈指针 要点 Cortex-M3寄存器介绍 寄存器图 简要介绍 知识 出入栈 入栈(压栈) 出栈 重点知识 异常的响应序列* 入栈 取向量 更新寄存器 小结知识* FreeRTO ...

  4. 基于Linux的kfifo移植到STM32(支持os的互斥访问)

    基于Linux的kfifo移植到STM32(支持os的互斥访问) 关于kfifo kfifo是内核里面的一个First In First Out数据结构,它采用环形循环队列的数据结构来实现:它提供一个 ...

  5. STM32与FreeRTOS实现低功耗

    在工作过程中,遇到这样一个产品,它基于 Cortex-M7 内核的 STM32F769 芯片,同时使用了 FreeRTOS 实时操作系统. 由于该产品使用电池供电,因此有着低功耗的需求. 接下来,我将 ...

  6. STM32 使用 FreeRTOS过程记录

    资源:http://blog.csdn.net/zhzht19861011/article/category/6191478 资源:可以下载安富莱的STM32-V5开发版资料中的FreeRTOS教程, ...

  7. STM32之FreeRTOS

    STM32之FreeRTOS http://www.freertos.org/index.html http://www.freertos.org/a00090.html#ST http://www. ...

  8. 【转载】MDK环境下让STM32用上FreeRTOS v8.1.2和FreeRTOS+Trace v2.6.0全过程

    [转载]https://www.amobbs.com/thread-5601460-1-2.html?_dsign=6a59067b   本人选择使用FreeRTOS的最大原因就是想使用FreeRTO ...

  9. FreeRTOS移植到STM32上的移植过程

    所有的单片机都是顺序执行的,而对于多任务而言就显得力不从心了,虽然在一些小项目中可以通过定时器来实现,但这种实现方式没有实时性,一旦任务需要在规定时间内做出响应,那只能通过实时操作系统来完成了.在很多 ...

随机推荐

  1. JS代理模式实现图片预加载

    ---恢复内容开始--- 刚刚说了懒加载,现在我们来搞搞预加载吧 预加载的核心: 图片等静态资源在使用前提前请求. 资源后续使用可以直接从缓存中加载,提升用户体验. 几个误区: 预加载不是为了减少页面 ...

  2. jq插件写法

    如今做web开发,jQuery 几乎是必不可少的,同时jquery插件也是不断的被大家所熟知,以及运用.最近在搞这个jquery插件,发现它的牛逼之处,所以讲一讲jQuery插件的写法以及使用  (f ...

  3. html5的web存储与cookie的区别

    以下从3个方面进行比较: 1,容量:cookie只有4KB,localStorage和sessionStorage最大容量5M 2,是否会携带到ajax中:cookie由每个对服务器的请求来传递,会影 ...

  4. 活字格Web应用平台学习笔记 7 - 导出 Excel

    活字格一直强调和Excel的兼容,可以导入导出Excel,今天终于学到这一课了. 课程目标: 好吧,就是这么快,已经加了一个“导出到Excel”的按钮了 我以为多高深呢,原来人家都给写好逻辑了,直接选 ...

  5. 通过 Cobalt Strike 利用 ms14-068

    拓扑图 攻击者(kali) 位于 192.168.245.0/24 网段,域环境位于 192.168.31.0/24 网段. 域中有一台 win7 有两张网卡,可以同时访问两个网段,以这台机器作为跳板 ...

  6. 【疑难杂症04】EOFException异常详解

    最近线上的系统被检测出有错误日志,领导让我检查下问题,我就顺便了解了下这个异常. 了解一个类,当然是先去看他的API,EOFException的API如下: 通过这个API,我们可以得出以下信息: 这 ...

  7. 【Python】插入sqlite数据库

    import sqlite3 from datetime import datetime conn = sqlite3.connect('data.db') print("Opened da ...

  8. oracle--ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效

    SELECT sid, serial#, username, osuser FROM v$session where sid in(select session_id from v$locked_ob ...

  9. Oracle EBS AR 收款调整取值

    SELECT ct.trx_number ,adj.adjustment_number ,ad.amount_dr ,ad.amount_cr ,ad.source_table ,ad.source_ ...

  10. 找回master库中被删除的系统表

    接手的某个数据库实例中,master数据库中的所有系统表都被误删除掉了. 最直接影响就是一旦涉及到要查询这些系统表,就会出现错误. 例如,右键点击某个数据,查看属性时会出现如下图所示错误: 那么怎么找 ...