[英]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.