
For flere år siden ble jeg kjent med russiske mikrokontrollere fra Milandr. Det var i 2013, da ingeniører diskuterte heftig de første resultatene av det føderale Target-programmet "Utvikling av elektronisk komponentbase og radioelektronikk" for 2008-2015. På den tiden var K1986BE9x-kontrolleren (Cortex-M3-kjerne) allerede utgitt, og 1986BE1T-kontrolleren (Cortex-M1-kjerne) hadde nettopp dukket opp. I LQFP-144-plastkassen hadde den betegnelsen K1986BE1QI (luftfart) i dokumentasjonen, og på selve brikken betegnelsen MDR32F1QI. På produsentens nettsted har den suffikset "luftfart", siden den har grensesnitt spesifikke for flyindustrien (ARINC 429, MIL_STD_1553).
Overraskende nok hadde Milandr, på tidspunktet for distribusjonen av disse kontrollerne, utarbeidet feilsøkingssett og et bibliotek med rutiner for å jobbe med periferien, «men uten ytterligere garantier og forpliktelser angående bibliotekets korrekthet.» Biblioteket ligner på Standard Peripheral Library fra STMicroelectronics. Generelt har alle ARM-kontrollere bygget på Cortex-M-kjernen mye til felles. Av denne grunn gikk det raskt å bli kjent med de nye russiske kontrollerne. Og for de som kjøpte feilsøkingssett av merkevarekvalitet, ble det gitt teknisk støtte under bruk.

Feilsøkingssett for mikrokontroller 1986BE1T, © Milandr
Men over tid begynte "startvanskene" med nye brikker og biblioteker å dukke opp. Testeksempler på firmware fungerte uten synlige problemer, men med betydelig modifikasjon regnet feil og feil ned. Den første "babysvalen" i min praksis var uforklarlige feil i driften av CAN-kontrolleren. Et år senere ble det oppdaget et problem med modulen på 1986BE1T (avia)-kontrolleren fra tidlig revisjon. Generelt sett var alle revisjoner av disse mikrokontrollerne frem til 2016 av begrenset nytte. Mye tid og nerver ble brukt på å identifisere disse problemene, noe som nå kan bekreftes i .
En ubehagelig funksjon var at arbeid og feilsøking ikke måtte gjøres på feilsøkingskort, men på prototypekort til enheter som var planlagt for serieproduksjon fra fabrikk. Bortsett fra JTAG-kontakten var det vanligvis ingenting der. Det var vanskelig og upraktisk å koble til en logikkanalysator, og det var vanligvis ingen LED-lys eller skjermer. Av denne grunn dukket ideen om å lage mitt eget feilsøkingskort opp i hodet mitt.
På den ene siden fantes det merkevarebaserte feilsøkingssett på markedet, samt fantastiske kort fra LDM-Systems fra Zelenograd. På den annen side er prisene på disse produktene svimlende, og den grunnleggende funksjonaliteten uten utvidelseskort oppfyller ikke forventningene. Et kort med en loddet kontroller og en pin-kontakt er ikke interessant for meg. Og mer interessante kort er dyre.

Feilsøkingskort MILANDR LDM-HELPER-K1986BE1QI-FULL, © LDM Systems
Milandr har en unik prispolitikk og markedsføring. For eksempel er det mulig å få gratis vareprøver av noen mikrokretser, men dette er bare tilgjengelig for juridiske enheter og er forbundet med et byråkratisk oppdrag. Generelt er mikrokretser i et metall-keramisk kabinett gull verdt i bokstavelig og billedlig forstand. For eksempel koster 1986BE1T-kontrolleren fra 14 til 24 tusen rubler i Moskva. Mikrokretsen 1645RU6U med statisk minne koster fra 15000 1986 rubler. Og slike priser gjelder for alle produkter. Som et resultat sparer og viker selv spesialiserte forskningsinstitutter med statlige ordre unna slike priser. Mikrokretser i et plastkabinett for sivilt bruk er betydelig billigere, men de er ikke tilgjengelige fra populære leverandører. I tillegg er kvaliteten på mikrokretser i et plastkabinett, etter min mening, dårligere enn de "gylne". For eksempel kunne jeg ikke starte K1BE128QI-kontrolleren på en frekvens på 40 MHz uten å øke flash-latensparameteren. Samtidig steg temperaturen på denne kontrolleren til 50–1986 °C. Men 1BE128T-kontrolleren («gull») startet på XNUMX MHz uten noen ekstra innstillinger og forble kjølig. Den er virkelig bra.

