آموزش STM32 با توابع HAL قسمت چهارم: دیباگ در STM32Cube IDE

آموزش STM32 با توابع HAL قسمت چهارم: دیباگ در STM32Cube IDE

آموزش STM32 با توابع HAL قسمت چهارم: دیباگ در STM32Cube IDE
آموزش STM32 با توابع HAL قسمت چهارم: دیباگ در STM32Cube IDE

در قسمت پیشین از سری آموزش STM32 با توابع HAL، در مورد ریست و کلاک میکروکنترلر و نحوه تنظیم واحد RCC توضیح دادیم. در این قسمت، می‌خواهیم نحوه دیباگ در STM32CubeIDE را یاد بگیریم، با سیسوگ همراه باشید.

 

 

برای دیباگ کردن به یک دستگاه دیباگر نیاز داریم که ما در این آموزش از پروگرمر و دیباگر ST Link استفاده خواهیم کرد. بااین‌حال دیباگرهای دیگری نیز وجود دارند که از طریق پورت SWD یا JTAG و با عملکردی مشابه ST Link می‌توانند برای پروگرام و دیباگ مورداستفاده قرار گیرند. در این بخش از آموزش، در مورد نحوه تنظیم دیباگر در پیکربندی پروژه، اتصال آن به بورد و چگونگی استفاده از آن را یاد می‌گیریم. اما قبل از آن، می‌خواهیم در مورد پشتیبانی ARM Cortex-M3 (یعنی پردازنده به کاررفته در میکروکنترلر موردنظر ما) از قابلیت دیباگ در STM32CubeIDE، صحبت کنیم.

دیباگر میکروکنترلر، دستگاهی است که این امکان را به ما می‌دهد که اجرای برنامه را در هر قسمت دلخواهی متوقف کرده تا متغیرهای مختلف را بررسی کنیم. بسته به نوع دیباگر مورداستفاده، می‌توانیم تعداد مشخصی Break Point در برنامه قرار دهیم تا هنگام دیباگ، اجرا در این نقاط متوقف شود. علاوه بر این در حالت دیباگ می‌توانیم برنامه را خط به خط اجرا کنیم و تغییرات را زیر نظر بگیریم.

پردازنده‌های ARM Cortex M3 & M4، به دلیل بهره‌گیری از افزونه‌های سخت‌افزاری دیباگ، امکان پشتیبانی از قابلیت‌های دیباگ پیشرفته رادارند. افزونه‌های گفته‌شده، به پردازنده این قابلیت را می‌دهند که در زمان فچ کردن دستور (اصطلاحاً breakpoint) یا دسترسی به داده (watchpoiont) متوقف شود. در این توقف‌ها، حالت داخلی هسته پردازشی و همچنین حالت بیرونی سیستم، قابل‌بررسی هستند. درنهایت و پس از بررسی حالت‌های سیستم، می‌توان پردازنده را به حالت کار عادی و ادامه اجرای برنامه، بازگرداند.

این قابلیت‌های دیباگ، بااتصال میکروکنترلر به دستگاه دیباگر قابل‌استفاده هستند. در ابتدای این قسمت، گفتیم که برای دیباگ معمولاً از دو پورت JTAG و یا SWD (Serial Wire Debug) استفاده می‌شود. در این قسمت آموزش، برای دیباگ میکروکنترلر موجود روی بورد Blue Pill، یعنی STM32f103c8 از پورت SWD استفاده می‌کنیم.

در شکل زیر، دیاگرام سخت‌افزار مربوط به دیباگ در پردازنده ARM Cortex-M3 نشان داده‌شده است. در این شکل می‌توان دید که سخت‌افزار گفته‌شده، شامل ویژگی‌های مختلفی (ازجمله ITM) است که امکان دیباگ پیشرفته را فراهم می‌کنند.

همان‌طور که در شکل مشخص است، این سخت‌افزار شامل بخش‌های زیر می‌شود:

  • SWJ-DP: Serial wire / JTAG debug port
  • AHP-AP: AHB access port
  • ITM: Instrumentation trace macrocell
  • FPB: Flash patch breakpoint
  • DWT: Data watchpoint trigger
  • TPUI: Trace port unit interface (available on larger packages, where the corresponding pins are mapped)
  • ETM: Embedded Trace Macrocell (available on larger packages, where the corresponding pins are mapped)

 

