راه اندازی UART FIFO با DMA در STM32

راه اندازی UART در STM32 برای توان عملیاتی بالا در هندلینگ دیتا میتواند چالش برانگیز باشد. اکثر پریفرال های STM32 وابسته به DMA هستند اگر بخواهیم از توان عملیاتی بالا استفاده کنیم. مثل پریفرال I2S که برای ارسال دیتای صوت دیجیتال است.

عملکرد I2S DMA:

پیاده سازی DMA برای I2S به منظور دریافت صوت دیجیتال روتین و سرراسته. شما در واقع DMA رو کانفیگ میکنید برای متچ کردن فرمت صدا و انتخاب یک سایز بافر فریم. سپس، شما I2S را در مد CIRCULAR BUFFER کانفیگ می کنید. اینتراپت STM32 زمانیکه بافر فریم نصفه پر شده یا کامل پر شده فعال میشه. شما از پروسسور استفاده می کنید تا دسترسی داشته باشید به نصف بافر که توسط DMA اشغال شده.

این یه مثال بود از عملکرد DMA در I2S حالا برگردیم به UART DMA و مشکلی که باهاش ممکنه داشته باشیم:

یکمقدار استفاده از DMA با UART عجیب بنظر میرسه برای اینکه درک بهتری داشته باشیم جدول مقایسه بین I2S و UART رو در شکل زیر ببینید:

UARTI2S
Variable Packet SizeFixed Packet Size
Unknown Packet SizeKnown Packet Size
Unpredictable Arrival TimesPredictable Arrival Times

با توجه به جدول بالا به دلیل یکسری ویژگی های UART مثل نامشخص بودن سایز پکت دیتا و غیره ما نمیتونیم از DMA به خوبی در UART استفاده کنیم. اما راه حل چیه؟

برای ایجاد یک راه حل کامل، ما نیاز داریم یک بافر نرم افزاری FIFO نیاز داریم و یک اینتراپت idle برای کانفیگ کردن یک بافر استاندارد UART DMA circular .

بافر FIFO:

در واقع FIFO به معنی first-in, first-out است. در این حالت، واحد DMA دیتا را از UART می خواند و آن دیتا را در بافر FIFO می نویسد. واحد DMA در مد چرخشی یا CIRCULAR تنظیم شده است که هنگامی که تا نیمه پر می شود یا کامل پر می شود سرویس دهی می کند.

برای توضیح FIFO از مثال دم (Tail) و سر (head) استفاده می کنیم:

در واقع دیتای نوشته شده در FIFO در سر یا head قرار میگیره و دیتای خوانده شده از دم یا tail خوانده می شود. روتین سرویس اینتراپت (Interrupt Service Routine) یا ISR سر یا head را حرکت می دهد ( و همچنین دم را در صورت نیاز برای نادیده گرفتن دیتاهای خوانده نشده). نرم افزار کاربر نیز دم یا tail را حرکت می دهد. و وقتی که سر و دم در یک مکان قرار بگیرند یعنی FIFO خالی است.

Empty FIFO

وقتی که یک بایت از طریق DMA دریافت می شود، این دیتا در لوکیشن اول از FIFO نوشته می شود. در واقع DMA نمی داند که این دیتا در یک FIFO نوشته شده است، و در واقع این دیتا در یک بافر گردشی (Circular buffer) نوشته می شود. بایت بعدی در لوکیشن دوم در FIFO نوشته می شود، و بایت بعدی در لوکیشن سوم نوشته می شود و به همین ترتیب تا آخر. (مثلا در شکل زیر سه بایت در لوکیشن های ۰ تا ۲ نوشته شده است)

3 Bytes Unserviced

در این نقطه که head و tail در یک لوکیشن قرار دارند، اگر نرم افزار تلاش کند که FIFO را بخواند، هیچی نخواهد خواند چون دم و سر در یکجا قرار دارند یا به عبارت دیگر head == tail است. در واقع مقدار head در لوکیشن صفر خواهد ماند تا زمانیکه یکی از سه حالت زیر رخ دهد:

  • یک وقفه بیکاری (an idle interrupt)
  • یک وقفه نیمه کامل (a half-complete interrupt)
  • یک وقفه کامل (a complete interrupt)

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

قبلا حساب کاربری ایجاد کرده اید؟
گذرواژه خود را فراموش کرده اید؟
Loading...