Çok farklı tarzlarda birçok gömülü sistem mikroişlemci uygulaması güç kesildiğinde de kullanıcı ya da sistem tarafından değiştirilebilen ya da ayarlanabilen bir çok veriyi kaydetmek durumundadır. Bunun için ilk akla gelen çoğu mikokontrollerde bulunmayan harici bir EEPROM ile verilerin saklanmasıdır. Harici EEPROM (electrically erasable programmable read-only memory) kullanmaktansa, STM32 serisindeki çoğu MCU’nun dahili Flash hafızasını kullanarak kalıcı veri saklama yapabildiğinizi biliyor muydunuz? Üstelik bu yöntemin harici EEPROM kullanmaya göre yazma ve okuma sürelerinin oldukça hızlı olması gibi çok daha avantajlı tarafları da mevcuttur.”AN2594” kodlu “EEPROM emulation in STM32F10x microcontrollers” isimli eke linkini eklediğim Application notundaki Tablo 1’de ayrıntılı inceleyebilirsiniz. EEPROM emulation işlemini ilk defa gerçekleştirirken bazi noktalarda fazlaca zaman harcadiğimdan takip ettiğim tüm gerekli adımları. daha sonra benzer problemler yaşayanlara yardımcı olma adına buraya aktararak bir yazı oluşturmaya karar verdim. Sorularınızı, yasadığınız problemleri aşağıdaki yorum kısmından aktarmanızdan memnun olurum.
Tasarladığım kartta her cihaz RS485 üzerinden haberleştiğinden her birinin en azından belirli ve ayarlanabilir Cihaz ID’lerinin olması gerekiyordu. Bu kadar kısıtlı miktarda bir veriyi saklamak için flasha yazma yerine OTP (one-time programmable) alanını ya da Back-Up Registers (BKP) birimini kullanabilir olsanız da ileride farklı parametre ekleme durumundan dolayı data hacmimin oldukça büyüyeceği bir senaryoda bu yöntemler işime pek de yaramayacaktı. Dolayısıyla, bu işlemi de asgari maliyette yani harici bir EEPROM ilave etmeden, hem de daha optimum bir şekilde çözmenin yollarını ararken bu yönteme başvurdum ve ayrıntılarını sizinle paylaşmak istedim.
Kullandığım ve test ettiğim MCU : STM32F100C8 (stm32vldiscovery board undaki MCU ile flash büyüklüğü hariç hemen hemen aynı özelliklere sahip bir mikrokontroller). Buna paralel olarak, flash adres ayarlamaları STM32F10x serisindeki orta ölçekli (32 ve 128 Kbyte arasında) flash büyüklüğüne sahip mikrokontrollerlara uygun olarak düşünülmüştür.
Kullandığım ve test ettiğim IDE: Keil MDK uVision 4
#define BANK1_WRITE_START_ADDR ((uint32_t)0x08000400) #define BANK1_WRITE_END_ADDR ((uint32_t)0x08003000) #define FLASH_PAGE_SIZE ((uint16_t)0x400)
STM32 bünyesinde herhangi bir MCU’da yazmış olduğunuz kodu çok farklı flash ve RAM büyüklüklerine ve adreslemelerine sahip MCU da çalıştırılabilir hale getiren nedir acaba? İşte bu aşamada, gömülü bağlayıcı kodu olarak da Türkçeye çevrilen Linker Scripts, derleyici tarafından oluşturulan ara kodları işletim sisteminin çalıştırabileceği makine kodlarına (.hex hex dosyası gibi) çeviren kod parçacığı devreye girmektedir. Linker ayarlamaları bağlamında kullanacağınız önemli noktalardan biri olan Scatter dosyasında, memory bölgelerini, adreslemelerini, heap/stack bölgesini, heap/stack büyüklüğünü ve RAM, ROM bölgelerinin kullanım taslağını tanımlama gibi imkânlara sahipsiniz. Bu genel bilgilendirmenin ardından, EEPROM emulasyonu surecinde yapılması gereken scatter dosyasındaki düzenlemeleri manüel ve otomatik olarak yapmanın yolunu su şekilde özet geçebiliriz.
Arayüz aracılığı ile flash data adres düzenlemesi:
Manual olarak flash data adres düzenlemesi:
Öncelikle manual kullanacağınızı buradan scatter dosyanızı göstererek seçiyorsunuz:
Scatter dosyası içeriği :
#define BANK1_WRITE_START_ADDR ((uint32_t)0x08000400) #define BANK1_WRITE_END_ADDR ((uint32_t)0x08003000) #define FLASH_PAGE_SIZE ((uint16_t)0x400)
uint32_t EEPROM_Read(void) { uint32_t readValue; FLASH_UnlockBank1(); Address = BANK1_WRITE_START_ADDR; readValue = (*(__IO uint32_t*) Address); FLASH_LockBank1(); return readValue; }
void EEPROM_Write(uint32_t Data) { //FLASH Bank1 Programlanmasi //Flash Bank1 Programlamak icin kilidin kaldirilmasi FLASH_UnlockBank1(); //İlgili bank da bulunan sayfa sayisini hesaplama NbrOfPage = (BANK1_WRITE_END_ADDR - BANK1_WRITE_START_ADDR) / FLASH_PAGE_SIZE; //Ilgili tum bayraklarin temizlenmesi FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); //Flash sayfalarinin silinmesi for(EraseCounter=0; EraseCounter<NbrOfPage; EraseCounter++) { FLASHStatus = FLASH_ErasePage(BANK1_WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter)); if (FLASHStatus != FLASH_COMPLETE) break; } //Flash Bank1 Programlanmasi Address = BANK1_WRITE_START_ADDR; while((Address < BANK1_WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE)) { FLASHStatus = FLASH_ProgramWord(Address, Data); Address = Address + 4; } FLASH_LockBank1(); //Yazilan datanin dogrulugunun kontrol edilmesi Address = BANK1_WRITE_START_ADDR; while((Address < BANK1_WRITE_END_ADDR) && (MemoryProgramStatus != FAILED)) { if((*(__IO uint32_t*) Address) != Data) { MemoryProgramStatus = FAILED; } Address += 4; } }
Dataların güvenli bir şekilde belirtilen adreslere yazıldığını STLink Utility den ekran vererek göstermeyi ve kisa bir video ile çalışan halinin videosunu eklemeyi en kısa zamanda yapmaya çalışacağım.
İbrahim Öztürk / Elektronik Mühendisi / York – UK
www.ozturkibrahim.com
[email protected]
4 sene ago ·
Hocam FLASH_UnlockBank1() fonksiyonu hata veriyor keil uvision 5 te
4 sene ago ·
Nasil bir hata veriyor?