Arduino UNO üzerinde bulunan mikrodenetleyici : atmega328p-u kullanarak bir kod yazdık, derledik, bir hex dosyamız var, yazdığımız kodun, sadece "herhangi bir" atmega328p-u üzerinde çalışmasını istiyoruz, yani farklı bir mikrodenetleyiciyede çalışmasın, ya da "sadece" tek bir atmega328p-u üzerinde çalışsın istiyoruz, bir nevi kod koruma gibi, bir şekilde yazılı olan mikrodenetleyici üzerindeki kod okutularak başka bir mikrodenetleyiciye kopyalandığında çalışmasın istiyoruz.
İlk seçenek sadece kod uyumluluğunu denetlemek için kullanılabilir, hex kodu alınıp örnek olsun diye Atmega2560 a yüklendiğinde "uyumsuz olacağı düşünülerek" çalışması engellenebilir.
İkinci seçenekse, farklı bir atmega328p-u ya da atılmış olsa çalışmasın, burada kod korumadan söz edebiliriz. Peki bunu sağlamak için ne yapabiliriz? Örnek olsun diye atmega328p nin kendine özgü, her mikrodenetleyici için "benzersiz" bir seri numarası olsa, yine örnek olsun diye bu seri numarası 6F 75 57 37 37 57 FF 25 98 olsa, ve kodumuzun en başında desek ki, mikrodenetleyicinin seri numarasını oku, bizim bildiğimiz seri numarası ile karşılaştır doğru değilse sonsuz bir döngüye gir, dolayısıyla kodun geri kalanı hiç çalışmasın. Uygun bir çözüm gibi, peki atmega328p-u bize böyle bir olanak sağlıyor mu? Datasheet e bir göz atalım:
31.5 Serial Number The product has a serial number which offers a unique ID to identify a specified part while it is in the field. It consists of several bytes, which can be accessed from the signature address space. The Signature row includes factory-programmed data:
- ID for each device type
- Serial number for each device
- Calibration bytes for factory calibrated peripherals
burda bahsettiğine göre böyle bir imkan var, ancak nedir nerden buluruz nasıl okuruz gibi bir bilgi malesef yok.Ancak bu bilgiye aynı ailenin farklı bir ferdi olan atmega328pb için yayınlanan datasheet üzerinde rastlıyoruz.
Table 31.5 Signature Row Adressing
Siganure Byte | Z-Pointer |
Device Signature Byte 1 | 0x0000 |
Device Signarure Byte 2 | 0x0002 |
Device Signature Byte 3 | 0x0004 |
Rc Oscillator Calibration Byte | 0x0001 |
Serial Number Byte 1 | 0x000E |
Serial Number Byte 0 | 0x000F |
Serial Number Byte 3 | 0x0010 |
Serial Number Byte 2 | 0x0011 |
Serial Number Byte 5 | 0x0012 |
Serial Number Byte 4 | 0x0013 |
Serial Number Byte 6 | 0x0015 |
Serial Number Byte 7 | 0x0016 |
Serial Number Byte 8 | 0x0017 |
Şair burada ne anlatmak istemiş? ID for each device type ile kasıt mikrodenetleyicinin imzası yani kim olduğu bilgisi: Device Signature Byte ile verilmiş, Serial Number ise "biraz karışık olmakla birlikte" 9 ayrı adres üzerinde 8 bitlik veriler olacak şekilde; Serial Number Byte 0 ile Serial Number Byte 8 olarak kodlanmış.
Nasıl ulaşacağız bu bilgilere ? Bu noktada boot.h yardımıza koşuyor ve bize
boot_signature_byte_get(addr) gibi bir fonksiyon sunuyor.
boot.h main.cpp ye include edilip kullanılabilir, ;Atmel Studio için örnek kod:
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/boot.h>
char devSignature[3];
char devSerial[9];
void getDevSignature(char* devsign)
{
for (size_t i = 0; i<3; i++)
{
devsign[i] = boot_signature_byte_get(i*2);
}
}
void getDevSerial(char* devSerial)
{
uint8_t add = 0;
for (size_t i = 0; i<9; i++)
{
if(i>=6)add=1;
devSerial[i+add] = boot_signature_byte_get(0x0E + i + add);
}
char tmp = devSerial[0];
devSerial[0]=devSerial[1];
devSerial[1]=tmp;
tmp = devSerial[2];
devSerial[2] = devSerial[3];
devSerial[3] = tmp;
tmp = devSerial[4];
devSerial[4] = devSerial[5];
devSerial[5] = tmp;
}
int main(void)
{
getDevSignature(devSignature);// Device Signature -hangi mikrodenetleyici
getDevSerial(devSerial); // Serial Number - seri numarası
}
Arduino IDE için örnek kod:
char devSerial[9];
#include <avr/boot.h>
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Device Signature : ");
for (uint8_t i = 0; i < 3; i++)
{
Serial.print(boot_signature_byte_get(0x0 + i*2),HEX);
Serial.print(" ");
}
Serial.println("");
getDevSerial(devSerial);
Serial.println("Device Serial Number : ");
for (uint8_t i = 0; i < 9; i++)
{
Serial.print(devSerial[i],HEX);Serial.print(" ");
}
}
void loop() {
// put your main code here, to run repeatedly:
}
void getDevSerial(char* devSerial)
{
uint8_t add = 0;
for (size_t i = 0; i<9; i++)
{
if(i>=6)add=1;
devSerial[i+add] = boot_signature_byte_get(0x0E + i + add);
}
char tmp = devSerial[0];
devSerial[0]=devSerial[1];
devSerial[1]=tmp;
tmp = devSerial[2];
devSerial[2] = devSerial[3];
devSerial[3] = tmp;
tmp = devSerial[4];
devSerial[4] = devSerial[5];
devSerial[5] = tmp;
}
Elimdeki 3 değişik atmega328p ile denedim her birinde farklı seri numaraları elde ettim, bir eşleşme olacağını düşünmüyorum, deneyenler yorumlara yazabilir.
-Kolay gelsin.