一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

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

【i.MX6ULL】驅(qū)動開發(fā)10—阻塞&非阻塞式按鍵檢測

碼農(nóng)愛學(xué)習(xí) ? 來源:碼農(nóng)愛學(xué)習(xí) ? 作者:碼農(nóng)愛學(xué)習(xí) ? 2022-05-27 09:08 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

上篇文章:介紹了linux中的五種I/O模型,本篇,就來使用阻塞式I/O非用阻塞式I/O兩種方式進行按鍵的讀取實驗,并對比之前使用輸入捕獲和中斷法檢測的按鍵程序,查看CPU的使用率是否降低。

1 阻塞I/O方式的按鍵檢測

1.1 阻塞I/O之等待隊列

阻塞訪問最大的好處就是當設(shè)備文件不可操作的時候進程可以進入休眠態(tài),這樣可以將CPU資源讓出來。但是,當設(shè)備文件可以操作的時候就必須喚醒進程,一般在中斷函數(shù)里面完成喚醒工作。Linux 內(nèi)核提供了等待隊列(wait queue)來實現(xiàn)阻塞進程的喚醒工作。

等待隊列頭使用結(jié)構(gòu)體wait_queue_head_t 表示:

struct __wait_queue_head { 
	spinlock_t       lock; 
	struct list_head task_list; 
}; 

typedef struct __wait_queue_head wait_queue_head_t; 

使用 init_waitqueue_head 函數(shù)初始化等待隊列頭:

/**
 * q: 要初始化的等待隊列頭
 * return: 無
 */
void init_waitqueue_head(wait_queue_head_t *q) 

當設(shè)備不可用的時, 將這些進程對應(yīng)的等待隊列項(wait_queue_t )添加到等待隊列里面:

struct __wait_queue { 
	unsigned int      flags; 
    void              *private; 
    wait_queue_func_t func; 
    struct list_head  task_list;
}; 

typedef struct __wait_queue wait_queue_t;

使用宏 DECLARE_WAITQUEUE 定義并初始化一個等待隊列項:

DECLARE_WAITQUEUE(name, tsk)

當設(shè)備不可訪問的時候就需要將進程對應(yīng)的等待隊列項添加到前面創(chuàng)建的等待隊列頭中:

/**
 * q: 要加入的等待隊列頭
 * wait:要加入的等待隊列項
 * return: 無
 */
void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) 

當設(shè)備可以訪問以后再將進程對應(yīng)的等待隊列項從等待隊列頭中刪除即可:

/**
 * q: 要刪除的等待隊列頭
 * wait:要刪除的等待隊列項
 * return: 無
 */
void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) 

當設(shè)備可以使用的時候就要喚醒進入休眠態(tài)的進程:

void wake_up(wait_queue_head_t *q) 
void wake_up_interruptible(wait_queue_head_t *q) 

1.2 阻塞I/O程序編寫

這里僅介紹與之前按鍵程序的主要區(qū)別。

1.2.1驅(qū)動程序

阻塞讀取邏輯如下,首先要定義一個等待隊列,當按鍵沒有按下時,就要阻塞等待了(將等待隊列添加到等待隊列頭),然后進行行一次任務(wù)切換,交出CPU的使用權(quán)。等待有按鍵按下時,會有信號喚醒該等待,并將按鍵值返回給應(yīng)用層的程序。

