OpenOCD, LPC17xx та srec_cat

Boot-loader в мікроконтролерах LPC17xx очікує 32-бітну контрольну суму перших семи слів прошивки (вміст вказівника стеку, та перших шести векторів) на місці не використовуваного вектора по адресі 0x1C. В це слово записується мінус-сума перших семи слів. Схожим чином перевіряє наявність програми і бутлоадер LPC2000.
OpenOCD вміє «на льоту» генерувати таку контрольну суму при програмуванні мікроконтролера, потрібно лишень в команді flash вказати аргумент calc_checksum (ця команда є у файлі target/lpc17xx.cfg пакету).
Але чомусь він не генерує її для звірки вмісту (верифікації). Причому сам він знає, що мені буде незручно, раніше навіть писав щось таке:

Warn : Verification will fail since checksum in image (0x00000000) to be written
    to flash is different from calculated vector checksum (0xeffee33a).
Warn : To remove this warning modify build tools on developer PC to inject
    correct LPC vector checksum.

Тобто якщо йому дати для верифікації той же файл, що йому було дано для прошивки, то він видасть помилку в тих чотирьох байтах. Ось нещодавно я в черговий раз підятягнув з репозиторію оновлення, зібрав та встановив свіжісіньку версію, однак маю:

~/scmRTOS/trunk/Samples/CortexM3/GCC/LPC17XX/4-Debug$ make program
Open On-Chip Debugger 0.6.0-dev-00640-g40801d2-dirty (2012-08-07-17:02)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.sourceforge.net/doc/doxygen/bugs.html
debug_level: 0
adapter_nsrst_delay: 200
jtag_ntrst_delay: 200
1000 kHz
    TargetName         Type       Endian TapName            State      
--  ------------------ ---------- ------ ------------------ ------------
 0* lpc1766.cpu        cortex_m3  little lpc1766.cpu        running
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x00001360 psp: 0x10000808
auto erase enabled
wrote 8192 bytes from file ./exe/4-Debug.bin in 0.674930s (11.853 KiB/s)
Error: checksum mismatch - attempting binary compare
diff 0 address 0x0000001c. Was 0x3a instead of 0x00
diff 1 address 0x0000001d. Was 0xe3 instead of 0x00
diff 2 address 0x0000001e. Was 0xfe instead of 0x00
diff 3 address 0x0000001f. Was 0xef instead of 0x00
No more differences found.
in procedure 'verify_image'
make: *** [program] Помилка 1
~/scmRTOS/trunk/Samples/CortexM3/GCC/LPC17XX/4-Debug$

Як на мене, це робить його можливість генерувати контрольний код на запис мало корисним, однак треба самому згенерувати для верифікації.
Ну що ж, займуся отим «modify build tools on developer PC to inject correct LPC vector checksum»… Якраз нещодавно сам радив використовувати srecord замість того, щоб навантажувати роботою програматор 🙂

Зазвичай в Makefile знаходяться рядки на зразок:

$(BIN): $(ELF)
    @echo --- make $@
    @$(OBJCOPY) -O binary $(ELF) $(BIN)

Щоб локалізувати зміни в Makefile, для файлу прошивки з контрольною сумою я залишаю ім’я $(BIN) яке використовується далі для програмування та верифікації.
Для проміжного файлу без контрольної суми вибираю $(BIN).nocsum. Тепер в моєму Makefile знаходяться рядки:

# Стара команда генеруює файл без CHECKSUM, але з іншим іменем.
$(BIN).nocsum: $(ELF)
    @echo --- extract binary file $@
    @$(OBJCOPY) -O binary $^ $@

# Нова команда генерує файл з контрольною сумою в потрібному місці.
$(BIN): $(BIN).nocsum
    @echo --- generate binary file with CSUM $@
    @srec_cat $^ -BIN -CR 0 0x1c -LECN 0x1C 4 4 $^ -BIN -E 0 0x20 -O $@ -BIN

Оцей рядок з ключами для srec_cat слід розшифрувати:

1
2
3
4
5
6
7
    @srec_cat \
    $^ -BIN \
    -CR 0 0x1c  \
    -LECN 0x1C 4 4 \
    $^ -BIN \
    -E 0 0x20 \
    -O $@ -BIN
  1. Кличу srec_cat (одна з програм пакету srecord).
  2. Кажу йому завантажити файл $(BIN).nocsum (тобто $^, що є першим файлом списку залежностей, який у даному випадку і є файлом $(BIN).nocsum), вказуючи, що він бінарний, ключем -BIN (man srec_cat).
  3. Ключем -CR 0 0x1C запускаю фільтр CROP, залишаючи для подальшої роботи лише шматочок адрес з 0 до 0x1B (man srec_input, розділ Input Filters).
  4. Обчислюю Little_Endian_Checksum_Negative того, що тепер в буфері. Сума має бути записана в адресу 0x1C, довжина суми чотири байти (перша четвірка в ключах) та при обчисленні суми слід брати чотирибайтові слова (друга четвірка).
  5. Знову завантажую початковий бінарний файл.
  6. Але тепер фільтром Exclude викидаю з нього байти з 0 по 0x1F, адреси при цьому не зсуваю.
    В діапазоні адрес 0..0x1b знаходиться початок цього файлу з першими векторами.
    В діапазоні 0x1c..0x1f щойно порахована контрольна сума, тому в буфер слід записати лише залишок файлу.
  7. Записую у файл $(BIN) (тобто у файл $@, який є метою правила), також в бінарному вигляді, прошивку з доданою контрольною сумою.

І маю радісне:

~/scmRTOS/trunk/Samples/CortexM3/GCC/LPC17XX/4-Debug$ make program
Open On-Chip Debugger 0.6.0-dev-00640-g40801d2-dirty (2012-08-07-17:02)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.sourceforge.net/doc/doxygen/bugs.html
debug_level: 0
adapter_nsrst_delay: 200
jtag_ntrst_delay: 200
1000 kHz
    TargetName         Type       Endian TapName            State      
--  ------------------ ---------- ------ ------------------ ------------
 0* lpc1766.cpu        cortex_m3  little lpc1766.cpu        running
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x00001360 psp: 0x10000808
auto erase enabled
wrote 8192 bytes from file ./exe/4-Debug.bin in 0.686367s (11.656 KiB/s)
verified 6900 bytes in 0.073601s (91.551 KiB/s)
shutdown command invoked
~/scmRTOS/trunk/Samples/CortexM3/GCC/LPC17XX/4-Debug$

p.s. Повний Makefile знаходитьcя в прикладах scmRTOS для CortexM3/GCC/LPC17xx.

Leave a Reply

[flagcounter image]