瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工藝,搭載一顆四核Cortex-A55處理器和Mali G52 2EE圖形處理器。RK3568支持4K解碼和1080P編碼,支持SATA/PCIE/USB3.0外圍接口。RK3568內(nèi)置獨(dú)立NPU,可用于輕量級(jí)人工智能應(yīng)用。RK3568支持安卓11和linux系統(tǒng),主要面向物聯(lián)網(wǎng)網(wǎng)關(guān)、NVR存儲(chǔ)、工控平板、工業(yè)檢測(cè)、工控盒、卡拉OK、云終端、車載中控等行業(yè)。
?

迅為RK568郵票孔版開(kāi)發(fā)板:
還在為工控機(jī)性能不足而煩惱?
還在為開(kāi)發(fā)周期長(zhǎng)而焦慮?
迅為RK568郵票孔版開(kāi)發(fā)板,為您提供一站式解決方案!
強(qiáng)勁性能,賦能工業(yè)未來(lái):
搭載瑞芯微RK568高性能處理器,采用先進(jìn)制程工藝,提供澎湃算力,輕松應(yīng)對(duì)復(fù)雜工業(yè)場(chǎng)景。
支持多種操作系統(tǒng),如Android、Linux等,滿足不同應(yīng)用需求。
豐富接口,擴(kuò)展性強(qiáng),可連接多種工業(yè)設(shè)備,構(gòu)建穩(wěn)定可靠的工業(yè)控制系統(tǒng)。
郵票孔設(shè)計(jì),靈活易用:
采用郵票孔連接方式,方便快捷,節(jié)省空間,易于集成到各種工控設(shè)備中。
提供配套外殼,防護(hù)等級(jí)高,適應(yīng)各種惡劣工業(yè)環(huán)境。
提供完善的技術(shù)支持和開(kāi)發(fā)資料,助您快速上手,縮短開(kāi)發(fā)周期。
廣泛應(yīng)用于工業(yè)自動(dòng)化控制、機(jī)器視覺(jué)、智能網(wǎng)關(guān)、工業(yè)機(jī)器人、物聯(lián)網(wǎng)終端等。

【公眾號(hào)】迅為電子
第19章 并發(fā)與競(jìng)爭(zhēng)實(shí)驗(yàn)
在前面章節(jié)的學(xué)習(xí)中,相信大家已經(jīng)對(duì)用戶空間與內(nèi)核空間數(shù)據(jù)傳遞進(jìn)行了實(shí)驗(yàn),假如要傳遞的數(shù)據(jù)被存放在了全局變量,該數(shù)據(jù)就可以作為共享資源被多個(gè)任務(wù)共同讀寫(xiě),從而造成數(shù)據(jù)的錯(cuò)誤傳輸,多個(gè)程序同時(shí)訪問(wèn)一個(gè)共享資源產(chǎn)生的問(wèn)題就叫做競(jìng)爭(zhēng)。競(jìng)爭(zhēng)產(chǎn)生的根本原因就是Linux系統(tǒng)的并發(fā)訪問(wèn)。
在本章節(jié)中首先會(huì)對(duì)并發(fā)與并行的概念進(jìn)行講解,隨后對(duì)競(jìng)爭(zhēng)產(chǎn)生的原因進(jìn)行總結(jié),最后以一個(gè)實(shí)際的競(jìng)爭(zhēng)實(shí)驗(yàn)加深大家的理解。下面就讓我們開(kāi)始本章節(jié)的學(xué)習(xí)吧。
19.1并發(fā)與競(jìng)爭(zhēng)
19.1.1并發(fā)
早期計(jì)算機(jī)大多只有一個(gè)CPU核心,一個(gè)CPU在同一時(shí)間只能執(zhí)行一個(gè)任務(wù),當(dāng)系統(tǒng)中有多個(gè)任務(wù)等待執(zhí)行時(shí),CPU只能執(zhí)行完一個(gè)再執(zhí)行下一個(gè)。而計(jì)算機(jī)的很多指令會(huì)涉及I/O操作,執(zhí)行速度遠(yuǎn)遠(yuǎn)低于CPU內(nèi)高速存儲(chǔ)器的存取速度,這就導(dǎo)致CPU經(jīng)常處于空閑狀態(tài),只能等待I/O操作完成后才能繼續(xù)執(zhí)行后面的指令。為了提高CPU利用率,減少等待時(shí)間,提出了CPU并發(fā)工作理論。
所謂并發(fā),就是通過(guò)算法將CPU資源合理地分配給多個(gè)任務(wù),當(dāng)一個(gè)任務(wù)執(zhí)行I/O操作時(shí),CPU可以轉(zhuǎn)而執(zhí)行其它的任務(wù),等到I/O操作完成以后,或者新的任務(wù)遇到I/O操作時(shí),CPU再回到原來(lái)的任務(wù)繼續(xù)執(zhí)行。
下圖(圖19-1)展示了兩個(gè)任務(wù)并發(fā)執(zhí)行的過(guò)程(為了容易理解,這里以兩個(gè)任務(wù)并發(fā)執(zhí)行為例,當(dāng)然一個(gè)CPU核心并不僅僅只能兩個(gè)任務(wù)并發(fā)):

