2008年6月13日 星期五

s3c2410 中斷異常處理(轉)

轉錄出處:幽靈空間 - 步入嵌入式 by Jacky Xu

這篇文章把2410中斷處理過程分析的淋漓盡致,感謝作者。。。

作者:蔡於清  www.another-prj.com

    在進入正題之前,我想先把ARM920T的異常向量表(Exception Vectors)做一個簡短的介紹。:]
ARM920T 的異常向量表有兩種存放方式,一種是低端存放(從0x00000000處開始存放),另一種是高端存放(從0xfff000000處開始存放)。關於為什麼要分兩種方式進行存放這點我將在介紹MMU的文章中進行說明,本文採用低端模式。ARM920T能處理有8個異常,他們分別是:
Reset,Undefined instruction,Software Interrupt,Abort (prefetch),Abort (data),Reserved,IRQ,FIQ
下面是某個採用低端模式的系統源碼片段:

_start:
b Handle_Reset
b HandleUndef
b HandleSWI
b HandlePrefetchAbort
b HandleDataAbort
b HandleNotUsed
b HandleIRQ
b HandleFIQ
…..

..
other codes

    上面這部分片段一般出現在一個名叫「head.s」的彙編文件裡,「b Handle_Reset」這條語句就是系統上電之後運行的第一條語句。也就是說這部分代碼的二進制碼必須位於內存的最開始部分(這正是低端存放模式),因為上電後CPU會從SDRAM的0x00000000處取第一條指令並執行。

Address     Instruct
0x00000000: b Handle_Reset
0x00000004: b HandleUndef
0x00000008: b HandleSWI
0x0000000C: b HandlePrefetchAbort
0x00000010: b HandleDataAbort
0x00000014: b HandleNotUsed
0x00000018: b HandleIRQ
0x0000001C: b HandleFIQ

    上面是該程序段在系統上電後加載到內存後的分佈情況,我們可以看到每條指令佔用了4個字節。
    上電後,PC指針會跳轉到Handle_Reset處開始運行。以後系統每當有異常出現,則CPU會根據異常號,從內存的0x00000000處開始查表做相應的處理,比如系統觸發了一個IRQ異常,IRQ為第6號異常,則CPU將把PC指向0x00000018地址(4*6=24=0x00000018)處運行,該地址的指令是跳轉到「中斷異常服務例程」(HandleIRQ)處運行。以上就是我對異常向量表的一個簡單介紹。現在可以進入我們文章的主題「中斷異常處理」,s3c2410的中斷分快中斷(FIQ)和普通中斷(IRQ),我們討論的重點是普通中斷(IRQ)。
s3c2410的中斷異常處理模塊總共由以下寄存器構成
  SRCPND(SOURCE PENDING REGISTER)
  INTMOD(INTERRUPT MODE REGISTER)
  INTMSK(INTERRUPT MASK REGISTER)
  PRIORITY( PRIORITY REGISTER)
  INTPND(INTERRUPT PENDING REGISTER)
  INTOFFSET(INTERRUPT OFFSET REGISTER)
  SUBSRCPND (INTERRUPT SUB SOURCE PENDING)
  INTSUBMSK  (INTERRUPT SUB MASK REGISTER)
下面我將講解每個寄存器在一個中斷處理流程中所扮演的角色:
    SRCPND/ SUBSRCPND這兩個寄存器在功能上是相同的,它們是中斷源引腳寄存器,在一個中斷異常處理流程中,中斷信號傳進中斷異常處理模塊後首先遇到的就是SRCPND/ SUBSRCPND,這兩個寄存器的作用是用於標示出哪個中斷請求被觸發。SRCPND的有效位為32,SUBSRCPND 的有效位為11,它們中的每一位分別代表一個中斷源。SRCPND為主中斷源引腳寄存器,SUBSRCPND為副中斷源引腳寄存器。