سخت‌افزار دیباگر ST-Link v2

گفتیم که برای دیباگ به سخت‌افزار ST-Link v2 نیاز داریم. در شکل زیر مدل مورداستفاده ما (مدل اصلی سمت راست) و کپی چینی آن (سمت چپ) نشان داده‌شده است. قابل‌ذکر است که نسخه کپی از قابلیت serial wire trace debugging پشتیبانی نمی‌کند. زیرا برخلاف نسخه اصلی، در pinout آن، پایه SWO وجود ندارد. در نسخه اصلی این پایه به پایه B3 بورد BluePill متصل می‌شود.

درواقع حالت serial wire trace debugging یا trace asynchronous sw به ما این امکان را می‌دهد که از طریق پایه SWO، از میکرو LOG بگیریم. از این طریق برای چاپ و مشاهده مقدار متغیرها و حالت میکرو، از UART و سخت‌افزارهای مبدل بی‌نیاز خواهیم بود.

برای تغییر مدل کپی و اضافه کردن پایه SWO، می‌توان به‌صورت دستی این پایه را از روی میکرو به یک پایه متصل کرد. به‌عنوان‌مثال در شکل زیر، SWO به پایه 5v  متصل شده است. اگرچه می‌توان از هر پایه دیگری (از میان 10 پایه موجود) نیز استفاده کرد.

تعویض پین 5v با SWO.

اکنون‌که تا اندازه با مفهوم دیباگ و جزییات سخت‌افزاری آن آشنا شده‌ایم، می‌خواهیم به سراغ ساخت یک پروژه برویم و سپس در محیط STM32CubeIDE مراحل دیباگ یک کد نمونه را باهم بررسی کنیم.

 

ایجاد یک پروژه نمونه

برای اینکه مراحل دیباگ را بررسی کنیم، نیاز به یک پروژه نمونه داریم. پس طبق مراحل شرح داده‌شده در قسمت قبلی، یک پروژه جدید می‌سازیم. تمام تنظیمات را در حالت اولیه رها می‌کنیم و تنها در تب Pinout & Configuration و در بخش System Core -> SYS نوع اتصال دیباگ را روی Serial Wire و یا Trace Asynchronous Sw تنظیم می‌کنیم. توجه کنید که در حالتی که Trace Asynchronous Sw انتخاب‌شده باشد پایه PB3 به SWO اختصاص خواهد یافت.

 

 

اکنون وارد بخش کد نویسی و دیباگ می‌شویم. بدین منظور از فایل‌های پروژه (در پنجره Project Explorer در سمت چپ)، از مسیر Core -> Src، ‌main.c را انتخاب می‌کنیم. در این فایل کدهای برنامه اصلی نوشته می‌شوند و توابع نوشته‌شده در سایر فایل‌ها فراخوانی خواهند شد. در این پروژه به دلیل کم بودن حجم کد موردنظر، تمام کد را در همین فایل می‌نویسیم.

 

نوشتن کد و شروع دیباگ

اکنون می‌خواهیم در فایل main.c کد ساده‌ای بنویسیم تا بتوانیم چگونگی دیباگ شدن پروژه را باهم بررسی کنیم. قبل از آن نگاهی به کد تولیدشده توسط نرم‌افزار در هنگام پیکربندی پروژه می‌اندازیم. ساختار این کد بدین‌صورت است که قبل از تابع int main(void)، توابع موردنیاز برای راه‌اندازی بخش‌های مختلف میکرو اعلان‌شده و سپس درون تابع int main(void) فراخوانی می‌شوند. در این پروژه تنها تابع استفاده‌شده void SystemClock_Config(void) است که همان‌طور که از نام آن مشخص است برای اعمال تنظیمات کلاک به‌کار می‌رود. درون بدنه تابع int main(void)، تابع دیگری نیز فراخوانی شده است که HAL_Init نام دارد. این تابع طبق تعریف کتابخانه HAL، در شروع هر برنامه‌ای فراخوانی می‌شود تا سه عمل را انجام دهد؛

  1. راه‌اندازی Cache مربوط به داده‌ها و دستورات و شروع فرایند pre-fetch
  2. تنظیم تایمر Sys Tick برای ایجاد وقفه در هر 1 میلی‌ثانیه (بر اساس کلاک HSI) با کمترین اولویت وقفه و همچنین راه‌اندازی تایمر Sys Tick
  3. فراخوانی تابع HAL_MspInit برای راه‌اندازی سیستم.

