Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: У кого-нибудь есть bootloader для mega32 и ft232rl?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
zheka
Господа, долго рылся в интернете в поисках - в основном вижу варианты, где D+ и D- напрямую подключены к контроллеру.
У меня Mega32 работает в связке с FT232RL.
Реально ли как-то организовать устройство, чтобы пр программировании не перетыкать перемычку, а просто выключать основную программу, работающую с устройством и включать программу прошивальщик?
Есть ли какие-нибудь готовые бутлоадеры, работающие с FT232RL или же придется переделывать? Желательно под COdeVision
demiurg_spb
Вам подойдёт любой бутлоадер для уарта коих подавляющее большинство.
Ведь FT232RL - это преобразователь USB в уарт и обратно.
На стороне ПК видится как виртуальный ком-порт. На стороне контроллера обычный уарт.
Слово USB можете вообще игнорироватьsm.gif
Ну а алгоритм входа в загрузчик можете организовать по вашему вкусу.
zheka
Нашел вот это.
Нельзя ли как-то пошагово объяснить, как все это состыковать?
1. В коде есть строки типа " #if defined _CHIP_ATMEGA128_ "
нужно где-то в начале написать "#defined _CHIP_ATMEGA128_ " ? Или же компилятор CodeVision будет брать эту нформацию из настроек проекта?

2. В коде написано "Clock frequency : 7.372800 MHz". Поменяю я настройки проекта на 16 Мгц, пересчитаю настройки USART, надо ли что-то еще делать?

3. Чем программировать? МОжно ли программировать средствами COdeVision, просто указав номер порта, присвоенного FT232 ?

4. Как организовать вход в загрузку? Не могу же я заставить программу-программатор на компе слать какое-то кодовое слово, по которому запускается процесс загрузки?

Извините за глупые вопросы, я в этом полный ноль, чтение информации по бутлоадерам пока что приводит в смятение...
haker_fox
QUOTE (zheka @ Feb 5 2012, 02:12) *
1. В коде есть строки типа " #if defined _CHIP_ATMEGA128_ "
нужно где-то в начале написать "#defined _CHIP_ATMEGA128_ " ? Или же компилятор CodeVision будет брать эту нформацию из настроек проекта?

Вряд ли из настроек проекта. Хотя... Вы исходник под какой компилятор нашли? Обычно игроков несколько: IAR, GCC, ну еще ImageCraft. CodeVision тоже популярен...
QUOTE (zheka @ Feb 5 2012, 02:12) *
2. В коде написано "Clock frequency : 7.372800 MHz". Поменяю я настройки проекта на 16 Мгц, пересчитаю настройки USART, надо ли что-то еще делать?

Да вроде бы этого должно быть достаточно. Хотя, нужно смотреть как бут реализован. М.б. ему что-нить от системной частоты нужно.
QUOTE (zheka @ Feb 5 2012, 02:12) *
4. Как организовать вход в загрузку? Не могу же я заставить программу-программатор на компе слать какое-то кодовое слово, по которому запускается процесс загрузки?

Как душа пожелает rolleyes.gif На AVR у меня при запуске (Вы же понимаете, что вначале всегда запускается бут) бутлоадер ждет в течение небольшого времени символ 's'. Если появился - входим в бут, если нет - запускаем приложение.
На ARM применен "более серьезныей подход". Там в течение 5 секунд нужно нажать 'Y' для входа, либо запустится приложение. Но и бут там с командной строкой и множеством "ненужных" прибамбасов rolleyes.gif
QUOTE (zheka @ Feb 5 2012, 02:12) *
Извините за глупые вопросы, я в этом полный ноль, чтение информации по бутлоадерам пока что приводит в смятение...

Все нормально. Глупых вопросов не бывает. Бывает глупая реакция на вопросы rolleyes.gif rolleyes.gif rolleyes.gif
А вообще для AVR написать свой бут по мотивам готовых, да при поддержки даташита - не очень сложно... ИМХО (самое смешное, что бут под AVR я с нуля не писал ни разу, а вот для ARM - сделал )))) )


Прикладываю свой бут. Он под 485-й интерфейс, но это не принципиально. Должен без переделки работать на USART (ведь отличие интерфейсов только в том, что первый - полудуплекс). За качество загрузчика - простите) Не задавался целью это дело красифо оформить. Да, ну и чип там другой - ATmega8. Но, думаю, это не принципиально...
zheka
Мой под CodeVIsion.
После того, как создал тему досконально проштудировал выложенный код и в прнципе, во всем разобрался. Осталось только два вопроса.
1. Чем после этого программировать-то по USB? Я прошил бут, прошил основную программу. Она точно работает, так как отправляет по USART приветствие и на отправку условного символа "<" отвечает. ПРобовал после этого в настройках CodeVision поменять номер порта програамматора на соответствующий - пытается программировать, но вытает сообщение которое обычно бывает при отсутствии ответа от МК.

