STM32 & FreeRTOS & KFIFO (巧夺天工)
巧夺天工 的 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 (巧夺天工)的更多相关文章
- 【MCU】移植AT32库&FreeRTOS教程
目录 前言 1. 移植AT库 1.1 移植内核相关文件 1.2 移植芯片型号相关文件 1.3 移植芯片外设驱动库 1.4 移植配置文件及中断回调函数文件 2. 移植FreeRTOS源码 2.1 获取 ...
- 【FreeRTOS】cpu利用率统计
目录 前言 概念 作用 必看点 实现 添加几个宏定义 源码 FreeRTOS STM32 定时器 简要说明 前言 本笔记基于 stm32+FreeRTOS. 主要参考野火.安富莱. 概念 简单概要: ...
- 【RTOS】堆栈与任务栈
目录 前言 概念 双堆栈指针 要点 Cortex-M3寄存器介绍 寄存器图 简要介绍 知识 出入栈 入栈(压栈) 出栈 重点知识 异常的响应序列* 入栈 取向量 更新寄存器 小结知识* FreeRTO ...
- 基于Linux的kfifo移植到STM32(支持os的互斥访问)
基于Linux的kfifo移植到STM32(支持os的互斥访问) 关于kfifo kfifo是内核里面的一个First In First Out数据结构,它采用环形循环队列的数据结构来实现:它提供一个 ...
- STM32与FreeRTOS实现低功耗
在工作过程中,遇到这样一个产品,它基于 Cortex-M7 内核的 STM32F769 芯片,同时使用了 FreeRTOS 实时操作系统. 由于该产品使用电池供电,因此有着低功耗的需求. 接下来,我将 ...
- STM32 使用 FreeRTOS过程记录
资源:http://blog.csdn.net/zhzht19861011/article/category/6191478 资源:可以下载安富莱的STM32-V5开发版资料中的FreeRTOS教程, ...
- STM32之FreeRTOS
STM32之FreeRTOS http://www.freertos.org/index.html http://www.freertos.org/a00090.html#ST http://www. ...
- 【转载】MDK环境下让STM32用上FreeRTOS v8.1.2和FreeRTOS+Trace v2.6.0全过程
[转载]https://www.amobbs.com/thread-5601460-1-2.html?_dsign=6a59067b 本人选择使用FreeRTOS的最大原因就是想使用FreeRTO ...
- FreeRTOS移植到STM32上的移植过程
所有的单片机都是顺序执行的,而对于多任务而言就显得力不从心了,虽然在一些小项目中可以通过定时器来实现,但这种实现方式没有实时性,一旦任务需要在规定时间内做出响应,那只能通过实时操作系统来完成了.在很多 ...
随机推荐
- 通过ssh实现远程登陆服务器!
通过ssh实现远程登陆前提是服务器已经开启ssh服务,至于怎么开启,可以参看上一篇“Linux服务器开启ssh服务,实现ssh远程登陆!”! 使用ssh登陆时,输入主机(linux的ip地址),账号, ...
- Map对象以及for of的使用方法
- JavaScript中何时使用===,何时使用==
建议尽量都使用===,原因如下: 一致性:使用==对一致性没有任何好处,那么为什么不避免使用呢. 简单和性能:一般来说,===是最简单的操作符,因为它不用进行类型转换.JavaScript引擎的性能参 ...
- CUDA(5.5)与MySQL 5.6的rint函数定义冲突引起的VS编译器C2264错误
向CUDA project中添加了如下的包含目录后: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include; ..\inclu ...
- 基于localStorge开发登录模块的记住密码与自动登录
前沿||我是乐于分享,善于交流的鸟窝 先做写一篇关于登录模块中记住密码与自动登录的模块.鸟窝微信:jkxx123321 关于这个模块功能模块的由来,这是鸟大大的处女秀,为什么这么说呢?一天在群里,一个 ...
- Python——Queue模块以及生产消费者模型
1.了解Queue Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 |queue.Qu ...
- 使用redis 处理高并发场景
1.原理: 当同一个用户获取锁之后,会让该用户一直持有锁.同样 的用户再次获取,会根据原子性 ,lock返回true. /** * 获取锁(非公平锁), 默认获取超时为2分钟 */ public bo ...
- git版本超前了N个版本且落后了N个版本的解决办法
当遇到该问题的时候,一般情况下我们会首先拉取,紧接着就出现了一系列问题………… 其实当输入命令,git pull的时候,会报错,这时瞬间就感到凌乱了&……*%%*%………… 莫慌…… 这时输入 ...
- SQL语句结合上下文查询(in查询)
在多个表联合查询时,使用linq语句查询就显得不那么方便了,执行效率也不高, SQL语句查询的优势就显现出来了. using (var context = new YZS_TRAEntities()) ...
- CAC的Debian-8-64bit安装BBR正确方式是?
裝过三台debian 64 bit, CAC, 2歐, KVM虛擬機 做法都一樣 0. 有裝銳速記得先刪除, 免得換核心後, 銳速在扯後腿 1.換4.9版kernel 有正式版 別裝啥rc版, 4.9 ...