這裡列舉出SRCPND的各個位信息:
 

   每個位的初始值皆為0。假設現在系統觸發了TIMER0中斷,則第10bit將被置1,代表TIMER0中斷被觸發,該中斷請求即將被處理(若該中斷沒有被屏蔽的話)。SUBSRCPND情況與SRCPND相同,這裡就不多講了。
    INTMOD寄存器有效位為32位,每一位與SRCPND中各位相對應,它的作用是指定該位相應的中斷源處理模式(IRQ還是FIQ)。若某位為0,則該位相對應的中斷按IRQ模式處理,為1則以FIQ模式進行處理,該寄存器初始化值為0x00000000,即所有中斷皆以IRQ模式進行處理。(詳細請參考s3c2410操作手冊)。
INTMSK/ INTSUBMSK 寄存器為中斷屏蔽寄存器 ,INTMSK為主中斷屏蔽寄存器,INTSUBMSK為副中斷屏蔽寄存器。INTMSK有效位為32,INTSUBMSK有效位為11,這兩個寄存器各個位與SRCPNDSUBSRCPND分別對應。它們的作用是決定該位相應的中斷請求是否被處理。若某位被設置為1,則該位相對應的中斷產生後將被忽略(CPU不處理該中斷請求),設置為0則對其進行處理。這兩個寄存器初始化後的值是0xFFFFFFFF和0x7FF,既默認情況下所有的中斷都是被屏蔽的。
到目前為止我們總共講解了SRCPND,INTMOD,INTMSK,SUBSRCPND,INTSUBMSK
五個寄存器,在繼續講解PRIORITY寄存器之前我們先來看一張圖。

   先弄清楚一點,現在要討論的是一個中斷優先級的判斷問題。為什麼會有中斷有先級的問題呢?我們知道CPU某個時刻只能對一個中斷源進行中斷處理,如果現在有3個中斷同時發生了,那CPU要按什麼順序處理這個3個中斷呢?這正是引入優先級判斷的原因所在,通過優先級判斷,CPU可以按某種順序逐個處理中斷請求。3sc2410的優先級判斷分為兩級。
    如上圖所示,SRCPND寄存器對應的32個中斷源總共被分為6個組,每個組由一個ARBITER(0~5)寄存器對其進行管理。中斷必須先由所屬組的ARBITER(0~5)進行第一次優先級判斷(第一級判斷)後再發往ARBITER6進行最終的判斷(第二級判斷)。ARBITER(0~5)這六個組的優先級已經固定,我們無法改變,也就是說由ARBITER0控制的該組中斷優先級最高(該組產生的中斷進行第一級判斷後永遠會以REQ0向ARBITER6傳遞過去)其次是ARBITER1, ARBITER2, ARBITER4, ARBITER4, ARBITER5.我們能夠控制的是某個組裡面各個中斷的優先級順序。怎麼控制?通過PRIORITY寄存器進行控制:]
