Я когда-то делал не через макросы, а пользовал IAR'овские интринсики, которые ближе к регистрам и ассемблеру по мнемонике. Но у меня так шифрованная прошивка используется, которая заливается в буфер ОЗУ по последовательному порту в прерываниях. Наверное, сейчас уже не модно так писАть, было это лет 12-15 назад, для Меги128... :))
//------------------------------------------------------------------------
// Если тип прошивки "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();
}