巧夺天工 的 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. ThinkPHP5+Layui实现图片上传加预览

    html代码 <div class="layui-upload"> <button type="button" class="lay ...

  2. python邮件发送

    '''qq邮件与其他邮件有所不同,下以我的qq邮件为例(切勿转载):''' import osimport smtplibfrom email.mime.text import MIMEText # ...

  3. phpstudy集成下Apache配置部署https安全证书

    一..先申请到安全证书.(腾讯云或者阿里云申请免费1年的安全证书),怎么申请这里也说下(以腾讯云为例): 1.登录腾讯云QQ或微信登录都行,第一次登录要通过实名认证,点击[产品]---[ss证书l] ...

  4. 语义SLAM的数据关联和语义定位(三)

    与现有方法的异同 特征点SLAM中的数据关联 先回忆一下特征点SLAM中,我们是如何处理数据关联的.下面以ORBSLAM为例. 在初始化部分,我们通过特征描述子的相似性,建立两帧之间的特征点关联,然后 ...

  5. eclipse代码中每行的开始和结尾出现多余的特殊符号

    window -> preferences -> general -> editors -> text editors ->          show whitespa ...

  6. Ubuntu安装ffmpeg

    二.linux源码安装: 如下: 下载 源码包:http://ffmpeg.org/releases/ffmpeg-3.3.tar.bz2 1.从网络上下载到的源码包,然后解压到指目录 假设下载目录 ...

  7. Oracle EBS 查看双节点是否做了信任

    perl $AD_TOP/patch/115/bin/txkRunSSHSetup.pl verifyssh -contextfile=$CONTEXT_FILE -hosts=erpapp1,erp ...

  8. Oracle EBS INV更新保留

    CREATE or REPPLACE PROCEDURE UpdateReservation AS -- Common Declarations l_api_version NUMBER := 1.0 ...

  9. FFmpeg实现监控摄像头的RTSP协议转RTMP协议直播

    文章来源:http://www.cuplayer.com/player/PlayerCode/RTSP/2014/0706/1419.html FFmpeg实现监控摄像头的RTSP协议转RTMP协议直 ...

  10. route命令详解与使用实例 ,同时访问内外网

    route命令详解与使用实例     2011-10-18 12:19:41|  分类: 其他 |  标签:route   |字号 订阅   1.   使用背景 需要接入两个网络,一个是部署环境所在内 ...