1. 程式人生 > >CYPEESS USB3.0程式解讀之---GPIO

CYPEESS USB3.0程式解讀之---GPIO

CPRESS 官方給出的SDK1.1中(目前最新的SDK),提供了大量的例程供我們開發軟體的時候作參考,就像STM32的開發一樣提供了庫一樣,但是又不是庫,僅僅是參考例程。

首先看一個簡單一點的GPIO的例子(GpioApp)

1.先是一個錯誤處理的函式,我們不需要它,故這是一個死迴圈。

2. CyFxDebugInit 這個函式,將串列埠作為除錯口用115200bps。

3.

void CyFxGpioIntrCb (

uint8_t gpioId /* Indicates thepin that triggered the interrupt */

)

 這個函式是一箇中斷回撥函式。必須在某個地方註冊一下。

 它有下列過程:

apiRetStatus=CyU3PGpioGetValue(gpioID,&gpioValue);

這個函式得到某個埠中斷的值

這個gpioValue是一個BOOL值。而ID則是某一個埠的埠號。這個函式只能返回一個引腳。

下面介紹這個ID是什麼指定的。

4.

CyU3PEventSet(&glFxGpioAppEvent,CY_FX_GPIOAPP_GPIO_HIGH_EVENT,CYU3P_EVENT_OR); 

如果為高,則設定一個事件。是一個高事件發生。注意到事件是一個全域性變數,而這個事件中有許多引數,其中比較重要的是一個回撥函式。應該在某個地方將這個事件與一個回撥函式聯絡起來。