"Gylden" mikrokontroller 1986BE1T, (c) Milandr
Jeg var heldig som fortsatt kunne kjøpe mikrokontrolleren i plastkasse i detaljhandelen fra LDM Systems, og alle kretskortene er fritt tilgjengelige. Det dårlige er at du på nettsiden, på bildet av kontrolleren, kan se merkingen, som sier at dette er den fjerde revisjonen av 4, dvs. med defekter. Jeg tenkte lenge - å kjøpe eller ikke kjøpe. Så gikk det flere år ...
Ideen om å lage et feilsøkingsbrett forsvant aldri. Gradvis dannet jeg meg alle kravene og tenkte på hvordan jeg skulle plassere alt dette på ett brett, slik at det ville være kompakt og rimelig. Samtidig bestilte jeg de manglende komponentene fra kineserne. Jeg hadde ingen hastverk – jeg gjorde alt selv. Kinesiske leverandører er kjent for sin slurv – jeg måtte bestille det samme fra forskjellige steder for å få alt jeg trengte. Dessuten viste det seg at noen av minnebrikkene var brukte – åpenbart loddet fra ødelagte enheter. Dette kom tilbake for å hjemsøke meg senere.
Det er ikke lett å kjøpe en Milandr K1986BE1QI (fly) mikrokontroller. I samme Chip and Dip-butikk, i seksjonen "Varer å bestille", fant jeg bare K1986BE92QI for 740 rubler, men den passet ikke for meg. Det eneste alternativet var å kjøpe en ikke helt fersk revisjon fra LDM-Systems for 2000 rubler. Siden jeg ikke fant en erstatning noe annet sted, bestemte jeg meg for å kjøpe det som var tilgjengelig. Til min hyggelige overraskelse solgte de meg en helt ny kontroller produsert i desember 2018, revisjon 6+ (1820). Og nettstedet har fortsatt et gammelt bilde, og i skrivende stund er kontrolleren ikke tilgjengelig ...

Mikrokontroller K1986BE1QI (luftfart) i teknologisk innpakning, (c) Foto av forfatteren
De viktigste tekniske egenskapene til utviklingskortet mitt MDB1986 følgende:
- innebygd feilsøkingsprogrammerer kompatibel med J-Link og CMSIS-DAP;
- statisk minne 4Mbit (256k x 16, 10 ns);
- 64 Mbit flash-minnebrikke, Winbond 25Q64FVSIG;
- RS-232-grensesnitttransceiver med RTS- og CTS-linjer;
- grensesnitt og kontakter for Ethernet, USB, CAN;
- 7-segments skjermkontroller MAX7221;
- pinnekontakt for arbeid med MICO (MIL_STD_1553) og ARINC429;
- fototransistor Everlight PT17-21C;
- fem fargede LED-lamper, tilbakestillingsknapp og to brukerknapper;
- strømforsyningen fra USB-porten er 5 volt;
- Kretskortmål 100 x 80 mm
Jeg likte kortene i STM-Discovery-serien fordi de har en innebygd programmerer-feilsøkingsenhet – ST-Link. Den proprietære ST-Link fungerer bare med STMicroelectronics-kontrollere, men for et par år siden ble det mulig å oppdatere fastvaren i ST-Link og få SEGGER J-Link OB (on-board) debugger. Juridisk sett er det en begrensning på å bruke en slik debugger kun med STMicroelectronics-kort, men potensialet er faktisk ubegrenset. Med J-Link OB kan du dermed ha en innebygd programmerer-feilsøkingsenhet på debug-kortet. Jeg legger merke til at produktene fra "LDM-Systems" bruker CP2102 (Usb2Uart)-omformeren, som bare kan flashe.

STM32F103C8T6 mikrokontrollere, ekte og ikke ekte, (c) Foto av forfatteren
Så det var nødvendig å kjøpe den originale STM32F103C8T6, siden den proprietære firmwaren ikke vil fungere riktig med klonen. Jeg tvilte på denne tesen og bestemte meg for å prøve CS32F103C8T6-kontrolleren fra det kinesiske selskapet CKS. Jeg har ingen klager på selve kontrolleren, men den proprietære ST-Link-firmwaren fungerte ikke i den. J-Link fungerte delvis - USB-enheten ble oppdaget, men programmereren utførte ikke funksjonene sine og minnet stadig på at den var "defekt".

