Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32L151 FLASH_ACR_LATENCY FLASH_ACR_ACC64
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
MiklPolikov
Переключаю напряжение питание ядра и тактовую частоту ~5раз в секунду. Это вместе со входом в спящие режимы позволяет экономить питание.
Но в самом экономичном сочетании частот и напряжений, которое согласно документации допустимо, процесор виснет раз в сутки.
В связи с этим вопрос, правильно ли я понимаю то что изложено в PM0062 FLASH and EEPROM Programming на с 50.
Понимаю написанное там так :

1)Биты ACC64 и LATENCY нужно ставить и снимать одновременно, другие вариации бессмысленны. Причём ставить сначала ACC64 следующей командой LATENCY а снимать сначала LATENCY а следующей командой ACC64.

2)При снятых ACC64 и LATENCY допустимы только некоторые сочетания напряжение частота , те которые в верхней строчке таблицы.
А при поставленных ACC64 и LATENCY все сочетания которые и в верхней строчке и в нижней.
По этой причине биты ставятся перед увеличением частоты.
А после уменьшения снимаются по желанию, для экономии потребления.
Будь это не так, было бы противоречие : биты выставлены, а частота ещё не увеличена, стало быть процессор какое-то время находится в недопустимом режиме.

DmitryM
Цитата(MiklPolikov @ Oct 3 2013, 10:54) *
В связи с этим вопрос, правильно ли я понимаю то что изложено в PM0062 FLASH and EEPROM Programming на с 50.
Понимаю написанное там так :
1)Биты ACC64 и LATENCY нужно ставить и снимать одновременно, другие вариации бессмысленны. Причём ставить сначала ACC64 следующей командой LATENCY а снимать сначала LATENCY а следующей командой ACC64.
2)При снятых ACC64 и LATENCY допустимы только некоторые сочетания напряжение частота , те которые в верхней строчке таблицы.
А при поставленных ACC64 и LATENCY все сочетания которые и в верхней строчке и в нижней.
По этой причине биты ставятся перед увеличением частоты.
А после уменьшения снимаются по желанию, для экономии потребления.
Будь это не так, было бы противоречие : биты выставлены, а частота ещё не увеличена, стало быть процессор какое-то время находится в недопустимом режиме.

На самом деле это сделано (ACC64 & LATENCY) для возможности Prefetch. Смотрите таблицу 5 с возможными конфигурациями ACC64, LATENCY, Prefetch.

Цитата
Prefetch is useful when the Flash memory cannot be accessed for a CPU cycle. In this case,
the number of wait states (LATENCY) must be correctly programmed in the Flash access
control register (FLASH_ACR) according to the frequency of the CPU clock (HCLK) and the
supply voltage of the device.
John Silver
Цитата(MiklPolikov @ Oct 3 2013, 09:54) *
Будь это не так, было бы противоречие : биты выставлены, а частота ещё не увеличена, стало быть процессор какое-то время находится в недопустимом режиме.


Думаю это не важно, главное в этот момент не обращаться к флеш (у меня вешалось когда оперировал константами).
Хотя, всегда лучше соблюсти рекомендации производителя.
ViKo
Перед повышением частоты я сначала устанавливал бы LATENCY, а потом ACC64.
MiklPolikov
Цитата(John Silver @ Oct 3 2013, 15:24) *
Думаю это не важно, главное в этот момент не обращаться к флеш (у меня вешалось когда оперировал константами).
Хотя, всегда лучше соблюсти рекомендации производителя.


Так в том и дело, что сами выставления бит командами вида FLASH->ACR |=FLASH_ACR_ACC64; и есть обращение к константам.
ViKo
Выполнение микроконтроллером команд и есть обращение к flash. Может повезти, что 2-3 команды будут браться из буфера (если он задействован), но потом все равно будет читаться flash.
DmitryM
Цитата(ViKo @ Oct 3 2013, 15:24) *
Перед повышением частоты я сначала устанавливал бы LATENCY, а потом ACC64.

Производитель же четко это оговорил
Цитата
ST strongly recommends to use the following software sequences to tune the number of
wait states needed to access the Flash memory with the CPU frequency.

