Boot Loader Yazmaya calışıyoruz.

Furkan KELEŞOĞLU

Kayıtlı Üye
Evet bugün Boot Loaderin ilk denemelerini attım. ( sadece gömülü sistem kısmı için)

Sonuç ? Hüsran :D


C:
// CONFIG1H
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 18        // Brown Out Reset Voltage bits (VBOR set to 1.8 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC   // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON      // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config HFOFST = ON      // HFINTOSC Fast Start-up (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection Block 0 (Block 0 (000800-003FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection Block 1 (Block 1 (004000-007FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection Block 2 (Block 2 (008000-00BFFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection Block 3 (Block 3 (00C000-00FFFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection Block 0 (Block 0 (000800-003FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection Block 1 (Block 1 (004000-007FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection Block 2 (Block 2 (008000-00BFFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection Block 3 (Block 3 (00C000h-00FFFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection Block 0 (Block 0 (000800-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection Block 1 (Block 1 (004000-007FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection Block 2 (Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection Block 3 (Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)


#define _XTAL_FREQ 4000000
#include <xc.h>
#include <stdint.h>
#define FLASH_HAFIZA_BASLANGIC 0x00001000
/////////// GLOBAL DEGISKEN TANIMLAMALARI /////////////
uint8_t string[20]="FURKANKELESOGLU";
/////////////  GLOBAL FONKSIYON TANIMLAMALARI ////////////////
void FLASH_HAFIZA_ADRES_KUR(uint32_t adres);
void KESMELERI_KAPAT(void);
void KESMELERI_AC(void);
void FLASH_HAFIZAYI_SIL(void);
void FLASH_HAFIZAYA_YAZ(void);
void FLASH_HAFIZAYA_VERI_YUKLE(uint8_t* data , uint8_t uzunluk);



void FLASH_HAFIZAYA_VERI_YUKLE(uint8_t* data , uint8_t uzunluk)
{
    // BU FONKSIYON HOLDING REGISTERINE DATALARI YAZAR.
    uint8_t counter = 0x00;
   
    for(counter = 0x00 ; counter < uzunluk ; counter++)
    {
        TABLAT = data[counter]; // DATA ARRAYINDAN COUNTER DEGERI KADAR ILERLE VE ILERLERDIGIN VERIYI TABLAT'A YAZ (HOLDING REGISTERINE BAK).
        asm("TBLWT*+"); // TABLOYA YAZ SONRA TABLO POINTERI 1 ARTTIR.
    }
   
   
}
void FLASH_HAFIZA_ADRES_KUR(uint32_t adres)
{
        // BU FONKSIYON VERILEN ADRESI TABLET POINTERE BAYTLARA AYIRARAK YUKLER. VE SET EDER.
    TBLPTRU = (adres & 0xFF0000) >> 16;  // ADRESIN UPPER KISMINI YUKLE
    TBLPTRH = (adres & 0xFF00) >> 8;  // ADRESIN HIGH KISMINI YUKLE
    TBLPTRL = (adres & 0xFF); // ADRESİN LOW KISMINI YUKLE
}

void FLASH_HAFIZAYI_SIL(void)
{
    EECON1bits.EEPGD = 1;
    EECON1bits.CFGS  = 0;
    EECON1bits.WREN  = 1;
    EECON1bits.FREE  = 1;
    KESMELERI_KAPAT(); // KESMELERIN HEPSİNİ KAPAT CPU'YU RAHATSIZ ETMESIN.
    EECON2 = 0x55;  // EECON2 YE 0x55 YUKLE YETKI VER
    EECON2 = 0xAA;  // EECON2 YE 0xAA YUKLE YETKI VER
    EECON1bits.WR = 1;  // CPU SIMDI STALL MODA GECICEK YAKLASIK 2 MS DAHILI BIR KESME KURUCAK CPU , BENLE ALAKASI YOK
    KESMELERI_AC(); // CPU STALL MODDAN CIKINCA KESMELERI AC
     
}