以下是PRIORITY寄存器各個位的參數表

   從表上我們可以知道PRIORITY寄存器內部各個位被分為兩種類型,一種是ARB_MODE,另一種為ARB_SEL, ARB_MODE類型有5組對應ARBITER(2~6)(PS:此處應更正為ARB_MODE類型有7組對應ARBITER(0~6),在datasheet中上表還有續表,為ARB_MODE1-0),ARB_SEL類型有7組對應ARBITER(0~6)。現在我將以ARBITER2為例,講解中斷組與PRIORITY寄存器中ARB_SEL, ARB_MODE之間的相互關係。
  首先我們看到ARBITER2寄存器管理的該組中斷裡包括了6個中斷,分別是INT_TIMER0,INT_TIMER1,INT_TIMER2,INT_TIMER3,INT_TIMER4,INT_UART2,她們的默認中斷請求號分別為REQ0,REQ1,REQ2,REQ3,REQ4,REQ5。我們先看PRIORITY寄存器中的ARB_SEL2,該參數由兩個位組成,初始值為00。從該表可以看出00定義了一個順序 0-1-2-3-4-5 ,這個順序就是這組中斷組的優先級排列,這個順序指明了以中斷請求號為0(REQ0)的INT_TIMER0具有最高的中斷優先級,其次是INT_TIMER1,INT_TIMER2…。假設現在ARB_SEL2的值被我們設置為01。則一個新的優先級次序將被使用,01對應的優先級次序為0-2-3-4-1-5,從中可以看出優先級最高和最低的中斷請求和之前沒有變化,但本來處於第2優先級的INT_TIMER1中斷現在變成了第5優先級。從ARB_SEL2被設置為00,01,10,11各個值所出現的情況我們可以看出,除最高和最低的優先級不變以外,其他各個中斷的優先級其實是在做一個旋轉排列(rotate)。為了達到對各個中斷平等對待這一目標,我們可以讓優先級次序在每個中斷請求被處理完之後自動進行一次旋轉,如何自動讓它旋轉呢?我們可以通過ARB_MODE2達到這個目的,該參數隻有1個 bit,置1代表開啟對應中斷組的優先級次序旋轉,0則為關閉。事實上當該位置為1之後,每處裡完某個組的一個中斷後,該組的ARB_SEL便遞增在1(達到11後恢復為00)。
    現在我們另ARB_MODE2=1,ARB_SEL2=00,則當前ARBITER2的優先級順序為0-1-2-3-4-5,假設現在該組的1號中斷請求INT_TIMER1和2號中斷請求INT_TIMER2被同時觸發,CPU根據優先級判斷後決定先把INT_TIMER1中斷向ARBITER6進行發送(在ARBITER6做第最終優先級判斷),接著再向ARBITER6發送INT_TIMER2中斷。請注意,在INT_TIMER1被處理完畢後,該組中段的優先級次序被自動做了一次旋轉,旋轉後ARBITER2的優先級順序變為0-2-3-4-1-5。假設之後某個時刻該組的INT_TIMER1和INT_TIMER2又被同時觸發,則此時CPU優先處理的會是INT_TIMER2。若我們另ARB_MODE2=0,則改組的中斷優先級次序在任何情況下都不做任何改變,除非我們人為地重新設置了ARB_SEL2的值。
    呼。。。好累。。。終於說完了麻煩的優先級-_-…繼續。。。
INTPND 寄存器可能是整個中斷處理過程中我們要特別注意的一個寄存器了,他的操作比較特別,怎麼特別?請聽我慢慢道來.:]
先看一下該寄存器各位詳細功能列表

    正如你所見的,INTPND寄存器與SRCPND長得一模一樣,但他們在中斷異常處理中卻扮演著不同的角色,如果說SRCPND是中斷信號進入中斷處理模塊後所經過的第一個場所的話,那麼INTPND則是中斷信號在中斷處理模塊裡經歷的最後一個寄存器。它的每個位對應一個中斷請求,若該位被置1,則表示相應的中斷請求被觸發,描述到這裡你可能會發現它不僅和SRCPND長得一模一樣,就連功能都一樣,其實不然,他們在功能上有著重大的區別。SRCPND是中斷源引腳寄存器,某個位被置1表示相應的中斷被觸發,但我們知道在同一時刻內系統可以觸發若干個中斷,只要中斷被觸發了,SRCPND的相應位便被置1,也就是說SRCPND在同一時刻可以有若干位同時被置1,然而INTPND則不同,他在某一時刻只能有1個位被置1,INTPND 某個位被置1(該位對應的中斷在所有已觸發的中斷裡具有最高優先級且該中斷沒有被屏蔽),則表示CPU即將或已經在對該位相應的中斷進行處理。於是我們可以有一個總結:SRCPND說明了有什麼中斷被觸發了,INTPND說明了CPU即將或已經在對某一個中斷進行處理。
特別注意:每當某一個中斷被處理完之後,我們必須手動地把SRCPND/SUBSRCPND , INTPND三個寄存器中與該中斷相應的位由1設置為0,剛才我說INTPND的操作很特別,它的特別之處就在於對當我們要把該寄存器中某個值為1的位設置為0時,我們不是往該位置0,而是往該位置1。假設SRCPND=0x00000003,INTPND=0x00000001,該值說明當前0號中斷和1號中斷被觸發,但當前正在被處理的是0號中斷,處理完畢後我們應該這樣設置INTPND和SRCPND
  SRCPND=0x00000002              //位0被置為0
  INTPND =0x00000001             //位0被置為0(方法是往該位寫入1)
INTOFFSET寄存器的功能則很簡單,它的作用只是用於表明哪個中斷正在被處理。下面是該寄存器各位詳細功能列表

    若當前INT_TIMER0被觸發了,則該寄存器的值為10,以此類推。
    現在我把整個中斷流程用一個圖加以說明

以上這個圖清楚地說明了一個中斷異常處理流程。
    下面我用INT_TIMER0, INT_TIMER2和INT_UART0三個中斷完整地介紹一次中斷異常處理。首先我們得做幾個假設:

假設1:這三個中斷的屏蔽被取消。
假設2:PRIORITY寄存器中ARB_MODE2,ARB_MODE5皆為0,既不進行優先級的自動旋轉排序,任何時候
ARBITER2,ARBITER5控制的中斷組優先級次序分別為0-1-2-3-4-5和1-2-3-4。
假設3:這三個中斷皆為IRQ類型。
假設4:這三個中斷同時被觸發。
INT_TIMER0,INT_TIMER2和INT_UART0三個中斷被同時觸發,此時三個中斷信號流向SRCPND寄存器,使該寄存器中的第10位,12位,28位被置為1,中斷信號繼續向前流經INTMASK寄存器,這三個中斷都沒有被屏蔽,於是信號進一步流經INTMODE寄存器,這三個中斷皆為IRQ類型,故中斷信號繼續向前流向PRIORITY寄存器,經過優先級判斷,INT_TIMER0中斷信號使INTPND寄存器的第10位置1(INT_TIMER0優先級最高),此時INTOFFSET寄存器的值為10,CPU轉向相應的中斷服務例程進行處理。處理完畢後,我們的程序將INTPNDSRCPND的第10置為0,至此INT_TIMER0中斷處理完畢。此時SRCPND的第12位,28位仍為1(這兩個中斷請求未被處理),故他們會繼續被CPU已剛才描述的方式進行處理。
中斷異常處理就先講到這吧 :]

以上是原帖內容,再次感謝作者。。。

PS:

在對2410的裸板進行中斷實驗的過程中,從菜鳥的角度出發,我把學到了一些東西和之前ARM體系結構的理論結合起來:

1、在ARM處理器中,r13(sp)和r14(lr)分別對應6個不同狀態下的物理寄存器,其中1個是用戶、系統模式共用的,其他分別對應5種異常模式(Exception Mode)。要在後續程序中使用中斷,則應先把要用到的各種模式的堆棧設置好,如設置IRQ和系統模式的sp:

msr cpsr_c, #0xd2        @進入IRQ模式,IRQ和FIQ都處於禁止狀態
ldr sp, =0x33000000
msr cpsr_c, #0xdf        @進入系統模式,IRQ和FIQ都處於禁止狀態
ldr sp, =0x34000000
bl init_irq              @初始化中斷
msr cpsr_r, #0x5f        @置控制域的I位為0,打開irq中斷。實驗中只用到irq

2、 如果用到按鍵等中斷控制,是屬於外部中斷的(External Interrupt),就需要配置EINT相關的寄存器。

原文地址 http://www.another-prj.com/viewthread.php?tid=14&extra=page%3D1

對S3C2410數據手冊中DMA部分的解讀(轉)

轉錄出處:幽靈空間 - 步入嵌入式 by Jacky Xu

在s3c2410數據手冊的中文翻譯版本基礎之上,我進行了部分知識點的歸納。

DMA請求源

通過設置DCON[23]位SWHW_SEL值,選擇硬/軟件請求,並可進一步通過設置HWSRCSEL[26:24]位選擇HW模式下的每個DMA通道的請求源

DMA工作過程

使用三態FSM(有限狀態機)進行操作,分三步操作:

Stage-1 初始狀態,等待DMA請求,若請求到達,進入Stage-2。此階段,DMA ACK和INT REQ都為0。

Stage-2 DMA ACK變為1,計數器CURR_TC從DCON[19:0]加載數值。注意:此時DMA ACK仍然為1,知道它隨後在stage-3中被清0。

Stage-3 在此狀態,對DMA進行原子操作的sub-FSM(子狀態機)被初始化它從源地址讀取數據然後寫入目的地址(此操作需要考慮數據大小和傳輸尺寸)。

