image

Платформа .NET nanoFramework позволяет разрабатывать приложения на C# для различных микроконтроллеров. В предыдущей публикации работали с ESP32 и STM32. Одна из замечательных особенностей .NET nanoFramework заключается в возможности запускать среду исполнения поверх интерфейса POSIX в Win32 для Unit-тестирования. Это означает быструю возможность переноса среды nanoFramework Runtime на любую операционную систему поддерживаемую POSIX стандартом. Именно таким образом, в качестве эксперимента, .NET nanoFramework был перенесен на микроконтроллер Raspberry Pi Pico, для запуска поверх операционной системы реального времени (RTOS) Apache NuttX. Как это было реализовано прошу под кат.

Что такое .NET nanoFramework можно почитать пост платформа для разработки приложений на C# для микроконтроллеров. Для начала рассмотрим, что из себя представляет Raspberry Pi Pico.

Плата Raspberry Pi Pico


Raspberry Pi Pico — это недорогая платформа для разработки на микроконтроллере RP2040. Два ядра ARM Cortex-M0+ с тактовой частотой 133 МГц обеспечат необходимую производительность для ваших устройств, роботов и других изобретений, где важен баланс производительности с низким энергопотреблением.

Raspberry Pi Pico nanoFramework
Плата Raspberry Pi Pico

Микроконтроллер Pico входит в аналогичный сегмент микроконтроллеров, что и ESP32, но обладает своими уникальными «фишками». Уникальная возможность Pico — подсистема программируемого ввода/вывода (Programmable I/O), с помощью которой можно реализовать произвольный аппаратный интерфейс: например, шину SD-карты или вывод VGA. Для подключения модулей предусмотрены аппаратные интерфейсы UART, SPI и I2C.

На плате присутствует чип Flash памяти на 2 Mб, кнопка BOOTSEL для перевода микроконтроллера в режим загрузчика, светодиод на 25 контакте и стабилизатор напряжения, позволяющий питать Pi Pico от источника питания с напряжением от 1.8 до 5.5 В. Плата Raspberry Pi Pico питается через разъём micro-USB или контакт VSYS.

Для Pi Pico создаются приложения на языках Си, C++ или MicroPython.

Что такое Apache NuttX?


NuttX_logo.png

NuttX — это операционная система реального времени (RTOS), специально разработанная для использования во встраиваемых системах с микроконтроллерами или процессорами разрядностью от 8 до 32 бит. Благодаря гибкой возможности настройки NuttX, разработчик может включать в образ только те модули, которые действительно необходимы для проекта. Одним из главных принципов NuttX является соответствие стандартам POSIX и ANSI. Благодаря этому, определяется общий интерфейс для различных операционных систем, что способствует переносимости, повторному использованию кода и поддержки приложений, использующих POSIX и ANSI. Дополнительные стандартные API из Unix и других RTOS (такая как VxWorks) адаптированы для функциональности, недоступны в соответствие со стандартами, и низкоуровневым окружением для встраиваемых систем (как fork()).

Список поддерживаемых платформ достаточно большой, в него входят процессоры ARM Cortex, Atmel AVR, Intel, RISC-V, STM32, и т.д. Среди поддерживаемых МК присутствует серия ESP32 от Espressif. Сама компания Espressif активно инвестирует в проект NuttX.

NuttX распространяется под свободной лицензией Apache 2.0 License.

Сборка базового образа NuttX для Raspberry Pi Pico


Образ NuttX для RP2040 поддерживает интерфейсы UART, I2C, SPI, PIO (RP2040 Programmable I/O), и т.д. В зависимости от подключаемых модулей будут доступны LCD экраны: ssd1306 (I2C), lcd1602 (I2C), st7735 (SPI). Поддерживается сеть Ethernet (модуль ENC28J60 на SPI).

Более детально про поддержку МК RP2040 можно почитать по ссылке incubator-nuttx/raspberrypi-pico.

Соберем минимальный образ для RP2040 с NuttShell в Ubuntu 20.04, задаваемый параметр для сборки — usbnsh. NuttShell это аналог консоли в Linux. Параметр usbnsh задействует порт USB CDC/ACM для работы с NuttShell.

Скрипт сборки:

$ sudo apt-get update
$ sudo apt-get install -y git
$ sudo apt-get install -y \
bison flex gettext texinfo libncurses5-dev libncursesw5-dev \
gperf automake libtool pkg-config build-essential gperf genromfs \
libgmp-dev libmpc-dev libmpfr-dev libisl-dev binutils-dev libelf-dev \
libexpat-dev gcc-multilib g++-multilib picocom u-boot-tools util-linux
$ sudo apt-get install -y kconfig-frontends
$ sudo apt-get install -y gcc-arm-none-eabi binutils-arm-none-eabi
$ sudo reboot now
$ mkdir -p /usr/share/pico
$ cd /usr/share/pico
$ git clone https://github.com/raspberrypi/pico-sdk
$ cd /usr/share/pico/pico-sdk
$ git reset --hard 26653ea81e340
$ export PICO_SDK_PATH=/usr/share/pico/pico-sdk
$ mkdir -p /usr/share/pico/nuttxspace
$ cd /usr/share/pico/nuttxspace
$ git clone https://github.com/apache/incubator-nuttx.git nuttx
$ git clone https://github.com/apache/incubator-nuttx-apps apps
$ cd /usr/share/pico/nuttxspace/nuttx
$ ./tools/configure.sh -l raspberrypi-pico:usbnsh
$ make -j

Более подробно процесс установки Getting Started » Installing.

После компиляции по пути /usr/share/pico/nuttxspace/nuttx появится файл nuttx.uf2.

Для загрузки прошивки в Pi Pico, необходимо на плате нажать кнопку BOOTSEL и подключить плату по USB порту.
Прошивка Pi Pico
bootFlash Raspberry Pi Pico

В операционной системе появится USB-диск:

Raspberry Pi Pico USB Flash
USB-диск в Windows 7 для загрузки прошивки Raspberry Pi Pico

Копируем в корень диска F:\ файл nuttx.uf2. После копирования файла, плата автоматически прошьет свою Flash-память и перегрузится.

Затем в списке устройств отобразится COM-устройство, в данном случае COM8. Обратите внимание, для Windows 7 штатный драйвер CDC/ACM отсутствует. Драйвер доступен только для Windows 10+ и Linux. В Linux консоли Pi Pico появится как устройство ttyACMx, например /dev/ttyACM0.

Открываем порт на скорости 115200 бод. Для доступа к PiPico совершаем быстрое двойное нажатие на Enter, и вводим несколько команд.

Raspberry Pi Pico nuttx
NuttShell консоль ОС NuttX на Raspberry Pi Pico

NuttX успешно запущен и работает на Raspberry Pi Pico!

Запуск .NET nanoFramework -> NuttX


.NET nanoFramework может работать с невероятными минимальными требованиями, для запуска необходимо всего 256 КБ флэш-памяти и 64 КБ ОЗУ. Pi Pico удовлетворяет этим требованиям более чем необходимо, сам чип RP2040 содержит 264 КБ ОЗУ, на самой плате разведена Flash-память на 2 МБ.

Для Unit-тестирования приложений для .NET nanoFramework разработчики обеспечили запуск nanoCLR в контексте Win32 благодаря соответствию POSIX стандарту.

nanoFramework Win32
Запуск .NET nanoFramework Win32 для тестирования

Matheus Castello пришла в голову замечательная идея, раз nanoCLR работает поверх RTOS. А разработчики NuttX объявили о поддержке Raspberry Pi Pico, то почему бы не запустить nanoFramework на NuttX одной из RTOS, вместо трудоемкого нативного портирования nanoCLR. По факту, так таковой перенос, как переписывание уровня HAL под определенную аппаратную платформу не требуется, необходимо только обеспечить соответствие вызываемым функциям в рамках POSIX стандарта.

