那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

i.MX6ULL|并發(fā)與競爭實(shí)驗(yàn)

玩轉(zhuǎn)單片機(jī) ? 來源:玩轉(zhuǎn)單片機(jī) ? 2023-08-02 15:40 ? 次閱讀

常用的處理并發(fā)和競爭的機(jī)制有四種,原子操作、自旋鎖、信號量和互斥體。下邊就通過編寫驅(qū)動來實(shí)現(xiàn),展示一下相關(guān)效果。當(dāng)前臺的應(yīng)用一直運(yùn)行,控制臺是不能輸入指令,測試并發(fā)與競爭最好是在后臺運(yùn)行,而解決并非與競爭最直接的手段就是只允許一個應(yīng)用去調(diào)用相關(guān)資源,這里為了好展示效果就通過任務(wù)運(yùn)行來體現(xiàn)。下面的實(shí)驗(yàn)使用了新字符驅(qū)動GPIO源碼,只需要復(fù)制一份即可使用。

|原子操作

驅(qū)動源碼

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

/*添加頭文件*/
#include
#include
#include
#include

#defineCHRDEVBASE_CNT1/*設(shè)備號個數(shù)*/
#defineCHRDEVBASE_NAME"chrdevbase"/*名字*/

#defineLEDOFF0/*關(guān)燈*/
#defineLEDON1/*開燈*/

/*chrdevbase設(shè)備結(jié)構(gòu)體*/
structnewchr_dev{
dev_tdevid;/*設(shè)備號*/
structcdevcdev;/*cdev*/
structclass*class;/*類*/
structdevice*device;/*設(shè)備*/
intmajor;/*主設(shè)備號*/
intminor;/*次設(shè)備號*/
structdevice_node*nd;/*設(shè)備節(jié)點(diǎn)*/
intled_gpio;/*led所使用的GPIO編號*/

atomic_tlock;/*原子變量*/
};

structnewchr_devchrdevbase;/*自定義字符設(shè)備*/

