娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

基于Linux的kfifo移植到STM32(支持os的互斥訪問)

發布者:Huanle最新更新時間:2019-12-14 來源: eefocus關鍵字:Linux  kfifo  移植  STM32  互斥訪問 手機看文章 掃描二維碼
隨時隨地手機看文章

關于kfifo

kfifo是內核里面的一個First In First Out數據結構,它采用環形循環隊列的數據結構來實現;它提供一個無邊界的字節流服務,最重要的一點是,它使用并行無鎖編程技術,即當它用于只有一個入隊線程和一個出隊線程的場情時,兩個線程可以并發操作,而不需要任何加鎖行為,就可以保證kfifo的線程安全。


具體什么是環形緩沖區,請看我以前的文章


說明

關于kfifo的相關概念我不會介紹,有興趣可以看他的相關文檔,我只將其實現過程移植重寫,移植到適用stm32開發板上,并且按照我個人習慣重新命名,RingBuff->意為環形緩沖區


RingBuff_t

環形緩沖區的結構體成員變量,具體含義看注釋。

buffer: 用于存放數據的緩存

size: buffer空間的大小

in, out: 和buffer一起構成一個循環隊列。 in指向buffer中隊頭,而且out指向buffer中的隊尾


typedef struct ringbuff 

{

uint8_t *buffer;  /* 數據區域 */

uint32_t size;      /* 環形緩沖區大小 */

uint32_t in;        /* 數據入隊指針 (in % size) */

uint32_t out;       /* 數據出隊指針 (out % size) */

#if USE_MUTEX

MUTEX_T *mutex;       /* 支持rtos的互斥 */

#endif

}RingBuff_t ;


Create_RingBuff

創建一個環形緩沖區,為了適應后續對緩沖區入隊出隊的高效操作,環形緩沖區的大小應為2^n字節,

如果不是這個大小,則系統默認裁剪以對應緩沖區字節。

當然還可以優化,不過我目前并未做,思路如下:如果系統支持動態分配內存,則向上對齊,避免浪費內存空間,否則就按照我默認的向下對齊,當內存越大,對齊導致內存泄漏則會越多。對齊采用的函數是roundup_pow_of_two。如果系統支持互斥量,那么還將創建一個互斥量用來做互斥訪問,防止多線程同時使用導致數據丟失。


/************************************************************

  * @brief   Create_RingBuff

  * @param   rb:環形緩沖區句柄

  *          buffer:環形緩沖區的數據區域

  *          size:環形緩沖區的大小,緩沖區大小要為2^n

  * @return  err_t:ERR_OK表示創建成功,其他表示失敗

  * @author  jiejie

  * @github  https://github.com/jiejieTop

  * @date    2018-xx-xx

  * @version v1.0

  * @note    用于創建一個環形緩沖區

  ***********************************************************/

err_t Create_RingBuff(RingBuff_t* rb, 

                      uint8_t *buffer,

                      uint32_t size

)

{

if((rb == NULL)||(buffer == NULL)||(size == 0))

{

PRINT_ERR("data is null!");

return ERR_NULL;

}

PRINT_DEBUG("ringbuff size is %d!",size);

/* 緩沖區大小必須為2^n字節,系統會強制轉換,

否則可能會導致指針訪問非法地址。

空間大小越大,強轉時丟失內存越多 */

if(size&(size - 1))

{

size = roundup_pow_of_two(size);

PRINT_DEBUG("change ringbuff size is %d!",size);

}


rb->buffer = buffer;

rb->size = size;

rb->in = rb->out = 0;

#if USE_MUTEX

  /* 創建信號量不成功 */

  if(!create_mutex(rb->mutex))

  {

    PRINT_ERR("create mutex fail!");

    ASSERT(ASSERT_ERR);

    return ERR_NOK;

  }

#endif

PRINT_DEBUG("create ringBuff ok!");

return ERR_OK;

}


roundup_pow_of_two

/************************************************************

  * @brief   roundup_pow_of_two

  * @param   size:傳遞進來的數據長度

  * @return  size:返回處理之后的數據長度

  * @author  jiejie

  * @github  https://github.com/jiejieTop

  * @date    2018-xx-xx

  * @version v1.0

  * @note    用于處理數據,使數據長度必須為 2^n

* 如果不是,則轉換,丟棄多余部分,如

* roundup_pow_of_two(66) -> 返回 64

  ***********************************************************/

static unsigned long roundup_pow_of_two(unsigned long x)

{

return (1 << (fls(x-1)-1)); //向下對齊

  //return (1UL << fls(x - 1)); //向上對齊,用動態內存可用使用

}


Delete_RingBuff