Порт nanoFramework для win32 запускается как консольное приложение. На самом деле запуск nanoCLR на Raspberry Pi Pico был второстепенной задачей, основная задача заключалась в запуске nanoCLR в окружение Linux. В процессе миграции Matheus Castello переписал части, написанные для win32, в переносимые стандартные вызовы C/C++ и вызовы POSIX. Так же были добавлены директивы препроцессора #if defined(__linux__), чтобы охватить некоторые конкретные вариации для приложения Linux. В некоторых блоках кода можно найти что-то вроде #if defined(_WIN32) || defined(__linux__):

// provide platform dependent delay to CLR code
#if defined(_WIN32) || defined(__linux__) || defined(__nuttx__)
#define OS_DELAY(milliSecs) ;
#else
#define OS_DELAY(milliSecs) PLATFORM_DELAY(milliSecs)
#endif

Ядро nanoCLR достаточно переносимо, но в некоторых случаях приходится выполнять тот или иной платформозависимый вызов. В этом случае вызов в nanoCLR будет реализован в коде, зависящем от платформы. Поскольку использовался проект win32 в качестве основы, то использовались те же define вызовы.

Порт для POSIX доступен по ссылке dotnuttx/nf-Community-Targets/tree/linux/posix.

После запуска nanoCLR в Linux, для связывания бинарника NuttX с приложением в образ сборки были добавлены файлы Kconfig, Make.defs и Makefile (Commit: a5e837c).

В файл Makefile были добавлены относительные пути к исходному коду локального форка nf-interpreter и  необходимые флаги/директивы препроцессора для компилятора. В конфигурацию NuttX для компиляции ядра были добавлены следующие настройки для обеспечения поддержки C++:

# C++
CONFIG_HAVE_CXX=y
CONFIG_LIBCXX=y

Интересная проблема, которая возникла, заключалась в использование различных заголовочных файлов, которые должны работать и вести себя одинаково как Linux, так и в NuttX. Но в NuttX некоторые include, не «подготовлены» для использования в C++. Пример использования utsname.h для получения информации о системе:

#if defined(__linux__) || defined(__nuttx__) 
#include <sys/utsname.h>
#endif

Если мы проверим header в Linux, то увидим, что в самом начале файла будет следующий фрагмент:

#ifndef    _SYS_UTSNAME_H
#define    _SYS_UTSNAME_H    1

#include 

__BEGIN_DECLS

Где __BEGIN_DECLS развертывается в:

/* C++ needs to know that types and declarations are C, not C++.  */
#ifdef    __cplusplus
# define __BEGIN_DECLS    extern "C" {
# define __END_DECLS    }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif

В NuttX utsname.h нет блока __cplusplus на случай использования C++, что приводит к неопределенным ошибкам ссылок во время сборки. Для решения этой проблемы был добавлен код:

#if defined(__linux__)
#include <sys/utsname.h>
#endif

#if defined(__nuttx__)
extern "C" {
#include <sys/utsname.h>
}
#endif

Теперь можно запустить .NET nanoFramework на Raspberry Pi Pico, благодаря поддержке платы в проекте NuttX.

Подготовка приложения


В NuttX не предоставляются GPIO во время исполнения программы, а предварительно конфигурируются во время сборки (над этим еще ведется работа, чтобы изменить). На данный момент для использования доступны только следующие контакты GPIO:

GP25 = GpioPinDriveMode_Output;
GP2 = GpioPinDriveMode_Output;
GP3 = GpioPinDriveMode_Output;
GP4 = GpioPinDriveMode_Output;
GP5 = GpioPinDriveMode_Output;

GP6 = GpioPinDriveMode_Input;
GP7 = GpioPinDriveMode_Input;
GP8 = GpioPinDriveMode_Input;
GP9 = GpioPinDriveMode_Input;

Демонстрационное приложение будет мигать светодиодом (GP25 — onboard LED) и выводить в консоль  отладки служебную информацию при нажатии на кнопку GP6 (pin 9).

Raspberry Pi Pico nanoFramework
Схема подключения кнопки к Raspberry Pi Pico

В качестве примера возьмем проект nanoFrameworkPOSIX-samples/PiPico. Файл Program.cs:

using System.Diagnostics;
using System.Threading;
using System.Device.Gpio;
using nanoFramework.Runtime.Native;