每一次DMA傳輸,必須先得到請求。

有兩種請求模式:DemandHandshake

差別在於是否等待DREQ信號無效:

Handshake模式下,DMA控制器在開始下一次傳輸之前要一直等待直到DREQ信號無效。如果DREQ信號無效了,DMA 控制器使DACK無效後繼續等待下一次DREQ信號有效,之後又開始數據傳輸,且使DACK信號有效。

Demand模式下,DMA控制器不等待DREQ信號無效。如果傳輸完畢後DREQ還是繼續有效,DMA控制器只是先無效DACK信號,然後又開始新一輪的傳輸。數據手冊上建議對外部DMA請求使用Handshake模式,以避免不經意的開始新一輪數據傳輸。

有兩種傳輸模式:Single serviceWhole service

差別在於三態FSM操作的Stage-3:

在Stage-3狀態,對DMA進行原子操作的Sub-FSM被初始化,它從源地址讀取數據然後寫入目的地址(此操作需要考慮數據大小和傳輸尺寸)。

Whole service模式下,這種讀、寫操作重複進行直到計數器(CURR_TC)變為0;而Single service模式下讀和寫操作只進行一次。

數據手冊上提醒注意:就算是Whole service傳輸模式,每一次sub-fsm的原子傳輸後DMA也會釋放總線,然後再試圖重新獲得總線,以保證其他設備能夠有機會獲得總線使用權。

每次原子傳輸(Sub-FSM中)的單元尺寸分為Unit1次讀和寫操作,單塊數據)和Burst4(分別執行4次連續讀、寫操作,4塊數據)。

下面是轉載來的:

之所以要介紹DMA,因為它對性能太重要了!只有活用了DMA,CPU的性能才能上去!S3c2410有四個DMA,每個DMA支持工作方式基本相同,但支持的source Dest可能略有不同,具體見Datasheet。

這裡具體DMA CONTROL寄存器(DCON)的配置說明,進而引出DMA的各種工作方式。

Atomic transfer:指的是DMA的單次原子操作,它可以是Unit模式(傳輸1個data size),也可以是burst模式(傳輸4個data size),具體對應DCON[28]。

Data Size:指的是單次原子操作的數據位寬,8、16、32,具體對應DCON[21:20]。

Request Source:DMA請求的來源有兩種,軟件&硬件模塊,由DCON[23]控制;當為前者時,由軟件對DMASKTRIG寄存器的位0置位觸發一次DMA 操作。當為後者時,具體來源由DCON[26:24]控制,不同硬件模塊的某時間觸發一次DMA操作,具體要見不同的硬件模塊。

DMA service mode:DMA的工作模式有兩種,單一服務模式&整體服務模式。前一模式下,一次DMA請求完成一項原子操作,並且transfer count的值減1。後一模式下,一次DMA請求完成一批原子操作,直到transfer count等於0表示完成一次整體服務。具體對應DCON[27]。

RELOAD:在reload模式下,當transfer count的值變為零時,將自動加src、dst、TC的值加載到CURR_DST、CURR_SRC、CURR_TC,並開始一次新的DMA傳輸。該模式一般和整體服務模式一起使用,也就是說當一次整體服務開始後,src、dst、TC的值都已經被加載,因此可以更改為下一次服務的地址,2410說明文檔中建議加入以下語句來判斷當前的服務開始,src、dst、TC的值可以被更改了:while((rDSTATn & 0xfffff) == 0) ;

Req&Ack:DMA請求和應答的協議有兩種,Demard mode 和 Handshake mode。兩者對Request和Ack的時序定義有所不同:在Demard模式下,如果DMA完成一次請求如果Request仍然有效,那麼DMA就認為這是下一次DMA請求;在Handshake模式下,DMA完成一次請求後等待Request信號無效,然後把ACK也置無效,再等待下一次Request。這個設計外部DMA請求時可能要用到。

傳輸總長度:DMA一次整體服務傳輸的總長度為:
Data Size × Atomic transfer size × TC(字節)。

2410的DMA支持四類DMA傳輸:系統總線到系統總線(ASB/AHB to ASB/AHB),系統總線到外設總線(ASB/AHB to APB),外設總線到系統總線(APB to ASB/AHB),外設總線到外設總線(APB to APB)。