void FLASH_HAFIZAYA_YAZ(void)
{
    EECON1bits.EEPGD = 1;  // FLASH PROGRAM HAFIZANA ERISIMI AC.
    EECON1bits.CFGS  = 0; // FLASH PROGRAM HAFIZASINI SEC. ( 1 OLUR İSE CONFIGRATION REGISTERINE ERISIM ACILIR ).
    EECON1bits.WREN  = 1; // PROGRAM FLASHINA YAZMAYI ETKINLESTIR.
    KESMELERI_KAPAT(); // TUM KESMELERI KAPAT.
    EECON2 = 0x55; // FLASH HAFIZA ISLEMLERI ICIN ISTEKTE BULUN VE ETKINLESTIR.
    EECON2 = 0xAA; // FLASH HAFIZA ISLEMLERI ICIN ISTEKTE BULUN VE ETKINLESTIR.
    EECON1bits.WREN = 1; // YAZMAYI ICIN CPU YA CYCLE VER YANI YAZMAYI YAPMASI ICIN YOL VER ISLEMCIYE.
    // CPU SUAN STALL MODUNA GECTI DAHILI TIMER KURDU YAKLASIK 2MS SURECEK
    KESMELERI_AC(); // CPU STALL MODDAN CIKINCA KESMELERI AC. ( STALL MOD : ISLEMCININ HIC BIRSEYE YANIT VERMEDIGI ZAMANDIR).  
}

void KESMELERI_KAPAT(void)
{
    INTCONbits.GIE  = 0;  // KESMELERI KAPAT.
    INTCONbits.GIEH = 0;  // YUKSEK SEVIYELI KESMEYI KAPAT.
    INTCONbits.GIEL = 0;  // DUSUK SEVIYELI KESMEYI KAPAT.
    INTCONbits.PEIE = 0;  // CEVRESEL KESMELERI KAPAT.
}

void KESMELERI_AC(void)
{
    INTCONbits.GIE  = 1;  // KESMELERI AC.
    INTCONbits.GIEH = 1;  // YUKSEK SEVIYELI KESMEYI AC.
    INTCONbits.GIEL =  1;  // DUSUK SEVIYELI KESMEYI AC.
    INTCONbits.PEIE = 1;  // CEVRESEL KESMELERI AC.
   
}



void main(void) {
    FLASH_HAFIZA_ADRES_KUR(FLASH_HAFIZA_BASLANGIC);
    NOP();
    NOP();
    FLASH_HAFIZAYA_VERI_YUKLE(string,20);
    NOP();
    NOP();
    FLASH_HAFIZAYA_YAZ();
    NOP();
    NOP();
    while(1)
    {
        // SONSUZ DONGU BLOGU.
    }
}

Araştırabildiğim kadar araştırdım. bunun sonucunda ortaya böyle bir yazılım cıkarttım. bu kodda ki amaç ise belirlediğim adresten itibaren FURKAN KELESOGLU yazması idi. Kodu pice yükledim daha sonra bread board'da pici calıştırdım biraz bekledim. sonra enerjiyi kestim pici progralayıcı takıyıp okudum normalde yazma adresi gösterdiğim yerden itibaren FURKANKELESOGLU karakterleri yazması gerekirken hiç bir şey yazmamış.

Screenshot_3.png



Neyse İlk başlangıcımızı yaptık :D zaten saat 4:45 sabah olacak benim beyinde offline konuma geçmeye başladı :D yarın devam edeceğim artık. öneri ve görüşlerinize açığım bu arada. o yüzden buraya koyuyorum ki hem bunu yaparken geçirdiğimiz aşamaları herkes görsün. ve varsa yanlış veya eksik bir şey sizlerin öneri ve görüşleriyle düzeltilmesi için.
 

taydin

Timur Aydın
Staff member
Flash bölgesine programlayıcıyı kullanarak birşeyler yaz ve o bölgeyi silecek bir kod geliştir önce. En basitten karmaşığa gitmek daha iyi.

Eğer silmeyi başarırsan, bir sonraki aşama yazmak :)
 

Furkan KELEŞOĞLU

Kayıtlı Üye
ULAN BU KADAR İŞTE BEEE... :D Yazdık yazdık :DDD

Screenshot_4.png



hexi yükledim pice biraz calıştırdım zaten yazma bitince sonsuz döngü bloğunda led için blink attırdım. blinki görünce yani yazma işlemi bitti demektir. enerjiyi kesip programlayıca takıyıp okudum vee sonuccc :D verdiğim adresten itibaren Little endian formatında yazmış :D