static ssize_t imx6uirq_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
    int ret = 0;
    unsigned char keyvalue = 0;
    unsigned char releasekey = 0;
    struct imx6uirq_dev *dev = (struct imx6uirq_dev *)filp->private_data;
    
    /* 定義一個等待隊列 <-------------------------- */
    DECLARE_WAITQUEUE(wait, current);
    
    /* 沒有按鍵按下 <------------------------------ */
    if(atomic_read(&dev->releasekey) == 0)
    {
        /* 將等待隊列添加到等待隊列頭 <------------ */
        add_wait_queue(&dev->r_wait, &wait);
        
        /* 設(shè)置任務(wù)狀態(tài) <-------------------------- */
        __set_current_state(TASK_INTERRUPTIBLE);
        
        /* 進行一次任務(wù)切換 <---------------------- */
        schedule();
        
        /* 判斷是否為信號引起的喚醒 <-------------- */
        if(signal_pending(current))
        {
            ret = -ERESTARTSYS;
            goto wait_error;
        }
        
        /* 將當前任務(wù)設(shè)置為運行狀態(tài) <-------------- */
        __set_current_state(TASK_RUNNING);
        
        /* 將對應(yīng)的隊列項從等待隊列頭刪除 <-------- */
        remove_wait_queue(&dev->r_wait, &wait);
    }

    keyvalue = atomic_read(&dev->keyvalue);
    releasekey = atomic_read(&dev->releasekey);

    /* 有按鍵按下 */
    if (releasekey)
    {
        //printk("releasekey!\r\n");
        if (keyvalue & 0x80)
        {
            keyvalue &= ~0x80;
            ret = copy_to_user(buf, &keyvalue, sizeof(keyvalue));
        }
        else
        {
            goto data_error;
        }
        atomic_set(&dev->releasekey, 0); /* 按下標志清零 */
    }
    else
    {
        goto data_error;
    }
    return 0;

wait_error:
    set_current_state(TASK_RUNNING);           /* 設(shè)置任務(wù)為運行態(tài) */
    remove_wait_queue(&dev->r_wait, &wait);    /* 將等待隊列移除 */
    return ret;
    
data_error:
    return -EINVAL;
}

按鍵的定時器去抖邏輯中的,讀取到按鍵后,觸發(fā)喚醒,這里以其中的一個按鍵為例,其邏輯如下:

void timer1_function(unsigned long arg)
{
    unsigned char value;
    struct irq_keydesc *keydesc;
    struct imx6uirq_dev *dev = (struct imx6uirq_dev *)arg;

    keydesc = &dev->irqkeydesc[0];

    value = gpio_get_value(keydesc->gpio); /* 讀取IO值 */
    if(value == 1) /* 按下按鍵 */
    {
        printk("get key1: high\r\n");
        atomic_set(&dev->keyvalue, keydesc->value);
    }
    else /* 按鍵松開 */
    {
        printk("key1 release\r\n");
        atomic_set(&dev->keyvalue, 0x80 | keydesc->value);
        atomic_set(&dev->releasekey, 1); /* 標記松開按鍵,即完成一次完整的按鍵過程 */            
    }
    
    /* 喚醒進程 */
    if(atomic_read(&dev->releasekey))
    {
        wake_up_interruptible(&dev->r_wait);
    }
}

1.2.2 應(yīng)用程序

應(yīng)用程序不需要修改,還使用之前的輪詢讀取的方式,為了在測試時看出阻塞與非阻塞方式的區(qū)別,在read函數(shù)前后添加打印,如果程序運行正常,會先打印read前一句的打印,直到有按鍵按下后,read函數(shù)才被接觸阻塞,read后一句的打印才會打印出。

/* 循環(huán)讀取按鍵值數(shù)據(jù)! */
while(1)
{
    printf("[APP] read begin...\r\n");
    read(fd, &keyvalue, sizeof(keyvalue));
    printf("[APP] read end\r\n");
    if (keyvalue == KEY1VALUE)
    {
        printf("[APP] KEY1 Press, value = %#X\r\n", keyvalue);
    }
    else if (keyvalue == KEY2VALUE)
    {
        printf("[APP] KEY2 Press, value = %#X\r\n", keyvalue);
    }
}

1.2 實驗

和之前一樣,使用Makefile編譯驅(qū)動程序和應(yīng)用程序,并復(fù)制到nfs根文件系統(tǒng)中。

開始測試,按如下圖,當沒有按鍵按下時,應(yīng)用程序被阻塞:

pYYBAGKPlZmAX1imAADhTzUjZGc198.png

按鍵程序在后臺運行,此時使用top指令開查看CPU的使用率,可以發(fā)現(xiàn)阻塞式按鍵驅(qū)動這種方式,CPU的暫用率幾乎為0,雖然按鍵應(yīng)用程序中仍實現(xiàn)循環(huán)讀取的方式,但因平時讀取不到按鍵值,按鍵應(yīng)用程序被阻塞住了,CPU的使用權(quán)被讓出,自然CPU的使用率就降下來了。