刪除一個環形緩沖區,刪除之后,緩沖區真正存儲地址是不會被改變的(目前我是使用自定義數組做緩沖區的),但是刪除之后,就無法對緩沖區進行讀寫操作。并且如果支持os的話,創建的互斥量會被刪除。


/************************************************************

  * @brief   Delete_RingBuff

  * @param   rb:環形緩沖區句柄

  * @return  err_t:ERR_OK表示成功,其他表示失敗

  * @author  jiejie

  * @github  https://github.com/jiejieTop

  * @date    2018-xx-xx

  * @version v1.0

  * @note    刪除一個環形緩沖區

  ***********************************************************/

err_t Delete_RingBuff(RingBuff_t *rb)

{

if(rb == NULL)

{

PRINT_ERR("ringbuff is null!");

return ERR_NULL;

}

rb->buffer = NULL;

rb->size = 0;

rb->in = rb->out = 0;

#if USE_MUTEX

  if(!deleta_mutex(rb->mutex))

  {

    PRINT_DEBUG("deleta mutex is fail!");

    return ERR_NOK;

  }

#endif

return ERR_OK;

}


Write_RingBuff

向環形緩沖區寫入指定數據,支持線程互斥訪問。用戶想要寫入緩沖區的數據長度不一定是真正入隊的長度,在完成的時候還要看看返回值是否與用戶需要的長度一致~

這個函數很有意思,也是比較高效的入隊操作,將指定區域的數據拷貝到指定的緩沖區中,過程看注釋即可


/************************************************************

  * @brief   Write_RingBuff

  * @param   rb:環形緩沖區句柄

  * @param   wbuff:寫入的數據起始地址

  * @param   len:寫入數據的長度(字節)

  * @return  len:實際寫入數據的長度(字節)

  * @author  jiejie

  * @github  https://github.com/jiejieTop

  * @date    2018-xx-xx

  * @version v1.0

  * @note    這個函數會從buff空間拷貝len字節長度的數據到

             rb環形緩沖區中的空閑空間。

  ***********************************************************/

uint32_t Write_RingBuff(RingBuff_t *rb,

                        uint8_t *wbuff, 

                        uint32_t len)

{

  uint32_t l;

#if USE_MUTEX

  /* 請求互斥量,成功才能進行ringbuff的訪問 */

  if(!request_mutex(rb->mutex))

  {

    PRINT_DEBUG("request mutex fail!");

    return 0;

  }

  else  /* 獲取互斥量成功 */

  {

#endif

    len = min(len, rb->size - rb->in + rb->out);


    /* 第一部分的拷貝:從環形緩沖區寫入數據直至緩沖區最后一個地址 */

    l = min(len, rb->size - (rb->in & (rb->size - 1)));

    memcpy(rb->buffer + (rb->in & (rb->size - 1)), wbuff, l);


    /* 如果溢出則在緩沖區頭寫入剩余的部分

       如果沒溢出這句代碼相當于無效 */

    memcpy(rb->buffer, wbuff + l, len - l);


    rb->in += len;

    

    PRINT_DEBUG("write ringBuff len is %d!",len);

#if USE_MUTEX

  }

  /* 釋放互斥量 */

  release_mutex(rb->mutex);

#endif

  return len;

}


Read_RingBuff

讀取緩沖區數據到指定區域,用戶指定讀取長度,用戶想要讀取的長度不一定是真正讀取的長度,在讀取完成的時候還要看看返回值是否與用戶需要的長度一致~也支持多線程互斥訪問。

也是緩沖區出隊的高效操作。過程看代碼注釋即可


/************************************************************

  * @brief   Read_RingBuff

  * @param   rb:環形緩沖區句柄

  * @param   wbuff:讀取數據保存的起始地址

  * @param   len:想要讀取數據的長度(字節)

  * @return  len:實際讀取數據的長度(字節)

  * @author  jiejie

  * @github  https://github.com/jiejieTop

  * @date    2018-xx-xx

  * @version v1.0

  * @note    這個函數會從rb環形緩沖區中的數據區域拷貝len字節

             長度的數據到rbuff空間。

  ***********************************************************/

uint32_t Read_RingBuff(RingBuff_t *rb,

                       uint8_t *rbuff, 

                       uint32_t len)

{

  uint32_t l;

#if USE_MUTEX

  /* 請求互斥量,成功才能進行ringbuff的訪問 */

  if(!request_mutex(rb->mutex))

  {

    PRINT_DEBUG("request mutex fail!");

    return 0;

  }

  else

  {

#endif

    len = min(len, rb->in - rb->out);


    /* 第一部分的拷貝:從環形緩沖區讀取數據直至緩沖區最后一個 */

    l = min(len, rb->size - (rb->out & (rb->size - 1)));

    memcpy(rbuff, rb->buffer + (rb->out & (rb->size - 1)), l);


    /* 如果溢出則在緩沖區頭讀取剩余的部分

       如果沒溢出這句代碼相當于無效 */

    memcpy(rbuff + l, rb->buffer, len - l);


    rb->out += len;

    

    PRINT_DEBUG("read ringBuff len is %d!",len);

#if USE_MUTEX

  }

  /* 釋放互斥量 */

  release_mutex(rb->mutex);

#endif

  return len;

}