Şimdi dershaneye gideceğim. gelince UART donanımını yazıp. bu sefer UART üzerinden aldığı veriye göre adresi yazdıracağım sonra sildirme komutu yollayıp sildireceğim. Bu işin suyunu iyice sıkıp cıkaracağız herşeyin doğru calıştığına emin olduktan sonra güzel bir boot kodu yazıp. daha sonra arayüz için uğraşmaya başlayacağız.
 
Son düzenleme:

Furkan KELEŞOĞLU

Kayıtlı Üye
Evet silme işide baraşılı oldu :D zaten yazdığını test etmiştik programa bir sorgu ekledim sonsuz döngüde eğer butona basılır ise o adresi silecek komutu verdim. butona bastım ve flash hafızayı silmiş olmalı diyip enerjiyi kesip programlayıcıya takıp okuma yaptım. evet istediğim adresteki veriyi silmiş.

Screenshot_5.png


Şimdi birde flash hafızayı okuyabilmemiz lazım. ama buraya kadar sapa sağlam saçları yontmadan gelebildik :D şimdi yapacağımız işlemlerin sırası şöyle olacak.

1- Pic'in UART donanımını kuracağız. ( yapılandıracağız )
2-PC ve PIC arası haberleşme için bir kaç komut define edeceğiz.
3- UART üzerinden yaz komutu verip peşine adresi onunda peşine yazılacak datayı göndereceğiz.
4-UART üzerinden okuma komutu göndereceğiz peşine okunacak adresi.
5- PIC ten istediğimiz adresi okuyup Terminale basmasını bekleyeceğiz ( eğer başarılı olursa 6. şartı uygulayacağız)
6- PIC'e sil komutu göndereceğiz peşine silinecek adresi göndereceğiz
7- PIC'e oku komutu göndereceğiz peşine okunacak adresi. bu okuduğu datayı UART hattına basacak.

Eğer sildikten sonra okuma yapıp terminalde data görmez isek. herşey başarılı demektir. bundan sonrası ise bu kodumuzu flash hafızanın başlangıc adresine yani 0x0000 adresine gömeceğiz böylelikle boot sektörümüzü oluşturmuş olacağız.

Hele buraya kadar bir gelelim ondan sonrasını bakalım ne yapacağız. :D
 

Furkan KELEŞOĞLU

Kayıtlı Üye
Evettt :D Boot Loader için UART donanımınıda yapılandırdım. Şuan herşey cok güzel calışıyor fakat baya yoruldum. datasheet incelemekten gözlerim pörtledi. birde bread board üstünde deniyorum. yeniden derle pici boarddan cıkar programla tekrar dene et. baya yoruldum.

Ama Şu Terminal ekranı bütün yorgunluğumu aldı :D Tadına varıyoruz. Proje güzel ilerliyor. Projede Şuan BOOT denemesi yapmadık sadece UART donanımını test ettik. yani hem alma hem göndermeyi istediğimiz baud rate içinde gerçekleştirecekmi evet bunu başardık. Ayrietten gönderilen komuta göre ledi yakıp kapatma gibi bir fonksiyon daha yazdım. test için kısacası UART library testten başarılı şekilde geçti. Şimdi Boot Loader için BOOT library si yazıcam. bizim PIC18F46K20 64 byte silme ve yazma yapabiliyor. RAMDE 64 byte lık bir array oluşturacağız plan bu gelen veriyi buraya alacağız. RAM'e aldığımız veriyi flasha yazıcaz. gerçi buralar biraz teori proje ilerledikçe ne olacağını göreceğiz HOST to PIC için ise bir struct oluşturacağım. ve Komut seti hazırlayacağım. bakalım buralara kadar geldik.

Screenshot_2.png

RAM VE ROM(Program Flash Hafızası) Dikkate almayın. şuanlık denemelerde olduğumuz için biraz yüksek kullanım oranına sahip. zaten şu texti bastırmak için ram'den yemek zorundaydık. herşey başarılı olunca program üzerinde bir optimizasyona gideceğim. hedefimiz ram ve romun sadece %1 ini kullanması. mümkün olduğunca bu değerlerde kalmaya calışacağız.


