واژه برنامه نویسی embedded برای طیف وسیعی از کلاس ها و دسته بندی مختلف برنامه نویسی بکار برده می شود .
رنج وسیعی از میکروکنترلرهای 8 بیتی مانند AVR های قدیمی که منابع بسیار کم در حد چند کیلوبایت RAM و ROM در اختیار قرار میدادند تا سیستم هایی مانند Raspberry Pi هایی مانند B 3+ که 4 هسته 64 بیتی Cortex-A53 با فرکانس کاری 1.4 گیگاهرتز با یک گیگابایت RAM در اختیار ما قرار میدهد .
براساس هدفی که انتخاب می کنیم منابع و محدودیت های مختفی پیش روی ما قرار میگیرد .
دوسطح عمومی برنامه نویسی امبدد وجود دارد :
Bare Metal , Hosted
توسعه برنامه برای Hosted Environments بسیار شبیه به برنامه نویسی برای یک کامپیوتر می باشد .به این معنی که شما با یک رابط سیستمی روبرو هستید که ارتباط با لایه های زیری مانند network , file systems , thread , memory management , Standard libraries و موارد دیگه را به عهده دارد و شما با این رابط ها ارتباط برقرار میکنید هنگام برنامه نویسی .همچنین ممکن است یک سری محدودیت ها هنگام دسترسی به شاخه های اصلی سیستم یا بخش هایی از حافظه ها داشته باشید .که بصورت کلی می توان گفت مانند این هست که شما برای یک کامپیوتر در حال برنامه نویسی و توسعه برنامه هستید .
اما در حالت Bare Metal قبل از اینکه برنامه شما اجرا شود هیچ کدی دیگری اجرا نخواهد شد .بدون اینکه نرم افزاری توسط سیستم عامل فراهم شود ما نمی توانیم از standard library ها استفاده کنیم .در عوض برنامه بهمراه crate هایی که استفاده میکنه مستقیم از سخت افزار برای کارایی استفاده خواهند کرد .
برای اینکه از بارگذاری standard library در Rust جلوگیری کنیم از no_std استفاده خواهیم کرد .بخشی از کتابخانه های استاندارد مستقل از پلتفرم هستند و همینطور خالی از بخش هایی هستند که عموما برای امبدد ها خیلی کاربردی نیستند که این بخش با اسم libcore شناخته می شود .
یکی از چیز هایی که در این تعبیه نشده است memory allocator برای dynamic memory allocation هست .که در صورتی که این مورد یا موارد مشابه در حالت استاندارد لازم دارید می تونید با استفاده از crate هایی به برنامه اضافه کنید و این قابلیت هارو داشته باشید .
libstd Runtime
همینطور که قبلا اشاره شد استفاده کردن از libstd نیازمند یک یکپارچه سازی با سیستم عامل هست اما فراهم کردن مسیرهایی برای ارتباط گرفتن با رابط های سیستم عامل تنها کاری نیست که این بخش انجام می دهد . این بخش همینطور runtime برای ما فراهم می کند که این بخش کارهایی مانند مواظبت از stack overflow – پردازش command line argument ها – ایجاد و استفاده از main thread قبل از اینکه فانکشنالیتی برنامه شروع به کار کند .که این runtime ها در حالت no_std وجود ندارد.
جمع بندی :
#![no_std]
یک ویژگی در سطح crate هست که مشخص میکنه این crate از core بجای std استفاده خواهد کرد . که libcore یک مجموعه ای crate های std هست که وابسته به سکو نیست .به طور مثال یک سری APIها برای کار با داده های اولیه مانند float , string , slice و همینطور یک سری APIبرای کار با atomic operation ها و SIMD instruction ها میده . البته که هر چیزی که وابسته به پلتفرم باشه را دیگه در این بخش نداریم بهمین دلیل گزینه بسیار مناسبی برای توسعه در بخش هایی مانند bootstrapping (stage 0) مانند bootloaderها و firmware , kernel هاست .
جمع بندی ویژگی های در دسترس :
feature | no_std | std |
---|---|---|
heap (dynamic memory) | * | ✓ |
collections (Vec, BTreeMap, etc) | ** | ✓ |
stack overflow protection | ✘ | ✓ |
runs init code before main | ✘ | ✓ |
libstd available | ✘ | ✓ |
libcore available | ✓ | ✓ |
writing firmware, kernel, or bootloader code | ✓ | ✘ |
*یک ستاره به معنی موقعی امکان استفاده وجود داره که crate به برنامه اضافه شود مانند alloc-cortex-m
**دو ستاره به معنی امکان استفاده موقعی وجود دارد که collections crate ها رو اضافه کرده باشیم و global default allocator هم پیکره بندی کرده باشیم .
HashMap , HashSet بخاطر نبود RNG در دسترس نخواهند بود در این حالت .