Давненько я не присал ничего для AVR. И вот, внезапно, возникла тень прошлого - микроконтроллер at90s8535, в который необходимо было залить некое ПО.
Что за ПО - неважно. Важно то, что я пользуюсь самодельным программатором
stk500 и программой
avrdude.
Запускал прошивку микроконтроллера я такой командой:
Code: Select all
~# avrdude -P /dev/ttyUSB1 -c stk500v2 -p 8535 -U flash:w:main.hex
Тестовая программка, занимающая 240 байт (не килобайт и не мегабайт!) бинарного кода прошивалась у меня за 16 (!!!!) секунд.
Меня это очень огочило. Потому что примерный рассчёт показывал, что 8Кбайт будет с такой скоростью прошиваться около 9 минут. Это нереально долго.
Расследование показало, что если для чипа не указаны парамеры paged, page_size и num_pages, то обмен между ПК и программатором идёт побайтно, а не блоками. То есть на каждый прошиваемый байт передаётся 14 байт запроса и 14 байт ответа. Даже на скорости 115200, с которой работет stk500, это очень медленно.
Поэтому, чтобы кардинально повсить скорость прошивки, необходимо указать размер страницы для флеш-памяти процессора.
Теперь, как это всё сделать практически.
Считаем, что у вас уже есть линукс и установленный avrdude.
Файл с описаниями программаторов и процессоров лежит тут: /etc/avrdude.conf. Копируем его в свой домашний каталог под именем .avrduderc:
Code: Select all
# cp /etc/avrdude.conf ~/.avrduderc
Затем заходим в него, находим описание нужного контроллера и указываем там параметры для flash-памяти: paged=yes, page_size=256 и num_pages=size/page_size.
В нашем примере, для at90s8535 num_pages=32.
В сплойере всё описание (пример для at90s8535), исправления выделены жирным шрифтом:
#------------------------------------------------------------
# AT90s8535
#------------------------------------------------------------
part
id = "8535";
desc = "AT90S8535";
stk500_devcode = 0x61;
avr910_devcode = 0x68;
signature = 0x1e 0x93 0x03;
chip_erase_delay = 20000;
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
"x x x x x x x x x x x x x x x x";
chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0",
"x x x x x x x x x x x x x x x x";
timeout = 200;
stabdelay = 100;
cmdexedelay = 25;
synchloops = 32;
bytedelay = 0;
pollindex = 3;
pollvalue = 0x53;
predelay = 1;
postdelay = 1;
pollmethod = 0;
pp_controlstack =
0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
hventerstabdelay = 100;
progmodedelay = 0;
latchcycles = 0;
togglevtg = 0;
poweroffdelay = 0;
resetdelayms = 0;
resetdelayus = 0;
hvleavestabdelay = 15;
chiperasepulsewidth = 15;
chiperasepolltimeout = 0;
programfusepulsewidth = 2;
programfusepolltimeout = 0;
programlockpulsewidth = 0;
programlockpolltimeout = 1;
memory "eeprom"
size = 512;
min_write_delay = 9000;
max_write_delay = 20000;
readback_p1 = 0x00;
readback_p2 = 0xff;
read = " 1 0 1 0 0 0 0 0 x x x x x x x a8",
"a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
write = " 1 1 0 0 0 0 0 0 x x x x x x x a8",
"a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i";
mode = 0x04;
delay = 12;
blocksize = 128;
readsize = 256;
;
memory "flash"
paged = yes;
page_size = 256;
num_pages = 32;
size = 8192;
min_write_delay = 9000;
max_write_delay = 20000;
readback_p1 = 0xff;
readback_p2 = 0xff;
read_lo = " 0 0 1 0 0 0 0 0",
" x x x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
read_hi = " 0 0 1 0 1 0 0 0",
" x x x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
write_lo = " 0 1 0 0 0 0 0 0",
" x x x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
write_hi = " 0 1 0 0 1 0 0 0",
" x x x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
mode = 0x04;
delay = 12;
blocksize = 128;
readsize = 256;
;
memory "signature"
size = 3;
read = "0 0 1 1 0 0 0 0 x x x x x x x x",
"x x x x x x a1 a0 o o o o o o o o";
;
memory "fuse"
size = 1;
read = "0 1 0 1 1 0 0 0 x x x x x x x x",
"x x x x x x x x x x x x x x x o";
write = "1 0 1 0 1 1 0 0 1 0 1 1 1 1 1 i",
"x x x x x x x x x x x x x x x x";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "lock"
size = 1;
read = "0 1 0 1 1 0 0 0 x x x x x x x x",
"x x x x x x x x o o x x x x x x";
write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1",
"x x x x x x x x x x x x x x x x";
min_write_delay = 9000;
max_write_delay = 9000;
;
;
После такого исправления скорость увеличилась кардинально - тестовая программмка в 240 байт шьётся за доли секунды.
Ньюансы:
1. page_size нельзя указывать более 256.
2. корректно рассчитывайте num_pages, иначе avrdude ругается и отказывается работать.
Всё решение - на скорую руку, так что если вылезут какие ошибки - я не виноват.