獲取緩沖區信息

這些就比較簡單了,看看緩沖區可讀可寫的數據有多少


/************************************************************

  * @brief   CanRead_RingBuff

* @param   rb:環形緩沖區句柄

* @return  uint32:可讀數據長度 0 / len

  * @author  jiejie

  * @github  https://github.com/jiejieTop

  * @date    2018-xx-xx

  * @version v1.0

  * @note    可讀數據長度

  ***********************************************************/

uint32_t CanRead_RingBuff(RingBuff_t *rb)

{

if(NULL == rb)

{

PRINT_ERR("ringbuff is null!");

return 0;

}

if(rb->in == rb->out)

return 0;

if(rb->in > rb->out)

return (rb->in - rb->out);

return (rb->size - (rb->out - rb->in));

}


/************************************************************

  * @brief   CanRead_RingBuff

* @param   rb:環形緩沖區句柄

* @return  uint32:可寫數據長度 0 / len

  * @author  jiejie

  * @github  https://github.com/jiejieTop

  * @date    2018-xx-xx

  * @version v1.0

  * @note    可寫數據長度

  ***********************************************************/

uint32_t CanWrite_RingBuff(RingBuff_t *rb)

{

if(NULL == rb)

{

PRINT_ERR("ringbuff is null!");

return 0;

}


return (rb->size - CanRead_RingBuff(rb));

}


附帶

這里的代碼我是用于測試的,隨便寫的


RingBuff_t ringbuff_handle;

uint8_t rb[64];

uint8_t res[64];

Create_RingBuff(&ringbuff_handle, 

rb,

sizeof(rb));

Write_RingBuff(&ringbuff_handle,

                     res, 

                     datapack.data_length);

PRINT_DEBUG("CanRead_RingBuff = %d!",CanRead_RingBuff(&ringbuff_handle));

PRINT_DEBUG("CanWrite_RingBuff = %d!",CanWrite_RingBuff(&ringbuff_handle));

Read_RingBuff(&ringbuff_handle,

                     res, 

                     datapack.data_length);


支持多個os的互斥量操作

此處模仿了文件系統的互斥操作


#if USE_MUTEX

#define  MUTEX_TIMEOUT   1000     /* 超時時間 */

#define  MUTEX_T         mutex_t  /* 互斥量控制塊 */

#endif


/*********************************** mutex **************************************************/

[1] [2]
關鍵字:Linux  kfifo  移植  STM32  互斥訪問 引用地址:基于Linux的kfifo移植到STM32(支持os的互斥訪問)

上一篇:一種Cortex-M內核中的精確延時方法
下一篇:【干貨】老外的GitHub整理的stm32f4驅動庫

推薦閱讀最新更新時間:2025-05-03 10:39