雖然CPU在同一時(shí)刻只能執(zhí)行一個(gè)任務(wù),但是通過(guò)將CPU的使用權(quán)在恰當(dāng)?shù)臅r(shí)機(jī)分配給不同的任務(wù),使得多個(gè)任務(wù)看起來(lái)是一起執(zhí)行的(CPU的執(zhí)行速度極快,多任務(wù)切換的時(shí)間也極短)。
至此關(guān)于并發(fā)的概念就講解完成了。
19.1.2并行
并發(fā)是針對(duì)單核CPU提出的,而并行則是針對(duì)多核CPU提出的。和單核CPU不同,多核CPU真正實(shí)現(xiàn)了“同時(shí)執(zhí)行多個(gè)任務(wù)”。多核CPU的每個(gè)核心都可以獨(dú)立地執(zhí)行一個(gè)任務(wù),而且多個(gè)核心之間不會(huì)相互干擾。在不同核心上執(zhí)行的多個(gè)任務(wù),是真正地同時(shí)運(yùn)行,這種狀態(tài)就叫做并行。雙核CPU的工作狀態(tài)如下圖(圖19-2)所示:

雙核CPU執(zhí)行兩個(gè)任務(wù)時(shí),每個(gè)核心各自執(zhí)行一個(gè)任務(wù),和單核CPU在兩個(gè)任務(wù)之間不斷切換相比,它的執(zhí)行效率更高。
至此對(duì)于并行的概念就講解完成了。
19.1.3并發(fā)+并行
在并行的工作狀態(tài)中,兩個(gè)CPU分別執(zhí)行兩個(gè)任務(wù),是一種理想狀態(tài)。但是在實(shí)際場(chǎng)景中,處于運(yùn)行狀態(tài)的任務(wù)是非常多的,以實(shí)際辦公電腦為例,windows系統(tǒng)在開(kāi)機(jī)之后會(huì)運(yùn)行幾十個(gè)任務(wù),而CPU往往只有4核、8核等,遠(yuǎn)遠(yuǎn)低于任務(wù)的數(shù)量,這個(gè)時(shí)候就會(huì)同時(shí)存在并發(fā)和并行兩種情況,即所有核心在并行工作的同時(shí),每個(gè)核心還要并發(fā)工作。
例如一個(gè)雙核 CPU要執(zhí)行四個(gè)任務(wù),它的工作狀態(tài)如下圖(圖19-3)所示:

為了容易理解,這里是以兩個(gè)任務(wù)并發(fā)執(zhí)行為例,當(dāng)然一個(gè)CPU核心并不僅僅只能兩個(gè)任務(wù)并發(fā),并發(fā)任務(wù)的數(shù)量和操作系統(tǒng)的分配方式、以及每個(gè)任務(wù)的工作狀態(tài)有關(guān)系。
至此,對(duì)于并發(fā)+并行的概念講解就結(jié)束了。
并發(fā)可以看作是并行的理想狀態(tài),為了便于講解和避免產(chǎn)生歧義,之后的章節(jié)無(wú)論是并發(fā)還是并行,都會(huì)統(tǒng)稱為并發(fā)。
19.1.4競(jìng)爭(zhēng)
并發(fā)可能會(huì)造成多個(gè)程序同時(shí)訪問(wèn)一個(gè)共享資源,這時(shí)候由并發(fā)同時(shí)訪問(wèn)一個(gè)共享資源產(chǎn)生的問(wèn)題就叫做競(jìng)爭(zhēng)。
競(jìng)爭(zhēng)產(chǎn)生的原因如下所示:
(1)多線程的并發(fā)訪問(wèn)。由于Linux是多任務(wù)操作系統(tǒng),所以多線程訪問(wèn)是競(jìng)爭(zhēng)產(chǎn)生的基本原因。
(2)中斷程序的并發(fā)訪問(wèn)。中斷任務(wù)產(chǎn)生后,CPU會(huì)立刻停止當(dāng)前工作,從而去執(zhí)行中斷中的任務(wù),如果中斷任務(wù)對(duì)共享資源進(jìn)行了修改,就會(huì)產(chǎn)生競(jìng)爭(zhēng)。
(3)搶占式并發(fā)訪問(wèn)。linux2.6及更高版本引入了搶占式內(nèi)核,高優(yōu)先級(jí)的任務(wù)可以打斷低優(yōu)先級(jí)的任務(wù)。在線程訪問(wèn)共享資源的時(shí)候,另一個(gè)線程打斷了現(xiàn)在正在訪問(wèn)共享資源的線程同時(shí)也對(duì)共享資源進(jìn)行操作,從而造成了競(jìng)爭(zhēng)。
(4)多處理器(SMP)并發(fā)訪問(wèn)。多核處理器之間存在核間并發(fā)訪問(wèn)。
19.1.5共享資源的保護(hù)
競(jìng)爭(zhēng)是由并發(fā)訪問(wèn)同一個(gè)共享資源產(chǎn)生的。為了防止“競(jìng)爭(zhēng)”的產(chǎn)生就要對(duì)共享資源進(jìn)行保護(hù),這里提到的共享資源又是什么呢?
以實(shí)際生活中的共享資源為例,可以是公共電話,也可以是共享單車、共享充電寶等公共物品,以上都屬于共享資源的范疇,以公共電話為例,每個(gè)人都可以對(duì)它進(jìn)行使用,但在同一時(shí)間內(nèi)只能由一個(gè)人進(jìn)行使用,如果兩個(gè)人都要對(duì)電話進(jìn)行使用,則產(chǎn)生了競(jìng)爭(zhēng)。而在實(shí)際的驅(qū)動(dòng)的代碼中,共享資源可以是全局變量,也可以是驅(qū)動(dòng)中的設(shè)備結(jié)構(gòu)體等,需要根據(jù)具體的驅(qū)動(dòng)程序來(lái)進(jìn)行分析。在下一小節(jié)的實(shí)驗(yàn)中,會(huì)以全局變量為例,進(jìn)行并發(fā)與競(jìng)爭(zhēng)實(shí)驗(yàn)。
19.2實(shí)驗(yàn)程序的編寫(xiě)
19.2.1驅(qū)動(dòng)程序編寫(xiě)
本實(shí)驗(yàn)對(duì)應(yīng)的網(wǎng)盤路徑為:iTOP-RK3568開(kāi)發(fā)板【底板V1.7版本】\03_【iTOP-RK3568開(kāi)發(fā)板】指南教程\02_Linux驅(qū)動(dòng)配套資料\04_Linux驅(qū)動(dòng)例程\14\module。
本實(shí)驗(yàn)將編寫(xiě)并發(fā)與競(jìng)爭(zhēng)的驅(qū)動(dòng)代碼,首先完善字符設(shè)備驅(qū)動(dòng)框架,然后通過(guò)copy_from_user(…)函數(shù)接收用戶空間傳遞到內(nèi)核空間的數(shù)據(jù)并進(jìn)行判斷,如果接收到的字符串?dāng)?shù)據(jù)為“topeet”會(huì)在睡眠4秒鐘后打印接收到的數(shù)據(jù),如果接收到的字符串?dāng)?shù)據(jù)為“itop”會(huì)在睡眠2秒鐘后打印接收到的數(shù)據(jù)。
編寫(xiě)完成的example.c代碼如下所示
#include
#include
#include
#include
#include
#include
#include
static int open_test(struct inode *inode,struct file *file)
{
printk("\nthis is open_test \n");
return 0;
}
static ssize_t read_test(struct file *file,char __user *ubuf,size_t len,loff_t *off)
{
int ret;
char kbuf[10] = "topeet";//定義char類型字符串變量kbuf
printk("\nthis is read_test \n");
ret = copy_to_user(ubuf,kbuf,strlen(kbuf));//使用copy_to_user接收用戶空間傳遞的數(shù)據(jù)
if (ret != 0){
printk("copy_to_user is error \n");
}
printk("copy_to_user is ok \n");
return 0;
}
static char kbuf[10] = {0};//定義char類型字符串全局變量kbuf
static ssize_t write_test(struct file *file,const char __user *ubuf,size_t len,loff_t *off)
{
int ret;
ret = copy_from_user(kbuf,ubuf,len);//使用copy_from_user接收用戶空間傳遞的數(shù)據(jù)
if (ret != 0){
printk("copy_from_user is error\n");
}
if(strcmp(kbuf,"topeet") == 0 ){//如果傳遞的kbuf是topeet就睡眠四秒鐘
ssleep(4);
}
else if(strcmp(kbuf,"itop") == 0){//如果傳遞的kbuf是itop就睡眠兩秒鐘
ssleep(2);
}
printk("copy_from_user buf is %s \n",kbuf);
return 0;
}
static int release_test(struct inode *inode,struct file *file)
{
//printk("\nthis is release_test \n");
return 0;
}
struct chrdev_test {
dev_t dev_num;//定義dev_t類型變量dev_num來(lái)表示設(shè)備號(hào)
int major,minor;//定義int類型的主設(shè)備號(hào)major和次設(shè)備號(hào)minor
struct cdev cdev_test;//定義struct cdev類型結(jié)構(gòu)體變量cdev_test,表示要注冊(cè)的字符設(shè)備
struct class *class_test;//定于struct class *類型結(jié)構(gòu)體變量class_test,表示要?jiǎng)?chuàng)建的類
};
struct chrdev_test dev1;//創(chuàng)建chrdev_test類型的
struct file_operations fops_test = {
.owner = THIS_MODULE,//將owner字段指向本模塊,可以避免在模塊的操作正在被使用時(shí)卸載該模塊
.open = open_test,//將open字段指向open_test(...)函數(shù)
.read = read_test,//將read字段指向read_test(...)函數(shù)
.write = write_test,//將write字段指向write_test(...)函數(shù)
.release = release_test,//將release字段指向release_test(...)函數(shù)
};
static int __init atomic_init(void)
{
if(alloc_chrdev_region(&dev1.dev_num,0,1,"chrdev_name") < 0 ){//自動(dòng)獲取設(shè)備號(hào),設(shè)備名chrdev_name
printk("alloc_chrdev_region is error \n");
}
printk("alloc_chrdev_region is ok \n");
dev1.major = MAJOR(dev1.dev_num);//使用MAJOR()函數(shù)獲取主設(shè)備號(hào)
dev1.minor = MINOR(dev1.dev_num);//使用MINOR()函數(shù)獲取次設(shè)備號(hào)
printk("major is %d,minor is %d\n",dev1.major,dev1.minor);
cdev_init(&dev1.cdev_test,&fops_test);//使用cdev_init()函數(shù)初始化cdev_test結(jié)構(gòu)體,并鏈接到fops_test結(jié)構(gòu)體
dev1.cdev_test.owner = THIS_MODULE;//將owner字段指向本模塊,可以避免在模塊的操作正在被使用時(shí)卸載該模塊
cdev_add(&dev1.cdev_test,dev1.dev_num,1);//使用cdev_add()函數(shù)進(jìn)行字符設(shè)備的添加
dev1.class_test = class_create(THIS_MODULE,"class_test");//使用class_create進(jìn)行類的創(chuàng)建,類名稱為class_test
device_create(dev1.class_test,0,dev1.dev_num,0,"device_test");//使用device_create進(jìn)行設(shè)備的創(chuàng)建,設(shè)備名稱為device_test
return 0;
}
static void __exit atomic_exit(void)
{
device_destroy(dev1.class_test,dev1.dev_num);//刪除創(chuàng)建的設(shè)備
class_destroy(dev1.class_test);//刪除創(chuàng)建的類
cdev_del(&dev1.cdev_test);//刪除添加的字符設(shè)備cdev_test
unregister_chrdev_region(dev1.dev_num,1);//釋放字符設(shè)備所申請(qǐng)的設(shè)備號(hào)
printk("module exit \n");
}
module_init(atomic_init);
module_exit(atomic_exit)
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("topeet");
對(duì)于重要邏輯部分已經(jīng)加粗,后續(xù)章節(jié)的實(shí)驗(yàn)都是對(duì)上述并發(fā)與競(jìng)爭(zhēng)實(shí)驗(yàn)的改進(jìn),以不同的方式來(lái)避免競(jìng)爭(zhēng)的產(chǎn)生。
19.2.2編寫(xiě)測(cè)試APP
本實(shí)驗(yàn)應(yīng)用程序?qū)?yīng)的網(wǎng)盤路徑為:iTOP-RK3568開(kāi)發(fā)板【底板V1.7版本】\03_【iTOP-RK3568開(kāi)發(fā)板】指南教程\02_Linux驅(qū)動(dòng)配套資料\04_Linux驅(qū)動(dòng)例程\14\app。
本測(cè)試app較為簡(jiǎn)單,需要輸入兩個(gè)參數(shù),第一個(gè)參數(shù)為對(duì)應(yīng)的設(shè)備節(jié)點(diǎn),第二個(gè)參數(shù)為“topeet”或者“itop”,分別代表向設(shè)備寫(xiě)入的數(shù)據(jù),編寫(xiě)完成的應(yīng)用程序app.c內(nèi)容如下所示:
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int fd;//定義int類型的文件描述符
char str1[10] = {0};//定義讀取緩沖區(qū)str1
fd = open(argv[1],O_RDWR);//調(diào)用open函數(shù),打開(kāi)輸入的第一個(gè)參數(shù)文件,權(quán)限為可讀可寫(xiě)
if(fd < 0 ){
printf("file open failed \n");
return -1;
}
/*如果第二個(gè)參數(shù)為topeet,條件成立,調(diào)用write函數(shù),寫(xiě)入topeet*/
if (strcmp(argv[2],"topeet") == 0 ){
write(fd,"topeet",10);
}
/*如果第二個(gè)參數(shù)為itop,條件成立,調(diào)用write函數(shù),寫(xiě)入itop*/
else if (strcmp(argv[2],"itop") == 0 ){
write(fd,"itop",10);
}
close(fd);
return 0;
}
19.3運(yùn)行測(cè)試
19.3.1編譯驅(qū)動(dòng)程序
在上一小節(jié)中的example.c代碼同一目錄下創(chuàng)建Makefile文件,Makefile文件內(nèi)容如下所示:
export ARCH=arm64#設(shè)置平臺(tái)架構(gòu)
export CROSS_COMPILE=aarch64-linux-gnu-#交叉編譯器前綴
obj-m += example.o #此處要和你的驅(qū)動(dòng)源文件同名
KDIR :=/home/topeet/Linux/linux_sdk/kernel #這里是你的內(nèi)核目錄
PWD ?= $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules #make操作
clean:
make -C $(KDIR) M=$(PWD) clean #make clean操作
對(duì)于Makefile的內(nèi)容注釋已在上圖添加,保存退出之后,來(lái)到存放example.c和Makefile文件目錄下,如下圖所示:

然后使用命令“make”進(jìn)行驅(qū)動(dòng)的編譯,編譯完成如下圖(圖19-5)所示:

編譯完生成example.ko目標(biāo)文件,如下圖(圖19-6)所示:

至此驅(qū)動(dòng)模塊就編譯成功了,下面進(jìn)行應(yīng)用程序的編譯。
19.3.2編譯應(yīng)用程序
來(lái)到應(yīng)用程序app.c文件的存放路徑如下圖(圖19-7)所示:

然后使用以下命令對(duì)app.c進(jìn)行交叉編譯,編譯完成如下圖(圖19-8)所示:
1
aarch64-linux-gnu-gcc -o app app.c -static

生成的app文件就是之后放在開(kāi)發(fā)板上運(yùn)行的可執(zhí)行文件,至此應(yīng)用程序的編譯就完成了。
19.3.3運(yùn)行測(cè)試
開(kāi)發(fā)板啟動(dòng)之后,使用以下命令進(jìn)行驅(qū)動(dòng)模塊的加載,如下圖(圖19-9)所示:
1
insmod example.ko

可以看到申請(qǐng)的主設(shè)備號(hào)和次設(shè)備號(hào)就被打印了出來(lái),然后使用以下代碼對(duì)自動(dòng)生成的設(shè)備節(jié)點(diǎn)device_test進(jìn)行查看,如下圖(圖19-10)所示:
1
ls /dev/device_test