در پروژه‌های آینده و با استفاده از دستگاه‌های جانبی بیشتر، کدهای بیشتری نیز توسط نرم‌افزار تولید می‌شوند تا تنظیمات انجام‌شده در زمان پیکربندی را برای ما اعمال کنند. اکنون به سراغ کد نویسی می‌رویم. بدین منظور در بدنه تابع (void)int main و قبل از حلقه (1) while، متغیر counter را تعریف می‌کنیم و مقدار اولیه آن را برابر با 0 می‌گذاریم؛

سپس در بدنه حلقه (1) while، مقدار متغیر counter را در هر بار تکرار افزایش می‌دهیم و سپس به‌اندازه 500ms تأخیر ایجاد می‌کنیم؛

اکنون باید کد نوشتن شده را compile کنیم و از پروژه build بگیریم. بدین منظور روی آیکون چکش در نوارابزار بالای صفحه کلیک کنیم. نکته‌ای که در این قسمت وجود دارد، امکان انتخاب میان دو حالت Debug و Release است. تفاوتی که میان این دو حالت وجود دارد این است که کد تولیدشده در حالت Release، به‌صورت بهینه ساخته می‌شود و درنتیجه بسیار کم‌حجم‌تر و اجرای آن سریع‌تر است. بااین‌حال، ازآنجایی‌که در این حالت، بخش‌هایی از کد حذف یا دچار تغییر می‌شوند، دیباگ کد تولیدشده با مشکلات و دشواری‌هایی روبرو می‌شود. پس برای دیباگ کردن از حالت Debug و برای تولید کد خروجی پروژه از حالت Release، استفاده خواهد شد.

 

باوجود نکات گفته‌شده، برخی توصیه می‌کنند که در حالت تولید کد خروجی نیز تنظیم Build روی حالت Debug قرار بگیرد. زیرا ممکن است در حالت Debug برنامه به خوبی اجرا شود اما در حالت Release، باگ‌های جدیدی ایجاد شوند. البته این توصیه برای زمانی است که ازنظر حجم کد و سرعت اجرا محدودیت خاصی نداشته باشیم و کد تولیدی در حالت Debug از این نظر قابل‌قبول باشد.

پس از Build گرفتن از پروژه، وارد حالت دیباگ می‌شویم. البته قبل از آن باید مطمئن شویم که دیباگر به‌درستی به سیستم متصل شده و شناخته‌شده است. همچنین میکروکنترلر باید به دیباگر متصل باشد. بهتر است آخرین ورژن فریمور دیباگر نیز نصب‌شده باشد. در رابطه با مورد آخر، خود برنامه STM32CubeIDE، در زمان اتصال دیباگر پیغامی برای آپدیت کردن فریمور دستگاه، خواهد داد.

برای رفتن به حالت Debug می‌توانیم از نوارابزار بالای صفحه آیکون حشره مانند دیباگ را انتخاب کنیم یا اینکه از منوی Run، ‌Debug را انتخاب کنیم؛

بعد از رفتن به حالت دیباگ پنجره‌های جدیدی اضافه می‌شوند و همچنین نوارابزار دچار تغییراتی خواهد شد. در پنجره اضافه‌شده در سمت چپ برنامه و در تب متغیرها، می‌توانیم متغیر counter و مقدار اولیه‌ی آن را مشاهده کنیم.

اکنون در خطی که مقدار متغییر counter افزایش می‌یابد، یک Breakpoint اضافه می‌کنیم. برای این کار، می‌توانیم در سمت چپ این خط کد، دبل کلیک کنیم. یا اینکه در همین قسمت کلیک راست کنیم و سپس گزینه Add Breakpoint را انتخاب کنیم.

درنهایت کلید مربوط به شروع اجرای کد () را انتخاب می‌کنیم. مشاهده می‌کنیم که اجرای برنامه تا همان خطی که Breakpoint قرار دارد، انجام‌شده و در همان‌جا متوقف می‌شود. با کلیک کردن دوباره روی کلید شروع اجرا یا Resume، اجرای برنامه ادامه پیدا می‌کند و مجدداً روی همین دستور متوقف می‌شود. اکنون در پنجره مربوط به متغیرها در پنجره سمت چپ می‌بینیم که مقدار متغیر counter، یک واحد افزایش‌یافته است؛

 

 

