Проекты смешанные C++/Asm с подавляющей по объему долей С++ - асм только где-то во обработчиках прерываний и очень, очень редко, уже и не помню, когда в последний раз пользовался в рабочем проекте.
В качестве инструментария: пакет EWAVR + мощный сторонний программерский редактор SlickEdit. Сборка под управлением gnu make, от самого EWAVR используеются компилятор, асм, линкер, библы, ессно, ну, словом, все то, что необходимо для компиляции. Саму оболочку использую только для запуска C-SPY.
По поводу симулятора. Симулятор как таковой в системах на МК вещь весьма бесполезная. Поясню. Симулятор - система
симулирующая (или, как это происходит на практике, пытающаяся это делать) работу программы в реальных условиях. Поскольку условия реальные воссоздать крайне сложно, если вообще возможно, то и результаты симуляции получаются соответствующими. Но все это не означает, что то, что называют симуляторами есть бесполезные вещи. Если использовать симулятор для
моделирования, то в этом случае есть приличный смысл в таких программах. Что понимается под моделированием? Под моделированием понимается прогон какого-то фрагмента кода (или части программы) при искусственном создании условий и наблюдение за поведением программы в этих условиях.
Например, мне надо отладить прием пакетов по UART. При этом меня интересует именно правильность приема байтов, проверка заголовка пакета, контрольной суммы и т.д. И для этого мне надо, чтобы на вход применика, а точнее в регистр данных приемника UART поступали эти самые байты.
Как добиться этого от симулятора, который честно, якобы, симулирует периферию МК? Я должен в этом случае создать довольно длинный и сложный стимул на соответствующюю ножку МК. Этот стимул руками писать замучаешься, да еще и ошибок наделаешь. Надо какую-нито утилитку для этого соорудить. И отладить. Возни, короче, выше ушей.
А вот как эта задача решается на "моделяторе" C-SPY. Там для этого существуют специальные макросы, позволяющие смоделировать требуемую ситуацию. Например, для упомянутого случая пишем такой код:
Код
__var T_C0_period;
__var UART_Rx_period;
__var UDR;
__var fid;
RxIn()
{
UDR = __readFile(fid);
__writeMemoryByte (UDR, 0x0c, "I/O-SPACE");
}
execUserSetup()
{
T_C0_period = 10000;
UART_Rx_period = 8000;
__cancelAllInterrupts();
__orderInterrupt("TIMER0 OVF", 1000000, T_C0_period, 0, 0, 100); // set T_C0 overflow interrupt
__orderInterrupt("USART RXC", 1151690, UART_Rx_period, 0, 0, 100); //
__setSimBreak("0x0c", "I/O-SPACE", 1, 1,"", "TRUE", "I", "RxIn()");
fid = __openFile("uart.dat", "r");
__message "fid = ", fid, "\n"; // debug
__message "err = ", err, "\n"; // debug
}
execUserExit()
{
__cancelAllInterrupts();
if(fid)
{
__closeFile(fid);
}
}
Как это работает. В системном макросе execUserSetup() происходит настройка моделятора - задаются прерывания, макросы, открывается на чтение файл "uart.dat".
Далее каждые 10000 тактов происходит прерывание от Т/С0. Каждые 8000 тактов происходит прерывание от приемника UART. При этом точно перед обращением к регистру UDR в программе (в обработчике прерывания) C-SPY генерирует так называемый immediate break при котором вызывается пользовательская функция-макрос RxIn(), в которой происходит считывание из файла очередного значения и запись его по указанному адресу, который является как раз адресом регистра UDR, после этого работа функции заканчивается и исполнение программы продолжается, но МК считывает из UDR то самое значение из файла. При следующем входе будет считано следующее значение. И т.д. Если в файле "uart.dat" было записано ff 13 0 0 1 12, то при первом прерывании будет считано ff, при втором 13, далее 0, 0, 1, 12, после этого все пойдет по кругу, но нас это уже не интересует - мы смогли спокойно посмотреть, как обработчик прерывания, получая байты от приемника UART, их обработал, весь пакет.
Далее, например, мы хотим смоделировать ситуацию, когда возникает наложение прерываний (в случае разрешения вложенных прерываний). Для этого достаточно просто указать нужные значения моментов времени (в тактах) активации прерываний и их периодов. Например, я знаю, что программа находится в прерывании от UART'а на 12530-м такте и выходит из него на 12555-м такте. Тогда задаю время активации прерывания от таймера, скажем, на 12540-м такте и спокойно наблюдаю, как обработчик прерывания прерван другим прерыванием, как работает сохранение контекста, как расходуется стек в этой более требовательной к размеру стека ситуации. Попробуйте это сделать на симуляторе, который честно симулирует периферию.

Или, скажем, надо мне смоделировать обработку потока данных от АЦП. Все аналогично, записываю во внейшний файл значения отсчетов, задаю __setSimBreak, макрос-функцию считывания данных из файла и вуаля. Полная гибкость и управляемостьь процессом моделирования. А симулятор честный годится только на то, чтобы посмотреть, как периферия инициализировалась (хотя это и в моделяторе можно посмотреть) да как, к примеру, таймер щелкает. Т.е. при начальном освоении МК эти вещи полезны, но в дальнейшем при серьезной работе от них толку почти никакого, когда есть такой инструмент, как C-SPY.
Исходя из вышесказанного, AVR Studio как средство отладки в режиме симулятора не представляется достойным инструментом по сравнению с тем же C-SPY. В режиме эмулятора (при использовании аппаратного эмулятора), конечно, ситуация другая. Но и тут C-SPY на высоте, ничем не уступает (в последней версии 4.12 научился наконец работать через USB). И по факту удобнее. В студии, к примеру, до сих пор нету окошка Locals. Вроде вещь элементарная и нужная, а до сих пор не сделали. У студии одно безоговорочное преимущество - она бесплатная.

Никого задеть и обидеть ни в коем случае не хотел, просто, как показывает опыт, народ в массе не знаком с возможностями моделятора C-SPY и нередко плюется от него. А зря.
«Отыщи всему начало, и ты многое поймёшь» К. Прутков