Да не в радостях дело Всякими манипуляциями с адресами и приведениями типов приходится достаточно плотно пользоваться. Например, мне понадобилось принять с СОМ-порта CRC-32 и положить в память. Порт USART в ATmege 128 байтовый. Я слепил первое, что пришло на ум:
// прием CRC-32
*((unsigned char*)&lProgCrc32 ) = cDecryptByte();
*((unsigned char*)&lProgCrc32 +1) = cDecryptByte();
*((unsigned char*)&lProgCrc32 +2) = cDecryptByte();
*((unsigned char*)&lProgCrc32 +3) = cDecryptByte();
Все приведения типов и адресная арифметика прекрасно уживаются. А какой код получается - прям ассемблерный:
LDI R26, LOW(lProgCrc32)
LDI R27, (lProgCrc32) >> 8
RCALL cDecryptByte
ST X+, R16
RCALL cDecryptByte
ST X+, R16
RCALL cDecryptByte
ST X+, R16
RCALL cDecryptByte
ST X, R16
Короче и лучше принять 4 байта и положить их как один лонг - не придумать.
А вот на счет чдачеств Атмела - не знаю. Вот, например. читаем описалово команды ELPM "...The program memory is organized in 16 bit words while the Z pointer is a byte address..." Вокруг да около этого места мы и ходим, по-моему. Память программ AVR 16-ти битная. И черт его дернул разбить ее на байты? Отсюда и все ляпы с функциями. IAR поправился в последнем релизе, что и немудрено, т.к., на сколько мне известно, семейство AVR разрабатывалось и изначально затачивалось под Си в сотрудничестве с IAR.
В общем, выходит, что или Атмел в связке с IAR'ом оба чудят (одни не умеют делать контроллеры, вторые не умеют писАть компиляторы), либо мы к ним слишком предвзяты... :-))