poYBAGKPlaGAGg-HAADTTCGipSQ073.png

2 非阻塞I/O方式的按鍵檢測

按鍵應(yīng)用程序以非阻塞的方式讀取,按鍵驅(qū)動程序也要以非阻塞的方式立即返回。應(yīng)用程序可以通過select、poll或epoll函數(shù)來 查詢設(shè)備是否可以操作,驅(qū)動程序使用poll函數(shù)。

2.1 非阻塞I/O之select/poll

select函數(shù)原型:

/**
 * nfs: 所要監(jiān)視的這三類文件描述集合中,最大文件描述符加1
 * readfds: 用于監(jiān)視指定描述符集的讀變化
 * writefds: 用于監(jiān)視文件是否可以進行寫操作
 * exceptfds: 用于監(jiān)視文件的異常
 * timeout: 超時時間
 * return: 0 超時發(fā)生, -1 發(fā)生錯誤, 其他值 可以進行操作的文件描述符個數(shù) 
 */
int select(int    nfds,  
           fd_set *readfds,  
           fd_set *writefds, 
           fd_set *exceptfds,  
           struct timeval *timeout) 

其中超時時間使用結(jié)構(gòu)體timeval表示:

struct timeval { 
   long tv_sec;  /* 秒   */ 
   long tv_usec; /* 微妙 */  
}; 

當timeout為NULL的時候就表示無限等待。

poll函數(shù)原型:

/**
 * fds: 要監(jiān)視的文件描述符集合以及要監(jiān)視的事件,為一個數(shù)組
 * nfds: 監(jiān)視的文件描述符數(shù)量
 * timeout: 超時時間,單位為 ms
 * return: 0 超時發(fā)生, -1 發(fā)生錯誤, 其他值 可以進行操作的文件描述符個數(shù) 
 */
int poll(struct pollfd *fds,  
         nfds_t nfds,  
         nt     timeout) 

2.2 非阻塞I/O程序編寫

2.2.1 驅(qū)動程序

poll函數(shù)處理部分:

unsigned int imx6uirq_poll(struct file *filp, struct poll_table_struct *wait)
{
    unsigned int mask = 0;
    struct imx6uirq_dev *dev = (struct imx6uirq_dev *)filp->private_data;

    /* 將等待隊列頭添加到poll_table中 */
    poll_wait(filp, &dev->r_wait, wait);
    
    /* 按鍵按下 */
    if(atomic_read(&dev->releasekey))
    {
        mask = POLLIN | POLLRDNORM;            /* 返回PLLIN */
    }
    return mask;
}

/* 設(shè)備操作函數(shù) */
static struct file_operations imx6uirq_fops = {
    .owner = THIS_MODULE,
    .open = imx6uirq_open,
    .read = imx6uirq_read,
    .poll = imx6uirq_poll,
};

read函數(shù)處理部分:

static ssize_t imx6uirq_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
    int ret = 0;
    unsigned char keyvalue = 0;
    unsigned char releasekey = 0;
    struct imx6uirq_dev *dev = (struct imx6uirq_dev *)filp->private_data;

    /* 非阻塞訪問 */
    if (filp->f_flags & O_NONBLOCK)
    {
        /* 沒有按鍵按下,返回-EAGAIN */
        if(atomic_read(&dev->releasekey) == 0)
        {
            return -EAGAIN;
        }
    }
    /* 阻塞訪問 */
    else
    {
        /* 加入等待隊列,等待被喚醒,也就是有按鍵按下 */
        ret = wait_event_interruptible(dev->r_wait, atomic_read(&dev->releasekey)); 
        if (ret)
        {
            goto wait_error;
        }
    }

    keyvalue = atomic_read(&dev->keyvalue);
    releasekey = atomic_read(&dev->releasekey);

    /* 有按鍵按下 */
    if (releasekey)
    {
        //printk("releasekey!\r\n");
        if (keyvalue & 0x80)
        {
            keyvalue &= ~0x80;
            ret = copy_to_user(buf, &keyvalue, sizeof(keyvalue));
        }
        else
        {
            goto data_error;
        }
        atomic_set(&dev->releasekey, 0); /* 按下標志清零 */
    }
    else
    {
        goto data_error;
    }
    return 0;