2410共有四條DMA通道,每條通道5個請求源。

Ch0:nXDREQ0,UART0,SDI,Timer,USB EP1
Ch1: nXDREQ1,UART1,I2SSDI,SPI0,USB EP2
Ch2:I2SSDO,I2SSDI,SDI,Timer, USB EP3
Ch3:UART1,SDI,SPI1,Timer, USB EP4

2410 DMA 三個比較重要的信號,引用2410官方文檔:

DMA REQ: In the Single service mode, these three states of main FSM are performed and then stops, and waits for another DMA REQ. And if DMA REQ comes in, all three states are repeated.

DMA ACK: DMA ACK is asserted and then deasserted for each atomic transfer. In contrast, in the Whole service mode, main FSM waits at state-3 until CURR_TC becomes 0. Therefore, DMA ACK is asserted during all the transfers and then deasserted when TC reaches 0.

INT REQ: INT REQ is asserted only if CURR_TC becomes 0 regardless of the service mode (Single service mode or Whole service mode).

2410 DMA狀態機:

2410 的DMA使用一個具有三個狀態的有限狀態機進行DMA 傳輸的流程控制,引用2410官方文檔:
State-1. As an initial state, the DMA waits for a DMA request. If it comes, it goes to state-2. At this state, DMA ACK and INT REQ are 0.
State-2. In this state, DMA ACK becomes 1 and the counter (CURR_TC) is loaded from DCON[19:0] register. Note that the DMA ACK remains 1 until it is cleared later.
State-3. In this state, sub-FSM handling the atomic operation of DMA is initiated. The sub-FSM reads the data from the source address and then writes it to destination address. In this operation, data size and transfer size(single or burst) are considered.

每當一次DMA操作結束,不管是使用什麼服務模式,DMA狀態機都會自動地從狀態三回到狀態一,開始另一次操作。注意這裡信號是DMA REQ 和 DMA ACK,而最終引腳信號是nXDREQ 和 nXDACK,所以最後實際輸出的電平與這裡的描述是相反的。

2410 DMA 的服務模式:

共有兩種服務模式,一種是單一服務模式(single service),另外一種是整體服務模式(whole service)。

在單一服務模式下,不使用傳統的DMA計數器,三個DMA狀態被順序執行一次後停止,等待DMA 請求再一次來臨後再重新開始另一次循環。
在整體服務模式下,使用傳統的DMA 計數器,狀態機會停留在狀態三,直到DMA計數器的值減為零,再回到狀態一,等待下一次DMA請求。

2410 DMA 數據傳輸模式:

共有兩種數據傳輸模式:
單位數據傳輸模式:執行一次讀操作和一次寫操作。
並發數據傳輸模式:執行四次讀操作和四次寫操作。

2410 DMA 的基本時序:

nXDREQ請求生效並經過2CLK週期同步後,nXDACK響應並開始生效,但至少還要經過3CLK的週期延遲,DMA控制器才可獲得總線的控制權,並開始數據傳輸。

2410 DMA 的兩種協議模式:

請求模式:If XnXDREQ remains asserted, the next transfer starts immediately. Otherwise it waits for XnXDREQ to be asserted.
握手模式:If XnXDREQ is deasserted, DMA deasserts XnXDACK in 2cycles. Otherwise it waits until XnXDREQ is deasserted.

2008年5月28日 星期三

Coasia s3c2440-I2S 設定值

iiscon 

黃色部份是IISCON的初始化值

在Transmit時需將Transmit DMA service request Enable 

                  和 Transmit channel idle command Not idle

iiscon |= S3C2410_IISCON_TXDMAEN | S3C2410_IISCON_IISEN;

傳送完之後要把上述兩項關掉

iismod

黃色部份是IISMOD的初始化值

static int s3c24xx_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
    int div_id, int div)
{   
    switch (div_id) {    
    case S3C24XX_DIV_MCLK:
        reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD)| (S3C2410_IISMOD_384FS);
        writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD);
        break;
    }
}

在這個Function裡原本會將S3C2410_IISMOD_384FS關掉

