Nomor Seri PIC yang Dapat Diedit dalam File HEX

8

Saat ini saya memiliki nomor seri yang dikodekan dalam firmware saya untuk desain yang saya kerjakan. Firmware dapat membaca dan melaporkan kembali nomor seri. Itu berfungsi dengan baik untuk apa yang saya butuhkan. Masalahnya adalah bahwa setiap nomor seri baru mengharuskan saya untuk mengubah kode dan mengkompilasi ulang. Ini rumit ketika ada banyak unit yang akan dibangun, memiliki kemungkinan untuk memperkenalkan kesalahan, dan merupakan praktik buruk yang menyeluruh. Nomor seri diberikan kepada saya dan desain perangkat keras diatur dalam batu, jadi saya tidak bisa menambahkan fitur dalam perangkat keras untuk membuat serial unit (EEPROM / Silicon ID Chip / Pull-Ups). Yang ingin saya lakukan adalah mencari nomor seri di alamat tetap, mengkompilasi kode sekali, lalu mengedit alamat itu di file HEX yang dikompilasi untuk setiap nomor seri baru. Nomor direferensikan di beberapa tempat, jadi idealnya, saya ingin mendefinisikan & menemukannya sekali, kemudian referensi "variabel" di tempat lain dalam kode saya. Adakah yang tahu cara menemukan data konstan di lokasi memori spesifik yang dapat saya pilih, menggunakan C18 Compiler? Apakah ada cara yang lebih baik yang bisa disarankan seseorang?

Joel B
sumber
1
Sekitar setengah dari PIC18s memiliki 128 byte hingga 1K EEPROM. Saya berasumsi dari pertanyaan Anda, PIC18 Anda adalah salah satu dari 50% yang tidak memiliki EEPROM?
tcrosley

Jawaban:

4

Khusus untuk menyelesaikan pertanyaan tentang variabel terikat ke alamat spesifik dalam memori flash pada PIC18 dengan kompiler C18, silakan merujuk bagian "Pragmas" di hlpC18ug.chm di direktori doc tempat kompiler diinstal.

Untuk melakukan ini, Anda perlu mendefinisikan "bagian" baru dalam memori dan mengikatnya ke alamat awal

#pragma romdata serial_no_section=0x1700

