巧夺天工 的 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. 通过ssh实现远程登陆服务器!

    通过ssh实现远程登陆前提是服务器已经开启ssh服务,至于怎么开启,可以参看上一篇“Linux服务器开启ssh服务,实现ssh远程登陆!”! 使用ssh登陆时,输入主机(linux的ip地址),账号, ...

  2. Map对象以及for of的使用方法

  3. JavaScript中何时使用===,何时使用==

    建议尽量都使用===,原因如下: 一致性:使用==对一致性没有任何好处,那么为什么不避免使用呢. 简单和性能:一般来说,===是最简单的操作符,因为它不用进行类型转换.JavaScript引擎的性能参 ...

  4. CUDA(5.5)与MySQL 5.6的rint函数定义冲突引起的VS编译器C2264错误

    向CUDA project中添加了如下的包含目录后: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include; ..\inclu ...

  5. 基于localStorge开发登录模块的记住密码与自动登录

    前沿||我是乐于分享,善于交流的鸟窝 先做写一篇关于登录模块中记住密码与自动登录的模块.鸟窝微信:jkxx123321 关于这个模块功能模块的由来,这是鸟大大的处女秀,为什么这么说呢?一天在群里,一个 ...

  6. Python——Queue模块以及生产消费者模型

    1.了解Queue Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 |queue.Qu ...

  7. 使用redis 处理高并发场景

    1.原理: 当同一个用户获取锁之后,会让该用户一直持有锁.同样 的用户再次获取,会根据原子性 ,lock返回true. /** * 获取锁(非公平锁), 默认获取超时为2分钟 */ public bo ...

  8. git版本超前了N个版本且落后了N个版本的解决办法

    当遇到该问题的时候,一般情况下我们会首先拉取,紧接着就出现了一系列问题………… 其实当输入命令,git pull的时候,会报错,这时瞬间就感到凌乱了&……*%%*%………… 莫慌…… 这时输入 ...

  9. SQL语句结合上下文查询(in查询)

    在多个表联合查询时,使用linq语句查询就显得不那么方便了,执行效率也不高, SQL语句查询的优势就显现出来了. using (var context = new YZS_TRAEntities()) ...

  10. CAC的Debian-8-64bit安装BBR正确方式是?

    裝过三台debian 64 bit, CAC, 2歐, KVM虛擬機 做法都一樣 0. 有裝銳速記得先刪除, 免得換核心後, 銳速在扯後腿 1.換4.9版kernel 有正式版 別裝啥rc版, 4.9 ...