Haberler:

Foruma Resim Yükleme ve Boyut Sınırlaması ( ! )  https://bit.ly/2GMFb8H

Ana Menü

Bootloader tavsiye

Başlatan homer380, 12 Şubat 2024, 22:52:56

homer380

İnternet üzerinde farklı kombinasyonlarla arama yaptım fakat istediğim şekilde bootloader bulamadım. Amacım sd kart üzerinden yeni versiyon programımı yüklemek. Aşağıdaki kod ile basit led yok söndür olayı yapıyorum. Videosunu da ekliyorum. Tecrübeli arkadaşların tavsiyelerini almak isterim. En basit denemelerim de gördüğüm kadarı farklı bir dosya açıp kod yazar isek ramdeki adresler tutmuyor buda yazdığımız kodun yüklense bile sağlıklı çalışmasını engelliyor. En güzeli bootloader kodunun olduğu kısımdan sonra güncellenecek programı yazmak. Denemelerimi elimde mevcut olan eski bir işlemci ile yaptım.
bootloader sanırım eksisi configuration ayarlarının değiştirilememesi, ama artısı daha fazla
(suan mevcut sd için hazırladığım programda sd kart ile spi haberleşme, fat32 dosyalama sistemine uygun sekilde sd kartta veri yazma ve okuma yapan programım mevcut)

Device 18F2550
  
                  ' We use some analog I/O's
@CONFIG_REQ
'
@__config CONFIG1L, PLLDIV_2_1 & CPUDIV_OSC4_PLL6_1   ;'pll kristali 2 e böl. cpudiv 4 ile carp
@__config CONFIG1H, FOSC_HSPLL_HS_1  & IESO_OFF_1 &  FCMEN_OFF_1  ;FOSC_HSPLL_HS_1 pll aktif ise kullan FOSC_HS_1  yerine
@__config CONFIG2L, PWRT_ON_2 & BOR_OFF_2 & VREGEN_ON_2
@__config CONFIG2H, WDT_OFF_2  
'& WDTPS_32768_2             'watch dog açık 8 saniye cevap almaz ise pic resetlenir.4 ms x 16384
@__config CONFIG3H, MCLRE_ON_3 & LPT1OSC_OFF_3 & PBADEN_OFF_3 & CCP2MX_OFF_3
@__config CONFIG4L, STVREN_OFF_4 & LVP_OFF_4  & XINST_OFF_4 & DEBUG_OFF_4
@__config CONFIG5L, CP0_OFF_5 & CP1_OFF_5 & CP2_OFF_5 & CP3_OFF_5
 
@__config CONFIG6L, WRT0_OFF_6 & WRT1_OFF_6 & WRT2_OFF_6
@__config CONFIG6H, WRTC_OFF_6 & WRTB_OFF_6 & WRTD_OFF_6
@__config CONFIG7L, EBTR0_OFF_7 & EBTR1_OFF_7 & EBTR2_OFF_7
@__config CONFIG7H, EBTRB_OFF_7


                             
All_Digital TRUE                    ' We use some analog I/O's
  Xtal=16
  TRISB=0
Dim test As Byte
Dim okunan As string*15   'flash hafıazayı okumak icin
Dim sayac As Byte
Declare Bootloader = On
Symbol RD = EECON1.0    ' Read Control
Symbol WR = EECON1.1    ' Write Control
Symbol WREN = EECON1.2  ' EEPROM Write/Enable
Symbol WRERR = EECON1.3 ' EEPROM Error Flag
Symbol FREE = EECON1.4  ' FLASH Row Erase Enable bit
Symbol CFGS = EECON1.6  ' FLASH Program/Data EEPROM or Configuration Select bit
Symbol EEPGD = EECON1.7 ' FLASH Program or Data EEPROM Memory Select bit
Symbol GIE =INTCON.7





flash_sil:

TBLPTRU=0:TBLPTRH=$10:TBLPTRL=$00  'silinecek adresi yükle
EECON1.7=1
EECON1.6=0
EECON1.2=1
EECON1.4=1
INTCON.7=0
EECON2=$55
Asm
Nop
Nop  'gerek yok bu kısma
Nop
EndAsm
EECON2=$AA
EECON1.1=1
INTCON.7=1
Tblrd*-
DelayMS 100
'***yüklenecek kod parcası 32 byte bloklar seklinde yazıyor.
TABLAT=$8a:Tblwt+*:TABLAT=$78:Tblwt+*:TABLAT=$64:Tblwt+* '1
TABLAT=$0e:Tblwt+*:TABLAT=$04:Tblwt+*:TABLAT=$ec:Tblwt+*
TABLAT=$00:Tblwt+*:TABLAT=$f0:Tblwt+*:TABLAT=$fb:Tblwt+*
TABLAT=$d7:Tblwt+*:TABLAT=$ff:Tblwt+*:TABLAT=$d7:Tblwt+*
TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*
TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+* '6

TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+* '7x3=21

TABLAT=$ff:Tblwt+*'22
TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*  '25
TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*  '28
TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*:TABLAT=$ff:Tblwt+*
  TBLPTRU=0:TBLPTRH=$10:TBLPTRL=$00  'programın adresi yükle

EEPGD=1:CFGS=0:WREN=1:GIE=0
EECON2=$55:EECON2=$AA
WR=1:GIE=1:WREN=0 'programı yükle
DelayMS 50

Asm
GoTo 4096  ' güncellenen programın adresine git
EndAsm

RaMu

Yazmayla bitebilecek bir konu değil bayağı detay var ama biraz bahsedeyim.

IDE üzerinde yazılan programların bootloader kod ve runtime kod şeklinde iki ayrı bölümü olacak,
Bootloader kod IDE üzerinde her yeni program yazılırken bootloader kod üzerinde hiçbir değişiklik yapılamadan aynen kullanılacak,
İlk enerjilenme, reset vs. Mcu kod koştururken her zaman öncelikle bootloader kod kısmını çalıştıracak,
Bootloader kod içinde "Sd karttan yeni kod yüklenecek mi" gibi bir sorgu olacak, açılışta butona basma, SD kart takılı mı vs gibi bir sorgusu olur,
Runtime kod başlangıç adresi Mcu flash memory de hep aynı adresten başlayacak,
Bootloader kısmından çalışmaya başlayan kod Runtime kod başlangıcına yönlendirme yapacak,
(Bootloader yeni kod yüklemesini başarıyla yaptı vs. gibi kontroller olmalı ki hatalı yüklemede olmayan bir kod çalıştırılmasın)
SD kart okuma (ve varsa yazma) ve Mcu hafıza silme yazma kodları bootloader kısmında olacak,
Runtime kod kısmının bootloader kod kısmına erişmesine izin verilmeyecek (interrupt ve error lar için kontrollü erişim verilecek)

Kesme ve hata vektörleri bootloader kod içinde tanımlanmış olmalı ve runtime kod içinde yine sabit adresli yerlere yönlendirilmeli.

Asıl problem yazdığın bootloader mcu modeline özel oluyor ve
bootloaderlı her projene dahil etmen gereken ve değiştiremeyeceğin bir bootloader programı yazıyorsun
bu kısmın hatasız ve gelecekte yapacağın her şeyi kapsaması gerekiyor, değiştirememek sıkıntı.

Birde IDE içinde linker kısmına müdahale etmek aslında işleri kolaylaştırıyor ama
hem bunu yapmak karmaşık hemde buradada linker dosyasınında her projen için kullanılması gerekliliği saklamak vs. dert.
Linker dosyası modifiyesi ise bahsettiğim sabit runtime program başlangıcı, kesme ve hata başlangıç adresleri vs. işini,
her yeni projede bootloaderlı şablon kullanmaktansa linker ile halletme imkanı sağlıyor.

Bir problemde Mcu flash memory ye SD kart tan okuyup yazacağın kodu nasıl oluşturacaksın
normalde IDE nin ürettiği .hex olan bu dosya içinden runtime kod kısmını bulup ayıklayıp SD karta bozmadan atman lazım bunu PC üzerinde yapabilirsin
yada bu işide yazdığın bootloader kod kısmı çözecek.

...
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

homer380

Yanıtınız için teşekkür ederim. flash hafızaya yazma işini yüklemek istenen dosya ismi ile halledecem eğer yüklenecek dosya ismi var ise boot işlemi gerçekleşecek yükleme yapıldıktan sonra dosya silinecek.  Kodlarım düzenli olmadığı için yayınlamıyorum. düzenleyince yayınlayacağım. Şu aşamada sadece led yak söndür yaptım. video da flash hafızanın 1000 adresinde başta herhangi bir yazma yok. serial ekranda yazma yapılacak dedikten bir süre sonra flash hafızanın 1000 adresine yazma işlemi yapılıyor ve yazma işlemi bitince 1000 adresine geçiyor.


