1. 程式人生 > >nanoPc T2裸機開發(三)

nanoPc T2裸機開發(三)

---------------------------寫在前面

已經好久沒有玩微控制器了,之前玩的stm32根本就不算是學習,只是單純地使用之前學過的51知識和呼叫原子的庫函式,菜得一匹。有什麼不對的地方,還請大家指正,謝謝。

參考:

開發板是使用友善之臂的nanoPc T2,Soc是S5P4418,其他的外設自己看wiki吧,上面都有。我覺得挺不錯的,雖然我就只用過這家的,但是用起來還是不錯的。

這是我參考的例程,雖然我沒有進去看,(因為我沒有微博。。。。)但是我有他的全部相關資料原始碼,就是整理的微博上的。叫做迪卡大佬,強得一匹。

----------------------------正文

我將以串列埠波特率的修改,中斷,定時器,進行總結,以上均為參考迪卡

大佬的文章學之。

一、串列埠波特率

在我們進行測試的時候,nano與pc串列埠通訊的波特濾是115200,我們沒有進行設定,那這些資訊從哪來的呢?別忘了,我們還有沒能碰的2ndboot,那就他裡面的程式指令的功能效果。我們通過我們自己寫程式來修改串列埠波特率。首先,我們與pc通訊,是通過引腳rx tx這兩個引腳進行收發的,這裡也涉及了外部引腳,即GPIO的配置問題。

ok,一步步來,首先查原理圖


ok,這樣我們就知道了,與外部相接的UART是UART0,他是GPIOD18,所以,我們先檢視他的引腳複用情況,可以先查GPIOD14  18 因為你不知道他在裡面叫什麼名字,使用搜索的時候可能會出現搜不到的情況,所以我們搜GPIOD14  18,

這樣我們就知道了UARTTXD0的複用功能號為Function1,即為01,同時我們也知道了引腳號為18,再查

這個又能查出他的暫存器的地址了,所以給他賦值為5:4=01,即,第5、4位為01,該引腳為UART0功能。然後RT也是相同的方法進行尋找和設定。ok,繼續,TX是輸出,RX是輸入,那麼繼續配置他的輸入輸出暫存器,還是一些使能開關的配置等等,這些都是可以在datasheet上查的到的。然後就是時鐘了,波特率必然又時鐘的。

這是在datasheet上查到的,如果我們要設定9600的波特率的話,時鐘需要大於3.6864MHZ,迪卡大佬的例子裡使用了10M,那麼我們也使用10M吧,那麼我們就可以反推出Baud Rate Divisor=941.104167,他又兩個暫存器,一個放16bit的整數部分,一個放6bit的小數部分,941的16進製為0x41,0.104167的二進位制為0x000110,不斷二乘,保留6位,這裡是有誤差的,但也是不可避免的。好了,我們就可以對其進行配置了。然後設定停止位啊,清除標誌位啊,巴拉巴拉的。ok,這就可以用了。

好,怎麼使用呢?我們傳送出去,我們要把資料放在資料暫存器中,供其傳送,即UARTDR暫存器,OK了。這就可以使用了。

二、定時器

這個就很簡單了,我也沒仔細看,就和設定UART的波特率的相似,找到相應的暫存器,進行配置就ok了,pwm也沒有詳細看看他有沒有很方便的功能引腳,直接輸出pwm,還是用定時器來模擬的。

三、中斷

關於中斷,我理解得不太深。現在我還沒有找到CPSR暫存器是在哪,搜技術文件也沒找著。先放著吧,等以後再說。

哎,看不懂啊。。。那一堆英文文件講得都是啥啊GIC啊,什麼玩意兒啊。。。。不懂不懂。看看能不能強行使用。

我們使用VIC吧:

中斷源有64 個,[31:0]是一組為CH0,,[63:32]是一組為CH1