2. как-то странно все работает. Поставил флажки в программе загрузки и основной программе. Когда прошиваю бут - срабатывает флажок бута и из бута программа не выходит. КОгда прошиваю основную программу - срабатывает ее флажок. В параметрах проекта бутлодера тип "bootloader" ставил, и при программмировании пишет, что прошиваю бут. Размер - 512 слов, начальный адрес бута 0xE00. ВРоде все правильно. Где копнуть, как понять где ошибка?

Цитата
Вряд ли из настроек проекта. Хотя...

Наверное все-таки как-то из настроек проекта параметр берется:
в хидере бута есть такие строки
Код
#elif defined _CHIP_ATMEGA32_
#define  DeviceID     'E'    // Mega32
#define     FlashSize     'n'    // Flash 32k
#define     PageSize     'S'    // 128 Bytes
#define  PageByte      128     // 128 Bytes
#define  AddressLshift    7
#asm(".EQU SpmcrAddr=0x57")
#include <mega32.h>


Когда связываюсь через терминал с устройством (путем отправки "<") устройство в ответ присылает те самые символы "Ens".

Вот для информации:
главный цикл бутлодера:
CODE
// USART initialization <<<
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 9600
UCSRA=0x00;
UCSRB=0xD8;
UCSRC=0x86;
//UBRRH=0x00;
//UBRRL=0x2F;
DDRD.5=1;
ubbr = (unsigned long int)_MCU_CLOCK_FREQUENCY_ / (BAUDRATE * 16) - 1;
UBRRH=ubbr >> 8;
UBRRL = ubbr;

putchar('>'); // ПРИ ЗАПУСКЕ КОНТРОЛЛЕРА ПОСТОЯННО ШЛЕТСЯ ПРИВЕТСТВИЕ.

while ( (! (UCSRA&128)) &( i < 32000) ) i++; //wait for data in or timeout
if (i < 32000) inchar= getchar();
if (inchar == '<') BootLoad(); // ПРИ ПОСЫЛКЕ ИЗ ТЕРМНАЛА УКАЗАННОГО СИМВОЛА ПРОГРАММА ЗАХОДИТ В
// BootLoad, проверено установкой флажка.
ExecCode(); // set up and jump to application


А вот собственно функция запуска основной программы:
CODE
void main(void)
{

void ExecCode(void)
{
#if defined _CHIP_ATMEGA128_
RAMPZ = 0;
#endif
MCUCR = 0x01; // Enable interrupt vector select
MCUCR = 0x00; // Move interrupt vector to flash

//<---- ФЛАЖОК, ПОСТАВЛЕННЫЙ ЗДЕСЬ СРАБАТЫВАЕТ
#asm("jmp 0x00"); // Run application code


//<---- А ФЛАЖОК, ПОСТАВЛЕННЫЙ ЗДЕСЬ УЖЕ НЕ СРАБАТЫВАЕТ, ТО ЕСТЬ ПРЫЖОК НА НУЛЕВОЙ АДРЕС ВСЕ ТАКИ ПРОИСХОДИТ.
// ВОТ ТОЛЬКО ПО ЭТОМУ АДРЕСУ НИЧЕГО НЕ ВЫПОЛНЯЕТСЯ, БУТ ЗАПУСКАЕТСЯ СНАЧАЛА.
}

}



Что делать и кто виноват?

В общем, складывается ощущение, что бутлодер пишется не на адрес 3E00, а на нулевой адрес, затирая основную программу. Потому что флажок в функции срабатывает постоянно, то есть программа бутлодера запускается вновь и вновь.
haker_fox
QUOTE (zheka @ Feb 5 2012, 15:04) *
В общем, складывается ощущение, что бутлодер пишется не на адрес 3E00, а на нулевой адрес, затирая основную программу. Потому что флажок в функции срабатывает постоянно, то есть программа бутлодера запускается вновь и вновь.

Все правильно. А как же программатор узнает, с какого адреса записать бут? Для этого в hex-файле (или любом другом), должны быть соответствующие адреса.
Тут нужно линкеру объяснить, с какого адреса размещать прошивку. См. документацию на CodeVision/
zheka
У меня в CodeVision настроено с какого адреса писать бут. См скрин.

Господа интересует другое. Нормальная связка бута и программы для его прошивки.
То что я скачал содержит бут. В архиве есть файл со ссылкой на модифицированный прошивальщик. Ссылка битая.

Скачал я еще два архива откуда-то: MegaLoadU.rar и Bootloader.rar. В первом из них прошивальщик без кода бутлоадера. К сожалению с тем бутом, что у меня есть, не работает. Во втором код бутлоадера, и программой прошивальщика, которая не запускается.