Konuyu Takip Eden arkadaşlar var ise yorumlarını almak istiyorum. Katılın konuya çekinmeyin. Burada ARGE yapıyoruz bir ürün geliştiriyoruz.:rolleyes:
 

Furkan KELEŞOĞLU

Kayıtlı Üye
Değiştirmemiz gereken bazı şeyler var şimdi fark ettim. ilk bunları yapmamız lazım. öncelikle 4 Mhz kristal ile denemeler yapıyorum ama bu MCU PLL ile 64Mhz cıkıyor. ama 16 Mhz kristal olması lazım bende şuan yok , okadar krital var envayi frekansta ama 16 Mhz yok şaşılacak şey yahu :D her neyse yarın 5 tane 16Mhz kristal de alayım. sonra UART'ı varsa başka değişecek yerler yeni Kristal Osilatör değerine göre tekrardan yapılandıracağız.

Bu arada PIC18F46K20 3.6v olmasına rağmen UART protokolünde bir sıkıntı cıkarmadı ben belki cıkarabilir diye düşünmüştüm ama sıkıntısız. gerçi 3.6v Logic 1 seviyesi içerisinde kalıyor. ama ne olur ne olmaz belki buraya logic level convertor tasarlayabiliriz.
 

taydin

Timur Aydın
Staff member
Eline sağlık Furkan, baya ilerleme katetmişsin :) Şu anda hiç boyutunu küçültmeye falan uğraşma bence. Öncelikle tüm işlevi doğru olarak yerine getirsin.
 

taydin

Timur Aydın
Staff member
Bu arada XMODEM, YMODEM, ZMODEM, KERMIT gibi seri bağlantılar üzerinden veri paketi göndermeyi sağlayan standart protokolleri de incelersen hem sana fikir verir, hem de olabilecek problemleri daha olmadan engellemeni sağlar. Hatta belki örneğin ZMODEM desteği eklersin senin boot koda, böylece bu protokolleri destekleyen sayısız hazır programı da kullanma şansın olur.
 

Furkan KELEŞOĞLU

Kayıtlı Üye
Bu arada XMODEM, YMODEM, ZMODEM, KERMIT gibi seri bağlantılar üzerinden veri paketi göndermeyi sağlayan standart protokolleri de incelersen hem sana fikir verir, hem de olabilecek problemleri daha olmadan engellemeni sağlar. Hatta belki örneğin ZMODEM desteği eklersin senin boot koda, böylece bu protokolleri destekleyen sayısız hazır programı da kullanma şansın olur.
Abi bu dediğin protokolleri ilk kez duyuyorum. Araştırmaya başlayacağım bunları. Akşam geleceğim eve boot kısmını bu akşam tamamen bitirmeyi planlıyorum. bakalım ne olacak :D
 

Furkan KELEŞOĞLU

Kayıtlı Üye
Şimdi Hesaba katmadığımız bir sorun cıktı karşımıza gerçi SUYUNU CIKARACAĞIZ bu işin diye demiştik ve öylede yapıcaz.

Şimdi biz YAZMA-SİLME-OKUMA için ilk adres göndermemiz lazım. terminal üzerinden adress gönderiyoruz. buraya kadar tamam ama Terminalden gönderdiğimiz veri ASCII yani biz 2 yazdığımız zaman aslında 2 gitmiyor onun ASCII hexadesimal karşılığı gidiyor.

E biz bir adres verip o adrese veri yazmasını beklersek daha cok bekleriz cünkü alakasız bir adrese yazma yapıcak veyahut TABLE POINTER kafayı yiyecek.

bu yüzden şöyle yapacağız. Terminalden String olarak aldığımız Adres bilgisini. parcalayacağız daha sonra switch-case yapısı kurup gelen karakterin aslında hangi sayı olduğunu return ile geri cevireceğiz. yani burayı nasıl anlatıcam size bilmiyorum. çünkü biraz karışık aslında karışık değilde neyse durun bir yolunu buluruz anlatmanın.

Şimdi return ile veriyi geri döndürdükten sonrada 64 bitlik bir değişken oluşturup gelen return bilgisini buna yükleyip 4 bit sola kaydıracağız veriyi. Böylelikle yaptığımız şey STRING HEXADESIMAL TO HEXADESIMAL gibi bir şey olacak. Bu algoritmanın isminede FURKAN algoritması diyorum :D