VICIRQSTATUS 只讀讀取的為IRQ 中斷狀態,受遮蔽位影響
VICFIQSTATUS 只讀讀取的為FIQ 中斷狀態,受遮蔽位影響
VICRAWINTR 只讀就像英文表達一樣,是生的中斷(沒有經過加工的,被遮蔽之前的)
VICINTSELECT 用來選擇中斷源,中斷時為IRQ 還是FIQ
VICINTENABLE 用來設定某一位中斷允許
VICINTENCLEAR 用來設定某一位中斷禁止
VICSOFTINT 用來設定某一位軟體中斷允許
VICSOFTINTCLEAR 用來設定某一位軟體中斷禁止
VICPROTECTION 保護模式不用管它啦
VICSWPRIORITYMASK 16 箇中斷優先順序遮蔽
VICVECTPRIORITYDAISY 向量中斷優先順序菊花鏈使用者可以通過程式設計選擇16 個向量中斷優
先級中任意一個優先順序為(看不懂)
VICVECTADDR0-31 一共32 個暫存器,用來存放ISR 向量的地址,只有相關中斷暫存器disable
時才能寫入,切記
如果系統不支援中斷向量地址,VICECTADDR 暫存器可以被程式設計為中斷源埠數字,這樣可
以容易的被確定
VICVECTPRIORITY0-31 一共32 個暫存器,選擇中斷優先順序
VICADDDRESS 當前active ISR,復位值為0x00000000,讀可以讀到ISR 地址,並設定當前中
斷被服務

以上是我直接從迪卡大佬那搬來的

彙編那裡看不懂啊,不過沒時間了,工作一天了。。。有點累。講一下大致思想吧。應該能用。

An FIQ or an IRQ (interrupt requests) are signaled by the Interrupt Controller to CPU. After arbitrating multiple

requests from internal peripherals and GPIO, the Controller requests an interrupt.

9.4.1 Interrupt Flow Sequence Using AHB
The following procedure shows the sequence for the IRQ interrupt flow:
 An IRQ interrupt occurs.
 The ARM processor branches to the IRQ interrupt vector
 Stack the workspace so that IRQ interrupts can be re-enabled later.
 Perform a dummy read to the VICADDRESS Register to set up priority status control in the VIC.
 Read the VICIRQSTATUS Register and determine which interrupt sources have to be service.
 Execute the ISR. At the beginning of the ISR, the interrupt of the processor can be re-enabled so that a higher
priority interrupt can be serviced.
 Clear the requesting interrupt in the peripheral, or write to the VICSOFTINTCLEAR Register if the request was
generated by a software interrupt.
 Disable the interrupt on the processor and restore the workspace.
 Write to the VICADDRESS Register. This clears the respective interrupt in the internal interrupt priority
hardware.

 Return from the interrupt. This re-enables the interrupts.

The following procedure shows the sequence for the FIQ interrupt flow.
 An FIQ interrupt occurs.
 The ARM processor branches to the FIQ interrupt vector.
 Branch to the ISR.
 Execute the ISR.
 Clear the requesting interrupt in the peripheral, or write to the VICSOFTINTCLEAR Register if the request was
generated by a software interrupt.
 Disable the interrupts and restore the workspace.

 Return from the interrupt. This re-enables the interrupts

應該這個就是介紹FIQ  IRQ的了吧,有空再翻譯吧。先mark。

我們現在只需要知道有兩個中斷方式,可以設定。然後查詢interrupt source 可知:

7 UART0 UART0 interrupt中斷源。只要有串列埠資訊就會觸發中斷,注意一下幾個語句:

VICVECTADDR7_CH0  = (unsigned int)UART0_ISR;                //UART0_ISR這個是中斷服務函式,把這個函式的入口地址賦給了VICVECTADDR7_CH0

if((addrCH0!=0) && (VICIRQSTTUS_CH0  & (1<<7) ))        //判斷標誌有觸發中斷
    {
       /*UART0*/
        p_func = (void(*)())addr_CH0;//讀取ISR地址,把地址傳給函式指標,就可以呼叫這個中斷服務函數了。

    }

彙編就看不懂了。。。。。

reset:
    /* 設定向量基址暫存器 */
    ldr r0, =_start
    mcr p15, 0, r0, c12, c0, 0
    mrc p15, 0, r0, c1, c0, 0
    bic r0, #(1<<13)
    mcr p15, 0, r0, c1, c0, 0
    /*開irq和fiq*/
    mrs    r5, cpsr                    @讀取cpsr->r5
    bic    r5, r5, #0xc0                @允許irq和fiq
    msr    cpsr, r5
    /*跳入C語言main程式*/
    bl main
    /*main執行完畢後,重新執行*/
    b reset

do_irqs:                       @將irq程式放在這兒
    ldr    sp, =0xffff9970 @隨便找了個應該用不到的地址來做棧區
    sub lr,lr,#4
    stmfd sp!,{r0-r12,lr}
    
    bl     do_irq
    

    ldmfd sp!,{r0-r12,pc}^

看註釋能知道是怎麼回事,如果讓自己寫的話,那就寫不出來了。這就有有點尷尬了。中斷還是難的啊。。。。不過給自己的時間有點少了,等下次再接觸這方面的東西再擼把。