可以看到device_test節(jié)點(diǎn)已經(jīng)被自動(dòng)創(chuàng)建了,然后使用以下命令運(yùn)行測(cè)試app,運(yùn)行結(jié)果如下圖(圖19-11)所示:
1
./app /dev/device_test topeet

可以看到傳遞的buf值為topeet,然后輸入以下命令在后臺(tái)運(yùn)行兩個(gè)app,來(lái)進(jìn)行競(jìng)爭(zhēng)測(cè)試,運(yùn)行結(jié)果如下圖(圖19-12)所示:
./app /dev/device_test topeet &
./app /dev/device_test itop &

在不存在競(jìng)爭(zhēng)的情況下,傳遞的兩個(gè)字符串?dāng)?shù)據(jù)應(yīng)該是topeet和itop,而在上圖中的打印信息為兩個(gè)itop,原因是第二個(gè)app應(yīng)用程序運(yùn)行之后對(duì)共享資源進(jìn)行了修改,兩個(gè)app應(yīng)用程序就產(chǎn)生了競(jìng)爭(zhēng)關(guān)系,會(huì)在之后的章節(jié)中使用不同的方法對(duì)上述驅(qū)動(dòng)程序進(jìn)行改進(jìn),從而避免競(jìng)爭(zhēng)的產(chǎn)生。
最后可以使用以下命令進(jìn)行驅(qū)動(dòng)的卸載,如下圖(圖19-13)所示:
1
rmmod example.ko

