Перейти к содержанию
    

ATSAM3S4B flash wait states

Поставил чип 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 не работает... кнопки нет, а название забыл. Модераторы, поправьте пожалуйста.

Изменено пользователем IgorKossak
[codebox] для простыней, пора бы запомнить!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Начал разбираться... Выяснил (благодара GDB), что это был не сбой. Что-то с инициализацией ADC - первый запуск как-будто не происходил, если команда давалась слишком быстро после инициализации. То, что не "сбой памяти" как он обычно выглядит, почти уверен.

upd: глюки переползают в другие места. В USART, в работу с PIO... где нечему сбоить. FWS=3 и никаких проблем...

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Инициализация не из флеш выполняется случайно? Т.к. про EEFC_FMR сказано следующее:

No Flash read should be done during change of this register.

На SAM3U изменение его содержимого при работе из флеш приводит к непредсказуемым глюкам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, это интересная строчка в даташите есть и в ATSAM3S.

Но, те же авторы демонстрационных программ атмела выполняют инициализацию из флеша (LowLevelInit), устанавливая вэитстэйты в значение

3 и не парятся вообще...

И нет никаких указаний на размещение функции SetFlashWaitState (boards\at91sam3u-ek\board_lowlevel.c(212)) в SRAM.

Опять же, значение после ресета там 0.

 

Ради проверки сделаю "честно" - переключение процессора на высокую скорость сделаю после копирования кода в ОЗУ - результат сообщу.

 

Интересно... пока характерных проявлений "сбоев" не обнаружил с

    EFC->EEFC_FMR = EEFC_FMR_FWS(2);    // Flash Wait State

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но, те же авторы демонстрационных программ атмела выполняют инициализацию из флеша (LowLevelInit), устанавливая вэитстэйты в значение

3 и не парятся вообще...

Ну, они в принципе не парятся.

 

Еще проверьте правильность настройки PLL: например, занижение входной частоты тоже приводит к интересным побочным эффектам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Правильнее было бы переключить на 12 МГц (не трогая EEFC_FMR), выполнить копирование а потом переключиться (из ОЗУ) на полную скорость... надо попробовать.

 

Еще проверьте правильность настройки PLL: например, занижение входной частоты тоже приводит к интересным побочным эффектам.

Не зря я свой код сюда целиком выложил... 12 МГц кварц, делители/умножители приведены (на 3 делим, на 32 умножаем... про вычитание единичек не забыл). PLL программируется правильно, частоты на выходах померяны не один раз.

 

upd: сделал как хотел - переключение на 12 МГц RC osc (не трогая программирование вэйтстэйтов), копирование, переключение на 64 МГц от кварца на 12 МГц. Полёт нормальный.

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот интересно - что, только я один наткнулся на это (или все используют инициализацию из ASF с FWS=3)?

Немного ранее очень "по крупному" разбирался с инициализацией - результат разбирательств в первом сообщении этой темы - так как вариант от Атмела _иногда_ не работал - не инициализировал... благодара встроенным счётчикам на ожидании готовности оно конечно проходило start up - но частота была не та, что надо.

 

Или, все нормальные люди используют STM32?

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как видите, не Вы один.

 

Не холивара ради: из Cortex-M3 использовал TI(Luminary), Atmel, NXP, ST. На будущее принял решение ориентироваться на NXP. Периферия и документация на нее от ST вызывает стойкое неприятие.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тоже не ради холивара: сами пользуемся NXP, но с рыночной точки зрения наиболее перспективными кажутся ST.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как видите, не Вы один.

 

Не холивара ради: из Cortex-M3 использовал TI(Luminary), Atmel, NXP, ST. На будущее принял решение ориентироваться на NXP. Периферия и документация на нее от ST вызывает стойкое неприятие.

 

Кому то нравится, кому то нет, к общему знаменателю мы не придем.

Я вот, например, к документацией NXP так и не сдружился в свое время, серия LPC23х в частности...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...