GpioController gpioController = new GpioController();
// GP25 (onboard LED)
GpioPin onBoardLED = gpioController.OpenPin(25, PinMode.Output);
// GP6 (pin 9)
GpioPin button = gpioController.OpenPin(6, PinMode.Input);

while (true)
{
    // blink
    onBoardLED.Toggle();

    // check if button is pressed
    if (button.Read() == PinValue.High)
    {
        Debug.WriteLine($"Running nanoFramework on {SystemInfo.TargetName}");
        Debug.WriteLine($"Platform: {SystemInfo.Platform}");
        Debug.WriteLine($"Firmware info: {SystemInfo.OEMString}");        
    }

    Thread.Sleep(500);
}

Выполним сборку в VS2019, меню Build > Build PiPico. В папке \PiPico\bin\Debug потребуются только файлы с расширением .pe, а именно:
  • mscorlib.pe
  • nanoFramework.Runtime.Events.pe
  • nanoFramework.Runtime.Native.pe
  • PiPico.pe
  • System.Device.Gpio.pe

Создание прошивки NuttX вместе с приложением


Приложение для Raspberry Pi Pico можно загрузить двумя путями. Первый, создать файл прошивки .uf2 содержащий NuttX, среду nanoCLR, исполняемое приложение .NET, и остальные модули. Второй, RP2040 может загружать программу с SD-карты памяти посредством интерфейса SPI.

Создадим единый бинарник прошивки, по первому варианту. Для создания прошивки воспользуемся docker-контейнером.

Загрузим образ dotnuttx/generate-pico-uf2, создадим volume nf-debug и скопируем в него файлы .pe полученные при сборке проекта.

$ docker pull dotnuttx/generate-pico-uf2:latest
$ docker volume create --name nf-debug

В каталоге /var/lib/docker/volumes/nf-debug/_data должны быть следующие файлы:

root@ubuntuvm:~# ls -l /var/lib/docker/volumes/nf-debug/_data
total 52
-rw-r--r-- 1 root root 31668 Jun 19  2021 mscorlib.pe
-rw-r--r-- 1 root root  3412 Jun 19  2021 nanoFramework.Runtime.Events.pe
-rw-r--r-- 1 root root  1496 Jun 19  2021 nanoFramework.Runtime.Native.pe
-rw-r--r-- 1 root root   772 May 23  2022 PiPico.pe
-rw-r--r-- 1 root root  5684 Jun 19  2021 System.Device.Gpio.pe

Теперь создадим контейнер и запустим компиляцию прошивки:

$ docker run --rm -it -v nf-debug:/nf dotnuttx/generate-pico-uf2

По результату в папке /var/lib/docker/volumes/nf-debug/_data появится файл прошивки dotnetnf.uf2.

Для загрузки прошивки в PiPico, необходимо нажать кнопку BOOTSEL и подключить плату по USB порту, как делали выше при прошивки RTOS NuttX. Копируем в корень USB-диска файл dotnetnf.uf2. После копирования файла плата автоматически прошьет собственную Flash-память и перегрузится.

Raspberry Pi Pico nanoFramework
Работа приложения nanoFramework в NuttX

Увидим мигание светодиода, .NET nanoFramework успешно работает на Raspberry Pi Pico!

Запуск приложения используя SD-карту памяти


Второй вариант немного сложнее, но более универсальный. В первом варианте, при любом изменении программного кода необходимо заново компилировать целиком NuttX вместе с приложением, что несколько неудобно. Вариант с SD-картой подразумевает однократную загрузку в Pi Pico исполнительной среды nanoFramework Runtime, с последующим запуском приложения с SD-карты. На SD-карту копируются файлы с расширением *.pe. Соответственно изменение приложения не затрагивает перепрошивку платы. Дополнительно для реализации данного варианта потребуется модуль чтения SD-карт на SPI интерфейсе.

Для начала загрузим nanoFramework Runtime в Raspberry Pi Pico, для того скачаем файл dotnet-nf.rp2040-Nuttx.2646 со странице POSIX nanoFramework, и скопируем его на плату в режиме прошивки (подключение при нажатой кнопки BOOTSEL).