Aslında atoi() fonksiyonu var ama bu atoi() kardeş ABCDEF gibi karakterleri gördümü 0 return edeceği için işimize yaramaz. aslında pek araştırmadım belki standart bir fonksiyonu vardır.

Biraz beyin fırtınası yapayım dedim. :D

C:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#define BYTE_4_BIT 4
#define BYTE_8_BIT 8


 unsigned char str[10];
 uint8_t Decode(uint8_t dat);
 uint32_t hesap(uint8_t *str , uint8_t len);
 
 
 
uint32_t hesap(uint8_t *str , uint8_t len)
     {
         uint8_t i=2;
         uint64_t veri = 0;  // 64 BITLIK DEGISKEN .
        
         for(i=2 ; i < len ; i++)  // STRING VERININ 0x KARAKTERINI ALMA ISLEME.
             {
            
                         veri =  (veri | Decode(str[i])) << BYTE_4_BIT;  // KARAKTERI DECODE ET SAYISAL KARSILIGINI VEYA ISLEMINE TABI TUT VE 4 BİT SOLA KAYDIR ( YENI VERI ICIN)
                         printf("veri : %#10X \n",veri);  // DEBUG ICIN YAZDIM BU SATIRI ( VERI OLUSUMUNU GOZLEMLEMEK ICIN)
                
                
                  
              }
              veri = (veri >> BYTE_4_BIT);  // VERININ KALAN KISMINI TEMIZLE
              printf("\nveri son hali : %#8X",veri);
              
              
         return  veri;  // OLSUNA HEXADESİMAL VERIYI RETURN ET.
     }
    
uint8_t Decode(uint8_t dat)     // GELEN KARAKTERLERI DECODE ET.
    {
        uint8_t islenmis = 0x00;
        switch(dat)
            {
                case '0':
                    islenmis = 0x0;
                    break;
                    case (char)'1':
                        islenmis = 0x1;
                        break;
                        case '2':
                            islenmis = 0x2;
                            break;
                            case '3':
                                islenmis = 0x3;
                                break;
                                case '4':
                                    islenmis = 0x4;
                                    break;
                                    case '5':
                                        islenmis = 0x5;
                                        break;
                                        case '6':
                                            islenmis = 0x6;
                                            break;
                                            case '7':
                                                islenmis = 0x7;
                                                break;
                                                case '8':
                                                    islenmis = 0x8;
                                                    break;
                                                    case '9':
                                                        islenmis = 0x9;
                                                        break;
                                                        case 'A':
                                                            islenmis = 0xA;
                                                            break;
                                                            case 'B':
                                                                islenmis = 0xB;
                                                                break;
                                                                case 'C':
                                                                    islenmis = 0xC;
                                                                    break;
                                                                    case 'D':
                                                                        islenmis = 0xD;
                                                                        break;
                                                                        case 'E':
                                                                            islenmis = 0xE;
                                                                            break;
                                                                            case 'F':
                                                                                islenmis = 0xF;
                                                                                break;
            }
            printf("islenmis : :%#2X\n",islenmis);   // KARAKTERLERI DOGRU SEKILDE HEXADESIMAL DECODE EDIYORMU GOSTER.
            return islenmis;   // ISLENEN 8 BIT DEGERI RETURN ET.
            
         }     
    
int main()
{
  
    uint32_t sonuc=0;  // SONUCU GORMEK ICIN 32 BITLIK DEGISKEN.
    
    printf("Enter string: ");
    scanf("%s",str);
    printf("String : %s \n",&str);
    
    
    sonuc = hesap(&str, sizeof(str));
    printf("\n Hexadesimal : %#8X",sonuc);
    printf("\n Hexadesimal to desimal : %u",sonuc);
    
    


    return 0;
}
Screenshot_5.png
 

Furkan KELEŞOĞLU

Kayıtlı Üye
Evet bunu DEVC++'da denedim calıştı. şimdi bunu bir library haline getirip. MPLAB proje dosyamıza ekleyeceğiz ve bir aksilik cıkmaz ise artık terminalden gönül rahatlığı ile adres bilgisi hexadesimal şekilde gönderip doğru adrese doğru şekilde erişebileceğiz. SUYUNU CIKARALIM :D