Ini menciptakan bagian baru yang disebut "serial_no_section" yang dimulai pada alamat 0x1700 dalam memori flash (program) (karena kami mendefinisikan "romdata" di #pragma).

Langsung setelah baris #pragma, tentukan variabel Anda jadi:

#pragma romdata serial_no_section=0x1700
const rom int mySerialNumber = 0x1234;
#pragma romdata

Sekarang Anda memiliki 0x12 di alamat 0x1700 dan 0x34 di alamat 0x1701 dalam memori (karena PIC18 menggunakan model little-endian). "Const rom" memastikan bahwa kompiler mengetahui bahwa ini adalah tipe variabel const, dan bahwa variabel tersebut terletak pada memori "rom" dan karenanya perlu diakses melalui instruksi membaca tabel.

#pragma romdataPernyataan akhir memastikan bahwa setiap deklarasi variabel berikut ini ditautkan ke bagian memori default sebagai linker melihat cocok daripada mengikuti di bagian "serial_no_section".

Sekarang semua kode dapat dengan mudah merujuk variabel "mySerialNumber", dan Anda tahu persis apa alamat nomor seri dapat ditemukan di dalam memori.

Mengedit kode HEX bisa sedikit menantang karena Anda perlu menghitung checksum untuk setiap baris yang Anda edit. Saya sedang mengerjakan kelas C ++ untuk memecahkan kode dan menyandikan file Intel HEX yang seharusnya membuat ini lebih mudah, tetapi belum selesai. File decoding berfungsi, encoding lagi belum diimplementasikan. Proyek (jika Anda tertarik) ada di sini https://github.com/codinghead/Intel-HEX-Class

Semoga ini membantu

Stuart Cording
sumber
4

Saya telah melakukan nomor seri (s / n singkatnya) dengan cara yang mirip dengan apa yang Joel gambarkan. Saya menggunakan kompilator PIC18F4620 dan CCS. Lokasi s / n dalam memori Flash memaksa hingga 4 byte terakhir. Karena saya hanya menggunakan 80% Flash, kompiler dan tautan saya tidak akan menulis kode yang dapat dieksekusi dalam 4 byte terakhir.

Lalu saya punya 2 cara alternatif untuk benar-benar menulis s / n ke unit individu:

  • CCS in-circuit debugger (ICD) memiliki fitur yang memungkinkan untuk memanipulasi setiap lokasi di dalam Flash. Itu adalah hack yang berguna. Sayangnya, dalam revisi selanjutnya mereka telah menghapusnya.
  • PIC memiliki tautan serial ke PC. s / n diunggah melalui itu. Firmware memiliki rutin yang akan menerima s / n dan menyimpannya di Flash.

Membalas komentar Joel

Tidak tahu tentang C18, tetapi kompiler CCS dilengkapi dengan fungsi pustaka write_program_eeprom(...)dan read_program_eeprom(...). Di sini terlihat seperti apa mereka berkumpul.

.................... write_program_eeprom (i_ADDR, iWord);
EF84: BSF FD0.6
EF86: CLRF FF8
EF88: MOVLW 7F
EF8A: MOVWF FF7
EF8C: MOVLW F0
EF8E: MOVWF FF6
EF90: MOVLB 0
EF92: BRA EF24
EF94: MOVLW F0
EF96: MOVWF FF6
EF98: MOVFF 490, FF5
EF9C: TBLWT * +
EF9E: MOVFF 491, FF5
EFA2: TBLWT *
EFA4: BCF FA6.6
EFA6: BSF FA6.4
EFA8: RCALL EF3C
EFAA: RCALL EF3C
EFAC: CLRF FF8
EFAE: CLRF FF8
.................... iWord = read_program_eeprom (i_ADDR); 
EF60: CLRF FF8
EF62: MOVLW 7F
EF64: MOVWF FF7
EF66: MOVLW F0
EF68: MOVWF FF6
EF6A: TBLRD * +
EF6C: MOVF FF5, W
EF6E: TBLRD *
EF70: MOVFF FF5,03
EF74: CLRF FF8
EF76: MOVLB 4
EF78: MOVWF x90
EF7A: MOVFF 03.491
Nick Alexeev
sumber
1
Ya, inilah tepatnya yang saya minta! Bisakah Anda menggambarkan atribut kode apa yang Anda gunakan untuk mengemas S / N Anda ke dalam beberapa byte terakhir flash?
Joel B
"Firmware memiliki rutin yang akan menerima s / n dan menyimpannya di Flash" write_program_eeprom(...)dan read_program_eeprom(...). EEPROM dan Flash adalah dua hal yang berbeda!
m.Alin
@ m.Alin Begitulah fungsi "kalengan" yang datang dengan ccompiler CCS dipanggil. Mereka benar-benar akan menulis dan membaca Flash.
Nick Alexeev
2

Saya sudah melakukan ini beberapa kali. Biasanya saya mendefinisikan area info firmware di lokasi tetap dalam memori program, kemudian menulis sebuah program yang membuat file HEX serial dari file HEX template. Ini semua adalah hal yang mudah dilakukan.

Dalam produksi, Anda menjalankan program bersambung satu kali setelah semua tes lulus. Itu membuat file HEX sementara dengan nomor seri unik, yang akan diprogram ke dalam PIC, kemudian file HEX sementara dihapus.

Saya tidak akan membiarkan lokasi dipindahkan, kemudian harus menemukannya. Itu dapat mengubah setiap bangunan saat tautan bergerak. Saya telah melakukannya untuk PIC yang sangat kecil seperti seri 10F di mana konstanta ini adalah bagian dari instruksi MOVLW. Dalam kasus-kasus itu saya minta baca file MAP dengan cepat untuk menentukan di mana lokasi tersebut. Saya memiliki kode parsing file MAP MPLINK di perpustakaan hanya untuk tujuan itu.

Untuk meletakkan sesuatu di lokasi tetap, tentukan segmen pada alamat tetap. Linker akan menempatkan segmen absolut seperti itu terlebih dahulu, kemudian yang relocatable di sekitarnya. Jangan lupa untuk menggunakan CODE_PACK alih-alih hanya CODE pada PIC 18, kalau tidak Anda akan berurusan dengan kata-kata instuksi keseluruhan alih-alih byte individu. Misalnya (cukup mengetik, tidak berjalan melewati assemlber):

.fwinfo code_pack h'1000 '; area info firmware di alamat yang diketahui tetap
         db h'FFFFFFFF '; nomor seri, diisi oleh program produksi
         db fwtype; jenis ID dari firmware ini
         db fwver; nomor versi
         db fwseq; buat nomor urut
Olin Lathrop
sumber
2

Saya sarankan menyimpan nomor seri di alamat tetap. Bergantung pada kompiler / tautan Anda dan bagian yang dimaksud, ada beberapa pendekatan yang dapat Anda ambil:

  1. Tentukan bagian yang dapat dipindahkan yang akan berisi nomor seri, gunakan arahan #pragma dalam kode Anda untuk memaksa nomor seri ke dalam bagian itu, dan paksa alamat bagian itu dalam spesifikasi tautan.
  2. Untuk bagian yang dapat membaca memori kode secara langsung, kecualikan area memori dari area yang boleh digunakan oleh linker (mis. Katakan bagian itu mis. Empat byte lebih kecil daripada sebenarnya), lalu baca nomor seri dalam kode menggunakan sesuatu seperti `((const panjang tidak bertanda *) 0x3FFC)`.
  3. Untuk bagian yang tidak dapat membaca memori kode secara langsung, Anda mungkin dapat menempatkan instruksi "RETLW" di beberapa alamat tetap, dan kemudian meyakinkan linker bahwa ada fungsi yang dapat dipanggil yang mengembalikan 'byte' di alamat tersebut. Maka orang akan mengatakan misalnya "out_hex (ser_byte0 ()); out_hex (ser_byte1 ()); out_hex (ser_byte2 ()); untuk menampilkan byte dari nomor seri.
supercat
sumber
Semua PIC 18F dapat membaca memori program mereka melalui mekanisme membaca tabel.
Olin Lathrop
Itu benar. Beberapa bagian 14-bit dapat membaca memori program juga. Bahkan pada PIC yang dapat membaca memori program, retlwpendekatannya seringkali jauh lebih cepat (pada PIC 18-bit, a callke a retlwmembutuhkan empat siklus total; menggunakan clrf TBLPTRU/movlw xx/movwf TBLPTRH/movlw xx/movwf TBLPTRL/tblrd *+/movf TABLAT,wakan membutuhkan delapan).
supercat
1

Saya akan melakukan yang sebaliknya: kompilasi dan tautkan kode, lalu cari tahu di mana nilai disimpan dari file linker. Anda mungkin perlu menemukan variabel secara eksplisit di segmen yang dipetakan ke flash.

Jangan meminta ini, tetapi perangkat lunak PC yang saya berikan untuk programmer Wisp648 saya memiliki kemampuan untuk membaca file .hex, memodifikasi lokasi tertentu, dan menulis file .hex kembali (ke file yang sama atau yang lain). Tidak perlu ada programmer saya hadir. Sumber tersedia (dalam Python), lisensi memungkinkan semua penggunaan: www.voti.nl/xwisp Mungkin berguna setelah Anda menyelesaikan masalah utama Anda.

Wouter van Ooijen
sumber
Terima kasih @Wouter van Ooijen! Saya mencoba untuk menghindari pendekatan "mencari tahu di mana nilai disimpan", karena itu kemungkinan besar berarti nilai tersebut dipindahkan pada kompilasi berturut-turut dan mengharuskan saya (atau beberapa orang sedih yang datang di belakang saya) untuk mencari tahu di mana nilai tersebut terletak lagi, pasti memperkenalkan masalah.
Joel B