Increasing the CPU frequency (in the same voltage range).
● Program the 64-bit access by setting the ACC64 bit in FLASH_ACR
● Check that 64-bit access is taken into account by reading FLASH_ACR
● Program 1 WS to the LATENCY bit in FLASH_ACR
● Check that the new number of WS is taken into account by reading FLASH_ACR
● Modify the CPU clock source by writing to the SW bits in the RCC_CFGR register
● If needed, modify the CPU clock prescaler by writing to the HPRE bits in RCC_CFGR
● Check that the new CPU clock source or/and the new CPU clock prescaler value is/are
taken into account by reading the clock source status (SWS bits) or/and the AHB
prescaler value (HPRE bits), respectively, in the RCC_CFGR register

Decreasing the CPU frequency (in the same voltage range).
● Modify the CPU clock source by writing to the SW bits in the RCC_CFGR register
● If needed, modify the CPU clock prescaler by writing to the HPRE bits in RCC_CFGR
● Check that the new CPU clock source or/and the new CPU clock prescaler value is/are
taken into account by reading the clock source status (SWS bits) or/and the AHB
prescaler value (HPRE bits), respectively, in the RCC_CFGR register
● Program the new number of WS to the LATENCY bit in FLASH_ACR
● Check that the new number of WS is taken into account by reading FLASH_ACR
● Program the 32-bit access by clearing ACC64 in FLASH_ACR
● Check that 32-bit access is taken into account by reading FLASH_ACR
ViKo
Цитата(DmitryM @ Oct 3 2013, 15:06) *
Производитель же четко это оговорил

Да, оговорил. Ну, значит, так надо и делать.
MiklPolikov
Цитата(ViKo @ Oct 3 2013, 16:16) *
Да, оговорил. Ну, значит, так надо и делать.


Я спрашиваю о другом.
То что при переходе на более высокую частоту ACC64 и LATECY установить надо это понятно.
А при возврате обратно на низкую, нужно снять или это по желанию ?
Размышления в п 2) первого сообщения.
ViKo
Цитата(MiklPolikov @ Oct 3 2013, 16:23) *
Я спрашиваю о другом.
То что при переходе на более высокую частоту ACC64 и LATECY установить надо это понятно.
А при возврате обратно на низкую, нужно снять или это по желанию ?

Можете все оставить. Только работать будет медленнее, из-за WS, который не нужен. И больше тока потреблять, чем, если буфер отключить.
DmitryM
Цитата(MiklPolikov @ Oct 3 2013, 17:23) *
А при возврате обратно на низкую, нужно снять или это по желанию ?
Размышления в п 2) первого сообщения.

Опять же я указывал таблицу 5.
Цитата
32-bit access reduces the consumption, so it is used when the CPU frequency is low. In this case, the number of
wait states must be 0

Т.е. если Вы хотите уменьшить энергопотребление переходом в 32-битный режим снимая ACC64, то и LATENCY и PRFTEN должны быть сброшены. Посмотрите внимательнее таблицу 5, там это четко оговорено.
MiklPolikov
Ещё вопросы :
1) Какие условия должны соблюдаться для записи во Flash ? Частота / voltage range ? Не вижу ничего про это в документе Flash and EEPROM programming
2) Допустим я разблокировал память для записи, пишу в неё массив в цикле.
В это время происходит какое-то прерывание, программа переходит в его обработчик. А там константы, т.е. чтение из флэш. Что при этом произойдёт ?

MiklPolikov
Проблема в том, что процессор висит если я переключаюсь (несколько раз в секунду) между

SYSTEM_CLOCK_HSI_VOLTAGE_RANGE_2;
SYSTEM_CLOCK_MSI_VOLTAGE_RANGE_3;

Зависает каждые 10ч работы, чёткой привязки ко времени нет.
Если я переключаюсь между

SYSTEM_CLOCK_HSI_VOLTAGE_RANGE_1;
SYSTEM_CLOCK_MSI_VOLTAGE_RANGE_1;

то всё хорошо.
При этом если я запускаю в бесконечном цикле
while(1)
{
SYSTEM_CLOCK_HSI_VOLTAGE_RANGE_2;
SYSTEM_CLOCK_MSI_VOLTAGE_RANGE_3;
}
То процессор не зависает.