Ha bu arada fonksiyon içerisinde 64 bitlik değişken kullanmamızın sebebi son veri 1 bayt veri. bunu bir kez daha kaydırınca 8.digit yok olmasın diye. zaten return ederken 32 bitlik return ediyoruz.

eğer 32 bit tanımlamış olsaydık. veriyi kaydırınca ilk verimiz kaybolacaktı. zaten return ederken 32 bit olarak return ediiyoruz. eğer bir taşma yoksa sıkıntısız dönüşümü yapmış oluyoruz. aslında taşmalara karşıda bir sorgu vermek lazım fonksiyona mesela picin hafızası 0x3FFFFFF mi ne bitiyordu. terminalden bu sayıdan daha büyük bir sayı girilince mesela böyle bir adres yok desin. :D güzel bunuda ekliyoruz projeye.
 

taydin

Timur Aydın
Staff member
Herhangi bir string'i herhangi bir tabana göre unsigned int'e dönüştürmek için strtoul kullanabilirsin. Bu fonksiyon string'deki olası her türlü hatayı algılayıp uygun hata kodu üretebilir.
Code:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   const char* hexstr = "12af47dc";
   unsigned int num;

   num = strtoul(hexstr, 0, 16);
   printf("hexstr = (%s), num = %u\n", hexstr, num);

   return 0;
}

Bunu derleyip çalıştıralım
Code:
[ta@bonsai ~]$ gcc a.c
[ta@bonsai ~]$ ./a.out
hexstr = (12af47dc), num = 313477084
[ta@bonsai ~]$
 

taydin

Timur Aydın
Staff member
Ama bu fonksiyonlarda full hata kontrolü için errno yu da kullanman lazım, yoksa geçerli bir rakamla başlayıp geçersiz karakterler içeren bir string'i, geçersizlere kadar da dönüştürür.

Code:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   const char* hexstr = "abdurrahman";
   unsigned int num;

   num = strtoul(hexstr, 0, 16);
   printf("hexstr = (%s), num = %u\n", hexstr, num);

   return 0;
}

Code:
[ta@bonsai ~]$ gcc a.c
[ta@bonsai ~]$ ./a.out
hexstr = (abdurrahman), num = 2749
[ta@bonsai ~]$

Gördüğün gibi abdurrahman'ı da dönüştürdü :) Ama aslında 0xabd yi dönüştürdü ve diğerlerini attı.
 

Furkan KELEŞOĞLU

Kayıtlı Üye
Abi cevabın için teşekkür ederim. bir şey daha öğrenmiş oldum.

Yalnız Flash işlemleri için yazdığım kod calışmıyor. yani calışan şey şuan calışmıyor bir şey fark ettim. artık yanlış mı doğrumu bilmiyorum kafamda baya dolu. ya MPLAB benim o adrese bir şey yazdığımı anlıyor kendisi o adrese onu .hex dosyası icinde yazıyor veya başka bir gariplik var. cünkü simülatörde bile derlediğim hex kodunu cıkardığım zaman. TABLE POTINTERE yüklenen değer ile benim programda verdiğim değerler alakası yok. anlamadım baya karıştı şimdi en başa dönücem bir daha.
 

taydin

Timur Aydın
Staff member
Abi cevabın için teşekkür ederim. bir şey daha öğrenmiş oldum.

Yalnız Flash işlemleri için yazdığım kod calışmıyor. yani calışan şey şuan calışmıyor bir şey fark ettim. artık yanlış mı doğrumu bilmiyorum kafamda baya dolu. ya MPLAB benim o adrese bir şey yazdığımı anlıyor kendisi o adrese onu .hex dosyası icinde yazıyor veya başka bir gariplik var. cünkü simülatörde bile derlediğim hex kodunu cıkardığım zaman. TABLE POTINTERE yüklenen değer ile benim programda verdiğim değerler alakası yok. anlamadım baya karıştı şimdi en başa dönücem bir daha.
O PIC'te yazma işi tam olarak nasıl yapılıyor bilmiyorum ama yazma işlemi zaman aldığı için döngü içinde beklemek gerekiyordur. Yani döngü içinde bir status register'da FLAG beklemen gerekiyor. Eğer beklemezsen işlem tamamlanmadan belki yarıda kalıyor.
 