至此,并發(fā)與競(jìng)爭(zhēng)的實(shí)驗(yàn)就完成了。
-
驅(qū)動(dòng)
+關(guān)注
關(guān)注
12文章
1916瀏覽量
86916 -
開(kāi)發(fā)板
+關(guān)注
關(guān)注
25文章
5679瀏覽量
104633 -
RK3568
+關(guān)注
關(guān)注
5文章
584瀏覽量
6402
發(fā)布評(píng)論請(qǐng)先 登錄
迅為RK3568開(kāi)發(fā)板驅(qū)動(dòng)指南Linux中通用SPI設(shè)備驅(qū)動(dòng)

迅為RK3568開(kāi)發(fā)板驅(qū)動(dòng)指南GPIO子系統(tǒng)三級(jí)節(jié)點(diǎn)操作函數(shù)實(shí)驗(yàn)

文檔更新 |迅為 RK3568開(kāi)發(fā)板驅(qū)動(dòng)指南-第十五/十六篇
文檔更新 | 迅為RK3568驅(qū)動(dòng)指南-第十七篇(串口)
迅為iTOP-RK3568開(kāi)發(fā)板驅(qū)動(dòng)開(kāi)發(fā)指南-第十八篇 PWM
iTOP-RK3568開(kāi)發(fā)板驅(qū)動(dòng)指南第五篇-中斷
更新 | 持續(xù)開(kāi)源 迅為RK3568驅(qū)動(dòng)指南第十一篇-pinctrl子系統(tǒng)
RK3568驅(qū)動(dòng)指南|驅(qū)動(dòng)基礎(chǔ)進(jìn)階篇-進(jìn)階8 內(nèi)核運(yùn)行ko文件總結(jié)

RK3568驅(qū)動(dòng)指南|驅(qū)動(dòng)基礎(chǔ)進(jìn)階篇-進(jìn)階5 自定義實(shí)現(xiàn)insmod命令實(shí)驗(yàn)

迅為RK3568開(kāi)發(fā)板驅(qū)動(dòng)開(kāi)發(fā)指南-輸入子系統(tǒng)

【北京迅為】iTOP-RK3568開(kāi)發(fā)板OpenHarmony系統(tǒng)南向驅(qū)動(dòng)開(kāi)發(fā)-第4章 UART基礎(chǔ)知識(shí)

RK3568驅(qū)動(dòng)指南|驅(qū)動(dòng)基礎(chǔ)進(jìn)階篇-進(jìn)階7 向系統(tǒng)中添加一個(gè)系統(tǒng)調(diào)用

RK3568驅(qū)動(dòng)指南|第十二篇 GPIO子系統(tǒng)-第135章 GPIO子系統(tǒng)與pinctrl子系統(tǒng)相結(jié)合實(shí)驗(yàn)

迅為RK3568驅(qū)動(dòng)指南GPIO子系統(tǒng) GPIO操作函數(shù)實(shí)驗(yàn)

RK3568驅(qū)動(dòng)指南|第十二篇 GPIO子系統(tǒng)-第130章 GPIO的調(diào)試方法

評(píng)論