GenaSPB 11 10 июня, 2012 Опубликовано 10 июня, 2012 (изменено) · Жалоба Поставил чип ATSM3S4B взамен AT91SAM7S64. Обнаружилось, что при запуске холодного устрйства иногда происходит зависание (не выяснял, что стряслось). ВЫлечилось установкой значения 3 в качестве wait states для FLASH (хотя, такое рекомендуется при частоте 64 МГц только при питании 1.65 вольта). У меня же - 1.8 от внутреннего стабилизатора (китайский тестер показывает 1.75 - но это скорее всего заниженно). Или установкой 32 МГц (и 2 wait states). Вот инициализация (некоторые комментарии про частоты устарели). // Clock Source Selection static void program_mckr_css(unsigned long cssvalue) { PMC->PMC_MCKR = (PMC->PMC_MCKR & ~ PMC_MCKR_CSS_Msk) | (cssvalue & PMC_MCKR_CSS_Msk); // Wiat MCLK ready while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0) ; } // CPU prescaler static void program_mckr_pres(unsigned long presvalue) { PMC->PMC_MCKR = (PMC->PMC_MCKR & ~ PMC_MCKR_PRES_Msk) | (presvalue & PMC_MCKR_PRES_Msk); // Wiat MCLK ready while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0) ; } // If a new value for CSS field corresponds to PLL Clock, static void program_mckr_switchtopll_a(void) { program_mckr_pres(PMC_MCKR_PRES_CLK_2); // with /2 divider program_mckr_css(PMC_MCKR_CSS_PLLA_CLK); } // If a new value for CSS field corresponds to Main Clock static void program_mckr_switchtomain(void) { program_mckr_css(PMC_MCKR_CSS_MAIN_CLK); #ifdef PMC_MCKR_PRES_CLK_1 program_mckr_pres(PMC_MCKR_PRES_CLK_1); // w/o divider #else program_mckr_pres(PMC_MCKR_PRES_CLK); // w/o divider #endif } static void program_use_xtal( int useXtalFlag /* 0 - использование RC генератора, не-0 - использование кварцевого генератора */ ) { // бит CKGR_MOR_MOSCSEL - источник MAINCK это кварцевый генератор const unsigned long mor = PMC->CKGR_MOR & ~ CKGR_MOR_KEY_Msk; if (((mor & CKGR_MOR_MOSCSEL) != 0) == (useXtalFlag != 0)) return; // переключение не требуется if (useXtalFlag != 0) PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | (mor | CKGR_MOR_MOSCSEL); else PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | (mor & ~ CKGR_MOR_MOSCSEL); // ожидание переключения кварцевого генератора while ((PMC->PMC_SR & PMC_SR_MOSCSELS) == 0) ; } // Enable on-chip RC oscillator static void program_enable_RC_12MHz(void) { #ifdef CKGR_MOR_MOSCRCF_12_MHz PMC->CKGR_MOR = (PMC->CKGR_MOR & ~ (CKGR_MOR_MOSCRCF_Msk | CKGR_MOR_KEY_Msk)) | // остальные биты не трогаем CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCRCF_12_MHz; #else PMC->CKGR_MOR = (PMC->CKGR_MOR & ~ (CKGR_MOR_MOSCRCF_Msk | CKGR_MOR_KEY_Msk)) | // остальные биты не трогаем CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCRCF_12MHZ; #endif // ожидание запуска RC генератора while ((PMC->PMC_SR & PMC_SR_MOSCRCS) == 0) ; } static void program_disable_rc(void) { const unsigned long mor = PMC->CKGR_MOR & ~ (CKGR_MOR_KEY_Msk | CKGR_MOR_MOSCRCEN); PMC->CKGR_MOR = mor | CKGR_MOR_KEY(0x37); } static void program_disable_xtal(void) { const unsigned long mor = PMC->CKGR_MOR & ~ (CKGR_MOR_KEY_Msk | CKGR_MOR_MOSCXTEN); PMC->CKGR_MOR = mor | CKGR_MOR_KEY(0x37); } // Enable high-frequency XTAL oscillator static void program_enable_xtal(void) { const unsigned long mor = PMC->CKGR_MOR & ~ (CKGR_MOR_KEY_Msk | CKGR_MOR_MOSCXTST_Msk); if ((mor & CKGR_MOR_MOSCXTEN) != 0) return; // кварцевый генератор уже запущен PMC->CKGR_MOR = mor | // стврые значения битов CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCXTST(128) | CKGR_MOR_MOSCXTEN; // ожидание запуска кварцевого генератора while ((PMC->PMC_SR & PMC_SR_MOSCXTS) == 0) ; } static void program_enable_plla(unsigned pllmul, unsigned plldiv) { #ifdef CKGR_PLLAR_ONE /* Initialize PLLA */ PMC->CKGR_PLLAR = (CKGR_PLLAR_ONE | // всегда должен быть установлен ((pllmul - 1) << CKGR_PLLAR_MULA_Pos) | (0x4 << CKGR_PLLAR_PLLACOUNT_Pos) | (plldiv << CKGR_PLLAR_DIVA_Pos)); #else /* Initialize PLLA */ PMC->CKGR_PLLAR = (CKGR_PLLAR_STUCKTO1 | // всегда должен быть установлен ((pllmul - 1) << CKGR_PLLAR_MULA_Pos) | (0x4 << CKGR_PLLAR_PLLACOUNT_Pos) | (plldiv << CKGR_PLLAR_DIVA_Pos)); #endif // Ожидание запуска PLL A while (!(PMC->PMC_SR & PMC_SR_LOCKA)) ; } #if 0 // unused now. static void program_enable_pllb(void) { //unsigned timer = 0xffffff; //enum { osc_mul = 32, osc_div = 6 }; // 12 MHz / 6 * 32 = 64 MHz enum { osc_mul = 8, osc_div = 1 }; // 12 MHz / 1 * 8 = 96 MHz //enum { osc_mul = 32, osc_div = 3 }; // 12 MHz / 3 * 32 = 128 MHz /* Initialize PLLA */ PMC->CKGR_PLLBR = //CKGR_PLLBR_STUCKTO1 | // всегда должен быть установлен ((osc_mul - 1) << CKGR_PLLBR_MULB_Pos) | (0x1 << CKGR_PLLBR_PLLBCOUNT_Pos) | (osc_div << CKGR_PLLBR_DIVB_Pos); //timeout = 0; //while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT)) while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0) ; } // If a new value for CSS field corresponds to Slow Clock, static void program_mckr_switchtoslow(void) { program_mckr_css(PMC_MCKR_CSS_SLOW_CLK); #ifdef PMC_MCKR_PRES_CLK_1 program_mckr_pres(PMC_MCKR_PRES_CLK_1); // w/o divider #else program_mckr_pres(PMC_MCKR_PRES_CLK); // w/o divider #endif } #endif /* инициализация внутреннего умножителя частоты. Вход - 12 МГц, внутренний RC генератор (12 МГц). внутренняя тактовая - 48 МГц, //частота генератора - 96 МГц Частота сраавнения PLL = 12 МГц */ static void lowlevel_sam3s_init_pll_clock_12_RC12(void) { // Embedded Flash Wait State VDDCORE set at 1.80V // FWS field = 0: up to 22 MHz // FWS field = 1: up to 38 MHz // FWS field = 2: up to 64 MHz //EFC->EEFC_FMR = EEFC_FMR_FWS_Msk & (0U << EEFC_FMR_FWS_Pos); EFC->EEFC_FMR = EEFC_FMR_FWS(3); // Flash Wait State //program_mckr_switchtoslow(); // переключаем на внутренний генератор 32 кГц program_mckr_switchtomain(); // выключить ФАПЧ, если была включена (проблема, если ранее был не ресет) program_enable_RC_12MHz(); program_use_xtal(0); program_disable_xtal(); EFC->EEFC_FMR = EEFC_FMR_FWS(0); // Flash Wait State } /* инициализация внутреннего умножителя частоты. Вход - 12 МГц, внутренний RC генератор (12 МГц). внутренняя тактовая - 48 МГц, //частота генератора - 96 МГц Частота сраавнения PLL = 12 МГц */ static void lowlevel_sam3s_init_pll_clock_48_RC12(unsigned pllmul, unsigned plldiv, unsigned fws) { // Embedded Flash Wait State VDDCORE set at 1.80V // FWS field = 0: up to 22 MHz // FWS field = 1: up to 38 MHz // FWS field = 2: up to 64 MHz EFC->EEFC_FMR = EEFC_FMR_FWS(3); // Flash Wait State //program_mckr_switchtoslow(); // переключаем на внутренний генератор 32 кГц program_mckr_switchtomain(); // выключить ФАПЧ, если была включена program_enable_RC_12MHz(); program_use_xtal(0); program_disable_xtal(); program_enable_plla(pllmul, plldiv); //program_enable_pllb(); program_mckr_switchtopll_a(); EFC->EEFC_FMR = EEFC_FMR_FWS(fws); // Flash Wait State } /* инициализация внутреннего умножителя частоты. Вход - 12 МГц, кварцевый резонатор внутренняя тактовая - 64 МГц, частота генератора - 12 МГц Частота сраавнения PLL = 4 МГц */ static void lowlevel_sam3s_init_pll_clock_48_xtal12(unsigned pllmul, unsigned plldiv, unsigned ws) { // Embedded Flash Wait State VDDCORE set at 1.80V // FWS field = 0: up to 22 MHz // FWS field = 1: up to 38 MHz // FWS field = 2: up to 64 MHz EFC->EEFC_FMR = EEFC_FMR_FWS(3); // Flash Wait State //program_mckr_switchtoslow(); // переключаем на внутренний генератор 32 кГц program_mckr_switchtomain(); // выключить ФАПЧ, если была включена program_enable_xtal(); program_use_xtal(1); program_disable_rc(); program_enable_plla(pllmul, plldiv); //program_enable_pllb(); program_mckr_switchtopll_a(); EFC->EEFC_FMR = EEFC_FMR_FWS(ws); // Flash Wait State } /* функция вызывается из start-up до копирования всех "быстрых" функций и до инициализации переменных */ void arm_cpu_initialize(void) { // Disable Watchdog WDT->WDT_MR = WDT_MR_WDDIS; // Embedded Flash Wait State VDDCORE set at 1.65V // 17 MHz - 1 cycle = FWS = 0 // 30 MHz - 2 cycle = FWS = 1 // 54 MHz - 3 cycle = FWS = 2 // 64 MHz - 4 cycle = FWS = 3 // Embedded Flash Wait State VDDCORE set at 1.80V // 32 MHz - 1 cycle = FWS = 0 // 38 MHz - 2 cicle = FWS = 1 // 64 MHz - 3 cycls = FWS = 2 #if CPU_FREQ == 64000000UL enum { OSC_MUL = 32, OSC_DIV = 3, FWS = 3 }; // 12 MHz / 3 * 32 = 128 MHz #elif CPU_FREQ == 48000000UL enum { OSC_MUL = 8, OSC_DIV = 1, FWS = 2 }; // 12 MHz / 1 * 8 = 96 MHz #elif CPU_FREQ == 32000000UL enum { OSC_MUL = 16, OSC_DIV = 3, FWS = 1 }; // 12 MHz / 3 * 16 = 96 MHz #else #error Unsupported CPU_FREQ value #endif if (CPU_FREQ == 12000000UL) { // 12 МГц от внутреннего RC генератора lowlevel_sam3s_init_pll_clock_12_RC12(); } else if (0) { // умножение кварцевого генератора lowlevel_sam3s_init_pll_clock_48_xtal12(OSC_MUL, OSC_DIV, FWS); } else if (1) { // умножение от внутреннего RC генератора lowlevel_sam3s_init_pll_clock_48_RC12(OSC_MUL, OSC_DIV, FWS); } } ps: Почему-то тэг CODEBLOCK не работает... кнопки нет, а название забыл. Модераторы, поправьте пожалуйста. Изменено 10 июня, 2012 пользователем IgorKossak [codebox] для простыней, пора бы запомнить!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 24 июня, 2012 Опубликовано 24 июня, 2012 (изменено) · Жалоба Начал разбираться... Выяснил (благодара GDB), что это был не сбой. Что-то с инициализацией ADC - первый запуск как-будто не происходил, если команда давалась слишком быстро после инициализации. То, что не "сбой памяти" как он обычно выглядит, почти уверен. upd: глюки переползают в другие места. В USART, в работу с PIO... где нечему сбоить. FWS=3 и никаких проблем... Изменено 24 июня, 2012 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 68 24 июня, 2012 Опубликовано 24 июня, 2012 · Жалоба Инициализация не из флеш выполняется случайно? Т.к. про EEFC_FMR сказано следующее: No Flash read should be done during change of this register. На SAM3U изменение его содержимого при работе из флеш приводит к непредсказуемым глюкам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 24 июня, 2012 Опубликовано 24 июня, 2012 (изменено) · Жалоба Да, это интересная строчка в даташите есть и в ATSAM3S. Но, те же авторы демонстрационных программ атмела выполняют инициализацию из флеша (LowLevelInit), устанавливая вэитстэйты в значение 3 и не парятся вообще... И нет никаких указаний на размещение функции SetFlashWaitState (boards\at91sam3u-ek\board_lowlevel.c(212)) в SRAM. Опять же, значение после ресета там 0. Ради проверки сделаю "честно" - переключение процессора на высокую скорость сделаю после копирования кода в ОЗУ - результат сообщу. Интересно... пока характерных проявлений "сбоев" не обнаружил с EFC->EEFC_FMR = EEFC_FMR_FWS(2); // Flash Wait State Изменено 24 июня, 2012 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 68 24 июня, 2012 Опубликовано 24 июня, 2012 · Жалоба Но, те же авторы демонстрационных программ атмела выполняют инициализацию из флеша (LowLevelInit), устанавливая вэитстэйты в значение 3 и не парятся вообще... Ну, они в принципе не парятся. Еще проверьте правильность настройки PLL: например, занижение входной частоты тоже приводит к интересным побочным эффектам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 24 июня, 2012 Опубликовано 24 июня, 2012 (изменено) · Жалоба Правильнее было бы переключить на 12 МГц (не трогая EEFC_FMR), выполнить копирование а потом переключиться (из ОЗУ) на полную скорость... надо попробовать. Еще проверьте правильность настройки PLL: например, занижение входной частоты тоже приводит к интересным побочным эффектам. Не зря я свой код сюда целиком выложил... 12 МГц кварц, делители/умножители приведены (на 3 делим, на 32 умножаем... про вычитание единичек не забыл). PLL программируется правильно, частоты на выходах померяны не один раз. upd: сделал как хотел - переключение на 12 МГц RC osc (не трогая программирование вэйтстэйтов), копирование, переключение на 64 МГц от кварца на 12 МГц. Полёт нормальный. Изменено 24 июня, 2012 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 24 июня, 2012 Опубликовано 24 июня, 2012 (изменено) · Жалоба А вот интересно - что, только я один наткнулся на это (или все используют инициализацию из ASF с FWS=3)? Немного ранее очень "по крупному" разбирался с инициализацией - результат разбирательств в первом сообщении этой темы - так как вариант от Атмела _иногда_ не работал - не инициализировал... благодара встроенным счётчикам на ожидании готовности оно конечно проходило start up - но частота была не та, что надо. Или, все нормальные люди используют STM32? Изменено 24 июня, 2012 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 68 24 июня, 2012 Опубликовано 24 июня, 2012 · Жалоба Как видите, не Вы один. Не холивара ради: из Cortex-M3 использовал TI(Luminary), Atmel, NXP, ST. На будущее принял решение ориентироваться на NXP. Периферия и документация на нее от ST вызывает стойкое неприятие. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 28 июня, 2012 Опубликовано 28 июня, 2012 · Жалоба Тоже не ради холивара: сами пользуемся NXP, но с рыночной точки зрения наиболее перспективными кажутся ST. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
topkin 0 28 июня, 2012 Опубликовано 28 июня, 2012 · Жалоба Как видите, не Вы один. Не холивара ради: из Cortex-M3 использовал TI(Luminary), Atmel, NXP, ST. На будущее принял решение ориентироваться на NXP. Периферия и документация на нее от ST вызывает стойкое неприятие. Кому то нравится, кому то нет, к общему знаменателю мы не придем. Я вот, например, к документацией NXP так и не сдружился в свое время, серия LPC23х в частности... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться