AHTOXA 25 March 31, 2015 Posted March 31, 2015 · Report post Всем привет. Добрался до Cortex-M0+ (STM32L0xx). Подумал, что отличий от порта для Cortex-M4(F) немного, и поэтому взял порт Cortex-M0 от Сергея Борща и влил его в M4(F). А так как порт Cortex-M4(F) уже поддерживал Cortex-M3, то порт получился универсальный. Назвал порт CortexMx, чтоб не трогать имеющиеся. Поддерживаются Cortex-M3, Cortex-M4(F), Cortex-M0, Cortex-M0+, Cortex-M1. Добавил также пример для STM32L0xx (плата STM32 NUCLEO-L053R8). Планирую после тестирования перевести на этот порт все примеры для M3/M4. Замечания и предложения приветствуются:) Quote Share this post Link to post Share on other sites More sharing options...
IgorKossak 1 April 3, 2015 Posted April 3, 2015 · Report post Замечания и предложения приветствуются:) Ну раз так, то настало время спросить. startup.c: Почему бы не разогнать ядро, выполнив init_HW() до инициализации .bss и .data? Зачем нужен __attribute__((__interrupt__)) для void Reset_Handler(void)? В стандартных шаблонах от производителей этого нет. sysinit.cpp: Не кошернее ли enable IOPx peripheral делать не в общем для всех случаев файле, а на уровне конкретного проекта? Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 April 3, 2015 Posted April 3, 2015 · Report post startup.c: Почему бы не разогнать ядро, выполнив init_HW() до инициализации .bss и .data? Дело в том, что в общем случае в init_HW() могут использоваться какие-нибудь статические/глобальные переменные, и тогда они будут использованы до инициализации. Если в вашем init_HW() гаранированно не нужны такие переменные, то можно и разогнать. Зачем нужен __attribute__((__interrupt__)) для void Reset_Handler(void)? В стандартных шаблонах от производителей этого нет. Это из каких-то совсем старых версий тянется, там было. Ни на что не влияет, можно смело убирать. sysinit.cpp: Не кошернее ли enable IOPx peripheral делать не в общем для всех случаев файле, а на уровне конкретного проекта? Так это и есть уровень проекта. Просто в примерах (когда их больше одного, как в STM32F1XX) файлы startup.c и sysinit.cpp совпадали, вот я их и вынес в папку SamplesCommon. Привычка к нормализации:) Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 April 11, 2015 Posted April 11, 2015 · Report post Обнаружил баг. Оказывается, Cortex-M0 не позволяет побайтовый доступ к регистрам System Control Block (SCB). Поэтому некорректно устанавливались приоритеты обработчиков прерываний PendSV и SysTick. Исправил в rev. 586. Quote Share this post Link to post Share on other sites More sharing options...
IgorKossak 1 April 16, 2015 Posted April 16, 2015 · Report post В более ранних версиях приоритеты обработчиков прерываний PendSV и SysTick устанавливались как SCB->SHPR3 = 0 | (3 << 22) // PendSV priority = 3, lowest | (2 << 30) // SysTick priority = 2, little higher ; Сейчас они устанавливаются одинаковыми, хоть и наинизшими. Есть какая-то причина? Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 April 16, 2015 Posted April 16, 2015 · Report post Нет, какой-то особой причины нет. Просто я сделал так, как было в порте для M3/M4. Там всю дорогу были одинаковые (наинизшие) приоритеты для PendSV и SysTick. Я подумал, что у M0 приоритетов и так мало, и жалко тратить аж два уровня из них на ось. К тому же, инициализация SysTick сделана опциональной, так что пользователь всегда может написать свой вариант функции __init_system_timer(), в которой задаст нужный ему приоритет. А зачем может быть нужно, чтобы SysTick мог прерывать PendSV? Quote Share this post Link to post Share on other sites More sharing options...
IgorKossak 1 April 16, 2015 Posted April 16, 2015 (edited) · Report post Я имел в виду другое. Возможно в более ранней версии для порта Cortex M0 была причина сделать так, чтобы PendSV могла быть вытеснена любым другим прерыванием, в том числе и SysTick. Об этом неплохо бы у Сергея Борща спросить ;) ПС: В порте для Cortex M3 приоритеты одинаковые. Edited April 16, 2015 by IgorKossak Quote Share this post Link to post Share on other sites More sharing options...
Сергей Борщ 187 April 16, 2015 Posted April 16, 2015 · Report post Да простая там идея - чтобы перепланировка выполнялась после всех прерываний, которые могут эту перепланировку потребовать. Чтобы не перепланировать дважды. Само прерывание перепланировки выполняется с запрещенными прерываниями и прервать его никто не может. Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 April 16, 2015 Posted April 16, 2015 · Report post Ага, то есть, если за время обработки какого-нибудь более приоритетного прерывания взведутся флаги SysTick и PendSV, то, при одинаковых приоритетах, сначала сработает PendSV, и уже потом SysTick, который в свою очередь может взвести флаг PendSV. А если мы поднимем приоритет SysTick-а, то всё сработает как надо - сначала SysTick, и уже потом PendSV. Так? Quote Share this post Link to post Share on other sites More sharing options...
Сергей Борщ 187 April 17, 2015 Posted April 17, 2015 · Report post А если мы поднимем приоритет SysTick-а, то всё сработает как надо - сначала SysTick, и уже потом PendSV. Так?Именно. Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 April 17, 2015 Posted April 17, 2015 · Report post Тогда надо приподнять. Сделаю на днях. Quote Share this post Link to post Share on other sites More sharing options...
IgorKossak 1 April 17, 2015 Posted April 17, 2015 · Report post Тогда надо приподнять. Сделаю на днях. Величины приоритетов сейчас задаются жёстко в файле OS_Target_cpp.cpp на уровне порта. Величина "приподнимания" в случае с Cortex M3/4 будет зависеть от параметра функции NVIC_SetPriorityGrouping(n), в функции void init_HW(void) в файле sysinit.cpp на уровне приложения. На мой взгляд такое распределение не очень удобно. Может лучше эти магические числа вынести куда-нибудь в scmRTOS_TARGET_CFG.h? Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 April 18, 2015 Posted April 18, 2015 · Report post Нас не волнует группировка приоритетов, нам же не надо, чтобы SysTick вытеснял PendSV, нам надо лишь, чтобы при одновременно установленных флагах этих прерываний первым срабатывало прерывание от SysTick. Для этого достаточно приподнять приоритет (или субприоритет) SysTick-а на 1 (== обнулить самую младшую значащую единичку в двоичном представлении приоритета). А вот с поиском позиции этой самой младшей значащей единички - надо будет подумать. Насколько я помню, число значащих бит приоритета зависит от реализации, а значит, его надо задавать на уровне проекта. К тому же, не хочется ломать совместимость с существующими проектами. Поэтому придётся добавтить в порт какие-то значения по умолчанию для каждой архитектуры. --- Думаю сделать как-то так: В scmRTOS_TARGET_CFG.h: #define CORE_PRIORITY_BITS 2 и в OS_Target_cpp.cpp: #if (!defined CORE_PRIORITY_BITS) # define SYS_TIMER_PRIO (0xFF) #else # define SYS_TIMER_PRIO (0xFE << (8-(CORE_PRIORITY_BITS))) #endif То есть, если не задано CORE_PRIORITY_BITS, то оставляем старое поведение. Quote Share this post Link to post Share on other sites More sharing options...
Сергей Борщ 187 April 18, 2015 Posted April 18, 2015 · Report post То есть в порт добавляется еще куча объявлений уровня проекта. Зачем вообще пихать это все в ОСь? Достаточно попросить пользователя настроить эти два прерывания и системный таймер где, когда и как ему будет удобно. Я вообще делаю все настройки периферии в стартапе и мне совершенно не нужны эти определения. Более того, меня напрягает необходимость сейчас передавать в потроха ОСи значение тактовой частоты. Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 April 18, 2015 Posted April 18, 2015 · Report post Какая куча? Добавляется всего одно объявление, причём как раз на уровне проекта. А в порте - fallback для старых проектов, в которых нет этого объявления. Как здесь можно сделать иначе? Что касаемо вообще настройки таймера в порте, а не в проекте - так уж исторически сложилось. В ядре есть специальный таймер для оси, поэтому удобно иметь настройку этого таймера на уровне порта. Вот например, сейчас - выяснилось, что полезно иметь приоритет системного таймера чуть повыше, чем приоритет прерывания планировщика. Я исправлю порт, и все проекты, использующие этот порт, автоматически получат это исправление. Разве это не хорошо? Возможность выбрать другой таймер - есть. Возможность заменить функцию инициализации таймера на свою - тоже есть. Естественно, такого рода вариативность требует некоторых телодвижений, типа задания значение тактовой частоты. Я думаю, что это небольшая плата за гибкость. Quote Share this post Link to post Share on other sites More sharing options...