Как всегда, первым запускается бут. У него инициализация (в IAR переопределена __low_level_init()) делается так:
Код
__interwork int __low_level_init(void)
{
PLLCON = 0;
PLLFEED = PLLFEED_DATA1;
PLLFEED = PLLFEED_DATA2;
//VPBDivider config
VPBDIV_bit.VPBDIV = 1;
// MAM init
MAMCR_bit.MODECTRL = 0;
MAMTIM_bit.CYCLES = 1;
MAMCR_bit.MODECTRL = 2; // MAM functions fully enabled
MEMMAP = 1;
}
{
PLLCON = 0;
PLLFEED = PLLFEED_DATA1;
PLLFEED = PLLFEED_DATA2;
//VPBDivider config
VPBDIV_bit.VPBDIV = 1;
// MAM init
MAMCR_bit.MODECTRL = 0;
MAMTIM_bit.CYCLES = 1;
MAMCR_bit.MODECTRL = 2; // MAM functions fully enabled
MEMMAP = 1;
}
В main() он сразу же передает управление в пользовательскую программу, которая слинкована в адреса 0х2000 - 0х7FFFF. И ее таблица векторов прерываний уложена в адрес 0x2000. Вот на него я и передаю управление. Т.е. точкой входа в код является ее родной вектор ресета. Далее мы попадаем в __low_level_init() основного кода, который заводит PLL на 48МГц:
Код
__interwork int __low_level_init(void)
{
//VPBDivider config
VPBDIV_bit.VPBDIV = 2;
PLLCFG_bit.MSEL = 3; // = 1 при 24МГц
PLLCFG_bit.PSEL = 0x1; // = 2 при 24МГц
PLLCON_bit.PLLE = 1; // Enable PLL
PLLFEED = PLLFEED_DATA1;
PLLFEED = PLLFEED_DATA2;
while (!PLLSTAT_bit.PLOCK); // Wait PLL lock
PLLCON_bit.PLLC = 1; // Connect PLL
PLLFEED = PLLFEED_DATA1;
PLLFEED = PLLFEED_DATA2;
// MAM init
MAMCR_bit.MODECTRL = 0;
MAMTIM_bit.CYCLES = 3; // = 2 при 24МГц
MAMCR_bit.MODECTRL = 2;
MEMMAP = 1;
return 1;
}
{
//VPBDivider config
VPBDIV_bit.VPBDIV = 2;
PLLCFG_bit.MSEL = 3; // = 1 при 24МГц
PLLCFG_bit.PSEL = 0x1; // = 2 при 24МГц
PLLCON_bit.PLLE = 1; // Enable PLL
PLLFEED = PLLFEED_DATA1;
PLLFEED = PLLFEED_DATA2;
while (!PLLSTAT_bit.PLOCK); // Wait PLL lock
PLLCON_bit.PLLC = 1; // Connect PLL
PLLFEED = PLLFEED_DATA1;
PLLFEED = PLLFEED_DATA2;
// MAM init
MAMCR_bit.MODECTRL = 0;
MAMTIM_bit.CYCLES = 3; // = 2 при 24МГц
MAMCR_bit.MODECTRL = 2;
MEMMAP = 1;
return 1;
}
С точки зрения камня, эта настройка повторная, т.к. ресета не было. Камень вешается вглухую на инсрукциях MAM init. Если вместо них написать еще что-то, то повиснем на этом чем-то. Светодиодами удалось выяснить, что вешается через 1-10 инструкций после записи PLLFEED.
Причем, именно вешается, а не аборт и т.п. (на них висят мои обработчики и они не срабатывают)! JTAG отваливается с падением IAR'a.
При этом если перестроить PLL на 24 мега (я в коде поставил комменты в тех строках, которые меняются при переходе на 24мега) все работает как часы.
Сам основной код без бутлоадера тоже прекрасно заводится на 48МГц и из ОЗУ и из флеша.
Пробовал играться с MAM - толку нет совсем. Errata тоже молчит на эту тему

Напоминает ситуацию, описанную тут. Там как раз упоминается нечетный CCO divider. У меня и получается что при 48МГц P=1, а при 24 P=2. Ну точнее в регистры пишется 1 и 2, а само деление производится на 2 или 4 соответственно.
PS: Если из первой инициализации вообще убрать строки с PLL (ибо он и так после ресета должен быть выключен), то ничего не меняется.
Никто с такой бедой не сталкивался?