STM32 تا کجا می‌تواند پیش برود؟

0
740
STM32
STM32

روش‌های برنامه‌نویسی تأثیر بسزایی در سرعت اجرای برنامه خواهندداشت. فرض‌کنید قصددارید ۶۴ کانال مجزای PWM با فرکانس ۱۰ کیلوهرتز ایجاد کنید، با دقت 8 بیتی هر PWM؛ در نگاه‌اول پیاده‌سازی با‌استفاده‌از میکروکنترلر حتی میکروکنترلرهای قدرتمندی چون ARM غیرممکن به‌نظرمی‌رسد و ممکن‌است برای پیاده‌سازی آن به سراغ FPGA بروید یا کلاً از پیاده‌سازی چشم‌پوشی کنید؛ اما با روش‌های صحیح برنامه‌نویسی و تسلط به میکروکنترلر به‌راحتی می‌توان این بحث را بااستفاده‌از یک میکروکنترلر STM32F103 انجام‌داد. شناخت محدودیت‌های موجود و داشتن مهارت برنامه‌نویسی به ما کمک می‌کند که قادربه طراحی بهینه باشیم و ازقبل بدانیم چه‌کاری ممکن و چه‌کاری غیر‌ممکن است. در این مقاله دو مبحث را مورد‌بررسی قرار می‌دهیم: 1. تأثیر روش‌های مختلف برنامه‌نویسی  2. حالت‌های مختلف اپتیمایز (Optimize) بر عملکرد و سرعت اجرای برنامه.

در این مقاله بااستفاده‌از میکروکنترلر STM32F103VET6 از مجموعه سری‌های ARM Cortex-M3 ساخت شرکت ST سعی‌داریم نشان‌دهیم که روش‌های مختلف برنامه‌نویسی و اپتیمایز‌های مختلف چه تأثیری در روند اجرای برنامه دارند. برای این اندازه‌گیری، از یک روش ساده و همیشگی استفاده‌خواهیم‌کرد: تغییر وضعیت یک پایه؛ هرچه فرکانس ایجاد‌شده بیشتر باشد، یعنی عملکرد بهینه‌تر و سریع‌تر برنامه. هم‌چنین از کامپایلر GCC که یک کامپایلر قدرتمند و متن‌باز است استفاده‌خواهیم‌کرد. این آزمایش را می‌توان توسط دو روش مختلف انجام داد:

  1. استفاده مستقیم از CPU برای تغییر وضعیت پایه
  2. استفاده‌از انتقال‌دهنده DMA

که در ادامه نتایج هر دو روش را بررسی می‌کنیم. استفاده‌از آی‌سی های ARM این اجازه را به ما می‌دهد که برنامه به زبان C را بدون استفاده‌از هیچ کتابخانه‌ای و به‌صورت ساده و مبتدی روی آن پیاده کنیم.

تنظیمات کلاک سیستم: کلاک سیستم می‌تواند فرکانس‌های مختلفی بین ۴۸ و ۷۲MHz داشته باشد که تنظیمات فلش روی کلاک سیستم تأثیرگذار است:

These bits represent the ratio of the SYSCLK (system clock) period to the Flash access time.
000 Zero wait state, if 0 < SYSCLK ≤ 24 MHz
001 One wait state, if 24 MHz < SYSCLK ≤ 48 MHz
010 Two wait states, if 48 MHz < SYSCLK ≤ 72 MHz

 

سرعت تغییر وضعیت STM32F1 یکی از روش‌های ساده برای کپی کردن اطلاعات از مموری به‌روی GPIO استفاده‌از حلقه‌ی for است:

{
u8 buffer[8] = {0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00};

while(1) {
for(u32 i=0; i<8; i++)
{
GPIOD->ODR = buffer[i];
}
}
}

 

در فرکانس ۴۸MHz بدون تنظیمات flash wait states، درحالت بهینه‌سازی نشده (O0)، به فرکانس بیش از ۱MHz دست پیدا می‌کند. در زمان اجرای برنامه در زمان‌های ری‌استارتِ حلقه‌ی while، شکافی در سرعت اجرا ایجاد می‌شود که به‌دلیل پاک‌شدن PipeLine درهنگام اجرای دستورات شرطی و پرشی است:

فرکانس ۴۸MHz در حالت بهینه‌سازی نشده (O0)
فرکانس ۴۸MHz در حالت بهینه‌سازی نشده (O0)

 

مجدداً برای فرکانس ۴۸MHz بدون تنظیمات flash wait states آزمایش را تکرار می‌کنیم ولی این‌بار بهینه‌سازی O2 را اعمال می‌کنیم. به فرکانس ۱.۸MHz دست پیدا می‌کند. درشکل نیز دیده می‌شود که شکاف‌های ایجادشده توسط حلقه‌ی while حذف شده‌اند:

فرکانس ۴۸MHz در حالت بهینه‌سازی نشده (O2)
فرکانس ۴۸MHz در حالت بهینه‌سازی نشده (O2)

 

وقتی‌که تنظیمات فلش را روی ۲wait states قرار دهیم، بدون اعمال بهینه‌سازی عملکرد CPU کاهش می‌یابد: (here -O0)