Коды макросов приведены ниже.
Вопрос : на первый взгляд код правильный ? Причина зависания глубже чем то что я просто что-то не понял из документации ?


CODE

#define VOLTAGE_RANGE_1 {\
while(PWR->CSR & PWR_CSR_VOSF){}\
PWR->CR &=~ PWR_CR_VOS_1;\
PWR->CR |= PWR_CR_VOS_0;\
while(PWR->CSR & PWR_CSR_VOSF){}}

#define VOLTAGE_RANGE_2 {\
while(PWR->CSR & PWR_CSR_VOSF){}\
PWR->CR &=~ PWR_CR_VOS_0;\
PWR->CR |= PWR_CR_VOS_1;\
while(PWR->CSR & PWR_CSR_VOSF){}}

#define VOLTAGE_RANGE_3 {\
while(PWR->CSR & PWR_CSR_VOSF){}\
PWR->CR |= PWR_CR_VOS_0;\
PWR->CR |= PWR_CR_VOS_1;\
while(PWR->CSR & PWR_CSR_VOSF){}}


#define SYSTEM_CLOCK_HSI_VOLTAGE_RANGE_1 {\
VOLTAGE_RANGE_1;\
RCC->CFGR &=~(RCC_CFGR_SW_0 | RCC_CFGR_SW_1);\
RCC->CFGR |=RCC_CFGR_SW_0;\
FLASH->ACR &=~FLASH_ACR_LATENCY;\
FLASH->ACR &=~FLASH_ACR_ACC64;}

#define SYSTEM_CLOCK_HSI_VOLTAGE_RANGE_2 {\
VOLTAGE_RANGE_2;\
FLASH->ACR |=FLASH_ACR_ACC64;\
FLASH->ACR |=FLASH_ACR_LATENCY;\
RCC->CFGR &=~(RCC_CFGR_SW_0 | RCC_CFGR_SW_1);\
RCC->CFGR |=RCC_CFGR_SW_0;}

#define SYSTEM_CLOCK_MSI_VOLTAGE_RANGE_1 {\
RCC->CFGR &=~(RCC_CFGR_SW_0 | RCC_CFGR_SW_1);\
FLASH->ACR &=~FLASH_ACR_LATENCY;\
FLASH->ACR &=~FLASH_ACR_ACC64;\
VOLTAGE_RANGE_1;}

#define SYSTEM_CLOCK_MSI_VOLTAGE_RANGE_2 {\
RCC->CFGR &=~(RCC_CFGR_SW_0 | RCC_CFGR_SW_1);\
FLASH->ACR &=~FLASH_ACR_LATENCY;\
FLASH->ACR &=~FLASH_ACR_ACC64;\
VOLTAGE_RANGE_2;}

#define SYSTEM_CLOCK_MSI_VOLTAGE_RANGE_3 {\
FLASH->ACR |=FLASH_ACR_ACC64;\
FLASH->ACR |=FLASH_ACR_LATENCY;\
RCC->CFGR &=~(RCC_CFGR_SW_0 | RCC_CFGR_SW_1);\
VOLTAGE_RANGE_3;}
сарматъ
а вы локализовали место и причину зависания?
MiklPolikov
Цитата(сарматъ @ Oct 8 2013, 09:08) *
а вы локализовали место и причину зависания?

Нет.

Я сейчас задаю приземлённый вопрос : последовательность, в которой я переключаю частоты, напряжения и биты ACC64 и LATENCY правильная ? С учётом того
что программа из каждого макроса может уйти в прерывание? Разумеется, в прерывании не будет другого макроса переключающего частоту.
MiklPolikov
Помогло глобальное запрещение прерываний на время действий с частотой, напряжением, битами ACC64 LATENCY
MiklPolikov
Цитата(MiklPolikov @ Oct 11 2013, 12:34) *
Помогло глобальное запрещение прерываний на время действий с частотой, напряжением, битами ACC64 LATENCY

+ включение генератора HSI перед каждым переключением на тактирование от него. Уж не знаю почему, но при частоте переключений несколько раз в секунду он нерегулярно ~раз в сутки оказывается выключен сам собой.

Муть какая-то.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.