سلام دوباره، در این قسمت جذاب که ادامه قسمت های اول کتابخانه CMSIS و دوم کتابخانه CMSIS است به ساختار این کتابخانه و در نهایت نحوه تعریف رجیستر ها و پریفرال ها در آن می پردازیم. در این بخش سعی می کنم با عکس های زیاد به طور دقیق بهتون توضیح بدم که این کتابخانه چه جوری می تونه شما رو به لایه های زیرین برنامه نویسی و در نهایت سخت افزار میکرو برسونه پس امیدوارم تا انتها منو همراهی کنید 😉
ساختار هسته CMSIS
قسمت core که در بخش اول در موردش توضیح دادم می تواند توسط سه فایل به برنامه شما اضافه بشه. دقت کنید که قسمت core در همه برنامه نویسی با CMSIS مورد نیاز است . این سه فایل startup code وsystem_<device>.c و main.c است
خوب بریم ببینیم هر کدوم از این قسمت ها چه جوری میان و اصلا کدوم ها رو ما باید اضافه کنیم.
۱- startup_<device>.s : این فایل زمانی ساخته می شود که شما در حال ساخت پروژه هستید و میکرو خوتون رو انتخاب می کنید و تنظیمات دیگه مثل مقدار stack رو انجام می دهید . این فایل توسط کامپایلر شما ساخته می شود و اگر بیشتر بخواید بدونید مشخص کننده vector table (در قسمت NVIC توضیح دادم ) هم هست
۲- system_<device>.c: این فایل دارای تمام توابعی است برای زمانی که میکرو از ریست بیرون می آید و در حال مقدار دهی اولیه است از جمله تنظیم ساختار درختی clock , ساختار باس داخلی و … .
**استثناً در اینجا به دلیل مثالی که شرکت st ارئه داده و از کتابخانه های hal مخصوص خودش هم استفاده کرده است device>.h> در فایل system_stm32f7xx.c به برنامه اضافه شده است که تفاوت خاصی هم ندارد.
۳- main.c : این فایل شامل کد برنامه نویس می شود
خب اضافه کردن سه قسمت بالا به طور تقریبی به کمک شما انجام می شد یعنی هنگام ساخت پروژه فایل های main.c و startup_<device>.s توسط محیط توسعه نرم افزار(IDE)و کامپایلر به پروژه اضافه می شدند وشما فقط باید فایل system_<device>.c را که توسط شرکت تولید کننده میکروتون آماده شده به پروژه اضافه کتید .
حالا می خوام یک توضیح مختصر با عکس در مورد نحوه اضافه شدن لایه های دو به بعد در ساختار CMSIS core بهتون بدم.
۴- core_<cpu>.h و system_<device>.h
۵- core_cmlnstr.h و core_cmFunc.h و Core_cm4_simd.h
** توجه کنید فایل ها ممکن است در ابتدا به برنامه اضافه نشوند و بعد از چند خط کد این اتفاق بیوفتد
خب توضیح در مورد ساختار CMSIS تموم شد و کم کم به جای جذاب تر از این کتابخانه می رسیم . جایی که رجیستر های هسته CPU و رجیستر های پریفرال ها مشخص می شوند . اگر تصمیم دارید به درکی از نحوه ارتباط برنامه C خوتون و سخت افزار داشته باشید حتما ادامه رو با من باشید
**به دلیل اینکه شاید در کل عمر برنامه نویسیتون با رجیستر های هسته CPU کاری نداشته باشید از توضیح اون بخش صرف نظر می کنم ولی خوب خودتون می تونید با کنجکاوی فایل core_<cpu>.h رو بگردید و قطعا بعد از یادگیری بخش زیر مشکلی در اون بخش نخواهید داشت
***اینجا لازم است تا توضیح کوتاهی در مورد struct ها در زبان C بهتون بدم تا در ادامه مشکلی در فهم مبحث نداشته باشید پس برای همین , این تایپیک جدا رو به عنوان پرانتز باز کردم تا بحث منحرف نشه .
نحوه دسترسی به رجیستر های پریفرال ها
خب اول میریم سر نحوه دسترسی به پریفرال ها که در فایل system_stm32f7xx.c تعریف شده اند. ( **دقت کنید که من از میکرو stm32f746 استفاده می کنیم و شرکت st به صورت مجموعه ای برای میکرو هاش فایل ها رو درست می کنه به طور مثال ابتدا فایل system_stm32f7xx.c رو به عنوان مجموعه میکروکنترلر های سری stm32f7 درست می کنه و در داخلش زیر مجموعه ها رو اضافه می کنه) خب اولین مثال میریم سر واحد I2C که برای میکرو من ۱۱ تا رجیستر داره
خوب همینطور که میبینید این رجیستر ها در فایل stm32f746xx.h تعریف شده اند
برای تعریف هر واحد, از ساختمان استفاده می شود . همانطور که در پست کمکی توضیح دادم هر داده در ساختمان پشت سر هم در حافظه قرار می گیرد. به آدرس هر کدوم از این داده ها آدرس آفست گفته میشود و در ادامه با آدرس پایه هم آشنا می شیم
آدرس آفست را در کادر قهوه ای مشاهده می کنید( این نوشته ها برای راهنمایی است و در کتابخانه CMSIS به فراوانی یافت می شود)
همینطور که در کادر سبز میبینیم رجیستر های I2C به صورت ۳۲ بیتی (۴ بایت) و بدون علامت و به صورت خواندنی نوشتنی هستند
در کادر قرمز میبینیم که این ساختمان با نام I2C_TypeDef تعریف شده است
خب حالا از کجا بفهمیم این رجیستر ها چه جوری آدرس دهی می شوند؟؟
خب از اینجا به بعد از بالا به پایین میریم 😉
خوب اینجا به طور مثال I2C1 یک ساختمان از نوع I2C_TypeDef است که آدرس شروع آن I2C1_BASE است یا به عبارتی دیگه از آدرس I2C1_BASE به اندازه ساختمان I2C_TypeDef فضا در مموری مپ به عنوان I2C1 در نظر گرفته شده است .
خوب حالا I2C1_BASE چیه و از کجا آمده؟
خب اینجا میبینیم که I2C1_BASE از جمع یک عدد با APB1PERIPH_BASE بدست می آید
خب APB1PERIPH_BASE چی هست و از کجا آمده؟
خب اینکه از کجا آمده تقریبا مشخص شد ولی اینکه چی هست رو باید توضیح بدم که سعی میکنم مختصر باشه و بحث منحرف نشه تا توی یک تاپیک جدا به صورت کامل در موردشون صحبت کنیم
میکرویی که من دارم دارای ۴ باس می باشد که بیشتر قسمت ها از طریق این باس ها به مموری یا هسته CPU متصل میشن . پس واحد مورد نظر ما (I2C1) هم از یکی از اون باس ها استفاده می کنه که در اینجا APB1 است
خب اگر کنجکاوید بدونید PERIPH_BASE چیه به عکس پایین دقت کنید تا متوجه آخرین مرحله بشید
خب به راحتی می شه فهمید که PERIPH_BASE آدرس پایه پریفرال هایی هست که روی ۴ باسی که توضیح دادم وجود داره
شاید بهتر باشه برای درک بهتر , مموری مپ داخل دیتا شیت یک میکرو را با مشخصات داخل این فایل از کتابخانه CMSIS مقایسه کنید.
خب امیدوارم خسته نشده باشید و این مطلب براتون مفید بوده باشه
اگر شکی در هر قسمتی از نوشته داشتید خوشحال میشم به سوالتون جواب بدم
اگر این نوشته برایتان مفید بود لطفا کامنت بنویسید.
بسیار ممنون ومتشکر
در عین کوتاه بودن خیلی مفید بود، کل ساختار cmsis تو ذهنم شکل گرفت
خیلی ممنون و خدا قوت بسیار عالی بود
ممنون بابت وقتی که برای انتشار مطالب صرف می کنید./.
عااااااااالی