به همین ترتیب با ادامه دادن به اجرای کد، مقدار متغیر counter به 2، 3 و بالاتر افزایش پیدا خواهد کرد.

 

 

همان‌طور که مشاهده می‌شود، یکی از کاربردهای مهم حالت دیباگ و استفاده از Breakpoint، توقف اجرای در یک خط مشخص از برنامه و نظارت بر مقدار متغیرها و حالت سیستم است. البته برنامه‌ی حاضر بیش‌ازحد ساده بوده و تنها شامل یک متغیر می‌شود. در آینده و در پروژه‌های پیچیده‌تر، پارامترهای بسیار بیشتری را می‌توانیم در حالت دیباگ، موردبررسی قرار دهیم. به‌عنوان‌مثال یک بخش دیگر که در حالت دیباگ می‌تواند موردبررسی قرار گیرد، رجیسترهای پردازنده هستند. برای بررسی رجیسترها، در پنجره سمت چپ، تب Registers را انتخاب می‌کنیم؛

 

 

علاوه بر این، می‌توانیم مقدار ذخیره شده در رجیسترهای خاص منظوره پردازنده و همچنین رجیسترهای کنترل Peripheralهای میکروکنترلر را در تب SFRs در همین پنجره، مشاهده کنیم؛

 

دیباگ در STM32CubeIDE

در این پروژه چون از پریفرال خاصی استفاده نکرده‌ایم وارد جزییات این قسمت نمی‌شویم. بااین‌حال در تمامی پروژه‌ها درصورتی‌که عملکرد موردنظر را از میکروکنترلر و دستگاه‌های جانبی دریافت نکنیم، می‌توانیم به سراغ بررسی این بخش برویم.

در آخر می‌خواهیم کاربرد بقیه کلیدهای پراستفاده‌ی نوارابزار اضافه‌شده در حالت دیباگ را توضیح دهیم. کلیدهای اصلی مورداستفاده ما در حالت دیباگ عبارت‌اند از:

پایان دادن به اجرا و شروع دوباره برنامه         

شروع و یا ادامه دادن به اجرای برنامه               

توقف کردن اجرای برنامه                                 

پایان دادن به اجرای برنامه و خروج از حالت دیباگ         

رفتن به درون بدنه تابع (یا اجرای یک خط کد و رفتن به خط بعد، در صورتی که آن خط کد، یک دستور ساده بوده و فراخوانی یک تابع نباشد)     

اجرای یک خط از کد و رفتن به خط بعدی           

بیرون آمدن از بدنه تابع(در صورتی که وارد بدنه یک تابع شده باشیم)          

در این قسمت ابزارها و بخش‌های مهم مربوط به دیباگ در محیط نرم‌افزار STM32CubeIDE را معرفی کردیم. در قسمت بعدی سری آموزش STM32 با توابع HAL، می‌خواهیم به GPIO و تنظیم پایه‌ها در حالت ورودی و خروجی بپردازیم. با ما همراه باشید.

   لینک این پروژه در گیت‌هاب

   منبع مقدمه دیباگ

2 نفر

پــــســنــدیـده انـد

توجه

سیاوش
سیاوش

کارشناس ارشد الکترونیک دیجیتال، علاقه‌مند به یادگیری

دیدگاه ها

4 دیدگاه

  • MEYTICOM
    ۶ شهریور ۱۴۰۱

    ممنون سیاوش جان استفاده کردم

    توی خط “در شکل زیر مدل مورداستفاده ما (مدل اصلی سمت راست) و کپی چینی آن (سمت چپ)” اصلاح بشه

  • m.h.Yazdani
    ۱ شهریور ۱۴۰۱

    با تشکر از زحماتی که میکشید و با کمال احترام
    الکترونیک علم به روزیه اگه به روز نباشید خیلی ساده عقب خواهید افتاد
    شاید بهتر بود نویسنده اطلاعات خودش رو قبل از نوشتن مطالب جدید اپدیت میکرد

    • Zeus ‌
      Zeus ‌
      ۲ شهریور ۱۴۰۱

      سلام دوست عزیز
      متشکر میشم اگر مشکلی در مقاله می بینید با ما هم در میان بگذارید تا اصلاح شود

پر بحث ترین ها