5.voidCyFxGpioInit (void

apiRetStatus =CyU3PGpioInit(&gpioClock,CyFxGpioIntrCB);

這個函式是設定gpio的時鐘,以及中斷的回撥函式。這與4中部分形成對照。

然後將gpio45定義為輸入且允許中斷

    gpioConfig.intrMode = CY_U3P_GPIO_INTR_BOTH_EDGE;

    apiRetStatus = CyU3PGpioSetSimpleConfig(45, &gpioConfig);

GPIO的21指令碼來作為GPIF的控制訊號的。不能用CyU3PDeviceConfigureIOMatrix來將它作為GPIF IOs.

這個過載API呼叫必須進行必須小心當改變這個引腳的功能時。如果IO腳作為GPIF的一部分連到外部裝置上。則它不能再作為GPIF IO使用。在這裡CTL4是不使用的,所以用它用IO腳是安全的。

apiRetStatus = CyU3PDeviceGpioOverride(21,CyTrue);

接下來

apiRetStatus =CyU3PGpioSetSimpleConfig(21,&gpioConfig);

6. 接下來有兩個執行緒,一個是輸出執行緒,一個是輸入執行緒,先看輸出執行緒:

apiRetStatus = CyFxDebugInit(); 

初始化除錯模式。這個在2中定義的。

CyFxGpioInit(); 

這個也在前面定義過。後面是一個閃燈程式。

apiRetStatus = CyU3PGpioSetValue(21,true);

將輸出置為高。

延時2秒,將輸出變為低。

延時2秒。

7. 下面再來看輸入執行緒:是一個迴圈,等事件發生。

txApiRetStatus = CyU3PEventGet(&glFxGpioAppEvent,

(CY_FX_GPIOAPP_GPIO_HIGH_EVENT |CY_FX_GPIOAPP_GPIO_LOW_EVENT),

CYU3P_EVENT_OR_CLEAR,&eventFlag, CYU3P_WAIT_FOREVER);

這裡表示永遠等下去。等到後要清除事件,另返回事件的標誌,這個標誌我們沒有用。如果等到高的標誌,就列印一個引腳為高,如果為低,就列印一個引腳為低的標誌。估計這個等事件標誌將被block.

這樣整個過程清楚了,IO腳觸發引起一箇中斷。這個中斷回撥函式中將觸發一個事件。在這個執行緒中將等事件發生,如果發生了,就打印出引腳的狀態。

事件在什麼地方初始化呢?還是不需要初始化?

8. 事件是要初始化的。在應用程式中初始化了,下面就看這個應用程式

先建立一個輸出執行緒。

再建立一個輸入執行緒

然後 

retThrdCreate =CyU3EventCreate(&glFxGpioAppEvent);

9. 最後看一下main()

main()中主要是將GPIO引腳初始化一下。

io_cfg.gpioSimpleEn[0] = 0;

io_cfg.gpioSimpleEn[1] = 0x00002000; /* GPIO 45 */

io_cfg.gpioComplexEn[0] = 0;

io_cfg.gpioComplexEn[1] = 0;

45引腳為什麼對應的是0x2000.?這是因為它是32位的,45引腳=32+13 ,這個第13位正好是0X2000(1<<13 就是0x2000)。

*例項總結

從main開始看起:

再看一下幾個定義:輸出執行緒,輸入執行緒及事件在檔案一開始就定義了。

CyU3PThread gpioOutputThread; /* GPIOthread structure */

CyU3PThreadgpioInputThread; /* GPIO thread structure */

CyU3PEventglFxGpioAppEvent; /* GPIO input event group. */

它主要是呼叫了一個串列埠設定函式,然後就進入到cache控制設定,再後來就是設定一個IO腳,45腳使之使能。並且選用配置模式(即LPP模式)。允許了UART,不允許IIC,IIS,SPI,另外isDQ32bit也不允許。這個表示它不支援GPIF的32位模式。

然後我們再看應用程式啟動,這是由系統自動呼叫的。我們可能修改它的內容,但是它是必須的。

這個函式中,它建立了兩個執行緒。一個是輸入執行緒,一個是輸出執行緒。

另外,容易遺忘的一件事是它建立了一個事件。事件的建立只要這樣就可以了:     

retThrdCreate = Cy3U3PEventCreate(&glFxGpioAppEvent);

再往上,就是輸入執行緒了。這個執行緒看輸入引腳的變化,而這個變化由中斷回撥函式引起,中斷回撥函式中,它會產生一個事件,而我們的執行緒就監視這個事件。如果有事件高發生,就串列埠列印一個引腳高,如果低,就列印一個引腳低。看它是如何實現的:

txApiRetStatus =CyU3PEventGet(&glFxGpioAppEvent,

(CY_FX_GPIOAPPP_GPIO_HIGH_EVENT|CY_FX_GPIOAPP_GPIO_LOW_EVENT),

CYU3P_EVENT_OR_CLEAR,&eventFlag,CYU3P_WAIT_FOREVER);

這是個等事件的函式,這個函式無法找到它的定義,它是一個API函式。我們找API,發現它的引數含義。

這裡有一個CYU3P_EVENT_OR_CLEAR表示只要上面有一個位被設定就返回且清除標誌。----OR。

而真正的事件就放在標誌中返回了。

既然有讀事件,就必有設定事件,事件的設定應該在中斷回撥中實現。而中斷回撥的註冊,應該在初始化時實現。下面應該可以很快看到這點。---事實上,在下面的輸出執行緒中就實現了註冊。

輸出執行緒實現,輸出執行緒比較有意思的是其DebugInit()居然是在它中間實現的,其實這個也可以在main中。

而接下來,它又呼叫了初始化GpioInit()這個函式。在這個函式中,先初始化GPIO,這個GPIO居然還要將時鐘也設定一下,有點不合常理。在這個初始化中,它還指明瞭GPIO中斷回撥函式的註冊。儘管這個中斷函式應該是在輸入執行緒中註冊似更合理一些。接下來,45腳要用之為輸入,所以要將配置設一下:

gpioConfig.outValue = CyTrue; //輸出為高 因為是輸入,要將它設為高

gpioConfig.inputEn = CyTrue; //輸入使能

gpioConfig.driveLowEn = CyFalse; //不要驅動低也不要驅動高

gpioConfig.driveHighEn = CyFalse;

gpioConfig.intrMode = CY_U3P_GPIO_INTR_BOTH_EDGE; //允許中斷

apiRetStatus = CyU3PGpioSetSimpleConfig(45, &gpioConfig);


如此這般配置了45腳。

接下來,要配置21腳,因為21腳比較特殊本來是用於GPIF的CTRL4的。現在要使用它就要過載一下:

這樣的IO腳是不可以象在主程式中哪樣,將它直接設為輸出的,而是要先過載。

同樣,看輸出腳是如何定義的

gpioConfig.outValue = CyFalse; //低電平

gpioConfig.driveLowEn = CyTrue; //允許低輸出

gpioConfig.driveHighEn = CyTrue; //允許高輸出

gpioConfig.inputEn = CyFalse; //方向設為輸出

gpioConfig.intrMode = CY_U3P_GPIO_NO_INTR; //不用中斷

再看一下回調函式,如何實現它的:

當引腳有跳變時,這個函式被呼叫。首先,它得到引腳的值。這個回撥函式是帶引數的。當它發生時,會帶過來一個引數。表明是哪一個引腳觸發了這個事件。這在庫函式中可能已經處理了,提供給使用者程式就不用麻煩再去看原因了。我想可能有一個機制,即有一箇中斷狀態暫存器,表示是哪一個引腳變化了。

在這裡呼叫了一個函式:

CyU3PGpioGetValue(gpioId,&gpioValue); 


注意到這個值是一個BOOL型的。

然後根據情況來設定事件:

CyU3PEventSet(&glFxGpioAppEvent,CY_FX_GPIOAPP_GPIO_HIGH_EVENT,CYU3P_EVENT_OR);

我們看,其中有要設定的事件指標,有什麼事件,以什麼方式設定,它是以OR的方式設定的。這個OR表示的是將這個第2個引數與當前的事件標誌進行或。顯然,如果相或的話,則事件標誌將被置1,而如果與則完全不同,它沒效果。(在得到事件中,有一個AND表示全部標誌都符合才生成事件,所以也是用OR的,不然,不可能全部符合的,永遠不會發生事件了,因為不可能既變高又變低的)。

至此整個程式解讀完了。在這個例子中,沒用到USB有關的部分。就是當一個MCU用的GPIO,因為這個晶片的CPU是ARM926EJ的核心,執行頻率可以達到200MHz,和之前的FX2晶片的51核心完全不是一個級別,所以這個做主控晶片是完全可以的。

相關推薦

CYPEESS USB3.0程式解讀---GPIO

CPRESS 官方給出的SDK1.1中(目前最新的SDK),提供了大量的例程供我們開發軟體的時候作參考,就像STM32的開發一樣提供了庫一樣,但是又不是庫,僅僅是參考例程。首先看一個簡單一點的GPIO的例子(GpioApp)1.先是一個錯誤處理的函式,我們不需要它,故這是一個

CYPEESS USB3.0程式解讀---SPI讀寫

前面已經解讀了GPIO以及同步FIFO操作,下面我們看一個SPI讀寫的例子,它是主程式命令從SPI中讀寫一些資料。SPI傳輸子程式看一下: 頁地址,位元組計數,緩衝區,讀寫標誌因為只能一頁一頁的讀或寫,故讀寫總是從頁地址開始的/* SPI read / writefor pr

Android6.0原始碼解讀Activity點選事件分發機制

    本篇博文是Android點選事件分發機制系列博文的第四篇,主要是從解讀Activity類的原始碼入手,根據原始碼理清Activity點選事件分發原理,並掌握Activity點選事件分法機制。特別宣告的是,本原始碼解讀是基於最新的Android6.0版本。

深入解讀HBase2.0新功能高可用讀Region Replica

數據庫摘要: 基於時間線一致的高可用讀(Timeline-consistent High Available Reads),又稱Region replica,為HBase帶來了高可用讀的能力。本文主要介紹region replica這個功能設計的背景,技術細節和使用方法,同時會仔細分析這個功能的優缺點並給出使

0開始的web程式

        寫寫自己剛入程式設計師,然後又走向JAVA,web短短一年的經驗和經歷,寫給未來自己,也寫給迷茫的新人們,讓他們少走一點彎路。         剛開始,學了c,就想做東西,現實狠狠的告訴我,發現只學了c做不了什麼

5.0 SpringBoot普通上傳功能 > 我的程式路:第四十章

SpringBoot 2.0 1.upLoad.html 1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.thymeleaf.org"> 3 <head> 4 <meta ch

5.0 SpringBoot普通上傳功能 > 我的程式路:第四十章

1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.thymeleaf.org"> 3 <head> 4 <meta charset="UTF-8"> 5 <title

USB3.0 RX Detect 的基本原理

RX Detect 的基本原理 在USB3.0 中 Device 連線到 Host等價於連線了一個R_Term 左圖為不接device的等效電路,此時由於R_term不存在,故電路模型實際為一RC串聯電路,可簡單計算出時間因子: T=R_DetectC_Parasitic, 右圖為接上de

深入解讀 HBase2.0 新功能高可用讀 Region Replica

1.前言 基於時間線一致的高可用讀(Timeline-consistent High Available Reads),又稱 Region replica。其實早在 HBase-1.2 版本的時候,這個功能就已經開發完畢了, 但是還是不太穩定,離生產可用級別還有一段距離,後來社群又陸陸續續修復了 一些 bu

USB3.0 HDMI輸入方案FT601Q

USB3.0 HDMI輸入方案之FT601Q        &nb

vue2.0學習筆記webpack-simple模板中的路由簡單配置案例

nbsp 主頁 default code vue 兩個文件 new ebp 命名 以下是完成後的目錄結構 案例基礎是已經用 webpack+vue-cli 創建了一個名為 vue_router的工程 , 並安裝了vue-rout

vue2.0學習筆記自定義組件

2.0 sco ron 自定義組件 定義 temp use 使用 imp step one: 推薦結構 step two: Loading.vue <template> <h3>{{msg}}<

win 7 旗艦版鏡像 註入USB3.0 驅動

win 7 旗艦版鏡像 註入usb3.0 驅動問題來源:原版的win7鏡像沒有集成USB3.0的驅動,然後如今的電腦主板基本是XHCI主控(以前是EHCI的),這一變動導致在安裝Win7的過程中會出現USB接口全部失靈的狀況,所以在安裝時無法識別USB3.0接口的鍵盤鼠標和U盤。這樣我們就只能在映像文件中添加

Android5.0網絡ipv6

ipv6地址 自己的 mod 大量 路由 ng- and 問題 ati 移動設備的大量興起勢必進一步加強ip地址不足的危機。ipv6或許成為一種比較好的選擇方案。 ipv6地址的獲取分為兩種方式:無狀態;有狀態 無狀態:通過接收路由公告(RA)來設置自己的ipv

dell usb3.0驅動故障

usb 驅動 dell 一、故障現象 dell3046 dell3050新主機安裝操作系統時,在BIOS、pe中能夠正常使用USB鍵鼠,安裝成功後,進入windows登錄後,安全模式,USB鍵鼠無任何反應。二、處理過程 1.因使用wds安裝系統,首先錯誤的認為是wds本身的問題,嘗試在WD

JDK 源碼解讀 Number類

only ria method key tty str can pre ati public abstract class Number implements java.io.Serializable {   Number類有修飾符 abstract 。表明Numbe

C語言在linux內核中do while(0)妙用

pos turn jsb world div fprintf cpp efault code 為什麽說do while(0) 妙?由於它的確就是妙,並且在linux內核中實現是相當的妙,我們來看看內核中的相關代碼: #define db_error(fmt, ..

JDK 源碼解讀 ArrayList

ont xtend empty 文檔 code access extend ces doesn public class ArrayList<E> extends AbstractList<E> implements List&l

Angular4.0踩坑路:探索子路由和懶加載

ati clas per 而是 配置 trap child property one 參考文章: Angular4路由快速入門 http://www.jianshu.com/p/e72c79c6968e Angular2文檔學習的知識點摘要——Angular模塊(NgMo

.NET Core 2.0遷移技巧MemoryCache問題修復

命名空間 ram ons ret http option ext obj mar 對於傳統的.NET Framework項目而言,System.Runtime.Caching命名空間是常用的工具了,其中MemoryCache類則常被用於實現內存緩存。 .NET Core