Feil ved kjøring av feilsøking på en ikke-original kontroller
Jeg stoppet ikke der, og skrev først en firmware for blinking av LED-lampen, og implementerte deretter IDCODE-forespørselen via JTAG-protokollen. ST-Link-programmereren jeg hadde på Discovery-kortet og ST-Link Utility-programmet flashet CS32F103C8T6 uten problemer. Som et resultat var jeg overbevist om at kortet mitt fungerer. Til min glede utstedte målkontrolleren K1986BE1QI (luftfart) muntert sin IDCODE via TDO-linjen.

Oscillogram av TDO-signallinje med kodet IDCODE-respons, (c) Foto av forfatteren

Så SWD-porten kom godt med for å feilsøke selve feilsøkingsprogrammet og sjekke IDCODE.
Det eneste alternativet som var igjen var med en feilsøkingsverktøy. Det er ikke lett å bygge et prosjekt fra ARM-kilder. Jeg tok prosjektet fra , og så prøvde jeg DAP42. Dessverre frøs Keil uVision og ville ikke jobbe med dem. Som et resultat byttet jeg ut feilsøkingsbrikken med en proprietær STM32F103C8T6, og problemet oppsto ikke igjen.

Vellykket drift av den innebygde feilsøkingsprogrammet J-Link STLink V2
Da alle nøkkelkomponentene til det fremtidige feilsøkingskortet var tilgjengelige, gikk jeg inn i Eagle CAD og fant ut at de ikke var i elementbiblioteket. Det var ingen vei utenom – jeg måtte tegne dem selv. Samtidig lagde jeg fotavtrykk for minne, en HanRun-kontakt for Ethernet og la til rammer for motstander og kondensatorer. Prosjektfilen og komponentbiblioteket finnes her. .
Skjematisk diagram av MDB1986 feilsøkingskortet
Kortet drives av en 5-volts likestrømskilde som mottas fra USB-porten. Det er to USB Type-B-porter på kortet. Den ene er for programmereren, den andre er for K1986BE1QI-kontrolleren. Kortet kan operere fra begge kildene eller begge samtidig. Den enkleste lastreguleringen og strømlinjebeskyttelsen implementeres ved hjelp av Schottky-dioder, i D2- og D3-diagrammet (SS24). Diagrammet viser også selvreparerende sikringer F1 og F2 for 500 mA. USB-portens signallinjer er beskyttet av en USBLC6-2SC6-diodeenhet.
ST-Link feilsøkings-programmeringskretsen er velkjent for mange, den kan finnes i dokumentasjonen for STM32-Discovery-kortene og andre kilder. For den første firmwaren til ST-Link/J-Link-OB/DAP-klonen (valgfritt), tok jeg frem SWDIO (PA13), SWCLK (PA14) og GND-linjene. Mange bruker UART for firmware og må trekke ut BOOT-jumperne. Men SWD er mer praktisk for meg, og denne protokollen tillater også feilsøking.
Nesten alle komponentene på kortet drives av 3.3 volt, som kommer fra spenningsregulatoren AMS1117-3.3. LC-filtre laget av kondensatorer og BLM31PG-serie choker brukes til å undertrykke elektromagnetisk interferens og strømstøt.
7-segments displaydriveren MAX7221 fortjener spesiell omtale. I følge spesifikasjonen er den anbefalte strømforsyningen fra 4 til 5.5 volt, og det høye signalnivået (logisk) er ikke mindre enn 3.5 V (0.7 x VCC), med en strømforsyning på 5 V. K1986BE1QI-kontrolleren (fly) har en logisk utgang som tilsvarer en spenning på 2.8 til 3.3 V. Det er åpenbart en avvik i signalnivåene, noe som kan forstyrre normal drift. Jeg bestemte meg for å drive MAX7221 fra 4 V og redusere signalnivåene til 2.8 V (0.7 x 4 = 2.8). For dette er en diode D4 (RS1A eller FR103) installert i serie i driverens strømforsyningskrets. Det totale spenningsfallet er 0.9 V (Schottky-diode 0.3 V og diode 0.6 V), og alt fungerer.
De fleste portene på K1986BE1QI-mikrokontrolleren (luftfart) er kompatible med signaler opptil 5V. Derfor er det ingen problemer med å bruke MCP2551 CAN-transceiveren, som også opererer fra 5V. MAX232-brikken er angitt som en RS-3232-transceiver på diagrammet, men faktisk brukte jeg SN65C3232D fra Texas Instruments, siden den opererer fra 3.3V og gir hastigheter opptil 1Mbit/s.
Det er fire kvartsresonatorer på kortet – én for feilsøkingsprogrammet (4 MHz) og tre for målmikrokontrolleren K8BE1986QI (fly) med nominelle verdier på 1 kHz, 32.768 MHz og 16 MHz. Dette er nødvendige komponenter, siden parametrene til den innebygde RC-generatoren ligger i store områder fra 25 til 6 MHz. Frekvensen på 10 MHz er nødvendig for driften av den innebygde Ethernet-kontrolleren. På Milandrs nettsted (muligens ved en feiltakelse) er det av en eller annen grunn indikert at det ikke er noe Ethernet i plastkassen. Men vi vil stole på spesifikasjonen og fakta.
Et viktig insentiv for å lage mitt eget feilsøkingsbrett var muligheten til å jobbe med den eksterne systembussen EBC (ekstern busskontroller), som i hovedsak er en parallellport. K1986BE1QI-mikrokontrolleren (avia) lar deg koble til og jobbe med eksterne minnebrikker og periferienheter, for eksempel ADC, FPGA, etc. Mulighetene til den eksterne systembussen er ganske store - du kan jobbe med 8-bit, 16-bit og 32-bit statisk RAM, ROM og NAND Flash. For å lese/skrive 32-bit data kan kontrolleren automatisk utføre 2 tilsvarende operasjoner for 16-bit brikker, og 8 operasjoner for 4-bit. Det er klart at en 32-bit input/output-operasjon vil bli utført raskest med en 32-bit databuss. Ulempene inkluderer behovet for at programmet skal kunne kjøre 32-bit data, og 32 spor må legges på kortet.

Brukte statiske RAM-brikker (gjett hvilken som er defekt)
En balansert løsning er å bruke 16-bits minnebrikker. Jeg hadde Integrated Silicon Solutions Inc.-brikker (ISSI IS61LV25616AL, 16 x 256k, 10 ns, 3.3V). Milandr har selvfølgelig sine egne statiske minnebrikker. , men de er for dyre og utilgjengelige. Som et alternativ finnes det pin-kompatible Samsung K6R4016V1D. Tidligere nevnte jeg at brikkene viste seg å være brukte, og kopien jeg installerte ga i utgangspunktet feil og kaotiske verdier i den 15. datalinjen. Det tok flere dager å finne maskinvarefeil, og desto større var tilfredsstillelsen da jeg erstattet den skadede brikken med en fungerende. Uansett, hastigheten på å jobbe med eksternt minne er mye å være ønsket.
Ekstern buss og StandAlone-modusK1986BE1QI-mikrokontrolleren (fly) har en unik StandAlone-modus, som er designet for direkte ekstern tilgang til Ethernet- og MKI-kontrollerne (MIL_STD_1553) via en ekstern buss, og kjernen er i tilbakestillingstilstand, dvs. ikke i bruk. Denne modusen er praktisk for prosessorer og FPGA-er som ikke har Ethernet og/eller MKI.
Tilkoblingsskjemaet er som følger:
- MCU-databuss (D0-D15) => SRAM (I/O0-I/O15),
- adressebuss MCU(A1-A18) => SRAM(A0-A17),
- kontroll MCU(nWR,nRD,PortC2) => SRAM (WE,OE,CE),
- SRAM (UB, LB) er koblet til eller trukket til jord via en motstand.
CE-linjen trekkes opp til strømforsyningen via en motstand, pinnene for valg av MCU-byte (BE0-BE3) brukes ikke. Under spoileren oppgir jeg initialiseringskoden for portene og den eksterne busskontrolleren.
Initialisering av porter og EBC (ekstern busskontroller)
void SRAM_Init (void)
{
EBC_InitTypeDef EBC_InitStruct = { 0 };
EBC_MemRegionInitTypeDef EBC_MemRegionInitStruct = { 0 };
PORT_InitTypeDef initStruct = { 0 };
RST_CLK_PCLKcmd (RST_CLK_PCLK_EBC, ENABLE);
PORT_StructInit (&initStruct);
//--------------------------------------------//
// DATA PA0..PA15 (D0..D15) //
//--------------------------------------------//
initStruct.PORT_MODE = PORT_MODE_DIGITAL;
initStruct.PORT_PD_SHM = PORT_PD_SHM_ON;
initStruct.PORT_SPEED = PORT_SPEED_FAST;
initStruct.PORT_FUNC = PORT_FUNC_MAIN;
initStruct.PORT_Pin = PORT_Pin_All;
PORT_Init (MDR_PORTA, &initStruct);
//--------------------------------------------//
// Address PF3-PF15 (A0..A12), A0 - not used. //
//--------------------------------------------//
initStruct.PORT_FUNC = PORT_FUNC_ALTER;
initStruct.PORT_Pin = PORT_Pin_4 | PORT_Pin_5 |
PORT_Pin_6 | PORT_Pin_7 |
PORT_Pin_8 | PORT_Pin_9 |
PORT_Pin_10 | PORT_Pin_11 |
PORT_Pin_12 | PORT_Pin_13 |
PORT_Pin_14 | PORT_Pin_15;
PORT_Init (MDR_PORTF, &initStruct);
//--------------------------------------------//
// Address PD3..PD0 (A13..A16) //
//--------------------------------------------//
initStruct.PORT_FUNC = PORT_FUNC_OVERRID;
initStruct.PORT_Pin = PORT_Pin_0 | PORT_Pin_1 |
PORT_Pin_2 | PORT_Pin_3;
PORT_Init (MDR_PORTD, &initStruct);
//--------------------------------------------//
// Address PE3, PE4 (A17, A18) //
//--------------------------------------------//
initStruct.PORT_FUNC = PORT_FUNC_ALTER;
initStruct.PORT_Pin = PORT_Pin_3 | PORT_Pin_4;
PORT_Init (MDR_PORTE, &initStruct);
//--------------------------------------------//
// Control PC0,PC1 (nWE,nOE) //
//--------------------------------------------//
initStruct.PORT_FUNC = PORT_FUNC_MAIN;
initStruct.PORT_Pin = PORT_Pin_0 | PORT_Pin_1;
PORT_Init (MDR_PORTC, &initStruct);
//--------------------------------------------//
// Control PC2 (nCE) //
//--------------------------------------------//
initStruct.PORT_PD = PORT_PD_DRIVER;
initStruct.PORT_OE = PORT_OE_OUT;
initStruct.PORT_FUNC = PORT_FUNC_PORT;
initStruct.PORT_Pin = MDB_SRAM_CE;
PORT_Init (MDR_PORTC, &initStruct);
//--------------------------------------------//
// Initialize EBC controler //
//--------------------------------------------//
EBC_DeInit();
EBC_StructInit(&EBC_InitStruct);
EBC_InitStruct.EBC_Mode = EBC_MODE_RAM;
EBC_InitStruct.EBC_WaitState = EBC_WAIT_STATE_3HCLK;
EBC_InitStruct.EBC_DataAlignment = EBC_EBC_DATA_ALIGNMENT_16;
EBC_Init(&EBC_InitStruct);
EBC_MemRegionStructInit(&EBC_MemRegionInitStruct);
EBC_MemRegionInitStruct.WS_Active = 2;
EBC_MemRegionInitStruct.WS_Setup = EBC_WS_SETUP_CYCLE_1HCLK;
EBC_MemRegionInitStruct.WS_Hold = EBC_WS_HOLD_CYCLE_1HCLK;
EBC_MemRegionInitStruct.Enable_Tune = ENABLE;
EBC_MemRegionInit (&EBC_MemRegionInitStruct, EBC_MEM_REGION_60000000);
EBC_MemRegionCMD(EBC_MEM_REGION_60000000, ENABLE);
// Turn ON RAM (nCE)
PORT_ResetBits (MDR_PORTC, MDB_SRAM_CE);
}
Mikrokontrolleren i LQFP-144-pakken og minnet i TSOP-44-pakken har mange tilkoblede pinner og tar opp mye plass på kretskortet. Med erfaring i å løse optimaliseringsproblemer innen økonomi var det åpenbart for meg at disse brikkene burde plasseres på kretskortet først. I forskjellige kilder kom jeg over rosende anmeldelser om Jeg lastet ned prøveversjonen og kunne eksportere prosjektet mitt fra Eagle CAD dit først etter at jeg slettet nesten alle komponentene. Dessverre hjalp ikke TopoR meg med å plassere engang 10 elementer på brettet. Først ble alle komponentene plassert i hjørnet, og deretter ble de plassert langs kanten. Jeg var ikke fornøyd med dette alternativet, og i lang tid tegnet jeg brettet manuelt i det kjente Eagle CAD-miljøet.
Et viktig element på kretskortet er silketrykk. Feilsøkingskortet skal ikke bare ha signaturer for de elektroniske komponentene, men alle kontakter skal også være merket. På baksiden av kortet plasserte jeg tabeller/notater med funksjonene til kontrollerportene (hoved, alternativ, omdefinert, faktisk). Jeg bestilte produksjon av kretskort i Kina hos det velkjente PCBWay-selskapet. Jeg vil ikke rose dem, for kvaliteten er god. De kan gjøre det bedre, med mindre toleranser, men .

Produserte kretskort MDB1986, (c) Foto av forfatteren
Jeg måtte lodde komponentene «på kneet» med et 40-watts loddebolt og POS-61 loddetinn, fordi jeg lodder sjelden, 1-2 ganger i året, og loddepasten tørket opp. Jeg måtte også bytte ut den kinesiske CS32F103-kontrolleren med den originale STM32F103, og deretter bytte ut minnet. Generelt er jeg helt fornøyd med resultatet nå, selv om jeg ennå ikke har sjekket driften av RS-232 og CAN.

MDB1986-feilsøkingskortet i drift – det skinner og varmes, (c) Foto av forfatteren
På Milandra sin nettside finner du ganske mye 1986BE9-serien (Cortex-M3-kjerne), men jeg ser ikke noe der for K1986BE1QI-mikrokontrolleren (luftfart). Etter å ha gjennomgått materialene, manualene og laboratoriearbeidet for universiteter som er publisert der, er jeg glad for at personell over hele landet blir opplært til å jobbe med russiske kontrollere. Det meste av opplæringsmateriellet er forberedt på å jobbe med input-output-porter, timere, ADC, DAC, SPI, UART. Ulike IDE-utviklingsmiljøer brukes (Keil, IAR, CodeMaster). Et sted programmerer de ved hjelp av CMSIS-registre, og et sted bruker de MDR-biblioteket. Det er nødvendig å nevne ressursen. , som inneholder mange artikler fra praktiserende programmerere. Og selvfølgelig bør vi ikke glemme .
Tanker om MilandraMikroelektronikk er under utvikling i Russland, og Milandr spiller en betydelig rolle i denne prosessen. Nye interessante mikrokontrollere dukker opp, for eksempel 1986BE81T og Electrosila med SpaceWire- og MKIO-grensesnitt (de samme som i 1986BE1 og muligens med de samme problemene), osv. Men det er urealistisk for vanlige studenter, lærere og sivilingeniører å kjøpe slike mikrokretser. Dette betyr at ingeniørmiljøet ikke raskt vil kunne identifisere feil og problemer med denne mikrokretsen. Det virker som om det først er nødvendig å produsere mikrokretser i et plasthus, distribuere dem blant alle interesserte, og først etter testing (latin approbatio - godkjenning, anerkjennelse) av spesialister kan vi forberede en revisjon i et metall-keramisk hus med beskyttelse mot alle forferdelige faktorer. Jeg håper at vi i nær fremtid ALLE vil være fornøyde med nye prosjekter som annonseres på utstillinger.
Feilsøkingsbrettet jeg utviklet kan replikeres, modifiseres og brukes i læringsprosessen av hvem som helst. Først lagde jeg brettet for meg selv, men det ble så bra at .
K1986BE1QI (avia) er en veldig interessant kontroller med unike grensesnitt, som kan brukes på universiteter for å undervise studenter. Jeg tror at etter å ha rettet opp feilene som ble funnet i kontrolleren og bestått sertifiseringstester, vil kontrolleren fly i ordets bokstavelige forstand!
Kilde: www.habr.com