А глядя на это:
CODE
void BootLoad(void)
{
// Send chip data to the programming software so that it knows
// how to format transmissions
putchar(DeviceID);
putchar(FlashSize);
putchar(BootSize);
putchar(PageSize);
// "!" means all ok and send the next data if there is more
putchar('!');
while(1)
{
PageAddress = (unsigned int)getchar() << 8; // Receive PageAddress high byte
PageAddress += getchar(); // Add PageAddress low byte
putchar(PageAddress);
if (PageAddress == 0xffff) ExecCode(); // The windows program sends this value when finished
#if defined _CHIP_ATMEGA128_
if (PageAddress >> 8) RAMPZ = 1;
else RAMPZ=0;
#endif
PageAddress = PageAddress << AddressLshift; //essentially the same as multiply by PageSize
if (GetPage()) //receive one page of data followed by a checksum byte and verify data
{
for (i=0;i<PageByte;i+=2) //fill temporary buffer in 2 byte chunks from PageBuffer

{
Pagedata=PageBuffer[i]+(PageBuffer[i+1]<<8);
while (SPMCR&1); //wait for spm complete
CurrentAddress=PageAddress+i;
spmcrval=1;
#asm
movw r30, r6 ;//move CurrentAddress to Z pointer
mov r1, r3 ;//move Pagedata MSB reg 1
mov r0, r2 ;//move Pagedata LSB reg 1
sts SpmcrAddr, r10 ;//move spmcrval to SPM control register
spm ;//store program memory
#endasm
}

while (SPMCR&1); //wait for spm complete
spmcrval=3; //erase page
#asm
movw r30, r4 ;//move PageAddress to Z pointer
sts SpmcrAddr, r10 ;//move spmcrval to SPM control register
spm ;//erase page
#endasm

while (SPMCR&1); //wait for spm complete
spmcrval=5; //write page
#asm
movw r30, r4 ;//move PageAddress to Z pointer
sts SpmcrAddr, r10 ;//move spmcrval to SPM control register
spm ;//write page
#endasm

while (SPMCR&1); //wait for spm complete
spmcrval=0x11; //enableRWW see mega8 datasheet for explanation
// P. 212 Section "Prevent reading the RWW section
// during self-programming
#asm
sts SpmcrAddr, r10 ;//move spmcrval to SPMCR
spm
#endasm
if (CheckFlash()) putchar('!'); //all ok, send next page
else putchar('@'); //there was an error, resend page
} //end if (GetPage())
else putchar('@'); //there was an error ,resend page
}
}


Возникает сильное желание написать прошивальщик самому.
У кого-нибудь есть РАБОЧАЯ связка бутлодера под CodeVision и утилиты для прошивки? Или информация о том, как залить прошивку через бутлоадер средствами CodeVision?
demiurg_spb
Цитата(zheka @ Feb 5 2012, 12:34) *
CodeVision?
Очень настоятельно рекомендую отказаться от CodeVision и чем раньше вы сделаете это тем быстрее поймёте смысл моего совета.
zheka
Более или менее разобрался. Работает и бутлоадер и основная программа, из одной в другую командами перехожу без проблем.

Теперь что касается софта - я так и не нашел подходящего (для скачанного мной бута есть лишь битая ссылка на модифицированную программу).

Кроме того мне будет удобно интегрировать код для перепрошивки контроллера в тот софт, что общается с устройством. Как выяснилось, алгоритм его передачи не такой уж и сложный.

У меня только возник вопрос по поводу формата HEX файла:

Цитата
:0A000000FFFFFFFFFFFFFFFFFFFF00
:10000A00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6
:10001A00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6
:10002A00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6
:10003A00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6
:10004A00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6


Объясните мне, почему размер страницы 128, а вышеуказанные строки - по 17 байт?
Код бутлодера, который я привел подразумевает загрузку нескольких страниц, из 128 байт и одного байта контрольной суммы.
Как исходя из этого алгоритма следует читать HEX файл?
_Артём_
Цитата(zheka @ Feb 5 2012, 12:14) *
Теперь что касается софта - я так и не нашел подходящего (для скачанного мной бута есть лишь битая ссылка на модифицированную программу).

Кроме того мне будет удобно интегрировать код для перепрошивки контроллера в тот софт, что общается с устройством. Как выяснилось, алгоритм его передачи не такой уж и сложный.


Напишите свой софт. Это просто.


Цитата(zheka @ Feb 5 2012, 12:14) *
У меня только возник вопрос по поводу формата HEX файла:


Не проще его преобразовать в bin?
И ним работать.


Цитата(zheka @ Feb 5 2012, 12:14) *
Объясните мне, почему размер страницы 128, а вышеуказанные строки - по 17 байт?

Размер записи в файле хекс и размер страницы флэш в контроллере - величины совершенно не связанные между собой: запись в файле может быть по 1,2,-100 байт (столько, сколько сгенерит линкер).
А размер страницы зависит только от чипа.

И кстати вышеуказанные строки по 16 байт(опечатка?).


Цитата(zheka @ Feb 5 2012, 12:14) *
Как исходя из этого алгоритма следует читать HEX файл?

Посмотрите формат хоть в вики.
zheka
Спасибо, я уже нашел информацию по хекс-формату, и пишу свой софт.
haker_fox
QUOTE (zheka @ Feb 5 2012, 17:34) *
и утилиты для прошивки?

HyperTerminal, terraterm, minicom и др...? rolleyes.gif
FAV
Посмотрите проект, как раз на CodeVision http://sites.google.com/site/osamaslab/Hom...ls/spark_loader
zheka
Спасибо, я уже разобрался, контроллер пашет, из программы в бут и наоборот переключается.
Программу для прошивки и искать не стал, ибо задумавшись о деталях моей задачи понял, что код прошивальщика мне надо писать свой и вставлять его в основную компьютерную программу. Софт написал, обмен данными наладил.

Остался один вопрос. Вот фрагмент бутлоадера:
Код
char GetPage(void)
{
char LocalCheckSum = 0;
char CheckSum = 0;
// The programming software generates a simple checksum in the
// same fashion as below to check for data transmission errors
for (j=0;j<PageByte;j++)
    {
    PageBuffer[j]=getchar();
    LocalCheckSum += PageBuffer[j];
    }
CheckSum = getchar();  
if (LocalCheckSum == CheckSum) return 1;
else return 0;
}


То есть в бутлоадере контрольная сумма проверяется для всей страницы, длина которой для mega32 - 128 байт.
А в HEX файле контрольная сумма после каждого 16 байта.
Мне что делать - в прошивальщике пересчитывать контрольную сумму для каждой страницы или в бутлодыре каждые 16 байт? Или я что-то не понял...


И вот :
Код
:10026000 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E
:10027000 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E


Строки одинаковые, а контрольные суммы разные....

Как понять "сумма всех байт в строке должна быть равна нулю" ?
Считать байты данных или все байты кроме двоеточия?
haker_fox
QUOTE (zheka @ Feb 9 2012, 01:33) *
То есть в бутлоадере контрольная сумма проверяется для всей страницы, длина которой для mega32 - 128 байт.
А в HEX файле контрольная сумма после каждого 16 байта.
Мне что делать - в прошивальщике пересчитывать контрольную сумму для каждой страницы или в бутлодыре каждые 16 байт? Или я что-то не понял...

Я полагаю, что считать КС нужно для каждой строки hex-файла, т.к. количество данных в строке может быть и меньше 16. Может ли быть больше - не знаю, не встречал. Меньше точно встречал.
Ну и рамер страницы МК и размер данных строки файла ни как не связанные величины.
QUOTE (zheka @ Feb 9 2012, 01:33) *
И вот :
CODE
:10026000 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E
:10027000 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E


Строки одинаковые, а контрольные суммы разные....

Как понять "сумма всех байт в строке должна быть равна нулю" ?
Считать байты данных или все байты кроме двоеточия?

Как это строки одинаковые? В первой строке 10026..., во второй 10027...
Если Вы просуммируете все байы (0x10 + 0x02 + 0x60 + ... + 0x9e, это для первой строки), то должен получиться ноль.
Считать все байты. Двоеточие это не байт)))
Имейте в виду, что кроме байтов данных в hex-файле еще может содержаться служебная информация, которая непосредственно в память МК не прошивается.

В общем, настоятельно рекомендую скачать документ от Intel, описывающий формат intel hex.
zheka
спасибо, теперь более или менее ясно.

Тогда объясните мне - бутлодер, что я привел, наверняка писал человек, который его же и проверил.
Исходя из этого кода суммируются только байты данных. И почему то у них сумма байтов равна контрольной сумме, а по идее должна быть равна 0 минус контрольная сумма.
Или я чего-то не понял.

Цитата
Имейте в виду, что кроме байтов данных в hex-файле еще может содержаться служебная информация, которая непосредственно в память МК не прошивается.

я так понял, служебка в первой строке, а в последней признак конца?
haker_fox
QUOTE (zheka @ Feb 9 2012, 11:59) *
Тогда объясните мне - бутлодер, что я привел, наверняка писал человек, который его же и проверил.
Исходя из этого кода суммируются только байты данных. И почему то у них сумма байтов равна контрольной сумме, а по идее должна быть равна 0 минус контрольная сумма.
Или я чего-то не понял.

Честно говоря, не знаю, чего там этот человек понаписал. Документ, описывающий формат intel hex на рассудит.
Вы знаете, хоть я и недавно писал бут по ARM (а там анализ hex тоже был), я просуммировал в калькуляторе приведенные Вами строки. Сумма всех байт равна нулю. Попробуйте сами. Это дело 1 минуты.

QUOTE (zheka @ Feb 9 2012, 11:59) *
я так понял, служебка в первой строке, а в последней признак конца?

Это частный случай. Для AVR может быть всегда так. Вот здесь ничего не скажу. Я просматриваю кадждую строку. Проверяю, что я буду писать в память. Не исключаю, что сделал не совсем правильно. Но работает.
Есть 6 типов записей (или строк) в hex файле. Один из них это данные, один - конец строки. Про остальные лучше почитать. Там с сегментами памяти связано. И похоже, введено для поддержки прошивок объемом более 65 кБ.
На этот вопрос, сам бы хотел услышать мнение уважаемого сообщества...
zheka
Цитата
Вы знаете, хоть я и недавно писал бут по ARM (а там анализ hex тоже был), я просуммировал в калькуляторе приведенные Вами строки. Сумма всех байт равна нулю. Попробуйте сами. Это дело 1 минуты.


Я тоже проверял, вы меня просто не поняли. Код бутлодера, который я выложио принимает ТОЛЬКО байты данных, суммирует их и сравнивает с контрольной суммой, приходящей вслед. То есть, по мнению автора бута, контрольная сумма - это просто сумма байтов, а не дополнение до нуля.
Впрочем, пишу для себя, софт пишу свой, так что сделаю как мне удобнее. А на мой взгляд все-же удобнее дополнять до нуля, так как в этом случае, можно просуммировать все байты со всеми контрольными суммами в каждой строке и подтвердить истинность всей страницы.
zheka
Покурил документ от Интел.
Не раскуривается следующий момент:
Цитата
. Смещение представляет собой сдвиг адреса на четыре бита влево. Например, смещение равное 0x1234 даст реальный адрес 0x12340.


Я так понял, смещение - это когда требуется записать фрагмент не в начале памяти, а где-нить в середине. А смещение должно означать начальный адрес программы. И все последующие строки имеют адрес, тот что в них записан, просуммированный со смещением.
Тогда почему 0x1234 даст реальный адрес 0x12340 ? Я так подумал, что програма начинается с этого адреа, а следующая строка при 16-ти байтах даст 0x1244...

Грубо говоря, если у меня смещение 0x1234, а адрес в одной строке 0x00, а в другой 0xFF, какое действие мне нужно произвести, чтобы сообщить истинный адрес бутлоадеру?
demaven
"Тогда почему 0x1234 даст реальный адрес 0x12340"
потому что следующие 16 байт информации будут располагаться начиная с адреса 0х12340 по 0х1234F
zheka
ниче не понимаю.
На hex калькуляторе посчитал - 0x1234 +0x01 = 0x1235...

Цитата
потому что следующие 16 байт информации будут располагаться начиная с адреса 0х12340 по 0х1234F


Так ведь для того, чтобы из 0x1234 получить 0x12340 нужно не прибавить 16, а умножить на 16....



Не, я не спорю, я хочу найти ошибку, как говорится, в своей ДНК.

Объясните если у меня смещение 0x1234, а адрес в одной строке 0x00, а в другой 0xFF, какое действие мне нужно произвести, чтобы сообщить истинный адрес этих строк бутлоадеру? Может я тогда пойму.
haker_fox
QUOTE (zheka @ Feb 9 2012, 19:17) *
Объясните если у меня смещение 0x1234, а адрес в одной строке 0x00, а в другой 0xFF, какое действие мне нужно произвести, чтобы сообщить истинный адрес этих строк бутлоадеру? Может я тогда пойму.

Адрес байта будет равен LBA + LINE OFFSET + номер позиции байта в строке.
LBA = ULBA << 16.
Про эти величины читайте в даташите rolleyes.gif Я этим занимался в начале года. Уже все подзабыл. Помню поверхностно.
В приложении на скорую руку писанный парсер hex-файлов. Для IBM PC. Там исходник и исполняемый файл. Скомпилировано GCC.
Запускаете HexParser.exe, он запрашивает имя файла. Вводите, например c:\temp\1.hex. Он выводит информацию по каждой строке в консоль. Делал для себя. За чистоту и честность не ручаюсь) Очень надеюсь, что он Вам чуть чуть поможет )))
Рекомендую Вам отладить этот алгоритм тоже на компьютере. Он не зависит от железа. Можно даже через виртуальные ком-порты отлаживать два приложения: клиент и сам бут. Затем в релизе допилить аппаратную часть...

З.Ы. Парсер под ARM... Поэтому записываемые данные после адреса - 32 бита... Но сути это не меняет...
zheka
Ни хрена не понимаю....
ВОт у меня адресное пространство, я хочу зарезервировать первые 256 байт.
Значит смещение у меня будет 0xFF.

Исходя из предложенной арифметикик при смещении 0xFF реальный адрес будет 0xFF0, то есть в десятичном исчислении 4080, и я прокину первые 4 килобайта?


Мне это непонятно. Может кто-нибудь на пальцах объяснить?

Перерыл все свои хексы, везде смещение 0, даже примера нет, чтобы на практике понятьдля чего оно нужно и почему именно так рассчитывается.

На Вашем скрине смещением (offset) обозвано то, что я привык считать адресом.... я еще больше запутался..
haker_fox
QUOTE (zheka @ Feb 9 2012, 21:06) *
Ни хрена не понимаю....
ВОт у меня адресное пространство, я хочу зарезервировать первые 256 байт.
Значит смещение у меня будет 0xFF.

Исходя из предложенной арифметикик при смещении 0xFF реальный адрес будет 0xFF0, то есть в десятичном исчислении 4080, и я прокину первые 4 килобайта?

Так в AVRовской прошивке ULBA, как правило, будет равно нулю...
QUOTE (zheka @ Feb 9 2012, 21:06) *
На Вашем скрине смещением (offset) обозвано то, что я привык считать адресом.... я еще больше запутался..