但因WinCE裡的初始設定是384FS,所以把他打開

static int s3c24xx_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai,
        unsigned int fmt)
{
    switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
    case SND_SOC_DAIFMT_CBM_CFM:
        iismod |= S3C2410_IISMOD_MASTER;
        break;
    case SND_SOC_DAIFMT_CBS_CFS:
        break;
    default:
        return -EINVAL;
    }     switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    case SND_SOC_DAIFMT_LEFT_J:
        iismod |= S3C2410_IISMOD_MSB;
        break;
    case SND_SOC_DAIFMT_I2S:
        iismod |= S3C2410_IISMOD_IIS;
                break;
    default:
        return -EINVAL;
    }
    return 0;
}

這個Function裡原本是將iismod設為S3C2410_IISMOD_SLAVE

但因WinCE裡的初始設定是MASTER,所以把他改成S3C2410_IISMOD_MASTER

S3C2410_IISMOD_MASTER並未在reg-iis.h設定,所以必須自已去加進去

#define S3C2410_IISMOD_MASTER     (0<<8)

iisfcon

黃色部份是IISFCON的初始化值

這個值只有在Transmit關掉時要把他關掉

2008年4月8日 星期二

LED設定GPIO B的值

pLED->pIOReg->GPBCON &= ~(0xf<<4);
pLED->pIOReg->GPBCON |= (0x5<<4);

pLED->pIOReg->GPBUDP &= ~(0xf<<4);
pLED->pIOReg->GPBUDP |= (0x00<<4);


pLED->pIOReg->GPBDAT |= (0xf<<2);


強者正哥找出來的值
三顆LED都亮的設定值

Map in GPIO registers

pVMem = (PUCHAR)VirtualAlloc(0, PAGE_SIZE*3, MEM_RESERVE,PAGE_NOACCESS);

if (pVMem) {
   // map in GPIO registers
   pVMem += PAGE_SIZE;
   bMapReturn = VirtualCopy(pVMem,
   (LPVOID)(S3C2443_BASE_REG_PA_IOPORT>>8),PAGE_SIZE,PAGE_READWRITE | PAGE_NOCACHE |PAGE_PHYSICAL);

   if (!bMapReturn) {
      err = GetLastError();
      return err;
   }
pLED->pIOReg = (volatile S3C2443_IOPORT_REG*)(pVMem);
}

一定要在Driver Init時就先Map好

然後進HW_Init時,對暫存器做動作才會有反應

這個Bug花了我好幾天的時間啊= =

害我還加了一堆我自已都覺得沒用的東西進去....


2008年3月31日 星期一

Wince中使用Platform裡的include檔

新建的WCE Dynamic-Link Library中
不能使用Platform裡的include檔
必須在Project中的sources檔裡加上
編譯就可以過啦

INCLUDES= \
$(_WINCEROOT)\public\common\ddk\inc;
$(_TARGETPLATROOT)\SRC\inc;
$(_WINCEROOT)\public\common\oak\inc;
$(INCLUDES) \

應該要接在一行
可是太長版面顯示不出來

2007年10月19日 星期五

ubuntu小小心得Ⅱ

如何在載入 GNOME 時啟動 Num Lock ?

sudo apt-get install numlockx
sudo cp /etc/X11/gdm/Init/Default /etc/X11/gdm/Init/Default_backup
sudo gedit /etc/X11/gdm/Init/Default

找到此段 ...
exit 0

在後面增加此段敘述

if [ -x /usr/bin/numlockx ]; then
/usr/bin/numlockx on
fi

如何修改開機時 GRUB 等待時間?

sudo cp /boot/grub/menu.lst /boot/grub/menu.lst_backup
sudo gedit /boot/grub/menu.lst

找到此行 ...
timeout 3
...

指定所需要的秒數 timeout 等待秒數
存檔

如何修改開機時 GRUB 啟動預設作業系統?

sudo cp /boot/grub/menu.lst /boot/grub/menu.lst_backup
sudo gedit /boot/grub/menu.lst

找到此行 ...
default 0
...

項目從零開始算起,請按照項目順序選擇 default 項目順序
存檔