1. ünite / 11 · yaklaşık 3 saat
Cortex-M mimarisi ve bellek haritası
ARM çekirdeği, STM32 aileleri, Harvard veri yolları ve her şeyin bir adres olduğu 4 GB'lık harita.
Bu ünitenin sonunda
- Cortex-M0+, M3, M4 ve M7 çekirdeklerini ve STM32 ailelerini (C0, F1, F4, G4, H7) ayırt etmek
- Flash, SRAM, çevre birimi ve sistem bölgelerini adres haritasında bulmak
- Bir çevre birimi yazmacının adresini taban + ofsetten hesaplamak
- Açılışta vektör tablosunun ve Reset_Handler'ın rolünü açıklamak
Ders notları
ARM, işlemci çekirdeğini tasarlar ve lisanslar; ST gibi üreticiler bu çekirdeğin çevresine bellek ve çevre birimleri koyup STM32 gibi mikrodenetleyiciler üretir. Cortex-M ailesi gömülü sistemler içindir: M0+ küçük ve az güç çeker, M4 kayan nokta birimi (FPU) ve DSP komutları ekler, M7 daha hızlı ve önbelleklidir.
Her şey bir adres
Cortex-M 32 bitlik bir adres alanı görür (4 GB). Haritanın düzeni sabittir: 0x0800_0000'da Flash, 0x2000_0000'da SRAM, 0x4000_0000'dan itibaren çevre birimleri, 0xE000_0000'da çekirdeğin kendi birimleri (NVIC, SysTick). Bir LED'i yakmak, aslında belirli bir adrese bir sayı yazmaktır: STM32F4'te GPIOA tabanı 0x4002_0000, ODR yazmacının ofseti 0x14, yani adres 0x4002_0014.
Açılış
Elektrik gelince çekirdek Flash'ın ilk iki kelimesini okur: yığının tepe adresi ve Reset_Handler adresi. Reset_Handler, ilk değerli değişkenleri (.data) Flash'tan RAM'e kopyalar, sıfır değerlileri (.bss) temizler ve main()'i çağırır. İşletim sistemi yoktur; main hiç dönmemelidir.
Bu derste STM32F4 (Nucleo-F401RE ya da F411 "Black Pill") temel alınır. Adresler ailelere göre değişir ama düşünce aynıdır: başvuru kılavuzu (Reference Manual) her yazmacın adresini ve bitlerini verir.
Simülasyon
Cortex-M bellek haritası gezgini
4 GB'lık adres alanında bir adres yaz ya da bir birime tıkla: hangi bölgede olduğunu, hangi çevre birimine ve yazmaç ofsetine düştüğünü gör. Adresler STM32F4 başvuru kılavuzundaki düzendedir.
Sol: bölgeler (ölçeksiz değil, 4 GB doğrusal). Sağ: bilinen birimlere tıkla.
Kendin dene
Bellek haritasında 0x4002_0014, 0x2000_0400 ve 0xE000_E100 adreslerini yaz: her biri hangi bölge ve birim? GPIOB'nin IDR yazmacının adresini hesapla ve doğrula. Sonra RCC'ye tıkla ve AHB1ENR'nin (ofset 0x30) adresini not et: GPIO saatini açmak için bu adrese yazacağız.
Kod
#include <stdint.h>
extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; /* bağlayıcı betiğinden */
int main(void);
void Reset_Handler(void);
void Default_Handler(void) { while (1) {} }
void SysTick_Handler(void) __attribute__((weak, alias("Default_Handler")));
/* Flash'ın başı (0x0800_0000): ilk kelime yığın tepesi, ikincisi reset adresi */
__attribute__((section(".isr_vector")))
const void *vectors[] = { &_estack, Reset_Handler, 0, 0, /* ... */ };
void Reset_Handler(void) {
uint32_t *src = &_sidata, *dst = &_sdata;
while (dst < &_edata) *dst++ = *src++; /* .data: ilk değerleri Flash'tan RAM'e kopyala */
for (dst = &_sbss; dst < &_ebss; ) *dst++ = 0; /* .bss: sıfırla */
main();
while (1) {}
}Sık yapılan hatalar
- Adresleri farklı aileler arasında aynı sanmak: STM32F1'de GPIO tabanı ve yazmaç düzeni farklıdır; her zaman kendi kartının başvuru kılavuzuna bak.
- Veri sayfası ile başvuru kılavuzunu karıştırmak: veri sayfası pin ve elektrik değerlerini, başvuru kılavuzu yazmaçları anlatır.
- main()'den dönmek: dönülecek bir işletim sistemi yoktur; sonsuz döngü şarttır.
- Yığın boyutunu hesaba katmamak: yığın taşınca .bss değişkenlerinin üzerine yazar ve hata tuhaf yerlerde görünür.
Yazılım mühendisliği bağlantısı
Gömülü yazılımda belgelere izlenebilirlik önemlidir: her yazmaç erişiminin yanına başvuru kılavuzunun bölüm numarasını yaz.
- Sihirli sayılar yerine CMSIS başlıklarındaki adlar (GPIOA->ODR, RCC_AHB1ENR_GPIOAEN) kullan.
- Kartı ve aileyi değiştirmeyi kolaylaştırmak için donanıma özgü kodu ayrı dosyada (bsp/) topla.
Kendini sına
STM32F4'te Flash hangi adresten başlar?
GPIOA tabanı 0x4002_0000, ODR ofseti 0x14. ODR adresi?
Reset_Handler main()'den önce ne yapar?
Kayan nokta birimi (FPU) hangi çekirdekte vardır?
