vpv.vpv (02.03.2017 10:07, просмотров: 320) ответил Adept на бутлодырь...
1. Стрим с UART'а загоняется в большой кольцевой буфер (сколько там RAM есть у камня) по прерываниям от приемника. Поток останавливается/пускается по сигналам RTS/CTS, для этого у тех же МАХ232 есть 2 приемника и 2 передатчика TTL <-> RS232. Нужен ещё таймер в своем прерывании, как только таймер увидел, что буфер на 1/3 освободился - активирует CTS, как только приемный буфер UART видит, что он заполнился - он этот CTS сбрасывает.
2. Основная программа выгребает порциями данные из большого приемного буфера в буфер страницы и программирует флеш. Пока данные не кончатся.
3. Все время подсчитывается CRC. Если в конце оно совпадает - CRC дописывается, формируются флажки "Programm done" ну или у кого там что. :)) иначе - ошибка.
Основная идея - прием данных с UART сделать автоматическим, в прерываниях, а программированием флеша заняться вручную, по опросу готовности. Хотя, наверное, можно и наоборот. :))
Если интересно, кусок программирования для Меги128 у меня когда-то выглядел вот так (компилятор Си - IAR AVR. За стиль написания не пинать, давно это было :))
//------------------------------------------------------------------------
// Если тип прошивки "F", то программирование FLASH
if (cProgType == 0x0F)
{
unsigned int iword;
unsigned char __hugeflash* pcfpointer;
unsigned char __hugeflash* pcflenth;
unsigned char __hugeflash* pcfcounter = 0;
pcflenth = (unsigned char __hugeflash*) lProgLenth;
if ((!pcflenth) || (pcflenth > (unsigned char __hugeflash*)0x1E000))
ShowFatalError(6); // Длина данных неверна
//-------------------------------------------------------------------------
while(pcflenth) // пока есть данные для программирования
{
pcfpointer = pcfcounter; // начать новую страницу
while (SPMCSR & (1<<SPMEN));// Ожидание готовности SPM;
__disable_interrupt();
__AddrToZ24ByteToSPMCR_SPM // стереть страницу
((unsigned char __farflash*)pcfpointer, (1<<PGERS)+(1<<SPMEN));
__enable_interrupt();
// ***********************************************************************
do // заполнять страницу...
{
iword = (unsigned int) cDecryptByte();
pcflenth --;
if (pcflenth)
{
iword |= ((unsigned int) cDecryptByte())<<8;
pcflenth --;
}
while (SPMCSR & (1<<SPMEN)); // Ожидание готовности SPM;
__disable_interrupt();
__AddrToZ24WordToR1R0ByteToSPMCR_SPM // записать слово в буфер страницы
((unsigned char __farflash*)pcfcounter, iword, (1<<SPMEN));
__enable_interrupt();
pcfcounter += 2; // переместить указатель
if (!pcflenth)
break; // если заполнять больше нечем, то выйти
}
while ((unsigned char)pcfcounter); // ... до границы страницы
// ***********************************************************************
while (SPMCSR & (1<<SPMEN)); // Ожидание готовности SPM;
__disable_interrupt();
__AddrToZ24ByteToSPMCR_SPM // записать страницу
((unsigned char __farflash*)pcfpointer, (1<<PGWRT) | (1<<SPMEN));
__enable_interrupt();
}
//------------------------------------------------------------------------
// ---------------- программирование FLASH закончено -----------------
while (SPMCSR & (1<<SPMEN)); // Ожидание готовности SPM;
__disable_interrupt();
__DataToR0ByteToSPMCR_SPM // разрешить RWW секцию
(0, (1<<RWWSRE)+(1<<SPMEN));
__enable_interrupt();
while (SPMCSR & (1<<SPMEN)); // Ожидание готовности SPM;
// прием CRC-32
*((unsigned char*)&lProgCrc32 ) = cDecryptByte();
*((unsigned char*)&lProgCrc32 +1) = cDecryptByte();
*((unsigned char*)&lProgCrc32 +2) = cDecryptByte();
*((unsigned char*)&lProgCrc32 +3) = cDecryptByte();
// записать новую сигнатуру в EEPROM
lE2ProgCrc32 = lProgCrc32;
lE2ProgLenth = lProgLenth;
// подсчитать CRC-32 записанного FLASH и сравнить
{
unsigned long ltemp = 0;
unsigned char __hugeflash* pcHFpoint = 0;
unsigned char __hugeflash* pcflenth =
(unsigned char __hugeflash *) lProgLenth;
while (pcflenth--)
ltemp = lCrc32Table [(ltemp >> 24) ^ *pcHFpoint++] ^ (ltemp << 8);
if (ltemp != lProgCrc32)
ShowFatalError(8); // не совпадает загруженная CRC-32!!!
}
ShowOk();
}
"cDecryptByte();" - это выгребание байта из приемного буфера с дешифрацией.