فراتر از حافظه با قابلیت DMA در میکروکنترلر
فرض کنید در پروژهای خاص دادههای دریافتی از سنسورها بسیار زیاد هستند. همچنین بارپردازشی روی پردازنده هم زیاد است. در چنین حالتی برای بهینه سازی توان پردازشگر بایستی بار مرتبط با دادههای دریافتی از سنسورها را از روی آن برداریم. یا در پروژهای دیگر اگر چند حافظه جانبی روی مدار سوار شده باشند و بخواهیم دادهها را بین آنها تبادل کنیم. باز هم لازم است که بار پردازشی سمت پردازنده ارسال نشود. در چنین حالتی بایستی از قابلیت DMA در میکروکنترلر استفاده کنید. در ادامه این پست راجع به شناخت و روش کار با این قابلیت در بردهای آردوینو مطالبی را ارایه میهیم. هدف ما ارتقا دانش کاربران فارسی زبان است. همچنین رشد اطلاعات عمومی مدیران در شرکتهای مختلف را مد نظر داریم. بنابراین اگر این مطلب از بلاگ دانشجو کیت برای شما ارزشمند بود و به اطلاعاتتان اضافه کرد، آنرا با دیگران به اشتراک بگذارید تا دانش فنی مدیرها و کاربران فارسی زبان در این حوزه و IoT رشد پیدا کند.
شناخت DMA در میکروکنترلرها
DMA (Direct Memory Access) یک تکنیک است که در سیستمهای کامپیوتری و میکروکنترلرها استفاده میشود. DMA به سختافزار یا کنترلرهای مجزا اجازه میدهد تا بدون دخالت مستقیم و پردازشگر اصلی (CPU)، دسترسی مستقیم به حافظه (به طور خاص RAM) را داشته باشند و دادهها را به صورت مستقیم انتقال دهند.زمانی که نیاز به انتقال حجم بزرگی از دادهها بین دستگاههای مختلف یا حافظه و دستگاهها وجود دارد، استفاده از DMA بسیار مفید است. بدون استفاده از DMA، این انتقالها باید توسط CPU انجام شوند و باعث مصرف زمان و منابع پردازشی بیشتر میشوند. DMA قادر به انتقال دادهها از یک منبع (مانند یک پورت ورودی یا حافظه) به یک مقصد (مانند حافظه، پورت خروجی یا دستگاه خارجی) یا حتی انتقال دادههای بین دو منبع و مقصد است. برای این کار، DMA یک مدار کنترل و سیگنالهای خاصی را در اختیار دارد که به طور مستقیم با سختافزار منبع و مقصد ارتباط برقرار میکند و به آنها دستور انتقال داده را میدهد.استفاده از DMA در انتقال دادهها سرعت و کارایی سیستم را بهبود میبخشد، زمان پردازش CPU را آزاد میکند و به طور کلی عملکرد سیستم را بهبود میبخشد.
بطور خلاصه، DMA به سختافزار اجازه میدهد که بدون تداخل از طریق کنترل و سیگنالهای خاص، به صورت مستقیم دادهها را از یک منبع (مانند حافظه) به یک مقصد (مانند دستگاه) منتقل کند، بدون نیاز به تداخل مستقیم پردازنده. این عملیات انتقال داده باعث افزایش کارایی و کارایی سیستم میشود و به پردازنده اصلی اجازه میدهد به وظایف دیگر خود ادامه دهد، در حالی که انتقال دادهها توسط DMA صورت میگیرد.به عنوان مثال، در سیستمهای بافرسازی داده، DMA میتواند دادههای ورودی را از منبعی مانند پورت ورودی خوانده و آنها را بدون دخالت مستقیم پردازنده به بافری در حافظه منتقل کند. به همین ترتیب، DMA میتواند دادههای را از حافظه به سمت دستگاههای خروجی انتقال دهد بدون نیاز به تداخل پردازنده. این تکنیک بهبود عملکرد سیستم را ارائه میدهد و به تسریع انتقال دادهها و کاهش بار پردازشی پردازنده اصلی کمک میکند.
روش استفاده از DMA در پروژه
برای راه اندازی DMA در بردهای آردوینو بایستی چند مرحله اجرا شود.
- مقداردهی اولیه به کنترل کننده DMA: این مورد شامل تنظیمات و رجیسترهای مورد نیاز برای تنظیم کنترل کننده DMA است، تا کنترل کننده DMA را بر اساس نیازهای خود پیکربندی کنید. همچنین ممکن است شامل انتخاب آدرس منبع و مقصد، تنظیم اندازه انتقال، پیکربندی حالت انتقال و سایر پارامترهای مربوطه باشد.
- تخصیص و آمادهسازی بافرها: بافرهای حافظه را برای دادههای منبع و مقصد که توسط DMA منتقل خواهند شد، تخصیص دهید و آنها را آماده کنید. اطمینان حاصل کنید که بافرها به درستی تراز شده و نیازمندیهای کنترل کننده DMA را برآورده میکنند.
- تنظیم پارامترهای انتقال DMA: پارامترهای لازم برای انتقال DMA را تنظیم کنید، مانند آدرسهای منبع و مقصد، اندازه انتقال، حالت انتقال (مثلا حافظه به حافظه، حافظه به دستگاه و برعکس) و سایر پارامترهای مشخص برای کنترل کننده DMA شما.
- فعال کردن کانال DMA: کانال خاص DMA را که برای انتقال استفاده خواهید کرد، فعال کنید. این مورد ممکن است شامل تنظیم بیتهای مربوطه در رجیسترهای کنترل کننده DMA یا استفاده از توابع API خاصی که توسط پلتفرم یا میکروکنترلر فراهم شده، باشد.
- شروع انتقال DMA: انتقال دادهها را آغاز کنید تا عملیات انتقال آغاز شود. علاوه بر دسترسی مستقیم به حافظه، DMA معمولا از بافرهای داده (Data Buffer) برای ذخیره دادههای ورودی و خروجی استفاده میکند. این بافرها به عنوان نقطه میانی بین دستگاه منبع و مقصد و DMA عمل میکنند. وظیفه DMA شامل کنترل انتقال دادهها بین بافرها و دستگاهها است، در حالی که وظیفه CPU برای انجام سایر عملیات پردازشی ادامه مییابد.
ویژگیهای DMA
شکلدهی انتقال: DMA میتواند به صورت (One-Shot) عمل کند، یعنی بعد از انجام یک عمل انتقال داده، تمام مشخصات آن را از بین ببرد، یا میتواند به صورت پیوسته (Continuous) عمل کند، به طوری که بعد از انتقال یک دسته داده، به صورت خودکار به دسته داده بعدی بپردازد.
حالتهای انتقال: DMA میتواند در حالتهای مختلفی عمل کند، از جمله حالت حافظه به حافظه (Memory-to-Memory)، حالت حافظه به دستگاه (Memory-to-Peripheral) و حالت دستگاه به حافظه (Peripheral-to-Memory). این حالتها به شما اجازه میدهند دادهها را بین دستگاهها و حافظه به صورت مستقیم منتقل کنید.
پشتیبانی از پروتکلهای مختلف: DMA از پروتکلهای مختلفی مانند DMA مبتنی بر حافظه (Memory-Based DMA)، DMA مبتنی بر دستگاه (Peripheral-Based DMA) و DMA مبتنی بر FIFO (FIFO-Based DMA) پشتیبانی میکند. این پروتکلها بسته به نیاز و سازگاری با دستگاهها و سیستمها استفاده میشود.
رویدادهای پایان انتقال را پردازش کنید: اگر کنترل کننده DMA شما رویدادهای یا سیگنالهای پایان انتقال ایجاد میکند، شما باید آنها را به درستی در کد خود پردازش کنید. این میتواند شامل انتظار برای پایان انتقال یا اجرای کد خاصی در پایان انتقال باشد.
روش فراخوانی DMA در آردوینو
در ادامه یک نمونه کد برای راه اندازی در آردوینو با قابلیت DMA را بررسی میکنیم. این کد یک برنامه ساده برای تنظیم و کنترل یک کنترل کننده DMA (Direct Memory Access) است. همانطور که توضیح دادیم DMA یک مکانیزم سختافزاری است که اجازه میدهد دادهها بین حافظه و دستگاههای ورودی/خروجی (مثل پردازندهها، کارتهای شبکه، کارتهای گرافیکی و غیره) به طور مستقیم منتقل شوند بدون نیاز به مداخلات مکرر از طرف پردازنده اصلی این مورد اجرا میشود. این انتقالها به طور معمول سریعتر از تبادل دادهها از طریق نرمافزار (برنامه اصلی) انجام میشوند.
#include <stdio.h>
#include <stdint.h>
// آدرس پایه کنترل کننده DMA
volatile uint32_t* DMA_CONTROLLER = (volatile uint32_t*)0x40001000;
// آدرس منبع و مقصد انتقال DMA
volatile uint32_t* sourceAddress = (volatile uint32_t*)0x20000000;
volatile uint32_t* destinationAddress = (volatile uint32_t*)0x30000000;
// اندازه انتقال DMA
uint32_t transferSize = 1024;
void configureDMA() {
// مرحله ۱: تنظیم پارامترهای DMA
DMA_CONTROLLER[0] = (uint32_t)sourceAddress; // تنظیم آدرس منبع
DMA_CONTROLLER[1] = (uint32_t)destinationAddress; // تنظیم آدرس مقصد
DMA_CONTROLLER[2] = transferSize; // تنظیم اندازه انتقال
DMA_CONTROLLER[3] = 0x0; // تنظیم سایر پارامترهای کنترل DMA
// مرحله ۲: فعال کردن کانال DMA
DMA_CONTROLLER[4] |= 0x1; // فعال کردن کانال ۰ DMA
}
void startDMA() {
// مرحله ۳: آغاز انتقال DMA
DMA_CONTROLLER[4] |= 0x10000; // آغاز انتقال DMA در کانال ۰
}
int main() {
configureDMA();
startDMA();
// منتظر بمانید تا انتقال DMA به پایان برسد
return 0;
}
تحلیل کد آردوینو DMA
در ابتدای کد، کتابخانههای مورد نیاز برای استفاده از DMA و نوع دادههای مورد استفاده، از جمله stdio.h و stdint.h، اضافه شدهاند.سپس، آدرس پایه کنترل کننده DMA به نوع دادهای volatile uint32_t* تعریف شده است. این آدرس برای دسترسی به ثباتهای کنترل کننده DMA استفاده میشود.سپس، آدرس منبع و مقصد انتقال DMA به نوع دادهای volatile uint32_t* تعریف شده است. این آدرسها نشان میدهند که دادهها از کجا به کجا منتقل میشوند.سپس، یک متغیر به نام transferSize به عنوان اندازه انتقال DMA تعریف شده است. این متغیر برای تعیین حجم دادههایی که باید منتقل شوند استفاده میشود. تابع configureDMA() تعریف شده است. در این تابع، پارامترهای DMA تنظیم میشوند. این پارامترها شامل آدرس منبع، آدرس مقصد و اندازه انتقال است. همچنین سایر پارامترهای کنترل کننده DMA نیز تنظیم میشوند.تابع startDMA() تعریف شده است. این تابع با فعال کردن کانال DMA مربوطه، انتقال DMA را آغاز میکند.تابع main() تعریف شده است. در این تابع، ابتدا تابع configureDMA() فراخوانی میشود تا DMA پیکربندی شود، سپس تابع startDMA() فراخوانی میشود تا انتقال DMA آغاز شود. در این نقطه، برنامه در حالت انتظار برای پایان انتقال DMA میماند. در نهایت، مقدار 0 بهد return برگشت داده میشود و برنامه به پایان میرسد.این نمونه کد برای فعال سازی DMA و انجام یک انتقال ساده استفاده میشود. با استفاده از توابع configureDMA() و startDMA() میتوانید کنترل کننده DMA را تنظیم کرده و انتقال را آغاز کنید. در نهایت، برنامه منتظر میماند تا انتقال DMA به پایان برسد.
جمع بندی
DMA یا Direct Memory Access (دسترسی مستقیم به حافظه)، یک تکنیک است که در برنامه نویسی میکروکنترلرها و سیستمهای تعبیه شده استفاده میشود. این تکنیک به کاربر این امکان را میدهد تا بتواند انتقال دادهها بین دستگاههای جانبی و حافظه اصلی را بدون دخالت مستقیم پردازنده انجام دهد.کاربرد اصلی DMA در میکروکنترلرها افزایش سرعت انتقال دادهها و کارایی سیستم است. با استفاده از DMA، میتوان دادهها را به طور مستقیم بین حافظه اصلی و دستگاههای جانبی، مانند حافظههای فلش، پورتها، سنسورها و سایر واحدهای ورودی/خروجی، منتقل کرد. به این ترتیب، پردازنده از زمان و انرژی صرفهجویی میکند و میتواند به عملکرد دیگر وظایف مربوط به کنترل سیستم و پردازشهای پیچیده بپردازد.برای استفاده از DMA، کاربر نیاز به پیکربندی کنترل کننده DMA دارد. این پیکربندی شامل تنظیم آدرس منبع و مقصد انتقال، اندازه انتقال، حالتهای انتقال (مانند حالت تکرار) و سایر پارامترهای کنترلی است. پس از پیکربندی، با فعال کردن DMA، انتقال دادهها آغاز میشود. بنابراین، DMA ابزاری قدرتمند است که در میکروکنترلرها و سیستمهای تعبیه شده به عنوان یک واسط بین دستگاههای جانبی و حافظه اصلی است استفاده از DMA، انتقال دادهها به طور مستقیم بین دستگاههای جانبی و حافظه صورت میگیرد، بدون نیاز به دخالت پردازنده اصلی. این باعث میشود که سرعت انتقال دادهها به طور قابل توجهی افزایش یابد.با استفاده از DMA، پردازنده اصلی درگیر انتقال داده نمیشود و میتواند به وظایف دیگر خود، مانند کنترل سیستم یا پردازش دادهها، تمرکز کند. این باعث میشود که عملکرد سیستم به طور کلی بهبود یابد.