Теперь подключим модуль SD-карт памяти как указано на схеме:

Raspberry Pi Pico nanoFramework
Схема подключения модуля SD-карт к Raspberry Pi Pico

Raspberry Pi Pico nanoFramework
Raspberry Pi Pico на макетной плате

Таблица подключения:

      SD card slot   Raspberry Pi Pico
       DAT2          (NC)
       DAT3/CS ----- GP17 (SPI0 CSn)        (Pin 22)
       CMD /DI ----- GP19 (SPI0 TX - MOSI)  (Pin 25)
       VDD     ----- 3V3 OUT                (Pin 36)
       CLK/SCK ----- GP18 (SPI0 SCK)        (Pin 24)
       VSS     ----- GND                    (Pin 3 or 38 or ...)
       DAT0/DO ----- GP16 (SPI0 RX - MISO)  (Pin 21)
       DAT1          (NC)

Заменим содержимое Program.cs из примера выше, на следующий код:

using System.Threading;
using System.Device.Gpio;

GpioController gpioController = new GpioController();
// GP25 (onboard LED)
GpioPin onBoardLED = gpioController.OpenPin(25, PinMode.Output);
// GP6 (pin 9)
GpioPin button = gpioController.OpenPin(6, PinMode.Input);

while (true)
{
    // check if button is pressed
    if (button.Read() == PinValue.Low)
    {
        onBoardLED.Write(PinValue.High);
    }
    else
    {
        onBoardLED.Write(PinValue.Low);
    }

    Thread.Sleep(200);
}

Несмотря на работу консоли NuttShell через COM-порт, вывод сообщений, используя метод Debug.WriteLine() не заработал, поэтому поведение программы было изменено. При нажатие на кнопку GP6 (pin 9) загорается светодиод GP25 (onboard LED) на плате, при отпускание выключается.

Далее, SD-карту памяти (желательно брать минимального размера, карта объемом 8 Гб подошла) необходимо отформатировать в FAT32 и скопировать в корень карты, сборки, файлы *.pe (mscorlib.pe, nanoFramework.Runtime.Events.pe, nanoFramework.Runtime.Native.pe, PiPico.pe, System.Device.Gpio.pe).

Вставляем SD-карту памяти со сборками в адаптер и подключаем Pi Pico по USB интерфейсу. Запускаем терминал, открываем порт COM8, и нажимаем на кнопку.

Raspberry Pi Pico nanoFramework
Работа приложения nanoFramework в NuttX

Если вам интересно более детально узнать какие изменения были внесены для возможности запуска nanoFramework в NuttX и как это работает, пишите в комментариях. Благодарю за внимание.

Ресурсы




