2017-02-07 86 views
4

我正在爲Raspberry Pi設備開發測試內核。這樣做,我需要設置UART,以便我們可以將數據寫入設備,並能夠檢索需要由內核處理的數據。我希望測試內核能夠在多個Raspberry Pi設備上運行。雖然有一個小問題:如何使用Arm Assembly/C來確定Rasberry Pi板的版本?

UART地址不同之間的版本。例如,地址爲RPI 1線UART GPIO是:

0x20200000 

但在RPI 2和Rpi 3行的地址爲UART GPIO是:

0x3F200000 

自然地,這意味着有需要兩個獨立的UART_INIT功能:1個用於RPi 1線路設備,1個用於RPi 2及以上。

以下是UART處理代碼的示例。這個代碼是從由osdev提供的代碼修改:

void uart_init_rpi1() 
{ 
    // Disable UART0. 
    mmio_write(PD_UART_INTERNAL_VALUES_RPI1->UART0_CR, 0x00000000); 
    // Setup the GPIO pin 14 && 15. 

    // Disable pull up/down for all GPIO pins & delay for 150 cycles. 
    mmio_write(PD_GPPUD_RPI1, 0x00000000); 
    delay(150); 

    // Disable pull up/down for pin 14,15 & delay for 150 cycles. 
    mmio_write(PD_GPPUDCLK0_RPI1, (1 << 14) | (1 << 15)); 
    delay(150); 

    // Write 0 to GPPUDCLK0 to make it take effect. 
    mmio_write(PD_GPPUDCLK0_RPI1, 0x00000000); 

    // Clear pending interrupts. 
    mmio_write(PD_UART_INTERNAL_VALUES_RPI1->UART0_ICR, 0x7FF); 

    // Set integer & fractional part of baud rate. 
    // Divider = UART_CLOCK/(16 * Baud) 
    // Fraction part register = (Fractional part * 64) + 0.5 
    // UART_CLOCK = 3000000; Baud = 115200. 

    // Divider = 3000000/(16 * 115200) = 1.627 = ~1. 
    // Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40. 
    mmio_write(PD_UART_INTERNAL_VALUES_RPI1->UART0_IBRD, 1); 
    mmio_write(PD_UART_INTERNAL_VALUES_RPI1->UART0_FBRD, 40); 

    // Enable FIFO & 8 bit data transmissio (1 stop bit, no parity). 
    mmio_write(PD_UART_INTERNAL_VALUES_RPI1->UART0_LCRH, (1 << 4) | (1 << 5) | (1 << 6)); 

    // Mask all interrupts. 
    mmio_write(PD_UART_INTERNAL_VALUES_RPI1->UART0_IMSC, (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) | 
         (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)); 

    // Enable UART0, receive & transfer part of UART. 
    mmio_write(PD_UART_INTERNAL_VALUES_RPI1->UART0_CR, (1 << 0) | (1 << 8) | (1 << 9)); 
} 

有用於處理UART INIT的RPI 2和Rpi 3-3線的次級,類似的功能。有兩個獨立的UART INIT函數是好的,而不是真正的問題。問題是能夠區分不同的電路板類型。如果有方法可以確定當前使用的電路板,它會爲我節省很多麻煩。無法做到這一點,意味着我需要爲RPi 1板,RPi 2-3板和任何其他類似RPi的板製作單獨的測試內核,例如ODROID OC-2。如果不知何故,有一種方法可以確定板的類型,我可以用它作爲條件並在啓動時加載適當的UART值,這意味着只需要一個單獨的內核文件。一種可行的方法是基於處理器進行測試,這在每個RPi修訂版和其他板卡之間是獨一無二的。在x86平臺上,您可以使用_RTDSC,但我相當肯定在NON-x86/x86-64處理器上不存在這樣的替代方案。

所以,我問的問題是:有沒有一種方式,無論是在彙編或C,允許一種方式來檢查哪種類型的董事會,用戶/代碼運行?由於我構建的是操作系統內核,因此我無法訪問非編譯器C庫,因此C代碼將不得不遵守易失性彙編指令。

+1

然後看一看已有的Linux內核模塊負責創建此信息。但我不太瞭解你如何爲不同版本創建便攜式內核,因爲UART並不是唯一的主要區別。不同的RP有不同的CPU –

+0

@inifinitelyManiac用戶應該是具有mSDHC上測試內核的人員。例如,我有一個RPi 3b,但我的一個朋友有一個RPi 1.我正在尋找一種方法,我不必爲每個板子變體重新編譯測試內核。我想我應該在那裏更具體。 –

+0

@eugene sh。正在使用的編譯器是一個通用目標:gcc-arm-none-eabi。我很瞭解板之間的內在差異,但他們都使用臂組裝。內核可執行文件在這個意義上是可移植的。 –

回答

1

RP1,RP2和RP2 v1.2(向前)的ARM內核是不同的, ARM11,Cortex-A7和Cortex-A53。

但是,ARM CP15具有關於內核體系結構,部件號和修訂版的信息,根據ARM文檔,相同的指令可以獲取兩個內核的詳細信息。

MRC p15,0,<Rd>,c0,c0,0; reads Main ID register 

ARM11將返回部分數量0xB76
的Cortex-A7會給0xC07
和Cortex-A53會給0xD03。

請參閱下面從infocenter.arm兩個引用(我不能添加更多的是兩個環節,所以提供給老人和引用最新那些只)

參考文獻:
ARM1176JZF-S(PI-1 ):
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/Bgbiddeb.html

Cortex-A53(PI-2 v1。2開始):http://infocenter.arm.com/help/topic/com.arm.doc.ddi0500g/BABFEABI.html

希望它有幫助。

[由於老定時器進行校正]

+0

pi2和p3是不同的內核,pi2是armv7 pi3 armv8(64位) –

+0

@舊計時器感謝您的輸入。我已經糾正了答案。 – RuSh

+0

注意pizero是一個縮小的pi1,因此它使用的是與arm地址空間中的pi1和相同外設基地址相同的芯片。 –

3

由於pi的每一代使用從臂不同的CPU核心(一個特定的ARMv6那麼ARMv7的再一個armv8)可以很容易地從一個CPU ID檢測到它們寄存器。

.globl GETCPUID 
GETCPUID: 
    mrc p15,0,r0,c0,c0,0 
    bx lr 

不同纖芯返回不同的值

PI3 0x410FD034 
PI2 0x410FC075 
PI1/Zero 0x410FB767 

並從那裏你可以設置你周圍的基礎

if((id&0xFFFFFFFF)==0x410FB767) PBASE=0x20000000; 
else       PBASE=0x3F000000;