OK6410A 開發板 (八) 7 linux-5.11 OK6410A usb camera移植
代碼 : https://github.com/lisider/linux/tree/ok6410a-linux-5.11 提交id : 0cf53aa024fbd417f0796a77ff7f9b891680dac8 defconfig : arch/arm/configs/ok6410A_sdboot_mini_net_lcd_x11_usb_debug_uvc_defconfig 用戶空間代碼 uvc_cam_test Makefile CROSS_COMPILE =arm-none-linux-gnueabi- KERNELDIR = CFLAGS = -I$(KERNELDIR)/include -O -Wa
[單片機]
rt-thread移植finSH控制臺中STM32 HAL庫的缺陷
小小的一個串口居然看了半天,原來對STM32系列的lib庫,好像是1.x版本感覺還不錯的。后來ST非要整個CUBEMx庫,往一個中斷接受函數里丟了一堆東西。 在rt-thread官網中給出了nano版本增加控制臺的示范例程,主要是增加了一個接受隊列。(如果用rt-thread studio配置控制臺,接受好像用的是查詢模式,如果只是單純一個控制臺,不干其他事情好像也沒啥事) #ifdef RT_USING_FINSH char rt_hw_console_getchar(void) { int ch = -1; if (__HAL_UART_GET_FLAG(&handle, UART_FLAG_RXNE) !=
[單片機]
Linux-2.6.32.2內核在mini2440上的移植(十四)---移植看門狗驅動
移植環境 1,主機環境:VMare下CentOS 5.5 ,1G內存。 2,集成開發環境:Elipse IDE 3,編譯編譯環境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。 4,開發板:mini2440,2M nor flash,128M nand flash。 5,u-boot版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,參考文章: 嵌入式linux應用開發完全手冊,韋東山,編著。 Mini2440 之Linux 移植開發實戰指南 Linux-2.6.32.2 內核具有完善的S3C2440 的看夢狗驅動,我們只需配
[單片機]
arm linux內核移植裁剪過程概覽
微處理器的產生為價格低廉、結構小巧的CPU和外設的連接提供了穩定可靠的硬件架構,這樣,限制嵌入式系統發展的瓶頸就突出表現在了軟件方面。盡管從八十年代末開始,已經陸續出現了一些嵌入式操作系統(比較著名的有Vxwork、pSOS、Neculeus和Windows CE)。但這些專用操作系統都是商業化產品,其高昂的價格使許多低端產品的小公司望而卻步;而且,源代碼封閉性也大大限制了開發者的積極性。而Linux的開放性,使得許多人都認為Linux非常適合多數Intemet設備。Linux操作系統可以支持不同的設備和不同的配置。Linux對廠商不偏不倚,而且成本極低,因而很快成為用于各種設備的操作系統。嵌入式linux是大勢所趨,其巨大的市場潛
[單片機]
基于linux-2.6.19內核的小型Linux系統制作移植
  引言   ARM9S3C2410微處理器與Linux的結合越來越緊密,逐漸在嵌入式領域得到廣范的應用。目前,在便攜式消費類電子產品、無線設備、汽車、網絡、存儲產品等都可以看到S3C2410與Linux相結合的身影。   S3C2410微處理器是一款由Samsung公司為手持終端設計的低價格、低功耗、高性能,基于ARM920T核的微處理器。它帶有內存管理單元(MMU),采用0.18mm工藝和AMBA新型總線結構,主頻可達203MHz。同時,它支持Thumb 16位壓縮指令集,從而能以較小的存儲空間獲得32位的系統性能。   在眾多嵌入式操作系統中,Linux目前發展最快、應用最為廣泛 。性能優良、源碼開放的Linux具有體
[單片機]
利用MLD自動化操作系統移植降低Linux的成本
隨著基于 Linux 的嵌入式系統得到日益廣泛的應用,人們不禁要問,類似 Linux 這樣的免費開放源代碼操作系統的真正成本到底是多少?其實,最主要的成本是在勞動力上。要將 Linux 內核移植到定制嵌入式處理系統,您必須對產品所需要的內核功能、這些功能對其他內核服務的依賴程度以及您的工程團隊的技能都有深入的了解。更重要的是,要了解可以借助哪些新技術來使這些任務自動化,以達到節省成本的目標。 開放源代碼與商業操作系統 我們很多人都看過為如何使用 Linux 源代碼提供指導的 GNU 通用公共許可證 (GPL)。要確定在系統中使用 Linux 的成本,一般來說,第一步是了解 Linux 的哪些部分是真正免費且不受法律約束的,哪些
[嵌入式]
imx6ull之根文件系統busybox移植
開發板:飛凌 OKMX6ULL-S + 7寸電阻屏 交叉編譯工具鏈:gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf busybox: busybox-1.32.1.tar.bz2 一、busybox移植   1、上傳并解壓busybox-1.32.1.tar.bz2:tar -jxvf busybox-1.32.1.tar.bz2   2、修改Makefile     164 CROSS_COMPILE ?= arm-linux-gnueabihf-     190 ARCH ?= arm   3、配置     make menuconfig     Settings -
[單片機]
imx6ull之根文件系統busybox<font color='red'>移植</font>
移植u-boot-2010.03問題 --- 網卡DM9000
1,找到u-boot-2010.03/include/configs/smdk6410.h //#define CONFIG_NET_MULTI //#define CONFIG_CS8900 /*we have aCS8900on-board*/ //#define CONFIG_CS8900_BASE 0x18800300 //#define CONFIG_CS8900_BUS16 /*follow the Linux driver*/ /**然后添加DM9000網卡的宏定義---ip以及子網掩碼等根據自己的需要修改***/ #defineCONFIG_NET_MULTI 1 #defineCONFIG_DM900
[單片機]
小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京B2-20211791 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 徐闻县| 新乡市| 论坛| 皋兰县| 永丰县| 昌黎县| 元朗区| 科尔| 乐清市| 乐业县| 肥乡县| 丰城市| 金门县| 岐山县| 司法| 阿坝| 孝义市| 延寿县| 鄱阳县| 奉新县| 潢川县| 富民县| 三门县| 霞浦县| 孙吴县| 南平市| 宜丰县| 冀州市| 封开县| 瓦房店市| 寿宁县| 唐山市| 收藏| 平山县| 武穴市| 和龙市| 拜泉县| 禄丰县| 山东省| 富宁县| 丽水市|