Комментарии (23)


  1. build_your_web
    01.06.2022 13:13
    +2

    Иметь возможность комфортно писать на строготипизированном языке для микроконтроллеров - это очень круто.
    Единственное, мне не понятно, почему они не сделали ручное управлени GC, чтобы программист мог запускать сборку мусора тогда, когда для этого есть свободное время (чтобы не сбивать тайминги при общении с внешним миром).


    1. devzona Автор
      01.06.2022 17:56

      Возможно в будущем появится ручное управление GC, скорее всего данные методы пока не в приоритете добавления. Программирование под МК в основном подразумевает статические переменные, которые "живут" на протяжение всей работы программы.


    1. Bromles
      02.06.2022 17:51
      +3

      Иметь возможность комфортно писать на строготипизированном языке для микроконтроллеров - это очень круто.

      Предлагаю ознакомиться с Rust. Очень строгая система типов и проверок, работа на куче платформ (от WASM до микроконтроллеров), отсутствие как GC (что позволяет писать среды реального времени), так и необходимости вручную освобождать память (что нередко вызывает ошибки)

      И просто огромное количество опционального сахара и zero-cost abstractions, благодаря чему писать приятно, а на выходе получается производительность на уровне С++


      1. devzona Автор
        02.06.2022 18:06

        Rust все же достаточно низкоуровневый язык, отсутствуют классы и нет систем наследования, по сравнению с C#. И порог вхождения существенно выше.


        1. Bromles
          02.06.2022 18:25
          +1

          Это принципиальная позиция, композиция вместо наследования, т.к. оно нередко приводит к ошибкам. При необходимости это наследование эмулируется с помощью дженериков и трейтов

          Про низкоуровневость не согласен. Если не хочется, то и не надо на низкий уровень опускаться. Посмотрите бэкенд на том же Actix и найдите 10 отличий от Express (кроме того, что Actix быстрее примерно в 10 раз). Это универсальный язык

          Про порог входа тоже не согласен. Язык гораздо чаще не дает совершать ошибок, куча сахара и тд. Если специально на низкий уровень не опускаться и в unsafe не лазать, то почти всё привычно. Только привыкнуть к системе владения и ссылкам (и то, владение есть в Свифте, а ссылки в неявном виде есть много где, взять ту же Джаву).

          Зато в награду паранойидальный, но очень умный и приятный компилятор, гарантирующий отсутствие утечек памяти, рейс кондишенов и тд без продажи души демонам

          А в шарпе я навскидку вот вспомню супернеочевидный как для новичка, так и для свитчера кейс, когда перестановка 2 множителей в выражении роняет перфоманс в 20 раз (что вообще противоречит математике и логике)


          1. build_your_web
            02.06.2022 18:54

            А как в Rust работать с прерываниями?

            Можно ли использовать async/await?

            Есть ли generic типы?


            1. Bromles
              02.06.2022 20:31
              +3

              А как в Rust работать с прерываниями?

              Вот целый блог по созданию ОС на Rust: https://os.phil-opp.com/

              Вот статья про прерывания в части официальной документации языка, посвященной embedded разработке: https://docs.rust-embedded.org/book/start/interrupts.html

              Можно ли использовать async/await?

              Да. Причем не только в полноценных функциях, можно даже делать async лямбды

              И полноценные потоки тоже никто не отбирает. При этом есть много проверок на отсутствие гонок и прочего, что делает многопоток сильно менее болезненным

              Есть ли generic типы?

              Тоже да. Причем, в отличие от темплейтов С++, компилятор не верит на слово и требует гарантий наличия нужных методов в дженерик типе.

              Подробнее можно посмотреть в официальной документации: https://doc.rust-lang.org/book/ch10-01-syntax.html

              Отдельно стоит упомянуть тот факт, что Rust построен на платформе LLVM, а значит совместим с С++. Т.е. Rust можно вызывать из C++ и наоборот.

              Кроме того, многое, ради чего в других языках нужно искать библиотеки, тут есть из коробки. Например, условное добавление кода на этапе компиляции, генерация тестов по документации, просмотр документации по всем зависимостям проекта локально в браузере с навигацией и поиском, и тд

              Многие корпорации (Amazon, Discord, Dropbox, Jetbrains, Microsoft, Mozilla) начали переписывать старые или разрабатывать новые проекты на этом языке, что меня очень радует. Хорошие инструменты должны популяризироваться.

              Вообще на всяких конференциях, посвященным микроконтроллерам и разработке под них, Rust уже тоже частый гость. Там на нем пишут под всё на свете, от STM32 до всякой экзотики

              Я формально работаю на Java, но фактически использую Java, Typescript, Kotlin. Ранее писал на С++. Сам на Rust наткнулся не так давно и просто влюбился в язык. Уже один пет на нём начал и один планирую. Первый на моей памяти такой, соединил всё лучшее из С++, Java и Python. Удобен, быстр, безопасен, позволяет писать как на высоком, так и на низком уровне. Как прикладные программы, так и системщину. И ни в одном из перечисленных применений нет ощущений, что натягиваешь сову на глобус


              1. devzona Автор
                02.06.2022 23:01

                Если Rust наберет популярность для embedded устройств, то это будет замечательно, все будут только в плюсе. Под разные задачи разработчик сможет выбрать наиболее для него подходящий инструмент. Применительно Rust к .NET nanoFramework, на Rust для .NET можно писать низкоуровневый неуправляемый код, т.е. нижний слой. И не забываем про критику Торвальдса.


                1. Bromles
                  02.06.2022 23:26

                  Торвальдс критикует всё, что не чистый Си. И то, разговоры о добавлении Rust в линь увенчались далеко не громким отказом (в отличие от того же С++)

                  Если Rust наберет популярность для embedded устройств, то это будет замечательно, все будут только в плюсе.

                  Так вроде уже. Не Си конечно по популярности, но никто и не претендовал. Библиотеки под всё самое используемое есть давно, статьи, на конференциях эмбеддщиков на нём кодят и тд

                  Применительно Rust к .NET nanoFramework, на Rust для .NET можно писать низкоуровневый неуправляемый код, т.е. нижний слой

                  Я не знаю, зачем такого монстра создавать. Почему бы просто не писать на Rust под голое железо? Pico же просто Cortex M, Rust в него давно уже умеет

                  Ну и у Rust есть имхо киллер-фича, которая ставит его на голову выше конкурентов в первую очередь в embedded мире. Паники, они же фатальные ошибки. А точнее то, как они реализованы. Rust в рантайме отслеживает все возможные критические ситуации. Паники срабатывают до критической ошибки, вызывая раскрутку стэка и прочее. Т.е., например, при вылете за границы массива, на Rust мы поймаем панику, но память не будет повреждена, т.к. он её выбросил до того, как ушел реальный вызов. А в embedded Rust мы при этом пишем глобальный обработчик паник (или пользуемся готовым, коих полно) и всё. Или уходим в бесконечный цикл, или логгируем падение, или еще что. Но самое главное, что наша ошибка не повлияла ни на что, кроме хода выполнения программы (включая память). А ведь есть среды, где менеджера памяти, а значит и защит, просто нет. И там только Rust сможет вам дать по рукам и спасти от ее порчи


                  1. devzona Автор
                    03.06.2022 00:47

                    Так вроде уже. Не Си конечно по популярности, но никто и не претендовал. Библиотеки под всё самое используемое есть давно, статьи, на конференциях эмбеддщиков на нём кодят и тд

                    Тогда ждем посты про Rust на embedded устройствах ;)


                    1. Bromles
                      03.06.2022 01:53

                      Да вроде уже, пусть и корявенькие)

                      https://habr.com/ru/company/ruvds/blog/645253/

                      https://habr.com/ru/post/495948/


                      1. devzona Автор
                        03.06.2022 02:21

                        Маловато будет. Я так понял в отличие от .NET nanoFramework на Rust Embedded отсутствует интерактивная отладка во время исполнения приложения, чтобы полностью стек просматривать?


                      1. Bromles
                        03.06.2022 08:24

                        Так это только два примера статей. Я ж не буду весь хабр перекапывать, плюс есть сторонние источники

                        Я так понял в отличие от .NET nanoFramework на Rust Embedded отсутствует интерактивная отладка во время исполнения приложения,

                        1. Присутствует, и даже несколькими способами. Просмотр стека, кучи, регистров, бэктрейса во время отладки. И тд

                          https://docs.rust-embedded.org/debugonomicon/

                        2. Не нужно путать теплое с мягким. Как я понял, дотнету обязательно нужна операционка для работы. Но если у нас есть операционка, то можно писать и на обычном полноценном Rust. А Embedded нужен для bare metal сред, когда мы пишем напрямую под железо, без какой-либо операционки или среды исполнения, только прошивка и программатор

                        UPD: погуглил, похоже дотнет тоже может на bare metal работать, но поддерживает меньше платформ, чем Rust (например FPGA от Xilinx). Просто по вашей статье сложилось впечатление, что он без позикса не живет. Ну в таком случае сравнение корректно, но я все равно считаю, что и сам язык удобнее и безопаснее, и отсутствие GC много где критично (= любое реальное время)


                      1. devzona Автор
                        03.06.2022 13:04

                        В первой части об этом идет речь, только не сделал четкое разделение реализации на bare metal и ОС.

                        Эталонная реализация .NET nanoFramework работает поверх ChibiOS, например для STM32. Но для ESP32 сделано исключение, и работает непосредственно на железе без ОС.

                        Для работы .NET на FPGA, тоже на Xilinx, есть один интересный проект .NET TO FPGA WITH HASTLAYER.


                      1. Bromles
                        03.06.2022 13:23

                        Ну тогда согласен, что это достойное решение для фанатов C#. По сути из реальных минусов только GC, наличие которого ставит крест на RT-окружении. Ну и работа поверх ОС тоже урезает доступные ресурсы и прочее. На той же STM32 Rust работает bare metal, как и на других embedded платформах (но при желании никто не мешает и поверх ОС запустить, тогда даже std будет)

                        Но я в целом шарп не люблю, как и Майкрософт, поэтому не для меня)


                      1. devzona Автор
                        03.06.2022 13:49

                        .NET вообще не позиционируется как решение для RT. Для меня .NET nanoFramework, это возможность создавать несложные бытовые устройства с минимальными затратами, например умная бытовая техника, сельское хозяйство, мониторинг. Если разработчик знает "большой" .NET, то ему минимум потребуется времени для перехода на nF, плюс к этому будет возможность переноса программного кода. А а люблю платформу .NET)


                      1. Bromles
                        03.06.2022 19:26

                        Ну я не спорю, что нормальная возможность. Но имхо на том же Rust это будет не сложнее, а профита и возможностей больше (а может просто у меня уже профдеформация из-за того, что пишу на нескольких языках)

                        К слову, код Rust тоже кроссплатформерный. В смысле один компилятор, есть кросс-компиляция и нет undefined behavior, т.е. можно гарантировать переносимость кода (если он конечно не использует системные апи или конкретное железо, но это и так очевидно)


  1. Mike-M
    02.06.2022 13:19
    -2

    Неужели так сложно перед публикацией статей хотя бы раз их перечитать?!

    которые действительно обходимыми для проекта
    Одним из главный принципов NuttX
    С списке устройств
    Pi Pico удовлетворяет этим требования
    По факту так таковой перенос, как переписывание уровня HAL
    и т. п.
    Про запятые и стилистику даже не упоминаю.


    1. devzona Автор
      02.06.2022 14:06
      +1

      С точки зрения приличия можно было ограничиться личным сообщением


      1. Mike-M
        02.06.2022 15:31
        -1

        Личными сообщениями я ограничивался в ваших предыдущих статьях. Таких сообщений было, наверное, под сотню. И свою помощь в корректуре на выгодных для вас условиях предлагал. Но Вы упорно продолжаете кормить читателей своими безграмотными публикациями. А вместо благодарности за указанные ошибки минусуете комментарий и гадите в карму.


        1. devzona Автор
          02.06.2022 15:46
          -1

          При всем уважении к Вам, я очень отрицательно отношусь к навязыванию своих услуг, то что Вы делаете. Если я не согласился на "выгодных для вас условиях", которые между прочим Вы не огласили, то на это были свои причины. Если Вы так принципиальны, все же огласите свои расценки. Да, очепятки необходимо вычищать до публикации поста, спору нет, но с ваших слов я прям специально пишу для аудитории "безграмотными публикациями". И запомните на будущее, кормят детей, а авторы пишут как и художники.


  1. Mike-M
    02.06.2022 16:29
    -1

    Запомните на будущее: в стилистике есть такой термин «фигура речи». «кормить статьями» — такой же пример, как, скажем, «кормить обещаниями».
    Третью статью подряд Вы не вычищаете опечатки до публикации. Поэтому, да, получается, что Вы делаете это специально.
    Свои расценки на корректуру я Вам уже назвал — любые, которые Вас устраивают.
    Писать (без)грамотные статьи — Ваше право. А право читателей, включая меня, ставить им плюс, минус, или не ставить ничего вообще.
    Ни в коем случае не навязываю своих услуг, лишь напоминаю, что моё предложение о помощи с корректурой пока в силе.


    1. devzona Автор
      02.06.2022 16:45

      Полегче бро