مسابقه دوم : چالش برنامه نویسی به زبان C

مسابقه دوم : چالش برنامه نویسی به زبان C

مسابقه اول سیسوگ (مسابقه اول: درک سخت افزار) انتقادهای زیادی رو در پی داشت تا جایی که حتی خودمم به نتیجه مسابقه...

Zeus ‌ Zeus ‌
  • 3 سال پیش
راه اندازی LCD گرافیکی Nokia 1661

راه اندازی LCD گرافیکی Nokia 1661

LCD گرافیکی یکی از مهم ترین پارامترهای موجود در طراحی انواع مدارات الکترونیکی پیچیده و حتی ساده است ، نمایش وضعیت و...

Zeus ‌ Zeus ‌
  • 4 سال پیش
ریموت کدلرن و چکونگی دکد کردن آن به همراه سورس برنامه

ریموت کدلرن و چکونگی دکد کردن آن به همراه سورس برنامه

ریموت کنترل امروزه کاربرد زیادی پیدا کرده است؛ از ریموت‌های درب بازکن تا ریموت‌های دزدگیر و کنترل روشنایی همه از یک اصول اولیه پیروی می‌کنند و آن‌هم ارسال اطلاعات به‌صورت بی‌سیم است....

Zeus ‌ Zeus ‌
  • 5 سال پیش
همه چیز درباره ریموت کنترل‌های هاپینگ

همه چیز درباره ریموت کنترل‌های هاپینگ

امنیت همیشه و در همه‌ی اعصار، مقوله‌ی مهم و قابل‌توجه‌ ای بوده و همیشه نوع بشر به دنبال امنیت بیشتر، دست به ابداعات و اختراعات گوناگونی زده است. ریموت کنترل یکی از این اختراعات است. در این مقاله، به بررسی امنیت انواع ریموت‌های کنترل خواهیم پرداخت....

Zeus ‌ Zeus ‌
  • 5 سال پیش
مسابقه سوم: استخراج داده از رشته ها در زبان C

مسابقه سوم: استخراج داده از رشته ها در زبان C

نزدیک به 5 ماه از مسابقه دوم سیسوگ می‌گذره و فکر کردم که بد نیست یک چالش جدید داشته باشیم! البته چالش‌ها...

Zeus ‌ Zeus ‌
  • 2 سال پیش
مسابقه ششم: بزن میکروکنترلر را بسوزون!

مسابقه ششم: بزن میکروکنترلر را بسوزون!

بزنم میکروکنترلر را بسوزونم اونم تو  این شرایط!، طراحی مسابقه از اون چیزی که به نظر می‌رسه سخت‌تر است، باید حواست باشه...

Zeus ‌ Zeus ‌
  • 12 ماه پیش
آموزش قدم به قدم راه اندازی NRF24L01

آموزش قدم به قدم راه اندازی NRF24L01

آموزش قدم به قدم راه اندازی +NRF24L01  با کتابخانه سازگار با انواع میکروکنترلرها و کامپایلرها قبل از اینکه قسمت بشه با ماژول...

رسول خواجوی بجستانی رسول خواجوی بجستانی
  • 3 سال پیش
کار با ماژول تمام عیار mc60 – قسمت دوم – راه اندازی OpenCPU

کار با ماژول تمام عیار mc60 – قسمت دوم – راه اندازی OpenCPU

در قسمت اول به یکسری اطلاعات کلی ماژول mc60 پرداختیم، با نرم افزار QNavigator کار کردیم و یک هدربرد هم برای کار...

Mahdi.h   Mahdi.h  
  • 3 سال پیش
ساخت ماینر با FPGA و ARM

ساخت ماینر با FPGA و ARM

چند ماهی هست که تب بیت کوین و ارزهای دیجیتال خیلی بالا رفته! چه شد که این پست را نوشتم همانطور که...

Zeus ‌ Zeus ‌
  • 3 سال پیش
مسابقه چهارم: کدام حلقه سریع‌تر است؟

مسابقه چهارم: کدام حلقه سریع‌تر است؟

حدود ۷ ماه پیش، مسابقه سوم سیسوگ رو برگزار کردیم و کلی نکته در مورد خواندن رشته‌های ورودی را بررسی کردیم. فکر...

Zeus ‌ Zeus ‌
  • 2 سال پیش
سیـــســـوگ

مرجع متن باز آموزش الکترونیک