wait state 2(here-O0(
wait state 2(here-O0(

 

با تنظیم فلش روی ۲wait states و اعمال بهینه‌سازی O2 عملکرد CPU نسبت‌به بدون تنظیمات فلش کاهش می‌یابد: (here -O2)

wait state 2(here-O2(
wait state 2(here-O2(

 

این‌بار فرکانس را روی ۷۲MHz تنظیم می‌کنیم و آزمایش‌ها را تکرار می‌کنیم. در حالت بدون تنظیمات flash wait states و بدون بهینه‌سازی عملکرد CPU بهبود می‌یابد: (here -O0)

فرکانس 72MHz (here -O0)
فرکانس 72MHz (here -O0)

 

با تنظیم فلش روی ۲wait states و اعمال بهینه‌سازی O2، عملکرد CPU در فرکانس ۷۲MHz نسبت به فرکانس ۴۲MHz بهبود می‌یابد: (here -O2)

فرکانس 72MHz (here -O2)
فرکانس 72MHz (here -O2)فرکانس 72MHz (here -O2)

 

در حالت بهینه‌سازی نشده، حلقه‌ی for در اجرای برنامه تأخیر ایجاد می‌کند. برای حل این مسئله دستورات برنامه را بدون‌استفاده‌از حلقه‌ی for می‌نویسیم:

{
u8 buffer[8] = {0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00};

while(1) {
GPIOD->ODR = buffer[0];
GPIOD->ODR = buffer[1];
GPIOD->ODR = buffer[2];
GPIOD->ODR = buffer[3];
GPIOD->ODR = buffer[4];
GPIOD->ODR = buffer[5];
GPIOD->ODR = buffer[6];
GPIOD->ODR = buffer[7];
}
}

 

در این برنامه با تنظیم‌فرکانس سیستم، برروی ۷۲MHz می‌توانیم به فرکانس ۳.۶MHz دست‌یابیم. البته تأثیر حلقه‌ی while همچنان باقی‌است:

فرکانس 72MHz با تأثیر حلقه‌ی while
فرکانس 72MHz با تأثیر حلقه‌ی while

 

در فرکانس ۷۲MHz مشابه حالت قبل اما با بهینه‌سازی O2 عملکرد CPU به‌طرز چشمگیری به ۱۸MHz بهبود می‌یابد. قابل‌توجه‌است که ۱۸MHz بالاترین سرعت GPIO بیان‌شده در دیتاشیت آن است.

فرکانس 72MHz با بهینه‌سازی O2
فرکانس 72MHz با بهینه‌سازی O2

 

ارسال اطلاعات توسط DMA به GPIO: روش دیگری برای کپی اطلاعات از SRAM روی GPIO استفاده‌از (DMA (Direct Memory Access است. DMA بدون استفاده‌از CPU اطلاعات را از A روی B کپی می‌کند.

u8 buffer[8] = {0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00};

/* DMA setup */
RCC->AHBENR |= RCC_AHBENR_DMA1EN;

/* channel 1: mem:8bit -> peri:8bit */
DMA1_Channel1->CNDTR = 8;
DMA1_Channel1->CMAR = (uint32_t)buffer;
DMA1_Channel1->CPAR = (uint32_t)&(GPIOD->ODR);
DMA1_Channel1->CCR = 0;
DMA1_Channel1->CCR = DMA_CCR1_MEM2MEM | DMA_CCR1_PL | DMA_CCR1_MINC | DMA_CCR1_CIRC | DMA_CCR1_DIR | DMA_CCR1_EN;

while(DMA1_Channel1->CNDTR);

 

درواقع، به‌دلیل استفاده‌از حلقه‌ی while در انتهای برنامه، روش DMA بدون استفاده‌از بهینه‌سازی به‌اندازه‌ی CPU سریع عمل نمی‌کند. در زمان استفاده DMA برای انتقال اطلاعات به GPIO ،اطلاعات خواسته‌شده از روی دیتاباس خوانده می‌شوند.

استفاده از حلقه‌ی while
استفاده از حلقه‌ی while

 

اینبار حلقه while را با یک حلقه for بدون شرط جایگزین می‌کنیم تا تفاوت را مشاهده‌کنیم:

//while(DMA1_Channel1->CNDTR);
for(;;) {}

 

در این حالت نتیجه با حالت استفاده‌از CPU مشابه میشود (۳.۶MHz):

استفاده از حلقه‌ی for
استفاده از حلقه‌ی for

 

قابل‌ذکر است که تمامی آزمایش‌های DMA بدون اعمال بهینه‌سازی انجام می‌شود؛ زیرا با اعمال بهینه‌سازی O2 نتایج مطلوبی حاصل نمی‌شود:

فرکانس نهایی
فرکانس نهایی

 

جمع‌بندی: با توجه‌به آزمایش‌های انجام‌شده ملاحظه‌شد که STM32F1 با اعمال بهینه‌سازی O2 و بدون استفاده‌از دستور حلقه‌ی for می‌تواند به فرکانس ۱۸MHz در GPIO دست پیدا کند (البته اعمال بهینه‌سازی O3 نتایج بهتری را تولید نمی‌کند). برای حالت انتقال اطلاعات توسط DMA اگر از ۳۲ بیت DMA برای خواندن اطلاعات از SRAM استفاده شود ممکن‌است بتوان به نتایج‌بهتری دست‌یافت.

 

 

 

منبع:‌سیسوگ

مطلب قبلیتبادل داده بین اندروید و آردوینو توسط بلوتوث
مطلب بعدیسیستم کنترل صوتی با کمک Raspberry Pi

پاسخ دهید

لطفا نظر خود را وارد کنید!
لطفا نام خود را در اینجا وارد کنید