wait_error:
    return ret;
data_error:
    return -EINVAL;
}

2.2.2 應(yīng)用程序

2.2.2.1 poll方式讀取

注意open函數(shù)的參數(shù)是O_NONBLOCK,即非阻塞訪問,并且為了在測試時看出阻塞讀取與非阻塞讀取的區(qū)別,在poll函數(shù)前后添加打印,如果程序正常運行,poll函數(shù)則不會被阻塞,500ms超時未讀取到按鍵值后會再次循環(huán)讀取,實際效果就是可以看打一直有打印輸出。

    filename = argv[1];
    fd = open(filename, O_RDWR | O_NONBLOCK);    /* 非阻塞訪問 */
    if (fd < 0)
    {
        printf("[APP] Can't open file %s\r\n", filename);
        return -1;
    }

    /* 構(gòu)造結(jié)構(gòu)體 */
    fds.fd = fd;
    fds.events = POLLIN;
    while(1)
    {
        printf("[APP] poll begin... \r\n", data);
        ret = poll(&fds, 1, 500);
        printf("[APP] poll end \r\n", data);
        /* 數(shù)據(jù)有效 */
        if (ret > 0)
        {
            ret = read(fd, &data, sizeof(data));
            if(ret < 0)
            {
                /* 讀取錯誤 */
            }
            else
            {
                if(data)
                {
                    printf("[APP] key value = %d \r\n", data);
                }
            }     
        }
        /* 超時 */
        else if (ret == 0)
        {
            /* 用戶自定義超時處理 */
        }
        /* 錯誤 */
        else
        {
            /* 用戶自定義錯誤處理 */
        }
    }

2.2.2.2 select方式讀取

select方式讀取與poll方式類似,都是非阻塞讀取,程序類似:

while(1)
{
    FD_ZERO(&readfds);
    FD_SET(fd, &readfds);
    /* 構(gòu)造超時時間 */
    timeout.tv_sec = 0;
    timeout.tv_usec = 500000; /* 500ms */
    ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
    switch (ret)
    {
            /* 超時 */
        case 0:
            /* 用戶自定義超時處理 */
            break;
            /* 錯誤 */
        case -1:
            /* 用戶自定義錯誤處理 */
            break;
            /* 可以讀取數(shù)據(jù) */
        default:
            if(FD_ISSET(fd, &readfds))
            {
                ret = read(fd, &data, sizeof(data));
                if (ret < 0)
                {
                    /* 讀取錯誤 */
                }
                else
                {
                    if (data)
                    {
                        printf("key value=%d\r\n", data);
                    }
                }
            }
            break;
    }
}

2.3 實驗

2.3.1 poll方式讀取

和之前一樣,使用Makefile編譯驅(qū)動程序和應(yīng)用程序,并復(fù)制到nfs根文件系統(tǒng)中。

開始測試,按如下圖,當沒有按鍵按下時,應(yīng)用程序也沒有被阻塞,從不斷的打印就可以看出應(yīng)用程序在循環(huán)運行。當有按鍵按下時,能夠讀取到對應(yīng)的按鍵值。

poYBAGKPla2AK2AvAAFXYivs3Nw253.png

按鍵程序在后臺運行,此時使用top指令開查看CPU的使用率,可以發(fā)現(xiàn)非阻塞式按鍵驅(qū)動這種方式,CPU的暫用率也幾乎為0,雖然按鍵應(yīng)用程序中仍實現(xiàn)循環(huán)讀取的方式,但poll函數(shù)有500ms的超時設(shè)置,在超時等待的時間里,CPU的使用權(quán)也是被讓出,所以CPU的使用率也降下來了。

pYYBAGKPlbaAI8KoAADgwZ96jiI026.png

2.3.2 select方式讀取

select方式讀取與poll方式讀取的效果一樣。

使用ps指令查看poll方式的按鍵進行號,使用kill殺帶該進程,再運行select方式的按鍵應(yīng)用程序:

pYYBAGKPlb2APMsmAAFCfrAxqzU216.png

select非阻塞讀取的方式,CPU的暫用率也幾乎為0:

poYBAGKPlcOATnPFAADSWuc1oCw810.png

3 總結(jié)

本篇使用兩種I/O模型進行按鍵讀取:阻塞式I/O非用阻塞式I/O,通過實際的實驗,對比兩者方式的實際運行效果與主要區(qū)別,并查看CPU的占用率,兩種方式的CPU使用率都幾乎為0。

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

    關(guān)注

    5152

    文章

    19675

    瀏覽量

    317550
  • 驅(qū)動
    +關(guān)注

    關(guān)注

    12

    文章

    1918

    瀏覽量

    86933
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11511

    瀏覽量

    213803
  • i.MX6
    +關(guān)注

    關(guān)注

    1

    文章

    37

    瀏覽量

    16566
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

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

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

    i.MX6ULL嵌入Linux開發(fā)1-uboot移植初探

    本系列教程以i.MX6ULL處理器的ARM開發(fā)板為實驗基礎(chǔ),學(xué)習(xí)記錄嵌入Linux開發(fā)的各種知識與經(jīng)驗,主要內(nèi)容包括嵌入Linux移植,
    的頭像 發(fā)表于 03-07 08:57 ?4317次閱讀
    <b class='flag-5'>i.MX6ULL</b>嵌入<b class='flag-5'>式</b>Linux<b class='flag-5'>開發(fā)</b>1-uboot移植初探

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

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

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

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

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

    i.MX6UL/i.MX6ULL開發(fā)常見問題》基于米爾電子 i.MX6UL/i.MX6ULL產(chǎn)品(V.
    發(fā)表于 07-01 17:50

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

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

    i.MX6ULL核心板資源

    操作系統(tǒng)鏡像&amp;amp;燒寫工具提供資料提供相關(guān)的 BSP 源代碼、文件系統(tǒng)源代碼其它默認配置i.MX6ULL、512MB DDR3、4GB EMMC可選配置i.MX6ULL、2
    發(fā)表于 07-12 17:50

    初識 i.MX6ULL 寄存器

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

    《Linux設(shè)備驅(qū)動開發(fā)詳解》第8章、Linux設(shè)備驅(qū)動中的阻塞阻塞IO

    《Linux設(shè)備驅(qū)動開發(fā)詳解》第8章、Linux設(shè)備驅(qū)動中的阻塞阻塞IO
    發(fā)表于 10-27 11:35 ?9次下載
    《Linux設(shè)備<b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>詳解》第8章、Linux設(shè)備<b class='flag-5'>驅(qū)動</b>中的<b class='flag-5'>阻塞</b>與<b class='flag-5'>非</b><b class='flag-5'>阻塞</b>IO

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

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

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

    合作伙伴,飛凌不負美譽,基于i.MX6ULL匠心打造的FETMX6ULL-S核心板一經(jīng)問世便好評不斷,且已有數(shù)百家來自工業(yè)、醫(yī)療、電力、物聯(lián)網(wǎng)等行業(yè)的用戶采用此款核心板快速完成了整機產(chǎn)品的開發(fā)上市。
    發(fā)表于 04-11 15:05 ?1314次閱讀
    基于NXP <b class='flag-5'>i.MX6ULL</b>處理器的FETMX<b class='flag-5'>6ULL</b>-C核心板

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

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

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

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

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

    基于i.MX6ULL的掉電檢測設(shè)計與軟件測試基于i.MX6ULL平臺設(shè)計實現(xiàn)掉電檢測功能,首先選擇一路IO,利用IO電平變化觸發(fā)中斷,在編寫驅(qū)動
    的頭像 發(fā)表于 11-09 10:40 ?1192次閱讀
    基于<b class='flag-5'>i.MX6ULL</b>的掉電<b class='flag-5'>檢測</b>設(shè)計與軟件測試

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

    【迅為電子】i.MX6UL和i.MX6ULL芯片區(qū)別與開發(fā)板對比
    的頭像 發(fā)表于 11-28 14:31 ?1334次閱讀
    【迅為電子】<b class='flag-5'>i.MX6</b>UL和<b class='flag-5'>i.MX6ULL</b>芯片區(qū)別與<b class='flag-5'>開發(fā)</b>板對比