Je suis en train de développer un noyau de test pour les périphériques Raspberry Pi. Pour ce faire, je dois configurer l'UART afin que nous puissions écrire des données sur l'appareil et pouvoir récupérer les données qui doivent être traitées par le noyau. Je veux que le noyau de test puisse fonctionner sur plusieurs périphériques Raspberry Pi. Il existe cependant un léger problème:Comment déterminer la version de la carte Rasberry Pi en utilisant Arm Assembly/C?
Les adresses UART Diffèrent entre les versions. Par exemple, l'adresse de l'IPD 1 ligne UART GPIO est:
0x20200000
Mais l'adresse de l'UART GPIO sur les lignes RPi 2 et RPi 3 est:
0x3F200000
Bien sûr, cela signifie qu'il y Il faudrait deux fonctions UART_INIT distinctes: 1 pour les périphériques RPi 1 et 1 pour RPi 2 et au-delà.
Voici un exemple de code de manipulation UART. Ce code est modifié à partir du code fourni par 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));
}
Il y a une fonction secondaire, similaire pour la manipulation du UART INIT sur la ligne RPi 2 et 3 RPi. Avoir deux fonctions distinctes UART INIT est bien, et pas vraiment le problème. Le problème est de pouvoir distinguer les types de cartes. cela me sauverait beaucoup de tracas s'il y avait un moyen de déterminer la carte en cours d'utilisation. Ne pas pouvoir, signifie que j'ai besoin de faire un noyau de test séparé pour les cartes RPi 1, les cartes RPi 2-3 et toutes les autres cartes RPi, comme ODROID OC-2 par exemple. Si d'une manière ou d'une autre, il y avait un moyen de déterminer le type de carte, je pourrais l'utiliser comme une condition et charger les bonnes valeurs UART au démarrage, ce qui signifie que seul un fichier noyau unique est nécessaire. Une méthode qui pourrait fonctionner est le test basé sur le processeur, qui est unique entre chaque RPi Revision et les cartes alternatives. Sur les plates-formes x86, vous pouvez utiliser _RTDSC, mais je suis assez certain qu'aucune alternative de ce type n'existe sur les processeurs NON-x86/x86-64. Donc, la question que je pose est la suivante: existe-t-il un moyen, en assembleur ou en C, de vérifier le type de carte sur laquelle s'exécute l'utilisateur/le code? Puisque je construis un noyau de système d'exploitation, je n'ai pas accès aux bibliothèques de C de non-compilateur, ainsi le code de C devrait reporter à l'instruction d'assemblée volatile.
Ensuite, prenez un coup d'œil sur le module du noyau Linux existant responsable de la création de cette information . Mais je ne comprends pas vraiment comment vous créez un noyau portable pour les différentes versions, car l'UART n'est vraiment pas la seule et principale différence. Différents RP ont des processeurs différents –
@inifinitelyManiac l'utilisateur serait la personne avec le noyau de test sur le mSDHC. par exemple, j'ai un RPi 3b, mais un de mes amis a un RPi 1. Je cherchais un moyen de ne pas avoir à recompiler le noyau de test pour chaque variation du tableau. Je suppose que j'aurais dû être un peu plus précis là-bas. –
@eugene sh. le compilateur utilisé est une cible générique: gcc-arm-none-eabi. Je suis bien conscient des différences intrinsèques entre les conseils, mais tous utilisent l'assemblage des bras. L'exécutable du noyau est portable dans ce seul sens. –