Furkan KELEŞOĞLU

Kayıtlı Üye
O PIC'te yazma işi tam olarak nasıl yapılıyor bilmiyorum ama yazma işlemi zaman aldığı için döngü içinde beklemek gerekiyordur. Yani döngü içinde bir status register'da FLAG beklemen gerekiyor. Eğer beklemezsen işlem tamamlanmadan belki yarıda kalıyor.

Abi FLAG yok bu işte :D şöyle gerçekleşiyor.

1-) ilk adresi TABLAT POINTER'a yüklüyorsun.
2-) Yazılacak veriyi TABLAT'a yazıyorsun ( Holding Registerlerine yazılıyor)
3-) veri yazma işlemi yaparken TABLAT POINTERI bir arttırsan komutu veriyorsun (TBLWT*+) ( İLK YAZ SONRA ADRESİ 1 ARTTIR)
4-) flashı yazma moduna gecirip tüm kesmeleri kapatıyorsun
5-) EECON2 registerine ardışık olarak 0x55 ve 0xAA yüklüyorsun ( Bu galiba checkerboard mı neyse tam anlamadım ama bunu yazmak lazım)
6-) EECON1 reg den WR bitini enable ediyorsun.

holding reg lere yazılmış tüm veri adreslere geçiliyor tek seferde 64 byte veri yazılabiliyor.

işte burada kesmelerde kapalı olduğu için CPU stall moduna giriyor hiç bir şeye yanıt vermiyor. kendi dahili timerini kendi kuruyormuş yaklaşık 2 ms diyor datashette . yazma işlemi bitince stall modundan cıkıyor. yani biz bir şeyi beklememize gerek yok. o yazma flaglarını filan otomatik kendi sıfırlıyor CPU zaten. ayrıca bu yorumun üzerine datashette örnek olarak verilmiş ve benimde oraya bakarka yazdığım assembly koduna baktım. orada da bir şart verilmemiş. yaz komutu verilmiş yazılmış. zaten bir flag olayı olsa benim ilk çalışan kod çalışmazdı diye düşünüyorum.

Ben şimdi MPLAB tan flashı doğru şekilde yazdığım zamanın historiysinden kodu cektim ve farklı bir adrese yazma yapptım. calıştı.

şuanki geldiğim noktada ki kod ile onu karşılaştıryorum ve hiç bir fark yok. IDE ile alakalı bir şey var . ama anlamadım ne olduğunu.
 

Furkan KELEŞOĞLU

Kayıtlı Üye
Sorunu buldum. Checker Board dediğim kısım varya .

EECON2 regine yüklenen ardışık değerler. ben bunları yazmaktansa bir fonksiyon yapiyim icine yaziyim oradan cağiriyim dedim. bu ardışık flasha yazma işlemi için izin alma kodlarını ( 0x55 ve 0xAA) fonksiyon içinde gönderince yapmıyor.

Bunun nedeni hakkında düşündüklerim şu.

bizim fonksiyon başka bir adrese atılıyor. hafızada. tam yazma işlemine girecekken demek ki cpu goto komutlarına filan cevap vermiyor. veyahut fonksiyona gidiyor. 0x55 ve 0xAA verisini alıyor ama o veriyi aldığında aslında CPU da gizli mod gibi bir şey acılıyor gibi bir şey diyebiliriz :D buraya girince bir daha stack yığınından(yani yazma fonksiyonuna) geri dönmüyor. veya orda tam orda bir şey oluyor ama anlamadım. bunun için şimdi farklı bir şey deniycem sonucu yine buraya aktarıcam.
 

Furkan KELEŞOĞLU

Kayıtlı Üye
yahu bu MPLAB IDE de bir dandiklik var ama çözemedim. ayarıyla mı oynadık ne yaptık asıl projede calışmayan şey farklı proje klasörü acıp derleyince calışıyor. neyse bugünlükte bu kadar boot işinden yarın devam edeceğiz.
 

taydin

Timur Aydın
Staff member
Projeyi sıfırdan tekrar oluştur ve kaynak kodunu ekle bakalım düzelecek mi :)
 
Top