/**********************************************************************************************************************
READ / ERASE / WRİTE FLASH PROGRAM
Project:Çağrı Dinç February 2014 İstanbul
Debugger:IAR Embedded Workbench IDE 6.5
Microcontroller:STM32F100RBT6
Referance:Programming Manual Flash Programming Datasheet
************************************************************************************************************************/
#include "stm32f10x.h"
///////////////////// DEĞİŞKEN TANIMLAMALARI ////////////////
uint16_t Read_Data;
/////////////////////////////////////////////////////////////
void SystemInit(void)
{
}
/////////////// İSTENİLEN ADRESTEKİ BİLGİYİ FLASHTAN OKUMA ALT PROGRAMI /////////////////
uint16_t Read_Flash(uint32_t adr)
{
uint16_t * Pntr = (uint16_t *)adr;
return(*Pntr);
}
///////////////// FLASH KİLİDİ AÇMA ALT PROGRAMI /////////////////////
void Unlock_Flash (void)
{
FLASH->KEYR=0x45670123; //Flash kilidini açmak için FLASH->KEYR registerine KEY1 ve KEY2 sırayla yazılmalıdır
FLASH->KEYR=0xCDEF89AB;
}
///////////////// FLASH KİLİTLEME ALT PROGRAMI /////////////////////
void Lock_Flash (void)
{
FLASH->CR=0x00000080; //FLASH_CR registeri resetlendiğinde FLASH kiltlenmiş olur
}
//////////////// İSTENİLEN ADRESTEKİ VERİYİ FLASHTAN SİLME ALT PROGRAMI //////
void Erase_Flash (uint32_t adr)
{
FLASH->CR|=0x00000002; //PER enable
FLASH->AR=adr; //FLASH->AR registerine silinmek istenen adres yazılır
FLASH->CR|=0x00000040; //STRT anable
while((FLASH->SR&0x00000001)); //İşlem bitene kadar bekle(BUSY kontrol ediliyor)
FLASH->CR &= ~0x00000042; //FLASH->CR ilk durumuna alınıyor (kilit hala açık!)
}
///////////////// İSTENİLEN ADRESE VERİ YAZMA ALT PROGRAMI /////////////////////
void Write_Flash (uint32_t adr, uint16_t data)
{
FLASH->CR|=0x00000001; //PG enable
*(__IO uint16_t*)adr = data; //istenen adrese istenen data yazılıyor
while((FLASH->SR&0x00000001)); //İşlem bitene kadar bekle(BUSY kontrol ediliyor)
}
//////////////////////////////////////////////////////
int main(void)
{
Unlock_Flash();
Erase_Flash(0x0801FB00);
Write_Flash(0x0801FB00,'c');
Lock_Flash();
Read_Data=Read_Flash(0x0801FB00);
for( ;; )
{
}
}
Sağolasın kardeşim heralde herkes biliyor böyle zor bulunan bir uygulamayı. Emeğine sağlık.
elinize sağlık. hemen favorilere ekliyorum.
Rica ederim arkadaşlar inşallah faydası olmuştur.
Daha önce bu konuyla hiç ilgilenmedim dokümanlara da bakmadım.
Flash roma page page yazılmıyormu? Örnekte 16 bit veri yazılmış. Bu garibime gitti.
Hayır hocam. Byte/word olarak yazılabiliyor. Hatta yazılan bir hücrenin 1 lan bitleri tekrar 0 da yapılabiliyor.
Ancak 0 olmuş bir biti tekrar 1 yapamıyorsunuz. Bunun için de komple Page silmek gerekiyor.
Hocam bu konuda bizi biraz aydınlatabilir misiniz?Stm32f407'de flash'a veri yazmak istiyorum.Ama anlamadığım bazı yerler.Kaba taslak izleyeceğim adımları anlatabilir misiniz?
ST'nin Flasha veri kaydetmek için yayınladığı "eeprom emulator" kodları var. Sanırım stm32F1 içindi. F4'ün flash donanımını incelemedim hiç. Ama ufak tefek değişikliklerle F4 için uygulanabileceğini düşünüyorum.
Flash'ı oldukça efektif kullanmamızı sağlayan bir mantığı var. Yanılmıyorsam "Örnekler" kategorisinin altında "Neden eeprom koymamışlar" başlıklı bir konuydu. Orada bu mesele hakkında konuşulmuştu.
Ben olsam oradan başlardım.
Hocam o sayfayı az çok okudum sayılır.Benim hıza pek ihtiyacım yok.Yani gerekli yeri silip tekrar yazabilirim.Çok sık aralıklarla da yazmayacam.O yüzden eeprom emülasyonu yapmadan direkt yazsam olur mu?Bir de mesela bana 128 kb yetiyo.Son 128 kb lık sektor de bu yazma işlemlerini yapsam sorun çıkar mı?
Z hocam half word(16bit) şeklinde yazılmak zorunda. Programming Manual Flash Programming Datasheet 13.sayfadaki algoritmaya da bakabilirsiniz.Bir de flasha yazacağımız başlangıç adresi doğru seçilmeli.Örneğin sayfa sonundaki son byte a veri yazılmaya kalkışılırsa işlemci düzgün çalışmıyor.Başlangıçta dalgınlıkla böyle bir adres seçmiştim, uyanana kadar uğraştırdı.ST nin forumlarında da benzer sıkıntıları çekenler vardı.
Klein da söylediği gibi F4 için Flasha yazma kısmı F1 e benzer, bir kaç değişiklik yaparak halledilebilir.Başka bir arkadaş ST nin kodları ile F4 kitindeki flashı kullandı oradan biliyorum.
hocam mikroc de flashwrite, flasherase gibi komutlar var sanırım bu komutlar dediğiniz işlemleri yapıyor ancak ben hangi hafıza alanının boş olduğunu, hangisini eeprom gibi kullanabileceğimi nasıl belirlerim. yani demek istediğim yanlışlıkla programa zarar verirmiyim? yöntem nedir?
Once oku
@yamak Hız sorunun yoksa, flash ömrünü kısaltacak kadar sık yazma okuma da yapmıyorsan eeprom emülasyonu kullanmayabilirsin. Gerekli yerleri silip yazabilirim demişsin. Komple sayfayı silmen gerektiğini unutma. işlemciye göre 1K ile 16K arasında olabilir. belki daha da fazla.
@tekosis Her szman son sayfaları kullanırsan sıkıntı yaşayacağını zannetmem.
Hocam veri tabanı kaydetmeyi planlıyorum ve sık sık güncellemede yapılacağını zannetmiyorum.stm32f407vgt6 kullanıyorum ve bu işlem için son sektörü kullanmayı planlıyorum son sektörün boyutu da 128 kb.
Peki hocam programı yazdıktan sonra flash'ta boş kalan yerleri okuduğumda nasıl bir değer okumuş olurum.0xFFFFFFFF mi?
(http://s30.postimg.cc/pam5hcsst/Ads_z.jpg) (http://postimg.cc/image/pam5hcsst/)
Flashta boş kalan yerler FF ile gösterilir.Ayrıca yanlış bir yere veri yazmamak için (örneğin kodunun bulunduğu flash alanı) ilgili işlemcinin datasheet içindeki memory map kısmını kontrol edip sondan başa doğru yazmakta fayda var.
Kafamdaki sorular henuz cevaplanmadi.
TI Flash algoritmalarinda;
Ilk once, Clear islemi yapilarak flashdaki tum bitler sifir yapilir.
Ardindan Erase islemi yapilarak flashdaki tum bitler bir yapilir.
Daha sonra programla islemi yapilarak veriler yazilir.
Ilk mesajda verilen ornekte boyle Clear islemi goremedim. Bu durumda Flash bastan temizlenmistir anliyorum yoksa Clear ve Erase islemi STM islemcilerde tek bir islem mi?
Diyelimki 2 bolgeden olusan Flash tika basa dolu.
Ilk bolgede flash programlama algoritmalarim vs var.
Flashin 1. bolgesindeki yazilim sayesinde 2. Bolgedeki programi silip ardindan yeni bir program yuklemek istersem ne yapmaliyim?
@cagri_dinc
Verdigin programla X adresini silip 0x0000 yazip ardindan silip 0xFFFF yazip tekrar silip ardindan 0x0000 yazabiliyormuyuz?
Henuz denemedim. Denediysen sonucu merak ediyorum.
Kodu incelemedim. Eğer hata yoksa X adresini 0 yapabilirsiniz. ancak FFFF yapamazsınız. Bunun için komple sayfayı silmeniz gerek. Sayfayı sildikten sonra tekrar X adese istediğiniz veriyi yazarsınız. İster 0 ister ABCD.
hocam ben olayı sanırım yanlış anlamışım. bu flash hafıza programın tutulduğu hafıza değil dimi? picte eeprom hafızanın yerine kullanılan bir alan oluyor sanırım. burayı değiştirmek yazılan programa zarar vermez değil mi?
Evet. Flash dediğimiz yer program hafızası. Programın buluduğu alana yazmazsan bir sorun çıkarmaz.
Pic'de eeprom var. Buraya istediğin gibi yazabilirsin ve okuyabilirsin.
hocam kullandığım cihazı bootloader kullanarak programlıyorum. elimde herhangi bir programlama cihazı yok. dolayısı ile programın nereye kadar uzandığını bilemiyorum. eğer hafızanın sonuna atarsam o zamanda bootloadere zarar verme ihtimalim var sanırım ki bir daha hiç programlayamam. bu iş için hafızanın nereye kadar dolu olduğunu nasıl öğrenebilirim acaba? diğer konuları araştırdım ama bir sonuca ulaşamadım.
Bootloader son sayfalarda mı?
Öğrenmenin en basit yolu o sayfada 0xFFFF haricinde bir değer aramak. En son sayfanın en son hücresinden başlayarak aramaya başlarsın. Eğer sayfanın herhangi bir yerinde 0xFFFF haricinde değere rastlarsan o sayfa doludur.
hocam bootloaderin yerleştiği adresi bilmiyorum ne yazık ki. ama pic serilerinde bildiğim kadarı ile hafızanın son kısımlarına yükleniyordu bootloader.
Bootloader'ın program hafızasında oluduğunu düşünmüyorum.Sonuçta benim yazdığım programın boyutu tüm hafızayı dolduracak büyüklükteyse yazdığım program da bootloader ı silebilir o zaman
Alıntı yapılan: tekosis - 10 Mart 2014, 02:41:36
hocam bootloaderin yerleştiği adresi bilmiyorum ne yazık ki. ama pic serilerinde bildiğim kadarı ile hafızanın son kısımlarına yükleniyordu bootloader.
Eğer cipin kendi bootloader'inden bahsediyorsanız, program belleğinde değil.
Kendiniz bir bootloader yazdıysanız, onun yerini biliyor olmanız gerek.
anladım hocam o zaman bi çılgınlık edip son sayfayı silip yazmayı deneyeyim. ya kısmet :)
Asagidaki kodlardan *(__IO uint16_t*)adr = data; satirinda islemci hard fault'a dusuyor.
Flashda 0x80002000 adresinden itibaren sildim ve buraya yazmaya calistim.
Nerede hata yapiyorum?
///////////////// İSTENİLEN ADRESE VERİ YAZMA ALT PROGRAMI /////////////////////
void Write_Flash (uint32_t adr, uint16_t data)
{
FLASH->CR|=0x00000001;
*(__IO uint16_t*)adr = data;
while((FLASH->SR&0x00000001));
}
ben pic32 de usb üzerinden flash okuma yazma programı yazmıştım. bir fiziksel adresten birde sanal adresten bahsediliyor datasheet te (pic32 için).
fiziksel adresler 1 er 1 er artarken sanal adresler 4 er 4 er artıyor. biz pointer belirleyip istediğimiz adresten okuma yapmak istediğimiz de sanal adresi girmemiz gerekiyor. ve dediğiniz gibi eğer 1-2-3 ün katlarında bir adres değeri yüklediğimizde pointer e hard fault durumu meydana geliyor kod tıkanıyor. o yüzden önce okuma yapmak istenilen adres parametresinin 4 ün katları olduğunu ve istenilen aralıklarda olduğunu kontrol ettirip daha sonra okuma yazma yaptırmıştım. güzel sağlıklı çalıştırabildim.
if(!HIDTxHandleBusy(USBInHandle)){
for(i=5;i<65;i++)ToSendDataBuffer[i]=0xff;
ToSendDataBuffer[0] = 0x83;
j = 0;
j +=ReceivedDataBuffer[1];
j +=ReceivedDataBuffer[2]<<8;
j +=ReceivedDataBuffer[3]<<16;
j +=ReceivedDataBuffer[4]<<24;
if((
0xBFC02FFF>=j && j>=0xBFC00000||
0xBF8FFFFF>=j && j>=0xBF800000||
0xBD01FFFF>=j && j>=0xBD000000||
0xA0007FFF>=j && j>=0xA0000000||
0x9FC02FFF>=j && j>=0x9FC00000||
0x9D01FFFF>=j && j>=0x9D000000||
0x80007FFF>=j && j>=0x80000000 )&&
j%4==0 )
{
LCD1=j;
k=(unsigned int*)j;
LCD2=*k;
ToSendDataBuffer[1]= *k;
ToSendDataBuffer[2]= (*k>>8);
ToSendDataBuffer[3]= (*k>>16);
ToSendDataBuffer[4]= (*k>>24);
}
else
{
ToSendDataBuffer[1]= 0xff;
ToSendDataBuffer[2]= 0xff;
ToSendDataBuffer[3]= 0xff;
ToSendDataBuffer[4]= 0xff;
}
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)&ToSendDataBuffer[0],64);
}
Z hocam yazmaya çalıştığınız adres hatalı.Hangi işlemciyi kullanıyorsunuz?Şayet F1 serisini kullanıyorsanız Flash memory 0x08000000 den itibaren başlıyor.Kullandığınız işlemcinin datasheetindeki Memory Map kısmını kontrol etmenizi öneriyorum.Dikkat etmeniz gereken bir diğer nokta da, şayet flash memory 0x08000000 adresinden başlıyorsa datanızı o adresten itibaren yazmaya başlamayın.Çünkü yazdığınız programın koduyla çakışabilir.F1 serisi için verdiğim örnekteki adresi kullanabilirsiniz.
Adresde sorun yok verdiğim adres sınırlar içerisinde. Zaten çok farklı adresler de denedim.
0x80002000 geçerli bir adres değil dikkat edin 0x08000000 ile karıştırıyor olabilirsiniz.
@cagri_dinc
Aynen dediğiniz gibi, bakar kör olmuşum.
0x08000000 adresi olması gereken ROM alanını 0x80000000 yazmışım ve nerede ise tüm pazar günüm bu sorunla uğraşmakla geçti.
z hocam ben de aynı interrupt sıkıntısıyla 2gün cebelleştim.Ben gibi diğer arkadaşlar bu sıkıntıyı çekmesinler diye forumda paylaşmaya karar vermiştim. :)
STM32f103 için bu şekilde veya emulated eeprom ile veri saklamanın bir sınırı var mıdır (yazma silme açısından) ?
Gün içinde 10larca kez değişecek ve herseferinde kaydedilmesi gereken 1bytelık 5 adet veri için doğru bir yöntem midir?
Boot flash'da yer alıyor diyor datasheet "2.4 Boot configuration sayfa 69". (http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf (http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf))
Memory will be organised as follows :
0x0800 0000 - 0x0800 2FFF (page 0 to page 5 of STM32F103RD) will be used or bootloader code.
0x0800 3000 - 0x0803 FFFF (page 6 to page 127) can be used for user's application code.
0x0804 0000 - 0x0805 FFFF (page 128 to page 191) will be used to store image recieved from Coordinator
detayları linkte:
http://www.cse.hcmut.edu.vn/~bvhieu/index.php/student-s-projects/computer-engineering-projects-fall-2013/23-home-automation-remote-reprogramming (http://www.cse.hcmut.edu.vn/~bvhieu/index.php/student-s-projects/computer-engineering-projects-fall-2013/23-home-automation-remote-reprogramming)
mesaj birleştirme:: 12 Mayıs 2014, 17:34:38
Alıntı yapılan: pathetic - 06 Mayıs 2014, 15:35:55
STM32f103 için bu şekilde veya emulated eeprom ile veri saklamanın bir sınırı var mıdır (yazma silme açısından) ?
Gün içinde 10larca kez değişecek ve herseferinde kaydedilmesi gereken 1bytelık 5 adet veri için doğru bir yöntem midir?
Bir kaç milyon kez yazılıp silinebilir datasheet'te bununla ilgili detay olması lazım. Ben dediğin yöntemi uzun zamandır kullanıyorum.
Alıntı yapılan: pathetic - 06 Mayıs 2014, 15:35:55
STM32f103 için bu şekilde veya emulated eeprom ile veri saklamanın bir sınırı var mıdır (yazma silme açısından) ?
Gün içinde 10larca kez değişecek ve herseferinde kaydedilmesi gereken 1bytelık 5 adet veri için doğru bir yöntem midir?
STM32F103 silme-yazma ömrü yanlış hatırlamıyorsam 100000 civarında.
eeprom emülasyon kodları 16 bit çalışıyor. her word iin bir de sanal adres bilgisi yazılıyor. toplamda 32 bit.
5 adet veriniz olduğuna göre 20 byte yer işgal edecekler. her biri 1k ( isterseniz daha da büyütebilirsiniz) olmak üzere 2 sayfa kullanıyoruz. toplamda 2k. her rayfaya yaklaşık 50 kez veri aydettiğinizde sayfayı silmeniz gerekiyor. 2 sayfa olduğu için 100 kez veri kaydedebilirsiniz. Flash ömrünün 100.000 olduğunu varsayarsak, 10M kez 5 byte veri yazabilirsiniz.
Programı biraz düzenleyerek bu sayıyı 2 katına , hatta biraz da akıllı bir algoritma kurarak bir kaç katına çıkarabilirsiniz.
Alıntı yapılan: singleiron - 12 Mayıs 2014, 17:32:55
mesaj birleştirme:: 13 Mayıs 2014, 07:34:38
Bir kaç milyon kez yazılıp silinebilir datasheet'te bununla ilgili detay olması lazım. Ben dediğin yöntemi uzun zamandır kullanıyorum.
Alıntı yapılan: Klein - 12 Mayıs 2014, 18:31:55
STM32F103 silme-yazma ömrü yanlış hatırlamıyorsam 100000 civarında.
eeprom emülasyon kodları 16 bit çalışıyor. her word iin bir de sanal adres bilgisi yazılıyor. toplamda 32 bit.
5 adet veriniz olduğuna göre 20 byte yer işgal edecekler. her biri 1k ( isterseniz daha da büyütebilirsiniz) olmak üzere 2 sayfa kullanıyoruz. toplamda 2k. her rayfaya yaklaşık 50 kez veri aydettiğinizde sayfayı silmeniz gerekiyor. 2 sayfa olduğu için 100 kez veri kaydedebilirsiniz. Flash ömrünün 100.000 olduğunu varsayarsak, 10M kez 5 byte veri yazabilirsiniz.
Programı biraz düzenleyerek bu sayıyı 2 katına , hatta biraz da akıllı bir algoritma kurarak bir kaç katına çıkarabilirsiniz.
Cevaplar için teşekkür ederim.
Peki "FLASH_Unlock();" dedikten sonra kullanım yapıyorum sorunsuz ama tekrar lock gerekli mi? Bu neyi sağlıyor?
Hexi PIC'deki gibi kod korumaya almak için ne yapılmalı? (Programlayıcım st link v2)
Hex oluştuktan sonra memory durum detayını nereden görebilirim? ARM'daki adresleme kısmını çok iyi anlayamadığım için ve birkaç glcd animasyonu koyduğum için adresler çakışsın istemiyorum. Boş sayfalar ve byteları ayarlayabilmek için gerekli olacak.
Not:
Mevcut durumda target ayarlarım IROM 0x8000000 0x10000 IRAM 0x20000000 0x5000
Eeprom değişkenlerim için kullandığım tablom const uint16_t VirtAddVarTab[] = { 0x5500, 0x5501, 0x5502, 0x5503, 0x5504, 0x5505, 0x5506, 0x5507}
Boş bir adrese veri yazarken sıkıntı yok ama içi boş olmayan yani 0xFFFF olmayan bir adrese veri yazmak için öncelikle erase işlemi yapmak gerekiyor.
FLASH_EraseSector(FLASH_Sector_2, VoltageRange_3);
gibi fonksiyonlarla silmeye çalıştığım zaman o fonksiyondan çıkamıyor(kilitliyor)
Bu fonksiyonda ise
void Erase_Flash (uint32_t adr)
{
FLASH->CR|=0x00000002; //PER enable
FLASH->AR=adr; //FLASH->AR registerine silinmek istenen adres yazılır
FLASH->CR|=0x00000040; //STRT anable
while((FLASH->SR&0x00000001)); //İşlem bitene kadar bekle(BUSY kontrol ediliyor)
FLASH->CR &= ~0x00000042; //FLASH->CR ilk durumuna alınıyor (kilit hala açık!)
}
FLASH->AR registerini tanımıyor, bu yüzden kullanamıyorum.
İstediğim adresi nasıl silebilirim?
Not: stm32f407 kullanıyorum
hocam flash hafızayı sektor olarak silebilirsin eeprom gibi byte olarak silinemiyor. Her sektör 256 byte dan oluşuyor öncelikle bir sektörü gözünüze kesitirip programın flash hafızasından yalıtmanız lazım bu yüzden kitlenmeler olabilir bunun için scatter file üzerinde adresleme gerekir.
Bu sektöre veri silmek yada daha önce kullandığınız bir alana bir word veri yazmak için o sektörü komple ram e yükleyin sonra silin sonra ramde düzeltme yapıp geri yükleyin. En genel kullanımı bu şekilde.
iyi çalışmalar.
Şuna da dikkat etmek gerek her MCU için flash sektör büyüklüğü 256 byte olmayabilir. Zira 2K sektöre sahip STM32 lerde mevcut. Bu gibi durumlarda "Flash Programming Guide" dökümanlarını okumak faydalı olur.
Sorunu düzelttim. Kilitlenmesinin sebebi, işlem bitmeden devam etmemmiş. Çünkü gözle görülür bir zaman alıyor, yaklaşık 0,5 - 1 saniye while'da bekletiyor.
FLASH_Status sildinmi;
sildinmi = FLASH_EraseSector(FLASH_Sector_2, VoltageRange_3);
while(sildinmi != FLASH_COMPLETE){} //silene kadar bekle
Bu işlem ne kadar sağlıklı bilmiyorum. Silme fonksiyonu yazıp, gönderilen adresin hangi sektöre denk geliyor bunu bulup, dediğiniz gibi sektörü ram'a alıp, sektörü silip, verileri düzenleyip sektörü tekrar kaydetme işlemi yapacağım.
Bu kadar zaman alması normal mi?
Normalde sektör silme işlemi cortex M3 işlemci için yaklaşık 7.5ms sürüyor. Burak hocamın da dediği gibi farklı işlemcide zamanlar ve komutlar değişebilir. M4 hiç kullanmadım.
iyi çalışmalar.
STM32F4 için flash programlama zamanlarını buldum ölçtüğünüz süreler normal gözüküyor.
(http://www.resimupload.net.tr/?di=6Z0B)
Alıntı Yap
Hex oluştuktan sonra memory durum detayını nereden görebilirim? ARM'daki adresleme kısmını çok iyi anlayamadığım için ve birkaç glcd animasyonu koyduğum için adresler çakışsın istemiyorum. Boş sayfalar ve byteları ayarlayabilmek için gerekli olacak.
St Toolset ierisinde ST-Link utiliyt var. onunla yapabilirsiniz.
meftun ben eeprom emulator örneğindeki algoitmayı kullanmanı şiddetle öneririm. Çok özel veri kaydetme işleri olmadığı sürece, parametre kaydetme için bence en uygun yöntem.
Flashla ilgili aklıma takılan birkaç şey var.Benim bir ana programım var ve ben gelen dataları tektek flasha yazmak ve bu flasha yazdıgım koddan baslamasını istiyorum programımın bunu nasıl yapabilirim. Yada şu şekilde sorayım ben system memorye program saklayabilirmiyim ve bunu işletebilirmiyim.istediğim zamanda main flash memory belleğini kullanabilirmiyim?
Yaparsın hocam;
Harici yazılımış bootloader yazılımları buna örnek olabilir. Ana programın dışında birde bootloaderın çalışması için kod yazıp hangisini çalıştırmak istiyorsan onun start vektorüne göndermen yetiyor. Eminim daha doyurucu bilgiler vardır üstadların fakat ben stm8'de dediğim gibi yaptım. STM32'dede section açma şekilde yapılıyor olsa gerek.
#if defined(BOOT_FROM_BANK1)
/* Set the vector table to the Bank1 start address */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, BANK1_START_ADDRESS);
#elif defined(BOOT_FROM_BANK2)
/* Set the vector table to the Bank1 start address */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, BANK2_START_ADDRESS);
#endif /* BOOT_FROM_BANK1 */
bir ornekte şu şekilde göstermiş ama ön işlemci komutlarıyla bunu program çalışırken nasıl yapabiliriz ki?
Kodda yanlış anlamadıysam vektör tablosunu kaydırmak bahsediyor. Yazılımların ayrı olması lazım sizin örneğinizde. Bu verdiğiniz kodlarda ön işlemci kodları ile kaydırma yapmış sadece diye görüyorum. Ayrı ayrı 2 software olması gerekiyor bence.
ben biraz araştırayım hocam eğer sizde örneğe anlatıma filan denk gelirseniz burda paylaşırsanız sevinirim.
mesaj birleştirme:: 21 Mayıs 2015, 15:14:50
bişeler buldum
http://www.st.com/web/en/catalog/tools/FM147/CL1794/SC961/SS1743/LN1734/PF257844 (http://www.st.com/web/en/catalog/tools/FM147/CL1794/SC961/SS1743/LN1734/PF257844)
Merhabalar; belki konuyu hortlatmış olacağım ama lazım olan birisi okursa işine yarayabilir. hem o
cagri_dinc ' e paylaşmış olduğu kod için teşekkür ederim öncelikle.
Flash hafızaya yazacağız ama ya yazdığımız yerde program kodları varsa. evet kesinlikle bu mümkün bu yüzden önlem almalısınız. bunun için benim kullandığım ve önerdiğim yöntem şudur.
const uint8_t My_Page[1024] @ 0x0800F000;
öncelikle yukarıda olduğu gibi bir değişken tanımlaması yaparsanız derleyici My_Page adında 1kbyte'lık bir bölümü sizin için ayırır ve buraya kod yazmaz. eğer kullandığınız derleyicinin flash sayfaları 2Kb is o zaman 2048byte uzunluğunda bir değişken tanımlayın.
bu değişkeni ekledikten sonra derleyicilerin %90'nı bu değişken yokmuş gibi davranır (optimizasyon) bunun önüne geçmek için program içinde
"0x0800F000" kullanmak yerine doğrudan "My_Page" ismini kullanın böylece derleyici sizin bu değişken alanını gerçekten kullandığınızı anlar ve bu kısmı boş bırakır.
*Düzeltme:
eğer;
const uint8_t My_Page[1024] @ 0x0800F000 ="ali-veli";
şeklinde bir atama yaparsanız bu sefer derleyici yine 9 byte'lık bir alan ayıracaktır. 1024 byte yalan olur yani. bu şekilde yapmayın.
tabi unutmamalı ki değer yazma ve okuma işlemlerini program içindeyken My_Page[n] şeklinde değil. flash okuma ve yazma fonksiyonları üzerinden yapmalıyız.
STM32 serisinde medium-density yada high-density gibi ürün grupları var her ürün grubunun sayfa büyüklüğü değişken. bunu işlemcinizin manualında bulabilirsiniz. cagri arkadaşımızın dediği gibi en son page'e veri yazmamak lazım. en sondan 1 önceki page'dan geriye doğru istediğiniz kadar page adresleyebilirsiniz yukarıda olduğu gibi.
seçtiğimiz adres mutlaka bir page'nin başlangıcı olmalı. :)
Benim kullandığım işlemci 64kb hafızaya sahip 1kb lık sayfaları olduğundan ben 60.kb'dan itibaren 1kb yer ayırıp kullandım.
(http://s14.postimg.cc/99bck8nrh/image.jpg) (http://postimg.cc/image/99bck8nrh/)
(https://s30.postimg.cc/t8g1db7ct/MAP.png) (https://postimg.cc/image/t8g1db7ct/)
EDİT : Aşağıdaki kod ile bir adrese veri yazıyorum, kalıcı olarak duruyor, ama daha sonra while döngüsü içinde buton ile 2 byte fazlası adrese veri yazmak istediğimde önceki yazdığım veri siliniyor, veritabanı gibi kullanmak istiyorum, nasıl düzeltebilirim?
int main()
{
uint32_t add=0x0801F002; //Bir adres seçtim
HAL_FLASH_Unlock(); //Flash kilidimi açıyorum
Erase_Flash(add); //Adres dolu olsada olmasada sil
HAL_FLASH_Program(TYPEPROGRAM_HALFWORD,add,1); //belirttiğim adrese 1 yazıyorum
HAL_FLASH_Lock(); //Flash kilidimi kapatıyorum
while(1)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==1)
{
HAL_Delay(250);
HAL_FLASH_Unlock();
Erase_Flash(add+2);
HAL_FLASH_Program(TYPEPROGRAM_HALFWORD,add+2,1);
HAL_FLASH_Lock();
}
}
}
void Erase_Flash (uint32_t adr)
{
FLASH->CR|=0x00000002;
FLASH->AR=adr;
FLASH->CR|=0x00000040;
while((FLASH->SR&0x00000001)); //Islem bitene kadar bekle
FLASH->CR &= ~0x00000042;
}
Merhabalar,
Hocam,"Erase_Flash(add+2);" dediğin zaman page komple siliniyor, bu yüzden eski yazdığın gidiyor. Bende bu durum ile cebelleşiyorum şuan. Sayfanın tamamını silmeden kayıtlı veriyi özgürce değiştirmenin bir yolu yordamı yok mu?
https://www.picproje.org/index.php/topic,68820.0.html
stm32 de hafızaya yazma okuma yaparken interrupt durma gibi bir durumla karşılaşıyor musunuz? kullandığım işlemci stm32f103
Alıntı yapılan: deneme_1234 - 01 Mart 2017, 16:34:21
stm32 de hafızaya yazma okuma yaparken interrupt durma gibi bir durumla karşılaşıyor musunuz? kullandığım işlemci stm32f103
Ben karşılaşıyorum, evet. Örneğin 4x3 7segment display tararken flash a yazma yaptığımda önce tüm page i silmek zorunda olduğum için bir süre kesinti oluyor. Bu esnada ne oluyor tam bilmiyorum. Bu yüzden direk yazma yerine St nin EEPROM Emulation örneğindeki driverlerı kullanıyorum. Orada iki page i yedekli olarak kullanıyor. Ve her yazdığınız veriyi sanal bir adres ile birlikte yazdığınız için her seferinde tüm page i silmek zorunda kalmıyorsunuz. Page dolduğunuda diğer page e geçip önceki siliniyor. Silinmeden önce de eski page teki son veriler yeni page in başına kopyalanıyor. Güzel bir algoritması var. Tavsiye ederim.Kesintiyi engellemiyor ama sadece page geçişlerinde olduğu için hissedilmiyor.
Peki eeprom yazma bölümünü RAM ya da ROM'a taşımak fark yaratıyor mu?
Selamlar.Bir sorum var.
St'nin yayınladığı emulator kullanarak dahili flash alanını kullansam, 32 bit bazı değişkenleri nasıl saklarım?İkiye bölmeden yapabilir miyim?
Emulatorde 32 bit bir alanın 16bit data 16bit Virtual address olarak kullanılıyor. Ancak ben elimdeki 32bit datayı bölmeden saklayamaz mıyım?
32 biti 2 adet 16 bite çevirip öyle yazıyoruz.dahili hafıza blokları 16 bit. okurken 16 bitleri birleştiriyoruz.
hello mr enr
Alıntı yapılan: enrique_iglesias - 11 Şubat 2017, 21:44:19
(https://s30.postimg.cc/t8g1db7ct/MAP.png) (https://postimg.cc/image/t8g1db7ct/)
EDİT : Aşağıdaki kod ile bir adrese veri yazıyorum, kalıcı olarak duruyor, ama daha sonra while döngüsü içinde buton ile 2 byte fazlası adrese veri yazmak istediğimde önceki yazdığım veri siliniyor, veritabanı gibi kullanmak istiyorum, nasıl düzeltebilirim?
int main()
{
uint32_t add=0x0801F002; //Bir adres seçtim
HAL_FLASH_Unlock(); //Flash kilidimi açıyorum
Erase_Flash(add); //Adres dolu olsada olmasada sil
HAL_FLASH_Program(TYPEPROGRAM_HALFWORD,add,1); //belirttiğim adrese 1 yazıyorum
HAL_FLASH_Lock(); //Flash kilidimi kapatıyorum
while(1)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==1)
{
HAL_Delay(250);
HAL_FLASH_Unlock();
Erase_Flash(add+2);
HAL_FLASH_Program(TYPEPROGRAM_HALFWORD,add+2,1);
HAL_FLASH_Lock();
}
}
}
void Erase_Flash (uint32_t adr)
{
FLASH->CR|=0x00000002;
FLASH->AR=adr;
FLASH->CR|=0x00000040;
while((FLASH->SR&0x00000001)); //Islem bitene kadar bekle
FLASH->CR &= ~0x00000042;
}
mr enrike did yu find solution for flash writing using HAL functions ???plz can you share with us thanks
Arkadaşlar Merhaba,
Yeni konu açmak istemedim flash ile ilgili bir problem yaşıyorum kullandığım işlemci stm32f103 flashı silebiliyorum fakat veri yazamıyorum kullandığım yazılım konunun başındakiyle aynı adrese kadar aynı kullanıyorum veri yazamıyorum başka bir ayrıntı varmı yapmamız gereken mesela hex i cip e atarken ?
@görkem Kod paylaşırsan yardımcı olabiliriz
Sadece işlemin olduğu kısmı yollaman yeterli.
@baran123 Bulunan adresteki page i sildiğimde page in komple FF olduğunu görüyorum fakat veri yazamıyorum.
#include "main.h"
#include "stm32f1xx_hal.h"
/* USER CODE BEGIN Includes */
#include "stm32f1xx_hal_flash.h"
#include "stm32f1xx_hal_flash_ex.h"
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
uint32_t adres;
uint16_t data,read_data=0;
uint8_t error_unlock,error_lock,error_write;
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
void Unlock_Flash(void)
{
FLASH->KEYR=0x45670123;
FLASH->KEYR=0xCDEF89AB;
}
void Lock_Flash(void)
{
FLASH->CR=0x00000080;
}
void Erase_Flash(uint32_t adr)
{
FLASH->CR|=0x00000002;
FLASH->AR=adr;
FLASH->CR|=0x00000040;
while((FLASH->SR&0x00000001));
FLASH->CR &= ~0x00000042;
}
void Write_Flash(uint32_t adr, uint16_t data)
{
FLASH->CR|=0x00000001;
*(__IO uint16_t*)adr = data;
while((FLASH->SR&0x00000001));
}
uint16_t Read_Flash(uint32_t adr)
{
uint16_t * Pntr = (uint16_t *)adr;
return(*Pntr);
}
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
adres=0x0801F800;
data=0xCDAE;
Unlock_Flash();
Erase_Flash(adres);
Write_Flash(adres,data);
Lock_Flash();
read_data=Read_Flash(0x0801F800);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
HAL_Delay(250);
}
/* USER CODE END 3 */
}
@görkem HAL bilmiyorum ama neden register ile yapıyorsun HAL da fonksiyonlar yok mu ?
Ben SPL ile STM32F4 için şöyle yapmıştım.
#define FLASH_READ_BYTE(ADDR) (*(__IO uint8_t *)ADDR)
#define FLASH_READ_HALFWORD(ADDR) (*(__IO uint16_t*)ADDR)
#define FLASH_READ_WORD(ADDR) (*(__IO uint32_t*)ADDR)
#define FLASH_READ_DOUBLEWORD(ADDR) (*(__IO uint64_t*)ADDR) //__IO = volatile
/*
Önce sil ve diğer verileri yedek.
*/
uint32_t Flash_WriteWithCheck(uint32_t addr, uint32_t data)
{
uint32_t status = 0; // 0 error 1 ok
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR);
FLASH_ClearFlag(FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
if(FLASH_ProgramWord(addr, data) == FLASH_COMPLETE)
{
if(FLASH_READ_WORD(addr) == data)
status = 1
else
status = 0;
}
else
status = 0;
FLASH_Lock();
return (status);
}
@baran123 Fonksiyonlarla stm32f4 de yazabiliyorum fakat stm32f103 de ne register nede hal fonksiyonlarıyla yazamadım silmesine siliyor fakat yazmıyor atladığım birşey mi var diye danışmak istedim
F0'da şöyle birşey yapmıştım :
HAL_FLASH_Unlock();
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, adres, inputBuffer);
HAL_FLASH_Lock();
@erpay onu denemiştim veri yazmıyor.
programlayıcı olarak stm32f4 discovery kitini kullanıyorum o yüzden mi oluyor acaba ? stm32f4 için yaptığımda silip yazıp okuyabiliyorum
Silip yazmaması ilginç kesin kodlarda bi hata vardır.
Aşağıdaki kod stm32f103 için dikkat edersen her yere volatile yazmışım çünkü derleyici (iar) optimize edeyim derken bizim kodları
siliyor kullanmıyor senin de böyle bir sorunun olabilir. Bu adrese yazıyor 0x8001000.
uint8_t ibox[]="ibox654654321";
uint32_t yazmem=0x8001000;
*((volatile uint32_t*) 0x40022004)=0x45670123; ////FLASH_KEYR key1 açılış şifresi
*((volatile uint32_t*) 0x40022004)=0xCDEF89AB; ////FLASH_KEYR key1
*((volatile uint32_t*) 0x40022010)=0x02; ////FLASH_CR page silime modu
*((volatile uint32_t*) 0x40022014)=yazmem; ////FLASH_AR page baş adres
*((volatile uint32_t*) 0x40022010)^=0x40; ////FLASH_CR tamam sil
*((volatile uint32_t*) 0x40022010)=0x01; ////FLASH_CR page yazma modu
uint16_t *mem=(uint16_t *) ibox;
while( (*((volatile uint32_t*) 0x4002200C)&1)); ///////FLASH_SR wait busy
for(uint32_t syc=0;syc<(sizeof(ibox)/2);syc++)
{
*((volatile uint16_t*) yazmem)=mem[syc];
yazmem+=2;
while((*((volatile uint32_t*) 0x4002200C)&1)); ///////FLASH_SR wait busy
}
*((volatile uint32_t*) 0x40022010)=0x0;
HAL_FLASH_Program sana ne dönüyor ? Debug ile girip denedin mi ?
@erpay debug ile bakıyorum 0 bilgisi dönüyor error kodu ile dönmüyor.
@iboibo volatile ile deneyeceğim birde.
yazmaya korumalı olabilir mi ?
Farklı bir pagede dene. Bir de yazıp yazmadığını st-link ile de kontrol etsene program içinde okuma yanında.
@erpay Kullandığım fonksiyonlar aşağıdaki şekilde. St-link ile baktığımda da adres değeri FF olarak okunuyor.
void sil(uint32_t ft)
{
HAL_FLASH_Unlock();//unlock flash writing
FLASH_PageErase(ft);
HAL_FLASH_Lock();
}
void flash_kayit(uint32_t adres,uint16_t dat)
{
HAL_FLASH_Unlock();
ok=HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,adres,dat);
HAL_FLASH_Lock();
}
sil(0x8010000);
flash_kayit(0x8010000,1);
(https://s18.postimg.cc/a26tny59x/flash.png) (https://postimg.cc/image/a26tny59x/)
ok=HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,adres,dat);
Burada hafword 16 bitlik bir veriden bahsediyor ama sen 8 bit yazmaya çalışıyosun belki bu bir problem oluşturabilir.
Onun yerine şöyle birşey dene bakalım:
HAL_FLASH_Unlock();
adres = 0x8010000
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, adres, adres);
HAL_FLASH_Lock();
@erpay o şekilde de denedim yazmıyor st-link ten baktım adreslerde korumada yok.
Cubemx'de F1 için kullandığın kütüphanede bir sorun olabilir onu güncelleyip yeniden oluşturmayı da dene istersen.
@erpay silme fonksiyonunu yazılımdan kaldırdığımda yazma yapabiliyor fakat fonksiyonu eklediğimde yazma yapmıyor.
not: değişkene volatile ekleyince yazmaya başladı. Silme fonksiyon sorunu devam ediyor.
sorun çözüldü hal kütüphanesinde sorun var FLASH->CR register ında page erase biti sürekli 1 de kalıyormuş yazarken sıfırlamak gerekiyor.
Eğer yazdığınız page'yi okumuyorsa derleyicinin optimizasyonunu kapatırsanız sorun çözülebilir çünkü bende aynı sorunla karşılaştım.
Yazılmayan sektör kısımları 0xFF olarak okunacaktır.
Merhabalar,
Ben de bu kodlarla yazıp siliyordum problem yoktu. kodlar artmaya başladıkça yazmamaya başladı. şimdi programın başına bir sonsuz döngü ekleyip yazıp sildiğimde program boyutu küçülüyor ve yazmaya okumaya başlıyor. ama gerçek programı aktif ettiğimde yazma silme yapmıyor.
işlemcim 32f103vct6 0x0803f000 adresinden başlatıyorum.
Benim kodum ne kadar tutuyor neresi boş hangi adrese yazmalıyım bi babayiğit açıklayabilir mi?
Alıntı yapılan: izturk - 27 Eylül 2018, 17:09:26Merhabalar,
Ben de bu kodlarla yazıp siliyordum problem yoktu. kodlar artmaya başladıkça yazmamaya başladı. şimdi programın başına bir sonsuz döngü ekleyip yazıp sildiğimde program boyutu küçülüyor ve yazmaya okumaya başlıyor. ama gerçek programı aktif ettiğimde yazma silme yapmıyor.
işlemcim 32f103vct6 0x0803f000 adresinden başlatıyorum.
Benim kodum ne kadar tutuyor neresi boş hangi adrese yazmalıyım bi babayiğit açıklayabilir mi?
hocam asıl program bloğu nerede bitiyor ona baktınız mı? yani sizin program bloğunuz 0x0803f200 de bitiyor ve siz 0x0803f000 dan yazıp silmeye başlıyorsanız kendi program bloğunuzu siliyorsunuz demektir bu da programınızı kullanlılmaz hale getirir.
2. bir durum da
FLASH-zAR register'ına yazdığınız adres page yapınız 1kb ise 1024, 2kb ise 2048 in katları olarak artmlaı.
aynı page içinde farklı adreslerden silme yapmaya çalıştığında 10-15 erase işleminden sonra çakılıyor. neden olduğunu bilmiyorum fakat başıma geldi ve bu şekilde çözdüm.