簡體   English   中英

如何使用Arm Assembly / C確定Rasberry Pi板版?

[英]How to determine Rasberry Pi board version using Arm Assembly/C?

我正在為Raspberry Pi設備開發測試內核。 在這樣做時,我需要設置UART,以便我們可以將數據寫入設備並能夠檢索需要由內核處理的數據。 我希望測試內核能夠在多個Raspberry 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));
}

在RPi 2和RPi 3線路上處理UART INIT有一個輔助的類似功能。 有兩個單獨的UART INIT功能很好,而不是真正的問題。 問題是能夠區分板類型。 如果有辦法確定當前使用的電路板,它會為我省去很多麻煩。 不能,意味着我需要為RPi 1板,RPi 2-3板和任何其他RPi板(例如ODROID OC-2)制作單獨的測試內核。 如果以某種方式,有一種方法可以確定板類型,我可以將它用作條件並在引導時加載正確的UART值,這意味着只需要一個單一的內核文件。 可能有效的一種方法是基於處理器進行測試,該處理器在每個RPi版本和備用板之間是唯一的。 在x86平台上,您可以使用_RTDSC,但我相當肯定在NON-x86 / x86-64處理器上不存在這樣的替代方案。

所以,我問的問題是:有沒有辦法,無論是在匯編還是C中,都可以通過某種方式檢查運行用戶/代碼的電路板類型? 由於我正在構建OS內核,因此我無法訪問非編譯器C庫,因此C代碼必須遵循易失性匯編指令。

由於每一代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;

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

希望能幫助到你。

[感謝老人更正]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM