ST uruchamia inicjatywę mającą na celu udostępnienie sterowników w Rust dla wielu naszych czujników, otwierając nową drogę dla tych, którzy chcą wykorzystać ten język programowania w rozwoju swoich systemów wbudowanych. Oczywiście nadal będziemy dostarczać i utrzymywać nasz ekosystem oparty na języku C. Zdajemy sobie jednak sprawę z rosnącej popularności języka Rust, korzyści, jakie przynosi on w wielu projektach, a także z tego, że zbudowanie solidnej, niezależnej od platformy alternatywy w innym języku programowania wymaga znacznego czasu i nakładów. Właśnie z tych powodów zaczęliśmy stopniowo portować sterowniki, a teraz oficjalnie informujemy o naszej obecności na crates.io i prezentujemy projekty takie jak Embassy STM32, który zapewnia warstwę abstrakcji sprzętu w Rust dla naszych MCU.
Powód nr 1: bezpieczeństwo

Jednym z najczęściej docenianych aspektów Rust jest jego wrodzone bezpieczeństwo kodu w porównaniu z innymi językami, w tym C i C++. W istocie oznacza to, że kompilator Rust zabroni wykonywania pewnych operacji, które mogłyby zagrozić bezpieczeństwu pamięci. Bezpieczeństwo pamięci oznacza, że kompilator Rust zablokuje każdy dostęp do pamięci, która nie została jawnie zaalokowana lub została już zwolniona. To znacząca różnica w stosunku do C i C++, gdzie programiści mają znacznie większą swobodę w zarządzaniu pamięcią. Oznacza to jednak również, że zły kod może prowadzić do takich problemów jak przepełnienie bufora, wycieki pamięci, błędy typu „use-after-free” czy wiszące wskaźniki. Wszystkie one mogą skutkować uszkodzeniem danych, a nawet lukami w zabezpieczeniach.
Rust jest bezpieczniejszy, ponieważ implementuje technikę „Resource acquisition is initialization” (RAII), która automatycznie i natychmiast alokuje zasoby w momencie tworzenia obiektu i zwalnia je, gdy obiekt jest usuwany. Kompilator przypisuje te zasoby właścicielowi, a następnie może przenieść własność lub, w razie potrzeby, pozwolić innemu właścicielowi na ich pożyczenie. W rezultacie Rust sam zarządza zasobami i nie potrzebuje garbage collectora do zarządzania alokacjami pamięci, w przeciwieństwie do C++, innego języka implementującego RAII, który jednak nadal wymaga od programistów samodzielnego zarządzania pamięcią. W praktyce brak garbage collectora zmniejsza narzut, ale sprawia też, że kod w Rust jest znacznie mniej pobłażliwy.
Choć ten wpis na blogu nie jest w stanie nawet zarysować wszystkich różnic między Rust a C i C++ (nie będziemy nawet poruszać tematu bezpieczeństwa typów), powyższy punkt ilustruje ważny powód, dla którego programiści przechodzą na Rust i dla którego ST już podjęło próbę udostępnienia alternatyw dla swoich sterowników czujników. Krzywa uczenia się Rust jest stroma. Pisanie bezpiecznego kodu, który się kompiluje, jest wymagające, ponieważ istnieje bardzo wiele zabezpieczeń gwarantujących bezpieczeństwo kodu. Oznacza to jednak również, że gdy kod już się skompiluje, programiści mają znacznie większą pewność co do jego bezpieczeństwa i ochrony. A dla programistów dopiero poznających Rust dostępność otwartych sterowników, takich jak te dostarczane przez ST, oznacza, że mogą oni analizować nasze implementacje i uczyć się na naszym doświadczeniu.
Powód nr 2: praktyczność, przenośność i wydajność (do pewnego stopnia)

Kolejnym powodem, dla którego programiści sięgają po Rust w projektach wbudowanych, jest sposób, w jaki obsługuje on interfejsy i operacje na magistralach. W przeciwieństwie do C, które tradycyjnie korzysta z abstrakcji magistrali opartej na wskaźnikach, Rust używa „Traits”, które definiują interfejsy jako typy, a następnie zapewniają nad nimi elastyczną abstrakcję. Dzięki standardom ekosystemu, takim jak embedded-HAL, interfejsy magistral takich jak I2C i SPI można implementować spójnie na różnych platformach, co pomaga programistom budować kompetencje. Co więcej, nasz kod już teraz korzysta z API zgodnych z naszymi oryginalnymi sterownikami w C, aby złagodzić krzywą uczenia się, a także przyjęliśmy spójne nazewnictwo, by ułatwić przejście na naszą alternatywę w Rust.
Jednym z nieporozumień, z którymi często się spotykamy, jest przekonanie, że Rust jest z natury „szybszy” niż C lub C++. Prawda jest znacznie bardziej złożona. W zależności od aplikacji Rust może być wolniejszy od C, równie szybki lub szybszy. Jednak w wielu przypadkach Rust zmusza zespoły do przepisania aplikacji, co w naturalny sposób prowadzi do refaktoryzacji, porzucenia starego kodu lub stworzenia nowych, zoptymalizowanych procesów. Brak garbage collectora w Rust czy usprawnienia jego nowoczesnego kompilatora z pewnością pomagają, ale programiści systemów wbudowanych nie powinni pochopnie zakładać, że Rust w magiczny sposób zapewni znaczną poprawę wydajności w czasie wykonania. Zapewni jednak znacznie bezpieczniejszy, często bardziej elastyczny kod, i właśnie dlatego udostępniamy alternatywy w Rust dla naszych sterowników czujników w C.
Powód nr 3: społeczność Rust

Dyskusje w naszym repozytorium GitHub dotyczące tego projektu pokazują prężnie działającą społeczność, co dla wielu programistów jest istotnym czynnikiem. Nie tylko kluczowi gracze branżowi, tacy jak Meta, Google czy Microsoft, publicznie zadeklarowali wdrożenie nowego języka programowania. Wiele mniejszych zespołów inwestuje w nowy język, ponieważ osiągnięcie biegłości wymaga czasu, a pozostanie w tyle mogłoby prowadzić do znacznego długu technologicznego, na którym skorzystałaby konkurencja. Wiemy, że adopcja jest wciąż na wczesnym etapie. Właśnie dlatego udostępniamy sterowniki czujników w Rust już teraz. ST chce wspierać tych, którzy chcą być pierwsi w tej transformacji, która, jak się wydaje, kształtuje przyszłość rozwoju systemów wbudowanych.
Najlepszym sposobem na rozpoczęcie jest instalacja Rust za pomocą rustup, a następnie, w miarę budowania projektu, sięgnięcie po jeden z naszych pakietów na Crates. Nasza strona GitHub prowadzi też użytkowników przez proces pobierania i integracji. Oferujemy przykłady w Cargo, aby pomóc zespołom szybciej osiągać rezultaty. I choć same sterowniki pozwalają inżynierom pozostać niezależnymi od MCU, nasze przykłady są napisane dla mikrokontrolerów STM32 i korzystają głównie z płytki rozwojowej NUCLEO-F401RE. Obecne sterowniki w Rust koncentrują się na interfejsach I2C i SPI, ponieważ są one zdecydowanie najczęściej używane, ale trwają prace nad dodatkowym wsparciem, w tym dla I3C, a my będziemy aktualizować ten wpis w miarę publikowania większych aktualizacji.
