Merhabalar, bu yazıda size geçenlerde üzerinde çalışıp gerçekleştirdiğimiz Tiva C serisi denetleyiciler için olan SD kart bootloader uygulamasından bahsedeceğim.
Bilindiği gibi bootloader yazılımları genel olarak denetleyicilere programlayıcı/debugger vs. ihtiyacı duymadan program yükleme işlemi yaparlar. Bootloaderın kendisi de bir programdır. Bazı denetleyicilerde dahili bootloader olmakla birlikte çoğunlukla bootloaderlar denetleyicinizin hafızasında asıl kodunuz ile birlikte bulunur, yer kaplar.
Şekil-1
Şekil-1’de temsili olarak bootlaoder bulunan ve bulunmayan iki denetleyicinin yada sistemin program hafızası görülmektedir. Bootloader bulunmayan sistemde(soldaki) görüldüğü gibi sadece yazdığımız kullanıcı programı bulunmaktadır. İşlemci resetlendikten sonra direkt olarak kullanıcı kodunu çalıştırmaya başlar. Bootloader bulunan sistemde ise görüldüğü gibi başlangıçta bootloader kodu bulunmaktadır. İşlemci resetlendikten sonra bootloader kodunu çalıştırır. Bootloader çalışınca yeni bir yükleme işlemi yada tetiklemesi olup olmadığına bakar, eğer yoksa hafızada bulunan kullanıcı kodunu çalıştırmaya devam eder. Eğer bir tetikleme var ise, bootloader program yükleme kodunu çalıştırır ve hangi kaynak belirtildi ise oradan yeni kullanıcı programını alır ve program hafızasına yükler. Genel olarak bootloaderların çalışması bu şekildedir.
Kaynak ve tetikleme gibi terimlerin oturması için bir kaç örnek vermek gerekirse, örneğin; Seri port üzerinden çalışan I/O tetiklemeli bootloader. Kullandığınız denetleyicinin herhangi bir I/O pinine buton vs. bağlanıp reset anında bu butona basılı tutularak denetleyicinin bootloader moduna geçmesi ve gerekli kodları seri porttan yüklemesi sağlanabilir. Tetikleme olayı genellikle buton ile yapılır, yada otomatikte yapılabilir. Örneğin Arduinolar üzerinde de seri port üzerinden çalışan bootloader bulunmaktadır. Tetikleme işlemi de işlemi de seri port üzerinden yapılmaktadır. Başka bir örnek ise USB bootloaderlar, baya oldu burada bir uygulama yapmıştım. Benzer şekilde buton tetiklemesi ile kullanıcı kodları USB üzerinden mikrodenetleyiciye aktarılır. Genel olarak piyasada 8/16/32 bit denetleyiciler için USB, UART, CAN, Ethernet, Wireless üzerinden program yükleyen bootlaoder uygulamaları mevcuttur. Üretici firmaların çoğu bootloader desteği sağlamakla birlikte istenirse yeni çıkan, düşük gerilimle çalışan flash hafızaya sahip denetleyicilerin çoğu için bootloader yazılabilir.
Bootloaderlar kullanıcı kodlarının güncellenmesi, programlayıcıya ihtiyaç duymaması, sistem üzerindeki mevcut donanımlar ile programlama imkanı sunması gibi faydalarından dolayı sıklıkla kullanılırlar. Bootloaderların dezavantajı ise denetleyicinin program hafızasında yer kaplamasıdır. Örneğin 8 kb flash hafızaya sahip bir denetleyici içerisine 1 kb bootloader programı yazılırsa kullanıcı için 7kb program hafızası kalır. Bootloaderlar düşük boyutta yer kaplayacak şekilde yazılmakla birlikte, günümüzde denetleyicilerin program hafızaları oldukça büyük seviyelere ulaştığı için bu durum pek sorun teşkil etmemektedir. Hatta bazı denetleyicilerin program hafızasından bağımsız ROM içerisine yerleştirilmiş bootloaderları mevcuttur.
TİVAWARE™ BOOT LOADER
TI firması Tiva serisi denetleyicileri için TivaWare™ Boot Loader isimli bootloader kodları sunmaktadır. Bu kodlar ve içerisinde bulunan örnek projeler ile kullandığınız Tiva denetleyicilere UART0, SSI0, I2C0, CAN, Ethernet ve USB çevre birimleri üzerinden çalışan bootlodaer programı yazabilirsiniz. Aynı zamanda kodları değiştirerek uygulamanıza özel bootloader programları yazabilirsiniz. TivaWare™ Boot Loader ile ilgili detaylı bilgiye buradan ingilizce olarak ulaşabilirsiniz. Ayrıca bootlaoder kodlarına ve örnek uygulamalara TivaWare™ for C Series yazılım paketi içerisinden ulaşabilirsiniz. TivaWare™ for C Series yazılım kütüphanesini buradan indirip bilgisayarınıza kurabilirsiniz. Şu anki sürümü 2.1.0.12573’dir. Tiva denetleyiciler için gerekli kütüphane dosyalarını, örnek uygulamaları vs. içerdiği için bu yazılım paketiniz kurmanız gereklidir.
SD KART BOOTLOADER
TivaWare ile gelen bootloader uygulamalarında SD kart ile bootloader bulunmamaktadır. Fakat bootloader kodları açık olduğu için geliştirmeye müsaittir. Bizde bu kodlardan faydalanarak SD kart üzerinden program yükleyebilen bootloader uygulaması geliştirdik. Bu sayede SD kart kullanılan uygulamalarınızda, SD kart içeresine gerekli kodları atarak istediğiniz zaman kolaylıkla bootloader ile denetleyicinize program yükleyebilirsiniz.
SD kart bootloader genel yapısı itibari ile yaklaşık olarak 3kb program hafızası işgal etmektedir. RAM bellek tüketimi ise tampon bellek boyutuna göre değişiklik göstermekle birlikte 128 byte tampon bellek ile 320 byte kadardır. Tampon bellek SD karttan tek seferde okunan veri miktarını belirler. Varsayılan olarak 128 byte seçilmiştir. SD kart bootloader uygulaması Keil IDE üzerinde geliştirilmiştir. Denemelerde Tiva Launchpad kullanılmıştır. Geliştirme kartı üzerinde SD kart soketi bulunmadığı için harici bağlantı ile SD kart soketi takılmıştır.
SD kart bootloader uygulaması çalıştığı anda öncelikle kendini RAM belleğe kopyalayıp oradan çalışmaya başlar. TI’nin sağladığı bu özellik sayesinde istenirse bootloader kodunun da güncellemesi yapılabilir. SD kart bootlaoder uygulamasında gerek görmediğim için bu özelliği dahil etmedim. Bootloader RAM üzerinde çalışmaya başladıktan sonra eğer tetikleme var ise yükleme moduna geçer. Yükleme moduna geçtikten sonra bootloader SD kart içinde “app.bin” isminde program dosyasını arar. Dosyayı bulursa dosyayı okuyup içerisindeki kodu belirtilen hafıza bölgesine yazar. Yazma, yükleme işlemi başarıyla tamamlandıktan sonra program kendini resetleyerek yeniden çalışmaya başlar. Resetlendikten sonra her hangi bir tetikleme yok ise bootloader yeni yüklenen kullanıcı kodunu çalıştırmaya başlar. Genel olarak SD kart bootlaoderın çalışma yapısı bu şekildedir.
Tetikleme kaynağı olarak SD kart bootloader iki şekilde tetiklenir. Birincisi eğer denetleyici içerisinde hiç bir uygulama kodu yok ise, ikincisi ise dışarıdan bir pinden sinyal okuyarak yani bir butona basma olayı ile olabilir. Tetikleme sağlandığı anda bootloader yukarıda bahsettiğim kod yükleme moduna geçer.
SD KART BOOTLOADER PROJE AYARLARI
SD Kart Bootloader programını düzgün bir şekilde derleyip yükleyebilmek içinde gerekli ayarlamaların yapılması gerekir.
Şekil-2 SD Kart Bootloader Proje Ayarları
Şekil-2’de görüldüğü gibi define tanımlamaları ve Path gösterimleri yapılmalıdır. Path olarak TivaWare yazılım paketinin kurul olduğu klasörün gösterilmesi gerekiyor.
Şekil-3
Diğer bir ayar ise linker ayarıdır. Şekil-3’te görüldüğü gibi bl_link.sct dosyayı linker’a gösterilmelidir. Bu dosyayı TivaWare_C_Series-2.1.0.12573\boot_loader klasörü altında bulabilirsiniz. SRAM üzerinde çalışma gibi işlemler için TI’nin Keil için hazırladığı linker dosyasıdır
Diğer proje ayarları genel proje ayarlarıdır. SD kart bootloaderın kodları proje halinde indirilip diğer ayarlar incelenebilir. Proje ayarları yapıldıktan sonra kodlar üzerinde konfigürasyon yapılması gerekir. Bootloader için gerekli konfirgürasyon ayarları bl_config.h dosyasında yer almaktadır.
//*************** // // bl_config.h - The configurable parameters of the boot loader. // // Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. // // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 2.1.0.12573 of the DK-TM4C123G Firmware Package. // //************************** #ifndef __BL_CONFIG_H__ #define __BL_CONFIG_H__ //*************************** // // The following defines are used to configure the operation of the boot // loader. For each define, its interactions with other defines are described. // First is the dependencies (in other words, the defines that must also be // defined if it is defined), next are the exclusives (in other words, the // defines that can not be defined if it is defined), and finally are the // requirements (in other words, the defines that must be defined if it is // defined). // // The following defines must be defined in order for the boot loader to // operate: // // One of CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE, // SSI_ENABLE_UPDATE, UART_ENABLE_UPDATE, or USB_ENABLE_UPDATE // APP_START_ADDRESS // VTABLE_START_ADDRESS // FLASH_PAGE_SIZE // STACK_SIZE // //***************************************************************************** #define LED_GPIO_PORT_BASE GPIO_PORTF_BASE #define LED_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOF #define LED_PORT_PIN GPIO_PIN_3 //***************************************************************************** // // The frequency of the crystal used to clock the microcontroller. // // This defines the crystal frequency used by the microcontroller running the // boot loader. If this is unknown at the time of production, then use the // UART_AUTOBAUD feature to properly configure the UART. // // Depends on: None // Exclusive of: None // Requires: None // //***************************************************************************** #define CRYSTAL_FREQ 16000000 //***************************************************************************** // // The starting address of the application. This must be a multiple of 1024 // bytes (making it aligned to a page boundary). A vector table is expected at // this location, and the perceived validity of the vector table (stack located // in SRAM, reset vector located in flash) is used as an indication of the // validity of the application image. // // The flash image of the boot loader must not be larger than this value. // // Depends on: None // Exclusive of: None // Requires: None // //***************************************************************************** #define APP_START_ADDRESS 0x2800 //***************************************************************************** // // The address at which the application locates its exception vector table. // This must be a multiple of 1024 bytes (making it aligned to a page // boundary). Typically, an application will start with its vector table and // this value should be set to APP_START_ADDRESS. This option is provided to // cater for applications which run from external memory which may not be // accessible by the NVIC (the vector table offset register is only 30 bits // long). // // Depends on: None // Exclusive of: None // Requires: None // //***************************************************************************** #define VTABLE_START_ADDRESS 0x2800 //***************************************************************************** // // The size of a single, erasable page in the flash. This must be a power // of 2. // // Depends on: None // Exclusive of: None // Requires: None // //***************************************************************************** #define FLASH_PAGE_SIZE 0x00000400 //***************************************************************************** // // The number of words of stack space to reserve for the boot loader. // // Depends on: None // Exclusive of: None // Requires: None // //***************************************************************************** #define STACK_SIZE 48 //***************************************************************************** // // The GPIO module to enable in order to check for a forced update. This will // be one of the SYSCTL_RCGC2_GPIOx values, where "x" is replaced with the port // name (such as B). The value of "x" should match the value of "x" for // FORCED_UPDATE_PORT. // // Depends on: none // Exclusive of: None // Requries: None // //***************************************************************************** #define FORCED_UPDATE_PERIPH SYSCTL_RCGC2_GPIOF //***************************************************************************** // // The GPIO port to check for a forced update. This will be one of the // GPIO_PORTx_BASE values, where "x" is replaced with the port name (such as // B). The value of "x" should match the value of "x" for // FORCED_UPDATE_PERIPH. // // Depends on: none // Exclusive of: None // Requries: None // //***************************************************************************** #define FORCED_UPDATE_PORT GPIO_PORTF_BASE #define FORCED_UPDATE_PORT_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOF //***************************************************************************** // // The pin to check for a forced update. This is a value between 0 and 7. // // Depends on: none // Exclusive of: None // Requries: None // //***************************************************************************** #define FORCED_UPDATE_PIN 4 //***************************************************************************** // // The polarity of the GPIO pin that results in a forced update. This value // should be 0 if the pin should be low and 1 if the pin should be high. // // Depends on: none // Exclusive of: None // Requries: None // //***************************** #define FORCED_UPDATE_POLARITY 0 //***************************** // // This enables a weak pull-up or pull-down for the GPIO pin used in a forced // update. Only one of FORCED_UPDATE_WPU or FORCED_UPDATE_WPD should be // defined, or neither if a weak pull-up or pull-down is not required. // // Depends on: none // Exclusive of: None // Requries: None // //************************** #define FORCED_UPDATE_WPU //#define FORCED_UPDATE_WPD #endif // __BL_CONFIG_H__
#define LED_GPIO_PORT_BASE GPIO_PORTF_BASE
#define LED_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOF
#define LED_PORT_PIN GPIO_PIN_3
LED ayarları, boot işlemleri sırasında yanıp sönen LED pini ilgili ayarlamalardır. Varsayılan olarak GPIOF.3 pini seçilmiştir.
#define CRYSTAL_FREQ 16000000
Kristal çalışma frekansı, Launchpad üzerinde 16 MHz kristal bulunduğundan varsayılan 16MHz seçilmiştir.
#define APP_START_ADDRESS 0x2800
#define VTABLE_START_ADDRESS 0x2800
Uygulama başlangıç ve Vektör tablosu adresleri. Bootloader kodunun boyutu göz önünde bulundurularak uygulama kodlarınızın hangi adresten başlayacağını belirtilir. Varsayılan olarak 0x2800(10Kb) olarak belirtilmiştir. Bootloader kodu 3kb kadar yer kapladığı için istenirse daha küçük adres değeri seçilebilir. APP_START_ADDRESS değeri boot loader ile yükleyeceğiniz uygulamanın proje ayarlarındaki (Keil için IROM1) program hafızası başlangıç adresi ile aynı seçilmelidir. VTABLE_START_ADDRESS değeri ise vektör tablosunun bulunduğu adresi belirtir. varsayılan olarak uygulama adresi ile aynı adres seçilmiştir. Yani uygulama kodunun başlangıcında vektör tablosu yer almaktadır.
#define FLASH_PAGE_SIZE 0x00000400
#define STACK_SIZE 48
Flash sayfa boyutu ve ayrılan yığın boyutudur. Flash sayfa boyutu Tiva denetleyiciler için 1Kb boyutundadır. Yığın değeri ise bootloader için tahsis edilen yığın genişliğini belirtir. Varsayılan olarak 48 belirtilmiştir.
#define FORCED_UPDATE_PERIPH SYSCTL_RCGC2_GPIOF
#define FORCED_UPDATE_PORT GPIO_PORTF_BASE
#define FORCED_UPDATE_PORT_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOF
#define FORCED_UPDATE_PIN 4
#define FORCED_UPDATE_POLARITY 0
#define FORCED_UPDATE_WPU
Bootloader tetikleme pini ilgili ayarlardır. Tetikleme için hangi port pini kullanılacağı, hangi lojik seviyede tetikleneceği gibi ayarlar belirtilir. Varsayılan olarak launchpad üzerinde butonun bağlı olduğu GPIOF.4 pini ayarlanmış, pull-up direnci aktif edilmiştir.
PETİT FAT SD KART KÜTÜPHANESİ
SD kart bootloader uygulamasında SD kart işlemleri için Elm Chan‘ın Petit Fat kütüphanesinden faydalanılmıştır. Düşük kod boyutuna sahip bu kütüphane bootloader gibi uygulamalar için idealdir.
Petit Fat kütüphanesi Tiva denetleyicilere uygun şekilde port edilmiştir. SD karta erişim için denetleyici SSI0 birimi kullanılmıştır. İstenirse diğer SSI birimleri de kullanılabilir.
Launchpad için SSIO ve SD kart bağlantıları aşağıdaki gibidir.
Launchpad —> SD Kart
PA.2(SSIO_CLK) —> SCLK
PA.3(SSIO_FSS) —> CS
PA.4(SSIO_RX) —> DO
PA.5(SSIO_TX) —> DI
3.3V —> VDD
GND —> VSS
Farklı SSI birimleri kullanılmak istenirse pffconf.h dosyasından gerekli ayarlar yapılmalıdır. SSI0 için pffconf.h dosyası ayarları aşağıdaki gibidir.
// GPIO for SSI pins
#define SDC_GPIO_PORT_BASE GPIO_PORTA_BASE
#define SDC_GPIO_SYSCTL_PERIPH SYSCTL_PERIPH_GPIOA
#define SDC_SSI_CLK GPIO_PIN_2
#define SDC_SSI_TX GPIO_PIN_5
#define SDC_SSI_RX GPIO_PIN_4
#define SDC_SSI_FSS GPIO_PIN_3
#define SDC_SSI_PINS (SDC_SSI_TX | SDC_SSI_RX | SDC_SSI_CLK | \
SDC_SSI_FSS)
Şekil-5
Şekil-5’te launchpad ile SD kartın deneme amaçlı bağlantısı görülmektedir.
ÖRNEK LED BLİNK PROJESİ
SD kart bootloader ile yüklediğiniz programların başlangıç adreslerinin, bootloader kodlarında belirtilen uygulama adresi ile aynı olması gerektiğinden bahsetmiştik. Keil IDE üzerinde bu ayarı yapmak için proje ayarlarından IROM1 değerini APP_START_ADDRESS değeri ile aynı yapmak gerekir.
Şekil-6
Şekil-6’da örnek LED projesinde görüldüğü gibi IROM1 değeri APP_START_ADDRESS değeri ile aynı seçilmiştir. Örnek LED blink uygulamasına ait kodlar aşağıdaki gibidir.
LED Blink
#include <stdint.h> #include <stdbool.h> #include <stdbool.h> #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "driverlib/debug.h" #include "driverlib/fpu.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "driverlib/systick.h" #include "driverlib/rom.h" int main(void) { uint32_t i; FPUEnable(); FPULazyStackingEnable(); SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2); // while(1) { GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_2,GPIO_PIN_2); for(i=0;i<100000;i++); GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_2,!GPIO_PIN_2); for(i=0;i<100000;i++); } }
Şekil-7
Şekil-7’de görüldüğü gibi projenin bin dosyası üretmesi için proje ayarlarında user sekmesinde Run #1 kısmına “fromelf –bin –output .\Bin\LEDBlink.bin .\Bin\LEDBlink.axf” komutu yazılmalıdır. Bu komut derlemeden sonra Keil ile birlikte kurulan fromelf programını çalıştırarak belirtilen .axf dosyasını .bin uzantılı binary dosyasına çevirir. SD Kart Bootloader binary dosyalar üzerinde işlem yaptığı için projenin binary dosya üretmesi gerekmektedir.
Bu şekilde örnek proje ile elde ettiğiniz “LEDBlink.bin” dosyasının adını “app.bin” olarak değiştirip SD kart içerisine atabilirsiniz. Sonrasında SD kartı launchpad’e takıp kit üzerindeki sw1 anahtarına basılı tutarak reset butonuna basmanız yeterli. Bootloader çalışmaya başladıktan sonra uyarı LED’i yükleme işlemi boyunca bir kaç kere yanıp sönecektir. Yükleme tamamlandıktan sonra herhangi bir sorun yok ise denetleyici kendini resetleyip yeni yüklediğiniz kodu çalıştırmaya başlayacaktır.
SD kart bootloader denetleyiciye ilk defa yüklendiğinde flash hafıza boş olacağı için sürekli olarak tetiklenecek ve içerisinde “app.bin” dosyası bulunan SD kartın takılmasını bekleyecektir. Bu aşamada uyarı LED’i sürekli olarak yanıp sönme işlemine devam edecektir. SD karta yüklenen “app.bin” dosyasının herhangi bir klasör içinde olmaması gerekir. Ayrıca SD kart FAT32 olarak biçimlendirilmelidir.
0 Yorumlar