
Cet article est la conclusion logique d'une
série d' articles sur l'
escalade d'Elbrus sur l'introduction d'
Embox à l'
architecture de processeur Elbrus (E2K) . Pourquoi une conclusion logique, car en conséquence, il était possible d'exécuter via telnet une application qui affiche l'image à l'écran, c'est-à-dire pour réaliser le fonctionnement complet d'Embox sur cette architecture. De nouvelles recherches peuvent difficilement être qualifiées d'introduction, bien que, bien sûr, beaucoup de choses restent floues. Et l'architecture elle-même possède de nombreuses fonctionnalités intéressantes, qui ne sont pas non plus actuellement comprises. Dans cet article, nous nous concentrerons sur l'organisation de la mémoire virtuelle, nous aborderons le PCI, parlerons un peu d'une carte réseau et toucherons une carte vidéo sur un matériel spécifique que nous avons.
Pour ceux qui sont trop paresseux pour lire l'article, je vais immédiatement donner une courte vidéo avec les résultats.
Et maintenant, pour ceux qui sont intéressés, nous allons révéler les détails techniques que nous avons pu comprendre dans le processus.
Mémoire virtuelle
Notre erreur de pile
Commençons par la mémoire virtuelle. En fait, c'est ce sur quoi nous nous sommes installés dans l'
article précédent
de la série. Il convient de rappeler immédiatement pourquoi nous avions besoin de mémoire virtuelle, car Embox peut fonctionner sans. C'est simple: la chose est la mise en cache. Vidyaha a fonctionné, mais j'ai dû enregistrer la même chose deux fois dans la mémoire vidéo pour une récupération d'image fiable. Bien sûr, il était possible de gérer le cache, mais nos exemples impliquent l'utilisation de la mémoire vidéo directement à partir d'une application utilisateur, sans aucun élément nucléaire tel que la gestion du cache, il était donc juste d'apprendre à mapper la mémoire comme non cache. La même chose peut être faite sous Linux en mappant fb (
exemple ).
Il convient de noter que bien que nous n'ayons pas écrit sur Elbrus depuis longtemps et qu'il puisse sembler que MMU dans cette architecture soit une sorte de super compliqué, mais la chose est différente. En fait, nous avons ajouté du soutien pendant l'été, nous n'avons tout simplement pas atteint nos mains pour écrire à ce sujet. Beaucoup de temps (plusieurs mois) a été consacré à notre stupide erreur. Cette erreur a même été commise dans le titre de l'article («Ou n'oubliez jamais ce que vous avez obtenu pendant l'intelligence»). Nous parlons de piles avec lesquelles nous avons assez bien traité et décrit cela dans l'article Climbing
Elbrus - Reconnaissance. Partie technique 1. Registres, piles et autres détails techniques .
" Nous avons souffert pendant très longtemps, perdant stupidement le fait que nous prenions la pile initiale (sur laquelle le système est initialisé) de quelque part à l'extérieur, et tout cartographié. ce dont nous avons besoin pour que Embox fonctionne, nous n'avons pas cartographié ces données.
Sous le chat, je vais donner une nouvelle fonction e2k_entry, décrite dans le deuxième article de l'
article de la série .
Si vous le souhaitez, vous pouvez comparer.
__attribute__ ((__section__(".e2k_entry"))) void e2k_entry(struct pt_regs *regs) { if (entries_count >= CPU_COUNT) { e2k_trap_handler(regs); RESTORE_COMMON_REGS(regs); E2K_DONE; } e2k_wait_all(); entries_count = __e2k_atomic32_add(1, &entries_count); if (entries_count > 1) { while(!sync_count); context_init(&cpu_ctx[0], CONTEXT_PRIVELEGED | CONTEXT_IRQDISABLE, cpu_idle, idle_stack, sizeof(idle_stack)); context_switch(&cpu_ctx_prev[0], &cpu_ctx[0]); } context_init(&cpu_ctx[1], CONTEXT_PRIVELEGED | CONTEXT_IRQDISABLE, e2k_kernel_start, &_stack_top, KERNEL_STACK_SZ); sync_count = __e2k_atomic32_add(1, &sync_count); context_switch(&cpu_ctx_prev[1], &cpu_ctx[1]); }
Je vais simplement expliquer que maintenant nous utilisons les fonctions context_init () et context_switch () uniquement pour basculer la pile en mémoire dans l'espace Embox. Et nous le faisons pour tous les cœurs, y compris ceux qui ne sont pas utilisés.
Organisation MMU
Je vais maintenant parler un peu de l'organisation de MMU dans l'architecture E2k.
En général, l'architecture MMU est assez ordinaire et comporte des tables à quatre niveaux (ou trois lorsque vous utilisez une page de 4 Mo).
Il existe plusieurs registres de service dans l'architecture E2k, accessibles via des commandes d'accès à des espaces alternatifs, ainsi qu'à l'espace d'E / S brièvement décrit dans l'article
«Embox commence à grimper sur Elbrus» .
Nous aurons besoin de tels registres:
#define MMU_REG_CR 0x00 #define MMU_REG_CONT 0x10 #define MMU_REG_CR3_RG 0x20 #define MMU_REG_ELB_PTB 0x30 #define MMU_REG_ROOT_PTB 0x40 /
En fait, c'est un registre de contrôle, un registre de numéros de contexte, un registre racine de tables et un peu obscur MMU_REG_ELB_PTB. Commençons par cela, ce registre devrait avoir une certaine valeur, les 512 Go suivants seront utilisés par le processeur pour les besoins de l'équipement, et ces adresses ne seront pas disponibles pour le programmeur. Je fournirai des explications de la lettre du spécialiste ICST, je peux difficilement mieux expliquer:
Sous Linux, nous définissons MMU_ELB_PTB sur 0xff1 << 39, puis
zone supérieure de la mémoire virtuelle (0xff8000000000 - 0xffffffffffff)
réservé aux besoins d'équipements, à savoir TLB. Chaque page
page table (TS) obtient son adresse unique dans cette zone,
de plus, ces adresses sont facilement obtenues à partir de l'adresse à laquelle le programme
fait appel à la mémoire. Et depuis TLB stocke les mappages d'adresses virtuelles
physique, cela vous permet de mettre en cache dans le même tampon TLB
diffuse non seulement pour les adresses des utilisateurs, mais aussi pour le véhicule lui-même.
Dans les processeurs / architectures où des TLB séparés sont faits pour différents
niveaux de table de page, une telle astuce devient inutile.
Ainsi, lorsque vous manquez le TLB, il devient possible de ne pas lancer la recherche
à partir du niveau zéro (pgd *), et vérifier immédiatement le dernier niveau du véhicule (pte *).
Il n'y a aucun matériel requis pour cartographier cette zone elle-même, Wirth. adresses de
il n'est nécessaire que comme index pour la recherche TLB. Cependant, au cœur de
le dernier pgd du niveau zéro de la table des pages est écrit nat. l'adresse de cette
niveau le plus nul. En conséquence, seulement
les 4 derniers Ko de la zone ff80'0000'0000 - ffff'ffff'ffff - i.e. juste
niveau zéro du véhicule. Cela permet d'accéder à pgd * par un utilisateur ordinaire
lire / écrire des instructions sur des adresses virtuelles.
En conséquence, il a été décidé de simplement mettre dans ce registre une grande valeur, ce qui ne nous dérangera pas. Après tout, la solution proposée nous permet d'optimiser la recherche de pages, mais nous ne sommes pas encore engagés dans l'optimisation. Livré le même que sous Linux.
Maintenant, le registre de contrôle. Vous devez activer MMU à travers elle. Les bits connus ressemblent à ceci:
#define _MMU_CR_TLB_EN 0x0000000000000001 #define _MMU_CR_CD_MASK 0x0000000000000006 #define _MMU_CR_SET1 0x0000000000000008 #define _MMU_CR_SET2 0x0000000000000010 #define _MMU_CR_SET3 0x0000000000000020 #define _MMU_CR_CR0_PG 0x0000000000000040 #define _MMU_CR_CR4_PSE 0x0000000000000080 #define _MMU_CR_CR0_CD 0x0000000000000100 #define _MMU_CR_TLU2_EN 0x0000000000000200 #define _MMU_CR_LD_MPT 0x0000000000000400 #define _MMU_CR_IPD_MASK 0x0000000000000800 #define _MMU_CR_UPT_EN 0x0000000000001000
Nous nous intéressons au premier bit, qui comprend la traduction d'adresses.
Nous avons également défini _MMU_CR_SET3, mais nous n'avons pas déterminé dans quels cas particuliers cela devrait être fait.
Inscription au concours Eh bien, si c'est simple, c'est le PID du processus ou de l'espace d'adressage. Plus techniquement, il s'agit d'une extension d'adresse 11 bits. Dans notre cas, nous avons rendu toutes les pages nucléaires, en mettant le bit de globalité dans toutes nos pages, nous utilisons le même espace d'adressage et donc nous pouvons utiliser zéro dans ce registre.
Dans le registre de la table racine se trouve un pointeur vers l'adresse physique du début de la table de traduction. Vous pouvez simplement faire une fraude en mappant la table également à l'adresse spécifiée dans le registre MMU_REG_ELB_PTB, mais comme je l'ai dit, nous n'étions pas concentrés sur l'optimisation.
Que puis-je dire d'autre, la structure des tableaux est assez ordinaire, les drapeaux sont les suivants:
#define E2K_MMU_PAGE_P 0x0000000000000001ULL #define E2K_MMU_PAGE_W 0x0000000000000002ULL #define E2K_MMU_PAGE_UU2 0x0000000000000004ULL #define E2K_MMU_PAGE_PWT 0x0000000000000008ULL #define E2K_MMU_PAGE_CD1 0x0000000000000010ULL #define E2K_MMU_PAGE_A 0x0000000000000020ULL #define E2K_MMU_PAGE_D 0x0000000000000040ULL #define E2K_MMU_PAGE_HUGE 0x0000000000000080ULL #define E2K_MMU_PAGE_G 0x0000000000000100ULL #define E2K_MMU_PAGE_CD2 0x0000000000000200ULL #define E2K_MMU_PAGE_NWA 0x0000000000000400ULL #define E2K_MMU_PAGE_AVAIL 0x0000000000000800ULL #define E2K_MMU_PAGE_PFN 0x000000fffffff000ULL #define E2K_MMU_PAGE_VALID 0x0000010000000000ULL #define E2K_MMU_PAGE_PV 0x0000020000000000ULL #define E2K_MMU_PAGE_INT_PR 0x0000040000000000ULL #define E2K_MMU_PAGE_NON_EX 0x0000080000000000ULL #define E2K_MMU_PAGE_RES 0x0000f00000000000ULL #define E2K_MMU_PAGE_C_UNIT 0xffff000000000000ULL
Pour la table à 4 niveaux, les décalages d'adresses sont les suivants:
#define __MMU_PGD_SHIFT (PAGE_SHIFT + 3 * (PAGE_SHIFT-3)) #define __MMU_PUD_SHIFT (PAGE_SHIFT + 2 * (PAGE_SHIFT-3)) #define __MMU_PMD_SHIFT (PAGE_SHIFT + 1 * (PAGE_SHIFT-3))
Un peu sur PCI
Communication via des espaces d'adresses alternatifs
Avant de passer à vidyaha et à la carte réseau, revenons brièvement à PCI. Nous en avons déjà un peu parlé dans la toute première partie de
"Embox commence à grimper le mont Elbrouz .
" Il a montré des macros pour communiquer avec d'autres espaces d'adressage:
#define _E2K_READ_MAS(addr, mas, type, size_letter, chan_letter) \ ({ \ register type res; \ asm volatile ("ld" #size_letter "," #chan_letter " \t0x0, [%1] %2, %0" \ : "=r" (res) \ : "r" ((__e2k_ptr_t) (addr)), \ "i" (mas)); \ res; \ }) #define _E2K_WRITE_MAS(addr, val, mas, type, size_letter, chan_letter) \ ({ \ asm volatile ("st" #size_letter "," #chan_letter " \t0x0, [%0] %2, %1" \ : \ : "r" ((__e2k_ptr_t) (addr)), \ "r" ((type) (val)), \ "i" (mas) \ : "memory"); \ })
Et il y avait une référence au principe des espaces d'adressage. Différents espaces d'adressage sont définis à l'aide du MAS (spécificateur d'adresse mémoire). Et par exemple, pour accéder à l'IO, par lequel le PCI est accessible, vous devez utiliser 6 et pour MMU 7.
Mais avec une étude plus approfondie de la macro, vous pouvez remarquer une sorte de chan_letter. Et si vous regardez la description des commandes e2k, nous trouvons
Lecture double mot LDD ddd
ldd [adresse] mas, dst
Autrement dit, à première vue, il n'y a pas de canaux. Mais si vous suivez les liens, il s'avère que le code pour l'opération donnée ldd est 67. Mais 67 est le code pour ldd uniquement pour les canaux AL0 / AL3 et AL2 / AL5, et pour les canaux AL1 / AL4 ce code correspond à l'opération POPCNTd.
Ainsi, il n'a pas été possible de comprendre pleinement quels sont les canaux dans la terminologie d'Elbrus. Je me risquerais à suggérer que cela est déjà lié au principe vliw, lorsque vous pouvez spécifier quel alu est utilisé, car dans ce type d'architecture, l'une des caractéristiques est la présence de plusieurs appareils informatiques indépendants. Je peux bien sûr me tromper, mais le fait est que pour accéder au PCI ou MMU, vous devez utiliser le deuxième ou le cinquième canal. Ainsi, la commande ressemblera à ceci:
ldd, 2 0x0, [addr_in_mas] mas_id,% reg
lspci
Je vais maintenant donner le résultat de la sortie de la commande lspci sur le périphérique que nous avons:
root @ embox: (null) #lspci
00: 0,0 (PCI dev E3E3: ABCD) [6 4]
Pont PCI-à-PCI: (null) Pont Elbrus PCIe (rév 01)
00: 1.0 (PCI dev 8086: E3E3) [6 4]
Pont PCI à PCI: Intel PCI Elbrus Virt PCI bridge (rev 01)
01: 0,0 (PCI dev 1FFF: 8000) [6 4]
Pont PCI-à-PCI: (nul) Pont Elbrus PCI (rév 05)
01: 1.0 (PCI dev 8086: 4D45) [2 0]
Contrôleur Ethernet: Intel Corporation MCST ETH1000 Gigabit Ethernet (rév 01)
01: 2.0 (PCI dev 8086: 4D49) [1 1]
Contrôleur IDE: Intel Corporation MCST IDE (rev 128)
01: 2.1 (PCI dev 8086: 0002) [7 2]
Comm simple. contrôleur: Intel Corporation (null) (rev 05)
01: 2.2 (PCI dev 8086: 8000) [7 128]
Comm simple. contrôleur: Intel Corporation Elbrus PCI bridge (rev 00)
01: 2.3 (PCI dev 1013: 6005) [4 1]
Périphérique multimédia: Cirrus Logic Crystal CS4281 PCI Audio (rev 01)
01: 3.0 (PCI dev 8086: 4748) [1 6]
Contrôleur de stockage de masse: Intel Corporation MCST SATA (rév 00)
01: 4.0 (PCI dev 8086: 554F) [12 3]
Périphérique USB: Intel Corporation OHCI pour Elbrus (rév 00)
01: 4.1 (PCI dev 8086: 5545) [12 3]
Périphérique USB: Intel Corporation EHCI pour Elbrus (rév 00)
02: 1.0 (PCI dev 126F: 0718) [3 0]
Contrôleur compatible VGA: Silicon Motion, Inc. SM718 LynxSE + (rév 160)
root @ embox: (null) #
Remarque
01: 2.2 (PCI dev 8086: 8000) [7 128]
Comm simple. contrôleur: Intel Corporation Elbrus PCI bridge (rev 00)
En fait, il s'agit d'un port série du MCST similaire à l'am85c30, au moins via cet appareil, nous communiquons via minicom.
Carte réseau
Structure générale
Passons maintenant à la carte réseau.
Si je comprends bien, il s'agit de la carte réseau d'origine, un peu similaire en fonctionnement à e1000, mais uniquement en fonctionnement (comme la présence de descripteurs dans les files d'attente de réception et de transmission).
Maintenant, plus sur les points importants que nous avons rencontrés.
Carte réseau PCI VID: PID 0x8086: 0x4D45. Ne soyez pas surpris que le VID soit le même qu'Intel, le MCST utilise souvent ce VID particulier, regardez au moins le périphérique de port série mentionné ci-dessus.
BAR0 contient une base de registres. Les registres sont les suivants:
#define L_E1000_E_CSR 0x00 #define L_E1000_MGIO_CSR 0x04 #define L_E1000_MGIO_DATA 0x08 #define L_E1000_E_BASE_ADDR 0x0c #define L_E1000_DMA_BASE_ADDR 0x10 #define L_E1000_PSF_CSR 0x14 #define L_E1000_PSF_DATA 0x18 #define L_E1000_INT_DELAY 0x1c
Les trois derniers (L_E1000_PSF_CSR, L_E1000_PSF_DATA, L_E1000_INT_DELAY) que nous n'avons pas utilisés, nous n'en parlerons donc pas. Commençons par MGIO, tout est simple: lecture-écriture en utilisant le protocole MII, c'est-à-dire communication avec la puce PHY. Plus précisément, nous avons une puce DP83865.
Les procédures ne sont pas particulièrement remarquables, je vais simplement les énumérer.
Lecture:
static int e1000_mii_readreg(struct net_device *dev, int phy_id, int reg_num) { struct l_e1000_priv *ep = netdev_priv(dev); uint32_t rd; uint16_t val_out = 0; int i = 0; rd = 0; rd |= 0x2 << MGIO_CS_OFF; rd |= 0x1 << MGIO_ST_OF_F_OFF; rd |= 0x2 << MGIO_OP_CODE_OFF; rd |= (phy_id & 0x1f) << MGIO_PHY_AD_OFF; rd |= (reg_num & 0x1f) << MGIO_REG_AD_OFF; e1000_write_mgio_data(ep, rd); rd = 0; for (i = 0; i != 1000; i++) { if (e1000_read_mgio_csr(ep) & MGIO_CSR_RRDY) { rd = (uint16_t)e1000_read_mgio_data(ep); val_out = rd & 0xffff; log_debug("reg 0x%x >>> 0x%x", reg_num, val_out); return val_out; } usleep(100); } log_error("mdio_read: Unable to read from MGIO_DATA reg\n"); return val_out; }
Record:
static void e1000_mii_writereg(struct net_device *dev, int phy_id, int reg_num, int val) { struct l_e1000_priv *ep = netdev_priv(dev); uint32_t wr; int i = 0; wr = 0; wr |= 0x2 << MGIO_CS_OFF; wr |= 0x1 << MGIO_ST_OF_F_OFF; wr |= 0x1 << MGIO_OP_CODE_OFF; wr |= (phy_id & 0x1f) << MGIO_PHY_AD_OFF; wr |= (reg_num & 0x1f) << MGIO_REG_AD_OFF; wr |= val & 0xffff; log_debug("reg 0x%x <<< 0x%x", reg_num, val); e1000_write_mgio_data(ep, wr); for (i = 0; i != 1000; i++) { if (e1000_read_mgio_csr(ep) & MGIO_CSR_RRDY) { return; } usleep(100); } log_error("Unable to write MGIO_DATA reg: val = 0x%x", wr); return; }
Maintenant L_E1000_DMA_BASE_ADDR et L_E1000_E_BASE_ADDR, en fait, ils décrivent un paramètre, l'adresse du bloc de description de la carte réseau. Autrement dit, l'adresse dans Elbrus est de 64 bits et les registres sont de 32 bits.
Code actuellement:
init_block_addr_part = (uint32_t)((uintptr_t)ep->init_block & 0xffffffff); e1000_write_e_base_addr(ep, init_block_addr_part); log_debug("Init Block Low DMA addr: 0x%x", init_block_addr_part); init_block_addr_part = (uint32_t)(((uintptr_t)(ep->init_block) >> 32) & 0xffffffff); e1000_write_dma_base_addr(ep, init_block_addr_part); log_debug("Init Block High DMA addr: 0x%x", init_block_addr_part);
D'où on peut voir que L_E1000_DMA_BASE_ADDR est la partie supérieure et L_E1000_DMA_BASE_ADDR est la partie inférieure de l'adresse d'un certain bloc d'initialisation (en fait un bloc de description de carte).
La structure de description est la suivante:
struct l_e1000_init_block { uint16_t mode; uint8_t paddr[6]; uint64_t laddrf; uint32_t rdra; uint32_t tdra; } __attribute__((packed));
C laddrf - ne comprenait pas, pour une raison quelconque, il est mis à zéro, nous avons fait de même.
paddr - comme vous pouvez le deviner, mac est l'adresse de la carte réseau.
rdra et tdra contiennent les adresses des anneaux des descripteurs de mémoire, les 4 bits inférieurs sont alloués à la taille de l'anneau, et c'est le logarithme de la taille. Autrement dit, s'il y a 8, alors le nombre de descripteurs dans l'anneau sera 2 ^ 8 (1 << 8 == 256).
mode est le mode de fonctionnement de la carte, les bits sont les suivants:
#define DRX (1 << 0) #define DTX (1 << 1) #define LOOP (1 << 2) #define DTCR (1 << 3) #define COLL (1 << 4) #define DRTY (1 << 5) #define INTL (1 << 6) #define EMBA (1 << 7) #define EJMF (1 << 8) #define EPSF (1 << 9) #define FULL (1 << 10) #define PROM (1 << 15)
Autrement dit, lorsque tout est configuré, vous devez définir le bit 10. Si vous voulez un mode promiscuous, puis également 15.
Descripteurs de paquets
Maintenant sur le format des descripteurs de paquets.
A la réception:
struct l_e1000_rx_desc { uint32_t base; int16_t buf_length; int16_t status; int16_t msg_length; uint16_t reserved1; uint32_t etmr; } __attribute__((packed));
base - comprendre probablement que c'est l'adresse du tampon pour le paquet
buf_length - taille du tampon
msg_length - après réception, contient la longueur du paquet reçu
statut - statut du descripteur. Lorsque le paquet est préparé et donné au DMA (carte), vous devez définir le bit 15 (RD_OWN). Si tout va bien, après avoir reçu le paquet dans ce descripteur, ce bit sera réinitialisé et 9 (RD_STP) et 8 (RD_ENP) seront définis.
Tous les bits d'état sont les suivants:
#define RD_OWN (1 << 15) #define RD_ERR (1 << 14) #define RD_FRAM (1 << 13) #define RD_OFLO (1 << 12) #define RD_CRC (1 << 11) #define RD_BUFF (1 << 10) #define RD_STP (1 << 9) #define RD_ENP (1 << 8) #define RD_PAM (1 << 6) #define RD_LAFM (1 << 4) #define RD_BAM (1 << 3)
Au transfert:
struct l_e1000_tx_desc { uint32_t base; int16_t buf_length; int16_t status; uint32_t misc; uint32_t etmr; } __attribute__((packed));
Presque identiques à la réception, les bits d'état sont les suivants:
#define TD_OWN (1 << 15) #define TD_ERR (1 << 14) #define TD_AFCS (1 << 13) #define TD_NOINTR (1 << 13) #define TD_MORE (1 << 12) #define TD_ONE (1 << 11) #define TD_DEF (1 << 10) #define TD_STP (1 << 9) #define TD_ENP (1 << 8)
Lorsqu'un paquet est envoyé, il est nécessaire de définir 15 (TD_OWN), 9 (TD_STP) et 8 (TD_ENP) en conséquence. Le bit 8 signifie que c'est le dernier paquet à traiter, par conséquent, si un paquet est envoyé, vous devez installer uniquement dans le dernier.
J'ai également oublié une caractéristique importante, la longueur du tampon dans les descripteurs est écrite avec un signe moins, probablement dans du code supplémentaire. Même en petit-boutien, mais comme Elbrus a le même ordre d'octets, ce n'est probablement pas important.
Registre de gestion
Nous décrivons maintenant le dernier registre non assemblé L_E1000_E_CSR:
#define E_CSR_ATME (1 << 24) #define E_CSR_TMCE (1 << 23) #define E_CSR_DRIN (1 << 22) #define E_CSR_DTIN (1 << 21) #define E_CSR_ESLE (1 << 20) #define E_CSR_SLVE (1 << 19) #define E_CSR_PSFI (1 << 18) #define E_CSR_SINT (1 << 16) #define E_CSR_ERR (1 << 15) #define E_CSR_BABL (1 << 14) #define E_CSR_CERR (1 << 13) #define E_CSR_MISS (1 << 12) #define E_CSR_MERR (1 << 11) #define E_CSR_RINT (1 << 10) #define E_CSR_TINT (1 << 9) #define E_CSR_IDON (1 << 8) #define E_CSR_INTR (1 << 7) #define E_CSR_INEA (1 << 6) #define E_CSR_RXON (1 << 5) #define E_CSR_TXON (1 << 4) #define E_CSR_TDMD (1 << 3) #define E_CSR_STOP (1 << 2) #define E_CSR_STRT (1 << 1) #define E_CSR_INIT (1 << 0)
Initialisation
Il y a une séquence d'initialisation quelque peu inhabituelle:
STOP-> INIT-> IDON-> STRT
Dans ce cas, les bits RXON et TXON montent indépendamment.
Plus de détails peuvent être trouvés dans notre pilote.
Carte vidéo
Comme déjà indiqué, notre appareil utilise un vidyah Silicon Motion appelé SM718 LynxSE +. Par conséquent, tout est simple, il existe des
sources de pilotes sous Linux et il n'y a rien à décrire en fait.
Eh bien, sauf que la vidéo montre qu'il s'est avéré être des images très faibles, cela ressemble à un accès lent à la mémoire. Mais ceci est sans optimisation du compilateur, et en général, c'est peut-être notre problème associé à l'utilisation incorrecte de l'architecture e2k.
Eh bien, quoi d'autre à dire sur Sakhaline Elbrus?
En principe, le temps est normal :)
Apparemment, Elbrus existe, travaille. Personnellement, je vois le principal problème du développement de cette architecture intéressante comme sa proximité. Il est difficile de croire qu'une entreprise relativement petite puisse créer un processeur, un compilateur, fournir un support et tout le reste. Oui, des développeurs de logiciels tiers ont commencé à apparaître, le même Basalt-SPO prend en charge
Alt-Linux, qui peut être installé sur Elbrus .
Oui, il a été signalé que des développeurs tiers fabriquaient du matériel basé sur le processeur Elbrus, par exemple
Fastwel . Mais ce ne sont là que de petites avancées vers l'ouverture. Un exemple très simple, afin de reproduire ce que nous avons dit et montré ici, nous avons besoin d'un compilateur, et seul le
MCST l'a , les informations données dans l'article sont un ajout aux informations reçues de, encore une fois, le
MCST , et je ne dis toujours pas qu'il est peu probable qu'un morceau de fer soit trouvé même au MCST. Il est assez ancien et
ICST propose des modèles plus récents.
PS Naturellement, vous pouvez tout voir dans
le référentiel Embox .
PPS Venez sur la chaîne de télégramme russe via Embox (
https://t.me/embox_chat ).
PPS Embox a mis à jour le deuxième composant de la version, désormais la version
0.4.0 actuelle