В текущей библиотеке файл MDR32F9Qx_config.h содержит настройки библиотеки и он един для всех микроконтроллеров.С помощью условной компиляции в этом файле задаются параметры по умолчанию, необходимые для работы библиотеки. В частности, задаются частоты внешних генераторов, которые подключены к конкретной плате. Пользователь должен сам модифицировать этот файл под свою плату. В нашей версии этот файл назван MDR_Config.h и лишь подключает Config_ХХ.h файлы для каждого конкретного МК. Это избавляет от необходимости парсить в уме условную компиляцию MDR32F9Qx_config.h и понимать какие настройки активны для данного МК, а какие нет. В Config_ХХ.h содержаться настройки валидные только для конкретного микроконтроллера.
#if defined (USE_MDR1986VE1) #include <MDR_ConfigVE1.h> #elif defined (USE_MDR1986VE3) #include <MDR_ConfigVE3.h> #elif defined (USE_MDR1986VE9x) #include <MDR_ConfigVE9x.h> ... ... #endif
Определения типа USE_MDR1986VE1 автоматически подключаются из Пака при выборе того или иного микроконтроллера в закладке Target опций проекта. При этом Config_ХХ.h файл, например MDR_ConfigVE9x.h, копируется в директорию RTE\Device\MDR1986VE91. Этот файл содержит настройки:
//============= Debug Uart printf settings ================== #define UART_DEBUG_IND 1 #define UART_DEBUG_SHOW_WELLCOME 1 #define UART_DEBUG_BAUD_DEF 9600
//============= Защита пинов совмещенных с Jtag ================== // Писать в пины порта совмещенные с Jtag можно только 0. // Иначе отладчик потеряет соединение. Активным может быть только один. //#define USE_JTAG_A #define USE_JTAG_B //#define USE_SWD_A //#define USE_SWD_B
Активный USE_JTAG_B не позволяет функциям драйвера MDR_GPIO испортить обмен по JtagB. Подробнее об этом тут - "Как вернуть кирпич в рабочее состояние". В отличие от текущей библиотеки здесь добавлены варианты для защиты только выводов SWD. Использовать SWD удобнее поскольку он занимает только 2 пина, вместо 5-ти при отладке по Jtag.
//================ Параметры источников частоты ================ // Internal Generators #define HSI_FREQ_HZ 8000000UL #define HSI_FREQ_TRIM MDR_BKP_HSI_TRIM_8M0Hz #define HSI_TIMEOUT 0x0600UL #define HSI_LOW_SRI MDR_LOWRI_le40MHz #define HSI_DELAY_EEPROM EEPROM_Delay_le25MHz #define HSE_FREQ_HZ 8000000UL #define HSE_TIMEOUT 0x0600UL #define HSE_LOW_SRI MDR_LOWRI_le40MHz #define HSE_DELAY_EEPROM EEPROM_Delay_le25MHz ... тоже самое для LSI, LSE
Это параметры по умолчанию для функций драйвера MDR_RST_Clock:
// ========================= DMA ================================ // Для экономии памяти можно прописать 0, если альтернативные структуры DMA не используются #define USE_DMA_ALTER_STRUCT 1 // Можно завести собственную управляющую структуру каналов вместо глобальной (по умолчанию). #define USE_DMA_USER_CNTLS_CTRL_TABLE 0
В драйвере MDR_DMA.c выделен массив структур основных и альтернативных для всех 32-х каналов DMA. Это 64 структуры по 4-ре 32-разрядных слова. Возможно в целях экономии памяти кому-то потребуется освободить эту память. Для этого необходимо выставить в 0 значение USE_DMA_ALTER_STRUCT. Если выставить USE_DMA_USER_CNTLS_CTRL_TABLE в 1, то можно завести свою структуру возможно меньшего размера и без альтернативных структур. При этом важно помнить, что своя структура должна быть выровнена необходимым образом по адресу!
// ========================= Timer Bugfixes ================================ // Прерывание возникает раньше, чем обновляются регистры CCR и CCR1 #define USE_TIM_CAP_FIX 0
Флаг использования обхода ошибки с захватом в канале таймера. Используется в драйвере MDR_Timer.c. Демопроект показывающий ошибку - CAPSyncChannels.
// ========================= POWER Bugfixes ================================ // Флаги событий не стираются с первого раза #define USE_PWR_CLR_FIX 1
Флаг реализует двойной сброс флагов PVD в драйвере блока детектора питания POWER. Раньше считалось что это ошибка, позднее вышло уточнение что так и должно быть. Первая запись в регистр разрешает доступ к сбросу, вторая запись непосредственно сбрасывает флаг события. Подробнее - Особенности детектора питания, блок Power. В последствии, если изменений не будет, то флаг будет удален, а двойной сброс будет выполняться без условной компиляции.
// ========================= MDR_Delay =========================== // Выбор реализации для MDR_Delay: // По умолчанию используется ассемблерный вариант, универсальный // Вариант на Си сильно зависит от опций компилятора // Вариант на DWT есть только в Cortex-M3/M4 и требует предварительное включение вызовом MDR_Delay_Init(). #define USE_MDR_DELAY_ASM //#define USE_MDR_DELAY_C //#define USE_MDR_DELAY_DWT // Исполнение функции задержки из ОЗУ / EEPROM происходит за разное количество тактов CPU. // Данными параметрами можно уточнить сколько тактов CPU занимает один цикл задержки в MDR_Funcs, для повышения точности. #define DELAY_LOOP_CYCLES_ASM 3 #define DELAY_LOOP_CYCLES_ASM_RAM 9 #define DELAY_LOOP_CYCLES_C 6 #define DELAY_LOOP_CYCLES_C_RAM 12 #define DELAY_LOOP_CYCLES_DWT 1 #ifdef USE_MDR_DELAY_C #define DELAY_LOOP_CYCLES DELAY_LOOP_CYCLES_C #define DELAY_LOOP_CYCLES_RAM DELAY_LOOP_CYCLES_C_RAM #elif defined USE_MDR_DELAY_DWT #define DELAY_LOOP_CYCLES DELAY_LOOP_CYCLES_DWT #define DELAY_LOOP_CYCLES_RAM DELAY_LOOP_CYCLES_WDT_RAM #else #define DELAY_LOOP_CYCLES DELAY_LOOP_CYCLES_ASM #define DELAY_LOOP_CYCLES_RAM DELAY_LOOP_CYCLES_ASM #endif
В данном разделе необходимо оставить активным один из вариантов реализации функции MDR_Delay(). В данном примере при USE_MDR_DELAY_ASM функция MDR_Delay() будет иметь ассемблерную реализацию. Плюс такой реализации в том, что она не зависит от опций компилятора и один цикл задержки занимает одно количество тактов, которое определено ниже в DELAY_LOOP_CYCLES_ASM. Это количество тактов CPU_Clock на цикл задержки при исполнении кода из флеш памяти. Если же задержка исполняется из ОЗУ, то шины работают немного по другому и количество тактов на исполнение тех-же ассемблерных инструкций занимает большее количество тактов - DELAY_LOOP_CYCLES_ASM_RAM.
Вариант на ассемблере самый универсальный, работает на всех микроконтроллерах. Вариант на Си сильно зависит от опций компилятора. Для Cortex-M3 (1986ВЕ9х) и Cortex-M4 (1986ВЕ8Т, "Электросила") доступна реализация задержки на основе отладочного блока трассировки - WDT. Здесь такты CPU_Clock считаются напрямую и с кодом никак не связаны, поэтому данный вариант самый точный и независимый. Но к сожалению есть не во всех микроконтроллерах.
Подробнее обо всем этом - MDR_Delay - Функция задержки и особенности её реализации в ассемблере.