/*
*@description:LED硬件初始化
*@param:無
*@return:無
*/
staticintled_hal_init(void)
{
intret=0;

/*設(shè)置LED所使用的GPIO*/
/* 1、獲取設(shè)備節(jié)點(diǎn):gpioled */
chrdevbase.nd=of_find_node_by_path("/gpioled");
if(chrdevbase.nd==NULL){
printk("chrdevbasenodecantnotfound!
");
return-EINVAL;
}else{
printk("chrdevbasenodehasbeenfound!
");
}

/*2、獲取設(shè)備樹中的gpio屬性,得到LED所使用的LED編號*/
chrdevbase.led_gpio=of_get_named_gpio(chrdevbase.nd,"led-gpio",0);
if(chrdevbase.led_gpio0){
printk("can'tgetled-gpio");
return-EINVAL;
}
printk("led-gpionum=%d
",chrdevbase.led_gpio);

/*3、設(shè)置GPIO1_IO03為輸出,并且輸出高電平,默認(rèn)關(guān)閉LED燈*/
ret=gpio_direction_output(chrdevbase.led_gpio,1);
if(ret0){
printk("can'tsetgpio!
");
}

return0;
}

/*
*@description:打開設(shè)備
*@param-inode:傳遞給驅(qū)動的inode
*@param-filp:設(shè)備文件,file結(jié)構(gòu)體有個叫做private_data的成員變量
*一般在open的時候?qū)rivate_data指向設(shè)備結(jié)構(gòu)體。
*@return:0成功;其他失敗
*/
staticintchrdevbase_open(structinode*inode,structfile*filp)
{
/*通過判斷原子變量的值來檢查LED有沒有被別的應(yīng)用使用*/
if(!atomic_dec_and_test(&chrdevbase.lock))
{
atomic_inc(&chrdevbase.lock);/*小于0的話就加1,使其原子變量等于0*/
return-EBUSY;/*LED被使用,返回忙*/
}
printk("[BSP]chrdevbaseopen!
");
filp->private_data=&chrdevbase;/*設(shè)置私有數(shù)據(jù)*/
return0;
}

/*
*@description:從設(shè)備讀取數(shù)據(jù)
*@param-filp:要打開的設(shè)備文件(文件描述符)
*@param-buf:返回給用戶空間的數(shù)據(jù)緩沖區(qū)
*@param-cnt:要讀取的數(shù)據(jù)長度
*@param-offt:相對于文件首地址的偏移
*@return:讀取的字節(jié)數(shù),如果為負(fù)值,表示讀取失敗
*/
staticssize_tchrdevbase_read(structfile*filp,char__user*buf,size_tcnt,loff_t*offt)
{
printk("chrdevbaseread!
");
return0;
}

/*
*@description:向設(shè)備寫數(shù)據(jù)
*@param-filp:設(shè)備文件,表示打開的文件描述符
*@param-buf:要寫給設(shè)備寫入的數(shù)據(jù)
*@param-cnt:要寫入的數(shù)據(jù)長度
*@param-offt:相對于文件首地址的偏移
*@return:寫入的字節(jié)數(shù),如果為負(fù)值,表示寫入失敗
*/
staticssize_tchrdevbase_write(structfile*filp,constchar__user*buf,size_tcnt,loff_t*offt)
{
intretvalue=0;
charwritebuf[1];
structnewchr_dev*dev=filp->private_data;

/*接收用戶空間傳遞給內(nèi)核的數(shù)據(jù)并且打印出來*/
retvalue=copy_from_user(writebuf,buf,cnt);
printk("[BSP]kernelrecevdatadata:%d!
",writebuf[0]);

if(writebuf[0]==LEDON){
gpio_set_value(dev->led_gpio,0);/*打開LED燈*/
}elseif(writebuf[0]==LEDOFF){
gpio_set_value(dev->led_gpio,1);/*關(guān)閉LED燈*/
}

//printk("chrdevbasewrite!
");
return0;
}

/*
*@description:關(guān)閉/釋放設(shè)備
*@param-filp:要關(guān)閉的設(shè)備文件(文件描述符)
*@return:0成功;其他失敗
*/
staticintchrdevbase_release(structinode*inode,structfile*filp)
{
structnewchr_dev*dev=filp->private_data;
/*關(guān)閉驅(qū)動文件的時候釋放原子變量*/
atomic_inc(&dev->lock);
printk("[BSP]release!
");
return0;
}

/*
*設(shè)備操作函數(shù)結(jié)構(gòu)體
*/
staticstructfile_operationschrdevbase_fops={
.owner=THIS_MODULE,
.open=chrdevbase_open,
.read=chrdevbase_read,
.write=chrdevbase_write,
.release=chrdevbase_release,
};

/*
*@description:驅(qū)動入口函數(shù)
*@param:無
*@return:0成功;其他失敗
*/
staticint__initchrdevbase_init(void)
{
/*初始化原子變量*/
atomic_set(&chrdevbase.lock,1);/*原子變量初始值為1*/

/*初始化硬件*/
led_hal_init();

/*注冊字符設(shè)備驅(qū)動*/
/*1、創(chuàng)建設(shè)備號*/
if(chrdevbase.major){/*定義了設(shè)備號*/
chrdevbase.devid=MKDEV(chrdevbase.major,0);
register_chrdev_region(chrdevbase.devid,CHRDEVBASE_CNT,CHRDEVBASE_NAME);
}else{/*沒有定義設(shè)備號*/
alloc_chrdev_region(&chrdevbase.devid,0,CHRDEVBASE_CNT,CHRDEVBASE_NAME);/*申請?jiān)O(shè)備號*/
chrdevbase.major=MAJOR(chrdevbase.devid);/*獲取主設(shè)備號*/
chrdevbase.minor=MINOR(chrdevbase.devid);/*獲取次設(shè)備號*/
}
printk("newcheledmajor=%d,minor=%d
",chrdevbase.major,chrdevbase.minor);

/*2、初始化cdev*/
chrdevbase.cdev.owner=THIS_MODULE;
cdev_init(&chrdevbase.cdev,&chrdevbase_fops);

/*3、添加一個cdev*/
cdev_add(&chrdevbase.cdev,chrdevbase.devid,CHRDEVBASE_CNT);

/*4、創(chuàng)建類*/
chrdevbase.class=class_create(THIS_MODULE,CHRDEVBASE_NAME);
if(IS_ERR(chrdevbase.class)){
returnPTR_ERR(chrdevbase.class);
}

/*5、創(chuàng)建設(shè)備*/
chrdevbase.device=device_create(chrdevbase.class,NULL,chrdevbase.devid,NULL,CHRDEVBASE_NAME);
if(IS_ERR(chrdevbase.device)){
returnPTR_ERR(chrdevbase.device);
}

return0;
}

/*
*@description:驅(qū)動出口函數(shù)
*@param:無
*@return:無
*/
staticvoid__exitchrdevbase_exit(void)
{
/*注銷字符設(shè)備*/
cdev_del(&chrdevbase.cdev);/*刪除cdev*/
unregister_chrdev_region(chrdevbase.devid,CHRDEVBASE_CNT);/*注銷設(shè)備號*/

device_destroy(chrdevbase.class,chrdevbase.devid);/*銷毀設(shè)備*/
class_destroy(chrdevbase.class);/*銷毀類*/

printk("[BSP]chrdevbaseexit!
");
}

/*
*將上面兩個函數(shù)指定為驅(qū)動的入口和出口函數(shù)
*/
module_init(chrdevbase_init);
module_exit(chrdevbase_exit);

/*
*LICENSE和作者信息
*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zuozhongkai");

應(yīng)用源碼

#include"stdio.h"
#include"unistd.h"
#include"sys/types.h"
#include"sys/stat.h"
#include"fcntl.h"
#include"stdlib.h"
#include"string.h"

/*
*@description:main主程序
*@param-argc:argv數(shù)組元素個數(shù)
*@param-argv:具體參數(shù)
*@return:0成功;其他失敗
*/
intmain(intargc,char*argv[])
{
intfd,retvalue;
char*filename;
charwritebuf[100];
unsignedchardatabuf[1];
unsignedcharcnt=0;

if(argc!=3){
printf("[APP]ErrorUsage!
");
return-1;
}

filename=argv[1];

/*打開驅(qū)動文件*/
fd=open(filename,O_RDWR);
if(fd0){
printf("[APP]Can'topenfile%s
",filename);
return-1;
}

/*把第三個參數(shù)賦值給databuf*/
databuf[0]=atoi(argv[2]);

/*向設(shè)備驅(qū)動寫數(shù)據(jù)*/
memcpy(writebuf,databuf,sizeof(databuf));
retvalue=write(fd,writebuf,sizeof(databuf));
if(retvalue0){
printf("[APP]writefile%sfailed!
",filename);
}

/*模擬占用25SLED*/
while(1)
{
sleep(5);
cnt++;
printf("Apprunningtimes:%d
",cnt);
if(cnt>=5)break;
}
printf("Apprunningfinished!");

/*關(guān)閉設(shè)備*/
retvalue=close(fd);
if(retvalue0){
printf("[APP]Can'tclosefile%s
",filename);
return-1;
}

return0;
}

實(shí)驗(yàn)現(xiàn)象

加了原子操作后,應(yīng)用程序運(yùn)行時,再次觸發(fā)是不能運(yùn)行的,這就解決了在復(fù)雜環(huán)境下的并發(fā)和競爭的問題。注意不加“&”表示直接運(yùn)行,控制臺不能輸入指令,加了“&”表示后臺運(yùn)行,可以繼續(xù)輸入指令。

baf1cecc-3083-11ee-9e74-dac502259ad0.png

套路分析

1、先在結(jié)構(gòu)體定義一個變量

/*chrdevbase設(shè)備結(jié)構(gòu)體*/
structnewchr_dev{
......
atomic_tlock;/*原子變量*/
};

2、在驅(qū)動入口初始化原子變量

/*
*@description:驅(qū)動入口函數(shù)
*@param:無
*@return:0成功;其他失敗
*/
staticint__initchrdevbase_init(void)
{
/*初始化原子變量*/
atomic_set(&chrdevbase.lock,1);/*原子變量初始值為1*/
......
return0;
}

3、在打開設(shè)備時判斷原子變量

/*
*@description:打開設(shè)備
*@param-inode:傳遞給驅(qū)動的inode
*@param-filp:設(shè)備文件,file結(jié)構(gòu)體有個叫做private_data的成員變量
*一般在open的時候?qū)rivate_data指向設(shè)備結(jié)構(gòu)體。
*@return:0成功;其他失敗
*/
staticintchrdevbase_open(structinode*inode,structfile*filp)
{
/*通過判斷原子變量的值來檢查LED有沒有被別的應(yīng)用使用*/
if(!atomic_dec_and_test(&chrdevbase.lock))
{
atomic_inc(&chrdevbase.lock);/*小于0的話就加1,使其原子變量等于0*/
return-EBUSY;/*LED被使用,返回忙*/
}
......
return0;
}

4、在釋放設(shè)備時釋放原子變量

/*
*@description:關(guān)閉/釋放設(shè)備
*@param-filp:要關(guān)閉的設(shè)備文件(文件描述符)
*@return:0成功;其他失敗
*/
staticintchrdevbase_release(structinode*inode,structfile*filp)
{
structnewchr_dev*dev=filp->private_data;
/*關(guān)閉驅(qū)動文件的時候釋放原子變量*/
atomic_inc(&dev->lock);
......
return0;
}

| 自旋鎖

驅(qū)動源碼

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

/*添加頭文件*/
#include
#include
#include
#include

#defineCHRDEVBASE_CNT1/*設(shè)備號個數(shù)*/
#defineCHRDEVBASE_NAME"chrdevbase"/*名字*/

#defineLEDOFF0/*關(guān)燈*/
#defineLEDON1/*開燈*/

/*chrdevbase設(shè)備結(jié)構(gòu)體*/
structnewchr_dev{
dev_tdevid;/*設(shè)備號*/
structcdevcdev;/*cdev*/
structclass*class;/*類*/
structdevice*device;/*設(shè)備*/
intmajor;/*主設(shè)備號*/
intminor;/*次設(shè)備號*/
structdevice_node*nd;/*設(shè)備節(jié)點(diǎn)*/
intled_gpio;/*led所使用的GPIO編號*/

intdev_stats;/*設(shè)備狀態(tài),0,設(shè)備未使用;>0,設(shè)備已經(jīng)被使用*/
spinlock_tlock;/*自旋鎖*/
};

structnewchr_devchrdevbase;/*自定義字符設(shè)備*/

/*
*@description:LED硬件初始化
*@param:無
*@return:無
*/
staticintled_hal_init(void)
{
intret=0;

/*設(shè)置LED所使用的GPIO*/
/* 1、獲取設(shè)備節(jié)點(diǎn):gpioled */
chrdevbase.nd=of_find_node_by_path("/gpioled");
if(chrdevbase.nd==NULL){
printk("chrdevbasenodecantnotfound!
");
return-EINVAL;
}else{
printk("chrdevbasenodehasbeenfound!
");
}

/*2、獲取設(shè)備樹中的gpio屬性,得到LED所使用的LED編號*/
chrdevbase.led_gpio=of_get_named_gpio(chrdevbase.nd,"led-gpio",0);
if(chrdevbase.led_gpio0){
printk("can'tgetled-gpio");
return-EINVAL;
}
printk("led-gpionum=%d
",chrdevbase.led_gpio);

/*3、設(shè)置GPIO1_IO03為輸出,并且輸出高電平,默認(rèn)關(guān)閉LED燈*/
ret=gpio_direction_output(chrdevbase.led_gpio,1);
if(ret0){
printk("can'tsetgpio!
");
}

return0;
}

/*
*@description:打開設(shè)備
*@param-inode:傳遞給驅(qū)動的inode
*@param-filp:設(shè)備文件,file結(jié)構(gòu)體有個叫做private_data的成員變量
*一般在open的時候?qū)rivate_data指向設(shè)備結(jié)構(gòu)體。
*@return:0成功;其他失敗
*/
staticintchrdevbase_open(structinode*inode,structfile*filp)
{
unsignedlongflags;
filp->private_data=&chrdevbase;/*設(shè)置私有數(shù)據(jù)*/

spin_lock_irqsave(&chrdevbase.lock,flags);/*上鎖*/
if(chrdevbase.dev_stats){/*如果設(shè)備被使用了*/
spin_unlock_irqrestore(&chrdevbase.lock,flags);/*解鎖*/
return-EBUSY;
}
chrdevbase.dev_stats++;/*如果設(shè)備沒有打開,那么就標(biāo)記已經(jīng)打開了*/
spin_unlock_irqrestore(&chrdevbase.lock,flags);/*解鎖*/

printk("[BSP]chrdevbaseopen!
");
return0;
}

/*
*@description:從設(shè)備讀取數(shù)據(jù)
*@param-filp:要打開的設(shè)備文件(文件描述符)
*@param-buf:返回給用戶空間的數(shù)據(jù)緩沖區(qū)
*@param-cnt:要讀取的數(shù)據(jù)長度
*@param-offt:相對于文件首地址的偏移
*@return:讀取的字節(jié)數(shù),如果為負(fù)值,表示讀取失敗
*/
staticssize_tchrdevbase_read(structfile*filp,char__user*buf,size_tcnt,loff_t*offt)
{
printk("chrdevbaseread!
");
return0;
}

/*
*@description:向設(shè)備寫數(shù)據(jù)
*@param-filp:設(shè)備文件,表示打開的文件描述符
*@param-buf:要寫給設(shè)備寫入的數(shù)據(jù)
*@param-cnt:要寫入的數(shù)據(jù)長度
*@param-offt:相對于文件首地址的偏移
*@return:寫入的字節(jié)數(shù),如果為負(fù)值,表示寫入失敗
*/
staticssize_tchrdevbase_write(structfile*filp,constchar__user*buf,size_tcnt,loff_t*offt)
{
intretvalue=0;
charwritebuf[1];
structnewchr_dev*dev=filp->private_data;

/*接收用戶空間傳遞給內(nèi)核的數(shù)據(jù)并且打印出來*/
retvalue=copy_from_user(writebuf,buf,cnt);
printk("[BSP]kernelrecevdatadata:%d!
",writebuf[0]);

if(writebuf[0]==LEDON){
gpio_set_value(dev->led_gpio,0);/*打開LED燈*/
}elseif(writebuf[0]==LEDOFF){
gpio_set_value(dev->led_gpio,1);/*關(guān)閉LED燈*/
}

//printk("chrdevbasewrite!
");
return0;
}

/*
*@description:關(guān)閉/釋放設(shè)備
*@param-filp:要關(guān)閉的設(shè)備文件(文件描述符)
*@return:0成功;其他失敗
*/
staticintchrdevbase_release(structinode*inode,structfile*filp)
{
unsignedlongflags;
structnewchr_dev*dev=filp->private_data;
/*關(guān)閉驅(qū)動文件的時候?qū)ev_stats減1*/
spin_lock_irqsave(&dev->lock,flags);/*上鎖*/
if(dev->dev_stats){
dev->dev_stats--;
}
spin_unlock_irqrestore(&dev->lock,flags);/*解鎖*/

printk("[BSP]release!
");
return0;
}

/*
*設(shè)備操作函數(shù)結(jié)構(gòu)體
*/
staticstructfile_operationschrdevbase_fops={
.owner=THIS_MODULE,
.open=chrdevbase_open,
.read=chrdevbase_read,
.write=chrdevbase_write,
.release=chrdevbase_release,
};

/*
*@description:驅(qū)動入口函數(shù)
*@param:無
*@return:0成功;其他失敗
*/
staticint__initchrdevbase_init(void)
{
/*初始化自旋鎖*/
spin_lock_init(&chrdevbase.lock);

/*初始化硬件*/
led_hal_init();

/*注冊字符設(shè)備驅(qū)動*/
/*1、創(chuàng)建設(shè)備號*/
if(chrdevbase.major){/*定義了設(shè)備號*/
chrdevbase.devid=MKDEV(chrdevbase.major,0);
register_chrdev_region(chrdevbase.devid,CHRDEVBASE_CNT,CHRDEVBASE_NAME);
}else{/*沒有定義設(shè)備號*/
alloc_chrdev_region(&chrdevbase.devid,0,CHRDEVBASE_CNT,CHRDEVBASE_NAME);/*申請?jiān)O(shè)備號*/
chrdevbase.major=MAJOR(chrdevbase.devid);/*獲取主設(shè)備號*/
chrdevbase.minor=MINOR(chrdevbase.devid);/*獲取次設(shè)備號*/
}
printk("newcheledmajor=%d,minor=%d
",chrdevbase.major,chrdevbase.minor);

/*2、初始化cdev*/
chrdevbase.cdev.owner=THIS_MODULE;
cdev_init(&chrdevbase.cdev,&chrdevbase_fops);

/*3、添加一個cdev*/
cdev_add(&chrdevbase.cdev,chrdevbase.devid,CHRDEVBASE_CNT);

/*4、創(chuàng)建類*/
chrdevbase.class=class_create(THIS_MODULE,CHRDEVBASE_NAME);
if(IS_ERR(chrdevbase.class)){
returnPTR_ERR(chrdevbase.class);
}

/*5、創(chuàng)建設(shè)備*/
chrdevbase.device=device_create(chrdevbase.class,NULL,chrdevbase.devid,NULL,CHRDEVBASE_NAME);
if(IS_ERR(chrdevbase.device)){
returnPTR_ERR(chrdevbase.device);
}

return0;
}

/*
*@description:驅(qū)動出口函數(shù)
*@param:無
*@return:無
*/
staticvoid__exitchrdevbase_exit(void)
{
/*注銷字符設(shè)備*/
cdev_del(&chrdevbase.cdev);/*刪除cdev*/
unregister_chrdev_region(chrdevbase.devid,CHRDEVBASE_CNT);/*注銷設(shè)備號*/

device_destroy(chrdevbase.class,chrdevbase.devid);/*銷毀設(shè)備*/
class_destroy(chrdevbase.class);/*銷毀類*/

printk("[BSP]chrdevbaseexit!
");
}

/*
*將上面兩個函數(shù)指定為驅(qū)動的入口和出口函數(shù)
*/
module_init(chrdevbase_init);
module_exit(chrdevbase_exit);

/*
*LICENSE和作者信息
*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zuozhongkai");

應(yīng)用源碼

和原子操作應(yīng)用源碼一樣,不需要修改!

實(shí)驗(yàn)現(xiàn)象

bb468e58-3083-11ee-9e74-dac502259ad0.png

套路分析

自旋鎖和RTOS中的臨界保護(hù)有點(diǎn)類似,套路分析如下:

1、在結(jié)構(gòu)體加入自旋鎖變量和一個狀態(tài)變量

/*chrdevbase設(shè)備結(jié)構(gòu)體*/
structnewchr_dev{
......
intdev_stats;/*設(shè)備狀態(tài),0,設(shè)備未使用;>0,設(shè)備已經(jīng)被使用*/
spinlock_tlock;/*自旋鎖*/
};

2、在驅(qū)動入口初始化自旋鎖

/*
*@description:驅(qū)動入口函數(shù)
*@param:無
*@return:0成功;其他失敗
*/
staticint__initchrdevbase_init(void)
{
/*初始化自旋鎖*/
spin_lock_init(&chrdevbase.lock);
......
return0;
}

3、在打開設(shè)備時判斷設(shè)備是否被使用

/*
*@description:打開設(shè)備
*@param-inode:傳遞給驅(qū)動的inode
*@param-filp:設(shè)備文件,file結(jié)構(gòu)體有個叫做private_data的成員變量
*一般在open的時候?qū)rivate_data指向設(shè)備結(jié)構(gòu)體。
*@return:0成功;其他失敗
*/
staticintchrdevbase_open(structinode*inode,structfile*filp)
{
unsignedlongflags;
filp->private_data=&chrdevbase;/*設(shè)置私有數(shù)據(jù)*/

spin_lock_irqsave(&chrdevbase.lock,flags);/*上鎖*/
if(chrdevbase.dev_stats){/*如果設(shè)備被使用了*/
spin_unlock_irqrestore(&chrdevbase.lock,flags);/*解鎖*/
return-EBUSY;
}
chrdevbase.dev_stats++;/*如果設(shè)備沒有打開,那么就標(biāo)記已經(jīng)打開了*/
spin_unlock_irqrestore(&chrdevbase.lock,flags);/*解鎖*/

......
return0;
}

4、在釋放設(shè)備時對狀態(tài)變量自減

/*
*@description:關(guān)閉/釋放設(shè)備
*@param-filp:要關(guān)閉的設(shè)備文件(文件描述符)
*@return:0成功;其他失敗
*/
staticintchrdevbase_release(structinode*inode,structfile*filp)
{
unsignedlongflags;
structnewchr_dev*dev=filp->private_data;
/*關(guān)閉驅(qū)動文件的時候?qū)ev_stats減1*/
spin_lock_irqsave(&dev->lock,flags);/*上鎖*/
if(dev->dev_stats){
dev->dev_stats--;
}
spin_unlock_irqrestore(&dev->lock,flags);/*解鎖*/

printk("[BSP]release!
");
return0;
}

| 信號量

驅(qū)動源碼

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

/*添加頭文件*/
#include
#include
#include
#include

#defineCHRDEVBASE_CNT1/*設(shè)備號個數(shù)*/
#defineCHRDEVBASE_NAME"chrdevbase"/*名字*/

#defineLEDOFF0/*關(guān)燈*/
#defineLEDON1/*開燈*/

/*chrdevbase設(shè)備結(jié)構(gòu)體*/
structnewchr_dev{
dev_tdevid;/*設(shè)備號*/
structcdevcdev;/*cdev*/
structclass*class;/*類*/
structdevice*device;/*設(shè)備*/
intmajor;/*主設(shè)備號*/
intminor;/*次設(shè)備號*/
structdevice_node*nd;/*設(shè)備節(jié)點(diǎn)*/
intled_gpio;/*led所使用的GPIO編號*/

structsemaphoresem;/*信號量*/
};

structnewchr_devchrdevbase;/*自定義字符設(shè)備*/

/*
*@description:LED硬件初始化
*@param:無
*@return:無
*/
staticintled_hal_init(void)
{
intret=0;

/*設(shè)置LED所使用的GPIO*/
/* 1、獲取設(shè)備節(jié)點(diǎn):gpioled */
chrdevbase.nd=of_find_node_by_path("/gpioled");
if(chrdevbase.nd==NULL){
printk("chrdevbasenodecantnotfound!
");
return-EINVAL;
}else{
printk("chrdevbasenodehasbeenfound!
");
}

/*2、獲取設(shè)備樹中的gpio屬性,得到LED所使用的LED編號*/
chrdevbase.led_gpio=of_get_named_gpio(chrdevbase.nd,"led-gpio",0);
if(chrdevbase.led_gpio0){
printk("can'tgetled-gpio");
return-EINVAL;
}
printk("led-gpionum=%d
",chrdevbase.led_gpio);

/*3、設(shè)置GPIO1_IO03為輸出,并且輸出高電平,默認(rèn)關(guān)閉LED燈*/
ret=gpio_direction_output(chrdevbase.led_gpio,1);
if(ret0){
printk("can'tsetgpio!
");
}

return0;
}

/*
*@description:打開設(shè)備
*@param-inode:傳遞給驅(qū)動的inode
*@param-filp:設(shè)備文件,file結(jié)構(gòu)體有個叫做private_data的成員變量
*一般在open的時候?qū)rivate_data指向設(shè)備結(jié)構(gòu)體。
*@return:0成功;其他失敗
*/
staticintchrdevbase_open(structinode*inode,structfile*filp)
{
printk("[BSP]chrdevbaseopen!
");
filp->private_data=&chrdevbase;/*設(shè)置私有數(shù)據(jù)*/

/*獲取信號量,進(jìn)入休眠狀態(tài)的進(jìn)程可以被信號打斷*/
if(down_interruptible(&chrdevbase.sem)){
return-ERESTARTSYS;
}
#if0
down(&chrdevbase.sem);/*不能被信號打斷*/
#endif
return0;
}

/*
*@description:從設(shè)備讀取數(shù)據(jù)
*@param-filp:要打開的設(shè)備文件(文件描述符)
*@param-buf:返回給用戶空間的數(shù)據(jù)緩沖區(qū)
*@param-cnt:要讀取的數(shù)據(jù)長度
*@param-offt:相對于文件首地址的偏移
*@return:讀取的字節(jié)數(shù),如果為負(fù)值,表示讀取失敗
*/
staticssize_tchrdevbase_read(structfile*filp,char__user*buf,size_tcnt,loff_t*offt)
{
printk("chrdevbaseread!
");
return0;
}

/*
*@description:向設(shè)備寫數(shù)據(jù)
*@param-filp:設(shè)備文件,表示打開的文件描述符
*@param-buf:要寫給設(shè)備寫入的數(shù)據(jù)
*@param-cnt:要寫入的數(shù)據(jù)長度
*@param-offt:相對于文件首地址的偏移
*@return:寫入的字節(jié)數(shù),如果為負(fù)值,表示寫入失敗
*/
staticssize_tchrdevbase_write(structfile*filp,constchar__user*buf,size_tcnt,loff_t*offt)
{
intretvalue=0;
charwritebuf[1];
structnewchr_dev*dev=filp->private_data;

/*接收用戶空間傳遞給內(nèi)核的數(shù)據(jù)并且打印出來*/
retvalue=copy_from_user(writebuf,buf,cnt);
printk("[BSP]kernelrecevdatadata:%d!
",writebuf[0]);

if(writebuf[0]==LEDON){
gpio_set_value(dev->led_gpio,0);/*打開LED燈*/
}elseif(writebuf[0]==LEDOFF){
gpio_set_value(dev->led_gpio,1);/*關(guān)閉LED燈*/
}

//printk("chrdevbasewrite!
");
return0;
}

/*
*@description:關(guān)閉/釋放設(shè)備
*@param-filp:要關(guān)閉的設(shè)備文件(文件描述符)
*@return:0成功;其他失敗
*/
staticintchrdevbase_release(structinode*inode,structfile*filp)
{
structnewchr_dev*dev=filp->private_data;
up(&dev->sem);/*釋放信號量,信號量值加1*/
printk("[BSP]release!
");
return0;
}

/*
*設(shè)備操作函數(shù)結(jié)構(gòu)體
*/
staticstructfile_operationschrdevbase_fops={
.owner=THIS_MODULE,
.open=chrdevbase_open,
.read=chrdevbase_read,
.write=chrdevbase_write,
.release=chrdevbase_release,
};

/*
*@description:驅(qū)動入口函數(shù)
*@param:無
*@return:0成功;其他失敗
*/
staticint__initchrdevbase_init(void)
{
/*初始化信號量*/
sema_init(&chrdevbase.sem,1);

/*初始化硬件*/
led_hal_init();

/*注冊字符設(shè)備驅(qū)動*/
/*1、創(chuàng)建設(shè)備號*/
if(chrdevbase.major){/*定義了設(shè)備號*/
chrdevbase.devid=MKDEV(chrdevbase.major,0);
register_chrdev_region(chrdevbase.devid,CHRDEVBASE_CNT,CHRDEVBASE_NAME);
}else{/*沒有定義設(shè)備號*/
alloc_chrdev_region(&chrdevbase.devid,0,CHRDEVBASE_CNT,CHRDEVBASE_NAME);/*申請?jiān)O(shè)備號*/
chrdevbase.major=MAJOR(chrdevbase.devid);/*獲取主設(shè)備號*/
chrdevbase.minor=MINOR(chrdevbase.devid);/*獲取次設(shè)備號*/
}
printk("newcheledmajor=%d,minor=%d
",chrdevbase.major,chrdevbase.minor);

/*2、初始化cdev*/
chrdevbase.cdev.owner=THIS_MODULE;
cdev_init(&chrdevbase.cdev,&chrdevbase_fops);

/*3、添加一個cdev*/
cdev_add(&chrdevbase.cdev,chrdevbase.devid,CHRDEVBASE_CNT);

/*4、創(chuàng)建類*/
chrdevbase.class=class_create(THIS_MODULE,CHRDEVBASE_NAME);
if(IS_ERR(chrdevbase.class)){
returnPTR_ERR(chrdevbase.class);
}

/*5、創(chuàng)建設(shè)備*/
chrdevbase.device=device_create(chrdevbase.class,NULL,chrdevbase.devid,NULL,CHRDEVBASE_NAME);
if(IS_ERR(chrdevbase.device)){
returnPTR_ERR(chrdevbase.device);
}

return0;
}

/*
*@description:驅(qū)動出口函數(shù)
*@param:無
*@return:無
*/
staticvoid__exitchrdevbase_exit(void)
{
/*注銷字符設(shè)備*/
cdev_del(&chrdevbase.cdev);/*刪除cdev*/
unregister_chrdev_region(chrdevbase.devid,CHRDEVBASE_CNT);/*注銷設(shè)備號*/

device_destroy(chrdevbase.class,chrdevbase.devid);/*銷毀設(shè)備*/
class_destroy(chrdevbase.class);/*銷毀類*/

printk("[BSP]chrdevbaseexit!
");
}

/*
*將上面兩個函數(shù)指定為驅(qū)動的入口和出口函數(shù)
*/
module_init(chrdevbase_init);
module_exit(chrdevbase_exit);

/*
*LICENSE和作者信息
*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zuozhongkai");

應(yīng)用源碼

和原子操作應(yīng)用源碼一樣,不需要修改!

實(shí)驗(yàn)現(xiàn)象

使用信號量不會出現(xiàn)設(shè)備打不開的問題,它會在任務(wù)結(jié)束后再次執(zhí)行!

bb90e480-3083-11ee-9e74-dac502259ad0.png

套路分析

1、在結(jié)構(gòu)體加入信號量

/*chrdevbase設(shè)備結(jié)構(gòu)體*/
structnewchr_dev{
......
structsemaphoresem;/*信號量*/
};

2、在驅(qū)動入口初始信號量

/*
*@description:驅(qū)動入口函數(shù)
*@param:無
*@return:0成功;其他失敗
*/
staticint__initchrdevbase_init(void)
{
/*初始化信號量*/
sema_init(&chrdevbase.sem,1);
......
return0;

3、在打開設(shè)備時獲取信號量

/*
*@description:打開設(shè)備
*@param-inode:傳遞給驅(qū)動的inode
*@param-filp:設(shè)備文件,file結(jié)構(gòu)體有個叫做private_data的成員變量
*一般在open的時候?qū)rivate_data指向設(shè)備結(jié)構(gòu)體。
*@return:0成功;其他失敗
*/
staticintchrdevbase_open(structinode*inode,structfile*filp)
{
printk("[BSP]chrdevbaseopen!
");
filp->private_data=&chrdevbase;/*設(shè)置私有數(shù)據(jù)*/

/*獲取信號量,進(jìn)入休眠狀態(tài)的進(jìn)程可以被信號打斷*/
if(down_interruptible(&chrdevbase.sem)){
return-ERESTARTSYS;
}
#if0
down(&chrdevbase.sem);/*不能被信號打斷*/
#endif
return0;
}

4、在釋放設(shè)備時釋放信號量

/*
*@description:關(guān)閉/釋放設(shè)備
*@param-filp:要關(guān)閉的設(shè)備文件(文件描述符)
*@return:0成功;其他失敗
*/
staticintchrdevbase_release(structinode*inode,structfile*filp)
{
structnewchr_dev*dev=filp->private_data;
up(&dev->sem);/*釋放信號量,信號量值加1*/
printk("[BSP]release!
");
return0;
}

| 互斥體

驅(qū)動源碼

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

/*添加頭文件*/
#include
#include
#include
#include

#defineCHRDEVBASE_CNT1/*設(shè)備號個數(shù)*/
#defineCHRDEVBASE_NAME"chrdevbase"/*名字*/

#defineLEDOFF0/*關(guān)燈*/
#defineLEDON1/*開燈*/

/*chrdevbase設(shè)備結(jié)構(gòu)體*/
structnewchr_dev{
dev_tdevid;/*設(shè)備號*/
structcdevcdev;/*cdev*/
structclass*class;/*類*/
structdevice*device;/*設(shè)備*/
intmajor;/*主設(shè)備號*/
intminor;/*次設(shè)備號*/
structdevice_node*nd;/*設(shè)備節(jié)點(diǎn)*/
intled_gpio;/*led所使用的GPIO編號*/

structmutexlock;/*互斥體*/
};

structnewchr_devchrdevbase;/*自定義字符設(shè)備*/

/*
*@description:LED硬件初始化
*@param:無
*@return:無
*/
staticintled_hal_init(void)
{
intret=0;

/*設(shè)置LED所使用的GPIO*/
/*1、獲取設(shè)備節(jié)點(diǎn):gpioled*/
chrdevbase.nd=of_find_node_by_path("/gpioled");
if(chrdevbase.nd==NULL){
printk("chrdevbasenodecantnotfound!
");
return-EINVAL;
}else{
printk("chrdevbasenodehasbeenfound!
");
}

/*2、獲取設(shè)備樹中的gpio屬性,得到LED所使用的LED編號*/
chrdevbase.led_gpio=of_get_named_gpio(chrdevbase.nd,"led-gpio",0);
if(chrdevbase.led_gpio0){
printk("can'tgetled-gpio");
return-EINVAL;
}
printk("led-gpionum=%d
",chrdevbase.led_gpio);

/*3、設(shè)置GPIO1_IO03為輸出,并且輸出高電平,默認(rèn)關(guān)閉LED燈*/
ret=gpio_direction_output(chrdevbase.led_gpio,1);
if(ret0){
printk("can'tsetgpio!
");
}

return0;
}

/*
*@description:打開設(shè)備
*@param-inode:傳遞給驅(qū)動的inode
*@param-filp:設(shè)備文件,file結(jié)構(gòu)體有個叫做private_data的成員變量
*一般在open的時候?qū)rivate_data指向設(shè)備結(jié)構(gòu)體。
*@return:0成功;其他失敗
*/
staticintchrdevbase_open(structinode*inode,structfile*filp)
{
printk("[BSP]chrdevbaseopen!
");
filp->private_data=&chrdevbase;/*設(shè)置私有數(shù)據(jù)*/

/*獲取互斥體,可以被信號打斷*/
if(mutex_lock_interruptible(&chrdevbase.lock)){
return-ERESTARTSYS;
}
#if0
mutex_lock(&chrdevbase.lock);/*不能被信號打斷*/
#endif

return0;
}

/*
*@description:從設(shè)備讀取數(shù)據(jù)
*@param-filp:要打開的設(shè)備文件(文件描述符)
*@param-buf:返回給用戶空間的數(shù)據(jù)緩沖區(qū)
*@param-cnt:要讀取的數(shù)據(jù)長度
*@param-offt:相對于文件首地址的偏移
*@return:讀取的字節(jié)數(shù),如果為負(fù)值,表示讀取失敗
*/
staticssize_tchrdevbase_read(structfile*filp,char__user*buf,size_tcnt,loff_t*offt)
{
printk("chrdevbaseread!
");
return0;
}

/*
*@description:向設(shè)備寫數(shù)據(jù)
*@param-filp:設(shè)備文件,表示打開的文件描述符
*@param-buf:要寫給設(shè)備寫入的數(shù)據(jù)
*@param-cnt:要寫入的數(shù)據(jù)長度
*@param-offt:相對于文件首地址的偏移
*@return:寫入的字節(jié)數(shù),如果為負(fù)值,表示寫入失敗
*/
staticssize_tchrdevbase_write(structfile*filp,constchar__user*buf,size_tcnt,loff_t*offt)
{
intretvalue=0;
charwritebuf[1];
structnewchr_dev*dev=filp->private_data;

/*接收用戶空間傳遞給內(nèi)核的數(shù)據(jù)并且打印出來*/
retvalue=copy_from_user(writebuf,buf,cnt);
printk("[BSP]kernelrecevdatadata:%d!
",writebuf[0]);

if(writebuf[0]==LEDON){
gpio_set_value(dev->led_gpio,0);/*打開LED燈*/
}elseif(writebuf[0]==LEDOFF){
gpio_set_value(dev->led_gpio,1);/*關(guān)閉LED燈*/
}

//printk("chrdevbasewrite!
");
return0;
}

/*
*@description:關(guān)閉/釋放設(shè)備
*@param-filp:要關(guān)閉的設(shè)備文件(文件描述符)
*@return:0成功;其他失敗
*/
staticintchrdevbase_release(structinode*inode,structfile*filp)
{
structnewchr_dev*dev=filp->private_data;
/*釋放互斥鎖*/
mutex_unlock(&dev->lock);
printk("[BSP]release!
");
return0;
}

/*
*設(shè)備操作函數(shù)結(jié)構(gòu)體
*/
staticstructfile_operationschrdevbase_fops={
.owner=THIS_MODULE,
.open=chrdevbase_open,
.read=chrdevbase_read,
.write=chrdevbase_write,
.release=chrdevbase_release,
};

/*
*@description:驅(qū)動入口函數(shù)
*@param:無
*@return:0成功;其他失敗
*/
staticint__initchrdevbase_init(void)
{
/*初始化互斥體*/
mutex_init(&chrdevbase.lock);

/*初始化硬件*/
led_hal_init();

/*注冊字符設(shè)備驅(qū)動*/
/*1、創(chuàng)建設(shè)備號*/
if(chrdevbase.major){/*定義了設(shè)備號*/
chrdevbase.devid=MKDEV(chrdevbase.major,0);
register_chrdev_region(chrdevbase.devid,CHRDEVBASE_CNT,CHRDEVBASE_NAME);
}else{/*沒有定義設(shè)備號*/
alloc_chrdev_region(&chrdevbase.devid,0,CHRDEVBASE_CNT,CHRDEVBASE_NAME);/*申請?jiān)O(shè)備號*/
chrdevbase.major=MAJOR(chrdevbase.devid);/*獲取主設(shè)備號*/
chrdevbase.minor=MINOR(chrdevbase.devid);/*獲取次設(shè)備號*/
}
printk("newcheledmajor=%d,minor=%d
",chrdevbase.major,chrdevbase.minor);

/*2、初始化cdev*/
chrdevbase.cdev.owner=THIS_MODULE;
cdev_init(&chrdevbase.cdev,&chrdevbase_fops);

/*3、添加一個cdev*/
cdev_add(&chrdevbase.cdev,chrdevbase.devid,CHRDEVBASE_CNT);

/*4、創(chuàng)建類*/
chrdevbase.class=class_create(THIS_MODULE,CHRDEVBASE_NAME);
if(IS_ERR(chrdevbase.class)){
returnPTR_ERR(chrdevbase.class);
}

/*5、創(chuàng)建設(shè)備*/
chrdevbase.device=device_create(chrdevbase.class,NULL,chrdevbase.devid,NULL,CHRDEVBASE_NAME);
if(IS_ERR(chrdevbase.device)){
returnPTR_ERR(chrdevbase.device);
}

return0;
}

/*
*@description:驅(qū)動出口函數(shù)
*@param:無
*@return:無
*/
staticvoid__exitchrdevbase_exit(void)
{
/*注銷字符設(shè)備*/
cdev_del(&chrdevbase.cdev);/*刪除cdev*/
unregister_chrdev_region(chrdevbase.devid,CHRDEVBASE_CNT);/*注銷設(shè)備號*/

device_destroy(chrdevbase.class,chrdevbase.devid);/*銷毀設(shè)備*/
class_destroy(chrdevbase.class);/*銷毀類*/

printk("[BSP]chrdevbaseexit!
");
}

/*
*將上面兩個函數(shù)指定為驅(qū)動的入口和出口函數(shù)
*/
module_init(chrdevbase_init);
module_exit(chrdevbase_exit);

/*
*LICENSE和作者信息
*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zuozhongkai");

應(yīng)用源碼

和原子操作應(yīng)用源碼一樣,不需要修改!

實(shí)驗(yàn)現(xiàn)象

互斥體和信號量的效果類似,也會在任務(wù)完成后再運(yùn)行。

bba62d0e-3083-11ee-9e74-dac502259ad0.png

套路分析

1、在結(jié)構(gòu)體加入互斥體

/*chrdevbase設(shè)備結(jié)構(gòu)體*/
structnewchr_dev{
....
structmutexlock;/*互斥體*/
};

2、在驅(qū)動入口初始化互斥體

/*
*@description:驅(qū)動入口函數(shù)
*@param:無
*@return:0成功;其他失敗
*/
staticint__initchrdevbase_init(void)
{
/*初始化互斥體*/
mutex_init(&chrdevbase.lock);
......
return0;
}

3、在打開設(shè)備時獲取互斥體

/*
*@description:打開設(shè)備
*@param-inode:傳遞給驅(qū)動的inode
*@param-filp:設(shè)備文件,file結(jié)構(gòu)體有個叫做private_data的成員變量
*一般在open的時候?qū)rivate_data指向設(shè)備結(jié)構(gòu)體。
*@return:0成功;其他失敗
*/
staticintchrdevbase_open(structinode*inode,structfile*filp)
{
printk("[BSP]chrdevbaseopen!
");
filp->private_data=&chrdevbase;/*設(shè)置私有數(shù)據(jù)*/

/*獲取互斥體,可以被信號打斷*/
if(mutex_lock_interruptible(&chrdevbase.lock)){
return-ERESTARTSYS;
}
#if0
mutex_lock(&chrdevbase.lock);/*不能被信號打斷*/
#endif

return0;
}

4、在釋放設(shè)備時釋放互斥體

/*
*@description:關(guān)閉/釋放設(shè)備
*@param-filp:要關(guān)閉的設(shè)備文件(文件描述符)
*@return:0成功;其他失敗
*/
staticintchrdevbase_release(structinode*inode,structfile*filp)
{
structnewchr_dev*dev=filp->private_data;
/*釋放互斥鎖*/
mutex_unlock(&dev->lock);
printk("[BSP]release!
");
return0;
}


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 驅(qū)動
    +關(guān)注

    關(guān)注

    12

    文章

    1851

    瀏覽量

    85647
  • 控制臺
    +關(guān)注

    關(guān)注

    0

    文章

    85

    瀏覽量

    10411
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    652

    瀏覽量

    29458

原文標(biāo)題:i.MX6ULL|并發(fā)與競爭實(shí)驗(yàn)

文章出處:【微信號:玩轉(zhuǎn)單片機(jī),微信公眾號:玩轉(zhuǎn)單片機(jī)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    i.MX6ULL 驅(qū)動開發(fā)7—按鍵輸入捕獲與GPIO輸入配置與高低電平讀取

    本篇主要介紹了i.MX6ULL的按鍵檢測的使用,主要的知識點(diǎn)是設(shè)備樹的修改,以及GPIO的輸入配置與高低電平的讀取。
    的頭像 發(fā)表于 05-24 09:11 ?6342次閱讀
    <b class='flag-5'>i.MX6ULL</b> 驅(qū)動開發(fā)7—按鍵輸入捕獲與GPIO輸入配置與高低電平讀取

    使用i.MX6ULL開發(fā)板進(jìn)行Linux根文件系統(tǒng)的完善

    上一篇推文講了怎么移植根文件系統(tǒng),并在i.MX6ULL開發(fā)板中運(yùn)行起來,但是會出現(xiàn)一些提示,現(xiàn)在來進(jìn)行根文件的完善。
    發(fā)表于 10-17 11:13 ?832次閱讀

    移植NXP官方linux 5.4內(nèi)核到i.MX6ULL開發(fā)板

    本文描述移植NXP官方 linux 5.4 內(nèi)核到i.MX6ULL開發(fā)板。
    發(fā)表于 12-19 11:10 ?2115次閱讀

    i.MX6UL/i.MX6ULL開發(fā)常見問題】單獨(dú)編譯內(nèi)核,uboot生成很多文件,具體用哪一個?

    i.MX6UL/i.MX6ULL開發(fā)常見問題》基于米爾電子 i.MX6UL/i.MX6ULL產(chǎn)品(V.10)2.3單獨(dú)編譯內(nèi)核,uboot生成很多文件,具體用哪一個?答:內(nèi)核編譯出來
    發(fā)表于 07-01 17:50

    i.MX6ULL開發(fā)板硬件資源

    迅為i.MX6ULL 終結(jié)者開發(fā)板硬件資源非常豐富,幾乎將 i.MX6ULL 芯片的所有資源都擴(kuò)展引出到底板上了,底板提供了豐富的外設(shè)接口,開發(fā)板的尺寸是 190mm*125mm,充分考慮了人性化設(shè)計(jì),整體顯得十分大。
    發(fā)表于 12-29 06:18

    初識 i.MX6ULL 寄存器

    裸機(jī)開發(fā)_L1_匯編LED實(shí)驗(yàn)0. 本節(jié)目標(biāo)1. 硬件層電路2. 初識 i.MX6ULL 寄存器2.1 i.MX6ULL 時鐘控制寄存器2.2 i.MX6ULL IO復(fù)用寄存器2.3
    發(fā)表于 12-20 07:13

    I.MX6ULL無法枚舉USB2514是為什么?

    你好目前,I.MX6ULL開發(fā)存在一些問題。其中之一是OTG USB2無法正常掛載USB2514,無法正確枚舉下游設(shè)備,只顯示設(shè)備id。usb設(shè)計(jì)要注意什么。
    發(fā)表于 04-03 06:55

    I.MX6ULL UART傳輸問題求解

    I.MX6ULL UART傳輸問題
    發(fā)表于 04-21 08:09

    珠海明遠(yuǎn)智??萍悸?lián)合NXP強(qiáng)勢推出i.MX6ull核心板

    NXP I.MX6ULL是一個高性能、低功耗、高性價比處理器系列,基于ARM Cortex-A7內(nèi)核,主頻可達(dá)900MHz。i.MX 6ULL應(yīng)用處理器包括一個集成的電源管理模塊,可以省掉外部
    發(fā)表于 04-24 14:10 ?573次閱讀

    飛凌i.MX6ULL開發(fā)板的評測,再次進(jìn)階擁有更高的性價比

    處理器MCIMX6Y2開發(fā)設(shè)計(jì),采用先進(jìn)的ARMCortex-A7內(nèi)核,運(yùn)行速度高達(dá)800MHz。i.MX6ULL應(yīng)用處理器包括一個集成的電源管理模塊,降低了外接電源的復(fù)雜性,并簡化了上電時序。 i.MX6ULL
    發(fā)表于 10-27 11:55 ?1508次閱讀
    飛凌<b class='flag-5'>i.MX6ULL</b>開發(fā)板的評測,再次進(jìn)階擁有更高的性價比

    基于NXP i.MX6ULL處理器的FETMX6ULL-C核心板

    “性價比高,功能接口豐富,資料齊全,穩(wěn)定性強(qiáng)”這是許多用戶對飛凌FETMX6ULL-S核心板的評價。作為NXP公司一顆經(jīng)典的MPU,i.MX6ULL的市場認(rèn)可度無需多言。而作為NXP公司的金牌
    發(fā)表于 04-11 15:05 ?1173次閱讀
    基于NXP <b class='flag-5'>i.MX6ULL</b>處理器的FETMX<b class='flag-5'>6ULL</b>-C核心板

    i.MX6ULL】驅(qū)動開發(fā)4——點(diǎn)亮LED(寄存器版)

    本篇主要介紹了如何通過操作寄存器來點(diǎn)亮i.MX6ULL開發(fā)板上的led,通過編寫LED對應(yīng)的驅(qū)動程序和應(yīng)用程序,實(shí)現(xiàn)程序設(shè)計(jì)的分層。
    的頭像 發(fā)表于 05-21 21:26 ?3034次閱讀
    【<b class='flag-5'>i.MX6ULL</b>】驅(qū)動開發(fā)4——點(diǎn)亮LED(寄存器版)

    【北京迅為】i.MX6ULL開發(fā)板移植 Debian 文件系統(tǒng)

    【北京迅為】i.MX6ULL開發(fā)板移植 Debian 文件系統(tǒng)
    的頭像 發(fā)表于 02-10 15:34 ?1234次閱讀
    【北京迅為】<b class='flag-5'>i.MX6ULL</b>開發(fā)板移植 Debian 文件系統(tǒng)

    基于i.MX6ULL的掉電檢測設(shè)計(jì)與軟件測試

    基于i.MX6ULL的掉電檢測設(shè)計(jì)與軟件測試基于i.MX6ULL平臺設(shè)計(jì)實(shí)現(xiàn)掉電檢測功能,首先選擇一路IO,利用IO電平變化觸發(fā)中斷,在編寫驅(qū)動時捕獲該路GPIO的中斷,然后在中斷響應(yīng)函數(shù)中發(fā)
    的頭像 發(fā)表于 11-09 10:40 ?925次閱讀
    基于<b class='flag-5'>i.MX6ULL</b>的掉電檢測設(shè)計(jì)與軟件測試

    【迅為電子】i.MX6UL和i.MX6ULL芯片區(qū)別與開發(fā)板對比

    【迅為電子】i.MX6UL和i.MX6ULL芯片區(qū)別與開發(fā)板對比
    的頭像 發(fā)表于 11-28 14:31 ?571次閱讀
    【迅為電子】<b class='flag-5'>i.MX6</b>UL和<b class='flag-5'>i.MX6ULL</b>芯片區(qū)別與開發(fā)板對比
    威尼斯人娱乐最新地址| 福安市| 百家乐官网桌14人| 博彩网百家乐官网中和局| 澳门百家乐官网怎么下载| 大连百家乐食品| 百家乐官网无敌直缆| 百家乐官网策略介绍| 天津太阳城橙翠园| 在线百家乐官网技巧| 百家乐五湖四海赌场娱乐网规则 | 游戏百家乐官网的玩法技巧和规则 | 五星百家乐官网的玩法技巧和规则 | 百家乐官网概率怎么算| 678百家乐官网博彩娱乐场开户注册| 百家乐赌场走势图| 大发888谨慎心态| 太阳城百家乐官网出千技术| KTV百家乐的玩法技巧和规则| 湟中县| 属马的和属猴的在一起做生意好吗| 麻将二八杠游戏| 新葡京百家乐官网娱乐城 | 德晋百家乐官网的玩法技巧和规则 | 投注平台网| 金钱豹百家乐官网的玩法技巧和规则 | 百家乐娱乐城体育| 至棒娱乐备用| 刀把状的房子做生意| 易胜博投注| 百家乐体育直播| 御匾会娱乐城| 百家乐神仙道官网| 远安县| 百家乐官网论坛香港马会| 单机百家乐的玩法技巧和规则| 百家乐官网庄河闲的赌法| 任我赢百家乐软件| 哪个百家乐官网技巧平台信誉好| 大发888娱乐城游戏下载| 百家乐官网网络游戏信誉怎么样 |