Для прошивки размером менее 65 кБ, смещение и будет адресом... В общем в документации на формат файла, есть формула для вычисления адреса (см. скрин)
ILYAUL
Посмотрите "Косвенная адресация операнда" может прояснит
demaven
Файл формата Intel HEX может состоять из любого количества записей. Каждая запись представляет собой ASCII-строку, состоящую из нескольких пар 16-ричных цифр. Строка должна начинаться с символа двоеточия и оканчиваться парой символов CR и LF. Запись состоит из пяти полей следующего формата:
LLAAAATTDD...CC
Каждая группа букв (LL, AAAA, TT и т. д.) представляет собой отдельное поле. Каждая буква — отдельную 16-ричную цифру (4 бита). Каждое поле состоит, как минимум, из двух 16-ричных цифр (байт). Ниже представлена расшифровка полей записи:
Каждая запись в файле Intel HEX должна начинаться с двоеточия.
LL Поле длины – показывает количество байт данных (DD) в записи. AAAA Поле адреса – представляет начальный адрес записи. TT Поле типа. Оно может принимать следующие значения: 00 запись содержит данные 01 запись представляет код конца файла 02 запись представляет адрес сегмента для i8086 04 запись расширения линейного адреса DD Поле данных. Запись может содержать несколько байт данных. Количество байт данных должно соответствовать полю LL. CC Поле контрольной суммы. Поле контрольной суммы вычисляется путем сложения значений всех байт (пар 16-ричных цифр) записи по модулю 256 с последующим переводом в дополнительный формат.
Запись данных

Пример одной записи данных:
10246200464C5549442050524F46494C4500464C33
где 10 Количество байт данных (16 байт) 2462 Адрес памяти, куда будет помещена запись. 00 Тип записи — данные. 464C...464C Данные 33 Контрольная сумма записи
Запись адреса сегмента

Файл формата Intel HEХможет содержать записи для процессоров i8086, которые определяют адрес сегмента (иначе говоря — номер параграфа, один параграф — это 16 байт). Если используется директива H167, то этот тип записи заменяет запись расширенного линейного адреса. Номер параграфа используется как смещение адреса для всех записей данных, следующих за этой записью. Смещение представляет собой сдвиг адреса на четыре бита влево. Например, смещение равное 0x1234 даст реальный адрес 0x12340. Пример записи:
020000021000EC
где: 02 Количество байт данных 0000 В этом типе записи всегда равно 0000 02 Тип записи 02 (запись расширенного линейного адреса). 1000 Номер параграфа (реальный адрес будет равен 0x10000). EC Контрольная сумма
Запись расширенного адреса

Когда используется директива H167, файл формата Intel HEX возможно будет содержать записи расширенного линейного адреса. Этот тип записи определяет значения двух старших байт абсолютного адреса (биты 16-31). Эти два старших байта адреса будут применяться как смещение адреса для всех записей данных, следующих за этой записью. Пример записи:
0200000400FFFB
где: 02 Количество байт данных 0000 Всегда равно 0 04 Тип записи 04 (запись расширенного линейного адреса) 00FF Старшее слово смещения адреса (0x00FF0000) FB Контрольная сумма Запись Конец Файла (EOF) Файлы формата Intel HEX должны иметь запись Конца Файла (EOF). Пример записи:
00000001FF
где: 00 Количество байт записи 0000 Поле игнорируется. Не имеет значения, что там записано, но обычно всегда равно 0 01 Тип записи 01 (Конец Файла) FF Контрольная сумма, вычисленная как 01h + NOT(00h + 00h + 00h + 01h). Пример файла формата Intel HEX
020000021000EC
10C20000E0A5E6F6FDFFE0AEE00FE6FCFDFFE6FD93
10C21000FFFFF6F50EFE4B66F2FA0CFEF2F40EFE90
10C22000F04EF05FF06CF07DCA0050C2F086F097DF
10C23000F04AF054BCF5204830592D02E018BB03F9
020000020000FC
04000000FA00000200
00000001FF

Использование в AVR

Прошивка для AVR микроконтроллеров обычно компилируется в формат Intel Hex. Следует учесть следующие моменты:
Любая команда AVR-контроллера занимает не менее 2-х байт, поэтому размер слова составляет 2 байта. Flash-память AVR адресуется в словах,
поэтому команда вида jmp 0x65 будет указывать на 101-е слово (0x65=101) или 202-й байт (он же 0xCA).
Байты в слове читаются "задом наперёд". Например, если в hex-файле встречается слово "12C0", то интерпретировать его нужно как "C0 12",
что будет означать rjmp 18.
zheka
Ура!
Контроллер и софт пришли наконце-то к взимопониманию. Контроллер шьется, CRC совпадает, сам контроллер ошибок не выдает.
Правда пока промашки с адресами. В связи с чем у меня вопрос.

Пересмотрел кучу хекс-файлов, которые выдает CodeVison - везде первай строка содержит не 16, а скажем 4 байта. Причем эта строка не информационная,
а именно с данными. А приведенный код принимает строго по 128 байт для mega16.
И все бы хорошо, я могу переделать программу которая читает строки как надо, тупо набивает буфер 128 байтами, отдельно считает CRC, отдельно высчитывает адрес,
так как в этом случае все страницы будут начинаться не с того адреса, с которого начинается строка. Но вот бемпокоит меня следующее -страницы флеш памяти в
контроллере - это понятие условное, можно ли рассматривать память как непрерывное адресное пространство? Или же страницы имеют физические номера с закрепленными адресами?
Как записывать файл начинающийся строками:
Код
:04
:10
:10
:10
:10

если имеющийся у меня бутлоадер принимает одинаковые пачки по 128 байт? Переделать не проблема, просто я боюсь трогать то, что по идее должно работать.
haker_fox
QUOTE (zheka @ Feb 10 2012, 17:18) *
Как записывать файл начинающийся строками:
CODE
:04
:10
:10
:10
:10

если имеющийся у меня бутлоадер принимает одинаковые пачки по 128 байт? Переделать не проблема, просто я боюсь трогать то, что по идее должно работать.

Гм... здесь проблема, учитывая, что запись страницы в память занимает еще и некоторое время... У Вас софт для прошивки какой? Я имею в виду, самописный? Если да, то можно ввести контроль потока, и передавать данные по 128 байт, ждать пока запишется страница, а затем выдавать очередную порцию данных.
Если для прошивки используется эмулятор терминала, то вводят задержки на символ и передаваемые строки...

Можно организовать буфер и складывать в него данные с запасом...
zheka
Цитата
Гм... здесь проблема, учитывая, что запись страницы в память занимает еще и некоторое время... У Вас софт для прошивки какой? Я имею в виду, самописный? Если да, то можно ввести контроль потока, и передавать данные по 128 байт, ждать пока запишется страница, а затем выдавать очередную порцию данных.
Если для прошивки используется эмулятор терминала, то вводят задержки на символ и передаваемые строки...


Родненький, я у вас спрашиваю, как девку подцепить, а вы мне рассказываете как соску сосать. Софт у меня самопальный. Пока я контроль обмена данных не наладил, задержки не оценил, у меня ничего не прошивалось. Сейчас все пашет, но не до конца, так как бутлоадер неуниверсальный, он жрет только пакеты определенных размеров и просит CRC, когда хочет. Данные из файла, прежде чем передавать нужно пережевать, как именно и почему я уже написал.

Цитата
Можно организовать буфер и складывать в него данные с запасом...

Организую обязательно. Как сделать буфер и записать в него я не то что знаю, мне спрашивать стыдно.

Каежтся я понял, почему файлы начинаются строками с разной длиной - последняя строка всегда заполнена значащими байтами до последнего символа. А количество символов в первой строке - это остаток от деления на 16, как бы вместо последней короткой строки решили сделать первую. Оригинально.

Цитата
:060000000C943E000C947C
:100006006E000C9400000C9400000C9400000C94FC


zheka
Полтретьего ночи...
Заработало! Все шьется без проблем.
haker_fox
QUOTE (zheka @ Feb 11 2012, 06:29) *
Полтретьего ночи...
Заработало! Все шьется без проблем.

Судя по окрепшему тону в сообщении №29, похоже действительно все у Вас работает.
Поздравляю.
zheka
Нет... я рано радовался. Какие-то места пишутся криво.
Пытаясь разобраться я упростил задачу - не читаю HEX файл, а генерирую данные сам, точнее пишу только нули. ОДнако нули пишутся только в первые 128 байт.

Вот мой код в C++ Builder:
Код
ADDRESS=0x00;
  for (ic = 0; ic < 10; ic++)
  {

    ADDRESS_HB=(unsigned char)(ADDRESS>>8); // Получаем старший байт
    ADDRESS_LB=(unsigned char)ADDRESS;     // Получаем младший байт
    CRC=0;
       CommandTrans(ADDRESS_HB); //Передаем старший байт
        recieved_byte=Recieved(); // получаем от контроллера сообщение, какой байт он принял
        RichEdit1->Lines->Add(AnsiString(recieved_byte)); // выводим, на практике все правильно

       CommandTrans(ADDRESS_LB); //Передаем младший байт
        recieved_byte=Recieved(); // получаем от контроллера сообщение, какой байт он принял
        RichEdit1->Lines->Add(AnsiString(recieved_byte)); // выводим, на практике все правильно

    //Выводим номер страницы, 16-ти битный Адрес и его байты (чтобы быть уверенным, что они правильно разложились)
    RichEdit1->Lines->Add("Пишем страницу №"+AnsiString(page)+" Адрес:"+AnsiString(ADDRESS)+" ("+AnsiString(ADDRESS_HB)+":"+AnsiString(ADDRESS_LB)+")");

     for (jc =0; jc < 128; jc++)
     {
      CommandTrans(0x00); //Для простоты заполняем страницу нулями
      }
      CommandTrans(0x00); //Отправляем CRC. Bootloader проверяет только сумму байт - естественно CRC равен нулю


   //Принимаем отчет от контроллера, который проверяет контрольную сумму принятых данных и проверяет
   // все ли правильно записалось во флеш
  recieved_byte=Recieved();
  if (recieved_byte==-2) RichEdit1->Lines->Add("Нет ответа от контроллера");
      else RichEdit1->Lines->Add(AnsiString((const char)recieved_byte));

       if (recieved_byte=='$') RichEdit1->Lines->Add("Ошибка FLASH");
       if (recieved_byte=='!')
            {
            RichEdit1->Lines->Add("Следующая страница");
            page_ok=1;
            }
          if (recieved_byte=='@')
           {
          RichEdit1->Lines->Add("Ошибка CRC");
           }

         Application->ProcessMessages();
         page++;


   //Увеличиваем адрес на 128 байт - адрес новой страницы.
ADDRESS+=0x80;
  }




А вот код бутлодера:
Код
char GetPage(void)
{
char LocalCheckSum = 0;
char CheckSum = 0;
// The programming software generates a simple checksum in the
// same fashion as below to check for data transmission errors

for (j=0;j<PageByte;j++)
    {
    PageBuffer[j]=getchar();
    LocalCheckSum += PageBuffer[j];
    }

CheckSum = getchar();  
//putchar(LocalCheckSum);
if (LocalCheckSum == CheckSum) return 1;
else return 0;
}


void BootLoad(void)
{
unsigned char crc,bbb;
// Send chip data to the programming software so that it knows
// how to format transmissions
putchar(DeviceID);
putchar(FlashSize);
putchar(BootSize);
putchar(PageSize);  
// "!" means all ok and send the next data if there is more
putchar('!');

while(1)
{



bbb=getchar();
PageAddress = (unsigned int)bbb << 8;  // Receive PageAddress high byte
putchar(bbb);


bbb=getchar();
PageAddress += bbb;   // Add PageAddress low byte
putchar(bbb);

if (PageAddress == 0xffff) ExecCode(); // The windows program sends this value when finished  

//#if defined _CHIP_ATMEGA128_  
//if (PageAddress >> 8) RAMPZ =  1;
//else RAMPZ=0;  
//#endif

PageAddress = PageAddress << AddressLshift; //essentially the same as multiply by PageSize


if (GetPage()) //receive one page of data followed by a checksum byte and verify data
{

  
  for (i=0;i<PageByte;i+=2) //fill temporary buffer in 2 byte chunks from PageBuffer      
    
        {
        Pagedata=PageBuffer[i]+(PageBuffer[i+1]<<8);
        while (SPMCR&1); //wait for spm complete
        CurrentAddress=PageAddress+i;
        spmcrval=1;
        #asm
        movw r30, r6  ;//move CurrentAddress to Z pointer  
        mov r1, r3      ;//move Pagedata MSB reg 1
        mov r0, r2      ;//move Pagedata LSB reg 1  
        sts SpmcrAddr, r10 ;//move spmcrval to SPM control register
        spm              ;//store program memory
        #endasm
        }    
  
    while (SPMCR&1);  //wait for spm complete
    spmcrval=3;        //erase page
    #asm
    movw r30, r4     ;//move PageAddress to Z pointer
    sts SpmcrAddr, r10  ;//move spmcrval to SPM control register              
    spm            ;//erase page
    #endasm
      
    while (SPMCR&1); //wait for spm complete
    spmcrval=5;        //write page
    #asm
    movw r30, r4     ;//move PageAddress to Z pointer
    sts SpmcrAddr, r10  ;//move spmcrval to SPM control register              
    spm            ;//write page
    #endasm

    while (SPMCR&1);  //wait for spm complete
    spmcrval=0x11;   //enableRWW  see mega8 datasheet for explanation
     // P. 212 Section "Prevent reading the RWW section
     // during self-programming
    #asm
    sts SpmcrAddr, r10 ;//move spmcrval to SPMCR              
    spm  
    #endasm
  
    if (CheckFlash()) putchar('!');  //all ok, send next page
     else putchar('$'); //there was an error, resend page
     }  //end if (GetPage())
  else putchar('@');  //there was an error ,resend page
// putchar('P');  //there was an error ,resend page
  
  }
  }



А результат, прочитанный из контроллера:
Код
:0400000000000000FC
:1000040000000000000000000000000000000000EC
:1000140000000000000000000000000000000000DC
:1000240000000000000000000000000000000000CC
:1000340000000000000000000000000000000000BC
:1000440000000000000000000000000000000000AC
:10005400000000000000000000000000000000009C
:10006400000000000000000000000000000000008C
:100074000000000000000000000000000C0D0E0F46  //вот здесь заканчивается 128 байтная страница
:10008400202020202020202020202020202020206C
:10009400202122232425262728292A2B2C2D2E2FE4   // Дальше почему-то не пишется...
:1000A400303132333435363738393A3B3C3D3E3FD4
:1000B400404142434445464748494A4B4C4D4E4FC4




Помогите найти ошибку.

Когда я испытывал полный код творилась фигня - программа писалась и даже работала. Но при изменении некоторых переменных, значение одних из них в прошивке менялось, другие оставались прежними.

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.