Служба управления питанием процессоров Blackfin |
![]() |
Добавил(а) microsin | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
В этой статье приведен перевод документации, касающейся службы управления питанием (Power Service или модуль Power Management, PM) - раздел "POWER MANAGEMENT MODULE" из даташита [1]. Эта служба библиотеки SSL (System Services Library) поддерживает динамическое управление питанием процессоров Blackfin. Рассматриваются следующие вопросы: • Как работает модуль PM - быстрый старт Модуль управления питанием (power management, далее просто сокращенно PM) предоставляет доступ ко всем возможностям динамического управления энергопотреблением (dynamic power management): • Динамическое переключение из одного рабочего режима (full-on, active, sleep, deep sleep и hibernate) в другой. Модуль PM поддерживает 2 стратегии для установки частот ядра (core clock, CCLK, она же частота процессора) и системной частоты (system clock, SCLK, она же частота шины): • Для имеющегося уровня напряжения частота ядра CCLK устанавливается на самую высокую допустимую для этого напряжения частоту. Частота системы SCLK устанавливается соответствующим образом. В обоих случаях на всех стадиях настроек делаются проверки допустимости, гарантирующие, что процессор не будет остановлен или поврежден. В разделе "Как работает модуль PM - быстрый старт" описываются стадии базовых операций, требуемые для использования модуля PM. Модуль PM использует недвусмысленную систему соглашения именований, чтобы избежать конфликтов с другими библиотеками как от Analog Devices, так и от других компаний. Для этой цели все значения перечислений enum, макроопределения #define и операторы определения типов typedef используют префикс ADI_PWR_, а функции и глобальные переменные используют эквивалентный префикс adi_pwr_ в нижнем регистре. Для каждого процессора существует 2 версии библиотеки. В текущей версии среды разработки VisualDSP++ они соответствуют конфигурациям отладки (debug) и релиза (release). В дополнение к обычным значениям по умолчанию для конфигурации debug, функции API выполняют проверки передаваемых аргументов и сообщают об ошибках соответствующими кодами возврата, если это необходимо. В версии release библиотеки большинство функций возвратят один из 2 кодов возврата: ADI_PWR_RESULT_SUCCESS при успешном завершении, или ADI_PWR_RESULT_NOT_INITIALIZED когда модуль PM не был инициализирован перед вызовом функции. Чтобы упростить конфигурацию параметров времени для драйверов устройств, используются Герцы (Hz) по умолчанию для единиц значений частот, а не мегагерцы (MHz). Для дополнительной информации см. врезку с описанием функции adi_pwr_Init. [Как работает модуль PM - быстрый старт] Следующий пример иллюстрирует использования модуля PM для конфигурирования 600 МГц процессора ADSP-BF533 платы разработчика EZ-KIT Lite board, чтобы он работал на заданных частотах ядра и шины (CCLK и SCLK), или чтобы он снизил свое энергопотребление путем снижения напряжения до 0.95V. Шаг 1: если используется контроллер EBIU для настроек параметров SDRAM, инициализируйте модуль EBIU вызовом adi_ebiu_Init(). Дополнительную информацию по модулю EBIU см. в разделе "External Bus Interface Unit Module" [1]. Шаг 2: инициализируйте модуль PM вызовом функции adi_pwr_Init, передавая ей параметры для используемой аппаратной конфигурации. Например, следующий код конфигурирует ADSP-BF533 EZ-KIT Lite. ADI_PWR_COMMAND_PAIR power_init_table[] = { // Вариант 600 MHz ADSP-BF533: { ADI_PWR_CMD_SET_PROC_VARIANT, (void*)ADI_PWR_PROC_BF533SKBC600 }, // в корпусе MBGA: { ADI_PWR_CMD_SET_PACKAGE, (void*)ADI_PWR_PACKAGE_MBGA }, // внешнее питание для регулятора 3.3V: { ADI_PWR_CMD_SET_VDDEXT, (void*)ADI_PWR_VDDEXT_330 }, // входная частота кварца 25 МГц: { ADI_PWR_CMD_SET_CLKIN, (void*) 25 }, // маркер конца списка команд: { ADI_PWR_CMD_END, 0 } }; adi_pwr_Init(power_init_table); Шаг 3: выберите стратегию управления питанием. Например, следующие сегменты кода покажут, как конфигурировать модуль PM для оптимальной скорости или оптимального энергопотребления. Оптимальная скорость. В этом примере модуль PM установит частоты ядра и шины на максимально возможные значения. adi_pwr_SetFreq (0, /* частота ядра (CCLK) */ 0, /* частота системной шины (SCLK) */ ADI_PWR_DF_ON /* не настраивать входной делитель PLL */); Оптимальное энергопотребление. Следующие операторы дают задание модулю PM установить такие частоты ядра и шины, чтобы они были максимально допустимы для уровня напряжения 0.85 V. adi_pwr_SetMaxFreqForVolt (ADI_PWR_VLEV_085); Использование автоматической синхронизации. Последовательность программирования PLL для двухъядерного процессора требует, чтобы оба ядра были приведены к состоянию ожидания (IDLE state), когда прикладываются изменения к регистрам PLL и VR. Двухъядерный процессор может выполнять программу на каждом ядре, или может выполнять программу только на одном ядре. Когда для выполнения программы используются оба яра, требуется механизм для обоих ядер, чтобы они перешли в состояние IDLE, и оставались в нем, пока записываются регистры. Модуль PM предоставляет механизм, который использует поддерживающее прерывание, чтобы синхронизировать ядра для программирования PLL. Этот механизм вовлекается автоматически путем вызова функции adi_pwr_Init() на обоих ядрах, и передаче команды ADI_PWR_CMD_SET_AUTO_SYNC_ENABLED с NULL в качестве аргумента, как это показано в следующей таблице пар команд для платы разработчика ADSP-BF561 EZ-KIT Lite. ADI_PWR_COMMAND_PAIR power_init_table[] = { // 500 MHz ADSP-BF561: { ADI_PWR_CMD_SET_PROC_VARIANT, (void*)ADI_PWR_PROC_BF561SKBCZ500X }, // корпус MBGA: { ADI_PWR_CMD_SET_PACKAGE, (void*)ADI_PWR_PACKAGE_MBGA }, // внешнее напряжение 3.3 V для регулятора питания: { ADI_PWR_CMD_SET_VDDEXT, (void*)ADI_PWR_VDDEXT_330 }, // входная частота 30 МГц: { ADI_PWR_CMD_SET_CLKIN, (void*) 30 }, // разрешить автосинхронизацию: { ADI_PWR_CMD_SET_AUTO_SYNC_ENABLED, NULL }, // маркер конца таблицы команд: { ADI_PWR_CMD_END, 0 } }; adi_pwr_Init(power_init_table); Требование синхронизации. Двухъядерные процессоры Blackfin могут работать на одном ядре, когда второе ядро находится в состоянии ожидания (idle). Управление питанием и управление EBIU требуют помещения обоих ядер в состояние IDLE, когда делается управление питанием и меняются настройки контроллера EBIU. Если модуль EBIU был инициализирован, и была изменена частота системной шины, то параметры времени сигналов SDRAM будут автоматически подстроены. Чтобы избежать повреждения данных в SDRAM, механизм автоматической синхронизации ядер принудительно выводит оба ядра в область вне адресного пространства SDRAM, пока обновляются параметры времени SDRAM. Здесь возможны 2 рабочих режима: работа приложения на одном ядре, и работа приложений на обоих ядрах. Приложение работает только на одном ядре. В этом случае используется одно ядро (core A), и другое ядро (core B) запрещено. При сбросе ядро B останется запрещенным, пока код, работающий на ядре A, на запустит ядро B путем очистки бита 5 регистра SICA_SYSCR. Например: *pSICA_SYSCR &= 0xFFDF; // очистка бита 5, чтобы ядро B начало работать Обратите внимание, что это не разбудит ядро B, если оно в состоянии IDLE. Это всего лишь разрешит для ядра B начинать выполнять инструкции при запуске (startup). Чтобы разбудить ядро B из состояния IDLE, используется одно из двух поддерживающих прерываний (supplemental interrupt 0 задействуется системными службами, оставляя supplemental interrupt 1 для других целей). Одноядерные приложения загружаются из flash-памяти или через порт SPI, чтобы удовлетворить вышеупомянутым требованиям синхронизации без какого-либо дальнейшего вмешательства. Однако сессия эмулятора в VisualDSP++ неизбежно разбудит ядро B. Разработчик приложения должен возвратить ядро B в запрещенное состояние, чтобы удовлетворить требования программирования PLL. Есть 2 способа выполнить это. Простейший из них состоит в запуске следующего кода на языке C на ядре B: void main() { while(1) { asm("IDLE;"); } } Всякий раз, когда ядро B проснется (из-за последовательности программирования PLL, выполняемой службой PM), оно будет немедленно помещено в состояние IDLE. Другой метод состоит в запрете бита пробуждения от PLL (PLL wakeup bit) в регистре SICB_IWR0, и переходе в состояние IDLE. Если это делается на языке ассемблера, то следующий код может быть помещен в код запуска (startup code): #include < defBF561.h >
.section program;
start: P0.H = HI(SICB_IWR0); P0.L = LO(SICB_IWR0); R0 = 0; [P0] = R0; IDLE; .start.end:
.global start;
.type start,STT_FUNC;
Приложение работает на обоих ядрах. В этом случае оба ядра выполняют код. Ядрам нужно синхронизироваться, чтобы гарантировать, что оба ядра находятся в состоянии IDLE и, в некоторых случаях, не было выхода выполнения кода из SDRAM, как это было описано в приведенных выше требованиях. Здесь есть 2 выбора: 1) определить свою собственную стратегию синхронизации, или 2) использовать встроенную синхронизацию, предоставляемую модулем PM (что должно быть разрешено отдельной командой). Чтобы использовать встроенную синхронизацию, включите следующую пару команда-значение в список команд для adi_pwr_Init() на обоих ядрах: { ADI_PWR_CMD_SET_AUTO_SYNC_ENABLED, NULL }
Будучи активизированной, встроенная синхронизация получит эксклюзивный контроль над поддерживающим прерыванием 0 и подключит в цепочку обработчиков подходящий обработчик прерывания на подходящий уровень IVG с использованием Менеджера Прерываний. Это защитит приложение от использования прерывания для любой другой синхронизации между ядрами. Однако поддерживающее прерывание 1 все еще остается доступным для использования вне системных служб для других целей синхронизации ядер. Можно использовать дополнительные команды, чтобы удовлетворять требованиям синхронизации (см. таблицу 3-1). Таблица 3-1. Дополнительные команды для адаптации синхронизации.
Синхронизация между ядрами. Любое ядро может прервать другое ядро, используя так называемое поддерживающее прерывание (supplemental interrupt). Для процессора ADSP-BF561 есть два таких поддерживающих прерывания: 0 и 1. Общая переменная блокировки размещена в памяти, которая может передавать информацию между ядрами и использоваться как метод синхронизации. Встроенный механизм требует, чтобы ядро A инициировало все изменения по управлению питанием, с ядром B, сконфигурированным на ответ на событие поддерживающего прерывания 0, которое сгенерирует ядро A. Конфигурация и обработка этого прерывания управляется внутри самого модуля PM. Таблица 3-2 описывает последовательность синхронизации. Таблица 3-2. Последовательность синхронизации между ядрами.
Встроенная переменная блокировки (Lock Variable) и соглашения о линковке. Переменная блокировки adi_pwr_lockvar декларируется в файле Blackfin \ lib \ src \ services \ pwr \ adi_pwr_lockvar.c следующим образом: section ("l2_shared") testset_t adi_pwr_lockvar = 0; где входная секция памяти l2_shared привязана к выходной секции MEM_L2_SRAM в настройках по умолчанию и генерируемых файлах описания конфигурации линкера (linker description files, .ldf). В соответствии с Приложением A руководства по программированию C/C++ и библиотекам в системе VisualDSP++ для процессоров Blackfin [2], есть два возможных способа написания приложений, которые работают на обоих ядрах. • Одно приложение на ядро, где исполняемые коды собираются для каждого ядра с помощью двух проходов линкера. Последний способ привязывает переменную блокировки к памяти L2, которая используется совместно обоими процессорами без какого-либо вмешательства пользователя. Способ "одно приложение на ядро" требует вмешательства пользователя для гарантии, что переменная блокировки была привязана на один и тот же адрес памяти L2 в каждом из исполняемых приложений. Это достигается с использованием оператора RESOLVE в файле .ldf, который можно использовать для определения адреса символа в памяти, назначенном в исполняемом файле для каждого ядра. Настройки по умолчанию и генерируемые файлы .ldf для ядра B содержат следующее: /* $VDSG< customize-shared-symbols > */
/* Этот код сохраняется, если LDF генерируется заново. */
/////////////////////////////////////////////////////////////
// ldf_shared_symbols
/* Оператор разрешения для общих символов, привязанных в ядре A.
** Ниже приведен пример, как это делается.
*/
#if defined(OTHERCORE) /* OTHERCORE это макрос, определенный для имени CoreA DXE */ #include < shared_symbols.h > /* Библиотека C runtime для общих символов использует
макрос OTHERCORE. */ #if 0 /* пример разрешения для общих данных пользователя */ RESOLVE(_a_shared_datum, OTHERCORE) #endif #endif /* OTHERCORE */ /* $VDSG< customize-shared-symbols > */
Заголовочный файл shared_symbols.h содержит операторы RESOLVE для общих библиотечных символов C/C++, и подключает дополнительный заголовочный файл services/services_shared_symbols.h, содержащий операторы RESOLVE для общих символов системных служб. В настоящий момент системные службы используют только один общий символ переменной adi_pwr_lockvar. Все, что требуется, это определить OTHERCORE в блоке настроек LDF, модифицируемом пользователем перед тем, где это проверено (или путем установки его значения через страницу Link: LDF Preprocessing окна диалога настроек проекта (Project Options VisualDSP++). Например, если исполняемый файл одного ядра CoreA.dxe, то для ядра A он находится в подкаталоге Release, то соседнее с этим ядром CoreB в его каталоге проекта требует определения OTHERCORE как ..\CoreA\Release\CoreA.dxe. Пример: #define OTHERCORE ..\CoreA\Release\CoreA.dxe#if defined(OTHERCORE) ... Подробности см. в Приложении A руководства [2] и документацию по линкеру и утилитам системы программирования VisualDSP++ 5.0. Инициализация SDRAM перед загрузкой исполняемого кода. Приложения, которые требуют размещения кода (и/или данных) в SDRAM в момент загрузки требуют, чтобы сначала был соответствующим образом (в зависимости от конфигурации подключенной внешней памяти SDRAM) был проинициализирован контроллер SDRAM. Это случай для всех приложений, где разрешено кэширование инструкций и/или данных. Однако подпрограмма adi_ebiu_Init() инициализации службы EBIU не выполнится, пока не будет загружено приложение. Есть два способа загрузить приложение в процессорное ядро: • Через сессию эмулятора (отладчика JTAG), подключенного в среде разработки VisualDSP++. В первом случае обязательно используется выбранная опция Use XML reset values в окне диалога настройки свойств целевого процессора (диалог Target Options, доступный через меню Settings, появляющееся после запуска сессии отладки, см. скриншоты ниже).
Также требуется указать место расположения файла XML для загружаемой сессии отладки (меню Settings -> Session..., см. скриншоты ниже).
Это гарантирует, что SDRAM корректно (пусть даже не оптимально) будет сконфигурировано перед тем, как в SRAM загрузится приложение и его данные. Будучи загруженным, приложение использует службы PM и EBIU для гарантии, что SDRAM конфигурируется оптимально. Когда приложение не загружается из сессии эмулятора, необходимо написать загрузчик, который целиком размещается в SRAM, и при запуске инициализирует SDRAM, после чего может быть загружено основное приложение [4]. Это достигается с использованием блока инициализации, как это описано в руководстве по библиотекарю и утилиты загрузчика VisualDSP++ 5.0 [2], где демонстрируется пример инициализации SDRAM (см. также [3, 4]). Этот блок кода инициализации копируется в исполняемый код, и передается загрузчику через опцию –init filename или в поле инициализации Load: Options на странице диалога настройки свойств проекта (Project Options) VisualDSP++. Для этого исполняемого блока инициализации требуется отдельный проект. Пример проекта для блока инициализации см. в соответствующей для процессора поддиректории каталога Blackfin\ldr\init_code в папке установки VisualDSP++. Значения, требуемые для регистров конфигурации SDRAM можно установить в соответствующие значения из файла .xml для применяемого процессора, например ADSP-BF533-proc.xml, который находится в каталоге System\Arch-Def директории инсталляции VisualDSP++. Когда требуются различные конфигурации для памяти (отличающиеся от предоставленных вместе с системами оценочных плат EZ-KIT Lite), пользователю придется поработать над установкой правильных значений. Когда программа загружается из среды разработки VisualDSP++ через отладчик, то либо используйте фичу Custom Board Support, доступную в VisualDSP++5.0 (описание см. в Help -> Graphical Environment -> Custom Board Support), или просто отредактируйте значения регистров в соответствующем файле .xml после сохранения копии оригинального файла. [Power Management API] В этом разделе приведено описание интерфейса программирования (API) модуля PM. Функция adi_pwr_AdjustFreq() позволяет модифицировать тактовые частоты ядра и системной шины (CCLK и SCLK), указывая коэффициенты деления частоты тактов ядра и системы CSEL и SSEL, находящиеся в полях регистра PLL_DIV. Процессор находится в активном режиме (не в состоянии ожидания). ADI_PWR_RESULT adi_pwr_AdjustFreq (ADI_PWR_CSEL csel,
ADI_PWR_SSEL ssel);
Аргументы:
Возвращаемые значения:
Функция adi_pwr_Control() разрешает конфигурировать регистры управления питанием или считывать их значения с помощью списков пар команда-значение (см. врезку ADI_PWR_COMMAND_PAIR), заданных одним из трех способов: 1) Будет передана одна пара команда-значение. adi_pwr_Control (ADI_PWR_CMD_SET_INPUT_DELAY, (void*)ADI_PWR_INPUT_DELAY_ENABLE); 2) Будет передана структура ADI_PWR_COMMAND_PAIR с одной парой команда-значение. ADI_PWR_COMMAND_PAIR cmd = { ADI_PWR_CMD_SET_INPUT_DELAY, (void*)ADI_PWR_INPUT_DELAY_ENABLE, }; adi_pwr_Control (ADI_PWR_CMD_PAIR, (void*)&cmd); 3) Будет передана таблица пар команд типа в виде списка структур ADI_PWR_COMMAND_PAIR. Последняя запись в списке должен быть с командой признака окончания списка ADI_PWR_CMD_END. ADI_PWR_COMMAND_PAIR table[] = { { ADI_PWR_CMD_SET_INPUT_DELAY, (void*)ADI_PWR_INPUT_DELAY_ENABLE }, { ADI_PWR_CMD_SET_OUTPUT_DELAY, (void*)ADI_PWR_OUTPUT_DELAY_ENABLE }, { ADI_PWR_CMD_END, 0} }; adi_pwr_Control(ADI_PWR_CMD_TABLE,(void*)table); Подробнее см. врезку ADI_PWR_COMMAND в разделе "Публичные типы данных и перечисления модуля PM", где приведен полный список команд и связанных с ними значений. ADI_PWR_RESULT adi_pwr_Control (ADI_PWR_COMMAND Command, void *Value); Аргументы:
Возвращаемые значения:
Функция adi_pwr_GetConfigSize() возвратит количество байт, требуемых для сохранения данных текущей конфигурации. Это значение также доступно через использование макроса ADI_PWR_SIZEOF_CONFIG. Возвращенное значение adi_pwr_GetConfigSize и этого макроса ADI_PWR_SIZEOF_CONFIG, объединяет размер конфигурации модуля EBIU, независимо от времени его инициализации. size_t adi_pwr_GetConfigSize (void); Возвращаемое значение: размер структуры конфигурации. Функция adi_pwr_GetFreq() возвратит текущие значения частот CCLK, SCLK (частота ядра и системной шины), а также частоту стабилизатора напряжения питания ядра. ADI_PWR_RESULT adi_pwr_GetFreq (u32 *fcclk, u32 *fsclk, u32 *fvco); Аргументы:
Возвращаемые значения:
Важное замечание: как мне кажется, в этой функции содержится ошибка. Заключается она в том, что текущие частоты ядра и шины (CCLK и SCLK) вычисляются в этой функции не на основе содержимого регистров PLL_CTL и PLL_DIV (как это должно быть), а почему-то из значений полей pll_ctl и pll_div структуры adi_pwr_active_config. По этой причине иногда (если adi_pwr_active_config заполнена неправильно), тактовые частоты функция adi_pwr_GetFreq вычисляет неверно. Не нашел в документации и примерах объяснения этого факта. Чтобы решить проблему, у нас есть два варианта - либо внести исправление в функцию adi_pwr_GetFreq, которая находится в модуле adi_pwr.c, и использовать в проекте исправленный вариант, либо предварительно правильно заполнить поля pll_ctl и pll_div структуры adi_pwr_active_config. Я выбрал второй вариант: extern ADI_PWR_CONFIG adi_pwr_active_config;
// Получение частот PLL. Без заполнения этих полей
// функция adi_pwr_GetFreq отработает неправильно! adi_pwr_active_config.pll_ctl = *(ADI_PWR_PLL_CTL_REG*)pPLL_CTL; adi_pwr_active_config.pll_div = *(ADI_PWR_PLL_DIV_REG*)pPLL_DIV; adi_pwr_GetFreq(&fcclk, &fsclk, &fvco); Функция adi_pwr_GetPowerMode() возвратит текущий режим процессора (доступно только для режимов full-on и active). ADI_PWR_MODE adi_pwr_GetPowerMode (void); Возвращаемое значение: текущий режим энергопотребления как значение типа ADI_PWR_MODE. Функция adi_pwr_GetPowerSaving() вычисляет значение экономии питания для текущей настройки PLL и регулятора напряжения ядра, по формулам из даташита с установкой для разных режимов питания. u32 adi_pwr_GetPowerSaving (void); Возвращаемое значение: на сколько процентов экономится питание. Функция adi_pwr_Init() инициализирует модуль PM. Для успешной установки нужно установить следующие значения:
Обмен с функцией adi_pwr_Init происходит через передачу указателя на таблицу пар команда-значение. Таблица должна завершаться командой ADI_PWR_CMD_END. Например, следующая таблица ADI_PWR_COMMAND_PAIR предоставлена для оценочной платы разработчика EZ-KIT Lite: ADI_PWR_COMMAND_PAIR ezkit_init[] = { { ADI_PWR_CMD_SET_PROC_VARIANT, ADI_PWR_PROC_BF533SKBC600 }, { ADI_PWR_CMD_SET_PACKAGE, ADI_PWR_PACKAGE_MBGA }, { ADI_PWR_CMD_SET_VDDEXT, ADI_PWR_VDDEXT_330 }, { ADI_PWR_CMD_SET_CLKIN, 25 /* МГц */ }, { ADI_PWR_CMD_END, 0 } }; В таблице 3-3 перечислены допустимые пары команда-значение. Таблица 3-3. Пары Command-Value для списка команд функции adi_pwr_Init.
Функцию adi_pwr_Init можно вызвать только один раз. Последующие вызовы adi_pwr_Init будут игнорироваться с кодом возврата ADI_PWR_RESULT_ALREADY_INITIALIZED. В таблице 3-4 перечислены допустимые пары команда-значение для двухъядерного процессора ADSP-BF561. Таблица 3-4. Пары Command-Value для ADSP-BF561 Dual-Core Processor.
Прототип функции: ADI_PWR_RESULT adi_pwr_Init (const ADI_PWR_COMMAND_PAIR *table); Аргумент:
Возвращаемые значения: в отладочной версии библиотеки adi_pwr_Init вернет коды возврата, перечисленные ниже. Иначе будет возвращено значение либо ADI_PWR_RESULT_SUCCESS, либо ADI_PWR_RESULT_ALREADY_INITIALIZED (когда модуль PM уже был инициализирован). Чтобы упростить конфигурирование параметров времени для драйверов устройств, единица по умолчанию для частоты при обмене с функциями PM задаются в Герцах (Гц), а не в мегагерцах (МГц). Если для приложения требуется единицы частот в МГц, а не Гц, то служба PM может управляться в формате частот мегагерц с помощью новой команды ADI_PWR_CMD_SET_FREQ_AS_MHZ для функции adi_pwr_Init(). С этой командой сопровождаемое значение параметра будет игнорироваться. Например, если если передается таблица команд в функцию adi_pwr_Init(), то в неё должна быть добавлена команда: { ADI_PWR_CMD_SET_FREQ_AS_MHZ, NULL },
В таблице 3-5 перечислены и объяснены коды возврата. Таблица 3-5. Коды возврата функции adi_pwr_Init.
Функция adi_pwr_LoadConfig() восстанавливает текущие значения конфигурации из области памяти, на которую указывает аргумент hConfig. Контроллер PLL и регулятор напряжения будут перепрограммированы. Если модуль EBIU был инициализирован, эта конфигурация также загружается, и программируется контроллер SDRAM. ADI_PWR_RESULT adi_pwr_LoadConfig (const ADI_PWR_CONFIG_HANDLE hConfig, const size_t szConfig); Аргументы:
Возвращаемые значения:
Функция adi_pwr_Reset() сбрасывает контроллер PLL в свои аппаратные значения по умолчанию, которые применяются при сбросе. void adi_pwr_Reset (void); Функция adi_pwr_SaveConfig() сохраняет текущие значения конфигурации в область памяти, на которую указывает аргумент hConfig. Если модуль EBIU был инициализирован, то его конфигурация сохраняется также; иначе соответствующие поля его конфигурации останутся незаполненными (не определенными). ADI_PWR_RESULT adi_pwr_SaveConfig (ADI_PWR_CONFIG_HANDLE hConfig, const size_t szConfig); Аргументы:
Возвращаемые значения:
Функция adi_pwr_SetFreq() настраивает контроллер PLL для предоставления частот CCLK и SCLK со значениями, максимально близкими к запрашиваемым (указанным в Гц). Если регулятор напряжения не запрещен, то его конфигурация будет подстроена (в случае необходимости) для предоставления минимального напряжения, которое может поддерживать запрашиваемые частоты. Процессор переводится в состояние ожидания (idle), чтобы изменения вошли в силу. Эта функция всегда находит такое решение, где делитель CSEL в делитель регистра PLL_DIV единица. Если запрошен входной делитель PLL, то будет минимизирована разница между запрашиваемыми значениями и установленными. Чтобы определить значения, которые были реально установлены этой функцией, используйте функцию adi_pwr_GetFreq. ADI_PWR_RESULT adi_pwr_SetFreq (const u32 fcclk, const u32 fsclk, const ADI_PWR_DF df); Аргументы:
Возвращаемые значения:
Функция adi_pwr_SetMaxFreqForVolt() устанавливает значение регистра управления регулятором напряжения (voltage regulator control register, VR_CTL), в соответствии с требуемым уровнем напряжения и подстраивает частоты процессора CCLK и SCLK, чтобы они были максимально допустимыми для установленного уровня напряжения питания. Чтобы применились изменения, процессор переводится в состояние ожидания (idle). ADI_PWR_RESULT adi_pwr_SetMaxFreqForVolt (const ADI_PWR_VLEV vlev); Аргумент:
Возвращаемые значения:
Функция adi_pwr_SetPowerMode() устанавливает режим питания (power mode) процессора. Имеется 5 режимов: Full-On. Тактовая частота ядра (CCLK) и системной шины (SCLK) имеют значения, установленные функциями adi_pwr_SetFreq или adi_pwr_SetVoltageRegulator. Разрешен полный функционал для DMA. Active. Блок PLL пропускается, так что ядро процессора и системная шина работают на входной тактовой частоте CLKIN (частота кварцевого генератора). Доступ DMA работает для правильно сконфигурированной памяти L1. Sleep. Ядро процессора находится в состоянии ожидания (idle), или состоянии сна. Системная частота (частота шины SCLK) продолжает поступать на скорости, установленной функциями adi_pwr_SetFreq или adi_pwr_SetVoltageRegulator functions. Работа DMA ограничена доступом к внешней памяти. См. ниже инструкции для выбора пробуждений процессора (wakeup), чтобы вывести его из режима сна. Deep Sleep. Глубокий сон, при котором запрещена работа ядра процессора и всех периферийных устройств, за исключением блока часов реального времени (real-time clock, RTC). В этом режиме DMA не поддерживается. SDRAM устанавливается в режим самообновления (self-refresh mode). Регулятор напряжения ядра включается по прерыванию от RTC или от события аппаратного сброса. В обоих случаях инициируется последовательность сброса ядра. Hibernate. Внутренний регулятор напряжения выключается. SDRAM устанавливается в режим самообновления. Регулятор напряжения включается от аппаратного сброса. См. ниже инструкции по выбору способа пробуждения для вывода процессора из режима hibernate. Пока SDRAM не будет правильно сконфигурировано и пока не будет для неё выбрана подходящая частота обновления (refresh rate), данные в SDRAM будут теряться. Это справедливо только для выхода из режимов hibernate или deep sleep по событию аппаратного сброса. Для процессорных ядер ADSP-BF531, ADSP-BF532 и ADSP-BF533 вывод SCKE процессора устанавливается при сбросе, чем SDRAM выводится из режима самообновления. Такое поведение является следствием ограничения для соответствия стандарту памяти PC-133. Для некоторых процессоров, в настоящее время включая семейства ADSP-BF537 и ADSP-BF527, это ограничение можно обойти разрешением бита CKELOW в регистре VR_CTL (см. врезку adi_pwr_SetVoltageRegulator). Этого можно также достичь вставкой следующей пары команда-значение в таблицу команд для функции adi_pwr_Init: { ADI_PWR_CMD_SET_PC133_COMPLIANCE, 0 }
Чтобы указать метод пробуждения (wakeup) для выхода из режимов sleep или hibernate: 1. Вызовите adi_int_SICGlobalWakeup для запрета всех событий wakeup. Прототип функции: ADI_PWR_RESULT adi_pwr_SetPowerMode (const ADI_PWR_MODE mode); Аргумент:
Возвращаемые значения:
Функция adi_pwr_SetVoltageRegulator() устанавливает регистр управления регулятором напряжения (voltage regulator control register, VR_CTL), настраивая одно или большее количество его следующих полей.
Эти значения передаются в функцию adi_pwr_SetVoltageRegulator через одну пару команда-значение или через последовательность пар в виде таблицы, которую завершает команда ADI_PWR_CMD_END - точно таким же способом, как это делалось в функции adi_pwr_Control. Подробнее см. врезку adi_pwr_Control. Например, чтобы пропустить встроенный регулятор напряжения, должен использоваться следующий код: adi_pwr_SetVoltageRegulator (ADI_PWR_SET_VR_FREQ, (void*) ADI_PWR_VR_FREQ_POWERDOWN); В таблице 3-6 определены пары команда-значение, которые могут использоваться с функцией adi_pwr_SetVoltageRegulator. Использование других пар недопустимо. Таблица 3-6. Пары Command-Value для функции adi_pwr_SetVoltageRegulator.
Частоты процессора CCLK и SCLK не подстраиваются. Когда это необходимо, процессор переходит в состояние ожидания (idle), чтобы изменения пришли в силу. Если запрошенное значение недостаточно для поддержки текущих значений частот, то функция вернет ошибку без изменения настроек. Прототип функции: ADI_PWR_RESULT adi_pwr_SetVoltageRegulator (ADI_PWR_COMMAND Command, void *Value); Аргументы:
Возвращаемые значения:
Функция adi_pwr_Terminate() завершает работу модуля PM, сбрасывает флаг "инициализировано", и отцепляет поддерживающее прерывание, если используется двухъядерная синхронизация. ADI_PWR_RESULT adi_pwr_Terminate (void); Возвращаемое значение:
[Публичные типы данных и перечисления модуля PM] В этом разделе предоставлено описание публичных данных и перечислений PM. Тип перечисления ADI_PWR_COMMAND описывает тип для команды в структуре ADI_PWR_COMMAND_PAIR. В таблице 3-7 описаны доступные команды, связанные значения данных и допустимый контекст для их использования. Таблица 3-7. Доступные команды ADI_PWR_COMMAND.
Этот тип данных используется для генерации таблицы управляющих команд. Эти команды посылаются модулю PM через функции adi_pwr_Init, adi_pwr_SetVoltageRegulator и adi_pwr_Control: typedef struct _ADI_PWR_COMMAND_PAIR { ADI_PWR_COMMAND kind; void *value; } ADI_PWR_COMMAND_PAIR; Подробнее см. врезку ADI_PWR_COMMAND для допустимых значений каждого поля. Этот тип данных определяет поле делителя тактовой частоты ядра в регистре PLL_DIV. Допустимы значения:
Этот тип данных определяет значения для бита DF в регистре управления PLL. Значение ADI_PWR_DF_ON означает передачу величины CLKIN/2 в модуль PLL. В соответствии с аппаратным руководством процессора ADSP-BF533, это введет к снижению рассеиваемой мощности.
Этот тип данных определяет значения бита входной задержки в регистре управления PLL.
Этот тип данных задает значения бита выходной задержки, которые можно установить в регистре управления PLL.
Этот тип данных определяет рабочие режимы процессора (power mode). Допустимы следующие значения:
Этот тип данных определяет тип корпуса процессора. Относится к внешнему напряжению (см. врезку ADI_PWR_VDDEXT). Это значение определяет возможности по рассеиванию тепла корпусом процессора.
Этот тип данных определяет допустимые значения для настроек, совместимых с PC-133, или другие настройки. Это значение управляет, будет ли устанавливаться вывод SCKE процессора при его сбросе.
Этот тип данных определяет вариант процессора, что управляет соответствующими пределами для выбора скорости. Он передается в функцию adi_pwr_Init() вместе с командой ADI_PWR_CMD_SET_PROC_VARIANT. Текущий список вариантов процессора показан в таблице 3-8. Поскольку могут быть добавлены новые процессоры, то самая актуальная информация может быть найдена в перечислении ADI_PWR_PROC_KIND, сгруппированном по семействам процессоров (конечно при условии, что система VisualDSP++ получала обновления). Это перечисление находится в заголовочном файле adi_pwr.h (Power Management Service API). Варианты процессоров, которые не определены здесь, могут быть определены по аналогии с помощью макроса в секции "equivalent values" файла adi_pwr.h. См. даташит на конкретную модель процессора для получения полного описания возможностей по тактовой частоте и питанию. Таблица 3-8. Варианты процессоров.
Модуль PM вернет код результата выполнения функции в виде значения из перечисления типа ADI_PWR_RESULT. В таблице 3-9 перечислены и описаны эти возвращаемые значения. Таблица 3-9. Коды возврата API-функций модуля PM.
Этот тип данных определяет поле делителя системной тактовой частоты в регистре PLL_DIV. Допустимые значения:
Этот тип данных определяет внешнее напряжение (VDDEXT), предоставленное для регулятора напряжения.
Этот тип данных определяет допустимые уровни напряжения для регулятора напряжения. Значения для процессоров ADSP-BF533 и ADSP-BF561 следующие:
Этот тип данных определяет допустимые значения для бита CANWE в регистре управления регулятором напряжения. Если это разрешено, то регулятор напряжения может быть разбужен из состояния power-down через активность контроллера интерфейса CAN.
Этот тип данных определяет допустимые значения для бита CKELOW в регистре управления регулятором напряжения. Если это разрешено, то вывод SCKE переводится в состояние лог. 0 при сбросе системы, чтобы разрешить для SDRAM оставаться в режиме самообновления (self-refresh mode).
Этот тип данных задает допустимые значения для бита CLKBUFOE в регистре управления регулятором напряжения. Если это разрешено, то сигнал CLKIN может использоваться совместно с периферийными устройствами, особенно Ethernet PHY.
Этот типа данных определяет допустимые частоты переключения для регулятора напряжения. Это напряжение связано со значениями конденсатора и индуктивности в силовом фильтре регулятора. Чем выше установлена частота, тем могут быть меньше значения емкости и индуктивности. Допустимые значения для всех процессоров Blackfin:
Этот тип данных определяет допустимые значения для усиления (gain) во внутренней петле обратной связи импульсного регулятора. Усиление управляет тем, насколько быстро выходное напряжение будет установлено в требуемое конечное значение. Чем выше усиление, тем короче время установки. Слишком большое значение усиления приводят к повышенным переходным процессам при регулировании.
Этот тип данных определяет значения для пробуждения общего назначения (GPWE, general-purpose wakeup) или бит MXVR в регистре управления регулятором напряжения для некоторых процессоров. Если это разрешено (ADI_PWR_VR_GPWE_MXVRWE_ENABLED), то напряжение регулятора может быть восстановлено при выходе из состояния hibernate при прерывании от general-purpose wakeup или MXVR.
Этот тип данных определяет значения для бита PHYWE в регистре управления регулятором напряжения. Если это разрешено, то регулятор напряжения может быть разбужен из состояния power-down активностью со стороны интерфейса PHY.
Этот тип данных определяет допустимые значения для бита USBWE в регистре управления регулятором напряжения. Если это разрешено, то регулятор напряжения может быть разбужен из состояния power-down активностью интерфейса USB.
Этот тип данных определяет допустимые значения для бита WAKE в регистре управления регулятором напряжения. Если это разрешено (ADI_PWR_VR_WAKE_ENABLED), то регулятор напряжения может быть разбужен из состояния power-down (ADI_PWR_VR_FREQ_POWERDOWN) при поступлении прерывания RTC или по перепаду в низкий уровень на выводе RESET.
[Макросы модуля PM] В таблице 3-10 перечислены и описаны макросы модуля PM (power management, управление питанием). Здесь не показан список вариантов процессора, который функционально эквивалентен списку перечисления ADI_PWR_PROC_KIND. Поскольку могут появляться новые процессоры, то просмотрите макросы в секции "equivalent values" заголовочного файла adi_pwr.h (Power Management Service API), чтобы получить полный список "эквивалентных" вариантов процессора. Таблица 3-10. Макросы модуля PM.
[Ссылки] 1. VisualDSP++ 5.0 Device Drivers and System Services Manual for Blackfin® Processors site:analog.com. |