homer380

denemeleri sandisk 8-16-32 (SDHC) kartlarla yaptım markasını bilmediğim 4gb kart ile de yaptım her birinde sonuç başarılı

işlemci olarak elimde dip kılıf olan pic18f2550 vardı bu yüzden bu işlemci ile denemelerimi yaptım. farklı model de yeni 18f serisi pic'ler var ama breadboard takamam
bootloader kodunun biraz daha düzenlenmeye ihityacı var.
eksikleri muhakkak vardır şuan itibari ile yaklaşık 1kb olan kod blogunu sd karttan istediğim şekilde yükledim
aklıma gelmeyen ama sizin aklınıza gelen durumlar var ise test etmek isterim böylelikle sd kart bootloader daha da gelişebilir.
yapılan işlemler
- değişken ata
- değişken değerini değiştir
- eeprom veri yaz
- donanımsal portb kesmesi yap
neden sd kartta ile yapmayı tercih ettim ? ilerde yazacağım kodu kullanıcı sadece sd kartta atacak, sd karttan yeni program yada güncelleme yapılmış olacak.
Geliştirmek için her türlü öneriye ve yardıma açığım
proteus ile fiziki ortam da yaptığım denemelerde ne yazikki flash'a belleğe yazma farklı. diyelim ki $FE85 kodu yazacaksınız. proteus'ta normal yazarken fiziki ortam da $85FE seklinde yazıyor. bu yüzden düzenleme yaptım ve fiziksel olarak testlere başlayınca proteus kullanmadım

test edilen kodum
Device 18F2550
  
                  ' We use some analog I/O's
@CONFIG_REQ
'
@__config CONFIG1L, PLLDIV_2_1 & CPUDIV_OSC4_PLL6_1  ;'pll kristali 2 e böl. cpudiv 4 ile carp
@__config CONFIG1H, FOSC_HSPLL_HS_1  & IESO_OFF_1 &  FCMEN_OFF_1  ;FOSC_HSPLL_HS_1 pll aktif ise kullan FOSC_HS_1  yerine
@__config CONFIG2L, PWRT_ON_2 & BOR_OFF_2 & VREGEN_ON_2
@__config CONFIG2H, WDT_OFF_2  
'& WDTPS_32768_2            'watch dog açık 8 saniye cevap almaz ise pic resetlenir.4 ms x 16384
@__config CONFIG3H, MCLRE_ON_3 & LPT1OSC_OFF_3 & PBADEN_OFF_3 & CCP2MX_OFF_3
@__config CONFIG4L, STVREN_OFF_4 & LVP_OFF_4  & XINST_OFF_4 & DEBUG_OFF_4
@__config CONFIG5L, CP0_OFF_5 & CP1_OFF_5 & CP2_OFF_5 & CP3_OFF_5
 
@__config CONFIG6L, WRT0_OFF_6 & WRT1_OFF_6 & WRT2_OFF_6
@__config CONFIG6H, WRTC_OFF_6 & WRTB_OFF_6 & WRTD_OFF_6
@__config CONFIG7L, EBTR0_OFF_7 & EBTR1_OFF_7 & EBTR2_OFF_7
@__config CONFIG7H, EBTRB_OFF_7



Declare Bootloader = 1
Declare Compiler_Start_Address = $1000
 On_Hardware_Interrupt GoTo kesme
  Xtal=16 
                              
All_Digital TRUE                    ' We use some analog I/O's


 Dim i As Byte
 i=0  
  TRISB=%11110000
  PORTB.7=1
INTCON2.7=0'pullup direncleri
 INTCON2.0=1
INTCON.7=1
INTCON.6=1
INTCON.3=1
INTCON.0=0 
 
led: 
 
PORTB.3=~PORTB.3
DelayMS 1000
SerOut PORTB.2, 84, ["ram deki i:  ",Dec i,"\r\n"]
Inc i
EWrite i,[47+i]
GoTo led

 kesme:
Context Save 

If INTCON.0=1 Then
    If PORTB.7=0 Then  
        SerOut PORTB.2, 84, ["kesme gerceklesti.\r\n"]
        DelayMS 100
        SerOut PORTB.2, 84, ["kesme gerceklesti1221.\r\n"]
        EndIf
    DelayMS 100
    INTCON.0=0 
EndIf
Context Restore
Return

test2:
 SerOut PORTB.2, 84, ["hoöer\r\n"]
 DelayMS 3000
 GoTo test2


 


sd kart bootloader'ım

Device 18F2550
  
                  ' We use some analog I/O's
@CONFIG_REQ
'
@__config CONFIG1L, PLLDIV_2_1 & CPUDIV_OSC4_PLL6_1  ;'pll kristali 2 e böl. cpudiv 4 ile carp
@__config CONFIG1H, FOSC_HSPLL_HS_1  & IESO_OFF_1 &  FCMEN_OFF_1  ;FOSC_HSPLL_HS_1 pll aktif ise kullan FOSC_HS_1  yerine
@__config CONFIG2L, PWRT_ON_2 & BOR_OFF_2 & VREGEN_ON_2
@__config CONFIG2H, WDT_OFF_2  
'& WDTPS_32768_2            'watch dog açık 8 saniye cevap almaz ise pic resetlenir.4 ms x 16384
@__config CONFIG3H, MCLRE_ON_3 & LPT1OSC_OFF_3 & PBADEN_OFF_3 & CCP2MX_OFF_3
@__config CONFIG4L, STVREN_OFF_4 & LVP_OFF_4  & XINST_OFF_4 & DEBUG_OFF_4
@__config CONFIG5L, CP0_OFF_5 & CP1_OFF_5 & CP2_OFF_5 & CP3_OFF_5
 
@__config CONFIG6L, WRT0_OFF_6 & WRT1_OFF_6 & WRT2_OFF_6
@__config CONFIG6H, WRTC_OFF_6 & WRTB_OFF_6 & WRTD_OFF_6
@__config CONFIG7L, EBTR0_OFF_7 & EBTR1_OFF_7 & EBTR2_OFF_7
@__config CONFIG7H, EBTRB_OFF_7


                            
All_Digital TRUE                    ' We use some analog I/O's
  Xtal=16
On_Hardware_Interrupt GoTo kesme 
  TRISB=0:PORTB.3=1
  

Dim dosyada_kul_cluster_say As Dword ' bir dosya için kullanılan cluster sayısı
Dim dosyaboyutu As Dword  '4 gb dosya boyutu alır en fazla
Dim fat As String * 10
Dim alinan[10] As Byte
Dim veri_koru[50] As Byte
Dim verial[50] As Byte
Dim karakter2 As String*15
Dim uzun_dos_adi[25] As Byte  
Dim donustur[10] As Byte 
'''Dim sayac As Byte 
Dim karakter[650] As Byte

Dim dd As Byte  
Dim kisa_ad As String * 11
Dim kisa2 As String * 10
  Dim dur1 As Word
    Dim i As Word
    Dim a As Word
    Dim j As Byte
    Dim y As Byte
    Dim zz As Word
    Dim veri As Byte
    Dim veri2 As Byte
    
    
    '*********************dosya işlemleri

Dim dosya_boyutu As Dword
Dim kalan As Word
Dim sayi1 As Byte
Dim sayi2 As Byte
Dim tur As Byte
Dim bos As Byte
Dim gun As Byte
Dim ay As Byte
Dim yil As Byte
Dim saniye As Byte
Dim dakika As Byte
Dim saat As Byte
Dim salise As Byte



Dim tarih As Word
Dim zaman As Word
Dim surat As Word
Dim boylam As Float
Dim enlem As Float
Dim altitude_gps As Word
Dim fix As Byte    


    '********************BOOTSECTOR OKUMA DEĞİŞKENLERİ*******
Dim rezerv_kok_sayisi As Word
Dim fat_sayisi As Byte
Dim fat_b_d_sector_say As Dword  'fat basına dusen sektor sayısı
Dim sector_add As Dword  
Dim sector_boyutu As Word 'kartın sectör boyutları 

Dim rootdizinadresi As Dword
Dim kullanilan_cluster As Word
Dim sectorsonu As Dword
Dim baslangic As Dword
Dim bos_cluster As Dword
Dim son_kul_cluster As Dword
Dim oncu_cluster As Dword
Dim sonraki_cluster As Dword
Dim ucuncu_cluster As Dword
Dim baslangincclusterkayit As Dword
Dim cluster_boyutu As Byte
Dim checksum As Byte

Dim sayac As Byte 
'Dim tur As Byte ' amac 1 clusterın sector sayısı eğer 64 olursa bir cluster dolar

'*******************SON*******************************
'Declare Bootloader = On
Symbol RD = EECON1.0    ' Read Control
Symbol WR = EECON1.1    ' Write Control
Symbol WREN = EECON1.2  ' EEPROM Write/Enable
Symbol WRERR = EECON1.3 ' EEPROM Error Flag
Symbol FREE = EECON1.4  ' FLASH Row Erase Enable bit
Symbol CFGS = EECON1.6  ' FLASH Program/Data EEPROM or Configuration Select bit
Symbol EEPGD = EECON1.7 ' FLASH Program or Data EEPROM Memory Select bit
Symbol GIE =INTCON.7
Symbol BF=SSPSTAT.0
Symbol ss = PORTA.1

    Symbol SSPEN=SSPCON1.5
    Symbol deger=SSPBUF
For i=0 To 2  'burası kaldıralabilir test ordamında ilk seri haberleşme başlarken anlamsız karakterler gelmesin diye
SerOut PORTB.2, 84, [ "booader testin\r\n"]:DelayMS 50
Next

  GoSub spikurulum
        
DelayMS 20  
GoSub cmd0:GoSub cmd8 'sd kart spi haberleşme için hazırlanıyor.
  For dd=0 To 9 ' sd kart ile iletişim için hata kodları duruma göre eklenecek 
  GoSub cmd55:DelayMS 50:GoSub cmd41:DelayMS 50
  If veri2=0 Then Break
  Next
    

 sayac=90  ' dosya sonuna ulaşunca sayac 0 yada 240 tan büyük olaacak rastgele 90 değeri
saniye=0:tarih=0:kalan=0:dur1=0: a=0:zz=511:DelayMS 50 :sector_add=8448:GoTo boot  '16 gb kartta denemler yapılmış olup kart 32 kb olarak fat32 bicimledirildi
                                                                                    'istenirse kokdizin bulunup oradan ilgili dosyaya ulaşılabilir
spikurulum:
    
      PORTA=0
    TRISA.1=0'ss  
    PORTC=0
    TRISC.7=0  'sdo
    PORTB.0=1
    TRISB.0=1 'sdi
    TRISB.1=0  'sck
    TRISA.1=0 
    'trisa.5=0' donanımsal ss master modda
    SSPCON1.5=0'sspen
    SSPCON1.4=0'ckp
    SSPSTAT.6=1 'cke
    SSPSTAT.7=0 'smp
    

  SSPCON1.0=0 'spi hanerleşme hızı 16 mHZ/64  olarak ayarlı ilk başlatırken sd kart 100-sanırım 625 khz hız ile başlatılıyor sonradan hız yükseltrilebilir
  SSPCON1.1=1 '00 fosc / 4, 01 fosc / 16, 10 fosc / 64, spi haberleşne hızı 

    SSPCON1.5=1'sspen spi haberleşme başlatma / durdurma
  
  Return
    spi_yaz:
  SSPBUF =veri 'spi haberleşme başlamadan ss pini önce ssıfıra sonra bire çek 
  While BF=0:Wend
  Return
  
  spi_oku:
  SSPBUF=veri  'spi okumada yada yazmada bir  yandan veri gönderilirken bir yandan da veri sspbuf dolar
  While BF=0:Wend
  veri=SSPBUF
  
  
  Return 

 cmd0:
 ss=1:DelayMS 2
 For i=0 To 9
 veri=$FF:GoSub spi_oku
 Next 
 i=0
 Repeat
 ss=1: veri=$FF:GoSub spi_oku
 veri=$ff :GoSub spi_oku
 ss=0
 veri=$ff :GoSub spi_oku
 veri=$40 :GoSub spi_oku
 veri=$00 :GoSub spi_oku
 veri=$00 :GoSub spi_oku
 veri=$00 :GoSub spi_oku 
 veri=$00 :GoSub spi_oku
 veri=$95 :GoSub spi_oku
 veri=$Ff :GoSub spi_oku
 veri=$Ff :GoSub spi_oku
 veri2=veri:Inc i
 veri=$ff:GoSub spi_oku:ss=1:veri=$ff:GoSub spi_oku
 Until veri2=1 Or i > 10  'sd karttan alınan veri 1 yada 10 tur sonra döngüden cıkılır
 Return


  cmd8:
 veri=$FF:GoSub spi_oku
 ss=0
 veri=$FF:GoSub spi_oku
 veri=$48:GoSub spi_oku
 veri=$00:GoSub spi_oku
 veri=$00:GoSub spi_oku
 veri=$01:GoSub spi_oku
 veri=$AA:GoSub spi_oku
 veri=$87:GoSub spi_oku
 veri=$FF:GoSub spi_oku
 GoSub spi_oku:veri2=veri  '1
 GoSub spi_oku:alinan[1]=veri '2
 GoSub spi_oku:alinan[2]=veri '3
 GoSub spi_oku:alinan[3]=veri '4
 GoSub spi_oku:alinan[4]=veri '4
 veri=$ff:GoSub spi_oku:ss=1:veri=$ff:GoSub spi_oku  'alinan veriler sd kartta ait bazı bilgiler içeriir istenirse kullanılabilir
 Return

 cmd55:  '4-32 gb karttlar da SDHC sınıfı karttlarda cmd55 ve cmd41 şart bilgi sayfalarında bu şekilde
 i=0
 Repeat 
 veri=$ff :GoSub spi_oku
 ss=0
 veri=$ff :GoSub spi_oku
 veri=$77 :GoSub spi_oku
 veri=$00 :GoSub spi_oku
 veri=$00 :GoSub spi_oku
 veri=$00 :GoSub spi_oku 
 veri=$00 :GoSub spi_oku
 veri=$01 :GoSub spi_oku
 veri=$FF :GoSub spi_oku
 veri=$FF :GoSub spi_oku
 veri2=veri
    
  veri=$ff:GoSub spi_oku:ss=1:veri=$ff:GoSub spi_oku
  Inc i
  If i>8 Then Break
 Until veri2=0 Or veri2=1 'gelen veri  1 yada 0 döngüden ise cık  
  Return

cmd41:
  i=0
 Repeat
 veri=$ff :GoSub spi_oku
 ss=0
 veri=$ff :GoSub spi_oku
 veri=$69 :GoSub spi_oku
 veri=$40 :GoSub spi_oku
 veri=$00 :GoSub spi_oku
 veri=$00 :GoSub spi_oku 
 veri=$00 :GoSub spi_oku
 veri=$01 :GoSub spi_oku
 veri=$FF :GoSub spi_oku
 veri=$FF :GoSub spi_oku
 veri2=veri 
 veri=$ff:GoSub spi_oku:ss=1:veri=$ff:GoSub spi_oku
    SerOut PORTB.2, 84, [Dec veri2,"\r\n"]
  Inc i
 If i>8 Then Break
 Until veri2=0 Or veri2=1  'ilk turda veri2 =1 daha sonraki turlarda veri2 =0 ise sd kart haberleşmeye hazır demek
  Return

    kokdizin:  'kok dizine gidip belirlenecek dosyanın adı var ise boot işlemi yapacak
  GoSub sd_veri_okuma
            
    cluster_boyutu = karakter[13]
  fat=karakter[82]+karakter[83]+karakter[84]+karakter[85]+karakter[86]+ karakter[510]+karakter[511] 'belirli adreslerideki karakter                                                                                                
  ' FAT32Uª karakteri ile eşleşyormu? eşleşmez ise 2048 katı olacak sekilde ilerle yani ilk 2048 ile dene fat32 sistemi burda değilse
  '4096 sonra 8192 şeklinde ilerliyor.4,8, 16 ve 32 denemelerimde 2048 yada 8192 idi fat32 başlangıcları
                                                                                                    
  If fat<>"FAT32Uª" Then 
  sector_add=sector_add + 2048:baslangic=sector_add ' FARKLI BOYUTTAKİ SD KART DENEMELERİM DE GENEL DE 2048 SECTOR DEN BAŞLIYOR bazen de 8192 bu yüzden
                                                ' 2048 katları olacak şkelide aldım. ileride farklılık olursa 0 sectorden de başlayabilir.
  GoTo kokdizin
  EndIf 
  
  If sector_add > 10000 Then Return
  
  
  If fat="FAT32Uª" Then
  rezerv_kok_sayisi.Byte0=karakter[14]
rezerv_kok_sayisi.Byte1= karakter[15]
fat_sayisi=karakter[16]
fat_b_d_sector_say.Byte0=karakter[36]
fat_b_d_sector_say.Byte1=karakter[37]
fat_b_d_sector_say.Byte2=karakter[38]
fat_b_d_sector_say.Byte3=karakter[39]
rootdizinadresi=rezerv_kok_sayisi +  fat_sayisi * fat_b_d_sector_say
sector_boyutu.Byte0=karakter[45]
sector_boyutu.Byte1=karakter[44]

For i=0 To 4
fat[i]=karakter[82+i]
Next


  EndIf
  rootdizinadresi= rootdizinadresi + sector_add
  sector_add=rootdizinadresi 'kok dizinin bulunduğu adres
 'sector_add root klasörünün başlangıc sectoru oluyor. 
 'SerOut PORTB.4, 84, [Hex sector_add,"  dizin"]
 Return
 
 sd_veri_okuma:    'istenen sector adresinden 512 byte veri okunur. SDHC sınıf kartlarda veri 512 bloklar seklinde geliyor
  veri=$ff :GoSub spi_oku
 ss=0
 veri=$ff :GoSub spi_oku    
 veri=$51 :GoSub spi_oku
 veri=sector_add.Byte3 :GoSub spi_oku ' istenen sectorden veri okuma işlemi
 veri=sector_add.Byte2 :GoSub spi_oku
 veri=sector_add.Byte1 :GoSub spi_oku 
 veri=sector_add.Byte0 :GoSub spi_oku 'düşük sector

 For i=0 To 20
 veri=$FF :GoSub spi_oku
 If veri= 0 Then Break
 Next
 
  For i=0 To 199
 veri=$FF :GoSub spi_oku
 If veri= $FE Then Break 'eğer $FE verisi geldi ise sd kart veri gönderecdk
 Next
 ' For i=a To zz
 For i=a To zz 'a değeri ilk başta a=0,zz=511  bu iki değer kalan veri boyutuna göre şekillenecek
                'kalan verilere göre döngü farklı yerden başlayacak 
  SSPBUF=$FF
  While BF=0:Wend
  karakter[i]=SSPBUF
  Next
                                                    
  veri=$ff:GoSub spi_oku:ss=1:veri=$ff:GoSub spi_oku
  sayi1=0
  For i=0 To zz'
    
  If karakter[i]=":" Then Inc sayi1  'sayi1 değişkeni ile 512 veride kaç tane ":" var buna göre sd karttın flashına yazma işlemi yapılacak
                                    'flasha yazma işi dosya sonuna gelene kadar her seferinde sayi1 değişkeninin 1 eksği kadar yapılacak
                                    ' kalan veriler sonraki okumaya düzenli aktarılacak
  If karakter[i] =":" And karakter[i+1] ="0" And karakter[i+2] ="0" And karakter[i+3] ="0" Then  
  tarih=1:sayac=sayi1 + 1 'yazma işleminde burdaki değişken durumlarına göre dosya sonu için sayac geriye sayac sayacak 
  EndIf
    
  Next
  i=0

 Return 
 
 
 boot:                                                                      'ilk 5 cluster sector dosyalarına ait

  For i=0 To 550  'kaldırlabilir
  karakter[i]=0
  Next
  
 GoSub sd_veri_okuma 'sd karttan veri okuma boot kısmmı silinip içerisindeki kodlar düzenleneip sd karttan başlatmadan sonraya alınabilir 

  
i=0:dur1=0:zz=511:tarih=0 'ilk okuma döngusunde karakter değişkenine veriler karakter[0]-karakter[511] şeklinde alıncak, 
                          'sonra kalan verilere göre zz ve  a değişkneleri düzenecek
GoTo yaz
 
 
yaz:

 If dur1 + 1 = sayi1 + tarih Then  '11 tane : nokta ile başlayan veri işlendi. dosya sonuna kadar her seferinde sayi1 değişkeninin bir eksiği tur yapılacak

              dur1=zz-i-43'kalan veri hesaplanıyor.
                kalan=dur1'sayi1 1 eksiği kadar kalan verimiz oluyor. 
                dur1=i+44 
              
                    If kalan<>0 Then
                        For i=0 To kalan-1'geriye kalan veriler karakter[0]'tan karakter[kalan] şeklinde aktarılacak
                        karakter[i]=karakter[DUR1+ i]'
                        
                        Next
                        
                    EndIf
                    
                    a=kalan:zz=511 + kalan 'kalan veriye göre sd karttan okunacak veriler karakter[]- 
                    dur1=0 
                    sector_add = sector_add + 1:GoSub sd_veri_okuma:i=0  'sd karttan yeni veriler okunacak
        i=0
    EndIf

If karakter[i]=":"  Then 'eğer : karakteri var ise 
      Inc dur1
        If tarih = 1 Then sayac = sayac - 1 'eğer dosyanın sonuna geldi isek geri sayım başlayacak ve 0 değerine ulaşunca istenen değere atlama yapılacak
                                            'tarih 1 değerini aldı ise dosya sonuna geldik sayac  0 olunca yada 240 değerinden büyük ise aşagıdaki kısımdan 
                                            'yüklenen koda geçiş için işaret. dosya sonunu string olarak alınca cok yer kaplıyor. böyle bir çözüm yaptım
      

donustur[2]=0  'donustur olayında 0 karakterine kadar 2 byte veri almak val fonksiyonu sıfıra kadar dönusum yapıyor . bu sayede 30 byte lık alan oluşyyor
            donustur=karakter[i+1],karakter[i+2]
            saat=Val(donustur,Hex)  'kaç byte veri var?
donustur[4]=0
                    donustur=karakter[i+3],karakter[i+4],karakter[i+5],karakter[i+6]
                    dosyada_kul_cluster_say=Val(donustur,Hex) 'yazılacak veri adresi
                    donustur[2]=0':donustur[3]=0
                  
                ' SerOut PORTB.4, 84, [dec sayac,"  sayac-sayi1:  ",dec sayi1,"\r\n"]    
    If  dosyada_kul_cluster_say >= $1000 Then
        dosyada_kul_cluster_say = dosyada_kul_cluster_say
        zaman = saat + dosyada_kul_cluster_say 
        TBLPTRU = dosyada_kul_cluster_say.Byte2:TBLPTRH=dosyada_kul_cluster_say.Byte1:TBLPTRL=dosyada_kul_cluster_say.Byte0 'adres

                      Tblrd*-  '
                    For j= 0 To saat*2 - 1  Step 4
                          
                          donustur[0]=karakter[i+j+9]:donustur[1]=karakter[i+j+10]'yazarken pickit2 önce ikinci karakter sonra birinci seklinde
                                                                                        ' bunu düzenlemek için bu şeklide yaptım 
                          surat=Val(donustur,Hex) :TABLAT=surat:Tblwt+* 
                          zaman=zaman+surat'zaman değişkenini checksum değeri sağlamak için kullanırım
                      
                            SerOut PORTB.2, 84, [Hex surat,"-"]
                            
                            donustur[0]=karakter[i+j+11]:donustur[1]=karakter[i+j+12]'yazarken pickit2 önce ikinci karakter sonra birinci seklinde
                                                                                        ' bunu düzenlemek için bu şeklide yaptım 
                          surat=Val(donustur,Hex) :TABLAT=surat:Tblwt+* 
                          zaman=zaman+surat'zaman değişkenini checksum değeri sağlamak için kullanırım
                          
                          SerOut PORTB.2, 84, [Hex surat,"-"] 
                          
                    Next 
  
        EEPGD=1:CFGS=0:WREN=1:GIE=0
        EECON2=$55:EECON2=$AA
        WR=1:GIE=0:WREN=0'normalde kesmeler acık ama ben kapattım

                    zaman=~zaman+1


    EndIf
    SerOut PORTB.2,84,[Dec sayac,"\r\n"]
                        If sayac=0 Or sayac>230 Then  'sayactan geriye sayılacak eğer
                        SerOut PORTB.2, 84, ["ok"]
                      Asm
                        GoTo 4096
                        EndAsm 
                        EndIf                
EndIf
    
  
Inc i
GoTo yaz


kesme:  'yüklenecek program bloğjnda kesme olur ise önce buraya sonra yeni belirlenecek adrese atlayacak.
        'proton ide Declare Compiler_Start_Address = $1000 komutu dan sonra eğer yüksek öncelikli kesme var ise 
        '$1000 + 8 adresine atlayacak orada yazılacak kodları uygulayacak
Context Save
Asm 
GoTo 4104
EndAsm
Context Restore